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