diff options
Diffstat (limited to 'dh.c')
-rw-r--r-- | dh.c | 62 |
1 files changed, 32 insertions, 30 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: dh.c,v 1.53 2013/11/21 00:45:44 djm Exp $ */ | 1 | /* $OpenBSD: dh.c,v 1.55 2015/01/20 23:14:00 deraadt Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Niels Provos. All rights reserved. | 3 | * Copyright (c) 2000 Niels Provos. All rights reserved. |
4 | * | 4 | * |
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | #include "includes.h" | 26 | #include "includes.h" |
27 | 27 | ||
28 | #include <sys/param.h> | 28 | #include <sys/param.h> /* MIN */ |
29 | 29 | ||
30 | #include <openssl/bn.h> | 30 | #include <openssl/bn.h> |
31 | #include <openssl/dh.h> | 31 | #include <openssl/dh.h> |
@@ -34,11 +34,13 @@ | |||
34 | #include <stdio.h> | 34 | #include <stdio.h> |
35 | #include <stdlib.h> | 35 | #include <stdlib.h> |
36 | #include <string.h> | 36 | #include <string.h> |
37 | #include <limits.h> | ||
37 | 38 | ||
38 | #include "dh.h" | 39 | #include "dh.h" |
39 | #include "pathnames.h" | 40 | #include "pathnames.h" |
40 | #include "log.h" | 41 | #include "log.h" |
41 | #include "misc.h" | 42 | #include "misc.h" |
43 | #include "ssherr.h" | ||
42 | 44 | ||
43 | static int | 45 | static int |
44 | parse_prime(int linenum, char *line, struct dhgroup *dhg) | 46 | parse_prime(int linenum, char *line, struct dhgroup *dhg) |
@@ -107,10 +109,11 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) | |||
107 | goto fail; | 109 | goto fail; |
108 | } | 110 | } |
109 | 111 | ||
110 | if ((dhg->g = BN_new()) == NULL) | 112 | if ((dhg->g = BN_new()) == NULL || |
111 | fatal("parse_prime: BN_new failed"); | 113 | (dhg->p = BN_new()) == NULL) { |
112 | if ((dhg->p = BN_new()) == NULL) | 114 | error("parse_prime: BN_new failed"); |
113 | fatal("parse_prime: BN_new failed"); | 115 | goto fail; |
116 | } | ||
114 | if (BN_hex2bn(&dhg->g, gen) == 0) { | 117 | if (BN_hex2bn(&dhg->g, gen) == 0) { |
115 | error("moduli:%d: could not parse generator value", linenum); | 118 | error("moduli:%d: could not parse generator value", linenum); |
116 | goto fail; | 119 | goto fail; |
@@ -128,7 +131,6 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) | |||
128 | error("moduli:%d: generator is invalid", linenum); | 131 | error("moduli:%d: generator is invalid", linenum); |
129 | goto fail; | 132 | goto fail; |
130 | } | 133 | } |
131 | |||
132 | return 1; | 134 | return 1; |
133 | 135 | ||
134 | fail: | 136 | fail: |
@@ -137,7 +139,6 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) | |||
137 | if (dhg->p != NULL) | 139 | if (dhg->p != NULL) |
138 | BN_clear_free(dhg->p); | 140 | BN_clear_free(dhg->p); |
139 | dhg->g = dhg->p = NULL; | 141 | dhg->g = dhg->p = NULL; |
140 | error("Bad prime description in line %d", linenum); | ||
141 | return 0; | 142 | return 0; |
142 | } | 143 | } |
143 | 144 | ||
@@ -200,9 +201,11 @@ choose_dh(int min, int wantbits, int max) | |||
200 | break; | 201 | break; |
201 | } | 202 | } |
202 | fclose(f); | 203 | fclose(f); |
203 | if (linenum != which+1) | 204 | if (linenum != which+1) { |
204 | fatal("WARNING: line %d disappeared in %s, giving up", | 205 | logit("WARNING: line %d disappeared in %s, giving up", |
205 | which, _PATH_DH_PRIMES); | 206 | which, _PATH_DH_PRIMES); |
207 | return (dh_new_group14()); | ||
208 | } | ||
206 | 209 | ||
207 | return (dh_new_group(dhg.g, dhg.p)); | 210 | return (dh_new_group(dhg.g, dhg.p)); |
208 | } | 211 | } |
@@ -251,22 +254,22 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) | |||
251 | return 0; | 254 | return 0; |
252 | } | 255 | } |
253 | 256 | ||
254 | void | 257 | int |
255 | dh_gen_key(DH *dh, int need) | 258 | dh_gen_key(DH *dh, int need) |
256 | { | 259 | { |
257 | int pbits; | 260 | int pbits; |
258 | 261 | ||
259 | if (need <= 0) | 262 | if (need < 0 || dh->p == NULL || |
260 | fatal("%s: need <= 0", __func__); | 263 | (pbits = BN_num_bits(dh->p)) <= 0 || |
261 | if (dh->p == NULL) | 264 | need > INT_MAX / 2 || 2 * need >= pbits) |
262 | fatal("%s: dh->p == NULL", __func__); | 265 | return SSH_ERR_INVALID_ARGUMENT; |
263 | if ((pbits = BN_num_bits(dh->p)) <= 0) | ||
264 | fatal("%s: bits(p) <= 0", __func__); | ||
265 | dh->length = MIN(need * 2, pbits - 1); | 266 | dh->length = MIN(need * 2, pbits - 1); |
266 | if (DH_generate_key(dh) == 0) | 267 | if (DH_generate_key(dh) == 0 || |
267 | fatal("%s: key generation failed", __func__); | 268 | !dh_pub_is_valid(dh, dh->pub_key)) { |
268 | if (!dh_pub_is_valid(dh, dh->pub_key)) | 269 | BN_clear_free(dh->priv_key); |
269 | fatal("%s: generated invalid key", __func__); | 270 | return SSH_ERR_LIBCRYPTO_ERROR; |
271 | } | ||
272 | return 0; | ||
270 | } | 273 | } |
271 | 274 | ||
272 | DH * | 275 | DH * |
@@ -275,13 +278,12 @@ dh_new_group_asc(const char *gen, const char *modulus) | |||
275 | DH *dh; | 278 | DH *dh; |
276 | 279 | ||
277 | if ((dh = DH_new()) == NULL) | 280 | if ((dh = DH_new()) == NULL) |
278 | fatal("dh_new_group_asc: DH_new"); | 281 | return NULL; |
279 | 282 | if (BN_hex2bn(&dh->p, modulus) == 0 || | |
280 | if (BN_hex2bn(&dh->p, modulus) == 0) | 283 | BN_hex2bn(&dh->g, gen) == 0) { |
281 | fatal("BN_hex2bn p"); | 284 | DH_free(dh); |
282 | if (BN_hex2bn(&dh->g, gen) == 0) | 285 | return NULL; |
283 | fatal("BN_hex2bn g"); | 286 | } |
284 | |||
285 | return (dh); | 287 | return (dh); |
286 | } | 288 | } |
287 | 289 | ||
@@ -296,7 +298,7 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus) | |||
296 | DH *dh; | 298 | DH *dh; |
297 | 299 | ||
298 | if ((dh = DH_new()) == NULL) | 300 | if ((dh = DH_new()) == NULL) |
299 | fatal("dh_new_group: DH_new"); | 301 | return NULL; |
300 | dh->p = modulus; | 302 | dh->p = modulus; |
301 | dh->g = gen; | 303 | dh->g = gen; |
302 | 304 | ||
@@ -344,7 +346,7 @@ dh_new_group14(void) | |||
344 | * from RFC4419 section 3. | 346 | * from RFC4419 section 3. |
345 | */ | 347 | */ |
346 | 348 | ||
347 | int | 349 | u_int |
348 | dh_estimate(int bits) | 350 | dh_estimate(int bits) |
349 | { | 351 | { |
350 | if (bits <= 112) | 352 | if (bits <= 112) |