Add DSA keygen to provider

Moved some shared FFC code into the FFC files.
Added extra paramgen parameters for seed, gindex.
Fixed bug in ossl_prov util to print bignums.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11303)
master
Shane Lontis 3 years ago
parent 09b3654096
commit b03ec3b5d6

@ -24,7 +24,7 @@
#include "crypto/evp.h"
#include <openssl/cms.h>
#include <openssl/core_names.h>
#include "openssl/param_build.h"
#include <openssl/param_build.h>
#include "internal/ffc.h"
/*
@ -558,7 +558,7 @@ static int dh_pkey_import_from(const OSSL_PARAM params[], void *key)
return 0;
}
if (!ffc_fromdata(dh_get0_params(dh), params)
if (!ffc_params_fromdata(dh_get0_params(dh), params)
|| !dh_key_fromdata(dh, params)
|| !EVP_PKEY_assign_DH(pkey, dh)) {
DH_free(dh);

@ -23,12 +23,14 @@
#include "crypto/bn_dh.h"
#include "crypto/dh.h"
#include "crypto/security_bits.h"
#include "e_os.h" /* strcasecmp */
#define FFDHE(sz) { NID_ffdhe##sz, sz, &_bignum_ffdhe##sz##_p }
#define MODP(sz) { NID_modp_##sz, sz, &_bignum_modp_##sz##_p }
#define FFDHE(sz) { SN_ffdhe##sz, NID_ffdhe##sz, sz, &_bignum_ffdhe##sz##_p }
#define MODP(sz) { SN_modp_##sz, NID_modp_##sz, sz, &_bignum_modp_##sz##_p }
typedef struct safe_prime_group_st {
const char *name;
int nid;
int32_t nbits;
const BIGNUM *p;
@ -50,6 +52,28 @@ static const SP_GROUP sp_groups[] = {
MODP(8192),
};
int ffc_named_group_to_nid(const char *name)
{
size_t i;
for (i = 0; i < OSSL_NELEM(sp_groups); ++i) {
if (strcasecmp(sp_groups[i].name, name) == 0)
return sp_groups[i].nid;
}
return NID_undef;
}
const char *ffc_named_group_from_nid(int nid)
{
size_t i;
for (i = 0; i < OSSL_NELEM(sp_groups); ++i) {
if (sp_groups[i].nid == nid)
return sp_groups[i].name;
}
return NULL;
}
#ifndef FIPS_MODE
static DH *dh_new_by_nid_with_ctx(OPENSSL_CTX *libctx, int nid);

@ -19,6 +19,12 @@
#include "crypto/bn.h"
#include "crypto/dh.h"
#ifdef FIPS_MODE
# define MIN_STRENGTH 112
#else
# define MIN_STRENGTH 80
#endif
static int generate_key(DH *dh);
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
const BIGNUM *a, const BIGNUM *p,
@ -287,7 +293,8 @@ static int generate_key(DH *dh)
* Max Private key size N = len(q)
*/
if (!ffc_generate_private_key(ctx, &dh->params,
BN_num_bits(dh->params.q), 112,
BN_num_bits(dh->params.q),
MIN_STRENGTH,
priv_key))
goto err;
}

@ -1,10 +1,10 @@
LIBS=../../libcrypto
$COMMON=dsa_sign.c dsa_vrf.c dsa_lib.c dsa_ossl.c dsa_check.c \
dsa_key.c dsa_backend.c
dsa_key.c dsa_backend.c dsa_gen.c
SOURCE[../../libcrypto]=$COMMON\
dsa_gen.c dsa_asn1.c \
dsa_asn1.c \
dsa_err.c dsa_depr.c dsa_ameth.c dsa_pmeth.c dsa_prn.c \
dsa_meth.c
SOURCE[../../providers/libfips.a]=$COMMON

@ -19,11 +19,11 @@
#include <openssl/bn.h>
#include <openssl/cms.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include "internal/cryptlib.h"
#include "crypto/asn1.h"
#include "crypto/dsa.h"
#include "crypto/evp.h"
#include "openssl/param_build.h"
#include "internal/ffc.h"
#include "dsa_local.h"
@ -586,7 +586,7 @@ static int dsa_pkey_import_from(const OSSL_PARAM params[], void *key)
return 0;
}
if (!ffc_fromdata(dsa_get0_params(dsa), params)
if (!dsa_ffc_params_fromdata(dsa, params)
|| !dsa_key_fromdata(dsa, params)
|| !EVP_PKEY_assign_DSA(pkey, dsa)) {
DSA_free(dsa);

@ -34,7 +34,7 @@ int dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[])
return 1;
/*
* DH documentation says that a public key must be present if a
* DSA documentation says that a public key must be present if a
* private key is present.
*/
if (param_priv_key != NULL && param_pub_key == NULL)

@ -24,32 +24,34 @@
#include "dsa_local.h"
int dsa_generate_ffc_parameters(DSA *dsa, int type,
int pbits, int qbits, int gindex,
BN_GENCB *cb)
int pbits, int qbits,
EVP_MD *md, 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;
if (md != NULL)
qbits = EVP_MD_size(md) * 8;
else
qbits = (pbits >= 2048 ? SHA256_DIGEST_LENGTH :
SHA_DIGEST_LENGTH) * 8;
}
dsa->params.gindex = gindex;
#ifndef FIPS_MODE
if (type == DSA_PARAMGEN_TYPE_FIPS_186_2)
ret = ffc_params_FIPS186_2_generate(dsa->libctx, &dsa->params,
FFC_PARAM_TYPE_DSA,
pbits, qbits, NULL, &res, cb);
pbits, qbits, md, &res, cb);
else
#endif
ret = ffc_params_FIPS186_4_generate(dsa->libctx, &dsa->params,
FFC_PARAM_TYPE_DSA,
pbits, qbits, NULL, &res, cb);
pbits, qbits, md, &res, cb);
if (ret > 0)
dsa->dirty_cnt++;
return ret;
}
#ifndef FIPS_MODE
int DSA_generate_parameters_ex(DSA *dsa, int bits,
const unsigned char *seed_in, int seed_len,
int *counter_ret, unsigned long *h_ret,
@ -68,13 +70,13 @@ int DSA_generate_parameters_ex(DSA *dsa, int bits,
/* The old code used FIPS 186-2 DSA Parameter generation */
if (bits <= 1024 && seed_len == 20) {
if (!dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_2,
bits, 160, -1, cb))
bits, 160, NULL, cb))
return 0;
} else
#endif
{
if (!dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_4,
bits, -1, -1, cb))
bits, -1, NULL, cb))
return 0;
}
@ -84,3 +86,4 @@ int DSA_generate_parameters_ex(DSA *dsa, int bits,
*h_ret = dsa->params.h;
return 1;
}
#endif

