X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=SecurityPkg%2FLibrary%2FTcgStorageOpalLib%2FTcgStorageOpalCore.c;h=b58597e61f93ebf2dbfce61362e79e7889b3a40b;hb=289b714b77008aa4200c0be25c4b4e25df04955a;hp=cc8d5ef3f00033d2a9530732f47a44192de9da58;hpb=6e7423c3c2ff56c9256b92a845b3e0c959ab0d74;p=mirror_edk2.git diff --git a/SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalCore.c b/SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalCore.c index cc8d5ef3f0..b58597e61f 100644 --- a/SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalCore.c +++ b/SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalCore.c @@ -1,14 +1,8 @@ /** @file Public API for Opal Core library. -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. +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -19,6 +13,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include +#include "TcgStorageOpalLibInternal.h" + #pragma pack(1) typedef struct { UINT8 HardwareReset : 1; @@ -89,6 +85,7 @@ OpalTrustedSend( @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 @@ -98,10 +95,10 @@ OpalTrustedRecv( UINT8 SecurityProtocol, UINT16 SpSpecific, VOID *Buffer, - UINTN BufferSize + UINTN BufferSize, + UINT32 EstimateTimeCost ) { - UINTN TransferLength512; UINT32 Tries; TCG_COM_PACKET *ComPacket; @@ -129,9 +126,15 @@ OpalTrustedRecv( // 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. - // have a max timeout of 10 seconds, 5000 tries * 2ms = 10s // - Tries = 5000; + // 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; @@ -146,7 +149,6 @@ OpalTrustedRecv( Buffer, &TransferSize ); - if (EFI_ERROR (Status)) { return TcgResultFailure; } @@ -179,23 +181,24 @@ OpalTrustedRecv( /** 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] 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( +OpalPerformMethod ( OPAL_SESSION *Session, UINT32 SendSize, VOID *Buffer, UINT32 BufferSize, TCG_PARSE_STRUCT *ParseStruct, - UINT8 *MethodStatus + UINT8 *MethodStatus, + UINT32 EstimateTimeCost ) { NULL_CHECK(Session); @@ -217,7 +220,8 @@ OpalPerformMethod( TCG_OPAL_SECURITY_PROTOCOL_1, Session->OpalBaseComId, Buffer, - BufferSize + BufferSize, + EstimateTimeCost )); ERROR_CHECK(TcgInitTcgParseStruct(ParseStruct, Buffer, BufferSize)); @@ -309,7 +313,59 @@ OpalPsidRevert( // // Send Revert Method Call // - ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus)); + 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; @@ -339,7 +395,8 @@ OpalRetrieveLevel0DiscoveryHeader( TCG_OPAL_SECURITY_PROTOCOL_1, // SP TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY, // SP_Specific BuffAddress, - BufferSize + BufferSize, + 0 )); } @@ -367,7 +424,8 @@ OpalRetrieveSupportedProtocolList( TCG_SECURITY_PROTOCOL_INFO, // SP TCG_SP_SPECIFIC_PROTOCOL_LIST, // SP_Specific BuffAddress, - BufferSize + BufferSize, + 0 )); } @@ -430,7 +488,7 @@ OpalStartSession( HostChallenge, HostSigningAuthority )); - ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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 } @@ -487,7 +545,8 @@ OpalEndSession( TCG_OPAL_SECURITY_PROTOCOL_1, Session->OpalBaseComId, Buffer, - sizeof(Buffer) + sizeof(Buffer), + 0 )); ERROR_CHECK(TcgInitTcgParseStruct(&ParseStruct, Buffer, sizeof(Buffer))); @@ -558,7 +617,7 @@ OpalGetMsid( // // Send MSID Method Call // - ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus)); + ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0)); METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure); ERROR_CHECK(TcgGetNextStartList(&ParseStruct)); @@ -592,6 +651,85 @@ OpalGetMsid( 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 @@ -666,7 +804,103 @@ OpalAdminRevert( // // Send RevertSP method call // - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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 @@ -729,7 +963,7 @@ OpalActivateLockingSp( // // Send Activate method call // - ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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; @@ -778,7 +1012,7 @@ OpalSetPassword( NewPinLength )); - ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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); @@ -831,7 +1065,7 @@ OpalSetLockingSpAuthorityEnabledAndPin( AuthorityUid, TRUE)); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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")); @@ -851,7 +1085,7 @@ OpalSetLockingSpAuthorityEnabledAndPin( NewPin, NewPinLength)); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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 @@ -870,7 +1104,7 @@ OpalSetLockingSpAuthorityEnabledAndPin( OPAL_LOCKING_SP_ADMINS_AUTHORITY )); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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")); @@ -891,7 +1125,7 @@ OpalSetLockingSpAuthorityEnabledAndPin( OPAL_LOCKING_SP_ADMINS_AUTHORITY )); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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")); @@ -900,10 +1134,10 @@ OpalSetLockingSpAuthorityEnabledAndPin( ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf))); ERROR_CHECK(OpalCreateRetrieveGlobalLockingRangeActiveKey(LockingSpSession, &CreateStruct, &Size)); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0)); // - // For Pyrite type SSC, it not supports Active Key. + // For Pyrite type SSC, it not supports Active Key. // So here add check logic before enable it. // Ret = OpalParseRetrieveGlobalLockingRangeActiveKey(&ParseStruct, &ActiveKey); @@ -922,12 +1156,12 @@ OpalSetLockingSpAuthorityEnabledAndPin( OPAL_LOCKING_SP_ADMINS_AUTHORITY )); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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")); // - // TODO do we want to disable user1 if all permissions are not granted + // Disable user1 if all permissions are not granted. // return TcgResultFailure; } @@ -947,7 +1181,7 @@ OpalSetLockingSpAuthorityEnabledAndPin( OPAL_LOCKING_SP_ADMINS_AUTHORITY )); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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")); @@ -991,7 +1225,7 @@ OpalDisableUser( OPAL_LOCKING_SP_USER1_AUTHORITY, FALSE)); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0)); return TcgResultSuccess; } @@ -1026,7 +1260,7 @@ OpalGlobalLockingRangeGenKey( // 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)); + ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0)); METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess); @@ -1047,7 +1281,7 @@ OpalGlobalLockingRangeGenKey( ERROR_CHECK(TcgEndPacket(&CreateStruct)); ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size)); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0)); return TcgResultSuccess; } @@ -1055,7 +1289,7 @@ OpalGlobalLockingRangeGenKey( /** The function updates the ReadLocked and WriteLocked columns of the Global Locking Range. - This funciton is required for a user1 authority, since a user1 authority shall only have access to ReadLocked and WriteLocked columns + 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 @@ -1113,7 +1347,7 @@ OpalUpdateGlobalLockingRange( ERROR_CHECK(TcgEndPacket(&CreateStruct)); ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size)); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0)); METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess); return TcgResultSuccess; @@ -1214,7 +1448,7 @@ OpalSetLockingRange( ERROR_CHECK(TcgEndPacket(&CreateStruct)); ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size)); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus)); + 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); @@ -1362,7 +1596,7 @@ OpalGetTryLimit( ERROR_CHECK(TcgEndPacket(&CreateStruct)); ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size)); - ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, &MethodStatus)); + ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, &MethodStatus, 0)); METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure); ERROR_CHECK(TcgGetNextStartList(&ParseStruct)); @@ -1404,7 +1638,9 @@ OpalGetSupportedAttributesInfo( 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); @@ -1491,19 +1727,38 @@ OpalGetSupportedAttributesInfo( } } + // + // 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); - SupportedAttributes->PyriteSsc = (Feat != NULL); - if (Feat != NULL && Size >= sizeof (PYRITE_SSC_FEATURE_DESCRIPTOR)) { + 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 (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", + *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; @@ -1519,16 +1774,33 @@ OpalGetSupportedAttributesInfo( 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!!!")); } - DEBUG ((DEBUG_INFO, "Base COMID 0x%04X \n", *OpalBaseComId)); + 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; } @@ -1574,6 +1846,57 @@ OpalGetLockingInfo( 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) @@ -1597,7 +1920,8 @@ OpalFeatureSupported( if (SupportedAttributes->OpalSscLite == 0 && SupportedAttributes->OpalSsc1 == 0 && SupportedAttributes->OpalSsc2 == 0 && - SupportedAttributes->PyriteSsc == 0 + SupportedAttributes->PyriteSsc == 0 && + SupportedAttributes->PyriteSscV2 == 0 ) { return FALSE; }