Skip to content

Commit d8a876c

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

13 files changed

Lines changed: 545 additions & 10 deletions

Makefile.am

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,13 @@ TESTS_SHELL += test/ecdh.sh
135135
endif
136136
if HAVE_OPENSSL_DIGEST_SIGN
137137
TESTS_SHELL += test/ecdsa-restricted.sh \
138-
test/rsasign_restricted.sh
138+
test/rsasign_restricted.sh \
139+
test/sm2_csr.sh \
140+
test/sm2sign.sh \
141+
test/sm2sign_emptyauth.sh \
142+
test/sm2sign_handle_flush.sh \
143+
test/sm2sign_importtpmparent.sh \
144+
test/sm2sign_parent.sh
139145
endif
140146
EXTRA_DIST += $(TESTS_SHELL) test/neg-handle.pem
141147
TEST_EXTENSIONS = .sh

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: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,12 @@ 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 = {
218+
.algorithm = TPM2_ALG_AES,
219+
.keyBits = { .sym = 128 },
220+
.mode = { .sym = TPM2_ALG_CFB }
221+
};
222+
TPM2_ALG_ID hash_alg = TPM2_ALG_SHA256;
217223

218224
tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data));
219225
if (tpm2Data == NULL) {
@@ -247,15 +253,16 @@ tpm2tss_tpm2data_readtpm(uint32_t handle, TPM2_DATA **tpm2Datap)
247253
goto error;
248254
}
249255

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

260267
/* Esys_StartAuthSession() and session handling use OpenSSL for random
261268
bytes and thus might end up inside this engine again. This becomes
@@ -271,7 +278,7 @@ tpm2tss_tpm2data_readtpm(uint32_t handle, TPM2_DATA **tpm2Datap)
271278
very cheap command. */
272279
r = Esys_StartAuthSession(esys_ctx, ESYS_TR_NONE, keyHandle,
273280
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
274-
NULL, TPM2_SE_HMAC, &sym, TPM2_ALG_SHA256,
281+
NULL, TPM2_SE_HMAC, &sym, hash_alg,
275282
&session);
276283
/* Though this response code is sub-optimal, it's the only way to
277284
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: 191 additions & 3 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,7 +374,8 @@ 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;
377+
hash_alg = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)) == NID_sm2 ?
378+
TPM2_ALG_SM3_256 : TPM2_ALG_SHA256;
364379
dgst_len = SHA256_DIGEST_LENGTH;
365380
} else if (dgst_len == SHA384_DIGEST_LENGTH ||
366381
(curve_len <= SHA384_DIGEST_LENGTH && dgst_len > SHA384_DIGEST_LENGTH)) {
@@ -516,6 +531,9 @@ populate_ecc(EC_KEY *key)
516531
case TPM2_ECC_NIST_P384:
517532
nid = EC_curve_nist2nid("P-384");
518533
break;
534+
case TPM2_ECC_SM2_P256:
535+
nid = NID_sm2;
536+
break;
519537
default:
520538
nid = -1;
521539
}
@@ -560,6 +578,55 @@ populate_ecc(EC_KEY *key)
560578
return 1;
561579
}
562580

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

603-
if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) {
670+
if (tpm2Data->pub.publicArea.parameters.eccDetail.curveID == TPM2_ECC_SM2_P256) {
671+
if (!EVP_PKEY_assign(pkey, EVP_PKEY_SM2, (char *)(eckey))) {
672+
ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
673+
EC_KEY_free(eckey);
674+
goto error;
675+
}
676+
} else if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) {
604677
ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE);
605678
EC_KEY_free(eckey);
606679
goto error;
@@ -796,6 +869,94 @@ tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password,
796869
return (r == TSS2_RC_SUCCESS);
797870
}
798871

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

8741062
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)