Implement DSA in the default provider
authorMatt Caswell <matt@openssl.org>
Fri, 30 Aug 2019 12:33:37 +0000 (13:33 +0100)
committerMatt Caswell <matt@openssl.org>
Mon, 9 Sep 2019 13:00:00 +0000 (14:00 +0100)
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9753)

20 files changed:
crypto/dh/dh_ameth.c
crypto/dsa/dsa_ameth.c
crypto/dsa/dsa_gen.c
crypto/dsa/dsa_key.c
crypto/dsa/dsa_lib.c
crypto/dsa/dsa_locl.h
crypto/evp/pmeth_fn.c
crypto/evp/pmeth_lib.c
include/openssl/core_names.h
include/openssl/core_numbers.h
include/openssl/evp.h
providers/common/build.info
providers/common/include/internal/provider_algs.h
providers/common/keymgmt/build.info
providers/common/keymgmt/dh_kmgmt.c
providers/common/keymgmt/dsa_kmgmt.c [new file with mode: 0644]
providers/common/signature/build.info [new file with mode: 0644]
providers/common/signature/dsa.c [new file with mode: 0644]
providers/default/defltprov.c
util/libcrypto.num

index 6da4878..7b75bd1 100644 (file)
@@ -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;
     }
 
index ef6fc76..4e0ed01 100644 (file)
@@ -8,14 +8,16 @@
  */
 
 #include <stdio.h>
-#include "internal/cryptlib.h"
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
-#include "dsa_locl.h"
 #include <openssl/bn.h>
 #include <openssl/cms.h>
+#include <openssl/core_names.h>
+#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
+    }
 };
index 858f127..14cb8e9 100644 (file)
@@ -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)
index 333bff9..86f79b8 100644 (file)
@@ -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:
index 1068f1d..034300f 100644 (file)
@@ -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;
 }
index 5c464e7..e56ff06 100644 (file)
@@ -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 {
index 44ce64e..53f4dbb 100644 (file)
@@ -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;
             }
index 7041020..563a2bd 100644 (file)
@@ -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)
 {
index b78a097..5a75aaf 100644 (file)
@@ -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
index 61ec153..ea32053 100644 (file)
@@ -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
 }
index b09547a..dc70686 100644 (file)
@@ -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))
index b098ca6..916cc3e 100644 (file)
@@ -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
index b9d2576..92aa647 100644 (file)
@@ -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[];
index a41f3da..4e7bc75 100644 (file)
@@ -1,5 +1,5 @@
 LIBS=../../../libcrypto
 IF[{- !$disabled{dh} -}]
   SOURCE[../../../libcrypto]=\
-          dh_kmgmt.c
+          dh_kmgmt.c dsa_kmgmt.c
 ENDIF
index 67e3205..c13f075 100644 (file)
@@ -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 (file)
index 0000000..a53c0b2
--- /dev/null
@@ -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 (file)
index 0000000..5b64229
--- /dev/null
@@ -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 (file)
index 0000000..69f4978
--- /dev/null
@@ -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 }
+};
index 8a95048..9ce918a 100644 (file)
@@ -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;
 }
index f2e6452..dd89bd3 100644 (file)
@@ -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: