dane.c revision 246854
129415Sjmg/* 250723Scg * Verify or create TLS authentication with DANE (RFC6698) 339899Sluigi * 429415Sjmg * (c) NLnetLabs 2012 529415Sjmg * 629415Sjmg * See the file LICENSE for the license. 729415Sjmg * 850723Scg */ 950723Scg 1029415Sjmg#include <ldns/config.h> 1129415Sjmg 1230869Sjmg#include <ldns/ldns.h> 1330869Sjmg#include <ldns/dane.h> 1430869Sjmg 1530869Sjmg#include <unistd.h> 1650723Scg#include <stdlib.h> 1750723Scg#include <sys/types.h> 1830869Sjmg#include <sys/socket.h> 1950723Scg#include <netdb.h> 2050723Scg 2150723Scg#ifdef HAVE_SSL 2250723Scg#include <openssl/ssl.h> 2350723Scg#include <openssl/err.h> 2450723Scg#include <openssl/x509v3.h> 2550723Scg#endif 2650723Scg 2750723Scgldns_status 2850723Scgldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name, 2950723Scg uint16_t port, ldns_dane_transport transport) 3050723Scg{ 3150959Speter char buf[LDNS_MAX_DOMAINLEN]; 3229415Sjmg size_t s; 3329415Sjmg 3453465Scg assert(tlsa_owner != NULL); 3529415Sjmg assert(name != NULL); 3629415Sjmg assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME); 3753465Scg 3853553Stanimura s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port); 3929415Sjmg buf[0] = (char)(s - 1); 4055706Scg 4155254Scg switch(transport) { 4250723Scg case LDNS_DANE_TRANSPORT_TCP: 4350723Scg s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp"); 4450723Scg break; 4550723Scg 4650723Scg case LDNS_DANE_TRANSPORT_UDP: 4750723Scg s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp"); 4850723Scg break; 4950723Scg 5050723Scg case LDNS_DANE_TRANSPORT_SCTP: 5129415Sjmg s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp"); 5264881Scg break; 5350723Scg 5464881Scg default: 5550723Scg return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT; 5664881Scg } 5729415Sjmg if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) { 5864881Scg return LDNS_STATUS_DOMAINNAME_OVERFLOW; 5950723Scg } 6064881Scg memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name)); 6150723Scg *tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 6264881Scg s + ldns_rdf_size(name), buf); 6329415Sjmg if (*tlsa_owner == NULL) { 6464881Scg return LDNS_STATUS_MEM_ERR; 6564881Scg } 6650723Scg return LDNS_STATUS_OK; 6764881Scg} 6850723Scg 6964881Scg 7029415Sjmg#ifdef HAVE_SSL 7164881Scgldns_status 7264881Scgldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert, 7350723Scg ldns_tlsa_selector selector, 7464881Scg ldns_tlsa_matching_type matching_type) 7550723Scg{ 7664881Scg unsigned char* buf = NULL; 7729415Sjmg size_t len; 7864881Scg 7964881Scg X509_PUBKEY* xpubkey; 8050723Scg EVP_PKEY* epubkey; 8164881Scg 8250723Scg unsigned char* digest; 8364881Scg 8429415Sjmg assert(rdf != NULL); 8564881Scg assert(cert != NULL); 8664881Scg 8750723Scg switch(selector) { 8864881Scg case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE: 8950723Scg 9064881Scg len = (size_t)i2d_X509(cert, &buf); 9129415Sjmg break; 9264881Scg 9364881Scg case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO: 9464881Scg 9564881Scg#ifndef S_SPLINT_S 9664881Scg xpubkey = X509_get_X509_PUBKEY(cert); 9764881Scg#endif 9854462Scg if (! xpubkey) { 9964881Scg return LDNS_STATUS_SSL_ERR; 10054462Scg } 10150723Scg epubkey = X509_PUBKEY_get(xpubkey); 10250723Scg if (! epubkey) { 10350723Scg return LDNS_STATUS_SSL_ERR; 10450723Scg } 10550723Scg len = (size_t)i2d_PUBKEY(epubkey, &buf); 10650723Scg break; 10750723Scg 10850723Scg default: 10950723Scg return LDNS_STATUS_DANE_UNKNOWN_SELECTOR; 11065340Scg } 11165340Scg 11265340Scg switch(matching_type) { 11365340Scg case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED: 11465340Scg 11565340Scg *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf); 11665340Scg 11765340Scg return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 11850723Scg break; 11929415Sjmg 12050723Scg case LDNS_TLSA_MATCHING_TYPE_SHA256: 12129415Sjmg 12250723Scg digest = LDNS_XMALLOC(unsigned char, SHA256_DIGEST_LENGTH); 12350723Scg if (digest == NULL) { 12450723Scg LDNS_FREE(buf); 12550723Scg return LDNS_STATUS_MEM_ERR; 12650723Scg } 12755706Scg (void) ldns_sha256(buf, (unsigned int)len, digest); 12850723Scg *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA256_DIGEST_LENGTH, 12929415Sjmg digest); 13050723Scg LDNS_FREE(buf); 13150723Scg 13250723Scg return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 13354462Scg break; 13454462Scg 13565644Scg case LDNS_TLSA_MATCHING_TYPE_SHA512: 13655706Scg 13729415Sjmg digest = LDNS_XMALLOC(unsigned char, SHA512_DIGEST_LENGTH); 13850723Scg if (digest == NULL) { 13950723Scg LDNS_FREE(buf); 14050723Scg return LDNS_STATUS_MEM_ERR; 14150723Scg } 14250723Scg (void) ldns_sha512(buf, (unsigned int)len, digest); 14350723Scg *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA512_DIGEST_LENGTH, 14450723Scg digest); 14550723Scg LDNS_FREE(buf); 14650723Scg 14750723Scg return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 14850723Scg break; 14950723Scg 15050723Scg default: 15150723Scg LDNS_FREE(buf); 15254462Scg return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE; 15329415Sjmg } 15450723Scg} 15555706Scg 15650723Scg 15750723Scg/* Ordinary PKIX validation of cert (with extra_certs to help) 15850723Scg * against the CA's in store 15950723Scg */ 16050723Scgstatic ldns_status 16150723Scgldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs, 16250723Scg X509_STORE* store) 16350723Scg{ 16465340Scg X509_STORE_CTX* vrfy_ctx; 16565340Scg ldns_status s; 16665340Scg 16765340Scg if (! store) { 16865340Scg return LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; 16950723Scg } 17050723Scg vrfy_ctx = X509_STORE_CTX_new(); 17150723Scg if (! vrfy_ctx) { 17250723Scg 17329415Sjmg return LDNS_STATUS_SSL_ERR; 17450723Scg 17529415Sjmg } else if (X509_STORE_CTX_init(vrfy_ctx, store, 17650723Scg cert, extra_certs) != 1) { 17750723Scg s = LDNS_STATUS_SSL_ERR; 17850723Scg 17950723Scg } else if (X509_verify_cert(vrfy_ctx) == 1) { 18050723Scg 18150723Scg s = LDNS_STATUS_OK; 18250723Scg 18329415Sjmg } else { 18429415Sjmg s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; 18529415Sjmg } 18650723Scg X509_STORE_CTX_free(vrfy_ctx); 18729415Sjmg return s; 18850723Scg} 18950723Scg 19050723Scg 19150723Scg/* Orinary PKIX validation of cert (with extra_certs to help) 19229415Sjmg * against the CA's in store, but also return the validation chain. 19350723Scg */ 19450723Scgstatic ldns_status 19550723Scgldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert, 19650723Scg STACK_OF(X509)* extra_certs, X509_STORE* store) 19750723Scg{ 19850723Scg ldns_status s; 19929415Sjmg X509_STORE* empty_store = NULL; 20029415Sjmg X509_STORE_CTX* vrfy_ctx; 20129415Sjmg 20250723Scg assert(chain != NULL); 20329415Sjmg 20450723Scg if (! store) { 20550723Scg store = empty_store = X509_STORE_new(); 20629415Sjmg } 20750723Scg s = LDNS_STATUS_SSL_ERR; 20850723Scg vrfy_ctx = X509_STORE_CTX_new(); 20950723Scg if (! vrfy_ctx) { 21050723Scg 21129415Sjmg goto exit_free_empty_store; 21229415Sjmg 21350723Scg } else if (X509_STORE_CTX_init(vrfy_ctx, store, 21450723Scg cert, extra_certs) != 1) { 21550723Scg goto exit_free_vrfy_ctx; 21650723Scg 21750723Scg } else if (X509_verify_cert(vrfy_ctx) == 1) { 21829415Sjmg 21929415Sjmg s = LDNS_STATUS_OK; 22050723Scg 22129415Sjmg } else { 22250723Scg s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; 22329415Sjmg } 22450723Scg *chain = X509_STORE_CTX_get1_chain(vrfy_ctx); 22550723Scg if (! *chain) { 22650723Scg s = LDNS_STATUS_SSL_ERR; 22750723Scg } 22850723Scg 22950723Scgexit_free_vrfy_ctx: 23050723Scg X509_STORE_CTX_free(vrfy_ctx); 23150723Scg 23250723Scgexit_free_empty_store: 23350723Scg if (empty_store) { 23429415Sjmg X509_STORE_free(empty_store); 23550723Scg } 23650723Scg return s; 23750723Scg} 23850723Scg 23950723Scg 24050723Scg/* Return the validation chain that can be build out of cert, with extra_certs. 24150723Scg */ 24250723Scgstatic ldns_status 24329415Sjmgldns_dane_pkix_get_chain(STACK_OF(X509)** chain, 24450723Scg X509* cert, STACK_OF(X509)* extra_certs) 24550723Scg{ 24650723Scg ldns_status s; 24750723Scg X509_STORE* empty_store = NULL; 24850723Scg X509_STORE_CTX* vrfy_ctx; 24950723Scg 25050723Scg assert(chain != NULL); 25150723Scg 25250723Scg empty_store = X509_STORE_new(); 25350723Scg s = LDNS_STATUS_SSL_ERR; 25429415Sjmg vrfy_ctx = X509_STORE_CTX_new(); 25550723Scg if (! vrfy_ctx) { 25650723Scg 25750723Scg goto exit_free_empty_store; 25850723Scg 25950723Scg } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store, 26050723Scg cert, extra_certs) != 1) { 26150723Scg goto exit_free_vrfy_ctx; 26250723Scg } 26350723Scg (void) X509_verify_cert(vrfy_ctx); 26450723Scg *chain = X509_STORE_CTX_get1_chain(vrfy_ctx); 26550723Scg if (! *chain) { 26629415Sjmg s = LDNS_STATUS_SSL_ERR; 26750723Scg } else { 26850723Scg s = LDNS_STATUS_OK; 26950723Scg } 27050723Scgexit_free_vrfy_ctx: 27150723Scg X509_STORE_CTX_free(vrfy_ctx); 27250723Scg 27350723Scgexit_free_empty_store: 27450723Scg X509_STORE_free(empty_store); 27529415Sjmg return s; 27650723Scg} 27750723Scg 27850723Scg 27950723Scg/* Pop n+1 certs and return the last popped. 28050723Scg */ 28150723Scgstatic ldns_status 28250723Scgldns_dane_get_nth_cert_from_validation_chain( 28331361Sjmg X509** cert, STACK_OF(X509)* chain, int n, bool ca) 28450723Scg{ 28550723Scg if (n >= sk_X509_num(chain) || n < 0) { 28650723Scg return LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE; 28750723Scg } 28850723Scg *cert = sk_X509_pop(chain); 28929415Sjmg while (n-- > 0) { 29050723Scg X509_free(*cert); 29150723Scg *cert = sk_X509_pop(chain); 29250723Scg } 29350723Scg if (ca && ! X509_check_ca(*cert)) { 29450723Scg return LDNS_STATUS_DANE_NON_CA_CERTIFICATE; 29550723Scg } 29629415Sjmg return LDNS_STATUS_OK; 29750723Scg} 29850723Scg 29929415Sjmg 30050723Scg/* Create validation chain with cert and extra_certs and returns the last 30150723Scg * self-signed (if present). 30250723Scg */ 30350723Scgstatic ldns_status 30429415Sjmgldns_dane_pkix_get_last_self_signed(X509** out_cert, 30550723Scg X509* cert, STACK_OF(X509)* extra_certs) 30650723Scg{ 30750723Scg ldns_status s; 30850723Scg X509_STORE* empty_store = NULL; 30950723Scg X509_STORE_CTX* vrfy_ctx; 31050723Scg 31150723Scg assert(out_cert != NULL); 31250723Scg 31329415Sjmg empty_store = X509_STORE_new(); 31450723Scg s = LDNS_STATUS_SSL_ERR; 31550723Scg vrfy_ctx = X509_STORE_CTX_new(); 31629415Sjmg if (! vrfy_ctx) { 31750723Scg goto exit_free_empty_store; 31850723Scg 31950723Scg } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store, 32050723Scg cert, extra_certs) != 1) { 32150723Scg goto exit_free_vrfy_ctx; 32250723Scg 32350723Scg } 32450723Scg (void) X509_verify_cert(vrfy_ctx); 32555706Scg if (vrfy_ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || 32655706Scg vrfy_ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){ 32750723Scg 32829415Sjmg *out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx); 32929415Sjmg s = LDNS_STATUS_OK; 33029415Sjmg } else { 33150723Scg s = LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR; 33229415Sjmg } 33350723Scgexit_free_vrfy_ctx: 33465644Scg X509_STORE_CTX_free(vrfy_ctx); 33565644Scg 33665644Scgexit_free_empty_store: 33750723Scg X509_STORE_free(empty_store); 33850723Scg return s; 33950723Scg} 34054462Scg 34150723Scg 34250723Scgldns_status 34350723Scgldns_dane_select_certificate(X509** selected_cert, 34454462Scg X509* cert, STACK_OF(X509)* extra_certs, 34550723Scg X509_STORE* pkix_validation_store, 34650723Scg ldns_tlsa_certificate_usage cert_usage, int offset) 34750723Scg{ 34854462Scg ldns_status s; 34950723Scg STACK_OF(X509)* pkix_validation_chain = NULL; 35050723Scg 35165644Scg assert(selected_cert != NULL); 35265644Scg assert(cert != NULL); 35365644Scg 35465644Scg /* With PKIX validation explicitely turned off (pkix_validation_store 35565644Scg * == NULL), treat the "CA constraint" and "Service certificate 35650723Scg * constraint" the same as "Trust anchor assertion" and "Domain issued 35729415Sjmg * certificate" respectively. 35850723Scg */ 35950723Scg if (pkix_validation_store == NULL) { 36050723Scg switch (cert_usage) { 36154462Scg 36254462Scg case LDNS_TLSA_USAGE_CA_CONSTRAINT: 36354462Scg 36450723Scg cert_usage = LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION; 36550723Scg break; 36654462Scg 36750723Scg case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: 36854462Scg 36950723Scg cert_usage = LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE; 37050723Scg break; 37154462Scg 37250723Scg default: 37354462Scg break; 37450723Scg } 37550723Scg } 37654462Scg 37750723Scg /* Now what to do with each Certificate usage... 37854462Scg */ 37958756Scg switch (cert_usage) { 38050723Scg 38154462Scg case LDNS_TLSA_USAGE_CA_CONSTRAINT: 38250723Scg 38329415Sjmg s = ldns_dane_pkix_validate_and_get_chain( 38450723Scg &pkix_validation_chain, 38558756Scg cert, extra_certs, 38655424Scg pkix_validation_store); 38754462Scg if (! pkix_validation_chain) { 38855424Scg return s; 38929415Sjmg } 39050723Scg if (s == LDNS_STATUS_OK) { 39154462Scg if (offset == -1) { 39255424Scg offset = 0; 39354462Scg } 39450723Scg s = ldns_dane_get_nth_cert_from_validation_chain( 39550723Scg selected_cert, pkix_validation_chain, 39650723Scg offset, true); 39729415Sjmg } 39829415Sjmg sk_X509_pop_free(pkix_validation_chain, X509_free); 39954462Scg return s; 40054462Scg break; 40129415Sjmg 40254462Scg 40354462Scg case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: 40454462Scg 40554462Scg *selected_cert = cert; 40654462Scg return ldns_dane_pkix_validate(cert, extra_certs, 40754462Scg pkix_validation_store); 40829415Sjmg break; 40954462Scg 41055706Scg 41155706Scg case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: 41255706Scg 41355706Scg if (offset == -1) { 41455706Scg s = ldns_dane_pkix_get_last_self_signed( 41558756Scg selected_cert, cert, extra_certs); 41654462Scg return s; 41729415Sjmg } else { 41854462Scg s = ldns_dane_pkix_get_chain( 41954462Scg &pkix_validation_chain, 42054462Scg cert, extra_certs); 42157973Sphk if (s == LDNS_STATUS_OK) { 42257973Sphk s = 42331361Sjmg ldns_dane_get_nth_cert_from_validation_chain( 42454462Scg selected_cert, pkix_validation_chain, 42550723Scg offset, false); 42641653Sbrian } else if (! pkix_validation_chain) { 42750723Scg return s; 42850723Scg } 42929415Sjmg sk_X509_pop_free(pkix_validation_chain, X509_free); 43050723Scg return s; 43158756Scg } 43229415Sjmg break; 43355706Scg 43455706Scg 43555706Scg case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: 43655706Scg 43765340Scg *selected_cert = cert; 43829415Sjmg return LDNS_STATUS_OK; 43965644Scg break; 44054462Scg 44154462Scg default: 44254462Scg return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE; 44354462Scg break; 44429415Sjmg } 44550723Scg} 44650723Scg 44750723Scg 44850723Scgldns_status 44955428Scgldns_dane_create_tlsa_rr(ldns_rr** tlsa, 45050723Scg ldns_tlsa_certificate_usage certificate_usage, 45150723Scg ldns_tlsa_selector selector, 45250723Scg ldns_tlsa_matching_type matching_type, 45350723Scg X509* cert) 45450723Scg{ 45529415Sjmg ldns_rdf* rdf; 45654462Scg ldns_status s; 45750723Scg 45854462Scg assert(tlsa != NULL); 45955706Scg assert(cert != NULL); 46055706Scg 46155706Scg /* create rr */ 46229415Sjmg *tlsa = ldns_rr_new_frm_type(LDNS_RR_TYPE_TLSA); 46355706Scg if (*tlsa == NULL) { 46455706Scg return LDNS_STATUS_MEM_ERR; 46558756Scg } 46658756Scg 46750723Scg rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 46829415Sjmg (uint8_t)certificate_usage); 46950723Scg if (rdf == NULL) { 47029415Sjmg goto memerror; 47150723Scg } 47250723Scg (void) ldns_rr_set_rdf(*tlsa, rdf, 0); 47350723Scg 47450723Scg rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)selector); 47529415Sjmg if (rdf == NULL) { 47665644Scg goto memerror; 47765644Scg } 47865644Scg (void) ldns_rr_set_rdf(*tlsa, rdf, 1); 47965644Scg 48065644Scg rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)matching_type); 48165644Scg if (rdf == NULL) { 48265644Scg goto memerror; 48365644Scg } 48465644Scg (void) ldns_rr_set_rdf(*tlsa, rdf, 2); 48565644Scg 48665644Scg s = ldns_dane_cert2rdf(&rdf, cert, selector, matching_type); 48765644Scg if (s == LDNS_STATUS_OK) { 48865644Scg (void) ldns_rr_set_rdf(*tlsa, rdf, 3); 48965644Scg return LDNS_STATUS_OK; 49065644Scg } 49150723Scg ldns_rr_free(*tlsa); 49250723Scg *tlsa = NULL; 49350723Scg return s; 49450723Scg 49550723Scgmemerror: 49629415Sjmg ldns_rr_free(*tlsa); 49750723Scg *tlsa = NULL; 49850723Scg return LDNS_STATUS_MEM_ERR; 49950723Scg} 50050723Scg 50150723Scg 50250723Scg/* Return tlsas that actually are TLSA resource records with known values 50350723Scg * for the Certificate usage, Selector and Matching type rdata fields. 50450723Scg */ 50550723Scgstatic ldns_rr_list* 50650723Scgldns_dane_filter_unusable_records(const ldns_rr_list* tlsas) 50750723Scg{ 50850723Scg size_t i; 50950723Scg ldns_rr_list* r = ldns_rr_list_new(); 51050723Scg ldns_rr* tlsa_rr; 51155706Scg 51255706Scg if (! r) { 51355706Scg return NULL; 51455706Scg } 51550723Scg for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) { 51650723Scg tlsa_rr = ldns_rr_list_rr(tlsas, i); 51755706Scg if (ldns_rr_get_type(tlsa_rr) == LDNS_RR_TYPE_TLSA && 51855706Scg ldns_rr_rd_count(tlsa_rr) == 4 && 51955706Scg ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) <= 3 && 52055706Scg ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) <= 1 && 52150723Scg ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) <= 2) { 52250723Scg 52350723Scg if (! ldns_rr_list_push_rr(r, tlsa_rr)) { 52450723Scg ldns_rr_list_free(r); 52550723Scg return NULL; 52650723Scg } 52750723Scg } 52850723Scg } 52950723Scg return r; 53055706Scg} 53155706Scg 53255706Scg 53355706Scg/* Return whether cert/selector/matching_type matches data. 53450723Scg */ 53531361Sjmgstatic ldns_status 53650723Scgldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector, 53755706Scg ldns_tlsa_matching_type matching_type, ldns_rdf* data) 53850723Scg{ 53950723Scg ldns_status s; 54050723Scg ldns_rdf* match_data; 54150723Scg 54255706Scg s = ldns_dane_cert2rdf(&match_data, cert, selector, matching_type); 54329415Sjmg if (s == LDNS_STATUS_OK) { 54450723Scg if (ldns_rdf_compare(data, match_data) != 0) { 54550723Scg s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH; 54650723Scg } 54750723Scg ldns_rdf_free(match_data); 54850723Scg } 54950723Scg return s; 55050723Scg} 55150723Scg 55250723Scg 55329415Sjmg/* Return whether any certificate from the chain with selector/matching_type 55450723Scg * matches data. 55555706Scg * ca should be true if the certificate has to be a CA certificate too. 55655706Scg */ 55729415Sjmgstatic ldns_status 55850723Scgldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain, 55950723Scg ldns_tlsa_selector selector, 56050723Scg ldns_tlsa_matching_type matching_type, 56150723Scg ldns_rdf* data, bool ca) 56250723Scg{ 56350723Scg ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH; 56455706Scg size_t n, i; 56555706Scg X509* cert; 56655706Scg 56755706Scg n = (size_t)sk_X509_num(chain); 56855706Scg for (i = 0; i < n; i++) { 56950723Scg cert = sk_X509_pop(chain); 57050723Scg if (! cert) { 57155706Scg s = LDNS_STATUS_SSL_ERR; 57255706Scg break; 57329415Sjmg } 57450723Scg s = ldns_dane_match_cert_with_data(cert, 57550723Scg selector, matching_type, data); 57650723Scg if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) { 57750723Scg s = LDNS_STATUS_DANE_NON_CA_CERTIFICATE; 57850723Scg } 57950723Scg X509_free(cert); 58050723Scg if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) { 58150723Scg break; 58250723Scg } 58350723Scg /* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH, 58450723Scg * try to match the next certificate 58550723Scg */ 58650723Scg } 58750723Scg return s; 58850723Scg} 58950723Scg 59050723Scg 59150723Scgldns_status 59250723Scgldns_dane_verify_rr(const ldns_rr* tlsa_rr, 59350723Scg X509* cert, STACK_OF(X509)* extra_certs, 59455706Scg X509_STORE* pkix_validation_store) 59555706Scg{ 59650723Scg ldns_status s; 59755706Scg 59850723Scg STACK_OF(X509)* pkix_validation_chain = NULL; 59929415Sjmg 60029415Sjmg ldns_tlsa_certificate_usage cert_usage; 60150723Scg ldns_tlsa_selector selector; 60250723Scg ldns_tlsa_matching_type matching_type; 60350723Scg ldns_rdf* data; 60450723Scg 60550723Scg if (! tlsa_rr) { 60650723Scg /* No TLSA, so regular PKIX validation 60750723Scg */ 60850723Scg return ldns_dane_pkix_validate(cert, extra_certs, 60954462Scg pkix_validation_store); 61054791Scg } 61129415Sjmg cert_usage = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)); 61255706Scg selector = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)); 61355706Scg matching_type = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)); 61450723Scg data = ldns_rr_rdf(tlsa_rr, 3) ; 61555706Scg 61655706Scg switch (cert_usage) { 61755706Scg case LDNS_TLSA_USAGE_CA_CONSTRAINT: 61855706Scg s = ldns_dane_pkix_validate_and_get_chain( 61950723Scg &pkix_validation_chain, 62055706Scg cert, extra_certs, 62155706Scg pkix_validation_store); 62255706Scg if (! pkix_validation_chain) { 62355706Scg return s; 62455706Scg } 62555706Scg if (s == LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) { 62650723Scg /* 62755706Scg * NO PKIX validation. We still try to match *any* 62855706Scg * certificate from the chain, so we return 62955706Scg * TLSA errors over PKIX errors. 63055706Scg * 63155706Scg * i.e. When the TLSA matches no certificate, we return 63255706Scg * TLSA_DID_NOT_MATCH and not PKIX_DID_NOT_VALIDATE 63355706Scg */ 63450723Scg s = ldns_dane_match_any_cert_with_data( 63550723Scg pkix_validation_chain, 63650723Scg selector, matching_type, data, true); 63750723Scg 63850723Scg if (s == LDNS_STATUS_OK) { 63950723Scg /* A TLSA record did match a cert from the 64050723Scg * chain, thus the error is failed PKIX 64129415Sjmg * validation. 64250723Scg */ 64350723Scg s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; 64450723Scg } 64529415Sjmg 64655706Scg } else if (s == LDNS_STATUS_OK) { 64755706Scg /* PKIX validated, does the TLSA match too? */ 64850723Scg 64950723Scg s = ldns_dane_match_any_cert_with_data( 65050723Scg pkix_validation_chain, 65150723Scg selector, matching_type, data, true); 65250723Scg } 65350723Scg sk_X509_pop_free(pkix_validation_chain, X509_free); 65450723Scg return s; 65550723Scg break; 65650723Scg 65729415Sjmg case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: 65855706Scg s = ldns_dane_match_cert_with_data(cert, 65955706Scg selector, matching_type, data); 66050723Scg 66150723Scg if (s == LDNS_STATUS_OK) { 66250723Scg return ldns_dane_pkix_validate(cert, extra_certs, 66329415Sjmg pkix_validation_store); 66455706Scg } 66555706Scg return s; 66655706Scg break; 66755706Scg 66855706Scg case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: 66955706Scg s = ldns_dane_pkix_get_chain(&pkix_validation_chain, 67055706Scg cert, extra_certs); 67155706Scg 67255706Scg if (s == LDNS_STATUS_OK) { 67355706Scg s = ldns_dane_match_any_cert_with_data( 67455706Scg pkix_validation_chain, 67555706Scg selector, matching_type, data, false); 67655706Scg 67755706Scg } else if (! pkix_validation_chain) { 67855706Scg return s; 67955706Scg } 68055706Scg sk_X509_pop_free(pkix_validation_chain, X509_free); 68155706Scg return s; 68255706Scg break; 68355706Scg 68455706Scg case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: 68555706Scg return ldns_dane_match_cert_with_data(cert, 68655706Scg selector, matching_type, data); 68755706Scg break; 68855706Scg 68955706Scg default: 69055706Scg break; 69155706Scg } 69255706Scg return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE; 69355706Scg} 69455706Scg 69555706Scg 69655706Scgldns_status 69755706Scgldns_dane_verify(ldns_rr_list* tlsas, 69855706Scg X509* cert, STACK_OF(X509)* extra_certs, 69955706Scg X509_STORE* pkix_validation_store) 70055706Scg{ 70155706Scg size_t i; 70255706Scg ldns_rr* tlsa_rr; 70355706Scg ldns_status s = LDNS_STATUS_OK, ps; 70455706Scg 70555706Scg assert(cert != NULL); 70655706Scg 70755706Scg if (tlsas && ldns_rr_list_rr_count(tlsas) > 0) { 70855706Scg tlsas = ldns_dane_filter_unusable_records(tlsas); 70955706Scg if (! tlsas) { 71055706Scg return LDNS_STATUS_MEM_ERR; 71155706Scg } 71255706Scg } 71355706Scg if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) { 71455706Scg /* No TLSA's, so regular PKIX validation 71555706Scg */ 71655706Scg return ldns_dane_pkix_validate(cert, extra_certs, 71755706Scg pkix_validation_store); 71855706Scg } else { 71955706Scg for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) { 72055706Scg tlsa_rr = ldns_rr_list_rr(tlsas, i); 72155706Scg ps = s; 72255706Scg s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs, 72355706Scg pkix_validation_store); 72455706Scg 72560958Scg if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH && 72655706Scg s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) { 72755706Scg 72855706Scg /* which would be LDNS_STATUS_OK (match) 72955706Scg * or some fatal error preventing use from 73055706Scg * trying the next TLSA record. 73155706Scg */ 73255706Scg break; 73355706Scg } 73455706Scg s = (s > ps ? s : ps); /* prefer PKIX_DID_NOT_VALIDATE 73555706Scg * over TLSA_DID_NOT_MATCH 73655706Scg */ 73755706Scg } 73855706Scg ldns_rr_list_free(tlsas); 73955706Scg } 74055706Scg return s; 74155706Scg} 74255706Scg#endif /* HAVE_SSL */ 74355706Scg