aboutsummaryrefslogtreecommitdiff
path: root/crypto/sm2
diff options
context:
space:
mode:
authorPaul Yang <yang.yang@baishancloud.com>2018-09-04 17:21:10 +0800
committerPaul Yang <yang.yang@baishancloud.com>2018-09-07 18:12:26 +0800
commit4803717f5e3bcfba3e3442e1611f421bf1090a47 (patch)
treef5745d40a7eeb81e8e49f734ae6f962173981eb7 /crypto/sm2
parent00433bad41bfa492f2e204675d42061314028ff2 (diff)
downloadopenssl-4803717f5e3bcfba3e3442e1611f421bf1090a47.zip
openssl-4803717f5e3bcfba3e3442e1611f421bf1090a47.tar.gz
openssl-4803717f5e3bcfba3e3442e1611f421bf1090a47.tar.bz2
Support setting SM2 ID
zero-length ID is allowed, but it's not allowed to skip the ID. Fixes: #6534 Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/7113)
Diffstat (limited to 'crypto/sm2')
-rw-r--r--crypto/sm2/sm2_err.c6
-rw-r--r--crypto/sm2/sm2_pmeth.c82
-rw-r--r--crypto/sm2/sm2_sign.c64
3 files changed, 96 insertions, 56 deletions
diff --git a/crypto/sm2/sm2_err.c b/crypto/sm2/sm2_err.c
index 035abdc..7bc812e 100644
--- a/crypto/sm2/sm2_err.c
+++ b/crypto/sm2/sm2_err.c
@@ -20,8 +20,8 @@ static const ERR_STRING_DATA SM2_str_functs[] = {
{ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"},
{ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_MSG_HASH, 0),
"sm2_compute_msg_hash"},
- {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_USERID_DIGEST, 0),
- "sm2_compute_userid_digest"},
+ {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_Z_DIGEST, 0),
+ "sm2_compute_z_digest"},
{ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_DECRYPT, 0), "sm2_decrypt"},
{ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_ENCRYPT, 0), "sm2_encrypt"},
{ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_PLAINTEXT_SIZE, 0), "sm2_plaintext_size"},
@@ -36,6 +36,7 @@ static const ERR_STRING_DATA SM2_str_reasons[] = {
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ASN1_ERROR), "asn1 error"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BAD_SIGNATURE), "bad signature"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BUFFER_TOO_SMALL), "buffer too small"},
+ {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ID_TOO_LARGE), "id too large"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_CURVE), "invalid curve"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST), "invalid digest"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST_TYPE),
@@ -43,7 +44,6 @@ static const ERR_STRING_DATA SM2_str_reasons[] = {
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_ENCODING), "invalid encoding"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_FIELD), "invalid field"},
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PARAMETERS_SET), "no parameters set"},
- {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_USER_ID_TOO_LARGE), "user id too large"},
{0, NULL}
};
diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c
index 63c9389..aed7f33 100644
--- a/crypto/sm2/sm2_pmeth.c
+++ b/crypto/sm2/sm2_pmeth.c
@@ -22,30 +22,34 @@ typedef struct {
EC_GROUP *gen_group;
/* message digest */
const EVP_MD *md;
+ /* Distinguishing Identifier, ISO/IEC 15946-3 */
uint8_t *id;
size_t id_len;
+ /* id_set indicates if the 'id' field is set (1) or not (0) */
+ int id_set;
} SM2_PKEY_CTX;
static int pkey_sm2_init(EVP_PKEY_CTX *ctx)
{
- SM2_PKEY_CTX *dctx;
+ SM2_PKEY_CTX *smctx;
- if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
+ if ((smctx = OPENSSL_zalloc(sizeof(*smctx))) == NULL) {
SM2err(SM2_F_PKEY_SM2_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
- ctx->data = dctx;
+ ctx->data = smctx;
return 1;
}
static void pkey_sm2_cleanup(EVP_PKEY_CTX *ctx)
{
- SM2_PKEY_CTX *dctx = ctx->data;
+ SM2_PKEY_CTX *smctx = ctx->data;
- if (dctx != NULL) {
- EC_GROUP_free(dctx->gen_group);
- OPENSSL_free(dctx);
+ if (smctx != NULL) {
+ EC_GROUP_free(smctx->gen_group);
+ OPENSSL_free(smctx->id);
+ OPENSSL_free(smctx);
ctx->data = NULL;
}
}
@@ -65,6 +69,16 @@ static int pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
return 0;
}
}
+ if (sctx->id != NULL) {
+ dctx->id = OPENSSL_malloc(sctx->id_len);
+ if (dctx->id == NULL) {
+ pkey_sm2_cleanup(dst);
+ return 0;
+ }
+ memcpy(dctx->id, sctx->id, sctx->id_len);
+ }
+ dctx->id_len = sctx->id_len;
+ dctx->id_set = sctx->id_set;
dctx->md = sctx->md;
return 1;
@@ -147,7 +161,7 @@ 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 *dctx = ctx->data;
+ SM2_PKEY_CTX *smctx = ctx->data;
EC_GROUP *group;
switch (type) {
@@ -157,29 +171,51 @@ static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_INVALID_CURVE);
return 0;
}
- EC_GROUP_free(dctx->gen_group);
- dctx->gen_group = group;
+ EC_GROUP_free(smctx->gen_group);
+ smctx->gen_group = group;
return 1;
case EVP_PKEY_CTRL_EC_PARAM_ENC:
- if (dctx->gen_group == NULL) {
+ if (smctx->gen_group == NULL) {
SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_NO_PARAMETERS_SET);
return 0;
}
- EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
+ EC_GROUP_set_asn1_flag(smctx->gen_group, p1);
return 1;
case EVP_PKEY_CTRL_MD:
- dctx->md = p2;
+ smctx->md = p2;
return 1;
case EVP_PKEY_CTRL_GET_MD:
- *(const EVP_MD **)p2 = dctx->md;
+ *(const EVP_MD **)p2 = smctx->md;
+ return 1;
+
+ case EVP_PKEY_CTRL_SET1_ID:
+ OPENSSL_free(smctx->id);
+ if (p1 > 0) {
+ smctx->id = OPENSSL_malloc(p1);
+ if (smctx->id == NULL)
+ return 0;
+ memcpy(smctx->id, p2, p1);
+ } else {
+ /* set null-ID */
+ smctx->id = NULL;
+ }
+ smctx->id_len = (size_t)p1;
+ smctx->id_set = 1;
+ return 1;
+
+ case EVP_PKEY_CTRL_GET1_ID:
+ memcpy(p2, smctx->id, smctx->id_len);
+ return 1;
+
+ case EVP_PKEY_CTRL_GET1_ID_LEN:
+ *(size_t *)p2 = smctx->id_len;
return 1;
default:
return -2;
-
}
}
@@ -214,21 +250,21 @@ static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx,
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;
+ SM2_PKEY_CTX *smctx = 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
+ if (!smctx->id_set) {
+ /*
+ * An ID value must be set. The specifications are not clear whether a
+ * NULL is allowed. We only allow it if set explicitly for maximum
+ * flexibility.
*/
return 0;
}
- /* get hashed prefix of tbs message */
- if (!sm2_compute_userid_digest(z, md, sctx->id, sctx->id_len, ec))
+ /* get hashed prefix 'z' of tbs message */
+ if (!sm2_compute_z_digest(z, md, smctx->id, smctx->id_len, ec))
return 0;
return EVP_DigestUpdate(mctx, z, EVP_MD_size(md));
diff --git a/crypto/sm2/sm2_sign.c b/crypto/sm2/sm2_sign.c
index bf68dde..e594ffd 100644
--- a/crypto/sm2/sm2_sign.c
+++ b/crypto/sm2/sm2_sign.c
@@ -18,11 +18,11 @@
#include <openssl/bn.h>
#include <string.h>
-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 sm2_compute_z_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);
@@ -37,13 +37,13 @@ int sm2_compute_userid_digest(uint8_t *out,
BIGNUM *yA = NULL;
int p_bytes = 0;
uint8_t *buf = NULL;
- uint16_t entla = 0;
+ uint16_t entl = 0;
uint8_t e_byte = 0;
hash = EVP_MD_CTX_new();
ctx = BN_CTX_new();
if (hash == NULL || ctx == NULL) {
- SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_MALLOC_FAILURE);
+ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -56,46 +56,50 @@ int sm2_compute_userid_digest(uint8_t *out,
yA = BN_CTX_get(ctx);
if (yA == NULL) {
- SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_MALLOC_FAILURE);
+ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
goto done;
}
if (!EVP_DigestInit(hash, digest)) {
- SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_EVP_LIB);
+ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
goto done;
}
- /* Z = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) */
+ /* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */
if (id_len >= (UINT16_MAX / 8)) {
/* too large */
- SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, SM2_R_USER_ID_TOO_LARGE);
+ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, SM2_R_ID_TOO_LARGE);
goto done;
}
- entla = (uint16_t)(8 * id_len);
+ entl = (uint16_t)(8 * id_len);
- e_byte = entla >> 8;
+ e_byte = entl >> 8;
if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
- SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_EVP_LIB);
+ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
goto done;
}
- e_byte = entla & 0xFF;
- if (!EVP_DigestUpdate(hash, &e_byte, 1)
- || !EVP_DigestUpdate(hash, id, id_len)) {
- SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_EVP_LIB);
+ e_byte = entl & 0xFF;
+ if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
+ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
+ goto done;
+ }
+
+ if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) {
+ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
goto done;
}
if (!EC_GROUP_get_curve(group, p, a, b, ctx)) {
- SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_EC_LIB);
+ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EC_LIB);
goto done;
}
p_bytes = BN_num_bytes(p);
buf = OPENSSL_zalloc(p_bytes);
if (buf == NULL) {
- SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_MALLOC_FAILURE);
+ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
goto done;
}
@@ -118,7 +122,7 @@ int sm2_compute_userid_digest(uint8_t *out,
|| BN_bn2binpad(yA, buf, p_bytes) < 0
|| !EVP_DigestUpdate(hash, buf, p_bytes)
|| !EVP_DigestFinal(hash, out, NULL)) {
- SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_INTERNAL_ERROR);
+ SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_INTERNAL_ERROR);
goto done;
}
@@ -139,7 +143,7 @@ static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
{
EVP_MD_CTX *hash = EVP_MD_CTX_new();
const int md_size = EVP_MD_size(digest);
- uint8_t *za = NULL;
+ uint8_t *z = NULL;
BIGNUM *e = NULL;
if (md_size < 0) {
@@ -147,32 +151,32 @@ static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
goto done;
}
- za = OPENSSL_zalloc(md_size);
- if (hash == NULL || za == NULL) {
+ z = OPENSSL_zalloc(md_size);
+ if (hash == NULL || z == NULL) {
SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_MALLOC_FAILURE);
goto done;
}
- if (!sm2_compute_userid_digest(za, digest, id, id_len, key)) {
+ if (!sm2_compute_z_digest(z, digest, id, id_len, key)) {
/* SM2err already called */
goto done;
}
if (!EVP_DigestInit(hash, digest)
- || !EVP_DigestUpdate(hash, za, md_size)
+ || !EVP_DigestUpdate(hash, z, md_size)
|| !EVP_DigestUpdate(hash, msg, msg_len)
- /* reuse za buffer to hold H(ZA || M) */
- || !EVP_DigestFinal(hash, za, NULL)) {
+ /* reuse z buffer to hold H(Z || M) */
+ || !EVP_DigestFinal(hash, z, NULL)) {
SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_EVP_LIB);
goto done;
}
- e = BN_bin2bn(za, md_size, NULL);
+ e = BN_bin2bn(z, md_size, NULL);
if (e == NULL)
SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_INTERNAL_ERROR);
done:
- OPENSSL_free(za);
+ OPENSSL_free(z);
EVP_MD_CTX_free(hash);
return e;
}