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