!15 add SM2 sign function for openssl engine
From: @wangyoukang Reviewed-by: @mailofzxf Signed-off-by: @mailofzxf
This commit is contained in:
commit
466c31996b
369
0003-add-SM2-sign-function-for-openssl-engine.patch
Normal file
369
0003-add-SM2-sign-function-for-openssl-engine.patch
Normal file
@ -0,0 +1,369 @@
|
||||
From a2d613ade54068d7ea44ecce9718023ca53eefde Mon Sep 17 00:00:00 2001
|
||||
From: guowentao <guowentao@xfusion.com>
|
||||
Date: Fri, 16 Jun 2023 11:39:29 +0800
|
||||
Subject: [PATCH] add SM2 sign function for openssl engine
|
||||
|
||||
Signed-off-by: guowentao <guowentao@xfusion.com>
|
||||
---
|
||||
src/tpm2-tss-engine-common.h | 1 +
|
||||
src/tpm2-tss-engine-ecc.c | 8 ++
|
||||
src/tpm2-tss-engine-err.h | 1 +
|
||||
src/tpm2-tss-engine-sm2.c | 241 +++++++++++++++++++++++++++++++++++
|
||||
src/tpm2-tss-engine.c | 7 +-
|
||||
5 files changed, 257 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/tpm2-tss-engine-common.h b/src/tpm2-tss-engine-common.h
|
||||
index 14c98a0..e15e9bd 100755
|
||||
--- a/src/tpm2-tss-engine-common.h
|
||||
+++ b/src/tpm2-tss-engine-common.h
|
||||
@@ -51,6 +51,7 @@ extern char *tcti_nameconf;
|
||||
int init_ecc(ENGINE *e);
|
||||
int init_rand(ENGINE *e);
|
||||
int init_rsa(ENGINE *e);
|
||||
+int init_sm2(ENGINE *e);
|
||||
|
||||
TSS2_RC esys_ctx_init (ESYS_CONTEXT **esys_ctx);
|
||||
|
||||
diff --git a/src/tpm2-tss-engine-ecc.c b/src/tpm2-tss-engine-ecc.c
|
||||
index c1c5864..ec1882f 100644
|
||||
--- a/src/tpm2-tss-engine-ecc.c
|
||||
+++ b/src/tpm2-tss-engine-ecc.c
|
||||
@@ -300,6 +300,9 @@ populate_ecc(EC_KEY *key)
|
||||
case TPM2_ECC_NIST_P384:
|
||||
nid = EC_curve_nist2nid("P-384");
|
||||
break;
|
||||
+ case TPM2_ECC_SM2_P256:
|
||||
+ nid = NID_sm2;
|
||||
+ break;
|
||||
default:
|
||||
nid = -1;
|
||||
}
|
||||
@@ -393,6 +396,11 @@ tpm2tss_ecc_makekey(TPM2_DATA *tpm2Data)
|
||||
goto error;
|
||||
}
|
||||
|
||||
+ if (!tpm2tss_sm2_setappdata(eckey, tpm2Data)) {
|
||||
+ ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
if (!populate_ecc(eckey))
|
||||
goto error;
|
||||
|
||||
diff --git a/src/tpm2-tss-engine-err.h b/src/tpm2-tss-engine-err.h
|
||||
index e6a7219..f9e0513 100644
|
||||
--- a/src/tpm2-tss-engine-err.h
|
||||
+++ b/src/tpm2-tss-engine-err.h
|
||||
@@ -98,6 +98,7 @@ void ERR_error(int function, int reason, const char *file, int line);
|
||||
/* tpm2-tss-engine-rsa.c */
|
||||
#define TPM2TSS_F_tpm2tss_sm2_genkey 144
|
||||
#define TPM2TSS_F_populate_sm2 145
|
||||
+#define TPM2TSS_F_tpm_pkey_sm2_sign 146
|
||||
|
||||
/* Reason codes */
|
||||
#define TPM2TSS_R_TPM2DATA_READ_FAILED 100
|
||||
diff --git a/src/tpm2-tss-engine-sm2.c b/src/tpm2-tss-engine-sm2.c
|
||||
index 679b36c..8a3908f 100644
|
||||
--- a/src/tpm2-tss-engine-sm2.c
|
||||
+++ b/src/tpm2-tss-engine-sm2.c
|
||||
@@ -43,6 +43,10 @@
|
||||
|
||||
static int ec_sm2_key_app_data = -1;
|
||||
|
||||
+static int (*sm2_pkey_orig_sign)(EVP_PKEY_CTX * ctx, unsigned char * sig, size_t * siglen, const unsigned char * tbs, size_t tbslen);
|
||||
+static int (*sm2_pkey_orig_verify)(EVP_PKEY_CTX * ctx, const unsigned char * sig, size_t siglen, const unsigned char * tbs, size_t tbslen);
|
||||
+static int (*sm2_pkey_orig_digest_custom)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);
|
||||
+
|
||||
static TPM2B_DATA allOutsideInfo = {
|
||||
.size = 0,
|
||||
};
|
||||
@@ -84,6 +88,181 @@ static TPM2B_PUBLIC keyEcTemplate = {
|
||||
}
|
||||
};
|
||||
|
||||
+static int
|
||||
+tpm_pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
||||
+ const unsigned char *tbs, size_t tbslen)
|
||||
+{
|
||||
+ DBG("[%s][IN] ctx:%p sig:%p siglen:%ld tbs:%p tbslen:%ld\n", __func__, ctx, sig, *siglen, tbs, tbslen);
|
||||
+ ECDSA_SIG *s = NULL;
|
||||
+ int sigleni;
|
||||
+ BIGNUM *bns = NULL, *bnr = NULL;
|
||||
+
|
||||
+ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
|
||||
+ EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey);
|
||||
+ const int sig_sz = ECDSA_size(eckey);
|
||||
+ TPM2_DATA *tpm2Data = tpm2tss_sm2_getappdata(eckey);
|
||||
+ TPM2_ALG_ID hash_alg;
|
||||
+
|
||||
+ /* If this is not a TPM2 key, fall through to software functions */
|
||||
+ if (tpm2Data == NULL) {
|
||||
+ DBG("origin sign funciton is called\n");
|
||||
+ sm2_pkey_orig_sign(ctx, sig, siglen, tbs, tbslen);
|
||||
+ }
|
||||
+ DBG("tbs content (size=%ld):\n", tbslen);
|
||||
+ DBGBUF(tbs, (int)tbslen);
|
||||
+
|
||||
+ TSS2_RC r = -1;
|
||||
+ ESYS_CONTEXT *esys_ctx = NULL;
|
||||
+ ESYS_TR keyHandle = ESYS_TR_NONE;
|
||||
+ TPMT_SIGNATURE *sig_tpm = NULL;
|
||||
+
|
||||
+ TPMT_TK_HASHCHECK validation = { .tag = TPM2_ST_HASHCHECK,
|
||||
+ .hierarchy = TPM2_RH_NULL,
|
||||
+ .digest.size = 0 };
|
||||
+
|
||||
+ TPMT_SIG_SCHEME inScheme = { .scheme = TPM2_ALG_SM2 };
|
||||
+
|
||||
+ if (sig_sz <= 0) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (sig == NULL) {
|
||||
+ *siglen = (size_t)sig_sz;
|
||||
+ DBG("siglen is %ld\n", *siglen);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (*siglen < (size_t)sig_sz) {
|
||||
+ DBG("error:SM2_F_PKEY_SM2_SIGN, SM2_R_BUFFER_TOO_SMALL");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ /*
|
||||
+ * ECDSA signatures truncate the incoming hash to fit the curve,
|
||||
+ * and the signature mechanism is the same regardless of the
|
||||
+ * hash being used.
|
||||
+ *
|
||||
+ * The TPM bizarrely wants to be told the hash algorithm, and
|
||||
+ * either it or the TSS will validate that the digest length
|
||||
+ * matches the hash that it's told, despite it having no business
|
||||
+ * caring about such things.
|
||||
+ *
|
||||
+ * So, we can truncate the digest any pretend it's any smaller
|
||||
+ * digest that the TPM actually does support, as long as that
|
||||
+ * digest is larger than the size of the curve.
|
||||
+ */
|
||||
+ int curve_len = (EC_GROUP_order_bits(EC_KEY_get0_group(eckey)) + 7) / 8;
|
||||
+ /* If we couldn't work it out, don't truncate */
|
||||
+ if (!curve_len)
|
||||
+ curve_len = tbslen;
|
||||
+ if (tbslen == SHA256_DIGEST_LENGTH ||
|
||||
+ (curve_len <= SHA256_DIGEST_LENGTH && tbslen > SHA256_DIGEST_LENGTH)) {
|
||||
+ hash_alg = TPM2_ALG_SM3_256;
|
||||
+ inScheme.details.ecdsa.hashAlg = hash_alg;
|
||||
+ tbslen = SHA256_DIGEST_LENGTH;
|
||||
+ } else {
|
||||
+ ERR(tpm_pkey_sm2_sign, TPM2TSS_R_PADDING_UNKNOWN);
|
||||
+ goto error;
|
||||
+ }
|
||||
+ DBG("hash alg is %d\n", hash_alg);
|
||||
+ TPM2B_DIGEST digest = { .size = tbslen };
|
||||
+ if (digest.size > sizeof(digest.buffer)) {
|
||||
+ ERR(ecdsa_sign, TPM2TSS_R_DIGEST_TOO_LARGE);
|
||||
+ goto error;
|
||||
+ }
|
||||
+ memcpy(&digest.buffer[0], tbs, tbslen);
|
||||
+
|
||||
+ r = init_tpm_key(&esys_ctx, &keyHandle, tpm2Data);
|
||||
+ ERRchktss(tpm_pkey_sm2_sign, r, goto error);
|
||||
+
|
||||
+ r = Esys_Sign(esys_ctx, keyHandle,
|
||||
+ ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
|
||||
+ &digest, &inScheme, &validation, &sig_tpm);
|
||||
+ ERRchktss(tpm_pkey_sm2_sign, r, goto error);
|
||||
+
|
||||
+ s = ECDSA_SIG_new();
|
||||
+ if (s == NULL) {
|
||||
+ ERR(ecdsa_sign, ERR_R_MALLOC_FAILURE);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ bns = BN_bin2bn(&sig_tpm->signature.ecdsa.signatureS.buffer[0],
|
||||
+ sig_tpm->signature.ecdsa.signatureS.size, NULL);
|
||||
+ bnr = BN_bin2bn(&sig_tpm->signature.ecdsa.signatureR.buffer[0],
|
||||
+ sig_tpm->signature.ecdsa.signatureR.size, NULL);
|
||||
+ if (!bns || !bnr) {
|
||||
+ ERR(tpm_pkey_sm2_sign, ERR_R_MALLOC_FAILURE);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ ECDSA_SIG_set0(s, bnr, bns);
|
||||
+
|
||||
+ #ifndef NDEBUG
|
||||
+ unsigned char *sig_debug = sig;
|
||||
+ #endif
|
||||
+ sigleni = i2d_ECDSA_SIG(s, &sig);
|
||||
+ if (sigleni < 0) {
|
||||
+ ERR(tpm_pkey_sm2_sign, ERR_R_MALLOC_FAILURE);
|
||||
+ goto error;
|
||||
+ }
|
||||
+ *siglen = (unsigned int)sigleni;
|
||||
+ DBG("sig content (size=%ld):\n", *siglen);
|
||||
+ DBGBUF(sig_debug, *siglen);
|
||||
+ DBG("[%s][OUT] ctx:%p sig:%p siglen:%ld tbs:%p tbslen:%ld\n", __func__, ctx, sig, *siglen, tbs, tbslen);
|
||||
+
|
||||
+ goto out;
|
||||
+error:
|
||||
+ r = -1;
|
||||
+out:
|
||||
+ if (keyHandle != ESYS_TR_NONE) {
|
||||
+ if (tpm2Data->privatetype == KEY_TYPE_HANDLE) {
|
||||
+ Esys_TR_Close(esys_ctx, &keyHandle);
|
||||
+ } else {
|
||||
+ Esys_FlushContext(esys_ctx, keyHandle);
|
||||
+ }
|
||||
+ }
|
||||
+ if (r != TSS2_RC_SUCCESS && s != NULL) {
|
||||
+ if (bns)
|
||||
+ BN_free(bns);
|
||||
+ if (bnr)
|
||||
+ BN_free(bnr);
|
||||
+ }
|
||||
+ if (r != TSS2_RC_SUCCESS) {
|
||||
+ if (s)
|
||||
+ ECDSA_SIG_free(s);
|
||||
+ r = -1;
|
||||
+ }
|
||||
+
|
||||
+ esys_ctx_free(&esys_ctx);
|
||||
+ return (r == TSS2_RC_SUCCESS) ? 1 : r;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+tpm_pkey_sm2_verify(EVP_PKEY_CTX * ctx, const unsigned char * sig, size_t siglen, const unsigned char * tbs, size_t tbslen)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ DBG("[%s] ctx:%p sig:%p siglen:%ld tbs:%p tbslen:%ld\n", __func__, ctx, sig, siglen, tbs, tbslen);
|
||||
+ DBG("tbs content (size=%ld):\n", tbslen);
|
||||
+ DBGBUF(tbs, (int)tbslen);
|
||||
+ DBG("sig content (size=%ld):\n", siglen);
|
||||
+ DBGBUF(sig, siglen);
|
||||
+ if(sm2_pkey_orig_verify != NULL)
|
||||
+ ret = sm2_pkey_orig_verify(ctx, sig, siglen, tbs, tbslen);
|
||||
+ DBG("[%s] ret is %d\n", __func__, ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* called for digest & sign init, after message digest algorithm set */
|
||||
+static int
|
||||
+tpm_pkey_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
|
||||
+{
|
||||
+ DBG("[%s] ctx:%p mctx:%p \n", __func__, ctx, mctx);
|
||||
+ int ret = 0;
|
||||
+ if(sm2_pkey_orig_digest_custom != NULL)
|
||||
+ ret = sm2_pkey_orig_digest_custom(ctx, mctx);
|
||||
+ DBG("[%s] ret is %d\n", __func__, ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/** Retrieve app data
|
||||
*
|
||||
* Since the ECC api (opposed to the RSA api) does not provide a standardized
|
||||
@@ -96,6 +275,11 @@ static TPM2B_PUBLIC keyEcTemplate = {
|
||||
TPM2_DATA *
|
||||
tpm2tss_sm2_getappdata(EC_KEY *key)
|
||||
{
|
||||
+ if (ec_sm2_key_app_data == -1) {
|
||||
+ DBG("Module uninitialized\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
return EC_KEY_get_ex_data(key, ec_sm2_key_app_data);
|
||||
}
|
||||
|
||||
@@ -112,6 +296,11 @@ tpm2tss_sm2_getappdata(EC_KEY *key)
|
||||
int
|
||||
tpm2tss_sm2_setappdata(EC_KEY *key, TPM2_DATA *tpm2Data)
|
||||
{
|
||||
+ if (ec_sm2_key_app_data == -1) {
|
||||
+ DBG("Module uninitialized\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
return EC_KEY_set_ex_data(key, ec_sm2_key_app_data, tpm2Data);
|
||||
}
|
||||
|
||||
@@ -182,6 +371,23 @@ populate_sm2(EC_KEY *key)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static void
|
||||
+free_sm2_appdata(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
|
||||
+ long argl, void *argp)
|
||||
+{
|
||||
+ TPM2_DATA *tpm2Data = ptr;
|
||||
+
|
||||
+ (void)parent;
|
||||
+ (void)ad;
|
||||
+ (void)idx;
|
||||
+ (void)argl;
|
||||
+ (void)argp;
|
||||
+
|
||||
+ if (!ptr)
|
||||
+ return;
|
||||
+
|
||||
+ OPENSSL_free(tpm2Data);
|
||||
+}
|
||||
|
||||
/** Generate a tpm2tss sm2 key object.
|
||||
*
|
||||
@@ -287,3 +493,38 @@ tpm2tss_sm2_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password,
|
||||
return (r == TSS2_RC_SUCCESS);
|
||||
}
|
||||
|
||||
+int
|
||||
+init_sm2(ENGINE *e)
|
||||
+{
|
||||
+ (void)(e);
|
||||
+
|
||||
+ if (ec_sm2_key_app_data == -1)
|
||||
+ ec_sm2_key_app_data = EC_KEY_get_ex_new_index(0, NULL, NULL, NULL, free_sm2_appdata);
|
||||
+
|
||||
+ EVP_PKEY_METHOD *pkey_sm2_methods;
|
||||
+
|
||||
+ pkey_sm2_methods = EVP_PKEY_meth_new(EVP_PKEY_SM2, 0);
|
||||
+ if (pkey_sm2_methods == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ const EVP_PKEY_METHOD *pkey_orig_sm2_methods =
|
||||
+ EVP_PKEY_meth_find(EVP_PKEY_SM2);
|
||||
+ if (pkey_orig_sm2_methods == NULL)
|
||||
+ return 0;
|
||||
+ EVP_PKEY_meth_copy(pkey_sm2_methods, pkey_orig_sm2_methods);
|
||||
+ /*
|
||||
+ * save originals since we only override some of the pkey
|
||||
+ * functionality, rather than reimplementing all of it
|
||||
+ */
|
||||
+ EVP_PKEY_meth_get_sign(pkey_sm2_methods, NULL, &sm2_pkey_orig_sign);
|
||||
+ EVP_PKEY_meth_get_verify(pkey_sm2_methods, NULL, &sm2_pkey_orig_verify);
|
||||
+ EVP_PKEY_meth_get_digest_custom((EVP_PKEY_METHOD *)pkey_orig_sm2_methods, &sm2_pkey_orig_digest_custom);
|
||||
+
|
||||
+ EVP_PKEY_meth_set_sign(pkey_sm2_methods, NULL, tpm_pkey_sm2_sign);
|
||||
+ EVP_PKEY_meth_set_verify(pkey_sm2_methods, NULL, tpm_pkey_sm2_verify);
|
||||
+ EVP_PKEY_meth_set_digest_custom(pkey_sm2_methods, tpm_pkey_sm2_digest_custom);
|
||||
+ EVP_PKEY_meth_add0(pkey_sm2_methods);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
diff --git a/src/tpm2-tss-engine.c b/src/tpm2-tss-engine.c
|
||||
index 824f538..8a5fb52 100644
|
||||
--- a/src/tpm2-tss-engine.c
|
||||
+++ b/src/tpm2-tss-engine.c
|
||||
@@ -293,7 +293,12 @@ init_engine(ENGINE *e) {
|
||||
ERR(init_engine, TPM2TSS_R_SUBINIT_FAILED);
|
||||
return rc;
|
||||
}
|
||||
-
|
||||
+
|
||||
+ rc = init_sm2(e);
|
||||
+ if (rc != 1) {
|
||||
+ ERR(init_engine, TPM2TSS_R_SUBINIT_FAILED);
|
||||
+ return rc;
|
||||
+ }
|
||||
initialized = 1;
|
||||
return 1;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
Name: tpm2-tss-engine
|
||||
Version: 1.1.0
|
||||
Release: 1.u2
|
||||
Release: 1.u3
|
||||
Summary: OpenSSL Engine for TPM2 devices using the tpm2-tss software stack
|
||||
|
||||
License: BSD
|
||||
@ -9,6 +9,7 @@ Source0: https://github.com/tpm2-software/tpm2-tss-engine/releases/downlo
|
||||
|
||||
Patch10001: 0001-add-bootstrap-for-source-code-compilation.patch
|
||||
Patch10002: 0002-add-SM2-genkey-function.patch
|
||||
Patch10003: 0003-add-SM2-sign-function-for-openssl-engine.patch
|
||||
|
||||
BuildRequires: make
|
||||
BuildRequires: autoconf
|
||||
@ -85,13 +86,18 @@ uses the tpm2-tss software stack
|
||||
|
||||
|
||||
%changelog
|
||||
* Tue Aug 1 2023 wangyoukang<wangyoukang@xfusio.com> - 1.1.0-1.u2
|
||||
- Type:bugfix
|
||||
* Tue Aug 1 2023 wangyoukang<wangyoukang@xfusion.com> - 1.1.0-1.u3
|
||||
- Type:req
|
||||
- CVE:
|
||||
- DESC: add SM2 sign function for openssl engine
|
||||
|
||||
* Tue Aug 1 2023 wangyoukang<wangyoukang@xfusion.com> - 1.1.0-1.u2
|
||||
- Type:req
|
||||
- CVE:
|
||||
- DESC: add SM2 genkey function
|
||||
|
||||
* Tue Aug 1 2023 wangyoukang<wangyoukang@xfusio.com> - 1.1.0-1.u1
|
||||
- Type:bugfix
|
||||
* Tue Aug 1 2023 wangyoukang<wangyoukang@xfusion.com> - 1.1.0-1.u1
|
||||
- Type:req
|
||||
- CVE:
|
||||
- DESC: add bootstratp for source code compilation
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user