*Hugo Landau*
+ * When generating safe-prime DH parameters set the recommended private key
+ length equivalent to minimum key lengths as in RFC 7919.
+
+ *Tomáš Mráz*
+
OpenSSL 3.0
-----------
#include <openssl/bn.h>
#include <openssl/sha.h>
#include "crypto/dh.h"
+#include "crypto/security_bits.h"
#include "dh_local.h"
#ifndef FIPS_MODULE
goto err;
if (!BN_set_word(ret->params.g, g))
goto err;
+ /* We are using safe prime p, set key length equivalent to RFC 7919 */
+ ret->length = (2 * ossl_ifc_ffc_compute_security_bits(prime_len)
+ + 24) / 25 * 25;
ret->dirty_cnt++;
ok = 1;
err:
if (dh == NULL)
return NULL;
- ossl_ffc_named_group_set_pqg(&dh->params, group);
+ ossl_ffc_named_group_set(&dh->params, group);
dh->params.nid = ossl_ffc_named_group_get_uid(group);
dh->dirty_cnt++;
return dh;
dh->params.g)) != NULL) {
if (dh->params.q == NULL)
dh->params.q = (BIGNUM *)ossl_ffc_named_group_get_q(group);
- /* cache the nid */
+ /* cache the nid and default key length */
dh->params.nid = ossl_ffc_named_group_get_uid(group);
+ dh->params.keylength = ossl_ffc_named_group_get_keylength(group);
dh->dirty_cnt++;
}
}
if (prm->data_type != OSSL_PARAM_UTF8_STRING
|| prm->data == NULL
|| (group = ossl_ffc_name_to_dh_named_group(prm->data)) == NULL
- || !ossl_ffc_named_group_set_pqg(ffc, group))
+ || !ossl_ffc_named_group_set(ffc, group))
#endif
goto err;
}
#ifndef OPENSSL_NO_DH
-# define FFDHE(sz) { \
+# define FFDHE(sz, keylength) { \
SN_ffdhe##sz, NID_ffdhe##sz, \
sz, \
+ keylength, \
&ossl_bignum_ffdhe##sz##_p, &ossl_bignum_ffdhe##sz##_q, \
&ossl_bignum_const_2, \
}
-# define MODP(sz) { \
+# define MODP(sz, keylength) { \
SN_modp_##sz, NID_modp_##sz, \
sz, \
+ keylength, \
&ossl_bignum_modp_##sz##_p, &ossl_bignum_modp_##sz##_q, \
&ossl_bignum_const_2 \
}
# define RFC5114(name, uid, sz, tag) { \
name, uid, \
sz, \
+ 0, \
&ossl_bignum_dh##tag##_p, &ossl_bignum_dh##tag##_q, \
&ossl_bignum_dh##tag##_g \
}
#else
-# define FFDHE(sz) { SN_ffdhe##sz, NID_ffdhe##sz }
-# define MODP(sz) { SN_modp_##sz, NID_modp_##sz }
+# define FFDHE(sz, keylength) { SN_ffdhe##sz, NID_ffdhe##sz }
+# define MODP(sz, keylength) { SN_modp_##sz, NID_modp_##sz }
# define RFC5114(name, uid, sz, tag) { name, uid }
#endif
int uid;
#ifndef OPENSSL_NO_DH
int32_t nbits;
+ int keylength;
const BIGNUM *p;
const BIGNUM *q;
const BIGNUM *g;
#endif
};
+/*
+ * The private key length values are taken from RFC7919 with the values for
+ * MODP primes given the same lengths as the equivalent FFDHE.
+ * The MODP 1536 value is approximated.
+ */
static const DH_NAMED_GROUP dh_named_groups[] = {
- FFDHE(2048),
- FFDHE(3072),
- FFDHE(4096),
- FFDHE(6144),
- FFDHE(8192),
+ FFDHE(2048, 225),
+ FFDHE(3072, 275),
+ FFDHE(4096, 325),
+ FFDHE(6144, 375),
+ FFDHE(8192, 400),
#ifndef FIPS_MODULE
- MODP(1536),
+ MODP(1536, 200),
#endif
- MODP(2048),
- MODP(3072),
- MODP(4096),
- MODP(6144),
- MODP(8192),
+ MODP(2048, 225),
+ MODP(3072, 275),
+ MODP(4096, 325),
+ MODP(6144, 375),
+ MODP(8192, 400),
/*
* Additional dh named groups from RFC 5114 that have a different g.
* The uid can be any unique identifier.
}
#ifndef OPENSSL_NO_DH
+int ossl_ffc_named_group_get_keylength(const DH_NAMED_GROUP *group)
+{
+ if (group == NULL)
+ return 0;
+ return group->keylength;
+}
+
const BIGNUM *ossl_ffc_named_group_get_q(const DH_NAMED_GROUP *group)
{
if (group == NULL)
return group->q;
}
-int ossl_ffc_named_group_set_pqg(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group)
+int ossl_ffc_named_group_set(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group)
{
if (ffc == NULL || group == NULL)
return 0;
ossl_ffc_params_set0_pqg(ffc, (BIGNUM *)group->p, (BIGNUM *)group->q,
(BIGNUM *)group->g);
+ ffc->keylength = group->keylength;
/* flush the cached nid, The DH layer is responsible for caching */
ffc->nid = NID_undef;
int ret = 0, qbits = BN_num_bits(params->q);
BIGNUM *m, *two_powN = NULL;
- /* Deal with the edge case where the value of N is not set */
- if (N == 0)
- N = qbits;
+ /* Deal with the edge cases where the value of N and/or s is not set */
if (s == 0)
- s = N / 2;
+ goto err;
+ if (N == 0)
+ N = params->keylength ? params->keylength : 2 * s;
/* Step (2) : check range of N */
if (N < 2 * s || N > qbits)
*/
const char *mdname;
const char *mdprops;
+ /* Default key length for known named groups according to RFC7919 */
+ int keylength;
} FFC_PARAMS;
void ossl_ffc_params_init(FFC_PARAMS *params);
int ossl_ffc_named_group_get_uid(const DH_NAMED_GROUP *group);
const char *ossl_ffc_named_group_get_name(const DH_NAMED_GROUP *);
#ifndef OPENSSL_NO_DH
+int ossl_ffc_named_group_get_keylength(const DH_NAMED_GROUP *group);
const BIGNUM *ossl_ffc_named_group_get_q(const DH_NAMED_GROUP *group);
-int ossl_ffc_named_group_set_pqg(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group);
+int ossl_ffc_named_group_set(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group);
#endif
#endif /* OSSL_INTERNAL_FFC_H */
#include "testutil.h"
#include "internal/ffc.h"
+#include "crypto/security_bits.h"
#ifndef OPENSSL_NO_DSA
static const unsigned char dsa_2048_224_sha224_p[] = {
/* fail since N > len(q) */
if (!TEST_false(ossl_ffc_generate_private_key(ctx, params, N + 1, 112, priv)))
goto err;
+ /* s must be always set */
+ if (!TEST_false(ossl_ffc_generate_private_key(ctx, params, N, 0, priv)))
+ goto err;
/* pass since 2s <= N <= len(q) */
if (!TEST_true(ossl_ffc_generate_private_key(ctx, params, N, 112, priv)))
goto err;
goto err;
if (!TEST_true(ossl_ffc_validate_private_key(params->q, priv, &res)))
goto err;
-
- /* N and s are ignored in this case */
- if (!TEST_true(ossl_ffc_generate_private_key(ctx, params, 0, 0, priv)))
+ /* N is ignored in this case */
+ if (!TEST_true(ossl_ffc_generate_private_key(ctx, params, 0,
+ ossl_ifc_ffc_compute_security_bits(BN_num_bits(params->p)),
+ priv)))
goto err;
if (!TEST_true(ossl_ffc_validate_private_key(params->q, priv, &res)))
goto err;