From ba48ea6e3df83ce3e66efd94ee2efecc38e2e94a Mon Sep 17 00:00:00 2001 From: "Shencb@123" <1944340417@qq.com> Date: Tue, 3 Sep 2024 12:40:12 +0800 Subject: [PATCH 1/2] 11 --- ...dd-support-for-udev-to-create-tcm-de.patch | 22 + Hygon-add-ecc-encrypt-decrypt-support.patch | 1354 +++++++++++++++++ add-bootstrap-file-from-upstream.patch | 113 ++ backport-esys-add-SM4-algorithm-support.patch | 688 +++++++++ tpm2-tss.spec | 16 +- 5 files changed, 2192 insertions(+), 1 deletion(-) create mode 100644 Hygon-Add-support-for-udev-to-create-tcm-de.patch create mode 100644 Hygon-add-ecc-encrypt-decrypt-support.patch create mode 100644 add-bootstrap-file-from-upstream.patch create mode 100644 backport-esys-add-SM4-algorithm-support.patch diff --git a/Hygon-Add-support-for-udev-to-create-tcm-de.patch b/Hygon-Add-support-for-udev-to-create-tcm-de.patch new file mode 100644 index 0000000..58e045c --- /dev/null +++ b/Hygon-Add-support-for-udev-to-create-tcm-de.patch @@ -0,0 +1,22 @@ +From 61a3e15944eff1acb7f17528ea71d30db09405b5 Mon Sep 17 00:00:00 2001 +From: chench +Date: Fri, 5 Jul 2024 16:25:08 +0800 +Subject: [PATCH] [newfeature][tcm] Add support for udev to create tcm devices + +Change-Id: I15958fd5864a7688655d8b2933280237c63c4e86 +--- + dist/tpm-udev.rules | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/dist/tpm-udev.rules b/dist/tpm-udev.rules +index d7745b4..fde36bb 100644 +--- a/dist/tpm-udev.rules ++++ b/dist/tpm-udev.rules +@@ -2,3 +2,5 @@ + # group members can access tpmrm devices + KERNEL=="tpm[0-9]*", TAG+="systemd", MODE="0660", OWNER="tss" + KERNEL=="tpmrm[0-9]*", TAG+="systemd", MODE="0660", GROUP="tss" ++KERNEL=="tcm[0-9]*", TAG+="systemd", MODE="0660", OWNER="tss" ++KERNEL=="tcmrm[0-9]*", TAG+="systemd", MODE="0660", GROUP="tss" +-- +2.17.1 diff --git a/Hygon-add-ecc-encrypt-decrypt-support.patch b/Hygon-add-ecc-encrypt-decrypt-support.patch new file mode 100644 index 0000000..3006536 --- /dev/null +++ b/Hygon-add-ecc-encrypt-decrypt-support.patch @@ -0,0 +1,1354 @@ +From 406ee12062de2f8132ff10f1abc6887f32e6c03b Mon Sep 17 00:00:00 2001 +From: mayuanchen +Date: Tue, 9 May 2023 18:39:47 -0400 +Subject: [PATCH 1/3] newfeature: tpm: add ecc encrypt/decrypt support. + +Change-Id: I0176b508015a907e6dff48b8d8c90427b59f7a5e +--- + include/tss2/tss2_esys.h | 61 +++++ + include/tss2/tss2_mu.h | 14 + + include/tss2/tss2_sys.h | 46 ++++ + include/tss2/tss2_tpm2_types.h | 13 +- + lib/tss2-esys.def | 6 + + lib/tss2-esys.map | 6 + + lib/tss2-mu.def | 2 + + lib/tss2-mu.map | 2 + + lib/tss2-sys.def | 6 + + lib/tss2-sys.map | 6 + + src/tss2-esys/api/Esys_ECC_Decrypt.c | 347 ++++++++++++++++++++++++ + src/tss2-esys/api/Esys_ECC_Encrypt.c | 341 +++++++++++++++++++++++ + src/tss2-mu/tpmt-types.c | 6 + + src/tss2-sys/api/Tss2_Sys_ECC_Decrypt.c | 153 +++++++++++ + src/tss2-sys/api/Tss2_Sys_ECC_Encrypt.c | 153 +++++++++++ + src/tss2-sys/sysapi_util.c | 4 +- + 16 files changed, 1164 insertions(+), 2 deletions(-) + create mode 100644 src/tss2-esys/api/Esys_ECC_Decrypt.c + create mode 100644 src/tss2-esys/api/Esys_ECC_Encrypt.c + create mode 100644 src/tss2-sys/api/Tss2_Sys_ECC_Decrypt.c + create mode 100644 src/tss2-sys/api/Tss2_Sys_ECC_Encrypt.c + +diff --git a/include/tss2/tss2_esys.h b/include/tss2/tss2_esys.h +index 6641f8d..fd06eeb 100644 +--- a/include/tss2/tss2_esys.h ++++ b/include/tss2/tss2_esys.h +@@ -3759,6 +3759,67 @@ Esys_NV_Certify_Finish( + TPM2B_ATTEST **certifyInfo, + TPMT_SIGNATURE **signature); + ++TSS2_RC ++Esys_ECC_Encrypt( ++ ESYS_CONTEXT *esysContext, ++ ESYS_TR keyHandle, ++ ESYS_TR shandle1, ++ ESYS_TR shandle2, ++ ESYS_TR shandle3, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2, ++ TPM2B_MAX_BUFFER **outData); ++ ++TSS2_RC ++Esys_ECC_Encrypt_Async( ++ ESYS_CONTEXT *esysContext, ++ ESYS_TR keyHandle, ++ ESYS_TR shandle1, ++ ESYS_TR shandle2, ++ ESYS_TR shandle3, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2); ++ ++TSS2_RC ++Esys_ECC_Encrypt_Finish( ++ ESYS_CONTEXT *esysContext, ++ TPM2B_MAX_BUFFER **outData); ++ ++TSS2_RC ++Esys_ECC_Decrypt( ++ ESYS_CONTEXT *esysContext, ++ ESYS_TR keyHandle, ++ ESYS_TR shandle1, ++ ESYS_TR shandle2, ++ ESYS_TR shandle3, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2, ++ TPM2B_MAX_BUFFER **outData); ++ ++TSS2_RC ++Esys_ECC_Decrypt_Async( ++ ESYS_CONTEXT *esysContext, ++ ESYS_TR keyHandle, ++ ESYS_TR shandle1, ++ ESYS_TR shandle2, ++ ESYS_TR shandle3, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2); ++ ++TSS2_RC ++Esys_ECC_Decrypt_Finish( ++ ESYS_CONTEXT *esysContext, ++ TPM2B_MAX_BUFFER **outData); ++ ++ + /* Table 233 - TPM2_Vendor_TCG_Test Command */ + + TSS2_RC +diff --git a/include/tss2/tss2_mu.h b/include/tss2/tss2_mu.h +index 8933efc..25717d7 100644 +--- a/include/tss2/tss2_mu.h ++++ b/include/tss2/tss2_mu.h +@@ -1800,6 +1800,20 @@ Tss2_MU_TPMT_RSA_DECRYPT_Unmarshal( + size_t *offset, + TPMT_RSA_DECRYPT *dest); + ++TSS2_RC ++Tss2_MU_TPMT_ECC_DECRYPT_Marshal( ++ TPMT_ECC_DECRYPT const *src, ++ uint8_t buffer[], ++ size_t buffer_size, ++ size_t *offset); ++ ++TSS2_RC ++Tss2_MU_TPMT_ECC_DECRYPT_Unmarshal( ++ uint8_t const buffer[], ++ size_t buffer_size, ++ size_t *offset, ++ TPMT_ECC_DECRYPT *dest); ++ + TSS2_RC + Tss2_MU_TPMT_ECC_SCHEME_Marshal( + TPMT_ECC_SCHEME const *src, +diff --git a/include/tss2/tss2_sys.h b/include/tss2/tss2_sys.h +index a672898..80e42f6 100644 +--- a/include/tss2/tss2_sys.h ++++ b/include/tss2/tss2_sys.h +@@ -2319,6 +2319,52 @@ TSS2_RC Tss2_Sys_PolicyAuthorizeNV( + TSS2L_SYS_AUTH_COMMAND const *cmdAuthsArray, + TSS2L_SYS_AUTH_RESPONSE *rspAuthsArray); + ++TSS2_RC Tss2_Sys_ECC_Encrypt_Prepare( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPMI_DH_OBJECT keyHandle, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2); ++ ++TSS2_RC Tss2_Sys_ECC_Encrypt_Complete( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPM2B_MAX_BUFFER *outData); ++ ++TSS2_RC Tss2_Sys_ECC_Encrypt( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPMI_DH_OBJECT keyHandle, ++ TSS2L_SYS_AUTH_COMMAND const *cmdAuthsArray, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2, ++ TPM2B_MAX_BUFFER *outData, ++ TSS2L_SYS_AUTH_RESPONSE *rspAuthsArray); ++ ++TSS2_RC Tss2_Sys_ECC_Decrypt_Prepare( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPMI_DH_OBJECT keyHandle, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2); ++ ++TSS2_RC Tss2_Sys_ECC_Decrypt_Complete( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPM2B_MAX_BUFFER *outData); ++ ++TSS2_RC Tss2_Sys_ECC_Decrypt( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPMI_DH_OBJECT keyHandle, ++ TSS2L_SYS_AUTH_COMMAND const *cmdAuthsArray, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2, ++ TPM2B_MAX_BUFFER *outData, ++ TSS2L_SYS_AUTH_RESPONSE *rspAuthsArray); ++ + #ifdef __cplusplus + } + #endif +diff --git a/include/tss2/tss2_tpm2_types.h b/include/tss2/tss2_tpm2_types.h +index 1ce737e..c5f53d9 100644 +--- a/include/tss2/tss2_tpm2_types.h ++++ b/include/tss2/tss2_tpm2_types.h +@@ -249,7 +249,9 @@ typedef UINT32 TPM2_CC; + #define TPM2_CC_Policy_AC_SendSelect ((TPM2_CC) 0x00000196) + #define TPM2_CC_CertifyX509 ((TPM2_CC) 0x00000197) + #define TPM2_CC_ACT_SetTimeout ((TPM2_CC) 0x00000198) +-#define TPM2_CC_LAST ((TPM2_CC) 0x00000198) ++#define TPM2_CC_ECC_Encrypt ((TPM2_CC) 0x00000199) ++#define TPM2_CC_ECC_Decrypt ((TPM2_CC) 0x0000019a) ++#define TPM2_CC_LAST ((TPM2_CC) 0x0000019a) + #define TPM2_CC_Vendor_TCG_Test ((TPM2_CC) 0x20000000) + + /* Definition of Types for Documentation Clarity */ +@@ -1630,6 +1632,15 @@ struct TPM2B_PRIVATE_KEY_RSA { + BYTE buffer[TPM2_MAX_RSA_KEY_BYTES/2 * 5]; + }; + ++/* Definition of TPM2_ALG_ID ECC TPMI_ALG_ECC_DECRYPT Type */ ++typedef TPM2_ALG_ID TPMI_ALG_ECC_DECRYPT; ++ ++/* Definition of ECC TPMT_ECC_DECRYPT Structure */ ++typedef struct { ++ TPMI_ALG_ECC_DECRYPT scheme; /* scheme selector */ ++ TPMU_ASYM_SCHEME details; /* scheme parameters */ ++} TPMT_ECC_DECRYPT; ++ + /* Definition of ECC TPM2B_ECC_PARAMETER Structure */ + typedef struct TPM2B_ECC_PARAMETER TPM2B_ECC_PARAMETER; + struct TPM2B_ECC_PARAMETER { +diff --git a/lib/tss2-esys.def b/lib/tss2-esys.def +index c6890d8..3b762f7 100644 +--- a/lib/tss2-esys.def ++++ b/lib/tss2-esys.def +@@ -66,6 +66,12 @@ EXPORTS + Esys_Duplicate + Esys_Duplicate_Async + Esys_Duplicate_Finish ++ Esys_ECC_Decrypt ++ Esys_ECC_Decrypt_Async ++ Esys_ECC_Decrypt_Finish ++ Esys_ECC_Encrypt ++ Esys_ECC_Encrypt_Async ++ Esys_ECC_Encrypt_Finish + Esys_ECC_Parameters + Esys_ECC_Parameters_Async + Esys_ECC_Parameters_Finish +diff --git a/lib/tss2-esys.map b/lib/tss2-esys.map +index 2062cc3..6884075 100644 +--- a/lib/tss2-esys.map ++++ b/lib/tss2-esys.map +@@ -66,6 +66,12 @@ + Esys_Duplicate; + Esys_Duplicate_Async; + Esys_Duplicate_Finish; ++ Esys_ECC_Decrypt; ++ Esys_ECC_Decrypt_Async; ++ Esys_ECC_Decrypt_Finish; ++ Esys_ECC_Encrypt; ++ Esys_ECC_Encrypt_Async; ++ Esys_ECC_Encrypt_Finish; + Esys_ECC_Parameters; + Esys_ECC_Parameters_Async; + Esys_ECC_Parameters_Finish; +diff --git a/lib/tss2-mu.def b/lib/tss2-mu.def +index d978c83..7b2e957 100644 +--- a/lib/tss2-mu.def ++++ b/lib/tss2-mu.def +@@ -284,3 +284,5 @@ EXPORTS + Tss2_MU_TPM2_NT_Unmarshal + Tss2_MU_TPMI_ALG_HASH_Marshal + Tss2_MU_TPMI_ALG_HASH_Unmarshal ++ Tss2_MU_TPMT_ECC_DECRYPT_Marshal ++ Tss2_MU_TPMT_ECC_DECRYPT_Unmarshal +diff --git a/lib/tss2-mu.map b/lib/tss2-mu.map +index 3f4c8cb..2149a5f 100644 +--- a/lib/tss2-mu.map ++++ b/lib/tss2-mu.map +@@ -284,6 +284,8 @@ + Tss2_MU_TPM2_NT_Unmarshal; + Tss2_MU_TPMI_ALG_HASH_Marshal; + Tss2_MU_TPMI_ALG_HASH_Unmarshal; ++ Tss2_MU_TPMT_ECC_DECRYPT_Marshal; ++ Tss2_MU_TPMT_ECC_DECRYPT_Unmarshal; + local: + *; + }; +diff --git a/lib/tss2-sys.def b/lib/tss2-sys.def +index 751ef33..b25dcd9 100644 +--- a/lib/tss2-sys.def ++++ b/lib/tss2-sys.def +@@ -372,3 +372,9 @@ EXPORTS + Tss2_Sys_ZGen_2Phase_Prepare + Tss2_Sys_ZGen_2Phase_Complete + Tss2_Sys_ZGen_2Phase ++ Tss2_Sys_ECC_Encrypt_Prepare ++ Tss2_Sys_ECC_Encrypt_Complete ++ Tss2_Sys_ECC_Encrypt ++ Tss2_Sys_ECC_Decrypt_Prepare ++ Tss2_Sys_ECC_Decrypt_Complete ++ Tss2_Sys_ECC_Decrypt +diff --git a/lib/tss2-sys.map b/lib/tss2-sys.map +index 0027df9..eba70f7 100644 +--- a/lib/tss2-sys.map ++++ b/lib/tss2-sys.map +@@ -376,6 +376,12 @@ + Tss2_Sys_ZGen_2Phase_Prepare; + Tss2_Sys_ZGen_2Phase_Complete; + Tss2_Sys_ZGen_2Phase; ++ Tss2_Sys_ECC_Encrypt_Prepare; ++ Tss2_Sys_ECC_Encrypt_Complete; ++ Tss2_Sys_ECC_Encrypt; ++ Tss2_Sys_ECC_Decrypt_Prepare; ++ Tss2_Sys_ECC_Decrypt_Complete; ++ Tss2_Sys_ECC_Decrypt; + local: + *; + }; +diff --git a/src/tss2-esys/api/Esys_ECC_Decrypt.c b/src/tss2-esys/api/Esys_ECC_Decrypt.c +new file mode 100644 +index 0000000..1515563 +--- /dev/null ++++ b/src/tss2-esys/api/Esys_ECC_Decrypt.c +@@ -0,0 +1,347 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/******************************************************************************* ++ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG ++ * All rights reserved. ++ ******************************************************************************/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "tss2_mu.h" ++#include "tss2_sys.h" ++#include "tss2_esys.h" ++ ++#include "esys_types.h" ++#include "esys_iutil.h" ++#include "esys_mu.h" ++#define LOGMODULE esys ++#include "util/log.h" ++#include "util/aux_util.h" ++ ++/** One-Call function for TPM2_ECC_Decrypt ++ * ++ * This function invokes the TPM2_ECC_Decrypt command in a one-call ++ * variant. This means the function will block until the TPM response is ++ * available. All input parameters are const. The memory for non-simple output ++ * parameters is allocated by the function implementation. ++ * ++ * @param[in,out] esysContext The ESYS_CONTEXT. ++ * @param[in] keyHandle Reference to public portion of ECC key to use for ++ * encryption. ++ * @param[in] shandle1 First session handle. ++ * @param[in] shandle2 Second session handle. ++ * @param[in] shandle3 Third session handle. ++ * @param[in] inScheme TPM2_The padding scheme to use if scheme associated with ++ * keyHandle is TPM2_ALG_NULL. ++ * @param[in] cipherText Cipher text to be decrypted. ++ * @param[in] sharedData1 Optional sharedData1 to be associated with the inScheme. ++ * @param[in] sharedData2 Optional sharedData2 to be associated with the inScheme. ++ * @param[out] outData Encrypted output. ++ * (callee-allocated) ++ * @retval TSS2_RC_SUCCESS if the function call was a success. ++ * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input ++ * pointers or required output handle references are NULL. ++ * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected. ++ * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for ++ * internal operations or return parameters. ++ * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous ++ * operation already pending. ++ * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not ++ * at least contain the tag, response length, and response code. ++ * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted. ++ * @retval TSS2_ESYS_RC_RSP_AUTH_FAILED: if the response HMAC from the TPM ++ did not verify. ++ * @retval TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS: if more than one session has ++ * the 'decrypt' attribute bit set. ++ * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS: if more than one session has ++ * the 'encrypt' attribute bit set. ++ * @retval TSS2_ESYS_RC_BAD_TR: if any of the ESYS_TR objects are unknown ++ * to the ESYS_CONTEXT or are of the wrong type or if required ++ * ESYS_TR objects are ESYS_TR_NONE. ++ * @retval TSS2_RCs produced by lower layers of the software stack may be ++ * returned to the caller unaltered unless handled internally. ++ */ ++TSS2_RC ++Esys_ECC_Decrypt( ++ ESYS_CONTEXT *esysContext, ++ ESYS_TR keyHandle, ++ ESYS_TR shandle1, ++ ESYS_TR shandle2, ++ ESYS_TR shandle3, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *cipherText, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2, ++ TPM2B_MAX_BUFFER **outData) ++{ ++ TSS2_RC r; ++ ++ r = Esys_ECC_Decrypt_Async(esysContext, keyHandle, shandle1, shandle2, ++ shandle3, inScheme, cipherText, sharedData1, sharedData2); ++ return_if_error(r, "Error in async function"); ++ ++ /* Set the timeout to indefinite for now, since we want _Finish to block */ ++ int32_t timeouttmp = esysContext->timeout; ++ esysContext->timeout = -1; ++ /* ++ * Now we call the finish function, until return code is not equal to ++ * from TSS2_BASE_RC_TRY_AGAIN. ++ * Note that the finish function may return TSS2_RC_TRY_AGAIN, even if we ++ * have set the timeout to -1. This occurs for example if the TPM requests ++ * a retransmission of the command via TPM2_RC_YIELDED. ++ */ ++ do { ++ r = Esys_ECC_Decrypt_Finish(esysContext, outData); ++ /* This is just debug information about the reattempt to finish the ++ command */ ++ if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) ++ LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32 ++ " => resubmitting command", r); ++ } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN); ++ ++ /* Restore the timeout value to the original value */ ++ esysContext->timeout = timeouttmp; ++ return_if_error(r, "Esys Finish"); ++ ++ return TSS2_RC_SUCCESS; ++} ++ ++/** Asynchronous function for TPM2_ECC_Decrypt ++ * ++ * This function invokes the TPM2_ECC_Decrypt command in a asynchronous ++ * variant. This means the function will return as soon as the command has been ++ * sent downwards the stack to the TPM. All input parameters are const. ++ * In order to retrieve the TPM's response call Esys_ECC_Decrypt_Finish. ++ * ++ * @param[in,out] esysContext The ESYS_CONTEXT. ++ * @param[in] keyHandle Reference to public portion of ECC key to use for ++ * encryption. ++ * @param[in] shandle1 First session handle. ++ * @param[in] shandle2 Second session handle. ++ * @param[in] shandle3 Third session handle. ++ * @param[in] inScheme TPM2_The padding scheme to use if scheme associated with ++ * keyHandle is TPM2_ALG_NULL. ++ * @param[in] cipherText Cipher text to be decrypted. ++ * @param[in] sharedData1 Optional sharedData1 to be associated with the inScheme. ++ * @param[in] sharedData2 Optional sharedData2 to be associated with the inScheme. ++ * @retval ESYS_RC_SUCCESS if the function call was a success. ++ * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input ++ * pointers or required output handle references are NULL. ++ * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected. ++ * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for ++ * internal operations or return parameters. ++ * @retval TSS2_RCs produced by lower layers of the software stack may be ++ returned to the caller unaltered unless handled internally. ++ * @retval TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS: if more than one session has ++ * the 'decrypt' attribute bit set. ++ * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS: if more than one session has ++ * the 'encrypt' attribute bit set. ++ * @retval TSS2_ESYS_RC_BAD_TR: if any of the ESYS_TR objects are unknown ++ * to the ESYS_CONTEXT or are of the wrong type or if required ++ * ESYS_TR objects are ESYS_TR_NONE. ++ */ ++TSS2_RC ++Esys_ECC_Decrypt_Async( ++ ESYS_CONTEXT *esysContext, ++ ESYS_TR keyHandle, ++ ESYS_TR shandle1, ++ ESYS_TR shandle2, ++ ESYS_TR shandle3, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *cipherText, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2) ++{ ++ TSS2_RC r; ++ LOG_TRACE("context=%p, keyHandle=%"PRIx32 ", cipherText=%p," ++ "inScheme=%p, sharedData1=%p, sharedData2=%p", ++ esysContext, keyHandle, cipherText, inScheme, sharedData1, sharedData2); ++ TSS2L_SYS_AUTH_COMMAND auths; ++ RSRC_NODE_T *keyHandleNode; ++ ++ /* Check context, sequence correctness and set state to error for now */ ++ if (esysContext == NULL) { ++ LOG_ERROR("esyscontext is NULL."); ++ return TSS2_ESYS_RC_BAD_REFERENCE; ++ } ++ r = iesys_check_sequence_async(esysContext); ++ if (r != TSS2_RC_SUCCESS) ++ return r; ++ esysContext->state = _ESYS_STATE_INTERNALERROR; ++ ++ /* Check input parameters */ ++ r = check_session_feasibility(shandle1, shandle2, shandle3, 1); ++ return_state_if_error(r, _ESYS_STATE_INIT, "Check session usage"); ++ ++ /* Retrieve the metadata objects for provided handles */ ++ r = esys_GetResourceObject(esysContext, keyHandle, &keyHandleNode); ++ return_state_if_error(r, _ESYS_STATE_INIT, "keyHandle unknown."); ++ ++ /* Initial invocation of SAPI to prepare the command buffer with parameters */ ++ r = Tss2_Sys_ECC_Decrypt_Prepare(esysContext->sys, ++ (keyHandleNode == NULL) ? TPM2_RH_NULL ++ : keyHandleNode->rsrc.handle, inScheme, ++ cipherText, sharedData1, sharedData2); ++ return_state_if_error(r, _ESYS_STATE_INIT, "SAPI Prepare returned error."); ++ ++ /* Calculate the cpHash Values */ ++ r = init_session_tab(esysContext, shandle1, shandle2, shandle3); ++ return_state_if_error(r, _ESYS_STATE_INIT, "Initialize session resources"); ++ if (keyHandleNode != NULL) ++ iesys_compute_session_value(esysContext->session_tab[0], ++ &keyHandleNode->rsrc.name, &keyHandleNode->auth); ++ else ++ iesys_compute_session_value(esysContext->session_tab[0], NULL, NULL); ++ ++ iesys_compute_session_value(esysContext->session_tab[1], NULL, NULL); ++ iesys_compute_session_value(esysContext->session_tab[2], NULL, NULL); ++ ++ /* Generate the auth values and set them in the SAPI command buffer */ ++ r = iesys_gen_auths(esysContext, keyHandleNode, NULL, NULL, &auths); ++ return_state_if_error(r, _ESYS_STATE_INIT, ++ "Error in computation of auth values"); ++ ++ esysContext->authsCount = auths.count; ++ if (auths.count > 0) { ++ r = Tss2_Sys_SetCmdAuths(esysContext->sys, &auths); ++ return_state_if_error(r, _ESYS_STATE_INIT, "SAPI error on SetCmdAuths"); ++ } ++ ++ /* Trigger execution and finish the async invocation */ ++ r = Tss2_Sys_ExecuteAsync(esysContext->sys); ++ return_state_if_error(r, _ESYS_STATE_INTERNALERROR, ++ "Finish (Execute Async)"); ++ ++ esysContext->state = _ESYS_STATE_SENT; ++ ++ return r; ++} ++ ++/** Asynchronous finish function for TPM2_ECC_Decrypt ++ * ++ * This function returns the results of a TPM2_ECC_Decrypt command ++ * invoked via Esys_ECC_Decrypt_Finish. All non-simple output parameters ++ * are allocated by the function's implementation. NULL can be passed for every ++ * output parameter if the value is not required. ++ * ++ * @param[in,out] esysContext The ESYS_CONTEXT. ++ * @param[out] outData Decrypted output. ++ * (callee-allocated) ++ * @retval TSS2_RC_SUCCESS on success ++ * @retval ESYS_RC_SUCCESS if the function call was a success. ++ * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input ++ * pointers or required output handle references are NULL. ++ * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected. ++ * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for ++ * internal operations or return parameters. ++ * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous ++ * operation already pending. ++ * @retval TSS2_ESYS_RC_TRY_AGAIN: if the timeout counter expires before the ++ * TPM response is received. ++ * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not ++ * at least contain the tag, response length, and response code. ++ * @retval TSS2_ESYS_RC_RSP_AUTH_FAILED: if the response HMAC from the TPM did ++ * not verify. ++ * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted. ++ * @retval TSS2_RCs produced by lower layers of the software stack may be ++ * returned to the caller unaltered unless handled internally. ++ */ ++TSS2_RC ++Esys_ECC_Decrypt_Finish( ++ ESYS_CONTEXT *esysContext, ++ TPM2B_MAX_BUFFER **outData) ++{ ++ TSS2_RC r; ++ LOG_TRACE("context=%p, outData=%p", ++ esysContext, outData); ++ ++ if (esysContext == NULL) { ++ LOG_ERROR("esyscontext is NULL."); ++ return TSS2_ESYS_RC_BAD_REFERENCE; ++ } ++ ++ /* Check for correct sequence and set sequence to irregular for now */ ++ if (esysContext->state != _ESYS_STATE_SENT && ++ esysContext->state != _ESYS_STATE_RESUBMISSION) { ++ LOG_ERROR("Esys called in bad sequence."); ++ return TSS2_ESYS_RC_BAD_SEQUENCE; ++ } ++ esysContext->state = _ESYS_STATE_INTERNALERROR; ++ ++ /* Allocate memory for response parameters */ ++ if (outData != NULL) { ++ *outData = calloc(sizeof(TPM2B_MAX_BUFFER), 1); ++ if (*outData == NULL) { ++ return_error(TSS2_ESYS_RC_MEMORY, "Out of memory"); ++ } ++ } ++ ++ /*Receive the TPM response and handle resubmissions if necessary. */ ++ r = Tss2_Sys_ExecuteFinish(esysContext->sys, esysContext->timeout); ++ if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) { ++ LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32, r); ++ esysContext->state = _ESYS_STATE_SENT; ++ goto error_cleanup; ++ } ++ /* This block handle the resubmission of TPM commands given a certain set of ++ * TPM response codes. */ ++ if (r == TPM2_RC_RETRY || r == TPM2_RC_TESTING || r == TPM2_RC_YIELDED) { ++ LOG_DEBUG("TPM returned RETRY, TESTING or YIELDED, which triggers a " ++ "resubmission: %" PRIx32, r); ++ if (esysContext->submissionCount++ >= _ESYS_MAX_SUBMISSIONS) { ++ LOG_WARNING("Maximum number of (re)submissions has been reached."); ++ esysContext->state = _ESYS_STATE_INIT; ++ goto error_cleanup; ++ } ++ esysContext->state = _ESYS_STATE_RESUBMISSION; ++ r = Tss2_Sys_ExecuteAsync(esysContext->sys); ++ if (r != TSS2_RC_SUCCESS) { ++ LOG_WARNING("Error attempting to resubmit"); ++ /* We do not set esysContext->state here but inherit the most recent ++ * state of the _async function. */ ++ goto error_cleanup; ++ } ++ r = TSS2_ESYS_RC_TRY_AGAIN; ++ LOG_DEBUG("Resubmission initiated and returning RC_TRY_AGAIN."); ++ goto error_cleanup; ++ } ++ /* The following is the "regular error" handling. */ ++ if (iesys_tpm_error(r)) { ++ LOG_WARNING("Received TPM Error"); ++ esysContext->state = _ESYS_STATE_INIT; ++ goto error_cleanup; ++ } else if (r != TSS2_RC_SUCCESS) { ++ LOG_ERROR("Received a non-TPM Error"); ++ esysContext->state = _ESYS_STATE_INTERNALERROR; ++ goto error_cleanup; ++ } ++ ++ /* ++ * Now the verification of the response (hmac check) and if necessary the ++ * parameter decryption have to be done. ++ */ ++ r = iesys_check_response(esysContext); ++ goto_state_if_error(r, _ESYS_STATE_INTERNALERROR, "Error: check response", ++ error_cleanup); ++ ++ /* ++ * After the verification of the response we call the complete function ++ * to deliver the result. ++ */ ++ r = Tss2_Sys_ECC_Decrypt_Complete(esysContext->sys, ++ (outData != NULL) ? *outData : NULL); ++ goto_state_if_error(r, _ESYS_STATE_INTERNALERROR, ++ "Received error from SAPI unmarshaling" , ++ error_cleanup); ++ ++ esysContext->state = _ESYS_STATE_INIT; ++ ++ return TSS2_RC_SUCCESS; ++ ++error_cleanup: ++ if (outData != NULL) ++ SAFE_FREE(*outData); ++ ++ return r; ++} +diff --git a/src/tss2-esys/api/Esys_ECC_Encrypt.c b/src/tss2-esys/api/Esys_ECC_Encrypt.c +new file mode 100644 +index 0000000..498bca6 +--- /dev/null ++++ b/src/tss2-esys/api/Esys_ECC_Encrypt.c +@@ -0,0 +1,341 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/******************************************************************************* ++ * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG ++ * All rights reserved. ++ ******************************************************************************/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "tss2_mu.h" ++#include "tss2_sys.h" ++#include "tss2_esys.h" ++ ++#include "esys_types.h" ++#include "esys_iutil.h" ++#include "esys_mu.h" ++#define LOGMODULE esys ++#include "util/log.h" ++#include "util/aux_util.h" ++ ++/** One-Call function for TPM2_ECC_Encrypt ++ * ++ * This function invokes the TPM2_ECC_Encrypt command in a one-call ++ * variant. This means the function will block until the TPM response is ++ * available. All input parameters are const. The memory for non-simple output ++ * parameters is allocated by the function implementation. ++ * ++ * @param[in,out] esysContext The ESYS_CONTEXT. ++ * @param[in] keyHandle Reference to public portion of ECC key to use for ++ * encryption. ++ * @param[in] shandle1 First session handle. ++ * @param[in] shandle2 Second session handle. ++ * @param[in] shandle3 Third session handle. ++ * @param[in] inScheme TPM2_The padding scheme to use if scheme associated with ++ * keyHandle is TPM2_ALG_NULL. ++ * @param[in] message Message to be encrypted. ++ * @param[in] sharedData1 Optional sharedData1 to be associated with the inScheme. ++ * @param[in] sharedData2 Optional sharedData2 to be associated with the inScheme. ++ * @param[out] outData Encrypted output. ++ * (callee-allocated) ++ * @retval TSS2_RC_SUCCESS if the function call was a success. ++ * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input ++ * pointers or required output handle references are NULL. ++ * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected. ++ * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for ++ * internal operations or return parameters. ++ * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous ++ * operation already pending. ++ * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not ++ * at least contain the tag, response length, and response code. ++ * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted. ++ * @retval TSS2_ESYS_RC_RSP_AUTH_FAILED: if the response HMAC from the TPM ++ did not verify. ++ * @retval TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS: if more than one session has ++ * the 'decrypt' attribute bit set. ++ * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS: if more than one session has ++ * the 'encrypt' attribute bit set. ++ * @retval TSS2_ESYS_RC_BAD_TR: if any of the ESYS_TR objects are unknown ++ * to the ESYS_CONTEXT or are of the wrong type or if required ++ * ESYS_TR objects are ESYS_TR_NONE. ++ * @retval TSS2_RCs produced by lower layers of the software stack may be ++ * returned to the caller unaltered unless handled internally. ++ */ ++TSS2_RC ++Esys_ECC_Encrypt( ++ ESYS_CONTEXT *esysContext, ++ ESYS_TR keyHandle, ++ ESYS_TR shandle1, ++ ESYS_TR shandle2, ++ ESYS_TR shandle3, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2, ++ TPM2B_MAX_BUFFER **outData) ++{ ++ TSS2_RC r; ++ ++ r = Esys_ECC_Encrypt_Async(esysContext, keyHandle, shandle1, shandle2, ++ shandle3, inScheme, message, sharedData1, sharedData2); ++ return_if_error(r, "Error in async function"); ++ ++ /* Set the timeout to indefinite for now, since we want _Finish to block */ ++ int32_t timeouttmp = esysContext->timeout; ++ esysContext->timeout = -1; ++ /* ++ * Now we call the finish function, until return code is not equal to ++ * from TSS2_BASE_RC_TRY_AGAIN. ++ * Note that the finish function may return TSS2_RC_TRY_AGAIN, even if we ++ * have set the timeout to -1. This occurs for example if the TPM requests ++ * a retransmission of the command via TPM2_RC_YIELDED. ++ */ ++ do { ++ r = Esys_ECC_Encrypt_Finish(esysContext, outData); ++ /* This is just debug information about the reattempt to finish the ++ command */ ++ if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) ++ LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32 ++ " => resubmitting command", r); ++ } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN); ++ ++ /* Restore the timeout value to the original value */ ++ esysContext->timeout = timeouttmp; ++ return_if_error(r, "Esys Finish"); ++ ++ return TSS2_RC_SUCCESS; ++} ++ ++/** Asynchronous function for TPM2_ECC_Encrypt ++ * ++ * This function invokes the TPM2_ECC_Encrypt command in a asynchronous ++ * variant. This means the function will return as soon as the command has been ++ * sent downwards the stack to the TPM. All input parameters are const. ++ * In order to retrieve the TPM's response call Esys_ECC_Encrypt_Finish. ++ * ++ * @param[in,out] esysContext The ESYS_CONTEXT. ++ * @param[in] keyHandle Reference to public portion of ECC key to use for ++ * encryption. ++ * @param[in] shandle1 First session handle. ++ * @param[in] shandle2 Second session handle. ++ * @param[in] shandle3 Third session handle. ++ * @param[in] message Message to be encrypted. ++ * @param[in] inScheme TPM2_The padding scheme to use if scheme associated with ++ * keyHandle is TPM2_ALG_NULL. ++ * @param[in] label Optional label L to be associated with the message. ++ * @retval ESYS_RC_SUCCESS if the function call was a success. ++ * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input ++ * pointers or required output handle references are NULL. ++ * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected. ++ * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for ++ * internal operations or return parameters. ++ * @retval TSS2_RCs produced by lower layers of the software stack may be ++ returned to the caller unaltered unless handled internally. ++ * @retval TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS: if more than one session has ++ * the 'decrypt' attribute bit set. ++ * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS: if more than one session has ++ * the 'encrypt' attribute bit set. ++ * @retval TSS2_ESYS_RC_BAD_TR: if any of the ESYS_TR objects are unknown ++ * to the ESYS_CONTEXT or are of the wrong type or if required ++ * ESYS_TR objects are ESYS_TR_NONE. ++ */ ++TSS2_RC ++Esys_ECC_Encrypt_Async( ++ ESYS_CONTEXT *esysContext, ++ ESYS_TR keyHandle, ++ ESYS_TR shandle1, ++ ESYS_TR shandle2, ++ ESYS_TR shandle3, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2) ++{ ++ TSS2_RC r; ++ LOG_TRACE("context=%p, keyHandle=%"PRIx32 ", message=%p," ++ "inScheme=%p, sharedData1=%p, sharedData2=%p", ++ esysContext, keyHandle, message, inScheme, sharedData1, sharedData2); ++ TSS2L_SYS_AUTH_COMMAND auths; ++ RSRC_NODE_T *keyHandleNode; ++ ++ /* Check context, sequence correctness and set state to error for now */ ++ if (esysContext == NULL) { ++ LOG_ERROR("esyscontext is NULL."); ++ return TSS2_ESYS_RC_BAD_REFERENCE; ++ } ++ r = iesys_check_sequence_async(esysContext); ++ if (r != TSS2_RC_SUCCESS) ++ return r; ++ esysContext->state = _ESYS_STATE_INTERNALERROR; ++ ++ /* Check input parameters */ ++ r = check_session_feasibility(shandle1, shandle2, shandle3, 0); ++ return_state_if_error(r, _ESYS_STATE_INIT, "Check session usage"); ++ ++ /* Retrieve the metadata objects for provided handles */ ++ r = esys_GetResourceObject(esysContext, keyHandle, &keyHandleNode); ++ return_state_if_error(r, _ESYS_STATE_INIT, "keyHandle unknown."); ++ ++ /* Initial invocation of SAPI to prepare the command buffer with parameters */ ++ r = Tss2_Sys_ECC_Encrypt_Prepare(esysContext->sys, ++ (keyHandleNode == NULL) ? TPM2_RH_NULL ++ : keyHandleNode->rsrc.handle, inScheme, ++ message, sharedData1, sharedData2); ++ return_state_if_error(r, _ESYS_STATE_INIT, "SAPI Prepare returned error."); ++ ++ /* Calculate the cpHash Values */ ++ r = init_session_tab(esysContext, shandle1, shandle2, shandle3); ++ return_state_if_error(r, _ESYS_STATE_INIT, "Initialize session resources"); ++ iesys_compute_session_value(esysContext->session_tab[0], NULL, NULL); ++ iesys_compute_session_value(esysContext->session_tab[1], NULL, NULL); ++ iesys_compute_session_value(esysContext->session_tab[2], NULL, NULL); ++ ++ /* Generate the auth values and set them in the SAPI command buffer */ ++ r = iesys_gen_auths(esysContext, keyHandleNode, NULL, NULL, &auths); ++ return_state_if_error(r, _ESYS_STATE_INIT, ++ "Error in computation of auth values"); ++ ++ esysContext->authsCount = auths.count; ++ if (auths.count > 0) { ++ r = Tss2_Sys_SetCmdAuths(esysContext->sys, &auths); ++ return_state_if_error(r, _ESYS_STATE_INIT, "SAPI error on SetCmdAuths"); ++ } ++ ++ /* Trigger execution and finish the async invocation */ ++ r = Tss2_Sys_ExecuteAsync(esysContext->sys); ++ return_state_if_error(r, _ESYS_STATE_INTERNALERROR, ++ "Finish (Execute Async)"); ++ ++ esysContext->state = _ESYS_STATE_SENT; ++ ++ return r; ++} ++ ++/** Asynchronous finish function for TPM2_ECC_Encrypt ++ * ++ * This function returns the results of a TPM2_ECC_Encrypt command ++ * invoked via Esys_ECC_Encrypt_Finish. All non-simple output parameters ++ * are allocated by the function's implementation. NULL can be passed for every ++ * output parameter if the value is not required. ++ * ++ * @param[in,out] esysContext The ESYS_CONTEXT. ++ * @param[out] outData Encrypted output. ++ * (callee-allocated) ++ * @retval TSS2_RC_SUCCESS on success ++ * @retval ESYS_RC_SUCCESS if the function call was a success. ++ * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input ++ * pointers or required output handle references are NULL. ++ * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected. ++ * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for ++ * internal operations or return parameters. ++ * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous ++ * operation already pending. ++ * @retval TSS2_ESYS_RC_TRY_AGAIN: if the timeout counter expires before the ++ * TPM response is received. ++ * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not ++ * at least contain the tag, response length, and response code. ++ * @retval TSS2_ESYS_RC_RSP_AUTH_FAILED: if the response HMAC from the TPM did ++ * not verify. ++ * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted. ++ * @retval TSS2_RCs produced by lower layers of the software stack may be ++ * returned to the caller unaltered unless handled internally. ++ */ ++TSS2_RC ++Esys_ECC_Encrypt_Finish( ++ ESYS_CONTEXT *esysContext, ++ TPM2B_MAX_BUFFER **outData) ++{ ++ TSS2_RC r; ++ LOG_TRACE("context=%p, outData=%p", ++ esysContext, outData); ++ ++ if (esysContext == NULL) { ++ LOG_ERROR("esyscontext is NULL."); ++ return TSS2_ESYS_RC_BAD_REFERENCE; ++ } ++ ++ /* Check for correct sequence and set sequence to irregular for now */ ++ if (esysContext->state != _ESYS_STATE_SENT && ++ esysContext->state != _ESYS_STATE_RESUBMISSION) { ++ LOG_ERROR("Esys called in bad sequence."); ++ return TSS2_ESYS_RC_BAD_SEQUENCE; ++ } ++ esysContext->state = _ESYS_STATE_INTERNALERROR; ++ ++ /* Allocate memory for response parameters */ ++ if (outData != NULL) { ++ *outData = calloc(sizeof(TPM2B_MAX_BUFFER), 1); ++ if (*outData == NULL) { ++ return_error(TSS2_ESYS_RC_MEMORY, "Out of memory"); ++ } ++ } ++ ++ /*Receive the TPM response and handle resubmissions if necessary. */ ++ r = Tss2_Sys_ExecuteFinish(esysContext->sys, esysContext->timeout); ++ if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) { ++ LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32, r); ++ esysContext->state = _ESYS_STATE_SENT; ++ goto error_cleanup; ++ } ++ /* This block handle the resubmission of TPM commands given a certain set of ++ * TPM response codes. */ ++ if (r == TPM2_RC_RETRY || r == TPM2_RC_TESTING || r == TPM2_RC_YIELDED) { ++ LOG_DEBUG("TPM returned RETRY, TESTING or YIELDED, which triggers a " ++ "resubmission: %" PRIx32, r); ++ if (esysContext->submissionCount++ >= _ESYS_MAX_SUBMISSIONS) { ++ LOG_WARNING("Maximum number of (re)submissions has been reached."); ++ esysContext->state = _ESYS_STATE_INIT; ++ goto error_cleanup; ++ } ++ esysContext->state = _ESYS_STATE_RESUBMISSION; ++ r = Tss2_Sys_ExecuteAsync(esysContext->sys); ++ if (r != TSS2_RC_SUCCESS) { ++ LOG_WARNING("Error attempting to resubmit"); ++ /* We do not set esysContext->state here but inherit the most recent ++ * state of the _async function. */ ++ goto error_cleanup; ++ } ++ r = TSS2_ESYS_RC_TRY_AGAIN; ++ LOG_DEBUG("Resubmission initiated and returning RC_TRY_AGAIN."); ++ goto error_cleanup; ++ } ++ /* The following is the "regular error" handling. */ ++ if (iesys_tpm_error(r)) { ++ LOG_WARNING("Received TPM Error"); ++ esysContext->state = _ESYS_STATE_INIT; ++ goto error_cleanup; ++ } else if (r != TSS2_RC_SUCCESS) { ++ LOG_ERROR("Received a non-TPM Error"); ++ esysContext->state = _ESYS_STATE_INTERNALERROR; ++ goto error_cleanup; ++ } ++ ++ /* ++ * Now the verification of the response (hmac check) and if necessary the ++ * parameter decryption have to be done. ++ */ ++ r = iesys_check_response(esysContext); ++ goto_state_if_error(r, _ESYS_STATE_INTERNALERROR, "Error: check response", ++ error_cleanup); ++ ++ /* ++ * After the verification of the response we call the complete function ++ * to deliver the result. ++ */ ++ r = Tss2_Sys_ECC_Encrypt_Complete(esysContext->sys, ++ (outData != NULL) ? *outData : NULL); ++ goto_state_if_error(r, _ESYS_STATE_INTERNALERROR, ++ "Received error from SAPI unmarshaling" , ++ error_cleanup); ++ ++ esysContext->state = _ESYS_STATE_INIT; ++ ++ return TSS2_RC_SUCCESS; ++ ++error_cleanup: ++ if (outData != NULL) ++ SAFE_FREE(*outData); ++ ++ return r; ++} +diff --git a/src/tss2-mu/tpmt-types.c b/src/tss2-mu/tpmt-types.c +index df899a6..41cdf36 100644 +--- a/src/tss2-mu/tpmt-types.c ++++ b/src/tss2-mu/tpmt-types.c +@@ -552,6 +552,12 @@ TPMT_MARSHAL_2(TPMT_RSA_DECRYPT, scheme, VAL, Tss2_MU_UINT16_Marshal, + TPMT_UNMARSHAL_2(TPMT_RSA_DECRYPT, scheme, Tss2_MU_UINT16_Unmarshal, + details, scheme, Tss2_MU_TPMU_ASYM_SCHEME_Unmarshal) + ++TPMT_MARSHAL_2(TPMT_ECC_DECRYPT, scheme, VAL, Tss2_MU_UINT16_Marshal, ++ details, ADDR, scheme, Tss2_MU_TPMU_ASYM_SCHEME_Marshal) ++ ++TPMT_UNMARSHAL_2(TPMT_ECC_DECRYPT, scheme, Tss2_MU_UINT16_Unmarshal, ++ details, scheme, Tss2_MU_TPMU_ASYM_SCHEME_Unmarshal) ++ + TPMT_MARSHAL_2(TPMT_ECC_SCHEME, scheme, VAL, Tss2_MU_UINT16_Marshal, + details, ADDR, scheme, Tss2_MU_TPMU_ASYM_SCHEME_Marshal) + +diff --git a/src/tss2-sys/api/Tss2_Sys_ECC_Decrypt.c b/src/tss2-sys/api/Tss2_Sys_ECC_Decrypt.c +new file mode 100644 +index 0000000..9f6a596 +--- /dev/null ++++ b/src/tss2-sys/api/Tss2_Sys_ECC_Decrypt.c +@@ -0,0 +1,153 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/***********************************************************************; ++ * Copyright (c) 2015 - 2017, Intel Corporation ++ * All rights reserved. ++ ***********************************************************************/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "tss2_tpm2_types.h" ++#include "tss2_mu.h" ++#include "sysapi_util.h" ++ ++TSS2_RC Tss2_Sys_ECC_Decrypt_Prepare( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPMI_DH_OBJECT keyHandle, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *cipherText, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2) ++{ ++ _TSS2_SYS_CONTEXT_BLOB *ctx = syscontext_cast(sysContext); ++ TSS2_RC rval; ++ ++ if (!ctx || !inScheme) ++ return TSS2_SYS_RC_BAD_REFERENCE; ++ ++ rval = CommonPreparePrologue(ctx, TPM2_CC_ECC_Decrypt); ++ if (rval) ++ return rval; ++ ++ rval = Tss2_MU_UINT32_Marshal(keyHandle, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ if (rval) ++ return rval; ++ ++ /* Encryption is not possible because the exchange of parameter inScheme ++ and cipherText in tcm2.0 spec. so disable decryptAllowed in the following code. ++ */ ++ rval = Tss2_MU_TPMT_ECC_DECRYPT_Marshal(inScheme, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ if (rval) ++ return rval; ++ ++ if (!cipherText) { ++ ctx->decryptNull = 1; ++ ++ rval = Tss2_MU_UINT16_Marshal(0, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ } else { ++ ++ rval = Tss2_MU_TPM2B_MAX_BUFFER_Marshal(cipherText, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ } ++ ++ if (rval) ++ return rval; ++ ++#if 0 ++ rval = Tss2_MU_TPMT_ECC_DECRYPT_Marshal(inScheme, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ if (rval) ++ return rval; ++#endif ++ ++ if (!sharedData1) { ++ rval = Tss2_MU_UINT16_Marshal(0, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ ++ } else { ++ ++ rval = Tss2_MU_TPM2B_DATA_Marshal(sharedData1, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ } ++ if (rval) ++ return rval; ++ ++ if (!sharedData2) { ++ rval = Tss2_MU_UINT16_Marshal(0, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ ++ } else { ++ ++ rval = Tss2_MU_TPM2B_DATA_Marshal(sharedData2, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ } ++ if (rval) ++ return rval; ++ ++ //ctx->decryptAllowed = 1; ++ ctx->decryptAllowed = 0; ++ ctx->encryptAllowed = 1; ++ ctx->authAllowed = 1; ++ ++ return CommonPrepareEpilogue(ctx); ++} ++ ++TSS2_RC Tss2_Sys_ECC_Decrypt_Complete( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPM2B_MAX_BUFFER *outData) ++{ ++ _TSS2_SYS_CONTEXT_BLOB *ctx = syscontext_cast(sysContext); ++ TSS2_RC rval; ++ ++ if (!ctx) ++ return TSS2_SYS_RC_BAD_REFERENCE; ++ ++ rval = CommonComplete(ctx); ++ if (rval) ++ return rval; ++ ++ return Tss2_MU_TPM2B_MAX_BUFFER_Unmarshal(ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData, outData); ++} ++ ++TSS2_RC Tss2_Sys_ECC_Decrypt( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPMI_DH_OBJECT keyHandle, ++ TSS2L_SYS_AUTH_COMMAND const *cmdAuthsArray, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2, ++ TPM2B_MAX_BUFFER *outData, ++ TSS2L_SYS_AUTH_RESPONSE *rspAuthsArray) ++{ ++ _TSS2_SYS_CONTEXT_BLOB *ctx = syscontext_cast(sysContext); ++ TSS2_RC rval; ++ ++ if (!inScheme) ++ return TSS2_SYS_RC_BAD_REFERENCE; ++ ++ rval = Tss2_Sys_ECC_Decrypt_Prepare(sysContext, keyHandle, inScheme, message, sharedData1, sharedData2); ++ if (rval) ++ return rval; ++ ++ rval = CommonOneCall(ctx, cmdAuthsArray, rspAuthsArray); ++ if (rval) ++ return rval; ++ ++ return Tss2_Sys_ECC_Decrypt_Complete(sysContext, outData); ++} +diff --git a/src/tss2-sys/api/Tss2_Sys_ECC_Encrypt.c b/src/tss2-sys/api/Tss2_Sys_ECC_Encrypt.c +new file mode 100644 +index 0000000..af02d4c +--- /dev/null ++++ b/src/tss2-sys/api/Tss2_Sys_ECC_Encrypt.c +@@ -0,0 +1,153 @@ ++/* SPDX-License-Identifier: BSD-2-Clause */ ++/***********************************************************************; ++ * Copyright (c) 2015 - 2017, Intel Corporation ++ * All rights reserved. ++ ***********************************************************************/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "tss2_tpm2_types.h" ++#include "tss2_mu.h" ++#include "sysapi_util.h" ++ ++TSS2_RC Tss2_Sys_ECC_Encrypt_Prepare( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPMI_DH_OBJECT keyHandle, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2) ++{ ++ _TSS2_SYS_CONTEXT_BLOB *ctx = syscontext_cast(sysContext); ++ TSS2_RC rval; ++ ++ if (!ctx || !inScheme) ++ return TSS2_SYS_RC_BAD_REFERENCE; ++ ++ rval = CommonPreparePrologue(ctx, TPM2_CC_ECC_Encrypt); ++ if (rval) ++ return rval; ++ ++ rval = Tss2_MU_UINT32_Marshal(keyHandle, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ if (rval) ++ return rval; ++ ++ /* Encryption is not possible because the exchange of parameter inScheme ++ and message in tcm2.0 spec. so disable decryptAllowed in the following code. ++ */ ++ rval = Tss2_MU_TPMT_ECC_DECRYPT_Marshal(inScheme, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ if (rval) ++ return rval; ++ ++ if (!message) { ++ ctx->decryptNull = 1; ++ ++ rval = Tss2_MU_UINT16_Marshal(0, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ } else { ++ ++ rval = Tss2_MU_TPM2B_MAX_BUFFER_Marshal(message, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ } ++ ++ if (rval) ++ return rval; ++ ++#if 0 ++ rval = Tss2_MU_TPMT_ECC_DECRYPT_Marshal(inScheme, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ if (rval) ++ return rval; ++#endif ++ ++ if (!sharedData1) { ++ rval = Tss2_MU_UINT16_Marshal(0, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ ++ } else { ++ ++ rval = Tss2_MU_TPM2B_DATA_Marshal(sharedData1, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ } ++ if (rval) ++ return rval; ++ ++ if (!sharedData2) { ++ rval = Tss2_MU_UINT16_Marshal(0, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ ++ } else { ++ ++ rval = Tss2_MU_TPM2B_DATA_Marshal(sharedData2, ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData); ++ } ++ if (rval) ++ return rval; ++ ++ //ctx->decryptAllowed = 1; ++ ctx->decryptAllowed = 0; ++ ctx->encryptAllowed = 1; ++ ctx->authAllowed = 1; ++ ++ return CommonPrepareEpilogue(ctx); ++} ++ ++TSS2_RC Tss2_Sys_ECC_Encrypt_Complete( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPM2B_MAX_BUFFER *outData) ++{ ++ _TSS2_SYS_CONTEXT_BLOB *ctx = syscontext_cast(sysContext); ++ TSS2_RC rval; ++ ++ if (!ctx) ++ return TSS2_SYS_RC_BAD_REFERENCE; ++ ++ rval = CommonComplete(ctx); ++ if (rval) ++ return rval; ++ ++ return Tss2_MU_TPM2B_MAX_BUFFER_Unmarshal(ctx->cmdBuffer, ++ ctx->maxCmdSize, ++ &ctx->nextData, outData); ++} ++ ++TSS2_RC Tss2_Sys_ECC_Encrypt( ++ TSS2_SYS_CONTEXT *sysContext, ++ TPMI_DH_OBJECT keyHandle, ++ TSS2L_SYS_AUTH_COMMAND const *cmdAuthsArray, ++ const TPMT_ECC_DECRYPT *inScheme, ++ const TPM2B_MAX_BUFFER *message, ++ const TPM2B_DATA *sharedData1, ++ const TPM2B_DATA *sharedData2, ++ TPM2B_MAX_BUFFER *outData, ++ TSS2L_SYS_AUTH_RESPONSE *rspAuthsArray) ++{ ++ _TSS2_SYS_CONTEXT_BLOB *ctx = syscontext_cast(sysContext); ++ TSS2_RC rval; ++ ++ if (!inScheme) ++ return TSS2_SYS_RC_BAD_REFERENCE; ++ ++ rval = Tss2_Sys_ECC_Encrypt_Prepare(sysContext, keyHandle, inScheme, message, sharedData1, sharedData2); ++ if (rval) ++ return rval; ++ ++ rval = CommonOneCall(ctx, cmdAuthsArray, rspAuthsArray); ++ if (rval) ++ return rval; ++ ++ return Tss2_Sys_ECC_Encrypt_Complete(sysContext, outData); ++} +diff --git a/src/tss2-sys/sysapi_util.c b/src/tss2-sys/sysapi_util.c +index 6e59da0..9824824 100644 +--- a/src/tss2-sys/sysapi_util.c ++++ b/src/tss2-sys/sysapi_util.c +@@ -288,7 +288,9 @@ static int GetNumHandles(TPM2_CC commandCode, bool req) + { TPM2_CC_AC_Send, 3, 0 }, + { TPM2_CC_Policy_AC_SendSelect, 1, 0 }, + { TPM2_CC_ACT_SetTimeout, 1, 0 }, +- { TPM2_CC_CertifyX509, 2, 0 } ++ { TPM2_CC_CertifyX509, 2, 0 }, ++ { TPM2_CC_ECC_Encrypt, 1, 0 }, ++ { TPM2_CC_ECC_Decrypt, 1, 0 } + }; + + uint8_t i; +-- +2.17.1 \ No newline at end of file diff --git a/add-bootstrap-file-from-upstream.patch b/add-bootstrap-file-from-upstream.patch new file mode 100644 index 0000000..be86399 --- /dev/null +++ b/add-bootstrap-file-from-upstream.patch @@ -0,0 +1,113 @@ +From ba537356b598515ede5d18952117a7f5d183549a Mon Sep 17 00:00:00 2001 +From: chench +Date: Fri, 29 Dec 2023 12:07:37 +0800 +Subject: [PATCH] add bootstrap file + +--- + bootstrap | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 95 insertions(+) + create mode 100755 bootstrap + +diff --git a/bootstrap b/bootstrap +new file mode 100755 +index 0000000..c25c9a3 +--- /dev/null ++++ b/bootstrap +@@ -0,0 +1,95 @@ ++#!/bin/sh ++set -e ++ ++#git describe --tags --always --dirty > VERSION ++ ++# generate list of source files for use in Makefile.am ++# if you add new source files, you must run ./bootstrap again ++src_listvar () { ++ basedir=$1 ++ suffix=$2 ++ var=$3 ++ ++ find "${basedir}" -name "${suffix}" | LC_ALL=C sort | tr '\n' ' ' | (printf "${var} = " && cat) ++ echo "" ++} ++ ++# remove source files from list if their usage depends on a configure option ++remove_src () { ++ files=$1 ++ shift ++ for x in $* ++ do ++ x=$(echo "$x" | sed 's/\//\\\//g') ++ files=$(echo $files | sed -e "s/$x//") ++ done ++ echo $files ++} ++ ++# generate list of eys source files for use in Makefile.am ++# if you add new source files, you must run ./bootstrap again ++# files after the var name will be elimenated from list list ++src_esys_listvar () { ++ basedir=$1; ++ shift; ++ suffix=$1 ++ shift; ++ var=$1 ++ shift; ++ ++ files=$(find "${basedir}" -name "${suffix}" | LC_ALL=C sort | tr '\n' ' ') ++ files=$(remove_src "${files}" $*) ++ printf "${var} = ${files}" ++ echo "" ++} ++ ++VARS_FILE=src_vars.mk ++AUTORECONF=${AUTORECONF:-autoreconf} ++ ++echo "Generating file lists: ${VARS_FILE}" ++( ++ src_listvar "src/util" "*.c" "UTIL_C" ++ src_listvar "src/util" "*.h" "UTIL_H" ++ printf "UTIL_SRC = \$(UTIL_C) \$(UTIL_H)\n" ++ ++ src_listvar "src/tss2-sys/" "*.c" "TSS2_SYS_C" ++ src_listvar "src/tss2-sys/" "*.h" "TSS2_SYS_H" ++ printf "TSS2_SYS_SRC = \$(TSS2_SYS_H) \$(TSS2_SYS_C)\n" ++ ++ src_esys_listvar "src/tss2-esys/" "*.h" "TSS2_ESYS_H" src/tss2-esys/esys_crypto_ossl.h src/tss2-esys/esys_crypto_mbed.h ++ src_esys_listvar "src/tss2-esys/" "*.c" "TSS2_ESYS_C" src/tss2-esys/esys_crypto_ossl.c src/tss2-esys/esys_crypto_mbed.c ++ printf "TSS2_ESYS_SRC = \$(TSS2_ESYS_H) \$(TSS2_ESYS_C)\n" ++ ++ src_listvar "src/tss2-fapi/" "*.h" "TSS2_FAPI_H" ++ src_listvar "src/tss2-fapi/" "*.c" "TSS2_FAPI_C" ++ printf "TSS2_FAPI_SRC = \$(TSS2_FAPI_H) \$(TSS2_FAPI_C)\n" ++ ++ src_listvar "src/tss2-mu" "*.c" "TSS2_MU_C" ++ src_listvar "src/tss2-mu" "*.h" "TSS2_MU_H" ++ printf "TSS2_MU_SRC = \$(TSS2_MU_C) \$(TSS2_MU_H)\n" ++ ++ src_listvar "src/tss2-rc" "*.c" "TSS2_RC_C" ++ src_listvar "src/tss2-rc" "*.h" "TSS2_RC_H" ++ printf "TSS2_RC_SRC = \$(TSS2_RC_C) \$(TSS2_RC_H)\n" ++ ++ src_listvar "src/tss2-policy" "*.c" "TSS2_POLICY_C" ++ src_listvar "src/tss2-policy" "*.h" "TSS2_POLICY_H" ++ printf "TSS2_POLICY_SRC = \$(TSS2_POLICY_C) \$(TSS2_POLICY_H)" ++) > ${VARS_FILE} ++ ++# Do not generate fuzz tests unless environment variable GEN_FUZZ is set to 1 ++rm -rf Makefile-fuzz-generated.am ++if test "${GEN_FUZZ}0" -eq 10; then ++ echo "Generating fuzz tests" ++ script/gen_fuzz.py ++else ++ touch Makefile-fuzz-generated.am ++fi ++ ++${AUTORECONF} --install --sym $@ ++ ++if grep "Invalid policy. Valid policies: git-directory, minor-version." configure >/dev/null; then ++ echo "ERROR: ax_is_release.m4 is outdated. ./configure will fail." ++ echo "Please download from http://ftpmirror.gnu.org/autoconf-archive/autoconf-archive-2019.01.06.tar.xz" ++ exit 1 ++fi +-- +2.27.0 diff --git a/backport-esys-add-SM4-algorithm-support.patch b/backport-esys-add-SM4-algorithm-support.patch new file mode 100644 index 0000000..1795283 --- /dev/null +++ b/backport-esys-add-SM4-algorithm-support.patch @@ -0,0 +1,688 @@ +From 0288dda4cec03e39a89f48333702a9301fb1ce80 Mon Sep 17 00:00:00 2001 +From: mayuanchen <94815698+mayuanchenma@users.noreply.github.com> +Date: Fri, 25 Nov 2022 18:59:26 +0800 +Subject: [PATCH] esys: add SM4 algorithm support. + +commit 75e68b77b5c2ddce424ae41f859616b4e8d2b240 upstream. + +Signed-off-by: mayuanchen <94815698+mayuanchenma@users.noreply.github.com> +Change-Id: I63f61888b92dcf06fb921aec08b40ca00c40ecdf +--- + configure.ac | 3 + + include/tss2/tss2_esys.h | 54 ++++++++++ + src/tss2-esys/esys_crypto.c | 53 ++++++++++ + src/tss2-esys/esys_crypto.h | 23 +++++ + src/tss2-esys/esys_crypto_mbed.h | 2 + + src/tss2-esys/esys_crypto_ossl.c | 158 +++++++++++++++++++++++++++++ + src/tss2-esys/esys_crypto_ossl.h | 29 ++++++ + src/tss2-esys/esys_iutil.c | 66 +++++++++++- + test/integration/esys-crypto.int.c | 6 ++ + test/unit/esys-crypto.c | 62 +++++++++++ + 10 files changed, 454 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index b655027..f6c254a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -191,6 +191,9 @@ AS_IF([test "x$enable_esys" = xyes], + AC_CHECK_LIB(crypto,[EVP_sm3], [ + AC_DEFINE([HAVE_EVP_SM3], [1], [Support EVP_sm3 in openssl])], + []) ++ AC_CHECK_LIB(crypto, [EVP_sm4_cfb128], [ ++ AC_DEFINE([HAVE_EVP_SM4_CFB], [1], [Support EVP_sm4_cfb in openssl])], ++ []) + TSS2_ESYS_CFLAGS_CRYPTO="$CRYPTO_CFLAGS" + TSS2_ESYS_LDFLAGS_CRYPTO="$CRYPTO_LIBS" + ], [test "x$with_crypto" = xmbed], [ +diff --git a/include/tss2/tss2_esys.h b/include/tss2/tss2_esys.h +index 6ef910e..6641f8d 100644 +--- a/include/tss2/tss2_esys.h ++++ b/include/tss2/tss2_esys.h +@@ -315,6 +315,58 @@ typedef TSS2_RC + uint8_t *iv, + void *userdata); + ++/** Encrypt data with SM4. ++ * ++ * @param[in] key key used for SM4. ++ * @param[in] tpm_sym_alg SM4 type in TSS2 notation (must be TPM2_ALG_SM4). ++ * @param[in] key_bits Key size in bits. ++ * @param[in] tpm_mode Block cipher mode of opertion in TSS2 notation (CFB). ++ * For parameter encryption only CFB can be used. ++ * @param[in,out] buffer Data to be encrypted. The encrypted date will be stored ++ * in this buffer. ++ * @param[in] buffer_size size of data to be encrypted. ++ * @param[in] iv The initialization vector. ++ * @param[in/out] userdata information. ++ * @retval TSS2_RC_SUCCESS on success ++ * @retval USER_DEFINED user defined errors on failure. ++ */ ++typedef TSS2_RC ++ (*ESYS_CRYPTO_SM4_ENCRYPT_FNP)( ++ uint8_t *key, ++ TPM2_ALG_ID tpm_sym_alg, ++ TPMI_SM4_KEY_BITS key_bits, ++ TPM2_ALG_ID tpm_mode, ++ uint8_t *buffer, ++ size_t buffer_size, ++ uint8_t *iv, ++ void *userdata); ++ ++/** Decrypt data with SM4. ++ * ++ * @param[in] key key used for SM4. ++ * @param[in] tpm_sym_alg SM4 type in TSS2 notation (must be TPM2_ALG_SM4). ++ * @param[in] key_bits Key size in bits. ++ * @param[in] tpm_mode Block cipher mode of opertion in TSS2 notation (CFB). ++ * For parameter encryption only CFB can be used. ++ * @param[in,out] buffer Data to be decrypted. The decrypted date will be stored ++ * in this buffer. ++ * @param[in] buffer_size size of data to be encrypted. ++ * @param[in] iv The initialization vector. ++ * @param[in/out] userdata information. ++ * @retval TSS2_RC_SUCCESS on success ++ * @retval USER_DEFINED user defined errors on failure. ++ */ ++typedef TSS2_RC ++ (*ESYS_CRYPTO_SM4_DECRYPT_FNP)( ++ uint8_t *key, ++ TPM2_ALG_ID tpm_sym_alg, ++ TPMI_SM4_KEY_BITS key_bits, ++ TPM2_ALG_ID tpm_mode, ++ uint8_t *buffer, ++ size_t buffer_size, ++ uint8_t *iv, ++ void *userdata); ++ + /** Encryption of a buffer using a public (RSA) key. + * + * Encrypting a buffer using a public key is used for example during +@@ -367,6 +419,8 @@ struct ESYS_CRYPTO_CALLBACKS { + ESYS_CRYPTO_GET_ECDH_POINT_FNP get_ecdh_point; + ESYS_CRYPTO_AES_ENCRYPT_FNP aes_encrypt; + ESYS_CRYPTO_AES_DECRYPT_FNP aes_decrypt; ++ ESYS_CRYPTO_SM4_ENCRYPT_FNP sm4_encrypt; ++ ESYS_CRYPTO_SM4_DECRYPT_FNP sm4_decrypt; + ESYS_CRYPTO_INIT_FNP init; + void *userdata; + }; +diff --git a/src/tss2-esys/esys_crypto.c b/src/tss2-esys/esys_crypto.c +index e54c95c..8cfc97a 100644 +--- a/src/tss2-esys/esys_crypto.c ++++ b/src/tss2-esys/esys_crypto.c +@@ -280,6 +280,46 @@ TSS2_RC iesys_crypto_aes_decrypt( + iv); + } + ++TSS2_RC iesys_crypto_sm4_encrypt( ++ ESYS_CRYPTO_CALLBACKS *crypto_cb, ++ uint8_t *key, ++ TPM2_ALG_ID tpm_sym_alg, ++ TPMI_SM4_KEY_BITS key_bits, ++ TPM2_ALG_ID tpm_mode, ++ uint8_t *buffer, ++ size_t buffer_size, ++ uint8_t *iv) ++{ ++ DO_CALLBACK(sm4_encrypt, ++ key, ++ tpm_sym_alg, ++ key_bits, ++ tpm_mode, ++ buffer, ++ buffer_size, ++ iv); ++} ++ ++TSS2_RC iesys_crypto_sm4_decrypt( ++ ESYS_CRYPTO_CALLBACKS *crypto_cb, ++ uint8_t *key, ++ TPM2_ALG_ID tpm_sym_alg, ++ TPMI_SM4_KEY_BITS key_bits, ++ TPM2_ALG_ID tpm_mode, ++ uint8_t *buffer, ++ size_t buffer_size, ++ uint8_t *iv) ++{ ++ DO_CALLBACK(sm4_decrypt, ++ key, ++ tpm_sym_alg, ++ key_bits, ++ tpm_mode, ++ buffer, ++ buffer_size, ++ iv); ++} ++ + /** Compute the command or response parameter hash. + * + * These hashes are needed for the computation of the HMAC used for the +@@ -782,6 +822,8 @@ TSS2_RC + crypto_cb->userdata = NULL; + crypto_cb->aes_decrypt = _iesys_crypto_aes_decrypt; + crypto_cb->aes_encrypt = _iesys_crypto_aes_encrypt; ++ crypto_cb->sm4_decrypt = _iesys_crypto_sm4_decrypt; ++ crypto_cb->sm4_encrypt = _iesys_crypto_sm4_encrypt; + crypto_cb->get_ecdh_point = _iesys_crypto_get_ecdh_point; + crypto_cb->hash_abort = _iesys_crypto_hash_abort; + crypto_cb->hash_finish = _iesys_crypto_hash_finish; +@@ -799,6 +841,17 @@ TSS2_RC + + TEST_AND_SET_CALLBACK(crypto_cb, user_cb, aes_decrypt); + TEST_AND_SET_CALLBACK(crypto_cb, user_cb, aes_encrypt); ++ // sm4 is optional ++ if (user_cb->sm4_encrypt) { ++ crypto_cb->sm4_encrypt = user_cb->sm4_encrypt; ++ } else { ++ crypto_cb->sm4_encrypt = _iesys_crypto_sm4_encrypt; ++ } ++ if (user_cb->sm4_decrypt) { ++ crypto_cb->sm4_decrypt = user_cb->sm4_decrypt; ++ } else { ++ crypto_cb->sm4_decrypt = _iesys_crypto_sm4_decrypt; ++ } + TEST_AND_SET_CALLBACK(crypto_cb, user_cb, get_ecdh_point); + TEST_AND_SET_CALLBACK(crypto_cb, user_cb, get_random2b); + TEST_AND_SET_CALLBACK(crypto_cb, user_cb, rsa_pk_encrypt); +diff --git a/src/tss2-esys/esys_crypto.h b/src/tss2-esys/esys_crypto.h +index 8798bc6..c6efac1 100644 +--- a/src/tss2-esys/esys_crypto.h ++++ b/src/tss2-esys/esys_crypto.h +@@ -16,6 +16,8 @@ + #else + #define _iesys_crypto_aes_decrypt NULL; + #define _iesys_crypto_aes_encrypt NULL; ++#define _iesys_crypto_sm4_decrypt NULL; ++#define _iesys_crypto_sm4_encrypt NULL; + #define _iesys_crypto_get_ecdh_point NULL; + #define _iesys_crypto_hash_abort NULL; + #define _iesys_crypto_hash_finish NULL; +@@ -35,6 +37,7 @@ extern "C" { + #endif + + #define AES_BLOCK_SIZE_IN_BYTES 16 ++#define SM4_BLOCK_SIZE_IN_BYTES 16 + + TSS2_RC iesys_crypto_hash_get_digest_size(TPM2_ALG_ID hashAlg, size_t *size); + +@@ -163,6 +166,26 @@ TSS2_RC iesys_crypto_aes_decrypt( + size_t buffer_size, + uint8_t *iv); + ++TSS2_RC iesys_crypto_sm4_encrypt( ++ ESYS_CRYPTO_CALLBACKS *crypto_cb, ++ uint8_t *key, ++ TPM2_ALG_ID tpm_sym_alg, ++ TPMI_SM4_KEY_BITS key_bits, ++ TPM2_ALG_ID tpm_mode, ++ uint8_t *buffer, ++ size_t buffer_size, ++ uint8_t *iv); ++ ++TSS2_RC iesys_crypto_sm4_decrypt( ++ ESYS_CRYPTO_CALLBACKS *crypto_cb, ++ uint8_t *key, ++ TPM2_ALG_ID tpm_sym_alg, ++ TPMI_SM4_KEY_BITS key_bits, ++ TPM2_ALG_ID tpm_mode, ++ uint8_t *buffer, ++ size_t buffer_size, ++ uint8_t *iv); ++ + TSS2_RC iesys_crypto_authHmac( + ESYS_CRYPTO_CALLBACKS *crypto_cb, + TPM2_ALG_ID alg, +diff --git a/src/tss2-esys/esys_crypto_mbed.h b/src/tss2-esys/esys_crypto_mbed.h +index 24b1d8e..40a976b 100644 +--- a/src/tss2-esys/esys_crypto_mbed.h ++++ b/src/tss2-esys/esys_crypto_mbed.h +@@ -120,6 +120,8 @@ TSS2_RC iesys_cryptmbed_init(void *userdata); + #define _iesys_crypto_get_ecdh_point iesys_cryptmbed_get_ecdh_point + #define _iesys_crypto_aes_encrypt iesys_cryptmbed_sym_aes_encrypt + #define _iesys_crypto_aes_decrypt iesys_cryptmbed_sym_aes_decrypt ++#define _iesys_crypto_sm4_encrypt NULL ++#define _iesys_crypto_sm4_decrypt NULL + + #define _iesys_crypto_init iesys_cryptmbed_init + +diff --git a/src/tss2-esys/esys_crypto_ossl.c b/src/tss2-esys/esys_crypto_ossl.c +index 89d312f..a92ecc4 100644 +--- a/src/tss2-esys/esys_crypto_ossl.c ++++ b/src/tss2-esys/esys_crypto_ossl.c +@@ -1212,6 +1212,164 @@ iesys_cryptossl_sym_aes_decrypt(uint8_t * key, + return r; + } + ++#if HAVE_EVP_SM4_CFB && !defined(OPENSSL_NO_SM4) ++/** Encrypt data with SM4. ++ * ++ * @param[in] key key used for SM4. ++ * @param[in] tpm_sym_alg SM4 type in TSS2 notation (must be TPM2_ALG_SM4). ++ * @param[in] key_bits Key size in bits. ++ * @param[in] tpm_mode Block cipher mode of opertion in TSS2 notation (CFB). ++ * For parameter encryption only CFB can be used. ++ * @param[in,out] buffer Data to be encrypted. The encrypted date will be stored ++ * in this buffer. ++ * @param[in] buffer_size size of data to be encrypted. ++ * @param[in] iv The initialization vector. ++ * @retval TSS2_RC_SUCCESS on success, or TSS2_ESYS_RC_BAD_VALUE and ++ * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters, ++ * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library. ++ */ ++TSS2_RC ++iesys_cryptossl_sym_sm4_encrypt(uint8_t * key, ++ TPM2_ALG_ID tpm_sym_alg, ++ TPMI_SM4_KEY_BITS key_bits, ++ TPM2_ALG_ID tpm_mode, ++ uint8_t * buffer, ++ size_t buffer_size, ++ uint8_t * iv, ++ void *userdata) ++{ ++ UNUSED(userdata); ++ ++ TSS2_RC r = TSS2_RC_SUCCESS; ++ const EVP_CIPHER *cipher_alg = NULL; ++ EVP_CIPHER_CTX *ctx = NULL; ++ int cipher_len; ++ ++ if (key == NULL || buffer == NULL) { ++ return_error(TSS2_ESYS_RC_BAD_REFERENCE, "Bad reference"); ++ } ++ ++ LOGBLOB_TRACE(buffer, buffer_size, "IESYS SM4 input"); ++ ++ if (key_bits == 128 && tpm_mode == TPM2_ALG_CFB) ++ cipher_alg = EVP_sm4_cfb128(); ++ else { ++ goto_error(r, TSS2_ESYS_RC_BAD_VALUE, ++ "SM4 algorithm not implemented or illegal mode (CFB expected).", ++ cleanup); ++ } ++ ++ if (tpm_sym_alg != TPM2_ALG_SM4) { ++ goto_error(r, TSS2_ESYS_RC_BAD_VALUE, ++ "SM4 encrypt called with wrong algorithm.", cleanup); ++ } ++ ++ /* Create and initialize the context */ ++ if(!(ctx = EVP_CIPHER_CTX_new())) { ++ goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, ++ "Initialize cipher context", cleanup); ++ } ++ ++ if (1 != EVP_EncryptInit(ctx, cipher_alg, key, iv)) { ++ goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, ++ "Initialize cipher operation", cleanup); ++ } ++ ++ /* Perform the encryption */ ++ if (1 != EVP_EncryptUpdate(ctx, buffer, &cipher_len, buffer, buffer_size)) { ++ goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Encrypt update", cleanup); ++ } ++ ++ if (1 != EVP_EncryptFinal(ctx, buffer, &cipher_len)) { ++ goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Encrypt final", cleanup); ++ } ++ LOGBLOB_TRACE(buffer, buffer_size, "IESYS SM4 output"); ++ ++cleanup: ++ ++ OSSL_FREE(ctx,EVP_CIPHER_CTX); ++ ++ return r; ++} ++ ++/** Decrypt data with SM4. ++ * ++ * @param[in] key key used for SM4. ++ * @param[in] tpm_sym_alg SM4 type in TSS2 notation (must be TPM2_ALG_SM4). ++ * @param[in] key_bits Key size in bits. ++ * @param[in] tpm_mode Block cipher mode of opertion in TSS2 notation (CFB). ++ * For parameter encryption only CFB can be used. ++ * @param[in,out] buffer Data to be decrypted. The decrypted date will be stored ++ * in this buffer. ++ * @param[in] buffer_size size of data to be encrypted. ++ * @param[in] iv The initialization vector. ++ * @retval TSS2_RC_SUCCESS on success, or TSS2_ESYS_RC_BAD_VALUE and ++ * @retval TSS2_ESYS_RC_BAD_REFERENCE for invalid parameters, ++ * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library. ++ */ ++TSS2_RC ++iesys_cryptossl_sym_sm4_decrypt(uint8_t * key, ++ TPM2_ALG_ID tpm_sym_alg, ++ TPMI_SM4_KEY_BITS key_bits, ++ TPM2_ALG_ID tpm_mode, ++ uint8_t * buffer, ++ size_t buffer_size, ++ uint8_t * iv, ++ void *userdata) ++{ ++ UNUSED(userdata); ++ ++ TSS2_RC r = TSS2_RC_SUCCESS; ++ const EVP_CIPHER *cipher_alg = NULL; ++ EVP_CIPHER_CTX *ctx = NULL; ++ int cipher_len = 0; ++ ++ if (key == NULL || buffer == NULL) { ++ return_error(TSS2_ESYS_RC_BAD_REFERENCE, "Bad reference"); ++ } ++ ++ if (tpm_sym_alg != TPM2_ALG_SM4) { ++ goto_error(r, TSS2_ESYS_RC_BAD_VALUE, ++ "SM4 decrypt called with wrong algorithm.", cleanup); ++ } ++ ++ if (key_bits == 128 && tpm_mode == TPM2_ALG_CFB) ++ cipher_alg = EVP_sm4_cfb128(); ++ else { ++ goto_error(r, TSS2_ESYS_RC_BAD_VALUE, ++ "SM4 algorithm not implemented or illegal mode (CFB expected).", ++ cleanup); ++ } ++ ++ /* Create and initialize the context */ ++ if(!(ctx = EVP_CIPHER_CTX_new())) { ++ goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, ++ "Initialize cipher context", cleanup); ++ } ++ ++ LOGBLOB_TRACE(buffer, buffer_size, "IESYS SM4 input"); ++ ++ if (1 != EVP_DecryptInit(ctx, cipher_alg, key, iv)) { ++ goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, ++ "Initialize cipher operation", cleanup); ++ } ++ ++ /* Perform the decryption */ ++ if (1 != EVP_DecryptUpdate(ctx, buffer, &cipher_len, buffer, buffer_size)) { ++ goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Encrypt update", cleanup); ++ } ++ ++ if (1 != EVP_DecryptFinal(ctx, buffer, &cipher_len)) { ++ goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Encrypt final", cleanup); ++ } ++ LOGBLOB_TRACE(buffer, buffer_size, "IESYS SM4 output"); ++ ++cleanup: ++ ++ OSSL_FREE(ctx,EVP_CIPHER_CTX); ++ return r; ++} ++#endif + + /** Initialize OpenSSL crypto backend. + * +diff --git a/src/tss2-esys/esys_crypto_ossl.h b/src/tss2-esys/esys_crypto_ossl.h +index ae3c33a..d8e84d6 100644 +--- a/src/tss2-esys/esys_crypto_ossl.h ++++ b/src/tss2-esys/esys_crypto_ossl.h +@@ -109,6 +109,28 @@ TSS2_RC iesys_cryptossl_sym_aes_decrypt( + uint8_t *iv, + void *userdata); + ++#if HAVE_EVP_SM4_CFB && !defined(OPENSSL_NO_SM4) ++TSS2_RC iesys_cryptossl_sym_sm4_encrypt( ++ uint8_t *key, ++ TPM2_ALG_ID tpm_sym_alg, ++ TPMI_SM4_KEY_BITS key_bits, ++ TPM2_ALG_ID tpm_mode, ++ uint8_t *dst, ++ size_t dst_size, ++ uint8_t *iv, ++ void *userdata); ++ ++TSS2_RC iesys_cryptossl_sym_sm4_decrypt( ++ uint8_t *key, ++ TPM2_ALG_ID tpm_sym_alg, ++ TPMI_SM4_KEY_BITS key_bits, ++ TPM2_ALG_ID tpm_mode, ++ uint8_t *dst, ++ size_t dst_size, ++ uint8_t *iv, ++ void *userdata); ++#endif ++ + TSS2_RC iesys_cryptossl_get_ecdh_point( + TPM2B_PUBLIC *key, + size_t max_out_size, +@@ -122,6 +144,13 @@ TSS2_RC iesys_cryptossl_get_ecdh_point( + #define _iesys_crypto_get_ecdh_point iesys_cryptossl_get_ecdh_point + #define _iesys_crypto_aes_encrypt iesys_cryptossl_sym_aes_encrypt + #define _iesys_crypto_aes_decrypt iesys_cryptossl_sym_aes_decrypt ++#if HAVE_EVP_SM4_CFB && !defined(OPENSSL_NO_SM4) ++#define _iesys_crypto_sm4_encrypt iesys_cryptossl_sym_sm4_encrypt ++#define _iesys_crypto_sm4_decrypt iesys_cryptossl_sym_sm4_decrypt ++#else ++#define _iesys_crypto_sm4_encrypt NULL ++#define _iesys_crypto_sm4_decrypt NULL ++#endif + + TSS2_RC iesys_cryptossl_init(void *userdata); + +diff --git a/src/tss2-esys/esys_iutil.c b/src/tss2-esys/esys_iutil.c +index c8346b3..79e6143 100644 +--- a/src/tss2-esys/esys_iutil.c ++++ b/src/tss2-esys/esys_iutil.c +@@ -745,6 +745,31 @@ iesys_encrypt_param(ESYS_CONTEXT * esys_context, + &encrypt_buffer[0], paramSize, + &symKey[aes_off]); + return_if_error(r, "AES encryption not possible"); ++ } else if (symDef->algorithm == TPM2_ALG_SM4) { ++ /* SM4 encryption with key derived with KDFa */ ++ if (symDef->mode.sm4 != TPM2_ALG_CFB) { ++ return_error(TSS2_ESYS_RC_BAD_VALUE, ++ "Invalid symmetric mode (must be CFB)"); ++ } ++ r = iesys_crypto_KDFa(&esys_context->crypto_backend, rsrc_session->authHash, ++ &rsrc_session->sessionValue[0], ++ rsrc_session->sizeSessionValue, "CFB", ++ &rsrc_session->nonceCaller, ++ &rsrc_session->nonceTPM, ++ symDef->keyBits.sm4 + SM4_BLOCK_SIZE_IN_BYTES * 8, ++ NULL, &symKey[0], FALSE); ++ return_if_error(r, "while computing KDFa"); ++ ++ size_t sm4_off = ( symDef->keyBits.sm4 + 7) / 8; ++ r = iesys_crypto_sm4_encrypt( ++ &esys_context->crypto_backend, ++ &symKey[0], ++ symDef->algorithm, ++ symDef->keyBits.sm4, ++ symDef->mode.sm4, ++ &encrypt_buffer[0], paramSize, ++ &symKey[sm4_off]); ++ return_if_error(r, "SM4 encryption not possible"); + } + /* XOR obfuscation of parameter */ + else if (symDef->algorithm == TPM2_ALG_XOR) { +@@ -760,7 +785,7 @@ iesys_encrypt_param(ESYS_CONTEXT * esys_context, + + } else { + return_error(TSS2_ESYS_RC_BAD_VALUE, +- "Invalid symmetric algorithm (should be XOR or AES)"); ++ "Invalid symmetric algorithm (should be XOR, AES, or SM4)"); + } + r = Tss2_Sys_SetDecryptParam(esys_context->sys, paramSize, + &encrypt_buffer[0]); +@@ -848,6 +873,43 @@ iesys_decrypt_param(ESYS_CONTEXT * esys_context) + &symKey[aes_off]); + return_if_error(r, "Decryption error"); + ++ r = Tss2_Sys_SetEncryptParam(esys_context->sys, p2BSize, &plaintext[0]); ++ return_if_error(r, "Setting plaintext"); ++ } else if (symDef->algorithm == TPM2_ALG_SM4) { ++ /* Parameter decryption with a symmetric SM4 key derived by KDFa */ ++ if (symDef->mode.sm4 != TPM2_ALG_CFB) { ++ return_error(TSS2_ESYS_RC_BAD_VALUE, ++ "Invalid symmetric mode (must be CFB)"); ++ } ++ LOGBLOB_DEBUG(&rsrc_session->sessionKey.buffer[0], ++ rsrc_session->sessionKey.size, ++ "IESYS encrypt session key"); ++ ++ r = iesys_crypto_KDFa(&esys_context->crypto_backend, rsrc_session->authHash, ++ &rsrc_session->sessionValue[0], ++ rsrc_session->sizeSessionValue, ++ "CFB", &rsrc_session->nonceTPM, ++ &rsrc_session->nonceCaller, ++ symDef->keyBits.sm4 ++ + SM4_BLOCK_SIZE_IN_BYTES * 8, NULL, ++ &symKey[0], FALSE); ++ return_if_error(r, "KDFa error"); ++ LOGBLOB_DEBUG(&symKey[0], ++ ((symDef->keyBits.sm4 + ++ SM4_BLOCK_SIZE_IN_BYTES * 8) + 7) / 8, ++ "IESYS encrypt KDFa key"); ++ ++ size_t sm4_off = ( symDef->keyBits.sm4 + 7) / 8; ++ r = iesys_crypto_sm4_decrypt( ++ &esys_context->crypto_backend, ++ &symKey[0], ++ symDef->algorithm, ++ symDef->keyBits.sm4, ++ symDef->mode.sm4, ++ &plaintext[0], p2BSize, ++ &symKey[sm4_off]); ++ return_if_error(r, "Decryption error"); ++ + r = Tss2_Sys_SetEncryptParam(esys_context->sys, p2BSize, &plaintext[0]); + return_if_error(r, "Setting plaintext"); + } else if (symDef->algorithm == TPM2_ALG_XOR) { +@@ -866,7 +928,7 @@ iesys_decrypt_param(ESYS_CONTEXT * esys_context) + return_if_error(r, "Setting plaintext"); + } else { + return_error(TSS2_ESYS_RC_BAD_VALUE, +- "Invalid symmetric algorithm (should be XOR or AES)"); ++ "Invalid symmetric algorithm (should be XOR, AES, or SM4)"); + } + return TSS2_RC_SUCCESS; + } +diff --git a/test/integration/esys-crypto.int.c b/test/integration/esys-crypto.int.c +index 1618e9c..7969f54 100644 +--- a/test/integration/esys-crypto.int.c ++++ b/test/integration/esys-crypto.int.c +@@ -61,6 +61,8 @@ test_invoke_esys(ESYS_CONTEXT *esys_context) + + CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, aes_decrypt); + CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, aes_encrypt); ++ CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, sm4_decrypt); ++ CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, sm4_encrypt); + CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, get_ecdh_point); + CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, get_random2b); + CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, rsa_pk_encrypt); +@@ -68,6 +70,8 @@ test_invoke_esys(ESYS_CONTEXT *esys_context) + ESYS_CRYPTO_CALLBACKS callbacks = { + .aes_decrypt = TEST_FN_PTR, + .aes_encrypt = TEST_FN_PTR, ++ .sm4_decrypt = TEST_FN_PTR, ++ .sm4_encrypt = TEST_FN_PTR, + .get_ecdh_point = TEST_FN_PTR, + .get_random2b = TEST_FN_PTR, + .rsa_pk_encrypt = TEST_FN_PTR, +@@ -123,6 +127,8 @@ test_invoke_esys(ESYS_CONTEXT *esys_context) + + CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, aes_decrypt); + CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, aes_encrypt); ++ CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, sm4_decrypt); ++ CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, sm4_encrypt); + CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, get_ecdh_point); + CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, get_random2b); + CHECK_BACKEND_FN_NOT_TEST(esys_context->crypto_backend, rsa_pk_encrypt); +diff --git a/test/unit/esys-crypto.c b/test/unit/esys-crypto.c +index b47cfdd..4901b91 100644 +--- a/test/unit/esys-crypto.c ++++ b/test/unit/esys-crypto.c +@@ -258,6 +258,61 @@ check_aes_encrypt(void **state) + assert_int_equal (rc, TSS2_ESYS_RC_BAD_VALUE); + } + ++#if HAVE_EVP_SM4_CFB && !defined(OPENSSL_NO_SM4) ++static void ++check_sm4_encrypt(void **state) ++{ ++ TSS2_RC rc; ++ uint8_t key[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; ++ uint8_t buffer[5] = { 1, 2, 3, 4, 5 }; ++ size_t size = sizeof(buffer); ++ ++ ESYS_CRYPTO_CALLBACKS crypto_cb = { 0 }; ++ rc = iesys_initialize_crypto_backend(&crypto_cb, NULL); ++ assert_int_equal (rc, TSS2_RC_SUCCESS); ++ ++ rc = iesys_crypto_sm4_encrypt(&crypto_cb, NULL, TPM2_ALG_SM4, 128, TPM2_ALG_CFB, ++ &buffer[0], size, &key[0]); ++ assert_int_equal (rc, TSS2_ESYS_RC_BAD_REFERENCE); ++ ++ rc = iesys_crypto_sm4_encrypt(&crypto_cb, &key[0], 0, 128, TPM2_ALG_CFB, ++ &buffer[0], size, &key[0]); ++ assert_int_equal (rc, TSS2_ESYS_RC_BAD_VALUE); ++ ++ rc = iesys_crypto_sm4_encrypt(&crypto_cb, &key[0], TPM2_ALG_SM4, 128, 0, ++ &buffer[0], size, &key[0]); ++ assert_int_equal (rc, TSS2_ESYS_RC_BAD_VALUE); ++ ++ rc = iesys_crypto_sm4_encrypt(&crypto_cb, &key[0], TPM2_ALG_SM4, 999, TPM2_ALG_CFB, ++ &buffer[0], size, &key[0]); ++ assert_int_equal (rc, TSS2_ESYS_RC_BAD_VALUE); ++ ++ rc = iesys_crypto_sm4_encrypt(&crypto_cb, &key[0], TPM2_ALG_SM4, 128, TPM2_ALG_CFB, ++ &buffer[0], size, &key[0]); ++ assert_int_equal (rc, TSS2_RC_SUCCESS); ++ ++ rc = iesys_crypto_sm4_decrypt(&crypto_cb, NULL, TPM2_ALG_SM4, 128, TPM2_ALG_CFB, ++ &buffer[0], size, &key[0]); ++ assert_int_equal (rc, TSS2_ESYS_RC_BAD_REFERENCE); ++ ++ rc = iesys_crypto_sm4_decrypt(&crypto_cb, &key[0], 0, 128, TPM2_ALG_CFB, ++ &buffer[0], size, &key[0]); ++ assert_int_equal (rc, TSS2_ESYS_RC_BAD_VALUE); ++ ++ rc = iesys_crypto_sm4_decrypt(&crypto_cb, &key[0], TPM2_ALG_SM4, 128, 0, ++ &buffer[0], size, &key[0]); ++ assert_int_equal (rc, TSS2_ESYS_RC_BAD_VALUE); ++ ++ rc = iesys_crypto_sm4_decrypt(&crypto_cb, &key[0], TPM2_ALG_SM4, 999, TPM2_ALG_CFB, ++ &buffer[0], size, &key[0]); ++ assert_int_equal (rc, TSS2_ESYS_RC_BAD_VALUE); ++ ++ rc = iesys_crypto_sm4_decrypt(&crypto_cb, &key[0], TPM2_ALG_SM4, 128, TPM2_ALG_CFB, ++ &buffer[0], size, &key[0]); ++ assert_int_equal (rc, TSS2_RC_SUCCESS); ++} ++#endif ++ + static void + check_free(void **state) + { +@@ -320,6 +375,8 @@ static void test_backend_set(void **state) { + + CHECK_BACKEND_FN(crypto_cb, aes_decrypt); + CHECK_BACKEND_FN(crypto_cb, aes_encrypt); ++ CHECK_BACKEND_FN(crypto_cb, sm4_decrypt); ++ CHECK_BACKEND_FN(crypto_cb, sm4_encrypt); + CHECK_BACKEND_FN(crypto_cb, get_ecdh_point); + CHECK_BACKEND_FN(crypto_cb, get_random2b); + CHECK_BACKEND_FN(crypto_cb, rsa_pk_encrypt); +@@ -328,6 +385,8 @@ static void test_backend_set(void **state) { + ESYS_CRYPTO_CALLBACKS user_cb = { + .aes_decrypt = (void *)0xBADCC0DE, + .aes_encrypt = (void *)0xBADCC0DE, ++ .sm4_decrypt = (void *)0xBADCC0DE, ++ .sm4_encrypt = (void *)0xBADCC0DE, + .get_ecdh_point = (void *)0xBADCC0DE, + .get_random2b = (void *)0xBADCC0DE, + .rsa_pk_encrypt = (void *)0xBADCC0DE, +@@ -377,6 +436,9 @@ main(int argc, char *argv[]) + cmocka_unit_test(check_random), + cmocka_unit_test(check_pk_encrypt), + cmocka_unit_test(check_aes_encrypt), ++#if HAVE_EVP_SM4_CFB && !defined(OPENSSL_NO_SM4) ++ cmocka_unit_test(check_sm4_encrypt), ++#endif + cmocka_unit_test(check_free), + cmocka_unit_test(check_get_sys_context), + cmocka_unit_test(test_backend_set) +-- +2.17.1 diff --git a/tpm2-tss.spec b/tpm2-tss.spec index b57c08b..6c2fc8f 100644 --- a/tpm2-tss.spec +++ b/tpm2-tss.spec @@ -1,6 +1,6 @@ Name: tpm2-tss Version: 4.0.1 -Release: 2 +Release: 3 Summary: TPM2.0 Software Stack License: BSD URL: https://github.com/tpm2-software/tpm2-tss @@ -8,6 +8,10 @@ Source0: https://github.com/tpm2-software/tpm2-tss/releases/download/%{ver Patch0001: backport-FAPI-Skip-test-fapi-fix-provisioning-with-template-i.patch Patch0002: backport-CVE-2024-29040-FAPI-Fix-check-of-magic-.patch +Patch0003: backport-esys-add-SM4-algorithm-support.patch +Patch0004: Hygon-Add-support-for-udev-to-create-tcm-de.patch +Patch0005: Hygon-add-ecc-encrypt-decrypt-support.patch +Patch0006: add-bootstrap-file-from-upstream.patch BuildRequires: gcc-c++ autoconf-archive libtool pkgconfig systemd libgcrypt-devel openssl-devel doxygen json-c-devel libcurl-devel util-linux-devel BuildRequires: curl >= 7.80.0 libcmocka-devel iproute uthash-devel swtpm @@ -31,6 +35,7 @@ Obsoletes: %{name}-static %autosetup -n %{name}-%{version} -p1 %build +./bootstrap %configure --disable-static --disable-silent-rules --with-udevrulesdir=%{_udevrulesdir} --with-udevrulesprefix=80- \ --with-runstatedir=%{_rundir} --with-tmpfilesdir=%{_tmpfilesdir} --with-sysusersdir=%{_sysusersdir} \ --enable-unit --enable-integration @@ -74,6 +79,15 @@ make check %{_mandir}/man*/* %changelog +* Fri Aug 2 2024 chench - 4.0.1-3 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:add SM4 algorithm support + - Add support for udev to create tcm devices + - add ecc encrypt/decrypt support + - add bootstrap file from upstream + * Wed May 8 2024 jinlun - 4.0.1-2 - fix CVE-2024-29040 and fix test check error -- Gitee From 15e36aaa46d9412c613a9c7e706c5de919c47045 Mon Sep 17 00:00:00 2001 From: "Shencb@123" <1944340417@qq.com> Date: Tue, 3 Sep 2024 12:45:17 +0800 Subject: [PATCH 2/2] 11 --- Hygon-add-ecc-encrypt-decrypt-support.patch | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Hygon-add-ecc-encrypt-decrypt-support.patch b/Hygon-add-ecc-encrypt-decrypt-support.patch index 3006536..0135936 100644 --- a/Hygon-add-ecc-encrypt-decrypt-support.patch +++ b/Hygon-add-ecc-encrypt-decrypt-support.patch @@ -185,17 +185,6 @@ diff --git a/include/tss2/tss2_tpm2_types.h b/include/tss2/tss2_tpm2_types.h index 1ce737e..c5f53d9 100644 --- a/include/tss2/tss2_tpm2_types.h +++ b/include/tss2/tss2_tpm2_types.h -@@ -249,7 +249,9 @@ typedef UINT32 TPM2_CC; - #define TPM2_CC_Policy_AC_SendSelect ((TPM2_CC) 0x00000196) - #define TPM2_CC_CertifyX509 ((TPM2_CC) 0x00000197) - #define TPM2_CC_ACT_SetTimeout ((TPM2_CC) 0x00000198) --#define TPM2_CC_LAST ((TPM2_CC) 0x00000198) -+#define TPM2_CC_ECC_Encrypt ((TPM2_CC) 0x00000199) -+#define TPM2_CC_ECC_Decrypt ((TPM2_CC) 0x0000019a) -+#define TPM2_CC_LAST ((TPM2_CC) 0x0000019a) - #define TPM2_CC_Vendor_TCG_Test ((TPM2_CC) 0x20000000) - - /* Definition of Types for Documentation Clarity */ @@ -1630,6 +1632,15 @@ struct TPM2B_PRIVATE_KEY_RSA { BYTE buffer[TPM2_MAX_RSA_KEY_BYTES/2 * 5]; }; -- Gitee