12787e39aSDag-Erling Smørgrav /*
22787e39aSDag-Erling Smørgrav * Verify or create TLS authentication with DANE (RFC6698)
32787e39aSDag-Erling Smørgrav *
4*5afab0e5SDag-Erling Smørgrav * (c) NLnetLabs 2012-2020
52787e39aSDag-Erling Smørgrav *
62787e39aSDag-Erling Smørgrav * See the file LICENSE for the license.
72787e39aSDag-Erling Smørgrav *
82787e39aSDag-Erling Smørgrav */
92787e39aSDag-Erling Smørgrav
102787e39aSDag-Erling Smørgrav #include <ldns/config.h>
1117d15b25SDag-Erling Smørgrav #ifdef USE_DANE
122787e39aSDag-Erling Smørgrav
132787e39aSDag-Erling Smørgrav #include <ldns/ldns.h>
142787e39aSDag-Erling Smørgrav #include <ldns/dane.h>
152787e39aSDag-Erling Smørgrav
162787e39aSDag-Erling Smørgrav #include <unistd.h>
172787e39aSDag-Erling Smørgrav #include <stdlib.h>
182787e39aSDag-Erling Smørgrav #include <sys/types.h>
1917d15b25SDag-Erling Smørgrav #ifdef HAVE_SYS_SOCKET_H
202787e39aSDag-Erling Smørgrav #include <sys/socket.h>
2117d15b25SDag-Erling Smørgrav #endif
2217d15b25SDag-Erling Smørgrav #ifdef HAVE_NETDB_H
232787e39aSDag-Erling Smørgrav #include <netdb.h>
2417d15b25SDag-Erling Smørgrav #endif
252787e39aSDag-Erling Smørgrav
262787e39aSDag-Erling Smørgrav #ifdef HAVE_SSL
272787e39aSDag-Erling Smørgrav #include <openssl/ssl.h>
282787e39aSDag-Erling Smørgrav #include <openssl/err.h>
292787e39aSDag-Erling Smørgrav #include <openssl/x509v3.h>
302787e39aSDag-Erling Smørgrav #endif
312787e39aSDag-Erling Smørgrav
32*5afab0e5SDag-Erling Smørgrav /* OpenSSL context options. At the moment, disable SSLv2, SSLv3
33*5afab0e5SDag-Erling Smørgrav * and Compression, if available. TLSv1.0 is allowed at the moment.
34*5afab0e5SDag-Erling Smørgrav * TLSv1.1 is the first to provide elliptic curves, so it is usually
35*5afab0e5SDag-Erling Smørgrav * allowed in a TLS stack. TLSv1.2 is the first to provide authentication
36*5afab0e5SDag-Erling Smørgrav * modes of operation, like GCM. The defines below are a moving
37*5afab0e5SDag-Erling Smørgrav * target based on OpenSSL library version. Grep is useful to find
38*5afab0e5SDag-Erling Smørgrav * the defines: grep -IR SSL_OP_NO_ /usr/include/openssl.
39*5afab0e5SDag-Erling Smørgrav */
40*5afab0e5SDag-Erling Smørgrav #ifdef HAVE_SSL
41*5afab0e5SDag-Erling Smørgrav # ifdef SSL_OP_NO_SSLv2
42*5afab0e5SDag-Erling Smørgrav const long NoOpenSSLv2 = SSL_OP_NO_SSLv2;
43*5afab0e5SDag-Erling Smørgrav # else
44*5afab0e5SDag-Erling Smørgrav const long NoOpenSSLv2 = 0L;
45*5afab0e5SDag-Erling Smørgrav # endif
46*5afab0e5SDag-Erling Smørgrav # ifdef SSL_OP_NO_SSLv3
47*5afab0e5SDag-Erling Smørgrav const long NoOpenSSLv3 = SSL_OP_NO_SSLv3;
48*5afab0e5SDag-Erling Smørgrav # else
49*5afab0e5SDag-Erling Smørgrav const long NoOpenSSLv3 = 0L;
50*5afab0e5SDag-Erling Smørgrav # endif
51*5afab0e5SDag-Erling Smørgrav # ifdef SSL_OP_NO_TLSv1
52*5afab0e5SDag-Erling Smørgrav const long NoOpenTLSv1 = SSL_OP_NO_TLSv1;
53*5afab0e5SDag-Erling Smørgrav # else
54*5afab0e5SDag-Erling Smørgrav const long NoOpenTLSv1 = 0L;
55*5afab0e5SDag-Erling Smørgrav # endif
56*5afab0e5SDag-Erling Smørgrav # ifdef SSL_OP_NO_DTLSv1
57*5afab0e5SDag-Erling Smørgrav const long NoOpenDTLSv1 = SSL_OP_NO_DTLSv1;
58*5afab0e5SDag-Erling Smørgrav # else
59*5afab0e5SDag-Erling Smørgrav const long NoOpenDTLSv1 = 0L;
60*5afab0e5SDag-Erling Smørgrav # endif
61*5afab0e5SDag-Erling Smørgrav # ifdef SSL_OP_NO_COMPRESSION
62*5afab0e5SDag-Erling Smørgrav const long NoOpenSSLCompression = SSL_OP_NO_COMPRESSION;
63*5afab0e5SDag-Erling Smørgrav # else
64*5afab0e5SDag-Erling Smørgrav const long NoOpenSSLCompression = 0L;
65*5afab0e5SDag-Erling Smørgrav # endif
66*5afab0e5SDag-Erling Smørgrav #endif
67*5afab0e5SDag-Erling Smørgrav
68*5afab0e5SDag-Erling Smørgrav #if defined(USE_DANE_VERIFY) && defined(USE_DANE_TA_USAGE)
69*5afab0e5SDag-Erling Smørgrav static SSL_CTX*
ldns_dane_new_ssl_context(void)70*5afab0e5SDag-Erling Smørgrav ldns_dane_new_ssl_context(void)
71*5afab0e5SDag-Erling Smørgrav {
72*5afab0e5SDag-Erling Smørgrav SSL_CTX* ssl_ctx;
73*5afab0e5SDag-Erling Smørgrav
74*5afab0e5SDag-Erling Smørgrav ssl_ctx = SSL_CTX_new(TLS_client_method());
75*5afab0e5SDag-Erling Smørgrav if (ssl_ctx != NULL)
76*5afab0e5SDag-Erling Smørgrav {
77*5afab0e5SDag-Erling Smørgrav /* ldns allows TLS and DTLS v1.0 at the moment. Some may disagree.
78*5afab0e5SDag-Erling Smørgrav * Sometime in the future they may be disabled, too. Maybe
79*5afab0e5SDag-Erling Smørgrav * --disable-tlsv1 and --disable-dtlsv1 should be configure options.
80*5afab0e5SDag-Erling Smørgrav */
81*5afab0e5SDag-Erling Smørgrav long flags = NoOpenSSLv2 | NoOpenSSLv3 | NoOpenSSLCompression;
82*5afab0e5SDag-Erling Smørgrav SSL_CTX_set_options(ssl_ctx, flags);
83*5afab0e5SDag-Erling Smørgrav }
84*5afab0e5SDag-Erling Smørgrav
85*5afab0e5SDag-Erling Smørgrav return ssl_ctx;
86*5afab0e5SDag-Erling Smørgrav }
87*5afab0e5SDag-Erling Smørgrav #endif
88*5afab0e5SDag-Erling Smørgrav
892787e39aSDag-Erling Smørgrav ldns_status
ldns_dane_create_tlsa_owner(ldns_rdf ** tlsa_owner,const ldns_rdf * name,uint16_t port,ldns_dane_transport transport)902787e39aSDag-Erling Smørgrav ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name,
912787e39aSDag-Erling Smørgrav uint16_t port, ldns_dane_transport transport)
922787e39aSDag-Erling Smørgrav {
932787e39aSDag-Erling Smørgrav char buf[LDNS_MAX_DOMAINLEN];
942787e39aSDag-Erling Smørgrav size_t s;
952787e39aSDag-Erling Smørgrav
962787e39aSDag-Erling Smørgrav assert(tlsa_owner != NULL);
972787e39aSDag-Erling Smørgrav assert(name != NULL);
982787e39aSDag-Erling Smørgrav assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME);
992787e39aSDag-Erling Smørgrav
1002787e39aSDag-Erling Smørgrav s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port);
1012787e39aSDag-Erling Smørgrav buf[0] = (char)(s - 1);
1022787e39aSDag-Erling Smørgrav
1032787e39aSDag-Erling Smørgrav switch(transport) {
1042787e39aSDag-Erling Smørgrav case LDNS_DANE_TRANSPORT_TCP:
1052787e39aSDag-Erling Smørgrav s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp");
1062787e39aSDag-Erling Smørgrav break;
1072787e39aSDag-Erling Smørgrav
1082787e39aSDag-Erling Smørgrav case LDNS_DANE_TRANSPORT_UDP:
1092787e39aSDag-Erling Smørgrav s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp");
1102787e39aSDag-Erling Smørgrav break;
1112787e39aSDag-Erling Smørgrav
1122787e39aSDag-Erling Smørgrav case LDNS_DANE_TRANSPORT_SCTP:
1132787e39aSDag-Erling Smørgrav s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp");
1142787e39aSDag-Erling Smørgrav break;
1152787e39aSDag-Erling Smørgrav
1162787e39aSDag-Erling Smørgrav default:
1172787e39aSDag-Erling Smørgrav return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT;
1182787e39aSDag-Erling Smørgrav }
1192787e39aSDag-Erling Smørgrav if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) {
1202787e39aSDag-Erling Smørgrav return LDNS_STATUS_DOMAINNAME_OVERFLOW;
1212787e39aSDag-Erling Smørgrav }
1222787e39aSDag-Erling Smørgrav memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name));
1232787e39aSDag-Erling Smørgrav *tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
1242787e39aSDag-Erling Smørgrav s + ldns_rdf_size(name), buf);
1252787e39aSDag-Erling Smørgrav if (*tlsa_owner == NULL) {
1262787e39aSDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1272787e39aSDag-Erling Smørgrav }
1282787e39aSDag-Erling Smørgrav return LDNS_STATUS_OK;
1292787e39aSDag-Erling Smørgrav }
1302787e39aSDag-Erling Smørgrav
1312787e39aSDag-Erling Smørgrav
1322787e39aSDag-Erling Smørgrav #ifdef HAVE_SSL
1332787e39aSDag-Erling Smørgrav ldns_status
ldns_dane_cert2rdf(ldns_rdf ** rdf,X509 * cert,ldns_tlsa_selector selector,ldns_tlsa_matching_type matching_type)1342787e39aSDag-Erling Smørgrav ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
1352787e39aSDag-Erling Smørgrav ldns_tlsa_selector selector,
1362787e39aSDag-Erling Smørgrav ldns_tlsa_matching_type matching_type)
1372787e39aSDag-Erling Smørgrav {
1382787e39aSDag-Erling Smørgrav unsigned char* buf = NULL;
1392787e39aSDag-Erling Smørgrav size_t len;
1402787e39aSDag-Erling Smørgrav
1412787e39aSDag-Erling Smørgrav X509_PUBKEY* xpubkey;
1422787e39aSDag-Erling Smørgrav EVP_PKEY* epubkey;
1432787e39aSDag-Erling Smørgrav
1442787e39aSDag-Erling Smørgrav unsigned char* digest;
1452787e39aSDag-Erling Smørgrav
1462787e39aSDag-Erling Smørgrav assert(rdf != NULL);
1472787e39aSDag-Erling Smørgrav assert(cert != NULL);
1482787e39aSDag-Erling Smørgrav
1492787e39aSDag-Erling Smørgrav switch(selector) {
1502787e39aSDag-Erling Smørgrav case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE:
1512787e39aSDag-Erling Smørgrav
1522787e39aSDag-Erling Smørgrav len = (size_t)i2d_X509(cert, &buf);
1532787e39aSDag-Erling Smørgrav break;
1542787e39aSDag-Erling Smørgrav
1552787e39aSDag-Erling Smørgrav case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO:
1562787e39aSDag-Erling Smørgrav
1572787e39aSDag-Erling Smørgrav #ifndef S_SPLINT_S
1582787e39aSDag-Erling Smørgrav xpubkey = X509_get_X509_PUBKEY(cert);
1592787e39aSDag-Erling Smørgrav #endif
1602787e39aSDag-Erling Smørgrav if (! xpubkey) {
1612787e39aSDag-Erling Smørgrav return LDNS_STATUS_SSL_ERR;
1622787e39aSDag-Erling Smørgrav }
1632787e39aSDag-Erling Smørgrav epubkey = X509_PUBKEY_get(xpubkey);
1642787e39aSDag-Erling Smørgrav if (! epubkey) {
1652787e39aSDag-Erling Smørgrav return LDNS_STATUS_SSL_ERR;
1662787e39aSDag-Erling Smørgrav }
1672787e39aSDag-Erling Smørgrav len = (size_t)i2d_PUBKEY(epubkey, &buf);
1682787e39aSDag-Erling Smørgrav break;
1692787e39aSDag-Erling Smørgrav
1702787e39aSDag-Erling Smørgrav default:
1712787e39aSDag-Erling Smørgrav return LDNS_STATUS_DANE_UNKNOWN_SELECTOR;
1722787e39aSDag-Erling Smørgrav }
1732787e39aSDag-Erling Smørgrav
1742787e39aSDag-Erling Smørgrav switch(matching_type) {
1752787e39aSDag-Erling Smørgrav case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED:
1762787e39aSDag-Erling Smørgrav
1772787e39aSDag-Erling Smørgrav *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf);
1782787e39aSDag-Erling Smørgrav
1792787e39aSDag-Erling Smørgrav return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
1802787e39aSDag-Erling Smørgrav break;
1812787e39aSDag-Erling Smørgrav
1822787e39aSDag-Erling Smørgrav case LDNS_TLSA_MATCHING_TYPE_SHA256:
1832787e39aSDag-Erling Smørgrav
18417d15b25SDag-Erling Smørgrav digest = LDNS_XMALLOC(unsigned char, LDNS_SHA256_DIGEST_LENGTH);
1852787e39aSDag-Erling Smørgrav if (digest == NULL) {
1862787e39aSDag-Erling Smørgrav LDNS_FREE(buf);
1872787e39aSDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1882787e39aSDag-Erling Smørgrav }
1892787e39aSDag-Erling Smørgrav (void) ldns_sha256(buf, (unsigned int)len, digest);
19017d15b25SDag-Erling Smørgrav *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, LDNS_SHA256_DIGEST_LENGTH,
1912787e39aSDag-Erling Smørgrav digest);
1922787e39aSDag-Erling Smørgrav LDNS_FREE(buf);
1932787e39aSDag-Erling Smørgrav
1942787e39aSDag-Erling Smørgrav return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
1952787e39aSDag-Erling Smørgrav break;
1962787e39aSDag-Erling Smørgrav
1972787e39aSDag-Erling Smørgrav case LDNS_TLSA_MATCHING_TYPE_SHA512:
1982787e39aSDag-Erling Smørgrav
19917d15b25SDag-Erling Smørgrav digest = LDNS_XMALLOC(unsigned char, LDNS_SHA512_DIGEST_LENGTH);
2002787e39aSDag-Erling Smørgrav if (digest == NULL) {
2012787e39aSDag-Erling Smørgrav LDNS_FREE(buf);
2022787e39aSDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
2032787e39aSDag-Erling Smørgrav }
2042787e39aSDag-Erling Smørgrav (void) ldns_sha512(buf, (unsigned int)len, digest);
20517d15b25SDag-Erling Smørgrav *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, LDNS_SHA512_DIGEST_LENGTH,
2062787e39aSDag-Erling Smørgrav digest);
2072787e39aSDag-Erling Smørgrav LDNS_FREE(buf);
2082787e39aSDag-Erling Smørgrav
2092787e39aSDag-Erling Smørgrav return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
2102787e39aSDag-Erling Smørgrav break;
2112787e39aSDag-Erling Smørgrav
2122787e39aSDag-Erling Smørgrav default:
2132787e39aSDag-Erling Smørgrav LDNS_FREE(buf);
2142787e39aSDag-Erling Smørgrav return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE;
2152787e39aSDag-Erling Smørgrav }
2162787e39aSDag-Erling Smørgrav }
2172787e39aSDag-Erling Smørgrav
2182787e39aSDag-Erling Smørgrav
2192787e39aSDag-Erling Smørgrav /* Ordinary PKIX validation of cert (with extra_certs to help)
2202787e39aSDag-Erling Smørgrav * against the CA's in store
2212787e39aSDag-Erling Smørgrav */
2222787e39aSDag-Erling Smørgrav static ldns_status
ldns_dane_pkix_validate(X509 * cert,STACK_OF (X509)* extra_certs,X509_STORE * store)2232787e39aSDag-Erling Smørgrav ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs,
2242787e39aSDag-Erling Smørgrav X509_STORE* store)
2252787e39aSDag-Erling Smørgrav {
2262787e39aSDag-Erling Smørgrav X509_STORE_CTX* vrfy_ctx;
2272787e39aSDag-Erling Smørgrav ldns_status s;
2282787e39aSDag-Erling Smørgrav
2292787e39aSDag-Erling Smørgrav if (! store) {
2302787e39aSDag-Erling Smørgrav return LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
2312787e39aSDag-Erling Smørgrav }
2322787e39aSDag-Erling Smørgrav vrfy_ctx = X509_STORE_CTX_new();
2332787e39aSDag-Erling Smørgrav if (! vrfy_ctx) {
2342787e39aSDag-Erling Smørgrav
2352787e39aSDag-Erling Smørgrav return LDNS_STATUS_SSL_ERR;
2362787e39aSDag-Erling Smørgrav
2372787e39aSDag-Erling Smørgrav } else if (X509_STORE_CTX_init(vrfy_ctx, store,
2382787e39aSDag-Erling Smørgrav cert, extra_certs) != 1) {
2392787e39aSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
2402787e39aSDag-Erling Smørgrav
2412787e39aSDag-Erling Smørgrav } else if (X509_verify_cert(vrfy_ctx) == 1) {
2422787e39aSDag-Erling Smørgrav
2432787e39aSDag-Erling Smørgrav s = LDNS_STATUS_OK;
2442787e39aSDag-Erling Smørgrav
2452787e39aSDag-Erling Smørgrav } else {
2462787e39aSDag-Erling Smørgrav s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
2472787e39aSDag-Erling Smørgrav }
2482787e39aSDag-Erling Smørgrav X509_STORE_CTX_free(vrfy_ctx);
2492787e39aSDag-Erling Smørgrav return s;
2502787e39aSDag-Erling Smørgrav }
2512787e39aSDag-Erling Smørgrav
2522787e39aSDag-Erling Smørgrav
253*5afab0e5SDag-Erling Smørgrav /* Ordinary PKIX validation of cert (with extra_certs to help)
2542787e39aSDag-Erling Smørgrav * against the CA's in store, but also return the validation chain.
2552787e39aSDag-Erling Smørgrav */
2562787e39aSDag-Erling Smørgrav static ldns_status
ldns_dane_pkix_validate_and_get_chain(STACK_OF (X509)** chain,X509 * cert,STACK_OF (X509)* extra_certs,X509_STORE * store)2572787e39aSDag-Erling Smørgrav ldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert,
2582787e39aSDag-Erling Smørgrav STACK_OF(X509)* extra_certs, X509_STORE* store)
2592787e39aSDag-Erling Smørgrav {
2602787e39aSDag-Erling Smørgrav ldns_status s;
2612787e39aSDag-Erling Smørgrav X509_STORE* empty_store = NULL;
2622787e39aSDag-Erling Smørgrav X509_STORE_CTX* vrfy_ctx;
2632787e39aSDag-Erling Smørgrav
2642787e39aSDag-Erling Smørgrav assert(chain != NULL);
2652787e39aSDag-Erling Smørgrav
2662787e39aSDag-Erling Smørgrav if (! store) {
2672787e39aSDag-Erling Smørgrav store = empty_store = X509_STORE_new();
2682787e39aSDag-Erling Smørgrav }
2692787e39aSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
2702787e39aSDag-Erling Smørgrav vrfy_ctx = X509_STORE_CTX_new();
2712787e39aSDag-Erling Smørgrav if (! vrfy_ctx) {
2722787e39aSDag-Erling Smørgrav
2732787e39aSDag-Erling Smørgrav goto exit_free_empty_store;
2742787e39aSDag-Erling Smørgrav
2752787e39aSDag-Erling Smørgrav } else if (X509_STORE_CTX_init(vrfy_ctx, store,
2762787e39aSDag-Erling Smørgrav cert, extra_certs) != 1) {
2772787e39aSDag-Erling Smørgrav goto exit_free_vrfy_ctx;
2782787e39aSDag-Erling Smørgrav
2792787e39aSDag-Erling Smørgrav } else if (X509_verify_cert(vrfy_ctx) == 1) {
2802787e39aSDag-Erling Smørgrav
2812787e39aSDag-Erling Smørgrav s = LDNS_STATUS_OK;
2822787e39aSDag-Erling Smørgrav
2832787e39aSDag-Erling Smørgrav } else {
2842787e39aSDag-Erling Smørgrav s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
2852787e39aSDag-Erling Smørgrav }
2862787e39aSDag-Erling Smørgrav *chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
2872787e39aSDag-Erling Smørgrav if (! *chain) {
2882787e39aSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
2892787e39aSDag-Erling Smørgrav }
2902787e39aSDag-Erling Smørgrav
2912787e39aSDag-Erling Smørgrav exit_free_vrfy_ctx:
2922787e39aSDag-Erling Smørgrav X509_STORE_CTX_free(vrfy_ctx);
2932787e39aSDag-Erling Smørgrav
2942787e39aSDag-Erling Smørgrav exit_free_empty_store:
2952787e39aSDag-Erling Smørgrav if (empty_store) {
2962787e39aSDag-Erling Smørgrav X509_STORE_free(empty_store);
2972787e39aSDag-Erling Smørgrav }
2982787e39aSDag-Erling Smørgrav return s;
2992787e39aSDag-Erling Smørgrav }
3002787e39aSDag-Erling Smørgrav
3012787e39aSDag-Erling Smørgrav
3022787e39aSDag-Erling Smørgrav /* Return the validation chain that can be build out of cert, with extra_certs.
3032787e39aSDag-Erling Smørgrav */
3042787e39aSDag-Erling Smørgrav static ldns_status
ldns_dane_pkix_get_chain(STACK_OF (X509)** chain,X509 * cert,STACK_OF (X509)* extra_certs)3052787e39aSDag-Erling Smørgrav ldns_dane_pkix_get_chain(STACK_OF(X509)** chain,
3062787e39aSDag-Erling Smørgrav X509* cert, STACK_OF(X509)* extra_certs)
3072787e39aSDag-Erling Smørgrav {
3082787e39aSDag-Erling Smørgrav ldns_status s;
3092787e39aSDag-Erling Smørgrav X509_STORE* empty_store = NULL;
3102787e39aSDag-Erling Smørgrav X509_STORE_CTX* vrfy_ctx;
3112787e39aSDag-Erling Smørgrav
3122787e39aSDag-Erling Smørgrav assert(chain != NULL);
3132787e39aSDag-Erling Smørgrav
3142787e39aSDag-Erling Smørgrav empty_store = X509_STORE_new();
3152787e39aSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
3162787e39aSDag-Erling Smørgrav vrfy_ctx = X509_STORE_CTX_new();
3172787e39aSDag-Erling Smørgrav if (! vrfy_ctx) {
3182787e39aSDag-Erling Smørgrav
3192787e39aSDag-Erling Smørgrav goto exit_free_empty_store;
3202787e39aSDag-Erling Smørgrav
3212787e39aSDag-Erling Smørgrav } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
3222787e39aSDag-Erling Smørgrav cert, extra_certs) != 1) {
3232787e39aSDag-Erling Smørgrav goto exit_free_vrfy_ctx;
3242787e39aSDag-Erling Smørgrav }
3252787e39aSDag-Erling Smørgrav (void) X509_verify_cert(vrfy_ctx);
3262787e39aSDag-Erling Smørgrav *chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
3272787e39aSDag-Erling Smørgrav if (! *chain) {
3282787e39aSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
3292787e39aSDag-Erling Smørgrav } else {
3302787e39aSDag-Erling Smørgrav s = LDNS_STATUS_OK;
3312787e39aSDag-Erling Smørgrav }
3322787e39aSDag-Erling Smørgrav exit_free_vrfy_ctx:
3332787e39aSDag-Erling Smørgrav X509_STORE_CTX_free(vrfy_ctx);
3342787e39aSDag-Erling Smørgrav
3352787e39aSDag-Erling Smørgrav exit_free_empty_store:
3362787e39aSDag-Erling Smørgrav X509_STORE_free(empty_store);
3372787e39aSDag-Erling Smørgrav return s;
3382787e39aSDag-Erling Smørgrav }
3392787e39aSDag-Erling Smørgrav
3402787e39aSDag-Erling Smørgrav
3412787e39aSDag-Erling Smørgrav /* Pop n+1 certs and return the last popped.
3422787e39aSDag-Erling Smørgrav */
3432787e39aSDag-Erling Smørgrav static ldns_status
ldns_dane_get_nth_cert_from_validation_chain(X509 ** cert,STACK_OF (X509)* chain,int n,bool ca)3442787e39aSDag-Erling Smørgrav ldns_dane_get_nth_cert_from_validation_chain(
3452787e39aSDag-Erling Smørgrav X509** cert, STACK_OF(X509)* chain, int n, bool ca)
3462787e39aSDag-Erling Smørgrav {
3472787e39aSDag-Erling Smørgrav if (n >= sk_X509_num(chain) || n < 0) {
3482787e39aSDag-Erling Smørgrav return LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE;
3492787e39aSDag-Erling Smørgrav }
3502787e39aSDag-Erling Smørgrav *cert = sk_X509_pop(chain);
3512787e39aSDag-Erling Smørgrav while (n-- > 0) {
3522787e39aSDag-Erling Smørgrav X509_free(*cert);
3532787e39aSDag-Erling Smørgrav *cert = sk_X509_pop(chain);
3542787e39aSDag-Erling Smørgrav }
3552787e39aSDag-Erling Smørgrav if (ca && ! X509_check_ca(*cert)) {
3562787e39aSDag-Erling Smørgrav return LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
3572787e39aSDag-Erling Smørgrav }
3582787e39aSDag-Erling Smørgrav return LDNS_STATUS_OK;
3592787e39aSDag-Erling Smørgrav }
3602787e39aSDag-Erling Smørgrav
3612787e39aSDag-Erling Smørgrav
3622787e39aSDag-Erling Smørgrav /* Create validation chain with cert and extra_certs and returns the last
3632787e39aSDag-Erling Smørgrav * self-signed (if present).
3642787e39aSDag-Erling Smørgrav */
3652787e39aSDag-Erling Smørgrav static ldns_status
ldns_dane_pkix_get_last_self_signed(X509 ** out_cert,X509 * cert,STACK_OF (X509)* extra_certs)3662787e39aSDag-Erling Smørgrav ldns_dane_pkix_get_last_self_signed(X509** out_cert,
3672787e39aSDag-Erling Smørgrav X509* cert, STACK_OF(X509)* extra_certs)
3682787e39aSDag-Erling Smørgrav {
3692787e39aSDag-Erling Smørgrav ldns_status s;
3702787e39aSDag-Erling Smørgrav X509_STORE* empty_store = NULL;
3712787e39aSDag-Erling Smørgrav X509_STORE_CTX* vrfy_ctx;
3722787e39aSDag-Erling Smørgrav
3732787e39aSDag-Erling Smørgrav assert(out_cert != NULL);
3742787e39aSDag-Erling Smørgrav
3752787e39aSDag-Erling Smørgrav empty_store = X509_STORE_new();
3762787e39aSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
3772787e39aSDag-Erling Smørgrav vrfy_ctx = X509_STORE_CTX_new();
3782787e39aSDag-Erling Smørgrav if (! vrfy_ctx) {
3792787e39aSDag-Erling Smørgrav goto exit_free_empty_store;
3802787e39aSDag-Erling Smørgrav
3812787e39aSDag-Erling Smørgrav } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
3822787e39aSDag-Erling Smørgrav cert, extra_certs) != 1) {
3832787e39aSDag-Erling Smørgrav goto exit_free_vrfy_ctx;
3842787e39aSDag-Erling Smørgrav
3852787e39aSDag-Erling Smørgrav }
3862787e39aSDag-Erling Smørgrav (void) X509_verify_cert(vrfy_ctx);
387986ba33cSDag-Erling Smørgrav if (X509_STORE_CTX_get_error(vrfy_ctx) == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
388986ba33cSDag-Erling Smørgrav X509_STORE_CTX_get_error(vrfy_ctx) == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){
3892787e39aSDag-Erling Smørgrav
3902787e39aSDag-Erling Smørgrav *out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx);
3912787e39aSDag-Erling Smørgrav s = LDNS_STATUS_OK;
3922787e39aSDag-Erling Smørgrav } else {
3932787e39aSDag-Erling Smørgrav s = LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR;
3942787e39aSDag-Erling Smørgrav }
3952787e39aSDag-Erling Smørgrav exit_free_vrfy_ctx:
3962787e39aSDag-Erling Smørgrav X509_STORE_CTX_free(vrfy_ctx);
3972787e39aSDag-Erling Smørgrav
3982787e39aSDag-Erling Smørgrav exit_free_empty_store:
3992787e39aSDag-Erling Smørgrav X509_STORE_free(empty_store);
4002787e39aSDag-Erling Smørgrav return s;
4012787e39aSDag-Erling Smørgrav }
4022787e39aSDag-Erling Smørgrav
4032787e39aSDag-Erling Smørgrav
4042787e39aSDag-Erling Smørgrav ldns_status
ldns_dane_select_certificate(X509 ** selected_cert,X509 * cert,STACK_OF (X509)* extra_certs,X509_STORE * pkix_validation_store,ldns_tlsa_certificate_usage cert_usage,int offset)4052787e39aSDag-Erling Smørgrav ldns_dane_select_certificate(X509** selected_cert,
4062787e39aSDag-Erling Smørgrav X509* cert, STACK_OF(X509)* extra_certs,
4072787e39aSDag-Erling Smørgrav X509_STORE* pkix_validation_store,
4082787e39aSDag-Erling Smørgrav ldns_tlsa_certificate_usage cert_usage, int offset)
4092787e39aSDag-Erling Smørgrav {
4102787e39aSDag-Erling Smørgrav ldns_status s;
4112787e39aSDag-Erling Smørgrav STACK_OF(X509)* pkix_validation_chain = NULL;
4122787e39aSDag-Erling Smørgrav
4132787e39aSDag-Erling Smørgrav assert(selected_cert != NULL);
4142787e39aSDag-Erling Smørgrav assert(cert != NULL);
4152787e39aSDag-Erling Smørgrav
416986ba33cSDag-Erling Smørgrav /* With PKIX validation explicitly turned off (pkix_validation_store
4172787e39aSDag-Erling Smørgrav * == NULL), treat the "CA constraint" and "Service certificate
4182787e39aSDag-Erling Smørgrav * constraint" the same as "Trust anchor assertion" and "Domain issued
4192787e39aSDag-Erling Smørgrav * certificate" respectively.
4202787e39aSDag-Erling Smørgrav */
4212787e39aSDag-Erling Smørgrav if (pkix_validation_store == NULL) {
4222787e39aSDag-Erling Smørgrav switch (cert_usage) {
4232787e39aSDag-Erling Smørgrav
4242787e39aSDag-Erling Smørgrav case LDNS_TLSA_USAGE_CA_CONSTRAINT:
4252787e39aSDag-Erling Smørgrav
4262787e39aSDag-Erling Smørgrav cert_usage = LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION;
4272787e39aSDag-Erling Smørgrav break;
4282787e39aSDag-Erling Smørgrav
4292787e39aSDag-Erling Smørgrav case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
4302787e39aSDag-Erling Smørgrav
4312787e39aSDag-Erling Smørgrav cert_usage = LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE;
4322787e39aSDag-Erling Smørgrav break;
4332787e39aSDag-Erling Smørgrav
4342787e39aSDag-Erling Smørgrav default:
4352787e39aSDag-Erling Smørgrav break;
4362787e39aSDag-Erling Smørgrav }
4372787e39aSDag-Erling Smørgrav }
4382787e39aSDag-Erling Smørgrav
4392787e39aSDag-Erling Smørgrav /* Now what to do with each Certificate usage...
4402787e39aSDag-Erling Smørgrav */
4412787e39aSDag-Erling Smørgrav switch (cert_usage) {
4422787e39aSDag-Erling Smørgrav
4432787e39aSDag-Erling Smørgrav case LDNS_TLSA_USAGE_CA_CONSTRAINT:
4442787e39aSDag-Erling Smørgrav
4452787e39aSDag-Erling Smørgrav s = ldns_dane_pkix_validate_and_get_chain(
4462787e39aSDag-Erling Smørgrav &pkix_validation_chain,
4472787e39aSDag-Erling Smørgrav cert, extra_certs,
4482787e39aSDag-Erling Smørgrav pkix_validation_store);
4492787e39aSDag-Erling Smørgrav if (! pkix_validation_chain) {
4502787e39aSDag-Erling Smørgrav return s;
4512787e39aSDag-Erling Smørgrav }
4522787e39aSDag-Erling Smørgrav if (s == LDNS_STATUS_OK) {
4532787e39aSDag-Erling Smørgrav if (offset == -1) {
4542787e39aSDag-Erling Smørgrav offset = 0;
4552787e39aSDag-Erling Smørgrav }
4562787e39aSDag-Erling Smørgrav s = ldns_dane_get_nth_cert_from_validation_chain(
4572787e39aSDag-Erling Smørgrav selected_cert, pkix_validation_chain,
4582787e39aSDag-Erling Smørgrav offset, true);
4592787e39aSDag-Erling Smørgrav }
4602787e39aSDag-Erling Smørgrav sk_X509_pop_free(pkix_validation_chain, X509_free);
4612787e39aSDag-Erling Smørgrav return s;
4622787e39aSDag-Erling Smørgrav break;
4632787e39aSDag-Erling Smørgrav
4642787e39aSDag-Erling Smørgrav
4652787e39aSDag-Erling Smørgrav case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
4662787e39aSDag-Erling Smørgrav
4672787e39aSDag-Erling Smørgrav *selected_cert = cert;
4682787e39aSDag-Erling Smørgrav return ldns_dane_pkix_validate(cert, extra_certs,
4692787e39aSDag-Erling Smørgrav pkix_validation_store);
4702787e39aSDag-Erling Smørgrav break;
4712787e39aSDag-Erling Smørgrav
4722787e39aSDag-Erling Smørgrav
4732787e39aSDag-Erling Smørgrav case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
4742787e39aSDag-Erling Smørgrav
4752787e39aSDag-Erling Smørgrav if (offset == -1) {
4762787e39aSDag-Erling Smørgrav s = ldns_dane_pkix_get_last_self_signed(
4772787e39aSDag-Erling Smørgrav selected_cert, cert, extra_certs);
4782787e39aSDag-Erling Smørgrav return s;
4792787e39aSDag-Erling Smørgrav } else {
4802787e39aSDag-Erling Smørgrav s = ldns_dane_pkix_get_chain(
4812787e39aSDag-Erling Smørgrav &pkix_validation_chain,
4822787e39aSDag-Erling Smørgrav cert, extra_certs);
4832787e39aSDag-Erling Smørgrav if (s == LDNS_STATUS_OK) {
4842787e39aSDag-Erling Smørgrav s =
4852787e39aSDag-Erling Smørgrav ldns_dane_get_nth_cert_from_validation_chain(
4862787e39aSDag-Erling Smørgrav selected_cert, pkix_validation_chain,
4872787e39aSDag-Erling Smørgrav offset, false);
4882787e39aSDag-Erling Smørgrav } else if (! pkix_validation_chain) {
4892787e39aSDag-Erling Smørgrav return s;
4902787e39aSDag-Erling Smørgrav }
4912787e39aSDag-Erling Smørgrav sk_X509_pop_free(pkix_validation_chain, X509_free);
4922787e39aSDag-Erling Smørgrav return s;
4932787e39aSDag-Erling Smørgrav }
4942787e39aSDag-Erling Smørgrav break;
4952787e39aSDag-Erling Smørgrav
4962787e39aSDag-Erling Smørgrav
4972787e39aSDag-Erling Smørgrav case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
4982787e39aSDag-Erling Smørgrav
4992787e39aSDag-Erling Smørgrav *selected_cert = cert;
5002787e39aSDag-Erling Smørgrav return LDNS_STATUS_OK;
5012787e39aSDag-Erling Smørgrav break;
5022787e39aSDag-Erling Smørgrav
5032787e39aSDag-Erling Smørgrav default:
5042787e39aSDag-Erling Smørgrav return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
5052787e39aSDag-Erling Smørgrav break;
5062787e39aSDag-Erling Smørgrav }
5072787e39aSDag-Erling Smørgrav }
5082787e39aSDag-Erling Smørgrav
5092787e39aSDag-Erling Smørgrav
5102787e39aSDag-Erling Smørgrav ldns_status
ldns_dane_create_tlsa_rr(ldns_rr ** tlsa,ldns_tlsa_certificate_usage certificate_usage,ldns_tlsa_selector selector,ldns_tlsa_matching_type matching_type,X509 * cert)5112787e39aSDag-Erling Smørgrav ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
5122787e39aSDag-Erling Smørgrav ldns_tlsa_certificate_usage certificate_usage,
5132787e39aSDag-Erling Smørgrav ldns_tlsa_selector selector,
5142787e39aSDag-Erling Smørgrav ldns_tlsa_matching_type matching_type,
5152787e39aSDag-Erling Smørgrav X509* cert)
5162787e39aSDag-Erling Smørgrav {
5172787e39aSDag-Erling Smørgrav ldns_rdf* rdf;
5182787e39aSDag-Erling Smørgrav ldns_status s;
5192787e39aSDag-Erling Smørgrav
5202787e39aSDag-Erling Smørgrav assert(tlsa != NULL);
5212787e39aSDag-Erling Smørgrav assert(cert != NULL);
5222787e39aSDag-Erling Smørgrav
5232787e39aSDag-Erling Smørgrav /* create rr */
5242787e39aSDag-Erling Smørgrav *tlsa = ldns_rr_new_frm_type(LDNS_RR_TYPE_TLSA);
5252787e39aSDag-Erling Smørgrav if (*tlsa == NULL) {
5262787e39aSDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
5272787e39aSDag-Erling Smørgrav }
5282787e39aSDag-Erling Smørgrav
5292787e39aSDag-Erling Smørgrav rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
5302787e39aSDag-Erling Smørgrav (uint8_t)certificate_usage);
5312787e39aSDag-Erling Smørgrav if (rdf == NULL) {
5322787e39aSDag-Erling Smørgrav goto memerror;
5332787e39aSDag-Erling Smørgrav }
5342787e39aSDag-Erling Smørgrav (void) ldns_rr_set_rdf(*tlsa, rdf, 0);
5352787e39aSDag-Erling Smørgrav
5362787e39aSDag-Erling Smørgrav rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)selector);
5372787e39aSDag-Erling Smørgrav if (rdf == NULL) {
5382787e39aSDag-Erling Smørgrav goto memerror;
5392787e39aSDag-Erling Smørgrav }
5402787e39aSDag-Erling Smørgrav (void) ldns_rr_set_rdf(*tlsa, rdf, 1);
5412787e39aSDag-Erling Smørgrav
5422787e39aSDag-Erling Smørgrav rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)matching_type);
5432787e39aSDag-Erling Smørgrav if (rdf == NULL) {
5442787e39aSDag-Erling Smørgrav goto memerror;
5452787e39aSDag-Erling Smørgrav }
5462787e39aSDag-Erling Smørgrav (void) ldns_rr_set_rdf(*tlsa, rdf, 2);
5472787e39aSDag-Erling Smørgrav
5482787e39aSDag-Erling Smørgrav s = ldns_dane_cert2rdf(&rdf, cert, selector, matching_type);
5492787e39aSDag-Erling Smørgrav if (s == LDNS_STATUS_OK) {
5502787e39aSDag-Erling Smørgrav (void) ldns_rr_set_rdf(*tlsa, rdf, 3);
5512787e39aSDag-Erling Smørgrav return LDNS_STATUS_OK;
5522787e39aSDag-Erling Smørgrav }
5532787e39aSDag-Erling Smørgrav ldns_rr_free(*tlsa);
5542787e39aSDag-Erling Smørgrav *tlsa = NULL;
5552787e39aSDag-Erling Smørgrav return s;
5562787e39aSDag-Erling Smørgrav
5572787e39aSDag-Erling Smørgrav memerror:
5582787e39aSDag-Erling Smørgrav ldns_rr_free(*tlsa);
5592787e39aSDag-Erling Smørgrav *tlsa = NULL;
5602787e39aSDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
5612787e39aSDag-Erling Smørgrav }
5622787e39aSDag-Erling Smørgrav
5632787e39aSDag-Erling Smørgrav
564986ba33cSDag-Erling Smørgrav #ifdef USE_DANE_VERIFY
5652787e39aSDag-Erling Smørgrav /* Return tlsas that actually are TLSA resource records with known values
5662787e39aSDag-Erling Smørgrav * for the Certificate usage, Selector and Matching type rdata fields.
5672787e39aSDag-Erling Smørgrav */
5682787e39aSDag-Erling Smørgrav static ldns_rr_list*
ldns_dane_filter_unusable_records(const ldns_rr_list * tlsas)5692787e39aSDag-Erling Smørgrav ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas)
5702787e39aSDag-Erling Smørgrav {
5712787e39aSDag-Erling Smørgrav size_t i;
5722787e39aSDag-Erling Smørgrav ldns_rr_list* r = ldns_rr_list_new();
5732787e39aSDag-Erling Smørgrav ldns_rr* tlsa_rr;
5742787e39aSDag-Erling Smørgrav
5752787e39aSDag-Erling Smørgrav if (! r) {
5762787e39aSDag-Erling Smørgrav return NULL;
5772787e39aSDag-Erling Smørgrav }
5782787e39aSDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
5792787e39aSDag-Erling Smørgrav tlsa_rr = ldns_rr_list_rr(tlsas, i);
5802787e39aSDag-Erling Smørgrav if (ldns_rr_get_type(tlsa_rr) == LDNS_RR_TYPE_TLSA &&
5812787e39aSDag-Erling Smørgrav ldns_rr_rd_count(tlsa_rr) == 4 &&
5822787e39aSDag-Erling Smørgrav ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) <= 3 &&
5832787e39aSDag-Erling Smørgrav ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) <= 1 &&
5842787e39aSDag-Erling Smørgrav ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) <= 2) {
5852787e39aSDag-Erling Smørgrav
5862787e39aSDag-Erling Smørgrav if (! ldns_rr_list_push_rr(r, tlsa_rr)) {
5872787e39aSDag-Erling Smørgrav ldns_rr_list_free(r);
5882787e39aSDag-Erling Smørgrav return NULL;
5892787e39aSDag-Erling Smørgrav }
5902787e39aSDag-Erling Smørgrav }
5912787e39aSDag-Erling Smørgrav }
5922787e39aSDag-Erling Smørgrav return r;
5932787e39aSDag-Erling Smørgrav }
5942787e39aSDag-Erling Smørgrav
5952787e39aSDag-Erling Smørgrav
596986ba33cSDag-Erling Smørgrav #if !defined(USE_DANE_TA_USAGE)
5972787e39aSDag-Erling Smørgrav /* Return whether cert/selector/matching_type matches data.
5982787e39aSDag-Erling Smørgrav */
5992787e39aSDag-Erling Smørgrav static ldns_status
ldns_dane_match_cert_with_data(X509 * cert,ldns_tlsa_selector selector,ldns_tlsa_matching_type matching_type,ldns_rdf * data)6002787e39aSDag-Erling Smørgrav ldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector,
6012787e39aSDag-Erling Smørgrav ldns_tlsa_matching_type matching_type, ldns_rdf* data)
6022787e39aSDag-Erling Smørgrav {
6032787e39aSDag-Erling Smørgrav ldns_status s;
6042787e39aSDag-Erling Smørgrav ldns_rdf* match_data;
6052787e39aSDag-Erling Smørgrav
6062787e39aSDag-Erling Smørgrav s = ldns_dane_cert2rdf(&match_data, cert, selector, matching_type);
6072787e39aSDag-Erling Smørgrav if (s == LDNS_STATUS_OK) {
6082787e39aSDag-Erling Smørgrav if (ldns_rdf_compare(data, match_data) != 0) {
6092787e39aSDag-Erling Smørgrav s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
6102787e39aSDag-Erling Smørgrav }
6112787e39aSDag-Erling Smørgrav ldns_rdf_free(match_data);
6122787e39aSDag-Erling Smørgrav }
6132787e39aSDag-Erling Smørgrav return s;
6142787e39aSDag-Erling Smørgrav }
6152787e39aSDag-Erling Smørgrav
6162787e39aSDag-Erling Smørgrav
6172787e39aSDag-Erling Smørgrav /* Return whether any certificate from the chain with selector/matching_type
6182787e39aSDag-Erling Smørgrav * matches data.
6192787e39aSDag-Erling Smørgrav * ca should be true if the certificate has to be a CA certificate too.
6202787e39aSDag-Erling Smørgrav */
6212787e39aSDag-Erling Smørgrav static ldns_status
ldns_dane_match_any_cert_with_data(STACK_OF (X509)* chain,ldns_tlsa_selector selector,ldns_tlsa_matching_type matching_type,ldns_rdf * data,bool ca)6222787e39aSDag-Erling Smørgrav ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain,
6232787e39aSDag-Erling Smørgrav ldns_tlsa_selector selector,
6242787e39aSDag-Erling Smørgrav ldns_tlsa_matching_type matching_type,
6252787e39aSDag-Erling Smørgrav ldns_rdf* data, bool ca)
6262787e39aSDag-Erling Smørgrav {
6272787e39aSDag-Erling Smørgrav ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
6282787e39aSDag-Erling Smørgrav size_t n, i;
6292787e39aSDag-Erling Smørgrav X509* cert;
6302787e39aSDag-Erling Smørgrav
6312787e39aSDag-Erling Smørgrav n = (size_t)sk_X509_num(chain);
6322787e39aSDag-Erling Smørgrav for (i = 0; i < n; i++) {
6332787e39aSDag-Erling Smørgrav cert = sk_X509_pop(chain);
6342787e39aSDag-Erling Smørgrav if (! cert) {
6352787e39aSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
6362787e39aSDag-Erling Smørgrav break;
6372787e39aSDag-Erling Smørgrav }
6382787e39aSDag-Erling Smørgrav s = ldns_dane_match_cert_with_data(cert,
6392787e39aSDag-Erling Smørgrav selector, matching_type, data);
6402787e39aSDag-Erling Smørgrav if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) {
6412787e39aSDag-Erling Smørgrav s = LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
6422787e39aSDag-Erling Smørgrav }
6432787e39aSDag-Erling Smørgrav X509_free(cert);
6442787e39aSDag-Erling Smørgrav if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) {
6452787e39aSDag-Erling Smørgrav break;
6462787e39aSDag-Erling Smørgrav }
6472787e39aSDag-Erling Smørgrav /* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
6482787e39aSDag-Erling Smørgrav * try to match the next certificate
6492787e39aSDag-Erling Smørgrav */
6502787e39aSDag-Erling Smørgrav }
6512787e39aSDag-Erling Smørgrav return s;
6522787e39aSDag-Erling Smørgrav }
653986ba33cSDag-Erling Smørgrav #endif /* !defined(USE_DANE_TA_USAGE) */
654986ba33cSDag-Erling Smørgrav #endif /* USE_DANE_VERIFY */
6552787e39aSDag-Erling Smørgrav
656986ba33cSDag-Erling Smørgrav #ifdef USE_DANE_VERIFY
6572787e39aSDag-Erling Smørgrav ldns_status
ldns_dane_verify_rr(const ldns_rr * tlsa_rr,X509 * cert,STACK_OF (X509)* extra_certs,X509_STORE * pkix_validation_store)6582787e39aSDag-Erling Smørgrav ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
6592787e39aSDag-Erling Smørgrav X509* cert, STACK_OF(X509)* extra_certs,
6602787e39aSDag-Erling Smørgrav X509_STORE* pkix_validation_store)
6612787e39aSDag-Erling Smørgrav {
662986ba33cSDag-Erling Smørgrav #if defined(USE_DANE_TA_USAGE)
663986ba33cSDag-Erling Smørgrav SSL_CTX *ssl_ctx = NULL;
664986ba33cSDag-Erling Smørgrav SSL *ssl = NULL;
665986ba33cSDag-Erling Smørgrav X509_STORE_CTX *store_ctx = NULL;
666986ba33cSDag-Erling Smørgrav #else
6672787e39aSDag-Erling Smørgrav STACK_OF(X509)* pkix_validation_chain = NULL;
668986ba33cSDag-Erling Smørgrav #endif
669986ba33cSDag-Erling Smørgrav ldns_status s = LDNS_STATUS_OK;
6702787e39aSDag-Erling Smørgrav
671986ba33cSDag-Erling Smørgrav ldns_tlsa_certificate_usage usage;
6722787e39aSDag-Erling Smørgrav ldns_tlsa_selector selector;
673986ba33cSDag-Erling Smørgrav ldns_tlsa_matching_type mtype;
6742787e39aSDag-Erling Smørgrav ldns_rdf* data;
6752787e39aSDag-Erling Smørgrav
676986ba33cSDag-Erling Smørgrav if (! tlsa_rr || ldns_rr_get_type(tlsa_rr) != LDNS_RR_TYPE_TLSA ||
677986ba33cSDag-Erling Smørgrav ldns_rr_rd_count(tlsa_rr) != 4 ||
678986ba33cSDag-Erling Smørgrav ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) > 3 ||
679986ba33cSDag-Erling Smørgrav ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) > 1 ||
680986ba33cSDag-Erling Smørgrav ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) > 2 ) {
681986ba33cSDag-Erling Smørgrav /* No (usable) TLSA, so regular PKIX validation
6822787e39aSDag-Erling Smørgrav */
6832787e39aSDag-Erling Smørgrav return ldns_dane_pkix_validate(cert, extra_certs,
6842787e39aSDag-Erling Smørgrav pkix_validation_store);
6852787e39aSDag-Erling Smørgrav }
686986ba33cSDag-Erling Smørgrav usage = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0));
6872787e39aSDag-Erling Smørgrav selector = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1));
688986ba33cSDag-Erling Smørgrav mtype = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2));
6892787e39aSDag-Erling Smørgrav data = ldns_rr_rdf(tlsa_rr, 3) ;
6902787e39aSDag-Erling Smørgrav
691986ba33cSDag-Erling Smørgrav #if defined(USE_DANE_TA_USAGE)
692986ba33cSDag-Erling Smørgrav /* Rely on OpenSSL dane functions.
693986ba33cSDag-Erling Smørgrav *
694986ba33cSDag-Erling Smørgrav * OpenSSL does not provide offline dane verification. The dane unit
695986ba33cSDag-Erling Smørgrav * tests within openssl use the undocumented SSL_get0_dane() and
696986ba33cSDag-Erling Smørgrav * X509_STORE_CTX_set0_dane() to convey dane parameters set on SSL and
697986ba33cSDag-Erling Smørgrav * SSL_CTX to a X509_STORE_CTX that can be used to do offline
698986ba33cSDag-Erling Smørgrav * verification. We use these undocumented means with the ldns
699986ba33cSDag-Erling Smørgrav * dane function prototypes which did only offline dane verification.
700986ba33cSDag-Erling Smørgrav */
701*5afab0e5SDag-Erling Smørgrav if (!(ssl_ctx = ldns_dane_new_ssl_context()))
702986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_MEM_ERR;
703986ba33cSDag-Erling Smørgrav
704986ba33cSDag-Erling Smørgrav else if (SSL_CTX_dane_enable(ssl_ctx) <= 0)
705986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
706986ba33cSDag-Erling Smørgrav
707986ba33cSDag-Erling Smørgrav else if (SSL_CTX_dane_set_flags(
708986ba33cSDag-Erling Smørgrav ssl_ctx, DANE_FLAG_NO_DANE_EE_NAMECHECKS),
709986ba33cSDag-Erling Smørgrav !(ssl = SSL_new(ssl_ctx)))
710986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_MEM_ERR;
711986ba33cSDag-Erling Smørgrav
712986ba33cSDag-Erling Smørgrav else if (SSL_set_connect_state(ssl),
713986ba33cSDag-Erling Smørgrav (SSL_dane_enable(ssl, NULL) <= 0))
714986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
715986ba33cSDag-Erling Smørgrav
716986ba33cSDag-Erling Smørgrav else if (SSL_dane_tlsa_add(ssl, usage, selector, mtype,
717986ba33cSDag-Erling Smørgrav ldns_rdf_data(data), ldns_rdf_size(data)) <= 0)
718986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
719986ba33cSDag-Erling Smørgrav
720986ba33cSDag-Erling Smørgrav else if (!(store_ctx = X509_STORE_CTX_new()))
721986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_MEM_ERR;
722986ba33cSDag-Erling Smørgrav
723986ba33cSDag-Erling Smørgrav else if (!X509_STORE_CTX_init(store_ctx, pkix_validation_store, cert, extra_certs))
724986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
725986ba33cSDag-Erling Smørgrav
726986ba33cSDag-Erling Smørgrav else {
727986ba33cSDag-Erling Smørgrav int ret;
728986ba33cSDag-Erling Smørgrav
729986ba33cSDag-Erling Smørgrav X509_STORE_CTX_set_default(store_ctx,
730986ba33cSDag-Erling Smørgrav SSL_is_server(ssl) ? "ssl_client" : "ssl_server");
731986ba33cSDag-Erling Smørgrav X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(store_ctx),
732986ba33cSDag-Erling Smørgrav SSL_get0_param(ssl));
733986ba33cSDag-Erling Smørgrav X509_STORE_CTX_set0_dane(store_ctx, SSL_get0_dane(ssl));
734986ba33cSDag-Erling Smørgrav if (SSL_get_verify_callback(ssl))
735986ba33cSDag-Erling Smørgrav X509_STORE_CTX_set_verify_cb(store_ctx, SSL_get_verify_callback(ssl));
736986ba33cSDag-Erling Smørgrav
737986ba33cSDag-Erling Smørgrav ret = X509_verify_cert(store_ctx);
738986ba33cSDag-Erling Smørgrav if (!ret) {
739986ba33cSDag-Erling Smørgrav if (X509_STORE_CTX_get_error(store_ctx) == X509_V_ERR_DANE_NO_MATCH)
740986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
741986ba33cSDag-Erling Smørgrav else
742986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
743986ba33cSDag-Erling Smørgrav }
744986ba33cSDag-Erling Smørgrav X509_STORE_CTX_cleanup(store_ctx);
745986ba33cSDag-Erling Smørgrav }
746986ba33cSDag-Erling Smørgrav if (store_ctx)
747986ba33cSDag-Erling Smørgrav X509_STORE_CTX_free(store_ctx);
748986ba33cSDag-Erling Smørgrav if (ssl)
749986ba33cSDag-Erling Smørgrav SSL_free(ssl);
750986ba33cSDag-Erling Smørgrav if (ssl_ctx)
751986ba33cSDag-Erling Smørgrav SSL_CTX_free(ssl_ctx);
752986ba33cSDag-Erling Smørgrav return s;
753986ba33cSDag-Erling Smørgrav #else
754986ba33cSDag-Erling Smørgrav switch (usage) {
7552787e39aSDag-Erling Smørgrav case LDNS_TLSA_USAGE_CA_CONSTRAINT:
7562787e39aSDag-Erling Smørgrav s = ldns_dane_pkix_validate_and_get_chain(
7572787e39aSDag-Erling Smørgrav &pkix_validation_chain,
7582787e39aSDag-Erling Smørgrav cert, extra_certs,
7592787e39aSDag-Erling Smørgrav pkix_validation_store);
7602787e39aSDag-Erling Smørgrav if (! pkix_validation_chain) {
7612787e39aSDag-Erling Smørgrav return s;
7622787e39aSDag-Erling Smørgrav }
7632787e39aSDag-Erling Smørgrav if (s == LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
7642787e39aSDag-Erling Smørgrav /*
7652787e39aSDag-Erling Smørgrav * NO PKIX validation. We still try to match *any*
7662787e39aSDag-Erling Smørgrav * certificate from the chain, so we return
7672787e39aSDag-Erling Smørgrav * TLSA errors over PKIX errors.
7682787e39aSDag-Erling Smørgrav *
7692787e39aSDag-Erling Smørgrav * i.e. When the TLSA matches no certificate, we return
7702787e39aSDag-Erling Smørgrav * TLSA_DID_NOT_MATCH and not PKIX_DID_NOT_VALIDATE
7712787e39aSDag-Erling Smørgrav */
7722787e39aSDag-Erling Smørgrav s = ldns_dane_match_any_cert_with_data(
7732787e39aSDag-Erling Smørgrav pkix_validation_chain,
774986ba33cSDag-Erling Smørgrav selector, mtype, data, true);
7752787e39aSDag-Erling Smørgrav
7762787e39aSDag-Erling Smørgrav if (s == LDNS_STATUS_OK) {
7772787e39aSDag-Erling Smørgrav /* A TLSA record did match a cert from the
7782787e39aSDag-Erling Smørgrav * chain, thus the error is failed PKIX
7792787e39aSDag-Erling Smørgrav * validation.
7802787e39aSDag-Erling Smørgrav */
7812787e39aSDag-Erling Smørgrav s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
7822787e39aSDag-Erling Smørgrav }
7832787e39aSDag-Erling Smørgrav
7842787e39aSDag-Erling Smørgrav } else if (s == LDNS_STATUS_OK) {
7852787e39aSDag-Erling Smørgrav /* PKIX validated, does the TLSA match too? */
7862787e39aSDag-Erling Smørgrav
7872787e39aSDag-Erling Smørgrav s = ldns_dane_match_any_cert_with_data(
7882787e39aSDag-Erling Smørgrav pkix_validation_chain,
789986ba33cSDag-Erling Smørgrav selector, mtype, data, true);
7902787e39aSDag-Erling Smørgrav }
7912787e39aSDag-Erling Smørgrav sk_X509_pop_free(pkix_validation_chain, X509_free);
7922787e39aSDag-Erling Smørgrav return s;
7932787e39aSDag-Erling Smørgrav break;
7942787e39aSDag-Erling Smørgrav
7952787e39aSDag-Erling Smørgrav case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
796986ba33cSDag-Erling Smørgrav
7972787e39aSDag-Erling Smørgrav s = ldns_dane_match_cert_with_data(cert,
798986ba33cSDag-Erling Smørgrav selector, mtype, data);
7992787e39aSDag-Erling Smørgrav
8002787e39aSDag-Erling Smørgrav if (s == LDNS_STATUS_OK) {
8012787e39aSDag-Erling Smørgrav return ldns_dane_pkix_validate(cert, extra_certs,
8022787e39aSDag-Erling Smørgrav pkix_validation_store);
8032787e39aSDag-Erling Smørgrav }
8042787e39aSDag-Erling Smørgrav return s;
8052787e39aSDag-Erling Smørgrav break;
8062787e39aSDag-Erling Smørgrav
8072787e39aSDag-Erling Smørgrav case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
808986ba33cSDag-Erling Smørgrav #if 0
8092787e39aSDag-Erling Smørgrav s = ldns_dane_pkix_get_chain(&pkix_validation_chain,
8102787e39aSDag-Erling Smørgrav cert, extra_certs);
8112787e39aSDag-Erling Smørgrav
8122787e39aSDag-Erling Smørgrav if (s == LDNS_STATUS_OK) {
8132787e39aSDag-Erling Smørgrav s = ldns_dane_match_any_cert_with_data(
8142787e39aSDag-Erling Smørgrav pkix_validation_chain,
815986ba33cSDag-Erling Smørgrav selector, mtype, data, false);
8162787e39aSDag-Erling Smørgrav
8172787e39aSDag-Erling Smørgrav } else if (! pkix_validation_chain) {
8182787e39aSDag-Erling Smørgrav return s;
8192787e39aSDag-Erling Smørgrav }
8202787e39aSDag-Erling Smørgrav sk_X509_pop_free(pkix_validation_chain, X509_free);
8212787e39aSDag-Erling Smørgrav return s;
822986ba33cSDag-Erling Smørgrav #else
823986ba33cSDag-Erling Smørgrav return LDNS_STATUS_DANE_NEED_OPENSSL_GE_1_1_FOR_DANE_TA;
824986ba33cSDag-Erling Smørgrav #endif
8252787e39aSDag-Erling Smørgrav break;
8262787e39aSDag-Erling Smørgrav
8272787e39aSDag-Erling Smørgrav case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
8282787e39aSDag-Erling Smørgrav return ldns_dane_match_cert_with_data(cert,
829986ba33cSDag-Erling Smørgrav selector, mtype, data);
8302787e39aSDag-Erling Smørgrav break;
8312787e39aSDag-Erling Smørgrav
8322787e39aSDag-Erling Smørgrav default:
8332787e39aSDag-Erling Smørgrav break;
8342787e39aSDag-Erling Smørgrav }
835986ba33cSDag-Erling Smørgrav #endif
8362787e39aSDag-Erling Smørgrav return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
8372787e39aSDag-Erling Smørgrav }
8382787e39aSDag-Erling Smørgrav
8392787e39aSDag-Erling Smørgrav
8402787e39aSDag-Erling Smørgrav ldns_status
ldns_dane_verify(const ldns_rr_list * tlsas,X509 * cert,STACK_OF (X509)* extra_certs,X509_STORE * pkix_validation_store)841986ba33cSDag-Erling Smørgrav ldns_dane_verify(const ldns_rr_list* tlsas,
8422787e39aSDag-Erling Smørgrav X509* cert, STACK_OF(X509)* extra_certs,
8432787e39aSDag-Erling Smørgrav X509_STORE* pkix_validation_store)
8442787e39aSDag-Erling Smørgrav {
845986ba33cSDag-Erling Smørgrav #if defined(USE_DANE_TA_USAGE)
846986ba33cSDag-Erling Smørgrav SSL_CTX *ssl_ctx = NULL;
847986ba33cSDag-Erling Smørgrav ldns_rdf *basename_rdf = NULL;
848986ba33cSDag-Erling Smørgrav char *basename = NULL;
849986ba33cSDag-Erling Smørgrav SSL *ssl = NULL;
850986ba33cSDag-Erling Smørgrav X509_STORE_CTX *store_ctx = NULL;
851986ba33cSDag-Erling Smørgrav #else
852986ba33cSDag-Erling Smørgrav ldns_status ps;
853986ba33cSDag-Erling Smørgrav #endif
8542787e39aSDag-Erling Smørgrav size_t i;
8552787e39aSDag-Erling Smørgrav ldns_rr* tlsa_rr;
856986ba33cSDag-Erling Smørgrav ldns_rr_list *usable_tlsas;
857986ba33cSDag-Erling Smørgrav ldns_status s = LDNS_STATUS_OK;
8582787e39aSDag-Erling Smørgrav
8592787e39aSDag-Erling Smørgrav assert(cert != NULL);
8602787e39aSDag-Erling Smørgrav
861986ba33cSDag-Erling Smørgrav if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0)
8622787e39aSDag-Erling Smørgrav /* No TLSA's, so regular PKIX validation
8632787e39aSDag-Erling Smørgrav */
8642787e39aSDag-Erling Smørgrav return ldns_dane_pkix_validate(cert, extra_certs,
8652787e39aSDag-Erling Smørgrav pkix_validation_store);
866986ba33cSDag-Erling Smørgrav
867986ba33cSDag-Erling Smørgrav /* To enable name checks (which we don't) */
868986ba33cSDag-Erling Smørgrav #if defined(USE_DANE_TA_USAGE) && 0
869986ba33cSDag-Erling Smørgrav else if (!(basename_rdf = ldns_dname_clone_from(
870986ba33cSDag-Erling Smørgrav ldns_rr_list_owner(tlsas), 2)))
871986ba33cSDag-Erling Smørgrav /* Could nog get DANE base name */
872986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_ERR;
873986ba33cSDag-Erling Smørgrav
874986ba33cSDag-Erling Smørgrav else if (!(basename = ldns_rdf2str(basename_rdf)))
875986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_MEM_ERR;
876986ba33cSDag-Erling Smørgrav
877986ba33cSDag-Erling Smørgrav else if (strlen(basename) && (basename[strlen(basename)-1] = 0))
878986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_ERR; /* Intended to be unreachable */
879986ba33cSDag-Erling Smørgrav #endif
880986ba33cSDag-Erling Smørgrav
881986ba33cSDag-Erling Smørgrav else if (!(usable_tlsas = ldns_dane_filter_unusable_records(tlsas)))
882986ba33cSDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
883986ba33cSDag-Erling Smørgrav
884986ba33cSDag-Erling Smørgrav else if (ldns_rr_list_rr_count(usable_tlsas) == 0) {
885986ba33cSDag-Erling Smørgrav /* No TLSA's, so regular PKIX validation
886986ba33cSDag-Erling Smørgrav */
887986ba33cSDag-Erling Smørgrav ldns_rr_list_free(usable_tlsas);
888986ba33cSDag-Erling Smørgrav return ldns_dane_pkix_validate(cert, extra_certs,
889986ba33cSDag-Erling Smørgrav pkix_validation_store);
890986ba33cSDag-Erling Smørgrav }
891986ba33cSDag-Erling Smørgrav #if defined(USE_DANE_TA_USAGE)
892986ba33cSDag-Erling Smørgrav /* Rely on OpenSSL dane functions.
893986ba33cSDag-Erling Smørgrav *
894986ba33cSDag-Erling Smørgrav * OpenSSL does not provide offline dane verification. The dane unit
895986ba33cSDag-Erling Smørgrav * tests within openssl use the undocumented SSL_get0_dane() and
896986ba33cSDag-Erling Smørgrav * X509_STORE_CTX_set0_dane() to convey dane parameters set on SSL and
897986ba33cSDag-Erling Smørgrav * SSL_CTX to a X509_STORE_CTX that can be used to do offline
898986ba33cSDag-Erling Smørgrav * verification. We use these undocumented means with the ldns
899986ba33cSDag-Erling Smørgrav * dane function prototypes which did only offline dane verification.
900986ba33cSDag-Erling Smørgrav */
901*5afab0e5SDag-Erling Smørgrav if (!(ssl_ctx = ldns_dane_new_ssl_context()))
902986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_MEM_ERR;
903986ba33cSDag-Erling Smørgrav
904986ba33cSDag-Erling Smørgrav else if (SSL_CTX_dane_enable(ssl_ctx) <= 0)
905986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
906986ba33cSDag-Erling Smørgrav
907986ba33cSDag-Erling Smørgrav else if (SSL_CTX_dane_set_flags(
908986ba33cSDag-Erling Smørgrav ssl_ctx, DANE_FLAG_NO_DANE_EE_NAMECHECKS),
909986ba33cSDag-Erling Smørgrav !(ssl = SSL_new(ssl_ctx)))
910986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_MEM_ERR;
911986ba33cSDag-Erling Smørgrav
912986ba33cSDag-Erling Smørgrav else if (SSL_set_connect_state(ssl),
913986ba33cSDag-Erling Smørgrav (SSL_dane_enable(ssl, basename) <= 0))
914986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
915986ba33cSDag-Erling Smørgrav
916986ba33cSDag-Erling Smørgrav else for (i = 0; i < ldns_rr_list_rr_count(usable_tlsas); i++) {
917986ba33cSDag-Erling Smørgrav ldns_tlsa_certificate_usage usage;
918986ba33cSDag-Erling Smørgrav ldns_tlsa_selector selector;
919986ba33cSDag-Erling Smørgrav ldns_tlsa_matching_type mtype;
920986ba33cSDag-Erling Smørgrav ldns_rdf* data;
921986ba33cSDag-Erling Smørgrav
922986ba33cSDag-Erling Smørgrav tlsa_rr = ldns_rr_list_rr(usable_tlsas, i);
923986ba33cSDag-Erling Smørgrav usage = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr,0));
924986ba33cSDag-Erling Smørgrav selector= ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr,1));
925986ba33cSDag-Erling Smørgrav mtype = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr,2));
926986ba33cSDag-Erling Smørgrav data = ldns_rr_rdf(tlsa_rr,3) ;
927986ba33cSDag-Erling Smørgrav
928986ba33cSDag-Erling Smørgrav if (SSL_dane_tlsa_add(ssl, usage, selector, mtype,
929986ba33cSDag-Erling Smørgrav ldns_rdf_data(data),
930986ba33cSDag-Erling Smørgrav ldns_rdf_size(data)) <= 0) {
931986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
932986ba33cSDag-Erling Smørgrav break;
933986ba33cSDag-Erling Smørgrav }
934986ba33cSDag-Erling Smørgrav }
935986ba33cSDag-Erling Smørgrav if (!s && !(store_ctx = X509_STORE_CTX_new()))
936986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_MEM_ERR;
937986ba33cSDag-Erling Smørgrav
938986ba33cSDag-Erling Smørgrav else if (!X509_STORE_CTX_init(store_ctx, pkix_validation_store, cert, extra_certs))
939986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_SSL_ERR;
940986ba33cSDag-Erling Smørgrav
941986ba33cSDag-Erling Smørgrav else {
942986ba33cSDag-Erling Smørgrav int ret;
943986ba33cSDag-Erling Smørgrav
944986ba33cSDag-Erling Smørgrav X509_STORE_CTX_set_default(store_ctx,
945986ba33cSDag-Erling Smørgrav SSL_is_server(ssl) ? "ssl_client" : "ssl_server");
946986ba33cSDag-Erling Smørgrav X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(store_ctx),
947986ba33cSDag-Erling Smørgrav SSL_get0_param(ssl));
948986ba33cSDag-Erling Smørgrav X509_STORE_CTX_set0_dane(store_ctx, SSL_get0_dane(ssl));
949986ba33cSDag-Erling Smørgrav if (SSL_get_verify_callback(ssl))
950986ba33cSDag-Erling Smørgrav X509_STORE_CTX_set_verify_cb(store_ctx, SSL_get_verify_callback(ssl));
951986ba33cSDag-Erling Smørgrav
952986ba33cSDag-Erling Smørgrav ret = X509_verify_cert(store_ctx);
953986ba33cSDag-Erling Smørgrav if (!ret) {
954986ba33cSDag-Erling Smørgrav if (X509_STORE_CTX_get_error(store_ctx) == X509_V_ERR_DANE_NO_MATCH)
955986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
956986ba33cSDag-Erling Smørgrav else
957986ba33cSDag-Erling Smørgrav s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
958986ba33cSDag-Erling Smørgrav }
959986ba33cSDag-Erling Smørgrav X509_STORE_CTX_cleanup(store_ctx);
960986ba33cSDag-Erling Smørgrav }
961986ba33cSDag-Erling Smørgrav if (store_ctx)
962986ba33cSDag-Erling Smørgrav X509_STORE_CTX_free(store_ctx);
963986ba33cSDag-Erling Smørgrav if (ssl)
964986ba33cSDag-Erling Smørgrav SSL_free(ssl);
965986ba33cSDag-Erling Smørgrav if (ssl_ctx)
966986ba33cSDag-Erling Smørgrav SSL_CTX_free(ssl_ctx);
967986ba33cSDag-Erling Smørgrav if (basename)
968986ba33cSDag-Erling Smørgrav free(basename);
969986ba33cSDag-Erling Smørgrav ldns_rdf_deep_free(basename_rdf);
970986ba33cSDag-Erling Smørgrav #else
971986ba33cSDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(usable_tlsas); i++) {
972986ba33cSDag-Erling Smørgrav tlsa_rr = ldns_rr_list_rr(usable_tlsas, i);
9732787e39aSDag-Erling Smørgrav ps = s;
9742787e39aSDag-Erling Smørgrav s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs,
9752787e39aSDag-Erling Smørgrav pkix_validation_store);
9762787e39aSDag-Erling Smørgrav
9772787e39aSDag-Erling Smørgrav if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH &&
978986ba33cSDag-Erling Smørgrav s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE &&
979986ba33cSDag-Erling Smørgrav s != LDNS_STATUS_DANE_NEED_OPENSSL_GE_1_1_FOR_DANE_TA) {
9802787e39aSDag-Erling Smørgrav
9812787e39aSDag-Erling Smørgrav /* which would be LDNS_STATUS_OK (match)
9822787e39aSDag-Erling Smørgrav * or some fatal error preventing use from
9832787e39aSDag-Erling Smørgrav * trying the next TLSA record.
9842787e39aSDag-Erling Smørgrav */
9852787e39aSDag-Erling Smørgrav break;
9862787e39aSDag-Erling Smørgrav }
987986ba33cSDag-Erling Smørgrav s = (s > ps ? s : ps); /* pref NEED_OPENSSL_GE_1_1_FOR_DANE_TA
988986ba33cSDag-Erling Smørgrav * over PKIX_DID_NOT_VALIDATE
9892787e39aSDag-Erling Smørgrav * over TLSA_DID_NOT_MATCH
9902787e39aSDag-Erling Smørgrav */
9912787e39aSDag-Erling Smørgrav }
992986ba33cSDag-Erling Smørgrav #endif
993986ba33cSDag-Erling Smørgrav ldns_rr_list_free(usable_tlsas);
9942787e39aSDag-Erling Smørgrav return s;
9952787e39aSDag-Erling Smørgrav }
996986ba33cSDag-Erling Smørgrav #endif /* USE_DANE_VERIFY */
9972787e39aSDag-Erling Smørgrav #endif /* HAVE_SSL */
99817d15b25SDag-Erling Smørgrav #endif /* USE_DANE */
999