]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c
00593289501c3c30bb90cad6f1d5ccdddf408ce8
[mirror_edk2.git] / SecurityPkg / Library / DxeRsa2048Sha256GuidedSectionExtractLib / DxeRsa2048Sha256GuidedSectionExtractLib.c
1 /** @file
2
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.
6
7 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <PiDxe.h>
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>
25
26 ///
27 /// RSA 2048 SHA 256 Guided Section header
28 ///
29 typedef struct {
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;
33
34 typedef struct {
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;
38
39 ///
40 /// Public Exponent of RSA Key.
41 ///
42 CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
43
44 /**
45
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.
49
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.
54
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.
58
59 **/
60 EFI_STATUS
61 EFIAPI
62 Rsa2048Sha256GuidedSectionGetInfo (
63 IN CONST VOID *InputSection,
64 OUT UINT32 *OutputBufferSize,
65 OUT UINT32 *ScratchBufferSize,
66 OUT UINT16 *SectionAttribute
67 )
68 {
69 if (IS_SECTION2 (InputSection)) {
70 //
71 // Check whether the input guid section is recognized.
72 //
73 if (!CompareGuid (
74 &gEfiCertTypeRsa2048Sha256Guid,
75 &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {
76 return EFI_INVALID_PARAMETER;
77 }
78 //
79 // Retrieve the size and attribute of the input section data.
80 //
81 *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes;
82 *ScratchBufferSize = 0;
83 *OutputBufferSize = SECTION2_SIZE (InputSection) - sizeof(RSA_2048_SHA_256_SECTION2_HEADER);
84 } else {
85 //
86 // Check whether the input guid section is recognized.
87 //
88 if (!CompareGuid (
89 &gEfiCertTypeRsa2048Sha256Guid,
90 &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
91 return EFI_INVALID_PARAMETER;
92 }
93 //
94 // Retrieve the size and attribute of the input section data.
95 //
96 *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes;
97 *ScratchBufferSize = 0;
98 *OutputBufferSize = SECTION_SIZE (InputSection) - sizeof(RSA_2048_SHA_256_SECTION_HEADER);
99 }
100
101 return EFI_SUCCESS;
102 }
103
104 /**
105
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.
110
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.
116
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.
119
120 **/
121 EFI_STATUS
122 EFIAPI
123 Rsa2048Sha256GuidedSectionHandler (
124 IN CONST VOID *InputSection,
125 OUT VOID **OutputBuffer,
126 IN VOID *ScratchBuffer, OPTIONAL
127 OUT UINT32 *AuthenticationStatus
128 )
129 {
130 EFI_STATUS Status;
131 UINT32 OutputBufferSize;
132 VOID *DummyInterface;
133 EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlockRsa2048Sha256;
134 BOOLEAN CryptoStatus;
135 UINT8 Digest[SHA256_DIGEST_SIZE];
136 UINT8 *PublicKey;
137 UINTN PublicKeyBufferSize;
138 VOID *HashContext;
139 VOID *Rsa;
140
141 HashContext = NULL;
142 Rsa = NULL;
143
144 if (IS_SECTION2 (InputSection)) {
145 //
146 // Check whether the input guid section is recognized.
147 //
148 if (!CompareGuid (
149 &gEfiCertTypeRsa2048Sha256Guid,
150 &(((EFI_GUID_DEFINED_SECTION2 *)InputSection)->SectionDefinitionGuid))) {
151 return EFI_INVALID_PARAMETER;
152 }
153
154 //
155 // Get the RSA 2048 SHA 256 information.
156 //
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");
163 } else {
164 *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
165 }
166
167 //
168 // Implicitly RSA 2048 SHA 256 GUIDed section should have STATUS_VALID bit set
169 //
170 ASSERT ((((EFI_GUID_DEFINED_SECTION2 *)InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0);
171 *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
172 } else {
173 //
174 // Check whether the input guid section is recognized.
175 //
176 if (!CompareGuid (
177 &gEfiCertTypeRsa2048Sha256Guid,
178 &(((EFI_GUID_DEFINED_SECTION *)InputSection)->SectionDefinitionGuid))) {
179 return EFI_INVALID_PARAMETER;
180 }
181
182 //
183 // Get the RSA 2048 SHA 256 information.
184 //
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");
191 } else {
192 *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER);
193 }
194
195 //
196 // Implicitly RSA 2048 SHA 256 GUIDed section should have STATUS_VALID bit set
197 //
198 ASSERT ((((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0);
199 *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
200 }
201
202 //
203 // Check whether there exists EFI_SECURITY_POLICY_PROTOCOL_GUID.
204 //
205 Status = gBS->LocateProtocol (&gEfiSecurityPolicyProtocolGuid, NULL, &DummyInterface);
206 if (!EFI_ERROR (Status)) {
207 //
208 // If SecurityPolicy Protocol exist, AUTH platform override bit is set.
209 //
210 *AuthenticationStatus |= EFI_AUTH_STATUS_PLATFORM_OVERRIDE;
211
212 return EFI_SUCCESS;
213 }
214
215 //
216 // All paths from here return EFI_SUCESS and result is returned in AuthenticationStatus
217 //
218 Status = EFI_SUCCESS;
219
220 //
221 // Fail if the HashType is not SHA 256
222 //
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;
226 goto Done;
227 }
228
229 //
230 // Allocate hash context buffer required for SHA 256
231 //
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;
236 goto Done;
237 }
238
239 //
240 // Hash public key from data payload with SHA256.
241 //
242 ZeroMem (Digest, SHA256_DIGEST_SIZE);
243 CryptoStatus = Sha256Init (HashContext);
244 if (!CryptoStatus) {
245 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Init() failed\n"));
246 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
247 goto Done;
248 }
249 CryptoStatus = Sha256Update (HashContext, &CertBlockRsa2048Sha256->PublicKey, sizeof(CertBlockRsa2048Sha256->PublicKey));
250 if (!CryptoStatus) {
251 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Update() failed\n"));
252 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
253 goto Done;
254 }
255 CryptoStatus = Sha256Final (HashContext, Digest);
256 if (!CryptoStatus) {
257 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Final() failed\n"));
258 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
259 goto Done;
260 }
261
262 //
263 // Fail if the PublicKey is not one of the public keys in PcdRsa2048Sha256PublicKeyBuffer
264 //
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) {
275 CryptoStatus = TRUE;
276 break;
277 }
278 PublicKey = PublicKey + SHA256_DIGEST_SIZE;
279 PublicKeyBufferSize = PublicKeyBufferSize - SHA256_DIGEST_SIZE;
280 }
281 if (!CryptoStatus) {
282 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Public key in section is not supported\n"));
283 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
284 goto Done;
285 }
286
287 //
288 // Generate & Initialize RSA Context.
289 //
290 Rsa = RsaNew ();
291 if (Rsa == NULL) {
292 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaNew() failed\n"));
293 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
294 goto Done;
295 }
296
297 //
298 // Set RSA Key Components.
299 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
300 //
301 CryptoStatus = RsaSetKey (Rsa, RsaKeyN, CertBlockRsa2048Sha256->PublicKey, sizeof(CertBlockRsa2048Sha256->PublicKey));
302 if (!CryptoStatus) {
303 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaSetKey(RsaKeyN) failed\n"));
304 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
305 goto Done;
306 }
307 CryptoStatus = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
308 if (!CryptoStatus) {
309 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaSetKey(RsaKeyE) failed\n"));
310 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
311 goto Done;
312 }
313
314 //
315 // Hash data payload with SHA256.
316 //
317 ZeroMem (Digest, SHA256_DIGEST_SIZE);
318 CryptoStatus = Sha256Init (HashContext);
319 if (!CryptoStatus) {
320 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Init() failed\n"));
321 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
322 goto Done;
323 }
324 PERF_INMODULE_BEGIN ("DxeRsaShaData");
325 CryptoStatus = Sha256Update (HashContext, *OutputBuffer, OutputBufferSize);
326 PERF_INMODULE_END ("DxeRsaShaData");
327 if (!CryptoStatus) {
328 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Update() failed\n"));
329 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
330 goto Done;
331 }
332 CryptoStatus = Sha256Final (HashContext, Digest);
333 if (!CryptoStatus) {
334 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: Sha256Final() failed\n"));
335 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
336 goto Done;
337 }
338
339 //
340 // Verify the RSA 2048 SHA 256 signature.
341 //
342 PERF_INMODULE_BEGIN ("DxeRsaVerify");
343 CryptoStatus = RsaPkcs1Verify (
344 Rsa,
345 Digest,
346 SHA256_DIGEST_SIZE,
347 CertBlockRsa2048Sha256->Signature,
348 sizeof (CertBlockRsa2048Sha256->Signature)
349 );
350 PERF_INMODULE_END ("DxeRsaVerify");
351 if (!CryptoStatus) {
352 //
353 // If RSA 2048 SHA 256 signature verification fails, AUTH tested failed bit is set.
354 //
355 DEBUG ((DEBUG_ERROR, "DxeRsa2048Sha256: RsaPkcs1Verify() failed\n"));
356 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
357 }
358
359 Done:
360 //
361 // Free allocated resources used to perform RSA 2048 SHA 256 signature verification
362 //
363 if (Rsa != NULL) {
364 RsaFree (Rsa);
365 }
366 if (HashContext != NULL) {
367 FreePool (HashContext);
368 }
369
370 DEBUG ((DEBUG_VERBOSE, "DxeRsa2048Sha256: Status = %r AuthenticationStatus = %08x\n", Status, *AuthenticationStatus));
371
372 return Status;
373 }
374
375 /**
376 Register the handler to extract RSA 2048 SHA 256 guided section.
377
378 @param ImageHandle ImageHandle of the loaded driver.
379 @param SystemTable Pointer to the EFI System Table.
380
381 @retval EFI_SUCCESS Register successfully.
382 @retval EFI_OUT_OF_RESOURCES Not enough memory to register this handler.
383 **/
384 EFI_STATUS
385 EFIAPI
386 DxeRsa2048Sha256GuidedSectionExtractLibConstructor (
387 IN EFI_HANDLE ImageHandle,
388 IN EFI_SYSTEM_TABLE *SystemTable
389 )
390 {
391 return ExtractGuidedSectionRegisterHandlers (
392 &gEfiCertTypeRsa2048Sha256Guid,
393 Rsa2048Sha256GuidedSectionGetInfo,
394 Rsa2048Sha256GuidedSectionHandler
395 );
396 }