Skip to content

Commit d79fe82

Browse files
committed
add gm algorithm support.
Signed-off-by: chench246 <chench246@hotmail.com>
1 parent 3d01024 commit d79fe82

6 files changed

Lines changed: 243 additions & 13 deletions

File tree

include/tpm2-tss-engine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ int
8787
tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password,
8888
TPM2_HANDLE parentHandle);
8989

90+
int add_sm2_asn1_meths(void);
91+
9092
TPM2_DATA *
9193
#if OPENSSL_VERSION_NUMBER < 0x10100000
9294
tpm2tss_ecc_getappdata(EC_KEY *key);

src/tpm2-tss-engine-common.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ tpm2tss_tpm2data_readtpm(uint32_t handle, TPM2_DATA **tpm2Datap)
214214
ESYS_TR keyHandle = ESYS_TR_NONE;
215215
ESYS_CONTEXT *esys_ctx = NULL;
216216
TPM2B_PUBLIC *outPublic;
217+
TPMT_SYM_DEF sym = {.algorithm = TPM2_ALG_AES,
218+
.keyBits = {.aes = 128},
219+
.mode = {.aes = TPM2_ALG_CFB}
220+
};
221+
TPM2_ALG_ID hash_alg = TPM2_ALG_SHA256;
217222

218223
tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data));
219224
if (tpm2Data == NULL) {
@@ -247,15 +252,19 @@ tpm2tss_tpm2data_readtpm(uint32_t handle, TPM2_DATA **tpm2Datap)
247252
goto error;
248253
}
249254

255+
if (outPublic->publicArea.parameters.eccDetail.curveID == TPM2_ECC_SM2_P256) {
256+
sym.algorithm = TPM2_ALG_SM4;
257+
sym.keyBits.sm4 = 128;
258+
sym.mode.sm4 = TPM2_ALG_CFB;
259+
260+
hash_alg = TPM2_ALG_SM3_256;
261+
}
262+
250263
/* If the persistent key has the NODA flag set, we check whether it does
251264
have an empty authValue. If NODA is not set, then we don't check because
252265
that would increment the DA lockout counter */
253266
if ((outPublic->publicArea.objectAttributes & TPMA_OBJECT_NODA) != 0) {
254267
ESYS_TR session;
255-
TPMT_SYM_DEF sym = {.algorithm = TPM2_ALG_AES,
256-
.keyBits = {.aes = 128},
257-
.mode = {.aes = TPM2_ALG_CFB}
258-
};
259268

260269
/* Esys_StartAuthSession() and session handling use OpenSSL for random
261270
bytes and thus might end up inside this engine again. This becomes
@@ -271,7 +280,7 @@ tpm2tss_tpm2data_readtpm(uint32_t handle, TPM2_DATA **tpm2Datap)
271280
very cheap command. */
272281
r = Esys_StartAuthSession(esys_ctx, ESYS_TR_NONE, keyHandle,
273282
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
274-
NULL, TPM2_SE_HMAC, &sym, TPM2_ALG_SHA256,
283+
NULL, TPM2_SE_HMAC, &sym, hash_alg,
275284
&session);
276285
/* Though this response code is sub-optimal, it's the only way to
277286
detect the bug in ESYS. */

src/tpm2-tss-engine-digest-sign.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ digest_init(EVP_MD_CTX *ctx, TPM2_SIG_DATA *data)
7979
case NID_sha512:
8080
data->hash_alg = TPM2_ALG_SHA512;
8181
break;
82+
case NID_sm3:
83+
data->hash_alg = TPM2_ALG_SM3_256;
84+
break;
8285
default:
8386
ERR(digest_init, TPM2TSS_R_UNKNOWN_ALG);
8487
return 0;

src/tpm2-tss-engine-ecc.c

Lines changed: 203 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
#include <openssl/engine.h>
3535
#include <openssl/ec.h>
3636
#include <openssl/ecdsa.h>
37+
#include <openssl/objects.h>
38+
#include <openssl/x509.h>
39+
#include <openssl/evp.h>
3740

3841
#include <tss2/tss2_mu.h>
3942
#include <tss2/tss2_esys.h>
@@ -54,6 +57,23 @@ EC_KEY_METHOD *ecc_methods = NULL;
5457
#ifdef HAVE_OPENSSL_DIGEST_SIGN
5558
static int (*ecdsa_pkey_orig_copy)(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src);
5659
static void (*ecdsa_pkey_orig_cleanup)(EVP_PKEY_CTX *ctx);
60+
static int (*sm2_digest_custom_default) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) = NULL;
61+
static int (*sm2_ctrl_default)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) = NULL;
62+
static int (*sm2_ctrl_str_default)(EVP_PKEY_CTX *ctx, const char *type, const char *value) = NULL;
63+
64+
/* The default user id as specified in GM/T 0009-2012.
65+
* For details, please refer to GM/T 0003.1-2012 -- 0003.5-2012 SM2 and
66+
* described at http://www.gmbz.org.cn/upload/2024-11-18/1731899635265027729.pdf
67+
*/
68+
#define SM2_DEFAULT_USERID "1234567812345678"
69+
#define SM2_DEFAULT_USERID_LEN (sizeof(SM2_DEFAULT_USERID) - 1)
70+
71+
/* ec_sm2 caches the last seen TPM2 SM2 public key.
72+
* The cache is needed since pkey_sm2_sign needs to get ahold of the actual
73+
* key which is inaccessible inside the EVP_PKEY is an opaque struct.
74+
*/
75+
EC_KEY *ec_sm2 = NULL;
76+
5777
#endif /* HAVE_OPENSSL_DIGEST_SIGN */
5878

5979
static TPM2B_DATA allOutsideInfo = {
@@ -238,7 +258,7 @@ ecdsa_sign(ESYS_CONTEXT *esys_ctx, ESYS_TR key_handle,
238258
TPM2_ALG_ID hash_alg)
239259
{
240260
TPMT_SIG_SCHEME inScheme = {
241-
.scheme = TPM2_ALG_ECDSA,
261+
.scheme = (hash_alg == TPM2_ALG_SM3_256) ? TPM2_ALG_SM2 : TPM2_ALG_ECDSA,
242262
.details.ecdsa.hashAlg = hash_alg,
243263
};
244264
BIGNUM *bns = NULL, *bnr = NULL;
@@ -360,8 +380,11 @@ ecdsa_ec_key_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
360380
dgst_len = SHA_DIGEST_LENGTH;
361381
} else if (dgst_len == SHA256_DIGEST_LENGTH ||
362382
(curve_len <= SHA256_DIGEST_LENGTH && dgst_len > SHA256_DIGEST_LENGTH)) {
363-
hash_alg = TPM2_ALG_SHA256;
364-
dgst_len = SHA256_DIGEST_LENGTH;
383+
if (EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)) == NID_sm2)
384+
hash_alg = TPM2_ALG_SM3_256;
385+
else
386+
hash_alg = TPM2_ALG_SHA256;
387+
dgst_len = SHA256_DIGEST_LENGTH;
365388
} else if (dgst_len == SHA384_DIGEST_LENGTH ||
366389
(curve_len <= SHA384_DIGEST_LENGTH && dgst_len > SHA384_DIGEST_LENGTH)) {
367390
hash_alg = TPM2_ALG_SHA384;
@@ -516,6 +539,9 @@ populate_ecc(EC_KEY *key)
516539
case TPM2_ECC_NIST_P384:
517540
nid = EC_curve_nist2nid("P-384");
518541
break;
542+
case TPM2_ECC_SM2_P256:
543+
nid = NID_sm2;
544+
break;
519545
default:
520546
nid = -1;
521547
}
@@ -560,6 +586,55 @@ populate_ecc(EC_KEY *key)
560586
return 1;
561587
}
562588

589+
/* add sm2 asn1 method copy from ecc asn1 */
590+
int
591+
add_sm2_asn1_meths(void)
592+
{
593+
const EVP_PKEY_ASN1_METHOD *ec_ameth = NULL;
594+
EVP_PKEY_ASN1_METHOD *sm2_ameth = NULL;
595+
596+
ec_ameth = EVP_PKEY_asn1_find(NULL, EVP_PKEY_EC);
597+
if (!ec_ameth) {
598+
DBG("find ec_asn1_method failed.\n");
599+
return 0;
600+
}
601+
602+
sm2_ameth = EVP_PKEY_asn1_new(EVP_PKEY_SM2, 0, "ec-wrap", "EC with SM2 alias");
603+
if (!sm2_ameth) {
604+
DBG("set new sm2_asn1_method failed.\n");
605+
return 0;
606+
}
607+
608+
EVP_PKEY_asn1_copy(sm2_ameth, ec_ameth);
609+
610+
if (!EVP_PKEY_asn1_add0(sm2_ameth)) {
611+
612+
EVP_PKEY_asn1_free(sm2_ameth);
613+
return 0;
614+
}
615+
616+
return 1;
617+
}
618+
619+
static void
620+
add_sm2_sm3_sig_alg_mapping(void)
621+
{
622+
int nid_sm3 = OBJ_txt2nid("SM3"); /* 1143 */
623+
int nid_sm2 = EVP_PKEY_SM2; /* 1172 */
624+
int nid_sm2sig = OBJ_txt2nid("sm2sign-with-sm3");
625+
626+
/* If it is NID_undef, then register the OID. */
627+
if (nid_sm2sig == NID_undef) {
628+
/* offical OID:1.2.156.10197.1.501 */
629+
nid_sm2sig = OBJ_create("1.2.156.10197.1.501",
630+
"SM2Sign-with-SM3",
631+
"sm2sign-with-sm3");
632+
}
633+
if (nid_sm3 != NID_undef && nid_sm2 != NID_undef && nid_sm2sig != NID_undef) {
634+
OBJ_add_sigid(nid_sm2sig, nid_sm3, nid_sm2);
635+
}
636+
}
637+
563638
/** Helper to load an ECC key from a tpm2Data
564639
*
565640
* This function creates a key object given a TPM2_DATA object. The resulting
@@ -600,10 +675,19 @@ tpm2tss_ecc_makekey(TPM2_DATA *tpm2Data)
600675
goto error;
601676
}
602677

603-
if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) {
604-
ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
605-
EC_KEY_free(eckey);
606-
goto error;
678+
if (tpm2Data->pub.publicArea.parameters.eccDetail.curveID == TPM2_ECC_SM2_P256) {
679+
if (!EVP_PKEY_assign(pkey, EVP_PKEY_SM2, (char *)(eckey))) {
680+
ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
681+
EC_KEY_free(eckey);
682+
goto error;
683+
}
684+
ec_sm2 = eckey;
685+
} else {
686+
if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) {
687+
ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
688+
EC_KEY_free(eckey);
689+
goto error;
690+
}
607691
}
608692

609693
if (!tpm2tss_ecc_setappdata(eckey, tpm2Data)) {
@@ -796,6 +880,91 @@ tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password,
796880
return (r == TSS2_RC_SUCCESS);
797881
}
798882

883+
/** Customize the pkey_sm2_sign interface
884+
*
885+
* Customize the pkey_sm2_sign interface. When there is a tpm key extension value, call the ecdsa_ec_key_sign interface to sign.
886+
* @retval 1 on success
887+
* @retval 0 on failure
888+
*/
889+
static int pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
890+
const unsigned char *tbs, size_t tbslen)
891+
{
892+
(void)ctx;
893+
894+
EC_KEY *ec = ec_sm2;
895+
if (!ec)
896+
return 0;
897+
898+
/* call tpm sig function */
899+
const int sig_sz = ECDSA_size(ec);
900+
if (sig_sz <= 0) {
901+
return 0;
902+
}
903+
if (sig == NULL) {
904+
*siglen = (size_t)sig_sz;
905+
return 1;
906+
}
907+
if (*siglen < (size_t)sig_sz)
908+
return 0;
909+
ECDSA_SIG *sig_res = ecdsa_ec_key_sign(tbs, tbslen, NULL, NULL, ec);
910+
911+
int siglen_temp = i2d_ECDSA_SIG(sig_res, &sig);
912+
ECDSA_SIG_free(sig_res);
913+
if (siglen_temp < 0)
914+
return 0;
915+
*siglen = siglen_temp;
916+
917+
return 1;
918+
}
919+
920+
static int sm2_ctrl_wrap(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
921+
{
922+
switch (type) {
923+
case EVP_PKEY_CTRL_DIGESTINIT:
924+
/* Ignore explicit digest selection.*/
925+
return 1;
926+
default:
927+
return sm2_ctrl_default ? sm2_ctrl_default(ctx, type, p1, p2) : 1;
928+
}
929+
}
930+
931+
static int sm2_ctrl_str_wrap(EVP_PKEY_CTX *ctx, const char *type, const char *value)
932+
{
933+
if (type) {
934+
if (!strcmp(type, "digest") || !strcmp(type, "md")) {
935+
/* Swallow "digest=sm3" coming from -sm3 to avoid unsupported ctrl; always return success. */
936+
return 1;
937+
}
938+
if (!strcmp(type, "distid") || !strcmp(type, "sm2_id")) {
939+
/* Let default ctrl_str handle ID parsing/storage. */
940+
return sm2_ctrl_default ? sm2_ctrl_default(ctx, EVP_PKEY_CTRL_SET1_ID, (int)strlen(value), (void*)value) : 1;
941+
}
942+
}
943+
return sm2_ctrl_str_default ? sm2_ctrl_str_default(ctx, type, value) : 1;
944+
}
945+
946+
static int pkey_sm2_digest_custom_wrap(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
947+
{
948+
int ret;
949+
int id_len = 0;
950+
951+
ret = sm2_ctrl_default ? sm2_ctrl_default(ctx, EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(&id_len)) : 0;
952+
if (ret != 1) {
953+
DBG("Get id len failed.\n");
954+
return 0;
955+
}
956+
957+
if (id_len == 0) {
958+
ret = sm2_ctrl_default ? sm2_ctrl_default(ctx, EVP_PKEY_CTRL_SET1_ID, (int)SM2_DEFAULT_USERID_LEN, (void *)SM2_DEFAULT_USERID) : 0;
959+
if (ret != 1) {
960+
DBG("Set default id failed.\n");
961+
return 0;
962+
}
963+
}
964+
965+
return sm2_digest_custom_default ? sm2_digest_custom_default(ctx, mctx) : 1;
966+
}
967+
799968
/** Initialize the tpm2tss engine's ecc submodule
800969
*
801970
* Initialize the tpm2tss engine's submodule by setting function pointer.
@@ -869,6 +1038,33 @@ init_ecc(ENGINE *e)
8691038
EVP_PKEY_meth_set_signctx(pkey_ecc_methods, NULL, ecdsa_signctx);
8701039
EVP_PKEY_meth_set_digest_custom(pkey_ecc_methods, ecdsa_digest_custom);
8711040
EVP_PKEY_meth_add0(pkey_ecc_methods);
1041+
1042+
/* add engine for sm2*/
1043+
const EVP_PKEY_METHOD *pkey_orig_sm2_methods = EVP_PKEY_meth_find(EVP_PKEY_SM2);
1044+
if (pkey_orig_sm2_methods == NULL) {
1045+
return 0;
1046+
}
1047+
EVP_PKEY_METHOD *pkey_sm2_methods = EVP_PKEY_meth_new(EVP_PKEY_SM2, 0);
1048+
if (pkey_sm2_methods == NULL)
1049+
return 0;
1050+
1051+
int (*pkey_sm2_sign_default) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
1052+
const unsigned char *tbs, size_t tbslen) = NULL;
1053+
int (*sm2_sign_init_default)(EVP_PKEY_CTX *ctx) = NULL;
1054+
1055+
EVP_PKEY_meth_copy(pkey_sm2_methods, pkey_orig_sm2_methods);
1056+
1057+
EVP_PKEY_meth_get_digest_custom((EVP_PKEY_METHOD *)(uintptr_t)(pkey_orig_sm2_methods), &sm2_digest_custom_default);
1058+
EVP_PKEY_meth_get_sign(pkey_orig_sm2_methods, &sm2_sign_init_default, &pkey_sm2_sign_default);
1059+
EVP_PKEY_meth_get_ctrl(pkey_orig_sm2_methods, &sm2_ctrl_default, &sm2_ctrl_str_default);
1060+
1061+
EVP_PKEY_meth_set_digest_custom(pkey_sm2_methods, pkey_sm2_digest_custom_wrap);
1062+
EVP_PKEY_meth_set_sign(pkey_sm2_methods, sm2_sign_init_default, pkey_sm2_sign);
1063+
EVP_PKEY_meth_set_ctrl(pkey_sm2_methods, sm2_ctrl_wrap, sm2_ctrl_str_wrap);
1064+
EVP_PKEY_meth_add0(pkey_sm2_methods);
1065+
1066+
add_sm2_sm3_sig_alg_mapping();
1067+
8721068
#endif /* HAVE_OPENSSL_DIGEST_SIGN */
8731069

8741070
return 1;

src/tpm2-tss-engine.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,11 @@ bind(ENGINE *e, const char *id)
347347
goto end;
348348
}
349349

350+
if (!ENGINE_set_load_pubkey_function(e, loadkey)) {
351+
DBG("ENGINE_set_load_pubkey_function failed\n");
352+
goto end;
353+
}
354+
350355
if (!ENGINE_set_destroy_function(e, destroy_engine)) {
351356
DBG("ENGINE_set_destroy_function failed\n");
352357
goto end;
@@ -362,6 +367,11 @@ bind(ENGINE *e, const char *id)
362367
goto end;
363368
}
364369

370+
if (!add_sm2_asn1_meths()) {
371+
DBG("created sm2_asn1_meths failed\n");
372+
goto end;
373+
}
374+
365375
ERR_load_TPM2TSS_strings();
366376
return 1;
367377
end:

0 commit comments

Comments
 (0)