3 This library registers RSA 2048 SHA 256 guided section handler
4 to parse RSA 2048 SHA 256 encapsulation section and extract raw data.
5 It uses the BaseCrypyLib based on OpenSSL to authenticate the signature.
7 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Protocol/Hash.h>
14 #include <Protocol/SecurityPolicy.h>
15 #include <Library/ExtractGuidedSectionLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/MemoryAllocationLib.h>
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Library/PcdLib.h>
21 #include <Guid/WinCertificate.h>
22 #include <Library/BaseCryptLib.h>
23 #include <Library/PerformanceLib.h>
24 #include <Guid/SecurityPkgTokenSpace.h>
27 /// RSA 2048 SHA 256 Guided Section header
30 EFI_GUID_DEFINED_SECTION GuidedSectionHeader
; ///< EFI guided section header
31 EFI_CERT_BLOCK_RSA_2048_SHA256 CertBlockRsa2048Sha256
; ///< RSA 2048-bit Signature
32 } RSA_2048_SHA_256_SECTION_HEADER
;
35 EFI_GUID_DEFINED_SECTION2 GuidedSectionHeader
; ///< EFI guided section header
36 EFI_CERT_BLOCK_RSA_2048_SHA256 CertBlockRsa2048Sha256
; ///< RSA 2048-bit Signature
37 } RSA_2048_SHA_256_SECTION2_HEADER
;
40 /// Public Exponent of RSA Key.
42 CONST UINT8 mRsaE
[] = { 0x01, 0x00, 0x01 };
46 GetInfo gets raw data size and attribute of the input guided section.
47 It first checks whether the input guid section is supported.
48 If not, EFI_INVALID_PARAMETER will return.
50 @param InputSection Buffer containing the input GUIDed section to be processed.
51 @param OutputBufferSize The size of OutputBuffer.
52 @param ScratchBufferSize The size of ScratchBuffer.
53 @param SectionAttribute The attribute of the input guided section.
55 @retval EFI_SUCCESS The size of destination buffer, the size of scratch buffer and
56 the attribute of the input section are successfully retrieved.
57 @retval EFI_INVALID_PARAMETER The GUID in InputSection does not match this instance guid.
62 Rsa2048Sha256GuidedSectionGetInfo (
63 IN CONST VOID
*InputSection
,
64 OUT UINT32
*OutputBufferSize
,
65 OUT UINT32
*ScratchBufferSize
,
66 OUT UINT16
*SectionAttribute
69 if (IS_SECTION2 (InputSection
)) {
71 // Check whether the input guid section is recognized.
74 &gEfiCertTypeRsa2048Sha256Guid
,
75 &(((EFI_GUID_DEFINED_SECTION2
*) InputSection
)->SectionDefinitionGuid
))) {
76 return EFI_INVALID_PARAMETER
;
79 // Retrieve the size and attribute of the input section data.
81 *SectionAttribute
= ((EFI_GUID_DEFINED_SECTION2
*) InputSection
)->Attributes
;
82 *ScratchBufferSize
= 0;
83 *OutputBufferSize
= SECTION2_SIZE (InputSection
) - sizeof(RSA_2048_SHA_256_SECTION2_HEADER
);
86 // Check whether the input guid section is recognized.
89 &gEfiCertTypeRsa2048Sha256Guid
,
90 &(((EFI_GUID_DEFINED_SECTION
*) InputSection
)->SectionDefinitionGuid
))) {
91 return EFI_INVALID_PARAMETER
;
94 // Retrieve the size and attribute of the input section data.
96 *SectionAttribute
= ((EFI_GUID_DEFINED_SECTION
*) InputSection
)->Attributes
;
97 *ScratchBufferSize
= 0;
98 *OutputBufferSize
= SECTION_SIZE (InputSection
) - sizeof(RSA_2048_SHA_256_SECTION_HEADER
);
106 Extraction handler tries to extract raw data from the input guided section.
107 It also does authentication check for RSA 2048 SHA 256 signature in the input guided section.
108 It first checks whether the input guid section is supported.
109 If not, EFI_INVALID_PARAMETER will return.
111 @param InputSection Buffer containing the input GUIDed section to be processed.
112 @param OutputBuffer Buffer to contain the output raw data allocated by the caller.
113 @param ScratchBuffer A pointer to a caller-allocated buffer for function internal use.
114 @param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the
115 authentication status of the output buffer.
117 @retval EFI_SUCCESS Section Data and Auth Status is extracted successfully.
118 @retval EFI_INVALID_PARAMETER The GUID in InputSection does not match this instance guid.
123 Rsa2048Sha256GuidedSectionHandler (
124 IN CONST VOID
*InputSection
,
125 OUT VOID
**OutputBuffer
,
126 IN VOID
*ScratchBuffer
, OPTIONAL
127 OUT UINT32
*AuthenticationStatus
131 UINT32 OutputBufferSize
;
132 VOID
*DummyInterface
;
133 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlockRsa2048Sha256
;
134 BOOLEAN CryptoStatus
;
135 UINT8 Digest
[SHA256_DIGEST_SIZE
];
137 UINTN PublicKeyBufferSize
;
144 if (IS_SECTION2 (InputSection
)) {
146 // Check whether the input guid section is recognized.
149 &gEfiCertTypeRsa2048Sha256Guid
,
150 &(((EFI_GUID_DEFINED_SECTION2
*)InputSection
)->SectionDefinitionGuid
))) {
151 return EFI_INVALID_PARAMETER
;
155 // Get the RSA 2048 SHA 256 information.
157 CertBlockRsa2048Sha256
= &((RSA_2048_SHA_256_SECTION2_HEADER
*) InputSection
)->CertBlockRsa2048Sha256
;
158 OutputBufferSize
= SECTION2_SIZE (InputSection
) - sizeof (RSA_2048_SHA_256_SECTION2_HEADER
);
159 if ((((EFI_GUID_DEFINED_SECTION
*)InputSection
)->Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
160 PERF_INMODULE_BEGIN ("DxeRsaCopy");
161 CopyMem (*OutputBuffer
, (UINT8
*)InputSection
+ sizeof (RSA_2048_SHA_256_SECTION2_HEADER
), OutputBufferSize
);
162 PERF_INMODULE_END ("DxeRsaCopy");
164 *OutputBuffer
= (UINT8
*)InputSection
+ sizeof (RSA_2048_SHA_256_SECTION2_HEADER
);
168 // Implicitly RSA 2048 SHA 256 GUIDed section should have STATUS_VALID bit set
170 ASSERT ((((EFI_GUID_DEFINED_SECTION2
*)InputSection
)->Attributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0);
171 *AuthenticationStatus
= EFI_AUTH_STATUS_IMAGE_SIGNED
;
174 // Check whether the input guid section is recognized.
177 &gEfiCertTypeRsa2048Sha256Guid
,
178 &(((EFI_GUID_DEFINED_SECTION
*)InputSection
)->SectionDefinitionGuid
))) {
179 return EFI_INVALID_PARAMETER
;
183 // Get the RSA 2048 SHA 256 information.
185 CertBlockRsa2048Sha256
= &((RSA_2048_SHA_256_SECTION_HEADER
*)InputSection
)->CertBlockRsa2048Sha256
;
186 OutputBufferSize
= SECTION_SIZE (InputSection
) - sizeof (RSA_2048_SHA_256_SECTION_HEADER
);
187 if ((((EFI_GUID_DEFINED_SECTION
*)InputSection
)->Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
188 PERF_INMODULE_BEGIN ("DxeRsaCopy");
189 CopyMem (*OutputBuffer
, (UINT8
*)InputSection
+ sizeof (RSA_2048_SHA_256_SECTION_HEADER
), OutputBufferSize
);
190 PERF_INMODULE_END ("DxeRsaCopy");
192 *OutputBuffer
= (UINT8
*)InputSection
+ sizeof (RSA_2048_SHA_256_SECTION_HEADER
);
196 // Implicitly RSA 2048 SHA 256 GUIDed section should have STATUS_VALID bit set
198 ASSERT ((((EFI_GUID_DEFINED_SECTION
*) InputSection
)->Attributes
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0);
199 *AuthenticationStatus
= EFI_AUTH_STATUS_IMAGE_SIGNED
;
203 // Check whether there exists EFI_SECURITY_POLICY_PROTOCOL_GUID.
205 Status
= gBS
->LocateProtocol (&gEfiSecurityPolicyProtocolGuid
, NULL
, &DummyInterface
);
206 if (!EFI_ERROR (Status
)) {
208 // If SecurityPolicy Protocol exist, AUTH platform override bit is set.
210 *AuthenticationStatus
|= EFI_AUTH_STATUS_PLATFORM_OVERRIDE
;
216 // All paths from here return EFI_SUCESS and result is returned in AuthenticationStatus
218 Status
= EFI_SUCCESS
;
221 // Fail if the HashType is not SHA 256
223 if (!CompareGuid (&gEfiHashAlgorithmSha256Guid
, &CertBlockRsa2048Sha256
->HashType
)) {
224 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: HASH type of section is not supported\n"));
225 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
230 // Allocate hash context buffer required for SHA 256
232 HashContext
= AllocatePool (Sha256GetContextSize ());
233 if (HashContext
== NULL
) {
234 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: Can not allocate hash context\n"));
235 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
240 // Hash public key from data payload with SHA256.
242 ZeroMem (Digest
, SHA256_DIGEST_SIZE
);
243 CryptoStatus
= Sha256Init (HashContext
);
245 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: Sha256Init() failed\n"));
246 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
249 CryptoStatus
= Sha256Update (HashContext
, &CertBlockRsa2048Sha256
->PublicKey
, sizeof(CertBlockRsa2048Sha256
->PublicKey
));
251 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: Sha256Update() failed\n"));
252 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
255 CryptoStatus
= Sha256Final (HashContext
, Digest
);
257 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: Sha256Final() failed\n"));
258 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
263 // Fail if the PublicKey is not one of the public keys in PcdRsa2048Sha256PublicKeyBuffer
265 PublicKey
= (UINT8
*)PcdGetPtr (PcdRsa2048Sha256PublicKeyBuffer
);
266 DEBUG ((DEBUG_VERBOSE
, "DxePcdRsa2048Sha256: PublicKeyBuffer = %p\n", PublicKey
));
267 ASSERT (PublicKey
!= NULL
);
268 DEBUG ((DEBUG_VERBOSE
, "DxePcdRsa2048Sha256: PublicKeyBuffer Token = %08x\n", PcdToken (PcdRsa2048Sha256PublicKeyBuffer
)));
269 PublicKeyBufferSize
= PcdGetSize (PcdRsa2048Sha256PublicKeyBuffer
);
270 DEBUG ((DEBUG_VERBOSE
, "DxePcdRsa2048Sha256: PublicKeyBuffer Size = %08x\n", PublicKeyBufferSize
));
271 ASSERT ((PublicKeyBufferSize
% SHA256_DIGEST_SIZE
) == 0);
272 CryptoStatus
= FALSE
;
273 while (PublicKeyBufferSize
!= 0) {
274 if (CompareMem (Digest
, PublicKey
, SHA256_DIGEST_SIZE
) == 0) {
278 PublicKey
= PublicKey
+ SHA256_DIGEST_SIZE
;
279 PublicKeyBufferSize
= PublicKeyBufferSize
- SHA256_DIGEST_SIZE
;
282 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: Public key in section is not supported\n"));
283 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
288 // Generate & Initialize RSA Context.
292 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: RsaNew() failed\n"));
293 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
298 // Set RSA Key Components.
299 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
301 CryptoStatus
= RsaSetKey (Rsa
, RsaKeyN
, CertBlockRsa2048Sha256
->PublicKey
, sizeof(CertBlockRsa2048Sha256
->PublicKey
));
303 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: RsaSetKey(RsaKeyN) failed\n"));
304 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
307 CryptoStatus
= RsaSetKey (Rsa
, RsaKeyE
, mRsaE
, sizeof (mRsaE
));
309 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: RsaSetKey(RsaKeyE) failed\n"));
310 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
315 // Hash data payload with SHA256.
317 ZeroMem (Digest
, SHA256_DIGEST_SIZE
);
318 CryptoStatus
= Sha256Init (HashContext
);
320 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: Sha256Init() failed\n"));
321 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
324 PERF_INMODULE_BEGIN ("DxeRsaShaData");
325 CryptoStatus
= Sha256Update (HashContext
, *OutputBuffer
, OutputBufferSize
);
326 PERF_INMODULE_END ("DxeRsaShaData");
328 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: Sha256Update() failed\n"));
329 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
332 CryptoStatus
= Sha256Final (HashContext
, Digest
);
334 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: Sha256Final() failed\n"));
335 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
340 // Verify the RSA 2048 SHA 256 signature.
342 PERF_INMODULE_BEGIN ("DxeRsaVerify");
343 CryptoStatus
= RsaPkcs1Verify (
347 CertBlockRsa2048Sha256
->Signature
,
348 sizeof (CertBlockRsa2048Sha256
->Signature
)
350 PERF_INMODULE_END ("DxeRsaVerify");
353 // If RSA 2048 SHA 256 signature verification fails, AUTH tested failed bit is set.
355 DEBUG ((DEBUG_ERROR
, "DxeRsa2048Sha256: RsaPkcs1Verify() failed\n"));
356 *AuthenticationStatus
|= EFI_AUTH_STATUS_TEST_FAILED
;
361 // Free allocated resources used to perform RSA 2048 SHA 256 signature verification
366 if (HashContext
!= NULL
) {
367 FreePool (HashContext
);
370 DEBUG ((DEBUG_VERBOSE
, "DxeRsa2048Sha256: Status = %r AuthenticationStatus = %08x\n", Status
, *AuthenticationStatus
));
376 Register the handler to extract RSA 2048 SHA 256 guided section.
378 @param ImageHandle ImageHandle of the loaded driver.
379 @param SystemTable Pointer to the EFI System Table.
381 @retval EFI_SUCCESS Register successfully.
382 @retval EFI_OUT_OF_RESOURCES Not enough memory to register this handler.
386 DxeRsa2048Sha256GuidedSectionExtractLibConstructor (
387 IN EFI_HANDLE ImageHandle
,
388 IN EFI_SYSTEM_TABLE
*SystemTable
391 return ExtractGuidedSectionRegisterHandlers (
392 &gEfiCertTypeRsa2048Sha256Guid
,
393 Rsa2048Sha256GuidedSectionGetInfo
,
394 Rsa2048Sha256GuidedSectionHandler