From 8116e7add58e28a50addeaa76c5e00ad39ff1025 Mon Sep 17 00:00:00 2001 From: fly2x Date: Fri, 15 Dec 2023 09:16:04 +0800 Subject: [PATCH] Add SM3 and SM4 support Signed-off-by: fly2x --- libtpms.spec | 6 +- tpm2-Add-SM3-and-SM4-Support.patch | 852 +++++++++++++++++++++++++++++ 2 files changed, 857 insertions(+), 1 deletion(-) create mode 100644 tpm2-Add-SM3-and-SM4-Support.patch diff --git a/libtpms.spec b/libtpms.spec index 1a4979b..b250d86 100644 --- a/libtpms.spec +++ b/libtpms.spec @@ -6,7 +6,7 @@ %define name libtpms %define versionx 0.7.3 -%define release 8 +%define release 9 # Valid crypto subsystems are 'freebl' and 'openssl' %if "%{?crypto_subsystem}" == "" @@ -41,6 +41,7 @@ Patch11: tpm2-Reset-TPM2B-buffer-sizes-after-test-fails-for-v.patch Patch12: tpm2-Add-maxSize-parameter-to-TPM2B_Marshal-for-sani.patch Patch13: tpm2-Restore-original-value-if-unmarsalled-value-was.patch Patch14: tpm2-Check-size-of-buffer-before-accessing-it-CVE-20.patch +Patch15: tpm2-Add-SM3-and-SM4-Support.patch %if "%{crypto_subsystem}" == "openssl" BuildRequires: openssl-devel @@ -133,6 +134,9 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/libtpms.la %postun -p /sbin/ldconfig %changelog +* Wed Dec 15 2023 fly2x - 0.7.3-9 +- Add SM3 and SM4 support + * Wed May 17 2023 jiangfangjie - 0.7.3-8 - fix CVE-2023--1018 and CVE-2023-1017 diff --git a/tpm2-Add-SM3-and-SM4-Support.patch b/tpm2-Add-SM3-and-SM4-Support.patch new file mode 100644 index 0000000..cb0b9cd --- /dev/null +++ b/tpm2-Add-SM3-and-SM4-Support.patch @@ -0,0 +1,852 @@ +From ce3616804b84ce30563a3e1cb03d1878c6b31355 Mon Sep 17 00:00:00 2001 +From: fly2x +Date: Thu, 14 Dec 2023 19:55:14 +0800 +Subject: [PATCH] tpm2 add SM3 and SM4 support + +--- + configure.ac | 10 ++ + src/tpm2/AlgorithmTests.c | 7 +- + src/tpm2/HashTestData.h | 9 ++ + src/tpm2/Marshal.c | 9 ++ + src/tpm2/Marshal_fp.h | 4 + + src/tpm2/NVMarshal.c | 141 ++++++++++++++++++++++++ + src/tpm2/SymmetricTest.h | 4 +- + src/tpm2/SymmetricTestData.h | 45 ++++++++ + src/tpm2/Unmarshal_fp.h | 4 + + src/tpm2/crypto/CryptHash.h | 3 + + src/tpm2/crypto/CryptSym.h | 5 + + src/tpm2/crypto/openssl/CryptCmac.c | 10 ++ + src/tpm2/crypto/openssl/CryptHash.c | 8 ++ + src/tpm2/crypto/openssl/CryptSym.c | 18 +++ + src/tpm2/crypto/openssl/Helpers.c | 127 ++++++++++++++++++++- + src/tpm2/crypto/openssl/TpmToOsslHash.h | 41 ++++++- + src/tpm2/crypto/openssl/TpmToOsslSym.h | 40 ++++++- + 17 files changed, 474 insertions(+), 11 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 0c57ef3..e85c5fa 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -237,6 +237,15 @@ AC_ARG_ENABLE([test-coverage], + AS_HELP_STRING([--enable-test-coverage], [Enable test coverage flags]), + [COVERAGE_CFLAGS="-fprofile-arcs -ftest-coverage" COVERAGE_LDFLAGS="-fprofile-arcs"]) + ++AC_ARG_WITH([openssl-SM], ++ AS_HELP_STRING([--with-openssl-SM], [libtpms supports SM3 and SM4, default not support]), [with_openssl_SM=yes], [with_openssl_SM=no] ++) ++ ++AS_IF([test "x$with_openssl_SM" != "xno"], [ ++ AC_DEFINE([ALG_SM3_256], [1], [1 denotes to support SM3, and 0 not support]) ++ AC_DEFINE([ALG_SM4], [1], [1 denotes to support SM4, and 0 not support]) ++]) ++ + LT_INIT + AC_PROG_CC + AC_PROG_CXX +@@ -316,6 +325,7 @@ echo "Version to build : $PACKAGE_VERSION" + echo "Crypto library : $cryptolib" + echo "Debug build : $enable_debug" + echo "With TPM2 support : $with_tpm2" ++echo "With SM3 and SM4 support: $with_openssl_SM" + echo "HAVE_VERSION_SCRIPT : $have_version_script" + echo "Use openssl crypto for : $use_openssl_functions_for" + echo +diff --git a/src/tpm2/AlgorithmTests.c b/src/tpm2/AlgorithmTests.c +index d30c6f8..8749ec2 100644 +--- a/src/tpm2/AlgorithmTests.c ++++ b/src/tpm2/AlgorithmTests.c +@@ -860,7 +860,7 @@ TestAlgorithm( + #if ALG_SM4 + // if SM4 is implemented, its test is like other block ciphers but there + // aren't any test vectors for it yet +- // case ALG_SM4_VALUE: ++ case ALG_SM4_VALUE: /* libtpms changed */ + #endif + #if ALG_CAMELLIA + // no test vectors for camellia +@@ -925,10 +925,9 @@ TestAlgorithm( + #if ALG_SHA512 + case ALG_SHA512_VALUE: + #endif // TPM_ALG_SHA512 +- // if SM3 is implemented its test is like any other hash, but there +- // aren't any test vectors yet. ++ + #if ALG_SM3_256 +- // case ALG_SM3_256_VALUE: ++ case ALG_SM3_256_VALUE: /* libtpms changed */ + #endif // TPM_ALG_SM3_256 + if(doTest) + result = TestHash(alg, toTest); +diff --git a/src/tpm2/HashTestData.h b/src/tpm2/HashTestData.h +index d13843a..604fd43 100644 +--- a/src/tpm2/HashTestData.h ++++ b/src/tpm2/HashTestData.h +@@ -127,6 +127,15 @@ TPM2B_SHA512 c_SHA512_digest = {{64, { + }}}; + #endif + ++// libtpms added begin ++#if ALG_SM3_256 == YES ++TPM2B_TYPE(SM3_256, 32); ++TPM2B_SM3_256 c_SM3_256_digest = {{32, { ++ 0xbb,0x9e,0x23,0x79,0xfe,0xbb,0xf8,0xb0,0x1d,0x27,0x5f,0x30,0x71,0xbe,0xce,0x8a, ++ 0xb7,0x3f,0xee,0x6b,0xed,0xd7,0xee,0x45,0x4f,0x80,0xca,0x70,0x6c,0x09,0xb6,0x1a ++ }}}; ++#endif ++// libtpms added end + // libtpms added begin + #if ALG_CMAC + TPM2B_TYPE(AES128, 16); +diff --git a/src/tpm2/Marshal.c b/src/tpm2/Marshal.c +index 39e69e4..aae9a4f 100644 +--- a/src/tpm2/Marshal.c ++++ b/src/tpm2/Marshal.c +@@ -1135,6 +1135,15 @@ TPMI_TDES_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS *source, BYTE **buffer, INT32 *siz + return written; + } // libtpms added end + ++#if ALG_SM4 // libtpms added begin ++UINT16 ++TPMI_SM4_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS *source, BYTE **buffer, INT32 *size) ++{ ++ UINT16 written = 0; ++ written += TPM_KEY_BITS_Marshal(source, buffer, size); ++ return written; ++} ++#endif // libtpms added end + /* Table 2:128 - Definition of TPMU_SYM_KEY_BITS Union (StructuresTable()) */ + + UINT16 +diff --git a/src/tpm2/Marshal_fp.h b/src/tpm2/Marshal_fp.h +index 582cc9e..f02ff37 100644 +--- a/src/tpm2/Marshal_fp.h ++++ b/src/tpm2/Marshal_fp.h +@@ -228,6 +228,10 @@ extern "C" { + TPM2B_ATTEST_Marshal(TPM2B_ATTEST *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_AES_KEY_BITS_Marshal(TPMI_AES_KEY_BITS *source, BYTE **buffer, INT32 *size); ++#if ALG_SM4 ++ UINT16 ++ TPMI_SM4_KEY_BITS_Marshal(TPMI_AES_KEY_BITS *source, BYTE **buffer, INT32 *size); ++#endif + UINT16 + TPMU_SYM_KEY_BITS_Marshal(TPMU_SYM_KEY_BITS *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 +diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c +index 40be17e..d67f5b4 100644 +--- a/src/tpm2/NVMarshal.c ++++ b/src/tpm2/NVMarshal.c +@@ -1970,6 +1970,135 @@ skip_future_versions: + } + #endif + ++#if ALG_SM3_256 ++ ++#define HASH_STATE_SM3_256_MAGIC 0x10854a09 ++#define HASH_STATE_SM3_256_VERSION 2 ++ ++static UINT16 ++tpmHashStateSM3_256_Marshal(tpmHashStateSM3_256_t *data, BYTE **buffer, INT32 *size, ++ UINT16 hashAlg) ++{ ++ UINT16 written = 0; ++ UINT16 array_size; ++ SM3_CTX *sm3_ctx = NULL; ++ BLOCK_SKIP_INIT; ++ ++ sm3_ctx = EVP_MD_CTX_md_data(*data); ++ written = NV_HEADER_Marshal(buffer, size, ++ HASH_STATE_SM3_256_VERSION, ++ HASH_STATE_SM3_256_MAGIC, 1); ++ written += UINT32_Marshal(&sm3_ctx->A, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->B, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->C, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->D, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->E, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->F, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->G, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->H, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->Nl, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->Nh, buffer, size); ++ /* data must be written as array */ ++ array_size = sizeof(sm3_ctx->data); ++ written += UINT16_Marshal(&array_size, buffer, size); ++ written += Array_Marshal((BYTE *)&sm3_ctx->data[0], array_size, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->num, buffer, size); ++ written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); ++ /* future versions append below this line */ ++ ++ BLOCK_SKIP_WRITE_POP(size); ++ ++ BLOCK_SKIP_WRITE_CHECK; ++ ++ return written; ++} ++ ++static UINT16 ++tpmHashStateSM3_256_Unmarshal(tpmHashStateSM3_256_t *data, BYTE **buffer, INT32 *size, ++ UINT16 hashAlg) ++{ ++ UINT16 rc = TPM_RC_SUCCESS; ++ UINT16 array_size; ++ NV_HEADER hdr; ++ SM3_CTX *sm3_ctx = NULL; ++ ++ (*data) = EVP_MD_CTX_new(); ++ if ((*data) == NULL) { ++ rc = TPM_RC_FAILURE; ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ EVP_DigestInit_ex(*data, EVP_sm3(), NULL); ++ sm3_ctx = EVP_MD_CTX_md_data(*data); ++ } ++ ++ if (rc == TPM_RC_SUCCESS) { ++ rc = NV_HEADER_Unmarshal(&hdr, buffer, size, ++ HASH_STATE_SM3_256_VERSION, ++ HASH_STATE_SM3_256_MAGIC); ++ } ++ ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->A, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->B, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->C, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->D, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->E, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->F, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->G, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->H, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->Nl, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->Nh, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT16_Unmarshal(&array_size, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS && ++ array_size != sizeof(sm3_ctx->data)) { ++ TPMLIB_LogTPM2Error("HASH_STATE_SM3_256: Bad array size for data; " ++ "expected %zu, got %u\n", ++ sizeof(sm3_ctx->data), array_size); ++ rc = TPM_RC_BAD_PARAMETER; ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = Array_Unmarshal((BYTE *)&sm3_ctx->data[0], array_size, ++ buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->num, buffer, size); ++ } ++ ++ /* version 2 starts having indicator for next versions that we can skip; ++ this allows us to downgrade state */ ++ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { ++ BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, ++ "HASH_STATE_SM3_256", "version 3 or later"); ++ /* future versions nest-append here */ ++ } ++skip_future_versions: ++ ++ return rc; ++} ++#endif ++ ++ + #define ANY_HASH_STATE_MAGIC 0x349d494b + #define ANY_HASH_STATE_VERSION 2 + +@@ -2006,6 +2135,12 @@ ANY_HASH_STATE_Marshal(ANY_HASH_STATE *data, BYTE **buffer, INT32 *size, + written += tpmHashStateSHA512_Marshal(&data->Sha512, buffer, size, + ALG_SHA512_VALUE); + break; ++#endif ++#if ALG_SM3_256 ++ case ALG_SM3_256_VALUE: ++ written += tpmHashStateSM3_256_Marshal(&data->Sm3_256, buffer, size, ++ ALG_SHA512_VALUE); ++ break; + #endif + default: + break; +@@ -2056,6 +2191,12 @@ ANY_HASH_STATE_Unmarshal(ANY_HASH_STATE *data, BYTE **buffer, INT32 *size, + rc = tpmHashStateSHA512_Unmarshal(&data->Sha512, buffer, size, + ALG_SHA512_VALUE); + break; ++#endif ++#if ALG_SM3_256 ++ case ALG_SM3_256_VALUE: ++ rc = tpmHashStateSM3_256_Unmarshal(&data->Sm3_256, buffer, size, ++ ALG_SHA512_VALUE); ++ break; + #endif + } + +diff --git a/src/tpm2/SymmetricTest.h b/src/tpm2/SymmetricTest.h +index 56580de..72502ce 100644 +--- a/src/tpm2/SymmetricTest.h ++++ b/src/tpm2/SymmetricTest.h +@@ -98,11 +98,11 @@ const SYMMETRIC_TEST_VECTOR c_symTestValues[NUM_SYMS] = { + # undef COMMA + # define COMMA , + #endif +-#if SM4_128 ++#if ALG_SM4 && SM4_128 + COMMA + {ALG_SM4_VALUE, 128, key_SM4128, 16, sizeof(dataIn_SM4128), dataIn_SM4128, + {dataOut_SM4128_CTR, dataOut_SM4128_OFB, dataOut_SM4128_CBC, +- dataOut_SM4128_CFB, dataOut_AES128_ECB}} ++ dataOut_SM4128_CFB, dataOut_SM4128_ECB}} + #endif + // libtpms added begin + #if TDES_128 +diff --git a/src/tpm2/SymmetricTestData.h b/src/tpm2/SymmetricTestData.h +index f64fb4f..fe850e7 100644 +--- a/src/tpm2/SymmetricTestData.h ++++ b/src/tpm2/SymmetricTestData.h +@@ -269,6 +269,51 @@ const BYTE dataOutShort_TDES192_CFB[] = { + const BYTE dataOutShort_TDES192_OFB[] = { + 0xd3, 0xf3, 0x36, 0x3a, 0x4d}; + #endif ++ ++#if SM4_128 ++// source: https://tools.ietf.org/html/draft-ribose-cfrg-sm4-04#appendix-A.2 ++const BYTE key_SM4128 [] = { ++ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, ++ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; ++const BYTE dataIn_SM4128 [] = { ++ 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, ++ 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDD, 0xDD, ++ 0xEE, 0xEE, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB}; ++const BYTE dataOut_SM4128_ECB [] = { ++ 0x5E, 0xC8, 0x14, 0x3D, 0xE5, 0x09, 0xCF, 0xF7, ++ 0xB5, 0x17, 0x9F, 0x8F, 0x47, 0x4B, 0x86, 0x19, ++ 0x2F, 0x1D, 0x30, 0x5A, 0x7F, 0xB1, 0x7D, 0xF9, ++ 0x85, 0xF8, 0x1C, 0x84, 0x82, 0x19, 0x23, 0x04, ++ 0x00, 0x2A, 0x8A, 0x4E, 0xFA, 0x86, 0x3C, 0xCA, ++ 0xD0, 0x24, 0xAC, 0x03, 0x00, 0xBB, 0x40, 0xD2}; ++const BYTE dataOut_SM4128_CBC [] = { ++ 0x78, 0xEB, 0xB1, 0x1C, 0xC4, 0x0B, 0x0A, 0x48, ++ 0x31, 0x2A, 0xAE, 0xB2, 0x04, 0x02, 0x44, 0xCB, ++ 0x4C, 0xB7, 0x01, 0x69, 0x51, 0x90, 0x92, 0x26, ++ 0x97, 0x9B, 0x0D, 0x15, 0xDC, 0x6A, 0x8F, 0x6D, ++ 0x40, 0xD8, 0x41, 0x32, 0xE9, 0x99, 0x74, 0xA4, ++ 0xA8, 0x80, 0x88, 0x68, 0x42, 0x07, 0x48, 0x59}; ++const BYTE dataOut_SM4128_CFB [] = { ++ 0xAC, 0x32, 0x36, 0xCB, 0x86, 0x1D, 0xD3, 0x16, ++ 0xE6, 0x41, 0x3B, 0x4E, 0x3C, 0x75, 0x24, 0xB7, ++ 0x69, 0xD4, 0xC5, 0x4E, 0xD4, 0x33, 0xB9, 0xA0, ++ 0x34, 0x60, 0x09, 0xBE, 0xB3, 0x7B, 0x2B, 0x3F}; ++const BYTE dataOut_SM4128_OFB [] = { ++ 0xAC, 0x32, 0x36, 0xCB, 0x86, 0x1D, 0xD3, 0x16, ++ 0xE6, 0x41, 0x3B, 0x4E, 0x3C, 0x75, 0x24, 0xB7, ++ 0x1D, 0x01, 0xAC, 0xA2, 0x48, 0x7C, 0xA5, 0x82, ++ 0xCB, 0xF5, 0x46, 0x3E, 0x66, 0x98, 0x53, 0x9B}; ++/* The data are obtained by running the commands as below: ++ echo "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFFAAAAAAAABBBBBBBB" | xxd -p -r > plain.txt ++ openssl enc -sm4-ctr -in plain.txt -iv "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF" -out out.txt -K "0123456789ABCDEFFEDCBA9876543210" ++*/ ++const BYTE dataOut_SM4128_CTR [] = { ++ 0xF4, 0x88, 0x4C, 0x6D, 0x39, 0x7E, 0x0B, 0x06, ++ 0x3D, 0xAC, 0xD9, 0x46, 0x1A, 0xA4, 0xA5, 0x6A, ++ 0x60, 0xDD, 0xA7, 0x5F, 0x86, 0xBC, 0xFE, 0xA4, ++ 0xF1, 0x5D, 0xB4, 0x6A, 0xD1, 0x4E, 0x7C, 0x7F}; ++#endif + // libtpms added end + + #endif +diff --git a/src/tpm2/Unmarshal_fp.h b/src/tpm2/Unmarshal_fp.h +index 8f148b3..5279671 100644 +--- a/src/tpm2/Unmarshal_fp.h ++++ b/src/tpm2/Unmarshal_fp.h +@@ -286,6 +286,10 @@ extern "C" { + #endif /* libtpms added */ + LIB_EXPORT TPM_RC + TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *size); ++#if ALG_SM4 ++ LIB_EXPORT TPM_RC ++ TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size); ++#endif + LIB_EXPORT TPM_RC + TPMU_SYM_KEY_BITS_Unmarshal(TPMU_SYM_KEY_BITS *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC +diff --git a/src/tpm2/crypto/CryptHash.h b/src/tpm2/crypto/CryptHash.h +index 6ba76c2..ffaa034 100644 +--- a/src/tpm2/crypto/CryptHash.h ++++ b/src/tpm2/crypto/CryptHash.h +@@ -133,6 +133,9 @@ typedef union + #endif + #if ALG_SHA512 + tpmHashStateSHA512_t Sha512; ++#endif ++#if ALG_SM3_256 ++ tpmHashStateSM3_256_t Sm3_256; + #endif + // Additions for symmetric block cipher MAC + #if SMAC_IMPLEMENTED +diff --git a/src/tpm2/crypto/CryptSym.h b/src/tpm2/crypto/CryptSym.h +index 7c84279..d481b33 100644 +--- a/src/tpm2/crypto/CryptSym.h ++++ b/src/tpm2/crypto/CryptSym.h +@@ -94,6 +94,9 @@ union tpmCryptKeySchedule_t { + encrypt(SWIZZLE(keySchedule, in, out)) + # define DECRYPT(keySchedule, in, out) \ + decrypt(SWIZZLE(keySchedule, in, out)) ++ ++# define FINAL(keySchedule) final((void *)(keySchedule)) // libtpms added ++ + /* Note that the macros rely on encrypt as local values in the functions that use these + macros. Those parameters are set by the macro that set the key schedule to be used for the + call. */ +@@ -101,11 +104,13 @@ union tpmCryptKeySchedule_t { + case TPM_ALG_##ALG: \ + TpmCryptSetEncryptKey##ALG(key, keySizeInBits, &keySchedule.ALG); \ + encrypt = (TpmCryptSetSymKeyCall_t)TpmCryptEncrypt##ALG; \ ++ final = (TpmCryptSymFinal_t)TpmCryptFinal##ALG; /* libtpms added */ \ + break; + #define DECRYPT_CASE(ALG) \ + case TPM_ALG_##ALG: \ + TpmCryptSetDecryptKey##ALG(key, keySizeInBits, &keySchedule.ALG); \ + decrypt = (TpmCryptSetSymKeyCall_t)TpmCryptDecrypt##ALG; \ ++ final = (TpmCryptSymFinal_t)TpmCryptFinal##ALG; /* libtpms added */ \ + break; + #if ALG_AES + #define ENCRYPT_CASE_AES ENCRYPT_CASE(AES) +diff --git a/src/tpm2/crypto/openssl/CryptCmac.c b/src/tpm2/crypto/openssl/CryptCmac.c +index 8e35a59..2b28723 100644 +--- a/src/tpm2/crypto/openssl/CryptCmac.c ++++ b/src/tpm2/crypto/openssl/CryptCmac.c +@@ -120,6 +120,7 @@ CryptCmacData( + UINT16 keySizeInBits = cmacState->keySizeBits; + tpmCryptKeySchedule_t keySchedule; + TpmCryptSetSymKeyCall_t encrypt; ++ TpmCryptSymFinal_t final; /* libtpms added */ + // + SELECT(ENCRYPT); + while(size > 0) +@@ -135,6 +136,10 @@ CryptCmacData( + cmacState->iv.t.buffer[cmacState->bcount] ^= *buffer++; + } + } ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + } + /* 10.2.6.3.3 CryptCmacEnd() */ + /* This is the completion function for the CMAC. It does padding, if needed, and selects the subkey +@@ -154,6 +159,7 @@ CryptCmacEnd( + UINT16 keySizeInBits = cState->keySizeBits; + tpmCryptKeySchedule_t keySchedule; + TpmCryptSetSymKeyCall_t encrypt; ++ TpmCryptSymFinal_t final; /* libtpms added */ + TPM2B_IV subkey = {{0, {0}}}; + BOOL xorVal; + UINT16 i; +@@ -186,6 +192,10 @@ CryptCmacEnd( + ENCRYPT(&keySchedule, cState->iv.t.buffer, cState->iv.t.buffer); + i = (UINT16)MIN(cState->iv.t.size, outSize); + MemoryCopy(outBuffer, cState->iv.t.buffer, i); ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + return i; + } + #endif +diff --git a/src/tpm2/crypto/openssl/CryptHash.c b/src/tpm2/crypto/openssl/CryptHash.c +index fdf66b5..3cdb5a8 100644 +--- a/src/tpm2/crypto/openssl/CryptHash.c ++++ b/src/tpm2/crypto/openssl/CryptHash.c +@@ -79,6 +79,9 @@ HASH_DEF_TEMPLATE(SHA384); + #if ALG_SHA512 + HASH_DEF_TEMPLATE(SHA512); + #endif ++#if ALG_SM3_256 ++HASH_DEF_TEMPLATE(SM3_256); ++#endif + HASH_DEF nullDef = {{0}}; + /* 10.2.13.3 Obligatory Initialization Functions */ + /* This function is called by _TPM_Init() do perform the initialization operations for the +@@ -134,6 +137,11 @@ CryptGetHashDef( + case ALG_SHA512_VALUE: + retVal = &SHA512_Def; + break; ++#endif ++#if ALG_SM3_256 ++ case ALG_SM3_256_VALUE: ++ retVal = &SM3_256_Def; ++ break; + #endif + default: + retVal = &nullDef; +diff --git a/src/tpm2/crypto/openssl/CryptSym.c b/src/tpm2/crypto/openssl/CryptSym.c +index 856def6..9c1f501 100644 +--- a/src/tpm2/crypto/openssl/CryptSym.c ++++ b/src/tpm2/crypto/openssl/CryptSym.c +@@ -184,6 +184,7 @@ CryptSymmetricEncrypt( + tpmCryptKeySchedule_t keySchedule; + INT16 blockSize; + TpmCryptSetSymKeyCall_t encrypt; ++ TpmCryptSymFinal_t final; + BYTE *iv; + BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; + // +@@ -296,8 +297,16 @@ CryptSymmetricEncrypt( + break; + #endif + default: ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + return TPM_RC_FAILURE; + } ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + return TPM_RC_SUCCESS; + } + /* 10.2.20.5.1 CryptSymmetricDecrypt() */ +@@ -328,6 +337,7 @@ CryptSymmetricDecrypt( + BYTE *iv; + TpmCryptSetSymKeyCall_t encrypt; + TpmCryptSetSymKeyCall_t decrypt; ++ TpmCryptSymFinal_t final; /* libtpms added */ + BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; + // These are used but the compiler can't tell because they are initialized + // in case statements and it can't tell if they are always initialized +@@ -457,8 +467,16 @@ CryptSymmetricDecrypt( + break; + #endif + default: ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + return TPM_RC_FAILURE; + } ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + return TPM_RC_SUCCESS; + } + +diff --git a/src/tpm2/crypto/openssl/Helpers.c b/src/tpm2/crypto/openssl/Helpers.c +index 8a33259..0d34582 100644 +--- a/src/tpm2/crypto/openssl/Helpers.c ++++ b/src/tpm2/crypto/openssl/Helpers.c +@@ -187,8 +187,35 @@ evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN + } + #endif + #if ALG_SM4 +-#error Missing implementation of EVP for SM4 + case TPM_ALG_SM4: ++ *keyToUseLen = keySizeInBytes; ++ switch (mode) { ++#if ALG_CTR ++ case TPM_ALG_CTR: ++ evpfn = (evpfunc[]){EVP_sm4_ctr, NULL, NULL}[i]; ++ break; ++#endif ++#if ALG_OFB ++ case TPM_ALG_OFB: ++ evpfn = (evpfunc[]){EVP_sm4_ofb, NULL, NULL}[i]; ++ break; ++#endif ++#if ALG_CBC ++ case TPM_ALG_CBC: ++ evpfn = (evpfunc[]){EVP_sm4_cbc, NULL, NULL}[i]; ++ break; ++#endif ++#if ALG_CFB ++ case TPM_ALG_CFB: ++ evpfn = (evpfunc[]){EVP_sm4_cfb, NULL, NULL}[i]; ++ break; ++#endif ++#if ALG_ECB ++ case TPM_ALG_ECB: ++ evpfn = (evpfunc[]){EVP_sm4_ecb, NULL, NULL}[i]; ++ break; ++#endif ++ } + break; + #endif + #if ALG_CAMELLIA +@@ -264,11 +291,16 @@ static const struct hnames { + .name = "sha512", + .hashAlg = ALG_SHA512_VALUE, + }, { ++#endif ++#if ALG_SM3_256 ++ .name = "sm3", ++ .hashAlg = ALG_SM3_256_VALUE, ++ }, { + #endif + .name = NULL, + } + }; +-#if HASH_COUNT != ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA512 ++#if HASH_COUNT != ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA512 + ALG_SM3_256 + # error Missing entry in hnames array! + #endif + +@@ -493,3 +525,94 @@ OpenSSLCryptRsaGenerateKey( + } + + #endif // USE_OPENSSL_FUNCTIONS_RSA ++ ++#if ALG_SM4 ++static int SetSM4Key(const uint8_t *key, SM4_KEY *ks, int direction) ++{ ++ int rc = 0; ++ UINT8 iv[MAX_SM4_BLOCK_SIZE_BYTES] = { 0 }; ++ const EVP_CIPHER *sm4Cipher = EVP_sm4_ecb(); ++ ++ *ks = EVP_CIPHER_CTX_new(); ++ if (*ks == NULL) { ++ return SM4_FAIL; ++ } ++ if (direction == SM4_ENCRYPT) { ++ rc = EVP_EncryptInit_ex(*ks, sm4Cipher, NULL, key, iv); ++ } else { ++ rc = EVP_DecryptInit_ex(*ks, sm4Cipher, NULL, key, iv); ++ } ++ if (rc != SM4_SUCCESS) { ++ return SM4_FAIL; ++ } ++ return SM4_SUCCESS; ++} ++ ++int SM4_set_encrypt_key(const uint8_t *key, SM4_KEY *ks) ++{ ++ return SetSM4Key(key, ks, SM4_ENCRYPT); ++} ++ ++int SM4_set_decrypt_key(const uint8_t *key, SM4_KEY *ks) ++{ ++ return SetSM4Key(key, ks, SM4_DECRYPT); ++} ++ ++static void SM4EncryptDecrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks, int direction) ++{ ++ int outLen = SM4_128_BLOCK_SIZE_BYTES; ++ int rc = 0; ++ ++ if (direction == SM4_ENCRYPT) { ++ rc = EVP_EncryptUpdate(*ks, out, &outLen, in, SM4_128_BLOCK_SIZE_BYTES); ++ } else { ++ rc = EVP_DecryptUpdate(*ks, out, &outLen, in, SM4_128_BLOCK_SIZE_BYTES); ++ } ++ pAssert(rc != SM4_SUCCESS || outLen != SM4_128_BLOCK_SIZE_BYTES); ++} ++ ++void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks) ++{ ++ SM4EncryptDecrypt(in, out, ks, SM4_ENCRYPT); ++} ++ ++void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks) ++{ ++ SM4EncryptDecrypt(in, out, ks, SM4_DECRYPT); ++} ++ ++void SM4_final(const SM4_KEY *ks) ++{ ++ if (*ks != NULL) { ++ EVP_CIPHER_CTX_cleanup(*ks); ++ } ++} ++#endif ++#if ALG_SM3_256 ++int sm3_init(SM3_TPM_CTX *c) ++{ ++ *c = EVP_MD_CTX_new(); ++ if (*c == NULL) { ++ return SM3_FAIL; ++ } ++ return EVP_DigestInit_ex(*c, EVP_sm3(), NULL); ++} ++ ++int sm3_update(SM3_TPM_CTX *c, const void *data, size_t len) ++{ ++ return EVP_DigestUpdate(*c, data, len); ++} ++ ++int sm3_final(unsigned char *md, SM3_TPM_CTX *c) ++{ ++ uint32_t len = SM3_256_DIGEST_SIZE; ++ int ret = EVP_DigestFinal_ex(*c, md, &len); ++ ++ if (ret != SM3_SUCCESS || len != SM3_256_DIGEST_SIZE) { ++ ret = SM3_FAIL; ++ } ++ EVP_MD_CTX_destroy(*c); ++ *c = NULL; ++ return ret; ++} ++#endif +diff --git a/src/tpm2/crypto/openssl/TpmToOsslHash.h b/src/tpm2/crypto/openssl/TpmToOsslHash.h +index 7624824..78a1d93 100644 +--- a/src/tpm2/crypto/openssl/TpmToOsslHash.h ++++ b/src/tpm2/crypto/openssl/TpmToOsslHash.h +@@ -71,6 +71,35 @@ + #include + #include + #include ++ ++#if ALG_SM3_256 ++# if defined(OPENSSL_NO_SM3) || OPENSSL_VERSION_NUMBER < 0x10101010L ++# if ALG_SM3_256 // libtpms added begin ++# error This version of OpenSSL does not support SM3 ++# endif // libtpms added end ++# undef ALG_SM3_256 ++# define ALG_SM3_256 ALG_NO ++# else ++# include ++ ++# define SM3_LBLOCK (64/4) ++# define SM3_SUCCESS 1 ++# define SM3_FAIL 0 ++typedef struct SM3state_st { ++ unsigned int A, B, C, D, E, F, G, H; ++ unsigned int Nl, Nh; ++ unsigned int data[SM3_LBLOCK]; ++ unsigned int num; ++} SM3_CTX; ++ ++typedef EVP_MD_CTX* SM3_TPM_CTX; ++ ++int sm3_init(SM3_TPM_CTX *c); ++int sm3_update(SM3_TPM_CTX *c, const void *data, size_t len); ++int sm3_final(unsigned char *md, SM3_TPM_CTX *c); ++#endif ++#endif // ALG_SM3_256 ++ + /* B.2.2.1.2. Links to the OpenSSL HASH code */ + /* Redefine the internal name used for each of the hash state structures to the name used by the + library. These defines need to be known in all parts of the TPM so that the structure sizes can +@@ -80,8 +109,9 @@ + #define tpmHashStateSHA384_t SHA512_CTX + #define tpmHashStateSHA512_t SHA512_CTX + #if ALG_SM3_256 +-# error "The version of OpenSSL used by this code does not support SM3" ++#define tpmHashStateSM3_256_t SM3_TPM_CTX + #endif ++ + /* The defines below are only needed when compiling CryptHash.c or CryptSmac.c. This isolation + is primarily to avoid name space collision. However, if there is a real collision, it will + likely show up when the linker tries to put things together. */ +@@ -171,6 +201,15 @@ typedef const BYTE *PCBYTE; + #define tpmHashStateCopy_SHA512 memcpy + #define tpmHashStateExport_SHA512 memcpy + #define tpmHashStateImport_SHA512 memcpy ++#if ALG_SM3_256 ++#define tpmHashStart_SM3_256 sm3_init ++#define tpmHashData_SM3_256 sm3_update ++#define tpmHashEnd_SM3_256 sm3_final ++#define tpmHashStateCopy_SM3_256 memcpy ++#define tpmHashStateExport_SM3_256 memcpy ++#define tpmHashStateImport_SM3_256 memcpy ++#endif ++ + #endif // _CRYPT_HASH_C_ + #define LibHashInit() + /* This definition would change if there were something to report */ +diff --git a/src/tpm2/crypto/openssl/TpmToOsslSym.h b/src/tpm2/crypto/openssl/TpmToOsslSym.h +index 646d16d..2278c81 100644 +--- a/src/tpm2/crypto/openssl/TpmToOsslSym.h ++++ b/src/tpm2/crypto/openssl/TpmToOsslSym.h +@@ -76,8 +76,25 @@ + #include + /* B.2.2.3.2. Links to the OpenSSL AES code */ + #if ALG_SM4 +-#error "SM4 is not available" +-#endif ++# if defined(OPENSSL_NO_SM4) || OPENSSL_VERSION_NUMBER < 0x10101010L ++# undef ALG_SM4 ++# define ALG_SM4 ALG_NO ++# else ++# include ++ typedef EVP_CIPHER_CTX* SM4_KEY; ++# define SM4_ENCRYPT 1 ++# define SM4_DECRYPT 0 ++# define SM4_SUCCESS 1 ++# define SM4_FAIL 0 ++ ++int SM4_set_encrypt_key(const uint8_t *key, SM4_KEY *ks); ++int SM4_set_decrypt_key(const uint8_t *key, SM4_KEY *ks); ++void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); ++void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); ++void SM4_final(const SM4_KEY *ks); ++# endif ++#endif // ALG_SM4 ++ + #if ALG_CAMELLIA + #error "Camellia is not available" + #endif +@@ -88,6 +105,7 @@ typedef void(*TpmCryptSetSymKeyCall_t)( + BYTE *out, + void *keySchedule + ); ++typedef void(*TpmCryptSymFinal_t)(void *keySchedule); /* libtpms added */ + /* The Crypt functions that call the block encryption function use the parameters in the order: */ + /* a) keySchedule */ + /* b) in buffer */ +@@ -106,6 +124,13 @@ typedef void(*TpmCryptSetSymKeyCall_t)( + TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule)) + #define TpmCryptSetDecryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule)) ++#if ALG_SM4 ++#define TpmCryptSetEncryptKeySM4(key, keySizeInBits, schedule) \ ++ SM4_set_encrypt_key((key), (tpmKeyScheduleSM4 *)(schedule)) /* libtpms changed */ ++#define TpmCryptSetDecryptKeySM4(key, keySizeInBits, schedule) \ ++ SM4_set_decrypt_key((key), (tpmKeyScheduleSM4 *)(schedule)) /* libtpms changed */ ++#endif ++ + /* Macros to alias encryption calls to specific algorithms. This should be used + sparingly. Currently, only used by CryptRand.c */ + /* When using these calls, to call the AES block encryption code, the caller should use: +@@ -113,9 +138,20 @@ typedef void(*TpmCryptSetSymKeyCall_t)( + #define TpmCryptEncryptAES AES_encrypt + #define TpmCryptDecryptAES AES_decrypt + #define tpmKeyScheduleAES AES_KEY ++#define TpmCryptFinalAES NULL /* libtpms added */ ++ + #define TpmCryptEncryptTDES TDES_encrypt + #define TpmCryptDecryptTDES TDES_decrypt + #define tpmKeyScheduleTDES DES_key_schedule ++#define TpmCryptFinalTDES NULL /* libtpms added */ ++ ++#if ALG_SM4 ++#define TpmCryptEncryptSM4 SM4_encrypt /* libtpms added */ ++#define TpmCryptDecryptSM4 SM4_decrypt /* libtpms added */ ++#define tpmKeyScheduleSM4 SM4_KEY /* libtpms added */ ++#define TpmCryptFinalSM4 SM4_final /* libtpms added */ ++#endif ++ + typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t; + #if ALG_TDES + #include "TpmToOsslDesSupport_fp.h" +-- +2.39.3 (Apple Git-145) + -- Gitee