@ -21,6 +21,12 @@
#include "crypto/dsa.h"
#include "dsa_local.h"
#ifdef FIPS_MODE
# define MIN_STRENGTH 112
#else
# define MIN_STRENGTH 80
#endif
static int dsa_keygen(DSA *dsa, int pairwise_test);
static int dsa_keygen_pairwise_test(DSA *dsa, OSSL_CALLBACK *cb, void *cbarg);
@ -69,7 +75,7 @@ static int dsa_keygen(DSA *dsa, int pairwise_test)
}
if (!ffc_generate_private_key(ctx, &dsa->params, BN_num_bits(dsa->params.q),
112, priv_key))
MIN_STRENGTH, priv_key))
goto err;
if (dsa->pub_key == NULL) {

@ -19,7 +19,9 @@
#include <openssl/bn.h>
#include <openssl/asn1.h>
#include <openssl/engine.h>
#include <openssl/core_names.h>
#include "dsa_local.h"
#include "crypto/evp.h"
#include "crypto/dsa.h"
#include "crypto/dh.h" /* required by DSA_dup_DH() */
@ -342,3 +344,162 @@ FFC_PARAMS *dsa_get0_params(DSA *dsa)
{
return &dsa->params;
}
int dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[])
{
int ret;
FFC_PARAMS *ffc;
if (dsa == NULL)
return 0;
ffc = dsa_get0_params(dsa);
if (ffc == NULL)
return 0;
ret = ffc_params_fromdata(ffc, params);
if (ret)
dsa->dirty_cnt++;
return ret;
}
static int dsa_paramgen_check(EVP_PKEY_CTX *ctx)
{
if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
/* If key type not DSA return error */
if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_DSA)
return -1;
return 1;
}
int EVP_PKEY_CTX_set_dsa_paramgen_type(EVP_PKEY_CTX *ctx, const char *name)
{
int ret;
OSSL_PARAM params[2], *p = params;
if ((ret = dsa_paramgen_check(ctx)) <= 0)
return ret;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE,
(char *)name, 0);
*p++ = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, params);
}
int EVP_PKEY_CTX_set_dsa_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex)
{
int ret;
OSSL_PARAM params[2], *p = params;
if ((ret = dsa_paramgen_check(ctx)) <= 0)
return ret;
*p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GINDEX, &gindex);
*p++ = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, params);
}
int EVP_PKEY_CTX_set_dsa_paramgen_seed(EVP_PKEY_CTX *ctx,
const unsigned char *seed,
size_t seedlen)
{
int ret;
OSSL_PARAM params[2], *p = params;
if ((ret = dsa_paramgen_check(ctx)) <= 0)
return ret;
*p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_FFC_SEED,
(void *)seed, seedlen);
*p++ = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, params);
}
int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits)
{
int ret;
OSSL_PARAM params[2], *p = params;
size_t bits = nbits;
if ((ret = dsa_paramgen_check(ctx)) <= 0)
return ret;
#if !defined(FIPS_MODE)
/* TODO(3.0): Remove this eventually when no more legacy */
if (ctx->op.keymgmt.genctx == NULL)
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, nbits, NULL);
#endif
*p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_PBITS, &bits);
*p++ = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, params);
}
int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, int qbits)
{
int ret;
OSSL_PARAM params[2], *p = params;
size_t bits2 = qbits;
if ((ret = dsa_paramgen_check(ctx)) <= 0)
return ret;
#if !defined(FIPS_MODE)
/* TODO(3.0): Remove this eventually when no more legacy */
if (ctx->op.keymgmt.genctx == NULL)
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits, NULL);
#endif
*p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_QBITS, &bits2);
*p++ = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, params);
}
int EVP_PKEY_CTX_set_dsa_paramgen_md_props(EVP_PKEY_CTX *ctx,
const char *md_name,
const char *md_properties)
{
int ret;
OSSL_PARAM params[3], *p = params;
if ((ret = dsa_paramgen_check(ctx)) <= 0)
return ret;
#if !defined(FIPS_MODE)
/* TODO(3.0): Remove this eventually when no more legacy */
if (ctx->op.keymgmt.genctx == NULL) {
const EVP_MD *md = EVP_get_digestbyname(md_name);
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, (void *)(md));
}
#endif
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST,
(char *)md_name, 0);
if (md_properties != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS,
(char *)md_properties, 0);
*p++ = OSSL_PARAM_construct_end();
return EVP_PKEY_CTX_set_params(ctx, params);
}
#if !defined(FIPS_MODE)
int EVP_PKEY_CTX_set_dsa_paramgen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
{
const char *md_name = (md == NULL) ? "" : EVP_MD_name(md);
return EVP_PKEY_CTX_set_dsa_paramgen_md_props(ctx, md_name, NULL);
}
#endif

@ -627,14 +627,6 @@ RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey)
# endif
# ifndef OPENSSL_NO_DSA
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
{
int ret = EVP_PKEY_assign_DSA(pkey, key);
if (ret)
DSA_up_ref(key);
return ret;
}
DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey)
{
if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) {
@ -648,6 +640,13 @@ DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey)
return pkey->pkey.dsa;
}
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
{
int ret = EVP_PKEY_assign_DSA(pkey, key);
if (ret)
DSA_up_ref(key);
return ret;
}
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
{
DSA *ret = EVP_PKEY_get0_DSA(pkey);
@ -655,10 +654,11 @@ DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
DSA_up_ref(ret);
return ret;
}
# endif
# endif /* OPENSSL_NO_DSA */
#endif /* FIPS_MODE */
#ifndef FIPS_MODE
# ifndef OPENSSL_NO_EC
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
{
int ret = EVP_PKEY_assign_EC_KEY(pkey, key);

@ -8,7 +8,7 @@
*/
/*
* DH low level APIs are deprecated for public use, but still ok for
* Low level key APIs (DH etc) are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
@ -816,6 +816,18 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
}
}
# endif
# ifndef OPENSSL_NO_DSA
if (keytype == EVP_PKEY_DSA) {
switch (cmd) {
case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS:
return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, p1);
case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS:
return EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, p1);
case EVP_PKEY_CTRL_DSA_PARAMGEN_MD:
return EVP_PKEY_CTX_set_dsa_paramgen_md(ctx, p2);
}
}
# endif
# ifndef OPENSSL_NO_EC
if (keytype == EVP_PKEY_EC) {
switch (cmd) {
@ -1000,6 +1012,14 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
name = OSSL_PKEY_PARAM_RSA_E;
else if (strcmp(name, "rsa_keygen_primes") == 0)
name = OSSL_PKEY_PARAM_RSA_PRIMES;
# ifndef OPENSSL_NO_DSA
else if (strcmp(name, "dsa_paramgen_bits") == 0)
name = OSSL_PKEY_PARAM_FFC_PBITS;
else if (strcmp(name, "dsa_paramgen_q_bits") == 0)
name = OSSL_PKEY_PARAM_FFC_QBITS;
else if (strcmp(name, "dsa_paramgen_md") == 0)
name = OSSL_PKEY_PARAM_FFC_DIGEST;
# endif
# ifndef OPENSSL_NO_DH
else if (strcmp(name, "dh_pad") == 0)
name = OSSL_EXCHANGE_PARAM_PAD;

@ -9,6 +9,7 @@
#include <openssl/core_names.h>
#include "internal/ffc.h"
#include "internal/sizes.h"
/*
* The intention with the "backend" source file is to offer backend support
@ -16,27 +17,75 @@
* implementations alike.
*/
int ffc_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[])
int ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[])
{
const OSSL_PARAM *prm;
const OSSL_PARAM *param_p, *param_q, *param_g;
BIGNUM *p = NULL, *q = NULL, *g = NULL;
BIGNUM *p = NULL, *q = NULL, *g = NULL, *j = NULL;
#if 0
char group_name[OSSL_MAX_NAME_SIZE];
char *str = group_name;
#endif
int i;
if (ffc == NULL)
return 0;
/* TODO(3.0) Add for DH PR */
#if 0
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GROUP);
if (prm != NULL) {
if (!OSSL_PARAM_get_utf8_string(prm, &str, sizeof(group_name)))
goto err;
if (!ffc_set_group_pqg(ffc, group_name))
goto err;
}
#endif
param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q);
param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q);
if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
|| (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q))
|| (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)))
goto err;
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);
if (prm != NULL) {
if (!OSSL_PARAM_get_int(prm, &i))
goto err;
ffc->gindex = i;
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);
if (prm != NULL) {
if (!OSSL_PARAM_get_int(prm, &i))
goto err;
ffc->pcounter = i;
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_COFACTOR);
if (prm != NULL) {
if (!OSSL_PARAM_get_BN(prm, &j))
goto err;
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);
if (prm != NULL) {
if (!OSSL_PARAM_get_int(prm, &i))
goto err;
ffc->h = i;
}
prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);
if (prm != NULL) {
if (prm->data_type != OSSL_PARAM_OCTET_STRING)
goto err;
if (!ffc_params_set_seed(ffc, prm->data, prm->data_size))
goto err;
}
ffc_params_set0_pqg(ffc, p, q, g);
ffc_params_set0_j(ffc, j);
return 1;
err:
BN_free(j);
BN_free(p);
BN_free(q);
BN_free(g);

