From: Eric Dong Date: Tue, 29 Mar 2016 06:41:20 +0000 (+0800) Subject: SecurityPkg: TcgStorageCoreLib: Add TCG storage core library. X-Git-Tag: edk2-stable201903~7481 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=085dcf01f7f4ed84a0ecc58e46ad5122b26539f9 SecurityPkg: TcgStorageCoreLib: Add TCG storage core library. APIs used to create commands defined by TCG storage core spec. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Eric Dong Reviewed-by: Feng Tian --- diff --git a/SecurityPkg/Include/Library/TcgStorageCoreLib.h b/SecurityPkg/Include/Library/TcgStorageCoreLib.h new file mode 100644 index 0000000000..67ccf22892 --- /dev/null +++ b/SecurityPkg/Include/Library/TcgStorageCoreLib.h @@ -0,0 +1,1310 @@ +/** @file + Public API for the Tcg Core library to perform the lowest level TCG Data encoding. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TCG_CORE_H_ +#define _TCG_CORE_H_ + +#include + +#define ERROR_CHECK(arg) \ + { \ + TCG_RESULT ret = (arg); \ + if (ret != TcgResultSuccess) { \ + DEBUG ((DEBUG_INFO, "ERROR_CHECK failed at %s:%u\n", __FILE__, __LINE__)); \ + return ret; \ + } \ + } + +#define METHOD_STATUS_ERROR_CHECK(arg, failRet) \ + if ((arg) != TCG_METHOD_STATUS_CODE_SUCCESS) { \ + DEBUG ((DEBUG_INFO, "Method Status error: 0x%02X (%s)\n", arg, TcgMethodStatusString(arg))); \ + return (failRet); \ + } + +#define NULL_CHECK(arg) \ + do { \ + if ((arg) == NULL) { \ + DEBUG ((DEBUG_INFO, "NULL_CHECK(%s) failed at %s:%u\n", #arg, __FILE__, __LINE__)); \ + return TcgResultFailureNullPointer; \ + } \ + } while (0) + +#pragma pack(1) + +/** +Tcg result codes. + +The result code indicates if the Tcg function call was successful or not +**/ +typedef enum { + // + // This is the return result upon successful completion of a Tcg function call + // + TcgResultSuccess, + + // + // This is the return "catchall" result for the failure of a Tcg function call + // + TcgResultFailure, + + // + // This is the return result if a required parameter was Null for a Tcg function call + // + TcgResultFailureNullPointer, + + // + // This is the return result if a required buffersize was 0 for a Tcg function call + // + TcgResultFailureZeroSize, + + // + // This is the return result if a Tcg function call was executed out of order. + // For instance, starting a Tcg subpacket before starting its Tcg packet. + // + TcgResultFailureInvalidAction, + + // + // This is the return result if the buffersize provided is not big enough to add a requested Tcg encoded item. + // + TcgResultFailureBufferTooSmall, + + // + // This is the return result for a Tcg parse function if the end of the parsed Buffer is reached, yet Data is still attempted to be retrieved. + // For instance, attempting to retrieve another Tcg token from the Buffer after it has reached the end of the Tcg subpacket payload. + // + TcgResultFailureEndBuffer, + + // + // This is the return result for a Tcg parse function if the Tcg Token item requested is not the expected type. + // For instance, the caller requested to receive an integer and the Tcg token was a byte sequence. + // + TcgResultFailureInvalidType, +} TCG_RESULT; + +// +// Structure that is used to build the Tcg ComPacket. It contains the start Buffer pointer and the current position of the +// Tcg ComPacket, current Tcg Packet and Tcg SubPacket. This structure must be initialized +// by calling tcgInitTcgCreateStruct before it is used as parameter to any other Tcg function. +// This structure should NOT be directly modified by the client of this library. +// +// NOTE: WE MAY MAKE THIS AN ABSTRACT STRUCTURE WITH A DEFINED SIZE AND KEEP THE VARIABLES +// INTERNAL AND ONLY KNOWN TO THE TCG LIBRARY +// +// tcgInitTcgCreateStruct +// +typedef struct { + // + // Buffer allocated and freed by the client of the Tcg library. + // This is the Buffer that shall contain the final Tcg encoded compacket. + // + VOID *Buffer; + + // + // Size of the Buffer provided. + // + UINT32 BufferSize; + + // + //Pointer to the start of the Tcg ComPacket. It should point to a location within Buffer. + // + TCG_COM_PACKET *ComPacket; + + // + // Current Tcg Packet that is being created. It should point to a location within Buffer. + // + TCG_PACKET *CurPacket; + + // + // Current Tcg SubPacket that is being created. It should point to a location within Buffer. + // + TCG_SUB_PACKET *CurSubPacket; + + // + // Flag used to indicate if the Buffer of the structure should be filled out. + // This is intended to be used to support a use-case where the client of library + // can perform all the desired tcg calls to determine what the actual Size of the final compacket will be. + // Then the client can allocate the required Buffer Size and re-run the tcg calls. + // THIS MAY NOT BE IMPLEMENTED... REQUIRES MORE THOUGHT BECAUSE YOU CANNOT SOLVE ISSUE FOR RECEIVE + // + BOOLEAN DryRun; +} TCG_CREATE_STRUCT; + +// +// Structure that is used to parse the Tcg response received. It contains the response Buffer pointer +// and the current position of the Tcg ComPacket, current Tcg Packet and Tcg SubPacket being parsed. +// This structure must be initialized by calling tcgInitTcgParseStruct before it is used as parameter to any other Tcg parse function. +// This structure should NOT be directly modified by the client of this library. +// +// NOTE: WE MAY MAKE THIS AN ABSTRACT STRUCTURE WITH A DEFINED SIZE AND KEEP THE VARIABLES +// INTERNAL AND ONLY KNOWN TO THE TCG LIBRARY +// +// @sa tcgInitTcgParseStruct +// +typedef struct { + // + // Buffer allocated and freed by the client of the Tcg library. + // This is the Buffer that contains the Tcg response to decode/parse. + // + const VOID* Buffer; + + // + //Size of the Buffer provided. + // + UINT32 BufferSize; + + // + // Pointer to the start of the Tcg ComPacket. It should point to a location within Buffer. + // + TCG_COM_PACKET *ComPacket; + + // + // Current Tcg Packet that is being created. It should point to a location within Buffer. + // + TCG_PACKET *CurPacket; + + // + // Current Tcg SubPacket that is being created. It should point to a location within Buffer. + // + TCG_SUB_PACKET *CurSubPacket; + + // + // Current pointer within the current subpacket payload. + // + UINT8 *CurPtr; +} TCG_PARSE_STRUCT ; + + +// +// Structure that is used to represent a Tcg Token that is retrieved by Tcg parse functions. +// +typedef struct { + // + // Describes the type of Tcg token the Hdr start points to. + // + TCG_TOKEN_TYPE Type; + + // + // Pointer to the beginning of the Header of the Tcg token + // + UINT8 *HdrStart; +} TCG_TOKEN ; + +/** + + Required to be called before calling any other Tcg functions with the TCG_CREATE_STRUCT. + Initializes the packet variables to NULL. Additionally, the buffer will be memset. + + @param[in/out] CreateStruct Structure to initialize + @param[in] Buffer Buffer allocated by client of library. It will contain the Tcg encoded packet. This cannot be null. + @param[in] BufferSize Size of buffer provided. It cannot be 0. + +**/ +TCG_RESULT +EFIAPI +TcgInitTcgCreateStruct( + TCG_CREATE_STRUCT *CreateStruct, + VOID *Buffer, + UINT32 BufferSize + ); + + +/** + + Encodes the ComPacket header to the data structure. + + @param[in/out] CreateStruct Structure to initialize + @param[in] ComId ComID of the Tcg ComPacket. + @param[in] ComIdExtension ComID Extension of the Tcg ComPacket. + +**/ +TCG_RESULT +EFIAPI +TcgStartComPacket( + TCG_CREATE_STRUCT *CreateStruct, + UINT16 ComId, + UINT16 ComIdExtension + ); + + +/** + + Starts a new ComPacket in the Data structure. + + @param[in/out] CreateStruct Structure used to add Tcg Packet + @param[in] Tsn Packet Tper session number + @param[in] Hsn Packet Host session number + @param[in] SeqNumber Packet Sequence Number + @param[in] AckType Packet Acknowledge Type + @param[in] Ack Packet Acknowledge + +**/ +TCG_RESULT +EFIAPI +TcgStartPacket( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 Tsn, + UINT32 Hsn, + UINT32 SeqNumber, + UINT16 AckType, + UINT32 Ack + ); + +/** + + Starts a new SubPacket in the Data structure. + + @param[in/out] CreateStruct Structure used to start Tcg SubPacket + @param[in] Kind SubPacket kind + +**/ +TCG_RESULT +EFIAPI +TcgStartSubPacket( + TCG_CREATE_STRUCT *CreateStruct, + UINT16 Kind + ); + + +/** + + Ends the current SubPacket in the Data structure. This function will also perform the 4-byte padding + required for Subpackets. + + @param[in/out] CreateStruct Structure used to end the current Tcg SubPacket + +**/ +TCG_RESULT +EFIAPI +TcgEndSubPacket( + TCG_CREATE_STRUCT *CreateStruct + ); + + +/** + + Ends the current Packet in the Data structure. + + @param[in/out] CreateStruct Structure used to end the current Tcg Packet + +**/ +TCG_RESULT +EFIAPI +TcgEndPacket( + TCG_CREATE_STRUCT *CreateStruct + ); + + +/** + + Ends the ComPacket in the Data structure and ret + + @param[in/out] CreateStruct Structure used to end the Tcg ComPacket + @param[in/out] Size Describes the Size of the entire ComPacket (Header and payload). Filled out by function. + +**/ +TCG_RESULT +EFIAPI +TcgEndComPacket( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 *Size + ); + +/** + Adds a single raw token byte to the Data structure. + + @param[in/out] CreateStruct Structure used to add the byte + @param [in] Byte Byte to add + +**/ +TCG_RESULT +EFIAPI +TcgAddRawByte( + TCG_CREATE_STRUCT *CreateStruct, + UINT8 Byte + ); + + +/** + + Adds the Data parameter as a byte sequence to the Data structure. + + @param [in/out] CreateStruct Structure used to add the byte sequence + @param[in] Data Byte sequence that will be encoded and copied into Data structure + @param[in] DataSize Length of Data provided + @param[in] Continued TRUE if byte sequence is continued or + FALSE if the Data contains the entire byte sequence to be encoded + +**/ +TCG_RESULT +EFIAPI +TcgAddByteSequence( + TCG_CREATE_STRUCT *CreateStruct, + const VOID *Data, + UINT32 DataSize, + BOOLEAN Continued + ); + + +/** + + Adds an arbitrary-Length integer to the Data structure. + + The integer will be encoded using the shortest possible atom. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Data Integer in host byte order that will be encoded and copied into Data structure + @param[in] DataSize Length in bytes of the Data provided + @param[in] SignedInteger TRUE if the integer is signed or FALSE if the integer is unsigned + +**/ +TCG_RESULT +EFIAPI +TcgAddInteger( + TCG_CREATE_STRUCT *CreateStruct, + const VOID *Data, + UINT32 DataSize, + BOOLEAN SignedInteger + ); + + +/** + Adds an 8-bit unsigned integer to the Data structure. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Value Integer Value to add + +**/ +TCG_RESULT +EFIAPI +TcgAddUINT8( + TCG_CREATE_STRUCT *CreateStruct, + UINT8 Value + ); + +/** + + Adds a 16-bit unsigned integer to the Data structure. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Value Integer Value to add + +**/ +TCG_RESULT +EFIAPI +TcgAddUINT16 ( + TCG_CREATE_STRUCT *CreateStruct, + UINT16 Value + ); + +/** + + Adds a 32-bit unsigned integer to the Data structure. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Value Integer Value to add + +**/ +TCG_RESULT +EFIAPI +TcgAddUINT32( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 Value + ); + + +/** + + Adds a 64-bit unsigned integer to the Data structure. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Value Integer Value to add + +**/ +TCG_RESULT +EFIAPI +TcgAddUINT64( + TCG_CREATE_STRUCT *CreateStruct, + UINT64 Value + ); + +/** + Adds a BOOLEAN to the Data structure. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Value BOOLEAN Value to add + +**/ +TCG_RESULT +EFIAPI +TcgAddBOOLEAN( + TCG_CREATE_STRUCT *CreateStruct, + BOOLEAN Value + ); + +/** + Add tcg uid info. + + @param [in/out] CreateStruct Structure used to add the integer + @param Uid Input uid info. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddTcgUid( + TCG_CREATE_STRUCT *CreateStruct, + TCG_UID Uid + ); + +/** + Adds a Start List token to the Data structure. + + @param[in/out] CreateStruct Structure used to add the token + +**/ +TCG_RESULT +EFIAPI +TcgAddStartList( + TCG_CREATE_STRUCT *CreateStruct + ); + + +/** + + Adds an End List token to the Data structure. + + @param [in/out] CreateStruct Structure used to add the token + +**/ +TCG_RESULT +EFIAPI +TcgAddEndList( + TCG_CREATE_STRUCT *CreateStruct + ); + + +/** + Adds a Start Name token to the Data structure. + + @param[in/out] CreateStruct Structure used to add the token + +**/ +TCG_RESULT +EFIAPI +TcgAddStartName( + TCG_CREATE_STRUCT *CreateStruct + ); + + +/** + + Adds an End Name token to the Data structure. + + @param [in/out] CreateStruct Structure used to add the token + +**/ +TCG_RESULT +EFIAPI +TcgAddEndName( + TCG_CREATE_STRUCT *CreateStruct + ); + + +/** + Adds a Call token to the Data structure. + + @param [in/out] CreateStruct Structure used to add the token + +**/ +TCG_RESULT +EFIAPI +TcgAddCall( + TCG_CREATE_STRUCT *CreateStruct + ); + + +/** + +Adds an End of Data token to the Data structure. + +@param[in/out] CreateStruct Structure used to add the token + +**/ +TCG_RESULT +EFIAPI +TcgAddEndOfData( + TCG_CREATE_STRUCT *CreateStruct + ); + + +/** + +Adds an End of Session token to the Data structure. + +@param [in/out] CreateStruct Structure used to add the token + +**/ +TCG_RESULT +EFIAPI +TcgAddEndOfSession( + TCG_CREATE_STRUCT *CreateStruct + ); + + +/** + Adds a Start Transaction token to the Data structure. + + @param [in/out] CreateStruct Structure used to add the token + +**/ +TCG_RESULT +EFIAPI +TcgAddStartTransaction( + TCG_CREATE_STRUCT *CreateStruct + ); + + +/** + Adds an End Transaction token to the Data structure. + + @param[in/out] CreateStruct Structure used to add the token + +**/ +TCG_RESULT +EFIAPI +TcgAddEndTransaction( + TCG_CREATE_STRUCT *CreateStruct + ); + +/** + Initial the tcg parse stucture. + + @param ParseStruct Input parse structure. + @param Buffer Input buffer data. + @param BufferSize Input buffer size. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgInitTcgParseStruct( + TCG_PARSE_STRUCT *ParseStruct, + const VOID *Buffer, + UINT32 BufferSize + ); + +/** + Get next token info. + + @param ParseStruct Input parse structure info. + @param TcgToken return the tcg token info. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextToken( + TCG_PARSE_STRUCT *ParseStruct, + TCG_TOKEN *TcgToken + ); + +/** + Get next token Type. + + @param ParseStruct Input parse structure. + @param Type Input the type need to check. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextTokenType( + TCG_PARSE_STRUCT *ParseStruct, + TCG_TOKEN_TYPE Type + ); + +/** + Get atom info. + + @param TcgToken Input token info. + @param HeaderLength return the header length. + @param DataLength return the data length. + @param ByteOrInt return the atom Type. + @param SignOrCont return the sign or count info. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetAtomInfo( + const TCG_TOKEN *TcgToken, + UINT32 *HeaderLength, + UINT32 *DataLength, + UINT8 *ByteOrInt, + UINT8 *SignOrCont + ); + +/** + Get token byte sequence. + + @param TcgToken Input token info. + @param Length Input the length info. + + @retval Return the value data. + +**/ +UINT8* +EFIAPI +TcgGetTokenByteSequence( + const TCG_TOKEN *TcgToken, + UINT32 *Length + ); + +/** + Get token specified value. + + @param TcgToken Input token info. + @param Value return the value. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetTokenUINT64( + const TCG_TOKEN *TcgToken, + UINT64 *Value + ); + + +/** + Get next specify value. + + @param ParseStruct Input parse structure. + @param Value Return vlaue. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextUINT8( + TCG_PARSE_STRUCT *ParseStruct, + UINT8 *Value + ); + + +/** + Get next specify value. + + @param ParseStruct Input parse structure. + @param Value Return vlaue. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextUINT16( + TCG_PARSE_STRUCT *ParseStruct, + UINT16 *Value + ); + +/** + Get next specify value. + + @param ParseStruct Input parse structure. + @param Value Return vlaue. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextUINT32( + TCG_PARSE_STRUCT *ParseStruct, + UINT32 *Value + ); + +/** + Get next specify value. + + @param ParseStruct Input parse structure. + @param Value Return vlaue. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextUINT64( + TCG_PARSE_STRUCT *ParseStruct, + UINT64 *Value + ); + +/** + Get next specify value. + + @param ParseStruct Input parse structure. + @param Value Return vlaue. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextBOOLEAN( + TCG_PARSE_STRUCT *ParseStruct, + BOOLEAN *Value + ); + +/** + Get next tcg uid info. + + @param ParseStruct Input parse structure. + @param Uid Get the uid info. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextTcgUid( + TCG_PARSE_STRUCT *ParseStruct, + TCG_UID *Uid + ); + +/** + Get next byte sequence. + + @param ParseStruct Input parse structure. + @param Data return the data. + @param Length return the length. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextByteSequence( + TCG_PARSE_STRUCT *ParseStruct, + const VOID **Data, + UINT32 *Length + ); + +/** + Get next start list. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextStartList( + TCG_PARSE_STRUCT *ParseStruct + ); + +/** + Get next end list. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextEndList( + TCG_PARSE_STRUCT *ParseStruct + ); + +/** + Get next start name. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextStartName( + TCG_PARSE_STRUCT *ParseStruct + ); + +/** + Get next end name. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextEndName( + TCG_PARSE_STRUCT *ParseStruct + ); + +/** + Get next call. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextCall( + TCG_PARSE_STRUCT *ParseStruct + ); + +/** + Get next end data. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextEndOfData( + TCG_PARSE_STRUCT *ParseStruct + ); + +/** + Get next end of session. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextEndOfSession( + TCG_PARSE_STRUCT *ParseStruct + ); + +/** + Get next start transaction. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextStartTransaction( + TCG_PARSE_STRUCT *ParseStruct + ); + +/** + Get next end transaction. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextEndTransaction( + TCG_PARSE_STRUCT *ParseStruct + ); + +// end of parse functions + + +typedef +BOOLEAN +(EFIAPI* TCG_LEVEL0_ENUM_CALLBACK) ( + const TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader, + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER *Feature, + UINTN FeatureSize, // includes header + VOID *Context +); + +/** + 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 + ); + +/** + Adds START LIST token. + + @param CreateStruct The input create structure. + +**/ +TCG_RESULT +EFIAPI +TcgStartParameters( + TCG_CREATE_STRUCT *CreateStruct + ); + +/** + Adds END LIST token. + + @param CreateStruct The input create structure. + +**/ +TCG_RESULT +EFIAPI +TcgEndParameters( + TCG_CREATE_STRUCT *CreateStruct + ); + +/** + Adds END Data token and method list. + + @param CreateStruct The input create structure. + +**/ +TCG_RESULT +EFIAPI +TcgEndMethodCall( + TCG_CREATE_STRUCT *CreateStruct + ); + +/** + + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + + 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 + ); + + +/** + + Retrieves human-readable token type name. + + @param[in] Type Token type to retrieve + +**/ +CHAR8* +EFIAPI +TcgTokenTypeString( + TCG_TOKEN_TYPE Type + ); + +/** + 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 + ); + +/** + 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 + ); + + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 Logiccal 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 + ); + +/** + 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 + ); + +/** + Get Feature code from the header. + + @param DiscoveryHeader The discovery header. + @param FeatureCode reutrn 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 + ); + +/** + 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 + ); + +/** + Determines if the Locking Feature "Locked" bit is set in the level 0 discovery response. + + @param[in] Discovery Level 0 discovery response + + @return TRUE = Locked is set, FALSE = Locked is false + +**/ +BOOLEAN +EFIAPI +TcgIsLocked( + const TCG_LEVEL0_DISCOVERY_HEADER *Discovery + ); + +#pragma pack() + + +#endif // _TCG_CORE_H_ diff --git a/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCore.c b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCore.c new file mode 100644 index 0000000000..e333b55352 --- /dev/null +++ b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCore.c @@ -0,0 +1,1650 @@ +/** @file + Provide functions to provide tcg storage core spec related functions. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +//#include + +/** + Required to be called before calling any other Tcg functions with the TCG_CREATE_STRUCT. + Initializes the packet variables to NULL. Additionally, the buffer will be memset. + + @param [in/out] CreateStruct Structure to initialize + @param [in] Buffer Buffer allocated by client of library. It will contain the Tcg encoded packet. This cannot be null. + @param [in] BufferSize Size of buffer provided. It cannot be 0. + + @retval Return the action result. +**/ +TCG_RESULT +EFIAPI +TcgInitTcgCreateStruct( + TCG_CREATE_STRUCT *CreateStruct, + VOID *Buffer, + UINT32 BufferSize + ) +{ + NULL_CHECK(CreateStruct); + NULL_CHECK(Buffer); + + if (BufferSize == 0) { + DEBUG ((DEBUG_INFO, "BufferSize=0\n")); + return (TcgResultFailureZeroSize); + } + + ZeroMem(Buffer, BufferSize); + CreateStruct->BufferSize = BufferSize; + CreateStruct->Buffer = Buffer; + CreateStruct->ComPacket = NULL; + CreateStruct->CurPacket = NULL; + CreateStruct->CurSubPacket = NULL; + + return (TcgResultSuccess); +} + +/** + + Encodes the ComPacket header to the data structure. + + @param[in/out] CreateStruct Structure to initialize + @param[in] ComId ComID of the Tcg ComPacket. + @param[in] ComIdExtension ComID Extension of the Tcg ComPacket. + +**/ +TCG_RESULT +EFIAPI +TcgStartComPacket( + TCG_CREATE_STRUCT *CreateStruct, + UINT16 ComId, + UINT16 ComIdExtension + ) +{ + 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); + } + + if (sizeof(TCG_COM_PACKET) > CreateStruct->BufferSize) { + DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize)); + return (TcgResultFailureBufferTooSmall); + } + + CreateStruct->ComPacket = (TCG_COM_PACKET*)CreateStruct->Buffer; + CreateStruct->ComPacket->ComIDBE = SwapBytes16(ComId); + CreateStruct->ComPacket->ComIDExtensionBE = SwapBytes16(ComIdExtension); + + return (TcgResultSuccess); +} + +/** + + Starts a new ComPacket in the Data structure. + + @param [in/out] CreateStruct Structure used to add Tcg Packet + @param[in] Tsn Packet Tper session number + @param[in] Hsn Packet Host session number + @param[in] SeqNumber Packet Sequence Number + @param[in] AckType Packet Acknowledge Type + @param[in] Ack Packet Acknowledge + +**/ +TCG_RESULT +EFIAPI +TcgStartPacket( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 Tsn, + UINT32 Hsn, + UINT32 SeqNumber, + UINT16 AckType, + UINT32 Ack + ) +{ + UINT32 AddedSize; + NULL_CHECK(CreateStruct); + + AddedSize = 0; + + 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); + } + + // update TCG_COM_PACKET and packet lengths + AddedSize = sizeof(TCG_PACKET); + + if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize) > CreateStruct->BufferSize) { + DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize)); + return (TcgResultFailureBufferTooSmall); + } + + CreateStruct->CurPacket = (TCG_PACKET*)(CreateStruct->ComPacket->Payload + SwapBytes32(CreateStruct->ComPacket->LengthBE)); + + CreateStruct->CurPacket->TperSessionNumberBE = SwapBytes32( Tsn ); + CreateStruct->CurPacket->HostSessionNumberBE = SwapBytes32( Hsn ); + CreateStruct->CurPacket->SequenceNumberBE = SwapBytes32( SeqNumber ); + CreateStruct->CurPacket->AckTypeBE = SwapBytes16( AckType ); + CreateStruct->CurPacket->AcknowledgementBE = SwapBytes32( Ack ); + + CreateStruct->CurPacket->LengthBE = 0; + + // update TCG_COM_PACKET Length for next pointer + CreateStruct->ComPacket->LengthBE = SwapBytes32( SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize ); + + return (TcgResultSuccess); +} + +/** + + Starts a new SubPacket in the Data structure. + + @param[in/out] CreateStruct Structure used to start Tcg SubPacket + @param[in] Kind SubPacket kind + +**/ +TCG_RESULT +EFIAPI +TcgStartSubPacket( + TCG_CREATE_STRUCT *CreateStruct, + UINT16 Kind + ) +{ + UINT32 AddedSize; + + NULL_CHECK(CreateStruct); + + AddedSize = 0; + + 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); + } + + AddedSize = sizeof(TCG_SUB_PACKET); + + if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize) > CreateStruct->BufferSize) { + DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize)); + return (TcgResultFailureBufferTooSmall); + } + + CreateStruct->CurSubPacket = (TCG_SUB_PACKET*)(CreateStruct->CurPacket->Payload + SwapBytes32(CreateStruct->CurPacket->LengthBE)); + CreateStruct->CurSubPacket->KindBE = SwapBytes16(Kind); + + // update lengths + CreateStruct->CurSubPacket->LengthBE = 0; + + // update TCG_COM_PACKET and packet lengths + CreateStruct->ComPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize); + CreateStruct->CurPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurPacket->LengthBE) + AddedSize); + + return (TcgResultSuccess); +} + +/** + + Ends the current SubPacket in the Data structure. This function will also perform the 4-byte padding + required for Subpackets. + + @param[in/out] CreateStruct Structure used to end the current Tcg SubPacket + +**/ +TCG_RESULT +EFIAPI +TcgEndSubPacket( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + UINT32 PadSize; + + NULL_CHECK(CreateStruct); + + PadSize = 0; + + 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); + } + + // align to 4-byte boundaries, so shift padding + // pad Size does not apply to subpacket Length + PadSize = TCG_SUBPACKET_ALIGNMENT - (SwapBytes32(CreateStruct->CurSubPacket->LengthBE) & (TCG_SUBPACKET_ALIGNMENT - 1)); + + if (PadSize == TCG_SUBPACKET_ALIGNMENT) { + PadSize = 0; + } + + if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + PadSize) > CreateStruct->BufferSize) { + DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize)); + return (TcgResultFailureBufferTooSmall); + } + + CreateStruct->CurPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurPacket->LengthBE) + PadSize); + CreateStruct->ComPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->ComPacket->LengthBE) + PadSize); + + CreateStruct->CurSubPacket = NULL; + + return (TcgResultSuccess); +} + +/** + + Ends the current Packet in the Data structure. + + @param[in/out] CreateStruct Structure used to end the current Tcg Packet + +**/ +TCG_RESULT +EFIAPI +TcgEndPacket( + 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); + } + + CreateStruct->CurPacket = NULL; + + return (TcgResultSuccess); +} + +/** + + Ends the ComPacket in the Data structure and ret + + @param [in/out] CreateStruct Structure used to end the Tcg ComPacket + @param [in/out] Size Describes the Size of the entire ComPacket (Header and payload). Filled out by function. + +**/ +TCG_RESULT +EFIAPI +TcgEndComPacket( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 *Size + ) +{ + NULL_CHECK(CreateStruct); + NULL_CHECK(Size); + + 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); + } + + *Size = SwapBytes32(CreateStruct->ComPacket->LengthBE) + sizeof(*CreateStruct->ComPacket); + CreateStruct->ComPacket = NULL; + + return (TcgResultSuccess); +} + +/** + Adds raw Data with optional Header + + @param CreateStruct The create structure. + @param Header The header structure. + @param HeaderSize The header size. + @param Data The data need to add. + @param DataSize The data size. + @param ByteSwapData Whether byte or swap data. + +**/ +TCG_RESULT +TcgAddRawTokenData( + TCG_CREATE_STRUCT *CreateStruct, + const VOID *Header, + UINT8 HeaderSize, + const VOID *Data, + UINT32 DataSize, + BOOLEAN ByteSwapData + ) +{ + UINT32 AddedSize; + UINT8* Dest; + const UINT8* DataBytes; + UINT32 Index; + + AddedSize = 0; + Index = 0; + Dest = NULL; + + NULL_CHECK(CreateStruct); + + if ((HeaderSize != 0 && Header == NULL) || + (DataSize != 0 && Data == NULL) + ) { + DEBUG ((DEBUG_INFO, "HeaderSize=0x%X Header=%p DataSize=0x%X Data=%p\n", HeaderSize, Header, DataSize, Data)); + return (TcgResultFailureNullPointer); + } + + 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); + } + + // verify there is enough Buffer Size + AddedSize = HeaderSize + DataSize; + if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize) > CreateStruct->BufferSize) { + return (TcgResultFailureBufferTooSmall); + } + + // Get a pointer to where the new bytes should go + Dest = CreateStruct->ComPacket->Payload + SwapBytes32(CreateStruct->ComPacket->LengthBE); + + switch (HeaderSize) { + case sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM): + case sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM): + case sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM): + CopyMem(Dest, Header, HeaderSize); + Dest += HeaderSize; + case 0: // no Header is valid + break; + // invalid Header Size + default: + DEBUG ((DEBUG_INFO, "unsupported HeaderSize=%u\n", HeaderSize)); + return TcgResultFailure; + } + + // copy the Data bytes + if (ByteSwapData) { + DataBytes = (const UINT8*)Data; + for (Index = 0; Index < DataSize; Index++) { + Dest[Index] = DataBytes[DataSize - 1 - Index]; + } + } else { + CopyMem(Dest, Data, DataSize); + } + + // Update all the packet sizes + CreateStruct->ComPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize); + CreateStruct->CurPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurPacket->LengthBE) + AddedSize); + CreateStruct->CurSubPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurSubPacket->LengthBE) + AddedSize); + + return (TcgResultSuccess); +} + +/** + + Adds a single raw token byte to the Data structure. + + @param[in/out] CreateStruct Structure used to add the byte + @param[in] Byte Byte to add + +**/ +TCG_RESULT +EFIAPI +TcgAddRawByte( + TCG_CREATE_STRUCT *CreateStruct, + UINT8 Byte + ) +{ + return TcgAddRawTokenData(CreateStruct, NULL, 0, &Byte, 1, FALSE); +} + + +/** + simple tokens - atoms: tiny, short, medium, long and empty atoms. + tiny atom can be a signed or unsigned integer. + short, medium, long can be a signed or unsigned integer OR a complete or non-final byte sequence. + + @param CreateStruct The create structure. + @param Data The data need to add. + @param DataSize The data size. + @param ByteOrInt, Data format is byte or int. + @param SignOrCont sign or cont. + + +**/ +TCG_RESULT +TcgAddAtom( + TCG_CREATE_STRUCT *CreateStruct, + const VOID *Data, + UINT32 DataSize, + UINT8 ByteOrInt, + UINT8 SignOrCont + ) +{ + const UINT8* DataBytes; + TCG_SIMPLE_TOKEN_TINY_ATOM TinyAtom; + TCG_SIMPLE_TOKEN_SHORT_ATOM ShortAtom; + TCG_SIMPLE_TOKEN_MEDIUM_ATOM MediumAtom; + TCG_SIMPLE_TOKEN_LONG_ATOM LongAtom; + + NULL_CHECK(CreateStruct); + + if (DataSize == 0) { + if (ByteOrInt == TCG_ATOM_TYPE_INTEGER) { + DEBUG ((DEBUG_INFO, "0-Size integer not allowed\n")); + return TcgResultFailure; + } + } else { + // if DataSize != 0, Data must be valid + NULL_CHECK(Data); + } + + // encode Data using the shortest possible atom + DataBytes = (const UINT8*)Data; + if ((DataSize == 1) && + (ByteOrInt == TCG_ATOM_TYPE_INTEGER) && + ((SignOrCont != 0 && ((TCG_TOKEN_TINYATOM_SIGNED_MIN_VALUE <= *(INT8*)Data) && (*(INT8*)Data <= TCG_TOKEN_TINYATOM_SIGNED_MAX_VALUE))) || + (SignOrCont == 0 && ((*DataBytes <= TCG_TOKEN_TINYATOM_UNSIGNED_MAX_VALUE)))) + ) { + TinyAtom.TinyAtomBits.IsZero = 0; + TinyAtom.TinyAtomBits.Sign = SignOrCont; + TinyAtom.TinyAtomBits.Data = *DataBytes & TCG_TOKEN_TINYATOM_UNSIGNED_MAX_VALUE; + return TcgAddRawTokenData(CreateStruct, NULL, 0, (UINT8*)&TinyAtom, sizeof(TCG_SIMPLE_TOKEN_TINY_ATOM), FALSE); + } + + if (DataSize <= TCG_TOKEN_SHORTATOM_MAX_BYTE_SIZE) { + ShortAtom.ShortAtomBits.IsOne = 1; + ShortAtom.ShortAtomBits.IsZero = 0; + ShortAtom.ShortAtomBits.ByteOrInt = ByteOrInt; + ShortAtom.ShortAtomBits.SignOrCont = SignOrCont; + ShortAtom.ShortAtomBits.Length = DataSize & 0x0F; + return TcgAddRawTokenData(CreateStruct, &ShortAtom, sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM), Data, DataSize, ByteOrInt == TCG_ATOM_TYPE_INTEGER); + } + + if (DataSize <= TCG_TOKEN_MEDIUMATOM_MAX_BYTE_SIZE) { + MediumAtom.MediumAtomBits.IsOne1 = 1; + MediumAtom.MediumAtomBits.IsOne2 = 1; + MediumAtom.MediumAtomBits.IsZero = 0; + MediumAtom.MediumAtomBits.ByteOrInt = ByteOrInt; + MediumAtom.MediumAtomBits.SignOrCont = SignOrCont; + MediumAtom.MediumAtomBits.LengthLow = DataSize & 0xFF; + MediumAtom.MediumAtomBits.LengthHigh = (DataSize >> TCG_MEDIUM_ATOM_LENGTH_HIGH_SHIFT) & TCG_MEDIUM_ATOM_LENGTH_HIGH_MASK; + return TcgAddRawTokenData(CreateStruct, &MediumAtom, sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM), Data, DataSize, ByteOrInt == TCG_ATOM_TYPE_INTEGER); + } + + LongAtom.LongAtomBits.IsOne1 = 1; + LongAtom.LongAtomBits.IsOne2 = 1; + LongAtom.LongAtomBits.IsOne3 = 1; + LongAtom.LongAtomBits.IsZero = 0; + LongAtom.LongAtomBits.ByteOrInt = ByteOrInt; + LongAtom.LongAtomBits.SignOrCont = SignOrCont; + LongAtom.LongAtomBits.LengthLow = DataSize & 0xFF; + LongAtom.LongAtomBits.LengthMid = (DataSize >> TCG_LONG_ATOM_LENGTH_MID_SHIFT) & 0xFF; + LongAtom.LongAtomBits.LengthHigh = (DataSize >> TCG_LONG_ATOM_LENGTH_HIGH_SHIFT) & 0xFF; + return TcgAddRawTokenData(CreateStruct, &LongAtom, sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM), Data, DataSize, ByteOrInt == TCG_ATOM_TYPE_INTEGER); +} + +/** + + Adds the Data parameter as a byte sequence to the Data structure. + + @param[in/out] CreateStruct Structure used to add the byte sequence + @param[in] Data Byte sequence that will be encoded and copied into Data structure + @param[in] DataSize Length of Data provided + @param[in] Continued TRUE if byte sequence is continued or + FALSE if the Data contains the entire byte sequence to be encoded + +**/ +TCG_RESULT +EFIAPI +TcgAddByteSequence( + TCG_CREATE_STRUCT *CreateStruct, + const VOID *Data, + UINT32 DataSize, + BOOLEAN Continued + ) +{ + return TcgAddAtom(CreateStruct, Data, DataSize, TCG_ATOM_TYPE_BYTE, Continued ? 1 : 0); +} + +/** + + Adds an arbitrary-Length integer to the Data structure. + The integer will be encoded using the shortest possible atom. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Data Integer in host byte order that will be encoded and copied into Data structure + @param[in] DataSize Length in bytes of the Data provided + @param[in] SignedInteger TRUE if the integer is signed or FALSE if the integer is unsigned + +**/ +TCG_RESULT +EFIAPI +TcgAddInteger( + TCG_CREATE_STRUCT *CreateStruct, + const VOID *Data, + UINT32 DataSize, + BOOLEAN SignedInteger + ) +{ + const UINT8* DataBytes; + UINT32 ActualDataSize; + BOOLEAN ValueIsNegative; + + NULL_CHECK(CreateStruct); + NULL_CHECK(Data); + + if (DataSize == 0) { + DEBUG ((DEBUG_INFO, "invalid DataSize=0\n")); + return TcgResultFailure; + } + + DataBytes = (const UINT8*)Data; + + // integer should be represented by smallest atom possible + // so calculate real Data Size + ValueIsNegative = SignedInteger && DataBytes[ DataSize - 1 ] & 0x80; + + // assumes native Data is little endian + // shorten Data to smallest byte representation + for (ActualDataSize = DataSize; ActualDataSize > 1; ActualDataSize--) { + // ignore sign extended FFs + if (ValueIsNegative && (DataBytes[ActualDataSize - 1] != 0xFF)) { + break; + } else if (!ValueIsNegative && (DataBytes[ActualDataSize - 1] != 0)) { + // ignore extended 00s + break; + } + } + + return TcgAddAtom(CreateStruct, Data, ActualDataSize, TCG_ATOM_TYPE_INTEGER, SignedInteger ? 1 : 0); +} + +/** + Adds an 8-bit unsigned integer to the Data structure. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Value Integer Value to add + +**/ +TCG_RESULT +EFIAPI +TcgAddUINT8( + TCG_CREATE_STRUCT *CreateStruct, + UINT8 Value + ) +{ + return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE); +} + +/** + + Adds a 16-bit unsigned integer to the Data structure. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Value Integer Value to add + +**/ +TCG_RESULT +EFIAPI +TcgAddUINT16 ( + TCG_CREATE_STRUCT *CreateStruct, + UINT16 Value + ) +{ + return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE); +} + +/** + + Adds a 32-bit unsigned integer to the Data structure. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Value Integer Value to add + +**/ +TCG_RESULT +EFIAPI +TcgAddUINT32( + TCG_CREATE_STRUCT *CreateStruct, + UINT32 Value + ) +{ + return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE); +} + + +/** + + Adds a 64-bit unsigned integer to the Data structure. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Value Integer Value to add + +**/ +TCG_RESULT +EFIAPI +TcgAddUINT64( + TCG_CREATE_STRUCT *CreateStruct, + UINT64 Value + ) +{ + return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE); +} + +/** + Adds a BOOLEAN to the Data structure. + + @param[in/out] CreateStruct Structure used to add the integer + @param[in] Value BOOLEAN Value to add + +**/ +TCG_RESULT +EFIAPI +TcgAddBOOLEAN( + TCG_CREATE_STRUCT *CreateStruct, + BOOLEAN Value + ) +{ + return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE); +} + +/** + Add tcg uid info. + + @param [in/out] CreateStruct Structure used to add the integer + @param Uid Input uid info. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddTcgUid( + TCG_CREATE_STRUCT *CreateStruct, + TCG_UID Uid + ) +{ + return TcgAddByteSequence(CreateStruct, &Uid, sizeof(TCG_UID), FALSE); +} + +/** + Add start list. + + @param [in/out] CreateStruct Structure used to add the integer + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddStartList( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + return TcgAddRawByte(CreateStruct, TCG_TOKEN_STARTLIST); +} + +/** + Add end list. + + @param [in/out] CreateStruct Structure used to add the integer + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddEndList( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDLIST); +} + +/** + Add start name. + + @param [in/out] CreateStruct Structure used to add the integer + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddStartName( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + return TcgAddRawByte(CreateStruct, TCG_TOKEN_STARTNAME); +} + +/** + Add end name. + + @param [in/out] CreateStruct Structure used to add the integer + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddEndName( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDNAME); +} + +/** + Add end call. + + @param [in/out] CreateStruct Structure used to add the integer + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddCall( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + return TcgAddRawByte(CreateStruct, TCG_TOKEN_CALL); +} + +/** + Add end of data. + + @param [in/out] CreateStruct Structure used to add the integer + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddEndOfData( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDDATA); +} + +/** + Add end of session. + + @param [in/out] CreateStruct Structure used to add the integer + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddEndOfSession( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDSESSION); +} + +/** + Add start transaction. + + @param [in/out] CreateStruct Structure used to add the integer + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddStartTransaction( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + return TcgAddRawByte(CreateStruct, TCG_TOKEN_STARTTRANSACTION); +} + +/** + Add end transaction. + + @param [in/out] CreateStruct Structure used to add the integer + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgAddEndTransaction( + TCG_CREATE_STRUCT *CreateStruct + ) +{ + return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDTRANSACTION); +} + +/** + Initial the tcg parse stucture. + + @param ParseStruct Input parse structure. + @param Buffer Input buffer data. + @param BufferSize Input buffer size. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgInitTcgParseStruct( + TCG_PARSE_STRUCT *ParseStruct, + const VOID *Buffer, + UINT32 BufferSize + ) +{ + UINT32 ComPacketLength; + UINT32 PacketLength; + + NULL_CHECK(ParseStruct); + NULL_CHECK(Buffer); + + if (BufferSize < sizeof(TCG_COM_PACKET)) { + return (TcgResultFailureBufferTooSmall); + } + + ParseStruct->ComPacket = (TCG_COM_PACKET*)Buffer; + + ComPacketLength = SwapBytes32(ParseStruct->ComPacket->LengthBE); + + if ((BufferSize - sizeof(TCG_COM_PACKET)) < ComPacketLength) { + DEBUG ((DEBUG_INFO, "Buffer %u too small for ComPacket %u\n", BufferSize, ComPacketLength)); + return (TcgResultFailureBufferTooSmall); + } + + ParseStruct->BufferSize = BufferSize; + ParseStruct->Buffer = Buffer; + + ParseStruct->CurPacket = NULL; + ParseStruct->CurSubPacket = NULL; + ParseStruct->CurPtr = NULL; + + // if payload > 0, then must have a packet + if (ComPacketLength != 0) { + if (ComPacketLength < sizeof(TCG_PACKET)) { + DEBUG ((DEBUG_INFO, "ComPacket too small for Packet\n")); + return (TcgResultFailureBufferTooSmall); + } + ParseStruct->CurPacket = (TCG_PACKET*)ParseStruct->ComPacket->Payload; + + PacketLength = SwapBytes32(ParseStruct->CurPacket->LengthBE); + + if (PacketLength > 0) { + if (PacketLength < sizeof(TCG_SUB_PACKET)) { + DEBUG ((DEBUG_INFO, "Packet too small for SubPacket\n")); + return (TcgResultFailureBufferTooSmall); + } + + ParseStruct->CurSubPacket = (TCG_SUB_PACKET*)ParseStruct->CurPacket->Payload; + } + } + + //TODO should check for method status list at this point? + + return (TcgResultSuccess); +} + +/** + Get next token info. + + @param ParseStruct Input parse structure info. + @param TcgToken return the tcg token info. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextToken( + TCG_PARSE_STRUCT *ParseStruct, + TCG_TOKEN *TcgToken + ) +{ + const UINT8* EndOfSubPacket; + UINT8* TokenEnd; + UINT8 Hdr; + TCG_SIMPLE_TOKEN_SHORT_ATOM* TmpShort; + const TCG_SIMPLE_TOKEN_MEDIUM_ATOM* TmpMed; + const TCG_SIMPLE_TOKEN_LONG_ATOM* TmpLong; + + NULL_CHECK(ParseStruct); + NULL_CHECK(TcgToken); + + 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; + } + + // initial call, start at sub packet + if (ParseStruct->CurPtr == NULL) { + ParseStruct->CurPtr = ParseStruct->CurSubPacket->Payload; + } + + EndOfSubPacket = ParseStruct->CurSubPacket->Payload + SwapBytes32(ParseStruct->CurSubPacket->LengthBE); + TokenEnd = NULL; + + // confirmed that subpacket Length falls within end of Buffer and TCG_COM_PACKET, + // so simply need to verify the loop stays within current subpacket + if (ParseStruct->CurPtr >= EndOfSubPacket) { + DEBUG ((DEBUG_INFO, "ParseStruct->CurPtr >= EndOfSubPacket\n")); + return (TcgResultFailureEndBuffer); + } + + Hdr = *ParseStruct->CurPtr; + TcgToken->HdrStart = ParseStruct->CurPtr; + + // Tiny Atom range + if (Hdr <= 0x7F) { + // tiny atom Header is only 1 byte, so don't need to verify Size before cast and access + TcgToken->Type = TcgTokenTypeTinyAtom; + + TokenEnd = TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_TINY_ATOM); + + // verify caller will have enough Size to reference token + if (TokenEnd >= EndOfSubPacket) { + DEBUG ((DEBUG_INFO, "Tiny Atom TokenEnd >= EndOfSubPacket\n")); + return (TcgResultFailureEndBuffer); + } + } + // Short Atom Range + else if (0x80 <= Hdr && Hdr <= 0xBF) { + // short atom Header is only 1 byte, so don't need to verify Size before cast and access + TmpShort = (TCG_SIMPLE_TOKEN_SHORT_ATOM*)(ParseStruct->CurPtr); + TcgToken->Type = TcgTokenTypeShortAtom; + + TokenEnd = (TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM) + TmpShort->ShortAtomBits.Length); + + // verify caller will have enough Size to reference token + if (TokenEnd >= EndOfSubPacket) { + DEBUG ((DEBUG_INFO, "Short Atom TokenEnd >= EndOfSubPacket\n")); + return (TcgResultFailureEndBuffer); + } + } + // Medium Atom Range + else if (0xC0 <= Hdr && Hdr <= 0xDF) { + if (TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM) >= EndOfSubPacket) { + return (TcgResultFailureEndBuffer); + } + TmpMed = (const TCG_SIMPLE_TOKEN_MEDIUM_ATOM*)ParseStruct->CurPtr; + TcgToken->Type = TcgTokenTypeMediumAtom; + TokenEnd = TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM) + + ((TmpMed->MediumAtomBits.LengthHigh << TCG_MEDIUM_ATOM_LENGTH_HIGH_SHIFT) | + TmpMed->MediumAtomBits.LengthLow); + + // verify caller will have enough Size to reference token + if (TokenEnd >= EndOfSubPacket) { + DEBUG ((DEBUG_INFO, "Medium Atom TokenEnd >= EndOfSubPacket\n")); + return (TcgResultFailureEndBuffer); + } + } + // Long Atom Range + else if (0xE0 <= Hdr && Hdr <= 0xE3) { + if (TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM) >= EndOfSubPacket) { + return (TcgResultFailureEndBuffer); + } + TmpLong = (const TCG_SIMPLE_TOKEN_LONG_ATOM*)ParseStruct->CurPtr; + TcgToken->Type = TcgTokenTypeLongAtom; + + TokenEnd = TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM) + + ((TmpLong->LongAtomBits.LengthHigh << TCG_LONG_ATOM_LENGTH_HIGH_SHIFT) | + (TmpLong->LongAtomBits.LengthMid << TCG_LONG_ATOM_LENGTH_MID_SHIFT) | + TmpLong->LongAtomBits.LengthLow); + + // verify caller will have enough Size to reference token + if (TokenEnd >= EndOfSubPacket) { + DEBUG ((DEBUG_INFO, "Long Atom TokenEnd >= EndOfSubPacket\n")); + return (TcgResultFailureEndBuffer); + } + } else { + // single byte tokens + switch (Hdr) { + case TCG_TOKEN_STARTLIST: + TcgToken->Type = TcgTokenTypeStartList; + break; + case TCG_TOKEN_ENDLIST: + TcgToken->Type = TcgTokenTypeEndList; + break; + case TCG_TOKEN_STARTNAME: + TcgToken->Type = TcgTokenTypeStartName; + break; + case TCG_TOKEN_ENDNAME: + TcgToken->Type = TcgTokenTypeEndName; + break; + case TCG_TOKEN_CALL: + TcgToken->Type = TcgTokenTypeCall; + break; + case TCG_TOKEN_ENDDATA: + TcgToken->Type = TcgTokenTypeEndOfData; + break; + case TCG_TOKEN_ENDSESSION: + TcgToken->Type = TcgTokenTypeEndOfSession; + break; + case TCG_TOKEN_STARTTRANSACTION: + TcgToken->Type = TcgTokenTypeStartTransaction; + break; + case TCG_TOKEN_ENDTRANSACTION: + TcgToken->Type = TcgTokenTypeEndTransaction; + break; + case TCG_TOKEN_EMPTY: + TcgToken->Type = TcgTokenTypeEmptyAtom; + break; + default: + DEBUG ((DEBUG_INFO, "WARNING: reserved token Type 0x%02X\n", Hdr)); + TcgToken->Type = TcgTokenTypeReserved; + break; + } + ParseStruct->CurPtr++; + TokenEnd = TcgToken->HdrStart + 1; + } + + // increment curptr for next call + ParseStruct->CurPtr = TokenEnd; + return (TcgResultSuccess); +} + +/** + Get atom info. + + @param TcgToken Input token info. + @param HeaderLength return the header length. + @param DataLength return the data length. + @param ByteOrInt return the atom Type. + @param SignOrCont return the sign or count info. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetAtomInfo( + const TCG_TOKEN *TcgToken, + UINT32 *HeaderLength, + UINT32 *DataLength, + UINT8 *ByteOrInt, + UINT8 *SignOrCont + ) +{ + TCG_SIMPLE_TOKEN_TINY_ATOM* TinyAtom; + TCG_SIMPLE_TOKEN_SHORT_ATOM* ShortAtom; + TCG_SIMPLE_TOKEN_MEDIUM_ATOM* MediumAtom; + TCG_SIMPLE_TOKEN_LONG_ATOM* LongAtom; + + NULL_CHECK(TcgToken); + NULL_CHECK(HeaderLength); + NULL_CHECK(DataLength); + NULL_CHECK(ByteOrInt); + NULL_CHECK(SignOrCont); + + switch (TcgToken->Type) { + case TcgTokenTypeTinyAtom: { + TinyAtom = (TCG_SIMPLE_TOKEN_TINY_ATOM*)TcgToken->HdrStart; + *ByteOrInt = TCG_ATOM_TYPE_INTEGER; + *SignOrCont = TinyAtom->TinyAtomBits.Sign; + *HeaderLength = 0; + *DataLength = 0; // tiny atom must be handled as a special case - Header and Data in the same byte + return TcgResultSuccess; + } + + case TcgTokenTypeShortAtom: { + ShortAtom = (TCG_SIMPLE_TOKEN_SHORT_ATOM*)TcgToken->HdrStart; + *ByteOrInt = ShortAtom->ShortAtomBits.ByteOrInt; + *SignOrCont = ShortAtom->ShortAtomBits.SignOrCont; + *HeaderLength = sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM); + *DataLength = ShortAtom->ShortAtomBits.Length; + return TcgResultSuccess; + } + + case TcgTokenTypeMediumAtom: { + MediumAtom = (TCG_SIMPLE_TOKEN_MEDIUM_ATOM*)TcgToken->HdrStart; + *ByteOrInt = MediumAtom->MediumAtomBits.ByteOrInt; + *SignOrCont = MediumAtom->MediumAtomBits.SignOrCont; + *HeaderLength = sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM); + *DataLength = (MediumAtom->MediumAtomBits.LengthHigh << TCG_MEDIUM_ATOM_LENGTH_HIGH_SHIFT) | MediumAtom->MediumAtomBits.LengthLow; + return TcgResultSuccess; + } + + case TcgTokenTypeLongAtom: { + LongAtom = (TCG_SIMPLE_TOKEN_LONG_ATOM*)TcgToken->HdrStart; + *ByteOrInt = LongAtom->LongAtomBits.ByteOrInt; + *SignOrCont = LongAtom->LongAtomBits.SignOrCont; + *HeaderLength = sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM); + *DataLength = (LongAtom->LongAtomBits.LengthHigh << TCG_LONG_ATOM_LENGTH_HIGH_SHIFT) | + (LongAtom->LongAtomBits.LengthMid << TCG_LONG_ATOM_LENGTH_MID_SHIFT) | + LongAtom->LongAtomBits.LengthLow; + return TcgResultSuccess; + } + + default: + DEBUG ((DEBUG_INFO, "Token Type is not simple atom (%d)\n", TcgToken->Type)); + return (TcgResultFailureInvalidType); + } +} + +/** + Get token specified value. + + @param TcgToken Input token info. + @param Value return the value. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetTokenUINT64( + const TCG_TOKEN *TcgToken, + UINT64 *Value + ) +{ + UINT32 HdrLength; + UINT32 DataLength; + UINT8 ByteOrInt; + UINT8 IsSigned; + TCG_SIMPLE_TOKEN_TINY_ATOM* TmpTiny; + const UINT8* Data; + UINT32 Index; + + NULL_CHECK(TcgToken); + NULL_CHECK(Value); + + Index = 0; + *Value = 0; + ERROR_CHECK(TcgGetAtomInfo(TcgToken, &HdrLength, &DataLength, &ByteOrInt, &IsSigned)); + + if (ByteOrInt != TCG_ATOM_TYPE_INTEGER) { + DEBUG ((DEBUG_INFO, "Invalid Type, expected integer not byte sequence\n")); + return TcgResultFailureInvalidType; + } + + if (IsSigned != 0) { + DEBUG ((DEBUG_INFO, "Integer is signed, expected unsigned\n")); + return TcgResultFailureInvalidType; + } + + // special case for tiny atom + // Header and Data are in one byte, so extract only the Data bitfield + if (TcgToken->Type == TcgTokenTypeTinyAtom) { + TmpTiny = (TCG_SIMPLE_TOKEN_TINY_ATOM*)TcgToken->HdrStart; + *Value = TmpTiny->TinyAtomBits.Data; + return TcgResultSuccess; + } + + if (DataLength > sizeof(UINT64)) { + DEBUG ((DEBUG_INFO, "Length %d is greater than Size of UINT64\n", DataLength)); + return TcgResultFailureBufferTooSmall; + } + + // read big-endian integer + Data = TcgToken->HdrStart + HdrLength; + for (Index = 0; Index < DataLength; Index++) { + *Value = LShiftU64(*Value, 8) | Data[Index]; + } + + return TcgResultSuccess; +} + +/** + Get token byte sequence. + + @param TcgToken Input token info. + @param Length Input the length info. + + @retval Return the value data. + +**/ +UINT8* +EFIAPI +TcgGetTokenByteSequence( + const TCG_TOKEN *TcgToken, + UINT32 *Length + ) +{ + UINT32 HdrLength; + UINT8 ByteOrInt; + UINT8 SignOrCont; + + if (TcgToken == NULL || Length == NULL) { + return NULL; + } + + *Length = 0; + if (TcgGetAtomInfo(TcgToken, &HdrLength, Length, &ByteOrInt, &SignOrCont) != TcgResultSuccess) { + DEBUG ((DEBUG_INFO, "Failed to get simple token info\n")); + return NULL; + } + + if (ByteOrInt != TCG_ATOM_TYPE_BYTE) { + DEBUG ((DEBUG_INFO, "Invalid Type, expected byte sequence not integer\n")); + return NULL; + } + + return (TcgToken->HdrStart + HdrLength); +} + +/** + Get next specify value. + + @param ParseStruct Input parse structure. + @param Value Return vlaue. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextUINT8( + TCG_PARSE_STRUCT *ParseStruct, + UINT8 *Value + ) +{ + UINT64 Value64; + TCG_TOKEN Tok; + + NULL_CHECK(Value); + + ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok)); + ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64)); + + if (Value64 > MAX_UINT8) { + return TcgResultFailure; + } + + *Value = (UINT8)Value64; + + return TcgResultSuccess; +} + +/** + Get next specify value. + + @param ParseStruct Input parse structure. + @param Value Return vlaue. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextUINT16( + TCG_PARSE_STRUCT *ParseStruct, + UINT16 *Value + ) +{ + UINT64 Value64; + TCG_TOKEN Tok; + + NULL_CHECK(Value); + + ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok)); + ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64)); + + if (Value64 > MAX_UINT16) { + return TcgResultFailure; + } + + *Value = (UINT16)Value64; + + return TcgResultSuccess; +} + +/** + Get next specify value. + + @param ParseStruct Input parse structure. + @param Value Return vlaue. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextUINT32( + TCG_PARSE_STRUCT *ParseStruct, + UINT32 *Value + ) +{ + UINT64 Value64; + TCG_TOKEN Tok; + + NULL_CHECK(Value); + + ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok)); + ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64)); + + if (Value64 > MAX_UINT32) { + return TcgResultFailure; + } + + *Value = (UINT32)Value64; + + return TcgResultSuccess; +} + +/** + Get next specify value. + + @param ParseStruct Input parse structure. + @param Value Return vlaue. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextUINT64( + TCG_PARSE_STRUCT *ParseStruct, + UINT64 *Value + ) +{ + TCG_TOKEN Tok; + ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok)); + ERROR_CHECK(TcgGetTokenUINT64(&Tok, Value)); + return TcgResultSuccess; +} + +/** + Get next specify value. + + @param ParseStruct Input parse structure. + @param Value Return vlaue. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextBOOLEAN( + TCG_PARSE_STRUCT *ParseStruct, + BOOLEAN *Value + ) +{ + UINT64 Value64; + TCG_TOKEN Tok; + + NULL_CHECK(Value); + + ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok)); + ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64)); + + if (Value64 > 1) { + return TcgResultFailure; + } + + *Value = (BOOLEAN)Value64; + + return TcgResultSuccess; +} + +/** + Get next tcg uid info. + + @param ParseStruct Input parse structure. + @param Uid Get the uid info. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextTcgUid( + TCG_PARSE_STRUCT *ParseStruct, + TCG_UID *Uid + ) +{ + TCG_TOKEN Tok; + UINT32 Length; + const UINT8* ByteSeq; + + NULL_CHECK(Uid); + + ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok)); + ByteSeq = TcgGetTokenByteSequence(&Tok, &Length); + + if (Length != sizeof(TCG_UID)) { + DEBUG ((DEBUG_INFO, "Token Length %u != TCG_UID Size %u\n", Length, (UINT32)sizeof(TCG_UID))); + return TcgResultFailure; + } + + CopyMem(Uid, ByteSeq, sizeof(TCG_UID)); + + return TcgResultSuccess; +} + +/** + Get next byte sequence. + + @param ParseStruct Input parse structure. + @param Data return the data. + @param Length return the length. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextByteSequence( + TCG_PARSE_STRUCT *ParseStruct, + const VOID **Data, + UINT32 *Length + ) +{ + TCG_TOKEN Tok; + const UINT8* Bs; + + ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok)); + Bs = TcgGetTokenByteSequence(&Tok, Length); + + if (Bs == NULL) { + return TcgResultFailure; + } + *Data = Bs; + return TcgResultSuccess; +} + +/** + Get next token Type. + + @param ParseStruct Input parse structure. + @param Type Input the type need to check. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextTokenType( + TCG_PARSE_STRUCT *ParseStruct, + TCG_TOKEN_TYPE Type + ) +{ + TCG_TOKEN Tok; + ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok)); + if (Tok.Type != Type) { + DEBUG ((DEBUG_INFO, "expected Type %u, got Type %u\n", Type, Tok.Type)); + return TcgResultFailure; + } + return TcgResultSuccess; +} + +/** + Get next start list. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextStartList( + TCG_PARSE_STRUCT *ParseStruct + ) +{ + return TcgGetNextTokenType(ParseStruct, TcgTokenTypeStartList); +} + +/** + Get next end list. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextEndList( + TCG_PARSE_STRUCT *ParseStruct + ) +{ + return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndList); +} + +/** + Get next start name. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextStartName( + TCG_PARSE_STRUCT *ParseStruct + ) +{ + return TcgGetNextTokenType(ParseStruct, TcgTokenTypeStartName); +} + +/** + Get next end name. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextEndName( + TCG_PARSE_STRUCT *ParseStruct + ) +{ + return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndName); +} + +/** + Get next call. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextCall( + TCG_PARSE_STRUCT *ParseStruct + ) +{ + return TcgGetNextTokenType(ParseStruct, TcgTokenTypeCall); +} + +/** + Get next end data. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextEndOfData( + TCG_PARSE_STRUCT *ParseStruct + ) +{ + return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndOfData); +} + +/** + Get next end of session. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextEndOfSession( + TCG_PARSE_STRUCT *ParseStruct + ) +{ + return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndOfSession); +} + +/** + Get next start transaction. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextStartTransaction( + TCG_PARSE_STRUCT *ParseStruct + ) +{ + return TcgGetNextTokenType(ParseStruct, TcgTokenTypeStartTransaction); +} + +/** + Get next end transaction. + + @param ParseStruct Input parse structure. + + @retval return the action result. + +**/ +TCG_RESULT +EFIAPI +TcgGetNextEndTransaction( + TCG_PARSE_STRUCT *ParseStruct + ) +{ + return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndTransaction); +} diff --git a/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf new file mode 100644 index 0000000000..a80cb00a9c --- /dev/null +++ b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf @@ -0,0 +1,38 @@ +## @file +# This is a Tcg Storage core library. +# +# This module is used to provide API used by Opal password solution. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## +[Defines] + INF_VERSION = 0x00010017 + BASE_NAME = TcgStorageCoreLib + FILE_GUID = ad63b09b-1fc9-4789-af0c-5af8a3fb1f9c + VERSION_STRING = 1.0 + MODULE_TYPE = BASE + LIBRARY_CLASS = TcgStorageCoreLib|DXE_DRIVER DXE_CORE DXE_SMM_DRIVER +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[LibraryClasses] + BaseLib + BaseMemoryLib + +[Packages] + MdePkg/MdePkg.dec + SecurityPkg/SecurityPkg.dec + +[Sources] + TcgStorageCore.c + TcgStorageUtil.c diff --git a/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c new file mode 100644 index 0000000000..30808cd835 --- /dev/null +++ b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c @@ -0,0 +1,907 @@ +/** @file + Provide functions to provide tcg storage core spec related functions. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include + +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 Logiccal 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 reutrn 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 TURE 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; +}