tpm2: Only write the necessary number of bytes of command bitmaps

Only write the necessary number of bytes of the ppList and auditCommands
bitmaps. The entries in both of these bitmaps are set by a command's
index and the necessary number of bytes can be determined by finding the
command with the highest command code that is enabled in the current
profile (1). This in turn can be found by by searching for the last byte
in the enableCommandsByIdx bitmap that has any bit set.

1) It would be possible to skip writing these arrays entirely if they have
   no bits set. The unmarshalling functions would clear the arrays.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
Stefan Berger 2026-03-09 13:13:39 -04:00 committed by Stefan Berger
parent 2fa21bb386
commit 426cc786c6
3 changed files with 38 additions and 6 deletions

View File

@ -4106,7 +4106,8 @@ skip_future_versions:
static UINT16
PERSISTENT_DATA_PPList_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size,
UINT16 blob_version, UINT32 commandCount)
UINT16 blob_version,
UINT32 commandCount, UINT32 commandArraySize)
{
UINT8 ppList[(110 + 7) / 8];
UINT16 array_size;
@ -4126,7 +4127,8 @@ PERSISTENT_DATA_PPList_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size
ptr = ppList;
} else {
/* write the array as it is */
array_size = sizeof(data->ppList);
array_size = commandArraySize;
assert(array_size <= sizeof(data->ppList));
ptr = data->ppList;
}
written = UINT16_Marshal(&array_size, buffer, size);
@ -4171,7 +4173,8 @@ PERSISTENT_DATA_PPList_Unmarshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *si
static UINT16
PERSISTENT_DATA_AuditCommands_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size,
UINT16 blob_version, UINT32 commandCount)
UINT16 blob_version,
UINT32 commandCount, UINT32 commandArraySize)
{
UINT8 auditCommands[(110 + 1 + 7) / 8];
UINT16 array_size;
@ -4192,7 +4195,8 @@ PERSISTENT_DATA_AuditCommands_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT3
ptr = auditCommands;
} else {
/* write the array as it is */
array_size = sizeof(data->auditCommands);
array_size = commandArraySize;
assert(array_size <= sizeof(data->auditCommands));
ptr = data->auditCommands;
}
written = UINT16_Marshal(&array_size, buffer, size);
@ -4244,6 +4248,7 @@ PERSISTENT_DATA_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size,
struct RuntimeProfile *RuntimeProfile)
{
UINT32 commandCount = RuntimeCommandsCountEnabled(&RuntimeProfile->RuntimeCommands);
UINT32 commandArraySize = RuntimeCommandsGetArraySize(&RuntimeProfile->RuntimeCommands);
UINT16 written;
UINT8 clocksize;
BOOL has_block;
@ -4299,7 +4304,8 @@ PERSISTENT_DATA_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size,
written += TPML_PCR_SELECTION_Marshal(&data->pcrAllocated, buffer, size);
written += PERSISTENT_DATA_PPList_Marshal(data, buffer, size, blob_version, commandCount);
written += PERSISTENT_DATA_PPList_Marshal(data, buffer, size, blob_version,
commandCount, commandArraySize);
written += UINT32_Marshal(&data->failedTries, buffer, size);
written += UINT32_Marshal(&data->maxTries, buffer, size);
written += UINT32_Marshal(&data->recoveryTime, buffer, size);
@ -4307,7 +4313,8 @@ PERSISTENT_DATA_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size,
written += BOOL_Marshal(&data->lockOutAuthEnabled, buffer, size);
written += UINT16_Marshal(&data->orderlyState, buffer, size);
written += PERSISTENT_DATA_AuditCommands_Marshal(data, buffer, size, blob_version, commandCount);
written += PERSISTENT_DATA_AuditCommands_Marshal(data, buffer, size, blob_version,
commandCount, commandArraySize);
written += TPM_ALG_ID_Marshal(&data->auditHashAlg, buffer, size);
written += UINT64_Marshal(&data->auditCounter, buffer, size);
written += UINT32_Marshal(&data->algorithmSet, buffer, size);

View File

@ -476,6 +476,28 @@ RuntimeCommandPrint(char *buffer,
return nbuffer;
}
/*
* Determine the size of a byte array where each bit represents a command.
* The size of the array depends on the command with the highest command code
* that is enabled. This function can be used to determine how many bytes
* of the ppList and auditCommands bitmaps are used at maximum and need to be
* written.
*/
LIB_EXPORT size_t
RuntimeCommandsGetArraySize(struct RuntimeCommands *RuntimeCommands)
{
size_t i;
/* search for byte where command with highest code is enabled */
for (i = sizeof(RuntimeCommands->enabledCommandsByIdx) - 1;
i >= 0;
i--) {
if (RuntimeCommands->enabledCommandsByIdx[i])
return i + 1;
}
return 0;
}
LIB_EXPORT char *
RuntimeCommandsPrint(struct RuntimeCommands *RuntimeCommands,
enum RuntimeCommandType rct)

View File

@ -80,6 +80,9 @@ RuntimeCommandsCheckEnabled(struct RuntimeCommands *RuntimeCommands,
TPM_CC cc // IN: the command code to check
);
size_t
RuntimeCommandsGetArraySize(struct RuntimeCommands *RuntimeCommands);
LIB_EXPORT UINT32
RuntimeCommandsCountEnabled(struct RuntimeCommands *RuntimeCommands);