Line data Source code
1 : /*
2 : * Copyright (C) 2012 KU Leuven
3 : * Copyright (C) 2013 Christian Grothoff
4 : * Copyright (C) 2013 Nikos Mavrogiannopoulos
5 : *
6 : * Author: Nikos Mavrogiannopoulos
7 : *
8 : * This file is part of libdane.
9 : *
10 : * The libdane library is free software; you can redistribute it
11 : * and/or modify it under the terms of the GNU Lesser General Public
12 : * License as published by the Free Software Foundation; either
13 : * version 2.1 of the License, or (at your option) any later version.
14 : *
15 : * This library is distributed in the hope that it will be useful, but
16 : * WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 : * Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public License
21 : * along with this program. If not, see <https://www.gnu.org/licenses/>
22 : *
23 : */
24 :
25 : #include <config.h>
26 :
27 : #include <stdio.h>
28 : #include <stdlib.h>
29 : #include <string.h>
30 : #include <errno.h>
31 : #include <arpa/inet.h>
32 : #include <unbound.h>
33 : #include <gnutls/dane.h>
34 : #include <gnutls/x509.h>
35 : #include <gnutls/abstract.h>
36 : #include <gnutls/crypto.h>
37 : #include "../lib/gnutls_int.h"
38 :
39 : #define MAX_DATA_ENTRIES 100
40 :
41 : #undef gnutls_assert
42 : #undef gnutls_assert_val
43 :
44 : #ifdef DEBUG
45 : #define gnutls_assert() fprintf(stderr, "ASSERT: %s: %d\n", __FILE__, __LINE__);
46 : #define gnutls_assert_val(x) gnutls_assert_val_int(x, __FILE__, __LINE__)
47 : static int gnutls_assert_val_int(int val, const char *file, int line)
48 : {
49 : fprintf(stderr, "ASSERT: %s: %d\n", file, line);
50 : return val;
51 : }
52 : #else
53 : #define gnutls_assert()
54 : #define gnutls_assert_val(x) (x)
55 : #endif
56 :
57 : struct dane_state_st {
58 : struct ub_ctx *ctx;
59 : unsigned int flags;
60 : };
61 :
62 : struct dane_query_st {
63 : struct ub_result *result;
64 : unsigned int data_entries;
65 : dane_cert_usage_t usage[MAX_DATA_ENTRIES];
66 : dane_cert_type_t type[MAX_DATA_ENTRIES];
67 : dane_match_type_t match[MAX_DATA_ENTRIES];
68 : gnutls_datum_t data[MAX_DATA_ENTRIES];
69 : unsigned int flags;
70 : dane_query_status_t status;
71 : };
72 :
73 : /**
74 : * dane_query_status:
75 : * @q: The query result structure
76 : *
77 : * This function will return the status of the query response.
78 : * See %dane_query_status_t for the possible types.
79 : *
80 : * Returns: The status type.
81 : **/
82 0 : dane_query_status_t dane_query_status(dane_query_t q)
83 : {
84 0 : return q->status;
85 : }
86 :
87 : /**
88 : * dane_query_entries:
89 : * @q: The query result structure
90 : *
91 : * This function will return the number of entries in a query.
92 : *
93 : * Returns: The number of entries.
94 : **/
95 3 : unsigned int dane_query_entries(dane_query_t q)
96 : {
97 3 : return q->data_entries;
98 : }
99 :
100 : /**
101 : * dane_query_data:
102 : * @q: The query result structure
103 : * @idx: The index of the query response.
104 : * @usage: The certificate usage (see %dane_cert_usage_t)
105 : * @type: The certificate type (see %dane_cert_type_t)
106 : * @match: The DANE matching type (see %dane_match_type_t)
107 : * @data: The DANE data.
108 : *
109 : * This function will provide the DANE data from the query
110 : * response.
111 : *
112 : * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
113 : * negative error value.
114 : **/
115 : int
116 17 : dane_query_data(dane_query_t q, unsigned int idx,
117 : unsigned int *usage, unsigned int *type,
118 : unsigned int *match, gnutls_datum_t * data)
119 : {
120 17 : if (idx >= q->data_entries)
121 : return
122 : gnutls_assert_val(DANE_E_REQUESTED_DATA_NOT_AVAILABLE);
123 :
124 14 : if (usage)
125 14 : *usage = q->usage[idx];
126 14 : if (type)
127 14 : *type = q->type[idx];
128 14 : if (match)
129 14 : *match = q->match[idx];
130 14 : if (data) {
131 14 : data->data = q->data[idx].data;
132 14 : data->size = q->data[idx].size;
133 : }
134 :
135 : return DANE_E_SUCCESS;
136 : }
137 :
138 : /**
139 : * dane_query_to_raw_tlsa:
140 : * @q: The query result structure
141 : * @data_entries: Pointer set to the number of entries in the query
142 : * @dane_data: Pointer to contain an array of DNS rdata items, terminated with a NULL pointer;
143 : * caller must guarantee that the referenced data remains
144 : * valid until dane_query_deinit() is called.
145 : * @dane_data_len: Pointer to contain the length n bytes of the dane_data items
146 : * @secure: Pointer set true if the result is validated securely, false if
147 : * validation failed or the domain queried has no security info
148 : * @bogus: Pointer set true if the result was not secure due to a security failure
149 : *
150 : * This function will provide the DANE data from the query
151 : * response.
152 : *
153 : * The pointers dane_data and dane_data_len are allocated with gnutls_malloc()
154 : * to contain the data from the query result structure (individual
155 : * @dane_data items simply point to the original data and are not allocated separately).
156 : * The returned @dane_data are only valid during the lifetime of @q.
157 : *
158 : * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
159 : * negative error value.
160 : */
161 : int
162 8 : dane_query_to_raw_tlsa(dane_query_t q, unsigned int *data_entries,
163 : char ***dane_data, int **dane_data_len, int *secure, int *bogus)
164 : {
165 8 : size_t data_sz;
166 8 : char *data_buf;
167 8 : unsigned int idx;
168 :
169 8 : *data_entries = 0;
170 8 : *dane_data = NULL;
171 8 : *dane_data_len = NULL;
172 :
173 8 : if (secure) {
174 8 : if (q->status & DANE_QUERY_DNSSEC_VERIFIED)
175 8 : *secure = 1;
176 : else
177 0 : *secure = 0;
178 : }
179 :
180 8 : if (bogus) {
181 8 : if (q->status & DANE_QUERY_BOGUS)
182 0 : *bogus = 1;
183 : else
184 8 : *bogus = 0;
185 : }
186 :
187 : /* pack dane_data pointer list followed by dane_data contents */
188 8 : data_sz = sizeof (**dane_data) * (q->data_entries + 1);
189 23 : for (idx = 0; idx < q->data_entries; idx++)
190 15 : data_sz += 3 + q->data[idx].size;
191 :
192 8 : *dane_data = gnutls_calloc (1, data_sz);
193 8 : if (*dane_data == NULL)
194 : return DANE_E_MEMORY_ERROR;
195 8 : data_buf = (char *)*dane_data;
196 8 : data_buf += sizeof (**dane_data) * (q->data_entries + 1);
197 :
198 8 : *dane_data_len = gnutls_calloc (q->data_entries + 1, sizeof (**dane_data_len));
199 8 : if (*dane_data_len == NULL) {
200 0 : free(*dane_data);
201 0 : *dane_data = NULL;
202 0 : return DANE_E_MEMORY_ERROR;
203 : }
204 :
205 23 : for (idx = 0; idx < q->data_entries; idx++) {
206 15 : (*dane_data)[idx] = data_buf;
207 15 : (*dane_data)[idx][0] = q->usage[idx];
208 15 : (*dane_data)[idx][1] = q->type[idx];
209 15 : (*dane_data)[idx][2] = q->match[idx];
210 15 : memcpy(&(*dane_data)[idx][3], q->data[idx].data, q->data[idx].size);
211 15 : (*dane_data_len)[idx] = 3 + q->data[idx].size;
212 15 : data_buf += 3 + q->data[idx].size;
213 : }
214 8 : (*dane_data)[idx] = NULL;
215 8 : (*dane_data_len)[idx] = 0;
216 8 : *data_entries = q->data_entries;
217 :
218 8 : return DANE_E_SUCCESS;
219 : }
220 :
221 : /**
222 : * dane_state_init:
223 : * @s: The structure to be initialized
224 : * @flags: flags from the %dane_state_flags enumeration
225 : *
226 : * This function will initialize the backend resolver. It is
227 : * intended to be used in scenarios where multiple resolvings
228 : * occur, to optimize against multiple re-initializations.
229 : *
230 : * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
231 : * negative error value.
232 : **/
233 4 : int dane_state_init(dane_state_t * s, unsigned int flags)
234 : {
235 4 : struct ub_ctx *ctx;
236 4 : int ret;
237 :
238 4 : *s = calloc(1, sizeof(struct dane_state_st));
239 4 : if (*s == NULL)
240 : return gnutls_assert_val(DANE_E_MEMORY_ERROR);
241 :
242 4 : ctx = ub_ctx_create();
243 4 : if (!ctx) {
244 0 : gnutls_assert();
245 0 : ret = DANE_E_INITIALIZATION_ERROR;
246 0 : goto cleanup;
247 : }
248 4 : ub_ctx_debugout(ctx, stderr);
249 :
250 4 : if (!(flags & DANE_F_IGNORE_LOCAL_RESOLVER)) {
251 0 : if (ub_ctx_resolvconf(ctx, NULL) != 0) {
252 0 : gnutls_assert();
253 0 : ret = DANE_E_INITIALIZATION_ERROR;
254 0 : goto cleanup;
255 : }
256 :
257 0 : if (ub_ctx_hosts(ctx, NULL) != 0) {
258 0 : gnutls_assert();
259 0 : ret = DANE_E_INITIALIZATION_ERROR;
260 0 : goto cleanup;
261 : }
262 : }
263 :
264 : /* read public keys for DNSSEC verification */
265 4 : if (!(flags & DANE_F_IGNORE_DNSSEC)) {
266 4 : if (ub_ctx_add_ta_file(ctx,
267 : (char *) UNBOUND_ROOT_KEY_FILE) !=
268 : 0) {
269 0 : gnutls_assert();
270 0 : ret = DANE_E_INITIALIZATION_ERROR;
271 0 : goto cleanup;
272 : }
273 : }
274 :
275 4 : (*s)->ctx = ctx;
276 4 : (*s)->flags = flags;
277 :
278 4 : return DANE_E_SUCCESS;
279 0 : cleanup:
280 :
281 0 : if (ctx)
282 0 : ub_ctx_delete(ctx);
283 0 : free(*s);
284 :
285 0 : return ret;
286 : }
287 :
288 : /**
289 : * dane_state_deinit:
290 : * @s: The structure to be deinitialized
291 : *
292 : * This function will deinitialize a DANE query structure.
293 : *
294 : **/
295 4 : void dane_state_deinit(dane_state_t s)
296 : {
297 4 : ub_ctx_delete(s->ctx);
298 4 : free(s);
299 4 : }
300 :
301 : /**
302 : * dane_state_set_dlv_file:
303 : * @s: The structure to be deinitialized
304 : * @file: The file holding the DLV keys.
305 : *
306 : * This function will set a file with trusted keys
307 : * for DLV (DNSSEC Lookaside Validation).
308 : *
309 : **/
310 0 : int dane_state_set_dlv_file(dane_state_t s, const char *file)
311 : {
312 0 : int ret;
313 :
314 0 : ret =
315 0 : ub_ctx_set_option(s->ctx, (char *) "dlv-anchor-file:",
316 : (void *) file);
317 0 : if (ret != 0)
318 0 : return gnutls_assert_val(DANE_E_FILE_ERROR);
319 :
320 : return 0;
321 : }
322 :
323 : /**
324 : * dane_query_deinit:
325 : * @q: The structure to be deinitialized
326 : *
327 : * This function will deinitialize a DANE query result structure.
328 : *
329 : **/
330 14 : void dane_query_deinit(dane_query_t q)
331 : {
332 14 : if (q->result)
333 6 : ub_resolve_free(q->result);
334 14 : free(q);
335 14 : }
336 :
337 :
338 : /**
339 : * dane_raw_tlsa:
340 : * @s: The DANE state structure
341 : * @r: A structure to place the result
342 : * @dane_data: array of DNS rdata items, terminated with a NULL pointer;
343 : * caller must guarantee that the referenced data remains
344 : * valid until dane_query_deinit() is called.
345 : * @dane_data_len: the length n bytes of the dane_data items
346 : * @secure: true if the result is validated securely, false if
347 : * validation failed or the domain queried has no security info
348 : * @bogus: if the result was not secure (secure = 0) due to a security failure,
349 : * and the result is due to a security failure, bogus is true.
350 : *
351 : * This function will fill in the TLSA (DANE) structure from
352 : * the given raw DNS record data. The @dane_data must be valid
353 : * during the lifetime of the query.
354 : *
355 : * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
356 : * negative error value.
357 : **/
358 : int
359 14 : dane_raw_tlsa(dane_state_t s, dane_query_t * r, char *const *dane_data,
360 : const int *dane_data_len, int secure, int bogus)
361 : {
362 14 : int ret = DANE_E_SUCCESS;
363 14 : unsigned int i;
364 :
365 14 : *r = calloc(1, sizeof(struct dane_query_st));
366 14 : if (*r == NULL)
367 : return gnutls_assert_val(DANE_E_MEMORY_ERROR);
368 :
369 14 : (*r)->data_entries = 0;
370 :
371 35 : for (i = 0; i < MAX_DATA_ENTRIES; i++) {
372 35 : if (dane_data[i] == NULL)
373 : break;
374 :
375 21 : if (dane_data_len[i] <= 3)
376 : return
377 : gnutls_assert_val
378 : (DANE_E_RECEIVED_CORRUPT_DATA);
379 :
380 21 : (*r)->usage[i] = dane_data[i][0];
381 21 : (*r)->type[i] = dane_data[i][1];
382 21 : (*r)->match[i] = dane_data[i][2];
383 21 : (*r)->data[i].data = (void *) &dane_data[i][3];
384 21 : (*r)->data[i].size = dane_data_len[i] - 3;
385 21 : (*r)->data_entries++;
386 : }
387 :
388 14 : if (!(s->flags & DANE_F_INSECURE) && !secure) {
389 0 : if (bogus)
390 : ret = gnutls_assert_val(DANE_E_INVALID_DNSSEC_SIG);
391 : else
392 0 : ret = gnutls_assert_val(DANE_E_NO_DNSSEC_SIG);
393 : }
394 :
395 : /* show security status */
396 14 : if (secure) {
397 14 : (*r)->status = DANE_QUERY_DNSSEC_VERIFIED;
398 0 : } else if (bogus) {
399 0 : gnutls_assert();
400 0 : (*r)->status = DANE_QUERY_BOGUS;
401 : } else {
402 0 : gnutls_assert();
403 0 : (*r)->status = DANE_QUERY_NO_DNSSEC;
404 : }
405 :
406 : return ret;
407 : }
408 :
409 :
410 : /**
411 : * dane_query_tlsa:
412 : * @s: The DANE state structure
413 : * @r: A structure to place the result
414 : * @host: The host name to resolve.
415 : * @proto: The protocol type (tcp, udp, etc.)
416 : * @port: The service port number (eg. 443).
417 : *
418 : * This function will query the DNS server for the TLSA (DANE)
419 : * data for the given host.
420 : *
421 : * Returns: On success, %DANE_E_SUCCESS (0) is returned, otherwise a
422 : * negative error value.
423 : **/
424 : int
425 6 : dane_query_tlsa(dane_state_t s, dane_query_t * r, const char *host,
426 : const char *proto, unsigned int port)
427 : {
428 6 : char ns[1024];
429 6 : int ret;
430 6 : struct ub_result *result;
431 :
432 6 : snprintf(ns, sizeof(ns), "_%u._%s.%s", port, proto, host);
433 :
434 : /* query for webserver */
435 6 : ret = ub_resolve(s->ctx, ns, 52, 1, &result);
436 6 : if (ret != 0) {
437 : return gnutls_assert_val(DANE_E_RESOLVING_ERROR);
438 : }
439 :
440 : /* show first result */
441 6 : if (!result->havedata) {
442 0 : ub_resolve_free(result);
443 0 : return gnutls_assert_val(DANE_E_NO_DANE_DATA);
444 : }
445 :
446 6 : ret =
447 6 : dane_raw_tlsa(s, r, result->data, result->len, result->secure,
448 : result->bogus);
449 6 : if (*r == NULL) {
450 0 : ub_resolve_free(result);
451 0 : return ret;
452 : }
453 6 : (*r)->result = result;
454 6 : return ret;
455 : }
456 :
457 :
458 : static unsigned int
459 9 : matches(const gnutls_datum_t * raw1, const gnutls_datum_t * raw2,
460 : dane_match_type_t match)
461 : {
462 9 : uint8_t digest[64];
463 9 : int ret;
464 :
465 9 : if (match == DANE_MATCH_EXACT) {
466 0 : if (raw1->size != raw2->size)
467 : return gnutls_assert_val(0);
468 :
469 0 : if (memcmp(raw1->data, raw2->data, raw1->size) != 0)
470 : return gnutls_assert_val(0);
471 :
472 0 : return 1;
473 9 : } else if (match == DANE_MATCH_SHA2_256) {
474 :
475 9 : if (raw2->size != 32)
476 : return gnutls_assert_val(0);
477 :
478 9 : ret =
479 18 : gnutls_hash_fast(GNUTLS_DIG_SHA256, raw1->data,
480 9 : raw1->size, digest);
481 9 : if (ret < 0)
482 : return gnutls_assert_val(0);
483 :
484 9 : if (memcmp(digest, raw2->data, 32) != 0)
485 : return gnutls_assert_val(0);
486 :
487 7 : return 1;
488 0 : } else if (match == DANE_MATCH_SHA2_512) {
489 0 : if (raw2->size != 64)
490 : return gnutls_assert_val(0);
491 :
492 0 : ret =
493 0 : gnutls_hash_fast(GNUTLS_DIG_SHA512, raw1->data,
494 0 : raw1->size, digest);
495 0 : if (ret < 0)
496 : return gnutls_assert_val(0);
497 :
498 0 : if (memcmp(digest, raw2->data, 64) != 0)
499 : return gnutls_assert_val(0);
500 :
501 0 : return 1;
502 : }
503 :
504 : return gnutls_assert_val(0);
505 : }
506 :
507 : static int
508 5 : crt_to_pubkey(const gnutls_datum_t * raw_crt, gnutls_datum_t * out)
509 : {
510 5 : gnutls_pubkey_t pub = NULL;
511 5 : gnutls_x509_crt_t crt = NULL;
512 5 : int ret;
513 :
514 5 : out->data = NULL;
515 :
516 5 : ret = gnutls_x509_crt_init(&crt);
517 5 : if (ret < 0)
518 : return gnutls_assert_val(DANE_E_PUBKEY_ERROR);
519 :
520 5 : ret = gnutls_pubkey_init(&pub);
521 5 : if (ret < 0) {
522 0 : gnutls_assert();
523 0 : ret = DANE_E_PUBKEY_ERROR;
524 0 : goto cleanup;
525 : }
526 :
527 5 : ret = gnutls_x509_crt_import(crt, raw_crt, GNUTLS_X509_FMT_DER);
528 5 : if (ret < 0) {
529 0 : gnutls_assert();
530 0 : ret = DANE_E_PUBKEY_ERROR;
531 0 : goto cleanup;
532 : }
533 :
534 5 : ret = gnutls_pubkey_import_x509(pub, crt, 0);
535 5 : if (ret < 0) {
536 0 : gnutls_assert();
537 0 : ret = DANE_E_PUBKEY_ERROR;
538 0 : goto cleanup;
539 : }
540 :
541 5 : ret = gnutls_pubkey_export2(pub, GNUTLS_X509_FMT_DER, out);
542 5 : if (ret < 0) {
543 0 : gnutls_assert();
544 0 : ret = DANE_E_PUBKEY_ERROR;
545 0 : goto cleanup;
546 : }
547 :
548 5 : ret = 0;
549 5 : goto clean_certs;
550 :
551 0 : cleanup:
552 0 : free(out->data);
553 0 : out->data = NULL;
554 5 : clean_certs:
555 5 : if (pub)
556 5 : gnutls_pubkey_deinit(pub);
557 5 : if (crt)
558 5 : gnutls_x509_crt_deinit(crt);
559 :
560 : return ret;
561 : }
562 :
563 : static int
564 6 : verify_ca(const gnutls_datum_t * raw_crt, unsigned raw_crt_size,
565 : gnutls_certificate_type_t crt_type,
566 : dane_cert_type_t ctype,
567 : dane_match_type_t match, gnutls_datum_t * data,
568 : unsigned int *verify)
569 : {
570 6 : gnutls_datum_t pubkey = { NULL, 0 };
571 6 : int ret, i;
572 6 : unsigned int vstatus = 0;
573 6 : gnutls_x509_crt_t crt = NULL, ca = NULL;
574 6 : unsigned is_ok = 0;
575 :
576 6 : if (raw_crt_size < 2) /* we cannot verify the CA */
577 : return gnutls_assert_val(DANE_E_UNKNOWN_DANE_DATA);
578 :
579 4 : if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
580 4 : is_ok = 0;
581 5 : for (i=raw_crt_size-1;i>=1;i--) {
582 4 : if (matches(&raw_crt[i], data, match)) {
583 : is_ok = 1;
584 : break;
585 : }
586 : }
587 :
588 4 : if (is_ok == 0) {
589 1 : gnutls_assert();
590 1 : *verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
591 : }
592 :
593 0 : } else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
594 0 : is_ok = 0;
595 :
596 0 : for (i=raw_crt_size-1;i>=1;i--) {
597 0 : ret = crt_to_pubkey(&raw_crt[i], &pubkey);
598 0 : if (ret < 0) {
599 0 : gnutls_assert();
600 0 : goto cleanup;
601 : }
602 :
603 0 : if (matches(&pubkey, data, match)) {
604 : is_ok = 1;
605 : break;
606 : }
607 :
608 0 : free(pubkey.data);
609 0 : pubkey.data = NULL;
610 : }
611 :
612 0 : if (is_ok == 0) {
613 0 : gnutls_assert();
614 0 : *verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
615 : }
616 : } else {
617 0 : ret = gnutls_assert_val(DANE_E_UNKNOWN_DANE_DATA);
618 0 : goto cleanup;
619 : }
620 :
621 : /* check if the certificate chain is actually a chain */
622 4 : ret = gnutls_x509_crt_init(&crt);
623 4 : if (ret < 0) {
624 0 : ret = gnutls_assert_val(DANE_E_CERT_ERROR);
625 0 : goto cleanup;
626 : }
627 :
628 4 : ret =
629 4 : gnutls_x509_crt_import(crt, &raw_crt[0], GNUTLS_X509_FMT_DER);
630 4 : if (ret < 0) {
631 0 : ret = gnutls_assert_val(DANE_E_CERT_ERROR);
632 0 : goto cleanup;
633 : }
634 :
635 4 : for (i=raw_crt_size-1;i>=1;i--) {
636 4 : ret = gnutls_x509_crt_init(&ca);
637 4 : if (ret < 0) {
638 0 : ret = gnutls_assert_val(DANE_E_CERT_ERROR);
639 0 : goto cleanup;
640 : }
641 :
642 4 : ret = gnutls_x509_crt_import(ca, &raw_crt[i], GNUTLS_X509_FMT_DER);
643 4 : if (ret < 0) {
644 0 : ret = gnutls_assert_val(DANE_E_CERT_ERROR);
645 0 : goto cleanup;
646 : }
647 :
648 4 : ret = gnutls_x509_crt_check_issuer(crt, ca);
649 4 : if (ret != 0)
650 : break;
651 :
652 0 : gnutls_x509_crt_deinit(ca);
653 0 : ca = NULL;
654 : }
655 :
656 4 : if (ca == NULL) {
657 0 : gnutls_assert();
658 0 : *verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
659 : } else {
660 4 : ret = gnutls_x509_crt_verify(crt, &ca, 1, 0, &vstatus);
661 4 : if (ret < 0) {
662 0 : ret = gnutls_assert_val(DANE_E_CERT_ERROR);
663 0 : goto cleanup;
664 : }
665 :
666 4 : if (vstatus != 0)
667 0 : *verify |= DANE_VERIFY_CA_CONSTRAINTS_VIOLATED;
668 : }
669 :
670 : ret = 0;
671 4 : cleanup:
672 4 : free(pubkey.data);
673 4 : if (crt != NULL)
674 4 : gnutls_x509_crt_deinit(crt);
675 4 : if (ca != NULL)
676 4 : gnutls_x509_crt_deinit(ca);
677 : return ret;
678 : }
679 :
680 : static int
681 5 : verify_ee(const gnutls_datum_t * raw_crt,
682 : gnutls_certificate_type_t crt_type, dane_cert_type_t ctype,
683 : dane_match_type_t match, gnutls_datum_t * data,
684 : unsigned int *verify)
685 : {
686 5 : gnutls_datum_t pubkey = { NULL, 0 };
687 5 : int ret;
688 :
689 5 : if (ctype == DANE_CERT_X509 && crt_type == GNUTLS_CRT_X509) {
690 :
691 0 : if (!matches(raw_crt, data, match)) {
692 0 : gnutls_assert();
693 0 : *verify |= DANE_VERIFY_CERT_DIFFERS;
694 : }
695 :
696 5 : } else if (ctype == DANE_CERT_PK && crt_type == GNUTLS_CRT_X509) {
697 :
698 5 : ret = crt_to_pubkey(raw_crt, &pubkey);
699 5 : if (ret < 0) {
700 0 : gnutls_assert();
701 0 : goto cleanup;
702 : }
703 :
704 5 : if (!matches(&pubkey, data, match)) {
705 1 : gnutls_assert();
706 1 : *verify |= DANE_VERIFY_CERT_DIFFERS;
707 : }
708 : } else {
709 0 : ret = gnutls_assert_val(DANE_E_UNKNOWN_DANE_DATA);
710 0 : goto cleanup;
711 : }
712 :
713 : ret = 0;
714 5 : cleanup:
715 5 : free(pubkey.data);
716 5 : return ret;
717 : }
718 :
719 : #define CHECK_VRET(ret, checked, record_status, status) \
720 : if (ret == DANE_E_UNKNOWN_DANE_DATA) { \
721 : /* skip that entry */ \
722 : continue; \
723 : } else if (ret < 0) { \
724 : gnutls_assert(); \
725 : goto cleanup; \
726 : } \
727 : checked = 1; \
728 : if (record_status == 0) { \
729 : status = 0; \
730 : break; \
731 : } else { \
732 : status |= record_status; \
733 : }
734 :
735 : /**
736 : * dane_verify_crt_raw:
737 : * @s: A DANE state structure (may be NULL)
738 : * @chain: A certificate chain
739 : * @chain_size: The size of the chain
740 : * @chain_type: The type of the certificate chain
741 : * @r: DANE data to check against
742 : * @sflags: Flags for the initialization of @s (if NULL)
743 : * @vflags: Verification flags; an OR'ed list of %dane_verify_flags_t.
744 : * @verify: An OR'ed list of %dane_verify_status_t.
745 : *
746 : * This is the low-level function of dane_verify_crt(). See the
747 : * high level function for documentation.
748 : *
749 : * This function does not perform any resolving, it utilizes
750 : * cached entries from @r.
751 : *
752 : * Returns: a negative error code on error and %DANE_E_SUCCESS (0)
753 : * when the DANE entries were successfully parsed, irrespective of
754 : * whether they were verified (see @verify for that information). If
755 : * no usable entries were encountered %DANE_E_REQUESTED_DATA_NOT_AVAILABLE
756 : * will be returned.
757 : *
758 : **/
759 : int
760 10 : dane_verify_crt_raw(dane_state_t s,
761 : const gnutls_datum_t * chain, unsigned chain_size,
762 : gnutls_certificate_type_t chain_type,
763 : dane_query_t r,
764 : unsigned int sflags, unsigned int vflags,
765 : unsigned int *verify)
766 : {
767 10 : int ret;
768 10 : unsigned checked = 0;
769 10 : unsigned int usage, type, match, idx;
770 10 : gnutls_datum_t data;
771 :
772 10 : if (chain_type != GNUTLS_CRT_X509)
773 : return gnutls_assert_val(DANE_E_INVALID_REQUEST);
774 :
775 10 : if (chain_size == 0)
776 : return gnutls_assert_val(DANE_E_NO_CERT);
777 :
778 10 : *verify = 0;
779 10 : idx = 0;
780 14 : do {
781 14 : unsigned int record_verify = 0;
782 :
783 14 : ret =
784 14 : dane_query_data(r, idx++, &usage, &type, &match,
785 : &data);
786 14 : if (ret == DANE_E_REQUESTED_DATA_NOT_AVAILABLE)
787 : break;
788 :
789 11 : if (ret < 0) {
790 0 : gnutls_assert();
791 0 : goto cleanup;
792 : }
793 :
794 11 : if (!(vflags & DANE_VFLAG_ONLY_CHECK_EE_USAGE)
795 11 : && (usage == DANE_CERT_USAGE_LOCAL_CA
796 11 : || usage == DANE_CERT_USAGE_CA)) {
797 6 : ret =
798 6 : verify_ca(chain, chain_size, chain_type, type,
799 : match, &data, &record_verify);
800 6 : CHECK_VRET(ret, checked, record_verify, *verify);
801 :
802 5 : } else if (!(vflags & DANE_VFLAG_ONLY_CHECK_CA_USAGE)
803 5 : && (usage == DANE_CERT_USAGE_LOCAL_EE
804 5 : || usage == DANE_CERT_USAGE_EE)) {
805 5 : ret =
806 5 : verify_ee(&chain[0], chain_type, type, match,
807 : &data, &record_verify);
808 6 : CHECK_VRET(ret, checked, record_verify, *verify);
809 : }
810 : }
811 : while (1);
812 :
813 10 : if ((vflags & DANE_VFLAG_FAIL_IF_NOT_CHECKED) && checked == 0) {
814 : ret =
815 : gnutls_assert_val(DANE_E_REQUESTED_DATA_NOT_AVAILABLE);
816 10 : } else if (checked == 0) {
817 1 : *verify |= DANE_VERIFY_UNKNOWN_DANE_INFO;
818 : } else {
819 : ret = 0;
820 : }
821 :
822 : cleanup:
823 : return ret;
824 : }
825 :
826 :
827 : /**
828 : * dane_verify_crt:
829 : * @s: A DANE state structure (may be NULL)
830 : * @chain: A certificate chain
831 : * @chain_size: The size of the chain
832 : * @chain_type: The type of the certificate chain
833 : * @hostname: The hostname associated with the chain
834 : * @proto: The protocol of the service connecting (e.g. tcp)
835 : * @port: The port of the service connecting (e.g. 443)
836 : * @sflags: Flags for the initialization of @s (if NULL)
837 : * @vflags: Verification flags; an OR'ed list of %dane_verify_flags_t.
838 : * @verify: An OR'ed list of %dane_verify_status_t.
839 : *
840 : * This function will verify the given certificate chain against the
841 : * CA constrains and/or the certificate available via DANE.
842 : * If no information via DANE can be obtained the flag %DANE_VERIFY_NO_DANE_INFO
843 : * is set. If a DNSSEC signature is not available for the DANE
844 : * record then the verify flag %DANE_VERIFY_NO_DNSSEC_DATA is set.
845 : *
846 : * Due to the many possible options of DANE, there is no single threat
847 : * model countered. When notifying the user about DANE verification results
848 : * it may be better to mention: DANE verification did not reject the certificate,
849 : * rather than mentioning a successful DANE verication.
850 : *
851 : * Note that this function is designed to be run in addition to
852 : * PKIX - certificate chain - verification. To be run independently
853 : * the %DANE_VFLAG_ONLY_CHECK_EE_USAGE flag should be specified;
854 : * then the function will check whether the key of the peer matches the
855 : * key advertized in the DANE entry.
856 : *
857 : * Returns: a negative error code on error and %DANE_E_SUCCESS (0)
858 : * when the DANE entries were successfully parsed, irrespective of
859 : * whether they were verified (see @verify for that information). If
860 : * no usable entries were encountered %DANE_E_REQUESTED_DATA_NOT_AVAILABLE
861 : * will be returned.
862 : *
863 : **/
864 : int
865 3 : dane_verify_crt(dane_state_t s,
866 : const gnutls_datum_t * chain, unsigned chain_size,
867 : gnutls_certificate_type_t chain_type,
868 : const char *hostname, const char *proto, unsigned int port,
869 : unsigned int sflags, unsigned int vflags,
870 : unsigned int *verify)
871 : {
872 3 : dane_state_t state = NULL;
873 3 : dane_query_t r = NULL;
874 3 : int ret;
875 :
876 3 : *verify = 0;
877 3 : if (s == NULL) {
878 0 : ret = dane_state_init(&state, sflags);
879 0 : if (ret < 0) {
880 : gnutls_assert();
881 : return ret;
882 : }
883 : } else
884 3 : state = s;
885 :
886 3 : ret = dane_query_tlsa(state, &r, hostname, proto, port);
887 3 : if (ret < 0) {
888 0 : gnutls_assert();
889 0 : goto cleanup;
890 : }
891 3 : ret = dane_verify_crt_raw(state, chain, chain_size, chain_type,
892 : r, sflags, vflags, verify);
893 3 : cleanup:
894 3 : if (state != s)
895 0 : dane_state_deinit(state);
896 3 : if (r != NULL)
897 3 : dane_query_deinit(r);
898 : return ret;
899 : }
900 :
901 : /**
902 : * dane_verify_session_crt:
903 : * @s: A DANE state structure (may be NULL)
904 : * @session: A gnutls session
905 : * @hostname: The hostname associated with the chain
906 : * @proto: The protocol of the service connecting (e.g. tcp)
907 : * @port: The port of the service connecting (e.g. 443)
908 : * @sflags: Flags for the initialization of @s (if NULL)
909 : * @vflags: Verification flags; an OR'ed list of %dane_verify_flags_t.
910 : * @verify: An OR'ed list of %dane_verify_status_t.
911 : *
912 : * This function will verify session's certificate chain against the
913 : * CA constrains and/or the certificate available via DANE.
914 : * See dane_verify_crt() for more information.
915 : *
916 : * This will not verify the chain for validity; unless the DANE
917 : * verification is restricted to end certificates, this must be
918 : * be performed separately using gnutls_certificate_verify_peers3().
919 : *
920 : * Returns: a negative error code on error and %DANE_E_SUCCESS (0)
921 : * when the DANE entries were successfully parsed, irrespective of
922 : * whether they were verified (see @verify for that information). If
923 : * no usable entries were encountered %DANE_E_REQUESTED_DATA_NOT_AVAILABLE
924 : * will be returned.
925 : *
926 : **/
927 : int
928 0 : dane_verify_session_crt(dane_state_t s,
929 : gnutls_session_t session,
930 : const char *hostname, const char *proto,
931 : unsigned int port, unsigned int sflags,
932 : unsigned int vflags, unsigned int *verify)
933 : {
934 0 : const gnutls_datum_t *cert_list;
935 0 : unsigned int cert_list_size = 0;
936 0 : unsigned int type;
937 0 : int ret;
938 :
939 0 : cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
940 0 : if (cert_list_size == 0) {
941 : return gnutls_assert_val(DANE_E_NO_CERT);
942 : }
943 :
944 0 : type = gnutls_certificate_type_get(session);
945 :
946 : /* this list may be incomplete, try to get the self-signed CA if any */
947 0 : if (cert_list_size > 0) {
948 0 : gnutls_x509_crt_t crt, ca;
949 0 : gnutls_certificate_credentials_t sc;
950 :
951 0 : ret = gnutls_x509_crt_init(&crt);
952 0 : if (ret < 0) {
953 0 : gnutls_assert();
954 0 : goto failsafe;
955 : }
956 :
957 0 : ret = gnutls_x509_crt_import(crt, &cert_list[cert_list_size-1], GNUTLS_X509_FMT_DER);
958 0 : if (ret < 0) {
959 0 : gnutls_assert();
960 0 : gnutls_x509_crt_deinit(crt);
961 0 : goto failsafe;
962 : }
963 :
964 : /* if it is already self signed continue normally */
965 0 : ret = gnutls_x509_crt_check_issuer(crt, crt);
966 0 : if (ret != 0) {
967 0 : gnutls_assert();
968 0 : gnutls_x509_crt_deinit(crt);
969 0 : goto failsafe;
970 : }
971 :
972 : /* chain does not finish in a self signed cert, try to obtain the issuer */
973 0 : ret = gnutls_credentials_get(session, GNUTLS_CRD_CERTIFICATE, (void**)&sc);
974 0 : if (ret < 0) {
975 0 : gnutls_assert();
976 0 : gnutls_x509_crt_deinit(crt);
977 0 : goto failsafe;
978 : }
979 :
980 0 : ret = gnutls_certificate_get_issuer(sc, crt, &ca, 0);
981 0 : if (ret < 0) {
982 0 : gnutls_assert();
983 0 : gnutls_x509_crt_deinit(crt);
984 0 : goto failsafe;
985 : }
986 :
987 : /* make the new list */
988 0 : gnutls_datum_t *new_cert_list;
989 :
990 0 : new_cert_list = gnutls_malloc((cert_list_size + 1) * sizeof(gnutls_datum_t));
991 0 : if (new_cert_list == NULL) {
992 0 : gnutls_assert();
993 0 : gnutls_x509_crt_deinit(crt);
994 0 : goto failsafe;
995 : }
996 :
997 0 : memcpy(new_cert_list, cert_list, cert_list_size*sizeof(gnutls_datum_t));
998 :
999 0 : ret = gnutls_x509_crt_export2(ca, GNUTLS_X509_FMT_DER, &new_cert_list[cert_list_size]);
1000 0 : if (ret < 0) {
1001 0 : gnutls_assert();
1002 0 : free(new_cert_list);
1003 0 : gnutls_x509_crt_deinit(crt);
1004 0 : goto failsafe;
1005 : }
1006 :
1007 0 : ret = dane_verify_crt(s, new_cert_list, cert_list_size+1, type,
1008 : hostname, proto, port, sflags, vflags,
1009 : verify);
1010 0 : if (ret < 0) {
1011 0 : gnutls_assert();
1012 : }
1013 0 : gnutls_free(new_cert_list[cert_list_size].data);
1014 0 : free(new_cert_list);
1015 0 : return ret;
1016 : }
1017 :
1018 0 : failsafe:
1019 0 : return dane_verify_crt(s, cert_list, cert_list_size, type,
1020 : hostname, proto, port, sflags, vflags,
1021 : verify);
1022 : }
1023 :
1024 : /**
1025 : * dane_verification_status_print:
1026 : * @status: The status flags to be printed
1027 : * @type: The certificate type
1028 : * @out: Newly allocated datum with (0) terminated string.
1029 : * @flags: should be zero
1030 : *
1031 : * This function will pretty print the status of a verification
1032 : * process -- eg. the one obtained by dane_verify_crt().
1033 : *
1034 : * The output @out needs to be deallocated using gnutls_free().
1035 : *
1036 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1037 : * negative error value.
1038 : **/
1039 : int
1040 3 : dane_verification_status_print(unsigned int status,
1041 : gnutls_datum_t * out, unsigned int flags)
1042 : {
1043 3 : gnutls_buffer_st str;
1044 :
1045 3 : _gnutls_buffer_init(&str);
1046 :
1047 3 : if (status == 0)
1048 3 : _gnutls_buffer_append_str(&str,
1049 3 : _("Certificate matches. "));
1050 : else
1051 0 : _gnutls_buffer_append_str(&str,
1052 0 : _("Verification failed. "));
1053 :
1054 3 : if (status & DANE_VERIFY_CA_CONSTRAINTS_VIOLATED)
1055 0 : _gnutls_buffer_append_str(&str,
1056 0 : _
1057 : ("CA constrains were violated. "));
1058 :
1059 3 : if (status & DANE_VERIFY_CERT_DIFFERS)
1060 0 : _gnutls_buffer_append_str(&str,
1061 0 : _("The certificate differs. "));
1062 :
1063 3 : if (status & DANE_VERIFY_NO_DANE_INFO)
1064 0 : _gnutls_buffer_append_str(&str,
1065 0 : _
1066 : ("There were no DANE information. "));
1067 :
1068 3 : return _gnutls_buffer_to_datum(&str, out, 1);
1069 : }
|