diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c | 901 |
1 files changed, 901 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c new file mode 100644 index 00000000..5a975057 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c @@ -0,0 +1,901 @@ +/** @file + Provide functions to provide tcg storage core spec related functions. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Library/TcgStorageCoreLib.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> + +typedef struct { + UINT16 FeatureCode; + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER *Feature; + UINTN FeatureSize; +} TCG_FIND_FEATURE_CTX; + +/** + Returns a human-readable string representing a method status return code. + + @param[in] MethodStatus Method status to translate to a string + + + @retval return the string info. +**/ +CHAR8* +EFIAPI +TcgMethodStatusString( + UINT8 MethodStatus + ) +{ + switch (MethodStatus) { + #define C(status) case TCG_METHOD_STATUS_CODE_ ## status: return #status + C(SUCCESS); + C(NOT_AUTHORIZED); + C(OBSOLETE); + C(SP_BUSY); + C(SP_FAILED); + C(SP_DISABLED); + C(SP_FROZEN); + C(NO_SESSIONS_AVAILABLE); + C(UNIQUENESS_CONFLICT); + C(INSUFFICIENT_SPACE); + C(INSUFFICIENT_ROWS); + C(INVALID_PARAMETER); + C(OBSOLETE2); + C(OBSOLETE3); + C(TPER_MALFUNCTION); + C(TRANSACTION_FAILURE); + C(RESPONSE_OVERFLOW); + C(AUTHORITY_LOCKED_OUT); + C(FAIL); + #undef C + } + return "unknown"; +} + + +/** + adds call token and method Header (invoking id, and method id). + + @param CreateStruct The input create structure. + @param InvokingId Invoking id. + @param MethodId Method id. + +**/ +TCG_RESULT +EFIAPI +TcgStartMethodCall( + TCG_CREATE_STRUCT *CreateStruct, + TCG_UID InvokingId, + TCG_UID MethodId + ) +{ + NULL_CHECK(CreateStruct); + + if (CreateStruct->ComPacket == NULL || + CreateStruct->CurPacket == NULL || + CreateStruct->CurSubPacket == NULL + ) { + DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket)); + return (TcgResultFailureInvalidAction); + } + + ERROR_CHECK(TcgAddCall(CreateStruct)); + ERROR_CHECK(TcgAddTcgUid(CreateStruct, InvokingId)); + ERROR_CHECK(TcgAddTcgUid(CreateStruct, MethodId)); + + return TcgResultSuccess; +} + +/** + Adds START LIST token. + + @param CreateStruct The input create structure. + +**/ +TCG_RESULT +EFIAPI +TcgStartParameters( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + NULL_CHECK(CreateStruct); + + if (CreateStruct->ComPacket == NULL || + CreateStruct->CurPacket == NULL || + CreateStruct->CurSubPacket == NULL + ) { + DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket)); + return (TcgResultFailureInvalidAction); + } + + return TcgAddStartList(CreateStruct); +} + +/** + Adds END LIST token. + + @param CreateStruct The input create structure. + +**/ +TCG_RESULT +EFIAPI +TcgEndParameters( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + NULL_CHECK(CreateStruct); + + if (CreateStruct->ComPacket == NULL || + CreateStruct->CurPacket == NULL || + CreateStruct->CurSubPacket == NULL + ) { + DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket)); + return (TcgResultFailureInvalidAction); + } + + return TcgAddEndList(CreateStruct); +} + +/** + Adds END Data token and method list. + + @param CreateStruct The input create structure. + +**/ +TCG_RESULT +EFIAPI +TcgEndMethodCall( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + NULL_CHECK(CreateStruct); + + if (CreateStruct->ComPacket == NULL || + CreateStruct->CurPacket == NULL || + CreateStruct->CurSubPacket == NULL + ) { + DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket)); + return (TcgResultFailureInvalidAction); + } + + ERROR_CHECK(TcgAddEndOfData(CreateStruct)); + + ERROR_CHECK(TcgAddStartList(CreateStruct)); + ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00)); // expected to complete properly + ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00)); // reserved + ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00)); // reserved + ERROR_CHECK(TcgAddEndList(CreateStruct)); + + return TcgResultSuccess; +} + +/** + Retrieves the comID and Extended comID of the ComPacket in the Tcg response. + It is intended to be used to confirm the received Tcg response is intended for user that received it. + + @param [in] ParseStruct Structure used to parse received TCG response. + @param [in/out] ComId comID retrieved from received ComPacket. + @param [in/out] ComIdExtension Extended comID retrieved from received ComPacket + +**/ +TCG_RESULT +EFIAPI +TcgGetComIds( + const TCG_PARSE_STRUCT *ParseStruct, + UINT16 *ComId, + UINT16 *ComIdExtension + ) +{ + NULL_CHECK(ParseStruct); + NULL_CHECK(ComId); + NULL_CHECK(ComIdExtension); + + if (ParseStruct->ComPacket == NULL) { + DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p\n", ParseStruct->ComPacket)); + return TcgResultFailureInvalidAction; + } + + *ComId = SwapBytes16(ParseStruct->ComPacket->ComIDBE); + *ComIdExtension = SwapBytes16(ParseStruct->ComPacket->ComIDExtensionBE); + + return TcgResultSuccess; +} + +/** + Checks if the ComIDs of the response match the expected values. + + @param[in] ParseStruct Structure used to parse received TCG response + @param[in] ExpectedComId Expected comID + @param[in] ExpectedComIdExtension Expected extended comID + +**/ +TCG_RESULT +EFIAPI +TcgCheckComIds( + const TCG_PARSE_STRUCT *ParseStruct, + UINT16 ExpectedComId, + UINT16 ExpectedComIdExtension + ) +{ + UINT16 ParseComId; + UINT16 ParseComIdExtension; + + ERROR_CHECK(TcgGetComIds(ParseStruct, &ParseComId, &ParseComIdExtension)); + if (ParseComId != ExpectedComId || ParseComIdExtension != ExpectedComIdExtension) { + DEBUG ((DEBUG_INFO, "Com ID: Actual 0x%02X Expected 0x%02X\n", ParseComId, ExpectedComId)); + DEBUG ((DEBUG_INFO, "Extended Com ID: 0x%02X Expected 0x%02X\n", ParseComIdExtension, ExpectedComIdExtension)); + return TcgResultFailure; + } + return TcgResultSuccess; +} + +/** + Returns the method status of the current subpacket. Does not affect the current position + in the ComPacket. In other words, it can be called whenever you have a valid SubPacket. + + @param [in/out] ParseStruct Structure used to parse received TCG response + @param [in/out] MethodStatus Method status retrieved of the current SubPacket + +**/ +TCG_RESULT +EFIAPI +TcgGetMethodStatus( + const TCG_PARSE_STRUCT *ParseStruct, + UINT8 *MethodStatus + ) +{ + TCG_PARSE_STRUCT TmpParseStruct; + TCG_TOKEN TcgToken; + UINT8 Reserved1, Reserved2; + + NULL_CHECK(ParseStruct); + NULL_CHECK(MethodStatus); + + if (ParseStruct->ComPacket == NULL || + ParseStruct->CurPacket == NULL || + ParseStruct->CurSubPacket == NULL + ) { + DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", ParseStruct->ComPacket, ParseStruct->CurPacket, ParseStruct->CurSubPacket)); + return TcgResultFailureInvalidAction; + } + + // duplicate ParseStruct, then don't need to "reset" location cur ptr + CopyMem (&TmpParseStruct, ParseStruct, sizeof(TCG_PARSE_STRUCT)); + + // method status list exists after the end method call in the subpacket + // skip tokens until ENDDATA is found + do { + ERROR_CHECK(TcgGetNextToken(&TmpParseStruct, &TcgToken)); + } while (TcgToken.Type != TcgTokenTypeEndOfData); + + // only reach here if enddata is found + // at this point, the curptr is pointing at method status list beginning + ERROR_CHECK(TcgGetNextStartList(&TmpParseStruct)); + ERROR_CHECK(TcgGetNextUINT8(&TmpParseStruct, MethodStatus)); + ERROR_CHECK(TcgGetNextUINT8(&TmpParseStruct, &Reserved1)); + ERROR_CHECK(TcgGetNextUINT8(&TmpParseStruct, &Reserved2)); + ERROR_CHECK(TcgGetNextEndList(&TmpParseStruct)); + + if (Reserved1 != 0) { + DEBUG ((DEBUG_INFO, "Method status reserved1 = 0x%02X (expected 0)\n", Reserved1)); + return TcgResultFailure; + } + + if (Reserved2 != 0) { + DEBUG ((DEBUG_INFO, "Method status reserved2 = 0x%02X (expected 0)\n", Reserved1)); + return TcgResultFailure; + } + + return TcgResultSuccess; +} + +/** + Return the toke type string info. + + @param Type Input the type info. + + @retval Return the string for this type. + +**/ +CHAR8* +EFIAPI +TcgTokenTypeString( + TCG_TOKEN_TYPE Type + ) +{ + switch (Type) { + case TcgTokenTypeReserved: return "Reserved"; + case TcgTokenTypeTinyAtom: return "Tiny Atom"; + case TcgTokenTypeShortAtom: return "Short Atom"; + case TcgTokenTypeMediumAtom: return "Medium Atom"; + case TcgTokenTypeLongAtom: return "Long Atom"; + case TcgTokenTypeStartList: return "Start List"; + case TcgTokenTypeEndList: return "End List"; + case TcgTokenTypeStartName: return "Start Name"; + case TcgTokenTypeEndName: return "End Name"; + case TcgTokenTypeCall: return "Call"; + case TcgTokenTypeEndOfData: return "End of Data"; + case TcgTokenTypeEndOfSession: return "End of Session"; + case TcgTokenTypeStartTransaction: return "Start Transaction"; + case TcgTokenTypeEndTransaction: return "End Transaction"; + case TcgTokenTypeEmptyAtom: return "Empty atom"; + } + return "Unknown"; +} + + +/** + + Adds Start Session call to the data structure. This creates the entire ComPacket structure and + returns the size of the entire compacket in the size parameter. + + @param [in/out] CreateStruct Structure used to add the start session call + @param [in/out] Size Describes the size of the entire ComPacket (header and payload). Filled out by function. + @param [in] ComId ComID for the ComPacket + @param [in] ComIdExtension Extended ComID for the ComPacket + @param [in] HostSessionId Host Session ID + @param [in] SpId Security Provider to start session with + @param [in] Write Write option for start session. TRUE = start session requests write access + @param [in] HostChallengeLength Length of the host challenge. Length should be 0 if hostChallenge is NULL + @param [in] HostChallenge Host challenge for Host Signing Authority. If NULL, then no Host Challenge shall be sent. + @param [in] HostSigningAuthority Host Signing Authority used for start session. If NULL, then no Host Signing Authority shall be sent. + +**/ +TCG_RESULT +EFIAPI +TcgCreateStartSession( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 *Size, + UINT16 ComId, + UINT16 ComIdExtension, + UINT32 HostSessionId, + TCG_UID SpId, + BOOLEAN Write, + UINT32 HostChallengeLength, + const VOID *HostChallenge, + TCG_UID HostSigningAuthority + ) +{ + ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension)); + ERROR_CHECK(TcgStartPacket(CreateStruct, 0x0, 0x0, 0x0, 0x0, 0x0)) ; + ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0)); + ERROR_CHECK(TcgStartMethodCall(CreateStruct, TCG_UID_SMUID, TCG_UID_SM_START_SESSION)); + ERROR_CHECK(TcgStartParameters(CreateStruct)); + ERROR_CHECK(TcgAddUINT32(CreateStruct, HostSessionId)); + ERROR_CHECK(TcgAddTcgUid(CreateStruct, SpId)); + ERROR_CHECK(TcgAddBOOLEAN(CreateStruct, Write)); + + // optional parameters + if (HostChallenge != NULL && HostChallengeLength != 0) { + ERROR_CHECK(TcgAddStartName(CreateStruct)); + ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00)); //TODO Create Enum for Method Optional Parameters? + ERROR_CHECK(TcgAddByteSequence(CreateStruct, HostChallenge, HostChallengeLength, FALSE)); + ERROR_CHECK(TcgAddEndName(CreateStruct)); + } + // optional parameters + if (HostSigningAuthority != 0) { + ERROR_CHECK(TcgAddStartName(CreateStruct)); + ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x03)); //TODO Create Enum for Method Optional Parameters? + ERROR_CHECK(TcgAddTcgUid(CreateStruct, HostSigningAuthority)); + ERROR_CHECK(TcgAddEndName(CreateStruct)); + } + + ERROR_CHECK(TcgEndParameters(CreateStruct)); + ERROR_CHECK(TcgEndMethodCall(CreateStruct)); + ERROR_CHECK(TcgEndSubPacket(CreateStruct)); + ERROR_CHECK(TcgEndPacket(CreateStruct)); + ERROR_CHECK(TcgEndComPacket(CreateStruct, Size)); + + return TcgResultSuccess; +} + +/** + Parses the Sync Session response contained in the parseStruct to retrieve Tper session ID. If the Sync Session response + parameters do not match the comID, extended ComID and host session ID then a failure is returned. + + @param[in/out] ParseStruct Structure used to parse received TCG response, contains Sync Session response. + @param[in] ComId Expected ComID that is compared to actual ComID of response + @param[in] ComIdExtension Expected Extended ComID that is compared to actual Extended ComID of response + @param[in] HostSessionId Expected Host Session ID that is compared to actual Host Session ID of response + @param[in/out] TperSessionId Tper Session ID retrieved from the Sync Session response. + +**/ +TCG_RESULT +EFIAPI +TcgParseSyncSession( + const TCG_PARSE_STRUCT *ParseStruct, + UINT16 ComId, + UINT16 ComIdExtension, + UINT32 HostSessionId, + UINT32 *TperSessionId + ) +{ + UINT8 MethodStatus; + TCG_PARSE_STRUCT TmpParseStruct; + UINT16 ParseComId; + UINT16 ParseExtComId; + TCG_UID InvokingUID; + TCG_UID MethodUID; + UINT32 RecvHostSessionId; + + NULL_CHECK(ParseStruct); + NULL_CHECK(TperSessionId); + + CopyMem (&TmpParseStruct, ParseStruct, sizeof(TCG_PARSE_STRUCT)); + + // verify method status is good + ERROR_CHECK(TcgGetMethodStatus(&TmpParseStruct, &MethodStatus)); + METHOD_STATUS_ERROR_CHECK (MethodStatus, TcgResultFailure); + + // verify comids + ERROR_CHECK(TcgGetComIds(&TmpParseStruct, &ParseComId, &ParseExtComId)); + + if ((ComId != ParseComId) || (ComIdExtension != ParseExtComId)) { + DEBUG ((DEBUG_INFO, "unmatched comid (exp: 0x%X recv: 0x%X) or comid extension (exp: 0x%X recv: 0x%X)\n", ComId, ParseComId, ComIdExtension, ParseExtComId)); + return TcgResultFailure; + } + ERROR_CHECK(TcgGetNextCall(&TmpParseStruct)); + ERROR_CHECK(TcgGetNextTcgUid(&TmpParseStruct, &InvokingUID)); + ERROR_CHECK(TcgGetNextTcgUid(&TmpParseStruct, &MethodUID)); + ERROR_CHECK(TcgGetNextStartList(&TmpParseStruct)); + ERROR_CHECK(TcgGetNextUINT32(&TmpParseStruct, &RecvHostSessionId)); + ERROR_CHECK(TcgGetNextUINT32(&TmpParseStruct, TperSessionId)); + ERROR_CHECK(TcgGetNextEndList(&TmpParseStruct)); + ERROR_CHECK(TcgGetNextEndOfData(&TmpParseStruct)); + + if (InvokingUID != TCG_UID_SMUID) { + DEBUG ((DEBUG_INFO, "Invoking UID did not match UID_SMUID\n")); + return TcgResultFailure; + } + + if (MethodUID != TCG_UID_SM_SYNC_SESSION) { + DEBUG ((DEBUG_INFO, "Method UID did not match UID_SM_SYNC_SESSION\n")); + return TcgResultFailure; + } + + if (HostSessionId != RecvHostSessionId) { + DEBUG ((DEBUG_INFO, "unmatched HostSessionId (exp: 0x%X recv: 0x%X)\n", HostSessionId, RecvHostSessionId)); + return TcgResultFailure; + } + + return TcgResultSuccess; +} + +/** + + Creates ComPacket with EndSession. + This assumes a start session has already been opened. + + @param [in/out] CreateStruct Structure used to add Endsession + @param [in/out] Size Describes the size of the entire ComPacket (header and payload). Filled out by function. + @param [in] ComId ComID for the ComPacket + @param [in] ComIdExtension Extended ComID for the ComPacket + @param [in] HostSessionId Host Session ID for the Packet + @param [in] TpSessionId Tper Session ID for the Packet + +**/ +TCG_RESULT +EFIAPI +TcgCreateEndSession( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 *Size, + UINT16 ComId, + UINT16 ComIdExtension, + UINT32 HostSessionId, + UINT32 TpSessionId + ) +{ + ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension)); + ERROR_CHECK(TcgStartPacket(CreateStruct, TpSessionId, HostSessionId, 0x0, 0x0, 0x0)); + ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0)); + ERROR_CHECK(TcgAddEndOfSession(CreateStruct)); + ERROR_CHECK(TcgEndSubPacket(CreateStruct)); + ERROR_CHECK(TcgEndPacket(CreateStruct)); + ERROR_CHECK(TcgEndComPacket(CreateStruct, Size)); + + return TcgResultSuccess; +} + +/** + Set start method. + + @param CreateStruct Input create structure. + @param Row Input the row info. + @param ColumnNumber the column info. + +**/ +TCG_RESULT +EFIAPI +TcgStartMethodSet( + TCG_CREATE_STRUCT *CreateStruct, + TCG_UID Row, + UINT32 ColumnNumber + ) +{ + ERROR_CHECK(TcgStartMethodCall(CreateStruct, Row, TCG_UID_METHOD_SET)); + ERROR_CHECK(TcgStartParameters(CreateStruct)); + ERROR_CHECK(TcgAddStartName(CreateStruct)); + ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x01)); // "Values" + ERROR_CHECK(TcgAddStartList(CreateStruct)); + ERROR_CHECK(TcgAddStartName(CreateStruct)); + ERROR_CHECK(TcgAddUINT32(CreateStruct, ColumnNumber)); + return TcgResultSuccess; +} + +/** + Set end method. + + @param CreateStruct Input create structure. + +**/ +TCG_RESULT +EFIAPI +TcgEndMethodSet( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + ERROR_CHECK(TcgAddEndName(CreateStruct)); + ERROR_CHECK(TcgAddEndList(CreateStruct)); + ERROR_CHECK(TcgAddEndName(CreateStruct)); + ERROR_CHECK(TcgEndParameters(CreateStruct)); + ERROR_CHECK(TcgEndMethodCall(CreateStruct)); + return TcgResultSuccess; +} + +/** + Creates ComPacket with a Method call that sets the PIN column for the row specified. + This assumes a start session has already been opened with the desired SP. + + @param [in/out] CreateStruct Structure used to add method call. + @param [in/out] Size Describes the size of the entire ComPacket (header and payload). Filled out by function. + @param [in] ComId ComID for the ComPacket + @param [in] ComIdExtension Extended ComID for the ComPacket + @param [in] TperSession Tper Session ID for the Packet + @param [in] HostSession Host Session ID for the Packet + @param [in] SidRow UID of row of current SP to set PIN column + @param [in] Password value of PIN to set + @param [in] PasswordSize Size of PIN + +**/ +TCG_RESULT +EFIAPI +TcgCreateSetCPin( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 *Size, + UINT16 ComId, + UINT16 ComIdExtension, + UINT32 TperSession, + UINT32 HostSession, + TCG_UID SidRow, + const VOID *Password, + UINT32 PasswordSize + ) +{ + // set new SID Password + ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension)); + ERROR_CHECK(TcgStartPacket(CreateStruct, TperSession, HostSession, 0x0, 0x0, 0x0)); + ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0)); + ERROR_CHECK(TcgStartMethodSet(CreateStruct, SidRow, 0x03)); // "PIN" + ERROR_CHECK(TcgAddByteSequence(CreateStruct, Password, PasswordSize, FALSE)); + ERROR_CHECK(TcgEndMethodSet(CreateStruct)); + ERROR_CHECK(TcgEndSubPacket(CreateStruct)); + ERROR_CHECK(TcgEndPacket(CreateStruct)); + ERROR_CHECK(TcgEndComPacket(CreateStruct, Size)); + return TcgResultSuccess; +} + +/** + Creates ComPacket with a Method call that sets the "Enabled" column for the row specified using the value specified. + This assumes a start session has already been opened with the desired SP. + + @param [in/out] CreateStruct Structure used to add method call + @param [in/out] Size Describes the size of the entire ComPacket (header and payload). Filled out by function. + @param [in] ComId ComID for the ComPacket + @param [in] ComIdExtension Extended ComID for the ComPacket + @param [in] TperSession Tper Session ID for the Packet + @param [in] HostSession Host Session ID for the Packet + @param [in] AuthorityUid Authority UID to modify the "Enabled" column for + @param [in] Enabled Value to set the "Enabled" column to + +**/ +TCG_RESULT +EFIAPI +TcgSetAuthorityEnabled( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 *Size, + UINT16 ComId, + UINT16 ComIdExtension, + UINT32 TperSession, + UINT32 HostSession, + TCG_UID AuthorityUid, + BOOLEAN Enabled + ) +{ + ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension)); + ERROR_CHECK(TcgStartPacket(CreateStruct, TperSession, HostSession, 0x0, 0x0, 0x0)); + ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0)); + ERROR_CHECK(TcgStartMethodSet(CreateStruct, AuthorityUid, 0x05)); // "Enabled" + ERROR_CHECK(TcgAddBOOLEAN(CreateStruct, Enabled)); + ERROR_CHECK(TcgEndMethodSet(CreateStruct)); + ERROR_CHECK(TcgEndSubPacket(CreateStruct)); + ERROR_CHECK(TcgEndPacket(CreateStruct)); + ERROR_CHECK(TcgEndComPacket(CreateStruct, Size)); + return TcgResultSuccess; +} + +/** + Create set ace. + + @param CreateStruct Input create structure. + @param Size size info. + @param ComId ComId info. + @param ComIdExtension ComId extension info. + @param TperSession Tper session data. + @param HostSession Host session data. + @param AceRow Ace row info. + @param Authority1 Authority 1 info. + @param LogicalOperator Logical operator info. + @param Authority2 Authority 2 info. + + @retval Return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgCreateSetAce( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 *Size, + UINT16 ComId, + UINT16 ComIdExtension, + UINT32 TperSession, + UINT32 HostSession, + TCG_UID AceRow, + TCG_UID Authority1, + BOOLEAN LogicalOperator, + TCG_UID Authority2 + ) +{ + UINT8 HalfUidAuthorityObjectRef[4]; + UINT8 HalfUidBooleanAce[4]; + + HalfUidAuthorityObjectRef[0] = 0x0; + HalfUidAuthorityObjectRef[1] = 0x0; + HalfUidAuthorityObjectRef[2] = 0xC; + HalfUidAuthorityObjectRef[3] = 0x5; + + HalfUidBooleanAce[0] = 0x0; + HalfUidBooleanAce[1] = 0x0; + HalfUidBooleanAce[2] = 0x4; + HalfUidBooleanAce[3] = 0xE; + + ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension)); + ERROR_CHECK(TcgStartPacket(CreateStruct, TperSession, HostSession, 0x0, 0x0, 0x0)); + ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0)); + ERROR_CHECK(TcgStartMethodSet(CreateStruct, AceRow, 0x03)); // "BooleanExpr" + ERROR_CHECK(TcgAddStartList(CreateStruct)); + ERROR_CHECK(TcgAddStartName(CreateStruct)); + ERROR_CHECK(TcgAddByteSequence(CreateStruct, HalfUidAuthorityObjectRef, sizeof(HalfUidAuthorityObjectRef), FALSE)); + ERROR_CHECK(TcgAddTcgUid(CreateStruct, Authority1)); + ERROR_CHECK(TcgAddEndName(CreateStruct)); + ERROR_CHECK(TcgAddStartName(CreateStruct)); + ERROR_CHECK(TcgAddByteSequence(CreateStruct, HalfUidAuthorityObjectRef, sizeof(HalfUidAuthorityObjectRef), FALSE)); + ERROR_CHECK(TcgAddTcgUid(CreateStruct, Authority2)); + ERROR_CHECK(TcgAddEndName(CreateStruct)); + + ERROR_CHECK(TcgAddStartName(CreateStruct)); + ERROR_CHECK(TcgAddByteSequence(CreateStruct, HalfUidBooleanAce, sizeof(HalfUidBooleanAce), FALSE)); + ERROR_CHECK(TcgAddBOOLEAN(CreateStruct, LogicalOperator)); + ERROR_CHECK(TcgAddEndName(CreateStruct)); + ERROR_CHECK(TcgAddEndList(CreateStruct)); + ERROR_CHECK(TcgEndMethodSet(CreateStruct)); + ERROR_CHECK(TcgEndSubPacket(CreateStruct)); + ERROR_CHECK(TcgEndPacket(CreateStruct)); + ERROR_CHECK(TcgEndComPacket(CreateStruct, Size)); + return TcgResultSuccess; +} + +/** + Enum level 0 discovery. + + @param DiscoveryHeader Discovery header. + @param Callback Callback function. + @param Context The context for the function. + + @retval return true if the callback return TRUE, else return FALSE. + +**/ +BOOLEAN +EFIAPI +TcgEnumLevel0Discovery( + const TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader, + TCG_LEVEL0_ENUM_CALLBACK Callback, + VOID *Context + ) +{ + UINT32 BytesLeft; + const UINT8 *DiscoveryBufferPtr; + UINT32 FeatLength; + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER *Feat; + + // + // Total bytes including descriptors but not including the Length field + // + BytesLeft = SwapBytes32(DiscoveryHeader->LengthBE); + + // + // If discovery Header is not valid, exit + // + if (BytesLeft == 0) { + return FALSE; + } + + // + // Subtract the Length of the Header, except the Length field, which is not included + // + BytesLeft -= (sizeof(TCG_LEVEL0_DISCOVERY_HEADER) - sizeof(DiscoveryHeader->LengthBE)); + + // + // Move ptr to first descriptor + // + DiscoveryBufferPtr = (const UINT8*)DiscoveryHeader + sizeof(TCG_LEVEL0_DISCOVERY_HEADER); + + while (BytesLeft > sizeof(TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER)) { + // + // Pointer to beginning of descriptor (including common Header) + // + Feat = (TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER*)DiscoveryBufferPtr; + + FeatLength = Feat->Length + sizeof(TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER); + + // + // Not enough bytes left for Feature descriptor + // + if (BytesLeft < FeatLength) { + break; + } + + // + // Report the Feature to the callback + // + if (Callback(DiscoveryHeader, Feat, FeatLength, Context)) { + return TRUE; + } + + // + // Descriptor Length only describes Data after common Header + // + BytesLeft -= FeatLength; + DiscoveryBufferPtr += FeatLength; + } + + return FALSE; +} + +/** + The callback function for Get Feature function. + + @param DiscoveryHeader Input discovery header. + @param Feature Input Feature. + @param FeatureSize Input Feature size. + @param Context The context. + +**/ +BOOLEAN +EFIAPI +TcgFindFeatureCallback( + const TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader, + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER *Feature, + UINTN FeatureSize, + VOID *Context + ) +{ + TCG_FIND_FEATURE_CTX* FindCtx; + + FindCtx = (TCG_FIND_FEATURE_CTX*)Context; + if ( SwapBytes16( Feature->FeatureCode_BE ) == FindCtx->FeatureCode ) { + FindCtx->Feature = Feature; + FindCtx->FeatureSize = FeatureSize; + return TRUE; // done enumerating features + } + return FALSE; // continue enumerating +} + +/** + Get Feature code from the header. + + @param DiscoveryHeader The discovery header. + @param FeatureCode return the Feature code. + @param FeatureSize return the Feature size. + + @retval return the Feature code data. +**/ +TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER* +EFIAPI +TcgGetFeature( + const TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader, + UINT16 FeatureCode, + UINTN *FeatureSize + ) +{ + TCG_FIND_FEATURE_CTX FindCtx; + + FindCtx.FeatureCode = FeatureCode; + FindCtx.Feature = NULL; + FindCtx.FeatureSize = 0; + + TcgEnumLevel0Discovery(DiscoveryHeader, TcgFindFeatureCallback, &FindCtx); + if (FeatureSize != NULL) { + *FeatureSize = FindCtx.FeatureSize; + } + return FindCtx.Feature; +} + +/** + Determines if the protocol provided is part of the provided supported protocol list. + + @param[in] ProtocolList Supported protocol list to investigate + @param[in] Protocol Protocol value to determine if supported + + @return TRUE = protocol is supported, FALSE = protocol is not supported +**/ +BOOLEAN +EFIAPI +TcgIsProtocolSupported( + const TCG_SUPPORTED_SECURITY_PROTOCOLS *ProtocolList, + UINT16 Protocol + ) +{ + UINT16 Index; + UINT16 ListLength; + + ListLength = SwapBytes16(ProtocolList->ListLength_BE); + + if (ListLength > sizeof(ProtocolList->List)) { + DEBUG ((DEBUG_INFO, "WARNING: list Length is larger than max allowed Value; truncating\n")); + ListLength = sizeof(ProtocolList->List); + } + + for (Index = 0; Index < ListLength; Index++) { + if (ProtocolList->List[Index] == Protocol) { + return TRUE; + } + } + + return FALSE; +} + +/** + Check whether lock or not. + + @param Discovery + + @retval TRUE if lock, FALSE if not lock. +**/ +BOOLEAN +EFIAPI +TcgIsLocked( + const TCG_LEVEL0_DISCOVERY_HEADER *Discovery + ) +{ + UINTN Size; + TCG_LOCKING_FEATURE_DESCRIPTOR *LockDescriptor; + + Size = 0; + LockDescriptor =(TCG_LOCKING_FEATURE_DESCRIPTOR*) TcgGetFeature (Discovery, TCG_FEATURE_LOCKING, &Size); + + if (LockDescriptor != NULL && Size >= sizeof(*LockDescriptor)) { + DEBUG ((DEBUG_INFO, "locked: %d\n", LockDescriptor->Locked)); + return LockDescriptor->Locked; + } + + // + // Descriptor was not found + // + return FALSE; +} |