Skip to content

Commit f65a434

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

File tree

7 files changed

+283
-13
lines changed

7 files changed

+283
-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: 47 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,41 @@ typedef struct {
183195
size_t sig_size;
184196
} TPM2_SIG_DATA;
185197

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

5972
static TPM2B_DATA allOutsideInfo = {
@@ -238,7 +251,7 @@ ecdsa_sign(ESYS_CONTEXT *esys_ctx, ESYS_TR key_handle,
238251
TPM2_ALG_ID hash_alg)
239252
{
240253
TPMT_SIG_SCHEME inScheme = {
241-
.scheme = TPM2_ALG_ECDSA,
254+
.scheme = (hash_alg == TPM2_ALG_SM3_256) ? TPM2_ALG_SM2 : TPM2_ALG_ECDSA,
242255
.details.ecdsa.hashAlg = hash_alg,
243256
};
244257
BIGNUM *bns = NULL, *bnr = NULL;
@@ -360,8 +373,11 @@ ecdsa_ec_key_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
360373
dgst_len = SHA_DIGEST_LENGTH;
361374
} else if (dgst_len == SHA256_DIGEST_LENGTH ||
362375
(curve_len <= SHA256_DIGEST_LENGTH && dgst_len > SHA256_DIGEST_LENGTH)) {
363-
hash_alg = TPM2_ALG_SHA256;
364-
dgst_len = SHA256_DIGEST_LENGTH;
376+
if (EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)) == NID_sm2)
377+
hash_alg = TPM2_ALG_SM3_256;
378+
else
379+
hash_alg = TPM2_ALG_SHA256;
380+
dgst_len = SHA256_DIGEST_LENGTH;
365381
} else if (dgst_len == SHA384_DIGEST_LENGTH ||
366382
(curve_len <= SHA384_DIGEST_LENGTH && dgst_len > SHA384_DIGEST_LENGTH)) {
367383
hash_alg = TPM2_ALG_SHA384;
@@ -516,6 +532,9 @@ populate_ecc(EC_KEY *key)
516532
case TPM2_ECC_NIST_P384:
517533
nid = EC_curve_nist2nid("P-384");
518534
break;
535+
case TPM2_ECC_SM2_P256:
536+
nid = NID_sm2;
537+
break;
519538
default:
520539
nid = -1;
521540
}
@@ -560,6 +579,57 @@ populate_ecc(EC_KEY *key)
560579
return 1;
561580
}
562581

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

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

609687
if (!tpm2tss_ecc_setappdata(eckey, tpm2Data)) {
@@ -796,6 +874,95 @@ tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password,
796874
return (r == TSS2_RC_SUCCESS);
797875
}
798876

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

8741063
return 1;

0 commit comments

Comments
 (0)