dane.c revision 246828
1/*
2 * Verify or create TLS authentication with DANE (RFC6698)
3 *
4 * (c) NLnetLabs 2012
5 *
6 * See the file LICENSE for the license.
7 *
8 */
9
10#include <ldns/config.h>
11
12#include <ldns/ldns.h>
13#include <ldns/dane.h>
14
15#include <unistd.h>
16#include <stdlib.h>
17#include <sys/types.h>
18#include <sys/socket.h>
19#include <netdb.h>
20
21#ifdef HAVE_SSL
22#include <openssl/ssl.h>
23#include <openssl/err.h>
24#include <openssl/x509v3.h>
25#endif
26
27ldns_status
28ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name,
29		uint16_t port, ldns_dane_transport transport)
30{
31	char buf[LDNS_MAX_DOMAINLEN];
32	size_t s;
33
34	assert(tlsa_owner != NULL);
35	assert(name != NULL);
36	assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME);
37
38	s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port);
39	buf[0] = (char)(s - 1);
40
41	switch(transport) {
42	case LDNS_DANE_TRANSPORT_TCP:
43		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp");
44		break;
45
46	case LDNS_DANE_TRANSPORT_UDP:
47		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp");
48		break;
49
50	case LDNS_DANE_TRANSPORT_SCTP:
51		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp");
52		break;
53
54	default:
55		return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT;
56	}
57	if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) {
58		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
59	}
60	memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name));
61	*tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
62			s + ldns_rdf_size(name), buf);
63	if (*tlsa_owner == NULL) {
64		return LDNS_STATUS_MEM_ERR;
65	}
66	return LDNS_STATUS_OK;
67}
68
69
70#ifdef HAVE_SSL
71ldns_status
72ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
73		ldns_tlsa_selector      selector,
74		ldns_tlsa_matching_type matching_type)
75{
76	unsigned char* buf = NULL;
77	size_t len;
78
79	X509_PUBKEY* xpubkey;
80	EVP_PKEY* epubkey;
81
82	unsigned char* digest;
83
84	assert(rdf != NULL);
85	assert(cert != NULL);
86
87	switch(selector) {
88	case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE:
89
90		len = (size_t)i2d_X509(cert, &buf);
91		break;
92
93	case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO:
94
95#ifndef S_SPLINT_S
96		xpubkey = X509_get_X509_PUBKEY(cert);
97#endif
98		if (! xpubkey) {
99			return LDNS_STATUS_SSL_ERR;
100		}
101		epubkey = X509_PUBKEY_get(xpubkey);
102		if (! epubkey) {
103			return LDNS_STATUS_SSL_ERR;
104		}
105		len = (size_t)i2d_PUBKEY(epubkey, &buf);
106		break;
107
108	default:
109		return LDNS_STATUS_DANE_UNKNOWN_SELECTOR;
110	}
111
112	switch(matching_type) {
113	case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED:
114
115		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf);
116
117		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
118		break;
119
120	case LDNS_TLSA_MATCHING_TYPE_SHA256:
121
122		digest = LDNS_XMALLOC(unsigned char, SHA256_DIGEST_LENGTH);
123		if (digest == NULL) {
124			LDNS_FREE(buf);
125			return LDNS_STATUS_MEM_ERR;
126		}
127		(void) ldns_sha256(buf, (unsigned int)len, digest);
128		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA256_DIGEST_LENGTH,
129				digest);
130		LDNS_FREE(buf);
131
132		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
133		break;
134
135	case LDNS_TLSA_MATCHING_TYPE_SHA512:
136
137		digest = LDNS_XMALLOC(unsigned char, SHA512_DIGEST_LENGTH);
138		if (digest == NULL) {
139			LDNS_FREE(buf);
140			return LDNS_STATUS_MEM_ERR;
141		}
142		(void) ldns_sha512(buf, (unsigned int)len, digest);
143		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA512_DIGEST_LENGTH,
144				digest);
145		LDNS_FREE(buf);
146
147		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
148		break;
149
150	default:
151		LDNS_FREE(buf);
152		return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE;
153	}
154}
155
156
157/* Ordinary PKIX validation of cert (with extra_certs to help)
158 * against the CA's in store
159 */
160static ldns_status
161ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs,
162		X509_STORE* store)
163{
164	X509_STORE_CTX* vrfy_ctx;
165	ldns_status s;
166
167	if (! store) {
168		return LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
169	}
170	vrfy_ctx = X509_STORE_CTX_new();
171	if (! vrfy_ctx) {
172
173		return LDNS_STATUS_SSL_ERR;
174
175	} else if (X509_STORE_CTX_init(vrfy_ctx, store,
176				cert, extra_certs) != 1) {
177		s = LDNS_STATUS_SSL_ERR;
178
179	} else if (X509_verify_cert(vrfy_ctx) == 1) {
180
181		s = LDNS_STATUS_OK;
182
183	} else {
184		s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
185	}
186	X509_STORE_CTX_free(vrfy_ctx);
187	return s;
188}
189
190
191/* Orinary PKIX validation of cert (with extra_certs to help)
192 * against the CA's in store, but also return the validation chain.
193 */
194static ldns_status
195ldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert,
196		STACK_OF(X509)* extra_certs, X509_STORE* store)
197{
198	ldns_status s;
199	X509_STORE* empty_store = NULL;
200	X509_STORE_CTX* vrfy_ctx;
201
202	assert(chain != NULL);
203
204	if (! store) {
205		store = empty_store = X509_STORE_new();
206	}
207	s = LDNS_STATUS_SSL_ERR;
208	vrfy_ctx = X509_STORE_CTX_new();
209	if (! vrfy_ctx) {
210
211		goto exit_free_empty_store;
212
213	} else if (X509_STORE_CTX_init(vrfy_ctx, store,
214					cert, extra_certs) != 1) {
215		goto exit_free_vrfy_ctx;
216
217	} else if (X509_verify_cert(vrfy_ctx) == 1) {
218
219		s = LDNS_STATUS_OK;
220
221	} else {
222		s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
223	}
224	*chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
225	if (! *chain) {
226		s = LDNS_STATUS_SSL_ERR;
227	}
228
229exit_free_vrfy_ctx:
230	X509_STORE_CTX_free(vrfy_ctx);
231
232exit_free_empty_store:
233	if (empty_store) {
234		X509_STORE_free(empty_store);
235	}
236	return s;
237}
238
239
240/* Return the validation chain that can be build out of cert, with extra_certs.
241 */
242static ldns_status
243ldns_dane_pkix_get_chain(STACK_OF(X509)** chain,
244		X509* cert, STACK_OF(X509)* extra_certs)
245{
246	ldns_status s;
247	X509_STORE* empty_store = NULL;
248	X509_STORE_CTX* vrfy_ctx;
249
250	assert(chain != NULL);
251
252	empty_store = X509_STORE_new();
253	s = LDNS_STATUS_SSL_ERR;
254	vrfy_ctx = X509_STORE_CTX_new();
255	if (! vrfy_ctx) {
256
257		goto exit_free_empty_store;
258
259	} else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
260					cert, extra_certs) != 1) {
261		goto exit_free_vrfy_ctx;
262	}
263	(void) X509_verify_cert(vrfy_ctx);
264	*chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
265	if (! *chain) {
266		s = LDNS_STATUS_SSL_ERR;
267	} else {
268		s = LDNS_STATUS_OK;
269	}
270exit_free_vrfy_ctx:
271	X509_STORE_CTX_free(vrfy_ctx);
272
273exit_free_empty_store:
274	X509_STORE_free(empty_store);
275	return s;
276}
277
278
279/* Pop n+1 certs and return the last popped.
280 */
281static ldns_status
282ldns_dane_get_nth_cert_from_validation_chain(
283		X509** cert, STACK_OF(X509)* chain, int n, bool ca)
284{
285	if (n >= sk_X509_num(chain) || n < 0) {
286		return LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE;
287	}
288	*cert = sk_X509_pop(chain);
289	while (n-- > 0) {
290		X509_free(*cert);
291		*cert = sk_X509_pop(chain);
292	}
293	if (ca && ! X509_check_ca(*cert)) {
294		return LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
295	}
296	return LDNS_STATUS_OK;
297}
298
299
300/* Create validation chain with cert and extra_certs and returns the last
301 * self-signed (if present).
302 */
303static ldns_status
304ldns_dane_pkix_get_last_self_signed(X509** out_cert,
305		X509* cert, STACK_OF(X509)* extra_certs)
306{
307	ldns_status s;
308	X509_STORE* empty_store = NULL;
309	X509_STORE_CTX* vrfy_ctx;
310
311	assert(out_cert != NULL);
312
313	empty_store = X509_STORE_new();
314	s = LDNS_STATUS_SSL_ERR;
315	vrfy_ctx = X509_STORE_CTX_new();
316	if (! vrfy_ctx) {
317		goto exit_free_empty_store;
318
319	} else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
320					cert, extra_certs) != 1) {
321		goto exit_free_vrfy_ctx;
322
323	}
324	(void) X509_verify_cert(vrfy_ctx);
325	if (vrfy_ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
326	    vrfy_ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){
327
328		*out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx);
329		s = LDNS_STATUS_OK;
330	} else {
331		s = LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR;
332	}
333exit_free_vrfy_ctx:
334	X509_STORE_CTX_free(vrfy_ctx);
335
336exit_free_empty_store:
337	X509_STORE_free(empty_store);
338	return s;
339}
340
341
342ldns_status
343ldns_dane_select_certificate(X509** selected_cert,
344		X509* cert, STACK_OF(X509)* extra_certs,
345		X509_STORE* pkix_validation_store,
346		ldns_tlsa_certificate_usage cert_usage, int offset)
347{
348	ldns_status s;
349	STACK_OF(X509)* pkix_validation_chain = NULL;
350
351	assert(selected_cert != NULL);
352	assert(cert != NULL);
353
354	/* With PKIX validation explicitely turned off (pkix_validation_store
355	 *  == NULL), treat the "CA constraint" and "Service certificate
356	 * constraint" the same as "Trust anchor assertion" and "Domain issued
357	 * certificate" respectively.
358	 */
359	if (pkix_validation_store == NULL) {
360		switch (cert_usage) {
361
362		case LDNS_TLSA_USAGE_CA_CONSTRAINT:
363
364			cert_usage = LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION;
365			break;
366
367		case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
368
369			cert_usage = LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE;
370			break;
371
372		default:
373			break;
374		}
375	}
376
377	/* Now what to do with each Certificate usage...
378	 */
379	switch (cert_usage) {
380
381	case LDNS_TLSA_USAGE_CA_CONSTRAINT:
382
383		s = ldns_dane_pkix_validate_and_get_chain(
384				&pkix_validation_chain,
385				cert, extra_certs,
386				pkix_validation_store);
387		if (! pkix_validation_chain) {
388			return s;
389		}
390		if (s == LDNS_STATUS_OK) {
391			if (offset == -1) {
392				offset = 0;
393			}
394			s = ldns_dane_get_nth_cert_from_validation_chain(
395					selected_cert, pkix_validation_chain,
396					offset, true);
397		}
398		sk_X509_pop_free(pkix_validation_chain, X509_free);
399		return s;
400		break;
401
402
403	case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
404
405		*selected_cert = cert;
406		return ldns_dane_pkix_validate(cert, extra_certs,
407				pkix_validation_store);
408		break;
409
410
411	case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
412
413		if (offset == -1) {
414			s = ldns_dane_pkix_get_last_self_signed(
415					selected_cert, cert, extra_certs);
416			return s;
417		} else {
418			s = ldns_dane_pkix_get_chain(
419					&pkix_validation_chain,
420					cert, extra_certs);
421			if (s == LDNS_STATUS_OK) {
422				s =
423				ldns_dane_get_nth_cert_from_validation_chain(
424					selected_cert, pkix_validation_chain,
425					offset, false);
426			} else if (! pkix_validation_chain) {
427				return s;
428			}
429			sk_X509_pop_free(pkix_validation_chain, X509_free);
430			return s;
431		}
432		break;
433
434
435	case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
436
437		*selected_cert = cert;
438		return LDNS_STATUS_OK;
439		break;
440
441	default:
442		return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
443		break;
444	}
445}
446
447
448ldns_status
449ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
450		ldns_tlsa_certificate_usage certificate_usage,
451		ldns_tlsa_selector          selector,
452		ldns_tlsa_matching_type     matching_type,
453		X509* cert)
454{
455	ldns_rdf* rdf;
456	ldns_status s;
457
458	assert(tlsa != NULL);
459	assert(cert != NULL);
460
461	/* create rr */
462	*tlsa = ldns_rr_new_frm_type(LDNS_RR_TYPE_TLSA);
463	if (*tlsa == NULL) {
464		return LDNS_STATUS_MEM_ERR;
465	}
466
467	rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
468			(uint8_t)certificate_usage);
469	if (rdf == NULL) {
470		goto memerror;
471	}
472	(void) ldns_rr_set_rdf(*tlsa, rdf, 0);
473
474	rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)selector);
475	if (rdf == NULL) {
476		goto memerror;
477	}
478	(void) ldns_rr_set_rdf(*tlsa, rdf, 1);
479
480	rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)matching_type);
481	if (rdf == NULL) {
482		goto memerror;
483	}
484	(void) ldns_rr_set_rdf(*tlsa, rdf, 2);
485
486	s = ldns_dane_cert2rdf(&rdf, cert, selector, matching_type);
487	if (s == LDNS_STATUS_OK) {
488		(void) ldns_rr_set_rdf(*tlsa, rdf, 3);
489		return LDNS_STATUS_OK;
490	}
491	ldns_rr_free(*tlsa);
492	*tlsa = NULL;
493	return s;
494
495memerror:
496	ldns_rr_free(*tlsa);
497	*tlsa = NULL;
498	return LDNS_STATUS_MEM_ERR;
499}
500
501
502/* Return tlsas that actually are TLSA resource records with known values
503 * for the Certificate usage, Selector and Matching type rdata fields.
504 */
505static ldns_rr_list*
506ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas)
507{
508	size_t i;
509	ldns_rr_list* r = ldns_rr_list_new();
510	ldns_rr* tlsa_rr;
511
512	if (! r) {
513		return NULL;
514	}
515	for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
516		tlsa_rr = ldns_rr_list_rr(tlsas, i);
517		if (ldns_rr_get_type(tlsa_rr) == LDNS_RR_TYPE_TLSA &&
518		    ldns_rr_rd_count(tlsa_rr) == 4 &&
519		    ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) <= 3 &&
520		    ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) <= 1 &&
521		    ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) <= 2) {
522
523			if (! ldns_rr_list_push_rr(r, tlsa_rr)) {
524				ldns_rr_list_free(r);
525				return NULL;
526			}
527		}
528	}
529	return r;
530}
531
532
533/* Return whether cert/selector/matching_type matches data.
534 */
535static ldns_status
536ldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector,
537		ldns_tlsa_matching_type matching_type, ldns_rdf* data)
538{
539	ldns_status s;
540	ldns_rdf* match_data;
541
542	s = ldns_dane_cert2rdf(&match_data, cert, selector, matching_type);
543	if (s == LDNS_STATUS_OK) {
544		if (ldns_rdf_compare(data, match_data) != 0) {
545			s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
546		}
547		ldns_rdf_free(match_data);
548	}
549	return s;
550}
551
552
553/* Return whether any certificate from the chain with selector/matching_type
554 * matches data.
555 * ca should be true if the certificate has to be a CA certificate too.
556 */
557static ldns_status
558ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain,
559		ldns_tlsa_selector      selector,
560		ldns_tlsa_matching_type matching_type,
561		ldns_rdf* data, bool ca)
562{
563	ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
564	size_t n, i;
565	X509* cert;
566
567	n = (size_t)sk_X509_num(chain);
568	for (i = 0; i < n; i++) {
569		cert = sk_X509_pop(chain);
570		if (! cert) {
571			s = LDNS_STATUS_SSL_ERR;
572			break;
573		}
574		s = ldns_dane_match_cert_with_data(cert,
575				selector, matching_type, data);
576		if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) {
577			s = LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
578		}
579		X509_free(cert);
580		if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) {
581			break;
582		}
583		/* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
584		 * try to match the next certificate
585		 */
586	}
587	return s;
588}
589
590
591ldns_status
592ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
593		X509* cert, STACK_OF(X509)* extra_certs,
594		X509_STORE* pkix_validation_store)
595{
596	ldns_status s;
597
598	STACK_OF(X509)* pkix_validation_chain = NULL;
599
600	ldns_tlsa_certificate_usage cert_usage;
601	ldns_tlsa_selector          selector;
602	ldns_tlsa_matching_type     matching_type;
603	ldns_rdf*                   data;
604
605	if (! tlsa_rr) {
606		/* No TLSA, so regular PKIX validation
607		 */
608		return ldns_dane_pkix_validate(cert, extra_certs,
609				pkix_validation_store);
610	}
611	cert_usage    = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0));
612	selector      = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1));
613	matching_type = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2));
614	data          =                      ldns_rr_rdf(tlsa_rr, 3) ;
615
616	switch (cert_usage) {
617	case LDNS_TLSA_USAGE_CA_CONSTRAINT:
618		s = ldns_dane_pkix_validate_and_get_chain(
619				&pkix_validation_chain,
620				cert, extra_certs,
621				pkix_validation_store);
622		if (! pkix_validation_chain) {
623			return s;
624		}
625		if (s == LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
626			/*
627			 * NO PKIX validation. We still try to match *any*
628			 * certificate from the chain, so we return
629			 * TLSA errors over PKIX errors.
630			 *
631			 * i.e. When the TLSA matches no certificate, we return
632			 * TLSA_DID_NOT_MATCH and not PKIX_DID_NOT_VALIDATE
633			 */
634			s = ldns_dane_match_any_cert_with_data(
635					pkix_validation_chain,
636					selector, matching_type, data, true);
637
638			if (s == LDNS_STATUS_OK) {
639				/* A TLSA record did match a cert from the
640				 * chain, thus the error is failed PKIX
641				 * validation.
642				 */
643				s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
644			}
645
646		} else if (s == LDNS_STATUS_OK) {
647			/* PKIX validated, does the TLSA match too? */
648
649			s = ldns_dane_match_any_cert_with_data(
650					pkix_validation_chain,
651					selector, matching_type, data, true);
652		}
653		sk_X509_pop_free(pkix_validation_chain, X509_free);
654		return s;
655		break;
656
657	case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
658		s = ldns_dane_match_cert_with_data(cert,
659				selector, matching_type, data);
660
661		if (s == LDNS_STATUS_OK) {
662			return ldns_dane_pkix_validate(cert, extra_certs,
663					pkix_validation_store);
664		}
665		return s;
666		break;
667
668	case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
669		s = ldns_dane_pkix_get_chain(&pkix_validation_chain,
670				cert, extra_certs);
671
672		if (s == LDNS_STATUS_OK) {
673			s = ldns_dane_match_any_cert_with_data(
674					pkix_validation_chain,
675					selector, matching_type, data, false);
676
677		} else if (! pkix_validation_chain) {
678			return s;
679		}
680		sk_X509_pop_free(pkix_validation_chain, X509_free);
681		return s;
682		break;
683
684	case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
685		return ldns_dane_match_cert_with_data(cert,
686				selector, matching_type, data);
687		break;
688
689	default:
690		break;
691	}
692	return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
693}
694
695
696ldns_status
697ldns_dane_verify(ldns_rr_list* tlsas,
698		X509* cert, STACK_OF(X509)* extra_certs,
699		X509_STORE* pkix_validation_store)
700{
701	size_t i;
702	ldns_rr* tlsa_rr;
703	ldns_status s = LDNS_STATUS_OK, ps;
704
705	assert(cert != NULL);
706
707	if (tlsas && ldns_rr_list_rr_count(tlsas) > 0) {
708		tlsas = ldns_dane_filter_unusable_records(tlsas);
709		if (! tlsas) {
710			return LDNS_STATUS_MEM_ERR;
711		}
712	}
713	if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) {
714		/* No TLSA's, so regular PKIX validation
715		 */
716		return ldns_dane_pkix_validate(cert, extra_certs,
717				pkix_validation_store);
718	} else {
719		for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
720			tlsa_rr = ldns_rr_list_rr(tlsas, i);
721			ps = s;
722			s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs,
723					pkix_validation_store);
724
725			if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH &&
726			    s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
727
728				/* which would be LDNS_STATUS_OK (match)
729				 * or some fatal error preventing use from
730				 * trying the next TLSA record.
731				 */
732				break;
733			}
734			s = (s > ps ? s : ps); /* prefer PKIX_DID_NOT_VALIDATE
735						* over   TLSA_DID_NOT_MATCH
736						*/
737		}
738		ldns_rr_list_free(tlsas);
739	}
740	return s;
741}
742#endif /* HAVE_SSL */
743