From 00433bad41bfa492f2e204675d42061314028ff2 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Tue, 4 Sep 2018 01:24:55 +0800 Subject: [PATCH] Make SM2 ID stick to specification Reviewed-by: Tim Hudson Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/7113) --- crypto/include/internal/sm2.h | 14 ++++++++++++-- crypto/sm2/sm2_pmeth.c | 33 ++++++++++++++++++++++++++++++++- crypto/sm2/sm2_sign.c | 34 +++++++++++++++++++--------------- test/sm2_internal_test.c | 7 ++++--- 4 files changed, 67 insertions(+), 21 deletions(-) diff --git a/crypto/include/internal/sm2.h b/crypto/include/internal/sm2.h index 11af248b5a..26a90660ee 100644 --- a/crypto/include/internal/sm2.h +++ b/crypto/include/internal/sm2.h @@ -20,18 +20,28 @@ /* 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. diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c index b027131889..63c93891e2 100644 --- a/crypto/sm2/sm2_pmeth.c +++ b/crypto/sm2/sm2_pmeth.c @@ -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 }; diff --git a/crypto/sm2/sm2_sign.c b/crypto/sm2/sm2_sign.c index 0a4281fb5d..bf68dde7b6 100644 --- a/crypto/sm2/sm2_sign.c +++ b/crypto/sm2/sm2_sign.c @@ -18,10 +18,11 @@ #include #include -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; diff --git a/test/sm2_internal_test.c b/test/sm2_internal_test.c index 0d145e8553..015fa85e68 100644 --- a/test/sm2_internal_test.c +++ b/test/sm2_internal_test.c @@ -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); -- 2.25.1