From 4889dadcb8511176c30888c748f1981adc38451d Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 30 Aug 2019 13:33:37 +0100 Subject: [PATCH] Implement DSA in the default provider Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/9753) --- crypto/dh/dh_ameth.c | 6 +- crypto/dsa/dsa_ameth.c | 71 +++++++++- crypto/dsa/dsa_gen.c | 2 + crypto/dsa/dsa_key.c | 1 + crypto/dsa/dsa_lib.c | 2 + crypto/dsa/dsa_locl.h | 3 + crypto/evp/pmeth_fn.c | 2 + crypto/evp/pmeth_lib.c | 32 +++++ include/openssl/core_names.h | 17 ++- include/openssl/core_numbers.h | 3 + include/openssl/evp.h | 6 +- providers/common/build.info | 2 +- .../common/include/internal/provider_algs.h | 4 + providers/common/keymgmt/build.info | 2 +- providers/common/keymgmt/dh_kmgmt.c | 4 +- providers/common/keymgmt/dsa_kmgmt.c | 91 ++++++++++++ providers/common/signature/build.info | 7 + providers/common/signature/dsa.c | 132 ++++++++++++++++++ providers/default/defltprov.c | 13 ++ util/libcrypto.num | 1 + 20 files changed, 383 insertions(+), 18 deletions(-) create mode 100644 providers/common/keymgmt/dsa_kmgmt.c create mode 100644 providers/common/signature/build.info create mode 100644 providers/common/signature/dsa.c diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 6da4878200..7b75bd1a1a 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -563,13 +563,13 @@ static void *dh_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) return NULL; ossl_param_bld_init(&tmpl); - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_P, p) - || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_G, g) + if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p) + || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g) || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PUB_KEY, pub_key)) return NULL; if (q != NULL) { - if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_Q, q)) + if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q)) return NULL; } diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index ef6fc7632a..4e0ed01970 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -8,14 +8,16 @@ */ #include -#include "internal/cryptlib.h" #include #include -#include "dsa_locl.h" #include #include +#include +#include "internal/cryptlib.h" #include "internal/asn1_int.h" #include "internal/evp_int.h" +#include "internal/param_build.h" +#include "dsa_locl.h" static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) { @@ -63,6 +65,7 @@ static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) goto err; } + dsa->dirty_cnt++; ASN1_INTEGER_free(public_key); EVP_PKEY_assign_DSA(pkey, dsa); return 1; @@ -185,6 +188,7 @@ static int dsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) goto dsaerr; } + dsa->dirty_cnt++; EVP_PKEY_assign_DSA(pkey, dsa); ret = 1; @@ -300,6 +304,7 @@ static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) return 0; BN_free(to->pkey.dsa->g); to->pkey.dsa->g = a; + to->pkey.dsa->dirty_cnt++; return 1; } @@ -381,6 +386,7 @@ static int dsa_param_decode(EVP_PKEY *pkey, DSAerr(DSA_F_DSA_PARAM_DECODE, ERR_R_DSA_LIB); return 0; } + dsa->dirty_cnt++; EVP_PKEY_assign_DSA(pkey, dsa); return 1; } @@ -417,6 +423,7 @@ static int old_dsa_priv_decode(EVP_PKEY *pkey, DSAerr(DSA_F_OLD_DSA_PRIV_DECODE, ERR_R_DSA_LIB); return 0; } + dsa->dirty_cnt++; EVP_PKEY_assign_DSA(pkey, dsa); return 1; } @@ -514,6 +521,56 @@ static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) } +static size_t dsa_pkey_dirty_cnt(const EVP_PKEY *pkey) +{ + return pkey->pkey.dsa->dirty_cnt; +} + +static void *dsa_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) +{ + DSA *dsa = pk->pkey.dsa; + OSSL_PARAM_BLD tmpl; + const BIGNUM *p = DSA_get0_p(dsa), *g = DSA_get0_g(dsa); + const BIGNUM *q = DSA_get0_q(dsa), *pub_key = DSA_get0_pub_key(dsa); + const BIGNUM *priv_key = DSA_get0_priv_key(dsa); + OSSL_PARAM *params; + void *provkey = NULL; + + if (p == NULL || q == NULL || g == NULL) + return NULL; + + ossl_param_bld_init(&tmpl); + if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p) + || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q) + || !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g)) + return NULL; + + /* + * This may be used to pass domain parameters only without any key data - + * so "pub_key" is optional. We can never have a "priv_key" without a + * corresponding "pub_key" though. + */ + if (pub_key != NULL) { + if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PUB_KEY, + pub_key)) + return NULL; + + if (priv_key != NULL) { + if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DSA_PRIV_KEY, + priv_key)) + return NULL; + } + } + + params = ossl_param_bld_to_param(&tmpl); + + /* We export, the provider imports */ + provkey = evp_keymgmt_importkey(keymgmt, params); + + ossl_param_bld_free(params); + return provkey; +} + /* NB these are sorted in pkey_id order, lowest first */ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5] = { @@ -570,5 +627,13 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5] = { int_dsa_free, dsa_pkey_ctrl, old_dsa_priv_decode, - old_dsa_priv_encode} + old_dsa_priv_encode, + + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + + dsa_pkey_dirty_cnt, + dsa_pkey_export_to + } }; diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index 858f127315..14cb8e9f53 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -281,6 +281,7 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, ret->p = BN_dup(p); ret->q = BN_dup(q); ret->g = BN_dup(g); + ret->dirty_cnt++; if (ret->p == NULL || ret->q == NULL || ret->g == NULL) { ok = 0; goto err; @@ -598,6 +599,7 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, ok = -1; goto err; } + ret->dirty_cnt++; if (counter_ret != NULL) *counter_ret = counter; if (h_ret != NULL) diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index 333bff959e..86f79b804e 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -65,6 +65,7 @@ static int dsa_builtin_keygen(DSA *dsa) dsa->priv_key = priv_key; dsa->pub_key = pub_key; + dsa->dirty_cnt++; ok = 1; err: diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index 1068f1da77..034300fc7e 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -273,6 +273,7 @@ int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) BN_free(d->g); d->g = g; } + d->dirty_cnt++; return 1; } @@ -303,6 +304,7 @@ int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) BN_free(d->priv_key); d->priv_key = priv_key; } + d->dirty_cnt++; return 1; } diff --git a/crypto/dsa/dsa_locl.h b/crypto/dsa/dsa_locl.h index 5c464e7c25..e56ff06977 100644 --- a/crypto/dsa/dsa_locl.h +++ b/crypto/dsa/dsa_locl.h @@ -31,6 +31,9 @@ struct dsa_st { /* functional reference if 'meth' is ENGINE-provided */ ENGINE *engine; CRYPTO_RWLOCK *lock; + + /* Provider data */ + size_t dirty_cnt; /* If any key material changes, increment this */ }; struct DSA_SIG_st { diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c index 44ce64e59f..53f4dbbf74 100644 --- a/crypto/evp/pmeth_fn.c +++ b/crypto/evp/pmeth_fn.c @@ -194,6 +194,8 @@ int EVP_PKEY_sign_init_ex(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature) */ if (ctx->pkey != NULL) { switch (ctx->pkey->type) { + case NID_dsa: + break; default: goto legacy; } diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 7041020cb0..563a2bd7ba 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -430,6 +430,38 @@ int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad) } #endif +int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) +{ + OSSL_PARAM sig_md_params[3]; + size_t mdsize; + const char *name; + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (ctx->sigprovctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, + EVP_PKEY_CTRL_MD, 0, (void *)(md)); + + if (md == NULL) + return 1; + + mdsize = EVP_MD_size(md); + name = EVP_MD_name(md); + sig_md_params[0] = OSSL_PARAM_construct_utf8_string( + OSSL_SIGNATURE_PARAM_DIGEST, + /* + * Cast away the const. This is read only so should + * be safe + */ + (char *)name, + strlen(name) + 1); + sig_md_params[1] = OSSL_PARAM_construct_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, + &mdsize); + sig_md_params[2] = OSSL_PARAM_construct_end(); + + return EVP_PKEY_CTX_set_params(ctx, sig_md_params); + +} + static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2) { diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index b78a0978fd..5a75aaf280 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -129,18 +129,27 @@ extern "C" { #define OSSL_KDF_PARAM_SIZE "size" /* size_t */ /* PKEY parameters */ -/* Diffie-Hellman Parameters */ -#define OSSL_PKEY_PARAM_DH_P "dh-p" -#define OSSL_PKEY_PARAM_DH_G "dh-g" -#define OSSL_PKEY_PARAM_DH_Q "dh-q" +/* Diffie-Hellman/DSA Parameters */ +#define OSSL_PKEY_PARAM_FFC_P "ffc-p" +#define OSSL_PKEY_PARAM_FFC_G "ffc-g" +#define OSSL_PKEY_PARAM_FFC_Q "ffc-q" + /* Diffie-Hellman Keys */ #define OSSL_PKEY_PARAM_DH_PUB_KEY "dh-pub" #define OSSL_PKEY_PARAM_DH_PRIV_KEY "dh-priv" +/* DSA Keys */ +#define OSSL_PKEY_PARAM_DSA_PUB_KEY "dsa-pub" +#define OSSL_PKEY_PARAM_DSA_PRIV_KEY "dsa-priv" + /* Key Exchange parameters */ #define OSSL_EXCHANGE_PARAM_PAD "exchange-pad" /* uint */ +/* Signature parameters */ +#define OSSL_SIGNATURE_PARAM_DIGEST "digest" +#define OSSL_SIGNATURE_PARAM_DIGEST_SIZE "digest-size" + # ifdef __cplusplus } # endif diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h index 61ec1537b6..ea320537e7 100644 --- a/include/openssl/core_numbers.h +++ b/include/openssl/core_numbers.h @@ -408,6 +408,7 @@ OSSL_CORE_MAKE_FUNC(int, OP_keyexch_set_params, (void *ctx, # define OSSL_FUNC_SIGNATURE_SIGN 3 # define OSSL_FUNC_SIGNATURE_FREECTX 4 # define OSSL_FUNC_SIGNATURE_DUPCTX 5 +# define OSSL_FUNC_SIGNATURE_SET_PARAMS 6 OSSL_CORE_MAKE_FUNC(void *, OP_signature_newctx, (void *provctx)) OSSL_CORE_MAKE_FUNC(int, OP_signature_sign_init, (void *ctx, void *provkey)) @@ -417,6 +418,8 @@ OSSL_CORE_MAKE_FUNC(int, OP_signature_sign, (void *ctx, unsigned char *sig, size_t tbslen)) OSSL_CORE_MAKE_FUNC(void, OP_signature_freectx, (void *ctx)) OSSL_CORE_MAKE_FUNC(void *, OP_signature_dupctx, (void *ctx)) +OSSL_CORE_MAKE_FUNC(int, OP_signature_set_params, (void *ctx, + const OSSL_PARAM params[])) # ifdef __cplusplus } diff --git a/include/openssl/evp.h b/include/openssl/evp.h index b09547a8b0..dc70686f8f 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1337,6 +1337,8 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, int (*pkey_security_bits) (const EVP_PKEY *pk)); +int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); + # define EVP_PKEY_OP_UNDEFINED 0 # define EVP_PKEY_OP_PARAMGEN (1<<1) # define EVP_PKEY_OP_KEYGEN (1<<2) @@ -1362,10 +1364,6 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, # define EVP_PKEY_OP_TYPE_GEN \ (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN) -# define EVP_PKEY_CTX_set_signature_md(ctx, md) \ - EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \ - EVP_PKEY_CTRL_MD, 0, (void *)(md)) - # define EVP_PKEY_CTX_get_signature_md(ctx, pmd) \ EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \ EVP_PKEY_CTRL_GET_MD, 0, (void *)(pmd)) diff --git a/providers/common/build.info b/providers/common/build.info index b098ca6958..916cc3e4ea 100644 --- a/providers/common/build.info +++ b/providers/common/build.info @@ -1,4 +1,4 @@ -SUBDIRS=digests ciphers macs kdfs exchange keymgmt +SUBDIRS=digests ciphers macs kdfs exchange keymgmt signature $COMMON=provider_util.c SOURCE[../../libcrypto]=$COMMON provider_err.c provlib.c diff --git a/providers/common/include/internal/provider_algs.h b/providers/common/include/internal/provider_algs.h index b9d257649f..92aa64772e 100644 --- a/providers/common/include/internal/provider_algs.h +++ b/providers/common/include/internal/provider_algs.h @@ -161,6 +161,10 @@ extern const OSSL_DISPATCH kdf_x942_kdf_functions[]; /* Key management */ extern const OSSL_DISPATCH dh_keymgmt_functions[]; +extern const OSSL_DISPATCH dsa_keymgmt_functions[]; /* Key Exchange */ extern const OSSL_DISPATCH dh_keyexch_functions[]; + +/* Signature */ +extern const OSSL_DISPATCH dsa_signature_functions[]; diff --git a/providers/common/keymgmt/build.info b/providers/common/keymgmt/build.info index a41f3dac6e..4e7bc750f5 100644 --- a/providers/common/keymgmt/build.info +++ b/providers/common/keymgmt/build.info @@ -1,5 +1,5 @@ LIBS=../../../libcrypto IF[{- !$disabled{dh} -}] SOURCE[../../../libcrypto]=\ - dh_kmgmt.c + dh_kmgmt.c dsa_kmgmt.c ENDIF diff --git a/providers/common/keymgmt/dh_kmgmt.c b/providers/common/keymgmt/dh_kmgmt.c index 67e3205edc..c13f07546b 100644 --- a/providers/common/keymgmt/dh_kmgmt.c +++ b/providers/common/keymgmt/dh_kmgmt.c @@ -24,8 +24,8 @@ static int params_to_key(DH *dh, const OSSL_PARAM params[]) if (dh == NULL) return 0; - param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_P); - param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_G); + param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P); + param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G); param_priv_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_KEY); param_pub_key = diff --git a/providers/common/keymgmt/dsa_kmgmt.c b/providers/common/keymgmt/dsa_kmgmt.c new file mode 100644 index 0000000000..a53c0b212c --- /dev/null +++ b/providers/common/keymgmt/dsa_kmgmt.c @@ -0,0 +1,91 @@ +/* + * Copyright 2019 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 +#include +#include +#include +#include +#include "internal/provider_algs.h" + +static OSSL_OP_keymgmt_importkey_fn dsa_importkey; + +static int params_to_key(DSA *dsa, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *param_p, *param_q, *param_g, *param_priv_key; + const OSSL_PARAM *param_pub_key; + BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL; + + if (dsa == NULL) + return 0; + + 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_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PRIV_KEY); + param_pub_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PUB_KEY); + + /* + * DSA documentation says that a public key must be present if a private key + * is. + */ + if (param_priv_key != NULL && param_pub_key == NULL) + return 0; + + 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)) + || (param_priv_key != NULL + && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) + || (param_pub_key != NULL + && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))) + goto err; + + if (!DSA_set0_pqg(dsa, p, q, g)) + goto err; + p = q = g = NULL; + + if (pub_key != NULL && !DSA_set0_key(dsa, pub_key, priv_key)) + goto err; + priv_key = pub_key = NULL; + + return 1; + + err: + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(priv_key); + BN_free(pub_key); + return 0; +} + +static void *dsa_importkey(void *provctx, const OSSL_PARAM params[]) +{ + DSA *dsa; + + if ((dsa = DSA_new()) == NULL + || !params_to_key(dsa, params)) { + DSA_free(dsa); + dsa = NULL; + } + return dsa; +} + +const OSSL_DISPATCH dsa_keymgmt_functions[] = { + /* + * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also + * implement OSSL_FUNC_KEYMGMT_EXPORTKEY. + */ + { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dsa_importkey }, + { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DSA_free }, + { 0, NULL } +}; diff --git a/providers/common/signature/build.info b/providers/common/signature/build.info new file mode 100644 index 0000000000..5b64229dfc --- /dev/null +++ b/providers/common/signature/build.info @@ -0,0 +1,7 @@ +LIBS=../../../libcrypto +IF[{- !$disabled{dsa} -}] + SOURCE[../../../libcrypto]=\ + dsa.c +ENDIF + + diff --git a/providers/common/signature/dsa.c b/providers/common/signature/dsa.c new file mode 100644 index 0000000000..69f4978729 --- /dev/null +++ b/providers/common/signature/dsa.c @@ -0,0 +1,132 @@ +/* + * Copyright 2019 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 +#include +#include +#include +#include +#include "internal/provider_algs.h" + +static OSSL_OP_signature_newctx_fn dsa_newctx; +static OSSL_OP_signature_sign_init_fn dsa_sign_init; +static OSSL_OP_signature_sign_fn dsa_sign; +static OSSL_OP_signature_freectx_fn dsa_freectx; +static OSSL_OP_signature_dupctx_fn dsa_dupctx; +static OSSL_OP_signature_set_params_fn dsa_set_params; + +/* + * What's passed as an actual key is defined by the KEYMGMT interface. + * We happen to know that our KEYMGMT simply passes DSA structures, so + * we use that here too. + */ + +typedef struct { + DSA *dsa; + size_t mdsize; +} PROV_DSA_CTX; + +static void *dsa_newctx(void *provctx) +{ + return OPENSSL_zalloc(sizeof(PROV_DSA_CTX)); +} + +static int dsa_sign_init(void *vpdsactx, void *vdsa) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + + if (pdsactx == NULL || vdsa == NULL || !DSA_up_ref(vdsa)) + return 0; + DSA_free(pdsactx->dsa); + pdsactx->dsa = vdsa; + return 1; +} + +static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen, + size_t sigsize, const unsigned char *tbs, size_t tbslen) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + int ret; + unsigned int sltmp; + size_t dsasize = DSA_size(pdsactx->dsa); + + if (sig == NULL) { + *siglen = dsasize; + return 1; + } + + if (sigsize < (size_t)dsasize) + return 0; + + if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize) + return 0; + + ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, pdsactx-> dsa); + + if (ret <= 0) + return 0; + + *siglen = sltmp; + return 1; +} + +static void dsa_freectx(void *vpdsactx) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + + DSA_free(pdsactx->dsa); + + OPENSSL_free(pdsactx); +} + +static void *dsa_dupctx(void *vpdsactx) +{ + PROV_DSA_CTX *srcctx = (PROV_DSA_CTX *)vpdsactx; + PROV_DSA_CTX *dstctx; + + dstctx = OPENSSL_zalloc(sizeof(*srcctx)); + if (dstctx == NULL) + return NULL; + + *dstctx = *srcctx; + if (dstctx->dsa != NULL && !DSA_up_ref(dstctx->dsa)) { + OPENSSL_free(dstctx); + return NULL; + } + + return dstctx; +} + +static int dsa_set_params(void *vpdsactx, const OSSL_PARAM params[]) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + const OSSL_PARAM *p; + size_t mdsize; + + if (pdsactx == NULL || params == NULL) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); + if (p == NULL || !OSSL_PARAM_get_size_t(p, &mdsize)) + return 0; + + pdsactx->mdsize = mdsize; + + return 1; +} + +const OSSL_DISPATCH dsa_signature_functions[] = { + { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))dsa_newctx }, + { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))dsa_sign_init }, + { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))dsa_sign }, + { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))dsa_freectx }, + { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))dsa_dupctx }, + { OSSL_FUNC_SIGNATURE_SET_PARAMS, (void (*)(void))dsa_set_params }, + { 0, NULL } +}; diff --git a/providers/default/defltprov.c b/providers/default/defltprov.c index 8a950482c8..9ce918aea5 100644 --- a/providers/default/defltprov.c +++ b/providers/default/defltprov.c @@ -234,9 +234,20 @@ static const OSSL_ALGORITHM deflt_keyexch[] = { { NULL, NULL, NULL } }; +static const OSSL_ALGORITHM deflt_signature[] = { +#ifndef OPENSSL_NO_DSA + { "DSA", "default=yes", dsa_signature_functions }, +#endif + { NULL, NULL, NULL } +}; + + static const OSSL_ALGORITHM deflt_keymgmt[] = { #ifndef OPENSSL_NO_DH { "dhKeyAgreement", "default=yes", dh_keymgmt_functions }, +#endif +#ifndef OPENSSL_NO_DSA + { "DSA", "default=yes", dsa_keymgmt_functions }, #endif { NULL, NULL, NULL } }; @@ -259,6 +270,8 @@ static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov, return deflt_keymgmt; case OSSL_OP_KEYEXCH: return deflt_keyexch; + case OSSL_OP_SIGNATURE: + return deflt_signature; } return NULL; } diff --git a/util/libcrypto.num b/util/libcrypto.num index f2e64526b2..dd89bd3f4a 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4745,3 +4745,4 @@ EVP_SIGNATURE_up_ref 4861 3_0_0 EXIST::FUNCTION: EVP_SIGNATURE_provider 4862 3_0_0 EXIST::FUNCTION: EVP_SIGNATURE_fetch 4863 3_0_0 EXIST::FUNCTION: EVP_PKEY_sign_init_ex 4864 3_0_0 EXIST::FUNCTION: +EVP_PKEY_CTX_set_signature_md 4865 3_0_0 EXIST::FUNCTION: -- 2.39.2