123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517 |
- /*
- # Copyright (c) 2014-2018, Linaro Limited. All rights reserved.
- #
- # SPDX-License-Identifier: BSD-2-Clause-Patent
- #
- */
- #include <RdkBootManagerLib.h>
- typedef enum KEY
- {
- PK_KEY=1,
- KEK_KEY,
- DB_KEY,
- DBX_KEY
- } eKey;
- /* ************************** */
- STATIC
- EFI_STATUS
- OpenFileByDevicePath(
- IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
- OUT EFI_FILE_HANDLE *FileHandle,
- IN UINT64 OpenMode,
- IN UINT64 Attributes
- )
- {
- EFI_STATUS Status;
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
- EFI_FILE_PROTOCOL *Handle1;
- EFI_FILE_PROTOCOL *Handle2;
- EFI_HANDLE DeviceHandle;
- if (FilePath == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- Status = gBS->LocateDevicePath (
- &gEfiSimpleFileSystemProtocolGuid,
- FilePath,
- &DeviceHandle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = gBS->OpenProtocol (
- DeviceHandle,
- &gEfiSimpleFileSystemProtocolGuid,
- (VOID**)&EfiSimpleFileSystemProtocol,
- gImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = EfiSimpleFileSystemProtocol->OpenVolume (\
- EfiSimpleFileSystemProtocol, &Handle1);
- if (EFI_ERROR (Status)) {
- FileHandle = NULL;
- return Status;
- }
- //
- // go down directories one node at a time.
- //
- while (!IsDevicePathEnd (*FilePath)) {
- //
- // For file system access each node should be a file path component
- //
- if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||
- DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
- ) {
- FileHandle = NULL;
- return (EFI_INVALID_PARAMETER);
- }
- //
- // Open this file path node
- //
- Handle2 = Handle1;
- Handle1 = NULL;
- //
- // Try to test opening an existing file
- //
- Status = Handle2->Open (
- Handle2,
- &Handle1,
- ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
- OpenMode &~EFI_FILE_MODE_CREATE,
- 0
- );
- //
- // see if the error was that it needs to be created
- //
- if ((EFI_ERROR (Status)) &&
- (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
- Status = Handle2->Open (
- Handle2,
- &Handle1,
- ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
- OpenMode,
- Attributes
- );
- }
- //
- // Close the last node
- //
- Handle2->Close (Handle2);
- if (EFI_ERROR (Status)) {
- return (Status);
- }
- //
- // Get the next node
- //
- *FilePath = NextDevicePathNode (*FilePath);
- }
- //
- // This is a weak spot since if the undefined
- // SHELL_FILE_HANDLE format changes this must change also!
- //
- *FileHandle = (VOID*)Handle1;
- return EFI_SUCCESS;
- }
- EFI_STATUS
- GetFileHandler (
- OUT EFI_FILE_HANDLE *FileHandle,
- IN CONST CHAR16 *Path,
- IN UINT64 OpenMode
- )
- {
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *KeyFileDevicePath;
- EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *DevicePathFromTextProtocol;
- Status = EFI_SUCCESS;
- KeyFileDevicePath = NULL;
- Status = gBS->LocateProtocol (
- &gEfiDevicePathFromTextProtocolGuid,
- NULL,
- (VOID**)&DevicePathFromTextProtocol
- );
- ASSERT_EFI_ERROR (Status);
- KeyFileDevicePath = DevicePathFromTextProtocol->ConvertTextToDevicePath (Path);
- if (KeyFileDevicePath != NULL)
- {
- Status = OpenFileByDevicePath (&KeyFileDevicePath, FileHandle, OpenMode, 0);
- if (Status != EFI_SUCCESS)
- {
- DEBUG ((DEBUG_ERROR, "Getting FileHandle of %s Failed\n",Path));
- }
- }
- return Status;
- }
- STATIC
- EFI_STATUS
- CreateTimeBasedPayload (
- IN OUT UINTN *DataSize,
- IN OUT UINT8 **Data
- )
- {
- EFI_STATUS Status;
- UINT8 *NewData;
- UINT8 *Payload;
- UINTN PayloadSize;
- EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;
- UINTN DescriptorSize;
- EFI_TIME Time;
- if (Data == NULL || DataSize == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // In Setup mode or Custom mode, the variable does not need to be signed but the
- // parameters to the SetVariable() call still need to be prepared as authenticated
- // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
- // data in it.
- //
- Payload = *Data;
- PayloadSize = *DataSize;
- DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + \
- OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
- NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
- if (NewData == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- if ((Payload != NULL) && (PayloadSize != 0)) {
- CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
- }
- DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
- ZeroMem (&Time, sizeof (EFI_TIME));
- Status = gRT->GetTime (&Time, NULL);
- if (EFI_ERROR (Status)) {
- FreePool(NewData);
- return Status;
- }
- Time.Pad1 = 0;
- Time.Nanosecond = 0;
- Time.TimeZone = 0;
- Time.Daylight = 0;
- Time.Pad2 = 0;
- CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
- DescriptorData->AuthInfo.Hdr.dwLength = \
- OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
- DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;
- DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
- CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);
- if (Payload != NULL) {
- FreePool(Payload);
- }
- *DataSize = DescriptorSize + PayloadSize;
- *Data = NewData;
- return EFI_SUCCESS;
- }
- STATIC
- EFI_STATUS
- SetBootMode (
- IN UINT8 SecureBootMode
- )
- {
- return gRT->SetVariable (
- EFI_CUSTOM_MODE_NAME,
- &gEfiCustomModeEnableGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
- sizeof (UINT8),
- &SecureBootMode
- );
- }
- STATIC
- EFI_STATUS
- SetVariable (
- IN EFI_SIGNATURE_LIST *PkCert,
- IN UINTN DataSize,
- IN eKey KeyType
- )
- {
- UINT32 Attr;
- EFI_STATUS Status;
- Status = EFI_SUCCESS;
- Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
- if (KeyType == PK_KEY)
- {
- DEBUG ((DEBUG_INFO, "Setting PK Key\n"));
- Status = gRT->SetVariable (
- EFI_PLATFORM_KEY_NAME,
- &gEfiGlobalVariableGuid,
- Attr,
- DataSize,
- PkCert
- );
- }
- else if (KeyType == KEK_KEY)
- {
- DEBUG ((DEBUG_INFO, "Setting KEK Key\n"));
- Status = gRT->SetVariable (
- EFI_KEY_EXCHANGE_KEY_NAME,
- &gEfiGlobalVariableGuid,
- Attr,
- DataSize,
- PkCert
- );
- Status = gRT->SetVariable (
- EFI_IMAGE_SECURITY_DATABASE,
- &gEfiImageSecurityDatabaseGuid,
- Attr,
- DataSize,
- PkCert
- );
- }
- else
- {
- ASSERT(FALSE);
- }
- return Status;
- }
- STATIC
- VOID
- PopulateCert (
- OUT EFI_SIGNATURE_LIST **Cert,
- IN UINTN DataSize,
- IN UINT8 *Data
- )
- {
- EFI_SIGNATURE_DATA *CertData = NULL;
- if ((*Cert) == NULL)
- {
- (*Cert) = (EFI_SIGNATURE_LIST*) AllocateZeroPool (sizeof (EFI_SIGNATURE_LIST)
- + sizeof(EFI_SIGNATURE_DATA) - 1
- + DataSize );
- ASSERT ((*Cert) != NULL);
- }
- (*Cert)->SignatureListSize = (UINT32) (sizeof (EFI_SIGNATURE_LIST)
- + sizeof (EFI_SIGNATURE_DATA) - 1
- + DataSize);
- (*Cert)->SignatureSize = (UINT32) (sizeof (EFI_SIGNATURE_DATA) - 1 + DataSize);
- (*Cert)->SignatureHeaderSize = 0;
- CopyGuid (&(*Cert)->SignatureType, &gEfiCertX509Guid);
- CertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*Cert) + \
- sizeof(EFI_SIGNATURE_LIST) + (*Cert)->SignatureHeaderSize);
- ASSERT (CertData != NULL);
- CopyGuid (&CertData->SignatureOwner, &gEfiGlobalVariableGuid);
- CopyMem (&CertData->SignatureData, Data, DataSize);
- }
- STATIC
- EFI_STATUS
- RegisterCert (
- IN UINT8 *KeyData,
- IN UINTN KeySize,
- IN eKey KeyType
- )
- {
- EFI_STATUS Status;
- EFI_SIGNATURE_LIST *Cert;
- Cert = NULL;
- Status = SetBootMode (CUSTOM_SECURE_BOOT_MODE);
- ASSERT_EFI_ERROR (Status);
- PopulateCert (&Cert, KeySize, KeyData);
- KeySize = Cert->SignatureListSize;
- Status = CreateTimeBasedPayload (&KeySize, (UINT8**) &Cert);
- ASSERT_EFI_ERROR (Status);
- Status = SetVariable (Cert, KeySize, KeyType);
- return Status;
- }
- STATIC
- VOID
- RdkSetVariable (
- VOID
- )
- {
- CONST CHAR16 *KeyPath;
- EFI_STATUS Status;
- UINT8 *KekKey, *PkKey, *KekCrtData;
- UINTN KekKeySize, PkKeySize, KekCrtSize;
- INT8* SetupMode;
- eKey KeyType;
- KeyPath = NULL;
- SetupMode = NULL;
- KekKey = PkKey = KekCrtData = NULL;
- KekKeySize = PkKeySize = KekCrtSize = 0;
- Status = GetRdkVariable (L"ROOTCERT", &KeyPath);
- //set only if the Kek Crt file mentioned in the configuration file
- if (KeyPath != NULL) {
- Status = RdkReadFile (
- KeyPath,
- (VOID **)&KekCrtData,
- &KekCrtSize
- );
- ASSERT_EFI_ERROR (Status);
- Status = gRT->SetVariable (
- L"RdkRootCertificate",
- &gRdkGlobalVariableGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- KekCrtSize,
- KekCrtData
- );
- ASSERT_EFI_ERROR (Status);
- if (KekCrtData) FreePool (KekCrtData);
- }
- Status = GetRdkVariable (L"KEKCERT", &KeyPath);
- ASSERT_EFI_ERROR (Status);
- Status = RdkReadFile (
- KeyPath,
- (VOID **)&KekKey,
- &KekKeySize
- );
- ASSERT_EFI_ERROR (Status);
- Status = GetRdkVariable (L"PKCERT", &KeyPath);
- ASSERT_EFI_ERROR (Status);
- Status = RdkReadFile (
- KeyPath,
- (VOID **)&PkKey,
- &PkKeySize
- );
- ASSERT_EFI_ERROR (Status);
- KeyType = PK_KEY;
- Status = RegisterCert (PkKey, PkKeySize, KeyType);
- GetEfiGlobalVariable2 (L"SetupMode", (VOID**)&SetupMode, NULL);
- if (*SetupMode == 0)
- {
- DEBUG ((DEBUG_INFO, "PK Key Got Registered. Now System in User Mode\n"));
- KeyType = KEK_KEY;
- Status = RegisterCert (KekKey, KekKeySize, KeyType);
- }
- else if(*SetupMode == 1)
- {
- DEBUG ((DEBUG_INFO, "System in Standard System Mode ::: Secure Boot Not enabled\n"));
- ASSERT_EFI_ERROR (Status);
- }
- if ( PkKey ) FreePool (PkKey);
- if ( KekKey ) FreePool (KekKey);
- }
- EFI_STATUS
- RdkSecureBoot (
- EFI_HANDLE ImageHandle,
- EFI_BOOT_SERVICES *BootServices
- )
- {
- UINTN ExitDataSize;
- CHAR16 *ExitData;
- CHAR16 LoadOption[128];
- CONST CHAR8 *CmdLine;
- CHAR16 *ImagePath;
- UINT8 *FdtData;
- CONST CHAR16 *DtbPath;
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- EFI_DEVICE_PATH_PROTOCOL *FilePath;
- EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
- EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *DevicePathFromTextProtocol;
- FilePath = NULL;
- ExitData = NULL;
- CmdLine = (CONST CHAR8 *)FixedPcdGetPtr (PcdRdkCmdLineArgs);
- if (FixedPcdGetBool (PcdDtbAvailable)) {
- FdtData = NULL;
- DtbPath = NULL;
- Status = GetRdkVariable (L"DTB", &DtbPath);
- ASSERT_EFI_ERROR (Status);
- Status = RdkReadFile (DtbPath, (VOID**) &FdtData, NULL);
- ASSERT_EFI_ERROR (Status);
- Status = gBS->InstallConfigurationTable (&gFdtTableGuid,(VOID*)FdtData);
- ASSERT_EFI_ERROR (Status);
- }
- RdkSetVariable ();
- Status = GetRdkVariable (L"IMAGE", (CONST CHAR16**)&ImagePath);
- ASSERT_EFI_ERROR (Status);
- Status = gBS->LocateProtocol (
- &gEfiDevicePathFromTextProtocolGuid,
- NULL,
- (VOID**)&DevicePathFromTextProtocol
- );
- ASSERT_EFI_ERROR (Status);
- FilePath = DevicePathFromTextProtocol->ConvertTextToDevicePath (ImagePath);
- ASSERT(NULL != FilePath);
- Status = BootServices->LoadImage (
- TRUE,
- ImageHandle,
- FilePath,
- NULL,
- 0,
- &Handle
- );
- ASSERT_EFI_ERROR (Status);
- UnicodeSPrintAsciiFormat (LoadOption, sizeof (LoadOption), CmdLine);
- Status = BootServices->HandleProtocol (\
- Handle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo);
- ASSERT_EFI_ERROR (Status);
- ImageInfo->LoadOptionsSize = sizeof (LoadOption);
- ImageInfo->LoadOptions = LoadOption;
- Status = BootServices->StartImage (Handle, &ExitDataSize, &ExitData);
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
|