dane.c revision 246828
1246828Sdes/* 2246828Sdes * Verify or create TLS authentication with DANE (RFC6698) 3246828Sdes * 4246828Sdes * (c) NLnetLabs 2012 5246828Sdes * 6246828Sdes * See the file LICENSE for the license. 7246828Sdes * 8246828Sdes */ 9246828Sdes 10246828Sdes#include <ldns/config.h> 11246828Sdes 12246828Sdes#include <ldns/ldns.h> 13246828Sdes#include <ldns/dane.h> 14246828Sdes 15246828Sdes#include <unistd.h> 16246828Sdes#include <stdlib.h> 17246828Sdes#include <sys/types.h> 18246828Sdes#include <sys/socket.h> 19246828Sdes#include <netdb.h> 20246828Sdes 21246828Sdes#ifdef HAVE_SSL 22246828Sdes#include <openssl/ssl.h> 23246828Sdes#include <openssl/err.h> 24246828Sdes#include <openssl/x509v3.h> 25246828Sdes#endif 26246828Sdes 27246828Sdesldns_status 28246828Sdesldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name, 29246828Sdes uint16_t port, ldns_dane_transport transport) 30246828Sdes{ 31246828Sdes char buf[LDNS_MAX_DOMAINLEN]; 32246828Sdes size_t s; 33246828Sdes 34246828Sdes assert(tlsa_owner != NULL); 35246828Sdes assert(name != NULL); 36246828Sdes assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME); 37246828Sdes 38246828Sdes s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port); 39246828Sdes buf[0] = (char)(s - 1); 40246828Sdes 41246828Sdes switch(transport) { 42246828Sdes case LDNS_DANE_TRANSPORT_TCP: 43246828Sdes s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp"); 44246828Sdes break; 45246828Sdes 46246828Sdes case LDNS_DANE_TRANSPORT_UDP: 47246828Sdes s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp"); 48246828Sdes break; 49246828Sdes 50246828Sdes case LDNS_DANE_TRANSPORT_SCTP: 51246828Sdes s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp"); 52246828Sdes break; 53246828Sdes 54246828Sdes default: 55246828Sdes return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT; 56246828Sdes } 57246828Sdes if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) { 58246828Sdes return LDNS_STATUS_DOMAINNAME_OVERFLOW; 59246828Sdes } 60246828Sdes memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name)); 61246828Sdes *tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 62246828Sdes s + ldns_rdf_size(name), buf); 63246828Sdes if (*tlsa_owner == NULL) { 64246828Sdes return LDNS_STATUS_MEM_ERR; 65246828Sdes } 66246828Sdes return LDNS_STATUS_OK; 67246828Sdes} 68246828Sdes 69246828Sdes 70246828Sdes#ifdef HAVE_SSL 71246828Sdesldns_status 72246828Sdesldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert, 73246828Sdes ldns_tlsa_selector selector, 74246828Sdes ldns_tlsa_matching_type matching_type) 75246828Sdes{ 76246828Sdes unsigned char* buf = NULL; 77246828Sdes size_t len; 78246828Sdes 79246828Sdes X509_PUBKEY* xpubkey; 80246828Sdes EVP_PKEY* epubkey; 81246828Sdes 82246828Sdes unsigned char* digest; 83246828Sdes 84246828Sdes assert(rdf != NULL); 85246828Sdes assert(cert != NULL); 86246828Sdes 87246828Sdes switch(selector) { 88246828Sdes case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE: 89246828Sdes 90246828Sdes len = (size_t)i2d_X509(cert, &buf); 91246828Sdes break; 92246828Sdes 93246828Sdes case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO: 94246828Sdes 95246828Sdes#ifndef S_SPLINT_S 96246828Sdes xpubkey = X509_get_X509_PUBKEY(cert); 97246828Sdes#endif 98246828Sdes if (! xpubkey) { 99246828Sdes return LDNS_STATUS_SSL_ERR; 100246828Sdes } 101246828Sdes epubkey = X509_PUBKEY_get(xpubkey); 102246828Sdes if (! epubkey) { 103246828Sdes return LDNS_STATUS_SSL_ERR; 104246828Sdes } 105246828Sdes len = (size_t)i2d_PUBKEY(epubkey, &buf); 106246828Sdes break; 107246828Sdes 108246828Sdes default: 109246828Sdes return LDNS_STATUS_DANE_UNKNOWN_SELECTOR; 110246828Sdes } 111246828Sdes 112246828Sdes switch(matching_type) { 113246828Sdes case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED: 114246828Sdes 115246828Sdes *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf); 116246828Sdes 117246828Sdes return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 118246828Sdes break; 119246828Sdes 120246828Sdes case LDNS_TLSA_MATCHING_TYPE_SHA256: 121246828Sdes 122246828Sdes digest = LDNS_XMALLOC(unsigned char, SHA256_DIGEST_LENGTH); 123246828Sdes if (digest == NULL) { 124246828Sdes LDNS_FREE(buf); 125246828Sdes return LDNS_STATUS_MEM_ERR; 126246828Sdes } 127246828Sdes (void) ldns_sha256(buf, (unsigned int)len, digest); 128246828Sdes *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA256_DIGEST_LENGTH, 129246828Sdes digest); 130246828Sdes LDNS_FREE(buf); 131246828Sdes 132246828Sdes return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 133246828Sdes break; 134246828Sdes 135246828Sdes case LDNS_TLSA_MATCHING_TYPE_SHA512: 136246828Sdes 137246828Sdes digest = LDNS_XMALLOC(unsigned char, SHA512_DIGEST_LENGTH); 138246828Sdes if (digest == NULL) { 139246828Sdes LDNS_FREE(buf); 140246828Sdes return LDNS_STATUS_MEM_ERR; 141246828Sdes } 142246828Sdes (void) ldns_sha512(buf, (unsigned int)len, digest); 143246828Sdes *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA512_DIGEST_LENGTH, 144246828Sdes digest); 145246828Sdes LDNS_FREE(buf); 146246828Sdes 147246828Sdes return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 148246828Sdes break; 149246828Sdes 150246828Sdes default: 151246828Sdes LDNS_FREE(buf); 152246828Sdes return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE; 153246828Sdes } 154246828Sdes} 155246828Sdes 156246828Sdes 157246828Sdes/* Ordinary PKIX validation of cert (with extra_certs to help) 158246828Sdes * against the CA's in store 159246828Sdes */ 160246828Sdesstatic ldns_status 161246828Sdesldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs, 162246828Sdes X509_STORE* store) 163246828Sdes{ 164246828Sdes X509_STORE_CTX* vrfy_ctx; 165246828Sdes ldns_status s; 166246828Sdes 167246828Sdes if (! store) { 168246828Sdes return LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; 169246828Sdes } 170246828Sdes vrfy_ctx = X509_STORE_CTX_new(); 171246828Sdes if (! vrfy_ctx) { 172246828Sdes 173246828Sdes return LDNS_STATUS_SSL_ERR; 174246828Sdes 175246828Sdes } else if (X509_STORE_CTX_init(vrfy_ctx, store, 176246828Sdes cert, extra_certs) != 1) { 177246828Sdes s = LDNS_STATUS_SSL_ERR; 178246828Sdes 179246828Sdes } else if (X509_verify_cert(vrfy_ctx) == 1) { 180246828Sdes 181246828Sdes s = LDNS_STATUS_OK; 182246828Sdes 183246828Sdes } else { 184246828Sdes s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; 185246828Sdes } 186246828Sdes X509_STORE_CTX_free(vrfy_ctx); 187246828Sdes return s; 188246828Sdes} 189246828Sdes 190246828Sdes 191246828Sdes/* Orinary PKIX validation of cert (with extra_certs to help) 192246828Sdes * against the CA's in store, but also return the validation chain. 193246828Sdes */ 194246828Sdesstatic ldns_status 195246828Sdesldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert, 196246828Sdes STACK_OF(X509)* extra_certs, X509_STORE* store) 197246828Sdes{ 198246828Sdes ldns_status s; 199246828Sdes X509_STORE* empty_store = NULL; 200246828Sdes X509_STORE_CTX* vrfy_ctx; 201246828Sdes 202246828Sdes assert(chain != NULL); 203246828Sdes 204246828Sdes if (! store) { 205246828Sdes store = empty_store = X509_STORE_new(); 206246828Sdes } 207246828Sdes s = LDNS_STATUS_SSL_ERR; 208246828Sdes vrfy_ctx = X509_STORE_CTX_new(); 209246828Sdes if (! vrfy_ctx) { 210246828Sdes 211246828Sdes goto exit_free_empty_store; 212246828Sdes 213246828Sdes } else if (X509_STORE_CTX_init(vrfy_ctx, store, 214246828Sdes cert, extra_certs) != 1) { 215246828Sdes goto exit_free_vrfy_ctx; 216246828Sdes 217246828Sdes } else if (X509_verify_cert(vrfy_ctx) == 1) { 218246828Sdes 219246828Sdes s = LDNS_STATUS_OK; 220246828Sdes 221246828Sdes } else { 222246828Sdes s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; 223246828Sdes } 224246828Sdes *chain = X509_STORE_CTX_get1_chain(vrfy_ctx); 225246828Sdes if (! *chain) { 226246828Sdes s = LDNS_STATUS_SSL_ERR; 227246828Sdes } 228246828Sdes 229246828Sdesexit_free_vrfy_ctx: 230246828Sdes X509_STORE_CTX_free(vrfy_ctx); 231246828Sdes 232246828Sdesexit_free_empty_store: 233246828Sdes if (empty_store) { 234246828Sdes X509_STORE_free(empty_store); 235246828Sdes } 236246828Sdes return s; 237246828Sdes} 238246828Sdes 239246828Sdes 240246828Sdes/* Return the validation chain that can be build out of cert, with extra_certs. 241246828Sdes */ 242246828Sdesstatic ldns_status 243246828Sdesldns_dane_pkix_get_chain(STACK_OF(X509)** chain, 244246828Sdes X509* cert, STACK_OF(X509)* extra_certs) 245246828Sdes{ 246246828Sdes ldns_status s; 247246828Sdes X509_STORE* empty_store = NULL; 248246828Sdes X509_STORE_CTX* vrfy_ctx; 249246828Sdes 250246828Sdes assert(chain != NULL); 251246828Sdes 252246828Sdes empty_store = X509_STORE_new(); 253246828Sdes s = LDNS_STATUS_SSL_ERR; 254246828Sdes vrfy_ctx = X509_STORE_CTX_new(); 255246828Sdes if (! vrfy_ctx) { 256246828Sdes 257246828Sdes goto exit_free_empty_store; 258246828Sdes 259246828Sdes } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store, 260246828Sdes cert, extra_certs) != 1) { 261246828Sdes goto exit_free_vrfy_ctx; 262246828Sdes } 263246828Sdes (void) X509_verify_cert(vrfy_ctx); 264246828Sdes *chain = X509_STORE_CTX_get1_chain(vrfy_ctx); 265246828Sdes if (! *chain) { 266246828Sdes s = LDNS_STATUS_SSL_ERR; 267246828Sdes } else { 268246828Sdes s = LDNS_STATUS_OK; 269246828Sdes } 270246828Sdesexit_free_vrfy_ctx: 271246828Sdes X509_STORE_CTX_free(vrfy_ctx); 272246828Sdes 273246828Sdesexit_free_empty_store: 274246828Sdes X509_STORE_free(empty_store); 275246828Sdes return s; 276246828Sdes} 277246828Sdes 278246828Sdes 279246828Sdes/* Pop n+1 certs and return the last popped. 280246828Sdes */ 281246828Sdesstatic ldns_status 282246828Sdesldns_dane_get_nth_cert_from_validation_chain( 283246828Sdes X509** cert, STACK_OF(X509)* chain, int n, bool ca) 284246828Sdes{ 285246828Sdes if (n >= sk_X509_num(chain) || n < 0) { 286246828Sdes return LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE; 287246828Sdes } 288246828Sdes *cert = sk_X509_pop(chain); 289246828Sdes while (n-- > 0) { 290246828Sdes X509_free(*cert); 291246828Sdes *cert = sk_X509_pop(chain); 292246828Sdes } 293246828Sdes if (ca && ! X509_check_ca(*cert)) { 294246828Sdes return LDNS_STATUS_DANE_NON_CA_CERTIFICATE; 295246828Sdes } 296246828Sdes return LDNS_STATUS_OK; 297246828Sdes} 298246828Sdes 299246828Sdes 300246828Sdes/* Create validation chain with cert and extra_certs and returns the last 301246828Sdes * self-signed (if present). 302246828Sdes */ 303246828Sdesstatic ldns_status 304246828Sdesldns_dane_pkix_get_last_self_signed(X509** out_cert, 305246828Sdes X509* cert, STACK_OF(X509)* extra_certs) 306246828Sdes{ 307246828Sdes ldns_status s; 308246828Sdes X509_STORE* empty_store = NULL; 309246828Sdes X509_STORE_CTX* vrfy_ctx; 310246828Sdes 311246828Sdes assert(out_cert != NULL); 312246828Sdes 313246828Sdes empty_store = X509_STORE_new(); 314246828Sdes s = LDNS_STATUS_SSL_ERR; 315246828Sdes vrfy_ctx = X509_STORE_CTX_new(); 316246828Sdes if (! vrfy_ctx) { 317246828Sdes goto exit_free_empty_store; 318246828Sdes 319246828Sdes } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store, 320246828Sdes cert, extra_certs) != 1) { 321246828Sdes goto exit_free_vrfy_ctx; 322246828Sdes 323246828Sdes } 324246828Sdes (void) X509_verify_cert(vrfy_ctx); 325246828Sdes if (vrfy_ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || 326246828Sdes vrfy_ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){ 327246828Sdes 328246828Sdes *out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx); 329246828Sdes s = LDNS_STATUS_OK; 330246828Sdes } else { 331246828Sdes s = LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR; 332246828Sdes } 333246828Sdesexit_free_vrfy_ctx: 334246828Sdes X509_STORE_CTX_free(vrfy_ctx); 335246828Sdes 336246828Sdesexit_free_empty_store: 337246828Sdes X509_STORE_free(empty_store); 338246828Sdes return s; 339246828Sdes} 340246828Sdes 341246828Sdes 342246828Sdesldns_status 343246828Sdesldns_dane_select_certificate(X509** selected_cert, 344246828Sdes X509* cert, STACK_OF(X509)* extra_certs, 345246828Sdes X509_STORE* pkix_validation_store, 346246828Sdes ldns_tlsa_certificate_usage cert_usage, int offset) 347246828Sdes{ 348246828Sdes ldns_status s; 349246828Sdes STACK_OF(X509)* pkix_validation_chain = NULL; 350246828Sdes 351246828Sdes assert(selected_cert != NULL); 352246828Sdes assert(cert != NULL); 353246828Sdes 354246828Sdes /* With PKIX validation explicitely turned off (pkix_validation_store 355246828Sdes * == NULL), treat the "CA constraint" and "Service certificate 356246828Sdes * constraint" the same as "Trust anchor assertion" and "Domain issued 357246828Sdes * certificate" respectively. 358246828Sdes */ 359246828Sdes if (pkix_validation_store == NULL) { 360246828Sdes switch (cert_usage) { 361246828Sdes 362246828Sdes case LDNS_TLSA_USAGE_CA_CONSTRAINT: 363246828Sdes 364246828Sdes cert_usage = LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION; 365246828Sdes break; 366246828Sdes 367246828Sdes case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: 368246828Sdes 369246828Sdes cert_usage = LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE; 370246828Sdes break; 371246828Sdes 372246828Sdes default: 373246828Sdes break; 374246828Sdes } 375246828Sdes } 376246828Sdes 377246828Sdes /* Now what to do with each Certificate usage... 378246828Sdes */ 379246828Sdes switch (cert_usage) { 380246828Sdes 381246828Sdes case LDNS_TLSA_USAGE_CA_CONSTRAINT: 382246828Sdes 383246828Sdes s = ldns_dane_pkix_validate_and_get_chain( 384246828Sdes &pkix_validation_chain, 385246828Sdes cert, extra_certs, 386246828Sdes pkix_validation_store); 387246828Sdes if (! pkix_validation_chain) { 388246828Sdes return s; 389246828Sdes } 390246828Sdes if (s == LDNS_STATUS_OK) { 391246828Sdes if (offset == -1) { 392246828Sdes offset = 0; 393246828Sdes } 394246828Sdes s = ldns_dane_get_nth_cert_from_validation_chain( 395246828Sdes selected_cert, pkix_validation_chain, 396246828Sdes offset, true); 397246828Sdes } 398246828Sdes sk_X509_pop_free(pkix_validation_chain, X509_free); 399246828Sdes return s; 400246828Sdes break; 401246828Sdes 402246828Sdes 403246828Sdes case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: 404246828Sdes 405246828Sdes *selected_cert = cert; 406246828Sdes return ldns_dane_pkix_validate(cert, extra_certs, 407246828Sdes pkix_validation_store); 408246828Sdes break; 409246828Sdes 410246828Sdes 411246828Sdes case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: 412246828Sdes 413246828Sdes if (offset == -1) { 414246828Sdes s = ldns_dane_pkix_get_last_self_signed( 415246828Sdes selected_cert, cert, extra_certs); 416246828Sdes return s; 417246828Sdes } else { 418246828Sdes s = ldns_dane_pkix_get_chain( 419246828Sdes &pkix_validation_chain, 420246828Sdes cert, extra_certs); 421246828Sdes if (s == LDNS_STATUS_OK) { 422246828Sdes s = 423246828Sdes ldns_dane_get_nth_cert_from_validation_chain( 424246828Sdes selected_cert, pkix_validation_chain, 425246828Sdes offset, false); 426246828Sdes } else if (! pkix_validation_chain) { 427246828Sdes return s; 428246828Sdes } 429246828Sdes sk_X509_pop_free(pkix_validation_chain, X509_free); 430246828Sdes return s; 431246828Sdes } 432246828Sdes break; 433246828Sdes 434246828Sdes 435246828Sdes case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: 436246828Sdes 437246828Sdes *selected_cert = cert; 438246828Sdes return LDNS_STATUS_OK; 439246828Sdes break; 440246828Sdes 441246828Sdes default: 442246828Sdes return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE; 443246828Sdes break; 444246828Sdes } 445246828Sdes} 446246828Sdes 447246828Sdes 448246828Sdesldns_status 449246828Sdesldns_dane_create_tlsa_rr(ldns_rr** tlsa, 450246828Sdes ldns_tlsa_certificate_usage certificate_usage, 451246828Sdes ldns_tlsa_selector selector, 452246828Sdes ldns_tlsa_matching_type matching_type, 453246828Sdes X509* cert) 454246828Sdes{ 455246828Sdes ldns_rdf* rdf; 456246828Sdes ldns_status s; 457246828Sdes 458246828Sdes assert(tlsa != NULL); 459246828Sdes assert(cert != NULL); 460246828Sdes 461246828Sdes /* create rr */ 462246828Sdes *tlsa = ldns_rr_new_frm_type(LDNS_RR_TYPE_TLSA); 463246828Sdes if (*tlsa == NULL) { 464246828Sdes return LDNS_STATUS_MEM_ERR; 465246828Sdes } 466246828Sdes 467246828Sdes rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 468246828Sdes (uint8_t)certificate_usage); 469246828Sdes if (rdf == NULL) { 470246828Sdes goto memerror; 471246828Sdes } 472246828Sdes (void) ldns_rr_set_rdf(*tlsa, rdf, 0); 473246828Sdes 474246828Sdes rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)selector); 475246828Sdes if (rdf == NULL) { 476246828Sdes goto memerror; 477246828Sdes } 478246828Sdes (void) ldns_rr_set_rdf(*tlsa, rdf, 1); 479246828Sdes 480246828Sdes rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)matching_type); 481246828Sdes if (rdf == NULL) { 482246828Sdes goto memerror; 483246828Sdes } 484246828Sdes (void) ldns_rr_set_rdf(*tlsa, rdf, 2); 485246828Sdes 486246828Sdes s = ldns_dane_cert2rdf(&rdf, cert, selector, matching_type); 487246828Sdes if (s == LDNS_STATUS_OK) { 488246828Sdes (void) ldns_rr_set_rdf(*tlsa, rdf, 3); 489246828Sdes return LDNS_STATUS_OK; 490246828Sdes } 491246828Sdes ldns_rr_free(*tlsa); 492246828Sdes *tlsa = NULL; 493246828Sdes return s; 494246828Sdes 495246828Sdesmemerror: 496246828Sdes ldns_rr_free(*tlsa); 497246828Sdes *tlsa = NULL; 498246828Sdes return LDNS_STATUS_MEM_ERR; 499246828Sdes} 500246828Sdes 501246828Sdes 502246828Sdes/* Return tlsas that actually are TLSA resource records with known values 503246828Sdes * for the Certificate usage, Selector and Matching type rdata fields. 504246828Sdes */ 505246828Sdesstatic ldns_rr_list* 506246828Sdesldns_dane_filter_unusable_records(const ldns_rr_list* tlsas) 507246828Sdes{ 508246828Sdes size_t i; 509246828Sdes ldns_rr_list* r = ldns_rr_list_new(); 510246828Sdes ldns_rr* tlsa_rr; 511246828Sdes 512246828Sdes if (! r) { 513246828Sdes return NULL; 514246828Sdes } 515246828Sdes for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) { 516246828Sdes tlsa_rr = ldns_rr_list_rr(tlsas, i); 517246828Sdes if (ldns_rr_get_type(tlsa_rr) == LDNS_RR_TYPE_TLSA && 518246828Sdes ldns_rr_rd_count(tlsa_rr) == 4 && 519246828Sdes ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) <= 3 && 520246828Sdes ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) <= 1 && 521246828Sdes ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) <= 2) { 522246828Sdes 523246828Sdes if (! ldns_rr_list_push_rr(r, tlsa_rr)) { 524246828Sdes ldns_rr_list_free(r); 525246828Sdes return NULL; 526246828Sdes } 527246828Sdes } 528246828Sdes } 529246828Sdes return r; 530246828Sdes} 531246828Sdes 532246828Sdes 533246828Sdes/* Return whether cert/selector/matching_type matches data. 534246828Sdes */ 535246828Sdesstatic ldns_status 536246828Sdesldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector, 537246828Sdes ldns_tlsa_matching_type matching_type, ldns_rdf* data) 538246828Sdes{ 539246828Sdes ldns_status s; 540246828Sdes ldns_rdf* match_data; 541246828Sdes 542246828Sdes s = ldns_dane_cert2rdf(&match_data, cert, selector, matching_type); 543246828Sdes if (s == LDNS_STATUS_OK) { 544246828Sdes if (ldns_rdf_compare(data, match_data) != 0) { 545246828Sdes s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH; 546246828Sdes } 547246828Sdes ldns_rdf_free(match_data); 548246828Sdes } 549246828Sdes return s; 550246828Sdes} 551246828Sdes 552246828Sdes 553246828Sdes/* Return whether any certificate from the chain with selector/matching_type 554246828Sdes * matches data. 555246828Sdes * ca should be true if the certificate has to be a CA certificate too. 556246828Sdes */ 557246828Sdesstatic ldns_status 558246828Sdesldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain, 559246828Sdes ldns_tlsa_selector selector, 560246828Sdes ldns_tlsa_matching_type matching_type, 561246828Sdes ldns_rdf* data, bool ca) 562246828Sdes{ 563246828Sdes ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH; 564246828Sdes size_t n, i; 565246828Sdes X509* cert; 566246828Sdes 567246828Sdes n = (size_t)sk_X509_num(chain); 568246828Sdes for (i = 0; i < n; i++) { 569246828Sdes cert = sk_X509_pop(chain); 570246828Sdes if (! cert) { 571246828Sdes s = LDNS_STATUS_SSL_ERR; 572246828Sdes break; 573246828Sdes } 574246828Sdes s = ldns_dane_match_cert_with_data(cert, 575246828Sdes selector, matching_type, data); 576246828Sdes if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) { 577246828Sdes s = LDNS_STATUS_DANE_NON_CA_CERTIFICATE; 578246828Sdes } 579246828Sdes X509_free(cert); 580246828Sdes if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) { 581246828Sdes break; 582246828Sdes } 583246828Sdes /* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH, 584246828Sdes * try to match the next certificate 585246828Sdes */ 586246828Sdes } 587246828Sdes return s; 588246828Sdes} 589246828Sdes 590246828Sdes 591246828Sdesldns_status 592246828Sdesldns_dane_verify_rr(const ldns_rr* tlsa_rr, 593246828Sdes X509* cert, STACK_OF(X509)* extra_certs, 594246828Sdes X509_STORE* pkix_validation_store) 595246828Sdes{ 596246828Sdes ldns_status s; 597246828Sdes 598246828Sdes STACK_OF(X509)* pkix_validation_chain = NULL; 599246828Sdes 600246828Sdes ldns_tlsa_certificate_usage cert_usage; 601246828Sdes ldns_tlsa_selector selector; 602246828Sdes ldns_tlsa_matching_type matching_type; 603246828Sdes ldns_rdf* data; 604246828Sdes 605246828Sdes if (! tlsa_rr) { 606246828Sdes /* No TLSA, so regular PKIX validation 607246828Sdes */ 608246828Sdes return ldns_dane_pkix_validate(cert, extra_certs, 609246828Sdes pkix_validation_store); 610246828Sdes } 611246828Sdes cert_usage = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)); 612246828Sdes selector = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)); 613246828Sdes matching_type = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)); 614246828Sdes data = ldns_rr_rdf(tlsa_rr, 3) ; 615246828Sdes 616246828Sdes switch (cert_usage) { 617246828Sdes case LDNS_TLSA_USAGE_CA_CONSTRAINT: 618246828Sdes s = ldns_dane_pkix_validate_and_get_chain( 619246828Sdes &pkix_validation_chain, 620246828Sdes cert, extra_certs, 621246828Sdes pkix_validation_store); 622246828Sdes if (! pkix_validation_chain) { 623246828Sdes return s; 624246828Sdes } 625246828Sdes if (s == LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) { 626246828Sdes /* 627246828Sdes * NO PKIX validation. We still try to match *any* 628246828Sdes * certificate from the chain, so we return 629246828Sdes * TLSA errors over PKIX errors. 630246828Sdes * 631246828Sdes * i.e. When the TLSA matches no certificate, we return 632246828Sdes * TLSA_DID_NOT_MATCH and not PKIX_DID_NOT_VALIDATE 633246828Sdes */ 634246828Sdes s = ldns_dane_match_any_cert_with_data( 635246828Sdes pkix_validation_chain, 636246828Sdes selector, matching_type, data, true); 637246828Sdes 638246828Sdes if (s == LDNS_STATUS_OK) { 639246828Sdes /* A TLSA record did match a cert from the 640246828Sdes * chain, thus the error is failed PKIX 641246828Sdes * validation. 642246828Sdes */ 643246828Sdes s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; 644246828Sdes } 645246828Sdes 646246828Sdes } else if (s == LDNS_STATUS_OK) { 647246828Sdes /* PKIX validated, does the TLSA match too? */ 648246828Sdes 649246828Sdes s = ldns_dane_match_any_cert_with_data( 650246828Sdes pkix_validation_chain, 651246828Sdes selector, matching_type, data, true); 652246828Sdes } 653246828Sdes sk_X509_pop_free(pkix_validation_chain, X509_free); 654246828Sdes return s; 655246828Sdes break; 656246828Sdes 657246828Sdes case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: 658246828Sdes s = ldns_dane_match_cert_with_data(cert, 659246828Sdes selector, matching_type, data); 660246828Sdes 661246828Sdes if (s == LDNS_STATUS_OK) { 662246828Sdes return ldns_dane_pkix_validate(cert, extra_certs, 663246828Sdes pkix_validation_store); 664246828Sdes } 665246828Sdes return s; 666246828Sdes break; 667246828Sdes 668246828Sdes case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: 669246828Sdes s = ldns_dane_pkix_get_chain(&pkix_validation_chain, 670246828Sdes cert, extra_certs); 671246828Sdes 672246828Sdes if (s == LDNS_STATUS_OK) { 673246828Sdes s = ldns_dane_match_any_cert_with_data( 674246828Sdes pkix_validation_chain, 675246828Sdes selector, matching_type, data, false); 676246828Sdes 677246828Sdes } else if (! pkix_validation_chain) { 678246828Sdes return s; 679246828Sdes } 680246828Sdes sk_X509_pop_free(pkix_validation_chain, X509_free); 681246828Sdes return s; 682246828Sdes break; 683246828Sdes 684246828Sdes case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: 685246828Sdes return ldns_dane_match_cert_with_data(cert, 686246828Sdes selector, matching_type, data); 687246828Sdes break; 688246828Sdes 689246828Sdes default: 690246828Sdes break; 691246828Sdes } 692246828Sdes return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE; 693246828Sdes} 694246828Sdes 695246828Sdes 696246828Sdesldns_status 697246828Sdesldns_dane_verify(ldns_rr_list* tlsas, 698246828Sdes X509* cert, STACK_OF(X509)* extra_certs, 699246828Sdes X509_STORE* pkix_validation_store) 700246828Sdes{ 701246828Sdes size_t i; 702246828Sdes ldns_rr* tlsa_rr; 703246828Sdes ldns_status s = LDNS_STATUS_OK, ps; 704246828Sdes 705246828Sdes assert(cert != NULL); 706246828Sdes 707246828Sdes if (tlsas && ldns_rr_list_rr_count(tlsas) > 0) { 708246828Sdes tlsas = ldns_dane_filter_unusable_records(tlsas); 709246828Sdes if (! tlsas) { 710246828Sdes return LDNS_STATUS_MEM_ERR; 711246828Sdes } 712246828Sdes } 713246828Sdes if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) { 714246828Sdes /* No TLSA's, so regular PKIX validation 715246828Sdes */ 716246828Sdes return ldns_dane_pkix_validate(cert, extra_certs, 717246828Sdes pkix_validation_store); 718246828Sdes } else { 719246828Sdes for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) { 720246828Sdes tlsa_rr = ldns_rr_list_rr(tlsas, i); 721246828Sdes ps = s; 722246828Sdes s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs, 723246828Sdes pkix_validation_store); 724246828Sdes 725246828Sdes if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH && 726246828Sdes s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) { 727246828Sdes 728246828Sdes /* which would be LDNS_STATUS_OK (match) 729246828Sdes * or some fatal error preventing use from 730246828Sdes * trying the next TLSA record. 731246828Sdes */ 732246828Sdes break; 733246828Sdes } 734246828Sdes s = (s > ps ? s : ps); /* prefer PKIX_DID_NOT_VALIDATE 735246828Sdes * over TLSA_DID_NOT_MATCH 736246828Sdes */ 737246828Sdes } 738246828Sdes ldns_rr_list_free(tlsas); 739246828Sdes } 740246828Sdes return s; 741246828Sdes} 742246828Sdes#endif /* HAVE_SSL */ 743