diff options
| -rw-r--r-- | src/lib/libcrypto/dh/dh_check.c | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/src/lib/libcrypto/dh/dh_check.c b/src/lib/libcrypto/dh/dh_check.c index 1ba85bc824..143699b4f6 100644 --- a/src/lib/libcrypto/dh/dh_check.c +++ b/src/lib/libcrypto/dh/dh_check.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: dh_check.c,v 1.31 2025/05/10 05:54:38 tb Exp $ */ | 1 | /* $OpenBSD: dh_check.c,v 1.32 2026/01/23 08:21:52 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 | * |
| @@ -104,6 +104,58 @@ DH_check_params(const DH *dh, int *flags) | |||
| 104 | return ok; | 104 | return ok; |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | typedef BIGNUM *(*get_p_fn)(BIGNUM *); | ||
| 108 | |||
| 109 | static const get_p_fn get_well_known_p[] = { | ||
| 110 | BN_get_rfc2409_prime_768, | ||
| 111 | BN_get_rfc2409_prime_1024, | ||
| 112 | BN_get_rfc3526_prime_1536, | ||
| 113 | BN_get_rfc3526_prime_2048, | ||
| 114 | BN_get_rfc3526_prime_3072, | ||
| 115 | BN_get_rfc3526_prime_4096, | ||
| 116 | BN_get_rfc3526_prime_6144, | ||
| 117 | BN_get_rfc3526_prime_8192, | ||
| 118 | }; | ||
| 119 | |||
| 120 | #define N_WELL_KNOWN_P_FN (sizeof(get_well_known_p) / sizeof(get_well_known_p[0])) | ||
| 121 | |||
| 122 | /* | ||
| 123 | * Scapy special: on startup it now calls DH_check() on all the well-known DH | ||
| 124 | * primes, which is a sensible thing to do. In any case, using BN_is_prime_ex() | ||
| 125 | * on a standardized domain parameter is dumb, so avoid it. | ||
| 126 | */ | ||
| 127 | static int | ||
| 128 | dh_is_well_known_p(const BIGNUM *p, BN_CTX *ctx, int *is_well_known) | ||
| 129 | { | ||
| 130 | BIGNUM *bn; | ||
| 131 | size_t i; | ||
| 132 | int ret = 0; | ||
| 133 | |||
| 134 | *is_well_known = 0; | ||
| 135 | |||
| 136 | BN_CTX_start(ctx); | ||
| 137 | if ((bn = BN_CTX_get(ctx)) == NULL) | ||
| 138 | goto err; | ||
| 139 | |||
| 140 | for (i = 0; i < N_WELL_KNOWN_P_FN; i++) { | ||
| 141 | get_p_fn get_p = get_well_known_p[i]; | ||
| 142 | |||
| 143 | if (get_p(bn) == NULL) | ||
| 144 | goto err; | ||
| 145 | if (BN_cmp(bn, p) == 0) { | ||
| 146 | *is_well_known = 1; | ||
| 147 | break; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | ret = 1; | ||
| 152 | |||
| 153 | err: | ||
| 154 | BN_CTX_end(ctx); | ||
| 155 | |||
| 156 | return ret; | ||
| 157 | } | ||
| 158 | |||
| 107 | /* | 159 | /* |
| 108 | * Check that p is a safe prime and that g is a suitable generator. | 160 | * Check that p is a safe prime and that g is a suitable generator. |
| 109 | */ | 161 | */ |
| @@ -112,7 +164,7 @@ int | |||
| 112 | DH_check(const DH *dh, int *flags) | 164 | DH_check(const DH *dh, int *flags) |
| 113 | { | 165 | { |
| 114 | BN_CTX *ctx = NULL; | 166 | BN_CTX *ctx = NULL; |
| 115 | int is_prime; | 167 | int is_prime, is_well_known; |
| 116 | int ok = 0; | 168 | int ok = 0; |
| 117 | 169 | ||
| 118 | *flags = 0; | 170 | *flags = 0; |
| @@ -150,6 +202,11 @@ DH_check(const DH *dh, int *flags) | |||
| 150 | *flags |= DH_CHECK_INVALID_Q_VALUE; | 202 | *flags |= DH_CHECK_INVALID_Q_VALUE; |
| 151 | } | 203 | } |
| 152 | 204 | ||
| 205 | if (!dh_is_well_known_p(dh->p, ctx, &is_well_known)) | ||
| 206 | goto err; | ||
| 207 | if (is_well_known) | ||
| 208 | goto done; | ||
| 209 | |||
| 153 | is_prime = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME, | 210 | is_prime = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME, |
| 154 | ctx, NULL); | 211 | ctx, NULL); |
| 155 | if (is_prime < 0) | 212 | if (is_prime < 0) |
| @@ -171,6 +228,7 @@ DH_check(const DH *dh, int *flags) | |||
| 171 | *flags |= DH_CHECK_P_NOT_SAFE_PRIME; | 228 | *flags |= DH_CHECK_P_NOT_SAFE_PRIME; |
| 172 | } | 229 | } |
| 173 | 230 | ||
| 231 | done: | ||
| 174 | ok = 1; | 232 | ok = 1; |
| 175 | 233 | ||
| 176 | err: | 234 | err: |
