diff options
author | djm@openbsd.org <djm@openbsd.org> | 2018-09-13 02:08:33 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2018-09-13 12:12:33 +1000 |
commit | 482d23bcacdd3664f21cc82a5135f66fc598275f (patch) | |
tree | 362f697a94da0a765d1dabcfbf33370b2a4df121 /dh.c | |
parent | d70d061828730a56636ab6f1f24fe4a8ccefcfc1 (diff) |
upstream: hold our collective noses and use the openssl-1.1.x API in
OpenSSH; feedback and ok tb@ jsing@ markus@
OpenBSD-Commit-ID: cacbcac87ce5da0d3ca7ef1b38a6f7fb349e4417
Diffstat (limited to 'dh.c')
-rw-r--r-- | dh.c | 60 |
1 files changed, 37 insertions, 23 deletions
@@ -216,14 +216,17 @@ choose_dh(int min, int wantbits, int max) | |||
216 | /* diffie-hellman-groupN-sha1 */ | 216 | /* diffie-hellman-groupN-sha1 */ |
217 | 217 | ||
218 | int | 218 | int |
219 | dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) | 219 | dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub) |
220 | { | 220 | { |
221 | int i; | 221 | int i; |
222 | int n = BN_num_bits(dh_pub); | 222 | int n = BN_num_bits(dh_pub); |
223 | int bits_set = 0; | 223 | int bits_set = 0; |
224 | BIGNUM *tmp; | 224 | BIGNUM *tmp; |
225 | const BIGNUM *dh_p; | ||
225 | 226 | ||
226 | if (dh_pub->neg) { | 227 | DH_get0_pqg(dh, &dh_p, NULL, NULL); |
228 | |||
229 | if (BN_is_negative(dh_pub)) { | ||
227 | logit("invalid public DH value: negative"); | 230 | logit("invalid public DH value: negative"); |
228 | return 0; | 231 | return 0; |
229 | } | 232 | } |
@@ -236,7 +239,7 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) | |||
236 | error("%s: BN_new failed", __func__); | 239 | error("%s: BN_new failed", __func__); |
237 | return 0; | 240 | return 0; |
238 | } | 241 | } |
239 | if (!BN_sub(tmp, dh->p, BN_value_one()) || | 242 | if (!BN_sub(tmp, dh_p, BN_value_one()) || |
240 | BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ | 243 | BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ |
241 | BN_clear_free(tmp); | 244 | BN_clear_free(tmp); |
242 | logit("invalid public DH value: >= p-1"); | 245 | logit("invalid public DH value: >= p-1"); |
@@ -247,14 +250,14 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) | |||
247 | for (i = 0; i <= n; i++) | 250 | for (i = 0; i <= n; i++) |
248 | if (BN_is_bit_set(dh_pub, i)) | 251 | if (BN_is_bit_set(dh_pub, i)) |
249 | bits_set++; | 252 | bits_set++; |
250 | debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p)); | 253 | debug2("bits set: %d/%d", bits_set, BN_num_bits(dh_p)); |
251 | 254 | ||
252 | /* | 255 | /* |
253 | * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial | 256 | * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial |
254 | */ | 257 | */ |
255 | if (bits_set < 4) { | 258 | if (bits_set < 4) { |
256 | logit("invalid public DH value (%d/%d)", | 259 | logit("invalid public DH value (%d/%d)", |
257 | bits_set, BN_num_bits(dh->p)); | 260 | bits_set, BN_num_bits(dh_p)); |
258 | return 0; | 261 | return 0; |
259 | } | 262 | } |
260 | return 1; | 263 | return 1; |
@@ -264,9 +267,12 @@ int | |||
264 | dh_gen_key(DH *dh, int need) | 267 | dh_gen_key(DH *dh, int need) |
265 | { | 268 | { |
266 | int pbits; | 269 | int pbits; |
270 | const BIGNUM *dh_p, *pub_key; | ||
271 | |||
272 | DH_get0_pqg(dh, &dh_p, NULL, NULL); | ||
267 | 273 | ||
268 | if (need < 0 || dh->p == NULL || | 274 | if (need < 0 || dh_p == NULL || |
269 | (pbits = BN_num_bits(dh->p)) <= 0 || | 275 | (pbits = BN_num_bits(dh_p)) <= 0 || |
270 | need > INT_MAX / 2 || 2 * need > pbits) | 276 | need > INT_MAX / 2 || 2 * need > pbits) |
271 | return SSH_ERR_INVALID_ARGUMENT; | 277 | return SSH_ERR_INVALID_ARGUMENT; |
272 | if (need < 256) | 278 | if (need < 256) |
@@ -275,13 +281,14 @@ dh_gen_key(DH *dh, int need) | |||
275 | * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)), | 281 | * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)), |
276 | * so double requested need here. | 282 | * so double requested need here. |
277 | */ | 283 | */ |
278 | dh->length = MINIMUM(need * 2, pbits - 1); | 284 | if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1))) |
279 | if (DH_generate_key(dh) == 0 || | ||
280 | !dh_pub_is_valid(dh, dh->pub_key)) { | ||
281 | BN_clear_free(dh->priv_key); | ||
282 | dh->priv_key = NULL; | ||
283 | return SSH_ERR_LIBCRYPTO_ERROR; | 285 | return SSH_ERR_LIBCRYPTO_ERROR; |
284 | } | 286 | |
287 | if (DH_generate_key(dh) == 0) | ||
288 | return SSH_ERR_LIBCRYPTO_ERROR; | ||
289 | DH_get0_key(dh, &pub_key, NULL); | ||
290 | if (!dh_pub_is_valid(dh, pub_key)) | ||
291 | return SSH_ERR_INVALID_FORMAT; | ||
285 | return 0; | 292 | return 0; |
286 | } | 293 | } |
287 | 294 | ||
@@ -289,22 +296,27 @@ DH * | |||
289 | dh_new_group_asc(const char *gen, const char *modulus) | 296 | dh_new_group_asc(const char *gen, const char *modulus) |
290 | { | 297 | { |
291 | DH *dh; | 298 | DH *dh; |
299 | BIGNUM *dh_p = NULL, *dh_g = NULL; | ||
292 | 300 | ||
293 | if ((dh = DH_new()) == NULL) | 301 | if ((dh = DH_new()) == NULL) |
294 | return NULL; | 302 | return NULL; |
295 | if (BN_hex2bn(&dh->p, modulus) == 0 || | 303 | if (BN_hex2bn(&dh_p, modulus) == 0 || |
296 | BN_hex2bn(&dh->g, gen) == 0) { | 304 | BN_hex2bn(&dh_g, gen) == 0) |
297 | DH_free(dh); | 305 | goto fail; |
298 | return NULL; | 306 | if (!DH_set0_pqg(dh, dh_p, NULL, dh_g)) |
299 | } | 307 | goto fail; |
300 | return (dh); | 308 | return dh; |
309 | fail: | ||
310 | DH_free(dh); | ||
311 | BN_clear_free(dh_p); | ||
312 | BN_clear_free(dh_g); | ||
313 | return NULL; | ||
301 | } | 314 | } |
302 | 315 | ||
303 | /* | 316 | /* |
304 | * This just returns the group, we still need to generate the exchange | 317 | * This just returns the group, we still need to generate the exchange |
305 | * value. | 318 | * value. |
306 | */ | 319 | */ |
307 | |||
308 | DH * | 320 | DH * |
309 | dh_new_group(BIGNUM *gen, BIGNUM *modulus) | 321 | dh_new_group(BIGNUM *gen, BIGNUM *modulus) |
310 | { | 322 | { |
@@ -312,10 +324,12 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus) | |||
312 | 324 | ||
313 | if ((dh = DH_new()) == NULL) | 325 | if ((dh = DH_new()) == NULL) |
314 | return NULL; | 326 | return NULL; |
315 | dh->p = modulus; | 327 | if (!DH_set0_pqg(dh, modulus, NULL, gen)) { |
316 | dh->g = gen; | 328 | DH_free(dh); |
329 | return NULL; | ||
330 | } | ||
317 | 331 | ||
318 | return (dh); | 332 | return dh; |
319 | } | 333 | } |
320 | 334 | ||
321 | /* rfc2409 "Second Oakley Group" (1024 bits) */ | 335 | /* rfc2409 "Second Oakley Group" (1024 bits) */ |