Make SM2 ID stick to specification
authorPaul Yang <yang.yang@baishancloud.com>
Mon, 3 Sep 2018 17:24:55 +0000 (01:24 +0800)
committerPaul Yang <yang.yang@baishancloud.com>
Fri, 7 Sep 2018 10:12:26 +0000 (18:12 +0800)
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7113)

crypto/include/internal/sm2.h
crypto/sm2/sm2_pmeth.c
crypto/sm2/sm2_sign.c
test/sm2_internal_test.c

index 11af248..26a9066 100644 (file)
 /* The default user id as specified in GM/T 0009-2012 */
 #  define SM2_DEFAULT_USERID "1234567812345678"
 
+int sm2_compute_userid_digest(uint8_t *out,
+                              const EVP_MD *digest,
+                              const uint8_t *id,
+                              const size_t id_len,
+                              const EC_KEY *key);
+
 /*
  * SM2 signature operation. Computes ZA (user id digest) and then signs
  * H(ZA || msg) using SM2
  */
 ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
                        const EVP_MD *digest,
-                       const char *user_id, const uint8_t *msg, size_t msg_len);
+                       const uint8_t *id,
+                       const size_t id_len,
+                       const uint8_t *msg, size_t msg_len);
 
 int sm2_do_verify(const EC_KEY *key,
                   const EVP_MD *digest,
                   const ECDSA_SIG *signature,
-                  const char *user_id, const uint8_t *msg, size_t msg_len);
+                  const uint8_t *id,
+                  const size_t id_len,
+                  const uint8_t *msg, size_t msg_len);
 
 /*
  * SM2 signature generation.
index b027131..63c9389 100644 (file)
@@ -22,6 +22,8 @@ typedef struct {
     EC_GROUP *gen_group;
     /* message digest */
     const EVP_MD *md;
+    uint8_t *id;
+    size_t id_len;
 } SM2_PKEY_CTX;
 
 static int pkey_sm2_init(EVP_PKEY_CTX *ctx)
@@ -209,6 +211,29 @@ static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx,
     return -2;
 }
 
+static int pkey_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
+{
+    uint8_t z[EVP_MAX_MD_SIZE];
+    SM2_PKEY_CTX *sctx = ctx->data;
+    EC_KEY *ec = ctx->pkey->pkey.ec;
+    const EVP_MD *md = EVP_MD_CTX_md(mctx);
+
+    if (sctx->id == NULL) {
+        /* XXX:
+         * currently we reject all null-ID for SM2, but this needs
+         * more considerations and discussion since the specifications
+         * on SM2 are not clear on null-ID
+         */
+        return 0;
+    }
+
+    /* get hashed prefix of tbs message */
+    if (!sm2_compute_userid_digest(z, md, sctx->id, sctx->id_len, ec))
+        return 0;
+
+    return EVP_DigestUpdate(mctx, z, EVP_MD_size(md));
+}
+
 const EVP_PKEY_METHOD sm2_pkey_meth = {
     EVP_PKEY_SM2,
     0,
@@ -241,5 +266,11 @@ const EVP_PKEY_METHOD sm2_pkey_meth = {
     0,
     0,
     pkey_sm2_ctrl,
-    pkey_sm2_ctrl_str
+    pkey_sm2_ctrl_str,
+
+    0, 0,
+
+    0, 0, 0,
+
+    pkey_sm2_digest_custom
 };
index 0a4281f..bf68dde 100644 (file)
 #include <openssl/bn.h>
 #include <string.h>
 
-static int sm2_compute_userid_digest(uint8_t *out,
-                                     const EVP_MD *digest,
-                                     const char *user_id,
-                                     const EC_KEY *key)
+int sm2_compute_userid_digest(uint8_t *out,
+                              const EVP_MD *digest,
+                              const uint8_t *id,
+                              const size_t id_len,
+                              const EC_KEY *key)
 {
     int rc = 0;
     const EC_GROUP *group = EC_KEY_get0_group(key);
@@ -36,7 +37,6 @@ static int sm2_compute_userid_digest(uint8_t *out,
     BIGNUM *yA = NULL;
     int p_bytes = 0;
     uint8_t *buf = NULL;
-    size_t uid_len = 0;
     uint16_t entla = 0;
     uint8_t e_byte = 0;
 
@@ -67,14 +67,13 @@ static int sm2_compute_userid_digest(uint8_t *out,
 
     /* Z = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) */
 
-    uid_len = strlen(user_id);
-    if (uid_len >= (UINT16_MAX / 8)) {
+    if (id_len >= (UINT16_MAX / 8)) {
         /* too large */
         SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, SM2_R_USER_ID_TOO_LARGE);
         goto done;
     }
 
-    entla = (uint16_t)(8 * uid_len);
+    entla = (uint16_t)(8 * id_len);
 
     e_byte = entla >> 8;
     if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
@@ -83,7 +82,7 @@ static int sm2_compute_userid_digest(uint8_t *out,
     }
     e_byte = entla & 0xFF;
     if (!EVP_DigestUpdate(hash, &e_byte, 1)
-            || !EVP_DigestUpdate(hash, user_id, uid_len)) {
+            || !EVP_DigestUpdate(hash, id, id_len)) {
         SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_EVP_LIB);
         goto done;
     }
@@ -134,7 +133,8 @@ static int sm2_compute_userid_digest(uint8_t *out,
 
 static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
                                     const EC_KEY *key,
-                                    const char *user_id,
+                                    const uint8_t *id,
+                                    const size_t id_len,
                                     const uint8_t *msg, size_t msg_len)
 {
     EVP_MD_CTX *hash = EVP_MD_CTX_new();
@@ -153,7 +153,7 @@ static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
         goto done;
     }
 
-    if (!sm2_compute_userid_digest(za, digest, user_id, key)) {
+    if (!sm2_compute_userid_digest(za, digest, id, id_len, key)) {
         /* SM2err already called */
         goto done;
     }
@@ -358,12 +358,14 @@ static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig,
 
 ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
                        const EVP_MD *digest,
-                       const char *user_id, const uint8_t *msg, size_t msg_len)
+                       const uint8_t *id,
+                       const size_t id_len,
+                       const uint8_t *msg, size_t msg_len)
 {
     BIGNUM *e = NULL;
     ECDSA_SIG *sig = NULL;
 
-    e = sm2_compute_msg_hash(digest, key, user_id, msg, msg_len);
+    e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len);
     if (e == NULL) {
         /* SM2err already called */
         goto done;
@@ -379,12 +381,14 @@ ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
 int sm2_do_verify(const EC_KEY *key,
                   const EVP_MD *digest,
                   const ECDSA_SIG *sig,
-                  const char *user_id, const uint8_t *msg, size_t msg_len)
+                  const uint8_t *id,
+                  const size_t id_len,
+                  const uint8_t *msg, size_t msg_len)
 {
     BIGNUM *e = NULL;
     int ret = 0;
 
-    e = sm2_compute_msg_hash(digest, key, user_id, msg, msg_len);
+    e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len);
     if (e == NULL) {
         /* SM2err already called */
         goto done;
index 0d145e8..015fa85 100644 (file)
@@ -294,7 +294,8 @@ static int test_sm2_sign(const EC_GROUP *group,
         goto done;
 
     start_fake_rand(k_hex);
-    sig = sm2_do_sign(key, EVP_sm3(), userid, (const uint8_t *)message, msg_len);
+    sig = sm2_do_sign(key, EVP_sm3(), (const uint8_t *)userid, strlen(userid),
+                      (const uint8_t *)message, msg_len);
     if (!TEST_ptr(sig)
             || !TEST_size_t_eq(fake_rand_bytes_offset, fake_rand_size)) {
         restore_rand();
@@ -310,8 +311,8 @@ static int test_sm2_sign(const EC_GROUP *group,
             || !TEST_BN_eq(s, sig_s))
         goto done;
 
-    ok = sm2_do_verify(key, EVP_sm3(), sig, userid, (const uint8_t *)message,
-                       msg_len);
+    ok = sm2_do_verify(key, EVP_sm3(), sig, (const uint8_t *)userid,
+                       strlen(userid), (const uint8_t *)message, msg_len);
 
     /* We goto done whether this passes or fails */
     TEST_true(ok);