@ -10,6 +10,7 @@
#include "internal/ffc.h"
/*
* For Fips mode:
* 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)].
*

@ -8,7 +8,10 @@
*/
#include <string.h> /* memset */
#include <openssl/core_names.h>
#include "internal/ffc.h"
#include "internal/param_build_set.h"
#ifndef FIPS_MODE
# include <openssl/asn1.h> /* ffc_params_print */
#endif
@ -67,15 +70,17 @@ void ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *j)
d->j = j;
}
int ffc_params_set_validate_params(FFC_PARAMS *params,
const unsigned char *seed, size_t seedlen,
int counter)
int ffc_params_set_seed(FFC_PARAMS *params,
const unsigned char *seed, size_t seedlen)
{
if (params == NULL)
return 0;
if (params->seed != NULL)
if (params->seed != NULL) {
if (params->seed == seed)
return 1;
OPENSSL_free(params->seed);
}
if (seed != NULL && seedlen > 0) {
params->seed = OPENSSL_memdup(seed, seedlen);
@ -86,6 +91,30 @@ int ffc_params_set_validate_params(FFC_PARAMS *params,
params->seed = NULL;
params->seedlen = 0;
}
return 1;
}
void ffc_params_set_gindex(FFC_PARAMS *params, int index)
{
params->gindex = index;
}
void ffc_params_set_pcounter(FFC_PARAMS *params, int index)
{
params->pcounter = index;
}
void ffc_params_set_h(FFC_PARAMS *params, int index)
{
params->h = index;
}
int ffc_params_set_validate_params(FFC_PARAMS *params,
const unsigned char *seed, size_t seedlen,
int counter)
{
if (!ffc_params_set_seed(params, seed, seedlen))
return 0;
params->pcounter = counter;
return 1;
}
@ -139,7 +168,10 @@ int ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src)
} else {
dst->seed = NULL;
}
dst->nid = src->nid;
dst->pcounter = src->pcounter;
dst->h = src->h;
dst->gindex = src->gindex;
return 1;
}
@ -150,7 +182,52 @@ int ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q)
&& (ignore_q || BN_cmp(a->q, b->q) == 0); /* Note: q may be NULL */
}
int ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld,
OSSL_PARAM params[])
{
if (ffc == NULL)
return 0;
if (ffc->p != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_P, ffc->p))
return 0;
if (ffc->q != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_Q, ffc->q))
return 0;
if (ffc->g != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_G, ffc->g))
return 0;
if (ffc->j != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_COFACTOR,
ffc->j))
return 0;
if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_GINDEX,
ffc->gindex))
return 0;
if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_PCOUNTER,
ffc->pcounter))
return 0;
if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_H, ffc->h))
return 0;
if (ffc->seed != NULL
&& !ossl_param_build_set_octet_string(bld, params,
OSSL_PKEY_PARAM_FFC_SEED,
ffc->seed, ffc->seedlen))
return 0;
if (ffc->nid != NID_undef) {
const char *name = ffc_named_group_from_nid(ffc->nid);
if (name == NULL
|| !ossl_param_build_set_utf8_string(bld, params,
OSSL_PKEY_PARAM_FFC_GROUP,
name))
return 0;
}
return 1;
}
#ifndef FIPS_MODE
int ffc_params_print(BIO *bp, const FFC_PARAMS *ffc, int indent)
{
if (!ASN1_bn_print(bp, "prime P:", ffc->p, NULL, indent))

@ -487,7 +487,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
BIGNUM *g = NULL, *q = NULL, *p = NULL;
BN_MONT_CTX *mont = NULL;
int n = 0, m = 0, qsize = N >> 3;
int canonical_g = 0, hret = -1;
int canonical_g = 0, hret = 0;
BN_CTX *ctx = NULL;
EVP_MD_CTX *mctx = NULL;
int generate = (validate_flags == 0);

@ -194,11 +194,15 @@ The number of bits in the generated prime. If not specified 2048 is used.
=item B<dsa_paramgen_q_bits>:I<numbits>
=item B<qbits>:I<numbits>
The number of bits in the q parameter. Must be one of 160, 224 or 256. If not
specified 224 is used.
=item B<dsa_paramgen_md>:I<digest>
=item B<digest>:I<digest>
The digest to use during parameter generation. Must be one of B<sha1>, B<sha224>
or B<sha256>. If set, then the number of bits in B<q> will match the output size
of the specified digest and the B<dsa_paramgen_q_bits> parameter will be
@ -206,6 +210,31 @@ ignored. If not set, then a digest will be used that gives an output matching
the number of bits in B<q>, i.e. B<sha1> if q length is 160, B<sha224> if it 224
or B<sha256> if it is 256.
=item B<properties>:I<query>
The I<digest> property I<query> string to use when fetching a digest from a provider.
=item B<type>:I<type>
The type of generation to use. Set this to 1 to use legacy FIPS186-2 parameter
generation. The default of 0 uses FIPS186-4 parameter generation.
=item B<gindex>:I<index>
The index to use for canonical generation and verification of the generator g.
Set this to a positive value ranging from 0..255 to use this mode. Larger values
will only use the bottom byte.
This I<index> must then be reused during key validation to verify the value of g.
If this value is not set then g is not verifiable. The default value is -1.
=item B<hexseed>:I<seed>
The seed I<seed> data to use instead of generating a random seed internally.
This should be used for testing purposes only. This will either produced fixed
values for the generated parameters OR it will fail if the seed did not
generate valid primes.
=back
=head2 DH Parameter Generation Options
@ -269,10 +298,12 @@ Generate a 2048 bit RSA key using 3 as the public exponent:
openssl genpkey -algorithm RSA -out key.pem \
-pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:3
Generate 2048 bit DSA parameters:
Generate 2048 bit DSA parameters that can be validated: The output values for
gindex and seed are required for key validation purposes and are not saved to
the output pem file).
openssl genpkey -genparam -algorithm DSA -out dsap.pem \
-pkeyopt dsa_paramgen_bits:2048
openssl genpkey -genparam -algorithm DSA -out dsap.pem -pkeyopt pbits:2048 \
-pkeyopt qbits:224 -pkeyopt digest:SHA256 -pkeyopt gindex:1 -text
Generate DSA key from parameters:

@ -33,6 +33,10 @@ EVP_PKEY_CTX_get0_rsa_oaep_label,
EVP_PKEY_CTX_set_dsa_paramgen_bits,
EVP_PKEY_CTX_set_dsa_paramgen_q_bits,
EVP_PKEY_CTX_set_dsa_paramgen_md,
EVP_PKEY_CTX_set_dsa_paramgen_md_props,
EVP_PKEY_CTX_set_dsa_paramgen_gindex,
EVP_PKEY_CTX_set_dsa_paramgen_type,
EVP_PKEY_CTX_set_dsa_paramgen_seed,
EVP_PKEY_CTX_set_dh_paramgen_prime_len,
EVP_PKEY_CTX_set_dh_paramgen_subprime_len,
EVP_PKEY_CTX_set_dh_paramgen_generator,
@ -121,6 +125,14 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len
int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits);
int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, int qbits);
int EVP_PKEY_CTX_set_dsa_paramgen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
int EVP_PKEY_CTX_set_dsa_paramgen_md_props(EVP_PKEY_CTX *ctx,
const char *md_name,
const char *md_properties);
int EVP_PKEY_CTX_set_dsa_paramgen_type(EVP_PKEY_CTX *ctx, const char *name);
int EVP_PKEY_CTX_set_dsa_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex);
int EVP_PKEY_CTX_set_dsa_paramgen_seed(EVP_PKEY_CTX *ctx,
const unsigned char *seed,
size_t seedlen);
#include <openssl/dh.h>
@ -395,19 +407,42 @@ negotiated protocol version. Otherwise it should be left unset.
=head2 DSA parameters
The EVP_PKEY_CTX_set_dsa_paramgen_bits() macro sets the number of bits used
The EVP_PKEY_CTX_set_dsa_paramgen_bits() method sets the number of bits used
for DSA parameter generation to I<nbits>. If not specified, 2048 is used.
The EVP_PKEY_CTX_set_dsa_paramgen_q_bits() macro sets the number of bits in the
The EVP_PKEY_CTX_set_dsa_paramgen_q_bits() method sets the number of bits in the
subprime parameter I<q> for DSA parameter generation to I<qbits>. If not
specified, 224 is used. If a digest function is specified below, this parameter
is ignored and instead, the number of bits in I<q> matches the size of the
digest.
The EVP_PKEY_CTX_set_dsa_paramgen_md() macro sets the digest function used for
The EVP_PKEY_CTX_set_dsa_paramgen_md() method sets the digest function used for
DSA parameter generation to I<md>. If not specified, one of SHA-1, SHA-224, or
SHA-256 is selected to match the bit length of I<q> above.
The EVP_PKEY_CTX_set_dsa_paramgen_md_props() method sets the digest function
used for DSA parameter generation using I<md_name> and I<md_properties> to
retrieve the digest from a provider.
If not specified, I<md_name> will be set to one of SHA-1, SHA-224, or
SHA-256 depending on the bit length of I<q> above. I<md_properties> is a
property query string that has a default value of '' if not specified.
The EVP_PKEY_CTX_set_dsa_paramgen_gindex() method sets the I<gindex> used by
the generator G. The default value is -1 which uses unverifiable g, otherwise
a positive value uses verifiable g. This value must be saved if key validation
of g is required, since it is not part of a persisted key.
The EVP_PKEY_CTX_set_dsa_paramgen_seed() method sets the I<seed> to use for
generation rather than using a randomly generated value for the seed. This is
useful for testing purposes only and can fail if the seed does not produce
primes for both p & q on its first iteration. This value must be saved if
key validation of p, q, and verifiable g are required, since it is not part of
a persisted key.
The EVP_PKEY_CTX_set_dsa_paramgen_type() method sets the generation type to
use FIPS186-4 generation if I<name> is "fips186_4", or FIPS186-2 generation if
I<name> is "fips186_2". The default value is "fips186_4".
=head2 DH parameters
The EVP_PKEY_CTX_set_dh_paramgen_prime_len() macro sets the length of the DH
@ -417,8 +452,7 @@ 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 I<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 B<DH_PARAMGEN_TYPE_FIPS_186_2> or
B<DH_PARAMGEN_TYPE_FIPS_186_4>.
paramgen type must have been set to "fips186_4".
The EVP_PKEY_CTX_set_dh_paramgen_generator() macro sets DH generator to I<gen>
for DH parameter generation. If not specified 2 is used.
@ -633,12 +667,16 @@ EVP_PKEY_CTX_get_rsa_padding(), EVP_PKEY_CTX_get_rsa_mgf1_md(),
EVP_PKEY_CTX_set_rsa_mgf1_md(), EVP_PKEY_CTX_set_rsa_oaep_md(),
EVP_PKEY_CTX_get_rsa_oaep_md(), EVP_PKEY_CTX_set0_rsa_oaep_label(),
EVP_PKEY_CTX_get0_rsa_oaep_label(), EVP_PKEY_CTX_set_rsa_pss_saltlen(),
EVP_PKEY_CTX_get_rsa_pss_saltlen(), were macros in OpenSSL 1.1.1 and below.
EVP_PKEY_CTX_get_rsa_pss_saltlen(), EVP_PKEY_CTX_set_dsa_paramgen_bits(),
EVP_PKEY_CTX_set_dsa_paramgen_q_bits() and EVP_PKEY_CTX_set_dsa_paramgen_md()
were macros in OpenSSL 1.1.1 and below.
From OpenSSL 3.0 they are functions.
EVP_PKEY_CTX_get_rsa_oaep_md_name(), EVP_PKEY_CTX_get_rsa_mgf1_md_name(),
EVP_PKEY_CTX_set_rsa_mgf1_md_name() and EVP_PKEY_CTX_set_rsa_oaep_md_name() were
added in OpenSSL 3.0.
EVP_PKEY_CTX_set_rsa_mgf1_md_name(), EVP_PKEY_CTX_set_rsa_oaep_md_name(),
EVP_PKEY_CTX_set_dsa_paramgen_md_props(), EVP_PKEY_CTX_set_dsa_paramgen_gindex(),
EVP_PKEY_CTX_set_dsa_paramgen_type() and EVP_PKEY_CTX_set_dsa_paramgen_seed()
were added in OpenSSL 3.0.
The EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and
EVP_PKEY_CTX_get1_id_len() macros were added in 1.1.1, other functions were
@ -646,7 +684,7 @@ added in OpenSSL 1.0.0.
=head1 COPYRIGHT
Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2006-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

