Слияние кода завершено, страница обновится автоматически
/** @file
Copyright (C) 2017-2020, vit9696. All rights reserved.
All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/OcCryptoLib.h>
#include <Library/OcMiscLib.h>
#include <Library/OcSmcLib.h>
#include <Library/OcRtcLib.h>
#include <Library/OcVariableLib.h>
#include "OcSmcLibInternal.h"
STATIC
EFI_EVENT
mAuthenticationKeyEraseEvent;
STATIC
VIRTUALSMC_KEY_VALUE
mVirtualSmcKeyValue[6] = {
{ SMC_KEY_KEY, SmcKeyTypeUint32, 4, SMC_KEY_ATTRIBUTE_READ, {0, 0, 0, ARRAY_SIZE (mVirtualSmcKeyValue)} },
{ SMC_KEY_RMde, SmcKeyTypeChar, 1, SMC_KEY_ATTRIBUTE_READ, {SMC_MODE_APPCODE} },
//
// Requested yet unused (battery inside, causes missing battery in UI).
//
//{ SMC_KEY_BBIN, SmcKeyTypeFlag, 1, SMC_KEY_ATTRIBUTE_READ, {0} },
{ SMC_KEY_BRSC, SmcKeyTypeUint16, 2, SMC_KEY_ATTRIBUTE_READ, {0} },
{ SMC_KEY_MSLD, SmcKeyTypeUint8, 1, SMC_KEY_ATTRIBUTE_READ, {0} },
{ SMC_KEY_BATP, SmcKeyTypeFlag, 1, SMC_KEY_ATTRIBUTE_READ, {0} },
//
// HBKP must always be the last key in the list (see mAuthenticationKeyIndex).
//
{ SMC_KEY_HBKP, SmcKeyTypeCh8s, 32, SMC_KEY_ATTRIBUTE_READ|SMC_KEY_ATTRIBUTE_WRITE, {0} }
};
STATIC
CONST UINT8
mAuthenticationKeyIndex = ARRAY_SIZE (mVirtualSmcKeyValue) - 1;
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcReadValue (
IN APPLE_SMC_IO_PROTOCOL *This,
IN SMC_KEY Key,
IN SMC_DATA_SIZE Size,
OUT SMC_DATA *Value
)
{
UINTN Index;
DEBUG ((DEBUG_INFO, "OCSMC: SmcReadValue Key %X Size %d\n", Key, Size));
if (Value == NULL) {
return EFI_SMC_BAD_PARAMETER;
}
for (Index = 0; Index < ARRAY_SIZE (mVirtualSmcKeyValue); Index++) {
if (mVirtualSmcKeyValue[Index].Key == Key) {
if (mVirtualSmcKeyValue[Index].Size != Size) {
return EFI_SMC_KEY_MISMATCH;
}
CopyMem (Value, mVirtualSmcKeyValue[Index].Data, Size);
return EFI_SMC_SUCCESS;
}
}
return EFI_SMC_NOT_FOUND;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcWriteValue (
IN APPLE_SMC_IO_PROTOCOL *This,
IN SMC_KEY Key,
IN SMC_DATA_SIZE Size,
IN SMC_DATA *Value
)
{
UINTN Index;
DEBUG ((DEBUG_INFO, "OCSMC: SmcWriteValue Key %X Size %d\n", Key, Size));
if (!Value || Size == 0) {
return EFI_SMC_BAD_PARAMETER;
}
//
// Handle HBKP separately to let boot.efi erase its contents as early as it wants.
//
if (Key == SMC_KEY_HBKP && Size <= SMC_HBKP_SIZE) {
SecureZeroMem (mVirtualSmcKeyValue[mAuthenticationKeyIndex].Data, SMC_HBKP_SIZE);
CopyMem (mVirtualSmcKeyValue[mAuthenticationKeyIndex].Data, Value, Size);
for (Index = 0; Index < SMC_HBKP_SIZE; Index++) {
if (mVirtualSmcKeyValue[mAuthenticationKeyIndex].Data[Index] != 0) {
DEBUG ((DEBUG_INFO, "OCSMC: Not updating key with non-zero data\n"));
break;
}
}
return EFI_SUCCESS;
}
return EFI_SMC_NOT_WRITABLE;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcMakeKey (
IN CHAR8 *Name,
OUT SMC_KEY *Key
)
{
UINTN Index;
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcMakeKey\n"));
if (Name != NULL && Key != NULL) {
*Key = 0;
Index = 0;
do {
if (SMC_KEY_IS_VALID_CHAR (Name[Index])) {
*Key <<= 8;
*Key |= Name[Index];
++Index;
} else {
*Key = 0;
return EFI_SMC_BAD_PARAMETER;
}
} while (Index < sizeof (*Key) / sizeof (*Name));
return EFI_SMC_SUCCESS;
}
return EFI_SMC_BAD_PARAMETER;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcGetKeyCount (
IN APPLE_SMC_IO_PROTOCOL *This,
OUT UINT32 *Count
)
{
DEBUG ((
DEBUG_VERBOSE,
"OCSMC: SmcIoVirtualSmcGetKeyCount %u\n",
(UINT32) ARRAY_SIZE (mVirtualSmcKeyValue)
));
if (Count == NULL) {
return EFI_SMC_BAD_PARAMETER;
}
*Count = SwapBytes32 (ARRAY_SIZE (mVirtualSmcKeyValue));
return EFI_SMC_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcGetKeyFromIndex (
IN APPLE_SMC_IO_PROTOCOL *This,
IN SMC_KEY_INDEX Index,
OUT SMC_KEY *Key
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcGetKeyFromIndex\n"));
if (Key == NULL) {
return EFI_SMC_BAD_PARAMETER;
}
if (Index < ARRAY_SIZE (mVirtualSmcKeyValue)) {
*Key = mVirtualSmcKeyValue[Index].Key;
return EFI_SMC_SUCCESS;
}
return EFI_SMC_NOT_FOUND;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcGetKeyInfo (
IN APPLE_SMC_IO_PROTOCOL *This,
IN SMC_KEY Key,
OUT SMC_DATA_SIZE *Size,
OUT SMC_KEY_TYPE *Type,
OUT SMC_KEY_ATTRIBUTES *Attributes
)
{
UINTN Index;
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcGetKeyFromIndex %X\n", Key));
if (Size == NULL || Type == NULL || Attributes == NULL) {
return EFI_SMC_BAD_PARAMETER;
}
for (Index = 0; Index < ARRAY_SIZE (mVirtualSmcKeyValue); Index++) {
if (mVirtualSmcKeyValue[Index].Key == Key) {
*Size = mVirtualSmcKeyValue[Index].Size;
*Type = mVirtualSmcKeyValue[Index].Type;
*Attributes = mVirtualSmcKeyValue[Index].Attributes;
return EFI_SMC_SUCCESS;
}
}
return EFI_SMC_NOT_FOUND;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcReset (
IN APPLE_SMC_IO_PROTOCOL *This,
IN UINT32 Mode
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcReset %X\n", Mode));
return EFI_SMC_SUCCESS;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcFlashType (
IN APPLE_SMC_IO_PROTOCOL *This,
IN SMC_FLASH_TYPE Type
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcFlashType %X\n", Type));
return EFI_SMC_UNSUPPORTED_FEATURE;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcUnsupported (
VOID
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcUnsupported\n"));
return EFI_SMC_UNSUPPORTED_FEATURE;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcFlashWrite (
IN APPLE_SMC_IO_PROTOCOL *This,
IN UINT32 Unknown,
IN SMC_FLASH_SIZE Size,
IN SMC_DATA *Data
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcFlashWrite %d\n", Size));
return EFI_SMC_UNSUPPORTED_FEATURE;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcFlashAuth (
IN APPLE_SMC_IO_PROTOCOL *This,
IN SMC_FLASH_SIZE Size,
IN SMC_DATA *Data
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcFlashAuth %d\n", Size));
return EFI_SMC_UNSUPPORTED_FEATURE;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcUnknown1 (
VOID
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcUnknown1\n"));
return EFI_SMC_UNSUPPORTED_FEATURE;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcUnknown2 (
IN APPLE_SMC_IO_PROTOCOL *This,
IN UINTN Ukn1,
IN UINTN Ukn2
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcUnknown2\n"));
return EFI_SMC_UNSUPPORTED_FEATURE;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcUnknown3 (
IN APPLE_SMC_IO_PROTOCOL *This,
IN UINTN Ukn1,
IN UINTN Ukn2
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcUnknown3\n"));
return EFI_SMC_UNSUPPORTED_FEATURE;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcUnknown4 (
IN APPLE_SMC_IO_PROTOCOL *This,
IN UINTN Ukn1
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcUnknown4\n"));
return EFI_SMC_UNSUPPORTED_FEATURE;
}
STATIC
EFI_STATUS
EFIAPI
SmcIoVirtualSmcUnknown5 (
IN APPLE_SMC_IO_PROTOCOL *This,
IN UINT8 *Data
)
{
DEBUG ((DEBUG_VERBOSE, "OCSMC: SmcIoVirtualSmcUnknown5\n"));
return EFI_SMC_UNSUPPORTED_FEATURE;
}
STATIC APPLE_SMC_IO_PROTOCOL mSmcIoProtocol = {
APPLE_SMC_IO_PROTOCOL_REVISION,
SmcIoVirtualSmcReadValue,
SmcIoVirtualSmcWriteValue,
SmcIoVirtualSmcGetKeyCount,
SmcIoVirtualSmcMakeKey,
SmcIoVirtualSmcGetKeyFromIndex,
SmcIoVirtualSmcGetKeyInfo,
SmcIoVirtualSmcReset,
SmcIoVirtualSmcFlashType,
SmcIoVirtualSmcUnsupported,
SmcIoVirtualSmcFlashWrite,
SmcIoVirtualSmcFlashAuth,
0,
SMC_PORT_BASE,
FALSE,
SmcIoVirtualSmcUnknown1,
SmcIoVirtualSmcUnknown2,
SmcIoVirtualSmcUnknown3,
SmcIoVirtualSmcUnknown4,
SmcIoVirtualSmcUnknown5
};
STATIC
VOID
EFIAPI
EraseAuthenticationKey (
IN EFI_EVENT Event,
IN VOID *Context
)
{
SecureZeroMem (mVirtualSmcKeyValue[mAuthenticationKeyIndex].Data, SMC_HBKP_SIZE);
}
STATIC
BOOLEAN
ExtractAuthentificationKey (
UINT8 *Buffer,
UINT32 Size
)
{
UINT8 Index;
AES_CONTEXT Context;
UINT8 EncryptKey[CONFIG_AES_KEY_SIZE];
CONST UINT8 *InitVector;
UINT8 *Payload;
UINT32 PayloadSize;
UINT32 RealSize;
if (Size < sizeof (UINT32) + SMC_HBKP_SIZE) {
DEBUG ((DEBUG_INFO, "OCSMC: Invalid key length - %u\n", (UINT32) Size));
return FALSE;
}
if (Buffer[0] == 'V' && Buffer[1] == 'S' && Buffer[2] == 'P' && Buffer[3] == 'T') {
//
// Perform an as-is copy of stored contents.
//
CopyMem (mVirtualSmcKeyValue[mAuthenticationKeyIndex].Data, Buffer + sizeof (UINT32), SMC_HBKP_SIZE);
} else if (Buffer[0] == 'V' && Buffer[1] == 'S' && Buffer[2] == 'E' && Buffer[3] == 'N') {
//
// The magic is followed by an IV and at least one AES block containing at least SMC_HBKP_SIZE bytes.
//
if (Size < sizeof (UINT32) + AES_BLOCK_SIZE + SMC_HBKP_SIZE || (Size - sizeof (UINT32)) % AES_BLOCK_SIZE != 0) {
DEBUG ((DEBUG_INFO, "OCSMC: Invalid encrypted key length - %u\n", (UINT32) Size));
return FALSE;
}
//
// Read and erase the temporary encryption key from CMOS memory.
//
for (Index = 0; Index < sizeof (EncryptKey); Index++) {
EncryptKey[Index] = OcRtcRead (0xD0 + Index);
OcRtcWrite (0xD0 + Index, 0);
}
//
// Perform the decryption.
//
InitVector = Buffer + sizeof (UINT32);
Payload = Buffer + sizeof (UINT32) + AES_BLOCK_SIZE;
PayloadSize = Size - (sizeof (UINT32) + AES_BLOCK_SIZE);
AesInitCtxIv (&Context, EncryptKey, InitVector);
AesCbcDecryptBuffer (&Context, Payload, PayloadSize);
SecureZeroMem (&Context, sizeof (Context));
SecureZeroMem (EncryptKey, sizeof (EncryptKey));
RealSize = *(const UINT32 *)Payload;
//
// Ensure the size matches SMC_HBKP_SIZE.
//
if (RealSize != SMC_HBKP_SIZE) {
DEBUG ((DEBUG_INFO, "OCSMC: Invalid decrypted key length - %d\n", RealSize));
return FALSE;
}
//
// Copy the decrypted contents.
//
CopyMem (mVirtualSmcKeyValue[mAuthenticationKeyIndex].Data, Payload + sizeof (UINT32), SMC_HBKP_SIZE);
} else {
DEBUG ((DEBUG_INFO, "OCSMC: Invalid key magic - %02X %02X %02X %02X\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3]));
return FALSE;
}
return TRUE;
}
STATIC
VOID
LoadAuthenticationKey (
VOID
)
{
EFI_STATUS Status;
VOID *Buffer = NULL;
UINT32 Attributes = 0;
UINTN Size = 0;
//
// Load encryption key contents.
//
Status = gRT->GetVariable (VIRTUALSMC_ENCRYPTION_KEY, &gOcWriteOnlyVariableGuid, &Attributes, &Size, NULL);
if (Status == EFI_BUFFER_TOO_SMALL) {
Buffer = AllocateZeroPool (Size);
if (Buffer != NULL) {
Status = gRT->GetVariable (VIRTUALSMC_ENCRYPTION_KEY, &gOcWriteOnlyVariableGuid, &Attributes, &Size, Buffer);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCSMC: Layer key (%u, %X) obtain failure - %r\n", (UINT32) Size, Attributes, Status));
}
} else {
DEBUG ((DEBUG_INFO, "OCSMC: Key buffer (%u) allocation failure - %r\n", (UINT32) Size, Status));
Status = EFI_OUT_OF_RESOURCES;
}
} else {
DEBUG ((DEBUG_INFO, "OCSMC: Initial key obtain failure - %r\n", Status));
}
//
// Nullify or (at least) remove existing vsmc-key variable.
//
if (Buffer != NULL) {
//
// Parse encryption contents if any.
//
if (!EFI_ERROR (Status)) {
ExtractAuthentificationKey (Buffer, (UINT32)Size);
}
SecureZeroMem (Buffer, Size);
Status = gRT->SetVariable (VIRTUALSMC_ENCRYPTION_KEY, &gOcWriteOnlyVariableGuid, Attributes, Size, Buffer);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCSMC: Failed to zero key - %r\n", Status));
Status = gRT->SetVariable (VIRTUALSMC_ENCRYPTION_KEY, &gOcWriteOnlyVariableGuid, 0, 0, NULL);
}
gBS->FreePool (Buffer);
Buffer = NULL;
} else {
Status = gRT->SetVariable (VIRTUALSMC_ENCRYPTION_KEY, &gOcWriteOnlyVariableGuid, 0, 0, NULL);
}
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCSMC: Failed to remove key - %r\n", Status));
}
//
// Erase local HBKP key copy at exit boot services.
//
Status = gBS->CreateEvent (
EVT_SIGNAL_EXIT_BOOT_SERVICES,
TPL_NOTIFY,
EraseAuthenticationKey,
NULL,
&mAuthenticationKeyEraseEvent
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCSMC: Failed to create exit bs event for hbkp erase\n"));
}
}
STATIC
VOID
ExportStatusKey (
VOID
)
{
EFI_STATUS Status;
UINT32 StatusBuffer[2];
UINT8 *StatusBufferMagic;
StatusBufferMagic = (UINT8 *) &StatusBuffer[0];
//
// Build the structure.
//
StatusBufferMagic[0] = 'V';
StatusBufferMagic[1] = 'S';
StatusBufferMagic[2] = 'M';
StatusBufferMagic[3] = 'C';
StatusBuffer[1] = 1;
//
// Set status key for kext frontend.
//
Status = OcSetSystemVariable (
VIRTUALSMC_STATUS_KEY,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof (StatusBuffer),
StatusBuffer,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCSMC: Failed to create status - %r\n", Status));
}
}
APPLE_SMC_IO_PROTOCOL *
OcSmcIoInstallProtocol (
IN BOOLEAN Reinstall,
IN BOOLEAN AuthRestart
)
{
EFI_STATUS Status;
APPLE_SMC_IO_PROTOCOL *Protocol;
EFI_HANDLE NewHandle;
if (AuthRestart) {
LoadAuthenticationKey ();
ExportStatusKey ();
}
if (Reinstall) {
Status = OcUninstallAllProtocolInstances (&gAppleSmcIoProtocolGuid);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "OCSMC: Uninstall failed: %r\n", Status));
return NULL;
}
} else {
Status = gBS->LocateProtocol (
&gAppleSmcIoProtocolGuid,
NULL,
(VOID *) &Protocol
);
if (!EFI_ERROR (Status)) {
return Protocol;
}
}
NewHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&NewHandle,
&gAppleSmcIoProtocolGuid,
(VOID *) &mSmcIoProtocol,
NULL
);
if (EFI_ERROR (Status)) {
return NULL;
}
return &mSmcIoProtocol;
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )