Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions include/tpm2-tss-engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
17 changes: 12 additions & 5 deletions src/tpm2-tss-engine-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Comment thread
williamcroberts marked this conversation as resolved.

tpm2Data = OPENSSL_malloc(sizeof(*tpm2Data));
if (tpm2Data == NULL) {
Expand Down Expand Up @@ -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
Expand All @@ -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. */
Expand Down
3 changes: 3 additions & 0 deletions src/tpm2-tss-engine-digest-sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
194 changes: 191 additions & 3 deletions src/tpm2-tss-engine-ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
#include <openssl/engine.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/evp.h>

#include <tss2/tss2_mu.h>
#include <tss2/tss2_esys.h>
Expand All @@ -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)

Comment thread
chench246 marked this conversation as resolved.
#endif /* HAVE_OPENSSL_DIGEST_SIGN */

static TPM2B_DATA allOutsideInfo = {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Comment thread
williamcroberts marked this conversation as resolved.

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;
Comment thread
williamcroberts marked this conversation as resolved.

*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.
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions src/tpm2-tss-engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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:
Expand Down
12 changes: 11 additions & 1 deletion src/tpm2tss-genkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ char *help =
"Arguments:\n"
" <filename> 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"
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
Loading
Loading