summaryrefslogtreecommitdiffstats
path: root/providers/common
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2019-08-30 13:33:37 +0100
committerMatt Caswell <matt@openssl.org>2019-09-09 14:00:00 +0100
commit4889dadcb8511176c30888c748f1981adc38451d (patch)
treeb27f1a2529e512f43344d7a62d89daa1bcc2407d /providers/common
parentdfcb5d29b525f5d2b6bd80602dca5efe5fca77bb (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.info2
-rw-r--r--providers/common/include/internal/provider_algs.h4
-rw-r--r--providers/common/keymgmt/build.info2
-rw-r--r--providers/common/keymgmt/dh_kmgmt.c4
-rw-r--r--providers/common/keymgmt/dsa_kmgmt.c91
-rw-r--r--providers/common/signature/build.info7
-rw-r--r--providers/common/signature/dsa.c132
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 }
+};