summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2021-11-29 20:02:14 +0000
committertb <>2021-11-29 20:02:14 +0000
commitbd7738409d496371bd505cd5dbdb2a5675c5665f (patch)
treea1b7be0a5f53527fff389034167d093418d38eaf
parent33c4b670470691ed907e24ba05f290f1e366bd59 (diff)
downloadopenbsd-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
-rw-r--r--src/lib/libcrypto/dh/dh_check.c71
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
189int 189int
190DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) 190DH_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}