libtpms/src/tpm2/BackwardsCompatibilityBitArray.c
Stefan Berger 811616f87d tpm2: Implement function to convert from and to compressed lists' bit arrays
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2024-07-15 14:09:09 -04:00

278 lines
9.4 KiB
C

/********************************************************************************/
/* */
/* Backwards compatibility support related to command code arrays */
/* Written by Stefan Berger */
/* IBM Thomas J. Watson Research Center */
/* */
/* (c) Copyright IBM Corporation 2023. */
/* */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or without */
/* modification, are permitted provided that the following conditions are */
/* met: */
/* */
/* Redistributions of source code must retain the above copyright notice, */
/* this list of conditions and the following disclaimer. */
/* */
/* Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in the */
/* documentation and/or other materials provided with the distribution. */
/* */
/* Neither the names of the IBM Corporation nor the names of its */
/* contributors may be used to endorse or promote products derived from */
/* this software without specific prior written permission. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/********************************************************************************/
#include <assert.h>
#include "BackwardsCompatibilityBitArray.h"
/* The following array contains exactly the commands that libtpms v0.9 had enabled
* when 'compressed lists' were used. Do not change this array anymore!
* A bit in the PERSISTEN_DATA.auditCommands array corresponds to the index in
* this array where the command code can be found.
*/
static const struct {
TPM_CC cc;
#define ENTRY(CC, INDEX) \
[INDEX] = { .cc = CC }
} CCToCompressedListIndex[] = {
ENTRY(TPM_CC_NV_UndefineSpaceSpecial, 0),
ENTRY(TPM_CC_EvictControl, 1),
ENTRY(TPM_CC_HierarchyControl, 2),
ENTRY(TPM_CC_NV_UndefineSpace, 3),
ENTRY(TPM_CC_ChangeEPS, 4),
ENTRY(TPM_CC_ChangePPS, 5),
ENTRY(TPM_CC_Clear, 6),
ENTRY(TPM_CC_ClearControl, 7),
ENTRY(TPM_CC_ClockSet, 8),
ENTRY(TPM_CC_HierarchyChangeAuth, 9),
ENTRY(TPM_CC_NV_DefineSpace, 10),
ENTRY(TPM_CC_PCR_Allocate, 11),
ENTRY(TPM_CC_PCR_SetAuthPolicy, 12),
ENTRY(TPM_CC_PP_Commands, 13),
ENTRY(TPM_CC_SetPrimaryPolicy, 14),
/* CC_FieldUpdateStart */
ENTRY(TPM_CC_ClockRateAdjust, 15),
ENTRY(TPM_CC_CreatePrimary, 16),
ENTRY(TPM_CC_NV_GlobalWriteLock, 17),
ENTRY(TPM_CC_GetCommandAuditDigest, 18),
ENTRY(TPM_CC_NV_Increment, 19),
ENTRY(TPM_CC_NV_SetBits, 20),
ENTRY(TPM_CC_NV_Extend, 21),
ENTRY(TPM_CC_NV_Write, 22),
ENTRY(TPM_CC_NV_WriteLock, 23),
ENTRY(TPM_CC_DictionaryAttackLockReset, 24),
ENTRY(TPM_CC_DictionaryAttackParameters, 25),
ENTRY(TPM_CC_NV_ChangeAuth, 26),
ENTRY(TPM_CC_PCR_Event, 27),
ENTRY(TPM_CC_PCR_Reset, 28),
ENTRY(TPM_CC_SequenceComplete, 29),
ENTRY(TPM_CC_SetAlgorithmSet, 30),
ENTRY(TPM_CC_SetCommandCodeAuditStatus, 31),
/* CC_FieldUpgradeData */
ENTRY(TPM_CC_IncrementalSelfTest, 32),
ENTRY(TPM_CC_SelfTest, 33),
ENTRY(TPM_CC_Startup, 34),
ENTRY(TPM_CC_Shutdown, 35),
ENTRY(TPM_CC_StirRandom, 36),
ENTRY(TPM_CC_ActivateCredential, 37),
ENTRY(TPM_CC_Certify, 38),
ENTRY(TPM_CC_PolicyNV, 39),
ENTRY(TPM_CC_CertifyCreation, 40),
ENTRY(TPM_CC_Duplicate, 41),
ENTRY(TPM_CC_GetTime, 42),
ENTRY(TPM_CC_GetSessionAuditDigest, 43),
ENTRY(TPM_CC_NV_Read, 44),
ENTRY(TPM_CC_NV_ReadLock, 45),
ENTRY(TPM_CC_ObjectChangeAuth, 46),
ENTRY(TPM_CC_PolicySecret, 47),
ENTRY(TPM_CC_Rewrap, 48),
ENTRY(TPM_CC_Create, 49),
ENTRY(TPM_CC_ECDH_ZGen, 50),
ENTRY(TPM_CC_HMAC, 51),
ENTRY(TPM_CC_Import, 52),
ENTRY(TPM_CC_Load, 53),
ENTRY(TPM_CC_Quote, 54),
ENTRY(TPM_CC_RSA_Decrypt, 55),
ENTRY(TPM_CC_HMAC_Start, 56),
ENTRY(TPM_CC_SequenceUpdate, 57),
ENTRY(TPM_CC_Sign, 58),
ENTRY(TPM_CC_Unseal, 59),
ENTRY(TPM_CC_PolicySigned, 60),
ENTRY(TPM_CC_ContextLoad, 61),
ENTRY(TPM_CC_ContextSave, 62),
ENTRY(TPM_CC_ECDH_KeyGen, 63),
ENTRY(TPM_CC_EncryptDecrypt, 64),
ENTRY(TPM_CC_FlushContext, 65),
ENTRY(TPM_CC_LoadExternal, 66),
ENTRY(TPM_CC_MakeCredential, 67),
ENTRY(TPM_CC_NV_ReadPublic, 68),
ENTRY(TPM_CC_PolicyAuthorize, 69),
ENTRY(TPM_CC_PolicyAuthValue, 70),
ENTRY(TPM_CC_PolicyCommandCode, 71),
ENTRY(TPM_CC_PolicyCounterTimer, 72),
ENTRY(TPM_CC_PolicyCpHash, 73),
ENTRY(TPM_CC_PolicyLocality, 74),
ENTRY(TPM_CC_PolicyNameHash, 75),
ENTRY(TPM_CC_PolicyOR, 76),
ENTRY(TPM_CC_PolicyTicket, 77),
ENTRY(TPM_CC_ReadPublic, 78),
ENTRY(TPM_CC_RSA_Encrypt, 79),
ENTRY(TPM_CC_StartAuthSession, 80),
ENTRY(TPM_CC_VerifySignature, 81),
ENTRY(TPM_CC_ECC_Parameters, 82),
/* CC_FirmwareRead */
ENTRY(TPM_CC_GetCapability, 83),
ENTRY(TPM_CC_GetRandom, 84),
ENTRY(TPM_CC_GetTestResult, 85),
ENTRY(TPM_CC_Hash, 86),
ENTRY(TPM_CC_PCR_Read, 87),
ENTRY(TPM_CC_PolicyPCR, 88),
ENTRY(TPM_CC_PolicyRestart, 89),
ENTRY(TPM_CC_ReadClock, 90),
ENTRY(TPM_CC_PCR_Extend, 91),
ENTRY(TPM_CC_PCR_SetAuthValue, 92),
ENTRY(TPM_CC_NV_Certify, 93),
ENTRY(TPM_CC_EventSequenceComplete, 94),
ENTRY(TPM_CC_HashSequenceStart, 95),
ENTRY(TPM_CC_PolicyPhysicalPresence, 96),
ENTRY(TPM_CC_PolicyDuplicationSelect, 97),
ENTRY(TPM_CC_PolicyGetDigest, 98),
ENTRY(TPM_CC_TestParms, 99),
ENTRY(TPM_CC_Commit, 100),
ENTRY(TPM_CC_PolicyPassword, 101),
ENTRY(TPM_CC_ZGen_2Phase, 102),
ENTRY(TPM_CC_EC_Ephemeral, 103),
ENTRY(TPM_CC_PolicyNvWritten, 104),
ENTRY(TPM_CC_PolicyTemplate, 105),
ENTRY(TPM_CC_CreateLoaded, 106),
ENTRY(TPM_CC_PolicyAuthorizeNV, 107),
ENTRY(TPM_CC_EncryptDecrypt2, 108),
/* CC_AC_GetCapability -- never enable here */
/* CC_AC_Send -- never enable here */
/* CC_Policy_AC_SendSelect */
ENTRY(TPM_CC_CertifyX509, 109),
/* CC_ACT_SetTimeout -- never enable here */
/* CC_ECC_Encrypt -- never enable here */
/* CC_ECC_Decrypt -- never enable here */
/* never add new commands */
};
/* Convert from a bit array from the time when COMPRESSED_LIST was YES
* to an array where the indices do NOT correspond to a COMPRESSED_LIST.
*/
TPM_RC
ConvertFromCompressedBitArray(BYTE *inAuditCommands,
size_t inAuditCommandsLen,
BYTE *outAuditCommands,
size_t outAuditCommandsLen)
{
size_t max_bit = MIN(inAuditCommandsLen * 8, ARRAY_SIZE(CCToCompressedListIndex));
size_t bit = 0;
MemorySet(outAuditCommands, 0, outAuditCommandsLen);
while (bit < max_bit) {
BYTE bits = inAuditCommands[bit >> 3];
BYTE mask = 1;
size_t lbit = bit;
while (bits != 0 && lbit < max_bit) {
if ((bits & mask) != 0) {
TPM_CC cc = CCToCompressedListIndex[lbit].cc;
COMMAND_INDEX idx = cc - TPM_CC_NV_UndefineSpaceSpecial;
assert(idx != UNIMPLEMENTED_COMMAND_INDEX);
SetBit(idx, outAuditCommands, outAuditCommandsLen);
bits ^= mask; /* unset bit */
}
mask <<= 1;
lbit++;
}
bit += 8;
}
return TPM_RC_SUCCESS;
}
static size_t FindCCInCompressedListIndexArray(TPM_CC cc)
{
size_t e_index = ARRAY_SIZE(CCToCompressedListIndex) - 1;
size_t s_index = 0;
while (true) {
size_t index = (e_index + s_index) >> 1;
if (cc == CCToCompressedListIndex[index].cc) {
return index;
}
if (e_index == s_index) {
break;
}
if (cc < CCToCompressedListIndex[index].cc) {
e_index = index;
} else {
if (s_index != index)
s_index = index;
else
s_index++;
}
}
/* entry must have been found */
pAssert(false);
}
/* Convert to a bit array from the time when COMPRESSED_LIST was YES
* from an array where the indices do NOT correspond to a COMPRESSED_LIST.
*/
TPM_RC
ConvertToCompressedBitArray(BYTE *inAuditCommands,
size_t inAuditCommandsLen,
BYTE *outAuditCommands,
size_t outAuditCommandsLen)
{
size_t max_idx = inAuditCommandsLen * 8;
size_t idx = 0;
MemorySet(outAuditCommands, 0, outAuditCommandsLen);
while (idx < max_idx) {
BYTE bits = inAuditCommands[idx >> 3];
BYTE mask = 1;
size_t lidx = idx;
/* handle bits set in one byte in the loop */
while (bits != 0 && lidx < max_idx) {
if ((bits & mask) != 0) {
TPM_CC cc = lidx + TPM_CC_NV_UndefineSpaceSpecial;
size_t bit = FindCCInCompressedListIndexArray(cc);
SetBit(bit, outAuditCommands, outAuditCommandsLen);
bits ^= mask; /* unset bit */
}
mask <<= 1;
lidx++;
}
idx += 8;
}
return TPM_RC_SUCCESS;
}