summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509/x509_verify.c
diff options
context:
space:
mode:
authorbeck <>2020-09-13 15:06:17 +0000
committerbeck <>2020-09-13 15:06:17 +0000
commita328631fddec2556ad8af08ce4de240790c537c9 (patch)
tree4e2deda0db62092481ad6901c374736e60f249a2 /src/lib/libcrypto/x509/x509_verify.c
parent4f04d3f588f91c98b4b1cdfcffe028a036c96283 (diff)
downloadopenbsd-a328631fddec2556ad8af08ce4de240790c537c9.tar.gz
openbsd-a328631fddec2556ad8af08ce4de240790c537c9.tar.bz2
openbsd-a328631fddec2556ad8af08ce4de240790c537c9.zip
Add new x509 certificate chain validator in x509_verify.c
The new validator finds multiple validated chains to handle the modern PKI cases which may frequently have multiple paths via different intermediates to different roots. It is loosely based on golang's x509 validator This includes integration so that the new validator can be used via X509_verify_cert() as well as a new api x509_verify() which will return multiple chains (similar to go). The new validator is not enabled by default with this commit, this will be changed in a follow on commit. The new public API is not yet exposed, and will be finalized and exposed with a man page and a library minor bump later. ok tb@ inoguchi@ jsing@
Diffstat (limited to 'src/lib/libcrypto/x509/x509_verify.c')
-rw-r--r--src/lib/libcrypto/x509/x509_verify.c914
1 files changed, 914 insertions, 0 deletions
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c
new file mode 100644
index 0000000000..5f5070c122
--- /dev/null
+++ b/src/lib/libcrypto/x509/x509_verify.c
@@ -0,0 +1,914 @@
1/* $OpenBSD: x509_verify.c,v 1.1 2020/09/13 15:06:17 beck Exp $ */
2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* x509_verify - inspired by golang's crypto/x509/Verify */
19
20#include <errno.h>
21#include <stdio.h>
22#include <string.h>
23#include <time.h>
24#include <unistd.h>
25
26#include <openssl/safestack.h>
27#include <openssl/x509.h>
28#include <openssl/x509v3.h>
29
30#include "x509_internal.h"
31#include "x509_issuer_cache.h"
32
33static int x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert,
34 struct x509_verify_chain *current_chain);
35static void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
36 struct x509_verify_chain *current_chain);
37static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert,
38 size_t depth, int error, int ok);
39static void x509_verify_chain_free(struct x509_verify_chain *chain);
40
41#define X509_VERIFY_CERT_HASH (EVP_sha512())
42
43struct x509_verify_chain *
44x509_verify_chain_new(void)
45{
46 struct x509_verify_chain *chain;
47
48 if ((chain = calloc(1, sizeof(*chain))) == NULL)
49 goto err;
50 if ((chain->certs = sk_X509_new_null()) == NULL)
51 goto err;
52 if ((chain->names = x509_constraints_names_new()) == NULL)
53 goto err;
54
55 return chain;
56 err:
57 x509_verify_chain_free(chain);
58 return NULL;
59}
60
61static void
62x509_verify_chain_clear(struct x509_verify_chain *chain)
63{
64 sk_X509_pop_free(chain->certs, X509_free);
65 chain->certs = NULL;
66 x509_constraints_names_free(chain->names);
67 chain->names = NULL;
68}
69
70static void
71x509_verify_chain_free(struct x509_verify_chain *chain)
72{
73 if (chain == NULL)
74 return;
75 x509_verify_chain_clear(chain);
76 free(chain);
77}
78
79static struct x509_verify_chain *
80x509_verify_chain_dup(struct x509_verify_chain *chain)
81{
82 struct x509_verify_chain *new_chain;
83
84 if ((new_chain = x509_verify_chain_new()) == NULL)
85 goto err;
86 if ((new_chain->certs = X509_chain_up_ref(chain->certs)) == NULL)
87 goto err;
88 if ((new_chain->names =
89 x509_constraints_names_dup(chain->names)) == NULL)
90 goto err;
91 return(new_chain);
92 err:
93 x509_verify_chain_free(new_chain);
94 return NULL;
95}
96
97static int
98x509_verify_chain_append(struct x509_verify_chain *chain, X509 *cert,
99 int *error)
100{
101 int verify_err = X509_V_ERR_UNSPECIFIED;
102
103 if (!x509_constraints_extract_names(chain->names, cert,
104 sk_X509_num(chain->certs) == 0, &verify_err)) {
105 *error = verify_err;
106 return 0;
107 }
108 X509_up_ref(cert);
109 if (!sk_X509_push(chain->certs, cert)) {
110 X509_free(cert);
111 *error = X509_V_ERR_UNSPECIFIED;
112 return 0;
113 }
114 return 1;
115}
116
117static X509 *
118x509_verify_chain_last(struct x509_verify_chain *chain)
119{
120 int last;
121
122 if (chain->certs == NULL)
123 return NULL;
124 if ((last = sk_X509_num(chain->certs) - 1) < 0)
125 return NULL;
126 return sk_X509_value(chain->certs, last);
127}
128
129X509 *
130x509_verify_chain_leaf(struct x509_verify_chain *chain)
131{
132 if (chain->certs == NULL)
133 return NULL;
134 return sk_X509_value(chain->certs, 0);
135}
136
137static void
138x509_verify_ctx_reset(struct x509_verify_ctx *ctx)
139{
140 size_t i;
141
142 for (i = 0; i < ctx->chains_count; i++)
143 x509_verify_chain_free(ctx->chains[i]);
144 ctx->error = 0;
145 ctx->error_depth = 0;
146 ctx->chains_count = 0;
147 ctx->sig_checks = 0;
148 ctx->check_time = NULL;
149}
150
151static void
152x509_verify_ctx_clear(struct x509_verify_ctx *ctx)
153{
154 x509_verify_ctx_reset(ctx);
155 sk_X509_pop_free(ctx->intermediates, X509_free);
156 sk_X509_pop_free(ctx->roots, X509_free);
157 free(ctx->chains);
158 memset(ctx, 0, sizeof(*ctx));
159}
160
161static int
162x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert)
163{
164 int i;
165
166 for (i = 0; i < sk_X509_num(ctx->roots); i++) {
167 if (X509_cmp(sk_X509_value(ctx->roots, i), cert) == 0)
168 return 1;
169 }
170 return 0;
171}
172
173/* Add a validated chain to our list of valid chains */
174static int
175x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx,
176 struct x509_verify_chain *chain)
177{
178 size_t depth;
179 X509 *last = x509_verify_chain_last(chain);
180
181 depth = sk_X509_num(chain->certs);
182 if (depth > 0)
183 depth--;
184
185 if (ctx->chains_count >= ctx->max_chains)
186 return x509_verify_cert_error(ctx, last, depth,
187 X509_V_ERR_CERT_CHAIN_TOO_LONG, 0);
188
189 /*
190 * If we have a legacy xsc, choose a validated chain,
191 * and apply the extensions, revocation, and policy checks
192 * just like the legacy code did. We do this here instead
193 * of as building the chains to more easily support the
194 * callback and the bewildering array of VERIFY_PARAM
195 * knobs that are there for the fiddling.
196 */
197 if (ctx->xsc != NULL) {
198 ctx->xsc->last_untrusted = depth ? depth - 1 : 0;
199 sk_X509_pop_free(ctx->xsc->chain, X509_free);
200 ctx->xsc->chain = X509_chain_up_ref(chain->certs);
201 if (ctx->xsc->chain == NULL)
202 return x509_verify_cert_error(ctx, last, depth,
203 X509_V_ERR_OUT_OF_MEM, 0);
204
205 /*
206 * XXX currently this duplicates some work done
207 * in chain build, but we keep it here until
208 * we have feature parity
209 */
210 if (!x509_vfy_check_chain_extensions(ctx->xsc))
211 return 0;
212
213 if (!x509_constraints_chain(ctx->xsc->chain,
214 &ctx->xsc->error, &ctx->xsc->error_depth)) {
215 X509 *cert = sk_X509_value(ctx->xsc->chain, depth);
216 if (!x509_verify_cert_error(ctx, cert,
217 ctx->xsc->error_depth, ctx->xsc->error, 0))
218 return 0;
219 }
220
221 if (!x509_vfy_check_revocation(ctx->xsc))
222 return 0;
223
224 if (!x509_vfy_check_policy(ctx->xsc))
225 return 0;
226 }
227 /*
228 * no xsc means we are being called from the non-legacy API,
229 * extensions and purpose are dealt with as the chain is built.
230 *
231 * The non-legacy api returns multiple chains but does not do
232 * any revocation checking (it must be done by the caller on
233 * any chain they wish to use)
234 */
235
236 if ((ctx->chains[ctx->chains_count] = x509_verify_chain_dup(chain)) ==
237 NULL) {
238 return x509_verify_cert_error(ctx, last, depth,
239 X509_V_ERR_OUT_OF_MEM, 0);
240 }
241 ctx->chains_count++;
242 ctx->error = X509_V_OK;
243 ctx->error_depth = depth;
244 return 1;
245}
246
247static int
248x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent,
249 X509 *child)
250{
251 if (ctx->xsc != NULL)
252 return (ctx->xsc->check_issued(ctx->xsc, child, parent));
253
254 /* XXX key usage */
255 return X509_check_issued(child, parent) != X509_V_OK;
256}
257
258static int
259x509_verify_parent_signature(X509 *parent, X509 *child,
260 unsigned char *child_md, int *error)
261{
262 unsigned char parent_md[EVP_MAX_MD_SIZE] = { 0 };
263 EVP_PKEY *pkey;
264 int cached;
265 int ret = 0;
266
267 /* Use cached value if we have it */
268 if (child_md != NULL) {
269 if (!X509_digest(parent, X509_VERIFY_CERT_HASH, parent_md,
270 NULL))
271 return 0;
272 if ((cached = x509_issuer_cache_find(parent_md, child_md)) >= 0)
273 return cached;
274 }
275
276 /* Check signature. Did parent sign child? */
277 if ((pkey = X509_get_pubkey(parent)) == NULL) {
278 *error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
279 return 0;
280 }
281 if (X509_verify(child, pkey) <= 0)
282 *error = X509_V_ERR_CERT_SIGNATURE_FAILURE;
283 else
284 ret = 1;
285
286 /* Add result to cache */
287 if (child_md != NULL)
288 x509_issuer_cache_add(parent_md, child_md, ret);
289
290 EVP_PKEY_free(pkey);
291
292 return ret;
293}
294
295static int
296x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert,
297 unsigned char *cert_md, int is_root_cert, X509 *candidate,
298 struct x509_verify_chain *current_chain)
299{
300 int depth = sk_X509_num(current_chain->certs);
301 struct x509_verify_chain *new_chain;
302 int i;
303
304 /* Fail if the certificate is already in the chain */
305 for (i = 0; i < sk_X509_num(current_chain->certs); i++) {
306 if (X509_cmp(sk_X509_value(current_chain->certs, i),
307 candidate) == 0)
308 return 0;
309 }
310
311 if (ctx->sig_checks++ > X509_VERIFY_MAX_SIGCHECKS) {
312 /* don't allow callback to override safety check */
313 (void) x509_verify_cert_error(ctx, candidate, depth,
314 X509_V_ERR_CERT_CHAIN_TOO_LONG, 0);
315 return 0;
316 }
317
318
319 if (!x509_verify_parent_signature(candidate, cert, cert_md,
320 &ctx->error)) {
321 if (!x509_verify_cert_error(ctx, candidate, depth,
322 ctx->error, 0))
323 return 0;
324 }
325
326 if (!x509_verify_cert_valid(ctx, candidate, current_chain))
327 return 0;
328
329 /* candidate is good, add it to a copy of the current chain */
330 if ((new_chain = x509_verify_chain_dup(current_chain)) == NULL) {
331 x509_verify_cert_error(ctx, candidate, depth,
332 X509_V_ERR_OUT_OF_MEM, 0);
333 return 0;
334 }
335 if (!x509_verify_chain_append(new_chain, candidate, &ctx->error)) {
336 x509_verify_cert_error(ctx, candidate, depth,
337 ctx->error, 0);
338 x509_verify_chain_free(new_chain);
339 return 0;
340 }
341
342 /*
343 * If candidate is a trusted root, we have a validated chain,
344 * so we save it. Otherwise, recurse until we find a root or
345 * give up.
346 */
347 if (is_root_cert &&
348 x509_verify_cert_error(ctx, candidate, depth, X509_V_OK, 1))
349 (void) x509_verify_ctx_add_chain(ctx, new_chain);
350 else
351 x509_verify_build_chains(ctx, candidate, new_chain);
352
353 x509_verify_chain_free(new_chain);
354 return 1;
355}
356
357static int
358x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, size_t depth,
359 int error, int ok)
360{
361 ctx->error = error;
362 ctx->error_depth = depth;
363 if (ctx->xsc != NULL) {
364 ctx->xsc->error = error;
365 ctx->xsc->error_depth = depth;
366 ctx->xsc->current_cert = cert;
367 return ctx->xsc->verify_cb(ok, ctx->xsc);
368 }
369 return ok;
370}
371
372static void
373x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert,
374 struct x509_verify_chain *current_chain)
375{
376 unsigned char cert_md[EVP_MAX_MD_SIZE] = { 0 };
377 X509 *candidate;
378 int i, depth, count;
379
380 depth = sk_X509_num(current_chain->certs);
381 if (depth > 0)
382 depth--;
383
384 if (depth >= ctx->max_depth &&
385 !x509_verify_cert_error(ctx, cert, depth,
386 X509_V_ERR_CERT_CHAIN_TOO_LONG, 0))
387 return;
388
389 if (!X509_digest(cert, X509_VERIFY_CERT_HASH, cert_md, NULL) &&
390 !x509_verify_cert_error(ctx, cert, depth,
391 X509_V_ERR_UNSPECIFIED, 0))
392 return;
393
394 count = ctx->chains_count;
395 ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
396 ctx->error_depth = depth;
397
398 for (i = 0; i < sk_X509_num(ctx->roots); i++) {
399 candidate = sk_X509_value(ctx->roots, i);
400 if (x509_verify_potential_parent(ctx, candidate, cert)) {
401 x509_verify_consider_candidate(ctx, cert,
402 cert_md, 1, candidate, current_chain);
403 }
404 }
405
406 if (ctx->intermediates != NULL) {
407 for (i = 0; i < sk_X509_num(ctx->intermediates); i++) {
408 candidate = sk_X509_value(ctx->intermediates, i);
409 if (x509_verify_potential_parent(ctx, candidate, cert)) {
410 x509_verify_consider_candidate(ctx, cert,
411 cert_md, 0, candidate, current_chain);
412 }
413 }
414 }
415 if (ctx->chains_count > count) {
416 if (ctx->xsc != NULL) {
417 ctx->xsc->error = X509_V_OK;
418 ctx->xsc->error_depth = depth;
419 ctx->xsc->current_cert = cert;
420 (void) ctx->xsc->verify_cb(1, ctx->xsc);
421 }
422 } else if (ctx->error_depth == depth) {
423 (void) x509_verify_cert_error(ctx, cert, depth,
424 ctx->error, 0);
425 }
426}
427
428static int
429x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert, char *name)
430{
431 char *candidate;
432 size_t len;
433
434 if (name == NULL) {
435 if (ctx->xsc != NULL)
436 return x509_vfy_check_id(ctx->xsc);
437 return 1;
438 }
439 if ((candidate = strdup(name)) == NULL) {
440 ctx->error = X509_V_ERR_OUT_OF_MEM;
441 goto err;
442 }
443 if ((len = strlen(candidate)) < 1) {
444 ctx->error = X509_V_ERR_UNSPECIFIED; /* XXX */
445 goto err;
446 }
447
448 /* IP addresses may be written in [ ]. */
449 if (candidate[0] == '[' && candidate[len - 1] == ']') {
450 candidate[len - 1] = '\0';
451 if (X509_check_ip_asc(cert, candidate + 1, 0) <= 0) {
452 ctx->error = X509_V_ERR_IP_ADDRESS_MISMATCH;
453 goto err;
454 }
455 } else {
456 int flags = 0;
457
458 if (ctx->xsc == NULL)
459 flags = X509_CHECK_FLAG_NEVER_CHECK_SUBJECT;
460
461 if (X509_check_host(cert, candidate, len, flags, NULL) <= 0) {
462 ctx->error = X509_V_ERR_HOSTNAME_MISMATCH;
463 goto err;
464 }
465 }
466 free(candidate);
467 return 1;
468 err:
469 free(candidate);
470 return x509_verify_cert_error(ctx, cert, 0, ctx->error, 0);
471}
472
473static int
474x509_verify_set_check_time(struct x509_verify_ctx *ctx) {
475 if (ctx->xsc != NULL) {
476 if (ctx->xsc->param->flags & X509_V_FLAG_USE_CHECK_TIME) {
477 ctx->check_time = &ctx->xsc->param->check_time;
478 return 1;
479 }
480 if (ctx->xsc->param->flags & X509_V_FLAG_NO_CHECK_TIME)
481 return 0;
482 }
483
484 ctx->check_time = NULL;
485 return 1;
486}
487
488static int
489x509_verify_asn1_time_to_tm(const ASN1_TIME *atime, struct tm *tm, int notafter)
490{
491 time_t time;
492 int type;
493
494 memset(tm, 0, sizeof(*tm));
495
496 type = ASN1_time_parse(atime->data, atime->length, tm, atime->type);
497 if (type == -1)
498 return 0;
499
500 /* RFC 5280 section 4.1.2.5 */
501 if (tm->tm_year < 150 && type != V_ASN1_UTCTIME)
502 return 0;
503 if (tm->tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME)
504 return 0;
505
506 if (notafter) {
507 /*
508 * If we are a completely broken operating system with a
509 * 32 bit time_t, and we have been told this is a notafter
510 * date, limit the date to a 32 bit representable value.
511 */
512 if (!ASN1_time_tm_clamp_notafter(tm))
513 return 0;
514 }
515
516 /*
517 * Defensively fail if the time string is not representable as
518 * a time_t. A time_t must be sane if you care about times after
519 * Jan 19 2038.
520 */
521 if ((time = timegm(tm)) == -1)
522 return 0;
523
524 return 1;
525}
526
527static int
528x509_verify_cert_time(int is_notafter, const ASN1_TIME *cert_asn1,
529 time_t *cmp_time, int *error)
530{
531 struct tm cert_tm, when_tm;
532 time_t when;
533
534 if (cmp_time == NULL)
535 when = time(NULL);
536 else
537 when = *cmp_time;
538
539 if (!x509_verify_asn1_time_to_tm(cert_asn1, &cert_tm,
540 is_notafter)) {
541 *error = is_notafter ?
542 X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD :
543 X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
544 return 0;
545 }
546
547 if (gmtime_r(&when, &when_tm) == NULL) {
548 *error = X509_V_ERR_UNSPECIFIED;
549 return 0;
550 }
551
552 if (is_notafter) {
553 if (ASN1_time_tm_cmp(&cert_tm, &when_tm) == -1) {
554 *error = X509_V_ERR_CERT_HAS_EXPIRED;
555 return 0;
556 }
557 } else {
558 if (ASN1_time_tm_cmp(&cert_tm, &when_tm) == 1) {
559 *error = X509_V_ERR_CERT_NOT_YET_VALID;
560 return 0;
561 }
562 }
563
564 return 1;
565}
566
567static int
568x509_verify_validate_constraints(X509 *cert,
569 struct x509_verify_chain *current_chain, int *error)
570{
571 struct x509_constraints_names *excluded = NULL;
572 struct x509_constraints_names *permitted = NULL;
573 int err = X509_V_ERR_UNSPECIFIED;
574
575 if (current_chain == NULL)
576 return 1;
577
578 if (cert->nc != NULL) {
579 if ((permitted = x509_constraints_names_new()) == NULL) {
580 err = X509_V_ERR_OUT_OF_MEM;
581 goto err;
582 }
583 if ((excluded = x509_constraints_names_new()) == NULL) {
584 err = X509_V_ERR_OUT_OF_MEM;
585 goto err;
586 }
587 if (!x509_constraints_extract_constraints(cert,
588 permitted, excluded, &err))
589 goto err;
590 if (!x509_constraints_check(current_chain->names,
591 permitted, excluded, &err))
592 goto err;
593 x509_constraints_names_free(excluded);
594 x509_constraints_names_free(permitted);
595 }
596
597 return 1;
598 err:
599 *error = err;
600 x509_constraints_names_free(excluded);
601 x509_constraints_names_free(permitted);
602 return 0;
603}
604
605static int
606x509_verify_cert_extensions(struct x509_verify_ctx *ctx, X509 *cert, int need_ca)
607{
608 if (!(cert->ex_flags & EXFLAG_SET)) {
609 CRYPTO_w_lock(CRYPTO_LOCK_X509);
610 x509v3_cache_extensions(cert);
611 CRYPTO_w_unlock(CRYPTO_LOCK_X509);
612 }
613
614 if (ctx->xsc != NULL)
615 return 1; /* legacy is checked after chain is built */
616
617 if (cert->ex_flags & EXFLAG_CRITICAL) {
618 ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
619 return 0;
620 }
621 /* No we don't care about v1, netscape, and other ancient silliness */
622 if (need_ca && (!(cert->ex_flags & EXFLAG_BCONS) &&
623 (cert->ex_flags & EXFLAG_CA))) {
624 ctx->error = X509_V_ERR_INVALID_CA;
625 return 0;
626 }
627 if (ctx->purpose > 0 && X509_check_purpose(cert, ctx->purpose, need_ca)) {
628 ctx->error = X509_V_ERR_INVALID_PURPOSE;
629 return 0;
630 }
631
632 /* XXX support proxy certs later in new api */
633 if (ctx->xsc == NULL && cert->ex_flags & EXFLAG_PROXY) {
634 ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
635 return 0;
636 }
637
638 return 1;
639}
640
641/* Validate that cert is a possible candidate to append to current_chain */
642static int
643x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert,
644 struct x509_verify_chain *current_chain)
645{
646 X509 *issuer_candidate;
647 int should_be_ca = current_chain != NULL;
648 size_t depth = 0;
649
650 if (!should_be_ca)
651 depth = sk_X509_num(current_chain->certs);
652
653 if (!x509_verify_cert_extensions(ctx, cert, should_be_ca))
654 return 0;
655
656 if (should_be_ca) {
657 issuer_candidate = x509_verify_chain_last(current_chain);
658 if (issuer_candidate != NULL &&
659 !X509_check_issued(issuer_candidate, cert))
660 if (!x509_verify_cert_error(ctx, cert, depth,
661 X509_V_ERR_SUBJECT_ISSUER_MISMATCH, 0))
662 return 0;
663 }
664
665 if (x509_verify_set_check_time(ctx)) {
666 if (!x509_verify_cert_time(0, X509_get_notBefore(cert),
667 ctx->check_time, &ctx->error)) {
668 if (!x509_verify_cert_error(ctx, cert, depth,
669 ctx->error, 0))
670 return 0;
671 }
672
673 if (!x509_verify_cert_time(1, X509_get_notAfter(cert),
674 ctx->check_time, &ctx->error)) {
675 if (!x509_verify_cert_error(ctx, cert, depth,
676 ctx->error, 0))
677 return 0;
678 }
679 }
680
681 if (!x509_verify_validate_constraints(cert, current_chain,
682 &ctx->error) && !x509_verify_cert_error(ctx, cert, depth,
683 ctx->error, 0))
684 return 0;
685
686 return 1;
687}
688
689struct x509_verify_ctx *
690x509_verify_ctx_new_from_xsc(X509_STORE_CTX *xsc, STACK_OF(X509) *roots)
691{
692 struct x509_verify_ctx *ctx;
693
694 if (xsc == NULL)
695 return NULL;
696
697 if ((ctx = calloc(1, sizeof(struct x509_verify_ctx))) == NULL)
698 return NULL;
699
700 ctx->xsc = xsc;
701
702 if ((ctx->roots = X509_chain_up_ref(roots)) == NULL)
703 goto err;
704
705 if (xsc->untrusted &&
706 (ctx->intermediates = X509_chain_up_ref(xsc->untrusted)) == NULL)
707 goto err;
708
709 ctx->max_depth = xsc->param->depth;
710 if (ctx->max_depth == 0 || ctx->max_depth > X509_VERIFY_MAX_CHAIN_CERTS)
711 ctx->max_depth = X509_VERIFY_MAX_CHAIN_CERTS;
712
713 ctx->max_chains = X509_VERIFY_MAX_CHAINS;
714 ctx->max_sigs = X509_VERIFY_MAX_SIGCHECKS;
715
716 if ((ctx->chains = calloc(X509_VERIFY_MAX_CHAINS, sizeof(*ctx->chains))) ==
717 NULL)
718 goto err;
719
720 return ctx;
721 err:
722 x509_verify_ctx_free(ctx);
723 return NULL;
724}
725
726/* Public API */
727
728struct x509_verify_ctx *
729x509_verify_ctx_new(STACK_OF(X509) *roots)
730{
731 struct x509_verify_ctx *ctx;
732
733 if (roots == NULL)
734 return NULL;
735
736 if ((ctx = calloc(1, sizeof(struct x509_verify_ctx))) == NULL)
737 return NULL;
738
739 if ((ctx->roots = X509_chain_up_ref(roots)) == NULL)
740 goto err;
741
742 ctx->max_depth = X509_VERIFY_MAX_CHAIN_CERTS;
743 ctx->max_chains = X509_VERIFY_MAX_CHAINS;
744 ctx->max_sigs = X509_VERIFY_MAX_SIGCHECKS;
745
746 if ((ctx->chains = calloc(X509_VERIFY_MAX_CHAINS,
747 sizeof(*ctx->chains))) == NULL)
748 goto err;
749
750 return ctx;
751 err:
752 x509_verify_ctx_free(ctx);
753 return NULL;
754}
755
756void
757x509_verify_ctx_free(struct x509_verify_ctx *ctx)
758{
759 if (ctx == NULL)
760 return;
761 sk_X509_pop_free(ctx->roots, X509_free);
762 x509_verify_ctx_clear(ctx);
763 free(ctx);
764}
765
766int
767x509_verify_ctx_set_max_depth(struct x509_verify_ctx *ctx, size_t max)
768{
769 if (max < 1 || max > X509_VERIFY_MAX_CHAIN_CERTS)
770 return 0;
771 ctx->max_depth = max;
772 return 1;
773}
774
775int
776x509_verify_ctx_set_max_chains(struct x509_verify_ctx *ctx, size_t max)
777{
778 if (max < 1 || max > X509_VERIFY_MAX_CHAINS)
779 return 0;
780 ctx->max_chains = max;
781 return 1;
782}
783
784int
785x509_verify_ctx_set_max_signatures(struct x509_verify_ctx *ctx, size_t max)
786{
787 if (max < 1)
788 return 0;
789 if (max > 100000)
790 return 0;
791 ctx->max_sigs = max;
792 return 1;
793}
794
795int
796x509_verify_ctx_set_purpose(struct x509_verify_ctx *ctx, int purpose)
797{
798 if (purpose < X509_PURPOSE_MIN || purpose > X509_PURPOSE_MAX)
799 return 0;
800 ctx->purpose = purpose;
801 return 1;
802}
803
804int
805x509_verify_ctx_set_intermediates(struct x509_verify_ctx *ctx,
806 STACK_OF(X509) *intermediates)
807{
808 if ((ctx->intermediates = X509_chain_up_ref(intermediates)) == NULL)
809 return 0;
810 return 1;
811}
812
813const char *
814x509_verify_ctx_error_string(struct x509_verify_ctx *ctx)
815{
816 return X509_verify_cert_error_string(ctx->error);
817}
818
819size_t
820x509_verify_ctx_error_depth(struct x509_verify_ctx *ctx)
821{
822 return ctx->error_depth;
823}
824
825STACK_OF(X509) *
826x509_verify_ctx_chain(struct x509_verify_ctx *ctx, size_t i)
827{
828 if (i >= ctx->chains_count)
829 return NULL;
830 return ctx->chains[i]->certs;
831}
832
833size_t
834x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name)
835{
836 struct x509_verify_chain *current_chain;
837
838 if (ctx == NULL)
839 return 0;
840 if (ctx->roots == NULL || ctx->max_depth == 0) {
841 ctx->error = X509_V_ERR_INVALID_CALL;
842 return 0;
843 }
844
845 if (ctx->xsc != NULL) {
846 if (leaf != NULL || name != NULL) {
847 ctx->error = X509_V_ERR_INVALID_CALL;
848 return 0;
849 }
850 leaf = ctx->xsc->cert;
851 }
852
853 if (!x509_verify_cert_valid(ctx, leaf, NULL))
854 return 0;
855
856 if (!x509_verify_cert_hostname(ctx, leaf, name))
857 return 0;
858
859 if (ctx->xsc != NULL) {
860 /*
861 * XXX
862 * The legacy code expects the top level cert to be
863 * there, even if we didn't find a chain. So put it
864 * there, we will clobber it later if we find a valid
865 * chain.
866 */
867 if ((ctx->xsc->chain = sk_X509_new_null()) == NULL) {
868 ctx->error = X509_V_ERR_OUT_OF_MEM;
869 return 0;
870 }
871 if (!X509_up_ref(leaf)) {
872 ctx->error = X509_V_ERR_OUT_OF_MEM;
873 return 0;
874 }
875 if (!sk_X509_push(ctx->xsc->chain, leaf)) {
876 X509_free(leaf);
877 ctx->error = X509_V_ERR_OUT_OF_MEM;
878 return 0;
879 }
880 }
881
882 if ((current_chain = x509_verify_chain_new()) == NULL) {
883 ctx->error = X509_V_ERR_OUT_OF_MEM;
884 return 0;
885 }
886 if (!x509_verify_chain_append(current_chain, leaf, &ctx->error)) {
887 x509_verify_chain_free(current_chain);
888 return 0;
889 }
890 if (x509_verify_ctx_cert_is_root(ctx, leaf))
891 x509_verify_ctx_add_chain(ctx, current_chain);
892 else
893 x509_verify_build_chains(ctx, leaf, current_chain);
894
895 x509_verify_chain_free(current_chain);
896
897 /*
898 * Safety net:
899 * We could not find a validated chain, and for some reason do not
900 * have an error set.
901 */
902 if (ctx->chains_count == 0 && ctx->error == 0)
903 ctx->error = X509_V_ERR_UNSPECIFIED;
904
905 /* Clear whatever errors happened if we have any validated chain */
906 if (ctx->chains_count > 0)
907 ctx->error = X509_V_OK;
908
909 if (ctx->xsc != NULL) {
910 ctx->xsc->error = ctx->error;
911 return ctx->xsc->verify_cb(ctx->chains_count, ctx->xsc);
912 }
913 return (ctx->chains_count);
914}