Add the ability to perform signatures in a provider
authorMatt Caswell <matt@openssl.org>
Fri, 30 Aug 2019 12:33:10 +0000 (13:33 +0100)
committerMatt Caswell <matt@openssl.org>
Mon, 9 Sep 2019 12:52:26 +0000 (13:52 +0100)
This makes EVP_PKEY_sign and EVP_PKEY_sign_init provider aware. It
also introduces the new type EVP_SIGNATURE to represent signature
algorithms. This also automatically makes the EVP_Sign* APIs provider
aware because they use EVP_Digest* (which is already provider aware)
and EVP_PKEY_sign(_init) under the covers.

At this stage there are no signature algorithms in any providers. That
will come in the following commits.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9753)

12 files changed:
crypto/cms/cms_sd.c
crypto/evp/digest.c
crypto/evp/evp_locl.h
crypto/evp/exchange.c
crypto/evp/pmeth_fn.c
crypto/evp/pmeth_lib.c
crypto/include/internal/evp_int.h
crypto/pkcs7/pk7_doit.c
include/openssl/core_numbers.h
include/openssl/evp.h
include/openssl/ossl_typ.h
util/libcrypto.num

index 4de750b..6715e84 100644 (file)
@@ -706,11 +706,23 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
         si->pctx = pctx;
     }
 
+    /*
+     * TODO(3.0): This causes problems when providers are in use, so disabled
+     * for now. Can we get rid of this completely? AFAICT this ctrl has been
+     * present since CMS was first put in - but has never been used to do
+     * anything. All internal implementations just return 1 and ignore this ctrl
+     * and have always done so by the looks of things. To fix this we could
+     * convert this ctrl into a param, which would require us to send all the
+     * signer info data as a set of params...but that is non-trivial and since
+     * this isn't used by anything it may be better just to remove it.
+     */
+#if 0
     if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
                           EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) {
         CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
         goto err;
     }
+#endif
 
     alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf,
                          ASN1_ITEM_rptr(CMS_Attributes_Sign));
@@ -727,11 +739,23 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
     if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
         goto err;
 
+    /*
+     * TODO(3.0): This causes problems when providers are in use, so disabled
+     * for now. Can we get rid of this completely? AFAICT this ctrl has been
+     * present since CMS was first put in - but has never been used to do
+     * anything. All internal implementations just return 1 and ignore this ctrl
+     * and have always done so by the looks of things. To fix this we could
+     * convert this ctrl into a param, which would require us to send all the
+     * signer info data as a set of params...but that is non-trivial and since
+     * this isn't used by anything it may be better just to remove it.
+     */
+#if 0
     if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
                           EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0) {
         CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR);
         goto err;
     }
+#endif
 
     EVP_MD_CTX_reset(mctx);
 
index 6cb9064..5ef7452 100644 (file)
@@ -266,8 +266,11 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
  skip_to_init:
 #endif
 #ifndef FIPS_MODE
