The branch master has been updated
       via  7f293d9f3b5cee4f4b15624fff15a45e0517334f (commit)
       via  bac1030ae4f93f22b3a81e3a2d9d3c5db363d96f (commit)
       via  3995de2c0356d8e3b34e8fb2ddf22b20210e498d (commit)
       via  ef077ba0d2fa28fd1b481f80335bda723d3d1f20 (commit)
       via  bbaddbc0682a4cd3271ee41f58550f7c26e8194e (commit)
       via  0943d5dd6179e2e824ec9a38b7ea6caa17a84ebd (commit)
       via  f4e4382cae1fb85fec6e9aa26f65fc729a40a039 (commit)
      from  658608c471a6e1f9b6d7f88c060a7adb77d7d334 (commit)


- Log -----------------------------------------------------------------
commit 7f293d9f3b5cee4f4b15624fff15a45e0517334f
Author: Richard Levitte <[email protected]>
Date:   Thu Jan 30 16:02:49 2020 +0100

    CHANGES: Add note about the refactoring of SM2 EVP_PKEYs
    
    Reviewed-by: Matt Caswell <[email protected]>
    Reviewed-by: Dmitry Belyavskiy <[email protected]>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit bac1030ae4f93f22b3a81e3a2d9d3c5db363d96f
Author: Richard Levitte <[email protected]>
Date:   Fri Jan 24 18:45:23 2020 +0100

    Adapt some 'openssl' commands for SM2 changes.
    
    There's no longer any need to make an EVP_PKEY type change for SM2
    keys, so we trim away that code.
    
    Reviewed-by: Matt Caswell <[email protected]>
    Reviewed-by: Dmitry Belyavskiy <[email protected]>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit 3995de2c0356d8e3b34e8fb2ddf22b20210e498d
Author: Richard Levitte <[email protected]>
Date:   Fri Jan 24 18:14:53 2020 +0100

    Adapt tests for SM2 changes.
    
    With test/ecdsatest.c, we test all the curves once for each EC key
    type we have, i.e. one round trip with EVP_PKEY_EC and one with
    EVP_PKEY_SM2.  This shows that we can use "normal" EC computations on
    keys with the SM2 curve (which have the type EVP_PKEY_SM2 by default)
    and SM2 computations with any other curve (which have the type
    EVP_PKEY_EC by default)
    
    test/evp_test.c, on the other hand, doesn't need to explicitly set the
    EVP_PKEY_SM2 alias type, as that now happens automatically.
    
    Reviewed-by: Matt Caswell <[email protected]>
    Reviewed-by: Dmitry Belyavskiy <[email protected]>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit ef077ba0d2fa28fd1b481f80335bda723d3d1f20
Author: Richard Levitte <[email protected]>
Date:   Fri Jan 24 18:14:06 2020 +0100

    Make SM3 a mandatory hash function for SM2.
    
    Reviewed-by: Matt Caswell <[email protected]>
    Reviewed-by: Dmitry Belyavskiy <[email protected]>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit bbaddbc0682a4cd3271ee41f58550f7c26e8194e
Author: Richard Levitte <[email protected]>
Date:   Fri Jan 24 18:04:19 2020 +0100

    X509: Refactor X509_verify() and X509_REQ_verify() for better streamlining
    
    The solution to incorporate the SM2 identity processing was an off
    the side hack that more or less duplicated the ASN1_item_verify()
    code with just a few lines being different.  We replace this with
    a new function ASN1_item_verify_ctx(), which takes an EVP_MD_CTX
    pointer instead of an EVP_PKEY pointer, just like its sibling
    ASN1_item_sign_ctx().
    
    This allows us to refactor X509_verify() and X509_REQ_verify() to
    simply create a local EVP_MD_CTX and an attached EVP_PKEY_CTX,
    which gets to hold the SM2 identity, if there is one, and then let
    ASN1_item_verify_ctx() to its job.
    
    This will also make it easier to adapt ASN1_item_verify_ctx() for
    provider based keys.
    
    Reviewed-by: Matt Caswell <[email protected]>
    Reviewed-by: Dmitry Belyavskiy <[email protected]>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit 0943d5dd6179e2e824ec9a38b7ea6caa17a84ebd
Author: Richard Levitte <[email protected]>
Date:   Fri Jan 24 17:59:03 2020 +0100

    Add SM2 specific parameter and key generation
    
    This makes it possible to generate SM2 parameters and keys like this:
    
        EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2);
        EVP_PKEY *pkey = EVP_PKEY_new();
    
        EVP_PKEY_keygen_init(pctx);
        EVP_PKEY_keygen(pctx, pkey);
    
    Reviewed-by: Matt Caswell <[email protected]>
    Reviewed-by: Dmitry Belyavskiy <[email protected]>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit f4e4382cae1fb85fec6e9aa26f65fc729a40a039
Author: Richard Levitte <[email protected]>
Date:   Fri Jan 24 17:51:39 2020 +0100

    EVP_PKEY_assign_EC_KEY(): detect SM2 curve and set EVP_PKEY type accordingly
    
    This means that when loaded or created, EC EVP_PKEYs with the SM2
    curve will be regarded as EVP_PKEY_SM2 type keys by default.
    Applications are no longer forced to check and fix this.
    
    It's still possible, for those who want this, to set the key type to
    EVP_PKEY_EC and thereby run the normal EC computations with the SM2
    curve.  This has to be done explicitly.
    
    Reviewed-by: Matt Caswell <[email protected]>
    Reviewed-by: Dmitry Belyavskiy <[email protected]>
    (Merged from https://github.com/openssl/openssl/pull/10942)

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

Summary of changes:
 CHANGES                        |  13 +++
 apps/req.c                     | 113 +++++++-------------------
 apps/speed.c                   |   2 -
 crypto/asn1/a_verify.c         |  69 ++++++++++------
 crypto/ec/ec_ameth.c           |   4 +-
 crypto/evp/p_lib.c             |  13 ++-
 crypto/sm2/sm2_pmeth.c         |  67 +++++++++------
 crypto/x509/x_all.c            | 180 ++++++++++-------------------------------
 doc/man3/EVP_PKEY_set1_RSA.pod |  15 +++-
 doc/man7/SM2.pod               |  22 ++---
 include/openssl/x509.h         |   3 +
 test/ecdsatest.c               |  94 +++++++++++++++++----
 test/evp_test.c                |  11 ---
 util/libcrypto.num             |   1 +
 14 files changed, 285 insertions(+), 322 deletions(-)

diff --git a/CHANGES b/CHANGES
index b002df633c..9eb778a004 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,19 @@
 
  Changes between 1.1.1 and 3.0.0 [xx XXX xxxx]
 
+  *) Reworked the treatment of EC EVP_PKEYs with the SM2 curve to
+     automatically become EVP_PKEY_SM2 rather than EVP_PKEY_EC.
+     This means that applications don't have to look at the curve NID and
+     'EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)' to get SM2 computations.
+     However, they still can, that EVP_PKEY_set_alias_type() call acts as
+     a no-op when the EVP_PKEY is already of the given type.
+
+     Parameter and key generation is also reworked to make it possible
+     to generate EVP_PKEY_SM2 parameters and keys without having to go
+     through EVP_PKEY_EC generation and then change the EVP_PKEY type.
+     However, code that does the latter will still work as before.
+     [Richard Levitte]
+
   *) Deprecated EVP_PKEY_decrypt_old(), please use EVP_PKEY_decrypt_init()
      and EVP_PKEY_decrypt() instead.
      Deprecated EVP_PKEY_encrypt_old(), please use EVP_PKEY_encrypt_init()
diff --git a/apps/req.c b/apps/req.c
index 87994ceb7c..7140705f09 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -1674,41 +1674,16 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx)
     return 1;
 }
 
-#ifndef OPENSSL_NO_SM2
-static int ec_pkey_is_sm2(EVP_PKEY *pkey)
-{
-    EC_KEY *eckey = NULL;
-    const EC_GROUP *group = NULL;
-
-    if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2)
-        return 1;
-    if (EVP_PKEY_id(pkey) == EVP_PKEY_EC
-            && (eckey = EVP_PKEY_get0_EC_KEY(pkey)) != NULL
-            && (group = EC_KEY_get0_group(eckey)) != NULL
-            && EC_GROUP_get_curve_name(group) == NID_sm2)
-        return 1;
-    return 0;
-}
-#endif
-
 static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey,
                         const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts)
 {
     EVP_PKEY_CTX *pkctx = NULL;
-#ifndef OPENSSL_NO_SM2
     EVP_PKEY_CTX *pctx = NULL;
-#endif
     int i, def_nid, ret = 0;
 
     if (ctx == NULL)
         goto err;
-#ifndef OPENSSL_NO_SM2
-    if (ec_pkey_is_sm2(pkey)) {
-        /* initialize some SM2-specific code */
-        if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) {
-            BIO_printf(bio_err, "Internal error.\n");
-            goto err;
-        }
+    if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) {
         pctx = EVP_PKEY_CTX_new(pkey, NULL);
         if (pctx == NULL) {
             BIO_printf(bio_err, "memory allocation failure.\n");
@@ -1725,7 +1700,6 @@ static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey,
         }
         EVP_MD_CTX_set_pkey_ctx(ctx, pctx);
     }
-#endif
     /*
      * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory
      * for this algorithm.
@@ -1748,90 +1722,63 @@ static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey,
 
     ret = 1;
  err:
-#ifndef OPENSSL_NO_SM2
     if (!ret)
         EVP_PKEY_CTX_free(pctx);
-#endif
     return ret;
 }
 
+static void do_sign_cleanup(EVP_MD_CTX *ctx, EVP_PKEY *pkey)
+{
+    /*
+     * With SM2, do_sign_init() attached an EVP_PKEY_CTX to the EVP_MD_CTX,
+     * and we have to free it explicitly.
+     */
+    if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) {
+        EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(ctx);
+
+        EVP_MD_CTX_set_pkey_ctx(ctx, NULL);
+        EVP_PKEY_CTX_free(pctx);
+    }
+}
+
 int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
                  STACK_OF(OPENSSL_STRING) *sigopts)
 {
-    int rv;
+    int rv = 0;
     EVP_MD_CTX *mctx = EVP_MD_CTX_new();
-#ifndef OPENSSL_NO_SM2
-    EVP_PKEY_CTX *pctx = NULL;
-#endif
 
-    rv = do_sign_init(mctx, pkey, md, sigopts);
-    if (rv > 0) {
-        rv = X509_sign_ctx(x, mctx);
-#ifndef OPENSSL_NO_SM2
-        /*
-         * only in SM2 case we need to free the pctx explicitly
-         * if do_sign_init() fails, pctx is already freed in it
-         */
-        if (ec_pkey_is_sm2(pkey)) {
-            pctx = EVP_MD_CTX_pkey_ctx(mctx);
-            EVP_PKEY_CTX_free(pctx);
-        }
-#endif
+    if (do_sign_init(mctx, pkey, md, sigopts) > 0) {
+        rv = (X509_sign_ctx(x, mctx) > 0);
+        do_sign_cleanup(mctx, pkey);
     }
     EVP_MD_CTX_free(mctx);
-    return rv > 0 ? 1 : 0;
+    return rv;
 }
 
 int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
                      STACK_OF(OPENSSL_STRING) *sigopts)
 {
-    int rv;
+    int rv = 0;
     EVP_MD_CTX *mctx = EVP_MD_CTX_new();
-#ifndef OPENSSL_NO_SM2
-    EVP_PKEY_CTX *pctx = NULL;
-#endif
 
-    rv = do_sign_init(mctx, pkey, md, sigopts);
-    if (rv > 0) {
-        rv = X509_REQ_sign_ctx(x, mctx);
-#ifndef OPENSSL_NO_SM2
-        /*
-         * only in SM2 case we need to free the pctx explicitly
-         * if do_sign_init() fails, pctx is already freed in it
-         */
-        if (ec_pkey_is_sm2(pkey)) {
-            pctx = EVP_MD_CTX_pkey_ctx(mctx);
-            EVP_PKEY_CTX_free(pctx);
-        }
-#endif
+    if (do_sign_init(mctx, pkey, md, sigopts) > 0) {
+        rv = (X509_REQ_sign_ctx(x, mctx) > 0);
+        do_sign_cleanup(mctx, pkey);
     }
     EVP_MD_CTX_free(mctx);
-    return rv > 0 ? 1 : 0;
+    return rv;
 }
 
 int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
                      STACK_OF(OPENSSL_STRING) *sigopts)
 {
-    int rv;
+    int rv = 0;
     EVP_MD_CTX *mctx = EVP_MD_CTX_new();
-#ifndef OPENSSL_NO_SM2
-    EVP_PKEY_CTX *pctx = NULL;
-#endif
 
-    rv = do_sign_init(mctx, pkey, md, sigopts);
-    if (rv > 0) {
-        rv = X509_CRL_sign_ctx(x, mctx);
-#ifndef OPENSSL_NO_SM2
-        /*
-         * only in SM2 case we need to free the pctx explicitly
-         * if do_sign_init() fails, no need to double free pctx
-         */
-        if (ec_pkey_is_sm2(pkey)) {
-            pctx = EVP_MD_CTX_pkey_ctx(mctx);
-            EVP_PKEY_CTX_free(pctx);
-        }
-#endif
+    if (do_sign_init(mctx, pkey, md, sigopts) > 0) {
+        rv = (X509_CRL_sign_ctx(x, mctx) > 0);
+        do_sign_cleanup(mctx, pkey);
     }
     EVP_MD_CTX_free(mctx);
-    return rv > 0 ? 1 : 0;
+    return rv;
 }
diff --git a/apps/speed.c b/apps/speed.c
index a978bdf17a..d2afebb2c6 100644
--- a/apps/speed.c
+++ b/apps/speed.c
@@ -3399,8 +3399,6 @@ int speed_main(int argc, char **argv)
             /* attach it sooner to rely on main final cleanup */
             loopargs[i].sm2_pkey[testnum] = sm2_pkey;
             loopargs[i].sigsize = ECDSA_size(EVP_PKEY_get0_EC_KEY(sm2_pkey));
-            if (!EVP_PKEY_set_alias_type(sm2_pkey, EVP_PKEY_SM2))
-                break;
 
             sm2_pctx = EVP_PKEY_CTX_new(sm2_pkey, NULL);
             sm2_vfy_pctx = EVP_PKEY_CTX_new(sm2_pkey, NULL);
diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c
index 92f9448749..94a11c18d4 100644
--- a/crypto/asn1/a_verify.c
+++ b/crypto/asn1/a_verify.c
@@ -88,65 +88,85 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, 
ASN1_BIT_STRING *signature,
 int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
                      ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
 {
-    EVP_MD_CTX *ctx = NULL;
+    int rv = -1;
+    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL);
+
+    if (ctx == NULL || pctx == NULL) {
+        ASN1err(0, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    EVP_MD_CTX_set_pkey_ctx(ctx, pctx);
+
+    rv = ASN1_item_verify_ctx(it, a, signature, asn, ctx);
+
+ err:
+    EVP_PKEY_CTX_free(pctx);
+    EVP_MD_CTX_free(ctx);
+    return rv;
+}
+
+int ASN1_item_verify_ctx(const ASN1_ITEM *it, X509_ALGOR *a,
+                         ASN1_BIT_STRING *signature, void *asn,
+                         EVP_MD_CTX *ctx)
+{
+    EVP_PKEY *pkey;
     unsigned char *buf_in = NULL;
     int ret = -1, inl = 0;
     int mdnid, pknid;
     size_t inll = 0;
 
+    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx));
+
     if (pkey == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER);
+        ASN1err(0, ERR_R_PASSED_NULL_PARAMETER);
         return -1;
     }
 
     if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+        ASN1err(0, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
         return -1;
     }
 
-    ctx = EVP_MD_CTX_new();
-    if (ctx == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-
     /* Convert signature OID into digest and public key OIDs */
     if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+        ASN1err(0, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
         goto err;
     }
+
     if (mdnid == NID_undef) {
         if (pkey->ameth == NULL || pkey->ameth->item_verify == NULL) {
-            ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
-                    ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+            ASN1err(0, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
             goto err;
         }
         ret = pkey->ameth->item_verify(ctx, it, asn, a, signature, pkey);
         /*
-         * Return value of 2 means carry on, anything else means we exit
-         * straight away: either a fatal error of the underlying verification
-         * routine handles all verification.
+         * Return values meaning:
+         * <=0: error.
+         *   1: method does everything.
+         *   2: carry on as normal, method has called EVP_DigestVerifyInit()
          */
-        if (ret != 2)
+        if (ret <= 0)
+            ASN1err(0, ERR_R_EVP_LIB);
+        if (ret <= 1)
             goto err;
-        ret = -1;
     } else {
         const EVP_MD *type = EVP_get_digestbynid(mdnid);
 
         if (type == NULL) {
-            ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
-                    ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+            ASN1err(0, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
             goto err;
         }
 
         /* Check public key OID matches public key type */
         if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) {
-            ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
+            ASN1err(0, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
             goto err;
         }
 
         if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) {
-            ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
+            ASN1err(0, ERR_R_EVP_LIB);
             ret = 0;
             goto err;
         }
@@ -154,11 +174,11 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
 
     inl = ASN1_item_i2d(asn, &buf_in, it);
     if (inl <= 0) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_INTERNAL_ERROR);
+        ASN1err(0, ERR_R_INTERNAL_ERROR);
         goto err;
     }
     if (buf_in == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
+        ASN1err(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     inll = inl;
@@ -166,12 +186,11 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
     ret = EVP_DigestVerify(ctx, signature->data, (size_t)signature->length,
                            buf_in, inl);
     if (ret <= 0) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
+        ASN1err(0, ERR_R_EVP_LIB);
         goto err;
     }
     ret = 1;
  err:
     OPENSSL_clear_free(buf_in, inll);
-    EVP_MD_CTX_free(ctx);
     return ret;
 }
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index 6105e6b087..f38ab103ab 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -507,9 +507,9 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, 
void *arg2)
         if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) {
             /* For SM2, the only valid digest-alg is SM3 */
             *(int *)arg2 = NID_sm3;
-        } else {
-            *(int *)arg2 = NID_sha256;
+            return 2;            /* Make it mandatory */
         }
+        *(int *)arg2 = NID_sha256;
         return 1;
 
     case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 07316a4522..0a3c86d63a 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -401,8 +401,19 @@ ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
 # endif
 int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
 {
+    int alias = type;
+
+    if (EVP_PKEY_type(type) == EVP_PKEY_EC) {
+        const EC_GROUP *group = EC_KEY_get0_group(key);
+
+        if (group != NULL && EC_GROUP_get_curve_name(group) == NID_sm2)
+            alias = EVP_PKEY_SM2;
+    }
+
     if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
         return 0;
+    if (!EVP_PKEY_set_alias_type(pkey, alias))
+        return 0;
     pkey->pkey.ptr = key;
     return (key != NULL);
 }
@@ -519,7 +530,7 @@ int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
 
 EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey)
 {
-    if (pkey->type != EVP_PKEY_EC) {
+    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
         EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY);
         return NULL;
     }
diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c
index 27bec2cb06..1068b7b901 100644
--- a/crypto/sm2/sm2_pmeth.c
+++ b/crypto/sm2/sm2_pmeth.c
@@ -18,8 +18,6 @@
 /* EC pkey context structure */
 
 typedef struct {
-    /* Key and paramgen group */
-    EC_GROUP *gen_group;
     /* message digest */
     const EVP_MD *md;
     /* Distinguishing Identifier, ISO/IEC 15946-3 */
@@ -47,7 +45,6 @@ static void pkey_sm2_cleanup(EVP_PKEY_CTX *ctx)
     SM2_PKEY_CTX *smctx = ctx->data;
 
     if (smctx != NULL) {
-        EC_GROUP_free(smctx->gen_group);
         OPENSSL_free(smctx->id);
         OPENSSL_free(smctx);
         ctx->data = NULL;
@@ -62,13 +59,6 @@ static int pkey_sm2_copy(EVP_PKEY_CTX *dst, const 
EVP_PKEY_CTX *src)
         return 0;
     sctx = src->data;
     dctx = dst->data;
-    if (sctx->gen_group != NULL) {
-        dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
-        if (dctx->gen_group == NULL) {
-            pkey_sm2_cleanup(dst);
-            return 0;
-        }
-    }
     if (sctx->id != NULL) {
         dctx->id = OPENSSL_malloc(sctx->id_len);
         if (dctx->id == NULL) {
@@ -163,26 +153,21 @@ static int pkey_sm2_decrypt(EVP_PKEY_CTX *ctx,
 static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
 {
     SM2_PKEY_CTX *smctx = ctx->data;
-    EC_GROUP *group;
     uint8_t *tmp_id;
 
     switch (type) {
     case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
-        group = EC_GROUP_new_by_curve_name(p1);
-        if (group == NULL) {
+        /*
+         * This control could be removed, which would signal it being
+         * unsupported.  However, that means that when the caller uses
+         * the correct curve, it may interpret the unsupported signal
+         * as an error, so it's better to accept the control, check the
+         * value and return a corresponding value.
+         */
+        if (p1 != NID_sm2) {
             SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_INVALID_CURVE);
             return 0;
         }
-        EC_GROUP_free(smctx->gen_group);
-        smctx->gen_group = group;
-        return 1;
-
-    case EVP_PKEY_CTRL_EC_PARAM_ENC:
-        if (smctx->gen_group == NULL) {
-            SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_NO_PARAMETERS_SET);
-            return 0;
-        }
-        EC_GROUP_set_asn1_flag(smctx->gen_group, p1);
         return 1;
 
     case EVP_PKEY_CTRL_MD:
@@ -309,6 +294,38 @@ static int pkey_sm2_digest_custom(EVP_PKEY_CTX *ctx, 
EVP_MD_CTX *mctx)
     return EVP_DigestUpdate(mctx, z, (size_t)mdlen);
 }
 
+static int pkey_sm2_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+    EC_KEY *ec = NULL;
+    int ret;
+
+    ec = EC_KEY_new_by_curve_name(NID_sm2);
+    if (ec == NULL)
+        return 0;
+    if (!ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec)))
+        EC_KEY_free(ec);
+    return ret;
+}
+
+static int pkey_sm2_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+    EC_KEY *ec = NULL;
+
+    ec = EC_KEY_new_by_curve_name(NID_sm2);
+    if (ec == NULL)
+        return 0;
+    if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) {
+        EC_KEY_free(ec);
+        return 0;
+    }
+    /* Note: if error is returned, we count on caller to free pkey->pkey.ec */
+    if (ctx->pkey != NULL
+        && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
+        return 0;
+
+    return EC_KEY_generate_key(ec);
+}
+
 static const EVP_PKEY_METHOD sm2_pkey_meth = {
     EVP_PKEY_SM2,
     0,
@@ -317,10 +334,10 @@ static const EVP_PKEY_METHOD sm2_pkey_meth = {
     pkey_sm2_cleanup,
 
     0,
-    0,
+    pkey_sm2_paramgen,
 
     0,
-    0,
+    pkey_sm2_keygen,
 
     0,
     pkey_sm2_sign,
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index fbdb100c00..9af26e69f0 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -19,176 +19,78 @@
 #include <openssl/dsa.h>
 #include <openssl/x509v3.h>
 
-#ifndef OPENSSL_NO_SM2
+static void clean_id_ctx(EVP_MD_CTX *ctx)
+{
+    EVP_PKEY_CTX *pctx = EVP_MD_CTX_pkey_ctx(ctx);
 
-# include "crypto/asn1.h"
-# include "crypto/evp.h"
+    EVP_PKEY_CTX_free(pctx);
+    EVP_MD_CTX_free(ctx);
+}
 
-static int common_verify_sm2(void *data, EVP_PKEY *pkey,
-                             int mdnid, int pknid, int req)
+static EVP_MD_CTX *make_id_ctx(EVP_PKEY *r, ASN1_OCTET_STRING *id)
 {
-    X509 *x = NULL;
-    X509_REQ *r = NULL;
     EVP_MD_CTX *ctx = NULL;
-    unsigned char *buf_in = NULL;
-    int ret = -1, inl = 0;
-    size_t inll = 0;
     EVP_PKEY_CTX *pctx = NULL;
-    const EVP_MD *type = EVP_get_digestbynid(mdnid);
-    ASN1_BIT_STRING *signature = NULL;
-    ASN1_OCTET_STRING *sm2_id = NULL;
-    ASN1_VALUE *tbv = NULL;
-
-    if (type == NULL) {
-        X509err(X509_F_COMMON_VERIFY_SM2,
-                ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
-        goto err;
-    }
-
-    if (pkey == NULL) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_PASSED_NULL_PARAMETER);
-        return -1;
-    }
-
-    if (req == 1) {
-        r = (X509_REQ *)data;
-        signature = r->signature;
-        sm2_id = r->sm2_id;
-        tbv = (ASN1_VALUE *)&r->req_info;
-    } else {
-        x = (X509 *)data;
-        signature = &x->signature;
-        sm2_id = x->sm2_id;
-        tbv = (ASN1_VALUE *)&x->cert_info;
-    }
-
-    if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
-        return -1;
-    }
 
-    ctx = EVP_MD_CTX_new();
-    if (ctx == NULL) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_MALLOC_FAILURE);
-        goto err;
+    if ((ctx = EVP_MD_CTX_new()) == NULL
+        || (pctx = EVP_PKEY_CTX_new(r, NULL)) == NULL) {
+        X509err(0, ERR_R_MALLOC_FAILURE);
+        goto error;
     }
 
-    /* Check public key OID matches public key type */
-    if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
-        goto err;
+    if (id != NULL) {
+        if (EVP_PKEY_CTX_set1_id(pctx, id->data, id->length) <= 0) {
+            X509err(0, ERR_R_MALLOC_FAILURE);
+            goto error;
+        }
     }
 
-    if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB);
-        ret = 0;
-        goto err;
-    }
-    pctx = EVP_PKEY_CTX_new(pkey, NULL);
-    if (pctx == NULL) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB);
-        ret = 0;
-        goto err;
-    }
-    /* NOTE: we tolerate no actual ID, to provide maximum flexibility */
-    if (sm2_id != NULL
-            && EVP_PKEY_CTX_set1_id(pctx, sm2_id->data, sm2_id->length) != 1) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB);
-        ret = 0;
-        goto err;
-    }
     EVP_MD_CTX_set_pkey_ctx(ctx, pctx);
 
-    if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB);
-        ret = 0;
-        goto err;
-    }
-
-    inl = ASN1_item_i2d(tbv, &buf_in,
-                        req == 1 ?
-                        ASN1_ITEM_rptr(X509_REQ_INFO) :
-                        ASN1_ITEM_rptr(X509_CINF));
-    if (inl <= 0) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_INTERNAL_ERROR);
-        goto err;
-    }
-    if (buf_in == NULL) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-    inll = inl;
-
-    ret = EVP_DigestVerify(ctx, signature->data,
-                           (size_t)signature->length, buf_in, inl);
-    if (ret <= 0) {
-        X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB);
-        goto err;
-    }
-    ret = 1;
- err:
-    OPENSSL_clear_free(buf_in, inll);
-    EVP_MD_CTX_free(ctx);
+    return ctx;
+ error:
     EVP_PKEY_CTX_free(pctx);
-    return ret;
-}
-
-static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid)
-{
-    return common_verify_sm2(x, pkey, mdnid, pknid, 0);
-}
-
-static int x509_req_verify_sm2(X509_REQ *x, EVP_PKEY *pkey,
-                               int mdnid, int pknid)
-{
-    return common_verify_sm2(x, pkey, mdnid, pknid, 1);
+    EVP_MD_CTX_free(ctx);
+    return NULL;
 }
 
-#endif
-
 int X509_verify(X509 *a, EVP_PKEY *r)
 {
-#ifndef OPENSSL_NO_SM2
-    int mdnid, pknid;
-#endif
+    int rv = 0;
+    EVP_MD_CTX *ctx = NULL;
+    ASN1_OCTET_STRING *id = NULL;
 
     if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature))
         return 0;
 
 #ifndef OPENSSL_NO_SM2
-    /* Convert signature OID into digest and public key OIDs */
-    if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->sig_alg.algorithm),
-                             &mdnid, &pknid)) {
-        X509err(X509_F_X509_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
-        return 0;
-    }
-
-    if (pknid == NID_sm2)
-        return x509_verify_sm2(a, r, mdnid, pknid);
+    id = a->sm2_id;
 #endif
 
-    return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg,
-                             &a->signature, &a->cert_info, r));
+    if ((ctx = make_id_ctx(r, id)) != NULL) {
+        rv = ASN1_item_verify_ctx(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg,
+                                  &a->signature, &a->cert_info, ctx);
+        clean_id_ctx(ctx);
+    }
+    return rv;
 }
 
 int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
 {
-#ifndef OPENSSL_NO_SM2
-    int mdnid, pknid;
-
-    /* Convert signature OID into digest and public key OIDs */
-    if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->sig_alg.algorithm),
-                             &mdnid, &pknid)) {
-        X509err(X509_F_X509_REQ_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
-        return 0;
-    }
+    int rv = 0;
+    EVP_MD_CTX *ctx = NULL;
+    ASN1_OCTET_STRING *id = NULL;
 
-    if (pknid == NID_sm2)
-        return x509_req_verify_sm2(a, r, mdnid, pknid);
+#ifndef OPENSSL_NO_SM2
+    id = a->sm2_id;
 #endif
 
-    return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO),
-                             &a->sig_alg, a->signature, &a->req_info, r));
+    if ((ctx = make_id_ctx(r, id)) != NULL) {
+        rv = ASN1_item_verify_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), &a->sig_alg,
+                                  a->signature, &a->req_info, ctx);
+        clean_id_ctx(ctx);
+    }
+    return rv;
 }
 
 int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r)
diff --git a/doc/man3/EVP_PKEY_set1_RSA.pod b/doc/man3/EVP_PKEY_set1_RSA.pod
index 8f4d7f547a..8423a0a3b8 100644
--- a/doc/man3/EVP_PKEY_set1_RSA.pod
+++ b/doc/man3/EVP_PKEY_set1_RSA.pod
@@ -90,8 +90,7 @@ If B<engine> does not include an B<EVP_PKEY_METHOD> for 
B<pkey> an
 error occurs.
 
 EVP_PKEY_set_alias_type() allows modifying a EVP_PKEY to use a
-different set of algorithms than the default. This is currently used
-to support SM2 keys, which use an identical encoding to ECDSA.
+different set of algorithms than the default.
 
 =head1 NOTES
 
@@ -103,6 +102,16 @@ EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), 
EVP_PKEY_assign_DH(),
 EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305()
 and EVP_PKEY_assign_SIPHASH() are implemented as macros.
 
+EVP_PKEY_assign_EC_KEY() looks at the curve name id to determine if
+the passed B<EC_KEY> is an L<SM2(7)> key, and will set the B<EVP_PKEY>
+type to B<EVP_PKEY_SM2> in that case, instead of B<EVP_PKEY_EC>.
+
+It's possible to switch back and forth between the types B<EVP_PKEY_EC>
+and B<EVP_PKEY_SM2> with a call to EVP_PKEY_set_alias_type() on keys
+assigned with this macro if it's desirable to do a normal EC
+computations with the SM2 curve instead of the special SM2
+computations, and vice versa.
+
 Most applications wishing to know a key type will simply call
 EVP_PKEY_base_id() and will not care about the actual type:
 which will be identical in almost all cases.
@@ -143,7 +152,7 @@ algorithms with EVP_PKEY_set_alias_type:
 
 =head1 SEE ALSO
 
-L<EVP_PKEY_new(3)>
+L<EVP_PKEY_new(3)>, L<SM2(7)>
 
 =head1 COPYRIGHT
 
diff --git a/doc/man7/SM2.pod b/doc/man7/SM2.pod
index c7876a0cc6..93fd12c909 100644
--- a/doc/man7/SM2.pod
+++ b/doc/man7/SM2.pod
@@ -20,25 +20,17 @@ B<SM2> signatures can be generated by using the 
'DigestSign' series of APIs, for
 instance, EVP_DigestSignInit(), EVP_DigestSignUpdate() and 
EVP_DigestSignFinal().
 Ditto for the verification process by calling the 'DigestVerify' series of 
APIs.
 
-There are several special steps that need to be done before computing an B<SM2>
-signature.
-
-The B<EVP_PKEY> structure will default to using ECDSA for signatures when it is
-created. It should be set to B<EVP_PKEY_SM2> by calling:
-
- EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
-
-Then an ID should be set by calling:
+Before computing an B<SM2> signature, an B<EVP_PKEY_CTX> needs to be created,
+and an B<SM2> ID must be set for it, like this:
 
  EVP_PKEY_CTX_set1_id(pctx, id, id_len);
 
-When calling the EVP_DigestSignInit() or EVP_DigestVerifyInit() functions, a
-pre-allocated B<EVP_PKEY_CTX> should be assigned to the B<EVP_MD_CTX>. This is
-done by calling:
+Before calling the EVP_DigestSignInit() or EVP_DigestVerifyInit() functions,
+that B<EVP_PKEY_CTX> should be assigned to the B<EVP_MD_CTX>, like this:
 
  EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
 
-And normally there is no need to pass a B<pctx> parameter to 
EVP_DigestSignInit()
+There is normally no need to pass a B<pctx> parameter to EVP_DigestSignInit()
 or EVP_DigestVerifyInit() in such a scenario.
 
 SM2 can be tested with the L<openssl-speed(1)> application since version 3.0.0.
@@ -52,11 +44,10 @@ a message with the SM2 signature algorithm and the SM3 hash 
algorithm:
  #include <openssl/evp.h>
 
  /* obtain an EVP_PKEY using whatever methods... */
- EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
  mctx = EVP_MD_CTX_new();
  pctx = EVP_PKEY_CTX_new(pkey, NULL);
  EVP_PKEY_CTX_set1_id(pctx, id, id_len);
- EVP_MD_CTX_set_pkey_ctx(mctx, pctx);;
+ EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
  EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey);
  EVP_DigestVerifyUpdate(mctx, msg, msg_len);
  EVP_DigestVerifyFinal(mctx, sig, sig_len)
@@ -64,7 +55,6 @@ a message with the SM2 signature algorithm and the SM3 hash 
algorithm:
 =head1 SEE ALSO
 
 L<EVP_PKEY_CTX_new(3)>,
-L<EVP_PKEY_set_alias_type(3)>,
 L<EVP_DigestSignInit(3)>,
 L<EVP_DigestVerifyInit(3)>,
 L<EVP_PKEY_CTX_set1_id(3)>,
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 4cd17d24f5..5e553ef4d3 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -637,6 +637,9 @@ int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD 
*type, void *data,
 
 int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1,
                      ASN1_BIT_STRING *signature, void *data, EVP_PKEY *pkey);
+int ASN1_item_verify_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
+                         ASN1_BIT_STRING *signature, void *data,
+                         EVP_MD_CTX *ctx);
 
 int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1,
                    X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *data,
diff --git a/test/ecdsatest.c b/test/ecdsatest.c
index a62efad1cf..f99817898f 100644
--- a/test/ecdsatest.c
+++ b/test/ecdsatest.c
@@ -201,7 +201,30 @@ static int x9_62_tests(int n)
  * - reject that signature after modifying the signature
  * - accept that signature after un-modifying the signature
  */
-static int test_builtin(int n)
+static int set_sm2_id(EVP_MD_CTX *mctx, EVP_PKEY *pkey)
+{
+    /* With the SM2 key type, the SM2 ID is mandatory */
+    static const char sm2_id[] = { 1, 2, 3, 4, 'l', 'e', 't', 't', 'e', 'r' };
+    EVP_PKEY_CTX *pctx;
+
+    if (!TEST_ptr(pctx = EVP_PKEY_CTX_new(pkey, NULL))
+        || !TEST_int_gt(EVP_PKEY_CTX_set1_id(pctx, sm2_id, sizeof(sm2_id)), 0))
+        return 0;
+    EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
+    return 1;
+}
+
+static int clean_sm2_id(EVP_MD_CTX *mctx)
+{
+    EVP_PKEY_CTX *pctx;
+
+    if (!TEST_ptr(pctx = EVP_MD_CTX_pkey_ctx(mctx)))
+        return 0;
+    EVP_PKEY_CTX_free(pctx);
+    return 1;
+}
+
+static int test_builtin(int n, int as)
 {
     EC_KEY *eckey_neg = NULL, *eckey = NULL;
     unsigned char dirt, offset, tbs[128];
@@ -220,7 +243,8 @@ static int test_builtin(int n)
         return 1;
     }
 
-    TEST_info("testing ECDSA for curve %s", OBJ_nid2sn(nid));
+    TEST_info("testing ECDSA for curve %s as %s key type", OBJ_nid2sn(nid),
+              as == EVP_PKEY_EC ? "EC" : "SM2");
 
     if (!TEST_ptr(mctx = EVP_MD_CTX_new())
         /* get some random message data */
@@ -239,37 +263,62 @@ static int test_builtin(int n)
 
     temp = ECDSA_size(eckey);
 
+    /*
+     * |as| indicates how we want to treat the key, i.e. what sort of
+     * computation we want to do with it.  The two choices are the key
+     * types EVP_PKEY_EC and EVP_PKEY_SM2.  It's perfectly possible to
+     * switch back and forth between those two key types, regardless of
+     * curve, even though the default is to have EVP_PKEY_SM2 for the
+     * SM2 curve and EVP_PKEY_EC for all other curves.
+     */
+    if (!TEST_true(EVP_PKEY_set_alias_type(pkey, as))
+        || !TEST_true(EVP_PKEY_set_alias_type(pkey_neg, as)))
+            goto err;
+
     if (!TEST_int_ge(temp, 0)
         || !TEST_ptr(sig = OPENSSL_malloc(sig_len = (size_t)temp))
         /* create a signature */
+        || (as == EVP_PKEY_SM2 && !set_sm2_id(mctx, pkey))
         || !TEST_true(EVP_DigestSignInit(mctx, NULL, NULL, NULL, pkey))
         || !TEST_true(EVP_DigestSign(mctx, sig, &sig_len, tbs, sizeof(tbs)))
         || !TEST_int_le(sig_len, ECDSA_size(eckey))
-        /* negative test, verify with wrong key, 0 return */
+        || (as == EVP_PKEY_SM2 && !clean_sm2_id(mctx))
         || !TEST_true(EVP_MD_CTX_reset(mctx))
+        /* negative test, verify with wrong key, 0 return */
+        || (as == EVP_PKEY_SM2 && !set_sm2_id(mctx, pkey_neg))
         || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey_neg))
         || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 0)
-        /* negative test, verify with wrong signature length, -1 return */
+        || (as == EVP_PKEY_SM2 && !clean_sm2_id(mctx))
         || !TEST_true(EVP_MD_CTX_reset(mctx))
+        /* negative test, verify with wrong signature length, -1 return */
+        || (as == EVP_PKEY_SM2 && !set_sm2_id(mctx, pkey))
         || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
         || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len - 1, tbs, 
sizeof(tbs)), -1)
-        /* positive test, verify with correct key, 1 return */
+        || (as == EVP_PKEY_SM2 && !clean_sm2_id(mctx))
         || !TEST_true(EVP_MD_CTX_reset(mctx))
+        /* positive test, verify with correct key, 1 return */
+        || (as == EVP_PKEY_SM2 && !set_sm2_id(mctx, pkey))
         || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
-        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 1))
+        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 1)
+        || (as == EVP_PKEY_SM2 && !clean_sm2_id(mctx))
+        || !TEST_true(EVP_MD_CTX_reset(mctx)))
         goto err;
 
     /* muck with the message, test it fails with 0 return */
     tbs[0] ^= 1;
-    if (!TEST_true(EVP_MD_CTX_reset(mctx))
+    if ((as == EVP_PKEY_SM2 && !set_sm2_id(mctx, pkey))
         || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
-        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 0))
+        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 0)
+        || (as == EVP_PKEY_SM2 && !clean_sm2_id(mctx))
+        || !TEST_true(EVP_MD_CTX_reset(mctx)))
         goto err;
     /* un-muck and test it verifies */
     tbs[0] ^= 1;
-    if (!TEST_true(EVP_MD_CTX_reset(mctx))
+    if ((as == EVP_PKEY_SM2 && !set_sm2_id(mctx, pkey))
         || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
-        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 1))
+        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 1)
+        || (as == EVP_PKEY_SM2 && !clean_sm2_id(mctx))
+        || !TEST_true(EVP_MD_CTX_reset(mctx)))
         goto err;
 
     /*-
@@ -301,15 +350,19 @@ static int test_builtin(int n)
     offset = tbs[0] % sig_len;
     dirt = tbs[1] ? tbs[1] : 1;
     sig[offset] ^= dirt;
-    if (!TEST_true(EVP_MD_CTX_reset(mctx))
+    if ((as == EVP_PKEY_SM2 && !set_sm2_id(mctx, pkey))
         || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
-        || !TEST_int_ne(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 1))
+        || !TEST_int_ne(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 1)
+        || (as == EVP_PKEY_SM2 && !clean_sm2_id(mctx))
+        || !TEST_true(EVP_MD_CTX_reset(mctx)))
         goto err;
     /* un-muck and test it verifies */
     sig[offset] ^= dirt;
-    if (!TEST_true(EVP_MD_CTX_reset(mctx))
+    if ((as == EVP_PKEY_SM2 && !set_sm2_id(mctx, pkey))
         || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey))
-        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 1))
+        || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, 
sizeof(tbs)), 1)
+        || (as == EVP_PKEY_SM2 && !clean_sm2_id(mctx))
+        || !TEST_true(EVP_MD_CTX_reset(mctx)))
         goto err;
 
     ret = 1;
@@ -320,6 +373,16 @@ static int test_builtin(int n)
     OPENSSL_free(sig);
     return ret;
 }
+
+static int test_builtin_as_ec(int n)
+{
+    return test_builtin(n, EVP_PKEY_EC);
+}
+
+static int test_builtin_as_sm2(int n)
+{
+    return test_builtin(n, EVP_PKEY_SM2);
+}
 #endif
 
 int setup_tests(void)
@@ -332,7 +395,8 @@ int setup_tests(void)
     if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
         || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
         return 0;
-    ADD_ALL_TESTS(test_builtin, crv_len);
+    ADD_ALL_TESTS(test_builtin_as_ec, crv_len);
+    ADD_ALL_TESTS(test_builtin_as_sm2, crv_len);
     ADD_ALL_TESTS(x9_62_tests, OSSL_NELEM(ecdsa_cavs_kats));
 #endif
     return 1;
diff --git a/test/evp_test.c b/test/evp_test.c
index e4d30fb20d..a6335ac93e 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -3145,17 +3145,6 @@ top:
         if (!TEST_ptr(key = OPENSSL_malloc(sizeof(*key))))
             return 0;
         key->name = take_value(pp);
-
-        /* Hack to detect SM2 keys */
-        if(pkey != NULL && strstr(key->name, "SM2") != NULL) {
-#ifdef OPENSSL_NO_SM2
-            EVP_PKEY_free(pkey);
-            pkey = NULL;
-#else
-            EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
-#endif
-        }
-
         key->key = pkey;
         key->next = *klist;
         *klist = key;
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 8bec3443b6..9dc3f76e15 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4917,3 +4917,4 @@ PKCS8_pkey_add1_attr                    ? 3_0_0   
EXIST::FUNCTION:
 PKCS8_pkey_add1_attr_by_OBJ             ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_private_check                  ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_pairwise_check                 ?      3_0_0   EXIST::FUNCTION:
+ASN1_item_verify_ctx                    ?      3_0_0   EXIST::FUNCTION:

Reply via email to