Add FFC param/key generation

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10909)
This commit is contained in:
Shane Lontis 2020-02-06 22:28:36 +10:00
parent 104a733df6
commit f11f86f6ec
18 changed files with 1442 additions and 705 deletions

View File

@ -85,6 +85,7 @@ DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length)
FFC_PARAMS *params;
int_dhx942_dh *dhx = NULL;
DH *dh = NULL;
dh = DH_new();
if (dh == NULL)
return NULL;

View File

@ -15,19 +15,88 @@
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include "crypto/dh.h"
#include "dh_local.h"
#ifndef FIPS_MODE
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
BN_GENCB *cb);
#endif /* FIPS_MODE */
/*
* TODO(3.0): keygen should be able to use this method to do a FIPS186-4 style
* paramgen.
*/
int dh_generate_ffc_parameters(OPENSSL_CTX *libctx, DH *dh, int bits,
int qbits, int gindex, BN_GENCB *cb)
{
int ret, res;
if (qbits <= 0) {
const EVP_MD *evpmd = bits >= 2048 ? EVP_sha256() : EVP_sha1();
qbits = EVP_MD_size(evpmd) * 8;
}
dh->params.gindex = gindex;
ret = ffc_params_FIPS186_4_generate(libctx, &dh->params, FFC_PARAM_TYPE_DH,
bits, qbits, NULL, &res, cb);
if (ret > 0)
dh->dirty_cnt++;
return ret;
}
int DH_generate_parameters_ex(DH *ret, int prime_len, int generator,
BN_GENCB *cb)
{
#ifdef FIPS_MODE
/*
* Just choose an approved safe prime group.
* The alternative to this is to generate FIPS186-4 domain parameters i.e.
* return dh_generate_ffc_parameters(ret, prime_len, -1, -1, cb);
* As the FIPS186-4 generated params are for backwards compatability,
* the safe prime group should be used as the default.
*/
DH *dh = NULL;
int ok = 0, nid;
if (generator != 2)
return 0;
switch (prime_len) {
case 2048:
nid = NID_ffdhe2048;
break;
case 3072:
nid = NID_ffdhe3072;
break;
case 4096:
nid = NID_ffdhe4096;
break;
case 6144:
nid = NID_ffdhe6144;
break;
case 8192:
nid = NID_ffdhe8192;
break;
/* unsupported prime_len */
default:
return 0;
}
dh = DH_new_by_nid(nid);
if (dh != NULL && ffc_params_copy(&ret->params, &dh->params)) {
ok = 1;
ret->dirty_cnt++;
}
DH_free(dh);
return ok;
#else
if (ret->meth->generate_params)
return ret->meth->generate_params(ret, prime_len, generator, cb);
return dh_builtin_genparams(ret, prime_len, generator, cb);
#endif /* FIPS_MODE */
}
#ifndef FIPS_MODE
/*-
* We generate DH parameters as follows
* find a prime p which is prime_len bits long,
@ -133,3 +202,4 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
BN_CTX_free(ctx);
return ok;
}
#endif /* FIPS_MODE */

View File

