summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509/x509_vfy.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_vfy.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_vfy.c')
-rw-r--r--src/lib/libcrypto/x509/x509_vfy.c228
1 files changed, 180 insertions, 48 deletions
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c
index 28dbf60c38..b1cc9b5a00 100644
--- a/src/lib/libcrypto/x509/x509_vfy.c
+++ b/src/lib/libcrypto/x509/x509_vfy.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_vfy.c,v 1.74 2020/09/12 14:14:02 beck Exp $ */ 1/* $OpenBSD: x509_vfy.c,v 1.75 2020/09/13 15:06:17 beck Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -77,6 +77,7 @@
77#include "vpm_int.h" 77#include "vpm_int.h"
78#include "x509_internal.h" 78#include "x509_internal.h"
79#include "x509_lcl.h" 79#include "x509_lcl.h"
80#include "x509_internal.h"
80 81
81/* CRL score values */ 82/* CRL score values */
82 83
@@ -124,7 +125,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx);
124static int check_name_constraints(X509_STORE_CTX *ctx); 125static int check_name_constraints(X509_STORE_CTX *ctx);
125static int check_trust(X509_STORE_CTX *ctx); 126static int check_trust(X509_STORE_CTX *ctx);
126static int check_revocation(X509_STORE_CTX *ctx); 127static int check_revocation(X509_STORE_CTX *ctx);
127static int check_cert(X509_STORE_CTX *ctx); 128static int check_cert(X509_STORE_CTX *ctx, STACK_OF(X509) *chain, int depth);
128static int check_policy(X509_STORE_CTX *ctx); 129static int check_policy(X509_STORE_CTX *ctx);
129 130
130static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, 131static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
@@ -144,6 +145,7 @@ static int X509_cmp_time_internal(const ASN1_TIME *ctm, time_t *cmp_time,
144 int clamp_notafter); 145 int clamp_notafter);
145 146
146static int internal_verify(X509_STORE_CTX *ctx); 147static int internal_verify(X509_STORE_CTX *ctx);
148static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
147 149
148int ASN1_time_tm_clamp_notafter(struct tm *tm); 150int ASN1_time_tm_clamp_notafter(struct tm *tm);
149 151
@@ -224,7 +226,21 @@ check_id(X509_STORE_CTX *ctx)
224} 226}
225 227
226int 228int
227X509_verify_cert(X509_STORE_CTX *ctx) 229x509_vfy_check_id(X509_STORE_CTX *ctx) {
230 return check_id(ctx);
231}
232
233/*
234 * This is the effectively broken legacy OpenSSL chain builder. It
235 * might find an unvalidated chain and leave it sitting in
236 * ctx->chain. It does not correctly handle many cases where multiple
237 * chains could exist.
238 *
239 * Oh no.. I know a dirty word...
240 * Oooooooh..
241 */
242static int
243X509_verify_cert_legacy_build_chain(X509_STORE_CTX *ctx, int *bad)
228{ 244{
229 X509 *x, *xtmp, *xtmp2, *chain_ss = NULL; 245 X509 *x, *xtmp, *xtmp2, *chain_ss = NULL;
230 int bad_chain = 0; 246 int bad_chain = 0;
@@ -234,39 +250,6 @@ X509_verify_cert(X509_STORE_CTX *ctx)
234 int (*cb) (int xok, X509_STORE_CTX *xctx); 250 int (*cb) (int xok, X509_STORE_CTX *xctx);
235 STACK_OF(X509) *sktmp = NULL; 251 STACK_OF(X509) *sktmp = NULL;
236 252
237 if (ctx->cert == NULL) {
238 X509error(X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
239 ctx->error = X509_V_ERR_INVALID_CALL;
240 return -1;
241 }
242 if (ctx->chain != NULL) {
243 /*
244 * This X509_STORE_CTX has already been used to verify
245 * a cert. We cannot do another one.
246 */
247 X509error(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
248 ctx->error = X509_V_ERR_INVALID_CALL;
249 return -1;
250 }
251 if (ctx->param->id->poisoned) {
252 /*
253 * This X509_STORE_CTX had failures setting
254 * up verify parameters. We can not use it.
255 */
256 X509error(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
257 ctx->error = X509_V_ERR_INVALID_CALL;
258 return -1;
259 }
260 if (ctx->error != X509_V_ERR_INVALID_CALL) {
261 /*
262 * This X509_STORE_CTX has not been properly initialized.
263 */
264 X509error(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
265 ctx->error = X509_V_ERR_INVALID_CALL;
266 return -1;
267 }
268 ctx->error = X509_V_OK; /* Initialize to OK */
269
270 cb = ctx->verify_cb; 253 cb = ctx->verify_cb;
271 254
272 /* 255 /*
@@ -534,6 +517,23 @@ X509_verify_cert(X509_STORE_CTX *ctx)
534 if (!ok) 517 if (!ok)
535 goto end; 518 goto end;
536 } 519 }
520 end:
521 sk_X509_free(sktmp);
522 X509_free(chain_ss);
523 *bad = bad_chain;
524 return ok;
525}
526
527static int
528X509_verify_cert_legacy(X509_STORE_CTX *ctx)
529{
530 int ok = 0, bad_chain;
531
532 ctx->error = X509_V_OK; /* Initialize to OK */
533
534 ok = X509_verify_cert_legacy_build_chain(ctx, &bad_chain);
535 if (!ok)
536 goto end;
537 537
538 /* We have the chain complete: now we need to check its purpose */ 538 /* We have the chain complete: now we need to check its purpose */
539 ok = check_chain_extensions(ctx); 539 ok = check_chain_extensions(ctx);
@@ -548,6 +548,7 @@ X509_verify_cert(X509_STORE_CTX *ctx)
548 ok = check_id(ctx); 548 ok = check_id(ctx);
549 if (!ok) 549 if (!ok)
550 goto end; 550 goto end;
551
551 /* 552 /*
552 * Check revocation status: we do this after copying parameters because 553 * Check revocation status: we do this after copying parameters because
553 * they may be needed for CRL signature verification. 554 * they may be needed for CRL signature verification.
@@ -569,15 +570,125 @@ X509_verify_cert(X509_STORE_CTX *ctx)
569 ok = ctx->check_policy(ctx); 570 ok = ctx->check_policy(ctx);
570 571
571 end: 572 end:
572 sk_X509_free(sktmp);
573 X509_free(chain_ss);
574
575 /* Safety net, error returns must set ctx->error */ 573 /* Safety net, error returns must set ctx->error */
576 if (ok <= 0 && ctx->error == X509_V_OK) 574 if (ok <= 0 && ctx->error == X509_V_OK)
577 ctx->error = X509_V_ERR_UNSPECIFIED; 575 ctx->error = X509_V_ERR_UNSPECIFIED;
576
578 return ok; 577 return ok;
579} 578}
580 579
580int
581X509_verify_cert(X509_STORE_CTX *ctx)
582{
583 STACK_OF(X509) *roots = NULL;
584 struct x509_verify_ctx *vctx = NULL;
585 int chain_count = 0;
586
587 if (ctx->cert == NULL) {
588 X509error(X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
589 ctx->error = X509_V_ERR_INVALID_CALL;
590 return -1;
591 }
592 if (ctx->chain != NULL) {
593 /*
594 * This X509_STORE_CTX has already been used to verify
595 * a cert. We cannot do another one.
596 */
597 X509error(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
598 ctx->error = X509_V_ERR_INVALID_CALL;
599 return -1;
600 }
601 if (ctx->param->id->poisoned) {
602 /*
603 * This X509_STORE_CTX had failures setting
604 * up verify parameters. We can not use it.
605 */
606 X509error(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
607 ctx->error = X509_V_ERR_INVALID_CALL;
608 return -1;
609 }
610 if (ctx->error != X509_V_ERR_INVALID_CALL) {
611 /*
612 * This X509_STORE_CTX has not been properly initialized.
613 */
614 X509error(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
615 ctx->error = X509_V_ERR_INVALID_CALL;
616 return -1;
617 }
618
619 /*
620 * If flags request legacy, use the legacy verifier. If we
621 * requested "no alt chains" from the age of hammer pants, use
622 * the legacy verifier because the multi chain verifier really
623 * does find all the "alt chains".
624 *
625 * XXX deprecate the NO_ALT_CHAINS flag?
626 */
627 if ((ctx->param->flags & X509_V_FLAG_LEGACY_VERIFY) ||
628 (ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS))
629 return X509_verify_cert_legacy(ctx);
630
631 /* Use the modern multi-chain verifier from x509_verify_cert */
632
633 /* Find our trusted roots */
634 ctx->error = X509_V_ERR_OUT_OF_MEM;
635
636 if (ctx->get_issuer == get_issuer_sk) {
637 /*
638 * We are using the trusted stack method. so
639 * the roots are in the aptly named "ctx->other_ctx"
640 * pointer. (It could have been called "al")
641 */
642 if ((roots = X509_chain_up_ref(ctx->other_ctx)) == NULL)
643 return -1;
644 } else {
645 /*
646 * We have a X509_STORE and need to pull out the roots.
647 * Don't look Ethel...
648 */
649 STACK_OF(X509_OBJECT) *objs;
650 size_t i, good = 1;
651
652 if ((roots = sk_X509_new_null()) == NULL)
653 return -1;
654
655 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
656 if ((objs = X509_STORE_get0_objects(ctx->ctx)) == NULL)
657 good = 0;
658 for (i = 0; good && i < sk_X509_OBJECT_num(objs); i++) {
659 X509_OBJECT *obj;
660 X509 *root;
661 obj = sk_X509_OBJECT_value(objs, i);
662 if (obj->type != X509_LU_X509)
663 continue;
664 root = obj->data.x509;
665 if (X509_up_ref(root) == 0)
666 good = 0;
667 if (sk_X509_push(roots, root) == 0) {
668 X509_free(root);
669 good = 0;
670 }
671 }
672 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
673
674 if (!good) {
675 sk_X509_pop_free(roots, X509_free);
676 return -1;
677 }
678 }
679
680 if ((vctx = x509_verify_ctx_new_from_xsc(ctx, roots)) != NULL) {
681 ctx->error = X509_V_OK; /* Initialize to OK */
682 chain_count = x509_verify(vctx, NULL, NULL);
683 }
684
685 sk_X509_pop_free(roots, X509_free);
686 x509_verify_ctx_free(vctx);
687
688 /* if we succeed we have a chain in ctx->chain */
689 return (chain_count > 0 && ctx->chain != NULL);
690}
691
581/* Given a STACK_OF(X509) find the issuer of cert (if any) 692/* Given a STACK_OF(X509) find the issuer of cert (if any)
582 */ 693 */
583 694
@@ -637,8 +748,8 @@ get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
637 * with the supplied purpose 748 * with the supplied purpose
638 */ 749 */
639 750
640static int 751int
641check_chain_extensions(X509_STORE_CTX *ctx) 752x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx)
642{ 753{
643#ifdef OPENSSL_NO_CHAIN_VERIFY 754#ifdef OPENSSL_NO_CHAIN_VERIFY
644 return 1; 755 return 1;
@@ -781,6 +892,11 @@ end:
781} 892}
782 893
783static int 894static int
895check_chain_extensions(X509_STORE_CTX *ctx) {
896 return x509_vfy_check_chain_extensions(ctx);
897}
898
899static int
784check_name_constraints(X509_STORE_CTX *ctx) 900check_name_constraints(X509_STORE_CTX *ctx)
785{ 901{
786 if (!x509_constraints_chain(ctx->chain, &ctx->error, 902 if (!x509_constraints_chain(ctx->chain, &ctx->error,
@@ -875,6 +991,11 @@ static int check_trust(X509_STORE_CTX *ctx)
875 return X509_TRUST_UNTRUSTED; 991 return X509_TRUST_UNTRUSTED;
876} 992}
877 993
994int x509_vfy_check_trust(X509_STORE_CTX *ctx)
995{
996 return check_trust(ctx);
997}
998
878static int 999static int
879check_revocation(X509_STORE_CTX *ctx) 1000check_revocation(X509_STORE_CTX *ctx)
880{ 1001{
@@ -891,24 +1012,29 @@ check_revocation(X509_STORE_CTX *ctx)
891 last = 0; 1012 last = 0;
892 } 1013 }
893 for (i = 0; i <= last; i++) { 1014 for (i = 0; i <= last; i++) {
894 ctx->error_depth = i; 1015 ok = check_cert(ctx, ctx->chain, i);
895 ok = check_cert(ctx);
896 if (!ok) 1016 if (!ok)
897 return ok; 1017 return ok;
898 } 1018 }
899 return 1; 1019 return 1;
900} 1020}
901 1021
1022int
1023x509_vfy_check_revocation(X509_STORE_CTX *ctx)
1024{
1025 return check_revocation(ctx);
1026}
1027
902static int 1028static int
903check_cert(X509_STORE_CTX *ctx) 1029check_cert(X509_STORE_CTX *ctx, STACK_OF(X509) *chain, int depth)
904{ 1030{
905 X509_CRL *crl = NULL, *dcrl = NULL; 1031 X509_CRL *crl = NULL, *dcrl = NULL;
906 X509 *x; 1032 X509 *x;
907 int ok = 0, cnum; 1033 int ok = 0, cnum;
908 unsigned int last_reasons; 1034 unsigned int last_reasons;
909 1035
910 cnum = ctx->error_depth; 1036 cnum = ctx->error_depth = depth;
911 x = sk_X509_value(ctx->chain, cnum); 1037 x = sk_X509_value(chain, cnum);
912 ctx->current_cert = x; 1038 ctx->current_cert = x;
913 ctx->current_issuer = NULL; 1039 ctx->current_issuer = NULL;
914 ctx->current_crl_score = 0; 1040 ctx->current_crl_score = 0;
@@ -1660,8 +1786,8 @@ cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
1660 return 1; 1786 return 1;
1661} 1787}
1662 1788
1663static int 1789int
1664check_policy(X509_STORE_CTX *ctx) 1790x509_vfy_check_policy(X509_STORE_CTX *ctx)
1665{ 1791{
1666 int ret; 1792 int ret;
1667 1793
@@ -1707,6 +1833,12 @@ check_policy(X509_STORE_CTX *ctx)
1707 return 1; 1833 return 1;
1708} 1834}
1709 1835
1836static int
1837check_policy(X509_STORE_CTX *ctx)
1838{
1839 return x509_vfy_check_policy(ctx);
1840}
1841
1710/* 1842/*
1711 * Inform the verify callback of an error. 1843 * Inform the verify callback of an error.
1712 * 1844 *