Skip to content

Commit 5bbecf9

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

File tree

6 files changed

+233
-13
lines changed

6 files changed

+233
-13
lines changed

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: 193 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,17 @@ 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+
5771
#endif /* HAVE_OPENSSL_DIGEST_SIGN */
5872

5973
static TPM2B_DATA allOutsideInfo = {
@@ -238,7 +252,7 @@ ecdsa_sign(ESYS_CONTEXT *esys_ctx, ESYS_TR key_handle,
238252
TPM2_ALG_ID hash_alg)
239253
{
240254
TPMT_SIG_SCHEME inScheme = {
241-
.scheme = TPM2_ALG_ECDSA,
255+
.scheme = (hash_alg == TPM2_ALG_SM3_256) ? TPM2_ALG_SM2 : TPM2_ALG_ECDSA,
242256
.details.ecdsa.hashAlg = hash_alg,
243257
};
244258
BIGNUM *bns = NULL, *bnr = NULL;
@@ -360,8 +374,11 @@ ecdsa_ec_key_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
360374
dgst_len = SHA_DIGEST_LENGTH;
361375
} else if (dgst_len == SHA256_DIGEST_LENGTH ||
362376
(curve_len <= SHA256_DIGEST_LENGTH && dgst_len > SHA256_DIGEST_LENGTH)) {
363-
hash_alg = TPM2_ALG_SHA256;
364-
dgst_len = SHA256_DIGEST_LENGTH;
377+
if (EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)) == NID_sm2)
378+
hash_alg = TPM2_ALG_SM3_256;
379+
else
380+
hash_alg = TPM2_ALG_SHA256;
381+
dgst_len = SHA256_DIGEST_LENGTH;
365382
} else if (dgst_len == SHA384_DIGEST_LENGTH ||
366383
(curve_len <= SHA384_DIGEST_LENGTH && dgst_len > SHA384_DIGEST_LENGTH)) {
367384
hash_alg = TPM2_ALG_SHA384;
@@ -516,6 +533,9 @@ populate_ecc(EC_KEY *key)
516533
case TPM2_ECC_NIST_P384:
517534
nid = EC_curve_nist2nid("P-384");
518535
break;
536+
case TPM2_ECC_SM2_P256:
537+
nid = NID_sm2;
538+
break;
519539
default:
520540
nid = -1;
521541
}
@@ -560,6 +580,55 @@ populate_ecc(EC_KEY *key)
560580
return 1;
561581
}
562582

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

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;
672+
if (tpm2Data->pub.publicArea.parameters.eccDetail.curveID == TPM2_ECC_SM2_P256) {
673+
if (!EVP_PKEY_assign(pkey, EVP_PKEY_SM2, (char *)(eckey))) {
674+
ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
675+
EC_KEY_free(eckey);
676+
goto error;
677+
}
678+
} else {
679+
if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) {
680+
ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
681+
EC_KEY_free(eckey);
682+
goto error;
683+
}
607684
}
608685

609686
if (!tpm2tss_ecc_setappdata(eckey, tpm2Data)) {
@@ -796,6 +873,88 @@ tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password,
796873
return (r == TSS2_RC_SUCCESS);
797874
}
798875

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

8741060
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:

src/tpm2tss-genkey.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ char *help =
5252
"Arguments:\n"
5353
" <filename> storage for the encrypted private key\n"
5454
"Options:\n"
55-
" -a, --alg public key algorithm (rsa, ecdsa) (default: rsa)\n"
55+
" -a, --alg public key algorithm (rsa, ecdsa, sm2) (default: rsa)\n"
5656
" -c, --curve curve for ecc (default: nist_p256)\n"
5757
" -e, --exponent exponent for rsa (default: 65537)\n"
5858
" -h, --help print help\n"
@@ -148,6 +148,9 @@ parse_opts(int argc, char **argv)
148148
} else if (strcasecmp(optarg, "ecdsa") == 0) {
149149
opt.alg = TPM2_ALG_ECDSA;
150150
break;
151+
} else if (strcasecmp(optarg, "sm2") == 0) {
152+
opt.alg = TPM2_ALG_SM2;
153+
break;
151154
} else {
152155
ERR("Unknown algorithm.\n");
153156
exit(1);
@@ -159,6 +162,9 @@ parse_opts(int argc, char **argv)
159162
} else if (strcasecmp(optarg, "nist_p384") == 0) {
160163
opt.curve = TPM2_ECC_NIST_P384;
161164
break;
165+
} else if (strcasecmp(optarg, "sm2_p256") == 0) {
166+
opt.curve = TPM2_ECC_SM2_P256;
167+
break;
162168
} else {
163169
ERR("Unknown curve.\n");
164170
exit(1);
@@ -390,6 +396,10 @@ main(int argc, char **argv)
390396
VERB("Generating the ecdsa key\n");
391397
tpm2Data = genkey_ecdsa();
392398
break;
399+
case TPM2_ALG_SM2:
400+
VERB("Generating the sm2 key\n");
401+
tpm2Data = genkey_ecdsa();
402+
break;
393403
default:
394404
break;
395405
}

0 commit comments

Comments
 (0)