[openssl] master update

Richard Levitte levitte at openssl.org
Sun Feb 2 11:17:40 UTC 2020


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 <levitte at openssl.org>
Date:   Thu Jan 30 16:02:49 2020 +0100

    CHANGES: Add note about the refactoring of SM2 EVP_PKEYs
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Dmitry Belyavskiy <beldmit at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit bac1030ae4f93f22b3a81e3a2d9d3c5db363d96f
Author: Richard Levitte <levitte at openssl.org>
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 <matt at openssl.org>
    Reviewed-by: Dmitry Belyavskiy <beldmit at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit 3995de2c0356d8e3b34e8fb2ddf22b20210e498d
Author: Richard Levitte <levitte at openssl.org>
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 <matt at openssl.org>
    Reviewed-by: Dmitry Belyavskiy <beldmit at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit ef077ba0d2fa28fd1b481f80335bda723d3d1f20
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Jan 24 18:14:06 2020 +0100

    Make SM3 a mandatory hash function for SM2.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Dmitry Belyavskiy <beldmit at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit bbaddbc0682a4cd3271ee41f58550f7c26e8194e
Author: Richard Levitte <levitte at openssl.org>
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 <matt at openssl.org>
    Reviewed-by: Dmitry Belyavskiy <beldmit at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit 0943d5dd6179e2e824ec9a38b7ea6caa17a84ebd
Author: Richard Levitte <levitte at openssl.org>
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 <matt at openssl.org>
    Reviewed-by: Dmitry Belyavskiy <beldmit at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/10942)

commit f4e4382cae1fb85fec6e9aa26f65fc729a40a039
Author: Richard Levitte <levitte at openssl.org>
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 <matt at openssl.org>
    Reviewed-by: Dmitry Belyavskiy <beldmit at gmail.com>
    (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:


More information about the openssl-commits mailing list