@ -1,5 +1,5 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -13,10 +13,7 @@
#include "crypto/bn.h"
#include "crypto/dh.h"
#ifndef FIPS_MODE
static int generate_key(DH *dh);
#endif /* FIPS_MODE */
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
@ -123,11 +120,7 @@ int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh)
static DH_METHOD dh_ossl = {
"OpenSSL DH Method",
#ifndef FIPS_MODE
generate_key,
#else
NULL, /* TODO(3.0) : solve this in a keygen related PR */
#endif
compute_key,
dh_bn_mod_exp,
dh_init,
@ -160,6 +153,7 @@ static int dh_init(DH *dh)
{
dh->flags |= DH_FLAG_CACHE_MONT_P;
ffc_params_init(&dh->params);
dh->dirty_cnt++;
return 1;
}
@ -170,7 +164,6 @@ static int dh_finish(DH *dh)
}
#ifndef FIPS_MODE
void DH_set_default_method(const DH_METHOD *meth)
{
default_DH_method = meth;
@ -180,27 +173,30 @@ int DH_generate_key(DH *dh)
{
return dh->meth->generate_key(dh);
}
#endif /* FIPS_MODE */
static int generate_key(DH *dh)
static int dh_generate_key(OPENSSL_CTX *libctx, DH *dh)
{
int ok = 0;
int generate_new_key = 0;
#ifndef FIPS_MODE
unsigned l;
#endif
BN_CTX *ctx = NULL;
BN_MONT_CTX *mont = NULL;
BIGNUM *pub_key = NULL, *priv_key = NULL;
if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) {
DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE);
DHerr(0, DH_R_MODULUS_TOO_LARGE);
return 0;
}
if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) {
DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_SMALL);
DHerr(0, DH_R_MODULUS_TOO_SMALL);
return 0;
}
ctx = BN_CTX_new();
ctx = BN_CTX_new_ex(libctx);
if (ctx == NULL)
goto err;
@ -227,25 +223,52 @@ static int generate_key(DH *dh)
}
if (generate_new_key) {
if (dh->params.q != NULL) {
do {
if (!BN_priv_rand_range(priv_key, dh->params.q))
goto err;
}
while (BN_is_zero(priv_key) || BN_is_one(priv_key));
} else {
/* secret exponent length */
l = dh->length ? dh->length : BN_num_bits(dh->params.p) - 1;
if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
goto err;
/* Is it an approved safe prime ?*/
if (DH_get_nid(dh) != NID_undef) {
/*
* We handle just one known case where g is a quadratic non-residue:
* for g = 2: p % 8 == 3
* The safe prime group code sets N = 2*s
* (where s = max security strength supported).
* N = dh->length (N = maximum bit length of private key)
*/
if (BN_is_word(dh->params.g, DH_GENERATOR_2)
&& !BN_is_bit_set(dh->params.p, 2)) {
/* clear bit 0, since it won't be a secret anyway */
if (!BN_clear_bit(priv_key, 0))
if (dh->length == 0
|| dh->params.q == NULL
|| dh->length > BN_num_bits(dh->params.q))
goto err;
if (!ffc_generate_private_key(ctx, &dh->params, dh->length,
dh->length / 2, priv_key))
goto err;
} else {
#ifdef FIPS_MODE
if (dh->params.q == NULL)
goto err;
#else
if (dh->params.q == NULL) {
/* secret exponent length */
l = dh->length ? dh->length : BN_num_bits(dh->params.p) - 1;
if (!BN_priv_rand_ex(priv_key, l, BN_RAND_TOP_ONE,
BN_RAND_BOTTOM_ANY, ctx))
goto err;
/*
* We handle just one known case where g is a quadratic non-residue:
* for g = 2: p % 8 == 3
*/
if (BN_is_word(dh->params.g, DH_GENERATOR_2)
&& !BN_is_bit_set(dh->params.p, 2)) {
/* clear bit 0, since it won't be a secret anyway */
if (!BN_clear_bit(priv_key, 0))
goto err;
}
} else
#endif
{
/*
* For FFC FIPS 186-4 keygen
* security strength s = 112,
* Max Private key size N = len(q)
*/
if (!ffc_generate_private_key(ctx, &dh->params,
BN_num_bits(dh->params.q), 112,
priv_key))
goto err;
}
}
@ -258,6 +281,7 @@ static int generate_key(DH *dh)
goto err;
BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
/* pub_key = g^priv_key mod p */
if (!dh->meth->bn_mod_exp(dh, pub_key, dh->params.g, prk, dh->params.p,
ctx, mont)) {
BN_clear_free(prk);
@ -273,7 +297,7 @@ static int generate_key(DH *dh)
ok = 1;
err:
if (ok != 1)
DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB);
DHerr(0, ERR_R_BN_LIB);
if (pub_key != dh->pub_key)
BN_free(pub_key);
@ -283,6 +307,10 @@ static int generate_key(DH *dh)
return ok;
}
static int generate_key(DH *dh)
{
return dh_generate_key(NULL, dh);
}
int dh_buf2key(DH *dh, const unsigned char *buf, size_t len)
{
@ -346,4 +374,3 @@ size_t dh_key2buf(const DH *dh, unsigned char **pbuf_out)
*pbuf_out = pbuf;
return p_size;
}
#endif /* FIPS_MODE */

View File

@ -24,7 +24,7 @@ typedef struct {
/* Parameter gen parameters */
int prime_len;
int generator;
int use_dsa;
int paramgen_type;
int subprime_len;
int pad;
/* message digest used for parameter generation */
@ -69,6 +69,7 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx)
static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
{
DH_PKEY_CTX *dctx = ctx->data;
if (dctx != NULL) {
OPENSSL_free(dctx->kdf_ukm);
ASN1_OBJECT_free(dctx->kdf_oid);
@ -88,7 +89,7 @@ static int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
dctx->prime_len = sctx->prime_len;
dctx->subprime_len = sctx->subprime_len;
dctx->generator = sctx->generator;
dctx->use_dsa = sctx->use_dsa;
dctx->paramgen_type = sctx->paramgen_type;
dctx->pad = sctx->pad;
dctx->md = sctx->md;
dctx->rfc5114_param = sctx->rfc5114_param;
@ -120,7 +121,7 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 1;
case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
if (dctx->use_dsa == 0)
if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR)
return -2;
dctx->subprime_len = p1;
return 1;
@ -130,20 +131,20 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 1;
case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
if (dctx->use_dsa)
if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR)
return -2;
dctx->generator = p1;
return 1;
case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
#ifdef OPENSSL_NO_DSA
if (p1 != 0)
if (p1 != DH_PARAMGEN_TYPE_GENERATOR)
return -2;
#else
if (p1 < 0 || p1 > 2)
return -2;
#endif
dctx->use_dsa = p1;
dctx->paramgen_type = p1;
return 1;
case EVP_PKEY_CTRL_DH_RFC5114:
@ -271,33 +272,22 @@ static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
return -2;
}
#ifndef OPENSSL_NO_DSA
extern int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
const EVP_MD *evpmd,
const unsigned char *seed_in, size_t seed_len,
unsigned char *seed_out, int *counter_ret,
unsigned long *h_ret, BN_GENCB *cb);
extern int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
const EVP_MD *evpmd,
const unsigned char *seed_in,
size_t seed_len, int idx,
unsigned char *seed_out, int *counter_ret,
unsigned long *h_ret, BN_GENCB *cb);
static DSA *dsa_dh_generate(DH_PKEY_CTX *dctx, BN_GENCB *pcb)
static DH *ffc_params_generate(OPENSSL_CTX *libctx, DH_PKEY_CTX *dctx,
BN_GENCB *pcb)
{
DSA *ret;
DH *ret;
int rv = 0;
int res;
int prime_len = dctx->prime_len;
int subprime_len = dctx->subprime_len;
const EVP_MD *md = dctx->md;
if (dctx->use_dsa > 2)
if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4)
return NULL;
ret = DSA_new();
ret = DH_new();
if (ret == NULL)
return NULL;
if (subprime_len == -1) {
if (prime_len >= 2048)
subprime_len = 256;
@ -310,22 +300,29 @@ static DSA *dsa_dh_generate(DH_PKEY_CTX *dctx, BN_GENCB *pcb)
else
md = EVP_sha1();
}
if (dctx->use_dsa == 1)
rv = dsa_builtin_paramgen(ret, prime_len, subprime_len, md,
NULL, 0, NULL, NULL, NULL, pcb);
else if (dctx->use_dsa == 2)
rv = dsa_builtin_paramgen2(ret, prime_len, subprime_len, md,
NULL, 0, -1, NULL, NULL, NULL, pcb);
# ifndef FIPS_MODE
if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2)
rv = ffc_params_FIPS186_2_generate(libctx, &ret->params,
FFC_PARAM_TYPE_DH,
prime_len, subprime_len, md, &res,
pcb);
else
# endif
/* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */
if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2)
rv = ffc_params_FIPS186_4_generate(libctx, &ret->params,
FFC_PARAM_TYPE_DH,
prime_len, subprime_len, md, &res,
pcb);
if (rv <= 0) {
DSA_free(ret);
DH_free(ret);
return NULL;
}
return ret;
}
#endif
static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey)
{
DH *dh = NULL;
DH_PKEY_CTX *dctx = ctx->data;
@ -372,22 +369,17 @@ static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
return 0;
evp_pkey_set_cb_translate(pcb, ctx);
}
#ifndef OPENSSL_NO_DSA
if (dctx->use_dsa) {
DSA *dsa_dh;
dsa_dh = dsa_dh_generate(dctx, pcb);
# ifdef FIPS_MODE
dctx->paramgen_type = DH_PARAMGEN_TYPE_FIPS_186_4;
# endif /* FIPS_MODE */
if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) {
dh = ffc_params_generate(NULL, dctx, pcb);
BN_GENCB_free(pcb);
if (dsa_dh == NULL)
return 0;
dh = DSA_dup_DH(dsa_dh);
DSA_free(dsa_dh);
if (!dh)
if (dh == NULL)
return 0;
EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
return 1;
}
#endif
dh = DH_new();
if (dh == NULL) {
BN_GENCB_free(pcb);

View File

@ -1,5 +1,5 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -7,13 +7,6 @@
* https://www.openssl.org/source/license.html
*/
/*
* Parameter generation follows the updated Appendix 2.2 for FIPS PUB 186,
* also Appendix 2.2 of FIPS PUB 186-1 (i.e. use SHA as defined in FIPS PUB
* 180-1)
*/
#define xxxHASH EVP_sha1()
#include <openssl/opensslconf.h>
#include <stdio.h>
#include "internal/cryptlib.h"
@ -21,598 +14,79 @@
#include <openssl/bn.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include "crypto/dsa.h"
#include "dsa_local.h"
int DSA_generate_parameters_ex(DSA *ret, int bits,
int dsa_generate_ffc_parameters(OPENSSL_CTX *libctx, DSA *dsa, int type,
int pbits, int qbits, int gindex,
BN_GENCB *cb)
{
int ret = 0, res;
if (qbits <= 0) {
const EVP_MD *evpmd = pbits >= 2048 ? EVP_sha256() : EVP_sha1();
qbits = EVP_MD_size(evpmd) * 8;
}
dsa->params.gindex = gindex;
#ifndef FIPS_MODE
if (type == DSA_PARAMGEN_TYPE_FIPS_186_2)
ret = ffc_params_FIPS186_2_generate(libctx, &dsa->params,
FFC_PARAM_TYPE_DSA,
pbits, qbits, NULL, &res, cb);
else
#endif
ret = ffc_params_FIPS186_4_generate(libctx, &dsa->params,
FFC_PARAM_TYPE_DSA,
pbits, qbits, NULL, &res, cb);
if (ret > 0)
dsa->dirty_cnt++;
return ret;
}
int dsa_generate_parameters_ctx(OPENSSL_CTX *libctx, DSA *dsa, int bits,
const unsigned char *seed_in, int seed_len,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb)
{
#ifndef FIPS_MODE
if (dsa->meth->dsa_paramgen)
return dsa->meth->dsa_paramgen(dsa, bits, seed_in, seed_len,
counter_ret, h_ret, cb);
#endif
if (seed_in != NULL
&& !ffc_params_set_validate_params(&dsa->params, seed_in, seed_len, -1))
return 0;
#ifndef FIPS_MODE
/* The old code used FIPS 186-2 DSA Parameter generation */
if (bits <= 1024 && seed_len == 20) {
if (!dsa_generate_ffc_parameters(libctx, dsa,
DSA_PARAMGEN_TYPE_FIPS_186_2,
bits, 160, -1, cb))
return 0;
} else
#endif
{
if (!dsa_generate_ffc_parameters(libctx, dsa,
DSA_PARAMGEN_TYPE_FIPS_186_4,
bits, -1, -1, cb))
return 0;
}
if (counter_ret != NULL)
*counter_ret = dsa->params.pcounter;
if (h_ret != NULL)
*h_ret = dsa->params.h;
return 1;
}
int DSA_generate_parameters_ex(DSA *dsa, int bits,
const unsigned char *seed_in, int seed_len,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb)
{
if (ret->meth->dsa_paramgen)
return ret->meth->dsa_paramgen(ret, bits, seed_in, seed_len,
return dsa_generate_parameters_ctx(NULL, dsa, bits,
seed_in, seed_len,
counter_ret, h_ret, cb);
else {
const EVP_MD *evpmd = bits >= 2048 ? EVP_sha256() : EVP_sha1();
size_t qbits = EVP_MD_size(evpmd) * 8;
return dsa_builtin_paramgen(ret, bits, qbits, evpmd,
seed_in, seed_len, NULL, counter_ret,
h_ret, cb);
}
}
int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
const EVP_MD *evpmd, const unsigned char *seed_in,
size_t seed_len, unsigned char *seed_out,
int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
{
int ok = 0;
unsigned char seed[SHA256_DIGEST_LENGTH];
unsigned char md[SHA256_DIGEST_LENGTH];
unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH];
BIGNUM *r0, *W, *X, *c, *test;
BIGNUM *g = NULL, *q = NULL, *p = NULL;
BN_MONT_CTX *mont = NULL;
int i, k, n = 0, m = 0, qsize = qbits >> 3;
int counter = 0;
int r = 0;
BN_CTX *ctx = NULL;
unsigned int h = 2;
if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH &&
qsize != SHA256_DIGEST_LENGTH)
/* invalid q size */
return 0;
if (evpmd == NULL) {
if (qsize == SHA_DIGEST_LENGTH)
evpmd = EVP_sha1();
else if (qsize == SHA224_DIGEST_LENGTH)
evpmd = EVP_sha224();
else
evpmd = EVP_sha256();
} else {
qsize = EVP_MD_size(evpmd);
}
if (bits < 512)
bits = 512;
bits = (bits + 63) / 64 * 64;
if (seed_in != NULL) {
if (seed_len < (size_t)qsize) {
DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_SEED_LEN_SMALL);
return 0;
}
if (seed_len > (size_t)qsize) {
/* Only consume as much seed as is expected. */
seed_len = qsize;
}
memcpy(seed, seed_in, seed_len);
}
if ((mont = BN_MONT_CTX_new()) == NULL)
goto err;
if ((ctx = BN_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
r0 = BN_CTX_get(ctx);
g = BN_CTX_get(ctx);
W = BN_CTX_get(ctx);
q = BN_CTX_get(ctx);
X = BN_CTX_get(ctx);
c = BN_CTX_get(ctx);
p = BN_CTX_get(ctx);
test = BN_CTX_get(ctx);
if (test == NULL)
goto err;
if (!BN_lshift(test, BN_value_one(), bits - 1))
goto err;
for (;;) {
for (;;) { /* find q */
int use_random_seed = (seed_in == NULL);
/* step 1 */
if (!BN_GENCB_call(cb, 0, m++))
goto err;
if (use_random_seed) {
if (RAND_bytes(seed, qsize) <= 0)
goto err;
} else {
/* If we come back through, use random seed next time. */
seed_in = NULL;
}
memcpy(buf, seed, qsize);
memcpy(buf2, seed, qsize);
/* precompute "SEED + 1" for step 7: */
for (i = qsize - 1; i >= 0; i--) {
buf[i]++;
if (buf[i] != 0)
break;
}
/* step 2 */
if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL))
goto err;
if (!EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL))
goto err;
for (i = 0; i < qsize; i++)
md[i] ^= buf2[i];
/* step 3 */
md[0] |= 0x80;
md[qsize - 1] |= 0x01;
if (!BN_bin2bn(md, qsize, q))
goto err;
/* step 4 */
r = BN_check_prime(q, ctx, cb);
if (r > 0)
break;
if (r != 0)
goto err;
/* do a callback call */
/* step 5 */
}
if (!BN_GENCB_call(cb, 2, 0))
goto err;
if (!BN_GENCB_call(cb, 3, 0))
goto err;
/* step 6 */
counter = 0;
/* "offset = 2" */
n = (bits - 1) / 160;
for (;;) {
if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
goto err;
/* step 7 */
BN_zero(W);
/* now 'buf' contains "SEED + offset - 1" */
for (k = 0; k <= n; k++) {
/*
* obtain "SEED + offset + k" by incrementing:
*/
for (i = qsize - 1; i >= 0; i--) {
buf[i]++;
if (buf[i] != 0)
break;
}
if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL))
goto err;
/* step 8 */
if (!BN_bin2bn(md, qsize, r0))
goto err;
if (!BN_lshift(r0, r0, (qsize << 3) * k))
goto err;
if (!BN_add(W, W, r0))
goto err;
}
/* more of step 8 */
if (!BN_mask_bits(W, bits - 1))
goto err;
if (!BN_copy(X, W))
goto err;
if (!BN_add(X, X, test))
goto err;
/* step 9 */
if (!BN_lshift1(r0, q))
goto err;
if (!BN_mod(c, X, r0, ctx))
goto err;
if (!BN_sub(r0, c, BN_value_one()))
goto err;
if (!BN_sub(p, X, r0))
goto err;
/* step 10 */
if (BN_cmp(p, test) >= 0) {
/* step 11 */
r = BN_check_prime(p, ctx, cb);
if (r > 0)
goto end; /* found it */
if (r != 0)
goto err;
}
/* step 13 */
counter++;
/* "offset = offset + n + 1" */
/* step 14 */
if (counter >= 4096)
break;
}
}
end:
if (!BN_GENCB_call(cb, 2, 1))
goto err;
/* We now need to generate g */
/* Set r0=(p-1)/q */
if (!BN_sub(test, p, BN_value_one()))
goto err;
if (!BN_div(r0, NULL, test, q, ctx))
goto err;
if (!BN_set_word(test, h))
goto err;
if (!BN_MONT_CTX_set(mont, p, ctx))
goto err;
for (;;) {
/* g=test^r0%p */
if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
goto err;
if (!BN_is_one(g))
break;
if (!BN_add(test, test, BN_value_one()))
goto err;
h++;
}
if (!BN_GENCB_call(cb, 3, 1))
goto err;
ok = 1;
err:
if (ok) {
BN_free(ret->params.p);
BN_free(ret->params.q);
BN_free(ret->params.g);
ret->params.p = BN_dup(p);
ret->params.q = BN_dup(q);
ret->params.g = BN_dup(g);
ret->dirty_cnt++;
if (ret->params.p == NULL
|| ret->params.q == NULL
|| ret->params.g == NULL) {
ok = 0;
goto err;
}
if (counter_ret != NULL)
*counter_ret = counter;
if (h_ret != NULL)
*h_ret = h;
if (seed_out)
memcpy(seed_out, seed, qsize);
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_MONT_CTX_free(mont);
return ok;
}
/*
* This is a parameter generation algorithm for the DSA2 algorithm as
* described in FIPS 186-3.
*/
int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
const EVP_MD *evpmd, const unsigned char *seed_in,
size_t seed_len, int idx, unsigned char *seed_out,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb)
{
int ok = -1;
unsigned char *seed = NULL, *seed_tmp = NULL;
unsigned char md[EVP_MAX_MD_SIZE];
int mdsize;
BIGNUM *r0, *W, *X, *c, *test;
BIGNUM *g = NULL, *q = NULL, *p = NULL;
BN_MONT_CTX *mont = NULL;
int i, k, n = 0, m = 0, qsize = N >> 3;
int counter = 0;
int r = 0;
BN_CTX *ctx = NULL;
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
unsigned int h = 2;
if (mctx == NULL)
goto err;
/* make sure L > N, otherwise we'll get trapped in an infinite loop */
if (L <= N) {
DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS);
goto err;
}
if (evpmd == NULL) {
if (N == 160)
evpmd = EVP_sha1();
else if (N == 224)
evpmd = EVP_sha224();
else
evpmd = EVP_sha256();
}
mdsize = EVP_MD_size(evpmd);
/* If unverifiable g generation only don't need seed */
if (!ret->params.p || !ret->params.q || idx >= 0) {
if (seed_len == 0)
seed_len = mdsize;
seed = OPENSSL_malloc(seed_len);
if (seed_out)
seed_tmp = seed_out;
else
seed_tmp = OPENSSL_malloc(seed_len);
if (seed == NULL || seed_tmp == NULL)
goto err;
if (seed_in)
memcpy(seed, seed_in, seed_len);
}
if ((ctx = BN_CTX_new()) == NULL)
goto err;
if ((mont = BN_MONT_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
r0 = BN_CTX_get(ctx);
g = BN_CTX_get(ctx);
W = BN_CTX_get(ctx);
X = BN_CTX_get(ctx);
c = BN_CTX_get(ctx);
test = BN_CTX_get(ctx);
if (test == NULL)
goto err;
/* if p, q already supplied generate g only */
if (ret->params.p && ret->params.q) {
p = ret->params.p;
q = ret->params.q;
if (idx >= 0)
memcpy(seed_tmp, seed, seed_len);
goto g_only;
} else {
p = BN_CTX_get(ctx);
q = BN_CTX_get(ctx);
if (q == NULL)
goto err;
}
if (!BN_lshift(test, BN_value_one(), L - 1))
goto err;
for (;;) {
for (;;) { /* find q */
unsigned char *pmd;
/* step 1 */
if (!BN_GENCB_call(cb, 0, m++))
goto err;
if (!seed_in) {
if (RAND_bytes(seed, seed_len) <= 0)
goto err;
}
/* step 2 */
if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL))
goto err;
/* Take least significant bits of md */
if (mdsize > qsize)
pmd = md + mdsize - qsize;
else
pmd = md;
if (mdsize < qsize)
memset(md + mdsize, 0, qsize - mdsize);
/* step 3 */
pmd[0] |= 0x80;
pmd[qsize - 1] |= 0x01;
if (!BN_bin2bn(pmd, qsize, q))
goto err;
/* step 4 */
r = BN_check_prime(q, ctx, cb);
if (r > 0)
break;
if (r != 0)
goto err;
/* Provided seed didn't produce a prime: error */
if (seed_in) {
ok = 0;
DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_Q_NOT_PRIME);
goto err;
}
/* do a callback call */
/* step 5 */
}
/* Copy seed to seed_out before we mess with it */
if (seed_out)
memcpy(seed_out, seed, seed_len);
if (!BN_GENCB_call(cb, 2, 0))
goto err;
if (!BN_GENCB_call(cb, 3, 0))
goto err;
/* step 6 */
counter = 0;
/* "offset = 1" */
n = (L - 1) / (mdsize << 3);
for (;;) {
if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
goto err;
/* step 7 */
BN_zero(W);
/* now 'buf' contains "SEED + offset - 1" */
for (k = 0; k <= n; k++) {
/*
* obtain "SEED + offset + k" by incrementing:
*/
for (i = seed_len - 1; i >= 0; i--) {
seed[i]++;
if (seed[i] != 0)
break;
}
if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL))
goto err;
/* step 8 */
if (!BN_bin2bn(md, mdsize, r0))
goto err;
if (!BN_lshift(r0, r0, (mdsize << 3) * k))
goto err;
if (!BN_add(W, W, r0))
goto err;
}
/* more of step 8 */
if (!BN_mask_bits(W, L - 1))
goto err;
if (!BN_copy(X, W))
goto err;
if (!BN_add(X, X, test))
goto err;
/* step 9 */
if (!BN_lshift1(r0, q))
goto err;
if (!BN_mod(c, X, r0, ctx))
goto err;
if (!BN_sub(r0, c, BN_value_one()))
goto err;
if (!BN_sub(p, X, r0))
goto err;
/* step 10 */
if (BN_cmp(p, test) >= 0) {
/* step 11 */
r = BN_check_prime(p, ctx, cb);
if (r > 0)
goto end; /* found it */
if (r != 0)
goto err;
}
/* step 13 */
counter++;
/* "offset = offset + n + 1" */
/* step 14 */
if (counter >= (int)(4 * L))
break;
}
if (seed_in) {
ok = 0;
DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS);
goto err;
}
}
end:
if (!BN_GENCB_call(cb, 2, 1))
goto err;
g_only:
/* We now need to generate g */
/* Set r0=(p-1)/q */
if (!BN_sub(test, p, BN_value_one()))
goto err;
if (!BN_div(r0, NULL, test, q, ctx))
goto err;
if (idx < 0) {
if (!BN_set_word(test, h))
goto err;
} else
h = 1;
if (!BN_MONT_CTX_set(mont, p, ctx))
goto err;
for (;;) {
static const unsigned char ggen[4] = { 0x67, 0x67, 0x65, 0x6e };
if (idx >= 0) {
md[0] = idx & 0xff;
md[1] = (h >> 8) & 0xff;
md[2] = h & 0xff;
if (!EVP_DigestInit_ex(mctx, evpmd, NULL))
goto err;
if (!EVP_DigestUpdate(mctx, seed_tmp, seed_len))
goto err;
if (!EVP_DigestUpdate(mctx, ggen, sizeof(ggen)))
goto err;
if (!EVP_DigestUpdate(mctx, md, 3))
goto err;
if (!EVP_DigestFinal_ex(mctx, md, NULL))
goto err;
if (!BN_bin2bn(md, mdsize, test))
goto err;
}
/* g=test^r0%p */
if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
goto err;
if (!BN_is_one(g))
break;
if (idx < 0 && !BN_add(test, test, BN_value_one()))
goto err;
h++;
if (idx >= 0 && h > 0xffff)
goto err;
}
if (!BN_GENCB_call(cb, 3, 1))
goto err;
ok = 1;
err:
if (ok == 1) {
if (p != ret->params.p) {
BN_free(ret->params.p);
ret->params.p = BN_dup(p);
}
if (q != ret->params.q) {
BN_free(ret->params.q);
ret->params.q = BN_dup(q);
}
BN_free(ret->params.g);
ret->params.g = BN_dup(g);
if (ret->params.p == NULL
|| ret->params.q == NULL
|| ret->params.g == NULL) {
ok = -1;
goto err;
}
ret->dirty_cnt++;
if (counter_ret != NULL)
*counter_ret = counter;
if (h_ret != NULL)
*h_ret = h;
}
OPENSSL_free(seed);
if (seed_out != seed_tmp)
OPENSSL_free(seed_tmp);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_MONT_CTX_free(mont);
EVP_MD_CTX_free(mctx);
return ok;
}

