diff options
author | tb <> | 2021-11-29 20:02:14 +0000 |
---|---|---|
committer | tb <> | 2021-11-29 20:02:14 +0000 |
commit | bd7738409d496371bd505cd5dbdb2a5675c5665f (patch) | |
tree | a1b7be0a5f53527fff389034167d093418d38eaf /src | |
parent | 33c4b670470691ed907e24ba05f290f1e366bd59 (diff) | |
download | openbsd-bd7738409d496371bd505cd5dbdb2a5675c5665f.tar.gz openbsd-bd7738409d496371bd505cd5dbdb2a5675c5665f.tar.bz2 openbsd-bd7738409d496371bd505cd5dbdb2a5675c5665f.zip |
Clean up DH_check_pub_key() and ensure that y^q (mod p) == 1.
This aligns our behavior with OpenSSL 1.1.1 which includes a mitigation
for small subgroup attacks. This did not affect LibreSSL since we do
not support X9.42 style parameter files or RFC 5114.
The meat of this commit is from Matt Caswell, OpenSSL b128abc3
ok inoguchi jsing
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libcrypto/dh/dh_check.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/src/lib/libcrypto/dh/dh_check.c b/src/lib/libcrypto/dh/dh_check.c index b06e971235..7b9fcbdf5a 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.20 2021/11/29 19:54:07 tb Exp $ */ | 1 | /* $OpenBSD: dh_check.c,v 1.21 2021/11/29 20:02:14 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 | * |
@@ -187,22 +187,57 @@ DH_check(const DH *dh, int *flags) | |||
187 | } | 187 | } |
188 | 188 | ||
189 | int | 189 | int |
190 | DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) | 190 | DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *flags) |
191 | { | 191 | { |
192 | BIGNUM *q = NULL; | 192 | BN_CTX *ctx = NULL; |
193 | 193 | BIGNUM *max_pub_key; | |
194 | *ret = 0; | 194 | int ok = 0; |
195 | q = BN_new(); | 195 | |
196 | if (q == NULL) | 196 | *flags = 0; |
197 | return 0; | 197 | |
198 | BN_set_word(q, 1); | 198 | if ((ctx = BN_CTX_new()) == NULL) |
199 | if (BN_cmp(pub_key, q) <= 0) | 199 | goto err; |
200 | *ret |= DH_CHECK_PUBKEY_TOO_SMALL; | 200 | BN_CTX_start(ctx); |
201 | BN_copy(q, dh->p); | 201 | if ((max_pub_key = BN_CTX_get(ctx)) == NULL) |
202 | BN_sub_word(q, 1); | 202 | goto err; |
203 | if (BN_cmp(pub_key, q) >= 0) | 203 | |
204 | *ret |= DH_CHECK_PUBKEY_TOO_LARGE; | 204 | /* |
205 | 205 | * Check that 1 < pub_key < dh->p - 1 | |
206 | BN_free(q); | 206 | */ |
207 | return 1; | 207 | |
208 | if (BN_cmp(pub_key, BN_value_one()) <= 0) | ||
209 | *flags |= DH_CHECK_PUBKEY_TOO_SMALL; | ||
210 | |||
211 | /* max_pub_key = dh->p - 1 */ | ||
212 | if (BN_copy(max_pub_key, dh->p) == NULL) | ||
213 | goto err; | ||
214 | if (!BN_sub_word(max_pub_key, 1)) | ||
215 | goto err; | ||
216 | |||
217 | if (BN_cmp(pub_key, max_pub_key) >= 0) | ||
218 | *flags |= DH_CHECK_PUBKEY_TOO_LARGE; | ||
219 | |||
220 | /* | ||
221 | * If dh->q is set, check that pub_key^q == 1 mod p | ||
222 | */ | ||
223 | |||
224 | if (dh->q != NULL) { | ||
225 | BIGNUM *residue; | ||
226 | |||
227 | if ((residue = BN_CTX_get(ctx)) == NULL) | ||
228 | goto err; | ||
229 | |||
230 | if (!BN_mod_exp_ct(residue, pub_key, dh->q, dh->p, ctx)) | ||
231 | goto err; | ||
232 | if (!BN_is_one(residue)) | ||
233 | *flags = DH_CHECK_PUBKEY_INVALID; | ||
234 | } | ||
235 | |||
236 | ok = 1; | ||
237 | |||
238 | err: | ||
239 | BN_CTX_end(ctx); | ||
240 | BN_CTX_free(ctx); | ||
241 | |||
242 | return ok; | ||
208 | } | 243 | } |