From 9645ecaed118990141158d244d795a071dbf0125 Mon Sep 17 00:00:00 2001 From: chench246 Date: Tue, 16 Dec 2025 21:11:00 +0800 Subject: [PATCH] add gm algorithm support. Signed-off-by: chench246 --- Makefile.am | 8 +- include/tpm2-tss-engine.h | 2 + src/tpm2-tss-engine-common.c | 17 ++- src/tpm2-tss-engine-digest-sign.c | 3 + src/tpm2-tss-engine-ecc.c | 194 +++++++++++++++++++++++++++++- src/tpm2-tss-engine.c | 10 ++ src/tpm2tss-genkey.c | 12 +- test/sm2_csr.sh | 39 ++++++ test/sm2sign.sh | 38 ++++++ test/sm2sign_emptyauth.sh | 38 ++++++ test/sm2sign_handle_flush.sh | 74 ++++++++++++ test/sm2sign_importtpmparent.sh | 63 ++++++++++ test/sm2sign_parent.sh | 57 +++++++++ 13 files changed, 545 insertions(+), 10 deletions(-) create mode 100755 test/sm2_csr.sh create mode 100755 test/sm2sign.sh create mode 100755 test/sm2sign_emptyauth.sh create mode 100755 test/sm2sign_handle_flush.sh create mode 100755 test/sm2sign_importtpmparent.sh create mode 100755 test/sm2sign_parent.sh diff --git a/Makefile.am b/Makefile.am index bda32b4..2b71f46 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,7 +135,13 @@ TESTS_SHELL += test/ecdh.sh endif if HAVE_OPENSSL_DIGEST_SIGN TESTS_SHELL += test/ecdsa-restricted.sh \ - test/rsasign_restricted.sh + test/rsasign_restricted.sh \ + test/sm2_csr.sh \ + test/sm2sign.sh \ + test/sm2sign_emptyauth.sh \ + test/sm2sign_handle_flush.sh \ + test/sm2sign_importtpmparent.sh \ + test/sm2sign_parent.sh endif EXTRA_DIST += $(TESTS_SHELL) test/neg-handle.pem TEST_EXTENSIONS = .sh diff --git a/include/tpm2-tss-engine.h b/include/tpm2-tss-engine.h index 1d29530..2c99e33 100644 --- a/include/tpm2-tss-engine.h +++ b/include/tpm2-tss-engine.h @@ -87,6 +87,8 @@ int tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password, TPM2_HANDLE parentHandle); +int add_sm2_asn1_meths(void); + TPM2_DATA * #if OPENSSL_VERSION_NUMBER < 0x10100000 tpm2tss_ecc_getappdata(EC_KEY *key); diff --git a/src/tpm2-tss-engine-common.c b/src/tpm2-tss-engine-common.c index 9dc100d..fe75d91 100755 --- a/src/tpm2-tss-engine-common.c +++ b/src/tpm2-tss-engine-common.c @@ -214,6 +214,12 @@ tpm2tss_tpm2data_readtpm(uint32_t handle, TPM2_DATA **tpm2Datap) ESYS_TR keyHandle = ESYS_TR_NONE; ESYS_CONTEXT *esys_ctx = NULL; TPM2B_PUBLIC *outPublic; + TPMT_SYM_DEF sym = { + .algorithm = TPM2_ALG_AES, + .keyBits = { .sym = 128 }, + .mode = { .sym = TPM2_ALG_CFB } + }; + TPM2_ALG_ID hash_alg = TPM2_ALG_SHA256; tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data)); if (tpm2Data == NULL) { @@ -247,15 +253,16 @@ tpm2tss_tpm2data_readtpm(uint32_t handle, TPM2_DATA **tpm2Datap) goto error; } + if (outPublic->publicArea.parameters.eccDetail.curveID == TPM2_ECC_SM2_P256) { + sym.algorithm = TPM2_ALG_SM4; + hash_alg = TPM2_ALG_SM3_256; + } + /* If the persistent key has the NODA flag set, we check whether it does have an empty authValue. If NODA is not set, then we don't check because that would increment the DA lockout counter */ if ((outPublic->publicArea.objectAttributes & TPMA_OBJECT_NODA) != 0) { ESYS_TR session; - TPMT_SYM_DEF sym = {.algorithm = TPM2_ALG_AES, - .keyBits = {.aes = 128}, - .mode = {.aes = TPM2_ALG_CFB} - }; /* Esys_StartAuthSession() and session handling use OpenSSL for random 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) very cheap command. */ r = Esys_StartAuthSession(esys_ctx, ESYS_TR_NONE, keyHandle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, - NULL, TPM2_SE_HMAC, &sym, TPM2_ALG_SHA256, + NULL, TPM2_SE_HMAC, &sym, hash_alg, &session); /* Though this response code is sub-optimal, it's the only way to detect the bug in ESYS. */ diff --git a/src/tpm2-tss-engine-digest-sign.c b/src/tpm2-tss-engine-digest-sign.c index dc0603b..b7d879f 100644 --- a/src/tpm2-tss-engine-digest-sign.c +++ b/src/tpm2-tss-engine-digest-sign.c @@ -79,6 +79,9 @@ digest_init(EVP_MD_CTX *ctx, TPM2_SIG_DATA *data) case NID_sha512: data->hash_alg = TPM2_ALG_SHA512; break; + case NID_sm3: + data->hash_alg = TPM2_ALG_SM3_256; + break; default: ERR(digest_init, TPM2TSS_R_UNKNOWN_ALG); return 0; diff --git a/src/tpm2-tss-engine-ecc.c b/src/tpm2-tss-engine-ecc.c index 377693b..ac588c5 100644 --- a/src/tpm2-tss-engine-ecc.c +++ b/src/tpm2-tss-engine-ecc.c @@ -34,6 +34,9 @@ #include #include #include +#include +#include +#include #include #include @@ -54,6 +57,17 @@ EC_KEY_METHOD *ecc_methods = NULL; #ifdef HAVE_OPENSSL_DIGEST_SIGN static int (*ecdsa_pkey_orig_copy)(EVP_PKEY_CTX *dst, OSSL_CONST EVP_PKEY_CTX *src); static void (*ecdsa_pkey_orig_cleanup)(EVP_PKEY_CTX *ctx); +static int (*sm2_digest_custom_default) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) = NULL; +static int (*sm2_ctrl_default)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) = NULL; +static int (*sm2_ctrl_str_default)(EVP_PKEY_CTX *ctx, const char *type, const char *value) = NULL; + +/* The default user id as specified in GM/T 0009-2012. + * For details, please refer to GM/T 0003.1-2012 -- 0003.5-2012 SM2 and + * described at http://www.gmbz.org.cn/upload/2024-11-18/1731899635265027729.pdf + */ +#define SM2_DEFAULT_USERID "1234567812345678" +#define SM2_DEFAULT_USERID_LEN (sizeof(SM2_DEFAULT_USERID) - 1) + #endif /* HAVE_OPENSSL_DIGEST_SIGN */ static TPM2B_DATA allOutsideInfo = { @@ -238,7 +252,7 @@ ecdsa_sign(ESYS_CONTEXT *esys_ctx, ESYS_TR key_handle, TPM2_ALG_ID hash_alg) { TPMT_SIG_SCHEME inScheme = { - .scheme = TPM2_ALG_ECDSA, + .scheme = (hash_alg == TPM2_ALG_SM3_256) ? TPM2_ALG_SM2 : TPM2_ALG_ECDSA, .details.ecdsa.hashAlg = hash_alg, }; BIGNUM *bns = NULL, *bnr = NULL; @@ -360,7 +374,8 @@ ecdsa_ec_key_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, dgst_len = SHA_DIGEST_LENGTH; } else if (dgst_len == SHA256_DIGEST_LENGTH || (curve_len <= SHA256_DIGEST_LENGTH && dgst_len > SHA256_DIGEST_LENGTH)) { - hash_alg = TPM2_ALG_SHA256; + hash_alg = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)) == NID_sm2 ? + TPM2_ALG_SM3_256 : TPM2_ALG_SHA256; dgst_len = SHA256_DIGEST_LENGTH; } else if (dgst_len == SHA384_DIGEST_LENGTH || (curve_len <= SHA384_DIGEST_LENGTH && dgst_len > SHA384_DIGEST_LENGTH)) { @@ -516,6 +531,9 @@ populate_ecc(EC_KEY *key) case TPM2_ECC_NIST_P384: nid = EC_curve_nist2nid("P-384"); break; + case TPM2_ECC_SM2_P256: + nid = NID_sm2; + break; default: nid = -1; } @@ -560,6 +578,55 @@ populate_ecc(EC_KEY *key) return 1; } +/* add sm2 asn1 method copy from ecc asn1 */ +int +add_sm2_asn1_meths(void) +{ + const EVP_PKEY_ASN1_METHOD *ec_ameth = NULL; + EVP_PKEY_ASN1_METHOD *sm2_ameth = NULL; + + ec_ameth = EVP_PKEY_asn1_find(NULL, EVP_PKEY_EC); + if (!ec_ameth) { + DBG("find ec_asn1_method failed.\n"); + return 0; + } + + sm2_ameth = EVP_PKEY_asn1_new(EVP_PKEY_SM2, 0, "ec-wrap", "EC with SM2 alias"); + if (!sm2_ameth) { + DBG("set new sm2_asn1_method failed.\n"); + return 0; + } + + EVP_PKEY_asn1_copy(sm2_ameth, ec_ameth); + + if (!EVP_PKEY_asn1_add0(sm2_ameth)) { + + EVP_PKEY_asn1_free(sm2_ameth); + return 0; + } + + return 1; +} + +static void +add_sm2_sm3_sig_alg_mapping(void) +{ + int nid_sm3 = OBJ_txt2nid("SM3"); /* 1143 */ + int nid_sm2 = EVP_PKEY_SM2; /* 1172 */ + int nid_sm2sig = OBJ_txt2nid("sm2sign-with-sm3"); + + /* If it is NID_undef, then register the OID. */ + if (nid_sm2sig == NID_undef) { + /* offical OID:1.2.156.10197.1.501 */ + nid_sm2sig = OBJ_create("1.2.156.10197.1.501", + "SM2Sign-with-SM3", + "sm2sign-with-sm3"); + } + if (nid_sm3 != NID_undef && nid_sm2 != NID_undef && nid_sm2sig != NID_undef) { + OBJ_add_sigid(nid_sm2sig, nid_sm3, nid_sm2); + } +} + /** Helper to load an ECC key from a tpm2Data * * This function creates a key object given a TPM2_DATA object. The resulting @@ -600,7 +667,13 @@ tpm2tss_ecc_makekey(TPM2_DATA *tpm2Data) goto error; } - if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) { + if (tpm2Data->pub.publicArea.parameters.eccDetail.curveID == TPM2_ECC_SM2_P256) { + if (!EVP_PKEY_assign(pkey, EVP_PKEY_SM2, (char *)(eckey))) { + ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE); + EC_KEY_free(eckey); + goto error; + } + } else if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) { ERR(tpm2tss_ecc_makekey, TPM2TSS_R_GENERAL_FAILURE); EC_KEY_free(eckey); goto error; @@ -796,6 +869,94 @@ tpm2tss_ecc_genkey(EC_KEY *key, TPMI_ECC_CURVE curve, const char *password, return (r == TSS2_RC_SUCCESS); } +/** Customize the pkey_sm2_sign interface + * + * Customize the pkey_sm2_sign interface. When there is a tpm key extension value, call the ecdsa_ec_key_sign interface to sign. + * @retval 1 on success + * @retval 0 on failure + */ +static int +pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); + EC_KEY *ec = (EC_KEY *)EVP_PKEY_get0(pkey); + + /* call tpm sig function */ + const int sig_sz = ECDSA_size(ec); + if (sig_sz <= 0) + return 0; + + if (sig == NULL) { + *siglen = (size_t)sig_sz; + return 1; + } + + if (*siglen < (size_t)sig_sz) + return 0; + + ECDSA_SIG *sig_res = ecdsa_ec_key_sign(tbs, tbslen, NULL, NULL, ec); + + int siglen_temp = i2d_ECDSA_SIG(sig_res, &sig); + ECDSA_SIG_free(sig_res); + if (siglen_temp < 0) + return 0; + + *siglen = siglen_temp; + + return 1; +} + +static int +sm2_ctrl_wrap(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + switch (type) { + case EVP_PKEY_CTRL_DIGESTINIT: + /* Ignore explicit digest selection.*/ + return 1; + default: + return sm2_ctrl_default ? sm2_ctrl_default(ctx, type, p1, p2) : 1; + } +} + +static int +sm2_ctrl_str_wrap(EVP_PKEY_CTX *ctx, const char *type, const char *value) +{ + if (type) { + /* Swallow "digest=sm3" coming from -sm3 to avoid unsupported ctrl; always return success. */ + if (!strcmp(type, "digest") || !strcmp(type, "md")) + return 1; + + /* Let default ctrl_str handle ID parsing/storage. */ + if (!strcmp(type, "distid") || !strcmp(type, "sm2_id")) + return sm2_ctrl_default ? sm2_ctrl_default(ctx, EVP_PKEY_CTRL_SET1_ID, (int)strlen(value), (void*)value) : 1; + } + return sm2_ctrl_str_default ? sm2_ctrl_str_default(ctx, type, value) : 1; +} + +static int +pkey_sm2_digest_custom_wrap(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) +{ + int ret; + int id_len = 0; + + ret = sm2_ctrl_default ? sm2_ctrl_default(ctx, EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(&id_len)) : 0; + if (ret != 1) { + DBG("Get id len failed.\n"); + return 0; + } + + if (id_len == 0) { + ret = sm2_ctrl_default ? sm2_ctrl_default(ctx, EVP_PKEY_CTRL_SET1_ID, (int)SM2_DEFAULT_USERID_LEN, (void *)SM2_DEFAULT_USERID) : 0; + if (ret != 1) { + DBG("Set default id failed.\n"); + return 0; + } + } + + return sm2_digest_custom_default ? sm2_digest_custom_default(ctx, mctx) : 1; +} + /** Initialize the tpm2tss engine's ecc submodule * * Initialize the tpm2tss engine's submodule by setting function pointer. @@ -869,6 +1030,33 @@ init_ecc(ENGINE *e) EVP_PKEY_meth_set_signctx(pkey_ecc_methods, NULL, ecdsa_signctx); EVP_PKEY_meth_set_digest_custom(pkey_ecc_methods, ecdsa_digest_custom); EVP_PKEY_meth_add0(pkey_ecc_methods); + + /* add engine for sm2*/ + const EVP_PKEY_METHOD *pkey_orig_sm2_methods = EVP_PKEY_meth_find(EVP_PKEY_SM2); + if (pkey_orig_sm2_methods == NULL) { + return 0; + } + EVP_PKEY_METHOD *pkey_sm2_methods = EVP_PKEY_meth_new(EVP_PKEY_SM2, 0); + if (pkey_sm2_methods == NULL) + return 0; + + int (*pkey_sm2_sign_default) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) = NULL; + int (*sm2_sign_init_default)(EVP_PKEY_CTX *ctx) = NULL; + + EVP_PKEY_meth_copy(pkey_sm2_methods, pkey_orig_sm2_methods); + + EVP_PKEY_meth_get_digest_custom((EVP_PKEY_METHOD *)(uintptr_t)(pkey_orig_sm2_methods), &sm2_digest_custom_default); + EVP_PKEY_meth_get_sign(pkey_orig_sm2_methods, &sm2_sign_init_default, &pkey_sm2_sign_default); + EVP_PKEY_meth_get_ctrl(pkey_orig_sm2_methods, &sm2_ctrl_default, &sm2_ctrl_str_default); + + EVP_PKEY_meth_set_digest_custom(pkey_sm2_methods, pkey_sm2_digest_custom_wrap); + EVP_PKEY_meth_set_sign(pkey_sm2_methods, sm2_sign_init_default, pkey_sm2_sign); + EVP_PKEY_meth_set_ctrl(pkey_sm2_methods, sm2_ctrl_wrap, sm2_ctrl_str_wrap); + EVP_PKEY_meth_add0(pkey_sm2_methods); + + add_sm2_sm3_sig_alg_mapping(); + #endif /* HAVE_OPENSSL_DIGEST_SIGN */ return 1; diff --git a/src/tpm2-tss-engine.c b/src/tpm2-tss-engine.c index 824f538..03888aa 100644 --- a/src/tpm2-tss-engine.c +++ b/src/tpm2-tss-engine.c @@ -347,6 +347,11 @@ bind(ENGINE *e, const char *id) goto end; } + if (!ENGINE_set_load_pubkey_function(e, loadkey)) { + DBG("ENGINE_set_load_pubkey_function failed\n"); + goto end; + } + if (!ENGINE_set_destroy_function(e, destroy_engine)) { DBG("ENGINE_set_destroy_function failed\n"); goto end; @@ -362,6 +367,11 @@ bind(ENGINE *e, const char *id) goto end; } + if (!add_sm2_asn1_meths()) { + DBG("created sm2_asn1_meths failed\n"); + goto end; + } + ERR_load_TPM2TSS_strings(); return 1; end: diff --git a/src/tpm2tss-genkey.c b/src/tpm2tss-genkey.c index a731897..350fdd9 100644 --- a/src/tpm2tss-genkey.c +++ b/src/tpm2tss-genkey.c @@ -52,7 +52,7 @@ char *help = "Arguments:\n" " storage for the encrypted private key\n" "Options:\n" - " -a, --alg public key algorithm (rsa, ecdsa) (default: rsa)\n" + " -a, --alg public key algorithm (rsa, ecdsa, sm2) (default: rsa)\n" " -c, --curve curve for ecc (default: nist_p256)\n" " -e, --exponent exponent for rsa (default: 65537)\n" " -h, --help print help\n" @@ -148,6 +148,9 @@ parse_opts(int argc, char **argv) } else if (strcasecmp(optarg, "ecdsa") == 0) { opt.alg = TPM2_ALG_ECDSA; break; + } else if (strcasecmp(optarg, "sm2") == 0) { + opt.alg = TPM2_ALG_SM2; + break; } else { ERR("Unknown algorithm.\n"); exit(1); @@ -159,6 +162,9 @@ parse_opts(int argc, char **argv) } else if (strcasecmp(optarg, "nist_p384") == 0) { opt.curve = TPM2_ECC_NIST_P384; break; + } else if (strcasecmp(optarg, "sm2_p256") == 0) { + opt.curve = TPM2_ECC_SM2_P256; + break; } else { ERR("Unknown curve.\n"); exit(1); @@ -390,6 +396,10 @@ main(int argc, char **argv) VERB("Generating the ecdsa key\n"); tpm2Data = genkey_ecdsa(); break; + case TPM2_ALG_SM2: + VERB("Generating the sm2 key\n"); + tpm2Data = genkey_ecdsa(); + break; default: break; } diff --git a/test/sm2_csr.sh b/test/sm2_csr.sh new file mode 100755 index 0000000..75853dc --- /dev/null +++ b/test/sm2_csr.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +set -eufx + +# ---------- capability checks (skip gracefully) ---------- +# 1) OpenSSL must have SM2 + SM3 +if ! openssl list -digest-algorithms 2>/dev/null | grep -qi '\bsm3\b'; then + echo "SKIP: OpenSSL has no SM3 digest algorithms" + exit 77 +fi + +if ! (openssl list -public-key-algorithms 2>/dev/null | grep -qi 'sm2' || \ + openssl list -signature-algorithms 2>/dev/null | grep -qi 'sm2'); then + echo "SKIP: OpenSSL has no SM2 algorithms" + exit 77 +fi + +# 2) TPM must advertise SM2 curve + SM3 hash (names may vary by tpm2-tools version/vendor) +if ! tpm2_getcap ecc-curves 2>/dev/null | grep -qi 'sm2'; then + echo "SKIP: TPM does not support SM2 curve" + exit 77 +fi +if ! tpm2_getcap algorithms 2>/dev/null | grep -qi 'sm3'; then + echo "SKIP: TPM does not support SM3 algorithms" + exit 77 +fi + + +# tpm2tss-genkey supports "-a sm2" and "-c sm2_p256" +tpm2tss-genkey -a sm2 -c sm2_p256 sm2key + +openssl req -new -engine tpm2tss -keyform engine -key sm2key \ + -sm3 -subj "/C=CN/O=tpm2tss-engine/CN=sm2-test" -out test.csr + +R="$(openssl req -in test.csr -noout -verify -engine tpm2tss -key sm2key -keyform engine 2>&1 || true)" +if ! echo "$R" | grep -qi "verify OK" >/dev/null; then + echo "$R" + exit 1 +fi diff --git a/test/sm2sign.sh b/test/sm2sign.sh new file mode 100755 index 0000000..acf580b --- /dev/null +++ b/test/sm2sign.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +set -eufx + +# ---------- capability checks (skip gracefully) ---------- +# 1) OpenSSL must have SM2 + SM3 +if ! openssl list -digest-algorithms 2>/dev/null | grep -qi '\bsm3\b'; then + echo "SKIP: OpenSSL has no SM3 digest algorithms" + exit 77 +fi + +if ! (openssl list -public-key-algorithms 2>/dev/null | grep -qi 'sm2' || \ + openssl list -signature-algorithms 2>/dev/null | grep -qi 'sm2'); then + echo "SKIP: OpenSSL has no SM2 algorithms" + exit 77 +fi + +# 2) TPM must advertise SM2 curve + SM3 hash (names may vary by tpm2-tools version/vendor) +if ! tpm2_getcap ecc-curves 2>/dev/null | grep -qi 'sm2'; then + echo "SKIP: TPM does not support SM2 curve" + exit 77 +fi +if ! tpm2_getcap algorithms 2>/dev/null | grep -qi 'sm3'; then + echo "SKIP: TPM does not support SM3 algorithms" + exit 77 +fi + +echo -n "abcde12345abcde12345abcde12345ab">mydata + +tpm2tss-genkey -a sm2 -c sm2_p256 -p abc sm2key + +echo "abc" | openssl pkeyutl -keyform engine -engine tpm2tss -inkey sm2key -sign -in mydata -out mysig -passin stdin + +R="$(echo "abc" | openssl pkeyutl -keyform engine -engine tpm2tss -inkey sm2key -verify -in mydata -sigfile mysig -passin stdin || true)" +if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then + echo $R + exit 1 +fi diff --git a/test/sm2sign_emptyauth.sh b/test/sm2sign_emptyauth.sh new file mode 100755 index 0000000..4171a76 --- /dev/null +++ b/test/sm2sign_emptyauth.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +set -eufx + +# ---------- capability checks (skip gracefully) ---------- +# 1) OpenSSL must have SM2 + SM3 +if ! openssl list -digest-algorithms 2>/dev/null | grep -qi '\bsm3\b'; then + echo "SKIP: OpenSSL has no SM3 digest algorithms" + exit 77 +fi + +if ! (openssl list -public-key-algorithms 2>/dev/null | grep -qi 'sm2' || \ + openssl list -signature-algorithms 2>/dev/null | grep -qi 'sm2'); then + echo "SKIP: OpenSSL has no SM2 algorithms" + exit 77 +fi + +# 2) TPM must advertise SM2 curve + SM3 hash (names may vary by tpm2-tools version/vendor) +if ! tpm2_getcap ecc-curves 2>/dev/null | grep -qi 'sm2'; then + echo "SKIP: TPM does not support SM2 curve" + exit 77 +fi +if ! tpm2_getcap algorithms 2>/dev/null | grep -qi 'sm3'; then + echo "SKIP: TPM does not support SM3 algorithms" + exit 77 +fi + +echo -n "abcde12345abcde12345abcde12345ab">mydata + +tpm2tss-genkey -a sm2 -c sm2_p256 sm2key + +openssl pkeyutl -keyform engine -engine tpm2tss -inkey sm2key -sign -in mydata -out mysig + +R="$(openssl pkeyutl -keyform engine -engine tpm2tss -inkey sm2key -verify -in mydata -sigfile mysig || true)" +if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then + echo $R + exit 1 +fi diff --git a/test/sm2sign_handle_flush.sh b/test/sm2sign_handle_flush.sh new file mode 100755 index 0000000..510dc93 --- /dev/null +++ b/test/sm2sign_handle_flush.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +set -eufx + +# ---------- capability checks (skip gracefully) ---------- +# 1) OpenSSL must have SM2 + SM3 +if ! openssl list -digest-algorithms 2>/dev/null | grep -qi '\bsm3\b'; then + echo "SKIP: OpenSSL has no SM3 digest algorithms" + exit 77 +fi + +if ! (openssl list -public-key-algorithms 2>/dev/null | grep -qi 'sm2' || \ + openssl list -signature-algorithms 2>/dev/null | grep -qi 'sm2'); then + echo "SKIP: OpenSSL has no SM2 algorithms" + exit 77 +fi + +# 2) TPM must advertise SM2 curve + SM3 hash (names may vary by tpm2-tools version/vendor) +if ! tpm2_getcap ecc-curves 2>/dev/null | grep -qi 'sm2'; then + echo "SKIP: TPM does not support SM2 curve" + exit 77 +fi +if ! tpm2_getcap algorithms 2>/dev/null | grep -qi 'sm3'; then + echo "SKIP: TPM does not support SM3 algorithms" + exit 77 +fi + +echo -n "abcde12345abcde12345abcde12345ab">mydata.txt + +# Create a Primary key pair +echo "Generating primary key" +PARENT_CTX=primary_owner_key.ctx + +tpm2_createprimary --hierarchy=o --hash-algorithm=sm3_256 --key-algorithm=ecc_sm2:null:sm4128cfb \ + --key-context=${PARENT_CTX} +tpm2_flushcontext --transient-object + +# Create an SM2 key pair +echo "Generating SM2 key pair" +TPM_SM2_PUBKEY=sm2key.pub +TPM_SM2_KEY=sm2key +tpm2_create --key-auth=abc \ + --parent-context=${PARENT_CTX} \ + --hash-algorithm=sm3_256 --key-algorithm=ecc_sm2:sm2-sm3_256:null \ + --public=${TPM_SM2_PUBKEY} --private=${TPM_SM2_KEY} \ + --attributes=sign\|fixedtpm\|fixedparent\|sensitivedataorigin\|userwithauth +tpm2_flushcontext --transient-object + +# Load Key to persistent handle +SM2_CTX=sm2key.ctx +tpm2_load --parent-context=${PARENT_CTX} \ + --public=${TPM_SM2_PUBKEY} --private=${TPM_SM2_KEY} \ + --key-context=${SM2_CTX} +tpm2_flushcontext --transient-object + +HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${SM2_CTX} | cut -d ' ' -f 2 | head -n 1) +tpm2_flushcontext --transient-object + +# Signing Data +R="$(echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${HANDLE} -sign -in mydata.txt -out mysig -passin stdin 2>&1 || true)" +if echo $R | grep "ErrorCode (0x000001c4)" > /dev/null; then + echo $R + exit 1 +fi + +R="$(echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${HANDLE} -verify -in mydata.txt -sigfile mysig -passin stdin 2>&1 || true)" +if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then + echo $R + tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE} + exit 1 +fi + +# Release persistent HANDLE +tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE} diff --git a/test/sm2sign_importtpmparent.sh b/test/sm2sign_importtpmparent.sh new file mode 100755 index 0000000..050b2a0 --- /dev/null +++ b/test/sm2sign_importtpmparent.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +set -eufx + +# ---------- capability checks (skip gracefully) ---------- +# 1) OpenSSL must have SM2 + SM3 +if ! openssl list -digest-algorithms 2>/dev/null | grep -qi '\bsm3\b'; then + echo "SKIP: OpenSSL has no SM3 digest algorithms" + exit 77 +fi + +if ! (openssl list -public-key-algorithms 2>/dev/null | grep -qi 'sm2' || \ + openssl list -signature-algorithms 2>/dev/null | grep -qi 'sm2'); then + echo "SKIP: OpenSSL has no SM2 algorithms" + exit 77 +fi + +# 2) TPM must advertise SM2 curve + SM3 hash (names may vary by tpm2-tools version/vendor) +if ! tpm2_getcap ecc-curves 2>/dev/null | grep -qi 'sm2'; then + echo "SKIP: TPM does not support SM2 curve" + exit 77 +fi +if ! tpm2_getcap algorithms 2>/dev/null | grep -qi 'sm3'; then + echo "SKIP: TPM does not support SM3 algorithms" + exit 77 +fi + +DIR=$(mktemp -d) +TPM_SM2_PUBKEY=${DIR}/sm2key.pub +TPM_SM2_KEY=${DIR}/sm2key +PARENT_CTX=${DIR}/primary_owner_key.ctx + +echo -n "abcde12345abcde12345abcde12345ab">${DIR}/mydata + +# Create primary key as persistent handle +tpm2_createprimary --hierarchy=o --hash-algorithm=sm3_256 --key-algorithm=ecc_sm2:null:sm4128cfb \ + --key-context=${PARENT_CTX} +tpm2_flushcontext --transient-object + +HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${PARENT_CTX} | cut -d ' ' -f 2 | head -n 1) +tpm2_flushcontext --transient-object + +# Create an SM2 key pair +echo "Generating SM2 key pair" +tpm2_create --key-auth=abc --parent-context=${PARENT_CTX} \ + --hash-algorithm=sm3_256 --key-algorithm=ecc_sm2:sm2-sm3_256:null \ + --public=${TPM_SM2_PUBKEY} --private=${TPM_SM2_KEY} \ + --attributes=sign\|fixedtpm\|fixedparent\|sensitivedataorigin\|userwithauth\|noda +tpm2_flushcontext --transient-object + +tpm2tss-genkey --public ${TPM_SM2_PUBKEY} --private ${TPM_SM2_KEY} --password abc --parent ${HANDLE} ${DIR}/mykey + +echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${DIR}/mykey -sign -in ${DIR}/mydata -out ${DIR}/mysig -passin stdin + +R="$(echo "abc" | openssl pkeyutl -engine tpm2tss -keyform engine -inkey ${DIR}/mykey -verify -in ${DIR}/mydata -sigfile ${DIR}/mysig -passin stdin 2>&1 || true)" +if ! echo $R | grep "Signature Verified Successfully" >/dev/null; then + echo $R + tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE} + exit 1 +fi + +# Release persistent HANDLE +tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE} diff --git a/test/sm2sign_parent.sh b/test/sm2sign_parent.sh new file mode 100755 index 0000000..0b7175f --- /dev/null +++ b/test/sm2sign_parent.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +set -eufx + +# ---------- capability checks (skip gracefully) ---------- +# 1) OpenSSL must have SM2 + SM3 +if ! openssl list -digest-algorithms 2>/dev/null | grep -qi '\bsm3\b'; then + echo "SKIP: OpenSSL has no SM3 digest algorithms" + exit 77 +fi + +if ! (openssl list -public-key-algorithms 2>/dev/null | grep -qi 'sm2' || \ + openssl list -signature-algorithms 2>/dev/null | grep -qi 'sm2'); then + echo "SKIP: OpenSSL has no SM2 algorithms" + exit 77 +fi + +# 2) TPM must advertise SM2 curve + SM3 hash (names may vary by tpm2-tools version/vendor) +if ! tpm2_getcap ecc-curves 2>/dev/null | grep -qi 'sm2'; then + echo "SKIP: TPM does not support SM2 curve" + exit 77 +fi +if ! tpm2_getcap algorithms 2>/dev/null | grep -qi 'sm3'; then + echo "SKIP: TPM does not support SM3 algorithms" + exit 77 +fi + +# Generate 2k + a bit of data +dd if=/dev/zero of=mydata.txt count=4 bs=512 status=none +echo -n "abcde12345abcde12345abcde12345ab">mydata.txt + +# Create a Primary key pair +echo "Generating primary key" +PARENT_CTX=primary_owner_key.ctx + +tpm2_createprimary --hierarchy=o --hash-algorithm=sm3_256 --key-algorithm=ecc_sm2:null:sm4128cfb \ + --key-context=${PARENT_CTX} +tpm2_flushcontext --transient-object + +# Load primary key to persistent handle +HANDLE=$(tpm2_evictcontrol --hierarchy=o --object-context=${PARENT_CTX} | cut -d ' ' -f 2 | head -n 1) +tpm2_flushcontext --transient-object + +tpm2tss-genkey -a sm2 -c sm2_p256 -P ${HANDLE} mykey + +# Digest & sign Data +openssl dgst -engine tpm2tss -keyform engine -sm3 -sign mykey -out mysig mydata.txt + +R="$(openssl dgst -engine tpm2tss -keyform engine -sm3 -verify mykey -signature mysig mydata.txt || true)" +if ! echo $R | grep "Verified OK" >/dev/null; then + echo $R + tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE} + exit 1 +fi + +# Release persistent HANDLE +tpm2_evictcontrol --hierarchy=o --object-context=${HANDLE}