TianoCore EDK2 master
Loading...
Searching...
No Matches
PeiRsa2048Sha256GuidedSectionExtractLib.c
Go to the documentation of this file.
1
12#include <PiPei.h>
13#include <Protocol/Hash.h>
15#include <Library/DebugLib.h>
18#include <Library/PcdLib.h>
19#include <Guid/WinCertificate.h>
23
27typedef struct {
28 EFI_GUID_DEFINED_SECTION GuidedSectionHeader;
29 EFI_CERT_BLOCK_RSA_2048_SHA256 CertBlockRsa2048Sha256;
31
32typedef struct {
33 EFI_GUID_DEFINED_SECTION2 GuidedSectionHeader;
34 EFI_CERT_BLOCK_RSA_2048_SHA256 CertBlockRsa2048Sha256;
36
40CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
41
59EFIAPI
61 IN CONST VOID *InputSection,
62 OUT UINT32 *OutputBufferSize,
63 OUT UINT32 *ScratchBufferSize,
64 OUT UINT16 *SectionAttribute
65 )
66{
67 if (IS_SECTION2 (InputSection)) {
68 //
69 // Check whether the input guid section is recognized.
70 //
71 if (!CompareGuid (
72 &gEfiCertTypeRsa2048Sha256Guid,
73 &(((EFI_GUID_DEFINED_SECTION2 *)InputSection)->SectionDefinitionGuid)
74 ))
75 {
76 return EFI_INVALID_PARAMETER;
77 }
78
79 //
80 // Retrieve the size and attribute of the input section data.
81 //
82 *SectionAttribute = ((EFI_GUID_DEFINED_SECTION2 *)InputSection)->Attributes;
83 *ScratchBufferSize = 0;
84 *OutputBufferSize = SECTION2_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
85 } else {
86 //
87 // Check whether the input guid section is recognized.
88 //
89 if (!CompareGuid (
90 &gEfiCertTypeRsa2048Sha256Guid,
91 &(((EFI_GUID_DEFINED_SECTION *)InputSection)->SectionDefinitionGuid)
92 ))
93 {
94 return EFI_INVALID_PARAMETER;
95 }
96
97 //
98 // Retrieve the size and attribute of the input section data.
99 //
100 *SectionAttribute = ((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes;
101 *ScratchBufferSize = 0;
102 *OutputBufferSize = SECTION_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION_HEADER);
103 }
104
105 return EFI_SUCCESS;
106}
107
126EFIAPI
128 IN CONST VOID *InputSection,
129 OUT VOID **OutputBuffer,
130 IN VOID *ScratchBuffer OPTIONAL,
131 OUT UINT32 *AuthenticationStatus
132 )
133{
134 EFI_STATUS Status;
135 UINT32 OutputBufferSize;
136 EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlockRsa2048Sha256;
137 BOOLEAN CryptoStatus;
138 UINT8 Digest[SHA256_DIGEST_SIZE];
139 UINT8 *PublicKey;
140 UINTN PublicKeyBufferSize;
141 VOID *HashContext;
142 VOID *Rsa;
143
144 HashContext = NULL;
145 Rsa = NULL;
146
147 if (IS_SECTION2 (InputSection)) {
148 //
149 // Check whether the input guid section is recognized.
150 //
151 if (!CompareGuid (
152 &gEfiCertTypeRsa2048Sha256Guid,
153 &(((EFI_GUID_DEFINED_SECTION2 *)InputSection)->SectionDefinitionGuid)
154 ))
155 {
156 return EFI_INVALID_PARAMETER;
157 }
158
159 //
160 // Get the RSA 2048 SHA 256 information.
161 //
162 CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION2_HEADER *)InputSection)->CertBlockRsa2048Sha256;
163 OutputBufferSize = SECTION2_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
164 if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
165 PERF_INMODULE_BEGIN ("PeiRsaCopy");
166 CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER), OutputBufferSize);
167 PERF_INMODULE_END ("PeiRsaCopy");
168 } else {
169 *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION2_HEADER);
170 }
171
172 //
173 // Implicitly RSA 2048 SHA 256 GUIDed section should have STATUS_VALID bit set
174 //
175 ASSERT ((((EFI_GUID_DEFINED_SECTION2 *)InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0);
176 *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
177 } else {
178 //
179 // Check whether the input guid section is recognized.
180 //
181 if (!CompareGuid (
182 &gEfiCertTypeRsa2048Sha256Guid,
183 &(((EFI_GUID_DEFINED_SECTION *)InputSection)->SectionDefinitionGuid)
184 ))
185 {
186 return EFI_INVALID_PARAMETER;
187 }
188
189 //
190 // Get the RSA 2048 SHA 256 information.
191 //
192 CertBlockRsa2048Sha256 = &((RSA_2048_SHA_256_SECTION_HEADER *)InputSection)->CertBlockRsa2048Sha256;
193 OutputBufferSize = SECTION_SIZE (InputSection) - sizeof (RSA_2048_SHA_256_SECTION_HEADER);
194 if ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
195 PERF_INMODULE_BEGIN ("PeiRsaCopy");
196 CopyMem (*OutputBuffer, (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER), OutputBufferSize);
197 PERF_INMODULE_END ("PeiRsaCopy");
198 } else {
199 *OutputBuffer = (UINT8 *)InputSection + sizeof (RSA_2048_SHA_256_SECTION_HEADER);
200 }
201
202 //
203 // Implicitly RSA 2048 SHA 256 GUIDed section should have STATUS_VALID bit set
204 //
205 ASSERT ((((EFI_GUID_DEFINED_SECTION *)InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0);
206 *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
207 }
208
209 //
210 // All paths from here return EFI_SUCCESS and result is returned in AuthenticationStatus
211 //
212 Status = EFI_SUCCESS;
213
214 //
215 // Fail if the HashType is not SHA 256
216 //
217 if (!CompareGuid (&gEfiHashAlgorithmSha256Guid, &CertBlockRsa2048Sha256->HashType)) {
218 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: HASH type of section is not supported\n"));
219 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
220 goto Done;
221 }
222
223 //
224 // Allocate hash context buffer required for SHA 256
225 //
226 HashContext = AllocatePool (Sha256GetContextSize ());
227 if (HashContext == NULL) {
228 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Can not allocate hash context\n"));
229 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
230 goto Done;
231 }
232
233 //
234 // Hash public key from data payload with SHA256.
235 //
236 ZeroMem (Digest, SHA256_DIGEST_SIZE);
237 CryptoStatus = Sha256Init (HashContext);
238 if (!CryptoStatus) {
239 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Sha256Init() failed\n"));
240 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
241 goto Done;
242 }
243
244 CryptoStatus = Sha256Update (HashContext, &CertBlockRsa2048Sha256->PublicKey, sizeof (CertBlockRsa2048Sha256->PublicKey));
245 if (!CryptoStatus) {
246 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Sha256Update() failed\n"));
247 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
248 goto Done;
249 }
250
251 CryptoStatus = Sha256Final (HashContext, Digest);
252 if (!CryptoStatus) {
253 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Sha256Final() failed\n"));
254 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
255 goto Done;
256 }
257
258 //
259 // Fail if the PublicKey is not one of the public keys in PcdRsa2048Sha256PublicKeyBuffer
260 //
261 PublicKey = (UINT8 *)PcdGetPtr (PcdRsa2048Sha256PublicKeyBuffer);
262 DEBUG ((DEBUG_VERBOSE, "PeiPcdRsa2048Sha256: PublicKeyBuffer = %p\n", PublicKey));
263 ASSERT (PublicKey != NULL);
264 DEBUG ((DEBUG_VERBOSE, "PeiPcdRsa2048Sha256: PublicKeyBuffer Token = %08x\n", PcdToken (PcdRsa2048Sha256PublicKeyBuffer)));
265 PublicKeyBufferSize = PcdGetSize (PcdRsa2048Sha256PublicKeyBuffer);
266 DEBUG ((DEBUG_VERBOSE, "PeiPcdRsa2048Sha256: PublicKeyBuffer Size = %08x\n", PublicKeyBufferSize));
267 ASSERT ((PublicKeyBufferSize % SHA256_DIGEST_SIZE) == 0);
268 CryptoStatus = FALSE;
269 while (PublicKeyBufferSize != 0) {
270 if (CompareMem (Digest, PublicKey, SHA256_DIGEST_SIZE) == 0) {
271 CryptoStatus = TRUE;
272 break;
273 }
274
275 PublicKey = PublicKey + SHA256_DIGEST_SIZE;
276 PublicKeyBufferSize = PublicKeyBufferSize - SHA256_DIGEST_SIZE;
277 }
278
279 if (!CryptoStatus) {
280 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Public key in section is not supported\n"));
281 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
282 goto Done;
283 }
284
285 //
286 // Generate & Initialize RSA Context.
287 //
288 Rsa = RsaNew ();
289 if (Rsa == NULL) {
290 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: RsaNew() failed\n"));
291 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
292 goto Done;
293 }
294
295 //
296 // Set RSA Key Components.
297 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
298 //
299 CryptoStatus = RsaSetKey (Rsa, RsaKeyN, CertBlockRsa2048Sha256->PublicKey, sizeof (CertBlockRsa2048Sha256->PublicKey));
300 if (!CryptoStatus) {
301 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: RsaSetKey(RsaKeyN) failed\n"));
302 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
303 goto Done;
304 }
305
306 CryptoStatus = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
307 if (!CryptoStatus) {
308 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: RsaSetKey(RsaKeyE) failed\n"));
309 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
310 goto Done;
311 }
312
313 //
314 // Hash data payload with SHA256.
315 //
316 ZeroMem (Digest, SHA256_DIGEST_SIZE);
317 CryptoStatus = Sha256Init (HashContext);
318 if (!CryptoStatus) {
319 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Sha256Init() failed\n"));
320 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
321 goto Done;
322 }
323
324 PERF_INMODULE_BEGIN ("PeiRsaShaData");
325 CryptoStatus = Sha256Update (HashContext, *OutputBuffer, OutputBufferSize);
326 PERF_INMODULE_END ("PeiRsaShaData");
327 if (!CryptoStatus) {
328 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Sha256Update() failed\n"));
329 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
330 goto Done;
331 }
332
333 CryptoStatus = Sha256Final (HashContext, Digest);
334 if (!CryptoStatus) {
335 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: Sha256Final() failed\n"));
336 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
337 goto Done;
338 }
339
340 //
341 // Verify the RSA 2048 SHA 256 signature.
342 //
343 PERF_INMODULE_BEGIN ("PeiRsaVerify");
344 CryptoStatus = RsaPkcs1Verify (
345 Rsa,
346 Digest,
348 CertBlockRsa2048Sha256->Signature,
349 sizeof (CertBlockRsa2048Sha256->Signature)
350 );
351 PERF_INMODULE_END ("PeiRsaVerify");
352 if (!CryptoStatus) {
353 //
354 // If RSA 2048 SHA 256 signature verification fails, AUTH tested failed bit is set.
355 //
356 DEBUG ((DEBUG_ERROR, "PeiRsa2048Sha256: RsaPkcs1Verify() failed\n"));
357 *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
358 }
359
360Done:
361 //
362 // Free allocated resources used to perform RSA 2048 SHA 256 signature verification
363 //
364 if (Rsa != NULL) {
365 RsaFree (Rsa);
366 }
367
368 if (HashContext != NULL) {
369 FreePool (HashContext);
370 }
371
372 DEBUG ((DEBUG_VERBOSE, "PeiRsa2048Sha256: Status = %r AuthenticationStatus = %08x\n", Status, *AuthenticationStatus));
373
374 return Status;
375}
376
388EFIAPI
390 IN EFI_PEI_FILE_HANDLE FileHandle,
391 IN CONST EFI_PEI_SERVICES **PeiServices
392 )
393{
395 &gEfiCertTypeRsa2048Sha256Guid,
398 );
399}
UINT64 UINTN
@ RsaKeyN
RSA public Modulus (N)
Definition: BaseCryptLib.h:75
@ RsaKeyE
RSA Public exponent (e)
Definition: BaseCryptLib.h:76
UINTN EFIAPI Sha256GetContextSize(VOID)
Definition: CryptSha256.c:20
VOID *EFIAPI RsaNew(VOID)
Definition: CryptRsaBasic.c:30
BOOLEAN EFIAPI Sha256Init(OUT VOID *Sha256Context)
Definition: CryptSha256.c:44
BOOLEAN EFIAPI Sha256Final(IN OUT VOID *Sha256Context, OUT UINT8 *HashValue)
Definition: CryptSha256.c:161
#define SHA256_DIGEST_SIZE
Definition: BaseCryptLib.h:44
BOOLEAN EFIAPI RsaSetKey(IN OUT VOID *RsaContext, IN RSA_KEY_TAG KeyTag, IN CONST UINT8 *BigNumber, IN UINTN BnSize)
Definition: CryptRsaBasic.c:82
BOOLEAN EFIAPI Sha256Update(IN OUT VOID *Sha256Context, IN CONST VOID *Data, IN UINTN DataSize)
Definition: CryptSha256.c:113
VOID EFIAPI RsaFree(IN VOID *RsaContext)
Definition: CryptRsaBasic.c:48
BOOLEAN EFIAPI RsaPkcs1Verify(IN VOID *RsaContext, IN CONST UINT8 *MessageHash, IN UINTN HashSize, IN CONST UINT8 *Signature, IN UINTN SigSize)
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGetSize(TokenName)
Definition: PcdLib.h:440
#define PcdToken(TokenName)
Definition: PcdLib.h:36
#define PcdGetPtr(TokenName)
Definition: PcdLib.h:388
EFI_STATUS EFIAPI PeiRsa2048Sha256GuidedSectionExtractLibConstructor(IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices)
EFI_STATUS EFIAPI Rsa2048Sha256GuidedSectionGetInfo(IN CONST VOID *InputSection, OUT UINT32 *OutputBufferSize, OUT UINT32 *ScratchBufferSize, OUT UINT16 *SectionAttribute)
EFI_STATUS EFIAPI Rsa2048Sha256GuidedSectionHandler(IN CONST VOID *InputSection, OUT VOID **OutputBuffer, IN VOID *ScratchBuffer OPTIONAL, OUT UINT32 *AuthenticationStatus)
#define PERF_INMODULE_BEGIN(MeasurementString)
#define PERF_INMODULE_END(MeasurementString)
#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED
#define SECTION_SIZE(SectionHeaderPtr)
VOID * EFI_PEI_FILE_HANDLE
Definition: PiPeiCis.h:26
RETURN_STATUS EFIAPI ExtractGuidedSectionRegisterHandlers(IN CONST GUID *SectionGuid, IN EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER GetInfoHandler, IN EXTRACT_GUIDED_SECTION_DECODE_HANDLER DecodeHandler)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112