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)