View File

@ -11,42 +11,53 @@
#include <time.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include "crypto/dsa.h"
#include "dsa_local.h"
static int dsa_builtin_keygen(DSA *dsa);
static int dsa_builtin_keygen(OPENSSL_CTX *libctx, DSA *dsa);
int DSA_generate_key(DSA *dsa)
{
if (dsa->meth->dsa_keygen)
if (dsa->meth->dsa_keygen != NULL)
return dsa->meth->dsa_keygen(dsa);
return dsa_builtin_keygen(dsa);
return dsa_builtin_keygen(NULL, dsa);
}
static int dsa_builtin_keygen(DSA *dsa)
int dsa_generate_key_ctx(OPENSSL_CTX *libctx, DSA *dsa)
{
#ifndef FIPS_MODE
if (dsa->meth->dsa_keygen != NULL)
return dsa->meth->dsa_keygen(dsa);
#endif
return dsa_builtin_keygen(libctx, dsa);
}
static int dsa_builtin_keygen(OPENSSL_CTX *libctx, DSA *dsa)
{
int ok = 0;
BN_CTX *ctx = NULL;
BIGNUM *pub_key = NULL, *priv_key = NULL;
if ((ctx = BN_CTX_new()) == NULL)
if ((ctx = BN_CTX_new_ex(libctx)) == NULL)
goto err;
if (dsa->priv_key == NULL) {
if ((priv_key = BN_secure_new()) == NULL)
goto err;
} else
} else {
priv_key = dsa->priv_key;
}
do
if (!BN_priv_rand_range(priv_key, dsa->params.q))
goto err;
while (BN_is_zero(priv_key)) ;
if (!ffc_generate_private_key(ctx, &dsa->params, BN_num_bits(dsa->params.q),
112, priv_key))
goto err;
if (dsa->pub_key == NULL) {
if ((pub_key = BN_new()) == NULL)
goto err;
} else
} else {
pub_key = dsa->pub_key;
}
{
BIGNUM *prk = BN_new();
@ -55,6 +66,7 @@ static int dsa_builtin_keygen(DSA *dsa)
goto err;
BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
/* pub_key = g ^ priv_key mod p */
if (!BN_mod_exp(pub_key, dsa->params.g, prk, dsa->params.p, ctx)) {
BN_free(prk);
goto err;

View File

@ -68,17 +68,5 @@ struct dsa_method {
int (*dsa_keygen) (DSA *dsa);
};
int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
const EVP_MD *evpmd, const unsigned char *seed_in,
size_t seed_len, unsigned char *seed_out,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb);
int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
const EVP_MD *evpmd, const unsigned char *seed_in,
size_t seed_len, int idx, unsigned char *seed_out,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb);
DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst,
int dlen, DSA *dsa);

View File

@ -318,6 +318,7 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
BN_MONT_CTX *mont = NULL;
const BIGNUM *r, *s;
int ret = -1, i;
if (dsa->params.p == NULL
|| dsa->params.q == NULL
|| dsa->params.g == NULL) {
@ -421,6 +422,7 @@ static int dsa_init(DSA *dsa)
{
dsa->flags |= DSA_FLAG_CACHE_MONT_P;
ffc_params_init(&dsa->params);
dsa->dirty_cnt++;
return 1;
}

View File

@ -197,7 +197,7 @@ static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
DSA *dsa = NULL;
DSA_PKEY_CTX *dctx = ctx->data;
BN_GENCB *pcb;
int ret;
int ret, res;
if (ctx->pkey_gencb) {
pcb = BN_GENCB_new();
@ -211,8 +211,9 @@ static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
BN_GENCB_free(pcb);
return 0;
}
ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd,
NULL, 0, NULL, NULL, NULL, pcb);
ret = ffc_params_FIPS186_4_generate(NULL, &dsa->params, FFC_PARAM_TYPE_DSA,
dctx->nbits, dctx->qbits, dctx->pmd,
&res, pcb);
BN_GENCB_free(pcb);
if (ret)
EVP_PKEY_assign_DSA(pkey, dsa);

View File

@ -1,6 +1,6 @@
LIBS=../../libcrypto
$COMMON=ffc_params.c
$COMMON=ffc_params.c ffc_params_generate.c ffc_key_generate.c
SOURCE[../../libcrypto]=$COMMON
SOURCE[../../providers/libfips.a]=$COMMON

View File

@ -0,0 +1,61 @@
/*
* Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/ffc.h"
/*
* SP800-56Ar3 5.6.1.1.4 Key pair generation by testing candidates.
* Generates a private key in the interval [1, min(2 ^ N - 1, q - 1)].
*
* ctx must be set up with a libctx (for fips mode).
* params contains the FFC domain parameters p, q and g (for DH or DSA).
* N is the maximum bit length of the generated private key,
* s is the security strength.
* priv_key is the returned private key,
*/
int ffc_generate_private_key(BN_CTX *ctx, const FFC_PARAMS *params,
int N, int s, BIGNUM *priv)
{
#ifdef FIPS_MODE
int ret = 0;
BIGNUM *m, *two_powN = NULL;
/* Step (2) : check range of N */
if (N < 2 * s || N > BN_num_bits(params->q))
return 0;
two_powN = BN_new();
/* 2^N */
if (two_powN == NULL || !BN_lshift(two_powN, BN_value_one(), N))
goto err;
/* Step (5) : M = min(2 ^ N, q) */
m = (BN_cmp(two_powN, params->q) > 0) ? params->q : two_powN;
do {
/* Steps (3, 4 & 7) : c + 1 = 1 + random[0..2^N - 1] */
if (!BN_priv_rand_range_ex(priv, two_powN, ctx)
|| !BN_add_word(priv, 1))
goto err;
/* Step (6) : loop if c > M - 2 (i.e. c + 1 >= M) */
if (BN_cmp(priv, m) < 0)
break;
} while (1);
ret = 1;
err:
BN_free(two_powN);
return ret;
#else
do {
if (!BN_priv_rand_range_ex(priv, params->q, ctx))
return 0;
} while (BN_is_zero(priv) || BN_is_one(priv));
return 1;
#endif /* FIPS_MODE */
}

