Skip to content

Commit 22c5c5e

Browse files
committed
add gm algorithm support.
Signed-off-by: chench246 <[email protected]>
1 parent 3d01024 commit 22c5c5e

File tree

7 files changed

+281
-13
lines changed

7 files changed

+281
-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-common.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,23 @@
3737
&& !defined(__STDC_NO_ATOMICS__)
3838
# include <stdatomic.h>
3939
# define TPM2_TSS_ENGINE_HAVE_C11_ATOMICS
40+
#endif
41+
42+
#if defined(TPM2_TSS_ENGINE_HAVE_C11_ATOMICS)
4043
typedef _Atomic int T2TE_ATOMIC_INT;
4144
#else
4245
typedef int T2TE_ATOMIC_INT;
4346
#endif
4447

48+
#if defined(TPM2_TSS_ENGINE_HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \
49+
&& (ATOMIC_INT_LOCK_FREE > 0)
50+
typedef _Atomic int CRYPTO_REF_COUNT;
51+
#elif defined(_MSC_VER) && _MSC_VER >= 1200
52+
typedef volatile int CRYPTO_REF_COUNT;
53+
#else
54+
typedef int CRYPTO_REF_COUNT;
55+
#endif
56+
4557
#include <tpm2-tss-engine.h>
4658
#include <tss2/tss2_mu.h>
4759
#include <tss2/tss2_esys.h>
@@ -183,6 +195,44 @@ typedef struct {
183195
size_t sig_size;
184196
} TPM2_SIG_DATA;
185197

198+
#define SM2_DEFAULT_USERID "1234567812345678"
199+
#define SM2_DEFAULT_USERID_LEN (sizeof(SM2_DEFAULT_USERID) - 1)
200+
201+
#define MAX_KEYLEN 57
202+
203+
typedef struct {
204+
unsigned char pubkey[MAX_KEYLEN];
205+
unsigned char *privkey;
206+
} ECX_KEY;
207+
208+
struct evp_pkey_st {
209+
int type;
210+
int save_type;
211+
CRYPTO_REF_COUNT references;
212+
const EVP_PKEY_ASN1_METHOD *ameth;
213+
ENGINE *engine;
214+
ENGINE *pmeth_engine; /* If not NULL public key ENGINE to use */
215+
union {
216+
void *ptr;
217+
# ifndef OPENSSL_NO_RSA
218+
struct rsa_st *rsa; /* RSA */
219+
# endif
220+
# ifndef OPENSSL_NO_DSA
221+
struct dsa_st *dsa; /* DSA */
222+
# endif
223+
# ifndef OPENSSL_NO_DH
224+
struct dh_st *dh; /* DH */
225+
# endif
226+
# ifndef OPENSSL_NO_EC
227+
EC_KEY *ec; /* ECC */
228+
ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */
229+
# endif
230+
} pkey;
231+
int save_parameters;
232+
STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
233+
CRYPTO_RWLOCK *lock;
234+
} /* EVP_PKEY */ ;
235+
186236
int
187237
digest_update(EVP_MD_CTX *ctx, const void *data, size_t count);
188238
int

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 & 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,13 @@ 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 (*pkey_sm2_sign_default) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
62+
const unsigned char *tbs, size_t tbslen) = NULL;
63+
static int (*sm2_sign_init_default)(EVP_PKEY_CTX*) = NULL;
64+
static int (*sm2_ctrl_default)(EVP_PKEY_CTX*, int, int, void*) = NULL;
65+
static int (*sm2_ctrl_str_default)(EVP_PKEY_CTX*, const char*, const char*) = NULL;
66+
5767
#endif /* HAVE_OPENSSL_DIGEST_SIGN */
5868

5969
static TPM2B_DATA allOutsideInfo = {
@@ -238,7 +248,7 @@ ecdsa_sign(ESYS_CONTEXT *esys_ctx, ESYS_TR key_handle,
238248
TPM2_ALG_ID hash_alg)
239249
{
240250
TPMT_SIG_SCHEME inScheme = {
241-
.scheme = TPM2_ALG_ECDSA,
251+
.scheme = (hash_alg == TPM2_ALG_SM3_256) ? TPM2_ALG_SM2 : TPM2_ALG_ECDSA,
242252
.details.ecdsa.hashAlg = hash_alg,
243253
};
244254
BIGNUM *bns = NULL, *bnr = NULL;
@@ -360,8 +370,11 @@ ecdsa_ec_key_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
360370
dgst_len = SHA_DIGEST_LENGTH;
361371
} else if (dgst_len == SHA256_DIGEST_LENGTH ||
362372
(curve_len <= SHA256_DIGEST_LENGTH && dgst_len > SHA256_DIGEST_LENGTH)) {
363-
hash_alg = TPM2_ALG_SHA256;
364-
dgst_len = SHA256_DIGEST_LENGTH;
373+
if (EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)) == NID_sm2)
374+
hash_alg = TPM2_ALG_SM3_256;
375+
else
376+
hash_alg = TPM2_ALG_SHA256;
377+
dgst_len = SHA256_DIGEST_LENGTH;
365378
} else if (dgst_len == SHA384_DIGEST_LENGTH ||
366379
(curve_len <= SHA384_DIGEST_LENGTH && dgst_len > SHA384_DIGEST_LENGTH)) {
367380
hash_alg = TPM2_ALG_SHA384;
@@ -516,6 +529,9 @@ populate_ecc(EC_KEY *key)
516529
case TPM2_ECC_NIST_P384:
517530
nid = EC_curve_nist2nid("P-384");
518531
break;
532+
case TPM2_ECC_SM2_P256:
533+
nid = NID_sm2;
534+
break;
519535
default:
520536
nid = -1;
521537
}
@@ -560,6 +576,55 @@ populate_ecc(EC_KEY *key)
560576
return 1;
561577
}
562578

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

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

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

8741058
return 1;

0 commit comments

Comments
 (0)