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>
11266114Sdes#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>
19266114Sdes#ifdef HAVE_SYS_SOCKET_H
20246828Sdes#include <sys/socket.h>
21266114Sdes#endif
22266114Sdes#ifdef HAVE_NETDB_H
23246828Sdes#include <netdb.h>
24266114Sdes#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
127266114Sdes		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);
133266114Sdes		*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
142266114Sdes		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);
148266114Sdes		*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 */
748266114Sdes#endif /* USE_DANE */
749