mirror of https://github.com/wolfSSL/wolfTPM.git
Compare commits
16 Commits
Author | SHA1 | Date |
---|---|---|
|
8b2e4271d3 | |
|
8ce8eaaeba | |
|
33a532f58c | |
|
47193894e8 | |
|
d5872221ba | |
|
bd682553ac | |
|
a45f922c6d | |
|
f1507c697b | |
|
592210f321 | |
|
3e3038854c | |
|
32332fd2bb | |
|
761cb4adea | |
|
c364166542 | |
|
7411bc115f | |
|
4214ffa8a5 | |
|
cbb7c2969b |
|
@ -79,11 +79,41 @@ check_function_exists("gettimeofday" HAVE_GETTIMEOFDAY)
|
||||||
# * wait state
|
# * wait state
|
||||||
# * small stack
|
# * small stack
|
||||||
|
|
||||||
|
# Single threaded
|
||||||
|
set(WOLFTPM_SINGLE_THREADED "no" CACHE STRING
|
||||||
|
"Enable wolfTPM single threaded (default: disabled)")
|
||||||
|
set_property(CACHE WOLFTPM_SINGLE_THREADED
|
||||||
|
PROPERTY STRINGS "yes;no")
|
||||||
|
if(WOLFTPM_SINGLE_THREADED)
|
||||||
|
list(APPEND WOLFTPM_DEFINITIONS
|
||||||
|
"-DSINGLE_THREADED")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Mutex locking
|
||||||
|
set(WOLFTPM_NO_LOCK "no" CACHE STRING
|
||||||
|
"Enable thread mutex locking (default: enabled)")
|
||||||
|
set_property(CACHE WOLFTPM_NO_LOCK
|
||||||
|
PROPERTY STRINGS "yes;no")
|
||||||
|
if(NOT WOLFTPM_NO_LOCK)
|
||||||
|
list(APPEND WOLFTPM_DEFINITIONS
|
||||||
|
"-DWOLFTPM_NO_LOCK")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Active TPM - Thread local storage
|
||||||
|
set(WOLFTPM_NO_ACTIVE_THREAD_LS "no" CACHE STRING
|
||||||
|
"Disable active TPM thread local storage (default: disabled)")
|
||||||
|
set_property(CACHE WOLFTPM_NO_ACTIVE_THREAD_LS
|
||||||
|
PROPERTY STRINGS "yes;no")
|
||||||
|
if(WOLFTPM_NO_ACTIVE_THREAD_LS)
|
||||||
|
list(APPEND WOLFTPM_DEFINITIONS
|
||||||
|
"-DWOLFTPM_NO_ACTIVE_THREAD_LS")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Provisioning
|
# Provisioning
|
||||||
set(WOLFTPM_PROVISIONING "yes" CACHE STRING
|
set(WOLFTPM_PROVISIONING "yes" CACHE STRING
|
||||||
"Enable support for Provisioning Initial Device Identity (IDevID) and Attestation Identity Keys (default: enabled)")
|
"Enable support for Provisioning Initial Device Identity (IDevID) and Attestation Identity Keys (default: enabled)")
|
||||||
set_property(CACHE WOLFTPM_PROVISIONING
|
set_property(CACHE WOLFTPM_PROVISIONING
|
||||||
PROPERTY STRINGS "yes;no;verbose")
|
PROPERTY STRINGS "yes;no")
|
||||||
if(WOLFTPM_PROVISIONING)
|
if(WOLFTPM_PROVISIONING)
|
||||||
list(APPEND WOLFTPM_DEFINITIONS
|
list(APPEND WOLFTPM_DEFINITIONS
|
||||||
"-DWOLFTPM_PROVISIONING")
|
"-DWOLFTPM_PROVISIONING")
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\tpm2.c" />
|
<ClCompile Include="..\..\src\tpm2.c" />
|
||||||
|
<ClCompile Include="..\..\src\tpm2_asn.c" />
|
||||||
<ClCompile Include="..\..\src\tpm2_cryptocb.c" />
|
<ClCompile Include="..\..\src\tpm2_cryptocb.c" />
|
||||||
<ClCompile Include="..\..\src\tpm2_packet.c" />
|
<ClCompile Include="..\..\src\tpm2_packet.c" />
|
||||||
<ClCompile Include="..\..\src\tpm2_param_enc.c" />
|
<ClCompile Include="..\..\src\tpm2_param_enc.c" />
|
||||||
|
|
|
@ -49,8 +49,8 @@ static void usage(void)
|
||||||
printf("Notes:\n");
|
printf("Notes:\n");
|
||||||
printf("\tName digest is loaded from \"ak.name\" file\n");
|
printf("\tName digest is loaded from \"ak.name\" file\n");
|
||||||
printf("\tPublic key is loaded from a file containing TPM2B_PUBLIC\n");
|
printf("\tPublic key is loaded from a file containing TPM2B_PUBLIC\n");
|
||||||
printf("\t\"tek.pub\" for EK pub");
|
printf("\t\"ek.pub\" for EK pub\n");
|
||||||
printf("\t\"tsrk.pub\" for SRK pub");
|
printf("\t\"srk.pub\" for SRK pub\n");
|
||||||
printf("\tOutput is stored in \"cred.blob\"\n");
|
printf("\tOutput is stored in \"cred.blob\"\n");
|
||||||
printf("Demo usage without parameters, uses SRK pub\n");
|
printf("Demo usage without parameters, uses SRK pub\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,7 +221,7 @@ int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[])
|
||||||
|
|
||||||
/* Necessary for storing the publicArea with the correct encoding */
|
/* Necessary for storing the publicArea with the correct encoding */
|
||||||
rc = TPM2_ParsePublic(&keyBlob.pub, pubAreaBuffer,
|
rc = TPM2_ParsePublic(&keyBlob.pub, pubAreaBuffer,
|
||||||
(word32)sizeof(pubAreaBuffer), &pubAreaSize);
|
readSize, &pubAreaSize);
|
||||||
if (rc != TPM_RC_SUCCESS) {
|
if (rc != TPM_RC_SUCCESS) {
|
||||||
printf("Decoding of PublicArea failed. Unable to extract correctly.\n");
|
printf("Decoding of PublicArea failed. Unable to extract correctly.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
|
@ -378,7 +378,7 @@ run_tpm_tls_client() { # Usage: run_tpm_tls_client [ecc/rsa] [tpmargs] [tlsversi
|
||||||
generate_port
|
generate_port
|
||||||
pushd $WOLFSSL_PATH >> $TPMPWD/run.out 2>&1
|
pushd $WOLFSSL_PATH >> $TPMPWD/run.out 2>&1
|
||||||
echo -e "./examples/server/server -v $3 -p $port -w -g -A ./certs/tpm-ca-$1-cert.pem"
|
echo -e "./examples/server/server -v $3 -p $port -w -g -A ./certs/tpm-ca-$1-cert.pem"
|
||||||
./examples/server/server -p $port -w -g -A ./certs/tpm-ca-$1-cert.pem &> $TPMPWD/run.out &
|
./examples/server/server -p $port -w -g -A ./certs/tpm-ca-$1-cert.pem >> $TPMPWD/run.out 2>&1 &
|
||||||
RESULT=$?
|
RESULT=$?
|
||||||
[ $RESULT -ne 0 ] && echo -e "tls server $1 $2 failed! $RESULT" && exit 1
|
[ $RESULT -ne 0 ] && echo -e "tls server $1 $2 failed! $RESULT" && exit 1
|
||||||
popd >> $TPMPWD/run.out 2>&1
|
popd >> $TPMPWD/run.out 2>&1
|
||||||
|
@ -493,17 +493,9 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $WOLFCRYPT_ENABLE -eq 1 ] && [ $NO_FILESYSTEM -eq 0 ]; then
|
if [ $WOLFCRYPT_ENABLE -eq 1 ] && [ $NO_FILESYSTEM -eq 0 ]; then
|
||||||
./examples/keygen/keygen keyblob.bin -rsa >> $TPMPWD/run.out 2>&1
|
rm -f keyblob.bin
|
||||||
RESULT=$?
|
|
||||||
[ $RESULT -ne 0 ] && echo -e "keygen rsa failed! $RESULT" && exit 1
|
|
||||||
./examples/attestation/make_credential >> $TPMPWD/run.out 2>&1
|
|
||||||
RESULT=$?
|
|
||||||
[ $RESULT -ne 0 ] && echo -e "make_credential failed! $RESULT" && exit 1
|
|
||||||
./examples/attestation/activate_credential >> $TPMPWD/run.out 2>&1
|
|
||||||
RESULT=$?
|
|
||||||
[ $RESULT -ne 0 ] && echo -e "activate_credential failed! $RESULT" && exit 1
|
|
||||||
|
|
||||||
# Endorsement hierarchy
|
# Endorsement hierarchy (assumes keyblob.bin for key)
|
||||||
./examples/keygen/keygen keyblob.bin -rsa -eh >> $TPMPWD/run.out 2>&1
|
./examples/keygen/keygen keyblob.bin -rsa -eh >> $TPMPWD/run.out 2>&1
|
||||||
RESULT=$?
|
RESULT=$?
|
||||||
[ $RESULT -ne 0 ] && echo -e "keygen rsa endorsement failed! $RESULT" && exit 1
|
[ $RESULT -ne 0 ] && echo -e "keygen rsa endorsement failed! $RESULT" && exit 1
|
||||||
|
@ -514,10 +506,21 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ] && [ $NO_FILESYSTEM -eq 0 ]; then
|
||||||
RESULT=$?
|
RESULT=$?
|
||||||
[ $RESULT -ne 0 ] && echo -e "activate_credential endorsement failed! $RESULT" && exit 1
|
[ $RESULT -ne 0 ] && echo -e "activate_credential endorsement failed! $RESULT" && exit 1
|
||||||
|
|
||||||
|
./examples/keygen/keygen keyblob.bin -rsa >> $TPMPWD/run.out 2>&1
|
||||||
|
RESULT=$?
|
||||||
|
[ $RESULT -ne 0 ] && echo -e "keygen rsa failed! $RESULT" && exit 1
|
||||||
|
./examples/attestation/make_credential >> $TPMPWD/run.out 2>&1
|
||||||
|
RESULT=$?
|
||||||
|
[ $RESULT -ne 0 ] && echo -e "make_credential failed! $RESULT" && exit 1
|
||||||
|
./examples/attestation/activate_credential >> $TPMPWD/run.out 2>&1
|
||||||
|
RESULT=$?
|
||||||
|
[ $RESULT -ne 0 ] && echo -e "activate_credential failed! $RESULT" && exit 1
|
||||||
|
|
||||||
rm -f cred.blob
|
rm -f cred.blob
|
||||||
rm -f ek.pub
|
rm -f ek.pub
|
||||||
rm -f srk.pub
|
rm -f srk.pub
|
||||||
rm -f ak.name
|
rm -f ak.name
|
||||||
|
# Keeping keyblob.bin for tests later
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# PCR Quote Tests
|
# PCR Quote Tests
|
||||||
|
|
|
@ -535,7 +535,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
|
||||||
rc = wolfSSL_CTX_use_certificate_file(ctx, useCert, WOLFSSL_FILETYPE_PEM);
|
rc = wolfSSL_CTX_use_certificate_file(ctx, useCert, WOLFSSL_FILETYPE_PEM);
|
||||||
#endif
|
#endif
|
||||||
if (rc != WOLFSSL_SUCCESS) {
|
if (rc != WOLFSSL_SUCCESS) {
|
||||||
#ifndef NO_FILESYSTEM
|
#if !defined(NO_FILESYSTEM) && !defined(WOLFTPM_MFG_IDENTITY)
|
||||||
printf("Error loading ECC client cert: %s\n", useCert);
|
printf("Error loading ECC client cert: %s\n", useCert);
|
||||||
#else
|
#else
|
||||||
printf("Error loading ECC client cert\n");
|
printf("Error loading ECC client cert\n");
|
||||||
|
|
|
@ -216,7 +216,7 @@ int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key)
|
||||||
|
|
||||||
/* Decode the byte stream into a publicArea structure ready for use */
|
/* Decode the byte stream into a publicArea structure ready for use */
|
||||||
rc = TPM2_ParsePublic(&key->pub, pubAreaBuffer,
|
rc = TPM2_ParsePublic(&key->pub, pubAreaBuffer,
|
||||||
(word32)sizeof(pubAreaBuffer), &pubAreaSize);
|
sizeof(UINT16) + key->pub.size, &pubAreaSize);
|
||||||
if (rc != TPM_RC_SUCCESS) {
|
if (rc != TPM_RC_SUCCESS) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
109
src/tpm2.c
109
src/tpm2.c
|
@ -37,23 +37,26 @@
|
||||||
/* --- Local Variables -- */
|
/* --- Local Variables -- */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#ifdef WOLFTPM_NO_ACTIVE_THREAD_LS
|
|
||||||
/* if using gHwLock and want to use a shared active TPM2_CTX between threads */
|
|
||||||
static TPM2_CTX* gActiveTPM;
|
|
||||||
#else
|
|
||||||
static THREAD_LS_T TPM2_CTX* gActiveTPM;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WOLFTPM2_NO_WOLFCRYPT
|
#ifndef WOLFTPM2_NO_WOLFCRYPT
|
||||||
static volatile int gWolfCryptRefCount = 0;
|
static volatile int gWolfCryptRefCount = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(WOLFTPM_NO_LOCK) && \
|
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(WOLFTPM_NO_LOCK) && \
|
||||||
!defined(SINGLE_THREADED)
|
!defined(SINGLE_THREADED)
|
||||||
|
/* if a mutex lock is supported, then don't use thread local on gActiveTPM */
|
||||||
|
#undef WOLFTPM_NO_ACTIVE_THREAD_LS
|
||||||
|
#define WOLFTPM_NO_ACTIVE_THREAD_LS
|
||||||
|
|
||||||
static wolfSSL_Mutex gHwLock WOLFSSL_MUTEX_INITIALIZER_CLAUSE(gHwLock);
|
static wolfSSL_Mutex gHwLock WOLFSSL_MUTEX_INITIALIZER_CLAUSE(gHwLock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFTPM_NO_ACTIVE_THREAD_LS
|
||||||
|
/* if using gHwLock and want to use a shared active TPM2_CTX between threads */
|
||||||
|
static TPM2_CTX* gActiveTPM;
|
||||||
|
#else
|
||||||
|
static THREAD_LS_T TPM2_CTX* gActiveTPM;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WOLFTPM_LINUX_DEV
|
#ifdef WOLFTPM_LINUX_DEV
|
||||||
#define INTERNAL_SEND_COMMAND TPM2_LINUX_SendCommand
|
#define INTERNAL_SEND_COMMAND TPM2_LINUX_SendCommand
|
||||||
#define TPM2_INTERNAL_CLEANUP(ctx)
|
#define TPM2_INTERNAL_CLEANUP(ctx)
|
||||||
|
@ -160,7 +163,7 @@ static int TPM2_CommandProcess(TPM2_CTX* ctx, TPM2_Packet* packet,
|
||||||
|
|
||||||
if (session->sessionHandle != TPM_RS_PW) {
|
if (session->sessionHandle != TPM_RS_PW) {
|
||||||
/* Generate fresh nonce */
|
/* Generate fresh nonce */
|
||||||
rc = TPM2_GetNonce(session->nonceCaller.buffer,
|
rc = TPM2_GetNonceNoLock(session->nonceCaller.buffer,
|
||||||
session->nonceCaller.size);
|
session->nonceCaller.size);
|
||||||
if (rc != TPM_RC_SUCCESS) {
|
if (rc != TPM_RC_SUCCESS) {
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -5464,6 +5467,7 @@ TPM_RC TPM2_GetProductInfo(uint8_t* info, uint16_t size)
|
||||||
size = packet.size - 26;
|
size = packet.size - 26;
|
||||||
XMEMCPY(info, &packet.buf[25], size);
|
XMEMCPY(info, &packet.buf[25], size);
|
||||||
}
|
}
|
||||||
|
TPM2_ReleaseLock(ctx);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -5686,9 +5690,7 @@ int TPM2_GetHashType(TPMI_ALG_HASH hashAlg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can optionally define WOLFTPM2_USE_HW_RNG to force using TPM hardware for
|
int TPM2_GetNonceNoLock(byte* nonceBuf, int nonceSz)
|
||||||
* RNG source */
|
|
||||||
int TPM2_GetNonce(byte* nonceBuf, int nonceSz)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
TPM2_CTX* ctx = TPM2_GetActiveCtx();
|
TPM2_CTX* ctx = TPM2_GetActiveCtx();
|
||||||
|
@ -5717,44 +5719,58 @@ int TPM2_GetNonce(byte* nonceBuf, int nonceSz)
|
||||||
#else
|
#else
|
||||||
/* Call GetRandom directly, so a custom packet buffer can be used.
|
/* Call GetRandom directly, so a custom packet buffer can be used.
|
||||||
* This won't conflict when being called from TPM2_CommandProcess. */
|
* This won't conflict when being called from TPM2_CommandProcess. */
|
||||||
rc = TPM2_AcquireLock(ctx);
|
while (randSz < nonceSz) {
|
||||||
if (rc == TPM_RC_SUCCESS) {
|
UINT16 inSz = nonceSz - randSz, outSz = 0;
|
||||||
while (randSz < nonceSz) {
|
if (inSz > MAX_RNG_REQ_SIZE) {
|
||||||
UINT16 inSz = nonceSz - randSz, outSz = 0;
|
inSz = MAX_RNG_REQ_SIZE;
|
||||||
if (inSz > MAX_RNG_REQ_SIZE) {
|
|
||||||
inSz = MAX_RNG_REQ_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
TPM2_Packet_InitBuf(&packet, buffer, (int)sizeof(buffer));
|
|
||||||
TPM2_Packet_AppendU16(&packet, inSz);
|
|
||||||
TPM2_Packet_Finalize(&packet, TPM_ST_NO_SESSIONS, TPM_CC_GetRandom);
|
|
||||||
rc = TPM2_SendCommand(ctx, &packet);
|
|
||||||
#ifdef WOLFTPM_DEBUG_VERBOSE
|
|
||||||
printf("TPM2_GetNonce (%d bytes at %d): %d (%s)\n",
|
|
||||||
inSz, randSz, rc, TPM2_GetRCString(rc));
|
|
||||||
#endif
|
|
||||||
if (rc != TPM_RC_SUCCESS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TPM2_Packet_ParseU16(&packet, &outSz);
|
|
||||||
if (outSz > MAX_RNG_REQ_SIZE) {
|
|
||||||
#ifdef DEBUG_WOLFTPM
|
|
||||||
printf("TPM2_GetNonce out size error\n");
|
|
||||||
#endif
|
|
||||||
rc = BAD_FUNC_ARG;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
TPM2_Packet_ParseBytes(&packet, &nonceBuf[randSz], outSz);
|
|
||||||
randSz += outSz;
|
|
||||||
}
|
}
|
||||||
TPM2_ReleaseLock(ctx);
|
|
||||||
|
TPM2_Packet_InitBuf(&packet, buffer, (int)sizeof(buffer));
|
||||||
|
TPM2_Packet_AppendU16(&packet, inSz);
|
||||||
|
TPM2_Packet_Finalize(&packet, TPM_ST_NO_SESSIONS, TPM_CC_GetRandom);
|
||||||
|
rc = TPM2_SendCommand(ctx, &packet);
|
||||||
|
#ifdef WOLFTPM_DEBUG_VERBOSE
|
||||||
|
printf("TPM2_GetNonce (%d bytes at %d): %d (%s)\n",
|
||||||
|
inSz, randSz, rc, TPM2_GetRCString(rc));
|
||||||
|
#endif
|
||||||
|
if (rc != TPM_RC_SUCCESS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TPM2_Packet_ParseU16(&packet, &outSz);
|
||||||
|
if (outSz > MAX_RNG_REQ_SIZE) {
|
||||||
|
#ifdef DEBUG_WOLFTPM
|
||||||
|
printf("TPM2_GetNonce out size error\n");
|
||||||
|
#endif
|
||||||
|
rc = BAD_FUNC_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TPM2_Packet_ParseBytes(&packet, &nonceBuf[randSz], outSz);
|
||||||
|
randSz += outSz;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TPM2_GetNonce(byte* nonceBuf, int nonceSz)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
TPM2_CTX* ctx = TPM2_GetActiveCtx();
|
||||||
|
|
||||||
|
if (ctx == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = TPM2_AcquireLock(ctx);
|
||||||
|
if (rc == TPM_RC_SUCCESS) {
|
||||||
|
rc = TPM2_GetNonceNoLock(nonceBuf, nonceSz);
|
||||||
|
TPM2_ReleaseLock(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get name for object/handle */
|
/* Get name for object/handle */
|
||||||
int TPM2_GetName(TPM2_CTX* ctx, UINT32 handleValue, int handleCnt, int idx, TPM2B_NAME* name)
|
int TPM2_GetName(TPM2_CTX* ctx, UINT32 handleValue, int handleCnt, int idx, TPM2B_NAME* name)
|
||||||
{
|
{
|
||||||
|
@ -6449,13 +6465,6 @@ int TPM2_ParsePublic(TPM2B_PUBLIC* pub, byte* buf, word32 size, int* sizeUsed)
|
||||||
if (buf == NULL || pub == NULL || sizeUsed == NULL)
|
if (buf == NULL || pub == NULL || sizeUsed == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
if (size < sizeof(TPM2B_PUBLIC)) {
|
|
||||||
#ifdef DEBUG_WOLFTPM
|
|
||||||
printf("Insufficient buffer size for TPM2B_PUBLIC operations\n");
|
|
||||||
#endif
|
|
||||||
return TPM_RC_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare temporary buffer */
|
/* Prepare temporary buffer */
|
||||||
packet.buf = buf;
|
packet.buf = buf;
|
||||||
packet.pos = 0;
|
packet.pos = 0;
|
||||||
|
|
|
@ -27,6 +27,18 @@
|
||||||
|
|
||||||
#ifndef WOLFTPM2_NO_ASN
|
#ifndef WOLFTPM2_NO_ASN
|
||||||
|
|
||||||
|
/* Helper to trim leading zeros when not required */
|
||||||
|
byte* TPM2_ASN_TrimZeros(byte* in, word32* len)
|
||||||
|
{
|
||||||
|
word32 idx = 0;
|
||||||
|
while (idx+1 < *len && in[idx] == 0 && (in[idx+1] & 0x80) == 0) {
|
||||||
|
idx++;
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
*len -= idx;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
int TPM2_ASN_GetLength_ex(const uint8_t* input, word32* inOutIdx, int* len,
|
int TPM2_ASN_GetLength_ex(const uint8_t* input, word32* inOutIdx, int* len,
|
||||||
word32 maxIdx, int check)
|
word32 maxIdx, int check)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,24 +24,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <wolftpm/tpm2_wrap.h>
|
#include <wolftpm/tpm2_wrap.h>
|
||||||
|
#include <wolftpm/tpm2_asn.h>
|
||||||
|
|
||||||
#if !defined(WOLFTPM2_NO_WRAPPER)
|
#if !defined(WOLFTPM2_NO_WRAPPER)
|
||||||
|
|
||||||
#if defined(HAVE_ECC) && (defined(WOLFTPM_CRYPTOCB) || \
|
|
||||||
(defined(HAVE_PK_CALLBACKS) && !defined(WOLFCRYPT_ONLY)))
|
|
||||||
/* Helper to trim leading zeros when not required */
|
|
||||||
static byte* wolfTPM2_ASNTrimZeros(byte* in, word32* len)
|
|
||||||
{
|
|
||||||
word32 idx = 0;
|
|
||||||
while (idx+1 < *len && in[idx] == 0 && (in[idx+1] & 0x80) == 0) {
|
|
||||||
idx++;
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
*len -= idx;
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WOLFTPM_CRYPTOCB
|
#ifdef WOLFTPM_CRYPTOCB
|
||||||
|
|
||||||
/* Internal structure for tracking hash state */
|
/* Internal structure for tracking hash state */
|
||||||
|
@ -272,8 +258,8 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
|
||||||
rLen = sLen = rsLen / 2;
|
rLen = sLen = rsLen / 2;
|
||||||
r = &sigRS[0];
|
r = &sigRS[0];
|
||||||
s = &sigRS[rLen];
|
s = &sigRS[rLen];
|
||||||
r = wolfTPM2_ASNTrimZeros(r, &rLen);
|
r = TPM2_ASN_TrimZeros(r, &rLen);
|
||||||
s = wolfTPM2_ASNTrimZeros(s, &sLen);
|
s = TPM2_ASN_TrimZeros(s, &sLen);
|
||||||
|
|
||||||
/* Encode ECDSA Header */
|
/* Encode ECDSA Header */
|
||||||
rc = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen,
|
rc = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen,
|
||||||
|
@ -1134,8 +1120,8 @@ int wolfTPM2_PK_EccSign(WOLFSSL* ssl,
|
||||||
rLen = sLen = rsLen / 2;
|
rLen = sLen = rsLen / 2;
|
||||||
r = &sigRS[0];
|
r = &sigRS[0];
|
||||||
s = &sigRS[rLen];
|
s = &sigRS[rLen];
|
||||||
r = wolfTPM2_ASNTrimZeros(r, &rLen);
|
r = TPM2_ASN_TrimZeros(r, &rLen);
|
||||||
s = wolfTPM2_ASNTrimZeros(s, &sLen);
|
s = TPM2_ASN_TrimZeros(s, &sLen);
|
||||||
|
|
||||||
/* Encode ECDSA Header */
|
/* Encode ECDSA Header */
|
||||||
ret = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen, out, outSz);
|
ret = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen, out, outSz);
|
||||||
|
|
|
@ -481,7 +481,7 @@ int wolfTPM2_SetKeyBlobFromBuffer(WOLFTPM2_KEYBLOB* key, byte *buffer,
|
||||||
|
|
||||||
/* Decode the byte stream into a publicArea structure ready for use */
|
/* Decode the byte stream into a publicArea structure ready for use */
|
||||||
rc = TPM2_ParsePublic(&key->pub, pubAreaBuffer,
|
rc = TPM2_ParsePublic(&key->pub, pubAreaBuffer,
|
||||||
(word32)sizeof(pubAreaBuffer), &pubAreaSize);
|
(word32)(sizeof(UINT16) + key->pub.size), &pubAreaSize);
|
||||||
if (rc != TPM_RC_SUCCESS) {
|
if (rc != TPM_RC_SUCCESS) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1592,7 +1592,7 @@ int wolfTPM2_StartSession(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session,
|
||||||
authSesIn.symmetric.algorithm = TPM_ALG_NULL;
|
authSesIn.symmetric.algorithm = TPM_ALG_NULL;
|
||||||
}
|
}
|
||||||
authSesIn.nonceCaller.size = hashDigestSz;
|
authSesIn.nonceCaller.size = hashDigestSz;
|
||||||
rc = TPM2_GetNonce(authSesIn.nonceCaller.buffer,
|
rc = TPM2_GetNonceNoLock(authSesIn.nonceCaller.buffer,
|
||||||
authSesIn.nonceCaller.size);
|
authSesIn.nonceCaller.size);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
#ifdef DEBUG_WOLFTPM
|
#ifdef DEBUG_WOLFTPM
|
||||||
|
@ -1604,7 +1604,7 @@ int wolfTPM2_StartSession(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session,
|
||||||
if (authSesIn.tpmKey != TPM_RH_NULL) {
|
if (authSesIn.tpmKey != TPM_RH_NULL) {
|
||||||
/* Generate random salt */
|
/* Generate random salt */
|
||||||
session->salt.size = hashDigestSz;
|
session->salt.size = hashDigestSz;
|
||||||
rc = TPM2_GetNonce(session->salt.buffer, session->salt.size);
|
rc = TPM2_GetNonceNoLock(session->salt.buffer, session->salt.size);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -2481,6 +2481,7 @@ int wolfTPM2_ImportRsaPrivateKeySeed(WOLFTPM2_DEV* dev,
|
||||||
TPMI_ALG_RSA_SCHEME scheme, TPMI_ALG_HASH hashAlg, TPMA_OBJECT attributes,
|
TPMI_ALG_RSA_SCHEME scheme, TPMI_ALG_HASH hashAlg, TPMA_OBJECT attributes,
|
||||||
byte* seed, word32 seedSz)
|
byte* seed, word32 seedSz)
|
||||||
{
|
{
|
||||||
|
int rc = 0;
|
||||||
TPM2B_PUBLIC pub;
|
TPM2B_PUBLIC pub;
|
||||||
TPM2B_SENSITIVE sens;
|
TPM2B_SENSITIVE sens;
|
||||||
word32 digestSz;
|
word32 digestSz;
|
||||||
|
@ -2544,11 +2545,13 @@ int wolfTPM2_ImportRsaPrivateKeySeed(WOLFTPM2_DEV* dev,
|
||||||
else {
|
else {
|
||||||
/* assign random seed */
|
/* assign random seed */
|
||||||
sens.sensitiveArea.seedValue.size = digestSz;
|
sens.sensitiveArea.seedValue.size = digestSz;
|
||||||
TPM2_GetNonce(sens.sensitiveArea.seedValue.buffer,
|
rc = TPM2_GetNonceNoLock(sens.sensitiveArea.seedValue.buffer,
|
||||||
sens.sensitiveArea.seedValue.size);
|
sens.sensitiveArea.seedValue.size);
|
||||||
}
|
}
|
||||||
|
if (rc == 0) {
|
||||||
return wolfTPM2_ImportPrivateKey(dev, parentKey, keyBlob, &pub, &sens);
|
rc = wolfTPM2_ImportPrivateKey(dev, parentKey, keyBlob, &pub, &sens);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
int wolfTPM2_ImportRsaPrivateKey(WOLFTPM2_DEV* dev,
|
int wolfTPM2_ImportRsaPrivateKey(WOLFTPM2_DEV* dev,
|
||||||
const WOLFTPM2_KEY* parentKey, WOLFTPM2_KEYBLOB* keyBlob, const byte* rsaPub,
|
const WOLFTPM2_KEY* parentKey, WOLFTPM2_KEYBLOB* keyBlob, const byte* rsaPub,
|
||||||
|
@ -2633,6 +2636,7 @@ int wolfTPM2_ImportEccPrivateKeySeed(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* pare
|
||||||
const byte* eccPriv, word32 eccPrivSz,
|
const byte* eccPriv, word32 eccPrivSz,
|
||||||
TPMA_OBJECT attributes, byte* seed, word32 seedSz)
|
TPMA_OBJECT attributes, byte* seed, word32 seedSz)
|
||||||
{
|
{
|
||||||
|
int rc = 0;
|
||||||
TPM2B_PUBLIC pub;
|
TPM2B_PUBLIC pub;
|
||||||
TPM2B_SENSITIVE sens;
|
TPM2B_SENSITIVE sens;
|
||||||
word32 digestSz;
|
word32 digestSz;
|
||||||
|
@ -2696,11 +2700,14 @@ int wolfTPM2_ImportEccPrivateKeySeed(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* pare
|
||||||
else {
|
else {
|
||||||
/* assign random seed */
|
/* assign random seed */
|
||||||
sens.sensitiveArea.seedValue.size = digestSz;
|
sens.sensitiveArea.seedValue.size = digestSz;
|
||||||
TPM2_GetNonce(sens.sensitiveArea.seedValue.buffer,
|
rc = TPM2_GetNonceNoLock(sens.sensitiveArea.seedValue.buffer,
|
||||||
sens.sensitiveArea.seedValue.size);
|
sens.sensitiveArea.seedValue.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wolfTPM2_ImportPrivateKey(dev, parentKey, keyBlob, &pub, &sens);
|
if (rc == 0) {
|
||||||
|
rc = wolfTPM2_ImportPrivateKey(dev, parentKey, keyBlob, &pub, &sens);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wolfTPM2_ImportEccPrivateKey(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* parentKey,
|
int wolfTPM2_ImportEccPrivateKey(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* parentKey,
|
||||||
|
@ -3234,13 +3241,14 @@ int wolfTPM2_ImportPrivateKeyBuffer(WOLFTPM2_DEV* dev,
|
||||||
else {
|
else {
|
||||||
/* assign random seed */
|
/* assign random seed */
|
||||||
sens.sensitiveArea.seedValue.size = digestSz;
|
sens.sensitiveArea.seedValue.size = digestSz;
|
||||||
TPM2_GetNonce(sens.sensitiveArea.seedValue.buffer,
|
rc = TPM2_GetNonceNoLock(sens.sensitiveArea.seedValue.buffer,
|
||||||
sens.sensitiveArea.seedValue.size);
|
sens.sensitiveArea.seedValue.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
/* Import Private Key */
|
/* Import Private Key */
|
||||||
rc = wolfTPM2_ImportPrivateKey(dev, parentKey, keyBlob, pub, &sens);
|
rc = wolfTPM2_ImportPrivateKey(dev, parentKey, keyBlob, pub, &sens);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WOLFTPM2_PEM_DECODE
|
#ifdef WOLFTPM2_PEM_DECODE
|
||||||
|
@ -3748,7 +3756,7 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
||||||
int sigOutSz = 0;
|
int sigOutSz = 0;
|
||||||
|
|
||||||
if (dev == NULL || key == NULL || digest == NULL || sig == NULL ||
|
if (dev == NULL || key == NULL || digest == NULL || sig == NULL ||
|
||||||
sigSz == NULL) {
|
sigSz == NULL) {
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3764,10 +3772,24 @@ int wolfTPM2_SignHashScheme(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
||||||
/* set session auth for key */
|
/* set session auth for key */
|
||||||
wolfTPM2_SetAuthHandle(dev, 0, &key->handle);
|
wolfTPM2_SetAuthHandle(dev, 0, &key->handle);
|
||||||
|
|
||||||
|
/* verify input cannot exceed buffer */
|
||||||
|
if (digestSz > (int)sizeof(signIn.digest.buffer))
|
||||||
|
digestSz = (int)sizeof(signIn.digest.buffer);
|
||||||
|
|
||||||
XMEMSET(&signIn, 0, sizeof(signIn));
|
XMEMSET(&signIn, 0, sizeof(signIn));
|
||||||
signIn.keyHandle = key->handle.hndl;
|
signIn.keyHandle = key->handle.hndl;
|
||||||
signIn.digest.size = digestSz;
|
signIn.digest.size = TPM2_GetHashDigestSize(hashAlg);
|
||||||
XMEMCPY(signIn.digest.buffer, digest, signIn.digest.size);
|
if (signIn.digest.size <= 0) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
/* if digest provided is smaller than key size then zero pad leading */
|
||||||
|
if (digestSz < signIn.digest.size) {
|
||||||
|
XMEMCPY(&signIn.digest.buffer[signIn.digest.size - digestSz], digest,
|
||||||
|
digestSz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
XMEMCPY(signIn.digest.buffer, digest, digestSz);
|
||||||
|
}
|
||||||
signIn.inScheme.scheme = sigAlg;
|
signIn.inScheme.scheme = sigAlg;
|
||||||
signIn.inScheme.details.any.hashAlg = hashAlg;
|
signIn.inScheme.details.any.hashAlg = hashAlg;
|
||||||
signIn.validation.tag = TPM_ST_HASHCHECK;
|
signIn.validation.tag = TPM_ST_HASHCHECK;
|
||||||
|
@ -3910,8 +3932,18 @@ int wolfTPM2_VerifyHashTicket(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
||||||
|
|
||||||
XMEMSET(&verifySigIn, 0, sizeof(verifySigIn));
|
XMEMSET(&verifySigIn, 0, sizeof(verifySigIn));
|
||||||
verifySigIn.keyHandle = key->handle.hndl;
|
verifySigIn.keyHandle = key->handle.hndl;
|
||||||
verifySigIn.digest.size = digestSz;
|
verifySigIn.digest.size = TPM2_GetHashDigestSize(hashAlg);
|
||||||
XMEMCPY(verifySigIn.digest.buffer, digest, digestSz);
|
if (verifySigIn.digest.size <= 0) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
/* if digest provided is smaller than key size then zero pad leading */
|
||||||
|
if (digestSz < verifySigIn.digest.size) {
|
||||||
|
XMEMCPY(&verifySigIn.digest.buffer[verifySigIn.digest.size - digestSz],
|
||||||
|
digest, digestSz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
XMEMCPY(verifySigIn.digest.buffer, digest, digestSz);
|
||||||
|
}
|
||||||
verifySigIn.signature.sigAlg = sigAlg;
|
verifySigIn.signature.sigAlg = sigAlg;
|
||||||
verifySigIn.signature.signature.any.hashAlg = hashAlg;
|
verifySigIn.signature.signature.any.hashAlg = hashAlg;
|
||||||
if (key->pub.publicArea.type == TPM_ALG_ECC) {
|
if (key->pub.publicArea.type == TPM_ALG_ECC) {
|
||||||
|
@ -5776,7 +5808,7 @@ int wolfTPM2_ChangeHierarchyAuth(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = TPM2_GetNonce(in.newAuth.buffer, in.newAuth.size);
|
rc = TPM2_GetNonceNoLock(in.newAuth.buffer, in.newAuth.size);
|
||||||
}
|
}
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = TPM2_HierarchyChangeAuth(&in);
|
rc = TPM2_HierarchyChangeAuth(&in);
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <wolftpm/tpm2.h>
|
#include <wolftpm/tpm2.h>
|
||||||
#include <wolftpm/tpm2_wrap.h>
|
#include <wolftpm/tpm2_wrap.h>
|
||||||
#include <wolftpm/tpm2_param_enc.h>
|
#include <wolftpm/tpm2_param_enc.h>
|
||||||
|
#include <wolftpm/tpm2_asn.h>
|
||||||
|
|
||||||
#include <hal/tpm_io.h>
|
#include <hal/tpm_io.h>
|
||||||
#include <examples/tpm_test.h>
|
#include <examples/tpm_test.h>
|
||||||
|
@ -100,7 +101,8 @@ static void test_wolfTPM2_Init(void)
|
||||||
AssertIntNE(rc, 0);
|
AssertIntNE(rc, 0);
|
||||||
/* Test second argument, TPM2 IO Callbacks */
|
/* Test second argument, TPM2 IO Callbacks */
|
||||||
rc = wolfTPM2_Init(&dev, NULL, NULL);
|
rc = wolfTPM2_Init(&dev, NULL, NULL);
|
||||||
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || defined(WOLFTPM_WINAPI)
|
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || \
|
||||||
|
defined(WOLFTPM_WINAPI)
|
||||||
/* Custom IO Callbacks are not needed for Linux TIS driver */
|
/* Custom IO Callbacks are not needed for Linux TIS driver */
|
||||||
AssertIntEQ(rc, 0);
|
AssertIntEQ(rc, 0);
|
||||||
#else
|
#else
|
||||||
|
@ -275,11 +277,12 @@ static void test_TPM2_PCRSel(void)
|
||||||
|
|
||||||
/* Test bad case - invalid PCR */
|
/* Test bad case - invalid PCR */
|
||||||
XMEMSET(&pcr, 0, sizeof(pcr));
|
XMEMSET(&pcr, 0, sizeof(pcr));
|
||||||
pcrArray[0] = PCR_SELECT_MAX+1;
|
pcrArray[0] = PCR_LAST+1;
|
||||||
TPM2_SetupPCRSelArray(&pcr, TPM_ALG_SHA256, pcrArray, 1);
|
TPM2_SetupPCRSelArray(&pcr, TPM_ALG_SHA256, pcrArray, 1);
|
||||||
if (pcr.count != 0) {
|
if (pcr.count != 0) {
|
||||||
rc = BAD_FUNC_ARG;
|
rc = BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
/* Test bad case - too many hash algorithms */
|
/* Test bad case - too many hash algorithms */
|
||||||
XMEMSET(&pcr, 0, sizeof(pcr));
|
XMEMSET(&pcr, 0, sizeof(pcr));
|
||||||
|
@ -294,6 +297,7 @@ static void test_TPM2_PCRSel(void)
|
||||||
if (pcr.count != HASH_COUNT) {
|
if (pcr.count != HASH_COUNT) {
|
||||||
rc = BAD_FUNC_ARG;
|
rc = BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
printf("Test TPM Wrapper:\tPCR Select Array:\t%s\n",
|
printf("Test TPM Wrapper:\tPCR Select Array:\t%s\n",
|
||||||
rc == 0 ? "Passed" : "Failed");
|
rc == 0 ? "Passed" : "Failed");
|
||||||
|
@ -345,7 +349,8 @@ static void test_TPM2_KDFa(void)
|
||||||
0xd7, 0x04, 0xb6, 0x9a, 0x90, 0x2e, 0x9a, 0xde, 0x84, 0xc4};
|
0xd7, 0x04, 0xb6, 0x9a, 0x90, 0x2e, 0x9a, 0xde, 0x84, 0xc4};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc = TPM2_KDFa(TPM_ALG_SHA256, &keyIn, label, &contextU, &contextV, key, keyIn.size);
|
rc = TPM2_KDFa(TPM_ALG_SHA256, &keyIn, label, &contextU, &contextV, key,
|
||||||
|
keyIn.size);
|
||||||
#ifdef WOLFTPM2_NO_WOLFCRYPT
|
#ifdef WOLFTPM2_NO_WOLFCRYPT
|
||||||
AssertIntEQ(NOT_COMPILED_IN, rc);
|
AssertIntEQ(NOT_COMPILED_IN, rc);
|
||||||
#else
|
#else
|
||||||
|
@ -396,6 +401,172 @@ static void test_wolfTPM2_CSR(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \
|
||||||
|
!defined(WOLFTPM2_NO_ASN)
|
||||||
|
static void test_wolfTPM2_EccSignVerifyDig(WOLFTPM2_DEV* dev,
|
||||||
|
WOLFTPM2_KEY* storageKey, const byte* digest, int digestSz,
|
||||||
|
TPM_ECC_CURVE curve, TPMI_ALG_HASH hashAlg)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int verifyRes = 0;
|
||||||
|
WOLFTPM2_KEY eccKey;
|
||||||
|
TPMT_PUBLIC publicTemplate;
|
||||||
|
byte sigRs[MAX_ECC_BYTES*2];
|
||||||
|
word32 sigRsSz = (word32)sizeof(sigRs);
|
||||||
|
byte sig[ECC_MAX_SIG_SIZE];
|
||||||
|
word32 sigSz;
|
||||||
|
byte *r, *s;
|
||||||
|
word32 rLen, sLen;
|
||||||
|
ecc_key wolfKey;
|
||||||
|
int curveSize = TPM2_GetCurveSize(curve);
|
||||||
|
|
||||||
|
/* -- Use TPM key to sign and verify with wolfCrypt -- */
|
||||||
|
/* Create ECC key for signing */
|
||||||
|
rc = wolfTPM2_GetKeyTemplate_ECC_ex(&publicTemplate, hashAlg,
|
||||||
|
(TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
|
||||||
|
TPMA_OBJECT_sign | TPMA_OBJECT_noDA),
|
||||||
|
curve, TPM_ALG_ECDSA, hashAlg);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
rc = wolfTPM2_CreateAndLoadKey(dev, &eccKey, &storageKey->handle,
|
||||||
|
&publicTemplate, (byte*)gKeyAuth, sizeof(gKeyAuth)-1);
|
||||||
|
if ((rc & TPM_RC_HASH) == TPM_RC_HASH) {
|
||||||
|
printf("Hash type not supported... Skipping\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Sign with TPM */
|
||||||
|
rc = wolfTPM2_SignHashScheme(dev, &eccKey, digest, digestSz,
|
||||||
|
sigRs, (int*)&sigRsSz, TPM_ALG_ECDSA, hashAlg);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Make sure leading zero's not required are trimmed */
|
||||||
|
rLen = sLen = sigRsSz / 2;
|
||||||
|
r = &sigRs[0];
|
||||||
|
s = &sigRs[rLen];
|
||||||
|
r = TPM2_ASN_TrimZeros(r, &rLen);
|
||||||
|
s = TPM2_ASN_TrimZeros(s, &sLen);
|
||||||
|
|
||||||
|
/* Encode ECDSA Header */
|
||||||
|
sigSz = (word32)sizeof(sig);
|
||||||
|
rc = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen, sig, &sigSz);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Initialize wolfCrypt ECC key */
|
||||||
|
rc = wc_ecc_init(&wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Convert TPM key to wolfCrypt key for verification */
|
||||||
|
rc = wolfTPM2_EccKey_TpmToWolf(dev, &eccKey, &wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Verify TPM signature with wolfCrypt */
|
||||||
|
rc = wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verifyRes, &wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
AssertIntEQ(verifyRes, 1); /* 1 indicates successful verification */
|
||||||
|
|
||||||
|
/* Cleanup first wolfCrypt key */
|
||||||
|
wc_ecc_free(&wolfKey);
|
||||||
|
wolfTPM2_UnloadHandle(dev, &eccKey.handle);
|
||||||
|
|
||||||
|
|
||||||
|
/* -- Use wolfCrypt key to sign and verify with TPM -- */
|
||||||
|
/* Initialize new wolfCrypt ECC key */
|
||||||
|
rc = wc_ecc_init(&wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Generate new ECC key with wolfCrypt */
|
||||||
|
rc = wc_ecc_make_key(wolfTPM2_GetRng(dev), curveSize, &wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Sign with wolfCrypt */
|
||||||
|
sigSz = (word32)sizeof(sig);
|
||||||
|
rc = wc_ecc_sign_hash(digest, digestSz, sig, &sigSz, wolfTPM2_GetRng(dev),
|
||||||
|
&wolfKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Decode ECDSA Header */
|
||||||
|
r = sigRs;
|
||||||
|
s = &sigRs[MAX_ECC_BYTES];
|
||||||
|
rLen = sLen = MAX_ECC_BYTES;
|
||||||
|
rc = wc_ecc_sig_to_rs(sig,
|
||||||
|
sigSz, r, &rLen, s, &sLen);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Convert wolfCrypt key to TPM key for verification */
|
||||||
|
rc = wolfTPM2_EccKey_WolfToTpm(dev, &wolfKey, &eccKey);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* combine R and S at key size (zero pad leading) */
|
||||||
|
XMEMCPY(&sigRs[curveSize-rLen], r, rLen);
|
||||||
|
XMEMSET(&sigRs[0], 0, curveSize-rLen);
|
||||||
|
XMEMCPY(&sigRs[curveSize + (curveSize-sLen)], s, sLen);
|
||||||
|
XMEMSET(&sigRs[curveSize], 0, curveSize-sLen);
|
||||||
|
|
||||||
|
/* Verify wolfCrypt signature with TPM */
|
||||||
|
rc = wolfTPM2_VerifyHashScheme(dev, &eccKey, sigRs, curveSize*2,
|
||||||
|
digest, digestSz, TPM_ALG_ECDSA, hashAlg);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
wc_ecc_free(&wolfKey);
|
||||||
|
wolfTPM2_UnloadHandle(dev, &eccKey.handle);
|
||||||
|
|
||||||
|
printf("Test TPM Wrapper:\t"
|
||||||
|
"Sign/Verify (DigSz=%d, CurveSz=%d, Hash=%s):"
|
||||||
|
"\t%s\n",
|
||||||
|
digestSz, TPM2_GetCurveSize(curve), TPM2_GetAlgName(hashAlg),
|
||||||
|
rc == 0 ? "Passed" : "Failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test with smaller, same and larger digest sizes using different ECC curves.
|
||||||
|
* Interop sign and verify with wolfCrypt and TPM */
|
||||||
|
static void test_wolfTPM2_EccSignVerify(void)
|
||||||
|
{
|
||||||
|
int rc, i;
|
||||||
|
byte digest[TPM_MAX_DIGEST_SIZE];
|
||||||
|
WOLFTPM2_DEV dev;
|
||||||
|
WOLFTPM2_KEY storageKey;
|
||||||
|
|
||||||
|
/* Initialize TPM */
|
||||||
|
rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
/* Create storage key */
|
||||||
|
rc = wolfTPM2_CreateSRK(&dev, &storageKey, TPM_ALG_ECC,
|
||||||
|
(byte*)gStorageKeyAuth, sizeof(gStorageKeyAuth)-1);
|
||||||
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < (int)sizeof(digest); i++) {
|
||||||
|
digest[i] = (byte)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 20,
|
||||||
|
TPM_ECC_NIST_P256, TPM_ALG_SHA256);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 32,
|
||||||
|
TPM_ECC_NIST_P256, TPM_ALG_SHA256);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 48,
|
||||||
|
TPM_ECC_NIST_P256, TPM_ALG_SHA256);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 64,
|
||||||
|
TPM_ECC_NIST_P256, TPM_ALG_SHA256);
|
||||||
|
|
||||||
|
#if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 20,
|
||||||
|
TPM_ECC_NIST_P384, TPM_ALG_SHA384);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 32,
|
||||||
|
TPM_ECC_NIST_P384, TPM_ALG_SHA384);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 48,
|
||||||
|
TPM_ECC_NIST_P384, TPM_ALG_SHA384);
|
||||||
|
test_wolfTPM2_EccSignVerifyDig(&dev, &storageKey, digest, 64,
|
||||||
|
TPM_ECC_NIST_P384, TPM_ALG_SHA384);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wolfTPM2_UnloadHandle(&dev, &storageKey.handle);
|
||||||
|
wolfTPM2_Cleanup(&dev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFTPM2_PEM_DECODE) && \
|
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFTPM2_PEM_DECODE) && \
|
||||||
!defined(NO_RSA)
|
!defined(NO_RSA)
|
||||||
static WOLFTPM2_KEY authKey; /* also used for test_wolfTPM2_PCRPolicy */
|
static WOLFTPM2_KEY authKey; /* also used for test_wolfTPM2_PCRPolicy */
|
||||||
|
@ -479,7 +650,8 @@ static void test_wolfTPM2_PCRPolicy(void)
|
||||||
digest, &digestSz, NULL, 0);
|
digest, &digestSz, NULL, 0);
|
||||||
AssertIntEQ(rc, 0);
|
AssertIntEQ(rc, 0);
|
||||||
|
|
||||||
AssertIntEQ(XMEMCMP(digest, expectedPolicyAuth, sizeof(expectedPolicyAuth)), 0);
|
AssertIntEQ(XMEMCMP(digest, expectedPolicyAuth, sizeof(expectedPolicyAuth)),
|
||||||
|
0);
|
||||||
|
|
||||||
rc = wolfTPM2_ResetPCR(&dev, pcrIndex);
|
rc = wolfTPM2_ResetPCR(&dev, pcrIndex);
|
||||||
AssertIntEQ(rc, 0);
|
AssertIntEQ(rc, 0);
|
||||||
|
@ -679,6 +851,10 @@ int unit_tests(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
test_wolfTPM2_KeyBlob(TPM_ALG_RSA);
|
test_wolfTPM2_KeyBlob(TPM_ALG_RSA);
|
||||||
test_wolfTPM2_KeyBlob(TPM_ALG_ECC);
|
test_wolfTPM2_KeyBlob(TPM_ALG_ECC);
|
||||||
|
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(HAVE_ECC) && \
|
||||||
|
!defined(WOLFTPM2_NO_ASN)
|
||||||
|
test_wolfTPM2_EccSignVerify();
|
||||||
|
#endif
|
||||||
test_wolfTPM2_Cleanup();
|
test_wolfTPM2_Cleanup();
|
||||||
test_wolfTPM2_thread_local_storage();
|
test_wolfTPM2_thread_local_storage();
|
||||||
#endif /* !WOLFTPM2_NO_WRAPPER */
|
#endif /* !WOLFTPM2_NO_WRAPPER */
|
||||||
|
|
|
@ -3434,7 +3434,9 @@ WOLFTPM_API TPMI_ALG_HASH TPM2_GetTpmHashType(int hashType);
|
||||||
/*!
|
/*!
|
||||||
\ingroup TPM2_Proprietary
|
\ingroup TPM2_Proprietary
|
||||||
\brief Generate a fresh nonce of random numbers
|
\brief Generate a fresh nonce of random numbers
|
||||||
\note Can use the TPM random number generator if WOLFTPM2_USE_HW_RNG is defined
|
\note Can use the TPM random number generator if WOLFTPM2_USE_HW_RNG is defined.
|
||||||
|
To force use of the TPM's RNG use WOLFTPM2_USE_HW_RNG. Please make sure you
|
||||||
|
have parameter encryption enabled to protect the RNG data over the bus.
|
||||||
|
|
||||||
\return TPM_RC_SUCCESS: successful
|
\return TPM_RC_SUCCESS: successful
|
||||||
\return TPM_RC_FAILURE: generic failure (TPM IO issue or wolfcrypt configuration)
|
\return TPM_RC_FAILURE: generic failure (TPM IO issue or wolfcrypt configuration)
|
||||||
|
@ -3456,6 +3458,9 @@ WOLFTPM_API TPMI_ALG_HASH TPM2_GetTpmHashType(int hashType);
|
||||||
*/
|
*/
|
||||||
WOLFTPM_API int TPM2_GetNonce(byte* nonceBuf, int nonceSz);
|
WOLFTPM_API int TPM2_GetNonce(byte* nonceBuf, int nonceSz);
|
||||||
|
|
||||||
|
/* Internal API for getting nonce without taking lock */
|
||||||
|
WOLFTPM_LOCAL int TPM2_GetNonceNoLock(byte* nonceBuf, int nonceSz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\ingroup TPM2_Proprietary
|
\ingroup TPM2_Proprietary
|
||||||
\brief Helper function to prepare a correct PCR selection
|
\brief Helper function to prepare a correct PCR selection
|
||||||
|
|
|
@ -80,8 +80,9 @@ typedef struct DecodedX509 {
|
||||||
\param maxIdx Maximum allowed index in buffer
|
\param maxIdx Maximum allowed index in buffer
|
||||||
\return Length on success, TPM_RC_INSUFFICIENT on buffer error
|
\return Length on success, TPM_RC_INSUFFICIENT on buffer error
|
||||||
*/
|
*/
|
||||||
WOLFTPM_API int TPM2_ASN_GetLength(const uint8_t* input, word32* inOutIdx, int* len,
|
WOLFTPM_API int TPM2_ASN_GetLength(const uint8_t* input, word32* inOutIdx,
|
||||||
word32 maxIdx);
|
int* len, word32 maxIdx);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\ingroup ASN
|
\ingroup ASN
|
||||||
\brief Decodes ASN.1 length with optional length checking
|
\brief Decodes ASN.1 length with optional length checking
|
||||||
|
@ -92,8 +93,9 @@ WOLFTPM_API int TPM2_ASN_GetLength(const uint8_t* input, word32* inOutIdx, int*
|
||||||
\param check Flag to enable length validation
|
\param check Flag to enable length validation
|
||||||
\return Length on success, TPM_RC_INSUFFICIENT on buffer error
|
\return Length on success, TPM_RC_INSUFFICIENT on buffer error
|
||||||
*/
|
*/
|
||||||
WOLFTPM_API int TPM2_ASN_GetLength_ex(const uint8_t* input, word32* inOutIdx, int* len,
|
WOLFTPM_API int TPM2_ASN_GetLength_ex(const uint8_t* input, word32* inOutIdx,
|
||||||
word32 maxIdx, int check);
|
int* len, word32 maxIdx, int check);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\ingroup ASN
|
\ingroup ASN
|
||||||
\brief Decodes ASN.1 tag and validates length
|
\brief Decodes ASN.1 tag and validates length
|
||||||
|
@ -104,15 +106,19 @@ WOLFTPM_API int TPM2_ASN_GetLength_ex(const uint8_t* input, word32* inOutIdx, in
|
||||||
\param tag Expected ASN.1 tag value
|
\param tag Expected ASN.1 tag value
|
||||||
\return 0 on success, TPM_RC_INSUFFICIENT on buffer error, TPM_RC_VALUE on tag mismatch
|
\return 0 on success, TPM_RC_INSUFFICIENT on buffer error, TPM_RC_VALUE on tag mismatch
|
||||||
*/
|
*/
|
||||||
WOLFTPM_API int TPM2_ASN_DecodeTag(const uint8_t* input, int inputSz, int* inOutIdx, int* tag_len, uint8_t tag);
|
WOLFTPM_API int TPM2_ASN_DecodeTag(const uint8_t* input, int inputSz,
|
||||||
|
int* inOutIdx, int* tag_len, uint8_t tag);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\ingroup ASN
|
\ingroup ASN
|
||||||
\brief Decodes RSA signature from ASN.1 format
|
\brief Decodes RSA signature from ASN.1 format
|
||||||
\param pInput Pointer to buffer containing ASN.1 encoded RSA signature
|
\param pInput Pointer to buffer containing ASN.1 encoded RSA signature
|
||||||
\param inputSz Size of input buffer
|
\param inputSz Size of input buffer
|
||||||
\return Size of decoded signature on success, TPM_RC_VALUE on invalid input, TPM_RC_INSUFFICIENT on buffer error
|
\return Size of decoded signature on success, TPM_RC_VALUE on invalid input,
|
||||||
|
TPM_RC_INSUFFICIENT on buffer error
|
||||||
*/
|
*/
|
||||||
WOLFTPM_API int TPM2_ASN_RsaDecodeSignature(uint8_t** pInput, int inputSz);
|
WOLFTPM_API int TPM2_ASN_RsaDecodeSignature(uint8_t** pInput, int inputSz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Decodes an X.509 certificate
|
\brief Decodes an X.509 certificate
|
||||||
\param input Buffer containing ASN.1 encoded X.509 certificate
|
\param input Buffer containing ASN.1 encoded X.509 certificate
|
||||||
|
@ -120,25 +126,40 @@ WOLFTPM_API int TPM2_ASN_RsaDecodeSignature(uint8_t** pInput, int inputSz);
|
||||||
\param x509 Structure to store decoded certificate data
|
\param x509 Structure to store decoded certificate data
|
||||||
\return 0 on success, TPM_RC_VALUE on invalid input, TPM_RC_INSUFFICIENT on buffer error
|
\return 0 on success, TPM_RC_VALUE on invalid input, TPM_RC_INSUFFICIENT on buffer error
|
||||||
*/
|
*/
|
||||||
WOLFTPM_API int TPM2_ASN_DecodeX509Cert(uint8_t* input, int inputSz, DecodedX509* x509);
|
WOLFTPM_API int TPM2_ASN_DecodeX509Cert(uint8_t* input, int inputSz,
|
||||||
|
DecodedX509* x509);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\ingroup ASN
|
\ingroup ASN
|
||||||
\brief Decodes RSA public key from ASN.1 format into TPM2B_PUBLIC structure
|
\brief Decodes RSA public key from ASN.1 format into TPM2B_PUBLIC structure
|
||||||
\param input Buffer containing ASN.1 encoded RSA public key
|
\param input Buffer containing ASN.1 encoded RSA public key
|
||||||
\param inputSz Size of input buffer
|
\param inputSz Size of input buffer
|
||||||
\param pub TPM2B_PUBLIC structure to store decoded key
|
\param pub TPM2B_PUBLIC structure to store decoded key
|
||||||
\return 0 on success, TPM_RC_VALUE on invalid input, TPM_RC_INSUFFICIENT on buffer error
|
\return 0 on success, TPM_RC_VALUE on invalid input,
|
||||||
|
TPM_RC_INSUFFICIENT on buffer error
|
||||||
*/
|
*/
|
||||||
WOLFTPM_API int TPM2_ASN_DecodeRsaPubKey(uint8_t* input, int inputSz, TPM2B_PUBLIC* pub);
|
WOLFTPM_API int TPM2_ASN_DecodeRsaPubKey(uint8_t* input, int inputSz,
|
||||||
|
TPM2B_PUBLIC* pub);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\ingroup ASN
|
\ingroup ASN
|
||||||
\brief Removes PKCS#1 v1.5 padding from RSA signature
|
\brief Removes PKCS#1 v1.5 padding from RSA signature
|
||||||
\param pSig Pointer to buffer containing padded signature, updated to point to unpadded data
|
\param pSig Pointer to buffer containing padded signature, updated to point
|
||||||
|
to unpadded data
|
||||||
\param sigSz Size of signature buffer, updated with unpadded size
|
\param sigSz Size of signature buffer, updated with unpadded size
|
||||||
\return 0 on success, TPM_RC_VALUE on invalid padding
|
\return 0 on success, TPM_RC_VALUE on invalid padding
|
||||||
*/
|
*/
|
||||||
WOLFTPM_API int TPM2_ASN_RsaUnpadPkcsv15(uint8_t** pSig, int* sigSz);
|
WOLFTPM_API int TPM2_ASN_RsaUnpadPkcsv15(uint8_t** pSig, int* sigSz);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup ASN
|
||||||
|
\brief Removes leading zero bytes from a buffer
|
||||||
|
\param in Pointer to input buffer containing data to trim
|
||||||
|
\param len Pointer to length of input buffer, updated with new length after trimming
|
||||||
|
\return Pointer to the trimmed buffer (may be same as input if no trimming needed)
|
||||||
|
*/
|
||||||
|
WOLFTPM_API byte* TPM2_ASN_TrimZeros(byte* in, word32* len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue