mirror of https://github.com/wolfSSL/wolfTPM.git
Merge pull request #491 from aidangarske/fenrir-fixes-9
fwTPM/SPDM/src corrections and unit test additionspull/492/head
commit
423ce0dc71
|
|
@ -63,7 +63,7 @@
|
|||
#define LOG(t) { printf(__FILE__":%i: %s\n", __LINE__, t); }
|
||||
|
||||
#define READ_BE16(dest, buf, size, off) { \
|
||||
if (off + sizeof(dest) >= size) { \
|
||||
if (off + sizeof(dest) > size) { \
|
||||
LOG("FW file too short"); \
|
||||
return -1; \
|
||||
} \
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
}
|
||||
|
||||
#define READ_BE32(dest, buf, size, off) { \
|
||||
if (off + sizeof(dest) >= size) { \
|
||||
if (off + sizeof(dest) > size) { \
|
||||
LOG("FW file too short"); \
|
||||
return -1; \
|
||||
} \
|
||||
|
|
@ -172,7 +172,7 @@ static int extractFW(
|
|||
}
|
||||
|
||||
READ_BE32(size32, fw, fw_size, offset);
|
||||
if (offset + size32 >= fw_size) {
|
||||
if (offset + size32 > fw_size) {
|
||||
LOG("FW file too short");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ int TPM2_IFX_Firmware_Update(void* userCtx, int argc, char *argv[])
|
|||
else {
|
||||
printf("Success: Please reset or power cycle TPM\n");
|
||||
}
|
||||
return rc;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (manifest_file == NULL || firmware_file == NULL) {
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ int TPM2_ST33_Firmware_Update(void* userCtx, int argc, char *argv[])
|
|||
else {
|
||||
printf("Success: Please reset or power cycle TPM\n");
|
||||
}
|
||||
return rc;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (fi_file == NULL) {
|
||||
|
|
|
|||
|
|
@ -98,12 +98,17 @@ int TPM2_PCR_Quote_Test(void* userCtx, int argc, char *argv[])
|
|||
|
||||
/* Advanced usage */
|
||||
if (argv[1][0] != '-') {
|
||||
if (pcrIndex < 0 || pcrIndex > 23 || *argv[1] < '0' || *argv[1] > '9') {
|
||||
if (*argv[1] < '0' || *argv[1] > '9') {
|
||||
printf("PCR index is out of range (0-23)\n");
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
pcrIndex = XATOI(argv[1]);
|
||||
if (pcrIndex < 0 || pcrIndex > 23) {
|
||||
printf("PCR index is out of range (0-23)\n");
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (argc >= 3 && argv[2][0] != '-')
|
||||
outputFile = argv[2];
|
||||
|
|
|
|||
|
|
@ -115,10 +115,14 @@ static int PKCS7_SignVerifyEx(WOLFTPM2_DEV* dev, int tpmDevId,
|
|||
|
||||
XMEMSET(&pkcs7, 0, sizeof(pkcs7));
|
||||
|
||||
hashSz = wc_HashGetDigestSize(hashType);
|
||||
if (hashSz <= 0) {
|
||||
return hashSz;
|
||||
rc = wc_HashGetDigestSize(hashType);
|
||||
if (rc <= 0) {
|
||||
/* Preserve the wolfCrypt error on negatives; for a 0 return
|
||||
* (not currently produced by wolfCrypt), report BAD_FUNC_ARG
|
||||
* rather than masquerading as success. */
|
||||
return (rc < 0) ? rc : BAD_FUNC_ARG;
|
||||
}
|
||||
hashSz = (word32)rc;
|
||||
|
||||
/* calculate hash for content */
|
||||
rc = wc_HashInit(&hash, hashType);
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@
|
|||
#include <Qspi/SpiMaster/IfxQspi_SpiMaster.h>
|
||||
|
||||
/* externally declared SPI master channel */
|
||||
extern IfxQspi_SpiMaster_Channel spiMasterChannel
|
||||
extern IfxQspi_SpiMaster_Channel spiMasterChannel;
|
||||
|
||||
static int TPM2_IoCb_Infineon_TriCore_SPI(TPM2_CTX* ctx, const byte* txBuf,
|
||||
byte* rxBuf, word16 xferSz, void* userCtx)
|
||||
|
|
|
|||
|
|
@ -223,6 +223,8 @@
|
|||
return -1;
|
||||
}
|
||||
|
||||
busy_retry = TPM_I2C_TRIES;
|
||||
|
||||
while (I2C_BB_IsBusy() && --busy_retry > 0) {
|
||||
microchip_wait(250);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -429,6 +429,46 @@ static void FwLookupEntityAuth(FWTPM_CTX* ctx, TPM_HANDLE handle,
|
|||
}
|
||||
}
|
||||
|
||||
/* Constant-time password vs authValue comparison.
|
||||
* Iterates a fixed upper bound (TPM_MAX_DIGEST_SIZE) with bitwise masks so
|
||||
* neither the trip count nor per-iteration work depends on the secret
|
||||
* authValSz. Trailing zeros on either side are treated as insignificant
|
||||
* (matches TCG reference for authValues padded to nameAlg digest size).
|
||||
* Returns 1 on mismatch, 0 on match. Precondition: pwSz and avSz must
|
||||
* each be <= TPM_MAX_DIGEST_SIZE; out-of-range inputs fail closed. */
|
||||
static int FwCtAuthCompare(const byte* password, int pwSz,
|
||||
const byte* authVal, int avSz)
|
||||
{
|
||||
byte zeroAuth[TPM_MAX_DIGEST_SIZE];
|
||||
const byte* avPtr;
|
||||
volatile byte diff = 0;
|
||||
int ci;
|
||||
|
||||
if (pwSz < 0 || avSz < 0 ||
|
||||
pwSz > TPM_MAX_DIGEST_SIZE || avSz > TPM_MAX_DIGEST_SIZE) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
XMEMSET(zeroAuth, 0, sizeof(zeroAuth));
|
||||
avPtr = (authVal != NULL) ? authVal : zeroAuth;
|
||||
|
||||
for (ci = 0; ci < TPM_MAX_DIGEST_SIZE; ci++) {
|
||||
/* 0xFF if ci < bound, else 0x00. Use UINT32 (guaranteed 32-bit
|
||||
* wolfTPM typedef) so the >> 31 shift is always well-defined. */
|
||||
byte pwMask = (byte)-((UINT32)(ci - pwSz) >> 31);
|
||||
byte avMask = (byte)-((UINT32)(ci - avSz) >> 31);
|
||||
byte overlap = (byte)(pwMask & avMask);
|
||||
/* Overlap region: bytes must match */
|
||||
diff |= (byte)((password[ci] ^ avPtr[ci]) & overlap);
|
||||
/* Trailing bytes of pw past avSz must be zero */
|
||||
diff |= (byte)(password[ci] & (pwMask & (byte)~avMask));
|
||||
/* Trailing bytes of av past pwSz must be zero */
|
||||
diff |= (byte)(avPtr[ci] & (avMask & (byte)~pwMask));
|
||||
}
|
||||
|
||||
return ((int)diff != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Compute cpHash = H(commandCode || name1 || ... || cpBuffer)
|
||||
* Per TPM 2.0 Part 1 Section 18.7 */
|
||||
static int FwComputeCpHash(TPMI_ALG_HASH hashAlg, TPM_CC cmdCode,
|
||||
|
|
@ -9975,6 +10015,7 @@ static TPM_RC FwCmd_NV_DefineSpace(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
FwRspNoParams(rsp, cmdTag);
|
||||
}
|
||||
|
||||
TPM2_ForceZero(&auth, sizeof(auth));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -12719,9 +12760,7 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
|
|||
int doEncRsp = 0; /* Encrypt outgoing response param */
|
||||
#endif
|
||||
int pj, hj; /* Loop indices for auth validation */
|
||||
int pwSz, avSz, maxSz, minSz, authFail; /* Password comparison */
|
||||
volatile byte diff;
|
||||
int ci;
|
||||
int authFail; /* Password comparison result */
|
||||
|
||||
if (ctx == NULL || cmdBuf == NULL || rspBuf == NULL || rspSize == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
|
|
@ -13085,29 +13124,8 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
|
|||
|
||||
FwLookupEntityAuth(ctx, entityH, &authVal, &authValSz);
|
||||
|
||||
/* Compare password with authValue in constant time.
|
||||
* Per TCG reference implementation, trailing zeros are
|
||||
* insignificant (handles authValues padded to nameAlg
|
||||
* digest size). We compare up to the max of both sizes
|
||||
* and verify trailing bytes are zero, all in constant
|
||||
* time to avoid leaking the effective auth length. */
|
||||
diff = 0;
|
||||
pwSz = (int)cmdAuths[pj].passwordSize;
|
||||
avSz = authValSz;
|
||||
maxSz = (pwSz > avSz) ? pwSz : avSz;
|
||||
minSz = (pwSz < avSz) ? pwSz : avSz;
|
||||
/* Compare overlapping portion */
|
||||
for (ci = 0; ci < minSz; ci++) {
|
||||
diff |= cmdAuths[pj].password[ci] ^ authVal[ci];
|
||||
}
|
||||
/* Verify trailing bytes of the longer buffer are zero */
|
||||
for (ci = minSz; ci < maxSz; ci++) {
|
||||
if (ci < pwSz)
|
||||
diff |= cmdAuths[pj].password[ci];
|
||||
if (ci < avSz)
|
||||
diff |= authVal[ci];
|
||||
}
|
||||
authFail = ((int)diff != 0);
|
||||
authFail = FwCtAuthCompare(cmdAuths[pj].password,
|
||||
(int)cmdAuths[pj].passwordSize, authVal, authValSz);
|
||||
if (authFail) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("fwTPM: Password auth failed for handle "
|
||||
|
|
|
|||
|
|
@ -540,6 +540,178 @@ static int test_mitm_signature_rejected(void)
|
|||
TEST_PASS();
|
||||
}
|
||||
|
||||
/* Drive wolfSPDM_ParseKeyExchangeRsp past the signature check and exercise
|
||||
* the ResponderVerifyData HMAC compare. The fixture reuses a single P-384
|
||||
* key pair as both requester and responder identity so the test can
|
||||
* produce a signature that the parse path will accept; everything after
|
||||
* (ECDH, KDF, HMAC) then runs on real inputs. */
|
||||
static int test_key_exchange_rsp_hmac_check(void)
|
||||
{
|
||||
byte keRsp[300];
|
||||
const word32 keRspLen = 282;
|
||||
const word32 keRspPartialLen = 138;
|
||||
ecc_key ltKey;
|
||||
ecc_key respEphem;
|
||||
ecc_key ourPubKey;
|
||||
byte ltPriv[48], ltPubX[48], ltPubY[48], ltPub[96];
|
||||
word32 ltPrivSz = 48, ltPubXSz = 48, ltPubYSz = 48;
|
||||
byte respPubX[48], respPubY[48];
|
||||
word32 respPubXSz = 48, respPubYSz = 48;
|
||||
byte ourPubX[48], ourPubY[48];
|
||||
word32 ourXSz = 48, ourYSz = 48;
|
||||
byte sharedSecret[64];
|
||||
word32 sharedSz = sizeof(sharedSecret);
|
||||
byte signMsg[160];
|
||||
word32 signMsgLen = 0;
|
||||
byte th1SigHash[WOLFSPDM_HASH_SIZE];
|
||||
byte signMsgHash[WOLFSPDM_HASH_SIZE];
|
||||
byte th1[WOLFSPDM_HASH_SIZE];
|
||||
byte sigRaw[WOLFSPDM_ECC_SIG_SIZE];
|
||||
word32 sigRawSz = WOLFSPDM_ECC_SIG_SIZE;
|
||||
byte expectedHmac[WOLFSPDM_HASH_SIZE];
|
||||
const char* ctxStr = "responder-key_exchange_rsp signing";
|
||||
const word32 ctxStrLen = 34;
|
||||
word32 zeroPadLen;
|
||||
int i, rc;
|
||||
WOLFSPDM_CTX helperBuf;
|
||||
WOLFSPDM_CTX* helper = &helperBuf;
|
||||
TEST_CTX_SETUP_V12();
|
||||
|
||||
printf("test_key_exchange_rsp_hmac_check...\n");
|
||||
|
||||
/* Long-term P-384 key, shared between requester (for test signing)
|
||||
* and responder (for parse verification) */
|
||||
ASSERT_SUCCESS(wc_ecc_init(<Key));
|
||||
ASSERT_SUCCESS(wc_ecc_make_key(&ctx->rng, 48, <Key));
|
||||
ASSERT_SUCCESS(wc_ecc_export_private_only(<Key, ltPriv, <PrivSz));
|
||||
ASSERT_SUCCESS(wc_ecc_export_public_raw(<Key,
|
||||
ltPubX, <PubXSz, ltPubY, <PubYSz));
|
||||
if (ltPrivSz < 48) {
|
||||
XMEMMOVE(ltPriv + (48 - ltPrivSz), ltPriv, ltPrivSz);
|
||||
XMEMSET(ltPriv, 0, 48 - ltPrivSz);
|
||||
}
|
||||
if (ltPubXSz < 48) {
|
||||
XMEMMOVE(ltPubX + (48 - ltPubXSz), ltPubX, ltPubXSz);
|
||||
XMEMSET(ltPubX, 0, 48 - ltPubXSz);
|
||||
}
|
||||
if (ltPubYSz < 48) {
|
||||
XMEMMOVE(ltPubY + (48 - ltPubYSz), ltPubY, ltPubYSz);
|
||||
XMEMSET(ltPubY, 0, 48 - ltPubYSz);
|
||||
}
|
||||
XMEMCPY(ltPub, ltPubX, 48);
|
||||
XMEMCPY(ltPub + 48, ltPubY, 48);
|
||||
ASSERT_SUCCESS(wolfSPDM_SetRequesterKeyPair(ctx, ltPriv, 48, ltPub, 96));
|
||||
ASSERT_SUCCESS(wolfSPDM_SetResponderPubKey(ctx, ltPub, 96));
|
||||
|
||||
/* Our ephemeral ECDH key (requester side). Some wolfSSL builds
|
||||
* (e.g. ECC_TIMING_RESISTANT) require an RNG on the ECDH private
|
||||
* key for blinding; ensure one is attached for wc_ecc_shared_secret. */
|
||||
ASSERT_SUCCESS(wolfSPDM_GenerateEphemeralKey(ctx));
|
||||
ASSERT_SUCCESS(wc_ecc_set_rng(&ctx->ephemeralKey, &ctx->rng));
|
||||
ASSERT_SUCCESS(wolfSPDM_ExportEphemeralPubKey(ctx,
|
||||
ourPubX, &ourXSz, ourPubY, &ourYSz));
|
||||
|
||||
/* Responder ephemeral ECDH key (simulated responder side) */
|
||||
ASSERT_SUCCESS(wc_ecc_init(&respEphem));
|
||||
ASSERT_SUCCESS(wc_ecc_make_key(&ctx->rng, 48, &respEphem));
|
||||
ASSERT_SUCCESS(wc_ecc_set_rng(&respEphem, &ctx->rng));
|
||||
ASSERT_SUCCESS(wc_ecc_export_public_raw(&respEphem,
|
||||
respPubX, &respPubXSz, respPubY, &respPubYSz));
|
||||
if (respPubXSz < 48) {
|
||||
XMEMMOVE(respPubX + (48 - respPubXSz), respPubX, respPubXSz);
|
||||
XMEMSET(respPubX, 0, 48 - respPubXSz);
|
||||
}
|
||||
if (respPubYSz < 48) {
|
||||
XMEMMOVE(respPubY + (48 - respPubYSz), respPubY, respPubYSz);
|
||||
XMEMSET(respPubY, 0, 48 - respPubYSz);
|
||||
}
|
||||
|
||||
/* Build partial KE_RSP (bytes 0..137) */
|
||||
XMEMSET(keRsp, 0, sizeof(keRsp));
|
||||
keRsp[0] = SPDM_VERSION_12;
|
||||
keRsp[1] = SPDM_KEY_EXCHANGE_RSP;
|
||||
SPDM_Set16LE(&keRsp[4], 0x1234);
|
||||
XMEMSET(&keRsp[8], 0x5A, 32);
|
||||
XMEMCPY(&keRsp[40], respPubX, 48);
|
||||
XMEMCPY(&keRsp[88], respPubY, 48);
|
||||
SPDM_Set16LE(&keRsp[136], 0);
|
||||
|
||||
/* th1SigHash = Hash(transcript + partial KE_RSP); transcript starts empty */
|
||||
ASSERT_SUCCESS(wolfSPDM_Sha384Hash(th1SigHash,
|
||||
keRsp, keRspPartialLen, NULL, 0, NULL, 0));
|
||||
|
||||
/* Replicate wolfSPDM_BuildSignedHash for SPDM 1.2 over th1SigHash */
|
||||
signMsgLen = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
XMEMCPY(&signMsg[signMsgLen], "dmtf-spdm-v1.2.*", 16);
|
||||
signMsgLen += 16;
|
||||
}
|
||||
zeroPadLen = 36 - ctxStrLen;
|
||||
XMEMSET(&signMsg[signMsgLen], 0, zeroPadLen);
|
||||
signMsgLen += zeroPadLen;
|
||||
XMEMCPY(&signMsg[signMsgLen], ctxStr, ctxStrLen);
|
||||
signMsgLen += ctxStrLen;
|
||||
XMEMCPY(&signMsg[signMsgLen], th1SigHash, WOLFSPDM_HASH_SIZE);
|
||||
signMsgLen += WOLFSPDM_HASH_SIZE;
|
||||
ASSERT_SUCCESS(wolfSPDM_Sha384Hash(signMsgHash,
|
||||
signMsg, signMsgLen, NULL, 0, NULL, 0));
|
||||
|
||||
/* Sign with long-term key; wolfSPDM_SignHash pads R||S to 96 bytes */
|
||||
sigRawSz = WOLFSPDM_ECC_SIG_SIZE;
|
||||
ASSERT_SUCCESS(wolfSPDM_SignHash(ctx, signMsgHash, WOLFSPDM_HASH_SIZE,
|
||||
sigRaw, &sigRawSz));
|
||||
XMEMCPY(&keRsp[138], sigRaw, WOLFSPDM_ECC_SIG_SIZE);
|
||||
|
||||
/* TH1 = Hash(partial || signature) */
|
||||
ASSERT_SUCCESS(wolfSPDM_Sha384Hash(th1,
|
||||
keRsp, keRspPartialLen + WOLFSPDM_ECC_SIG_SIZE, NULL, 0, NULL, 0));
|
||||
|
||||
/* Shared secret from responder ephemeral and our public key (mirrors
|
||||
* ECDH(our_priv, resp_pub) that parse will compute on ctx) */
|
||||
ASSERT_SUCCESS(wc_ecc_init(&ourPubKey));
|
||||
ASSERT_SUCCESS(wc_ecc_import_unsigned(&ourPubKey,
|
||||
ourPubX, ourPubY, NULL, ECC_SECP384R1));
|
||||
ASSERT_SUCCESS(wc_ecc_shared_secret(&respEphem, &ourPubKey,
|
||||
sharedSecret, &sharedSz));
|
||||
wc_ecc_free(&ourPubKey);
|
||||
if (sharedSz < 48) {
|
||||
XMEMMOVE(sharedSecret + (48 - sharedSz), sharedSecret, sharedSz);
|
||||
XMEMSET(sharedSecret, 0, 48 - sharedSz);
|
||||
}
|
||||
sharedSz = 48;
|
||||
|
||||
/* Derive rspFinishedKey via a throwaway helper ctx */
|
||||
ASSERT_SUCCESS(wolfSPDM_Init(helper));
|
||||
helper->spdmVersion = SPDM_VERSION_12;
|
||||
XMEMCPY(helper->sharedSecret, sharedSecret, 48);
|
||||
helper->sharedSecretSz = 48;
|
||||
ASSERT_SUCCESS(wolfSPDM_DeriveHandshakeKeys(helper, th1));
|
||||
ASSERT_SUCCESS(wolfSPDM_ComputeVerifyData(
|
||||
helper->rspFinishedKey, th1, expectedHmac));
|
||||
wolfSPDM_Free(helper);
|
||||
|
||||
/* Positive: valid HMAC must succeed and advance state to KEY_EX */
|
||||
XMEMCPY(&keRsp[234], expectedHmac, WOLFSPDM_HASH_SIZE);
|
||||
rc = wolfSPDM_ParseKeyExchangeRsp(ctx, keRsp, keRspLen);
|
||||
ASSERT_EQ(rc, WOLFSPDM_SUCCESS, "valid HMAC should succeed");
|
||||
ASSERT_EQ(ctx->state, WOLFSPDM_STATE_KEY_EX,
|
||||
"state should advance to KEY_EX on valid parse");
|
||||
|
||||
/* Negative: a single bit flip in rspVerifyData must be rejected.
|
||||
* Reset transcript/state only; keep ephemeral key so ECDH reproduces. */
|
||||
wolfSPDM_TranscriptReset(ctx);
|
||||
ctx->state = WOLFSPDM_STATE_INIT;
|
||||
keRsp[234] ^= 0x01;
|
||||
rc = wolfSPDM_ParseKeyExchangeRsp(ctx, keRsp, keRspLen);
|
||||
ASSERT_EQ(rc, WOLFSPDM_E_BAD_HMAC,
|
||||
"flipped rspVerifyData byte must return BAD_HMAC");
|
||||
|
||||
wc_ecc_free(<Key);
|
||||
wc_ecc_free(&respEphem);
|
||||
TEST_CTX_FREE();
|
||||
TEST_PASS();
|
||||
}
|
||||
|
||||
/* Test Fix 4: Invalid curve point must be rejected by ComputeSharedSecret */
|
||||
static int test_invalid_curve_point(void)
|
||||
{
|
||||
|
|
@ -1400,6 +1572,71 @@ static int test_parse_psk_exchange_rsp_null_args(void)
|
|||
TEST_PASS();
|
||||
}
|
||||
|
||||
/* Drive wolfSPDM_ParsePskExchangeRsp through key derivation to exercise
|
||||
* the PSK ResponderVerifyData HMAC compare. Previously only NULL/short-
|
||||
* buffer paths were covered, so mutations of the `if (diff != 0)` block
|
||||
* or of `diff |= ...` → `diff &= ...` survived every test. */
|
||||
static int test_parse_psk_exchange_rsp_hmac_check(void)
|
||||
{
|
||||
byte pskRsp[64];
|
||||
const word32 pskRspLen = 60; /* 12-byte partial + 48 HMAC */
|
||||
const word32 pskRspPartialLen = 12;
|
||||
byte psk[48];
|
||||
byte th1[WOLFSPDM_HASH_SIZE];
|
||||
byte expectedHmac[WOLFSPDM_HASH_SIZE];
|
||||
int rc;
|
||||
WOLFSPDM_CTX helperBuf;
|
||||
WOLFSPDM_CTX* helper = &helperBuf;
|
||||
TEST_CTX_SETUP_V12();
|
||||
|
||||
printf("test_parse_psk_exchange_rsp_hmac_check...\n");
|
||||
|
||||
XMEMSET(psk, 0xA5, sizeof(psk));
|
||||
|
||||
/* Build PSK_EXCHANGE_RSP partial (12 bytes): rspContextLen=0, opaqueLen=0 */
|
||||
XMEMSET(pskRsp, 0, sizeof(pskRsp));
|
||||
pskRsp[0] = SPDM_VERSION_12;
|
||||
pskRsp[1] = SPDM_PSK_EXCHANGE_RSP;
|
||||
SPDM_Set16LE(&pskRsp[4], 0x1234); /* RspSessionID */
|
||||
SPDM_Set16LE(&pskRsp[8], 0); /* RspContextLength */
|
||||
SPDM_Set16LE(&pskRsp[10], 0); /* OpaqueDataLength */
|
||||
|
||||
/* TH1 = Hash(transcript + partial); transcript starts empty */
|
||||
ASSERT_SUCCESS(wolfSPDM_Sha384Hash(th1,
|
||||
pskRsp, pskRspPartialLen, NULL, 0, NULL, 0));
|
||||
|
||||
/* Derive rspFinishedKey on a throwaway helper ctx */
|
||||
ASSERT_SUCCESS(wolfSPDM_Init(helper));
|
||||
helper->spdmVersion = SPDM_VERSION_12;
|
||||
ASSERT_SUCCESS(wolfSPDM_SetPSK(helper, psk, sizeof(psk), NULL, 0));
|
||||
ASSERT_SUCCESS(wolfSPDM_DeriveHandshakeKeysPsk(helper, th1));
|
||||
ASSERT_SUCCESS(wolfSPDM_ComputeVerifyData(
|
||||
helper->rspFinishedKey, th1, expectedHmac));
|
||||
wolfSPDM_Free(helper);
|
||||
|
||||
/* Positive: correct HMAC must succeed and advance state to KEY_EX */
|
||||
XMEMCPY(&pskRsp[12], expectedHmac, WOLFSPDM_HASH_SIZE);
|
||||
ASSERT_SUCCESS(wolfSPDM_SetPSK(ctx, psk, sizeof(psk), NULL, 0));
|
||||
rc = wolfSPDM_ParsePskExchangeRsp(ctx, pskRsp, pskRspLen);
|
||||
ASSERT_EQ(rc, WOLFSPDM_SUCCESS, "valid PSK HMAC should succeed");
|
||||
ASSERT_EQ(ctx->state, WOLFSPDM_STATE_KEY_EX,
|
||||
"state should advance to KEY_EX on valid PSK parse");
|
||||
|
||||
/* Negative: flip one byte — must return BAD_HMAC.
|
||||
* Parse scrubs ctx->psk after derivation, so re-set it; also reset
|
||||
* transcript because the successful parse appended 60 bytes. */
|
||||
wolfSPDM_TranscriptReset(ctx);
|
||||
ctx->state = WOLFSPDM_STATE_INIT;
|
||||
ASSERT_SUCCESS(wolfSPDM_SetPSK(ctx, psk, sizeof(psk), NULL, 0));
|
||||
pskRsp[12] ^= 0x01;
|
||||
rc = wolfSPDM_ParsePskExchangeRsp(ctx, pskRsp, pskRspLen);
|
||||
ASSERT_EQ(rc, WOLFSPDM_E_BAD_HMAC,
|
||||
"flipped PSK rspVerifyData byte must return BAD_HMAC");
|
||||
|
||||
TEST_CTX_FREE();
|
||||
TEST_PASS();
|
||||
}
|
||||
|
||||
static int test_build_psk_finish_null_args(void)
|
||||
{
|
||||
byte buf[128];
|
||||
|
|
@ -1937,6 +2174,7 @@ int main(void)
|
|||
|
||||
/* Security tests */
|
||||
test_mitm_signature_rejected();
|
||||
test_key_exchange_rsp_hmac_check();
|
||||
test_invalid_curve_point();
|
||||
#ifdef WOLFTPM_SPDM_TCG
|
||||
test_tcg_underflow();
|
||||
|
|
@ -1989,6 +2227,7 @@ int main(void)
|
|||
#endif
|
||||
#ifdef WOLFTPM_SPDM_PSK
|
||||
test_parse_psk_exchange_rsp_null_args();
|
||||
test_parse_psk_exchange_rsp_hmac_check();
|
||||
test_build_psk_finish_null_args();
|
||||
test_build_psk_finish_format();
|
||||
test_parse_psk_finish_rsp();
|
||||
|
|
|
|||
72
src/tpm2.c
72
src/tpm2.c
|
|
@ -1304,14 +1304,19 @@ TPM_RC TPM2_PCR_Extend(PCR_Extend_In* in)
|
|||
int i;
|
||||
TPM2_Packet packet;
|
||||
CmdInfo_t info = {0,0,0,0};
|
||||
UINT32 count;
|
||||
info.inHandleCnt = 1;
|
||||
info.flags = (CMD_FLAG_AUTH_USER1);
|
||||
|
||||
count = in->digests.count;
|
||||
if (count > HASH_COUNT)
|
||||
count = HASH_COUNT;
|
||||
|
||||
TPM2_Packet_Init(ctx, &packet);
|
||||
TPM2_Packet_AppendU32(&packet, in->pcrHandle);
|
||||
TPM2_Packet_AppendAuth(&packet, ctx, &info);
|
||||
TPM2_Packet_AppendU32(&packet, in->digests.count);
|
||||
for (i=0; i<(int)in->digests.count; i++) {
|
||||
TPM2_Packet_AppendU32(&packet, count);
|
||||
for (i=0; i<(int)count; i++) {
|
||||
UINT16 hashAlg = in->digests.digests[i].hashAlg;
|
||||
int digestSz = TPM2_GetHashDigestSize(hashAlg);
|
||||
TPM2_Packet_AppendU16(&packet, hashAlg);
|
||||
|
|
@ -1719,34 +1724,14 @@ TPM_RC TPM2_LoadExternal(LoadExternal_In* in, LoadExternal_Out* out)
|
|||
TPM2_Packet_Init(ctx, &packet);
|
||||
|
||||
st = TPM2_Packet_AppendAuth(&packet, ctx, &info);
|
||||
/* Reading sensitive.any.size is valid regardless of sensitiveType:
|
||||
* every TPM2B variant in TPMU_SENSITIVE_COMPOSITE has UINT16 size
|
||||
* at offset 0, so the .any view reliably reflects the populated
|
||||
* typed member (common-initial-sequence aliasing). */
|
||||
if (in->inPrivate.sensitiveArea.authValue.size > 0 ||
|
||||
in->inPrivate.sensitiveArea.seedValue.size > 0 ||
|
||||
in->inPrivate.sensitiveArea.sensitive.any.size > 0) {
|
||||
|
||||
in->inPrivate.size = 2 + /* sensitiveType */
|
||||
2 + in->inPrivate.sensitiveArea.authValue.size +
|
||||
2 + in->inPrivate.sensitiveArea.seedValue.size +
|
||||
2 + in->inPrivate.sensitiveArea.sensitive.any.size;
|
||||
TPM2_Packet_AppendU16(&packet, in->inPrivate.size);
|
||||
|
||||
TPM2_Packet_AppendU16(&packet,
|
||||
in->inPrivate.sensitiveArea.sensitiveType);
|
||||
TPM2_Packet_AppendU16(&packet,
|
||||
in->inPrivate.sensitiveArea.authValue.size);
|
||||
TPM2_Packet_AppendBytes(&packet,
|
||||
in->inPrivate.sensitiveArea.authValue.buffer,
|
||||
in->inPrivate.sensitiveArea.authValue.size);
|
||||
TPM2_Packet_AppendU16(&packet,
|
||||
in->inPrivate.sensitiveArea.seedValue.size);
|
||||
TPM2_Packet_AppendBytes(&packet,
|
||||
in->inPrivate.sensitiveArea.seedValue.buffer,
|
||||
in->inPrivate.sensitiveArea.seedValue.size);
|
||||
|
||||
TPM2_Packet_AppendU16(&packet,
|
||||
in->inPrivate.sensitiveArea.sensitive.any.size);
|
||||
TPM2_Packet_AppendBytes(&packet,
|
||||
in->inPrivate.sensitiveArea.sensitive.any.buffer,
|
||||
in->inPrivate.sensitiveArea.sensitive.any.size);
|
||||
TPM2_Packet_AppendSensitive(&packet, &in->inPrivate);
|
||||
}
|
||||
else {
|
||||
TPM2_Packet_AppendU16(&packet, 0);
|
||||
|
|
@ -2310,10 +2295,7 @@ TPM_RC TPM2_ECC_Parameters(ECC_Parameters_In* in,
|
|||
TPM2_Packet_ParseU16(&packet,
|
||||
&out->parameters.kdf.details.any.hashAlg);
|
||||
|
||||
TPM2_Packet_ParseU16(&packet, &out->parameters.sign.scheme);
|
||||
if (out->parameters.sign.scheme != TPM_ALG_NULL)
|
||||
TPM2_Packet_ParseU16(&packet,
|
||||
&out->parameters.sign.details.any.hashAlg);
|
||||
TPM2_Packet_ParseEccScheme(&packet, &out->parameters.sign);
|
||||
|
||||
TPM2_Packet_ParseU16Buf(&packet, &out->parameters.p.size,
|
||||
out->parameters.p.buffer,
|
||||
|
|
@ -3325,9 +3307,18 @@ TPM_RC TPM2_SetCommandCodeAuditStatus(SetCommandCodeAuditStatus_In* in)
|
|||
int i;
|
||||
TPM2_Packet packet;
|
||||
CmdInfo_t info = {0,0,0,0};
|
||||
UINT32 setCount;
|
||||
UINT32 clearCount;
|
||||
info.inHandleCnt = 1;
|
||||
info.flags = (CMD_FLAG_AUTH_USER1);
|
||||
|
||||
setCount = in->setList.count;
|
||||
clearCount = in->clearList.count;
|
||||
if (setCount > MAX_CAP_CC)
|
||||
setCount = MAX_CAP_CC;
|
||||
if (clearCount > MAX_CAP_CC)
|
||||
clearCount = MAX_CAP_CC;
|
||||
|
||||
TPM2_Packet_Init(ctx, &packet);
|
||||
|
||||
TPM2_Packet_AppendU32(&packet, in->auth);
|
||||
|
|
@ -3336,13 +3327,13 @@ TPM_RC TPM2_SetCommandCodeAuditStatus(SetCommandCodeAuditStatus_In* in)
|
|||
|
||||
TPM2_Packet_AppendU16(&packet, in->auditAlg);
|
||||
|
||||
TPM2_Packet_AppendU32(&packet, in->setList.count);
|
||||
for (i=0; i<(int)in->setList.count; i++) {
|
||||
TPM2_Packet_AppendU32(&packet, setCount);
|
||||
for (i=0; i<(int)setCount; i++) {
|
||||
TPM2_Packet_AppendU32(&packet, in->setList.commandCodes[i]);
|
||||
}
|
||||
|
||||
TPM2_Packet_AppendU32(&packet, in->clearList.count);
|
||||
for (i=0; i<(int)in->clearList.count; i++) {
|
||||
TPM2_Packet_AppendU32(&packet, clearCount);
|
||||
for (i=0; i<(int)clearCount; i++) {
|
||||
TPM2_Packet_AppendU32(&packet, in->clearList.commandCodes[i]);
|
||||
}
|
||||
|
||||
|
|
@ -3742,12 +3733,19 @@ TPM_RC TPM2_PolicyOR(PolicyOR_In* in)
|
|||
if (rc == TPM_RC_SUCCESS) {
|
||||
int i;
|
||||
TPM2_Packet packet;
|
||||
const UINT32 digestsMax =
|
||||
(UINT32)(sizeof(in->pHashList.digests) /
|
||||
sizeof(in->pHashList.digests[0]));
|
||||
UINT32 count = in->pHashList.count;
|
||||
if (count > digestsMax)
|
||||
count = digestsMax;
|
||||
|
||||
TPM2_Packet_Init(ctx, &packet);
|
||||
|
||||
TPM2_Packet_AppendU32(&packet, in->policySession);
|
||||
|
||||
TPM2_Packet_AppendU32(&packet, in->pHashList.count);
|
||||
for (i=0; i<(int)in->pHashList.count; i++) {
|
||||
TPM2_Packet_AppendU32(&packet, count);
|
||||
for (i=0; i<(int)count; i++) {
|
||||
TPM2_Packet_AppendU16(&packet, in->pHashList.digests[i].size);
|
||||
TPM2_Packet_AppendBytes(&packet,
|
||||
in->pHashList.digests[i].buffer,
|
||||
|
|
|
|||
|
|
@ -5695,6 +5695,15 @@ int wolfTPM2_NVCreateAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent,
|
|||
if (dev == NULL || nv == NULL || parent == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (auth != NULL && authSz > 0 &&
|
||||
authSz > (int)sizeof(in.auth.buffer)) {
|
||||
return BUFFER_E;
|
||||
}
|
||||
if (authPolicy != NULL && authPolicySz > 0 &&
|
||||
authPolicySz >
|
||||
(int)sizeof(in.publicInfo.nvPublic.authPolicy.buffer)) {
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
/* set session auth for key */
|
||||
if (dev->ctx.session && !parent->policyAuth) {
|
||||
|
|
@ -5705,8 +5714,6 @@ int wolfTPM2_NVCreateAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent,
|
|||
XMEMSET(&in, 0, sizeof(in));
|
||||
in.authHandle = parent->hndl;
|
||||
if (auth != NULL && authSz > 0) {
|
||||
if (authSz > (int)sizeof(in.auth.buffer))
|
||||
authSz = (int)sizeof(in.auth.buffer);
|
||||
in.auth.size = authSz;
|
||||
XMEMCPY(in.auth.buffer, auth, in.auth.size);
|
||||
}
|
||||
|
|
@ -5715,11 +5722,6 @@ int wolfTPM2_NVCreateAuthPolicy(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent,
|
|||
in.publicInfo.nvPublic.attributes = nvAttributes;
|
||||
in.publicInfo.nvPublic.dataSize = (UINT16)maxSize;
|
||||
if (authPolicy != NULL && authPolicySz > 0) {
|
||||
if (authPolicySz >
|
||||
(int)sizeof(in.publicInfo.nvPublic.authPolicy.buffer)) {
|
||||
authPolicySz =
|
||||
(int)sizeof(in.publicInfo.nvPublic.authPolicy.buffer);
|
||||
}
|
||||
in.publicInfo.nvPublic.authPolicy.size = authPolicySz;
|
||||
XMEMCPY(in.publicInfo.nvPublic.authPolicy.buffer, authPolicy,
|
||||
in.publicInfo.nvPublic.authPolicy.size);
|
||||
|
|
@ -6375,10 +6377,10 @@ int wolfTPM2_HashStart(WOLFTPM2_DEV* dev, WOLFTPM2_HASH* hash,
|
|||
(usageAuthSz > 0 && usageAuth == NULL)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (usageAuthSz > sizeof(hash->handle.auth.buffer))
|
||||
return BUFFER_E;
|
||||
|
||||
/* Capture usage auth */
|
||||
if (usageAuthSz > sizeof(hash->handle.auth.buffer))
|
||||
usageAuthSz = sizeof(hash->handle.auth.buffer);
|
||||
XMEMSET(hash, 0, sizeof(WOLFTPM2_HASH));
|
||||
hash->handle.auth.size = usageAuthSz;
|
||||
if (usageAuth != NULL)
|
||||
|
|
@ -6833,6 +6835,10 @@ int wolfTPM2_LoadKeyedHashKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
|||
if (keySz == 0 || keySz > MAX_SYM_DATA) {
|
||||
return BUFFER_E;
|
||||
}
|
||||
if (usageAuth != NULL && usageAuthSz >
|
||||
sizeof(createIn.inSensitive.sensitive.userAuth.buffer)) {
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
hashAlgDigSz = TPM2_GetHashDigestSize(hashAlg);
|
||||
if (hashAlgDigSz <= 0) {
|
||||
|
|
@ -6848,11 +6854,6 @@ int wolfTPM2_LoadKeyedHashKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
|||
XMEMSET(&createIn, 0, sizeof(createIn));
|
||||
createIn.parentHandle = parent->hndl;
|
||||
if (usageAuth) {
|
||||
if (usageAuthSz >
|
||||
sizeof(createIn.inSensitive.sensitive.userAuth.buffer)) {
|
||||
usageAuthSz =
|
||||
sizeof(createIn.inSensitive.sensitive.userAuth.buffer); /* truncate */
|
||||
}
|
||||
createIn.inSensitive.sensitive.userAuth.size = usageAuthSz;
|
||||
XMEMCPY(createIn.inSensitive.sensitive.userAuth.buffer, usageAuth,
|
||||
usageAuthSz);
|
||||
|
|
@ -6925,11 +6926,13 @@ int wolfTPM2_HmacStart(WOLFTPM2_DEV* dev, WOLFTPM2_HMAC* hmac,
|
|||
if (dev == NULL || hmac == NULL || hashAlg == TPM_ALG_NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (usageAuth != NULL &&
|
||||
usageAuthSz > sizeof(hmac->hash.handle.auth.buffer)) {
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
if (usageAuth != NULL) {
|
||||
/* Capture usage auth */
|
||||
if (usageAuthSz > sizeof(hmac->hash.handle.auth.buffer))
|
||||
usageAuthSz = sizeof(hmac->hash.handle.auth.buffer); /* truncate */
|
||||
hmac->hash.handle.auth.size = usageAuthSz;
|
||||
XMEMCPY(hmac->hash.handle.auth.buffer, usageAuth, usageAuthSz);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1824,6 +1824,53 @@ static void test_TPM2_SchemeSerialize(void)
|
|||
printf("Test TPM Wrapper:\tSchemeSerialize:\t\tPassed\n");
|
||||
}
|
||||
|
||||
/* Exercise the parse sequence used by TPM2_ECC_Parameters response: sign
|
||||
* scheme = ECDAA (scheme + hashAlg + count) followed by a trailing U16
|
||||
* size field. Ensures the ECDAA count field is consumed so the next read
|
||||
* lands at the correct offset. The wire bytes are built by hand to avoid
|
||||
* relying on non-exported packet helpers. */
|
||||
static void test_TPM2_ECC_Parameters_EcdaaResponseParse(void)
|
||||
{
|
||||
TPM2_Packet packet;
|
||||
byte buf[32];
|
||||
TPMT_SIG_SCHEME signOut;
|
||||
UINT16 pSizeOut = 0;
|
||||
|
||||
/* Hand-built wire: TPM2B wire is big-endian.
|
||||
* [0-1] sign.scheme = TPM_ALG_ECDAA (0x001A)
|
||||
* [2-3] sign.hashAlg = TPM_ALG_SHA256 (0x000B)
|
||||
* [4-5] sign.count = 0x0007
|
||||
* [6-7] p.size sentinel= 0x0030
|
||||
*/
|
||||
XMEMSET(buf, 0, sizeof(buf));
|
||||
buf[0] = 0x00; buf[1] = (byte)TPM_ALG_ECDAA;
|
||||
buf[2] = 0x00; buf[3] = (byte)TPM_ALG_SHA256;
|
||||
buf[4] = 0x00; buf[5] = 0x07;
|
||||
buf[6] = 0x00; buf[7] = 0x30;
|
||||
|
||||
XMEMSET(&packet, 0, sizeof(packet));
|
||||
packet.buf = buf;
|
||||
packet.size = sizeof(buf);
|
||||
packet.pos = 0;
|
||||
|
||||
XMEMSET(&signOut, 0, sizeof(signOut));
|
||||
TPM2_Packet_ParseEccScheme(&packet, &signOut);
|
||||
AssertIntEQ(signOut.scheme, TPM_ALG_ECDAA);
|
||||
AssertIntEQ(signOut.details.ecdaa.hashAlg, TPM_ALG_SHA256);
|
||||
AssertIntEQ(signOut.details.ecdaa.count, 7);
|
||||
|
||||
/* After parsing the ECDAA scheme, packet.pos must be at byte 6 so the
|
||||
* next U16 read returns the sentinel 0x0030 (the simulated p.size).
|
||||
* The buggy inline parser in TPM2_ECC_Parameters consumed only
|
||||
* scheme+hashAlg (4 bytes) and left the count on the wire, which
|
||||
* would make p.size read 0x0007 instead. */
|
||||
AssertIntEQ(packet.pos, 6);
|
||||
pSizeOut = (UINT16)((buf[packet.pos] << 8) | buf[packet.pos + 1]);
|
||||
AssertIntEQ(pSizeOut, 0x0030);
|
||||
|
||||
printf("Test TPM Wrapper:\tEcdaaResponseParse:\t\tPassed\n");
|
||||
}
|
||||
|
||||
static void test_TPM2_KeyedHashScheme_XorSerialize(void)
|
||||
{
|
||||
TPM2_Packet packet;
|
||||
|
|
@ -2012,6 +2059,52 @@ static void test_TPM2_Sensitive_Roundtrip(void)
|
|||
AssertIntEQ(XMEMCMP(sensOut.sensitiveArea.sensitive.ecc.buffer,
|
||||
rsaPriv, sizeof(rsaPriv)), 0);
|
||||
|
||||
/* KEYEDHASH sensitive roundtrip */
|
||||
XMEMSET(&sensIn, 0, sizeof(sensIn));
|
||||
sensIn.sensitiveArea.sensitiveType = TPM_ALG_KEYEDHASH;
|
||||
sensIn.sensitiveArea.sensitive.bits.size = sizeof(rsaPriv);
|
||||
XMEMCPY(sensIn.sensitiveArea.sensitive.bits.buffer, rsaPriv,
|
||||
sizeof(rsaPriv));
|
||||
|
||||
XMEMSET(buf, 0, sizeof(buf));
|
||||
XMEMSET(&packet, 0, sizeof(packet));
|
||||
packet.buf = buf;
|
||||
packet.size = sizeof(buf);
|
||||
|
||||
TPM2_Packet_AppendSensitive(&packet, &sensIn);
|
||||
|
||||
packet.pos = 0;
|
||||
XMEMSET(&sensOut, 0, sizeof(sensOut));
|
||||
TPM2_Packet_ParseSensitive(&packet, &sensOut);
|
||||
|
||||
AssertIntEQ(sensOut.sensitiveArea.sensitiveType, TPM_ALG_KEYEDHASH);
|
||||
AssertIntEQ(sensOut.sensitiveArea.sensitive.bits.size, sizeof(rsaPriv));
|
||||
AssertIntEQ(XMEMCMP(sensOut.sensitiveArea.sensitive.bits.buffer,
|
||||
rsaPriv, sizeof(rsaPriv)), 0);
|
||||
|
||||
/* SYMCIPHER sensitive roundtrip */
|
||||
XMEMSET(&sensIn, 0, sizeof(sensIn));
|
||||
sensIn.sensitiveArea.sensitiveType = TPM_ALG_SYMCIPHER;
|
||||
sensIn.sensitiveArea.sensitive.sym.size = sizeof(rsaPriv);
|
||||
XMEMCPY(sensIn.sensitiveArea.sensitive.sym.buffer, rsaPriv,
|
||||
sizeof(rsaPriv));
|
||||
|
||||
XMEMSET(buf, 0, sizeof(buf));
|
||||
XMEMSET(&packet, 0, sizeof(packet));
|
||||
packet.buf = buf;
|
||||
packet.size = sizeof(buf);
|
||||
|
||||
TPM2_Packet_AppendSensitive(&packet, &sensIn);
|
||||
|
||||
packet.pos = 0;
|
||||
XMEMSET(&sensOut, 0, sizeof(sensOut));
|
||||
TPM2_Packet_ParseSensitive(&packet, &sensOut);
|
||||
|
||||
AssertIntEQ(sensOut.sensitiveArea.sensitiveType, TPM_ALG_SYMCIPHER);
|
||||
AssertIntEQ(sensOut.sensitiveArea.sensitive.sym.size, sizeof(rsaPriv));
|
||||
AssertIntEQ(XMEMCMP(sensOut.sensitiveArea.sensitive.sym.buffer,
|
||||
rsaPriv, sizeof(rsaPriv)), 0);
|
||||
|
||||
printf("Test TPM Wrapper:\tSensitive roundtrip:\t\tPassed\n");
|
||||
}
|
||||
|
||||
|
|
@ -3163,6 +3256,7 @@ int unit_tests(int argc, char *argv[])
|
|||
test_wolfTPM2_ComputeName();
|
||||
#endif
|
||||
test_TPM2_SchemeSerialize();
|
||||
test_TPM2_ECC_Parameters_EcdaaResponseParse();
|
||||
test_TPM2_KeyedHashScheme_XorSerialize();
|
||||
test_TPM2_Signature_EcSchnorrSm2Serialize();
|
||||
test_TPM2_Sensitive_Roundtrip();
|
||||
|
|
|
|||
Loading…
Reference in New Issue