[openssl] master update

Richard Levitte levitte at openssl.org
Tue Sep 8 10:09:06 UTC 2020


The branch master has been updated
       via  8d6481f532ab8c502de2ad17e09f688abb675a71 (commit)
       via  b968945204130620b1328f585610cbe1d6b5a69e (commit)
       via  86df26b3943509219057ae87f8764b3c15e0d8b8 (commit)
      from  ea0add4a822749d620714a4660eedd86a91e8e1b (commit)


- Log -----------------------------------------------------------------
commit 8d6481f532ab8c502de2ad17e09f688abb675a71
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Sep 4 18:00:29 2020 +0200

    EVP: Move the functions and controls for setting and getting distid
    
    Those functions were located in the EC files, but is really broader
    than that, even thought currently only used for SM2.  They should
    therefore be in a more central location, which was also indicated by
    diverse TODOs.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12789)

commit b968945204130620b1328f585610cbe1d6b5a69e
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Sep 3 07:22:00 2020 +0200

    EVP: Expand the use of EVP_PKEY_CTX_md()
    
    Setting a hash function was reserved for signature operations.
    However, it turns out that SM2 uses a hash function for encryption and
    decryption as well.
    Therefore, EVP_PKEY_CTX_md() must be called with an expanded operation
    type combination that includes EVP_PKEY_OP_TYPE_CRYPT when used in a
    generic way.
    
    For SM2, test/recipes/30-test_evp_data/evppkey_sm2.txt is expanded to
    test decryption both with an implicit and an explicit digest.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12789)

commit 86df26b3943509219057ae87f8764b3c15e0d8b8
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Sep 2 15:54:13 2020 +0200

    EVP: Add support for delayed EVP_PKEY operation parameters
    
    They get called "delayed parameters" because they may make it to the
    implementation at a later time than when they're given.
    
    This currently only covers the distinguished ID, as that's the only
    EVP_PKEY operation parameter so far that has been possible to give
    before the operation has been initialized.
    
    This includes a re-implementation of EVP_PKEY_CTX_set1_id(),
    EVP_PKEY_CTX_get1_id(), and EVP_PKEY_CTX_get1_id_len().
    
    Also, the more rigorous controls of keytype and optype are restored.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12789)

-----------------------------------------------------------------------

Summary of changes:
 crypto/evp/m_sigver.c                         |  13 +-
 crypto/evp/pmeth_lib.c                        | 369 ++++++++++++++++++++++----
 crypto/evp/signature.c                        |   9 +-
 include/crypto/evp.h                          |  21 ++
 include/openssl/core_names.h                  |   1 +
 include/openssl/ec.h                          |  16 --
 include/openssl/evp.h                         |   8 +-
 test/recipes/30-test_evp_data/evppkey_sm2.txt |   6 +
 util/libcrypto.num                            |   3 +
 9 files changed, 376 insertions(+), 70 deletions(-)

diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
index 0278d9ca09..a60d6e770b 100644
--- a/crypto/evp/m_sigver.c
+++ b/crypto/evp/m_sigver.c
@@ -204,7 +204,8 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                                           mdname, provkey);
     }
 
-    return ret ? 1 : 0;
+    goto end;
+
  err:
     evp_pkey_ctx_free_old_ops(locpctx);
     locpctx->operation = EVP_PKEY_OP_UNDEFINED;
@@ -279,7 +280,15 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     if (ctx->pctx->pmeth->digest_custom != NULL)
         ctx->pctx->flag_call_digest_custom = 1;
 
-    return 1;
+    ret = 1;
+
+ end:
+#ifndef FIPS_MODULE
+    if (ret > 0)
+        ret = evp_pkey_ctx_use_cached_data(locpctx);
+#endif
+
+    return ret > 0 ? 1 : 0;
 }
 
 int EVP_DigestSignInit_with_libctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 7f144b0afc..e557e14e18 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -33,6 +33,14 @@
 
 #ifndef FIPS_MODULE
 
+static int evp_pkey_ctx_store_cached_data(EVP_PKEY_CTX *ctx,
+                                          int keytype, int optype,
+                                          int cmd, const char *name,
+                                          const void *data, size_t data_len);
+static void evp_pkey_ctx_free_cached_data(EVP_PKEY_CTX *ctx,
+                                          int cmd, const char *name);
+static void evp_pkey_ctx_free_all_cached_data(EVP_PKEY_CTX *ctx);
+
 typedef const EVP_PKEY_METHOD *(*pmeth_fn)(void);
 typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
 
@@ -122,6 +130,29 @@ EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
     return pmeth;
 }
 
+/* Three possible states: */
+# define EVP_PKEY_STATE_UNKNOWN         0
+# define EVP_PKEY_STATE_LEGACY          1
+# define EVP_PKEY_STATE_PROVIDER        2
+
+static int evp_pkey_ctx_state(EVP_PKEY_CTX *ctx)
+{
+    if (ctx->operation == EVP_PKEY_OP_UNDEFINED)
+        return EVP_PKEY_STATE_UNKNOWN;
+
+    if ((EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
+         && ctx->op.kex.exchprovctx != NULL)
+        || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+            && ctx->op.sig.sigprovctx != NULL)
+        || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
+            && ctx->op.ciph.ciphprovctx != NULL)
+        || (EVP_PKEY_CTX_IS_GEN_OP(ctx)
+            && ctx->op.keymgmt.genctx != NULL))
+        return EVP_PKEY_STATE_PROVIDER;
+
+    return EVP_PKEY_STATE_LEGACY;
+}
+
 static void help_get_legacy_alg_type_from_keymgmt(const char *keytype,
                                                   void *arg)
 {
@@ -388,6 +419,9 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
         ctx->pmeth->cleanup(ctx);
 
     evp_pkey_ctx_free_old_ops(ctx);
+#ifndef FIPS_MODULE
+    evp_pkey_ctx_free_all_cached_data(ctx);
+#endif
     EVP_KEYMGMT_free(ctx->keymgmt);
 
     EVP_PKEY_free(ctx->pkey);
@@ -1065,9 +1099,100 @@ int EVP_PKEY_CTX_set_mac_key(EVP_PKEY_CTX *ctx, const unsigned char *key,
                                           key, keylen);
 }
 
+int evp_pkey_ctx_set1_id_prov(EVP_PKEY_CTX *ctx, const void *id, int len)
+{
+    OSSL_PARAM params[2], *p = params;
+    int ret;
+
+    if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_DIST_ID,
+                                             /*
+                                              * Cast away the const. This is
+                                              * read only so should be safe
+                                              */
+                                             (void *)id, (size_t)len);
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_set_params_strict(ctx, params);
+    if (ret == -2)
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+    return ret;
+}
+
+int EVP_PKEY_CTX_set1_id(EVP_PKEY_CTX *ctx, const void *id, int len)
+{
+    return EVP_PKEY_CTX_ctrl(ctx, -1, -1,
+                             EVP_PKEY_CTRL_SET1_ID, (int)len, (void*)(id));
+}
+
+static int get1_id_data(EVP_PKEY_CTX *ctx, void *id, size_t *id_len)
+{
+    int ret;
+    void *tmp_id = NULL;
+    OSSL_PARAM params[2], *p = params;
+
+    if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_PKEY_PARAM_DIST_ID,
+                                          &tmp_id, 0);
+    *p++ = OSSL_PARAM_construct_end();
+
+    ret = evp_pkey_ctx_get_params_strict(ctx, params);
+    if (ret == -2) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+    } else if (ret > 0) {
+        size_t tmp_id_len = params[0].return_size;
+
+        if (id != NULL)
+            memcpy(id, tmp_id, tmp_id_len);
+        if (id_len != NULL)
+            *id_len = tmp_id_len;
+    }
+    return ret;
+}
+
+int evp_pkey_ctx_get1_id_prov(EVP_PKEY_CTX *ctx, void *id)
+{
+    return get1_id_data(ctx, id, NULL);
+}
+
+int evp_pkey_ctx_get1_id_len_prov(EVP_PKEY_CTX *ctx, size_t *id_len)
+{
+    return get1_id_data(ctx, NULL, id_len);
+}
+
+int EVP_PKEY_CTX_get1_id(EVP_PKEY_CTX *ctx, void *id)
+{
+    return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_GET1_ID, 0, (void*)id);
+}
+
+int EVP_PKEY_CTX_get1_id_len(EVP_PKEY_CTX *ctx, size_t *id_len)
+{
+    return EVP_PKEY_CTX_ctrl(ctx, -1, -1,
+                             EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)id_len);
+}
+
 static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
                                 int cmd, int p1, void *p2)
 {
+    switch (cmd) {
+    case EVP_PKEY_CTRL_SET1_ID:
+        return evp_pkey_ctx_set1_id_prov(ctx, p2, p1);
+    case EVP_PKEY_CTRL_GET1_ID:
+        return evp_pkey_ctx_get1_id_prov(ctx, p2);
+    case EVP_PKEY_CTRL_GET1_ID_LEN:
+        return evp_pkey_ctx_get1_id_len_prov(ctx, p2);
+    }
+
 # ifndef OPENSSL_NO_DH
     if (keytype == EVP_PKEY_DHX) {
         switch (cmd) {
@@ -1281,53 +1406,77 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
     return 0;
 }
 
-int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
-                      int cmd, int p1, void *p2)
+static int evp_pkey_ctx_ctrl_int(EVP_PKEY_CTX *ctx, int keytype, int optype,
+                                 int cmd, int p1, void *p2)
 {
-    int ret;
+    int ret = 0;
 
     if (ctx == NULL) {
-        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
+        EVPerr(0, EVP_R_COMMAND_NOT_SUPPORTED);
         return -2;
     }
 
-    if ((EVP_PKEY_CTX_IS_DERIVE_OP(ctx) && ctx->op.kex.exchprovctx != NULL)
-            || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
-                && ctx->op.sig.sigprovctx != NULL)
-            || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
-                && ctx->op.ciph.ciphprovctx != NULL)
-            || (EVP_PKEY_CTX_IS_GEN_OP(ctx)
-                && ctx->op.keymgmt.genctx != NULL))
-        return legacy_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2);
+    /*
+     * If the method has a |digest_custom| function, we can relax the
+     * operation type check, since this can be called before the operation
+     * is initialized.
+     */
+    if (ctx->pmeth == NULL || ctx->pmeth->digest_custom == NULL) {
+        if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
+            EVPerr(0, EVP_R_NO_OPERATION_SET);
+            return -1;
+        }
 
-    if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) {
-        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
-        return -2;
+        if ((optype != -1) && !(ctx->operation & optype)) {
+            EVPerr(0, EVP_R_INVALID_OPERATION);
+            return -1;
+        }
     }
-    if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
-        return -1;
 
-    /* Skip the operation checks since this is called in a very early stage */
-    if (ctx->pmeth->digest_custom != NULL)
-        goto doit;
+    switch (evp_pkey_ctx_state(ctx)) {
+    case EVP_PKEY_STATE_PROVIDER:
+        return legacy_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2);
+    case EVP_PKEY_STATE_UNKNOWN:
+    case EVP_PKEY_STATE_LEGACY:
+        if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) {
+            EVPerr(0, EVP_R_COMMAND_NOT_SUPPORTED);
+            return -2;
+        }
+        if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
+            return -1;
 
-    if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
-        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET);
-        return -1;
-    }
+        ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
 
-    if ((optype != -1) && !(ctx->operation & optype)) {
-        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION);
-        return -1;
+        if (ret == -2)
+            EVPerr(0, EVP_R_COMMAND_NOT_SUPPORTED);
+        break;
     }
+    return ret;
+}
 
- doit:
-    ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
+int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
+                      int cmd, int p1, void *p2)
+{
+    int ret = 0;
 
-    if (ret == -2)
-        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
+    /* If unsupported, we don't want that reported here */
+    ERR_set_mark();
+    ret = evp_pkey_ctx_store_cached_data(ctx, keytype, optype,
+                                         cmd, NULL, p2, p1);
+    if (ret == -2) {
+        ERR_pop_to_mark();
+    } else {
+        ERR_clear_last_mark();
+        /*
+         * If there was an error, there was an error.
+         * If the operation isn't initialized yet, we also return, as
+         * the saved values will be used then anyway.
+         */
+        if (ret < 1 || ctx->operation == EVP_PKEY_OP_UNDEFINED)
+            return ret;
+    }
 
-    return ret;
+    return evp_pkey_ctx_ctrl_int(ctx, keytype, optype, cmd, p1, p2);
 }
 
 int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
@@ -1429,31 +1578,153 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
     }
 }
 
-int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
-                          const char *name, const char *value)
+static int evp_pkey_ctx_ctrl_str_int(EVP_PKEY_CTX *ctx,
+                                     const char *name, const char *value)
 {
+    int ret = 0;
+
     if (ctx == NULL) {
-        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
+        EVPerr(0, EVP_R_COMMAND_NOT_SUPPORTED);
         return -2;
     }
 
-    if ((EVP_PKEY_CTX_IS_DERIVE_OP(ctx) && ctx->op.kex.exchprovctx != NULL)
-            || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
-                && ctx->op.sig.sigprovctx != NULL)
-            || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
-                && ctx->op.ciph.ciphprovctx != NULL)
-            || (EVP_PKEY_CTX_IS_GEN_OP(ctx)
-                && ctx->op.keymgmt.genctx != NULL))
+    switch (evp_pkey_ctx_state(ctx)) {
+    case EVP_PKEY_STATE_PROVIDER:
         return legacy_ctrl_str_to_param(ctx, name, value);
+    case EVP_PKEY_STATE_UNKNOWN:
+    case EVP_PKEY_STATE_LEGACY:
+        if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->ctrl_str == NULL) {
+            EVPerr(0, EVP_R_COMMAND_NOT_SUPPORTED);
+            return -2;
+        }
+        if (strcmp(name, "digest") == 0)
+            ret = EVP_PKEY_CTX_md(ctx,
+                                  EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
+                                  EVP_PKEY_CTRL_MD, value);
+        else
+            ret = ctx->pmeth->ctrl_str(ctx, name, value);
+        break;
+    }
 
