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>
36 #define MAX_DATA_ENTRIES 4
40 unsigned int data_entries
;
41 dane_cert_usage_t usage
[MAX_DATA_ENTRIES
];
42 dane_cert_type_t type
[MAX_DATA_ENTRIES
];
43 dane_match_type_t match
[MAX_DATA_ENTRIES
];
44 gnutls_datum_t data
[MAX_DATA_ENTRIES
];
46 struct ub_result
* result
;
48 dane_query_status_t status
;
53 * @q: The query structure
55 * This function will return the status of the query response.
56 * See %dane_query_status_t for the possible types.
58 * Returns: The status type.
60 dane_query_status_t
dane_query_status(dane_query_t q
)
67 * @q: The query structure
69 * This function will return the number of entries in a query.
71 * Returns: The number of entries.
73 unsigned int dane_query_entries(dane_query_t q
)
75 return q
->data_entries
;
80 * @q: The query structure
81 * @idx: The index of the query response.
82 * @usage: The certificate usage (see %dane_cert_usage_t)
83 * @type: The certificate type (see %dane_cert_type_t)
84 * @match: The DANE matching type (see %dane_match_type_t)
85 * @data: The DANE data.
87 * This function will provide the DANE data from the query
90 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
91 * negative error value.
93 int dane_query_data(dane_query_t q
, unsigned int idx
,
94 unsigned int *usage
, unsigned int *type
,
95 unsigned int *match
, gnutls_datum_t
* data
)
97 if (idx
>= q
->data_entries
)
98 return DANE_E_REQUESTED_DATA_NOT_AVAILABLE
;
101 *usage
= q
->usage
[idx
];
103 *type
= q
->type
[idx
];
105 *match
= q
->match
[idx
];
107 data
->data
= q
->data
[idx
].data
;
108 data
->size
= q
->data
[idx
].size
;
111 return DANE_E_SUCCESS
;
116 * @q: The structure to be initialized
117 * @flags: flags from the DANE_F_* definitions
119 * This function will initialize a DANE query structure.
121 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
122 * negative error value.
124 int dane_query_init(dane_query_t
* q
, unsigned int flags
)
129 *q
= calloc(1, sizeof(struct dane_query_st
));
131 return DANE_E_MEMORY_ERROR
;
133 ctx
= ub_ctx_create();
135 ret
= DANE_E_INITIALIZATION_ERROR
;
138 ub_ctx_debugout(ctx
, stderr
);
140 if (!(flags
& DANE_F_IGNORE_LOCAL_RESOLVER
)) {
141 if( (ret
=ub_ctx_resolvconf(ctx
, NULL
)) != 0) {
142 ret
= DANE_E_INITIALIZATION_ERROR
;
146 if( (ret
=ub_ctx_hosts(ctx
, NULL
)) != 0) {
147 ret
= DANE_E_INITIALIZATION_ERROR
;
152 /* read public keys for DNSSEC verification */
153 if( (ret
=ub_ctx_add_ta_file(ctx
, (char*)UNBOUND_ROOT_KEY_FILE
)) != 0) {
154 ret
= DANE_E_INITIALIZATION_ERROR
;
161 return DANE_E_SUCCESS
;
173 * @q: The structure to be deinitialized
175 * This function will deinitialize a DANE query structure.
178 void dane_query_deinit(dane_query_t q
)
181 ub_ctx_delete(q
->ctx
);
182 ub_resolve_free(q
->result
);
188 * dane_query_resolve_tlsa:
189 * @q: The query structure
190 * @host: The host name to resolve.
191 * @proto: The protocol type (tcp, udp, etc.)
192 * @port: The service port number (eg. 443).
194 * This function will query the DNS server for the TLSA (DANE)
195 * data for the given host.
197 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
198 * negative error value.
200 int dane_query_resolve_tlsa(dane_query_t q
, const char* host
, const char* proto
, unsigned int port
)
207 ub_resolve_free(q
->result
);
211 snprintf(ns
, sizeof(ns
), "_%u._%s.%s", port
, proto
, host
);
213 /* query for webserver */
214 ret
= ub_resolve(q
->ctx
, ns
, 52, 1, &q
->result
);
216 return DANE_E_RESOLVING_ERROR
;
219 /* show first result */
220 if(!q
->result
->havedata
) {
221 return DANE_E_NO_DANE_DATA
;
227 if (q
->result
->len
[i
] > 3)
228 ret
= DANE_E_SUCCESS
;
230 return DANE_E_RECEIVED_CORRUPT_DATA
;
233 q
->usage
[i
] = q
->result
->data
[i
][0];
234 q
->type
[i
] = q
->result
->data
[i
][1];
235 q
->match
[i
] = q
->result
->data
[i
][2];
236 q
->data
[i
].data
= (void*)&q
->result
->data
[i
][3];
237 q
->data
[i
].size
= q
->result
->len
[i
];
239 } while(q
->result
->data
[i
] != NULL
);
243 if (!q
->result
->secure
) {
244 if (q
->result
->bogus
)
245 ret
= DANE_E_INVALID_DNSSEC_SIG
;
247 ret
= DANE_E_NO_DNSSEC_SIG
;
250 /* show security status */
251 if (q
->result
->secure
)
252 q
->status
= DANE_QUERY_DNSSEC_VERIFIED
;
253 else if (q
->result
->bogus
)
254 q
->status
= DANE_QUERY_BOGUS
;
255 else q
->status
= DANE_QUERY_NO_DNSSEC
;
260 static unsigned int matches(const gnutls_datum_t
*raw1
, const gnutls_datum_t
*raw2
,
261 dane_match_type_t match
)
266 if (match
== DANE_MATCH_EXACT
) {
267 if (raw1
->size
!= raw2
->size
)
270 if (memcmp(raw1
->data
, raw2
->data
, raw1
->size
) != 0)
274 } else if (match
== DANE_MATCH_SHA2_256
) {
279 ret
= gnutls_hash_fast(GNUTLS_DIG_SHA256
, raw1
->data
, raw1
->size
, digest
);
283 if (memcmp(digest
, raw2
->data
, 32) != 0)
287 } else if (match
== DANE_MATCH_SHA2_512
) {
291 ret
= gnutls_hash_fast(GNUTLS_DIG_SHA512
, raw1
->data
, raw1
->size
, digest
);
295 if (memcmp(digest
, raw2
->data
, 64) != 0)
304 static int crt_to_pubkey(const gnutls_datum_t
*raw_crt
, gnutls_datum_t
* out
)
306 gnutls_pubkey_t pub
= NULL
;
307 gnutls_x509_crt_t crt
= NULL
;
312 ret
= gnutls_x509_crt_init(&crt
);
314 return DANE_E_PUBKEY_ERROR
;
316 ret
= gnutls_pubkey_init( &pub
);
318 ret
= DANE_E_PUBKEY_ERROR
;
322 ret
= gnutls_x509_crt_import(crt
, raw_crt
, GNUTLS_X509_FMT_DER
);
324 ret
= DANE_E_PUBKEY_ERROR
;
328 ret
= gnutls_pubkey_import_x509(pub
, crt
, 0);
330 ret
= DANE_E_PUBKEY_ERROR
;
334 ret
= gnutls_pubkey_export2(pub
, GNUTLS_X509_FMT_DER
, out
);
336 ret
= DANE_E_PUBKEY_ERROR
;
347 gnutls_pubkey_deinit(pub
);
349 gnutls_x509_crt_deinit(crt
);
354 static int verify_ca(const gnutls_datum_t
*raw_crt
, unsigned raw_crt_size
,
355 gnutls_certificate_type_t crt_type
,
356 dane_cert_type_t ctype
,
357 dane_match_type_t match
, gnutls_datum_t
* data
,
358 unsigned int *verify
)
360 gnutls_datum_t pubkey
= {NULL
, 0};
363 if (raw_crt_size
< 2)
364 return DANE_E_INVALID_REQUEST
;
366 if (ctype
== DANE_CERT_X509
&& crt_type
== GNUTLS_CRT_X509
) {
368 if (!matches(&raw_crt
[1], data
, match
))
369 *verify
|= DANE_VERIFY_CA_CONSTRAINS_VIOLATED
;
371 } else if (ctype
== DANE_CERT_PK
&& crt_type
== GNUTLS_CRT_X509
) {
372 ret
= crt_to_pubkey(&raw_crt
[1], &pubkey
);
376 if (!matches(&pubkey
, data
, match
))
377 *verify
|= DANE_VERIFY_CA_CONSTRAINS_VIOLATED
;
386 static int verify_ee(const gnutls_datum_t
*raw_crt
, gnutls_certificate_type_t crt_type
,
387 dane_cert_type_t ctype
, dane_match_type_t match
, gnutls_datum_t
* data
,
388 unsigned int *verify
)
390 gnutls_datum_t pubkey
= {NULL
, 0};
393 if (ctype
== DANE_CERT_X509
&& crt_type
== GNUTLS_CRT_X509
) {
395 if (!matches(raw_crt
, data
, match
))
396 *verify
|= DANE_VERIFY_CERT_DIFFERS
;
398 } else if (ctype
== DANE_CERT_PK
&& crt_type
== GNUTLS_CRT_X509
) {
400 ret
= crt_to_pubkey(raw_crt
, &pubkey
);
404 if (!matches(&pubkey
, data
, match
))
405 *verify
|= DANE_VERIFY_CERT_DIFFERS
;
416 * @chain: A certificate chain
417 * @chain_size: The size of the chain
418 * @chain_type: The type of the certificate chain
419 * @hostname: The hostname associated with the chain
420 * @proto: The protocol of the service connecting (e.g. tcp)
421 * @port: The port of the service connecting (e.g. 443)
422 * @flags: The %DANE_F flags.
423 * @verify: An OR'ed list of %dane_verify_status_t.
425 * This function will verify the given certificate chain against the
426 * CA constrains and/or the certificate available via DANE.
427 * If no information via DANE can be obtained the flag %DANE_VERIFY_NO_DANE_INFO
428 * is set. If a DNSSEC signature is not available for the DANE
429 * record then the verify flag %DANE_VERIFY_NO_DNSSEC_DATA is set.
431 * Due to the many possible options of DANE, there is no single threat
432 * model countered. When notifying the user about DANE verification results
433 * it may be better to mention: DANE verification did not reject the certificate,
434 * rather than mentioning a successful DANE verication.
436 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
437 * negative error value.
440 int dane_verify_crt (
441 const gnutls_datum_t
*chain
, unsigned chain_size
,
442 gnutls_certificate_type_t chain_type
,
443 const char * hostname
, const char* proto
, unsigned int port
,
444 unsigned int flags
, unsigned int *verify
)
448 unsigned int usage
, type
, match
, idx
, status
;
451 if (chain_type
!= GNUTLS_CRT_X509
)
452 return DANE_E_INVALID_REQUEST
;
456 ret
= dane_query_init(&q
, flags
);
461 ret
= dane_query_resolve_tlsa(q
, hostname
, proto
, port
);
466 status
= dane_query_status(q
);
467 if (status
== DANE_QUERY_BOGUS
) {
468 *verify
|= DANE_VERIFY_DNSSEC_DATA_INVALID
;
470 } else if (status
== DANE_QUERY_NO_DNSSEC
) {
471 *verify
|= DANE_VERIFY_NO_DNSSEC_DATA
;
477 ret
= dane_query_data(q
, idx
++, &usage
, &type
, &match
, &data
);
478 if (ret
== DANE_E_REQUESTED_DATA_NOT_AVAILABLE
)
485 if (usage
== DANE_CERT_USAGE_LOCAL_CA
|| usage
== DANE_CERT_USAGE_CA
) {
486 ret
= verify_ca(chain
, chain_size
, chain_type
, type
, match
, &data
, verify
);
490 } else if (usage
== DANE_CERT_USAGE_LOCAL_EE
|| usage
== DANE_CERT_USAGE_EE
) {
491 ret
= verify_ee(&chain
[0], chain_type
, type
, match
, &data
, verify
);
500 dane_query_deinit(q
);
505 * dane_verify_session_crt:
506 * @session: A gnutls session
507 * @hostname: The hostname associated with the chain
508 * @proto: The protocol of the service connecting (e.g. tcp)
509 * @port: The port of the service connecting (e.g. 443)
510 * @flags: The %DANE_F flags.
511 * @verify: An OR'ed list of %dane_verify_status_t.
513 * This function will verify session's certificate chain against the
514 * CA constrains and/or the certificate available via DANE.
515 * See dane_verify_crt() for more information.
517 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
518 * negative error value.
521 int dane_verify_session_crt (
522 gnutls_session_t session
,
523 const char * hostname
, const char* proto
, unsigned int port
,
524 unsigned int flags
, unsigned int *verify
)
526 const gnutls_datum_t
*cert_list
;
527 unsigned int cert_list_size
= 0;
530 cert_list
= gnutls_certificate_get_peers(session
, &cert_list_size
);
531 if (cert_list_size
== 0) {
532 return DANE_E_NO_CERT
;
535 type
= gnutls_certificate_type_get(session
);
537 return dane_verify_crt(cert_list
, cert_list_size
, type
, hostname
, proto
, port
, flags
, verify
);