diff options
author | Matt Caswell <matt@openssl.org> | 2019-08-30 13:33:37 +0100 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2019-09-09 14:00:00 +0100 |
commit | 4889dadcb8511176c30888c748f1981adc38451d (patch) | |
tree | b27f1a2529e512f43344d7a62d89daa1bcc2407d /providers/common | |
parent | dfcb5d29b525f5d2b6bd80602dca5efe5fca77bb (diff) |
Implement DSA in the default provider
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9753)
Diffstat (limited to 'providers/common')
-rw-r--r-- | providers/common/build.info | 2 | ||||
-rw-r--r-- | providers/common/include/internal/provider_algs.h | 4 | ||||
-rw-r--r-- | providers/common/keymgmt/build.info | 2 | ||||
-rw-r--r-- | providers/common/keymgmt/dh_kmgmt.c | 4 | ||||
-rw-r--r-- | providers/common/keymgmt/dsa_kmgmt.c | 91 | ||||
-rw-r--r-- | providers/common/signature/build.info | 7 | ||||
-rw-r--r-- | providers/common/signature/dsa.c | 132 |
7 files changed, 238 insertions, 4 deletions
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 <openssl/core_numbers.h> +#include <openssl/core_names.h> +#include <openssl/bn.h> +#include <openssl/dsa.h> +#include <openssl/params.h> +#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 <openssl/crypto.h> +#include <openssl/core_numbers.h> +#include <openssl/core_names.h> +#include <openssl/dsa.h> +#include <openssl/params.h> +#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 } +}; |