summaryrefslogtreecommitdiff
path: root/Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c
diff options
context:
space:
mode:
authorKalyan Nagabhirava <kalyankumar.nagabhirava@linaro.org>2018-02-12 16:01:19 +0530
committerArd Biesheuvel <ard.biesheuvel@linaro.org>2018-03-02 14:45:38 +0000
commit43378096976333db0901bef685dd3e246392d196 (patch)
treedc3a39055be9824146eb5baf7c69b043cef9f2a9 /Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c
parent8e55eaa4c69f28509f3e801cfdb1e8275a579ccf (diff)
downloadedk2-platforms-43378096976333db0901bef685dd3e246392d196.tar.xz
Platform/Comcast: add RDK boot manager library implementation
Implemented features related to secure boot and DRI (downloading the image and storing on flash), library has utility of file read and write operations for fat flash partition, it reads file path and load the file content using configuration file. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Moorthy Baskaravenkatraman <moorthy.baskaravenkatraman-sambamoorthy@linaro.org> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Diffstat (limited to 'Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c')
-rw-r--r--Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c523
1 files changed, 523 insertions, 0 deletions
diff --git a/Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c b/Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c
new file mode 100644
index 0000000000..f063ccfbeb
--- /dev/null
+++ b/Platform/Comcast/Library/RdkBootManagerLib/SecureBoot.c
@@ -0,0 +1,523 @@
+/*
+# Copyright (c) 2014-2018, Linaro Limited. 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 <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;
+}