-/* $OpenBSD: dh.c,v 1.49 2011/12/07 05:44:38 djm Exp $ */
+/* $OpenBSD: dh.c,v 1.53 2013/11/21 00:45:44 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
*
const char *errstr = NULL;
long long n;
+ dhg->p = dhg->g = NULL;
cp = line;
if ((arg = strdelim(&cp)) == NULL)
return 0;
/* time */
if (cp == NULL || *arg == '\0')
- goto fail;
+ goto truncated;
arg = strsep(&cp, " "); /* type */
if (cp == NULL || *arg == '\0')
- goto fail;
+ goto truncated;
/* Ensure this is a safe prime */
n = strtonum(arg, 0, 5, &errstr);
- if (errstr != NULL || n != MODULI_TYPE_SAFE)
+ if (errstr != NULL || n != MODULI_TYPE_SAFE) {
+ error("moduli:%d: type is not %d", linenum, MODULI_TYPE_SAFE);
goto fail;
+ }
arg = strsep(&cp, " "); /* tests */
if (cp == NULL || *arg == '\0')
- goto fail;
+ goto truncated;
/* Ensure prime has been tested and is not composite */
n = strtonum(arg, 0, 0x1f, &errstr);
if (errstr != NULL ||
- (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE))
+ (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) {
+ error("moduli:%d: invalid moduli tests flag", linenum);
goto fail;
+ }
arg = strsep(&cp, " "); /* tries */
if (cp == NULL || *arg == '\0')
- goto fail;
+ goto truncated;
n = strtonum(arg, 0, 1<<30, &errstr);
- if (errstr != NULL || n == 0)
+ if (errstr != NULL || n == 0) {
+ error("moduli:%d: invalid primality trial count", linenum);
goto fail;
+ }
strsize = strsep(&cp, " "); /* size */
if (cp == NULL || *strsize == '\0' ||
(dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
- errstr)
+ errstr) {
+ error("moduli:%d: invalid prime length", linenum);
goto fail;
+ }
/* The whole group is one bit larger */
dhg->size++;
gen = strsep(&cp, " "); /* gen */
if (cp == NULL || *gen == '\0')
- goto fail;
+ goto truncated;
prime = strsep(&cp, " "); /* prime */
- if (cp != NULL || *prime == '\0')
+ if (cp != NULL || *prime == '\0') {
+ truncated:
+ error("moduli:%d: truncated", linenum);
goto fail;
+ }
if ((dhg->g = BN_new()) == NULL)
fatal("parse_prime: BN_new failed");
if ((dhg->p = BN_new()) == NULL)
fatal("parse_prime: BN_new failed");
- if (BN_hex2bn(&dhg->g, gen) == 0)
- goto failclean;
-
- if (BN_hex2bn(&dhg->p, prime) == 0)
- goto failclean;
-
- if (BN_num_bits(dhg->p) != dhg->size)
- goto failclean;
-
- if (BN_is_zero(dhg->g) || BN_is_one(dhg->g))
- goto failclean;
+ if (BN_hex2bn(&dhg->g, gen) == 0) {
+ error("moduli:%d: could not parse generator value", linenum);
+ goto fail;
+ }
+ if (BN_hex2bn(&dhg->p, prime) == 0) {
+ error("moduli:%d: could not parse prime value", linenum);
+ goto fail;
+ }
+ if (BN_num_bits(dhg->p) != dhg->size) {
+ error("moduli:%d: prime has wrong size: actual %d listed %d",
+ linenum, BN_num_bits(dhg->p), dhg->size - 1);
+ goto fail;
+ }
+ if (BN_cmp(dhg->g, BN_value_one()) <= 0) {
+ error("moduli:%d: generator is invalid", linenum);
+ goto fail;
+ }
- return (1);
+ return 1;
- failclean:
- BN_clear_free(dhg->g);
- BN_clear_free(dhg->p);
fail:
+ if (dhg->g != NULL)
+ BN_clear_free(dhg->g);
+ if (dhg->p != NULL)
+ BN_clear_free(dhg->p);
+ dhg->g = dhg->p = NULL;
error("Bad prime description in line %d", linenum);
- return (0);
+ return 0;
}
DH *
void
dh_gen_key(DH *dh, int need)
{
- int i, bits_set, tries = 0;
+ int pbits;
- if (need < 0)
- fatal("dh_gen_key: need < 0");
+ if (need <= 0)
+ fatal("%s: need <= 0", __func__);
if (dh->p == NULL)
- fatal("dh_gen_key: dh->p == NULL");
- if (need > INT_MAX / 2 || 2 * need >= BN_num_bits(dh->p))
- fatal("dh_gen_key: group too small: %d (2*need %d)",
- BN_num_bits(dh->p), 2*need);
- do {
- if (dh->priv_key != NULL)
- BN_clear_free(dh->priv_key);
- if ((dh->priv_key = BN_new()) == NULL)
- fatal("dh_gen_key: BN_new failed");
- /* generate a 2*need bits random private exponent */
- if (!BN_rand(dh->priv_key, 2*need, 0, 0))
- fatal("dh_gen_key: BN_rand failed");
- if (DH_generate_key(dh) == 0)
- fatal("DH_generate_key");
- for (i = 0, bits_set = 0; i <= BN_num_bits(dh->priv_key); i++)
- if (BN_is_bit_set(dh->priv_key, i))
- bits_set++;
- debug2("dh_gen_key: priv key bits set: %d/%d",
- bits_set, BN_num_bits(dh->priv_key));
- if (tries++ > 10)
- fatal("dh_gen_key: too many bad keys: giving up");
- } while (!dh_pub_is_valid(dh, dh->pub_key));
+ fatal("%s: dh->p == NULL", __func__);
+ if ((pbits = BN_num_bits(dh->p)) <= 0)
+ fatal("%s: bits(p) <= 0", __func__);
+ dh->length = MIN(need * 2, pbits - 1);
+ if (DH_generate_key(dh) == 0)
+ fatal("%s: key generation failed", __func__);
+ if (!dh_pub_is_valid(dh, dh->pub_key))
+ fatal("%s: generated invalid key", __func__);
}
DH *
/*
* Estimates the group order for a Diffie-Hellman group that has an
- * attack complexity approximately the same as O(2**bits). Estimate
- * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
+ * attack complexity approximately the same as O(2**bits).
+ * Values from NIST Special Publication 800-57: Recommendation for Key
+ * Management Part 1 (rev 3) limited by the recommended maximum value
+ * from RFC4419 section 3.
*/
int
dh_estimate(int bits)
{
-
+ if (bits <= 112)
+ return 2048;
if (bits <= 128)
- return (1024); /* O(2**86) */
+ return 3072;
if (bits <= 192)
- return (2048); /* O(2**116) */
- return (4096); /* O(2**156) */
+ return 7680;
+ return 8192;
}