-    if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) {
-        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
-        return -2;
+    return ret;
+}
+
+int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
+                          const char *name, const char *value)
+{
+    int ret = 0;
+
+    /* If unsupported, we don't want that reported here */
+    ERR_set_mark();
+    ret = evp_pkey_ctx_store_cached_data(ctx, -1, -1, -1,
+                                         name, value, strlen(value) + 1);
+    if (ret == -2) {
+        ERR_pop_to_mark();
+    } else {
+        ERR_clear_last_mark();
+        /*
+         * If there was an error, there was an error.
+         * If the operation isn't initialized yet, we also return, as
+         * the saved values will be used then anyway.
+         */
+        if (ret < 1 || ctx->operation == EVP_PKEY_OP_UNDEFINED)
+            return ret;
     }
-    if (strcmp(name, "digest") == 0)
-        return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD,
-                               value);
-    return ctx->pmeth->ctrl_str(ctx, name, value);
+
+    return evp_pkey_ctx_ctrl_str_int(ctx, name, value);
+}
+
+static int decode_cmd(int cmd, const char *name)
+{
+    if (cmd == -1) {
+        /*
+         * The consequence of the assertion not being true is that this
+         * function will return -1, which will cause the calling functions
+         * to signal that the command is unsupported...  in non-debug mode.
+         */
+        if (ossl_assert(name != NULL))
+            if (strcmp(name, "distid") == 0 || strcmp(name, "hexdistid") == 0)
+                cmd = EVP_PKEY_CTRL_SET1_ID;
+    }
+
+    return cmd;
+}
+
+static int evp_pkey_ctx_store_cached_data(EVP_PKEY_CTX *ctx,
+                                          int keytype, int optype,
+                                          int cmd, const char *name,
+                                          const void *data, size_t data_len)
+{
+    if ((keytype != -1 && ctx->pmeth->pkey_id != keytype)
+        || ((optype != -1) && !(ctx->operation & optype))) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+        return -1;
+    }
+
+    cmd = decode_cmd(cmd, name);
+    switch (cmd) {
+    case EVP_PKEY_CTRL_SET1_ID:
+        evp_pkey_ctx_free_cached_data(ctx, cmd, name);
+        if (name != NULL) {
+            ctx->cached_parameters.dist_id_name = OPENSSL_strdup(name);
+            if (ctx->cached_parameters.dist_id_name == NULL) {
+                ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+                return 0;
+            }
+        }
+        if (data_len > 0) {
+            ctx->cached_parameters.dist_id = OPENSSL_memdup(data, data_len);
+            if (ctx->cached_parameters.dist_id == NULL) {
+                ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+                return 0;
+            }
+        }
+        ctx->cached_parameters.dist_id_set = 1;
+        ctx->cached_parameters.dist_id_len = data_len;
+        return 1;
+    }
+
+    ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+    return -2;
+}
+
+static void evp_pkey_ctx_free_cached_data(EVP_PKEY_CTX *ctx,
+                                          int cmd, const char *name)
+{
+    cmd = decode_cmd(cmd, name);
+    switch (cmd) {
+    case EVP_PKEY_CTRL_SET1_ID:
+        OPENSSL_free(ctx->cached_parameters.dist_id);
+        OPENSSL_free(ctx->cached_parameters.dist_id_name);
+        ctx->cached_parameters.dist_id = NULL;
+        ctx->cached_parameters.dist_id_name = NULL;
+        break;
+    }
+}
+
+static void evp_pkey_ctx_free_all_cached_data(EVP_PKEY_CTX *ctx)
+{
+    evp_pkey_ctx_free_cached_data(ctx, EVP_PKEY_CTRL_SET1_ID, NULL);
+}
+
+int evp_pkey_ctx_use_cached_data(EVP_PKEY_CTX *ctx)
+{
+    int ret = 1;
+
+    if (ret && ctx->cached_parameters.dist_id_set) {
+        const char *name = ctx->cached_parameters.dist_id_name;
+        const void *val = ctx->cached_parameters.dist_id;
+        size_t len = ctx->cached_parameters.dist_id_len;
+
+        if (name != NULL)
+            ret = evp_pkey_ctx_ctrl_str_int(ctx, name, val);
+        else
+            ret = evp_pkey_ctx_ctrl_int(ctx, -1, ctx->operation,
+                                        EVP_PKEY_CTRL_SET1_ID,
+                                        (int)len, (void *)val);
+    }
+
+    return ret;
 }
 
 /* Utility functions to send a string of hex string to a ctrl */
diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c
index 67242f59be..7a2af1b5a2 100644
--- a/crypto/evp/signature.c
+++ b/crypto/evp/signature.c
@@ -482,7 +482,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
         ctx->op.sig.sigprovctx = NULL;
         goto err;
     }
