]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
6e3e9eea95200a7a5b73ea230ffc39de3bbae490
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
1 /** @file
2 Implement image verification services for secure boot service in UEFI2.3.1.
3
4 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "DxeImageVerificationLib.h"
16
17 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
18 UINTN mImageSize;
19 UINT32 mPeCoffHeaderOffset;
20 UINT8 mImageDigest[MAX_DIGEST_SIZE];
21 UINTN mImageDigestSize;
22 EFI_IMAGE_DATA_DIRECTORY *mSecDataDir = NULL;
23 UINT8 *mImageBase = NULL;
24 EFI_GUID mCertType;
25
26 //
27 // Notify string for authorization UI.
28 //
29 CHAR16 mNotifyString1[MAX_NOTIFY_STRING_LEN] = L"Image verification pass but not found in authorized database!";
30 CHAR16 mNotifyString2[MAX_NOTIFY_STRING_LEN] = L"Launch this image anyway? (Yes/Defer/No)";
31 //
32 // Public Exponent of RSA Key.
33 //
34 CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
35
36
37 //
38 // OID ASN.1 Value for Hash Algorithms
39 //
40 UINT8 mHashOidValue[] = {
41 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
42 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
43 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
44 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
45 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
46 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
47 };
48
49 HASH_TABLE mHash[] = {
50 { L"SHA1", 20, &mHashOidValue[8], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },
51 { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL },
52 { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize,Sha256Init, Sha256Update, Sha256Final},
53 { L"SHA384", 48, &mHashOidValue[31], 9, NULL, NULL, NULL, NULL },
54 { L"SHA512", 64, &mHashOidValue[40], 9, NULL, NULL, NULL, NULL }
55 };
56
57 /**
58 Reads contents of a PE/COFF image in memory buffer.
59
60 @param FileHandle Pointer to the file handle to read the PE/COFF image.
61 @param FileOffset Offset into the PE/COFF image to begin the read operation.
62 @param ReadSize On input, the size in bytes of the requested read operation.
63 On output, the number of bytes actually read.
64 @param Buffer Output buffer that contains the data read from the PE/COFF image.
65
66 @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
67 **/
68 EFI_STATUS
69 EFIAPI
70 ImageRead (
71 IN VOID *FileHandle,
72 IN UINTN FileOffset,
73 IN OUT UINTN *ReadSize,
74 OUT VOID *Buffer
75 )
76 {
77 UINTN EndPosition;
78
79 if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {
80 return EFI_INVALID_PARAMETER;
81 }
82
83 if (MAX_ADDRESS - FileOffset < *ReadSize) {
84 return EFI_INVALID_PARAMETER;
85 }
86
87 EndPosition = FileOffset + *ReadSize;
88 if (EndPosition > mImageSize) {
89 *ReadSize = (UINT32)(mImageSize - FileOffset);
90 }
91
92 if (FileOffset >= mImageSize) {
93 *ReadSize = 0;
94 }
95
96 CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);
97
98 return EFI_SUCCESS;
99 }
100
101
102 /**
103 Get the image type.
104
105 @param[in] File This is a pointer to the device path of the file that is
106 being dispatched.
107
108 @return UINT32 Image Type
109
110 **/
111 UINT32
112 GetImageType (
113 IN CONST EFI_DEVICE_PATH_PROTOCOL *File
114 )
115 {
116 EFI_STATUS Status;
117 EFI_HANDLE DeviceHandle;
118 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
119 EFI_BLOCK_IO_PROTOCOL *BlockIo;
120
121 //
122 // First check to see if File is from a Firmware Volume
123 //
124 DeviceHandle = NULL;
125 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
126 Status = gBS->LocateDevicePath (
127 &gEfiFirmwareVolume2ProtocolGuid,
128 &TempDevicePath,
129 &DeviceHandle
130 );
131 if (!EFI_ERROR (Status)) {
132 Status = gBS->OpenProtocol (
133 DeviceHandle,
134 &gEfiFirmwareVolume2ProtocolGuid,
135 NULL,
136 NULL,
137 NULL,
138 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
139 );
140 if (!EFI_ERROR (Status)) {
141 return IMAGE_FROM_FV;
142 }
143 }
144
145 //
146 // Next check to see if File is from a Block I/O device
147 //
148 DeviceHandle = NULL;
149 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
150 Status = gBS->LocateDevicePath (
151 &gEfiBlockIoProtocolGuid,
152 &TempDevicePath,
153 &DeviceHandle
154 );
155 if (!EFI_ERROR (Status)) {
156 BlockIo = NULL;
157 Status = gBS->OpenProtocol (
158 DeviceHandle,
159 &gEfiBlockIoProtocolGuid,
160 (VOID **) &BlockIo,
161 NULL,
162 NULL,
163 EFI_OPEN_PROTOCOL_GET_PROTOCOL
164 );
165 if (!EFI_ERROR (Status) && BlockIo != NULL) {
166 if (BlockIo->Media != NULL) {
167 if (BlockIo->Media->RemovableMedia) {
168 //
169 // Block I/O is present and specifies the media is removable
170 //
171 return IMAGE_FROM_REMOVABLE_MEDIA;
172 } else {
173 //
174 // Block I/O is present and specifies the media is not removable
175 //
176 return IMAGE_FROM_FIXED_MEDIA;
177 }
178 }
179 }
180 }
181
182 //
183 // File is not in a Firmware Volume or on a Block I/O device, so check to see if
184 // the device path supports the Simple File System Protocol.
185 //
186 DeviceHandle = NULL;
187 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
188 Status = gBS->LocateDevicePath (
189 &gEfiSimpleFileSystemProtocolGuid,
190 &TempDevicePath,
191 &DeviceHandle
192 );
193 if (!EFI_ERROR (Status)) {
194 //
195 // Simple File System is present without Block I/O, so assume media is fixed.
196 //
197 return IMAGE_FROM_FIXED_MEDIA;
198 }
199
200 //
201 // File is not from an FV, Block I/O or Simple File System, so the only options
202 // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
203 //
204 TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
205 while (!IsDevicePathEndType (TempDevicePath)) {
206 switch (DevicePathType (TempDevicePath)) {
207
208 case MEDIA_DEVICE_PATH:
209 if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
210 return IMAGE_FROM_OPTION_ROM;
211 }
212 break;
213
214 case MESSAGING_DEVICE_PATH:
215 if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {
216 return IMAGE_FROM_REMOVABLE_MEDIA;
217 }
218 break;
219
220 default:
221 break;
222 }
223 TempDevicePath = NextDevicePathNode (TempDevicePath);
224 }
225 return IMAGE_UNKNOWN;
226 }
227
228 /**
229 Caculate hash of Pe/Coff image based on the authenticode image hashing in
230 PE/COFF Specification 8.0 Appendix A
231
232 @param[in] HashAlg Hash algorithm type.
233
234 @retval TRUE Successfully hash image.
235 @retval FALSE Fail in hash image.
236
237 **/
238 BOOLEAN
239 HashPeImage (
240 IN UINT32 HashAlg
241 )
242 {
243 BOOLEAN Status;
244 UINT16 Magic;
245 EFI_IMAGE_SECTION_HEADER *Section;
246 VOID *HashCtx;
247 UINTN CtxSize;
248 UINT8 *HashBase;
249 UINTN HashSize;
250 UINTN SumOfBytesHashed;
251 EFI_IMAGE_SECTION_HEADER *SectionHeader;
252 UINTN Index;
253 UINTN Pos;
254 UINTN SumOfSectionBytes;
255 EFI_IMAGE_SECTION_HEADER *SectionCache;
256
257 HashCtx = NULL;
258 SectionHeader = NULL;
259 Status = FALSE;
260
261 if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {
262 return FALSE;
263 }
264
265 //
266 // Initialize context of hash.
267 //
268 ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
269
270 if (HashAlg == HASHALG_SHA1) {
271 mImageDigestSize = SHA1_DIGEST_SIZE;
272 mCertType = gEfiCertSha1Guid;
273 } else if (HashAlg == HASHALG_SHA256) {
274 mImageDigestSize = SHA256_DIGEST_SIZE;
275 mCertType = gEfiCertSha256Guid;
276 } else {
277 return FALSE;
278 }
279
280 CtxSize = mHash[HashAlg].GetContextSize();
281
282 HashCtx = AllocatePool (CtxSize);
283 if (HashCtx == NULL) {
284 return FALSE;
285 }
286
287 // 1. Load the image header into memory.
288
289 // 2. Initialize a SHA hash context.
290 Status = mHash[HashAlg].HashInit(HashCtx);
291
292 if (!Status) {
293 goto Done;
294 }
295 //
296 // Measuring PE/COFF Image Header;
297 // But CheckSum field and SECURITY data directory (certificate) are excluded
298 //
299 Magic = mNtHeader.Pe32->OptionalHeader.Magic;
300 //
301 // 3. Calculate the distance from the base of the image header to the image checksum address.
302 // 4. Hash the image header from its base to beginning of the image checksum.
303 //
304 HashBase = mImageBase;
305 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
306 //
307 // Use PE32 offset.
308 //
309 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);
310 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
311 //
312 // Use PE32+ offset.
313 //
314 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
315 } else {
316 //
317 // Invalid header magic number.
318 //
319 Status = FALSE;
320 goto Done;
321 }
322
323 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
324 if (!Status) {
325 goto Done;
326 }
327 //
328 // 5. Skip over the image checksum (it occupies a single ULONG).
329 // 6. Get the address of the beginning of the Cert Directory.
330 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
331 //
332 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
333 //
334 // Use PE32 offset.
335 //
336 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
337 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
338 } else {
339 //
340 // Use PE32+ offset.
341 //
342 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
343 HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
344 }
345
346 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
347 if (!Status) {
348 goto Done;
349 }
350 //
351 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
352 // 9. Hash everything from the end of the Cert Directory to the end of image header.
353 //
354 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
355 //
356 // Use PE32 offset
357 //
358 HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
359 HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);
360 } else {
361 //
362 // Use PE32+ offset.
363 //
364 HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
365 HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);
366 }
367
368 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
369 if (!Status) {
370 goto Done;
371 }
372 //
373 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
374 //
375 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
376 //
377 // Use PE32 offset.
378 //
379 SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
380 } else {
381 //
382 // Use PE32+ offset
383 //
384 SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
385 }
386
387
388 Section = (EFI_IMAGE_SECTION_HEADER *) (
389 mImageBase +
390 mPeCoffHeaderOffset +
391 sizeof (UINT32) +
392 sizeof (EFI_IMAGE_FILE_HEADER) +
393 mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
394 );
395
396 SectionCache = Section;
397 for (Index = 0, SumOfSectionBytes = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++, SectionCache++) {
398 SumOfSectionBytes += SectionCache->SizeOfRawData;
399 }
400
401 //
402 // Sanity check for file corruption. Sections raw data size should be smaller
403 // than Image Size.
404 //
405 if (SumOfSectionBytes >= mImageSize) {
406 Status = FALSE;
407 goto Done;
408 }
409
410 //
411 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
412 // structures in the image. The 'NumberOfSections' field of the image
413 // header indicates how big the table should be. Do not include any
414 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
415 //
416 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);
417 if (SectionHeader == NULL) {
418 Status = FALSE;
419 goto Done;
420 }
421 //
422 // 12. Using the 'PointerToRawData' in the referenced section headers as
423 // a key, arrange the elements in the table in ascending order. In other
424 // words, sort the section headers according to the disk-file offset of
425 // the section.
426 //
427 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
428 Pos = Index;
429 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
430 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
431 Pos--;
432 }
433 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
434 Section += 1;
435 }
436
437 //
438 // 13. Walk through the sorted table, bring the corresponding section
439 // into memory, and hash the entire section (using the 'SizeOfRawData'
440 // field in the section header to determine the amount of data to hash).
441 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
442 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
443 //
444 for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
445 Section = &SectionHeader[Index];
446 if (Section->SizeOfRawData == 0) {
447 continue;
448 }
449 HashBase = mImageBase + Section->PointerToRawData;
450 HashSize = (UINTN) Section->SizeOfRawData;
451
452 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
453 if (!Status) {
454 goto Done;
455 }
456
457 SumOfBytesHashed += HashSize;
458 }
459
460 //
461 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
462 // data in the file that needs to be added to the hash. This data begins
463 // at file offset SUM_OF_BYTES_HASHED and its length is:
464 // FileSize - (CertDirectory->Size)
465 //
466 if (mImageSize > SumOfBytesHashed) {
467 HashBase = mImageBase + SumOfBytesHashed;
468 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
469 if (mImageSize - SumOfBytesHashed < mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size) {
470 Status = FALSE;
471 goto Done;
472 }
473 //
474 // Use PE32 offset.
475 //
476 HashSize = (UINTN)(
477 mImageSize -
478 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
479 SumOfBytesHashed);
480 } else {
481 if (mImageSize - SumOfBytesHashed < mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size) {
482 Status = FALSE;
483 goto Done;
484 }
485 //
486 // Use PE32+ offset.
487 //
488 HashSize = (UINTN)(
489 mImageSize -
490 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
491 SumOfBytesHashed);
492 }
493
494 Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
495 if (!Status) {
496 goto Done;
497 }
498 }
499 Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);
500
501 Done:
502 if (HashCtx != NULL) {
503 FreePool (HashCtx);
504 }
505 if (SectionHeader != NULL) {
506 FreePool (SectionHeader);
507 }
508 return Status;
509 }
510
511 /**
512 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
513 Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
514 8.0 Appendix A
515
516 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
517 @retval EFI_SUCCESS Hash successfully.
518
519 **/
520 EFI_STATUS
521 HashPeImageByType (
522 VOID
523 )
524 {
525 UINT8 Index;
526 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
527
528 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);
529
530 for (Index = 0; Index < HASHALG_MAX; Index++) {
531 //
532 // Check the Hash algorithm in PE/COFF Authenticode.
533 // According to PKCS#7 Definition:
534 // SignedData ::= SEQUENCE {
535 // version Version,
536 // digestAlgorithms DigestAlgorithmIdentifiers,
537 // contentInfo ContentInfo,
538 // .... }
539 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
540 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
541 // Fixed offset (+32) is calculated based on two bytes of length encoding.
542 //
543 if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
544 //
545 // Only support two bytes of Long Form of Length Encoding.
546 //
547 continue;
548 }
549
550 if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
551 break;
552 }
553 }
554
555 if (Index == HASHALG_MAX) {
556 return EFI_UNSUPPORTED;
557 }
558
559 //
560 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
561 //
562 if (!HashPeImage(Index)) {
563 return EFI_UNSUPPORTED;
564 }
565
566 return EFI_SUCCESS;
567 }
568
569
570 /**
571 Returns the size of a given image execution info table in bytes.
572
573 This function returns the size, in bytes, of the image execution info table specified by
574 ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
575
576 @param ImageExeInfoTable A pointer to a image execution info table structure.
577
578 @retval 0 If ImageExeInfoTable is NULL.
579 @retval Others The size of a image execution info table in bytes.
580
581 **/
582 UINTN
583 GetImageExeInfoTableSize (
584 EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable
585 )
586 {
587 UINTN Index;
588 EFI_IMAGE_EXECUTION_INFO *ImageExeInfoItem;
589 UINTN TotalSize;
590
591 if (ImageExeInfoTable == NULL) {
592 return 0;
593 }
594
595 ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoTable + sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE));
596 TotalSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
597 for (Index = 0; Index < ImageExeInfoTable->NumberOfImages; Index++) {
598 TotalSize += ReadUnaligned32 ((UINT32 *) &ImageExeInfoItem->InfoSize);
599 ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoItem + ReadUnaligned32 ((UINT32 *) &ImageExeInfoItem->InfoSize));
600 }
601
602 return TotalSize;
603 }
604
605 /**
606 Create an Image Execution Information Table entry and add it to system configuration table.
607
608 @param[in] Action Describes the action taken by the firmware regarding this image.
609 @param[in] Name Input a null-terminated, user-friendly name.
610 @param[in] DevicePath Input device path pointer.
611 @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
612 @param[in] SignatureSize Size of signature.
613
614 **/
615 VOID
616 AddImageExeInfo (
617 IN EFI_IMAGE_EXECUTION_ACTION Action,
618 IN CHAR16 *Name OPTIONAL,
619 IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
620 IN EFI_SIGNATURE_LIST *Signature OPTIONAL,
621 IN UINTN SignatureSize
622 )
623 {
624 EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable;
625 EFI_IMAGE_EXECUTION_INFO_TABLE *NewImageExeInfoTable;
626 EFI_IMAGE_EXECUTION_INFO *ImageExeInfoEntry;
627 UINTN ImageExeInfoTableSize;
628 UINTN NewImageExeInfoEntrySize;
629 UINTN NameStringLen;
630 UINTN DevicePathSize;
631
632 ImageExeInfoTable = NULL;
633 NewImageExeInfoTable = NULL;
634 ImageExeInfoEntry = NULL;
635 NameStringLen = 0;
636
637 if (DevicePath == NULL) {
638 return ;
639 }
640
641 if (Name != NULL) {
642 NameStringLen = StrSize (Name);
643 }
644
645 ImageExeInfoTable = NULL;
646 EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID **) &ImageExeInfoTable);
647 if (ImageExeInfoTable != NULL) {
648 //
649 // The table has been found!
650 // We must enlarge the table to accmodate the new exe info entry.
651 //
652 ImageExeInfoTableSize = GetImageExeInfoTableSize (ImageExeInfoTable);
653 } else {
654 //
655 // Not Found!
656 // We should create a new table to append to the configuration table.
657 //
658 ImageExeInfoTableSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
659 }
660
661 DevicePathSize = GetDevicePathSize (DevicePath);
662 NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;
663 NewImageExeInfoTable = (EFI_IMAGE_EXECUTION_INFO_TABLE *) AllocateRuntimePool (ImageExeInfoTableSize + NewImageExeInfoEntrySize);
664 if (NewImageExeInfoTable == NULL) {
665 return ;
666 }
667
668 if (ImageExeInfoTable != NULL) {
669 CopyMem (NewImageExeInfoTable, ImageExeInfoTable, ImageExeInfoTableSize);
670 } else {
671 NewImageExeInfoTable->NumberOfImages = 0;
672 }
673 NewImageExeInfoTable->NumberOfImages++;
674 ImageExeInfoEntry = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) NewImageExeInfoTable + ImageExeInfoTableSize);
675 //
676 // Update new item's infomation.
677 //
678 WriteUnaligned32 ((UINT32 *) &ImageExeInfoEntry->Action, Action);
679 WriteUnaligned32 ((UINT32 *) &ImageExeInfoEntry->InfoSize, (UINT32) NewImageExeInfoEntrySize);
680
681 if (Name != NULL) {
682 CopyMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), Name, NameStringLen);
683 }
684 CopyMem (
685 (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen,
686 DevicePath,
687 DevicePathSize
688 );
689 if (Signature != NULL) {
690 CopyMem (
691 (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen + DevicePathSize,
692 Signature,
693 SignatureSize
694 );
695 }
696 //
697 // Update/replace the image execution table.
698 //
699 gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);
700
701 //
702 // Free Old table data!
703 //
704 if (ImageExeInfoTable != NULL) {
705 FreePool (ImageExeInfoTable);
706 }
707 }
708
709 /**
710 Discover if the UEFI image is authorized by user's policy setting.
711
712 @param[in] Policy Specify platform's policy setting.
713
714 @retval EFI_ACCESS_DENIED Image is not allowed to run.
715 @retval EFI_SECURITY_VIOLATION Image is deferred.
716 @retval EFI_SUCCESS Image is authorized to run.
717
718 **/
719 EFI_STATUS
720 ImageAuthorization (
721 IN UINT32 Policy
722 )
723 {
724 EFI_STATUS Status;
725 EFI_INPUT_KEY Key;
726
727 Status = EFI_ACCESS_DENIED;
728
729 switch (Policy) {
730
731 case QUERY_USER_ON_SECURITY_VIOLATION:
732 do {
733 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, mNotifyString1, mNotifyString2, NULL);
734 if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {
735 Status = EFI_SUCCESS;
736 break;
737 } else if (Key.UnicodeChar == L'N' || Key.UnicodeChar == L'n') {
738 Status = EFI_ACCESS_DENIED;
739 break;
740 } else if (Key.UnicodeChar == L'D' || Key.UnicodeChar == L'd') {
741 Status = EFI_SECURITY_VIOLATION;
742 break;
743 }
744 } while (TRUE);
745 break;
746
747 case ALLOW_EXECUTE_ON_SECURITY_VIOLATION:
748 Status = EFI_SUCCESS;
749 break;
750
751 case DEFER_EXECUTE_ON_SECURITY_VIOLATION:
752 Status = EFI_SECURITY_VIOLATION;
753 break;
754
755 case DENY_EXECUTE_ON_SECURITY_VIOLATION:
756 Status = EFI_ACCESS_DENIED;
757 break;
758 }
759
760 return Status;
761 }
762
763 /**
764 Check whether signature is in specified database.
765
766 @param[in] VariableName Name of database variable that is searched in.
767 @param[in] Signature Pointer to signature that is searched for.
768 @param[in] CertType Pointer to hash algrithom.
769 @param[in] SignatureSize Size of Signature.
770
771 @return TRUE Found the signature in the variable database.
772 @return FALSE Not found the signature in the variable database.
773
774 **/
775 BOOLEAN
776 IsSignatureFoundInDatabase (
777 IN CHAR16 *VariableName,
778 IN UINT8 *Signature,
779 IN EFI_GUID *CertType,
780 IN UINTN SignatureSize
781 )
782 {
783 EFI_STATUS Status;
784 EFI_SIGNATURE_LIST *CertList;
785 EFI_SIGNATURE_DATA *Cert;
786 UINTN DataSize;
787 UINT8 *Data;
788 UINTN Index;
789 UINTN CertCount;
790 BOOLEAN IsFound;
791 //
792 // Read signature database variable.
793 //
794 IsFound = FALSE;
795 Data = NULL;
796 DataSize = 0;
797 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
798 if (Status != EFI_BUFFER_TOO_SMALL) {
799 return FALSE;
800 }
801
802 Data = (UINT8 *) AllocateZeroPool (DataSize);
803 if (Data == NULL) {
804 return FALSE;
805 }
806
807 Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
808 if (EFI_ERROR (Status)) {
809 goto Done;
810 }
811 //
812 // Enumerate all signature data in SigDB to check if executable's signature exists.
813 //
814 CertList = (EFI_SIGNATURE_LIST *) Data;
815 while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
816 CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
817 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
818 if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, CertType))) {
819 for (Index = 0; Index < CertCount; Index++) {
820 if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {
821 //
822 // Find the signature in database.
823 //
824 IsFound = TRUE;
825 break;
826 }
827
828 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
829 }
830
831 if (IsFound) {
832 break;
833 }
834 }
835
836 DataSize -= CertList->SignatureListSize;
837 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
838 }
839
840 Done:
841 if (Data != NULL) {
842 FreePool (Data);
843 }
844
845 return IsFound;
846 }
847
848 /**
849 Verify PKCS#7 SignedData using certificate found in Variable which formatted
850 as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
851
852 @param VariableName Name of Variable to search for Certificate.
853 @param VendorGuid Variable vendor GUID.
854
855 @retval TRUE Image pass verification.
856 @retval FALSE Image fail verification.
857
858 **/
859 BOOLEAN
860 IsPkcsSignedDataVerifiedBySignatureList (
861 IN CHAR16 *VariableName,
862 IN EFI_GUID *VendorGuid
863 )
864 {
865 EFI_STATUS Status;
866 BOOLEAN VerifyStatus;
867 WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
868 EFI_SIGNATURE_LIST *CertList;
869 EFI_SIGNATURE_DATA *Cert;
870 UINTN DataSize;
871 UINT8 *Data;
872 UINT8 *RootCert;
873 UINTN RootCertSize;
874 UINTN Index;
875 UINTN CertCount;
876
877 Data = NULL;
878 CertList = NULL;
879 Cert = NULL;
880 RootCert = NULL;
881 RootCertSize = 0;
882 VerifyStatus = FALSE;
883 PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);
884
885 DataSize = 0;
886 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
887 if (Status == EFI_BUFFER_TOO_SMALL) {
888 Data = (UINT8 *) AllocateZeroPool (DataSize);
889 if (Data == NULL) {
890 return VerifyStatus;
891 }
892
893 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, (VOID *) Data);
894 if (EFI_ERROR (Status)) {
895 goto Done;
896 }
897
898 //
899 // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
900 //
901 CertList = (EFI_SIGNATURE_LIST *) Data;
902 while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
903 if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
904 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
905 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
906 for (Index = 0; Index < CertCount; Index++) {
907 //
908 // Iterate each Signature Data Node within this CertList for verify.
909 //
910 RootCert = Cert->SignatureData;
911 RootCertSize = CertList->SignatureSize;
912
913 //
914 // Call AuthenticodeVerify library to Verify Authenticode struct.
915 //
916 VerifyStatus = AuthenticodeVerify (
917 PkcsCertData->CertData,
918 mSecDataDir->Size - sizeof(PkcsCertData->Hdr),
919 RootCert,
920 RootCertSize,
921 mImageDigest,
922 mImageDigestSize
923 );
924 if (VerifyStatus) {
925 goto Done;
926 }
927 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
928 }
929 }
930 DataSize -= CertList->SignatureListSize;
931 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
932 }
933 }
934
935 Done:
936 if (Data != NULL) {
937 FreePool (Data);
938 }
939
940 return VerifyStatus;
941 }
942
943 /**
944 Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
945
946 @retval EFI_SUCCESS Image pass verification.
947 @retval EFI_SECURITY_VIOLATION Image fail verification.
948
949 **/
950 EFI_STATUS
951 VerifyCertPkcsSignedData (
952 VOID
953 )
954 {
955 //
956 // 1: Find certificate from DBX forbidden database for revoked certificate.
957 //
958 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {
959 //
960 // DBX is forbidden database, if Authenticode verification pass with
961 // one of the certificate in DBX, this image should be rejected.
962 //
963 return EFI_SECURITY_VIOLATION;
964 }
965
966 //
967 // 2: Find certificate from KEK database and try to verify authenticode struct.
968 //
969 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid)) {
970 return EFI_SUCCESS;
971 }
972
973 //
974 // 3: Find certificate from DB database and try to verify authenticode struct.
975 //
976 if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {
977 return EFI_SUCCESS;
978 } else {
979 return EFI_SECURITY_VIOLATION;
980 }
981 }
982
983 /**
984 Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.
985
986 @retval EFI_SUCCESS Image pass verification.
987 @retval EFI_SECURITY_VIOLATION Image fail verification.
988 @retval other error value
989
990 **/
991 EFI_STATUS
992 VerifyCertUefiGuid (
993 VOID
994 )
995 {
996 BOOLEAN Status;
997 WIN_CERTIFICATE_UEFI_GUID *EfiCert;
998 EFI_SIGNATURE_LIST *KekList;
999 EFI_SIGNATURE_DATA *KekItem;
1000 EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
1001 VOID *Rsa;
1002 UINTN KekCount;
1003 UINTN Index;
1004 UINTN KekDataSize;
1005 BOOLEAN IsFound;
1006 EFI_STATUS Result;
1007
1008 EfiCert = NULL;
1009 KekList = NULL;
1010 KekItem = NULL;
1011 CertBlock = NULL;
1012 Rsa = NULL;
1013 Status = FALSE;
1014 IsFound = FALSE;
1015 KekDataSize = 0;
1016
1017 EfiCert = (WIN_CERTIFICATE_UEFI_GUID *) (mImageBase + mSecDataDir->VirtualAddress);
1018 CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) EfiCert->CertData;
1019 if (!CompareGuid (&EfiCert->CertType, &gEfiCertTypeRsa2048Sha256Guid)) {
1020 //
1021 // Invalid Certificate Data Type.
1022 //
1023 return EFI_SECURITY_VIOLATION;
1024 }
1025
1026 //
1027 // Get KEK database variable data size
1028 //
1029 Result = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &KekDataSize, NULL);
1030 if (Result != EFI_BUFFER_TOO_SMALL) {
1031 return EFI_SECURITY_VIOLATION;
1032 }
1033
1034 //
1035 // Get KEK database variable.
1036 //
1037 KekList = GetEfiGlobalVariable (EFI_KEY_EXCHANGE_KEY_NAME);
1038 if (KekList == NULL) {
1039 return EFI_SECURITY_VIOLATION;
1040 }
1041
1042 //
1043 // Enumerate all Kek items in this list to verify the variable certificate data.
1044 // If anyone is authenticated successfully, it means the variable is correct!
1045 //
1046 while ((KekDataSize > 0) && (KekDataSize >= KekList->SignatureListSize)) {
1047 if (CompareGuid (&KekList->SignatureType, &gEfiCertRsa2048Guid)) {
1048 KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);
1049 KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;
1050 for (Index = 0; Index < KekCount; Index++) {
1051 if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
1052 IsFound = TRUE;
1053 break;
1054 }
1055 KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);
1056 }
1057 }
1058 KekDataSize -= KekList->SignatureListSize;
1059 KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);
1060 }
1061
1062 if (!IsFound) {
1063 //
1064 // Signed key is not a trust one.
1065 //
1066 goto Done;
1067 }
1068
1069 //
1070 // Now, we found the corresponding security policy.
1071 // Verify the data payload.
1072 //
1073 Rsa = RsaNew ();
1074 if (Rsa == NULL) {
1075 Status = FALSE;
1076 goto Done;
1077 }
1078
1079 //
1080 // Set RSA Key Components.
1081 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
1082 //
1083 Status = RsaSetKey (Rsa, RsaKeyN, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE);
1084 if (!Status) {
1085 goto Done;
1086 }
1087 Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
1088 if (!Status) {
1089 goto Done;
1090 }
1091 //
1092 // Verify the signature.
1093 //
1094 Status = RsaPkcs1Verify (
1095 Rsa,
1096 mImageDigest,
1097 mImageDigestSize,
1098 CertBlock->Signature,
1099 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
1100 );
1101
1102 Done:
1103 if (KekList != NULL) {
1104 FreePool (KekList);
1105 }
1106 if (Rsa != NULL ) {
1107 RsaFree (Rsa);
1108 }
1109 if (Status) {
1110 return EFI_SUCCESS;
1111 } else {
1112 return EFI_SECURITY_VIOLATION;
1113 }
1114 }
1115
1116 /**
1117 Provide verification service for signed images, which include both signature validation
1118 and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
1119 MSFT Authenticode type signatures are supported.
1120
1121 In this implementation, only verify external executables when in USER MODE.
1122 Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
1123
1124 The image verification process is:
1125 Is the Image signed?
1126 If yes,
1127 Does the image verify against a certificate (root or intermediate) in the allowed db?
1128 Run it
1129 Image verification fail
1130 Is the Image's Hash not in forbidden database and the Image's Hash in allowed db?
1131 Run it
1132 If no,
1133 Is the Image's Hash in the forbidden database (DBX)?
1134 if yes,
1135 Error out
1136 Is the Image's Hash in the allowed database (DB)?
1137 If yes,
1138 Run it
1139 If no,
1140 Error out
1141
1142 @param[in] AuthenticationStatus
1143 This is the authentication status returned from the security
1144 measurement services for the input file.
1145 @param[in] File This is a pointer to the device path of the file that is
1146 being dispatched. This will optionally be used for logging.
1147 @param[in] FileBuffer File buffer matches the input file device path.
1148 @param[in] FileSize Size of File buffer matches the input file device path.
1149
1150 @retval EFI_SUCCESS The file specified by File did authenticate, and the
1151 platform policy dictates that the DXE Core may use File.
1152 @retval EFI_INVALID_PARAMETER Input argument is incorrect.
1153 @retval EFI_OUT_RESOURCE Fail to allocate memory.
1154 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
1155 the platform policy dictates that File should be placed
1156 in the untrusted state. A file may be promoted from
1157 the untrusted to the trusted state at a future time
1158 with a call to the Trust() DXE Service.
1159 @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
1160 the platform policy dictates that File should not be
1161 used for any purpose.
1162
1163 **/
1164 EFI_STATUS
1165 EFIAPI
1166 DxeImageVerificationHandler (
1167 IN UINT32 AuthenticationStatus,
1168 IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
1169 IN VOID *FileBuffer,
1170 IN UINTN FileSize
1171 )
1172 {
1173 EFI_STATUS Status;
1174 UINT16 Magic;
1175 EFI_IMAGE_DOS_HEADER *DosHdr;
1176 EFI_STATUS VerifyStatus;
1177 UINT8 *SetupMode;
1178 EFI_SIGNATURE_LIST *SignatureList;
1179 UINTN SignatureListSize;
1180 EFI_SIGNATURE_DATA *Signature;
1181 EFI_IMAGE_EXECUTION_ACTION Action;
1182 WIN_CERTIFICATE *WinCertificate;
1183 UINT32 Policy;
1184 UINT8 *SecureBootEnable;
1185 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
1186
1187 if (File == NULL) {
1188 return EFI_INVALID_PARAMETER;
1189 }
1190
1191 SignatureList = NULL;
1192 SignatureListSize = 0;
1193 WinCertificate = NULL;
1194 Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
1195 Status = EFI_ACCESS_DENIED;
1196 //
1197 // Check the image type and get policy setting.
1198 //
1199 switch (GetImageType (File)) {
1200
1201 case IMAGE_FROM_FV:
1202 Policy = ALWAYS_EXECUTE;
1203 break;
1204
1205 case IMAGE_FROM_OPTION_ROM:
1206 Policy = PcdGet32 (PcdOptionRomImageVerificationPolicy);
1207 break;
1208
1209 case IMAGE_FROM_REMOVABLE_MEDIA:
1210 Policy = PcdGet32 (PcdRemovableMediaImageVerificationPolicy);
1211 break;
1212
1213 case IMAGE_FROM_FIXED_MEDIA:
1214 Policy = PcdGet32 (PcdFixedMediaImageVerificationPolicy);
1215 break;
1216
1217 default:
1218 Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;
1219 break;
1220 }
1221 //
1222 // If policy is always/never execute, return directly.
1223 //
1224 if (Policy == ALWAYS_EXECUTE) {
1225 return EFI_SUCCESS;
1226 } else if (Policy == NEVER_EXECUTE) {
1227 return EFI_ACCESS_DENIED;
1228 }
1229
1230 SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);
1231 //
1232 // Skip verification if SecureBootEnable variable doesn't exist.
1233 //
1234 if (SecureBootEnable == NULL) {
1235 return EFI_SUCCESS;
1236 }
1237
1238 //
1239 // Skip verification if SecureBootEnable is disabled.
1240 //
1241 if (*SecureBootEnable == SECURE_BOOT_DISABLE) {
1242 FreePool (SecureBootEnable);
1243 return EFI_SUCCESS;
1244 }
1245
1246 SetupMode = GetEfiGlobalVariable (EFI_SETUP_MODE_NAME);
1247
1248 //
1249 // SetupMode doesn't exist means no AuthVar driver is dispatched,
1250 // skip verification.
1251 //
1252 if (SetupMode == NULL) {
1253 return EFI_SUCCESS;
1254 }
1255
1256 //
1257 // If platform is in SETUP MODE, skip verification.
1258 //
1259 if (*SetupMode == SETUP_MODE) {
1260 FreePool (SetupMode);
1261 return EFI_SUCCESS;
1262 }
1263 //
1264 // Read the Dos header.
1265 //
1266 if (FileBuffer == NULL) {
1267 FreePool (SetupMode);
1268 return EFI_INVALID_PARAMETER;
1269 }
1270 mImageBase = (UINT8 *) FileBuffer;
1271 mImageSize = FileSize;
1272
1273 ZeroMem (&ImageContext, sizeof (ImageContext));
1274 ImageContext.Handle = (VOID *) FileBuffer;
1275 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) ImageRead;
1276
1277 //
1278 // Get information about the image being loaded
1279 //
1280 Status = PeCoffLoaderGetImageInfo (&ImageContext);
1281 if (EFI_ERROR (Status)) {
1282 //
1283 // The information can't be got from the invalid PeImage
1284 //
1285 goto Done;
1286 }
1287
1288 DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;
1289 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
1290 //
1291 // DOS image header is present,
1292 // so read the PE header after the DOS image header.
1293 //
1294 mPeCoffHeaderOffset = DosHdr->e_lfanew;
1295 } else {
1296 mPeCoffHeaderOffset = 0;
1297 }
1298 //
1299 // Check PE/COFF image.
1300 //
1301 mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (mImageBase + mPeCoffHeaderOffset);
1302 if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
1303 //
1304 // It is not a valid Pe/Coff file.
1305 //
1306 return EFI_ACCESS_DENIED;
1307 }
1308
1309 Magic = mNtHeader.Pe32->OptionalHeader.Magic;
1310 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1311 //
1312 // Use PE32 offset.
1313 //
1314 mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1315 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
1316 //
1317 // Use PE32+ offset.
1318 //
1319 mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1320 } else {
1321 //
1322 // Invalid header magic number.
1323 //
1324 Status = EFI_INVALID_PARAMETER;
1325 goto Done;
1326 }
1327
1328 if (mSecDataDir->VirtualAddress >= mImageSize) {
1329 //
1330 // Sanity check to see if this file is corrupted.
1331 //
1332 Status = EFI_INVALID_PARAMETER;
1333 goto Done;
1334 }
1335
1336 if (mSecDataDir->Size == 0) {
1337 //
1338 // This image is not signed.
1339 //
1340 if (!HashPeImage (HASHALG_SHA256)) {
1341 goto Done;
1342 }
1343
1344 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
1345 //
1346 // Image Hash is in forbidden database (DBX).
1347 //
1348 Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
1349 Status = EFI_ACCESS_DENIED;
1350 goto Done;
1351 }
1352
1353 if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
1354 //
1355 // Image Hash is in allowed database (DB).
1356 //
1357 return EFI_SUCCESS;
1358 }
1359
1360 //
1361 // Image Hash is not found in both forbidden and allowed database.
1362 //
1363 Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
1364 Status = EFI_ACCESS_DENIED;
1365 goto Done;
1366 }
1367
1368 //
1369 // Verify signature of executables.
1370 //
1371 WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);
1372
1373 switch (WinCertificate->wCertificateType) {
1374
1375 case WIN_CERT_TYPE_EFI_GUID:
1376 //
1377 // Verify UEFI GUID type.
1378 //
1379 if (!HashPeImage (HASHALG_SHA256)) {
1380 goto Done;
1381 }
1382
1383 VerifyStatus = VerifyCertUefiGuid ();
1384 break;
1385
1386 case WIN_CERT_TYPE_PKCS_SIGNED_DATA:
1387 //
1388 // Verify Pkcs signed data type.
1389 //
1390 Status = HashPeImageByType();
1391 if (EFI_ERROR (Status)) {
1392 goto Done;
1393 }
1394
1395 VerifyStatus = VerifyCertPkcsSignedData ();
1396
1397 //
1398 // For image verification against enrolled certificate(root or intermediate),
1399 // no need to check image's hash in the allowed database.
1400 //
1401 if (!EFI_ERROR (VerifyStatus)) {
1402 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
1403 return EFI_SUCCESS;
1404 }
1405 }
1406 break;
1407
1408 default:
1409 Status = EFI_ACCESS_DENIED;
1410 goto Done;
1411 }
1412 //
1413 // Get image hash value as executable's signature.
1414 //
1415 SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;
1416 SignatureList = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignatureListSize);
1417 if (SignatureList == NULL) {
1418 Status = EFI_OUT_OF_RESOURCES;
1419 goto Done;
1420 }
1421 SignatureList->SignatureHeaderSize = 0;
1422 SignatureList->SignatureListSize = (UINT32) SignatureListSize;
1423 SignatureList->SignatureSize = (UINT32) mImageDigestSize;
1424 CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));
1425 Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));
1426 CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);
1427 //
1428 // Signature database check after verification.
1429 //
1430 if (EFI_ERROR (VerifyStatus)) {
1431 //
1432 // Verification failure.
1433 //
1434 if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize) &&
1435 IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
1436 //
1437 // Verification fail, Image Hash is not in forbidden database (DBX),
1438 // and Image Hash is in allowed database (DB).
1439 //
1440 Status = EFI_SUCCESS;
1441 } else {
1442 Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
1443 Status = EFI_ACCESS_DENIED;
1444 }
1445 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Signature->SignatureData, &mCertType, mImageDigestSize)) {
1446 //
1447 // Executable signature verification passes, but is found in forbidden signature database.
1448 //
1449 Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
1450 Status = EFI_ACCESS_DENIED;
1451 } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, Signature->SignatureData, &mCertType, mImageDigestSize)) {
1452 //
1453 // Executable signature is found in authorized signature database.
1454 //
1455 Status = EFI_SUCCESS;
1456 } else {
1457 //
1458 // Executable signature verification passes, but cannot be found in authorized signature database.
1459 // Get platform policy to determine the action.
1460 //
1461 Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED;
1462 Status = ImageAuthorization (Policy);
1463 }
1464
1465 Done:
1466 if (Status != EFI_SUCCESS) {
1467 //
1468 // Policy decides to defer or reject the image; add its information in image executable information table.
1469 //
1470 AddImageExeInfo (Action, NULL, File, SignatureList, SignatureListSize);
1471 }
1472
1473 if (SignatureList != NULL) {
1474 FreePool (SignatureList);
1475 }
1476
1477 FreePool (SetupMode);
1478
1479 return Status;
1480 }
1481
1482 /**
1483 When VariableWriteArchProtocol install, create "SecureBoot" variable.
1484
1485 @param[in] Event Event whose notification function is being invoked.
1486 @param[in] Context Pointer to the notification function's context.
1487
1488 **/
1489 VOID
1490 EFIAPI
1491 VariableWriteCallBack (
1492 IN EFI_EVENT Event,
1493 IN VOID *Context
1494 )
1495 {
1496 UINT8 SecureBootMode;
1497 UINT8 *SecureBootModePtr;
1498 EFI_STATUS Status;
1499 VOID *ProtocolPointer;
1500
1501 Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, &ProtocolPointer);
1502 if (EFI_ERROR (Status)) {
1503 return;
1504 }
1505
1506 //
1507 // Check whether "SecureBoot" variable exists.
1508 // If this library is built-in, it means firmware has capability to perform
1509 // driver signing verification.
1510 //
1511 SecureBootModePtr = GetEfiGlobalVariable (EFI_SECURE_BOOT_MODE_NAME);
1512 if (SecureBootModePtr == NULL) {
1513 SecureBootMode = SECURE_BOOT_MODE_DISABLE;
1514 //
1515 // Authenticated variable driver will update "SecureBoot" depending on SetupMode variable.
1516 //
1517 gRT->SetVariable (
1518 EFI_SECURE_BOOT_MODE_NAME,
1519 &gEfiGlobalVariableGuid,
1520 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
1521 sizeof (UINT8),
1522 &SecureBootMode
1523 );
1524 } else {
1525 FreePool (SecureBootModePtr);
1526 }
1527 }
1528
1529 /**
1530 Register security measurement handler.
1531
1532 @param ImageHandle ImageHandle of the loaded driver.
1533 @param SystemTable Pointer to the EFI System Table.
1534
1535 @retval EFI_SUCCESS The handlers were registered successfully.
1536 **/
1537 EFI_STATUS
1538 EFIAPI
1539 DxeImageVerificationLibConstructor (
1540 IN EFI_HANDLE ImageHandle,
1541 IN EFI_SYSTEM_TABLE *SystemTable
1542 )
1543 {
1544 VOID *Registration;
1545
1546 //
1547 // Register callback function upon VariableWriteArchProtocol.
1548 //
1549 EfiCreateProtocolNotifyEvent (
1550 &gEfiVariableWriteArchProtocolGuid,
1551 TPL_CALLBACK,
1552 VariableWriteCallBack,
1553 NULL,
1554 &Registration
1555 );
1556
1557 return RegisterSecurityHandler (
1558 DxeImageVerificationHandler,
1559 EFI_AUTH_OPERATION_VERIFY_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED
1560 );
1561 }