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