From 4803717f5e3bcfba3e3442e1611f421bf1090a47 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Tue, 4 Sep 2018 17:21:10 +0800 Subject: [PATCH] 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/err/openssl.txt | 3 ++ crypto/evp/digest.c | 9 ++-- crypto/evp/evp_lib.c | 2 +- crypto/evp/m_sigver.c | 25 +++++----- crypto/evp/pmeth_lib.c | 7 ++- crypto/include/internal/evp_int.h | 6 +++ crypto/include/internal/sm2.h | 13 +++-- crypto/include/internal/sm2err.h | 4 +- crypto/sm2/sm2_err.c | 6 +-- crypto/sm2/sm2_pmeth.c | 82 ++++++++++++++++++++++--------- crypto/sm2/sm2_sign.c | 64 +++++++++++++----------- include/openssl/ec.h | 16 ++++++ include/openssl/evp.h | 6 +-- test/evp_extra_test.c | 14 ++++++ util/private.num | 3 ++ 15 files changed, 172 insertions(+), 88 deletions(-) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 3ecd44b5e8..2f86786d58 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1086,6 +1086,7 @@ SM2_F_PKEY_SM2_INIT:111:pkey_sm2_init SM2_F_PKEY_SM2_SIGN:112:pkey_sm2_sign SM2_F_SM2_COMPUTE_MSG_HASH:100:sm2_compute_msg_hash SM2_F_SM2_COMPUTE_USERID_DIGEST:101:sm2_compute_userid_digest +SM2_F_SM2_COMPUTE_Z_DIGEST:113:sm2_compute_z_digest SM2_F_SM2_DECRYPT:102:sm2_decrypt SM2_F_SM2_ENCRYPT:103:sm2_encrypt SM2_F_SM2_PLAINTEXT_SIZE:104:sm2_plaintext_size @@ -2554,6 +2555,8 @@ RSA_R_WRONG_SIGNATURE_LENGTH:119:wrong signature length SM2_R_ASN1_ERROR:100:asn1 error SM2_R_BAD_SIGNATURE:101:bad signature SM2_R_BUFFER_TOO_SMALL:107:buffer too small +SM2_R_DIST_ID_TOO_LARGE:110:dist id too large +SM2_R_ID_TOO_LARGE:111:id too large SM2_R_INVALID_CURVE:108:invalid curve SM2_R_INVALID_DIGEST:102:invalid digest SM2_R_INVALID_DIGEST_TYPE:103:invalid digest type diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index 8a2d162df1..f78dab7678 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -34,9 +34,9 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx) } /* * pctx should be freed by the user of EVP_MD_CTX - * if EVP_MD_CTX_FLAG_NEGLECT_PCTX is set + * if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set */ - if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_NEGLECT_PCTX)) + if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) EVP_PKEY_CTX_free(ctx->pctx); #ifndef OPENSSL_NO_ENGINE ENGINE_finish(ctx->engine); @@ -229,6 +229,9 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) EVP_MD_CTX_reset(out); memcpy(out, in, sizeof(*out)); + /* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */ + EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); + /* Null these variables, since they are getting fixed up * properly below. Anything else may cause a memleak and/or * double free if any of the memory allocations below fail diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 4faaf694b4..81a5bf0012 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -464,7 +464,7 @@ void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx) { ctx->pctx = pctx; /* make sure pctx is not freed when destroying EVP_MD_CTX */ - EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NEGLECT_PCTX); + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); } void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx) diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index 4a0e5d5c55..2eceede28c 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -75,14 +75,13 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, return 1; if (!EVP_DigestInit_ex(ctx, type, e)) return 0; - if (ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_DIGEST_CUSTOM) { - /* - * This indicates the current algorithm requires - * special treatment before hashing the tbs-message. - */ - if (ctx->pctx->pmeth->digest_custom) - return ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx); - } + /* + * This indicates the current algorithm requires + * special treatment before hashing the tbs-message. + */ + if (ctx->pctx->pmeth->digest_custom) + return ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx); + return 1; } @@ -184,9 +183,9 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, else vctx = 0; if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) { - if (vctx) { + if (vctx) r = ctx->pctx->pmeth->verifyctx(ctx->pctx, sig, siglen, ctx); - } else + else r = EVP_DigestFinal_ex(ctx, md, &mdlen); } else { EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); @@ -196,10 +195,10 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, EVP_MD_CTX_free(tmp_ctx); return -1; } - if (vctx) { + if (vctx) r = tmp_ctx->pctx->pmeth->verifyctx(tmp_ctx->pctx, sig, siglen, tmp_ctx); - } else + else r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen); EVP_MD_CTX_free(tmp_ctx); } diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 7e6388e8f5..76405154a9 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -367,6 +367,7 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2) { int ret; + if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) { EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); return -2; @@ -374,6 +375,10 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype)) return -1; + /* Skip the operation checks since this is called in a very early stage */ + if (ctx->pmeth->digest_custom != NULL) + goto doit; + if (ctx->operation == EVP_PKEY_OP_UNDEFINED) { EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET); return -1; @@ -384,13 +389,13 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, return -1; } + doit: ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2); if (ret == -2) EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); return ret; - } int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h index 3264b3df71..d86aed36f0 100644 --- a/crypto/include/internal/evp_int.h +++ b/crypto/include/internal/evp_int.h @@ -10,6 +10,12 @@ #include #include "internal/refcount.h" +/* + * Don't free up md_ctx->pctx in EVP_MD_CTX_reset, use the reserved flag + * values in evp.h + */ +#define EVP_MD_CTX_FLAG_KEEP_PKEY_CTX 0x0400 + struct evp_pkey_ctx_st { /* Method associated with this operation */ const EVP_PKEY_METHOD *pmeth; diff --git a/crypto/include/internal/sm2.h b/crypto/include/internal/sm2.h index 26a90660ee..5c5cd4b4f5 100644 --- a/crypto/include/internal/sm2.h +++ b/crypto/include/internal/sm2.h @@ -20,15 +20,14 @@ /* 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); +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); /* - * SM2 signature operation. Computes ZA (user id digest) and then signs - * H(ZA || msg) using SM2 + * SM2 signature operation. Computes Z and then signs H(Z || msg) using SM2 */ ECDSA_SIG *sm2_do_sign(const EC_KEY *key, const EVP_MD *digest, diff --git a/crypto/include/internal/sm2err.h b/crypto/include/internal/sm2err.h index 9a7e2b6275..4b8536db32 100644 --- a/crypto/include/internal/sm2err.h +++ b/crypto/include/internal/sm2err.h @@ -28,7 +28,7 @@ int ERR_load_SM2_strings(void); # define SM2_F_PKEY_SM2_INIT 111 # define SM2_F_PKEY_SM2_SIGN 112 # define SM2_F_SM2_COMPUTE_MSG_HASH 100 -# define SM2_F_SM2_COMPUTE_USERID_DIGEST 101 +# define SM2_F_SM2_COMPUTE_Z_DIGEST 113 # define SM2_F_SM2_DECRYPT 102 # define SM2_F_SM2_ENCRYPT 103 # define SM2_F_SM2_PLAINTEXT_SIZE 104 @@ -43,13 +43,13 @@ int ERR_load_SM2_strings(void); # define SM2_R_ASN1_ERROR 100 # define SM2_R_BAD_SIGNATURE 101 # define SM2_R_BUFFER_TOO_SMALL 107 +# define SM2_R_ID_TOO_LARGE 111 # define SM2_R_INVALID_CURVE 108 # define SM2_R_INVALID_DIGEST 102 # define SM2_R_INVALID_DIGEST_TYPE 103 # define SM2_R_INVALID_ENCODING 104 # define SM2_R_INVALID_FIELD 105 # define SM2_R_NO_PARAMETERS_SET 109 -# define SM2_R_USER_ID_TOO_LARGE 106 # endif #endif 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; } diff --git a/include/openssl/ec.h b/include/openssl/ec.h index 9cbb8b8e9d..4d70da70a6 100644 --- a/include/openssl/ec.h +++ b/include/openssl/ec.h @@ -1429,6 +1429,19 @@ void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)(p)) +/* SM2 will skip the operation check so no need to pass operation here */ +# define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id)) + +# define EVP_PKEY_CTX_get1_id(ctx, id) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id)) + +# define EVP_PKEY_CTX_get1_id_len(ctx, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(id_len)) + # define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) # define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) # define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3) @@ -1439,6 +1452,9 @@ void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, # define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) # define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) # define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13) /* KDF types */ # define EVP_PKEY_ECDH_KDF_NONE 1 # define EVP_PKEY_ECDH_KDF_X9_62 2 diff --git a/include/openssl/evp.h b/include/openssl/evp.h index b7c0243857..8c8051993f 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -180,9 +180,7 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd, * if the following flag is set. */ # define EVP_MD_CTX_FLAG_FINALISE 0x0200 - -/* Don't free up ctx->pctx in EVP_MD_CTX_reset */ -# define EVP_MD_CTX_FLAG_NEGLECT_PCTX 0x0400 +/* NOTE: 0x0400 is reserved for internal usage in evp_int.h */ EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len); EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher); @@ -1325,8 +1323,6 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, * Method handles all operations: don't assume any digest related defaults. */ # define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4 -/* Do a customized hashing process */ -# define EVP_PKEY_FLAG_DIGEST_CUSTOM 8 const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type); EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags); diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index 33a957f791..2fb3914ee8 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "testutil.h" #include "internal/nelem.h" #include "internal/evp_int.h" @@ -530,6 +531,7 @@ static int test_EVP_SM2(void) EVP_PKEY *params = NULL; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY_CTX *kctx = NULL; + EVP_PKEY_CTX *sctx = NULL; size_t sig_len = 0; unsigned char *sig = NULL; EVP_MD_CTX *md_ctx = NULL; @@ -542,6 +544,8 @@ static int test_EVP_SM2(void) uint8_t plaintext[8]; size_t ptext_len = sizeof(plaintext); + uint8_t sm2_id[] = {1, 2, 3, 4, 'l', 'e', 't', 't', 'e', 'r'}; + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (!TEST_ptr(pctx)) goto done; @@ -574,6 +578,15 @@ static int test_EVP_SM2(void) if (!TEST_ptr(md_ctx_verify = EVP_MD_CTX_new())) goto done; + if (!TEST_ptr(sctx = EVP_PKEY_CTX_new(pkey, NULL))) + goto done; + + EVP_MD_CTX_set_pkey_ctx(md_ctx, sctx); + EVP_MD_CTX_set_pkey_ctx(md_ctx_verify, sctx); + + if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(sctx, sm2_id, sizeof(sm2_id)), 0)) + goto done; + if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey))) goto done; @@ -631,6 +644,7 @@ static int test_EVP_SM2(void) done: EVP_PKEY_CTX_free(pctx); EVP_PKEY_CTX_free(kctx); + EVP_PKEY_CTX_free(sctx); EVP_PKEY_CTX_free(cctx); EVP_PKEY_free(pkey); EVP_PKEY_free(params); diff --git a/util/private.num b/util/private.num index b90e33db80..0391091a2f 100644 --- a/util/private.num +++ b/util/private.num @@ -413,3 +413,6 @@ SSLv23_method define SSLv23_server_method define X509_STORE_set_lookup_crls_cb define X509_STORE_set_verify_func define +EVP_PKEY_CTX_set1_id define +EVP_PKEY_CTX_get1_id define +EVP_PKEY_CTX_get1_id_len define -- 2.34.1