@ -328,6 +328,56 @@ from I<keydata_from> to I<keydata_to>. It is assumed that the caller
has ensured that I<keydata_to> and I<keydata_from> are both owned by
the implementation of this function.
=head2 Built-in DSA Key Generation Types
The following Key Generation types are available for the built-in DSA algorithm:
=over 4
=item "pbits" (B<OSSL_PKEY_PARAM_FFC_PBITS>) <unsigned integer>
Sets the DSA size (in bits) of the prime 'p'.
The value should be 2048 or 3072.
=item "qbits" (B<OSSL_PKEY_PARAM_FFC_QBITS>) <unsigned integer>
Sets the DSA size (in bits) of the prime 'q'.
The value should be 224 or 256.
=item "type" (B<OSSL_PKEY_PARAM_FFC_TYPE>) <integer>
Sets the type of parameter generation.
Use 0 for FIPS186-4, or 1 for legacy FIPS186-2.
The default is 0.
=item "digest" (B<OSSL_PKEY_PARAM_FFC_DIGEST>) <utf8_string>
Sets the Digest algorithm to be used as part of the Key Generation Function
associated with the given Key Generation I<ctx>.
=item "properties" (B<OSSL_PKEY_PARAM_FFC_DIGEST_PROPS>) <utf8_string>
Sets properties to be used upon look up of the implementation for the selected
Digest algorithm for the Key Generation Function associated with the given key
Generation I<ctx>.
=item "gindex" (B<OSSL_PKEY_PARAM_FFC_GINDEX>) <integer>
Sets the index to use for canonical generation and verification of the generator g.
Set this to a positive value to use this mode. This I<index> can then be reused
during key validation to verify the value of g. If this value is not set then
g is not verifiable. The default value is -1.
=item "seed" (B<OSSL_PKEY_PARAM_FFC_SEED>) <octet_string>
Sets the I<seed> data to use instead of generating a random seed internally.
This should be used for testing purposes only. This will either produced fixed
values for the generated parameters OR it will fail if the seed did not
generate valid primes.
=back
=head2 Built-in RSA Import/Export Types
The following Import/Export types are available for the built-in RSA algorithm:

@ -11,20 +11,20 @@
#include <openssl/dsa.h>
#include "internal/ffc.h"
#define DSA_PARAMGEN_TYPE_FIPS_186_4 0 /* Use FIPS186-4 standard */
#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 */
DSA *dsa_new_with_ctx(OPENSSL_CTX *libctx);
int dsa_generate_ffc_parameters(DSA *dsa, int type,
int pbits, int qbits, int gindex,
BN_GENCB *cb);
int pbits, int qbits, EVP_MD *md, BN_GENCB *cb);
int dsa_sign_int(int type, const unsigned char *dgst,
int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa);
const unsigned char *dsa_algorithmidentifier_encoding(int md_nid, size_t *len);
FFC_PARAMS *dsa_get0_params(DSA *dsa);
int dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[]);
int dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[]);
int dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa, const BIGNUM *priv_key,

@ -14,6 +14,8 @@
# include <openssl/bn.h>
# include <openssl/evp.h>
# include <openssl/dh.h> /* Uses Error codes from DH */
# include <openssl/params.h>
# include <openssl/param_build.h>
/* Default value for gindex when canonical generation of g is not used */
# define FFC_UNVERIFIABLE_GINDEX -1
@ -100,6 +102,12 @@ void ffc_params_set0_pqg(FFC_PARAMS *params, BIGNUM *p, BIGNUM *q, BIGNUM *g);
void ffc_params_get0_pqg(const FFC_PARAMS *params, const BIGNUM **p,
const BIGNUM **q, const BIGNUM **g);
void ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *j);
int ffc_params_set_seed(FFC_PARAMS *params,
const unsigned char *seed, size_t seedlen);
void ffc_params_set_gindex(FFC_PARAMS *params, int index);
void ffc_params_set_pcounter(FFC_PARAMS *params, int index);
void ffc_params_set_h(FFC_PARAMS *params, int index);
int ffc_params_set_validate_params(FFC_PARAMS *params,
const unsigned char *seed, size_t seedlen,
int counter);
@ -155,6 +163,11 @@ int ffc_validate_public_key_partial(const FFC_PARAMS *params,
int ffc_validate_private_key(const BIGNUM *upper, const BIGNUM *priv_key,
int *ret);
int ffc_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[]);
int ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *tmpl,
OSSL_PARAM params[]);
int ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[]);
int ffc_named_group_to_nid(const char *name);
const char *ffc_named_group_from_nid(int nid);
int ffc_set_group_pqg(FFC_PARAMS *ffc, const char *group_name);
#endif /* OSSL_INTERNAL_FFC_H */

