/** @file | |
Public API for Opal Core library. | |
Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <Uefi.h> | |
#include <Library/BaseLib.h> | |
#include <Library/TimerLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/TcgStorageOpalLib.h> | |
#include "TcgStorageOpalLibInternal.h" | |
#pragma pack(1) | |
typedef struct { | |
UINT8 HardwareReset : 1; | |
UINT8 Reserved : 7; | |
} TCG_BLOCK_SID_CLEAR_EVENTS; | |
#pragma pack() | |
#define TRUSTED_COMMAND_TIMEOUT_NS ((UINT64) 5 * ((UINT64)(1000000)) * 1000) // 5 seconds | |
#define BUFFER_SIZE 512 | |
/** | |
The function performs a Trusted Send of a Buffer containing a TCG_COM_PACKET. | |
@param[in] Sscp The input Ssc Protocol. | |
@param[in] MediaId The input Media id info used by Ssc Protocol. | |
@param[in] SecurityProtocol Security Protocol | |
@param[in] SpSpecific Security Protocol Specific | |
@param[in] TransferLength Transfer Length of Buffer (in bytes) - always a multiple of 512 | |
@param[in] Buffer Address of Data to transfer | |
@param[in] BufferSize Full Size of Buffer, including space that may be used for padding. | |
**/ | |
TCG_RESULT | |
OpalTrustedSend ( | |
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Sscp, | |
UINT32 MediaId, | |
UINT8 SecurityProtocol, | |
UINT16 SpSpecific, | |
UINTN TransferLength, | |
VOID *Buffer, | |
UINTN BufferSize | |
) | |
{ | |
UINTN TransferLength512; | |
EFI_STATUS Status; | |
// | |
// Round transferLength up to a 512-byte multiple | |
// | |
TransferLength512 = (TransferLength + 511) & ~(UINTN)511; | |
if (TransferLength512 > BufferSize) { | |
return TcgResultFailureBufferTooSmall; | |
} | |
ZeroMem ((UINT8 *)Buffer + TransferLength, TransferLength512 - TransferLength); | |
Status = Sscp->SendData ( | |
Sscp, | |
MediaId, | |
TRUSTED_COMMAND_TIMEOUT_NS, | |
SecurityProtocol, | |
SwapBytes16 (SpSpecific), | |
TransferLength512, | |
Buffer | |
); | |
return Status == EFI_SUCCESS ? TcgResultSuccess : TcgResultFailure; | |
} | |
/** | |
The function performs a Trusted Receive of a Buffer containing a TCG_COM_PACKET. | |
@param[in] Sscp The input Ssc Protocol. | |
@param[in] MediaId The input Media id info used by Ssc Protocol. | |
@param[in] SecurityProtocol Security Protocol | |
@param[in] SpSpecific Security Protocol Specific | |
@param[in] Buffer Address of Data to transfer | |
@param[in] BufferSize Full Size of Buffer, including space that may be used for padding. | |
@param[in] EstimateTimeCost Estimate the time needed. | |
**/ | |
TCG_RESULT | |
OpalTrustedRecv ( | |
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Sscp, | |
UINT32 MediaId, | |
UINT8 SecurityProtocol, | |
UINT16 SpSpecific, | |
VOID *Buffer, | |
UINTN BufferSize, | |
UINT32 EstimateTimeCost | |
) | |
{ | |
UINTN TransferLength512; | |
UINT32 Tries; | |
TCG_COM_PACKET *ComPacket; | |
UINT32 Length; | |
UINT32 OutstandingData; | |
EFI_STATUS Status; | |
UINTN TransferSize; | |
// | |
// Round Buffer Size down to a 512-byte multiple | |
// | |
TransferLength512 = BufferSize & ~(UINTN)511; | |
Tries = 0; | |
ComPacket = NULL; | |
Length = 0; | |
OutstandingData = 0; | |
if (TransferLength512 < sizeof (TCG_COM_PACKET)) { | |
DEBUG ((DEBUG_INFO, "transferLength %u too small for ComPacket\n", TransferLength512)); | |
return TcgResultFailureBufferTooSmall; | |
} | |
// | |
// Some devices respond with Length = 0 and OutstandingData = 1 to indicate that processing is not yet completed, | |
// so we need to retry the IF-RECV to get the actual Data. | |
// See TCG Core Spec v2 Table 45 IF-RECV ComPacket Field Values Summary | |
// This is an arbitrary number of retries, not from the spec. | |
// | |
// if user input estimate time cost(second level) value bigger than 10s, base on user input value to wait. | |
// Else, Use a max timeout of 10 seconds to wait, 5000 tries * 2ms = 10s | |
// | |
if (EstimateTimeCost > 10) { | |
Tries = EstimateTimeCost * 500; // 500 = 1000 * 1000 / 2000; | |
} else { | |
Tries = 5000; | |
} | |
while ((Tries--) > 0) { | |
ZeroMem (Buffer, BufferSize); | |
TransferSize = 0; | |
Status = Sscp->ReceiveData ( | |
Sscp, | |
MediaId, | |
TRUSTED_COMMAND_TIMEOUT_NS, | |
SecurityProtocol, | |
SwapBytes16 (SpSpecific), | |
TransferLength512, | |
Buffer, | |
&TransferSize | |
); | |
if (EFI_ERROR (Status)) { | |
return TcgResultFailure; | |
} | |
if ((SecurityProtocol != TCG_OPAL_SECURITY_PROTOCOL_1) && (SecurityProtocol != TCG_OPAL_SECURITY_PROTOCOL_2)) { | |
return TcgResultSuccess; | |
} | |
if (SpSpecific == TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY) { | |
return TcgResultSuccess; | |
} | |
ComPacket = (TCG_COM_PACKET *)Buffer; | |
Length = SwapBytes32 (ComPacket->LengthBE); | |
OutstandingData = SwapBytes32 (ComPacket->OutstandingDataBE); | |
if ((Length != 0) && (OutstandingData == 0)) { | |
return TcgResultSuccess; | |
} | |
// | |
// Delay for 2 ms | |
// | |
MicroSecondDelay (2000); | |
} | |
return TcgResultFailure; | |
} | |
/** | |
The function performs send, recv, check comIDs, check method status action. | |
@param[in] Session OPAL_SESSION related to this method.. | |
@param[in] SendSize Transfer Length of Buffer (in bytes) - always a multiple of 512 | |
@param[in] Buffer Address of Data to transfer | |
@param[in] BufferSize Full Size of Buffer, including space that may be used for padding. | |
@param[in] ParseStruct Structure used to parse received TCG response. | |
@param[in] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS. | |
@param[in] EstimateTimeCost Estimate the time need to for the method. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalPerformMethod ( | |
OPAL_SESSION *Session, | |
UINT32 SendSize, | |
VOID *Buffer, | |
UINT32 BufferSize, | |
TCG_PARSE_STRUCT *ParseStruct, | |
UINT8 *MethodStatus, | |
UINT32 EstimateTimeCost | |
) | |
{ | |
NULL_CHECK (Session); | |
NULL_CHECK (MethodStatus); | |
ERROR_CHECK ( | |
OpalTrustedSend ( | |
Session->Sscp, | |
Session->MediaId, | |
TCG_OPAL_SECURITY_PROTOCOL_1, | |
Session->OpalBaseComId, | |
SendSize, | |
Buffer, | |
BufferSize | |
) | |
); | |
ERROR_CHECK ( | |
OpalTrustedRecv ( | |
Session->Sscp, | |
Session->MediaId, | |
TCG_OPAL_SECURITY_PROTOCOL_1, | |
Session->OpalBaseComId, | |
Buffer, | |
BufferSize, | |
EstimateTimeCost | |
) | |
); | |
ERROR_CHECK (TcgInitTcgParseStruct (ParseStruct, Buffer, BufferSize)); | |
ERROR_CHECK (TcgCheckComIds (ParseStruct, Session->OpalBaseComId, Session->ComIdExtension)); | |
ERROR_CHECK (TcgGetMethodStatus (ParseStruct, MethodStatus)); | |
return TcgResultSuccess; | |
} | |
/** | |
Trig the block sid action. | |
@param[in] Session OPAL_SESSION related to this method.. | |
@param[in] HardwareReset Whether need to do hardware reset. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalBlockSid ( | |
OPAL_SESSION *Session, | |
BOOLEAN HardwareReset | |
) | |
{ | |
UINT8 Buffer[BUFFER_SIZE]; | |
TCG_BLOCK_SID_CLEAR_EVENTS *ClearEvents; | |
NULL_CHECK (Session); | |
// | |
// Set Hardware Reset bit | |
// | |
ClearEvents = (TCG_BLOCK_SID_CLEAR_EVENTS *)&Buffer[0]; | |
ClearEvents->Reserved = 0; | |
ClearEvents->HardwareReset = HardwareReset; | |
return (OpalTrustedSend ( | |
Session->Sscp, | |
Session->MediaId, | |
TCG_OPAL_SECURITY_PROTOCOL_2, | |
TCG_BLOCKSID_COMID, // hardcode ComID 0x0005 | |
1, | |
Buffer, | |
BUFFER_SIZE | |
)); | |
} | |
/** | |
Reverts device using Admin SP Revert method. | |
@param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalPsidRevert ( | |
OPAL_SESSION *AdminSpSession | |
) | |
{ | |
// | |
// Now that base comid is known, start Session | |
// we'll attempt to start Session as PSID authority | |
// verify PSID Authority is defined in ADMIN SP authority table... is this possible? | |
// | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
UINT8 Buffer[BUFFER_SIZE]; | |
UINT8 MethodStatus; | |
NULL_CHECK (AdminSpSession); | |
// | |
// Send Revert action on Admin SP | |
// | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buffer, BUFFER_SIZE)); | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, OPAL_UID_ADMIN_SP, OPAL_ADMIN_SP_REVERT_METHOD)); | |
ERROR_CHECK (TcgStartParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndMethodCall (&CreateStruct)); | |
ERROR_CHECK (TcgEndSubPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndComPacket (&CreateStruct, &Size)); | |
// | |
// Send Revert Method Call | |
// | |
ERROR_CHECK (OpalPerformMethod (AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0)); | |
METHOD_STATUS_ERROR_CHECK (MethodStatus, TcgResultFailure); | |
return TcgResultSuccess; | |
} | |
/** | |
Reverts device using Admin SP Revert method. | |
@param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert. | |
@param[in] EstimateTimeCost Estimate the time needed. | |
**/ | |
TCG_RESULT | |
OpalPyrite2PsidRevert ( | |
OPAL_SESSION *AdminSpSession, | |
UINT32 EstimateTimeCost | |
) | |
{ | |
// | |
// Now that base comid is known, start Session | |
// we'll attempt to start Session as PSID authority | |
// verify PSID Authority is defined in ADMIN SP authority table... is this possible? | |
// | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
UINT8 Buffer[BUFFER_SIZE]; | |
UINT8 MethodStatus; | |
NULL_CHECK (AdminSpSession); | |
// | |
// Send Revert action on Admin SP | |
// | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buffer, BUFFER_SIZE)); | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, OPAL_UID_ADMIN_SP, OPAL_ADMIN_SP_REVERT_METHOD)); | |
ERROR_CHECK (TcgStartParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndMethodCall (&CreateStruct)); | |
ERROR_CHECK (TcgEndSubPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndComPacket (&CreateStruct, &Size)); | |
// | |
// Send Revert Method Call | |
// | |
ERROR_CHECK (OpalPerformMethod (AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, EstimateTimeCost)); | |
METHOD_STATUS_ERROR_CHECK (MethodStatus, TcgResultFailure); | |
return TcgResultSuccess; | |
} | |
/** | |
The function fills in the provided Buffer with the level 0 discovery Header | |
of the device specified. | |
@param[in] Session OPAL_SESSION data. | |
@param[in] BufferSize Size of Buffer provided (in bytes) | |
@param[in] BuffAddress Buffer address to fill with Level 0 Discovery response | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalRetrieveLevel0DiscoveryHeader ( | |
OPAL_SESSION *Session, | |
UINTN BufferSize, | |
VOID *BuffAddress | |
) | |
{ | |
return (OpalTrustedRecv ( | |
Session->Sscp, | |
Session->MediaId, | |
TCG_OPAL_SECURITY_PROTOCOL_1, // SP | |
TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY, // SP_Specific | |
BuffAddress, | |
BufferSize, | |
0 | |
)); | |
} | |
/** | |
The function fills in the provided Buffer with the supported protocol list | |
of the device specified. | |
@param[in] Session OPAL_SESSION data. | |
@param[in] BufferSize Size of Buffer provided (in bytes) | |
@param[in] BuffAddress Buffer address to fill with security protocol list | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalRetrieveSupportedProtocolList ( | |
OPAL_SESSION *Session, | |
UINTN BufferSize, | |
VOID *BuffAddress | |
) | |
{ | |
return (OpalTrustedRecv ( | |
Session->Sscp, | |
Session->MediaId, | |
TCG_SECURITY_PROTOCOL_INFO, // SP | |
TCG_SP_SPECIFIC_PROTOCOL_LIST, // SP_Specific | |
BuffAddress, | |
BufferSize, | |
0 | |
)); | |
} | |
/** | |
Starts a session with a security provider (SP). | |
If a session is started successfully, the caller must end the session with OpalEndSession when finished | |
performing Opal actions. | |
@param[in/out] Session OPAL_SESSION to initialize. | |
@param[in] SpId Security provider ID to start the session with. | |
@param[in] Write Whether the session should be read-only (FALSE) or read/write (TRUE). | |
@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 will be sent. | |
@param[in] HostSigningAuthority Host Signing Authority used for start session. If NULL, then no Host Signing Authority will be sent. | |
@param[in/out] MethodStatus Status of the StartSession method; only valid if TcgResultSuccess is returned. | |
@return TcgResultSuccess indicates that the function completed without any internal errors. | |
The caller must inspect the MethodStatus field to determine whether the method completed successfully. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalStartSession ( | |
OPAL_SESSION *Session, | |
TCG_UID SpId, | |
BOOLEAN Write, | |
UINT32 HostChallengeLength, | |
const VOID *HostChallenge, | |
TCG_UID HostSigningAuthority, | |
UINT8 *MethodStatus | |
) | |
{ | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
UINT8 Buf[BUFFER_SIZE]; | |
UINT16 ComIdExtension; | |
UINT32 HostSessionId; | |
ComIdExtension = 0; | |
HostSessionId = 1; | |
NULL_CHECK (Session); | |
NULL_CHECK (MethodStatus); | |
Session->ComIdExtension = ComIdExtension; | |
Session->HostSessionId = HostSessionId; | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK ( | |
TcgCreateStartSession ( | |
&CreateStruct, | |
&Size, | |
Session->OpalBaseComId, | |
ComIdExtension, | |
HostSessionId, | |
SpId, | |
Write, | |
HostChallengeLength, | |
HostChallenge, | |
HostSigningAuthority | |
) | |
); | |
ERROR_CHECK (OpalPerformMethod (Session, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
return TcgResultSuccess; // return early if method failed - user must check MethodStatus | |
} | |
if (TcgParseSyncSession (&ParseStruct, Session->OpalBaseComId, ComIdExtension, HostSessionId, &Session->TperSessionId) != TcgResultSuccess) { | |
OpalEndSession (Session); | |
return TcgResultFailure; | |
} | |
return TcgResultSuccess; | |
} | |
/** | |
Close a session opened with OpalStartSession. | |
@param[in/out] Session OPAL_SESSION to end. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalEndSession ( | |
OPAL_SESSION *Session | |
) | |
{ | |
UINT8 Buffer[BUFFER_SIZE]; | |
TCG_CREATE_STRUCT CreateStruct; | |
UINT32 Size; | |
TCG_PARSE_STRUCT ParseStruct; | |
NULL_CHECK (Session); | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buffer, sizeof (Buffer))); | |
ERROR_CHECK ( | |
TcgCreateEndSession ( | |
&CreateStruct, | |
&Size, | |
Session->OpalBaseComId, | |
Session->ComIdExtension, | |
Session->HostSessionId, | |
Session->TperSessionId | |
) | |
); | |
ERROR_CHECK ( | |
OpalTrustedSend ( | |
Session->Sscp, | |
Session->MediaId, | |
TCG_OPAL_SECURITY_PROTOCOL_1, | |
Session->OpalBaseComId, | |
Size, | |
Buffer, | |
sizeof (Buffer) | |
) | |
); | |
ERROR_CHECK ( | |
OpalTrustedRecv ( | |
Session->Sscp, | |
Session->MediaId, | |
TCG_OPAL_SECURITY_PROTOCOL_1, | |
Session->OpalBaseComId, | |
Buffer, | |
sizeof (Buffer), | |
0 | |
) | |
); | |
ERROR_CHECK (TcgInitTcgParseStruct (&ParseStruct, Buffer, sizeof (Buffer))); | |
ERROR_CHECK (TcgCheckComIds (&ParseStruct, Session->OpalBaseComId, Session->ComIdExtension)); | |
ERROR_CHECK (TcgGetNextEndOfSession (&ParseStruct)); | |
return TcgResultSuccess; | |
} | |
/** | |
The function retrieves the MSID from the device specified | |
@param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert. | |
@param[in] MsidBufferSize Allocated Buffer Size (in bytes) for MSID allocated by caller | |
@param[in] Msid Variable Length byte sequence representing MSID of device | |
@param[in] MsidLength Actual Length of MSID retrieved from device | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalGetMsid ( | |
OPAL_SESSION *AdminSpSession, | |
UINT32 MsidBufferSize, | |
UINT8 *Msid, | |
UINT32 *MsidLength | |
) | |
{ | |
// | |
// now that base comid is known, start Session | |
// we'll attempt to start Session as PSID authority | |
// verify PSID Authority is defined in ADMIN SP authority table... is this possible? | |
// | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
UINT8 MethodStatus; | |
UINT32 Col; | |
const VOID *RecvMsid; | |
UINT8 Buffer[BUFFER_SIZE]; | |
NULL_CHECK (AdminSpSession); | |
NULL_CHECK (Msid); | |
NULL_CHECK (MsidLength); | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buffer, BUFFER_SIZE)); | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, OPAL_UID_ADMIN_SP_C_PIN_MSID, TCG_UID_METHOD_GET)); | |
ERROR_CHECK (TcgStartParameters (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartList (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, OPAL_ADMIN_SP_PIN_COL)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, OPAL_ADMIN_SP_PIN_COL)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddEndList (&CreateStruct)); | |
ERROR_CHECK (TcgEndParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndMethodCall (&CreateStruct)); | |
ERROR_CHECK (TcgEndSubPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndComPacket (&CreateStruct, &Size)); | |
// | |
// Send MSID Method Call | |
// | |
ERROR_CHECK (OpalPerformMethod (AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0)); | |
METHOD_STATUS_ERROR_CHECK (MethodStatus, TcgResultFailure); | |
ERROR_CHECK (TcgGetNextStartList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextStartList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextStartName (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextUINT32 (&ParseStruct, &Col)); | |
ERROR_CHECK (TcgGetNextByteSequence (&ParseStruct, &RecvMsid, MsidLength)); | |
ERROR_CHECK (TcgGetNextEndName (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndOfData (&ParseStruct)); | |
if (Col != OPAL_ADMIN_SP_PIN_COL) { | |
DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_ADMIN_SP_PIN_COL)); | |
return TcgResultFailure; | |
} | |
if (RecvMsid == NULL) { | |
return TcgResultFailure; | |
} | |
if (MsidBufferSize < *MsidLength) { | |
DEBUG ((DEBUG_INFO, "Buffer too small MsidBufferSize: %d MsidLength: %d\n", MsidBufferSize, *MsidLength)); | |
return TcgResultFailureBufferTooSmall; | |
} | |
// | |
// copy msid into Buffer | |
// | |
CopyMem (Msid, RecvMsid, *MsidLength); | |
return TcgResultSuccess; | |
} | |
/** | |
The function retrieves the MSID from the device specified | |
@param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_ANYBODY_AUTHORITY | |
@param[out] ActiveDataRemovalMechanism Active Data Removal Mechanism that the device will use for Revert/RevertSP calls. | |
**/ | |
TCG_RESULT | |
OpalPyrite2GetActiveDataRemovalMechanism ( | |
IN OPAL_SESSION *AdminSpSession, | |
OUT UINT8 *ActiveDataRemovalMechanism | |
) | |
{ | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
UINT8 MethodStatus; | |
UINT32 Col; | |
UINT8 RecvActiveDataRemovalMechanism; | |
UINT8 Buffer[BUFFER_SIZE]; | |
NULL_CHECK (AdminSpSession); | |
NULL_CHECK (ActiveDataRemovalMechanism); | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buffer, BUFFER_SIZE)); | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, OPAL_UID_ADMIN_SP_DATA_REMOVAL_MECHANISM, TCG_UID_METHOD_GET)); | |
ERROR_CHECK (TcgStartParameters (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartList (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddEndList (&CreateStruct)); | |
ERROR_CHECK (TcgEndParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndMethodCall (&CreateStruct)); | |
ERROR_CHECK (TcgEndSubPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndComPacket (&CreateStruct, &Size)); | |
// | |
// Send Get Active Data Removal Mechanism Method Call | |
// | |
ERROR_CHECK (OpalPerformMethod (AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0)); | |
METHOD_STATUS_ERROR_CHECK (MethodStatus, TcgResultFailure); | |
ERROR_CHECK (TcgGetNextStartList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextStartList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextStartName (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextUINT32 (&ParseStruct, &Col)); | |
ERROR_CHECK (TcgGetNextUINT8 (&ParseStruct, &RecvActiveDataRemovalMechanism)); | |
ERROR_CHECK (TcgGetNextEndName (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndOfData (&ParseStruct)); | |
if (Col != OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL) { | |
DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL)); | |
return TcgResultFailure; | |
} | |
if (RecvActiveDataRemovalMechanism >= ResearvedMechanism) { | |
return TcgResultFailure; | |
} | |
// | |
// Copy active data removal mechanism into Buffer | |
// | |
CopyMem (ActiveDataRemovalMechanism, &RecvActiveDataRemovalMechanism, sizeof (RecvActiveDataRemovalMechanism)); | |
return TcgResultSuccess; | |
} | |
/** | |
The function calls the Admin SP RevertSP method on the Locking SP. If KeepUserData is True, then the optional parameter | |
to keep the user Data is set to True, otherwise the optional parameter is not provided. | |
@param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to revertSP | |
@param[in] KeepUserData Specifies whether or not to keep user Data when performing RevertSP action. True = keeps user Data. | |
@param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalAdminRevert ( | |
OPAL_SESSION *LockingSpSession, | |
BOOLEAN KeepUserData, | |
UINT8 *MethodStatus | |
) | |
{ | |
UINT8 Buf[BUFFER_SIZE]; | |
TCG_CREATE_STRUCT CreateStruct; | |
UINT32 Size; | |
TCG_PARSE_STRUCT ParseStruct; | |
TCG_RESULT Ret; | |
NULL_CHECK (LockingSpSession); | |
NULL_CHECK (MethodStatus); | |
// | |
// ReadLocked or WriteLocked must be False (per Opal spec) to guarantee revertSP can keep user Data | |
// | |
if (KeepUserData) { | |
// | |
// set readlocked and writelocked to false | |
// | |
Ret = OpalUpdateGlobalLockingRange ( | |
LockingSpSession, | |
FALSE, | |
FALSE, | |
MethodStatus | |
); | |
if ((Ret != TcgResultSuccess) || (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
// | |
// bail out | |
// | |
return Ret; | |
} | |
} | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, TCG_UID_THIS_SP, OPAL_LOCKING_SP_REVERTSP_METHOD)); | |
ERROR_CHECK (TcgStartParameters (&CreateStruct)); | |
if (KeepUserData) { | |
// | |
// optional parameter to keep Data after revert | |
// | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT32 (&CreateStruct, 0x060000)); // weird Value but that's what spec says | |
ERROR_CHECK (TcgAddBOOLEAN (&CreateStruct, KeepUserData)); | |
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)); | |
// | |
// Send RevertSP method call | |
// | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
// | |
// Session is immediately ended by device after successful revertsp, so no need to end Session | |
// | |
if (*MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) { | |
// | |
// Caller should take ownership again | |
// | |
return TcgResultSuccess; | |
} else { | |
// | |
// End Session | |
// | |
METHOD_STATUS_ERROR_CHECK (*MethodStatus, TcgResultSuccess); // exit with success on method failure - user must inspect MethodStatus | |
} | |
return TcgResultSuccess; | |
} | |
/** | |
The function calls the Admin SP RevertSP method on the Locking SP. If KeepUserData is True, then the optional parameter | |
to keep the user Data is set to True, otherwise the optional parameter is not provided. | |
@param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to revertSP | |
@param[in] KeepUserData Specifies whether or not to keep user Data when performing RevertSP action. True = keeps user Data. | |
@param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS. | |
@param[in] EstimateTimeCost Estimate the time needed. | |
**/ | |
TCG_RESULT | |
OpalPyrite2AdminRevert ( | |
OPAL_SESSION *LockingSpSession, | |
BOOLEAN KeepUserData, | |
UINT8 *MethodStatus, | |
UINT32 EstimateTimeCost | |
) | |
{ | |
UINT8 Buf[BUFFER_SIZE]; | |
TCG_CREATE_STRUCT CreateStruct; | |
UINT32 Size; | |
TCG_PARSE_STRUCT ParseStruct; | |
TCG_RESULT Ret; | |
NULL_CHECK (LockingSpSession); | |
NULL_CHECK (MethodStatus); | |
// | |
// ReadLocked or WriteLocked must be False (per Opal spec) to guarantee revertSP can keep user Data | |
// | |
if (KeepUserData) { | |
// | |
// set readlocked and writelocked to false | |
// | |
Ret = OpalUpdateGlobalLockingRange ( | |
LockingSpSession, | |
FALSE, | |
FALSE, | |
MethodStatus | |
); | |
if ((Ret != TcgResultSuccess) || (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
// | |
// bail out | |
// | |
return Ret; | |
} | |
} | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, TCG_UID_THIS_SP, OPAL_LOCKING_SP_REVERTSP_METHOD)); | |
ERROR_CHECK (TcgStartParameters (&CreateStruct)); | |
if (KeepUserData) { | |
// | |
// optional parameter to keep Data after revert | |
// | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT32 (&CreateStruct, 0x060000)); // weird Value but that's what spec says | |
ERROR_CHECK (TcgAddBOOLEAN (&CreateStruct, KeepUserData)); | |
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)); | |
// | |
// Send RevertSP method call | |
// | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, EstimateTimeCost)); | |
// | |
// Session is immediately ended by device after successful revertsp, so no need to end Session | |
// | |
if (*MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) { | |
// | |
// Caller should take ownership again | |
// | |
return TcgResultSuccess; | |
} else { | |
// | |
// End Session | |
// | |
METHOD_STATUS_ERROR_CHECK (*MethodStatus, TcgResultSuccess); // exit with success on method failure - user must inspect MethodStatus | |
} | |
return TcgResultSuccess; | |
} | |
/** | |
The function activates the Locking SP. | |
Once activated, per Opal spec, the ADMIN SP SID PIN is copied over to the ADMIN1 LOCKING SP PIN. | |
If the Locking SP is already enabled, then TcgResultSuccess is returned and no action occurs. | |
@param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_SID_AUTHORITY to activate Locking SP | |
@param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalActivateLockingSp ( | |
OPAL_SESSION *AdminSpSession, | |
UINT8 *MethodStatus | |
) | |
{ | |
UINT8 Buf[BUFFER_SIZE]; | |
TCG_CREATE_STRUCT CreateStruct; | |
UINT32 Size; | |
TCG_PARSE_STRUCT ParseStruct; | |
NULL_CHECK (AdminSpSession); | |
NULL_CHECK (MethodStatus); | |
// | |
// Call Activate method on Locking SP | |
// | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, OPAL_UID_LOCKING_SP, OPAL_ADMIN_SP_ACTIVATE_METHOD)); | |
ERROR_CHECK (TcgStartParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndMethodCall (&CreateStruct)); | |
ERROR_CHECK (TcgEndSubPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndComPacket (&CreateStruct, &Size)); | |
// | |
// Send Activate method call | |
// | |
ERROR_CHECK (OpalPerformMethod (AdminSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
METHOD_STATUS_ERROR_CHECK (*MethodStatus, TcgResultSuccess); // exit with success on method failure - user must inspect MethodStatus | |
return TcgResultSuccess; | |
} | |
/** | |
The function sets the PIN column of the specified cpinRowUid (authority) with the newPin Value. | |
@param[in/out] Session OPAL_SESSION to set password | |
@param[in] CpinRowUid UID of row (authority) to update PIN column | |
@param[in] NewPin New Pin to set for cpinRowUid specified | |
@param[in] NewPinLength Length in bytes of newPin | |
@param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalSetPassword ( | |
OPAL_SESSION *Session, | |
TCG_UID CpinRowUid, | |
const VOID *NewPin, | |
UINT32 NewPinLength, | |
UINT8 *MethodStatus | |
) | |
{ | |
UINT8 Buf[BUFFER_SIZE]; | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
NULL_CHECK (Session); | |
NULL_CHECK (NewPin); | |
NULL_CHECK (MethodStatus); | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK ( | |
TcgCreateSetCPin ( | |
&CreateStruct, | |
&Size, | |
Session->OpalBaseComId, | |
Session->ComIdExtension, | |
Session->TperSessionId, | |
Session->HostSessionId, | |
CpinRowUid, | |
NewPin, | |
NewPinLength | |
) | |
); | |
ERROR_CHECK (OpalPerformMethod (Session, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
// exit with success on method failure - user must inspect MethodStatus | |
METHOD_STATUS_ERROR_CHECK (*MethodStatus, TcgResultSuccess); | |
return TcgResultSuccess; | |
} | |
/** | |
The function sets the Enabled column to TRUE for the authorityUid provided and updates the PIN column for the cpinRowUid provided | |
using the newPin provided. AuthorityUid and cpinRowUid should describe the same authority. | |
@param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to update | |
@param[in] CpinRowUid Row UID of C_PIN table of Locking SP to update PIN | |
@param[in] AuthorityUid UID of Locking SP authority to update Pin column with | |
@param[in] NewPin New Password used to set Pin column | |
@param[in] NewPinLength Length in bytes of new password | |
@param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalSetLockingSpAuthorityEnabledAndPin ( | |
OPAL_SESSION *LockingSpSession, | |
TCG_UID CpinRowUid, | |
TCG_UID AuthorityUid, | |
const VOID *NewPin, | |
UINT32 NewPinLength, | |
UINT8 *MethodStatus | |
) | |
{ | |
UINT8 Buf[BUFFER_SIZE]; | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
TCG_UID ActiveKey; | |
TCG_RESULT Ret; | |
NULL_CHECK (LockingSpSession); | |
NULL_CHECK (NewPin); | |
NULL_CHECK (MethodStatus); | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK ( | |
TcgSetAuthorityEnabled ( | |
&CreateStruct, | |
&Size, | |
LockingSpSession->OpalBaseComId, | |
LockingSpSession->ComIdExtension, | |
LockingSpSession->TperSessionId, | |
LockingSpSession->HostSessionId, | |
AuthorityUid, | |
TRUE | |
) | |
); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
DEBUG ((DEBUG_INFO, "Send Set Authority error\n")); | |
return TcgResultFailure; | |
} | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK ( | |
TcgCreateSetCPin ( | |
&CreateStruct, | |
&Size, | |
LockingSpSession->OpalBaseComId, | |
LockingSpSession->ComIdExtension, | |
LockingSpSession->TperSessionId, | |
LockingSpSession->HostSessionId, | |
CpinRowUid, | |
NewPin, | |
NewPinLength | |
) | |
); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
// | |
// allow user1 to set global range to unlocked/locked by modifying ACE_Locking_GlobalRange_SetRdLocked/SetWrLocked | |
// | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK ( | |
TcgCreateSetAce ( | |
&CreateStruct, | |
&Size, | |
LockingSpSession->OpalBaseComId, | |
LockingSpSession->ComIdExtension, | |
LockingSpSession->TperSessionId, | |
LockingSpSession->HostSessionId, | |
OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_SET_RDLOCKED, | |
OPAL_LOCKING_SP_USER1_AUTHORITY, | |
TCG_ACE_EXPRESSION_OR, | |
OPAL_LOCKING_SP_ADMINS_AUTHORITY | |
) | |
); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
DEBUG ((DEBUG_INFO, "Update ACE for RDLOCKED failed\n")); | |
return TcgResultFailure; | |
} | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK ( | |
TcgCreateSetAce ( | |
&CreateStruct, | |
&Size, | |
LockingSpSession->OpalBaseComId, | |
LockingSpSession->ComIdExtension, | |
LockingSpSession->TperSessionId, | |
LockingSpSession->HostSessionId, | |
OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_SET_WRLOCKED, | |
OPAL_LOCKING_SP_USER1_AUTHORITY, | |
TCG_ACE_EXPRESSION_OR, | |
OPAL_LOCKING_SP_ADMINS_AUTHORITY | |
) | |
); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
DEBUG ((DEBUG_INFO, "Update ACE for WRLOCKED failed\n")); | |
return TcgResultFailure; | |
} | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK (OpalCreateRetrieveGlobalLockingRangeActiveKey (LockingSpSession, &CreateStruct, &Size)); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
// | |
// For Pyrite type SSC, it not supports Active Key. | |
// So here add check logic before enable it. | |
// | |
Ret = OpalParseRetrieveGlobalLockingRangeActiveKey (&ParseStruct, &ActiveKey); | |
if (Ret == TcgResultSuccess) { | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK ( | |
TcgCreateSetAce ( | |
&CreateStruct, | |
&Size, | |
LockingSpSession->OpalBaseComId, | |
LockingSpSession->ComIdExtension, | |
LockingSpSession->TperSessionId, | |
LockingSpSession->HostSessionId, | |
(ActiveKey == OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY) ? OPAL_LOCKING_SP_ACE_K_AES_256_GLOBALRANGE_GENKEY : OPAL_LOCKING_SP_ACE_K_AES_128_GLOBALRANGE_GENKEY, | |
OPAL_LOCKING_SP_USER1_AUTHORITY, | |
TCG_ACE_EXPRESSION_OR, | |
OPAL_LOCKING_SP_ADMINS_AUTHORITY | |
) | |
); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
DEBUG ((DEBUG_INFO, "Update ACE for GLOBALRANGE_GENKEY failed\n")); | |
// | |
// Disable user1 if all permissions are not granted. | |
// | |
return TcgResultFailure; | |
} | |
} | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK ( | |
TcgCreateSetAce ( | |
&CreateStruct, | |
&Size, | |
LockingSpSession->OpalBaseComId, | |
LockingSpSession->ComIdExtension, | |
LockingSpSession->TperSessionId, | |
LockingSpSession->HostSessionId, | |
OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_GET_ALL, | |
OPAL_LOCKING_SP_USER1_AUTHORITY, | |
TCG_ACE_EXPRESSION_OR, | |
OPAL_LOCKING_SP_ADMINS_AUTHORITY | |
) | |
); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
DEBUG ((DEBUG_INFO, "Update ACE for OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_GET_ALL failed\n")); | |
return TcgResultFailure; | |
} | |
return TcgResultSuccess; | |
} | |
/** | |
The function sets the Enabled column to FALSE for the USER1 authority. | |
@param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to disable User1 | |
@param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalDisableUser ( | |
OPAL_SESSION *LockingSpSession, | |
UINT8 *MethodStatus | |
) | |
{ | |
UINT8 Buf[BUFFER_SIZE]; | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
NULL_CHECK (LockingSpSession); | |
NULL_CHECK (MethodStatus); | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK ( | |
TcgSetAuthorityEnabled ( | |
&CreateStruct, | |
&Size, | |
LockingSpSession->OpalBaseComId, | |
LockingSpSession->ComIdExtension, | |
LockingSpSession->TperSessionId, | |
LockingSpSession->HostSessionId, | |
OPAL_LOCKING_SP_USER1_AUTHORITY, | |
FALSE | |
) | |
); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
return TcgResultSuccess; | |
} | |
/** | |
The function retrieves the active key of the global locking range | |
and calls the GenKey method on the active key retrieved. | |
@param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key | |
@param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalGlobalLockingRangeGenKey ( | |
OPAL_SESSION *LockingSpSession, | |
UINT8 *MethodStatus | |
) | |
{ | |
UINT8 Buf[BUFFER_SIZE]; | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
TCG_UID ActiveKey; | |
NULL_CHECK (LockingSpSession); | |
NULL_CHECK (MethodStatus); | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
// | |
// retrieve the activekey in order to know which globalrange key to generate | |
// | |
ERROR_CHECK (OpalCreateRetrieveGlobalLockingRangeActiveKey (LockingSpSession, &CreateStruct, &Size)); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
METHOD_STATUS_ERROR_CHECK (*MethodStatus, TcgResultSuccess); | |
ERROR_CHECK (OpalParseRetrieveGlobalLockingRangeActiveKey (&ParseStruct, &ActiveKey)); | |
// | |
// call genkey on ActiveKey UID | |
// | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, ActiveKey, TCG_UID_METHOD_GEN_KEY)); | |
ERROR_CHECK (TcgStartParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndMethodCall (&CreateStruct)); | |
ERROR_CHECK (TcgEndSubPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndComPacket (&CreateStruct, &Size)); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
return TcgResultSuccess; | |
} | |
/** | |
The function updates the ReadLocked and WriteLocked columns of the Global Locking Range. | |
This function is required for a user1 authority, since a user1 authority shall only have access to ReadLocked and WriteLocked columns | |
(not ReadLockEnabled and WriteLockEnabled columns). | |
@param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key | |
@param[in] ReadLocked Value to set ReadLocked column for Global Locking Range | |
@param[in] WriteLocked Value to set WriteLocked column for Global Locking Range | |
@param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalUpdateGlobalLockingRange ( | |
OPAL_SESSION *LockingSpSession, | |
BOOLEAN ReadLocked, | |
BOOLEAN WriteLocked, | |
UINT8 *MethodStatus | |
) | |
{ | |
UINT8 Buf[BUFFER_SIZE]; | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
NULL_CHECK (LockingSpSession); | |
NULL_CHECK (MethodStatus); | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
// | |
// set global locking range values | |
// | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, OPAL_LOCKING_SP_LOCKING_GLOBALRANGE, 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 (TcgAddUINT8 (&CreateStruct, 0x07)); // "ReadLocked" | |
ERROR_CHECK (TcgAddBOOLEAN (&CreateStruct, ReadLocked)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, 0x08)); // "WriteLocked" | |
ERROR_CHECK (TcgAddBOOLEAN (&CreateStruct, WriteLocked)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddEndList (&CreateStruct)); | |
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)); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
METHOD_STATUS_ERROR_CHECK (*MethodStatus, TcgResultSuccess); | |
return TcgResultSuccess; | |
} | |
/** | |
The function updates the RangeStart, RangeLength, ReadLockedEnabled, WriteLockedEnabled, ReadLocked and WriteLocked columns | |
of the specified Locking Range. This function requires admin authority of a locking SP session. | |
@param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key | |
@param[in] LockingRangeUid Locking range UID to set values | |
@param[in] RangeStart Value to set RangeStart column for Locking Range | |
@param[in] RangeLength Value to set RangeLength column for Locking Range | |
@param[in] ReadLockEnabled Value to set readLockEnabled column for Locking Range | |
@param[in] WriteLockEnabled Value to set writeLockEnabled column for Locking Range | |
@param[in] ReadLocked Value to set ReadLocked column for Locking Range | |
@param[in] WriteLocked Value to set WriteLocked column for Locking Range | |
@param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalSetLockingRange ( | |
OPAL_SESSION *LockingSpSession, | |
TCG_UID LockingRangeUid, | |
UINT64 RangeStart, | |
UINT64 RangeLength, | |
BOOLEAN ReadLockEnabled, | |
BOOLEAN WriteLockEnabled, | |
BOOLEAN ReadLocked, | |
BOOLEAN WriteLocked, | |
UINT8 *MethodStatus | |
) | |
{ | |
UINT8 Buf[BUFFER_SIZE]; | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
NULL_CHECK (LockingSpSession); | |
NULL_CHECK (MethodStatus); | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
// | |
// set locking range values | |
// | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, LockingRangeUid, TCG_UID_METHOD_SET)); | |
ERROR_CHECK (TcgStartParameters (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, 0x01)); // "Values" | |
ERROR_CHECK (TcgAddStartList (&CreateStruct)); | |
// | |
// range start and range Length only apply to non-global locking ranges | |
// | |
if (LockingRangeUid != OPAL_LOCKING_SP_LOCKING_GLOBALRANGE) { | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, 0x03)); // "RangeStart" | |
ERROR_CHECK (TcgAddUINT64 (&CreateStruct, RangeStart)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, 0x04)); // "RangeLength" | |
ERROR_CHECK (TcgAddUINT64 (&CreateStruct, RangeLength)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
} | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, 0x05)); // "ReadLockEnabled" | |
ERROR_CHECK (TcgAddBOOLEAN (&CreateStruct, ReadLockEnabled)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, 0x06)); // "WriteLockEnabled" | |
ERROR_CHECK (TcgAddBOOLEAN (&CreateStruct, WriteLockEnabled)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, 0x07)); // "ReadLocked" | |
ERROR_CHECK (TcgAddBOOLEAN (&CreateStruct, ReadLocked)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, 0x08)); // "WriteLocked" | |
ERROR_CHECK (TcgAddBOOLEAN (&CreateStruct, WriteLocked)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddEndList (&CreateStruct)); | |
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)); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, MethodStatus, 0)); | |
// Exit with success on method failure - user must inspect MethodStatus | |
METHOD_STATUS_ERROR_CHECK (*MethodStatus, TcgResultSuccess); | |
return TcgResultSuccess; | |
} | |
/** | |
The function populates the CreateStruct with a payload that will retrieve the global locking range active key. | |
It is intended to be called with a session that is already started with a valid credential. | |
The function does not send the payload. | |
@param[in] Session OPAL_SESSION to populate command for, needs ComId | |
@param[in/out] CreateStruct Structure to populate with encoded TCG command | |
@param[in/out] Size Size in bytes of the command created. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalCreateRetrieveGlobalLockingRangeActiveKey ( | |
const OPAL_SESSION *Session, | |
TCG_CREATE_STRUCT *CreateStruct, | |
UINT32 *Size | |
) | |
{ | |
NULL_CHECK (Session); | |
NULL_CHECK (CreateStruct); | |
NULL_CHECK (Size); | |
// Retrieve the activekey in order to know which globalrange key to generate | |
ERROR_CHECK (TcgStartComPacket (CreateStruct, Session->OpalBaseComId, Session->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (CreateStruct, Session->TperSessionId, Session->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (CreateStruct, OPAL_LOCKING_SP_LOCKING_GLOBALRANGE, TCG_UID_METHOD_GET)); | |
ERROR_CHECK (TcgStartParameters (CreateStruct)); | |
ERROR_CHECK (TcgAddStartList (CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME)); | |
ERROR_CHECK (TcgAddUINT8 (CreateStruct, 0x0A)); // ActiveKey | |
ERROR_CHECK (TcgAddEndName (CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME)); | |
ERROR_CHECK (TcgAddUINT8 (CreateStruct, 0x0A)); | |
ERROR_CHECK (TcgAddEndName (CreateStruct)); | |
ERROR_CHECK (TcgAddEndList (CreateStruct)); | |
ERROR_CHECK (TcgEndParameters (CreateStruct)); | |
ERROR_CHECK (TcgEndMethodCall (CreateStruct)); | |
ERROR_CHECK (TcgEndSubPacket (CreateStruct)); | |
ERROR_CHECK (TcgEndPacket (CreateStruct)); | |
ERROR_CHECK (TcgEndComPacket (CreateStruct, Size)); | |
return TcgResultSuccess; | |
} | |
/** | |
The function acquires the activeKey specified for the Global Locking Range from the ParseStruct. | |
@param[in] ParseStruct Structure that contains the device's response with the activekey | |
@param[in/out] ActiveKey The UID of the active key retrieved | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalParseRetrieveGlobalLockingRangeActiveKey ( | |
TCG_PARSE_STRUCT *ParseStruct, | |
TCG_UID *ActiveKey | |
) | |
{ | |
UINT32 ColumnName; | |
NULL_CHECK (ParseStruct); | |
NULL_CHECK (ActiveKey); | |
// parse response | |
ERROR_CHECK (TcgGetNextStartList (ParseStruct)); | |
ERROR_CHECK (TcgGetNextStartList (ParseStruct)); | |
ERROR_CHECK (TcgGetNextStartName (ParseStruct)); | |
ERROR_CHECK (TcgGetNextUINT32 (ParseStruct, &ColumnName)); | |
ERROR_CHECK (TcgGetNextTcgUid (ParseStruct, ActiveKey)); | |
ERROR_CHECK (TcgGetNextEndName (ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndList (ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndList (ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndOfData (ParseStruct)); | |
if (ColumnName != 0x0A) { | |
DEBUG ((DEBUG_INFO, "Unexpected column name %u (exp 0x0A)\n", ColumnName)); | |
return TcgResultFailure; | |
} | |
if ((*ActiveKey != OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY) && (*ActiveKey != OPAL_LOCKING_SP_K_AES_128_GLOBALRANGE_KEY)) { | |
DEBUG ((DEBUG_INFO, "Unexpected gen key %u (exp %u or %u)\n", *ActiveKey, OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY, OPAL_LOCKING_SP_K_AES_128_GLOBALRANGE_KEY)); | |
return TcgResultFailure; | |
} | |
return TcgResultSuccess; | |
} | |
/** | |
The function retrieves the TryLimit column for the specified rowUid (authority). | |
@param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve try limit | |
@param[in] RowUid Row UID of the Locking SP C_PIN table to retrieve TryLimit column | |
@param[in/out] TryLimit Value from TryLimit column | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalGetTryLimit ( | |
OPAL_SESSION *LockingSpSession, | |
TCG_UID RowUid, | |
UINT32 *TryLimit | |
) | |
{ | |
TCG_CREATE_STRUCT CreateStruct; | |
TCG_PARSE_STRUCT ParseStruct; | |
UINT32 Size; | |
UINT8 MethodStatus; | |
UINT8 Buf[BUFFER_SIZE]; | |
UINT32 Col; | |
NULL_CHECK (LockingSpSession); | |
NULL_CHECK (TryLimit); | |
ERROR_CHECK (TcgInitTcgCreateStruct (&CreateStruct, Buf, sizeof (Buf))); | |
ERROR_CHECK (TcgStartComPacket (&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension)); | |
ERROR_CHECK (TcgStartPacket (&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0)); | |
ERROR_CHECK (TcgStartSubPacket (&CreateStruct, 0x0)); | |
ERROR_CHECK (TcgStartMethodCall (&CreateStruct, RowUid, TCG_UID_METHOD_GET)); | |
ERROR_CHECK (TcgStartParameters (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartList (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddStartName (&CreateStruct)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME)); | |
ERROR_CHECK (TcgAddUINT8 (&CreateStruct, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL)); | |
ERROR_CHECK (TcgAddEndName (&CreateStruct)); | |
ERROR_CHECK (TcgAddEndList (&CreateStruct)); | |
ERROR_CHECK (TcgEndParameters (&CreateStruct)); | |
ERROR_CHECK (TcgEndMethodCall (&CreateStruct)); | |
ERROR_CHECK (TcgEndSubPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndPacket (&CreateStruct)); | |
ERROR_CHECK (TcgEndComPacket (&CreateStruct, &Size)); | |
ERROR_CHECK (OpalPerformMethod (LockingSpSession, Size, Buf, sizeof (Buf), &ParseStruct, &MethodStatus, 0)); | |
METHOD_STATUS_ERROR_CHECK (MethodStatus, TcgResultFailure); | |
ERROR_CHECK (TcgGetNextStartList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextStartList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextStartName (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextUINT32 (&ParseStruct, &Col)); | |
ERROR_CHECK (TcgGetNextUINT32 (&ParseStruct, TryLimit)); | |
ERROR_CHECK (TcgGetNextEndName (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndList (&ParseStruct)); | |
ERROR_CHECK (TcgGetNextEndOfData (&ParseStruct)); | |
if (Col != OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL) { | |
DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL)); | |
return TcgResultFailure; | |
} | |
return TcgResultSuccess; | |
} | |
/** | |
Get the support attribute info. | |
@param[in] Session OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info. | |
@param[out] SupportedAttributes Return the support attribute info. | |
@param[out] OpalBaseComId Return the base com id info. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalGetSupportedAttributesInfo ( | |
IN OPAL_SESSION *Session, | |
OUT OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes, | |
OUT UINT16 *OpalBaseComId | |
) | |
{ | |
UINT8 Buffer[BUFFER_SIZE]; | |
TCG_SUPPORTED_SECURITY_PROTOCOLS *SupportedProtocols; | |
TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader; | |
OPAL_LEVEL0_FEATURE_DESCRIPTOR *Feat; | |
OPAL_LEVEL0_FEATURE_DESCRIPTOR *Feat2; | |
UINTN Size; | |
UINTN Size2; | |
NULL_CHECK (Session); | |
NULL_CHECK (SupportedAttributes); | |
NULL_CHECK (OpalBaseComId); | |
ZeroMem (Buffer, BUFFER_SIZE); | |
ZeroMem (SupportedAttributes, sizeof (OPAL_DISK_SUPPORT_ATTRIBUTE)); | |
ASSERT (sizeof (Buffer) >= sizeof (TCG_SUPPORTED_SECURITY_PROTOCOLS)); | |
// | |
// Retrieve supported protocols verify security protocol 1 is supported | |
// | |
SupportedProtocols = (TCG_SUPPORTED_SECURITY_PROTOCOLS *)Buffer; | |
// | |
// Get list of supported protocols | |
// | |
if (OpalRetrieveSupportedProtocolList (Session, sizeof (TCG_SUPPORTED_SECURITY_PROTOCOLS), SupportedProtocols) == TcgResultFailure) { | |
DEBUG ((DEBUG_INFO, "OpalRetrieveSupportedProtocolList failed\n")); | |
return TcgResultFailure; | |
} | |
SupportedAttributes->Sp1 = TcgIsProtocolSupported (SupportedProtocols, TCG_OPAL_SECURITY_PROTOCOL_1); | |
SupportedAttributes->Sp2 = TcgIsProtocolSupported (SupportedProtocols, TCG_OPAL_SECURITY_PROTOCOL_2); | |
SupportedAttributes->SpIeee1667 = TcgIsProtocolSupported (SupportedProtocols, TCG_SECURITY_PROTOCOL_IEEE_1667); | |
DEBUG (( | |
DEBUG_INFO, | |
"Supported Protocols: Sp1 %d Sp2: %d SpIeee1667 %d \n", | |
SupportedAttributes->Sp1, | |
SupportedAttributes->Sp2, | |
SupportedAttributes->SpIeee1667 | |
)); | |
// | |
// Perform level 0 discovery and assign desired feature info to Opal Disk structure | |
// | |
ZeroMem (Buffer, BUFFER_SIZE); | |
if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) { | |
DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n")); | |
return TcgResultFailure; | |
} | |
// | |
// Check for required feature descriptors | |
// | |
DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER *)Buffer; | |
Size = 0; | |
Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR *)TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_V2_0_0, &Size); | |
SupportedAttributes->OpalSsc2 = (Feat != NULL); | |
*OpalBaseComId = TCG_RESERVED_COMID; | |
// | |
// Check Opal SCC V2 has valid settings for SID C_PIN on revert | |
// | |
if (SupportedAttributes->OpalSsc2 && (Size >= sizeof (OPAL_SSCV2_FEATURE_DESCRIPTOR))) { | |
// | |
// Want opposite polarity b/c Value is greater than a bit, but we only care about non-zero vs zero | |
// | |
SupportedAttributes->InitCpinIndicator = (Feat->OpalSscV2.InitialCPINSIDPIN == 0); | |
SupportedAttributes->CpinUponRevert = (Feat->OpalSscV2.CPINSIDPINRevertBehavior == 0); | |
DEBUG (( | |
DEBUG_INFO, | |
"Opal SSC V2 InitCpinIndicator %d CpinUponRevert %d \n", | |
SupportedAttributes->InitCpinIndicator, | |
SupportedAttributes->CpinUponRevert | |
)); | |
*OpalBaseComId = SwapBytes16 (Feat->OpalSscV2.BaseComdIdBE); | |
} | |
Size = 0; | |
Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR *)TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_LITE, &Size); | |
SupportedAttributes->OpalSscLite = (Feat != NULL); | |
if ((Feat != NULL) && (Size >= sizeof (OPAL_SSCLITE_FEATURE_DESCRIPTOR))) { | |
if (*OpalBaseComId == TCG_RESERVED_COMID) { | |
// | |
// Pin values used always match up with ComId used | |
// | |
*OpalBaseComId = SwapBytes16 (Feat->OpalSscLite.BaseComdIdBE); | |
SupportedAttributes->InitCpinIndicator = (Feat->OpalSscV2.InitialCPINSIDPIN == 0); | |
SupportedAttributes->CpinUponRevert = (Feat->OpalSscV2.CPINSIDPINRevertBehavior == 0); | |
DEBUG (( | |
DEBUG_INFO, | |
"Opal SSC Lite InitCpinIndicator %d CpinUponRevert %d \n", | |
SupportedAttributes->InitCpinIndicator, | |
SupportedAttributes->CpinUponRevert | |
)); | |
} | |
} | |
// | |
// For some pyrite 2.0 device, it contains both pyrite 1.0 and 2.0 feature data. | |
// so here try to get data from pyrite 2.0 feature data first. | |
// | |
Size = 0; | |
Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR *)TcgGetFeature (DiscoveryHeader, TCG_FEATURE_PYRITE_SSC, &Size); | |
Size2 = 0; | |
Feat2 = (OPAL_LEVEL0_FEATURE_DESCRIPTOR *)TcgGetFeature (DiscoveryHeader, TCG_FEATURE_PYRITE_SSC_V2_0_0, &Size2); | |
if ((Feat2 != NULL) && (Size2 >= sizeof (PYRITE_SSCV2_FEATURE_DESCRIPTOR))) { | |
SupportedAttributes->PyriteSscV2 = TRUE; | |
if (*OpalBaseComId == TCG_RESERVED_COMID) { | |
*OpalBaseComId = SwapBytes16 (Feat2->PyriteSscV2.BaseComdIdBE); | |
SupportedAttributes->InitCpinIndicator = (Feat2->PyriteSscV2.InitialCPINSIDPIN == 0); | |
SupportedAttributes->CpinUponRevert = (Feat2->PyriteSscV2.CPINSIDPINRevertBehavior == 0); | |
DEBUG (( | |
DEBUG_INFO, | |
"Pyrite SSC V2 InitCpinIndicator %d CpinUponRevert %d \n", | |
SupportedAttributes->InitCpinIndicator, | |
SupportedAttributes->CpinUponRevert | |
)); | |
} | |
} else { | |
SupportedAttributes->PyriteSsc = (Feat != NULL); | |
if ((Feat != NULL) && (Size >= sizeof (PYRITE_SSC_FEATURE_DESCRIPTOR))) { | |
if (*OpalBaseComId == TCG_RESERVED_COMID) { | |
*OpalBaseComId = SwapBytes16 (Feat->PyriteSsc.BaseComdIdBE); | |
SupportedAttributes->InitCpinIndicator = (Feat->PyriteSsc.InitialCPINSIDPIN == 0); | |
SupportedAttributes->CpinUponRevert = (Feat->PyriteSsc.CPINSIDPINRevertBehavior == 0); | |
DEBUG (( | |
DEBUG_INFO, | |
"Pyrite SSC InitCpinIndicator %d CpinUponRevert %d \n", | |
SupportedAttributes->InitCpinIndicator, | |
SupportedAttributes->CpinUponRevert | |
)); | |
} | |
} | |
} | |
Size = 0; | |
Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR *)TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_V1_0_0, &Size); | |
SupportedAttributes->OpalSsc1 = (Feat != NULL); | |
if ((Feat != NULL) && (Size >= sizeof (OPAL_SSCV1_FEATURE_DESCRIPTOR))) { | |
if (*OpalBaseComId == TCG_RESERVED_COMID) { | |
*OpalBaseComId = SwapBytes16 (Feat->OpalSscV1.BaseComdIdBE); | |
} | |
} | |
Size = 0; | |
Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR *)TcgGetFeature (DiscoveryHeader, TCG_FEATURE_LOCKING, &Size); | |
if ((Feat != NULL) && (Size >= sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR))) { | |
SupportedAttributes->MediaEncryption = Feat->Locking.MediaEncryption; | |
DEBUG ((DEBUG_INFO, "SupportedAttributes->MediaEncryption 0x%X \n", SupportedAttributes->MediaEncryption)); | |
} | |
Size = 0; | |
Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR *)TcgGetFeature (DiscoveryHeader, TCG_FEATURE_BLOCK_SID, &Size); | |
if ((Feat != NULL) && (Size >= sizeof (TCG_BLOCK_SID_FEATURE_DESCRIPTOR))) { | |
SupportedAttributes->BlockSid = TRUE; | |
DEBUG ((DEBUG_INFO, "BlockSid Supported!!! Current Status is 0x%X \n", Feat->BlockSid.SIDBlockedState)); | |
} else { | |
DEBUG ((DEBUG_INFO, "BlockSid Unsupported!!!")); | |
} | |
Size = 0; | |
Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR *)TcgGetFeature (DiscoveryHeader, TCG_FEATURE_DATA_REMOVAL, &Size); | |
if ((Feat != NULL) && (Size >= sizeof (DATA_REMOVAL_FEATURE_DESCRIPTOR))) { | |
SupportedAttributes->DataRemoval = TRUE; | |
DEBUG ((DEBUG_INFO, "DataRemoval Feature Supported!\n")); | |
DEBUG ((DEBUG_INFO, "Operation Processing = 0x%x\n", Feat->DataRemoval.OperationProcessing)); | |
DEBUG ((DEBUG_INFO, "RemovalMechanism = 0x%x\n", Feat->DataRemoval.RemovalMechanism)); | |
DEBUG ((DEBUG_INFO, "BIT0 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit0, SwapBytes16 (Feat->DataRemoval.TimeBit0))); | |
DEBUG ((DEBUG_INFO, "BIT1 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit1, SwapBytes16 (Feat->DataRemoval.TimeBit1))); | |
DEBUG ((DEBUG_INFO, "BIT2 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit2, SwapBytes16 (Feat->DataRemoval.TimeBit2))); | |
DEBUG ((DEBUG_INFO, "BIT3 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit3, SwapBytes16 (Feat->DataRemoval.TimeBit3))); | |
DEBUG ((DEBUG_INFO, "BIT4 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit4, SwapBytes16 (Feat->DataRemoval.TimeBit4))); | |
} | |
DEBUG ((DEBUG_INFO, "Base COMID 0x%04X \n", *OpalBaseComId)); | |
return TcgResultSuccess; | |
} | |
/** | |
Get the support attribute info. | |
@param[in] Session OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info. | |
@param[in/out] LockingFeature Return the Locking info. | |
**/ | |
TCG_RESULT | |
EFIAPI | |
OpalGetLockingInfo ( | |
OPAL_SESSION *Session, | |
TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature | |
) | |
{ | |
UINT8 Buffer[BUFFER_SIZE]; | |
TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader; | |
OPAL_LEVEL0_FEATURE_DESCRIPTOR *Feat; | |
UINTN Size; | |
NULL_CHECK (Session); | |
NULL_CHECK (LockingFeature); | |
ZeroMem (Buffer, BUFFER_SIZE); | |
ASSERT (sizeof (Buffer) >= sizeof (TCG_SUPPORTED_SECURITY_PROTOCOLS)); | |
if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) { | |
DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n")); | |
return TcgResultFailure; | |
} | |
DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER *)Buffer; | |
Size = 0; | |
Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR *)TcgGetFeature (DiscoveryHeader, TCG_FEATURE_LOCKING, &Size); | |
if ((Feat != NULL) && (Size >= sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR))) { | |
CopyMem (LockingFeature, &Feat->Locking, sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR)); | |
} | |
return TcgResultSuccess; | |
} | |
/** | |
Get the descriptor for the specific feature code. | |
@param[in] Session OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info. | |
@param[in] FeatureCode The feature code user request. | |
@param[in, out] DataSize The data size. | |
@param[out] Data The data buffer used to save the feature descriptor. | |
**/ | |
TCG_RESULT | |
OpalGetFeatureDescriptor ( | |
IN OPAL_SESSION *Session, | |
IN UINT16 FeatureCode, | |
IN OUT UINTN *DataSize, | |
OUT VOID *Data | |
) | |
{ | |
UINT8 Buffer[BUFFER_SIZE]; | |
TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader; | |
OPAL_LEVEL0_FEATURE_DESCRIPTOR *Feat; | |
UINTN Size; | |
NULL_CHECK (Session); | |
NULL_CHECK (DataSize); | |
NULL_CHECK (Data); | |
ZeroMem (Buffer, BUFFER_SIZE); | |
ASSERT (sizeof (Buffer) >= sizeof (TCG_SUPPORTED_SECURITY_PROTOCOLS)); | |
if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) { | |
DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n")); | |
return TcgResultFailure; | |
} | |
DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER *)Buffer; | |
Size = 0; | |
Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR *)TcgGetFeature (DiscoveryHeader, FeatureCode, &Size); | |
if (Feat != NULL) { | |
if (Size > *DataSize) { | |
*DataSize = Size; | |
return TcgResultFailureBufferTooSmall; | |
} | |
*DataSize = Size; | |
CopyMem (Data, Feat, Size); | |
} | |
return TcgResultSuccess; | |
} | |
/** | |
The function determines whether or not all of the requirements for the Opal Feature (not full specification) | |
are met by the specified device. | |
@param[in] SupportedAttributes Opal device attribute. | |
**/ | |
BOOLEAN | |
EFIAPI | |
OpalFeatureSupported ( | |
OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes | |
) | |
{ | |
NULL_CHECK (SupportedAttributes); | |
if (SupportedAttributes->Sp1 == 0) { | |
return FALSE; | |
} | |
if ((SupportedAttributes->OpalSscLite == 0) && | |
(SupportedAttributes->OpalSsc1 == 0) && | |
(SupportedAttributes->OpalSsc2 == 0) && | |
(SupportedAttributes->PyriteSsc == 0) && | |
(SupportedAttributes->PyriteSscV2 == 0) | |
) | |
{ | |
return FALSE; | |
} | |
return TRUE; | |
} | |
/** | |
The function returns whether or not the device is Opal Enabled. | |
TRUE means that the device is partially or fully locked. | |
This will perform a Level 0 Discovery and parse the locking feature descriptor | |
@param[in] SupportedAttributes Opal device attribute. | |
@param[in] LockingFeature Opal device locking status. | |
**/ | |
BOOLEAN | |
EFIAPI | |
OpalFeatureEnabled ( | |
OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes, | |
TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature | |
) | |
{ | |
NULL_CHECK (SupportedAttributes); | |
NULL_CHECK (LockingFeature); | |
if (!OpalFeatureSupported (SupportedAttributes)) { | |
return FALSE; | |
} | |
if (LockingFeature->LockingSupported && LockingFeature->LockingEnabled) { | |
return TRUE; | |
} | |
return FALSE; | |
} | |
/** | |
The function returns whether or not the device is Opal Locked. | |
TRUE means that the device is partially or fully locked. | |
This will perform a Level 0 Discovery and parse the locking feature descriptor | |
@param[in] SupportedAttributes Opal device attribute. | |
@param[in] LockingFeature Opal device locking status. | |
**/ | |
BOOLEAN | |
OpalDeviceLocked ( | |
OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes, | |
TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature | |
) | |
{ | |
NULL_CHECK (SupportedAttributes); | |
NULL_CHECK (LockingFeature); | |
if (!OpalFeatureEnabled (SupportedAttributes, LockingFeature)) { | |
return FALSE; | |
} | |
return LockingFeature->Locked; | |
} |