summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/libcrypto/x509/x509_internal.h3
-rw-r--r--src/lib/libcrypto/x509/x509_verify.c5
-rw-r--r--src/lib/libcrypto/x509/x509_vfy.c143
-rw-r--r--src/lib/libcrypto/x509/x509_vfy.h9
4 files changed, 156 insertions, 4 deletions
diff --git a/src/lib/libcrypto/x509/x509_internal.h b/src/lib/libcrypto/x509/x509_internal.h
index c6ce5229ad..030f24c470 100644
--- a/src/lib/libcrypto/x509/x509_internal.h
+++ b/src/lib/libcrypto/x509/x509_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_internal.h,v 1.18 2022/03/14 21:15:49 tb Exp $ */ 1/* $OpenBSD: x509_internal.h,v 1.19 2022/06/27 14:10:22 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -135,6 +135,7 @@ int x509_constraints_check(struct x509_constraints_names *names,
135int x509_constraints_chain(STACK_OF(X509) *chain, int *error, 135int x509_constraints_chain(STACK_OF(X509) *chain, int *error,
136 int *depth); 136 int *depth);
137void x509_verify_cert_info_populate(X509 *cert); 137void x509_verify_cert_info_populate(X509 *cert);
138int x509_vfy_check_security_level(X509_STORE_CTX *ctx);
138 139
139__END_HIDDEN_DECLS 140__END_HIDDEN_DECLS
140 141
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c
index f6959d1f3a..83030672ef 100644
--- a/src/lib/libcrypto/x509/x509_verify.c
+++ b/src/lib/libcrypto/x509/x509_verify.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_verify.c,v 1.56 2022/06/25 20:01:43 beck Exp $ */ 1/* $OpenBSD: x509_verify.c,v 1.57 2022/06/27 14:10:22 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -415,6 +415,9 @@ x509_verify_ctx_validate_legacy_chain(struct x509_verify_ctx *ctx,
415 goto err; 415 goto err;
416#endif 416#endif
417 417
418 if (!x509_vfy_check_security_level(ctx->xsc))
419 goto err;
420
418 if (!x509_constraints_chain(ctx->xsc->chain, 421 if (!x509_constraints_chain(ctx->xsc->chain,
419 &ctx->xsc->error, &ctx->xsc->error_depth)) { 422 &ctx->xsc->error, &ctx->xsc->error_depth)) {
420 X509 *cert = sk_X509_value(ctx->xsc->chain, depth); 423 X509 *cert = sk_X509_value(ctx->xsc->chain, depth);
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c
index 9a929963f3..18cf08a07c 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.101 2022/01/22 00:36:46 inoguchi Exp $ */ 1/* $OpenBSD: x509_vfy.c,v 1.102 2022/06/27 14:10:22 tb 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 *
@@ -144,6 +144,8 @@ static int X509_cmp_time_internal(const ASN1_TIME *ctm, time_t *cmp_time,
144 144
145static int internal_verify(X509_STORE_CTX *ctx); 145static int internal_verify(X509_STORE_CTX *ctx);
146static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); 146static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
147static int check_key_level(X509_STORE_CTX *ctx, X509 *cert);
148static int verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err);
147 149
148int ASN1_time_tm_clamp_notafter(struct tm *tm); 150int ASN1_time_tm_clamp_notafter(struct tm *tm);
149 151
@@ -542,6 +544,11 @@ X509_verify_cert_legacy(X509_STORE_CTX *ctx)
542 if (!ok) 544 if (!ok)
543 goto end; 545 goto end;
544 546
547 /* Check that the chain satisfies the security level. */
548 ok = x509_vfy_check_security_level(ctx);
549 if (!ok)
550 goto end;
551
545 /* Check name constraints */ 552 /* Check name constraints */
546 ok = check_name_constraints(ctx); 553 ok = check_name_constraints(ctx);
547 if (!ok) 554 if (!ok)
@@ -629,6 +636,14 @@ X509_verify_cert(X509_STORE_CTX *ctx)
629 } 636 }
630 637
631 /* 638 /*
639 * If the certificate's public key is too weak, don't bother
640 * continuing.
641 */
642 if (!check_key_level(ctx, ctx->cert) &&
643 !verify_cb_cert(ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL))
644 return 0;
645
646 /*
632 * If flags request legacy, use the legacy verifier. If we 647 * If flags request legacy, use the legacy verifier. If we
633 * requested "no alt chains" from the age of hammer pants, use 648 * requested "no alt chains" from the age of hammer pants, use
634 * the legacy verifier because the multi chain verifier really 649 * the legacy verifier because the multi chain verifier really
@@ -2596,3 +2611,129 @@ X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
2596 X509_VERIFY_PARAM_free(ctx->param); 2611 X509_VERIFY_PARAM_free(ctx->param);
2597 ctx->param = param; 2612 ctx->param = param;
2598} 2613}
2614
2615/*
2616 * Check if |bits| are adequate for |security level|.
2617 * Returns 1 if ok, 0 otherwise.
2618 */
2619static int
2620enough_bits_for_security_level(int bits, int level)
2621{
2622 /*
2623 * Sigh. OpenSSL does this silly squashing, so we will
2624 * too. Derp for Derp compatibility being important.
2625 */
2626 if (level < 0)
2627 level = 0;
2628 if (level > 5)
2629 level = 5;
2630
2631 switch (level) {
2632 case 0:
2633 return 1;
2634 case 1:
2635 return bits >= 80;
2636 case 2:
2637 return bits >= 112;
2638 case 3:
2639 return bits >= 128;
2640 case 4:
2641 return bits >= 192;
2642 case 5:
2643 return bits >= 256;
2644 default:
2645 return 0;
2646 }
2647}
2648
2649/*
2650 * Check whether the public key of |cert| meets the security level of |ctx|.
2651 *
2652 * Returns 1 on success, 0 otherwise.
2653 */
2654static int
2655check_key_level(X509_STORE_CTX *ctx, X509 *cert)
2656{
2657 EVP_PKEY *pkey;
2658 int bits;
2659
2660 /* Unsupported or malformed keys are not secure */
2661 if ((pkey = X509_get0_pubkey(cert)) == NULL)
2662 return 0;
2663
2664 if ((bits = EVP_PKEY_security_bits(pkey)) <= 0)
2665 return 0;
2666
2667 return enough_bits_for_security_level(bits, ctx->param->security_level);
2668}
2669
2670/*
2671 * Check whether the signature digest algorithm of |cert| meets the security
2672 * level of |ctx|. Do not check trust anchors (self-signed or not).
2673 *
2674 * Returns 1 on success, 0 otherwise.
2675 */
2676static int
2677check_sig_level(X509_STORE_CTX *ctx, X509 *cert)
2678{
2679 const EVP_MD *md;
2680 int bits, nid, md_nid;
2681
2682 if ((nid = X509_get_signature_nid(cert)) == NID_undef)
2683 return 0;
2684
2685 /*
2686 * Look up signature algorithm digest.
2687 */
2688
2689 if (!OBJ_find_sigid_algs(nid, &md_nid, NULL))
2690 return 0;
2691
2692 if (md_nid == NID_undef)
2693 return 0;
2694
2695 if ((md = EVP_get_digestbynid(md_nid)) == NULL)
2696 return 0;
2697
2698 /* Assume 4 bits of collision resistance for each hash octet. */
2699 bits = EVP_MD_size(md) * 4;
2700
2701 return enough_bits_for_security_level(bits, ctx->param->security_level);
2702}
2703
2704int
2705x509_vfy_check_security_level(X509_STORE_CTX *ctx)
2706{
2707 int num = sk_X509_num(ctx->chain);
2708 int i;
2709
2710 if (ctx->param->security_level <= 0)
2711 return 1;
2712
2713 for (i = 0; i < num; i++) {
2714 X509 *cert = sk_X509_value(ctx->chain, i);
2715
2716 /*
2717 * We've already checked the security of the leaf key, so here
2718 * we only check the security of issuer keys.
2719 */
2720 if (i > 0) {
2721 if (!check_key_level(ctx, cert) &&
2722 !verify_cb_cert(ctx, cert, i,
2723 X509_V_ERR_CA_KEY_TOO_SMALL))
2724 return 0;
2725 }
2726
2727 /*
2728 * We also check the signature algorithm security of all certs
2729 * except those of the trust anchor at index num - 1.
2730 */
2731 if (i == num - 1)
2732 break;
2733
2734 if (!check_sig_level(ctx, cert) &&
2735 !verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_MD_TOO_WEAK))
2736 return 0;
2737 }
2738 return 1;
2739}
diff --git a/src/lib/libcrypto/x509/x509_vfy.h b/src/lib/libcrypto/x509/x509_vfy.h
index a007fe4795..d31e779aae 100644
--- a/src/lib/libcrypto/x509/x509_vfy.h
+++ b/src/lib/libcrypto/x509/x509_vfy.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_vfy.h,v 1.51 2022/06/27 14:00:09 tb Exp $ */ 1/* $OpenBSD: x509_vfy.h,v 1.52 2022/06/27 14:10:22 tb 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 *
@@ -205,6 +205,13 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
205/* Issuer lookup error */ 205/* Issuer lookup error */
206#define X509_V_ERR_STORE_LOOKUP 66 206#define X509_V_ERR_STORE_LOOKUP 66
207 207
208#if defined(LIBRESSL_INTERNAL)
209/* Security level errors */
210#define X509_V_ERR_EE_KEY_TOO_SMALL 67
211#define X509_V_ERR_CA_KEY_TOO_SMALL 68
212#define X509_V_ERR_CA_MD_TOO_WEAK 69
213#endif
214
208/* Certificate verify flags */ 215/* Certificate verify flags */
209 216
210/* Send issuer+subject checks to verify_cb */ 217/* Send issuer+subject checks to verify_cb */