| /** @file | |
| Public API for Opal Core library. | |
| Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include <Uefi.h> | |
| #include <Library/BaseLib.h> | |
| #include <Library/DebugLib.h> | |
| #include <Library/TcgStorageOpalLib.h> | |
| #include "TcgStorageOpalLibInternal.h" | |
| #define OPAL_MSID_LENGTH 128 | |
| /** | |
| Creates a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts device using Admin SP Revert method. | |
| @param[in] Session, The session info for one opal device. | |
| @param[in] Psid PSID of device to revert. | |
| @param[in] PsidLength Length of PSID in bytes. | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilPsidRevert ( | |
| OPAL_SESSION *Session, | |
| const VOID *Psid, | |
| UINT32 PsidLength | |
| ) | |
| { | |
| UINT8 MethodStatus; | |
| TCG_RESULT Ret; | |
| UINT32 RemovalTimeOut; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (Psid); | |
| RemovalTimeOut = GetRevertTimeOut (Session); | |
| DEBUG ((DEBUG_INFO, "OpalUtilPsidRevert: Timeout value = %d\n", RemovalTimeOut)); | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_ADMIN_SP, | |
| TRUE, | |
| PsidLength, | |
| Psid, | |
| OPAL_ADMIN_SP_PSID_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| Ret = OpalPyrite2PsidRevert (Session, RemovalTimeOut); | |
| if (Ret != TcgResultSuccess) { | |
| // | |
| // If revert was successful, session was already ended by TPer, so only end session on failure | |
| // | |
| OpalEndSession (Session); | |
| } | |
| } | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_SID_AUTHORITY, | |
| sets the OPAL_UID_ADMIN_SP_C_PIN_SID column with the new password, | |
| and activates the locking SP to copy SID PIN to Admin1 Locking SP PIN | |
| @param[in] Session, The session info for one opal device. | |
| @param[in] GeneratedSid Generated SID of disk | |
| @param[in] SidLength Length of generatedSid in bytes | |
| @param[in] Password New admin password to set | |
| @param[in] PassLength Length of password in bytes | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilSetAdminPasswordAsSid ( | |
| OPAL_SESSION *Session, | |
| const VOID *GeneratedSid, | |
| UINT32 SidLength, | |
| const VOID *Password, | |
| UINT32 PassLength | |
| ) | |
| { | |
| UINT8 MethodStatus; | |
| TCG_RESULT Ret; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (GeneratedSid); | |
| NULL_CHECK (Password); | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_ADMIN_SP, | |
| TRUE, | |
| SidLength, | |
| GeneratedSid, | |
| OPAL_ADMIN_SP_SID_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "start session with admin SP as SID authority failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus)); | |
| goto done; | |
| } | |
| // | |
| // 1. Update SID = new Password | |
| // | |
| Ret = OpalSetPassword ( | |
| Session, | |
| OPAL_UID_ADMIN_SP_C_PIN_SID, | |
| Password, | |
| PassLength, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| OpalEndSession (Session); | |
| DEBUG ((DEBUG_INFO, "set Password failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus)); | |
| goto done; | |
| } | |
| // | |
| // 2. Activate locking SP | |
| // | |
| Ret = OpalActivateLockingSp (Session, &MethodStatus); | |
| OpalEndSession (Session); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "activate locking SP failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus)); | |
| goto done; | |
| } | |
| done: | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Opens a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY, | |
| and updates the specified locking range with the provided column values | |
| @param[in] Session, The session info for one opal device. | |
| @param[in] Password New admin password to set | |
| @param[in] PassLength Length of password in bytes | |
| @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 | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilSetOpalLockingRange ( | |
| OPAL_SESSION *Session, | |
| const VOID *Password, | |
| UINT32 PassLength, | |
| TCG_UID LockingRangeUid, | |
| UINT64 RangeStart, | |
| UINT64 RangeLength, | |
| BOOLEAN ReadLockEnabled, | |
| BOOLEAN WriteLockEnabled, | |
| BOOLEAN ReadLocked, | |
| BOOLEAN WriteLocked | |
| ) | |
| { | |
| UINT8 MethodStatus; | |
| TCG_RESULT Ret; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (Password); | |
| // | |
| // Start session with Locking SP using current admin Password | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| PassLength, | |
| Password, | |
| OPAL_LOCKING_SP_ADMIN1_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "start session with locking SP failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus)); | |
| goto done; | |
| } | |
| // | |
| // Enable locking range | |
| // | |
| Ret = OpalSetLockingRange ( | |
| Session, | |
| LockingRangeUid, | |
| RangeStart, | |
| RangeLength, | |
| ReadLockEnabled, | |
| WriteLockEnabled, | |
| ReadLocked, | |
| WriteLocked, | |
| &MethodStatus | |
| ); | |
| OpalEndSession (Session); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "set locking range failed: Ret=%d MethodStatus=0x%x\n", Ret, MethodStatus)); | |
| } | |
| done: | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_SID_AUTHORITY, | |
| sets OPAL_UID_ADMIN_SP_C_PIN_SID with the new password, | |
| and sets OPAL_LOCKING_SP_C_PIN_ADMIN1 with the new password. | |
| @param[in] Session, The session info for one opal device. | |
| @param[in] OldPassword Current admin password | |
| @param[in] OldPasswordLength Length of current admin password in bytes | |
| @param[in] NewPassword New admin password to set | |
| @param[in] NewPasswordLength Length of new password in bytes | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilSetAdminPassword ( | |
| OPAL_SESSION *Session, | |
| const VOID *OldPassword, | |
| UINT32 OldPasswordLength, | |
| const VOID *NewPassword, | |
| UINT32 NewPasswordLength | |
| ) | |
| { | |
| TCG_RESULT Ret; | |
| UINT8 MethodStatus; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (OldPassword); | |
| NULL_CHECK (NewPassword); | |
| // | |
| // Unknown ownership | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_ADMIN_SP, | |
| TRUE, | |
| OldPasswordLength, | |
| OldPassword, | |
| OPAL_ADMIN_SP_SID_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "start session with admin SP using old Password failed\n")); | |
| goto done; | |
| } | |
| // | |
| // Update SID = new pw | |
| // | |
| Ret = OpalSetPassword (Session, OPAL_UID_ADMIN_SP_C_PIN_SID, NewPassword, NewPasswordLength, &MethodStatus); | |
| OpalEndSession (Session); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "set new admin SP Password failed\n")); | |
| goto done; | |
| } | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| OldPasswordLength, | |
| OldPassword, | |
| OPAL_LOCKING_SP_ADMIN1_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "start session with locking SP using old Password failed\n")); | |
| goto done; | |
| } | |
| // | |
| // Update admin locking SP to new pw | |
| // | |
| Ret = OpalSetPassword (Session, OPAL_LOCKING_SP_C_PIN_ADMIN1, NewPassword, NewPasswordLength, &MethodStatus); | |
| OpalEndSession (Session); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "set new locking SP Password failed\n")); | |
| goto done; | |
| } | |
| done: | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_USER1_AUTHORITY or OPAL_LOCKING_SP_ADMIN1_AUTHORITY | |
| and sets the User1 SP authority to enabled and sets the User1 password. | |
| @param[in] Session, The session info for one opal device. | |
| @param[in] OldPassword Current admin password | |
| @param[in] OldPasswordLength Length of current admin password in bytes | |
| @param[in] NewPassword New admin password to set | |
| @param[in] NewPasswordLength Length of new password in bytes | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilSetUserPassword ( | |
| OPAL_SESSION *Session, | |
| const VOID *OldPassword, | |
| UINT32 OldPasswordLength, | |
| const VOID *NewPassword, | |
| UINT32 NewPasswordLength | |
| ) | |
| { | |
| UINT8 MethodStatus; | |
| TCG_RESULT Ret; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (OldPassword); | |
| NULL_CHECK (NewPassword); | |
| // | |
| // See if updating user1 authority | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| OldPasswordLength, | |
| OldPassword, | |
| OPAL_LOCKING_SP_USER1_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| Ret = OpalSetPassword ( | |
| Session, | |
| OPAL_LOCKING_SP_C_PIN_USER1, | |
| NewPassword, | |
| NewPasswordLength, | |
| &MethodStatus | |
| ); | |
| OpalEndSession (Session); | |
| if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| return Ret; | |
| } | |
| } | |
| // | |
| // Setting Password for first time or setting Password as admin | |
| // | |
| // | |
| // Start session with Locking SP using current admin Password | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| OldPasswordLength, | |
| OldPassword, | |
| OPAL_LOCKING_SP_ADMIN1_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "StartSession with locking SP as admin1 authority failed\n")); | |
| goto done; | |
| } | |
| // | |
| // Enable User1 and set its PIN | |
| // | |
| Ret = OpalSetLockingSpAuthorityEnabledAndPin ( | |
| Session, | |
| OPAL_LOCKING_SP_C_PIN_USER1, | |
| OPAL_LOCKING_SP_USER1_AUTHORITY, | |
| NewPassword, | |
| NewPasswordLength, | |
| &MethodStatus | |
| ); | |
| OpalEndSession (Session); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "OpalSetLockingSpAuthorityEnabledAndPin failed\n")); | |
| goto done; | |
| } | |
| done: | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Verify whether user input the correct password. | |
| @param[in] Session, The session info for one opal device. | |
| @param[in] Password Admin password | |
| @param[in] PasswordLength Length of password in bytes | |
| @param[in/out] HostSigningAuthority Use the Host signing authority type. | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilVerifyPassword ( | |
| OPAL_SESSION *Session, | |
| const VOID *Password, | |
| UINT32 PasswordLength, | |
| TCG_UID HostSigningAuthority | |
| ) | |
| { | |
| TCG_RESULT Ret; | |
| UINT8 MethodStatus; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (Password); | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| PasswordLength, | |
| Password, | |
| HostSigningAuthority, | |
| &MethodStatus | |
| ); | |
| if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| OpalEndSession (Session); | |
| return TcgResultSuccess; | |
| } | |
| return TcgResultFailure; | |
| } | |
| /** | |
| Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_USER1_AUTHORITY or OPAL_LOCKING_SP_ADMIN1_AUTHORITY | |
| and generates a new global locking range key to erase the Data. | |
| @param[in] Session, The session info for one opal device. | |
| @param[in] Password Admin or user password | |
| @param[in] PasswordLength Length of password in bytes | |
| @param[in/out] PasswordFailed indicates if password failed (start session didn't work) | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilSecureErase ( | |
| OPAL_SESSION *Session, | |
| const VOID *Password, | |
| UINT32 PasswordLength, | |
| BOOLEAN *PasswordFailed | |
| ) | |
| { | |
| UINT8 MethodStatus; | |
| TCG_RESULT Ret; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (Password); | |
| NULL_CHECK (PasswordFailed); | |
| // | |
| // Try to generate a new key with admin1 | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| PasswordLength, | |
| Password, | |
| OPAL_LOCKING_SP_ADMIN1_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| Ret = OpalGlobalLockingRangeGenKey (Session, &MethodStatus); | |
| *PasswordFailed = FALSE; | |
| OpalEndSession (Session); | |
| } else { | |
| // | |
| // Try to generate a new key with user1 | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| PasswordLength, | |
| Password, | |
| OPAL_LOCKING_SP_USER1_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| Ret = OpalGlobalLockingRangeGenKey (Session, &MethodStatus); | |
| *PasswordFailed = FALSE; | |
| OpalEndSession (Session); | |
| } else { | |
| *PasswordFailed = TRUE; | |
| } | |
| } | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY and disables the User1 authority. | |
| @param[in] Session, The session info for one opal device. | |
| @param[in] Password Admin password | |
| @param[in] PasswordLength Length of password in bytes | |
| @param[in/out] PasswordFailed indicates if password failed (start session didn't work) | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilDisableUser ( | |
| OPAL_SESSION *Session, | |
| const VOID *Password, | |
| UINT32 PasswordLength, | |
| BOOLEAN *PasswordFailed | |
| ) | |
| { | |
| UINT8 MethodStatus; | |
| TCG_RESULT Ret; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (Password); | |
| NULL_CHECK (PasswordFailed); | |
| // | |
| // Start session with Locking SP using current admin Password | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| PasswordLength, | |
| Password, | |
| OPAL_LOCKING_SP_ADMIN1_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "StartSession with Locking SP as Admin1 failed\n")); | |
| *PasswordFailed = TRUE; | |
| goto done; | |
| } | |
| *PasswordFailed = FALSE; | |
| Ret = OpalDisableUser (Session, &MethodStatus); | |
| OpalEndSession (Session); | |
| done: | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts the device using the RevertSP method. | |
| @param[in] Session, The session info for one opal device. | |
| @param[in] KeepUserData TRUE to keep existing Data on the disk, or FALSE to erase it | |
| @param[in] Password Admin password | |
| @param[in] PasswordLength Length of password in bytes | |
| @param[in/out] PasswordFailed indicates if password failed (start session didn't work) | |
| @param[in] Msid Msid info. | |
| @param[in] MsidLength Msid data length. | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilRevert ( | |
| OPAL_SESSION *Session, | |
| BOOLEAN KeepUserData, | |
| const VOID *Password, | |
| UINT32 PasswordLength, | |
| BOOLEAN *PasswordFailed, | |
| UINT8 *Msid, | |
| UINT32 MsidLength | |
| ) | |
| { | |
| UINT8 MethodStatus; | |
| TCG_RESULT Ret; | |
| UINT32 RemovalTimeOut; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (Msid); | |
| NULL_CHECK (Password); | |
| NULL_CHECK (PasswordFailed); | |
| RemovalTimeOut = GetRevertTimeOut (Session); | |
| DEBUG ((DEBUG_INFO, "OpalUtilRevert: Timeout value = %d\n", RemovalTimeOut)); | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| PasswordLength, | |
| Password, | |
| OPAL_LOCKING_SP_ADMIN1_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "error starting session: Ret=%d, MethodStatus=%u\n", Ret, MethodStatus)); | |
| *PasswordFailed = TRUE; | |
| goto done; | |
| } | |
| *PasswordFailed = FALSE; | |
| // | |
| // Try to revert with admin1 | |
| // | |
| Ret = OpalPyrite2AdminRevert (Session, KeepUserData, &MethodStatus, RemovalTimeOut); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| // | |
| // Device ends the session on successful revert, so only call OpalEndSession when fail. | |
| // | |
| DEBUG ((DEBUG_INFO, "OpalAdminRevert as admin failed\n")); | |
| OpalEndSession (Session); | |
| } | |
| Ret = OpalUtilSetSIDtoMSID (Session, Password, PasswordLength, Msid, MsidLength); | |
| done: | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| After revert success, set SID to MSID. | |
| @param Session, The session info for one opal device. | |
| @param Password, Input password info. | |
| @param PasswordLength, Input password length. | |
| @param Msid Msid info. | |
| @param MsidLength Msid data length. | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilSetSIDtoMSID ( | |
| OPAL_SESSION *Session, | |
| const VOID *Password, | |
| UINT32 PasswordLength, | |
| UINT8 *Msid, | |
| UINT32 MsidLength | |
| ) | |
| { | |
| TCG_RESULT Ret; | |
| UINT8 MethodStatus; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (Msid); | |
| NULL_CHECK (Password); | |
| // | |
| // Start session with admin sp to update SID to MSID | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_ADMIN_SP, | |
| TRUE, | |
| PasswordLength, | |
| Password, | |
| OPAL_ADMIN_SP_SID_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| goto done; | |
| } | |
| // | |
| // Update SID pin | |
| // | |
| Ret = OpalSetPassword (Session, OPAL_UID_ADMIN_SP_C_PIN_SID, Msid, MsidLength, &MethodStatus); | |
| OpalEndSession (Session); | |
| done: | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Update global locking range. | |
| @param Session, The session info for one opal device. | |
| @param Password, Input password info. | |
| @param PasswordLength, Input password length. | |
| @param ReadLocked, Read lock info. | |
| @param WriteLocked write lock info. | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilUpdateGlobalLockingRange ( | |
| OPAL_SESSION *Session, | |
| const VOID *Password, | |
| UINT32 PasswordLength, | |
| BOOLEAN ReadLocked, | |
| BOOLEAN WriteLocked | |
| ) | |
| { | |
| UINT8 MethodStatus; | |
| TCG_RESULT Ret; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (Password); | |
| // | |
| // Try to start session with Locking SP as admin1 authority | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| PasswordLength, | |
| Password, | |
| OPAL_LOCKING_SP_ADMIN1_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| Ret = OpalUpdateGlobalLockingRange ( | |
| Session, | |
| ReadLocked, | |
| WriteLocked, | |
| &MethodStatus | |
| ); | |
| OpalEndSession (Session); | |
| if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| goto done; | |
| } | |
| } | |
| if (MethodStatus == TCG_METHOD_STATUS_CODE_AUTHORITY_LOCKED_OUT) { | |
| DEBUG ((DEBUG_INFO, "unlock as admin failed with AUTHORITY_LOCKED_OUT\n")); | |
| } | |
| // | |
| // Try user1 authority | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_LOCKING_SP, | |
| TRUE, | |
| PasswordLength, | |
| Password, | |
| OPAL_LOCKING_SP_USER1_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "StartSession with Locking SP as User1 failed\n")); | |
| goto done; | |
| } | |
| Ret = OpalUpdateGlobalLockingRange (Session, ReadLocked, WriteLocked, &MethodStatus); | |
| OpalEndSession (Session); | |
| done: | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| if (MethodStatus == TCG_METHOD_STATUS_CODE_AUTHORITY_LOCKED_OUT) { | |
| // | |
| // Caller need to know this special error, but return status not has type for it. | |
| // so here use TcgResultFailureInvalidType as an replacement. | |
| // | |
| Ret = TcgResultFailureInvalidType; | |
| } else { | |
| Ret = TcgResultFailure; | |
| } | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Update global locking range. | |
| @param Session, The session info for one opal device. | |
| @param Msid, The data buffer to save Msid info. | |
| @param MsidBufferLength, The data buffer length for Msid. | |
| @param MsidLength, The actual data length for Msid. | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilGetMsid ( | |
| OPAL_SESSION *Session, | |
| UINT8 *Msid, | |
| UINT32 MsidBufferLength, | |
| UINT32 *MsidLength | |
| ) | |
| { | |
| UINT8 MethodStatus; | |
| TCG_RESULT Ret; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (Msid); | |
| NULL_CHECK (MsidLength); | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_ADMIN_SP, | |
| TRUE, | |
| 0, | |
| NULL, | |
| TCG_UID_NULL, | |
| &MethodStatus | |
| ); | |
| if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| Ret = OpalGetMsid (Session, MsidBufferLength, Msid, MsidLength); | |
| OpalEndSession (Session); | |
| } | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| The function determines who owns the device by attempting to start a session with different credentials. | |
| If the SID PIN matches the MSID PIN, the no one owns the device. | |
| If the SID PIN matches the ourSidPin, then "Us" owns the device. Otherwise it is unknown. | |
| @param[in] Session The session info for one opal device. | |
| @param Msid, The Msid info. | |
| @param MsidLength, The data length for Msid. | |
| **/ | |
| OPAL_OWNER_SHIP | |
| EFIAPI | |
| OpalUtilDetermineOwnership ( | |
| OPAL_SESSION *Session, | |
| UINT8 *Msid, | |
| UINT32 MsidLength | |
| ) | |
| { | |
| UINT8 MethodStatus; | |
| TCG_RESULT Ret; | |
| OPAL_OWNER_SHIP Owner; | |
| if ((Session == NULL) || (Msid == NULL)) { | |
| return OpalOwnershipUnknown; | |
| } | |
| Owner = OpalOwnershipUnknown; | |
| // | |
| // Start Session as SID_UID with ADMIN_SP using MSID PIN | |
| // | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_ADMIN_SP, | |
| TRUE, | |
| MsidLength, | |
| Msid, | |
| OPAL_ADMIN_SP_SID_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| // | |
| // now we know that SID PIN == MSID PIN | |
| // | |
| Owner = OpalOwnershipNobody; | |
| OpalEndSession (Session); | |
| } | |
| return Owner; | |
| } | |
| /** | |
| The function returns if admin password exists. | |
| @param[in] OwnerShip The owner ship of the opal device. | |
| @param[in] LockingFeature The locking info of the opal device. | |
| @retval TRUE Admin password existed. | |
| @retval FALSE Admin password not existed. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| OpalUtilAdminPasswordExists ( | |
| IN UINT16 OwnerShip, | |
| IN TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature | |
| ) | |
| { | |
| NULL_CHECK (LockingFeature); | |
| // if it is Unknown who owns the device | |
| // then someone has set password previously through our UI | |
| // because the SID would no longer match the generated SID (ownership us) | |
| // or someone has set password using 3rd party software | |
| // | |
| // Locking sp enabled is checked b/c it must be enabled to change the PIN of the Admin1. | |
| // | |
| return (OwnerShip == OpalOwnershipUnknown && LockingFeature->LockingEnabled); | |
| } | |
| /** | |
| Get Active Data Removal Mechanism Value. | |
| @param[in] Session The session info for one opal device. | |
| @param[in] GeneratedSid Generated SID of disk | |
| @param[in] SidLength Length of generatedSid in bytes | |
| @param[out] ActiveDataRemovalMechanism Return the active data removal mechanism. | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilGetActiveDataRemovalMechanism ( | |
| OPAL_SESSION *Session, | |
| const VOID *GeneratedSid, | |
| UINT32 SidLength, | |
| UINT8 *ActiveDataRemovalMechanism | |
| ) | |
| { | |
| TCG_RESULT Ret; | |
| UINT8 MethodStatus; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (GeneratedSid); | |
| NULL_CHECK (ActiveDataRemovalMechanism); | |
| Ret = OpalStartSession ( | |
| Session, | |
| OPAL_UID_ADMIN_SP, | |
| TRUE, | |
| SidLength, | |
| GeneratedSid, | |
| OPAL_ADMIN_SP_ANYBODY_AUTHORITY, | |
| &MethodStatus | |
| ); | |
| if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) { | |
| DEBUG ((DEBUG_INFO, "Start session with admin SP as SID authority failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus)); | |
| if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) { | |
| Ret = TcgResultFailure; | |
| } | |
| return Ret; | |
| } | |
| Ret = OpalPyrite2GetActiveDataRemovalMechanism ( | |
| Session, | |
| ActiveDataRemovalMechanism | |
| ); | |
| if (Ret != TcgResultSuccess) { | |
| DEBUG ((DEBUG_INFO, "Pyrite2 Get Active Data Removal Mechanism failed: Ret=%d\n", Ret)); | |
| } | |
| OpalEndSession (Session); | |
| return Ret; | |
| } | |
| /** | |
| Calculate the estimated time. | |
| @param[in] IsMinute Whether the input time value is minute type or second type. | |
| @param[in] Time The input time value. | |
| **/ | |
| UINT32 | |
| CalculateDataRemovalTime ( | |
| IN BOOLEAN IsMinute, | |
| IN UINT16 Time | |
| ) | |
| { | |
| if (IsMinute) { | |
| return Time * 2 * 60; | |
| } else { | |
| return Time * 2; | |
| } | |
| } | |
| /** | |
| Return the estimated time for specific type. | |
| @param[in] Index The input data removal type. | |
| @param[in] Descriptor DATA_REMOVAL_FEATURE_DESCRIPTOR | |
| **/ | |
| UINT32 | |
| GetDataRemovalTime ( | |
| IN UINT8 Index, | |
| IN DATA_REMOVAL_FEATURE_DESCRIPTOR *Descriptor | |
| ) | |
| { | |
| switch (Index) { | |
| case OverwriteDataErase: | |
| return CalculateDataRemovalTime (Descriptor->FormatBit0, SwapBytes16 (Descriptor->TimeBit0)); | |
| case BlockErase: | |
| return CalculateDataRemovalTime (Descriptor->FormatBit1, SwapBytes16 (Descriptor->TimeBit1)); | |
| case CryptoErase: | |
| return CalculateDataRemovalTime (Descriptor->FormatBit2, SwapBytes16 (Descriptor->TimeBit2)); | |
| case Unmap: | |
| return CalculateDataRemovalTime (Descriptor->FormatBit3, SwapBytes16 (Descriptor->TimeBit3)); | |
| case ResetWritePointers: | |
| return CalculateDataRemovalTime (Descriptor->FormatBit4, SwapBytes16 (Descriptor->TimeBit4)); | |
| case VendorSpecificErase: | |
| return CalculateDataRemovalTime (Descriptor->FormatBit5, SwapBytes16 (Descriptor->TimeBit5)); | |
| default: | |
| return 0; | |
| } | |
| } | |
| /** | |
| Get the supported Data Removal Mechanism list. | |
| @param[in] Session The session info for one opal device. | |
| @param[out] RemovalMechanismLists Return the supported data removal mechanism lists. | |
| **/ | |
| TCG_RESULT | |
| EFIAPI | |
| OpalUtilGetDataRemovalMechanismLists ( | |
| IN OPAL_SESSION *Session, | |
| OUT UINT32 *RemovalMechanismLists | |
| ) | |
| { | |
| TCG_RESULT Ret; | |
| UINTN DataSize; | |
| DATA_REMOVAL_FEATURE_DESCRIPTOR Descriptor; | |
| UINT8 Index; | |
| UINT8 BitValue; | |
| NULL_CHECK (Session); | |
| NULL_CHECK (RemovalMechanismLists); | |
| DataSize = sizeof (Descriptor); | |
| Ret = OpalGetFeatureDescriptor (Session, TCG_FEATURE_DATA_REMOVAL, &DataSize, &Descriptor); | |
| if (Ret != TcgResultSuccess) { | |
| return TcgResultFailure; | |
| } | |
| ASSERT (Descriptor.RemovalMechanism != 0); | |
| for (Index = 0; Index < ResearvedMechanism; Index++) { | |
| BitValue = (BOOLEAN)BitFieldRead8 (Descriptor.RemovalMechanism, Index, Index); | |
| if (BitValue == 0) { | |
| RemovalMechanismLists[Index] = 0; | |
| } else { | |
| RemovalMechanismLists[Index] = GetDataRemovalTime (Index, &Descriptor); | |
| } | |
| } | |
| return TcgResultSuccess; | |
| } | |
| /** | |
| Get revert timeout value. | |
| @param[in] Session The session info for one opal device. | |
| **/ | |
| UINT32 | |
| GetRevertTimeOut ( | |
| IN OPAL_SESSION *Session | |
| ) | |
| { | |
| TCG_RESULT TcgResult; | |
| OPAL_DISK_SUPPORT_ATTRIBUTE SupportedAttributes; | |
| UINT16 BaseComId; | |
| UINT32 MsidLength; | |
| UINT8 Msid[OPAL_MSID_LENGTH]; | |
| UINT32 RemovalMechanishLists[ResearvedMechanism]; | |
| UINT8 ActiveDataRemovalMechanism; | |
| TcgResult = OpalGetSupportedAttributesInfo (Session, &SupportedAttributes, &BaseComId); | |
| if ((TcgResult != TcgResultSuccess) || (SupportedAttributes.DataRemoval == 0)) { | |
| return 0; | |
| } | |
| TcgResult = OpalUtilGetMsid (Session, Msid, OPAL_MSID_LENGTH, &MsidLength); | |
| if (TcgResult != TcgResultSuccess) { | |
| return 0; | |
| } | |
| TcgResult = OpalUtilGetDataRemovalMechanismLists (Session, RemovalMechanishLists); | |
| if (TcgResult != TcgResultSuccess) { | |
| return 0; | |
| } | |
| TcgResult = OpalUtilGetActiveDataRemovalMechanism (Session, Msid, MsidLength, &ActiveDataRemovalMechanism); | |
| if (TcgResult != TcgResultSuccess) { | |
| return 0; | |
| } | |
| return RemovalMechanishLists[ActiveDataRemovalMechanism]; | |
| } |