]> git.proxmox.com Git - mirror_edk2.git/blob - SignedCapsulePkg/Library/EdkiiSystemCapsuleLib/EdkiiSystemCapsuleLib.c
SignedCapsulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / SignedCapsulePkg / Library / EdkiiSystemCapsuleLib / EdkiiSystemCapsuleLib.c
1 /** @file
2 EDKII System Capsule library.
3
4 EDKII System Capsule library instance.
5
6 CapsuleAuthenticateSystemFirmware(), ExtractAuthenticatedImage() will receive
7 untrusted input and do basic validation.
8
9 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
10 SPDX-License-Identifier: BSD-2-Clause-Patent
11
12 **/
13
14 #include <PiDxe.h>
15
16 #include <Guid/SystemResourceTable.h>
17 #include <Guid/FirmwareContentsSigned.h>
18 #include <Guid/WinCertificate.h>
19 #include <Guid/EdkiiSystemFmpCapsule.h>
20 #include <Guid/WinCertificate.h>
21 #include <Guid/ImageAuthentication.h>
22
23 #include <Library/BaseLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/PcdLib.h>
27 #include <Library/MemoryAllocationLib.h>
28 #include <Library/EdkiiSystemCapsuleLib.h>
29 #include <Library/FmpAuthenticationLib.h>
30
31 #include <Protocol/FirmwareManagement.h>
32
33 EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *mImageFmpInfo;
34 UINTN mImageFmpInfoSize;
35 EFI_GUID mEdkiiSystemFirmwareFileGuid;
36
37 /**
38 Check if a block of buffer is erased.
39
40 @param[in] ErasePolarity Erase polarity attribute of the firmware volume
41 @param[in] InBuffer The buffer to be checked
42 @param[in] BufferSize Size of the buffer in bytes
43
44 @retval TRUE The block of buffer is erased
45 @retval FALSE The block of buffer is not erased
46 **/
47 BOOLEAN
48 IsBufferErased (
49 IN UINT8 ErasePolarity,
50 IN VOID *InBuffer,
51 IN UINTN BufferSize
52 )
53 {
54 UINTN Count;
55 UINT8 EraseByte;
56 UINT8 *Buffer;
57
58 if(ErasePolarity == 1) {
59 EraseByte = 0xFF;
60 } else {
61 EraseByte = 0;
62 }
63
64 Buffer = InBuffer;
65 for (Count = 0; Count < BufferSize; Count++) {
66 if (Buffer[Count] != EraseByte) {
67 return FALSE;
68 }
69 }
70
71 return TRUE;
72 }
73
74 /**
75 Get Section buffer pointer by SectionType and SectionInstance.
76
77 @param[in] SectionBuffer The buffer of section
78 @param[in] SectionBufferSize The size of SectionBuffer in bytes
79 @param[in] SectionType The SectionType of Section to be found
80 @param[in] SectionInstance The Instance of Section to be found
81 @param[out] OutSectionBuffer The section found, including SECTION_HEADER
82 @param[out] OutSectionSize The size of section found, including SECTION_HEADER
83
84 @retval TRUE The FFS buffer is found.
85 @retval FALSE The FFS buffer is not found.
86 **/
87 BOOLEAN
88 GetSectionByType (
89 IN VOID *SectionBuffer,
90 IN UINT32 SectionBufferSize,
91 IN EFI_SECTION_TYPE SectionType,
92 IN UINTN SectionInstance,
93 OUT VOID **OutSectionBuffer,
94 OUT UINTN *OutSectionSize
95 )
96 {
97 EFI_COMMON_SECTION_HEADER *SectionHeader;
98 UINTN SectionSize;
99 UINTN Instance;
100
101 DEBUG ((DEBUG_INFO, "GetSectionByType - Buffer: 0x%08x - 0x%08x\n", SectionBuffer, SectionBufferSize));
102
103 //
104 // Find Section
105 //
106 SectionHeader = SectionBuffer;
107
108 Instance = 0;
109 while ((UINTN)SectionHeader < (UINTN)SectionBuffer + SectionBufferSize) {
110 DEBUG ((DEBUG_INFO, "GetSectionByType - Section: 0x%08x\n", SectionHeader));
111 if (IS_SECTION2(SectionHeader)) {
112 SectionSize = SECTION2_SIZE(SectionHeader);
113 } else {
114 SectionSize = SECTION_SIZE(SectionHeader);
115 }
116
117 if (SectionHeader->Type == SectionType) {
118 if (Instance == SectionInstance) {
119 *OutSectionBuffer = (UINT8 *)SectionHeader;
120 *OutSectionSize = SectionSize;
121 DEBUG((DEBUG_INFO, "GetSectionByType - 0x%x - 0x%x\n", *OutSectionBuffer, *OutSectionSize));
122 return TRUE;
123 } else {
124 DEBUG((DEBUG_INFO, "GetSectionByType - find section instance %x\n", Instance));
125 Instance++;
126 }
127 } else {
128 //
129 // Skip other section type
130 //
131 DEBUG ((DEBUG_INFO, "GetSectionByType - other section type 0x%x\n", SectionHeader->Type));
132 }
133
134 //
135 // Next Section
136 //
137 SectionHeader = (EFI_COMMON_SECTION_HEADER *)((UINTN)SectionHeader + ALIGN_VALUE(SectionSize, 4));
138 }
139
140 return FALSE;
141 }
142
143 /**
144 Get FFS buffer pointer by FileName GUID and FileType.
145
146 @param[in] FdStart The System Firmware FD image
147 @param[in] FdSize The size of System Firmware FD image
148 @param[in] FileName The FileName GUID of FFS to be found
149 @param[in] Type The FileType of FFS to be found
150 @param[out] OutFfsBuffer The FFS buffer found, including FFS_FILE_HEADER
151 @param[out] OutFfsBufferSize The size of FFS buffer found, including FFS_FILE_HEADER
152
153 @retval TRUE The FFS buffer is found.
154 @retval FALSE The FFS buffer is not found.
155 **/
156 BOOLEAN
157 GetFfsByName (
158 IN VOID *FdStart,
159 IN UINTN FdSize,
160 IN EFI_GUID *FileName,
161 IN EFI_FV_FILETYPE Type,
162 OUT VOID **OutFfsBuffer,
163 OUT UINTN *OutFfsBufferSize
164 )
165 {
166 UINTN FvSize;
167 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
168 EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;
169 EFI_FFS_FILE_HEADER *FfsHeader;
170 UINT32 FfsSize;
171 UINTN TestLength;
172 BOOLEAN FvFound;
173
174 DEBUG ((DEBUG_INFO, "GetFfsByName - FV: 0x%08x - 0x%08x\n", (UINTN)FdStart, (UINTN)FdSize));
175
176 FvFound = FALSE;
177 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FdStart;
178 while ((UINTN)FvHeader < (UINTN)FdStart + FdSize - 1) {
179 FvSize = (UINTN)FdStart + FdSize - (UINTN)FvHeader;
180
181 if (FvHeader->Signature != EFI_FVH_SIGNATURE) {
182 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvHeader + SIZE_4KB);
183 continue;
184 }
185 DEBUG((DEBUG_INFO, "checking FV....0x%08x - 0x%x\n", FvHeader, FvHeader->FvLength));
186 FvFound = TRUE;
187 if (FvHeader->FvLength > FvSize) {
188 DEBUG((DEBUG_ERROR, "GetFfsByName - FvSize: 0x%08x, MaxSize - 0x%08x\n", (UINTN)FvHeader->FvLength, (UINTN)FvSize));
189 return FALSE;
190 }
191 FvSize = (UINTN)FvHeader->FvLength;
192
193 //
194 // Find FFS
195 //
196 if (FvHeader->ExtHeaderOffset != 0) {
197 FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FvHeader + FvHeader->ExtHeaderOffset);
198 FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FvExtHeader + FvExtHeader->ExtHeaderSize);
199 } else {
200 FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FvHeader + FvHeader->HeaderLength);
201 }
202 FfsHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FvHeader + ALIGN_VALUE((UINTN)FfsHeader - (UINTN)FvHeader, 8));
203
204 while ((UINTN)FfsHeader < (UINTN)FvHeader + FvSize - 1) {
205 DEBUG((DEBUG_INFO, "GetFfsByName - FFS: 0x%08x\n", FfsHeader));
206 TestLength = (UINTN)((UINTN)FvHeader + FvSize - (UINTN)FfsHeader);
207 if (TestLength > sizeof(EFI_FFS_FILE_HEADER)) {
208 TestLength = sizeof(EFI_FFS_FILE_HEADER);
209 }
210 if (IsBufferErased(1, FfsHeader, TestLength)) {
211 break;
212 }
213
214 if (IS_FFS_FILE2(FfsHeader)) {
215 FfsSize = FFS_FILE2_SIZE(FfsHeader);
216 } else {
217 FfsSize = FFS_FILE_SIZE(FfsHeader);
218 }
219
220 if (CompareGuid(FileName, &FfsHeader->Name) &&
221 ((Type == EFI_FV_FILETYPE_ALL) || (FfsHeader->Type == Type))) {
222 *OutFfsBuffer = FfsHeader;
223 *OutFfsBufferSize = FfsSize;
224 return TRUE;
225 } else {
226 //
227 // Any other type is not allowed
228 //
229 DEBUG((DEBUG_INFO, "GetFfsByName - other FFS type 0x%x, name %g\n", FfsHeader->Type, &FfsHeader->Name));
230 }
231
232 //
233 // Next File
234 //
235 FfsHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FfsHeader + ALIGN_VALUE(FfsSize, 8));
236 }
237
238 //
239 // Next FV
240 //
241 FvHeader = (VOID *)(UINTN)((UINTN)FvHeader + FvHeader->FvLength);
242 }
243
244 if (!FvFound) {
245 DEBUG((DEBUG_ERROR, "GetFfsByName - NO FV Found\n"));
246 }
247 return FALSE;
248 }
249
250 /**
251 Extract the driver FV from an authenticated image.
252
253 @param[in] AuthenticatedImage The authenticated capsule image.
254 @param[in] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
255 @param[out] DriverFvImage The driver FV image.
256 @param[out] DriverFvImageSize The size of the driver FV image in bytes.
257
258 @retval TRUE The driver Fv is extracted.
259 @retval FALSE The driver Fv is not extracted.
260 **/
261 BOOLEAN
262 EFIAPI
263 ExtractDriverFvImage (
264 IN VOID *AuthenticatedImage,
265 IN UINTN AuthenticatedImageSize,
266 OUT VOID **DriverFvImage,
267 OUT UINTN *DriverFvImageSize
268 )
269 {
270 BOOLEAN Result;
271 UINT32 FileHeaderSize;
272
273 *DriverFvImage = NULL;
274 *DriverFvImageSize = 0;
275
276 Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &gEdkiiSystemFmpCapsuleDriverFvFileGuid, EFI_FV_FILETYPE_RAW, DriverFvImage, DriverFvImageSize);
277 if (!Result) {
278 return FALSE;
279 }
280
281 if (IS_FFS_FILE2(*DriverFvImage)) {
282 FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
283 } else {
284 FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
285 }
286 *DriverFvImage = (UINT8 *)*DriverFvImage + FileHeaderSize;
287 *DriverFvImageSize = *DriverFvImageSize - FileHeaderSize;
288
289 return Result;
290 }
291
292 /**
293 Extract the config image from an authenticated image.
294
295 @param[in] AuthenticatedImage The authenticated capsule image.
296 @param[in] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
297 @param[out] ConfigImage The config image.
298 @param[out] ConfigImageSize The size of the config image in bytes.
299
300 @retval TRUE The config image is extracted.
301 @retval FALSE The config image is not extracted.
302 **/
303 BOOLEAN
304 EFIAPI
305 ExtractConfigImage (
306 IN VOID *AuthenticatedImage,
307 IN UINTN AuthenticatedImageSize,
308 OUT VOID **ConfigImage,
309 OUT UINTN *ConfigImageSize
310 )
311 {
312 BOOLEAN Result;
313 UINT32 FileHeaderSize;
314
315 *ConfigImage = NULL;
316 *ConfigImageSize = 0;
317
318 Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &gEdkiiSystemFmpCapsuleConfigFileGuid, EFI_FV_FILETYPE_RAW, ConfigImage, ConfigImageSize);
319 if (!Result) {
320 return FALSE;
321 }
322
323 if (IS_FFS_FILE2(*ConfigImage)) {
324 FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
325 } else {
326 FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
327 }
328 *ConfigImage = (UINT8 *)*ConfigImage + FileHeaderSize;
329 *ConfigImageSize = *ConfigImageSize - FileHeaderSize;
330
331 return Result;
332 }
333
334 /**
335 Extract the authenticated image from an FMP capsule image.
336
337 Caution: This function may receive untrusted input.
338
339 @param[in] Image The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
340 @param[in] ImageSize The size of FMP capsule image in bytes.
341 @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
342 @param[out] AuthenticatedImage The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
343 @param[out] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
344
345 @retval TRUE The authenticated image is extracted.
346 @retval FALSE The authenticated image is not extracted.
347 **/
348 BOOLEAN
349 EFIAPI
350 ExtractAuthenticatedImage (
351 IN VOID *Image,
352 IN UINTN ImageSize,
353 OUT UINT32 *LastAttemptStatus,
354 OUT VOID **AuthenticatedImage,
355 OUT UINTN *AuthenticatedImageSize
356 )
357 {
358 EFI_FIRMWARE_IMAGE_AUTHENTICATION *ImageAuth;
359 EFI_STATUS Status;
360 GUID *CertType;
361 VOID *PublicKeyData;
362 UINTN PublicKeyDataLength;
363
364 DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - Image: 0x%08x - 0x%08x\n", (UINTN)Image, (UINTN)ImageSize));
365
366 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
367 if ((Image == NULL) || (ImageSize == 0)) {
368 return FALSE;
369 }
370
371 ImageAuth = (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image;
372 if (ImageSize < sizeof(EFI_FIRMWARE_IMAGE_AUTHENTICATION)) {
373 DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - ImageSize too small\n"));
374 return FALSE;
375 }
376 if (ImageAuth->AuthInfo.Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {
377 DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - dwLength too small\n"));
378 return FALSE;
379 }
380 if ((UINTN) ImageAuth->AuthInfo.Hdr.dwLength > MAX_UINTN - sizeof(UINT64)) {
381 DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - dwLength too big\n"));
382 return FALSE;
383 }
384 if (ImageSize <= sizeof(ImageAuth->MonotonicCount) + ImageAuth->AuthInfo.Hdr.dwLength) {
385 DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - ImageSize too small\n"));
386 return FALSE;
387 }
388 if (ImageAuth->AuthInfo.Hdr.wRevision != 0x0200) {
389 DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - wRevision: 0x%02x, expect - 0x%02x\n", (UINTN)ImageAuth->AuthInfo.Hdr.wRevision, (UINTN)0x0200));
390 return FALSE;
391 }
392 if (ImageAuth->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) {
393 DEBUG((DEBUG_ERROR, "ExtractAuthenticatedImage - wCertificateType: 0x%02x, expect - 0x%02x\n", (UINTN)ImageAuth->AuthInfo.Hdr.wCertificateType, (UINTN)WIN_CERT_TYPE_EFI_GUID));
394 return FALSE;
395 }
396
397 CertType = &ImageAuth->AuthInfo.CertType;
398 DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - CertType: %g\n", CertType));
399
400 if (CompareGuid(&gEfiCertPkcs7Guid, CertType)) {
401 PublicKeyData = PcdGetPtr(PcdPkcs7CertBuffer);
402 PublicKeyDataLength = PcdGetSize(PcdPkcs7CertBuffer);
403 } else if (CompareGuid(&gEfiCertTypeRsa2048Sha256Guid, CertType)) {
404 PublicKeyData = PcdGetPtr(PcdRsa2048Sha256PublicKeyBuffer);
405 PublicKeyDataLength = PcdGetSize(PcdRsa2048Sha256PublicKeyBuffer);
406 } else {
407 return FALSE;
408 }
409 ASSERT (PublicKeyData != NULL);
410 ASSERT (PublicKeyDataLength != 0);
411
412 Status = AuthenticateFmpImage(
413 ImageAuth,
414 ImageSize,
415 PublicKeyData,
416 PublicKeyDataLength
417 );
418 switch (Status) {
419 case RETURN_SUCCESS:
420 *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
421 break;
422 case RETURN_SECURITY_VIOLATION:
423 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
424 break;
425 case RETURN_INVALID_PARAMETER:
426 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
427 break;
428 case RETURN_UNSUPPORTED:
429 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
430 break;
431 case RETURN_OUT_OF_RESOURCES:
432 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES;
433 break;
434 default:
435 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
436 break;
437 }
438 if (EFI_ERROR(Status)) {
439 return FALSE;
440 }
441
442 if (AuthenticatedImage != NULL) {
443 *AuthenticatedImage = (UINT8 *)ImageAuth + ImageAuth->AuthInfo.Hdr.dwLength + sizeof(ImageAuth->MonotonicCount);
444 }
445 if (AuthenticatedImageSize != NULL) {
446 *AuthenticatedImageSize = ImageSize - ImageAuth->AuthInfo.Hdr.dwLength - sizeof(ImageAuth->MonotonicCount);
447 }
448 return TRUE;
449 }
450
451 /**
452 Extract ImageFmpInfo from system firmware.
453
454 @param[in] SystemFirmwareImage The System Firmware image.
455 @param[in] SystemFirmwareImageSize The size of the System Firmware image in bytes.
456 @param[out] ImageFmpInfo The ImageFmpInfo.
457 @param[out] ImageFmpInfoSize The size of the ImageFmpInfo in bytes.
458
459 @retval TRUE The ImageFmpInfo is extracted.
460 @retval FALSE The ImageFmpInfo is not extracted.
461 **/
462 BOOLEAN
463 EFIAPI
464 ExtractSystemFirmwareImageFmpInfo (
465 IN VOID *SystemFirmwareImage,
466 IN UINTN SystemFirmwareImageSize,
467 OUT EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR **ImageFmpInfo,
468 OUT UINTN *ImageFmpInfoSize
469 )
470 {
471 BOOLEAN Result;
472 UINT32 SectionHeaderSize;
473 UINT32 FileHeaderSize;
474
475 *ImageFmpInfo = NULL;
476 *ImageFmpInfoSize = 0;
477
478 Result = GetFfsByName(SystemFirmwareImage, SystemFirmwareImageSize, &gEdkiiSystemFirmwareImageDescriptorFileGuid, EFI_FV_FILETYPE_ALL, (VOID **)ImageFmpInfo, ImageFmpInfoSize);
479 if (!Result) {
480 return FALSE;
481 }
482 if (IS_FFS_FILE2 (*ImageFmpInfo)) {
483 FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
484 } else {
485 FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
486 }
487 *ImageFmpInfo = (VOID *)((UINT8 *)*ImageFmpInfo + FileHeaderSize);
488 *ImageFmpInfoSize = *ImageFmpInfoSize - FileHeaderSize;
489
490 Result = GetSectionByType(*ImageFmpInfo, (UINT32)*ImageFmpInfoSize, EFI_SECTION_RAW, 0, (VOID **)ImageFmpInfo, ImageFmpInfoSize);
491 if (!Result) {
492 return FALSE;
493 }
494 if (IS_SECTION2(*ImageFmpInfo)) {
495 SectionHeaderSize = sizeof(EFI_RAW_SECTION2);
496 } else {
497 SectionHeaderSize = sizeof(EFI_RAW_SECTION);
498 }
499 *ImageFmpInfo = (VOID *)((UINT8 *)*ImageFmpInfo + SectionHeaderSize);
500 *ImageFmpInfoSize = *ImageFmpInfoSize - SectionHeaderSize;
501
502 return TRUE;
503 }
504
505 /**
506 Extract the System Firmware image from an authenticated image.
507
508 @param[in] AuthenticatedImage The authenticated capsule image.
509 @param[in] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
510 @param[out] SystemFirmwareImage The System Firmware image.
511 @param[out] SystemFirmwareImageSize The size of the System Firmware image in bytes.
512
513 @retval TRUE The System Firmware image is extracted.
514 @retval FALSE The System Firmware image is not extracted.
515 **/
516 BOOLEAN
517 EFIAPI
518 ExtractSystemFirmwareImage (
519 IN VOID *AuthenticatedImage,
520 IN UINTN AuthenticatedImageSize,
521 OUT VOID **SystemFirmwareImage,
522 OUT UINTN *SystemFirmwareImageSize
523 )
524 {
525 BOOLEAN Result;
526 UINT32 FileHeaderSize;
527
528 *SystemFirmwareImage = NULL;
529 *SystemFirmwareImageSize = 0;
530
531 Result = GetFfsByName(AuthenticatedImage, AuthenticatedImageSize, &mEdkiiSystemFirmwareFileGuid, EFI_FV_FILETYPE_RAW, SystemFirmwareImage, SystemFirmwareImageSize);
532 if (!Result) {
533 // no nested FV, just return all data.
534 *SystemFirmwareImage = AuthenticatedImage;
535 *SystemFirmwareImageSize = AuthenticatedImageSize;
536
537 return TRUE;
538 }
539 if (IS_FFS_FILE2 (*SystemFirmwareImage)) {
540 FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
541 } else {
542 FileHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
543 }
544 *SystemFirmwareImage = (UINT8 *)*SystemFirmwareImage + FileHeaderSize;
545 *SystemFirmwareImageSize = *SystemFirmwareImageSize - FileHeaderSize;
546
547 return Result;
548 }
549
550 /**
551 Authenticated system firmware FMP capsule image.
552
553 Caution: This function may receive untrusted input.
554
555 @param[in] Image The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
556 @param[in] ImageSize The size of FMP capsule image in bytes.
557 @param[in] ForceVersionMatch TRUE: The version of capsule must be as same as the version of current image.
558 FALSE: The version of capsule must be as same as greater than the lowest
559 supported version of current image.
560 @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
561 @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
562 @param[out] AuthenticatedImage The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
563 @param[out] AuthenticatedImageSize The size of the authenticated capsule image in bytes.
564
565 @retval TRUE Authentication passes and the authenticated image is extracted.
566 @retval FALSE Authentication fails and the authenticated image is not extracted.
567 **/
568 EFI_STATUS
569 EFIAPI
570 CapsuleAuthenticateSystemFirmware (
571 IN VOID *Image,
572 IN UINTN ImageSize,
573 IN BOOLEAN ForceVersionMatch,
574 OUT UINT32 *LastAttemptVersion,
575 OUT UINT32 *LastAttemptStatus,
576 OUT VOID **AuthenticatedImage,
577 OUT UINTN *AuthenticatedImageSize
578 )
579 {
580 BOOLEAN Result;
581 EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageFmpInfo;
582 UINTN ImageFmpInfoSize;
583 EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageFmpInfo;
584 UINTN CurrentImageFmpInfoSize;
585 VOID *SystemFirmwareImage;
586 UINTN SystemFirmwareImageSize;
587
588 *LastAttemptVersion = 0;
589
590 //
591 // NOTE: This function need run in an isolated environment.
592 // Do not touch FMP protocol and its private structure.
593 //
594 if (mImageFmpInfo == NULL) {
595 DEBUG((DEBUG_INFO, "ImageFmpInfo is not set\n"));
596 return EFI_SECURITY_VIOLATION;
597 }
598
599 Result = ExtractAuthenticatedImage((VOID *)Image, ImageSize, LastAttemptStatus, AuthenticatedImage, AuthenticatedImageSize);
600 if (!Result) {
601 DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - fail\n"));
602 return EFI_SECURITY_VIOLATION;
603 }
604
605 DEBUG((DEBUG_INFO, "AuthenticatedImage - 0x%x - 0x%x\n", *AuthenticatedImage, *AuthenticatedImageSize));
606
607 Result = ExtractSystemFirmwareImage(*AuthenticatedImage, *AuthenticatedImageSize, &SystemFirmwareImage, &SystemFirmwareImageSize);
608 if (!Result) {
609 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
610 DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImage - fail\n"));
611 return EFI_SECURITY_VIOLATION;
612 }
613 DEBUG((DEBUG_INFO, "SystemFirmwareImage - 0x%x - 0x%x\n", SystemFirmwareImage, SystemFirmwareImageSize));
614
615 Result = ExtractSystemFirmwareImageFmpInfo(SystemFirmwareImage, SystemFirmwareImageSize, &ImageFmpInfo, &ImageFmpInfoSize);
616 if (!Result) {
617 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
618 DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImageFmpInfo - fail\n"));
619 return EFI_SECURITY_VIOLATION;
620 }
621
622 *LastAttemptVersion = ImageFmpInfo->Version;
623 DEBUG((DEBUG_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", ImageFmpInfo, ImageFmpInfoSize));
624 DEBUG((DEBUG_INFO, "NewImage Version - 0x%x\n", ImageFmpInfo->Version));
625 DEBUG((DEBUG_INFO, "NewImage LowestSupportedImageVersion - 0x%x\n", ImageFmpInfo->LowestSupportedImageVersion));
626
627 CurrentImageFmpInfo = mImageFmpInfo;
628 CurrentImageFmpInfoSize = mImageFmpInfoSize;
629
630 DEBUG((DEBUG_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", CurrentImageFmpInfo, CurrentImageFmpInfoSize));
631 DEBUG((DEBUG_INFO, "Current Version - 0x%x\n", CurrentImageFmpInfo->Version));
632 DEBUG((DEBUG_INFO, "Current LowestSupportedImageVersion - 0x%x\n", CurrentImageFmpInfo->LowestSupportedImageVersion));
633
634 if (ForceVersionMatch) {
635 if (CurrentImageFmpInfo->Version != ImageFmpInfo->Version) {
636 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
637 DEBUG((DEBUG_INFO, "ForceVersionMatch check - fail\n"));
638 return EFI_SECURITY_VIOLATION;
639 }
640 } else {
641 if (ImageFmpInfo->Version < CurrentImageFmpInfo->LowestSupportedImageVersion) {
642 *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
643 DEBUG((DEBUG_INFO, "LowestSupportedImageVersion check - fail\n"));
644 return EFI_SECURITY_VIOLATION;
645 }
646 }
647
648 *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
649 return EFI_SUCCESS;
650 }
651
652 /**
653 PcdCallBack gets the real set PCD value
654
655 @param[in] CallBackGuid The PCD token GUID being set.
656 @param[in] CallBackToken The PCD token number being set.
657 @param[in, out] TokenData A pointer to the token data being set.
658 @param[in] TokenDataSize The size, in bytes, of the data being set.
659
660 **/
661 VOID
662 EFIAPI
663 EdkiiSystemCapsuleLibPcdCallBack (
664 IN CONST GUID *CallBackGuid, OPTIONAL
665 IN UINTN CallBackToken,
666 IN OUT VOID *TokenData,
667 IN UINTN TokenDataSize
668 )
669 {
670 if (CompareGuid (CallBackGuid, &gEfiSignedCapsulePkgTokenSpaceGuid) &&
671 CallBackToken == PcdToken (PcdEdkiiSystemFirmwareImageDescriptor)) {
672 mImageFmpInfoSize = TokenDataSize;
673 mImageFmpInfo = AllocateCopyPool (mImageFmpInfoSize, TokenData);
674 ASSERT(mImageFmpInfo != NULL);
675 //
676 // Cancel Callback after get the real set value
677 //
678 LibPcdCancelCallback (
679 &gEfiSignedCapsulePkgTokenSpaceGuid,
680 PcdToken (PcdEdkiiSystemFirmwareImageDescriptor),
681 EdkiiSystemCapsuleLibPcdCallBack
682 );
683 }
684
685 if (CompareGuid (CallBackGuid, &gEfiSignedCapsulePkgTokenSpaceGuid) &&
686 CallBackToken == PcdToken (PcdEdkiiSystemFirmwareFileGuid)) {
687 CopyGuid(&mEdkiiSystemFirmwareFileGuid, TokenData);
688 //
689 // Cancel Callback after get the real set value
690 //
691 LibPcdCancelCallback (
692 &gEfiSignedCapsulePkgTokenSpaceGuid,
693 PcdToken (PcdEdkiiSystemFirmwareFileGuid),
694 EdkiiSystemCapsuleLibPcdCallBack
695 );
696 }
697 }
698
699 /**
700 The constructor function.
701
702 @retval EFI_SUCCESS The constructor successfully .
703 **/
704 EFI_STATUS
705 EFIAPI
706 EdkiiSystemCapsuleLibConstructor (
707 VOID
708 )
709 {
710 mImageFmpInfoSize = PcdGetSize(PcdEdkiiSystemFirmwareImageDescriptor);
711 mImageFmpInfo = PcdGetPtr(PcdEdkiiSystemFirmwareImageDescriptor);
712 //
713 // Verify Firmware Image Descriptor first
714 //
715 if (mImageFmpInfoSize < sizeof (EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR) ||
716 mImageFmpInfo->Signature != EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE) {
717 //
718 // SystemFirmwareImageDescriptor is not set.
719 // Register PCD set callback to hook PCD value set.
720 //
721 mImageFmpInfo = NULL;
722 mImageFmpInfoSize = 0;
723 LibPcdCallbackOnSet (
724 &gEfiSignedCapsulePkgTokenSpaceGuid,
725 PcdToken (PcdEdkiiSystemFirmwareImageDescriptor),
726 EdkiiSystemCapsuleLibPcdCallBack
727 );
728 } else {
729 mImageFmpInfo = AllocateCopyPool (mImageFmpInfoSize, mImageFmpInfo);
730 ASSERT(mImageFmpInfo != NULL);
731 }
732
733 CopyGuid(&mEdkiiSystemFirmwareFileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid));
734 //
735 // Verify GUID value first
736 //
737 if (CompareGuid (&mEdkiiSystemFirmwareFileGuid, &gZeroGuid)) {
738 LibPcdCallbackOnSet (
739 &gEfiSignedCapsulePkgTokenSpaceGuid,
740 PcdToken (PcdEdkiiSystemFirmwareFileGuid),
741 EdkiiSystemCapsuleLibPcdCallBack
742 );
743 }
744 return EFI_SUCCESS;
745 }