From 4803717f5e3bcfba3e3442e1611f421bf1090a47 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Tue, 4 Sep 2018 17:21:10 +0800 Subject: Support setting SM2 ID zero-length ID is allowed, but it's not allowed to skip the ID. Fixes: #6534 Reviewed-by: Tim Hudson Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/7113) --- crypto/sm2/sm2_err.c | 6 ++-- crypto/sm2/sm2_pmeth.c | 82 ++++++++++++++++++++++++++++++++++++-------------- crypto/sm2/sm2_sign.c | 64 +++++++++++++++++++++------------------ 3 files changed, 96 insertions(+), 56 deletions(-) (limited to 'crypto/sm2') diff --git a/crypto/sm2/sm2_err.c b/crypto/sm2/sm2_err.c index 035abdc49e..7bc812e42e 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 63c93891e2..aed7f33044 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 bf68dde7b6..e594ffd10a 100644 --- a/crypto/sm2/sm2_sign.c +++ b/crypto/sm2/sm2_sign.c @@ -18,11 +18,11 @@ #include #include -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; } -- cgit v1.2.3