@ -191,6 +191,12 @@ extern "C" {
#define OSSL_PKEY_PARAM_FFC_P "p"
#define OSSL_PKEY_PARAM_FFC_G "g"
#define OSSL_PKEY_PARAM_FFC_Q "q"
#define OSSL_PKEY_PARAM_FFC_GINDEX "gindex"
#define OSSL_PKEY_PARAM_FFC_PCOUNTER "pcounter"
#define OSSL_PKEY_PARAM_FFC_SEED "seed"
#define OSSL_PKEY_PARAM_FFC_COFACTOR "j"
#define OSSL_PKEY_PARAM_FFC_H "hindex"
#define OSSL_PKEY_PARAM_FFC_GROUP "group"
/* Elliptic Curve Domain Parameters */
#define OSSL_PKEY_PARAM_EC_NAME "curve-name"
@ -255,6 +261,13 @@ extern "C" {
#define OSSL_PKEY_PARAM_RSA_BITS OSSL_PKEY_PARAM_BITS
#define OSSL_PKEY_PARAM_RSA_PRIMES "primes"
/* Key generation parameters */
#define OSSL_PKEY_PARAM_FFC_TYPE "type"
#define OSSL_PKEY_PARAM_FFC_PBITS "pbits"
#define OSSL_PKEY_PARAM_FFC_QBITS "qbits"
#define OSSL_PKEY_PARAM_FFC_DIGEST OSSL_PKEY_PARAM_DIGEST
#define OSSL_PKEY_PARAM_FFC_DIGEST_PROPS OSSL_PKEY_PARAM_PROPERTIES
/* Key Exchange parameters */
#define OSSL_EXCHANGE_PARAM_PAD "pad" /* uint */

@ -182,15 +182,17 @@ DEPRECATEDIN_3_0(int DSA_print_fp(FILE *bp, const DSA *x, int off))
DEPRECATEDIN_3_0(DH *DSA_dup_DH(const DSA *r))
# endif
# define EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \
EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, nbits, NULL)
# define EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, qbits) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \
EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits, NULL)
# define EVP_PKEY_CTX_set_dsa_paramgen_md(ctx, md) \
EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \
EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, (void *)(md))
int EVP_PKEY_CTX_set_dsa_paramgen_bits(EVP_PKEY_CTX *ctx, int nbits);
int EVP_PKEY_CTX_set_dsa_paramgen_q_bits(EVP_PKEY_CTX *ctx, int qbits);
int EVP_PKEY_CTX_set_dsa_paramgen_md_props(EVP_PKEY_CTX *ctx,
const char *md_name,
const char *md_properties);
int EVP_PKEY_CTX_set_dsa_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex);
int EVP_PKEY_CTX_set_dsa_paramgen_type(EVP_PKEY_CTX *ctx, const char *name);
int EVP_PKEY_CTX_set_dsa_paramgen_seed(EVP_PKEY_CTX *ctx,
const unsigned char *seed,
size_t seedlen);
int EVP_PKEY_CTX_set_dsa_paramgen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
# define EVP_PKEY_CTRL_DSA_PARAMGEN_BITS (EVP_PKEY_ALG_CTRL + 1)
# define EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS (EVP_PKEY_ALG_CTRL + 2)

