Line data Source code
1 : /*
2 : * Copyright (C) 2011-2016 Free Software Foundation, Inc.
3 : * Copyright (C) 2015-2016 Red Hat, Inc.
4 : *
5 : * Author: Nikos Mavrogiannopoulos
6 : *
7 : * This file is part of GnuTLS.
8 : *
9 : * The GnuTLS is free software; you can redistribute it and/or
10 : * modify it under the terms of the GNU Lesser General Public License
11 : * as published by the Free Software Foundation; either version 2.1 of
12 : * the License, or (at your option) any later version.
13 : *
14 : * This library is distributed in the hope that it will be useful, but
15 : * WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : * Lesser General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU Lesser General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>
21 : *
22 : */
23 :
24 : #include "gnutls_int.h"
25 : #include "errors.h"
26 : #include <libtasn1.h>
27 : #include <global.h>
28 : #include <num.h> /* MAX */
29 : #include <tls-sig.h>
30 : #include <str.h>
31 : #include <datum.h>
32 : #include <hash-pjw-bare.h>
33 : #include "x509_int.h"
34 : #include <common.h>
35 : #include <gnutls/x509-ext.h>
36 : #include "verify-high.h"
37 :
38 : struct named_cert_st {
39 : gnutls_x509_crt_t cert;
40 : uint8_t name[MAX_SERVER_NAME_SIZE];
41 : unsigned int name_size;
42 : };
43 :
44 : struct node_st {
45 : /* The trusted certificates */
46 : gnutls_x509_crt_t *trusted_cas;
47 : unsigned int trusted_ca_size;
48 :
49 : struct named_cert_st *named_certs;
50 : unsigned int named_cert_size;
51 :
52 : /* The trusted CRLs */
53 : gnutls_x509_crl_t *crls;
54 : unsigned int crl_size;
55 : };
56 :
57 : struct gnutls_x509_trust_list_iter {
58 : unsigned int node_index;
59 : unsigned int ca_index;
60 :
61 : #ifdef ENABLE_PKCS11
62 : gnutls_pkcs11_obj_t* pkcs11_list;
63 : unsigned int pkcs11_index;
64 : unsigned int pkcs11_size;
65 : #endif
66 : };
67 :
68 : #define DEFAULT_SIZE 127
69 :
70 : /**
71 : * gnutls_x509_trust_list_init:
72 : * @list: A pointer to the type to be initialized
73 : * @size: The size of the internal hash table. Use (0) for default size.
74 : *
75 : * This function will initialize an X.509 trust list structure.
76 : *
77 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
78 : * negative error value.
79 : *
80 : * Since: 3.0.0
81 : **/
82 : int
83 8282 : gnutls_x509_trust_list_init(gnutls_x509_trust_list_t * list,
84 : unsigned int size)
85 : {
86 8282 : gnutls_x509_trust_list_t tmp;
87 :
88 8282 : FAIL_IF_LIB_ERROR;
89 :
90 8282 : tmp =
91 8282 : gnutls_calloc(1, sizeof(struct gnutls_x509_trust_list_st));
92 :
93 8282 : if (!tmp)
94 : return GNUTLS_E_MEMORY_ERROR;
95 :
96 8282 : if (size == 0)
97 8282 : size = DEFAULT_SIZE;
98 8282 : tmp->size = size;
99 :
100 8282 : tmp->node = gnutls_calloc(1, tmp->size * sizeof(tmp->node[0]));
101 8282 : if (tmp->node == NULL) {
102 0 : gnutls_assert();
103 0 : gnutls_free(tmp);
104 0 : return GNUTLS_E_MEMORY_ERROR;
105 : }
106 :
107 8282 : *list = tmp;
108 :
109 8282 : return 0; /* success */
110 : }
111 :
112 : /**
113 : * gnutls_x509_trust_list_deinit:
114 : * @list: The list to be deinitialized
115 : * @all: if non-zero it will deinitialize all the certificates and CRLs contained in the structure.
116 : *
117 : * This function will deinitialize a trust list. Note that the
118 : * @all flag should be typically non-zero unless you have specified
119 : * your certificates using gnutls_x509_trust_list_add_cas() and you
120 : * want to prevent them from being deinitialized by this function.
121 : *
122 : * Since: 3.0.0
123 : **/
124 : void
125 7859 : gnutls_x509_trust_list_deinit(gnutls_x509_trust_list_t list,
126 : unsigned int all)
127 : {
128 7859 : unsigned int i, j;
129 :
130 7859 : if (!list)
131 : return;
132 :
133 7862 : for (j = 0; j < list->blacklisted_size; j++) {
134 3 : gnutls_x509_crt_deinit(list->blacklisted[j]);
135 : }
136 7859 : gnutls_free(list->blacklisted);
137 :
138 7861 : for (j = 0; j < list->keep_certs_size; j++) {
139 2 : gnutls_x509_crt_deinit(list->keep_certs[j]);
140 : }
141 7859 : gnutls_free(list->keep_certs);
142 :
143 1005950 : for (i = 0; i < list->size; i++) {
144 998093 : if (all) {
145 963229 : for (j = 0; j < list->node[i].trusted_ca_size; j++) {
146 3363 : gnutls_x509_crt_deinit(list->node[i].
147 3363 : trusted_cas[j]);
148 : }
149 : }
150 998093 : gnutls_free(list->node[i].trusted_cas);
151 :
152 :
153 998093 : if (all) {
154 960068 : for (j = 0; j < list->node[i].crl_size; j++) {
155 202 : gnutls_x509_crl_deinit(list->node[i].
156 202 : crls[j]);
157 : }
158 : }
159 998093 : gnutls_free(list->node[i].crls);
160 :
161 998093 : if (all) {
162 959867 : for (j = 0; j < list->node[i].named_cert_size; j++) {
163 1 : gnutls_x509_crt_deinit(list->node[i].
164 1 : named_certs[j].
165 : cert);
166 : }
167 : }
168 998093 : gnutls_free(list->node[i].named_certs);
169 : }
170 :
171 7859 : gnutls_free(list->x509_rdn_sequence.data);
172 7859 : gnutls_free(list->node);
173 7859 : gnutls_free(list->pkcs11_token);
174 7859 : gnutls_free(list);
175 : }
176 :
177 : static int
178 4102 : add_new_ca_to_rdn_seq(gnutls_x509_trust_list_t list,
179 : gnutls_x509_crt_t ca)
180 : {
181 4102 : gnutls_datum_t tmp;
182 4102 : size_t newsize;
183 4102 : unsigned char *newdata, *p;
184 :
185 : /* Add DN of the last added CAs to the RDN sequence
186 : * This will be sent to clients when a certificate
187 : * request message is sent.
188 : */
189 4102 : tmp.data = ca->raw_dn.data;
190 4102 : tmp.size = ca->raw_dn.size;
191 :
192 4102 : newsize = list->x509_rdn_sequence.size + 2 + tmp.size;
193 4102 : if (newsize < list->x509_rdn_sequence.size) {
194 0 : gnutls_assert();
195 0 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
196 : }
197 :
198 4102 : newdata =
199 4102 : gnutls_realloc_fast(list->x509_rdn_sequence.data,
200 : newsize);
201 4102 : if (newdata == NULL) {
202 0 : gnutls_assert();
203 0 : return GNUTLS_E_MEMORY_ERROR;
204 : }
205 :
206 4102 : p = newdata + list->x509_rdn_sequence.size;
207 4102 : _gnutls_write_uint16(tmp.size, p);
208 4102 : if (tmp.data != NULL)
209 4102 : memcpy(p + 2, tmp.data, tmp.size);
210 :
211 4102 : list->x509_rdn_sequence.size = newsize;
212 4102 : list->x509_rdn_sequence.data = newdata;
213 :
214 4102 : return 0;
215 : }
216 :
217 : #ifdef ENABLE_PKCS11
218 : /* Keeps the provided certificate in a structure that will be
219 : * deallocated on deinit. This is to handle get_issuer() with
220 : * pkcs11 trust modules when the GNUTLS_TL_GET_COPY flag isn't
221 : * given. It is not thread safe. */
222 : static int
223 2 : trust_list_add_compat(gnutls_x509_trust_list_t list,
224 : gnutls_x509_crt_t cert)
225 : {
226 4 : list->keep_certs =
227 2 : gnutls_realloc_fast(list->keep_certs,
228 2 : (list->keep_certs_size +
229 : 1) *
230 : sizeof(list->keep_certs[0]));
231 2 : if (list->keep_certs == NULL) {
232 0 : gnutls_assert();
233 0 : return GNUTLS_E_MEMORY_ERROR;
234 : }
235 :
236 2 : list->keep_certs[list->keep_certs_size] = cert;
237 2 : list->keep_certs_size++;
238 :
239 2 : return 0;
240 : }
241 : #endif
242 :
243 : /**
244 : * gnutls_x509_trust_list_add_cas:
245 : * @list: The list
246 : * @clist: A list of CAs
247 : * @clist_size: The length of the CA list
248 : * @flags: flags from %gnutls_trust_list_flags_t
249 : *
250 : * This function will add the given certificate authorities
251 : * to the trusted list. The CAs in @clist must not be deinitialized
252 : * during the lifetime of @list.
253 : *
254 : * If the flag %GNUTLS_TL_NO_DUPLICATES is specified, then
255 : * this function will ensure that no duplicates will be
256 : * present in the final trust list.
257 : *
258 : * If the flag %GNUTLS_TL_NO_DUPLICATE_KEY is specified, then
259 : * this function will ensure that no certificates with the
260 : * same key are present in the final trust list.
261 : *
262 : * If either %GNUTLS_TL_NO_DUPLICATE_KEY or %GNUTLS_TL_NO_DUPLICATES
263 : * are given, gnutls_x509_trust_list_deinit() must be called with parameter
264 : * @all being 1.
265 : *
266 : * Returns: The number of added elements is returned; that includes
267 : * duplicate entries.
268 : *
269 : * Since: 3.0.0
270 : **/
271 : int
272 1037 : gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list,
273 : const gnutls_x509_crt_t * clist,
274 : unsigned clist_size, unsigned int flags)
275 : {
276 1037 : unsigned i, j;
277 1037 : size_t hash;
278 1037 : int ret;
279 1037 : unsigned exists;
280 :
281 7356 : for (i = 0; i < clist_size; i++) {
282 6319 : exists = 0;
283 6319 : hash =
284 6319 : hash_pjw_bare(clist[i]->raw_dn.data,
285 6319 : clist[i]->raw_dn.size);
286 6319 : hash %= list->size;
287 :
288 : /* avoid duplicates */
289 6319 : if (flags & GNUTLS_TL_NO_DUPLICATES || flags & GNUTLS_TL_NO_DUPLICATE_KEY) {
290 8165 : for (j=0;j<list->node[hash].trusted_ca_size;j++) {
291 4014 : if (flags & GNUTLS_TL_NO_DUPLICATES)
292 4014 : ret = gnutls_x509_crt_equals(list->node[hash].trusted_cas[j], clist[i]);
293 : else
294 0 : ret = _gnutls_check_if_same_key(list->node[hash].trusted_cas[j], clist[i], 1);
295 4014 : if (ret != 0) {
296 : exists = 1;
297 : break;
298 : }
299 : }
300 :
301 6104 : if (exists != 0) {
302 1953 : gnutls_x509_crt_deinit(list->node[hash].trusted_cas[j]);
303 1953 : list->node[hash].trusted_cas[j] = clist[i];
304 1953 : continue;
305 : }
306 : }
307 :
308 8732 : list->node[hash].trusted_cas =
309 4366 : gnutls_realloc_fast(list->node[hash].trusted_cas,
310 4366 : (list->node[hash].trusted_ca_size +
311 : 1) *
312 : sizeof(list->node[hash].
313 : trusted_cas[0]));
314 4366 : if (list->node[hash].trusted_cas == NULL) {
315 0 : gnutls_assert();
316 0 : return i;
317 : }
318 :
319 8638 : if (gnutls_x509_crt_get_version(clist[i]) >= 3 &&
320 4272 : gnutls_x509_crt_get_ca_status(clist[i], NULL) <= 0) {
321 118 : gnutls_datum_t dn;
322 118 : gnutls_assert();
323 118 : if (gnutls_x509_crt_get_dn2(clist[i], &dn) >= 0) {
324 117 : _gnutls_audit_log(NULL,
325 : "There was a non-CA certificate in the trusted list: %s.\n",
326 : dn.data);
327 117 : gnutls_free(dn.data);
328 : }
329 : }
330 :
331 4366 : list->node[hash].trusted_cas[list->node[hash].
332 4366 : trusted_ca_size] = clist[i];
333 4366 : list->node[hash].trusted_ca_size++;
334 :
335 4366 : if (flags & GNUTLS_TL_USE_IN_TLS) {
336 4102 : ret = add_new_ca_to_rdn_seq(list, clist[i]);
337 4102 : if (ret < 0) {
338 0 : gnutls_assert();
339 0 : return i+1;
340 : }
341 : }
342 : }
343 :
344 1037 : return i;
345 : }
346 :
347 : static int
348 174 : advance_iter(gnutls_x509_trust_list_t list,
349 : gnutls_x509_trust_list_iter_t iter)
350 : {
351 174 : if (iter->node_index < list->size) {
352 88 : ++iter->ca_index;
353 :
354 : /* skip entries */
355 11137 : while (iter->node_index < list->size &&
356 11050 : iter->ca_index >= list->node[iter->node_index].trusted_ca_size) {
357 11049 : ++iter->node_index;
358 11049 : iter->ca_index = 0;
359 : }
360 :
361 88 : if (iter->node_index < list->size)
362 : return 0;
363 : }
364 :
365 : #ifdef ENABLE_PKCS11
366 173 : if (list->pkcs11_token != NULL) {
367 172 : if (iter->pkcs11_list == NULL) {
368 86 : int ret = gnutls_pkcs11_obj_list_import_url2(&iter->pkcs11_list, &iter->pkcs11_size,
369 : list->pkcs11_token, (GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE|GNUTLS_PKCS11_OBJ_FLAG_CRT|GNUTLS_PKCS11_OBJ_FLAG_MARK_CA|GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED), 0);
370 86 : if (ret < 0)
371 0 : return gnutls_assert_val(ret);
372 :
373 86 : if (iter->pkcs11_size > 0)
374 : return 0;
375 86 : } else if (iter->pkcs11_index < iter->pkcs11_size) {
376 86 : ++iter->pkcs11_index;
377 86 : if (iter->pkcs11_index < iter->pkcs11_size)
378 : return 0;
379 : }
380 : }
381 : #endif
382 :
383 87 : return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
384 : }
385 :
386 : /**
387 : * gnutls_x509_trust_list_iter_get_ca:
388 : * @list: The list
389 : * @iter: A pointer to an iterator (initially the iterator should be %NULL)
390 : * @crt: where the certificate will be copied
391 : *
392 : * This function obtains a certificate in the trust list and advances the
393 : * iterator to the next certificate. The certificate returned in @crt must be
394 : * deallocated with gnutls_x509_crt_deinit().
395 : *
396 : * When past the last element is accessed %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
397 : * is returned and the iterator is reset.
398 : *
399 : * The iterator is deinitialized and reset to %NULL automatically by this
400 : * function after iterating through all elements until
401 : * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. If the iteration is
402 : * aborted early, it must be manually deinitialized using
403 : * gnutls_x509_trust_list_iter_deinit().
404 : *
405 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
406 : * negative error value.
407 : *
408 : * Since: 3.4.0
409 : **/
410 : int
411 174 : gnutls_x509_trust_list_iter_get_ca(gnutls_x509_trust_list_t list,
412 : gnutls_x509_trust_list_iter_t *iter,
413 : gnutls_x509_crt_t *crt)
414 : {
415 174 : int ret;
416 :
417 : /* initialize iterator */
418 174 : if (*iter == NULL) {
419 87 : *iter = gnutls_malloc(sizeof (struct gnutls_x509_trust_list_iter));
420 87 : if (*iter == NULL)
421 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
422 :
423 87 : (*iter)->node_index = 0;
424 87 : (*iter)->ca_index = 0;
425 :
426 : #ifdef ENABLE_PKCS11
427 87 : (*iter)->pkcs11_list = NULL;
428 87 : (*iter)->pkcs11_size = 0;
429 87 : (*iter)->pkcs11_index = 0;
430 : #endif
431 :
432 : /* Advance iterator to the first valid entry */
433 87 : if (list->node[0].trusted_ca_size == 0) {
434 87 : ret = advance_iter(list, *iter);
435 87 : if (ret != 0) {
436 0 : gnutls_x509_trust_list_iter_deinit(*iter);
437 0 : *iter = NULL;
438 :
439 0 : *crt = NULL;
440 0 : return gnutls_assert_val(ret);
441 : }
442 : }
443 : }
444 :
445 : /* obtain the certificate at the current iterator position */
446 174 : if ((*iter)->node_index < list->size) {
447 1 : ret = gnutls_x509_crt_init(crt);
448 1 : if (ret < 0)
449 0 : return gnutls_assert_val(ret);
450 :
451 1 : ret = _gnutls_x509_crt_cpy(*crt, list->node[(*iter)->node_index].trusted_cas[(*iter)->ca_index]);
452 1 : if (ret < 0) {
453 0 : gnutls_x509_crt_deinit(*crt);
454 0 : return gnutls_assert_val(ret);
455 : }
456 : }
457 : #ifdef ENABLE_PKCS11
458 173 : else if ( (*iter)->pkcs11_index < (*iter)->pkcs11_size) {
459 86 : ret = gnutls_x509_crt_init(crt);
460 86 : if (ret < 0)
461 0 : return gnutls_assert_val(ret);
462 :
463 86 : ret = gnutls_x509_crt_import_pkcs11(*crt, (*iter)->pkcs11_list[(*iter)->pkcs11_index]);
464 86 : if (ret < 0) {
465 0 : gnutls_x509_crt_deinit(*crt);
466 0 : return gnutls_assert_val(ret);
467 : }
468 : }
469 : #endif
470 :
471 : else {
472 : /* iterator is at end */
473 87 : gnutls_x509_trust_list_iter_deinit(*iter);
474 87 : *iter = NULL;
475 :
476 87 : *crt = NULL;
477 87 : return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
478 : }
479 :
480 : /* Move iterator to the next position.
481 : * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned if the iterator
482 : * has been moved to the end position. That is okay, we return the
483 : * certificate that we read and when this function is called again we
484 : * report GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE to our caller. */
485 87 : ret = advance_iter(list, *iter);
486 87 : if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
487 0 : gnutls_x509_crt_deinit(*crt);
488 0 : *crt = NULL;
489 :
490 0 : return gnutls_assert_val(ret);
491 : }
492 :
493 : return 0;
494 : }
495 :
496 : /**
497 : * gnutls_x509_trust_list_iter_deinit:
498 : * @iter: The iterator structure to be deinitialized
499 : *
500 : * This function will deinitialize an iterator structure.
501 : *
502 : * Since: 3.4.0
503 : **/
504 87 : void gnutls_x509_trust_list_iter_deinit(gnutls_x509_trust_list_iter_t iter)
505 : {
506 87 : if (!iter)
507 : return;
508 :
509 : #ifdef ENABLE_PKCS11
510 87 : if (iter->pkcs11_size > 0) {
511 : unsigned i;
512 172 : for (i = 0; i < iter->pkcs11_size; ++i)
513 86 : gnutls_pkcs11_obj_deinit(iter->pkcs11_list[i]);
514 86 : gnutls_free(iter->pkcs11_list);
515 : }
516 : #endif
517 :
518 87 : gnutls_free(iter);
519 : }
520 :
521 35 : static gnutls_x509_crt_t crt_cpy(gnutls_x509_crt_t src)
522 : {
523 35 : gnutls_x509_crt_t dst;
524 35 : int ret;
525 :
526 35 : ret = gnutls_x509_crt_init(&dst);
527 35 : if (ret < 0) {
528 0 : gnutls_assert();
529 0 : return NULL;
530 : }
531 :
532 35 : ret = _gnutls_x509_crt_cpy(dst, src);
533 35 : if (ret < 0) {
534 0 : gnutls_x509_crt_deinit(dst);
535 0 : gnutls_assert();
536 0 : return NULL;
537 : }
538 :
539 35 : return dst;
540 : }
541 :
542 : /**
543 : * gnutls_x509_trust_list_remove_cas:
544 : * @list: The list
545 : * @clist: A list of CAs
546 : * @clist_size: The length of the CA list
547 : *
548 : * This function will remove the given certificate authorities
549 : * from the trusted list.
550 : *
551 : * Note that this function can accept certificates and authorities
552 : * not yet known. In that case they will be kept in a separate
553 : * black list that will be used during certificate verification.
554 : * Unlike gnutls_x509_trust_list_add_cas() there is no deinitialization
555 : * restriction for certificate list provided in this function.
556 : *
557 : * Returns: The number of removed elements is returned.
558 : *
559 : * Since: 3.1.10
560 : **/
561 : int
562 3 : gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list,
563 : const gnutls_x509_crt_t * clist,
564 : unsigned clist_size)
565 : {
566 3 : int r = 0;
567 3 : unsigned j, i;
568 3 : size_t hash;
569 :
570 6 : for (i = 0; i < clist_size; i++) {
571 3 : hash =
572 3 : hash_pjw_bare(clist[i]->raw_dn.data,
573 3 : clist[i]->raw_dn.size);
574 3 : hash %= list->size;
575 :
576 3 : for (j = 0; j < list->node[hash].trusted_ca_size; j++) {
577 3 : if (gnutls_x509_crt_equals
578 : (clist[i],
579 3 : list->node[hash].trusted_cas[j]) != 0) {
580 :
581 3 : gnutls_x509_crt_deinit(list->node[hash].
582 3 : trusted_cas[j]);
583 3 : list->node[hash].trusted_cas[j] =
584 3 : list->node[hash].trusted_cas[list->
585 : node
586 3 : [hash].
587 : trusted_ca_size
588 3 : - 1];
589 3 : list->node[hash].trusted_ca_size--;
590 3 : r++;
591 3 : break;
592 : }
593 : }
594 :
595 : /* Add the CA (or plain) certificate to the black list as well.
596 : * This will prevent a subordinate CA from being valid, and
597 : * ensure that a server certificate will also get rejected.
598 : */
599 6 : list->blacklisted =
600 3 : gnutls_realloc_fast(list->blacklisted,
601 3 : (list->blacklisted_size + 1) *
602 : sizeof(list->blacklisted[0]));
603 3 : if (list->blacklisted == NULL)
604 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
605 :
606 3 : list->blacklisted[list->blacklisted_size] = crt_cpy(clist[i]);
607 3 : if (list->blacklisted[list->blacklisted_size] != NULL)
608 3 : list->blacklisted_size++;
609 : }
610 :
611 : return r;
612 : }
613 :
614 : /**
615 : * gnutls_x509_trust_list_add_named_crt:
616 : * @list: The list
617 : * @cert: A certificate
618 : * @name: An identifier for the certificate
619 : * @name_size: The size of the identifier
620 : * @flags: should be 0.
621 : *
622 : * This function will add the given certificate to the trusted
623 : * list and associate it with a name. The certificate will not be
624 : * be used for verification with gnutls_x509_trust_list_verify_crt()
625 : * but with gnutls_x509_trust_list_verify_named_crt() or
626 : * gnutls_x509_trust_list_verify_crt2() - the latter only since
627 : * GnuTLS 3.4.0 and if a hostname is provided.
628 : *
629 : * In principle this function can be used to set individual "server"
630 : * certificates that are trusted by the user for that specific server
631 : * but for no other purposes.
632 : *
633 : * The certificate @cert must not be deinitialized during the lifetime
634 : * of the @list.
635 : *
636 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
637 : * negative error value.
638 : *
639 : * Since: 3.0.0
640 : **/
641 : int
642 1 : gnutls_x509_trust_list_add_named_crt(gnutls_x509_trust_list_t list,
643 : gnutls_x509_crt_t cert,
644 : const void *name, size_t name_size,
645 : unsigned int flags)
646 : {
647 1 : size_t hash;
648 :
649 1 : if (name_size >= MAX_SERVER_NAME_SIZE)
650 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
651 :
652 1 : hash =
653 1 : hash_pjw_bare(cert->raw_issuer_dn.data,
654 1 : cert->raw_issuer_dn.size);
655 1 : hash %= list->size;
656 :
657 2 : list->node[hash].named_certs =
658 1 : gnutls_realloc_fast(list->node[hash].named_certs,
659 1 : (list->node[hash].named_cert_size +
660 : 1) *
661 : sizeof(list->node[hash].named_certs[0]));
662 1 : if (list->node[hash].named_certs == NULL)
663 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
664 :
665 1 : list->node[hash].named_certs[list->node[hash].named_cert_size].
666 1 : cert = cert;
667 1 : memcpy(list->node[hash].
668 1 : named_certs[list->node[hash].named_cert_size].name, name,
669 : name_size);
670 1 : list->node[hash].named_certs[list->node[hash].
671 1 : named_cert_size].name_size =
672 : name_size;
673 :
674 1 : list->node[hash].named_cert_size++;
675 :
676 1 : return 0;
677 : }
678 :
679 : /**
680 : * gnutls_x509_trust_list_add_crls:
681 : * @list: The list
682 : * @crl_list: A list of CRLs
683 : * @crl_size: The length of the CRL list
684 : * @flags: flags from %gnutls_trust_list_flags_t
685 : * @verification_flags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL
686 : *
687 : * This function will add the given certificate revocation lists
688 : * to the trusted list. The CRLs in @crl_list must not be deinitialized
689 : * during the lifetime of @list.
690 : *
691 : * This function must be called after gnutls_x509_trust_list_add_cas()
692 : * to allow verifying the CRLs for validity. If the flag %GNUTLS_TL_NO_DUPLICATES
693 : * is given, then the final CRL list will not contain duplicate entries.
694 : *
695 : * If the flag %GNUTLS_TL_NO_DUPLICATES is given, gnutls_x509_trust_list_deinit() must be
696 : * called with parameter @all being 1.
697 : *
698 : * If flag %GNUTLS_TL_VERIFY_CRL is given the CRLs will be verified before being added,
699 : * and if verification fails, they will be skipped.
700 : *
701 : * Returns: The number of added elements is returned; that includes
702 : * duplicate entries.
703 : *
704 : * Since: 3.0
705 : **/
706 : int
707 84 : gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list,
708 : const gnutls_x509_crl_t * crl_list,
709 : unsigned crl_size, unsigned int flags,
710 : unsigned int verification_flags)
711 : {
712 84 : int ret;
713 84 : unsigned x, i, j = 0;
714 84 : unsigned int vret = 0;
715 84 : size_t hash;
716 84 : gnutls_x509_crl_t *tmp;
717 :
718 : /* Probably we can optimize things such as removing duplicates
719 : * etc.
720 : */
721 84 : if (crl_size == 0 || crl_list == NULL)
722 : return 0;
723 :
724 290 : for (i = 0; i < crl_size; i++) {
725 207 : hash =
726 207 : hash_pjw_bare(crl_list[i]->raw_issuer_dn.data,
727 207 : crl_list[i]->raw_issuer_dn.size);
728 207 : hash %= list->size;
729 :
730 207 : if (flags & GNUTLS_TL_VERIFY_CRL) {
731 :
732 5 : ret =
733 10 : gnutls_x509_crl_verify(crl_list[i],
734 5 : list->node[hash].
735 : trusted_cas,
736 5 : list->node[hash].
737 : trusted_ca_size,
738 : verification_flags,
739 : &vret);
740 5 : if (ret < 0 || vret != 0) {
741 4 : _gnutls_debug_log("CRL verification failed, not adding it\n");
742 4 : if (flags & GNUTLS_TL_NO_DUPLICATES)
743 1 : gnutls_x509_crl_deinit(crl_list[i]);
744 4 : if (flags & GNUTLS_TL_FAIL_ON_INVALID_CRL)
745 1 : return gnutls_assert_val(GNUTLS_E_CRL_VERIFICATION_ERROR);
746 3 : continue;
747 : }
748 : }
749 :
750 : /* If the CRL added overrides a previous one, then overwrite
751 : * the old one */
752 203 : if (flags & GNUTLS_TL_NO_DUPLICATES) {
753 2 : for (x=0;x<list->node[hash].crl_size;x++) {
754 0 : if (crl_list[i]->raw_issuer_dn.size == list->node[hash].crls[x]->raw_issuer_dn.size &&
755 0 : memcmp(crl_list[i]->raw_issuer_dn.data, list->node[hash].crls[x]->raw_issuer_dn.data, crl_list[i]->raw_issuer_dn.size) == 0) {
756 0 : if (gnutls_x509_crl_get_this_update(crl_list[i]) >=
757 0 : gnutls_x509_crl_get_this_update(list->node[hash].crls[x])) {
758 :
759 0 : gnutls_x509_crl_deinit(list->node[hash].crls[x]);
760 0 : list->node[hash].crls[x] = crl_list[i];
761 0 : goto next;
762 : } else {
763 : /* The new is older, discard it */
764 0 : gnutls_x509_crl_deinit(crl_list[i]);
765 0 : goto next;
766 : }
767 : }
768 : }
769 : }
770 :
771 203 : tmp =
772 406 : gnutls_realloc(list->node[hash].crls,
773 203 : (list->node[hash].crl_size +
774 : 1) *
775 : sizeof(list->node[hash].
776 : crls[0]));
777 203 : if (tmp == NULL) {
778 0 : ret = i;
779 0 : gnutls_assert();
780 0 : if (flags & GNUTLS_TL_NO_DUPLICATES)
781 0 : while (i < crl_size)
782 0 : gnutls_x509_crl_deinit(crl_list[i++]);
783 0 : return ret;
784 : }
785 203 : list->node[hash].crls = tmp;
786 :
787 :
788 203 : list->node[hash].crls[list->node[hash].crl_size] =
789 203 : crl_list[i];
790 203 : list->node[hash].crl_size++;
791 :
792 203 : next:
793 203 : j++;
794 : }
795 :
796 83 : return j;
797 : }
798 :
799 : /* Takes a certificate list and shortens it if there are
800 : * intermedia certificates already trusted by us.
801 : *
802 : * Returns the new size of the list or a negative number on error.
803 : */
804 795 : static int shorten_clist(gnutls_x509_trust_list_t list,
805 : gnutls_x509_crt_t * certificate_list,
806 : unsigned int clist_size)
807 : {
808 795 : unsigned int j, i;
809 795 : size_t hash;
810 :
811 795 : if (clist_size > 1) {
812 : /* Check if the last certificate in the path is self signed.
813 : * In that case ignore it (a certificate is trusted only if it
814 : * leads to a trusted party by us, not the server's).
815 : *
816 : * This prevents from verifying self signed certificates against
817 : * themselves. This (although not bad) caused verification
818 : * failures on some root self signed certificates that use the
819 : * MD2 algorithm.
820 : */
821 501 : if (gnutls_x509_crt_check_issuer
822 : (certificate_list[clist_size - 1],
823 501 : certificate_list[clist_size - 1]) != 0) {
824 281 : clist_size--;
825 : }
826 : }
827 :
828 : /* We want to shorten the chain by removing the cert that matches
829 : * one of the certs we trust and all the certs after that i.e. if
830 : * cert chain is A signed-by B signed-by C signed-by D (signed-by
831 : * self-signed E but already removed above), and we trust B, remove
832 : * B, C and D. */
833 1250 : for (i = 1; i < clist_size; i++) {
834 455 : hash =
835 455 : hash_pjw_bare(certificate_list[i]->raw_issuer_dn.data,
836 455 : certificate_list[i]->raw_issuer_dn.size);
837 455 : hash %= list->size;
838 :
839 752 : for (j = 0; j < list->node[hash].trusted_ca_size; j++) {
840 298 : if (gnutls_x509_crt_equals
841 : (certificate_list[i],
842 298 : list->node[hash].trusted_cas[j]) != 0) {
843 : /* cut the list at the point of first the trusted certificate */
844 1 : clist_size = i + 1;
845 1 : break;
846 : }
847 : }
848 : /* clist_size may have been changed which gets out of loop */
849 : }
850 :
851 795 : return clist_size;
852 : }
853 :
854 13 : int _gnutls_trust_list_get_issuer(gnutls_x509_trust_list_t list,
855 : gnutls_x509_crt_t cert,
856 : gnutls_x509_crt_t * issuer,
857 : unsigned int flags)
858 : {
859 13 : int ret;
860 13 : unsigned int i;
861 13 : size_t hash;
862 :
863 13 : hash =
864 13 : hash_pjw_bare(cert->raw_issuer_dn.data,
865 13 : cert->raw_issuer_dn.size);
866 13 : hash %= list->size;
867 :
868 13 : for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
869 18 : ret =
870 9 : gnutls_x509_crt_check_issuer(cert,
871 9 : list->node[hash].
872 9 : trusted_cas[i]);
873 9 : if (ret != 0) {
874 9 : if (flags & GNUTLS_TL_GET_COPY) {
875 3 : *issuer = crt_cpy(list->node[hash].trusted_cas[i]);
876 : } else {
877 6 : *issuer = list->node[hash].trusted_cas[i];
878 : }
879 9 : return 0;
880 : }
881 : }
882 :
883 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
884 : }
885 :
886 : static
887 42 : int trust_list_get_issuer_by_dn(gnutls_x509_trust_list_t list,
888 : const gnutls_datum_t *dn,
889 : const gnutls_datum_t *spki,
890 : gnutls_x509_crt_t * issuer,
891 : unsigned int flags)
892 : {
893 42 : int ret;
894 42 : unsigned int i, j;
895 42 : size_t hash;
896 42 : uint8_t tmp[256];
897 42 : size_t tmp_size;
898 :
899 42 : if (dn) {
900 38 : hash =
901 38 : hash_pjw_bare(dn->data,
902 38 : dn->size);
903 38 : hash %= list->size;
904 :
905 38 : for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
906 29 : ret = _gnutls_x509_compare_raw_dn(dn, &list->node[hash].trusted_cas[i]->raw_dn);
907 29 : if (ret != 0) {
908 29 : if (spki && spki->size > 0) {
909 0 : tmp_size = sizeof(tmp);
910 :
911 0 : ret = gnutls_x509_crt_get_subject_key_id(list->node[hash].trusted_cas[i], tmp, &tmp_size, NULL);
912 0 : if (ret < 0)
913 0 : continue;
914 0 : if (spki->size != tmp_size || memcmp(spki->data, tmp, spki->size) != 0)
915 0 : continue;
916 : }
917 29 : *issuer = crt_cpy(list->node[hash].trusted_cas[i]);
918 29 : return 0;
919 : }
920 : }
921 4 : } else if (spki) {
922 : /* search everything! */
923 512 : for (i = 0; i < list->size; i++) {
924 512 : for (j = 0; j < list->node[i].trusted_ca_size; j++) {
925 4 : tmp_size = sizeof(tmp);
926 :
927 4 : ret = gnutls_x509_crt_get_subject_key_id(list->node[i].trusted_cas[j], tmp, &tmp_size, NULL);
928 4 : if (ret < 0)
929 0 : continue;
930 :
931 4 : if (spki->size != tmp_size || memcmp(spki->data, tmp, spki->size) != 0)
932 4 : continue;
933 :
934 0 : *issuer = crt_cpy(list->node[i].trusted_cas[j]);
935 0 : return 0;
936 : }
937 : }
938 : }
939 :
940 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
941 : }
942 :
943 : /**
944 : * gnutls_x509_trust_list_get_issuer:
945 : * @list: The list
946 : * @cert: is the certificate to find issuer for
947 : * @issuer: Will hold the issuer if any. Should be treated as constant.
948 : * @flags: flags from %gnutls_trust_list_flags_t (%GNUTLS_TL_GET_COPY is applicable)
949 : *
950 : * This function will find the issuer of the given certificate.
951 : * If the flag %GNUTLS_TL_GET_COPY is specified a copy of the issuer
952 : * will be returned which must be freed using gnutls_x509_crt_deinit().
953 : * In that case the provided @issuer must not be initialized.
954 : *
955 : * Note that the flag %GNUTLS_TL_GET_COPY is required for this function
956 : * to work with PKCS#11 trust lists in a thread-safe way.
957 : *
958 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
959 : * negative error value.
960 : *
961 : * Since: 3.0
962 : **/
963 11 : int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t list,
964 : gnutls_x509_crt_t cert,
965 : gnutls_x509_crt_t * issuer,
966 : unsigned int flags)
967 : {
968 11 : int ret;
969 :
970 11 : ret = _gnutls_trust_list_get_issuer(list, cert, issuer, flags);
971 11 : if (ret == 0) {
972 : return 0;
973 : }
974 :
975 : #ifdef ENABLE_PKCS11
976 4 : if (ret < 0 && list->pkcs11_token) {
977 4 : gnutls_x509_crt_t crt;
978 4 : gnutls_datum_t der = {NULL, 0};
979 : /* use the token for verification */
980 4 : ret = gnutls_pkcs11_get_raw_issuer(list->pkcs11_token, cert, &der,
981 : GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE);
982 4 : if (ret < 0) {
983 0 : gnutls_assert();
984 0 : return ret;
985 : }
986 :
987 4 : ret = gnutls_x509_crt_init(&crt);
988 4 : if (ret < 0) {
989 0 : gnutls_free(der.data);
990 0 : return gnutls_assert_val(ret);
991 : }
992 :
993 4 : ret = gnutls_x509_crt_import(crt, &der, GNUTLS_X509_FMT_DER);
994 4 : gnutls_free(der.data);
995 4 : if (ret < 0) {
996 0 : gnutls_x509_crt_deinit(crt);
997 0 : return gnutls_assert_val(ret);
998 : }
999 :
1000 4 : if (flags & GNUTLS_TL_GET_COPY) {
1001 2 : *issuer = crt;
1002 2 : return 0;
1003 : } else {
1004 : /* we add this CA to the keep_cert list in order to make it
1005 : * persistent. It will be deallocated when the trust list is.
1006 : */
1007 2 : ret = trust_list_add_compat(list, crt);
1008 2 : if (ret < 0) {
1009 0 : gnutls_x509_crt_deinit(crt);
1010 0 : return gnutls_assert_val(ret);
1011 : }
1012 2 : *issuer = crt;
1013 2 : return ret;
1014 : }
1015 : }
1016 : #endif
1017 : return ret;
1018 : }
1019 :
1020 : /**
1021 : * gnutls_x509_trust_list_get_issuer_by_dn:
1022 : * @list: The list
1023 : * @dn: is the issuer's DN
1024 : * @issuer: Will hold the issuer if any. Should be deallocated after use.
1025 : * @flags: Use zero
1026 : *
1027 : * This function will find the issuer with the given name, and
1028 : * return a copy of the issuer, which must be freed using gnutls_x509_crt_deinit().
1029 : *
1030 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1031 : * negative error value.
1032 : *
1033 : * Since: 3.4.0
1034 : **/
1035 38 : int gnutls_x509_trust_list_get_issuer_by_dn(gnutls_x509_trust_list_t list,
1036 : const gnutls_datum_t *dn,
1037 : gnutls_x509_crt_t *issuer,
1038 : unsigned int flags)
1039 : {
1040 38 : int ret;
1041 :
1042 38 : ret = trust_list_get_issuer_by_dn(list, dn, NULL, issuer, flags);
1043 38 : if (ret == 0) {
1044 : return 0;
1045 : }
1046 :
1047 : #ifdef ENABLE_PKCS11
1048 9 : if (ret < 0 && list->pkcs11_token) {
1049 1 : gnutls_x509_crt_t crt;
1050 1 : gnutls_datum_t der = {NULL, 0};
1051 : /* use the token for verification */
1052 1 : ret = gnutls_pkcs11_get_raw_issuer_by_dn(list->pkcs11_token, dn, &der,
1053 : GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE);
1054 1 : if (ret < 0) {
1055 0 : gnutls_assert();
1056 0 : return ret;
1057 : }
1058 :
1059 1 : ret = gnutls_x509_crt_init(&crt);
1060 1 : if (ret < 0) {
1061 0 : gnutls_free(der.data);
1062 0 : return gnutls_assert_val(ret);
1063 : }
1064 :
1065 1 : ret = gnutls_x509_crt_import(crt, &der, GNUTLS_X509_FMT_DER);
1066 1 : gnutls_free(der.data);
1067 1 : if (ret < 0) {
1068 0 : gnutls_x509_crt_deinit(crt);
1069 0 : return gnutls_assert_val(ret);
1070 : }
1071 :
1072 1 : *issuer = crt;
1073 1 : return 0;
1074 : }
1075 : #endif
1076 : return ret;
1077 : }
1078 :
1079 : /**
1080 : * gnutls_x509_trust_list_get_issuer_by_subject_key_id:
1081 : * @list: The list
1082 : * @dn: is the issuer's DN (may be %NULL)
1083 : * @spki: is the subject key ID
1084 : * @issuer: Will hold the issuer if any. Should be deallocated after use.
1085 : * @flags: Use zero
1086 : *
1087 : * This function will find the issuer with the given name and subject key ID, and
1088 : * return a copy of the issuer, which must be freed using gnutls_x509_crt_deinit().
1089 : *
1090 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1091 : * negative error value.
1092 : *
1093 : * Since: 3.4.2
1094 : **/
1095 4 : int gnutls_x509_trust_list_get_issuer_by_subject_key_id(gnutls_x509_trust_list_t list,
1096 : const gnutls_datum_t *dn,
1097 : const gnutls_datum_t *spki,
1098 : gnutls_x509_crt_t *issuer,
1099 : unsigned int flags)
1100 : {
1101 4 : int ret;
1102 :
1103 4 : ret = trust_list_get_issuer_by_dn(list, dn, spki, issuer, flags);
1104 4 : if (ret == 0) {
1105 : return 0;
1106 : }
1107 :
1108 : #ifdef ENABLE_PKCS11
1109 4 : if (ret < 0 && list->pkcs11_token) {
1110 0 : gnutls_x509_crt_t crt;
1111 0 : gnutls_datum_t der = {NULL, 0};
1112 : /* use the token for verification */
1113 0 : ret = gnutls_pkcs11_get_raw_issuer_by_subject_key_id(list->pkcs11_token, dn, spki, &der,
1114 : GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE);
1115 0 : if (ret < 0) {
1116 0 : gnutls_assert();
1117 0 : return ret;
1118 : }
1119 :
1120 0 : ret = gnutls_x509_crt_init(&crt);
1121 0 : if (ret < 0) {
1122 0 : gnutls_free(der.data);
1123 0 : return gnutls_assert_val(ret);
1124 : }
1125 :
1126 0 : ret = gnutls_x509_crt_import(crt, &der, GNUTLS_X509_FMT_DER);
1127 0 : gnutls_free(der.data);
1128 0 : if (ret < 0) {
1129 0 : gnutls_x509_crt_deinit(crt);
1130 0 : return gnutls_assert_val(ret);
1131 : }
1132 :
1133 0 : *issuer = crt;
1134 0 : return 0;
1135 : }
1136 : #endif
1137 : return ret;
1138 : }
1139 :
1140 : static
1141 1196 : int check_if_in_blacklist(gnutls_x509_crt_t * cert_list, unsigned int cert_list_size,
1142 : gnutls_x509_crt_t * blacklist, unsigned int blacklist_size)
1143 : {
1144 1196 : unsigned i, j;
1145 :
1146 1196 : if (blacklist_size == 0)
1147 : return 0;
1148 :
1149 1 : for (i=0;i<cert_list_size;i++) {
1150 1 : for (j=0;j<blacklist_size;j++) {
1151 1 : if (gnutls_x509_crt_equals(cert_list[i], blacklist[j]) != 0) {
1152 : return 1;
1153 : }
1154 : }
1155 : }
1156 :
1157 : return 0;
1158 : }
1159 :
1160 : /**
1161 : * gnutls_x509_trust_list_verify_crt:
1162 : * @list: The list
1163 : * @cert_list: is the certificate list to be verified
1164 : * @cert_list_size: is the certificate list size
1165 : * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
1166 : * @voutput: will hold the certificate verification output.
1167 : * @func: If non-null will be called on each chain element verification with the output.
1168 : *
1169 : * This function will try to verify the given certificate and return
1170 : * its status. The @voutput parameter will hold an OR'ed sequence of
1171 : * %gnutls_certificate_status_t flags.
1172 : *
1173 : * The details of the verification are the same as in gnutls_x509_trust_list_verify_crt2().
1174 : *
1175 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1176 : * negative error value.
1177 : *
1178 : * Since: 3.0
1179 : **/
1180 : int
1181 206 : gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
1182 : gnutls_x509_crt_t * cert_list,
1183 : unsigned int cert_list_size,
1184 : unsigned int flags,
1185 : unsigned int *voutput,
1186 : gnutls_verify_output_function func)
1187 : {
1188 206 : return gnutls_x509_trust_list_verify_crt2(list, cert_list, cert_list_size,
1189 : NULL, 0, flags, voutput, func);
1190 : }
1191 :
1192 : #define LAST_DN cert_list[cert_list_size-1]->raw_dn
1193 : #define LAST_IDN cert_list[cert_list_size-1]->raw_issuer_dn
1194 : /* This macro is introduced to detect a verification output which
1195 : * indicates an unknown signer, a signer which uses an insecure
1196 : * algorithm (e.g., sha1), a signer has expired, or something that
1197 : * indicates a superseded signer */
1198 : #define SIGNER_OLD_OR_UNKNOWN(output) ((output & GNUTLS_CERT_SIGNER_NOT_FOUND) || \
1199 : (output & GNUTLS_CERT_EXPIRED) || \
1200 : (output & GNUTLS_CERT_INSECURE_ALGORITHM))
1201 : #define SIGNER_WAS_KNOWN(output) (!(output & GNUTLS_CERT_SIGNER_NOT_FOUND))
1202 :
1203 : /**
1204 : * gnutls_x509_trust_list_verify_crt2:
1205 : * @list: The list
1206 : * @cert_list: is the certificate list to be verified
1207 : * @cert_list_size: is the certificate list size
1208 : * @data: an array of typed data
1209 : * @elements: the number of data elements
1210 : * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
1211 : * @voutput: will hold the certificate verification output.
1212 : * @func: If non-null will be called on each chain element verification with the output.
1213 : *
1214 : * This function will attempt to verify the given certificate chain and return
1215 : * its status. The @voutput parameter will hold an OR'ed sequence of
1216 : * %gnutls_certificate_status_t flags.
1217 : *
1218 : * When a certificate chain of @cert_list_size with more than one certificates is
1219 : * provided, the verification status will apply to the first certificate in the chain
1220 : * that failed verification. The verification process starts from the end of the chain
1221 : * (from CA to end certificate). The first certificate in the chain must be the end-certificate
1222 : * while the rest of the members may be sorted or not.
1223 : *
1224 : * Additionally a certificate verification profile can be specified
1225 : * from the ones in %gnutls_certificate_verification_profiles_t by
1226 : * ORing the result of GNUTLS_PROFILE_TO_VFLAGS() to the verification
1227 : * flags.
1228 : *
1229 : * Additional verification parameters are possible via the @data types; the
1230 : * acceptable types are %GNUTLS_DT_DNS_HOSTNAME, %GNUTLS_DT_IP_ADDRESS and %GNUTLS_DT_KEY_PURPOSE_OID.
1231 : * The former accepts as data a null-terminated hostname, and the latter a null-terminated
1232 : * object identifier (e.g., %GNUTLS_KP_TLS_WWW_SERVER).
1233 : * If a DNS hostname is provided then this function will compare
1234 : * the hostname in the end certificate against the given. If names do not match the
1235 : * %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set. In addition it
1236 : * will consider certificates provided with gnutls_x509_trust_list_add_named_crt().
1237 : *
1238 : * If a key purpose OID is provided and the end-certificate contains the extended key
1239 : * usage PKIX extension, it will be required to match the provided OID
1240 : * or be marked for any purpose, otherwise verification will fail with
1241 : * %GNUTLS_CERT_PURPOSE_MISMATCH status.
1242 : *
1243 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1244 : * negative error value. Note that verification failure will not result to an
1245 : * error code, only @voutput will be updated.
1246 : *
1247 : * Since: 3.3.8
1248 : **/
1249 : int
1250 796 : gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
1251 : gnutls_x509_crt_t * cert_list,
1252 : unsigned int cert_list_size,
1253 : gnutls_typed_vdata_st *data,
1254 : unsigned int elements,
1255 : unsigned int flags,
1256 : unsigned int *voutput,
1257 : gnutls_verify_output_function func)
1258 : {
1259 796 : int ret;
1260 796 : unsigned int i;
1261 796 : size_t hash;
1262 796 : gnutls_x509_crt_t sorted[DEFAULT_MAX_VERIFY_DEPTH];
1263 796 : const char *hostname = NULL, *purpose = NULL, *email = NULL;
1264 796 : unsigned hostname_size = 0;
1265 796 : unsigned have_set_name = 0;
1266 796 : unsigned saved_output;
1267 796 : gnutls_datum_t ip = {NULL, 0};
1268 :
1269 796 : if (cert_list == NULL || cert_list_size < 1)
1270 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1271 :
1272 1586 : for (i=0;i<elements;i++) {
1273 790 : if (data[i].type == GNUTLS_DT_DNS_HOSTNAME) {
1274 398 : hostname = (void*)data[i].data;
1275 398 : if (data[i].size > 0) {
1276 4 : hostname_size = data[i].size;
1277 : }
1278 :
1279 398 : if (have_set_name != 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1280 : have_set_name = 1;
1281 392 : } else if (data[i].type == GNUTLS_DT_IP_ADDRESS) {
1282 3 : if (data[i].size > 0) {
1283 3 : ip.data = data[i].data;
1284 3 : ip.size = data[i].size;
1285 : }
1286 :
1287 3 : if (have_set_name != 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1288 : have_set_name = 1;
1289 389 : } else if (data[i].type == GNUTLS_DT_RFC822NAME) {
1290 8 : email = (void*)data[i].data;
1291 :
1292 8 : if (have_set_name != 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1293 : have_set_name = 1;
1294 381 : } else if (data[i].type == GNUTLS_DT_KEY_PURPOSE_OID) {
1295 381 : purpose = (void*)data[i].data;
1296 : }
1297 : }
1298 :
1299 796 : if (hostname) { /* shortcut using the named certs - if any */
1300 398 : unsigned vtmp = 0;
1301 398 : if (hostname_size == 0)
1302 394 : hostname_size = strlen(hostname);
1303 :
1304 398 : ret = gnutls_x509_trust_list_verify_named_crt(list,
1305 : cert_list[0], hostname, hostname_size,
1306 : flags, &vtmp, func);
1307 398 : if (ret == 0 && vtmp == 0) {
1308 1 : *voutput = vtmp;
1309 1 : return 0;
1310 : }
1311 : }
1312 :
1313 795 : if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN))
1314 794 : cert_list = _gnutls_sort_clist(sorted, cert_list, &cert_list_size, NULL);
1315 :
1316 795 : cert_list_size = shorten_clist(list, cert_list, cert_list_size);
1317 795 : if (cert_list_size <= 0)
1318 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
1319 :
1320 795 : hash =
1321 795 : hash_pjw_bare(cert_list[cert_list_size - 1]->raw_issuer_dn.
1322 : data,
1323 795 : cert_list[cert_list_size -
1324 795 : 1]->raw_issuer_dn.size);
1325 795 : hash %= list->size;
1326 :
1327 795 : ret = check_if_in_blacklist(cert_list, cert_list_size,
1328 : list->blacklisted, list->blacklisted_size);
1329 795 : if (ret != 0) {
1330 1 : *voutput = 0;
1331 1 : *voutput |= GNUTLS_CERT_REVOKED;
1332 1 : *voutput |= GNUTLS_CERT_INVALID;
1333 1 : return 0;
1334 : }
1335 :
1336 1588 : *voutput =
1337 794 : _gnutls_verify_crt_status(list, cert_list, cert_list_size,
1338 794 : list->node[hash].trusted_cas,
1339 794 : list->node[hash].trusted_ca_size,
1340 : flags, purpose, func);
1341 794 : saved_output = *voutput;
1342 :
1343 794 : if (SIGNER_OLD_OR_UNKNOWN(*voutput) &&
1344 302 : (LAST_DN.size != LAST_IDN.size ||
1345 84 : memcmp(LAST_DN.data, LAST_IDN.data, LAST_IDN.size) != 0)) {
1346 :
1347 : /* if we couldn't find the issuer, try to see if the last
1348 : * certificate is in the trusted list and try to verify against
1349 : * (if it is not self signed) */
1350 261 : hash =
1351 261 : hash_pjw_bare(cert_list[cert_list_size - 1]->raw_dn.
1352 : data, cert_list[cert_list_size - 1]->raw_dn.size);
1353 261 : hash %= list->size;
1354 :
1355 261 : _gnutls_debug_log("issuer in verification was not found or insecure; trying against trust list\n");
1356 :
1357 522 : *voutput =
1358 261 : _gnutls_verify_crt_status(list, cert_list, cert_list_size,
1359 261 : list->node[hash].trusted_cas,
1360 261 : list->node[hash].trusted_ca_size,
1361 : flags, purpose, func);
1362 261 : if (*voutput != 0) {
1363 255 : if (SIGNER_WAS_KNOWN(saved_output))
1364 33 : *voutput = saved_output;
1365 255 : gnutls_assert();
1366 : }
1367 : }
1368 :
1369 794 : saved_output = *voutput;
1370 :
1371 : #ifdef ENABLE_PKCS11
1372 794 : if (SIGNER_OLD_OR_UNKNOWN(*voutput) && list->pkcs11_token) {
1373 : /* use the token for verification */
1374 :
1375 86 : *voutput = _gnutls_pkcs11_verify_crt_status(list, list->pkcs11_token,
1376 : cert_list, cert_list_size,
1377 : purpose,
1378 : flags, func);
1379 86 : if (*voutput != 0) {
1380 49 : if (SIGNER_WAS_KNOWN(saved_output))
1381 0 : *voutput = saved_output;
1382 49 : gnutls_assert();
1383 : }
1384 : }
1385 : #endif
1386 :
1387 : /* End-certificate, key purpose and hostname checks. */
1388 794 : if (purpose) {
1389 381 : ret = _gnutls_check_key_purpose(cert_list[0], purpose, 0);
1390 381 : if (ret != 1) {
1391 11 : gnutls_assert();
1392 11 : *voutput |= GNUTLS_CERT_PURPOSE_MISMATCH|GNUTLS_CERT_INVALID;
1393 : }
1394 : }
1395 :
1396 794 : if (hostname) {
1397 794 : ret =
1398 397 : gnutls_x509_crt_check_hostname2(cert_list[0], hostname, flags);
1399 397 : if (ret == 0) {
1400 173 : gnutls_assert();
1401 173 : *voutput |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
1402 : }
1403 : }
1404 :
1405 794 : if (ip.data) {
1406 6 : ret =
1407 3 : gnutls_x509_crt_check_ip(cert_list[0], ip.data, ip.size, flags);
1408 3 : if (ret == 0) {
1409 1 : gnutls_assert();
1410 1 : *voutput |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
1411 : }
1412 : }
1413 :
1414 794 : if (email) {
1415 16 : ret =
1416 8 : gnutls_x509_crt_check_email(cert_list[0], email, 0);
1417 8 : if (ret == 0) {
1418 4 : gnutls_assert();
1419 4 : *voutput |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
1420 : }
1421 : }
1422 :
1423 : /* CRL checks follow */
1424 :
1425 794 : if (*voutput != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS))
1426 : return 0;
1427 :
1428 : /* Check revocation of individual certificates.
1429 : * start with the last one that we already have its hash
1430 : */
1431 396 : ret =
1432 792 : _gnutls_x509_crt_check_revocation(cert_list
1433 396 : [cert_list_size - 1],
1434 396 : list->node[hash].crls,
1435 396 : list->node[hash].crl_size,
1436 : func);
1437 396 : if (ret == 1) { /* revoked */
1438 2 : *voutput |= GNUTLS_CERT_REVOKED;
1439 2 : *voutput |= GNUTLS_CERT_INVALID;
1440 2 : return 0;
1441 : }
1442 :
1443 650 : for (i = 0; i < cert_list_size - 1; i++) {
1444 261 : hash =
1445 261 : hash_pjw_bare(cert_list[i]->raw_issuer_dn.data,
1446 261 : cert_list[i]->raw_issuer_dn.size);
1447 261 : hash %= list->size;
1448 :
1449 522 : ret = _gnutls_x509_crt_check_revocation(cert_list[i],
1450 261 : list->node[hash].
1451 : crls,
1452 261 : list->node[hash].
1453 : crl_size, func);
1454 261 : if (ret < 0) {
1455 0 : gnutls_assert();
1456 261 : } else if (ret == 1) { /* revoked */
1457 5 : *voutput |= GNUTLS_CERT_REVOKED;
1458 5 : *voutput |= GNUTLS_CERT_INVALID;
1459 5 : return 0;
1460 : }
1461 : }
1462 :
1463 : return 0;
1464 : }
1465 :
1466 : /**
1467 : * gnutls_x509_trust_list_verify_named_crt:
1468 : * @list: The list
1469 : * @cert: is the certificate to be verified
1470 : * @name: is the certificate's name
1471 : * @name_size: is the certificate's name size
1472 : * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
1473 : * @voutput: will hold the certificate verification output.
1474 : * @func: If non-null will be called on each chain element verification with the output.
1475 : *
1476 : * This function will try to find a certificate that is associated with the provided
1477 : * name --see gnutls_x509_trust_list_add_named_crt(). If a match is found the
1478 : * certificate is considered valid. In addition to that this function will also
1479 : * check CRLs. The @voutput parameter will hold an OR'ed sequence of
1480 : * %gnutls_certificate_status_t flags.
1481 : *
1482 : * Additionally a certificate verification profile can be specified
1483 : * from the ones in %gnutls_certificate_verification_profiles_t by
1484 : * ORing the result of GNUTLS_PROFILE_TO_VFLAGS() to the verification
1485 : * flags.
1486 : *
1487 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1488 : * negative error value.
1489 : *
1490 : * Since: 3.0.0
1491 : **/
1492 : int
1493 401 : gnutls_x509_trust_list_verify_named_crt(gnutls_x509_trust_list_t list,
1494 : gnutls_x509_crt_t cert,
1495 : const void *name,
1496 : size_t name_size,
1497 : unsigned int flags,
1498 : unsigned int *voutput,
1499 : gnutls_verify_output_function func)
1500 : {
1501 401 : int ret;
1502 401 : unsigned int i;
1503 401 : size_t hash;
1504 :
1505 :
1506 401 : hash =
1507 401 : hash_pjw_bare(cert->raw_issuer_dn.data,
1508 401 : cert->raw_issuer_dn.size);
1509 401 : hash %= list->size;
1510 :
1511 401 : ret = check_if_in_blacklist(&cert, 1,
1512 : list->blacklisted, list->blacklisted_size);
1513 401 : if (ret != 0) {
1514 0 : *voutput = 0;
1515 0 : *voutput |= GNUTLS_CERT_REVOKED;
1516 0 : *voutput |= GNUTLS_CERT_INVALID;
1517 0 : return 0;
1518 : }
1519 :
1520 401 : *voutput = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND;
1521 :
1522 404 : for (i = 0; i < list->node[hash].named_cert_size; i++) {
1523 5 : if (gnutls_x509_crt_equals(cert, list->node[hash].named_certs[i].cert) != 0) { /* check if name matches */
1524 5 : if (list->node[hash].named_certs[i].name_size ==
1525 : name_size
1526 2 : && memcmp(list->node[hash].named_certs[i].name,
1527 : name, name_size) == 0) {
1528 2 : *voutput = 0;
1529 2 : break;
1530 : }
1531 : }
1532 : }
1533 :
1534 401 : if (*voutput != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS))
1535 : return 0;
1536 :
1537 : /* Check revocation of individual certificates.
1538 : * start with the last one that we already have its hash
1539 : */
1540 4 : ret = _gnutls_x509_crt_check_revocation(cert,
1541 2 : list->node[hash].crls,
1542 2 : list->node[hash].crl_size,
1543 : func);
1544 2 : if (ret == 1) { /* revoked */
1545 0 : *voutput |= GNUTLS_CERT_REVOKED;
1546 0 : *voutput |= GNUTLS_CERT_INVALID;
1547 0 : return 0;
1548 : }
1549 :
1550 : return 0;
1551 : }
1552 :
1553 : /* return 1 if @cert is in @list, 0 if not */
1554 : int
1555 22 : _gnutls_trustlist_inlist(gnutls_x509_trust_list_t list,
1556 : gnutls_x509_crt_t cert)
1557 : {
1558 22 : int ret;
1559 22 : unsigned int i;
1560 22 : size_t hash;
1561 :
1562 22 : hash = hash_pjw_bare(cert->raw_dn.data, cert->raw_dn.size);
1563 22 : hash %= list->size;
1564 :
1565 22 : for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
1566 4 : ret =
1567 2 : gnutls_x509_crt_equals(cert,
1568 2 : list->node[hash].
1569 2 : trusted_cas[i]);
1570 2 : if (ret != 0)
1571 : return 1;
1572 : }
1573 :
1574 : return 0;
1575 : }
|