-    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
-    if (ctx->pctx != NULL) {
+    /*
+     * TODO(3.0): Temporarily no support for EVP_DigestSign* inside FIPS module
+     * or when using providers.
+     */
+    if (ctx->pctx != NULL && ctx->pctx->signature == NULL) {
         int r;
         r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
                               EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
index 750e593..284be8c 100644 (file)
@@ -91,6 +91,11 @@ struct evp_keymgmt_st {
     OSSL_OP_keymgmt_exportkey_types_fn *exportkey_types;
 } /* EVP_KEYMGMT */ ;
 
+struct keymgmt_data_st {
+    OPENSSL_CTX *ctx;
+    const char *properties;
+};
+
 struct evp_keyexch_st {
     char *name;
     OSSL_PROVIDER *prov;
@@ -108,6 +113,22 @@ struct evp_keyexch_st {
     OSSL_OP_keyexch_set_params_fn *set_params;
 } /* EVP_KEYEXCH */;
 
+struct evp_signature_st {
+    char *name;
+    OSSL_PROVIDER *prov;
+    CRYPTO_REF_COUNT refcnt;
+    CRYPTO_RWLOCK *lock;
+
+    EVP_KEYMGMT *keymgmt;
+
+    OSSL_OP_signature_newctx_fn *newctx;
+    OSSL_OP_signature_sign_init_fn *sign_init;
+    OSSL_OP_signature_sign_fn *sign;
+    OSSL_OP_signature_freectx_fn *freectx;
+    OSSL_OP_signature_dupctx_fn *dupctx;
+    OSSL_OP_signature_set_params_fn *set_params;
+} /* EVP_SIGNATURE */;
+
 int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
                              int passlen, ASN1_TYPE *param,
                              const EVP_CIPHER *c, const EVP_MD *md,
index e69e4fd..e9b7259 100644 (file)
@@ -32,11 +32,6 @@ static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov)
     return exchange;
 }
 
-struct keymgmt_data_st {
-    OPENSSL_CTX *ctx;
-    const char *properties;
-};
-
 static void *evp_keyexch_from_dispatch(const char *name,
                                        const OSSL_DISPATCH *fns,
                                        OSSL_PROVIDER *prov,
index 51df2be..44ce64e 100644 (file)
 #include <openssl/evp.h>
 #include "internal/cryptlib.h"
 #include "internal/evp_int.h"
+#include "internal/provider.h"
 #include "evp_locl.h"
 
-int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
+static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov)
+{
+    EVP_SIGNATURE *signature = OPENSSL_zalloc(sizeof(EVP_SIGNATURE));
+
+    signature->lock = CRYPTO_THREAD_lock_new();
+    if (signature->lock == NULL) {
+        OPENSSL_free(signature);
+        return NULL;
+    }
+    signature->prov = prov;
+    ossl_provider_up_ref(prov);
+    signature->refcnt = 1;
+
+    return signature;
+}
+
+static void *evp_signature_from_dispatch(const char *name,
+                                         const OSSL_DISPATCH *fns,
+                                         OSSL_PROVIDER *prov,
+                                         void *vkeymgmt_data)
+{
+    /*
+     * Signature functions cannot work without a key, and key management
+     * from the same provider to manage its keys.  We therefore fetch
+     * a key management method using the same algorithm and properties
+     * and pass that down to evp_generic_fetch to be passed on to our
+     * evp_signature_from_dispatch, which will attach the key management
+     * method to the newly created key exchange method as long as the
+     * provider matches.
+     */
+    struct keymgmt_data_st *keymgmt_data = vkeymgmt_data;
+    EVP_KEYMGMT *keymgmt = EVP_KEYMGMT_fetch(keymgmt_data->ctx, name,
+                                             keymgmt_data->properties);
+    EVP_SIGNATURE *signature = NULL;
+    int fncnt = 0;
+
+    if (keymgmt == NULL || EVP_KEYMGMT_provider(keymgmt) != prov) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEYMGMT_AVAILABLE);
+        goto err;
+    }
+
+    if ((signature = evp_signature_new(prov)) == NULL
+        || (signature->name = OPENSSL_strdup(name)) == NULL) {
+        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    signature->keymgmt = keymgmt;
+    keymgmt = NULL;              /* avoid double free on failure below */
+
+    for (; fns->function_id != 0; fns++) {
+        switch (fns->function_id) {
+        case OSSL_FUNC_SIGNATURE_NEWCTX:
+            if (signature->newctx != NULL)
+                break;
+            signature->newctx = OSSL_get_OP_signature_newctx(fns);
+            fncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_SIGN_INIT:
+            if (signature->sign_init != NULL)
+                break;
+            signature->sign_init = OSSL_get_OP_signature_sign_init(fns);
+            fncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_SIGN:
+            if (signature->sign != NULL)
+                break;
+            signature->sign = OSSL_get_OP_signature_sign(fns);
+            fncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_FREECTX:
+            if (signature->freectx != NULL)
+                break;
+            signature->freectx = OSSL_get_OP_signature_freectx(fns);
+            fncnt++;
+            break;
+        case OSSL_FUNC_SIGNATURE_DUPCTX:
+            if (signature->dupctx != NULL)
+                break;
+            signature->dupctx = OSSL_get_OP_signature_dupctx(fns);
+            break;
+        case OSSL_FUNC_SIGNATURE_SET_PARAMS:
+            if (signature->set_params != NULL)
+                break;
+            signature->set_params = OSSL_get_OP_signature_set_params(fns);
+            break;
+        }
+    }
+    if (fncnt != 4) {
+        /*
+         * In order to be a consistent set of functions we must have at least
+         * a complete set of "signature" functions: sign_init, sign, newctx,
+         * and freectx. The dupctx function is optional.
+         */
+        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+        goto err;
+    }
+
+    return signature;
+ err:
+    EVP_SIGNATURE_free(signature);
+    EVP_KEYMGMT_free(keymgmt);
+    return NULL;
+}
+
+void EVP_SIGNATURE_free(EVP_SIGNATURE *signature)
+{
+    if (signature != NULL) {
+        int i;
+
+        CRYPTO_DOWN_REF(&signature->refcnt, &i, signature->lock);
+        if (i > 0)
+            return;
+        EVP_KEYMGMT_free(signature->keymgmt);
+        ossl_provider_free(signature->prov);
+        OPENSSL_free(signature->name);
+        CRYPTO_THREAD_lock_free(signature->lock);
+        OPENSSL_free(signature);
+    }
+}
+
+int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature)
+{
+    int ref = 0;
+
+    CRYPTO_UP_REF(&signature->refcnt, &ref, signature->lock);
+    return 1;
+}
+
+OSSL_PROVIDER *EVP_SIGNATURE_provider(const EVP_SIGNATURE *signature)
+{
+    return signature->prov;
+}
+
+EVP_SIGNATURE *EVP_SIGNATURE_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                                   const char *properties)
+{
+    struct keymgmt_data_st keymgmt_data;
+
+    /*
+     * A signature operation cannot work without a key, so we need key
+     * management from the same provider to manage its keys.
+     */
+    keymgmt_data.ctx = ctx;
+    keymgmt_data.properties = properties;
+    return evp_generic_fetch(ctx, OSSL_OP_SIGNATURE, algorithm, properties,
+                             evp_signature_from_dispatch, &keymgmt_data,
+                             (int (*)(void *))EVP_SIGNATURE_up_ref,
+                             (void (*)(void *))EVP_SIGNATURE_free);
+}
+
+int EVP_PKEY_sign_init_ex(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature)
 {
     int ret;
-    if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
-        EVPerr(EVP_F_EVP_PKEY_SIGN_INIT,
-               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+    void *provkey = NULL;
+
+    if (ctx == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
         return -2;
     }
+
     ctx->operation = EVP_PKEY_OP_SIGN;
-    if (!ctx->pmeth->sign_init)
+
+    if (ctx->engine != NULL)
+        goto legacy;
+
+    if (signature != NULL) {
+        if (!EVP_SIGNATURE_up_ref(signature))
+            goto err;
+    } else {
+        int nid = ctx->pkey != NULL ? ctx->pkey->type : ctx->pmeth->pkey_id;
+
+        /*
+         * TODO(3.0): Check for legacy handling. Remove this once all all
+         * algorithms are moved to providers.
+         */
+        if (ctx->pkey != NULL) {
+            switch (ctx->pkey->type) {
+            default:
+                goto legacy;
+            }
+            signature = EVP_SIGNATURE_fetch(NULL, OBJ_nid2sn(nid), NULL);
+        } else {
+            goto legacy;
+        }
+
+        if (signature == NULL) {
+            EVPerr(0, EVP_R_INITIALIZATION_ERROR);
+            goto err;
+        }
+    }
+
+    if (ctx->sigprovctx != NULL && ctx->signature != NULL)
+        ctx->signature->freectx(ctx->sigprovctx);
+    EVP_SIGNATURE_free(ctx->signature);
+    ctx->signature = signature;
+    if (ctx->pkey != NULL) {
+        provkey = evp_keymgmt_export_to_provider(ctx->pkey, signature->keymgmt);
+        if (provkey == NULL) {
+            EVPerr(0, EVP_R_INITIALIZATION_ERROR);
+            goto err;
+        }
+    }
+    ctx->sigprovctx = signature->newctx(ossl_provider_ctx(signature->prov));
+    if (ctx->sigprovctx == NULL) {
+        /* The provider key can stay in the cache */
+        EVPerr(0, EVP_R_INITIALIZATION_ERROR);
+        goto err;
+    }
+    ret = signature->sign_init(ctx->sigprovctx, provkey);
+
+    return ret ? 1 : 0;
+ err:
+    ctx->operation = EVP_PKEY_OP_UNDEFINED;
+    return 0;
+
+ legacy:
+    if (ctx->pmeth == NULL || ctx->pmeth->sign == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    if (ctx->pmeth->sign_init == NULL)
         return 1;
     ret = ctx->pmeth->sign_init(ctx);
     if (ret <= 0)
@@ -32,19 +246,41 @@ int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
     return ret;
 }
 
+int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
+{
+    return EVP_PKEY_sign_init_ex(ctx, NULL);
+}
+
 int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
                   unsigned char *sig, size_t *siglen,
                   const unsigned char *tbs, size_t tbslen)
 {
-    if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
-        EVPerr(EVP_F_EVP_PKEY_SIGN,
-               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+    int ret;
+
+    if (ctx == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
         return -2;
     }
+
     if (ctx->operation != EVP_PKEY_OP_SIGN) {
-        EVPerr(EVP_F_EVP_PKEY_SIGN, EVP_R_OPERATON_NOT_INITIALIZED);
+        EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED);
         return -1;
     }
+
+    if (ctx->sigprovctx == NULL)
+        goto legacy;
+
+    ret = ctx->signature->sign(ctx->sigprovctx, sig, siglen, SIZE_MAX,
+                               tbs, tbslen);
+
+    return ret;
+ legacy:
+    if (ctx->pmeth == NULL || ctx->pmeth->sign == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
     M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN)
         return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen);
 }
index d2b28f8..7041020 100644 (file)
@@ -390,6 +390,11 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
 
     EVP_KEYEXCH_free(ctx->exchange);
 
+    if (ctx->sigprovctx != NULL && ctx->signature != NULL)
+        ctx->signature->freectx(ctx->sigprovctx);
+
+    EVP_SIGNATURE_free(ctx->signature);
+
     EVP_PKEY_free(ctx->pkey);
     EVP_PKEY_free(ctx->peerkey);
 #ifndef OPENSSL_NO_ENGINE
@@ -402,6 +407,8 @@ int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
 {
     if (ctx->exchprovctx != NULL && ctx->exchange != NULL)
         return ctx->exchange->set_params(ctx->exchprovctx, params);
+    if (ctx->sigprovctx != NULL && ctx->signature != NULL)
+        return ctx->signature->set_params(ctx->sigprovctx, params);
     return 0;
 }
 
index d54edc7..2b49e68 100644 (file)
@@ -21,6 +21,9 @@ struct evp_pkey_ctx_st {
     EVP_KEYEXCH *exchange;
     void *exchprovctx;
 
+    EVP_SIGNATURE *signature;
+    void *sigprovctx;
+
     /* Legacy fields below */
 
     /* Method associated with this operation */
index 3827709..cc09bbf 100644 (file)
@@ -834,11 +834,29 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
     if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0)
         goto err;
 
+    /*
+     * TODO(3.0): This causes problems when providers are in use, so disabled
+     * for now. Can we get rid of this completely? AFAICT this ctrl has never
+     * been used since it was first put in. All internal implementations just
+     * return 1 and ignore this ctrl and have always done so by the looks of
+     * things. To fix this we could convert this ctrl into a param, which would
+     * require us to send all the signer info data as a set of params...but that
+     * is non-trivial and since this isn't used by anything it may be better
+     * just to remove it. The original commit that added it had this
+     * justification in CHANGES:
+     *
+     * "During PKCS7 signing pass the PKCS7 SignerInfo structure to the
+     *  EVP_PKEY_METHOD before and after signing via the
+     *  EVP_PKEY_CTRL_PKCS7_SIGN ctrl. It can then customise the structure
+     *  before and/or after signing if necessary."
+     */
+#if 0
     if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
                           EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) {
         PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
         goto err;
     }
+#endif
 
     alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf,
                          ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
@@ -856,11 +874,29 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
     if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
         goto err;
 
+    /*
+     * TODO(3.0): This causes problems when providers are in use, so disabled
+     * for now. Can we get rid of this completely? AFAICT this ctrl has never
+     * been used since it was first put in. All internal implementations just
+     * return 1 and ignore this ctrl and have always done so by the looks of
+     * things. To fix this we could convert this ctrl into a param, which would
+     * require us to send all the signer info data as a set of params...but that
+     * is non-trivial and since this isn't used by anything it may be better
+     * just to remove it. The original commit that added it had this
+     * justification in CHANGES:
+     *
+     * "During PKCS7 signing pass the PKCS7 SignerInfo structure to the
+     *  EVP_PKEY_METHOD before and after signing via the
+     *  EVP_PKEY_CTRL_PKCS7_SIGN ctrl. It can then customise the structure
+     *  before and/or after signing if necessary."
+     */
+#if 0
     if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
                           EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) {
         PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
         goto err;
     }
