Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support SM3 and SM4 #271

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/tpm2/HashTestData.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ TPM2B_SHA512 c_SHA512_digest = {{64, {
TPM2B_TYPE(EMPTY, 1);

#if ALG_SM3_256 == YES
TPM2B_EMPTY c_SM3_256_digest = {{0, {0}}};
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

#if ALG_SHA3_256 == YES
Expand Down
166 changes: 158 additions & 8 deletions src/tpm2/NVMarshal.c
Original file line number Diff line number Diff line change
Expand Up @@ -774,8 +774,8 @@ PCR_SAVE_Marshal(PCR_SAVE *data, BYTE **buffer, INT32 *size)
written += Array_Marshal((BYTE *)&data->Sm3_256, array_size,
buffer, size);
#endif
#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256
#error SHA3 and SM3 are not supported
#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512
#error SHA3 are not supported
#endif

/* end marker */
Expand Down Expand Up @@ -879,8 +879,8 @@ PCR_SAVE_Unmarshal(PCR_SAVE *data, BYTE **buffer, INT32 *size,
t = (BYTE *)&data->Sm3_256;
break;
#endif
#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256
#error SHA3 and SM3 are not supported
#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512
#error SHA3 are not supported
#endif
case TPM_ALG_NULL:
/* end marker */
Expand Down Expand Up @@ -990,8 +990,8 @@ PCR_Marshal(PCR *data, BYTE **buffer, INT32 *size)
written += Array_Marshal((BYTE *)&data->Sm3_256Pcr, array_size,
buffer, size);
#endif
#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256
#error SHA3 and SM3 are not supported
#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512
#error SHA3 are not supported
#endif

/* end marker */
Expand Down Expand Up @@ -1061,8 +1061,8 @@ PCR_Unmarshal(PCR *data, BYTE **buffer, INT32 *size,
t = (BYTE *)&data->Sm3_256Pcr;
break;
#endif
#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256
#error SHA3 and SM3 are not supported
#if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512
#error SHA3 are not supported
#endif
case TPM_ALG_NULL:
/* end marker */
Expand Down Expand Up @@ -2026,7 +2026,145 @@ tpmHashStateSHA512_Unmarshal(SHA512_CTX *data, BYTE **buffer, INT32 *size,
return rc;
}
#endif
#if ALG_SM3_256

#define HASH_STATE_SM3_256_MAGIC 0x10854a09
#define HASH_STATE_SM3_256_VERSION 2

#include "Sm3Helper_fp.h"
static inline UINT16
SM3_WORD_Marshal(SM3_WORD *data, BYTE **buffer, INT32 *size)
{
return UINT32_Marshal(data, buffer, size);
}

static inline UINT16
SM3_WORD_Unmarshal(SM3_WORD *data, BYTE **buffer, INT32 *size)
{
return UINT32_Unmarshal(data, buffer, size);
}
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 += SM3_WORD_Marshal(&sm3_ctx->A, buffer, size);
written += SM3_WORD_Marshal(&sm3_ctx->B, buffer, size);
written += SM3_WORD_Marshal(&sm3_ctx->C, buffer, size);
written += SM3_WORD_Marshal(&sm3_ctx->D, buffer, size);
written += SM3_WORD_Marshal(&sm3_ctx->E, buffer, size);
written += SM3_WORD_Marshal(&sm3_ctx->F, buffer, size);
written += SM3_WORD_Marshal(&sm3_ctx->G, buffer, size);
written += SM3_WORD_Marshal(&sm3_ctx->H, buffer, size);
written += SM3_WORD_Marshal(&sm3_ctx->Nl, buffer, size);
written += SM3_WORD_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();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we shouldn't create a context here but fill the data just like we fill it with sha1 etc.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The risk with sm3 is that its data structure has always been opaque it seems. That leaves OpenSSL the opportunity to shuffle things around. They may not do that but the risk is there. In contrast to that we have the SHAT_CTX, SHA256_CTX, etc. that are available via sha.h, so there's less of a risk with them on that level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the OpenSSL 3.0 migration guide , users are strongly encouraged to update their code to use the high level APIs instead. Low level APIs have been deprecated in OpenSSL 3.0, and will most likely be removed in a future versions.
OpenSSL intentionally avoids the user to perceive the internal structure of XXX_CTX, we can only use its pointer. So we don't need to care about its structure.
In the long term, we need to switch to the "high level" APIs (such as the EVP APIs).

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know... but it's not going to be that simple. See my comment over there: #215 (comment)

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 = SM3_WORD_Unmarshal(&sm3_ctx->A, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
rc = SM3_WORD_Unmarshal(&sm3_ctx->B, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
rc = SM3_WORD_Unmarshal(&sm3_ctx->C, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
rc = SM3_WORD_Unmarshal(&sm3_ctx->D, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
rc = SM3_WORD_Unmarshal(&sm3_ctx->E, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
rc = SM3_WORD_Unmarshal(&sm3_ctx->F, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
rc = SM3_WORD_Unmarshal(&sm3_ctx->G, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
rc = SM3_WORD_Unmarshal(&sm3_ctx->H, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
rc = SM3_WORD_Unmarshal(&sm3_ctx->Nl, buffer, size);
}
if (rc == TPM_RC_SUCCESS) {
rc = SM3_WORD_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

Expand Down Expand Up @@ -2063,6 +2201,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_SM3_256_VALUE);
break;
#endif
default:
break;
Expand Down Expand Up @@ -2113,6 +2257,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_SM3_256_VALUE);
break;
#endif
}

Expand Down
32 changes: 31 additions & 1 deletion src/tpm2/crypto/openssl/Helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,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

Expand Down Expand Up @@ -623,3 +628,28 @@ OpenSSLCryptRsaGenerateKey(
}

#endif // USE_OPENSSL_FUNCTIONS_RSA
#if ALG_SM3_256
int sm3_init(SM3_TPM_CTX *c)
{
*c = EVP_MD_CTX_new();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is correct. It's probably better to initialize SM3_TPM_CTX ourselves here.

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)
JerryDevis marked this conversation as resolved.
Show resolved Hide resolved
{
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) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty line after variables declaration.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please just use '1' for OpenSSL function success checking, no SM3_SUCCESS.

ret = SM3_FAIL;
}
EVP_MD_CTX_destroy(*c);
*c = NULL;
return ret;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return SM3_SUCCESS

}
#endif
JerryDevis marked this conversation as resolved.
Show resolved Hide resolved
25 changes: 25 additions & 0 deletions src/tpm2/crypto/openssl/Sm3Helper_fp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef SM3_HELPER_FP
#define SM3_HELPER_FP
#if ALG_SM3_256
#include <openssl/evp.h>

typedef EVP_MD_CTX* SM3_TPM_CTX;
#define SM3_SUCCESS 1
#define SM3_FAIL 0
# define SM3_DIGEST_LENGTH 32
# define SM3_WORD unsigned int

# define SM3_CBLOCK 64
# define SM3_LBLOCK (SM3_CBLOCK/4)

typedef struct SM3state_st {
SM3_WORD A, B, C, D, E, F, G, H;
SM3_WORD Nl, Nh;
SM3_WORD data[SM3_LBLOCK];
unsigned int num;
} SM3_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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Large parts of this file are already in TpmToOsslHash.h and shouldn't be duplicated. Please try to use that file.

25 changes: 3 additions & 22 deletions src/tpm2/crypto/openssl/TpmToOsslHash.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,25 +75,9 @@
# endif // libtpms added end
# undef ALG_SM3_256
# define ALG_SM3_256 ALG_NO
# elif OPENSSL_VERSION_NUMBER >= 0x10200000L
# include <openssl/sm3.h>
# else
// OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory,
// and they do not get installed as part of the libssl package
# define SM3_LBLOCK (64/4)

# error Check support for this version of SM3 in OpenSSL (libtpms)
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;

int sm3_init(SM3_CTX *c);
int sm3_update(SM3_CTX *c, const void *data, size_t len);
int sm3_final(unsigned char *md, SM3_CTX *c);
# endif // OpenSSL < 1.2
#include "Sm3Helper_fp.h"
#endif
#endif // ALG_SM3_256
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you remove it from here? I'd rather not move this here to keep the differences to the reference code at a minimum.


#include <openssl/ossl_typ.h>
Expand All @@ -108,10 +92,7 @@ int sm3_final(unsigned char *md, SM3_CTX *c);
#define tpmHashStateSHA256_t SHA256_CTX
#define tpmHashStateSHA384_t SHA512_CTX
#define tpmHashStateSHA512_t SHA512_CTX
#define tpmHashStateSM3_256_t SM3_CTX
#if ALG_SM3_256
# error "The version of OpenSSL used by this code does not support SM3"
#endif
#define tpmHashStateSM3_256_t SM3_TPM_CTX
/* The defines below are only needed when compiling CryptHash.c or CryptSmac.c. This isolation
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this should stay here.

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. */
Expand Down