View File

@ -17,6 +17,7 @@ void ffc_params_init(FFC_PARAMS *params)
{
memset(params, 0, sizeof(FFC_PARAMS));
params->pcounter = -1;
params->gindex = FFC_UNVERIFIABLE_GINDEX;
}
void ffc_params_cleanup(FFC_PARAMS *params)

File diff suppressed because it is too large Load Diff

View File

@ -390,19 +390,37 @@ SHA-256 is selected to match the bit length of B<q> above.
The EVP_PKEY_CTX_set_dh_paramgen_prime_len() macro sets the length of the DH
prime parameter B<p> for DH parameter generation. If this macro is not called
then 1024 is used. Only accepts lengths greater than or equal to 256.
then 2048 is used. Only accepts lengths greater than or equal to 256.
The EVP_PKEY_CTX_set_dh_paramgen_subprime_len() macro sets the length of the DH
optional subprime parameter B<q> for DH parameter generation. The default is
256 if the prime is at least 2048 bits long or 160 otherwise. The DH
paramgen type must have been set to x9.42.
paramgen type must have been set to B<DH_PARAMGEN_TYPE_FIPS_186_2> or
B<DH_PARAMGEN_TYPE_FIPS_186_4>.
The EVP_PKEY_CTX_set_dh_paramgen_generator() macro sets DH generator to B<gen>
for DH parameter generation. If not specified 2 is used.
The EVP_PKEY_CTX_set_dh_paramgen_type() macro sets the key type for DH
parameter generation. Use 0 for PKCS#3 DH and 1 for X9.42 DH.
The default is 0.
parameter generation. The supported parameters are:
=over 4
=item B<DH_PARAMGEN_TYPE_GENERATOR>
Uses a generator g (PKCS#3 format).
=item B<DH_PARAMGEN_TYPE_FIPS_186_2>
FIPS186-2 FFC parameter generator (X9.42 DH).
=item B<DH_PARAMGEN_TYPE_FIPS_186_4>
FIPS186-4 FFC parameter generator.
=back
The default is B<DH_PARAMGEN_TYPE_GENERATOR>.
The EVP_PKEY_CTX_set_dh_pad() function sets the DH padding mode.
If B<pad> is 1 the shared secret is padded with zeros up to the size of the DH

View File

@ -10,6 +10,9 @@
#include <openssl/dh.h>
#include "internal/ffc.h"
int dh_generate_ffc_parameters(OPENSSL_CTX *libctx, DH *dh, int bits,
int qbits, int gindex, BN_GENCB *cb);
int dh_compute_key(OPENSSL_CTX *ctx, unsigned char *key, const BIGNUM *pub_key,
DH *dh);
int dh_compute_key_padded(OPENSSL_CTX *ctx, unsigned char *key,

View File

@ -9,7 +9,19 @@
#include <openssl/dsa.h>
#define DSA_PARAMGEN_TYPE_FIPS_186_2 1 /* Use legacy FIPS186-2 standard */
#define DSA_PARAMGEN_TYPE_FIPS_186_4 2 /* Use FIPS186-4 standard */
int dsa_generate_parameters_ctx(OPENSSL_CTX *libctx, DSA *dsa, int bits,
const unsigned char *seed_in, int seed_len,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb);
int dsa_generate_ffc_parameters(OPENSSL_CTX *libctx, DSA *dsa, int type,
int pbits, int qbits, int gindex,
BN_GENCB *cb);
int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst,
int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa);
int dsa_generate_key_ctx(OPENSSL_CTX *libctx, DSA *dsa);
const unsigned char *dsa_algorithmidentifier_encoding(int md_nid, size_t *len);

View File

@ -11,6 +11,45 @@
# define OSSL_INTERNAL_FFC_H
# include <openssl/bn.h>
# include <openssl/evp.h>
# include <openssl/dh.h> /* Uses Error codes from DH */
/* Default value for gindex when canonical generation of g is not used */
# define FFC_UNVERIFIABLE_GINDEX -1
/* The different types of FFC keys */
# define FFC_PARAM_TYPE_DSA 0
# define FFC_PARAM_TYPE_DH 1
/* Return codes for generation and validation of FFC parameters */
#define FFC_PARAMS_RET_STATUS_FAILED 0
#define FFC_PARAMS_RET_STATUS_SUCCESS 1
/* Returned if validating and g is only partially verifiable */
#define FFC_PARAMS_RET_STATUS_UNVERIFIABLE_G 2
/* Validation flags */
# define FFC_PARAMS_GENERATE 0x00
# define FFC_PARAMS_VALIDATE_PQ 0x01
# define FFC_PARAMS_VALIDATE_G 0x02
# define FFC_PARAMS_VALIDATE_ALL (FFC_PARAMS_VALIDATE_PQ | FFC_PARAMS_VALIDATE_G)
# define FFC_CHECK_P_NOT_PRIME DH_CHECK_P_NOT_PRIME
# define FFC_CHECK_P_NOT_SAFE_PRIME DH_CHECK_P_NOT_SAFE_PRIME
# define FFC_CHECK_UNKNOWN_GENERATOR DH_UNABLE_TO_CHECK_GENERATOR
# define FFC_CHECK_NOT_SUITABLE_GENERATOR DH_NOT_SUITABLE_GENERATOR
# define FFC_CHECK_Q_NOT_PRIME DH_CHECK_Q_NOT_PRIME
# define FFC_CHECK_INVALID_Q_VALUE DH_CHECK_INVALID_Q_VALUE
# define FFC_CHECK_INVALID_J_VALUE DH_CHECK_INVALID_J_VALUE
# define FFC_CHECK_BAD_LN_PAIR 0x00080
# define FFC_CHECK_INVALID_SEED_SIZE 0x00100
# define FFC_CHECK_MISSING_SEED_OR_COUNTER 0x00200
# define FFC_CHECK_INVALID_G 0x00400
# define FFC_CHECK_INVALID_PQ 0x00800
# define FFC_CHECK_INVALID_COUNTER 0x01000
# define FFC_CHECK_P_MISMATCH 0x02000
# define FFC_CHECK_Q_MISMATCH 0x04000
# define FFC_CHECK_G_MISMATCH 0x08000
# define FFC_CHECK_COUNTER_MISMATCH 0x10000
/*
* Finite field cryptography (FFC) domain parameters are used by DH and DSA.
@ -33,6 +72,12 @@ typedef struct ffc_params_st {
int pcounter;
int nid; /* The identity of a named group */
/*
* Required for FIPS186_4 generation & validation of canonical g.
* It uses unverifiable g if this value is -1.
*/
int gindex;
int h; /* loop counter for unverifiable g */
} FFC_PARAMS;
void ffc_params_init(FFC_PARAMS *params);
@ -55,4 +100,28 @@ int ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q);
int ffc_params_print(BIO *bp, const FFC_PARAMS *ffc, int indent);
#endif /* FIPS_MODE */
int ffc_params_FIPS186_4_generate(OPENSSL_CTX *libctx, FFC_PARAMS *params,
int type, size_t L, size_t N,
const EVP_MD *evpmd, int *res, BN_GENCB *cb);
int ffc_params_FIPS186_2_generate(OPENSSL_CTX *libctx, FFC_PARAMS *params,
int type, size_t L, size_t N,
const EVP_MD *evpmd, int *res, BN_GENCB *cb);
int ffc_param_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
int type, size_t L, size_t N,
const EVP_MD *evpmd, int validate_flags,
int *res, BN_GENCB *cb);
int ffc_param_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
int type, size_t L, size_t N,
const EVP_MD *evpmd, int validate_flags,
int *res, BN_GENCB *cb);
int ffc_generate_private_key(BN_CTX *ctx, const FFC_PARAMS *params,
int N, int s, BIGNUM *priv);
int ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont,
const BIGNUM *p, const BIGNUM *q,
const BIGNUM *g, BIGNUM *tmp, int *ret);
#endif /* OSSL_INTERNAL_FFC_H */

View File

@ -96,6 +96,11 @@ DECLARE_ASN1_ITEM(DHparams)
*/
# define DH_CHECK_P_NOT_STRONG_PRIME DH_CHECK_P_NOT_SAFE_PRIME
/* DH parameter generation types used by EVP_PKEY_CTX_set_dh_paramgen_type() */
# define DH_PARAMGEN_TYPE_GENERATOR 0 /* Use a generator g */
# define DH_PARAMGEN_TYPE_FIPS_186_2 1 /* Use legacy FIPS186-2 standard */
# define DH_PARAMGEN_TYPE_FIPS_186_4 2 /* Use FIPS186-4 standard */
# define d2i_DHparams_fp(fp,x) \
(DH *)ASN1_d2i_fp((char *(*)())DH_new, \
(char *(*)())d2i_DHparams, \