2 * Copyright (C) 2012 KU Leuven
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of libdane.
8 * libdane is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
29 #include <arpa/inet.h>
31 #include <gnutls/dane.h>
32 #include <gnutls/x509.h>
33 #include <gnutls/abstract.h>
34 #include <gnutls/crypto.h>
35 #include "../lib/gnutls_int.h"
37 #define MAX_DATA_ENTRIES 4
40 # define gnutls_assert() fprintf(stderr, "ASSERT: %s: %d\n", __FILE__, __LINE__);
41 # define gnutls_assert_val(x) gnutls_assert_val_int(x, __FILE__, __LINE__)
42 static int gnutls_assert_val_int (int val
, const char *file
, int line
)
44 fprintf(stderr
, "ASSERT: %s: %d\n", file
, line
);
48 # define gnutls_assert()
49 # define gnutls_assert_val(x) (x)
60 struct ub_result
* result
;
61 unsigned int data_entries
;
62 dane_cert_usage_t usage
[MAX_DATA_ENTRIES
];
63 dane_cert_type_t type
[MAX_DATA_ENTRIES
];
64 dane_match_type_t match
[MAX_DATA_ENTRIES
];
65 gnutls_datum_t data
[MAX_DATA_ENTRIES
];
67 dane_query_status_t status
;
72 * @q: The query result structure
74 * This function will return the status of the query response.
75 * See %dane_query_status_t for the possible types.
77 * Returns: The status type.
79 dane_query_status_t
dane_query_status(dane_query_t q
)
86 * @q: The query result structure
88 * This function will return the number of entries in a query.
90 * Returns: The number of entries.
92 unsigned int dane_query_entries(dane_query_t q
)
94 return q
->data_entries
;
99 * @q: The query result structure
100 * @idx: The index of the query response.
101 * @usage: The certificate usage (see %dane_cert_usage_t)
102 * @type: The certificate type (see %dane_cert_type_t)
103 * @match: The DANE matching type (see %dane_match_type_t)
104 * @data: The DANE data.
106 * This function will provide the DANE data from the query
109 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
110 * negative error value.
112 int dane_query_data(dane_query_t q
, unsigned int idx
,
113 unsigned int *usage
, unsigned int *type
,
114 unsigned int *match
, gnutls_datum_t
* data
)
116 if (idx
>= q
->data_entries
)
117 return gnutls_assert_val(DANE_E_REQUESTED_DATA_NOT_AVAILABLE
);
120 *usage
= q
->usage
[idx
];
122 *type
= q
->type
[idx
];
124 *match
= q
->match
[idx
];
126 data
->data
= q
->data
[idx
].data
;
127 data
->size
= q
->data
[idx
].size
;
130 return DANE_E_SUCCESS
;
135 * @s: The structure to be initialized
136 * @flags: flags from the %dane_state_flags enumeration
138 * This function will initialize a DANE query structure.
140 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
141 * negative error value.
143 int dane_state_init(dane_state_t
* s
, unsigned int flags
)
148 *s
= calloc(1, sizeof(struct dane_state_st
));
150 return gnutls_assert_val(DANE_E_MEMORY_ERROR
);
152 ctx
= ub_ctx_create();
155 ret
= DANE_E_INITIALIZATION_ERROR
;
158 ub_ctx_debugout(ctx
, stderr
);
160 if (!(flags
& DANE_F_IGNORE_LOCAL_RESOLVER
)) {
161 if( (ret
=ub_ctx_resolvconf(ctx
, NULL
)) != 0) {
163 ret
= DANE_E_INITIALIZATION_ERROR
;
167 if( (ret
=ub_ctx_hosts(ctx
, NULL
)) != 0) {
169 ret
= DANE_E_INITIALIZATION_ERROR
;
174 /* read public keys for DNSSEC verification */
175 if( (ret
=ub_ctx_add_ta_file(ctx
, (char*)UNBOUND_ROOT_KEY_FILE
)) != 0) {
177 ret
= DANE_E_INITIALIZATION_ERROR
;
184 return DANE_E_SUCCESS
;
196 * @s: The structure to be deinitialized
198 * This function will deinitialize a DANE query structure.
201 void dane_state_deinit(dane_state_t s
)
203 ub_ctx_delete(s
->ctx
);
210 * @q: The structure to be deinitialized
212 * This function will deinitialize a DANE query result structure.
215 void dane_query_deinit(dane_query_t q
)
217 ub_resolve_free(q
->result
);
223 * @s: The DANE state structure
224 * @r: A structure to place the result
225 * @host: The host name to resolve.
226 * @proto: The protocol type (tcp, udp, etc.)
227 * @port: The service port number (eg. 443).
229 * This function will query the DNS server for the TLSA (DANE)
230 * data for the given host.
232 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
233 * negative error value.
235 int dane_query_tlsa(dane_state_t s
, dane_query_t
*r
, const char* host
, const char* proto
, unsigned int port
)
241 *r
= calloc(1, sizeof(struct dane_query_st
));
243 return gnutls_assert_val(DANE_E_MEMORY_ERROR
);
245 snprintf(ns
, sizeof(ns
), "_%u._%s.%s", port
, proto
, host
);
247 /* query for webserver */
248 ret
= ub_resolve(s
->ctx
, ns
, 52, 1, &(*r
)->result
);
250 return gnutls_assert_val(DANE_E_RESOLVING_ERROR
);
253 /* show first result */
254 if(!(*r
)->result
->havedata
) {
255 return gnutls_assert_val(DANE_E_NO_DANE_DATA
);
261 if ((*r
)->result
->len
[i
] > 3)
262 ret
= DANE_E_SUCCESS
;
264 return gnutls_assert_val(DANE_E_RECEIVED_CORRUPT_DATA
);
267 (*r
)->usage
[i
] = (*r
)->result
->data
[i
][0];
268 (*r
)->type
[i
] = (*r
)->result
->data
[i
][1];
269 (*r
)->match
[i
] = (*r
)->result
->data
[i
][2];
270 (*r
)->data
[i
].data
= (void*)&(*r
)->result
->data
[i
][3];
271 (*r
)->data
[i
].size
= (*r
)->result
->len
[i
] - 3;
273 } while((*r
)->result
->data
[i
] != NULL
);
275 (*r
)->data_entries
= i
;
277 if (!(*r
)->result
->secure
) {
278 if ((*r
)->result
->bogus
)
279 ret
= gnutls_assert_val(DANE_E_INVALID_DNSSEC_SIG
);
281 ret
= gnutls_assert_val(DANE_E_NO_DNSSEC_SIG
);
284 /* show security status */
285 if ((*r
)->result
->secure
) {
286 (*r
)->status
= DANE_QUERY_DNSSEC_VERIFIED
;
287 } else if ((*r
)->result
->bogus
) {
289 (*r
)->status
= DANE_QUERY_BOGUS
;
292 (*r
)->status
= DANE_QUERY_NO_DNSSEC
;
298 static unsigned int matches(const gnutls_datum_t
*raw1
, const gnutls_datum_t
*raw2
,
299 dane_match_type_t match
)
304 if (match
== DANE_MATCH_EXACT
) {
305 if (raw1
->size
!= raw2
->size
)
306 return gnutls_assert_val(0);
308 if (memcmp(raw1
->data
, raw2
->data
, raw1
->size
) != 0)
309 return gnutls_assert_val(0);
312 } else if (match
== DANE_MATCH_SHA2_256
) {
314 if (raw2
->size
!= 32)
315 return gnutls_assert_val(0);
317 ret
= gnutls_hash_fast(GNUTLS_DIG_SHA256
, raw1
->data
, raw1
->size
, digest
);
319 return gnutls_assert_val(0);
321 if (memcmp(digest
, raw2
->data
, 32) != 0)
322 return gnutls_assert_val(0);
325 } else if (match
== DANE_MATCH_SHA2_512
) {
326 if (raw2
->size
!= 64)
327 return gnutls_assert_val(0);
329 ret
= gnutls_hash_fast(GNUTLS_DIG_SHA512
, raw1
->data
, raw1
->size
, digest
);
331 return gnutls_assert_val(0);
333 if (memcmp(digest
, raw2
->data
, 64) != 0)
334 return gnutls_assert_val(0);
339 return gnutls_assert_val(0);
342 static int crt_to_pubkey(const gnutls_datum_t
*raw_crt
, gnutls_datum_t
* out
)
344 gnutls_pubkey_t pub
= NULL
;
345 gnutls_x509_crt_t crt
= NULL
;
350 ret
= gnutls_x509_crt_init(&crt
);
352 return gnutls_assert_val(DANE_E_PUBKEY_ERROR
);
354 ret
= gnutls_pubkey_init( &pub
);
357 ret
= DANE_E_PUBKEY_ERROR
;
361 ret
= gnutls_x509_crt_import(crt
, raw_crt
, GNUTLS_X509_FMT_DER
);
364 ret
= DANE_E_PUBKEY_ERROR
;
368 ret
= gnutls_pubkey_import_x509(pub
, crt
, 0);
371 ret
= DANE_E_PUBKEY_ERROR
;
375 ret
= gnutls_pubkey_export2(pub
, GNUTLS_X509_FMT_DER
, out
);
378 ret
= DANE_E_PUBKEY_ERROR
;
389 gnutls_pubkey_deinit(pub
);
391 gnutls_x509_crt_deinit(crt
);
396 static int verify_ca(const gnutls_datum_t
*raw_crt
, unsigned raw_crt_size
,
397 gnutls_certificate_type_t crt_type
,
398 dane_cert_type_t ctype
,
399 dane_match_type_t match
, gnutls_datum_t
* data
,
400 unsigned int *verify
)
402 gnutls_datum_t pubkey
= {NULL
, 0};
405 if (raw_crt_size
< 2)
406 return gnutls_assert_val(DANE_E_INVALID_REQUEST
);
408 if (ctype
== DANE_CERT_X509
&& crt_type
== GNUTLS_CRT_X509
) {
410 if (!matches(&raw_crt
[1], data
, match
)) {
412 *verify
|= DANE_VERIFY_CA_CONSTRAINS_VIOLATED
;
415 } else if (ctype
== DANE_CERT_PK
&& crt_type
== GNUTLS_CRT_X509
) {
416 ret
= crt_to_pubkey(&raw_crt
[1], &pubkey
);
422 if (!matches(&pubkey
, data
, match
)) {
424 *verify
|= DANE_VERIFY_CA_CONSTRAINS_VIOLATED
;
434 static int verify_ee(const gnutls_datum_t
*raw_crt
, gnutls_certificate_type_t crt_type
,
435 dane_cert_type_t ctype
, dane_match_type_t match
, gnutls_datum_t
* data
,
436 unsigned int *verify
)
438 gnutls_datum_t pubkey
= {NULL
, 0};
441 if (ctype
== DANE_CERT_X509
&& crt_type
== GNUTLS_CRT_X509
) {
443 if (!matches(raw_crt
, data
, match
)) {
445 *verify
|= DANE_VERIFY_CERT_DIFFERS
;
448 } else if (ctype
== DANE_CERT_PK
&& crt_type
== GNUTLS_CRT_X509
) {
450 ret
= crt_to_pubkey(raw_crt
, &pubkey
);
456 if (!matches(&pubkey
, data
, match
)) {
458 *verify
|= DANE_VERIFY_CERT_DIFFERS
;
470 * @s: A DANE state structure (may be NULL)
471 * @chain: A certificate chain
472 * @chain_size: The size of the chain
473 * @chain_type: The type of the certificate chain
474 * @hostname: The hostname associated with the chain
475 * @proto: The protocol of the service connecting (e.g. tcp)
476 * @port: The port of the service connecting (e.g. 443)
477 * @sflags: Flags for the the initialization of @s (if NULL)
478 * @vflags: Verification flags; should be zero
479 * @verify: An OR'ed list of %dane_verify_status_t.
481 * This function will verify the given certificate chain against the
482 * CA constrains and/or the certificate available via DANE.
483 * If no information via DANE can be obtained the flag %DANE_VERIFY_NO_DANE_INFO
484 * is set. If a DNSSEC signature is not available for the DANE
485 * record then the verify flag %DANE_VERIFY_NO_DNSSEC_DATA is set.
487 * Due to the many possible options of DANE, there is no single threat
488 * model countered. When notifying the user about DANE verification results
489 * it may be better to mention: DANE verification did not reject the certificate,
490 * rather than mentioning a successful DANE verication.
492 * If the @q parameter is provided it will be used for caching entries.
494 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
495 * negative error value.
498 int dane_verify_crt (dane_state_t s
,
499 const gnutls_datum_t
*chain
, unsigned chain_size
,
500 gnutls_certificate_type_t chain_type
,
501 const char * hostname
, const char* proto
, unsigned int port
,
502 unsigned int sflags
, unsigned int vflags
,
503 unsigned int *verify
)
505 dane_state_t _s
= NULL
;
506 dane_query_t r
= NULL
;
508 unsigned int usage
, type
, match
, idx
;
511 if (chain_type
!= GNUTLS_CRT_X509
)
512 return gnutls_assert_val(DANE_E_INVALID_REQUEST
);
517 ret
= dane_state_init(&_s
, sflags
);
525 ret
= dane_query_tlsa(_s
, &r
, hostname
, proto
, port
);
533 ret
= dane_query_data(r
, idx
++, &usage
, &type
, &match
, &data
);
534 if (ret
== DANE_E_REQUESTED_DATA_NOT_AVAILABLE
)
542 if (usage
== DANE_CERT_USAGE_LOCAL_CA
|| usage
== DANE_CERT_USAGE_CA
) {
543 ret
= verify_ca(chain
, chain_size
, chain_type
, type
, match
, &data
, verify
);
549 } else if (usage
== DANE_CERT_USAGE_LOCAL_EE
|| usage
== DANE_CERT_USAGE_EE
) {
550 ret
= verify_ee(&chain
[0], chain_type
, type
, match
, &data
, verify
);
561 if (s
== NULL
) dane_state_deinit(_s
);
562 if (r
!= NULL
) dane_query_deinit(r
);
567 * dane_verify_session_crt:
568 * @s: A DANE state structure (may be NULL)
569 * @session: A gnutls session
570 * @hostname: The hostname associated with the chain
571 * @proto: The protocol of the service connecting (e.g. tcp)
572 * @port: The port of the service connecting (e.g. 443)
573 * @sflags: Flags for the the initialization of @s (if NULL)
574 * @vflags: Verification flags; should be zero
575 * @verify: An OR'ed list of %dane_verify_status_t.
577 * This function will verify session's certificate chain against the
578 * CA constrains and/or the certificate available via DANE.
579 * See dane_verify_crt() for more information.
581 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
582 * negative error value.
585 int dane_verify_session_crt (
587 gnutls_session_t session
,
588 const char * hostname
, const char* proto
, unsigned int port
,
589 unsigned int sflags
, unsigned int vflags
,
590 unsigned int *verify
)
592 const gnutls_datum_t
*cert_list
;
593 unsigned int cert_list_size
= 0;
596 cert_list
= gnutls_certificate_get_peers(session
, &cert_list_size
);
597 if (cert_list_size
== 0) {
598 return gnutls_assert_val(DANE_E_NO_CERT
);
601 type
= gnutls_certificate_type_get(session
);
603 return dane_verify_crt(s
, cert_list
, cert_list_size
, type
, hostname
, proto
, port
, sflags
, vflags
, verify
);
607 * dane_verification_status_print:
608 * @status: The status flags to be printed
609 * @type: The certificate type
610 * @out: Newly allocated datum with (0) terminated string.
611 * @flags: should be zero
613 * This function will pretty print the status of a verification
614 * process -- eg. the one obtained by dane_verify_crt().
616 * The output @out needs to be deallocated using gnutls_free().
618 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
619 * negative error value.
622 dane_verification_status_print (unsigned int status
,
623 gnutls_datum_t
* out
, unsigned int flags
)
625 gnutls_buffer_st str
;
628 _gnutls_buffer_init (&str
);
631 _gnutls_buffer_append_str (&str
, _("Certificate matches. "));
633 _gnutls_buffer_append_str (&str
, _("Verification failed. "));
635 if (status
& DANE_VERIFY_CA_CONSTRAINS_VIOLATED
)
636 _gnutls_buffer_append_str (&str
, _("CA constrains were violated. "));
638 if (status
& DANE_VERIFY_CERT_DIFFERS
)
639 _gnutls_buffer_append_str (&str
, _("The certificate differs. "));
641 if (status
& DANE_VERIFY_NO_DANE_INFO
)
642 _gnutls_buffer_append_str (&str
, _("There were no DANE information. "));
644 ret
= _gnutls_buffer_to_datum( &str
, out
);
645 if (out
->size
> 0) out
->size
--;