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