The high level functions accept sflags and vflags as separate options.
[gnutls.git] / libdane / dane.c
blob0596f8ee183ca8f25f8effc64dfe6ffb4c617b5a
1 /*
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/>
23 #include <config.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <arpa/inet.h>
30 #include <unbound.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
38 struct dane_state_st
40 struct ub_ctx* ctx;
41 unsigned int flags;
44 struct dane_query_st
46 struct ub_result* result;
47 unsigned int data_entries;
48 dane_cert_usage_t usage[MAX_DATA_ENTRIES];
49 dane_cert_type_t type[MAX_DATA_ENTRIES];
50 dane_match_type_t match[MAX_DATA_ENTRIES];
51 gnutls_datum_t data[MAX_DATA_ENTRIES];
52 unsigned int flags;
53 dane_query_status_t status;
56 /**
57 * dane_query_status:
58 * @q: The query result structure
60 * This function will return the status of the query response.
61 * See %dane_query_status_t for the possible types.
63 * Returns: The status type.
64 **/
65 dane_query_status_t dane_query_status(dane_query_t q)
67 return q->status;
70 /**
71 * dane_query_entries:
72 * @q: The query result structure
74 * This function will return the number of entries in a query.
76 * Returns: The number of entries.
77 **/
78 unsigned int dane_query_entries(dane_query_t q)
80 return q->data_entries;
83 /**
84 * dane_query_data:
85 * @q: The query result structure
86 * @idx: The index of the query response.
87 * @usage: The certificate usage (see %dane_cert_usage_t)
88 * @type: The certificate type (see %dane_cert_type_t)
89 * @match: The DANE matching type (see %dane_match_type_t)
90 * @data: The DANE data.
92 * This function will provide the DANE data from the query
93 * response.
95 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
96 * negative error value.
97 **/
98 int dane_query_data(dane_query_t q, unsigned int idx,
99 unsigned int *usage, unsigned int *type,
100 unsigned int *match, gnutls_datum_t * data)
102 if (idx >= q->data_entries)
103 return DANE_E_REQUESTED_DATA_NOT_AVAILABLE;
105 if (usage)
106 *usage = q->usage[idx];
107 if (type)
108 *type = q->type[idx];
109 if (match)
110 *match = q->match[idx];
111 if (data) {
112 data->data = q->data[idx].data;
113 data->size = q->data[idx].size;
116 return DANE_E_SUCCESS;
120 * dane_state_init:
121 * @s: The structure to be initialized
122 * @flags: flags from the %dane_state_flags enumeration
124 * This function will initialize a DANE query structure.
126 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
127 * negative error value.
129 int dane_state_init(dane_state_t* s, unsigned int flags)
131 struct ub_ctx* ctx;
132 int ret;
134 *s = calloc(1, sizeof(struct dane_state_st));
135 if (*s == NULL)
136 return DANE_E_MEMORY_ERROR;
138 ctx = ub_ctx_create();
139 if(!ctx) {
140 ret = DANE_E_INITIALIZATION_ERROR;
141 goto cleanup;
143 ub_ctx_debugout(ctx, stderr);
145 if (!(flags & DANE_F_IGNORE_LOCAL_RESOLVER)) {
146 if( (ret=ub_ctx_resolvconf(ctx, NULL)) != 0) {
147 ret = DANE_E_INITIALIZATION_ERROR;
148 goto cleanup;
151 if( (ret=ub_ctx_hosts(ctx, NULL)) != 0) {
152 ret = DANE_E_INITIALIZATION_ERROR;
153 goto cleanup;
157 /* read public keys for DNSSEC verification */
158 if( (ret=ub_ctx_add_ta_file(ctx, (char*)UNBOUND_ROOT_KEY_FILE)) != 0) {
159 ret = DANE_E_INITIALIZATION_ERROR;
160 goto cleanup;
163 (*s)->ctx = ctx;
164 (*s)->flags = flags;
166 return DANE_E_SUCCESS;
167 cleanup:
169 if (ctx)
170 ub_ctx_delete(ctx);
171 free(*s);
173 return ret;
177 * dane_state_deinit:
178 * @s: The structure to be deinitialized
180 * This function will deinitialize a DANE query structure.
183 void dane_state_deinit(dane_state_t s)
185 ub_ctx_delete(s->ctx);
186 free(s);
191 * dane_query_deinit:
192 * @q: The structure to be deinitialized
194 * This function will deinitialize a DANE query result structure.
197 void dane_query_deinit(dane_query_t q)
199 ub_resolve_free(q->result);
200 free(q);
204 * dane_query_tlsa:
205 * @s: The DANE state structure
206 * @r: A structure to place the result
207 * @host: The host name to resolve.
208 * @proto: The protocol type (tcp, udp, etc.)
209 * @port: The service port number (eg. 443).
211 * This function will query the DNS server for the TLSA (DANE)
212 * data for the given host.
214 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
215 * negative error value.
217 int dane_query_tlsa(dane_state_t s, dane_query_t *r, const char* host, const char* proto, unsigned int port)
219 char ns[1024];
220 int ret;
221 unsigned int i;
223 *r = calloc(1, sizeof(struct dane_query_st));
224 if (*r == NULL)
225 return DANE_E_MEMORY_ERROR;
227 snprintf(ns, sizeof(ns), "_%u._%s.%s", port, proto, host);
229 /* query for webserver */
230 ret = ub_resolve(s->ctx, ns, 52, 1, &(*r)->result);
231 if(ret != 0) {
232 return DANE_E_RESOLVING_ERROR;
235 /* show first result */
236 if(!(*r)->result->havedata) {
237 return DANE_E_NO_DANE_DATA;
240 i = 0;
241 do {
243 if ((*r)->result->len[i] > 3)
244 ret = DANE_E_SUCCESS;
245 else {
246 return DANE_E_RECEIVED_CORRUPT_DATA;
249 (*r)->usage[i] = (*r)->result->data[i][0];
250 (*r)->type[i] = (*r)->result->data[i][1];
251 (*r)->match[i] = (*r)->result->data[i][2];
252 (*r)->data[i].data = (void*)&(*r)->result->data[i][3];
253 (*r)->data[i].size = (*r)->result->len[i] - 3;
254 i++;
255 } while((*r)->result->data[i] != NULL);
257 (*r)->data_entries = i;
259 if (!(*r)->result->secure) {
260 if ((*r)->result->bogus)
261 ret = DANE_E_INVALID_DNSSEC_SIG;
262 else
263 ret = DANE_E_NO_DNSSEC_SIG;
266 /* show security status */
267 if ((*r)->result->secure)
268 (*r)->status = DANE_QUERY_DNSSEC_VERIFIED;
269 else if ((*r)->result->bogus)
270 (*r)->status = DANE_QUERY_BOGUS;
271 else (*r)->status = DANE_QUERY_NO_DNSSEC;
273 return ret;
276 static unsigned int matches(const gnutls_datum_t *raw1, const gnutls_datum_t *raw2,
277 dane_match_type_t match)
279 uint8_t digest[64];
280 int ret;
282 if (match == DANE_MATCH_EXACT) {
283 if (raw1->size != raw2->size)
284 return 0;
286 if (memcmp(raw1->data, raw2->data, raw1->size) != 0)
287 return 0;
289 return 1;
290 } else if (match == DANE_MATCH_SHA2_256) {
292 if (raw2->size != 32)
293 return 0;
295 ret = gnutls_hash_fast(GNUTLS_DIG_SHA256, raw1->data, raw1->size, digest);
296 if (ret < 0)
297 return 0;
299 if (memcmp(digest, raw2->data, 32) != 0)
300 return 0;
302 return 1;
303 } else if (match == DANE_MATCH_SHA2_512) {
304 if (raw2->size != 64)
305 return 0;
307 ret = gnutls_hash_fast(GNUTLS_DIG_SHA512, raw1->data, raw1->size, digest);
308 if (ret < 0)
309 return 0;
311 if (memcmp(digest, raw2->data, 64) != 0)
312 return 0;
314 return 1;
317 return 0;
320 static int crt_to_pubkey(const gnutls_datum_t *raw_crt, gnutls_datum_t * out)
322 gnutls_pubkey_t pub = NULL;
323 gnutls_x509_crt_t crt = NULL;
324 int ret;
326 out->data = NULL;
328 ret = gnutls_x509_crt_init(&crt);
329 if (ret < 0)
330 return DANE_E_PUBKEY_ERROR;
332 ret = gnutls_pubkey_init( &pub);
333 if (ret < 0) {
334 ret = DANE_E_PUBKEY_ERROR;
335 goto cleanup;
338 ret = gnutls_x509_crt_import(crt, raw_crt, GNUTLS_X509_FMT_DER);
339 if (ret < 0) {
340 ret = DANE_E_PUBKEY_ERROR;
341 goto cleanup;
344 ret = gnutls_pubkey_import_x509(pub, crt, 0);
345 if (ret < 0) {
346 ret = DANE_E_PUBKEY_ERROR;
347 goto cleanup;
350 ret = gnutls_pubkey_export2(pub, GNUTLS_X509_FMT_DER, out);
351 if (ret < 0) {
352 ret = DANE_E_PUBKEY_ERROR;
353 goto cleanup;
356 ret = 0;
357 goto clean_certs;
359 cleanup:
360 free(out->data);
361 clean_certs:
362 if (pub)
363 gnutls_pubkey_deinit(pub);
364 if (crt)
365 gnutls_x509_crt_deinit(crt);
367 return ret;
370 static int verify_ca(const gnutls_datum_t *raw_crt, unsigned raw_crt_size,
371 gnutls_certificate_type_t crt_type,
372 dane_cert_type_t ctype,
373 dane_match_type_t match, gnutls_datum_t * data,
374 unsigned int *verify)
376 gnutls_datum_t pubkey = {NULL, 0};
377 int ret;
379 if (raw_crt_size < 2)
380 return DANE_E_INVALID_REQUEST;
382 if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
384 if (!matches(&raw_crt[1], data, match))
385 *verify |= DANE_VERIFY_CA_CONSTRAINS_VIOLATED;
387 } else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
388 ret = crt_to_pubkey(&raw_crt[1], &pubkey);
389 if (ret < 0)
390 goto cleanup;
392 if (!matches(&pubkey, data, match))
393 *verify |= DANE_VERIFY_CA_CONSTRAINS_VIOLATED;
396 ret = 0;
397 cleanup:
398 free(pubkey.data);
399 return ret;
402 static int verify_ee(const gnutls_datum_t *raw_crt, gnutls_certificate_type_t crt_type,
403 dane_cert_type_t ctype, dane_match_type_t match, gnutls_datum_t * data,
404 unsigned int *verify)
406 gnutls_datum_t pubkey = {NULL, 0};
407 int ret;
409 if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
411 if (!matches(raw_crt, data, match))
412 *verify |= DANE_VERIFY_CERT_DIFFERS;
414 } else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
416 ret = crt_to_pubkey(raw_crt, &pubkey);
417 if (ret < 0)
418 goto cleanup;
420 if (!matches(&pubkey, data, match))
421 *verify |= DANE_VERIFY_CERT_DIFFERS;
424 ret = 0;
425 cleanup:
426 free(pubkey.data);
427 return ret;
431 * dane_verify_crt:
432 * @s: A DANE state structure (may be NULL)
433 * @chain: A certificate chain
434 * @chain_size: The size of the chain
435 * @chain_type: The type of the certificate chain
436 * @hostname: The hostname associated with the chain
437 * @proto: The protocol of the service connecting (e.g. tcp)
438 * @port: The port of the service connecting (e.g. 443)
439 * @sflags: Flags for the the initialization of @s (if NULL)
440 * @vflags: Verification flags; should be zero
441 * @verify: An OR'ed list of %dane_verify_status_t.
443 * This function will verify the given certificate chain against the
444 * CA constrains and/or the certificate available via DANE.
445 * If no information via DANE can be obtained the flag %DANE_VERIFY_NO_DANE_INFO
446 * is set. If a DNSSEC signature is not available for the DANE
447 * record then the verify flag %DANE_VERIFY_NO_DNSSEC_DATA is set.
449 * Due to the many possible options of DANE, there is no single threat
450 * model countered. When notifying the user about DANE verification results
451 * it may be better to mention: DANE verification did not reject the certificate,
452 * rather than mentioning a successful DANE verication.
454 * If the @q parameter is provided it will be used for caching entries.
456 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
457 * negative error value.
460 int dane_verify_crt (dane_state_t s,
461 const gnutls_datum_t *chain, unsigned chain_size,
462 gnutls_certificate_type_t chain_type,
463 const char * hostname, const char* proto, unsigned int port,
464 unsigned int sflags, unsigned int vflags,
465 unsigned int *verify)
467 dane_state_t _s = NULL;
468 dane_query_t r = NULL;
469 int ret;
470 unsigned int usage, type, match, idx;
471 gnutls_datum_t data;
473 if (chain_type != GNUTLS_CRT_X509)
474 return DANE_E_INVALID_REQUEST;
476 *verify = 0;
478 if (s == NULL) {
479 ret = dane_state_init(&_s, sflags);
480 if (ret < 0) {
481 return ret;
483 } else
484 _s = s;
486 ret = dane_query_tlsa(_s, &r, hostname, proto, port);
487 if (ret < 0) {
488 goto cleanup;
491 idx = 0;
492 do {
493 ret = dane_query_data(r, idx++, &usage, &type, &match, &data);
494 if (ret == DANE_E_REQUESTED_DATA_NOT_AVAILABLE)
495 break;
497 if (ret < 0) {
498 goto cleanup;
501 if (usage == DANE_CERT_USAGE_LOCAL_CA || usage == DANE_CERT_USAGE_CA) {
502 ret = verify_ca(chain, chain_size, chain_type, type, match, &data, verify);
503 if (ret < 0)
504 goto cleanup;
506 } else if (usage == DANE_CERT_USAGE_LOCAL_EE || usage == DANE_CERT_USAGE_EE) {
507 ret = verify_ee(&chain[0], chain_type, type, match, &data, verify);
508 if (ret < 0)
509 goto cleanup;
511 } while(1);
513 ret = 0;
515 cleanup:
516 if (s == NULL) dane_state_deinit(_s);
517 if (r != NULL) dane_query_deinit(r);
518 return ret;
522 * dane_verify_session_crt:
523 * @s: A DANE state structure (may be NULL)
524 * @session: A gnutls session
525 * @hostname: The hostname associated with the chain
526 * @proto: The protocol of the service connecting (e.g. tcp)
527 * @port: The port of the service connecting (e.g. 443)
528 * @sflags: Flags for the the initialization of @s (if NULL)
529 * @vflags: Verification flags; should be zero
530 * @verify: An OR'ed list of %dane_verify_status_t.
532 * This function will verify session's certificate chain against the
533 * CA constrains and/or the certificate available via DANE.
534 * See dane_verify_crt() for more information.
536 * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
537 * negative error value.
540 int dane_verify_session_crt (
541 dane_state_t s,
542 gnutls_session_t session,
543 const char * hostname, const char* proto, unsigned int port,
544 unsigned int sflags, unsigned int vflags,
545 unsigned int *verify)
547 const gnutls_datum_t *cert_list;
548 unsigned int cert_list_size = 0;
549 unsigned int type;
551 cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
552 if (cert_list_size == 0) {
553 return DANE_E_NO_CERT;
556 type = gnutls_certificate_type_get(session);
558 return dane_verify_crt(s, cert_list, cert_list_size, type, hostname, proto, port, sflags, vflags, verify);