@ -18,11 +18,11 @@
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/params.h>
#include <openssl/param_build.h>
#include "prov/implementations.h"
#include "prov/providercommon.h"
#include "prov/provider_ctx.h"
#include "crypto/dh.h"
#include "openssl/param_build.h"
static OSSL_OP_keymgmt_new_fn dh_newdata;
static OSSL_OP_keymgmt_free_fn dh_freedata;
@ -137,7 +137,7 @@ static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])
ok = 1;
if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
ok = ok && ffc_fromdata(dh_get0_params(dh), params);
ok = ok && ffc_params_fromdata(dh_get0_params(dh), params);
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
ok = ok && dh_key_fromdata(dh, params);
@ -148,7 +148,7 @@ static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
void *cbarg)
{
DH *dh = keydata;
OSSL_PARAM_BLD *tmpl;
OSSL_PARAM_BLD *tmpl = NULL;
OSSL_PARAM *params = NULL;
int ok = 1;
@ -166,13 +166,13 @@ static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
if (!ok
|| (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
OSSL_PARAM_BLD_free(tmpl);
return 0;
ok = 0;
goto err;
}
OSSL_PARAM_BLD_free(tmpl);
ok = param_cb(params, cbarg);
OSSL_PARAM_BLD_free_params(params);
err:
OSSL_PARAM_BLD_free(tmpl);
return ok;
}

@ -13,18 +13,27 @@
*/
#include "internal/deprecated.h"
#include "e_os.h" /* strcasecmp */
#include <openssl/core_numbers.h>
#include <openssl/core_names.h>
#include <openssl/bn.h>
#include <openssl/params.h>
#include "prov/implementations.h"
#include <openssl/err.h>
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "crypto/dsa.h"
#include "openssl/param_build.h"
#include "internal/sizes.h"
#include "internal/nelem.h"
#include "internal/param_build_set.h"
static OSSL_OP_keymgmt_new_fn dsa_newdata;
static OSSL_OP_keymgmt_free_fn dsa_freedata;
static OSSL_OP_keymgmt_gen_init_fn dsa_gen_init;
static OSSL_OP_keymgmt_gen_set_template_fn dsa_gen_set_template;
static OSSL_OP_keymgmt_gen_set_params_fn dsa_gen_set_params;
static OSSL_OP_keymgmt_gen_settable_params_fn dsa_gen_settable_params;
static OSSL_OP_keymgmt_gen_fn dsa_gen;
static OSSL_OP_keymgmt_gen_cleanup_fn dsa_gen_cleanup;
static OSSL_OP_keymgmt_get_params_fn dsa_get_params;
static OSSL_OP_keymgmt_gettable_params_fn dsa_gettable_params;
static OSSL_OP_keymgmt_has_fn dsa_has;
@ -36,45 +45,63 @@ static OSSL_OP_keymgmt_export_fn dsa_export;
static OSSL_OP_keymgmt_export_types_fn dsa_export_types;
#define DSA_DEFAULT_MD "SHA256"
#define DSA_POSSIBLE_SELECTIONS \
#define DSA_POSSIBLE_SELECTIONS \
(OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
static int domparams_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl)
{
const BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
struct dsa_gen_ctx {
OPENSSL_CTX *libctx;
FFC_PARAMS *ffc_params;
int selection;
/* All these parameters are used for parameter generation only */
size_t pbits;
size_t qbits;
EVP_MD *md;
unsigned char *seed; /* optional FIPS186-4 param for testing */
size_t seedlen;
int gindex; /* optional FIPS186-4 generator index (ignored if -1) */
int gen_type; /* DSA_PARAMGEN_TYPE_FIPS_186_2 or DSA_PARAMGEN_TYPE_FIPS_186_4 */
int pcounter;
int hindex;
OSSL_CALLBACK *cb;
void *cbarg;
};
typedef struct dh_name2id_st{
const char *name;
int id;
} DSA_GENTYPE_NAME2ID;
if (dsa == NULL)
return 0;
static const DSA_GENTYPE_NAME2ID dsatype2id[]=
{
{ "default", DSA_PARAMGEN_TYPE_FIPS_186_4 },
{ "fips186_4", DSA_PARAMGEN_TYPE_FIPS_186_4 },
{ "fips186_2", DSA_PARAMGEN_TYPE_FIPS_186_2 },
};
DSA_get0_pqg(dsa, &dsa_p, &dsa_q, &dsa_g);
if (dsa_p != NULL
&& !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, dsa_p))
return 0;
if (dsa_q != NULL
&& !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, dsa_q))
return 0;
if (dsa_g != NULL
&& !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, dsa_g))
return 0;
static int dsa_gen_type_name2id(const char *name)
{
size_t i;
return 1;
for (i = 0; i < OSSL_NELEM(dsatype2id); ++i) {
if (strcasecmp(dsatype2id[i].name, name) == 0)
return dsatype2id[i].id;
}
return -1;
}
static int key_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl)
static int dsa_key_todata(DSA *dsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
{
const BIGNUM *priv_key = NULL, *pub_key = NULL;
const BIGNUM *priv = NULL, *pub = NULL;
if (dsa == NULL)
return 0;
if (!domparams_to_params(dsa, tmpl))
return 0;
DSA_get0_key(dsa, &pub_key, &priv_key);
if (priv_key != NULL
&& !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key))
DSA_get0_key(dsa, &pub, &priv);
if (priv != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv))
return 0;
if (pub_key != NULL
&& !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
if (pub != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PUB_KEY, pub))
return 0;
return 1;
@ -133,16 +160,16 @@ static int dsa_match(const void *keydata1, const void *keydata2, int selection)
static int dsa_import(void *keydata, int selection, const OSSL_PARAM params[])
{
DSA *dsa = keydata;
int ok = 0;
int ok = 1;
if (dsa == NULL)
return 0;
if ((selection & DSA_POSSIBLE_SELECTIONS) != 0)
ok = 1;
if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
ok = ok && ffc_fromdata(dsa_get0_params(dsa), params);
ok = ok && dsa_ffc_params_fromdata(dsa, params);
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
ok = ok && dsa_key_fromdata(dsa, params);
@ -158,12 +185,12 @@ static int dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
int ok = 1;
if (dsa == NULL)
goto err;;
goto err;
if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
ok = ok && domparams_to_params(dsa, tmpl);
ok = ok && ffc_params_todata(dsa_get0_params(dsa), tmpl, NULL);
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
ok = ok && key_to_params(dsa, tmpl);
ok = ok && dsa_key_todata(dsa, tmpl, NULL);
if (!ok
|| (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
@ -178,10 +205,16 @@ err:
/* IMEXPORT = IMPORT + EXPORT */
# define DSA_IMEXPORTABLE_PARAMETERS \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0)
# define DSA_IMEXPORTABLE_PARAMETERS \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), \
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_GROUP, NULL, 0), \
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0)
# define DSA_IMEXPORTABLE_PUBLIC_KEY \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
# define DSA_IMEXPORTABLE_PRIVATE_KEY \
@ -246,7 +279,8 @@ static ossl_inline int dsa_get_params(void *key, OSSL_PARAM params[])
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
&& !OSSL_PARAM_set_utf8_string(p, DSA_DEFAULT_MD))
return 0;
return 1;
return ffc_params_todata(dsa_get0_params(dsa), NULL, params)
&& dsa_key_todata(dsa, NULL, params);
}
static const OSSL_PARAM dsa_params[] = {
@ -254,6 +288,9 @@ static const OSSL_PARAM dsa_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
DSA_IMEXPORTABLE_PARAMETERS,
DSA_IMEXPORTABLE_PUBLIC_KEY,
DSA_IMEXPORTABLE_PRIVATE_KEY,
OSSL_PARAM_END
};
@ -311,8 +348,224 @@ static int dsa_validate(void *keydata, int selection)
return ok;
}
static void *dsa_gen_init(void *provctx, int selection)
{
OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
struct dsa_gen_ctx *gctx = NULL;
if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
return NULL;
if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
gctx->selection = selection;