+#endif
 
     EVP_MD_CTX_free(mctx);
 
index 521cd8c..61ec153 100644 (file)
@@ -156,8 +156,9 @@ OSSL_CORE_MAKE_FUNC(const OSSL_ITEM *,provider_get_reason_strings,
 # define OSSL_OP_KDF                                 4
 # define OSSL_OP_KEYMGMT                            10
 # define OSSL_OP_KEYEXCH                            11
+# define OSSL_OP_SIGNATURE                          12
 /* Highest known operation number */
-# define OSSL_OP__HIGHEST                           11
+# define OSSL_OP__HIGHEST                           12
 
 /* Digests */
 
@@ -400,6 +401,23 @@ OSSL_CORE_MAKE_FUNC(void *, OP_keyexch_dupctx, (void *ctx))
 OSSL_CORE_MAKE_FUNC(int, OP_keyexch_set_params, (void *ctx,
                                                  const OSSL_PARAM params[]))
 
+/* Signature */
+
+# define OSSL_FUNC_SIGNATURE_NEWCTX                  1
+# define OSSL_FUNC_SIGNATURE_SIGN_INIT               2
+# define OSSL_FUNC_SIGNATURE_SIGN                    3
+# define OSSL_FUNC_SIGNATURE_FREECTX                 4
+# define OSSL_FUNC_SIGNATURE_DUPCTX                  5
+
+OSSL_CORE_MAKE_FUNC(void *, OP_signature_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, OP_signature_sign_init, (void *ctx, void *provkey))
+OSSL_CORE_MAKE_FUNC(int, OP_signature_sign, (void *ctx,  unsigned char *sig,
+                                             size_t *siglen, size_t sigsize,
+                                             const unsigned char *tbs,
+                                             size_t tbslen))
+OSSL_CORE_MAKE_FUNC(void, OP_signature_freectx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(void *, OP_signature_dupctx, (void *ctx))
+
 # ifdef __cplusplus
 }
 # endif
index d1bd0b6..b09547a 100644 (file)
@@ -1470,6 +1470,13 @@ EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx);
 void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
 void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
 
+void EVP_SIGNATURE_free(EVP_SIGNATURE *signature);
+int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature);
+OSSL_PROVIDER *EVP_SIGNATURE_provider(const EVP_SIGNATURE *signature);
+EVP_SIGNATURE *EVP_SIGNATURE_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                                   const char *properties);
+
+int EVP_PKEY_sign_init_ex(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature);
 int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
                   unsigned char *sig, size_t *siglen,
index 7eec053..530de2d 100644 (file)
@@ -108,6 +108,8 @@ typedef struct evp_kdf_ctx_st EVP_KDF_CTX;
 
 typedef struct evp_keyexch_st EVP_KEYEXCH;
 
+typedef struct evp_signature_st EVP_SIGNATURE;
+
 typedef struct evp_Encode_Ctx_st EVP_ENCODE_CTX;
 
 typedef struct hmac_ctx_st HMAC_CTX;
index 442a6bb..f2e6452 100644 (file)
@@ -4740,3 +4740,8 @@ EVP_KDF_gettable_params                 4856      3_0_0   EXIST::FUNCTION:
 EVP_KDF_CTX_gettable_params             4857   3_0_0   EXIST::FUNCTION:
 EVP_KDF_CTX_settable_params             4858   3_0_0   EXIST::FUNCTION:
 EVP_KDF_do_all_ex                       4859   3_0_0   EXIST::FUNCTION:
+EVP_SIGNATURE_free                      4860   3_0_0   EXIST::FUNCTION:
+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: