summaryrefslogtreecommitdiffstats
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
parent00433bad41bfa492f2e204675d42061314028ff2 (diff)
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)
-rw-r--r--crypto/err/openssl.txt3
-rw-r--r--crypto/evp/digest.c9
-rw-r--r--crypto/evp/evp_lib.c2
-rw-r--r--crypto/evp/m_sigver.c25
-rw-r--r--crypto/evp/pmeth_lib.c7
-rw-r--r--crypto/include/internal/evp_int.h6
-rw-r--r--crypto/include/internal/sm2.h13
-rw-r--r--crypto/include/internal/sm2err.h4
-rw-r--r--crypto/sm2/sm2_err.c6
-rw-r--r--crypto/sm2/sm2_pmeth.c82
-rw-r--r--crypto/sm2/sm2_sign.c64
-rw-r--r--include/openssl/ec.h16
-rw-r--r--include/openssl/evp.h6
-rw-r--r--test/evp_extra_test.c14
-rw-r--r--util/private.num3
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 <openssl/evp.h>
#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 <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;
}
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 <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
+#include <openssl/pem.h>
#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