From b03ec3b5d62ee26bf8437556b9040d4141d5bdd8 Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Wed, 15 Apr 2020 21:02:52 +1000 Subject: 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 (Merged from https://github.com/openssl/openssl/pull/11303) --- crypto/dsa/build.info | 4 +- crypto/dsa/dsa_ameth.c | 4 +- crypto/dsa/dsa_backend.c | 2 +- crypto/dsa/dsa_gen.c | 23 ++++--- crypto/dsa/dsa_key.c | 8 ++- crypto/dsa/dsa_lib.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 186 insertions(+), 16 deletions(-) (limited to 'crypto/dsa') diff --git a/crypto/dsa/build.info b/crypto/dsa/build.info index fb5a4fee2a..7f621cb56b 100644 --- a/crypto/dsa/build.info +++ b/crypto/dsa/build.info @@ -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 diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index d63c142fdd..81bb6d88f7 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -19,11 +19,11 @@ #include #include #include +#include #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); diff --git a/crypto/dsa/dsa_backend.c b/crypto/dsa/dsa_backend.c index b927465cfa..461cb187dd 100644 --- a/crypto/dsa/dsa_backend.c +++ b/crypto/dsa/dsa_backend.c @@ -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) diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index 2148a1a487..7b72867f71 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -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 diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index 2dec35f28f..1d625272e5 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -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) { diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index e3205223e9..b773f2c526 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -19,7 +19,9 @@ #include #include #include +#include #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 -- cgit v1.2.3