123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- /** @file
- This library registers RSA 2048 SHA 256 guided section handler
- to parse RSA 2048 SHA 256 encapsulation section and extract raw data.
- It uses the BaseCryptLib based on OpenSSL to authenticate the signature.
- Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <PiDxe.h>
- #include <Protocol/Hash.h>
- #include <Protocol/SecurityPolicy.h>
- #include <Library/ExtractGuidedSectionLib.h>
- #include <Library/DebugLib.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/PcdLib.h>
- #include <Guid/WinCertificate.h>
- #include <Library/BaseCryptLib.h>
- #include <Library/PerformanceLib.h>
- #include <Guid/SecurityPkgTokenSpace.h>
- ///
- /// RSA 2048 SHA 256 Guided Section header
- ///
- typedef struct {
- EFI_GUID_DEFINED_SECTION GuidedSectionHeader; ///< EFI guided section header
- EFI_CERT_BLOCK_RSA_2048_SHA256 CertBlockRsa2048Sha256; ///< RSA 2048-bit Signature
- } RSA_2048_SHA_256_SECTION_HEADER;
- typedef struct {
- EFI_GUID_DEFINED_SECTION2 GuidedSectionHeader; ///< EFI guided section header
- EFI_CERT_BLOCK_RSA_2048_SHA256 CertBlockRsa2048Sha256; ///< RSA 2048-bit Signature
- } RSA_2048_SHA_256_SECTION2_HEADER;
- ///
- /// Public Exponent of RSA Key.
- ///
- CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
- /**
- GetInfo gets raw data size and attribute of the input guided section.
- It first checks whether the input guid section is supported.
- If not, EFI_INVALID_PARAMETER will return.
- @param InputSection Buffer containing the input GUIDed section to be processed.
- @param OutputBufferSize The size of OutputBuffer.
- @param ScratchBufferSize The size of ScratchBuffer.
- @param SectionAttribute The attribute of the input guided section.
- @retval EFI_SUCCESS The size of destination buffer, the size of scratch buffer and
- the attribute of the input section are successfully retrieved.
- @retval EFI_INVALID_PARAMETER The GUID in InputSection does not match this instance guid.
- **/
- EFI_STATUS
- EFIAPI
- Rsa2048Sha256GuidedSectionGetInfo (
- IN CONST VOID *InputSection,
- OUT UINT32 *OutputBufferSize,
- OUT UINT32 *ScratchBufferSize,
- OUT UINT16 *SectionAttribute
- )
- {
- if (IS_SECTION2 (InputSection)) {
- //
- // Check whether the input guid section is recognized.
- //
- if (!CompareGuid (
- &gEfiCertTypeRsa2048Sha256Guid,
- &(((EFI_GUID_DEFINED_SECTION2 *)InputSection)->SectionDefinitionGuid)
- ))
- {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Retrieve the size and attribute of the input section data.
- //
- *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *)InputSection)->Attributes;
- *ScratchBufferSize = 0;
- *OutputBufferSize = SECTION2_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
- } else {
- //
- // Check whether the input guid section is recognized.
- //
- if (!CompareGuid (
- &gEfiCertTypeRsa2048Sha256Guid,
- &(((EFI_GUID_DEFINED_SECTION *)InputSection)->SectionDefinitionGuid)
- ))
- {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Retrieve the size and attribute of the input section data.
- //
- *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes;
- *ScratchBufferSize = 0;
- *OutputBufferSize = SECTION_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION_HEADER);
- }
- return EFI_SUCCESS;
- }
- /**
- Extraction handler tries to extract raw data from the input guided section.
- It also does authentication check for RSA 2048 SHA 256 signature in the input guided section.
- It first checks whether the input guid section is supported.
- If not, EFI_INVALID_PARAMETER will return.
- @param InputSection Buffer containing the input GUIDed section to be processed.
- @param OutputBuffer Buffer to contain the output raw data allocated by the caller.
- @param ScratchBuffer A pointer to a caller-allocated buffer for function internal use.
- @param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the
- authentication status of the output buffer.
- @retval EFI_SUCCESS Section Data and Auth Status is extracted successfully.
- @retval EFI_INVALID_PARAMETER The GUID in InputSection does not match this instance guid.
- **/
- EFI_STATUS
- EFIAPI
- Rsa2048Sha256GuidedSectionHandler (
- IN CONST VOID *InputSection,
- OUT VOID **OutputBuffer,
- IN VOID *ScratchBuffer OPTIONAL,
- OUT UINT32 *AuthenticationStatus
- )
- {
- EFI_STATUS Status;
- UINT32 OutputBufferSize;
- VOID *DummyInterface;
- EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlockRsa2048Sha256;
- BOOLEAN CryptoStatus;
- UINT8 Digest[SHA256_DIGEST_SIZE];
- UINT8 *PublicKey;
- UINTN PublicKeyBufferSize;
- VOID *HashContext;
- VOID *Rsa;
- HashContext = NULL;
- Rsa = NULL;
- if (IS_SECTION2 (InputSection)) {
- //
- // Check whether the input guid section is recognized.
- //
- if (!CompareGuid (
- &gEfiCertTypeRsa2048Sha256Guid,
- &(((EFI_GUID_DEFINED_SECTION2 *)InputSection)->SectionDefinitionGuid)
- ))
- {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Get the RSA 2048 SHA 256 information.
- //
- CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION2_HEADER *)InputSection)->CertBlockRsa2048Sha256;
- OutputBufferSize = SECTION2_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
- if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
- PERF_INMODULE_BEGIN ("DxeRsaCopy");
- CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER), OutputBufferSize);
- PERF_INMODULE_END ("DxeRsaCopy");
- } else {
- *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
- }
- //
- // Implicitly RSA 2048 SHA 256 GUIDed section should have STATUS_VALID bit set
- //
- ASSERT ((((EFI_GUID_DEFINED_SECTION2 *)InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0);
- *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
- } else {
- //
- // Check whether the input guid section is recognized.
- //
- if (!CompareGuid (
- &gEfiCertTypeRsa2048Sha256Guid,
- &(((EFI_GUID_DEFINED_SECTION *)InputSection)->SectionDefinitionGuid)
- ))
- {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Get the RSA 2048 SHA 256 information.
- //
- CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION_HEADER *)InputSection)->CertBlockRsa2048Sha256;
- OutputBufferSize = SECTION_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION_HEADER);
- if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
- PERF_INMODULE_BEGIN ("DxeRsaCopy");
- CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER), OutputBufferSize);
- PERF_INMODULE_END ("DxeRsaCopy");
- } else {
- *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER);
- }
- //
- // Implicitly RSA 2048 SHA 256 GUIDed section should have STATUS_VALID bit set
- //
- ASSERT ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0);
- *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
- }
- //
- // Check whether there exists EFI_SECURITY_POLICY_PROTOCOL_GUID.
- //
- Status = gBS->LocateProtocol (&gEfiSecurityPolicyProtocolGuid, NULL, &DummyInterface);
- if (!EFI_ERROR (Status)) {
- //
- // If SecurityPolicy Protocol exist, AUTH platform override bit is set.
- //
- *AuthenticationStatus |= EFI_AUTH_STATUS_PLATFORM_OVERRIDE;
- return EFI_SUCCESS;
- }
- //
- // All paths from here return EFI_SUCCESS and result is returned in AuthenticationStatus
- //
- Status = EFI_SUCCESS;
- //
- // Fail if the HashType is not SHA 256
- //
- if (!CompareGuid (&gEfiHashAlgorithmSha256Guid, &CertBlockRsa2048Sha256->HashType)) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: HASH type of section is not supported\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- //
- // Allocate hash context buffer required for SHA 256
- //
- HashContext = AllocatePool (Sha256GetContextSize ());
- if (HashContext == NULL) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Can not allocate hash context\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- //
- // Hash public key from data payload with SHA256.
- //
- ZeroMem (Digest, SHA256_DIGEST_SIZE);
- CryptoStatus = Sha256Init (HashContext);
- if (!CryptoStatus) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Init() failed\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- CryptoStatus = Sha256Update (HashContext, &CertBlockRsa2048Sha256->PublicKey, sizeof (CertBlockRsa2048Sha256->PublicKey));
- if (!CryptoStatus) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Update() failed\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- CryptoStatus = Sha256Final (HashContext, Digest);
- if (!CryptoStatus) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Final() failed\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- //
- // Fail if the PublicKey is not one of the public keys in PcdRsa2048Sha256PublicKeyBuffer
- //
- PublicKey = (UINT8 *)PcdGetPtr (PcdRsa2048Sha256PublicKeyBuffer);
- DEBUG ((DEBUG_VERBOSE, "DxePcdRsa2048Sha256: PublicKeyBuffer = %p\n", PublicKey));
- ASSERT (PublicKey != NULL);
- DEBUG ((DEBUG_VERBOSE, "DxePcdRsa2048Sha256: PublicKeyBuffer Token = %08x\n", PcdToken (PcdRsa2048Sha256PublicKeyBuffer)));
- PublicKeyBufferSize = PcdGetSize (PcdRsa2048Sha256PublicKeyBuffer);
- DEBUG ((DEBUG_VERBOSE, "DxePcdRsa2048Sha256: PublicKeyBuffer Size = %08x\n", PublicKeyBufferSize));
- ASSERT ((PublicKeyBufferSize % SHA256_DIGEST_SIZE) == 0);
- CryptoStatus = FALSE;
- while (PublicKeyBufferSize != 0) {
- if (CompareMem (Digest, PublicKey, SHA256_DIGEST_SIZE) == 0) {
- CryptoStatus = TRUE;
- break;
- }
- PublicKey = PublicKey + SHA256_DIGEST_SIZE;
- PublicKeyBufferSize = PublicKeyBufferSize - SHA256_DIGEST_SIZE;
- }
- if (!CryptoStatus) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Public key in section is not supported\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- //
- // Generate & Initialize RSA Context.
- //
- Rsa = RsaNew ();
- if (Rsa == NULL) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaNew() failed\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- //
- // Set RSA Key Components.
- // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
- //
- CryptoStatus = RsaSetKey (Rsa, RsaKeyN, CertBlockRsa2048Sha256->PublicKey, sizeof (CertBlockRsa2048Sha256->PublicKey));
- if (!CryptoStatus) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaSetKey(RsaKeyN) failed\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- CryptoStatus = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
- if (!CryptoStatus) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaSetKey(RsaKeyE) failed\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- //
- // Hash data payload with SHA256.
- //
- ZeroMem (Digest, SHA256_DIGEST_SIZE);
- CryptoStatus = Sha256Init (HashContext);
- if (!CryptoStatus) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Init() failed\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- PERF_INMODULE_BEGIN ("DxeRsaShaData");
- CryptoStatus = Sha256Update (HashContext, *OutputBuffer, OutputBufferSize);
- PERF_INMODULE_END ("DxeRsaShaData");
- if (!CryptoStatus) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Update() failed\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- CryptoStatus = Sha256Final (HashContext, Digest);
- if (!CryptoStatus) {
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Final() failed\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- goto Done;
- }
- //
- // Verify the RSA 2048 SHA 256 signature.
- //
- PERF_INMODULE_BEGIN ("DxeRsaVerify");
- CryptoStatus = RsaPkcs1Verify (
- Rsa,
- Digest,
- SHA256_DIGEST_SIZE,
- CertBlockRsa2048Sha256->Signature,
- sizeof (CertBlockRsa2048Sha256->Signature)
- );
- PERF_INMODULE_END ("DxeRsaVerify");
- if (!CryptoStatus) {
- //
- // If RSA 2048 SHA 256 signature verification fails, AUTH tested failed bit is set.
- //
- DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaPkcs1Verify() failed\n"));
- *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
- }
- Done:
- //
- // Free allocated resources used to perform RSA 2048 SHA 256 signature verification
- //
- if (Rsa != NULL) {
- RsaFree (Rsa);
- }
- if (HashContext != NULL) {
- FreePool (HashContext);
- }
- DEBUG ((DEBUG_VERBOSE, "DxeRsa2048Sha256: Status = %r AuthenticationStatus = %08x\n", Status, *AuthenticationStatus));
- return Status;
- }
- /**
- Register the handler to extract RSA 2048 SHA 256 guided section.
- @param ImageHandle ImageHandle of the loaded driver.
- @param SystemTable Pointer to the EFI System Table.
- @retval EFI_SUCCESS Register successfully.
- @retval EFI_OUT_OF_RESOURCES Not enough memory to register this handler.
- **/
- EFI_STATUS
- EFIAPI
- DxeRsa2048Sha256GuidedSectionExtractLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- return ExtractGuidedSectionRegisterHandlers (
- &gEfiCertTypeRsa2048Sha256Guid,
- Rsa2048Sha256GuidedSectionGetInfo,
- Rsa2048Sha256GuidedSectionHandler
- );
- }
|