diff options
author | tb <> | 2022-06-27 14:10:22 +0000 |
---|---|---|
committer | tb <> | 2022-06-27 14:10:22 +0000 |
commit | b5d221b6a5b4972e734f96ae385a030035125024 (patch) | |
tree | 8f690d35a09cd2d9e7808f00b7617746497fcde3 | |
parent | 6ed54976ab988ec7cfdbaf1ac00396b0eea716ba (diff) | |
download | openbsd-b5d221b6a5b4972e734f96ae385a030035125024.tar.gz openbsd-b5d221b6a5b4972e734f96ae385a030035125024.tar.bz2 openbsd-b5d221b6a5b4972e734f96ae385a030035125024.zip |
Allow security_level to mestastasize into the verifier
The tentacles are everywhere. This checks that all certs in a chain
have keys and signature algorithms matching the requirements of the
security_level configured in the verify parameters.
ok beck jsing
-rw-r--r-- | src/lib/libcrypto/x509/x509_internal.h | 3 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_verify.c | 5 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.c | 143 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.h | 9 |
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, | |||
135 | int x509_constraints_chain(STACK_OF(X509) *chain, int *error, | 135 | int x509_constraints_chain(STACK_OF(X509) *chain, int *error, |
136 | int *depth); | 136 | int *depth); |
137 | void x509_verify_cert_info_populate(X509 *cert); | 137 | void x509_verify_cert_info_populate(X509 *cert); |
138 | int 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 | ||
145 | static int internal_verify(X509_STORE_CTX *ctx); | 145 | static int internal_verify(X509_STORE_CTX *ctx); |
146 | static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); | 146 | static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); |
147 | static int check_key_level(X509_STORE_CTX *ctx, X509 *cert); | ||
148 | static int verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err); | ||
147 | 149 | ||
148 | int ASN1_time_tm_clamp_notafter(struct tm *tm); | 150 | int 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 | */ | ||
2619 | static int | ||
2620 | enough_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 | */ | ||
2654 | static int | ||
2655 | check_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 | */ | ||
2676 | static int | ||
2677 | check_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 | |||
2704 | int | ||
2705 | x509_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 */ |