-    return 1;
+    goto end;
 
  legacy:
     /*
@@ -523,8 +523,13 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
     }
     if (ret <= 0)
         goto err;
-    return ret;
+ end:
+#ifndef FIPS_MODULE
+    if (ret > 0)
+        ret = evp_pkey_ctx_use_cached_data(ctx);
+#endif
 
+    return ret;
  err:
     evp_pkey_ctx_free_old_ops(ctx);
     ctx->operation = EVP_PKEY_OP_UNDEFINED;
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
index 43ecc79f52..7008e490e8 100644
--- a/include/crypto/evp.h
+++ b/include/crypto/evp.h
@@ -52,6 +52,21 @@ struct evp_pkey_ctx_st {
         } ciph;
     } op;
 
+    /*
+     * Cached parameters.  Inits of operations that depend on these should
+     * call evp_pkey_ctx_use_delayed_data() when the operation has been set
+     * up properly.
+     */
+    struct {
+        /* Distinguishing Identifier, ISO/IEC 15946-3, FIPS 196 */
+        char *dist_id_name; /* The name used with EVP_PKEY_CTX_ctrl_str() */
+        void *dist_id;      /* The distinguishing ID itself */
+        size_t dist_id_len; /* The length of the distinguishing ID */
+
+        /* Indicators of what has been set.  Keep them together! */
+        unsigned int dist_id_set : 1;
+    } cached_parameters;
+
     /* Application specific data, usually used by the callback */
     void *app_data;
     /* Keygen callback */
@@ -769,6 +784,12 @@ EVP_MD_CTX *evp_md_ctx_new_with_libctx(EVP_PKEY *pkey,
                                        const ASN1_OCTET_STRING *id,
                                        OPENSSL_CTX *libctx, const char *propq);
 int evp_pkey_name2type(const char *name);
+
+int evp_pkey_ctx_set1_id_prov(EVP_PKEY_CTX *ctx, const void *id, int len);
+int evp_pkey_ctx_get1_id_prov(EVP_PKEY_CTX *ctx, void *id);
+int evp_pkey_ctx_get1_id_len_prov(EVP_PKEY_CTX *ctx, size_t *id_len);
+
+int evp_pkey_ctx_use_cached_data(EVP_PKEY_CTX *ctx);
 #endif /* !defined(FIPS_MODULE) */
 void evp_method_store_flush(OPENSSL_CTX *libctx);
 int evp_set_default_properties_int(OPENSSL_CTX *libctx, const char *propq,
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index fc8d2cea02..932dae932e 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -261,6 +261,7 @@ extern "C" {
 #define OSSL_PKEY_PARAM_MGF1_PROPERTIES     "mgf1-properties"
 #define OSSL_PKEY_PARAM_TLS_ENCODED_PT      "tls-encoded-pt"
 #define OSSL_PKEY_PARAM_GROUP_NAME          "group"
+#define OSSL_PKEY_PARAM_DIST_ID             "distid"
 #define OSSL_PKEY_PARAM_PUB_KEY             "pub"
 #define OSSL_PKEY_PARAM_PRIV_KEY            "priv"
 
diff --git a/include/openssl/ec.h b/include/openssl/ec.h
index 9db898cfed..9e0a6486cd 100644
--- a/include/openssl/ec.h
+++ b/include/openssl/ec.h
@@ -1492,18 +1492,6 @@ int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm,
                                    int len);
 int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
 
-/* SM2 will skip the operation check so no need to pass operation here */
-#  define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \
-        EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
-                          EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id))
-#  define EVP_PKEY_CTX_get1_id(ctx, id) \
-        EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
-                          EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id))
-
-#  define EVP_PKEY_CTX_get1_id_len(ctx, id_len) \
-        EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
-                          EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(id_len))
-
 #  define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID         (EVP_PKEY_ALG_CTRL + 1)
 #  define EVP_PKEY_CTRL_EC_PARAM_ENC                  (EVP_PKEY_ALG_CTRL + 2)
 #  define EVP_PKEY_CTRL_EC_ECDH_COFACTOR              (EVP_PKEY_ALG_CTRL + 3)
@@ -1514,10 +1502,6 @@ int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **ukm);
 #  define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN             (EVP_PKEY_ALG_CTRL + 8)
 #  define EVP_PKEY_CTRL_EC_KDF_UKM                    (EVP_PKEY_ALG_CTRL + 9)
 #  define EVP_PKEY_CTRL_GET_EC_KDF_UKM                (EVP_PKEY_ALG_CTRL + 10)
-/* TODO move next three #defines to evp.h when 'breaking' change is possible */
-#  define EVP_PKEY_CTRL_SET1_ID                       15
-#  define EVP_PKEY_CTRL_GET1_ID                       16
-#  define EVP_PKEY_CTRL_GET1_ID_LEN                   17
 
 /* KDF types */
 #  define EVP_PKEY_ECDH_KDF_NONE                      1
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 6bd6e26edf..74f97fd3e2 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1496,6 +1496,10 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
 int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md);
 int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
 
+int EVP_PKEY_CTX_set1_id(EVP_PKEY_CTX *ctx, const void *id, int len);
+int EVP_PKEY_CTX_get1_id(EVP_PKEY_CTX *ctx, void *id);
+int EVP_PKEY_CTX_get1_id_len(EVP_PKEY_CTX *ctx, size_t *id_len);
+
 # define EVP_PKEY_OP_UNDEFINED           0
 # define EVP_PKEY_OP_PARAMGEN            (1<<1)
 # define EVP_PKEY_OP_KEYGEN              (1<<2)
@@ -1544,7 +1548,9 @@ int EVP_PKEY_CTX_set_mac_key(EVP_PKEY_CTX *ctx, const unsigned char *key,
 # define EVP_PKEY_CTRL_CIPHER            12
 # define EVP_PKEY_CTRL_GET_MD            13
 # define EVP_PKEY_CTRL_SET_DIGEST_SIZE   14
-/* TODO move here three #defines of EVP_PKEY_CTRL_*ET1_ID* from ec.h */
+# define EVP_PKEY_CTRL_SET1_ID           15
+# define EVP_PKEY_CTRL_GET1_ID           16
+# define EVP_PKEY_CTRL_GET1_ID_LEN       17
 
 # define EVP_PKEY_ALG_CTRL               0x1000
 
diff --git a/test/recipes/30-test_evp_data/evppkey_sm2.txt b/test/recipes/30-test_evp_data/evppkey_sm2.txt
index b5b36dea3d..85a60b021f 100644
--- a/test/recipes/30-test_evp_data/evppkey_sm2.txt
+++ b/test/recipes/30-test_evp_data/evppkey_sm2.txt
@@ -40,6 +40,12 @@ Ctrl = digest:SHA512
 Input = 40AA1B203C9D8EE150B21C3C7CDA8261492E5420C5F2B9F7380700E094C303B48E62F319C1DA0E32EB40D113C5F1749CC61AEB499167890AB82F2CC9BB706971
 Output = 3046022100AE018933B9BA041784380069F2DDF609694DCD299FDBF23D09F4B711FBC103EC0221008440BB1A48C132DE4FB91BE9F43B958142FDD29FB9DABE01B17514023A2F638C
 
+Availablein = default
+Decrypt = SM2_key1
+Input = 30818A0220466BE2EF5C11782EC77864A0055417F407A5AFC11D653C6BCE69E417BB1D05B6022062B572E21FF0DDF5C726BD3F9FF2EAE56E6294713A607E9B9525628965F62CC804203C1B5713B5DB2728EB7BF775E44F4689FC32668BDC564F52EA45B09E8DF2A5F40422084A9D0CC2997092B7D3C404FCE95956EB604D732B2307A8E5B8900ED6608CA5B197
+Output = "The floofy bunnies hop at midnight"
+
+# This is the same as above, but with explicit digest control
 Availablein = default
 Decrypt = SM2_key1
 Ctrl = digest:SM3
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 26a9961d76..4982a7f93c 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5296,3 +5296,6 @@ asn1_d2i_read_bio                       ?	3_0_0	EXIST::FUNCTION:
 EVP_PKCS82PKEY_with_libctx              ?	3_0_0	EXIST::FUNCTION:
 ossl_b2i                                ?	3_0_0	EXIST::FUNCTION:DSA
 ossl_b2i_bio                            ?	3_0_0	EXIST::FUNCTION:DSA
+EVP_PKEY_CTX_set1_id                    ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_get1_id                    ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_get1_id_len                ?	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list