mirror of https://github.com/wolfSSL/wolfTPM.git
Merge pull request #584 from aidangarske/fenrir-fixes-11898-11920-11921-11925-11927
Fix TCG v185 complaince issues for fwtpm and spdmpull/591/head
commit
00591ba28c
|
|
@ -76,7 +76,8 @@ static TPM_RC FwParseAttestParams(TPM2_Packet* cmd, int cmdSize,
|
|||
#ifndef FWTPM_NO_NV
|
||||
static FWTPM_NvIndex* FwFindNvIndex(FWTPM_CTX* ctx, TPMI_RH_NV_INDEX nvIndex);
|
||||
static TPM_RC FwNvCheckAccess(TPM_HANDLE authHandle,
|
||||
TPMI_RH_NV_INDEX nvHandle, UINT32 attributes, int isWrite);
|
||||
TPMI_RH_NV_INDEX nvHandle, UINT32 attributes, int isWrite,
|
||||
int authIsPolicy);
|
||||
#endif
|
||||
static FWTPM_Object* FwFindObject(FWTPM_CTX* ctx, TPM_HANDLE handle);
|
||||
#ifndef FWTPM_NO_DA
|
||||
|
|
@ -1298,12 +1299,20 @@ static TPM_RC FwCmd_GetCapability(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
TPMA_ALGORITHM_object },
|
||||
#endif
|
||||
#ifdef WOLFTPM_V185
|
||||
{ TPM_ALG_MLKEM, TPMA_ALGORITHM_asymmetric |
|
||||
TPMA_ALGORITHM_object | TPMA_ALGORITHM_encrypting },
|
||||
{ TPM_ALG_MLDSA, TPMA_ALGORITHM_asymmetric |
|
||||
TPMA_ALGORITHM_object | TPMA_ALGORITHM_signing },
|
||||
{ TPM_ALG_HASH_MLDSA, TPMA_ALGORITHM_asymmetric |
|
||||
TPMA_ALGORITHM_object | TPMA_ALGORITHM_signing },
|
||||
/* v1.85 PQC object types per Part 2 Sec.8.2 Table 35:
|
||||
* bit 0 asymmetric, bit 3 object,
|
||||
* bit 8 signing, bit 9 encrypting.
|
||||
* MLKEM is encrypting (encap/decap); MLDSA / Hash-MLDSA are
|
||||
* signing. */
|
||||
#ifdef WOLFTPM_MLKEM
|
||||
{ TPM_ALG_MLKEM, 0x0209 }, /* asymmetric|object|encrypting */
|
||||
#endif
|
||||
#ifdef WOLFTPM_MLDSA
|
||||
{ TPM_ALG_MLDSA, 0x0109 }, /* asymmetric|object|signing */
|
||||
#endif
|
||||
#ifdef WOLFTPM_HASH_MLDSA
|
||||
{ TPM_ALG_HASH_MLDSA, 0x0109 }, /* asymmetric|object|signing */
|
||||
#endif
|
||||
#endif
|
||||
{ TPM_ALG_NULL, 0 },
|
||||
};
|
||||
|
|
@ -2054,6 +2063,7 @@ static TPM_RC FwValidateMlTemplate(const TPMT_PUBLIC* pub, int checkPubSize)
|
|||
}
|
||||
break;
|
||||
}
|
||||
#ifdef WOLFTPM_HASH_MLDSA
|
||||
case TPM_ALG_HASH_MLDSA: {
|
||||
int sz = FwMldsaPubKeySize(
|
||||
pub->parameters.hash_mldsaDetail.parameterSet);
|
||||
|
|
@ -2070,7 +2080,13 @@ static TPM_RC FwValidateMlTemplate(const TPMT_PUBLIC* pub, int checkPubSize)
|
|||
}
|
||||
break;
|
||||
}
|
||||
#endif /* WOLFTPM_HASH_MLDSA */
|
||||
#endif /* WOLFTPM_MLDSA */
|
||||
#if defined(WOLFTPM_PQC) && !defined(WOLFTPM_HASH_MLDSA)
|
||||
case TPM_ALG_HASH_MLDSA:
|
||||
rc = TPM_RC_TYPE;
|
||||
break;
|
||||
#endif /* WOLFTPM_PQC && !WOLFTPM_HASH_MLDSA */
|
||||
#ifdef WOLFTPM_MLKEM
|
||||
case TPM_ALG_MLKEM: {
|
||||
int sz = FwMlkemPubKeySize(
|
||||
|
|
@ -2108,6 +2124,19 @@ static TPM_RC FwValidateMlTemplate(const TPMT_PUBLIC* pub, int checkPubSize)
|
|||
return rc;
|
||||
}
|
||||
|
||||
#ifdef WOLFTPM_V185
|
||||
/* fwTPM does not implement the firmware/SVN-bound hierarchy seeds and
|
||||
* proofs required by limited objects. */
|
||||
static TPM_RC FwValidateLimitedAttributes(const TPMT_PUBLIC* pub)
|
||||
{
|
||||
if ((pub->objectAttributes &
|
||||
(TPMA_OBJECT_firmwareLimited | TPMA_OBJECT_svnLimited)) != 0) {
|
||||
return TPM_RC_ATTRIBUTES;
|
||||
}
|
||||
return TPM_RC_SUCCESS;
|
||||
}
|
||||
#endif /* WOLFTPM_V185 */
|
||||
|
||||
static TPM_RC FwCmd_TestParms(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize,
|
||||
TPM2_Packet* rsp, UINT16 cmdTag)
|
||||
{
|
||||
|
|
@ -2176,6 +2205,7 @@ static TPM_RC FwCmd_TestParms(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize,
|
|||
}
|
||||
break;
|
||||
}
|
||||
#ifdef WOLFTPM_HASH_MLDSA
|
||||
case TPM_ALG_HASH_MLDSA: {
|
||||
UINT16 ps, hashAlg;
|
||||
int psSupported = 0;
|
||||
|
|
@ -2202,6 +2232,7 @@ static TPM_RC FwCmd_TestParms(FWTPM_CTX* ctx, TPM2_Packet* cmd, int cmdSize,
|
|||
}
|
||||
break;
|
||||
}
|
||||
#endif /* WOLFTPM_HASH_MLDSA */
|
||||
#endif /* WOLFTPM_MLDSA */
|
||||
#ifdef WOLFTPM_MLKEM
|
||||
case TPM_ALG_MLKEM: {
|
||||
|
|
@ -3278,7 +3309,11 @@ static TPM_RC FwCmd_CreatePrimary(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
if (rc == 0) {
|
||||
rc = FwValidateMlTemplate(&inPublic->publicArea, 0);
|
||||
}
|
||||
|
||||
#ifdef WOLFTPM_V185
|
||||
if (rc == 0) {
|
||||
rc = FwValidateLimitedAttributes(&inPublic->publicArea);
|
||||
}
|
||||
#endif /* WOLFTPM_V185 */
|
||||
/* Parse outsideInfo (TPM2B_DATA) - skip */
|
||||
if (rc == 0) {
|
||||
if (cmd->pos + 2 > cmdSize) {
|
||||
|
|
@ -3363,8 +3398,12 @@ static TPM_RC FwCmd_CreatePrimary(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
/* MLDSA / HASH_MLDSA / MLKEM: only feed user-supplied unique
|
||||
* bytes into hashUnique, not the raw buffer. A size==0 arm
|
||||
* must not read the uninitialized buffer pointer. */
|
||||
#ifdef WOLFTPM_MLDSA
|
||||
case TPM_ALG_MLDSA:
|
||||
#endif
|
||||
#ifdef WOLFTPM_HASH_MLDSA
|
||||
case TPM_ALG_HASH_MLDSA:
|
||||
#endif
|
||||
if (inPublic->publicArea.unique.mldsa.size > 0) {
|
||||
uBuf = inPublic->publicArea.unique.mldsa.buffer;
|
||||
uSz = (int)inPublic->publicArea.unique.mldsa.size;
|
||||
|
|
@ -3482,7 +3521,10 @@ static TPM_RC FwCmd_CreatePrimary(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
* FIPS 204 deterministic keygen. Private material on the wire
|
||||
* is the seed itself per TCG Part 2 Table 210. */
|
||||
case TPM_ALG_MLDSA:
|
||||
case TPM_ALG_HASH_MLDSA: {
|
||||
#ifdef WOLFTPM_HASH_MLDSA
|
||||
case TPM_ALG_HASH_MLDSA:
|
||||
#endif
|
||||
{
|
||||
const char* label = (inPublic->publicArea.type == TPM_ALG_MLDSA)
|
||||
? "MLDSA" : "HASH_MLDSA";
|
||||
TPMI_MLDSA_PARAMETER_SET ps =
|
||||
|
|
@ -6013,7 +6055,11 @@ static TPM_RC FwCmd_Create(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
if (rc == 0) {
|
||||
rc = FwValidateMlTemplate(&inPublic->publicArea, 0);
|
||||
}
|
||||
|
||||
#ifdef WOLFTPM_V185
|
||||
if (rc == 0) {
|
||||
rc = FwValidateLimitedAttributes(&inPublic->publicArea);
|
||||
}
|
||||
#endif /* WOLFTPM_V185 */
|
||||
/* Skip outsideInfo */
|
||||
if (rc == 0) {
|
||||
if (cmd->pos + 2 > cmdSize) {
|
||||
|
|
@ -6090,7 +6136,10 @@ static TPM_RC FwCmd_Create(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
/* ML-DSA ordinary key: seed is random bytes (Part 1 Sec.24.6.2);
|
||||
* FIPS 204 keygen is then deterministic from the seed. */
|
||||
case TPM_ALG_MLDSA:
|
||||
case TPM_ALG_HASH_MLDSA: {
|
||||
#ifdef WOLFTPM_HASH_MLDSA
|
||||
case TPM_ALG_HASH_MLDSA:
|
||||
#endif
|
||||
{
|
||||
TPMI_MLDSA_PARAMETER_SET ps =
|
||||
(inPublic->publicArea.type == TPM_ALG_MLDSA)
|
||||
? inPublic->publicArea.parameters.mldsaDetail.parameterSet
|
||||
|
|
@ -6475,6 +6524,14 @@ static TPM_RC FwCmd_Load(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
TPM2_Packet_ParsePublic(cmd, &inPublic);
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
rc = FwValidateMlTemplate(&inPublic.publicArea, 0);
|
||||
}
|
||||
#ifdef WOLFTPM_V185
|
||||
if (rc == 0) {
|
||||
rc = FwValidateLimitedAttributes(&inPublic.publicArea);
|
||||
}
|
||||
#endif /* WOLFTPM_V185 */
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
if (rc == 0) {
|
||||
printf("fwTPM: Load(parent=0x%x, type=%d, privSz=%d)\n",
|
||||
|
|
@ -6659,6 +6716,12 @@ static TPM_RC FwCmd_LoadExternal(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
TPM2_Packet_ParsePublic(cmd, &inPublic);
|
||||
}
|
||||
|
||||
#ifdef WOLFTPM_V185
|
||||
if (rc == 0) {
|
||||
rc = FwValidateLimitedAttributes(&inPublic.publicArea);
|
||||
}
|
||||
#endif /* WOLFTPM_V185 */
|
||||
|
||||
/* authValue (present only with inPrivate) must not exceed the
|
||||
* object nameAlg digest size */
|
||||
if (rc == 0 && inPrivSize > 0 && authValue.size > 0) {
|
||||
|
|
@ -6989,6 +7052,14 @@ static TPM_RC FwCmd_Import(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
TPM2_Packet_ParsePublic(cmd, objectPublic);
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
rc = FwValidateMlTemplate(&objectPublic->publicArea, 0);
|
||||
}
|
||||
#ifdef WOLFTPM_V185
|
||||
if (rc == 0) {
|
||||
rc = FwValidateLimitedAttributes(&objectPublic->publicArea);
|
||||
}
|
||||
#endif /* WOLFTPM_V185 */
|
||||
/* Parse duplicate */
|
||||
if (rc == 0) {
|
||||
if (cmd->pos + 2 > cmdSize) {
|
||||
|
|
@ -8070,6 +8141,12 @@ static TPM_RC FwCmd_CreateLoaded(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
TPM2_Packet_ParsePublic(cmd, inPublic);
|
||||
}
|
||||
|
||||
#ifdef WOLFTPM_V185
|
||||
if (rc == 0) {
|
||||
rc = FwValidateLimitedAttributes(&inPublic->publicArea);
|
||||
}
|
||||
#endif /* WOLFTPM_V185 */
|
||||
|
||||
/* userAuth must not exceed the object nameAlg digest size */
|
||||
if (rc == 0 && userAuth.size > 0) {
|
||||
int digestSz = TPM2_GetHashDigestSize(inPublic->publicArea.nameAlg);
|
||||
|
|
@ -8125,7 +8202,10 @@ static TPM_RC FwCmd_CreateLoaded(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
/* ML-DSA ordinary key: seed is random bytes (Part 1 Sec.24.6.2);
|
||||
* FIPS 204 keygen is then deterministic from the seed. */
|
||||
case TPM_ALG_MLDSA:
|
||||
case TPM_ALG_HASH_MLDSA: {
|
||||
#ifdef WOLFTPM_HASH_MLDSA
|
||||
case TPM_ALG_HASH_MLDSA:
|
||||
#endif
|
||||
{
|
||||
TPMI_MLDSA_PARAMETER_SET ps =
|
||||
(inPublic->publicArea.type == TPM_ALG_MLDSA)
|
||||
? inPublic->publicArea.parameters.mldsaDetail.parameterSet
|
||||
|
|
@ -11814,7 +11894,7 @@ static TPM_RC FwCmd_PolicyNV(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
/* Verify caller is authorized to read the NV index */
|
||||
if (rc == 0) {
|
||||
rc = FwNvCheckAccess(authHandle, nvIndex,
|
||||
nv->nvPublic.attributes, 0);
|
||||
nv->nvPublic.attributes, 0, ctx->activeCmdAuthIsPolicy[0]);
|
||||
}
|
||||
|
||||
/* Find policy session */
|
||||
|
|
@ -12904,7 +12984,7 @@ static TPM_RC FwCmd_PolicyAuthorizeNV(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
/* Verify caller is authorized to read the NV index */
|
||||
if (rc == 0) {
|
||||
rc = FwNvCheckAccess(authHandle, nvHandle,
|
||||
nv->nvPublic.attributes, 0);
|
||||
nv->nvPublic.attributes, 0, ctx->activeCmdAuthIsPolicy[0]);
|
||||
}
|
||||
|
||||
if (rc == 0 && !nv->written) {
|
||||
|
|
@ -13022,7 +13102,8 @@ static FWTPM_NvIndex* FwFindNvIndex(FWTPM_CTX* ctx, TPMI_RH_NV_INDEX nvIndex)
|
|||
* isWrite: 1 = write/extend/increment/setbits/writelock,
|
||||
* 0 = read/readlock/certify */
|
||||
static TPM_RC FwNvCheckAccess(TPM_HANDLE authHandle,
|
||||
TPMI_RH_NV_INDEX nvHandle, UINT32 attributes, int isWrite)
|
||||
TPMI_RH_NV_INDEX nvHandle, UINT32 attributes, int isWrite,
|
||||
int authIsPolicy)
|
||||
{
|
||||
if (isWrite) {
|
||||
if (authHandle == TPM_RH_PLATFORM) {
|
||||
|
|
@ -13036,7 +13117,9 @@ static TPM_RC FwNvCheckAccess(TPM_HANDLE authHandle,
|
|||
return TPM_RC_NV_AUTHORIZATION;
|
||||
}
|
||||
else if (authHandle == (TPM_HANDLE)nvHandle) {
|
||||
if (!(attributes & (TPMA_NV_AUTHWRITE | TPMA_NV_POLICYWRITE)))
|
||||
UINT32 requiredAttr = authIsPolicy ?
|
||||
TPMA_NV_POLICYWRITE : TPMA_NV_AUTHWRITE;
|
||||
if (!(attributes & requiredAttr))
|
||||
return TPM_RC_NV_AUTHORIZATION;
|
||||
}
|
||||
else {
|
||||
|
|
@ -13055,7 +13138,9 @@ static TPM_RC FwNvCheckAccess(TPM_HANDLE authHandle,
|
|||
return TPM_RC_NV_AUTHORIZATION;
|
||||
}
|
||||
else if (authHandle == (TPM_HANDLE)nvHandle) {
|
||||
if (!(attributes & (TPMA_NV_AUTHREAD | TPMA_NV_POLICYREAD)))
|
||||
UINT32 requiredAttr = authIsPolicy ?
|
||||
TPMA_NV_POLICYREAD : TPMA_NV_AUTHREAD;
|
||||
if (!(attributes & requiredAttr))
|
||||
return TPM_RC_NV_AUTHORIZATION;
|
||||
}
|
||||
else {
|
||||
|
|
@ -13394,7 +13479,7 @@ static TPM_RC FwCmd_NV_Write(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
}
|
||||
if (rc == 0) {
|
||||
rc = FwNvCheckAccess(authHandle, nvHandle,
|
||||
nv->nvPublic.attributes, 1);
|
||||
nv->nvPublic.attributes, 1, ctx->activeCmdAuthIsPolicy[0]);
|
||||
}
|
||||
|
||||
/* Per TPM 2.0 Part 3 Section 31.3, NV_Write only valid for ordinary and PIN
|
||||
|
|
@ -13492,7 +13577,7 @@ static TPM_RC FwCmd_NV_Read(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
}
|
||||
if (rc == 0) {
|
||||
rc = FwNvCheckAccess(authHandle, nvHandle,
|
||||
nv->nvPublic.attributes, 0);
|
||||
nv->nvPublic.attributes, 0, ctx->activeCmdAuthIsPolicy[0]);
|
||||
}
|
||||
|
||||
if (rc == 0 && (nv->nvPublic.attributes & TPMA_NV_READLOCKED)) {
|
||||
|
|
@ -13555,7 +13640,7 @@ static TPM_RC FwCmd_NV_Extend(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
}
|
||||
if (rc == 0) {
|
||||
rc = FwNvCheckAccess(authHandle, nvHandle,
|
||||
nv->nvPublic.attributes, 1);
|
||||
nv->nvPublic.attributes, 1, ctx->activeCmdAuthIsPolicy[0]);
|
||||
}
|
||||
|
||||
if (rc == 0 && (nv->nvPublic.attributes & TPMA_NV_WRITELOCKED)) {
|
||||
|
|
@ -13641,7 +13726,7 @@ static TPM_RC FwCmd_NV_Increment(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
}
|
||||
if (rc == 0) {
|
||||
rc = FwNvCheckAccess(authHandle, nvHandle,
|
||||
nv->nvPublic.attributes, 1);
|
||||
nv->nvPublic.attributes, 1, ctx->activeCmdAuthIsPolicy[0]);
|
||||
}
|
||||
|
||||
if (rc == 0 && (nv->nvPublic.attributes & TPMA_NV_WRITELOCKED)) {
|
||||
|
|
@ -13693,7 +13778,7 @@ static TPM_RC FwCmd_NV_WriteLock(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
}
|
||||
if (rc == 0) {
|
||||
rc = FwNvCheckAccess(authHandle, nvHandle,
|
||||
nv->nvPublic.attributes, 1);
|
||||
nv->nvPublic.attributes, 1, ctx->activeCmdAuthIsPolicy[0]);
|
||||
}
|
||||
|
||||
/* Per TPM 2.0 Part 3 Section 31.5.2: NV_WriteLock requires
|
||||
|
|
@ -13736,7 +13821,7 @@ static TPM_RC FwCmd_NV_ReadLock(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
}
|
||||
if (rc == 0) {
|
||||
rc = FwNvCheckAccess(authHandle, nvHandle,
|
||||
nv->nvPublic.attributes, 0);
|
||||
nv->nvPublic.attributes, 0, ctx->activeCmdAuthIsPolicy[0]);
|
||||
}
|
||||
|
||||
/* Per TPM 2.0 Part 3 Section 31.4.2: NV_ReadLock requires
|
||||
|
|
@ -13784,7 +13869,7 @@ static TPM_RC FwCmd_NV_SetBits(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
}
|
||||
if (rc == 0) {
|
||||
rc = FwNvCheckAccess(authHandle, nvHandle,
|
||||
nv->nvPublic.attributes, 1);
|
||||
nv->nvPublic.attributes, 1, ctx->activeCmdAuthIsPolicy[0]);
|
||||
}
|
||||
|
||||
if (rc == 0 && (nv->nvPublic.attributes & TPMA_NV_WRITELOCKED)) {
|
||||
|
|
@ -14927,7 +15012,7 @@ static TPM_RC FwCmd_NV_Certify(FWTPM_CTX* ctx, TPM2_Packet* cmd,
|
|||
}
|
||||
if (rc == 0) {
|
||||
rc = FwNvCheckAccess(authHandle, nvHandle,
|
||||
nv->nvPublic.attributes, 0);
|
||||
nv->nvPublic.attributes, 0, ctx->activeCmdAuthIsPolicy[1]);
|
||||
}
|
||||
if (rc == 0 && (nv->nvPublic.attributes & TPMA_NV_READLOCKED)) {
|
||||
rc = TPM_RC_NV_LOCKED;
|
||||
|
|
@ -17865,6 +17950,7 @@ typedef struct {
|
|||
/* Bit 1: first rsp param is TPM2B (can encrypt) */
|
||||
/* Bit 2: first auth handle has DUP role */
|
||||
/* Bit 3: command flushes its handle (TPMA_CC.F) */
|
||||
/* Bit 4: first auth handle has ADMIN role */
|
||||
} FWTPM_CMD_ENTRY;
|
||||
|
||||
#ifndef FWTPM_NO_PARAM_ENC
|
||||
|
|
@ -17882,6 +17968,11 @@ typedef struct {
|
|||
* object or sequence named by the command's handle is flushed on success. */
|
||||
#define FW_CMD_MOD_FLUSHED 0x08
|
||||
|
||||
/* ADMIN role (TPM 2.0 Part 3): when an object has adminWithPolicy set, or
|
||||
* an NV index is authorized in its ADMIN role, policy authorization with a
|
||||
* matching PolicyCommandCode is required. */
|
||||
#define FW_CMD_FLAG_AUTH_ADMIN 0x10
|
||||
|
||||
/* inH aH oH flags */
|
||||
static const FWTPM_CMD_ENTRY fwCmdTable[] = {
|
||||
/* --- Basic (always enabled) --- */
|
||||
|
|
@ -17925,7 +18016,7 @@ static const FWTPM_CMD_ENTRY fwCmdTable[] = {
|
|||
{ TPM_CC_SetPrimaryPolicy, FwCmd_SetPrimaryPolicy, 1, 1, 0, FW_CMD_FLAG_ENC },
|
||||
{ TPM_CC_EvictControl, FwCmd_EvictControl, 2, 1, 0, 0 },
|
||||
{ TPM_CC_Create, FwCmd_Create, 1, 1, 0, FW_CMD_FLAG_ENC | FW_CMD_FLAG_DEC },
|
||||
{ TPM_CC_ObjectChangeAuth, FwCmd_ObjectChangeAuth, 2, 1, 0, FW_CMD_FLAG_ENC | FW_CMD_FLAG_DEC },
|
||||
{ TPM_CC_ObjectChangeAuth, FwCmd_ObjectChangeAuth, 2, 1, 0, FW_CMD_FLAG_ENC | FW_CMD_FLAG_DEC | FW_CMD_FLAG_AUTH_ADMIN },
|
||||
{ TPM_CC_Load, FwCmd_Load, 1, 1, 1, FW_CMD_FLAG_ENC | FW_CMD_FLAG_DEC },
|
||||
{ TPM_CC_Sign, FwCmd_Sign, 1, 1, 0, FW_CMD_FLAG_ENC },
|
||||
{ TPM_CC_VerifySignature, FwCmd_VerifySignature, 1, 0, 0, 0 },
|
||||
|
|
@ -18013,7 +18104,7 @@ static const FWTPM_CMD_ENTRY fwCmdTable[] = {
|
|||
#ifndef FWTPM_NO_NV
|
||||
{ TPM_CC_NV_DefineSpace, FwCmd_NV_DefineSpace, 1, 1, 0, FW_CMD_FLAG_ENC },
|
||||
{ TPM_CC_NV_UndefineSpace, FwCmd_NV_UndefineSpace, 2, 1, 0, 0 },
|
||||
{ TPM_CC_NV_UndefineSpaceSpecial, FwCmd_NV_UndefineSpaceSpecial, 2, 2, 0, 0 },
|
||||
{ TPM_CC_NV_UndefineSpaceSpecial, FwCmd_NV_UndefineSpaceSpecial, 2, 2, 0, FW_CMD_FLAG_AUTH_ADMIN },
|
||||
{ TPM_CC_NV_ReadPublic, FwCmd_NV_ReadPublic, 1, 0, 0, FW_CMD_FLAG_DEC },
|
||||
{ TPM_CC_NV_Write, FwCmd_NV_Write, 2, 1, 0, FW_CMD_FLAG_ENC },
|
||||
{ TPM_CC_NV_Read, FwCmd_NV_Read, 2, 1, 0, FW_CMD_FLAG_DEC },
|
||||
|
|
@ -18022,7 +18113,7 @@ static const FWTPM_CMD_ENTRY fwCmdTable[] = {
|
|||
{ TPM_CC_NV_WriteLock, FwCmd_NV_WriteLock, 2, 1, 0, 0 },
|
||||
{ TPM_CC_NV_ReadLock, FwCmd_NV_ReadLock, 2, 1, 0, 0 },
|
||||
{ TPM_CC_NV_SetBits, FwCmd_NV_SetBits, 2, 1, 0, 0 },
|
||||
{ TPM_CC_NV_ChangeAuth, FwCmd_NV_ChangeAuth, 1, 1, 0, FW_CMD_FLAG_ENC },
|
||||
{ TPM_CC_NV_ChangeAuth, FwCmd_NV_ChangeAuth, 1, 1, 0, FW_CMD_FLAG_ENC | FW_CMD_FLAG_AUTH_ADMIN },
|
||||
{ TPM_CC_NV_GlobalWriteLock, FwCmd_NV_GlobalWriteLock, 1, 1, 0, 0 },
|
||||
#endif /* !FWTPM_NO_NV */
|
||||
/* --- ECC Parameters --- */
|
||||
|
|
@ -18034,7 +18125,7 @@ static const FWTPM_CMD_ENTRY fwCmdTable[] = {
|
|||
/* --- Attestation --- */
|
||||
#ifndef FWTPM_NO_ATTESTATION
|
||||
{ TPM_CC_Quote, FwCmd_Quote, 1, 1, 0, FW_CMD_FLAG_DEC },
|
||||
{ TPM_CC_Certify, FwCmd_Certify, 2, 2, 0, FW_CMD_FLAG_DEC },
|
||||
{ TPM_CC_Certify, FwCmd_Certify, 2, 2, 0, FW_CMD_FLAG_DEC | FW_CMD_FLAG_AUTH_ADMIN },
|
||||
{ TPM_CC_CertifyCreation, FwCmd_CertifyCreation, 2, 1, 0, FW_CMD_FLAG_DEC },
|
||||
{ TPM_CC_GetTime, FwCmd_GetTime, 2, 2, 0, FW_CMD_FLAG_DEC },
|
||||
#ifndef FWTPM_NO_NV
|
||||
|
|
@ -18044,7 +18135,7 @@ static const FWTPM_CMD_ENTRY fwCmdTable[] = {
|
|||
/* --- Credentials --- */
|
||||
#ifndef FWTPM_NO_CREDENTIAL
|
||||
{ TPM_CC_MakeCredential, FwCmd_MakeCredential, 1, 0, 0, FW_CMD_FLAG_DEC },
|
||||
{ TPM_CC_ActivateCredential, FwCmd_ActivateCredential, 2, 2, 0, FW_CMD_FLAG_DEC },
|
||||
{ TPM_CC_ActivateCredential, FwCmd_ActivateCredential, 2, 2, 0, FW_CMD_FLAG_DEC | FW_CMD_FLAG_AUTH_ADMIN },
|
||||
#endif /* !FWTPM_NO_CREDENTIAL */
|
||||
/* --- Dictionary Attack --- */
|
||||
#ifndef FWTPM_NO_DA
|
||||
|
|
@ -18492,6 +18583,11 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifndef FWTPM_NO_NV
|
||||
XMEMSET(ctx->activeCmdAuthIsPolicy, 0,
|
||||
sizeof(ctx->activeCmdAuthIsPolicy));
|
||||
#endif
|
||||
|
||||
/* rspSize is in/out: capacity in, bytes written out. Callers that leave
|
||||
* it unset get the historic FWTPM_MAX_COMMAND_SIZE assumption. */
|
||||
/* Handlers commit state before marshalling and some write outside the
|
||||
|
|
@ -19088,6 +19184,61 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
|
|||
return TPM_RC_SUCCESS;
|
||||
}
|
||||
|
||||
/* ADMIN-role authorization requires a policy session when the object
|
||||
* sets adminWithPolicy, and always for an NV index. A policy used for
|
||||
* an ADMIN role must also be bound to this command with
|
||||
* PolicyCommandCode. */
|
||||
if ((entry->encDecFlags & FW_CMD_FLAG_AUTH_ADMIN) && cmdAuthCnt > 0) {
|
||||
TPM_HANDLE entityH = cmdHandles[0];
|
||||
FWTPM_Session* adminSess = cmdAuths[0].sess;
|
||||
FWTPM_Object* adminObj = NULL;
|
||||
int requirePolicy = 0;
|
||||
|
||||
if ((entityH & 0xFF000000) == (TRANSIENT_FIRST & 0xFF000000) ||
|
||||
(entityH & 0xFF000000) == (PERSISTENT_FIRST & 0xFF000000)) {
|
||||
adminObj = FwFindObject(ctx, entityH);
|
||||
if (adminObj != NULL &&
|
||||
(adminObj->pub.objectAttributes &
|
||||
TPMA_OBJECT_adminWithPolicy)) {
|
||||
requirePolicy = 1;
|
||||
}
|
||||
}
|
||||
#ifndef FWTPM_NO_NV
|
||||
else if ((entityH & 0xFF000000) ==
|
||||
(NV_INDEX_FIRST & 0xFF000000)) {
|
||||
requirePolicy = 1;
|
||||
}
|
||||
#endif
|
||||
else if (entityH == TPM_RH_OWNER ||
|
||||
entityH == TPM_RH_ENDORSEMENT ||
|
||||
entityH == TPM_RH_PLATFORM ||
|
||||
entityH == TPM_RH_PLATFORM_NV ||
|
||||
entityH == TPM_RH_LOCKOUT) {
|
||||
requirePolicy = 1;
|
||||
}
|
||||
|
||||
if (requirePolicy &&
|
||||
(adminSess == NULL || adminSess->sessionType != TPM_SE_POLICY)) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("fwTPM: ADMIN role requires a policy session (CC=0x%x)\n",
|
||||
cmdCode);
|
||||
#endif
|
||||
*rspSize = FwBuildErrorResponse(rspBuf, rspCap,
|
||||
TPM_ST_NO_SESSIONS, TPM_RC_AUTH_TYPE);
|
||||
return TPM_RC_SUCCESS;
|
||||
}
|
||||
if (adminSess != NULL && adminSess->sessionType == TPM_SE_POLICY &&
|
||||
adminSess->commandCode != cmdCode) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("fwTPM: ADMIN role requires PolicyCommandCode (CC=0x%x)\n",
|
||||
cmdCode);
|
||||
#endif
|
||||
*rspSize = FwBuildErrorResponse(rspBuf, rspCap,
|
||||
TPM_ST_NO_SESSIONS, TPM_RC_POLICY_CC);
|
||||
return TPM_RC_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* userWithAuth enforcement: per TPM 2.0 spec Part 1, Section 19.7.1,
|
||||
* if an object has authPolicy set and userWithAuth is CLEAR, only a
|
||||
* policy session can authorize the object. Reject password and HMAC
|
||||
|
|
@ -19297,7 +19448,18 @@ int FWTPM_ProcessCommand(FWTPM_CTX* ctx,
|
|||
/* Set up response packet */
|
||||
FwRspInit(&rspPkt, rspBuf, rspCap);
|
||||
|
||||
#ifndef FWTPM_NO_NV
|
||||
for (pj = 0; pj < cmdAuthCnt && pj < (int)entry->authHandleCnt; pj++) {
|
||||
ctx->activeCmdAuthIsPolicy[pj] =
|
||||
(byte)(cmdAuths[pj].sess != NULL &&
|
||||
cmdAuths[pj].sess->sessionType == TPM_SE_POLICY);
|
||||
}
|
||||
#endif
|
||||
rc = entry->handler(ctx, &cmdPkt, cmdSize, &rspPkt, cmdTag);
|
||||
#ifndef FWTPM_NO_NV
|
||||
XMEMSET(ctx->activeCmdAuthIsPolicy, 0,
|
||||
sizeof(ctx->activeCmdAuthIsPolicy));
|
||||
#endif
|
||||
/* A sessions-tagged FlushContext leaves its target session alive so the
|
||||
* dispatcher can use it to generate the response authorization area. */
|
||||
if (rc == TPM_RC_SUCCESS && cmdCode == TPM_CC_FlushContext &&
|
||||
|
|
|
|||
|
|
@ -1096,6 +1096,14 @@ static int RespDispatchSecured(WOLFSPDM_RESP_CTX* rctx,
|
|||
int sessionEnded = 0;
|
||||
int derivedAppKeys = 0;
|
||||
|
||||
/* KEY_EX has handshake traffic keys; CONNECTED has application traffic
|
||||
* keys. In every other state, decryption would use unestablished key
|
||||
* material (zeroed by initialization and reset). */
|
||||
if ((ctx->state != WOLFSPDM_STATE_KEY_EX &&
|
||||
ctx->state != WOLFSPDM_STATE_CONNECTED) || ctx->sessionId == 0) {
|
||||
return WOLFSPDM_E_BAD_STATE;
|
||||
}
|
||||
|
||||
plainSz = WOLFSPDM_MAX_MSG_SIZE;
|
||||
rc = RespDecrypt(ctx, securedIn, securedInSz, plain, &plainSz);
|
||||
if (rc != WOLFSPDM_SUCCESS) {
|
||||
|
|
|
|||
|
|
@ -2290,6 +2290,51 @@ static int test_responder_no_clear_tpm2_cmd(void)
|
|||
TEST_PASS();
|
||||
}
|
||||
|
||||
/* Secured records are valid only after key exchange establishes session
|
||||
* traffic state. Initialization and reset must both reject them before
|
||||
* attempting to parse the record. */
|
||||
static int test_responder_secured_requires_session(void)
|
||||
{
|
||||
byte rctxBuf[WOLFSPDM_RESP_CTX_STATIC_SIZE];
|
||||
WOLFSPDM_RESP_CTX* rctx = (WOLFSPDM_RESP_CTX*)rctxBuf;
|
||||
byte frame[WOLFSPDM_TCG_HEADER_SIZE + 1];
|
||||
byte outBuf[64];
|
||||
word32 outSz;
|
||||
int rc;
|
||||
|
||||
printf("test_responder_secured_requires_session...\n");
|
||||
ASSERT_SUCCESS(wolfSPDM_RespInit(rctx));
|
||||
ASSERT_SUCCESS(wolfSPDM_RespSetMode(rctx, 1, 0));
|
||||
g_tpmCbInvocations = 0;
|
||||
ASSERT_SUCCESS(wolfSPDM_RespSetTpmCallback(rctx, responder_tpm_stub,
|
||||
NULL));
|
||||
|
||||
XMEMSET(frame, 0, sizeof(frame));
|
||||
wolfSPDM_WriteTcgHeader(frame, WOLFSPDM_TCG_TAG_SECURED,
|
||||
sizeof(frame), 0, 0);
|
||||
|
||||
outSz = sizeof(outBuf);
|
||||
rc = wolfSPDM_RespHandleMessage(rctx, frame, sizeof(frame), outBuf,
|
||||
&outSz);
|
||||
ASSERT_EQ(rc, WOLFSPDM_E_BAD_STATE,
|
||||
"secured record without a session must return BAD_STATE");
|
||||
ASSERT_EQ(g_tpmCbInvocations, 0,
|
||||
"record without a session must not reach the TPM callback");
|
||||
|
||||
/* Reset must leave the responder in a sessionless state. */
|
||||
wolfSPDM_RespReset(rctx);
|
||||
outSz = sizeof(outBuf);
|
||||
rc = wolfSPDM_RespHandleMessage(rctx, frame, sizeof(frame), outBuf,
|
||||
&outSz);
|
||||
ASSERT_EQ(rc, WOLFSPDM_E_BAD_STATE,
|
||||
"secured record after reset must return BAD_STATE");
|
||||
ASSERT_EQ(g_tpmCbInvocations, 0,
|
||||
"reset record must not reach the TPM callback");
|
||||
|
||||
wolfSPDM_RespFree(rctx);
|
||||
TEST_PASS();
|
||||
}
|
||||
|
||||
#ifdef WOLFSPDM_NATIONS
|
||||
/* Send one vendor-defined command in a TCG clear frame. */
|
||||
static int resp_send_clear_vd(WOLFSPDM_RESP_CTX* rctx, const char* vdCode,
|
||||
|
|
@ -2408,6 +2453,9 @@ static int test_responder_psk_roundtrip(void)
|
|||
byte rctxBuf[WOLFSPDM_RESP_CTX_STATIC_SIZE];
|
||||
WOLFSPDM_RESP_CTX* rctx = (WOLFSPDM_RESP_CTX*)rctxBuf;
|
||||
byte cmd[10];
|
||||
byte frame[WOLFSPDM_TCG_HEADER_SIZE + 1];
|
||||
byte outBuf[64];
|
||||
word32 outSz;
|
||||
int rc;
|
||||
|
||||
printf("test_responder_psk_roundtrip...\n");
|
||||
|
|
@ -2445,6 +2493,19 @@ static int test_responder_psk_roundtrip(void)
|
|||
|
||||
ASSERT_SUCCESS(wolfSPDM_Disconnect(&req));
|
||||
|
||||
/* Session teardown must reject any later secured record until a new
|
||||
* handshake establishes fresh traffic keys. */
|
||||
XMEMSET(frame, 0, sizeof(frame));
|
||||
wolfSPDM_WriteTcgHeader(frame, WOLFSPDM_TCG_TAG_SECURED,
|
||||
sizeof(frame), 0, 0);
|
||||
outSz = sizeof(outBuf);
|
||||
rc = wolfSPDM_RespHandleMessage(rctx, frame, sizeof(frame), outBuf,
|
||||
&outSz);
|
||||
ASSERT_EQ(rc, WOLFSPDM_E_BAD_STATE,
|
||||
"secured record after session teardown must return BAD_STATE");
|
||||
ASSERT_EQ(g_tpmCbInvocations, 1,
|
||||
"sessionless record must not reach the TPM callback");
|
||||
|
||||
wolfSPDM_RespFree(rctx);
|
||||
wolfSPDM_Free(&req);
|
||||
TEST_PASS();
|
||||
|
|
@ -2592,6 +2653,7 @@ int main(void)
|
|||
test_responder_no_plaintext_bypass();
|
||||
#ifdef WOLFTPM_SPDM_TCG
|
||||
test_responder_no_clear_tpm2_cmd();
|
||||
test_responder_secured_requires_session();
|
||||
#ifdef WOLFSPDM_NATIONS
|
||||
test_responder_psk_replace_guard();
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3486,8 +3486,7 @@ static int SensitiveToPrivate(TPM2B_SENSITIVE* sens, TPM2B_PRIVATE* priv,
|
|||
|
||||
/* store the size of the integrity */
|
||||
if (rc == 0) {
|
||||
digestSz = TPM2_Packet_SwapU16(digestSz);
|
||||
XMEMCPY(&priv->buffer[0], &digestSz, sizeof(word16));
|
||||
TPM2_Packet_U16ToByteArray((word16)digestSz, &priv->buffer[0]);
|
||||
}
|
||||
|
||||
TPM2_ForceZero(&symKey, sizeof(symKey));
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -893,6 +893,11 @@ typedef struct FWTPM_CTX {
|
|||
* locality); 0-4 = owner, -1 = none. TIS layer only. */
|
||||
int tisLocality;
|
||||
#endif
|
||||
|
||||
#ifndef FWTPM_NO_NV
|
||||
/* Transient authorization methods for the command being dispatched. */
|
||||
byte activeCmdAuthIsPolicy[FWTPM_MAX_CMD_AUTHS];
|
||||
#endif
|
||||
} FWTPM_CTX;
|
||||
|
||||
/* fwTPM SPDM mode bits - used with FWTPM_CTX.spdmMode. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue