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
5558static int (* ecdsa_pkey_orig_copy )(EVP_PKEY_CTX * dst , const EVP_PKEY_CTX * src );
5659static 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+ /* The default user id as specified in GM/T 0009-2012.
68+ * For details, please refer to GM/T 0003.1-2012 -- 0003.5-2012 SM2 and
69+ * described at http://www.gmbz.org.cn/upload/2024-11-18/1731899635265027729.pdf
70+ */
71+ #define SM2_DEFAULT_USERID "1234567812345678"
72+ #define SM2_DEFAULT_USERID_LEN (sizeof(SM2_DEFAULT_USERID) - 1)
73+
74+ const EC_KEY * ec_sm2 = NULL ;
75+ const EVP_PKEY * pkey_sm2 = NULL ;
76+
5777#endif /* HAVE_OPENSSL_DIGEST_SIGN */
5878
5979static 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,20 @@ 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+ pkey_sm2 = pkey ;
685+ ec_sm2 = eckey ;
686+ } else {
687+ if (!EVP_PKEY_assign_EC_KEY (pkey , eckey )) {
688+ ERR (tpm2tss_ecc_makekey , TPM2TSS_R_GENERAL_FAILURE );
689+ EC_KEY_free (eckey );
690+ goto error ;
691+ }
607692 }
608693
609694 if (!tpm2tss_ecc_setappdata (eckey , tpm2Data )) {
@@ -796,6 +881,99 @@ tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password,
796881 return (r == TSS2_RC_SUCCESS );
797882}
798883
884+ /** Customize the pkey_sm2_sign interface
885+ *
886+ * Customize the pkey_sm2_sign interface. When there is a tpm key extension value, call the ecdsa_ec_key_sign interface to sign.
887+ * @retval 1 on success
888+ * @retval 0 on failure
889+ */
890+ static int pkey_sm2_sign (EVP_PKEY_CTX * ctx , unsigned char * sig , size_t * siglen ,
891+ const unsigned char * tbs , size_t tbslen )
892+ {
893+ EVP_PKEY * pkey = EVP_PKEY_CTX_get0_pkey (ctx );
894+ if (pkey != pkey_sm2 )
895+ return pkey_sm2_sign_default ? pkey_sm2_sign_default (ctx , sig , siglen , tbs , tbslen ) : 0 ;
896+
897+ EC_KEY * ec = ec_sm2 ;
898+ if (!ec )
899+ return 0 ;
900+
901+ if (tpm2tss_ecc_getappdata (ec ) == NULL ) {
902+ /* If this is not a TPM2 key, fall through to software functions. */
903+ return pkey_sm2_sign_default ? pkey_sm2_sign_default (ctx , sig , siglen , tbs , tbslen ) : 0 ;
904+ }
905+ else {
906+ /* call tpm sig function */
907+ const int sig_sz = ECDSA_size (ec );
908+ if (sig_sz <= 0 ) {
909+ return 0 ;
910+ }
911+ if (sig == NULL ) {
912+ * siglen = (size_t )sig_sz ;
913+ return 1 ;
914+ }
915+ if (* siglen < (size_t )sig_sz )
916+ return 0 ;
917+ ECDSA_SIG * sig_res = ecdsa_ec_key_sign (tbs , tbslen , NULL , NULL , ec );
918+ int siglen_temp = i2d_ECDSA_SIG (sig_res , & sig );
919+ ECDSA_SIG_free (sig_res );
920+ if (siglen_temp < 0 )
921+ return 0 ;
922+ * siglen = siglen_temp ;
923+ }
924+
925+ return 1 ;
926+ }
927+
928+ static int sm2_ctrl_wrap (EVP_PKEY_CTX * ctx , int type , int p1 , void * p2 )
929+ {
930+ switch (type ) {
931+ case EVP_PKEY_CTRL_DIGESTINIT :
932+ /* Ignore explicit digest selection.*/
933+ return 1 ;
934+ default :
935+ return sm2_ctrl_default ? sm2_ctrl_default (ctx , type , p1 , p2 ) : 1 ;
936+ }
937+ }
938+
939+ static int sm2_ctrl_str_wrap (EVP_PKEY_CTX * ctx , const char * type , const char * value )
940+ {
941+ if (type ) {
942+ if (!strcmp (type , "digest" ) || !strcmp (type , "md" )) {
943+ /* Swallow "digest=sm3" coming from -sm3 to avoid unsupported ctrl; always return success. */
944+ return 1 ;
945+ }
946+ if (!strcmp (type , "distid" ) || !strcmp (type , "sm2_id" )) {
947+ /* Let default ctrl_str handle ID parsing/storage. */
948+ return sm2_ctrl_default ? sm2_ctrl_default (ctx , EVP_PKEY_CTRL_SET1_ID , (int )strlen (value ), (void * )value ) : 1 ;
949+ }
950+ }
951+ return sm2_ctrl_str_default ? sm2_ctrl_str_default (ctx , type , value ) : 1 ;
952+ }
953+
954+ static int pkey_sm2_digest_custom_wrap (EVP_PKEY_CTX * ctx , EVP_MD_CTX * mctx )
955+ {
956+ int ret ;
957+ int id_len = 0 ;
958+ unsigned char id [] = SM2_DEFAULT_USERID ;
959+
960+ ret = sm2_ctrl_default ? sm2_ctrl_default (ctx , EVP_PKEY_CTRL_GET1_ID_LEN , 0 , (void * )(& id_len )) : 0 ;
961+ if (ret != 1 ) {
962+ DBG ("Get id len failed.\n" );
963+ return 0 ;
964+ }
965+
966+ if (id_len == 0 ) {
967+ ret = sm2_ctrl_default ? sm2_ctrl_default (ctx , EVP_PKEY_CTRL_SET1_ID , (int )SM2_DEFAULT_USERID_LEN , (void * )id ) : 0 ;
968+ if (ret != 1 ) {
969+ DBG ("Set default id failed.\n" );
970+ return 0 ;
971+ }
972+ }
973+
974+ return sm2_digest_custom_default ? sm2_digest_custom_default (ctx , mctx ) : 1 ;
975+ }
976+
799977/** Initialize the tpm2tss engine's ecc submodule
800978 *
801979 * Initialize the tpm2tss engine's submodule by setting function pointer.
@@ -869,6 +1047,28 @@ init_ecc(ENGINE *e)
8691047 EVP_PKEY_meth_set_signctx (pkey_ecc_methods , NULL , ecdsa_signctx );
8701048 EVP_PKEY_meth_set_digest_custom (pkey_ecc_methods , ecdsa_digest_custom );
8711049 EVP_PKEY_meth_add0 (pkey_ecc_methods );
1050+
1051+ /* add engine for sm2*/
1052+ const EVP_PKEY_METHOD * pkey_orig_sm2_methods = EVP_PKEY_meth_find (EVP_PKEY_SM2 );
1053+ if (pkey_orig_sm2_methods == NULL ) {
1054+ return 0 ;
1055+ }
1056+ EVP_PKEY_METHOD * pkey_sm2_methods = EVP_PKEY_meth_new (EVP_PKEY_SM2 , 0 );
1057+ if (pkey_sm2_methods == NULL )
1058+ return 0 ;
1059+ EVP_PKEY_meth_copy (pkey_sm2_methods , pkey_orig_sm2_methods );
1060+
1061+ EVP_PKEY_meth_get_digest_custom ((EVP_PKEY_METHOD * )(uintptr_t )(pkey_orig_sm2_methods ), & sm2_digest_custom_default );
1062+ EVP_PKEY_meth_get_sign (pkey_orig_sm2_methods , & sm2_sign_init_default , & pkey_sm2_sign_default );
1063+ EVP_PKEY_meth_get_ctrl (pkey_orig_sm2_methods , & sm2_ctrl_default , & sm2_ctrl_str_default );
1064+
1065+ EVP_PKEY_meth_set_digest_custom (pkey_sm2_methods , pkey_sm2_digest_custom_wrap );
1066+ EVP_PKEY_meth_set_sign (pkey_sm2_methods , sm2_sign_init_default , pkey_sm2_sign );
1067+ EVP_PKEY_meth_set_ctrl (pkey_sm2_methods , sm2_ctrl_wrap , sm2_ctrl_str_wrap );
1068+ EVP_PKEY_meth_add0 (pkey_sm2_methods );
1069+
1070+ add_sm2_sm3_sig_alg_mapping ();
1071+
8721072#endif /* HAVE_OPENSSL_DIGEST_SIGN */
8731073
8741074 return 1 ;
0 commit comments