1/** @file
2  Implement image verification services for secure boot service
3
4  Caution: This file requires additional review when modified.
5  This library will have external input - PE/COFF image.
6  This external input must be validated carefully to avoid security issue like
7  buffer overflow, integer overflow.
8
9  DxeImageVerificationLibImageRead() function will make sure the PE/COFF image content
10  read is within the image buffer.
11
12  DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept
13  untrusted PE/COFF image and validate its data structure within this image buffer before use.
14
15Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
16This program and the accompanying materials
17are licensed and made available under the terms and conditions of the BSD License
18which accompanies this distribution.  The full text of the license may be found at
19http://opensource.org/licenses/bsd-license.php
20
21THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
22WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23
24**/
25
26#include "DxeImageVerificationLib.h"
27
28//
29// Caution: This is used by a function which may receive untrusted input.
30// These global variables hold PE/COFF image data, and they should be validated before use.
31//
32EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
33UINT32                              mPeCoffHeaderOffset;
34EFI_GUID                            mCertType;
35
36//
37// Information on current PE/COFF image
38//
39UINTN                               mImageSize;
40UINT8                               *mImageBase       = NULL;
41UINT8                               mImageDigest[MAX_DIGEST_SIZE];
42UINTN                               mImageDigestSize;
43
44//
45// Notify string for authorization UI.
46//
47CHAR16  mNotifyString1[MAX_NOTIFY_STRING_LEN] = L"Image verification pass but not found in authorized database!";
48CHAR16  mNotifyString2[MAX_NOTIFY_STRING_LEN] = L"Launch this image anyway? (Yes/Defer/No)";
49//
50// Public Exponent of RSA Key.
51//
52CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
53
54
55//
56// OID ASN.1 Value for Hash Algorithms
57//
58UINT8 mHashOidValue[] = {
59  0x2B, 0x0E, 0x03, 0x02, 0x1A,                           // OBJ_sha1
60  0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,   // OBJ_sha224
61  0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,   // OBJ_sha256
62  0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,   // OBJ_sha384
63  0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,   // OBJ_sha512
64  };
65
66HASH_TABLE mHash[] = {
67  { L"SHA1",   20, &mHashOidValue[0],  5, Sha1GetContextSize,   Sha1Init,   Sha1Update,   Sha1Final  },
68  { L"SHA224", 28, &mHashOidValue[5],  9, NULL,                 NULL,       NULL,         NULL       },
69  { L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},
70  { L"SHA384", 48, &mHashOidValue[23], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},
71  { L"SHA512", 64, &mHashOidValue[32], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}
72};
73
74/**
75  SecureBoot Hook for processing image verification.
76
77  @param[in] VariableName                 Name of Variable to be found.
78  @param[in] VendorGuid                   Variable vendor GUID.
79  @param[in] DataSize                     Size of Data found. If size is less than the
80                                          data, this value contains the required size.
81  @param[in] Data                         Data pointer.
82
83**/
84VOID
85EFIAPI
86SecureBootHook (
87  IN CHAR16                                 *VariableName,
88  IN EFI_GUID                               *VendorGuid,
89  IN UINTN                                  DataSize,
90  IN VOID                                   *Data
91  );
92
93/**
94  Reads contents of a PE/COFF image in memory buffer.
95
96  Caution: This function may receive untrusted input.
97  PE/COFF image is external input, so this function will make sure the PE/COFF image content
98  read is within the image buffer.
99
100  @param  FileHandle      Pointer to the file handle to read the PE/COFF image.
101  @param  FileOffset      Offset into the PE/COFF image to begin the read operation.
102  @param  ReadSize        On input, the size in bytes of the requested read operation.
103                          On output, the number of bytes actually read.
104  @param  Buffer          Output buffer that contains the data read from the PE/COFF image.
105
106  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size
107**/
108EFI_STATUS
109EFIAPI
110DxeImageVerificationLibImageRead (
111  IN     VOID    *FileHandle,
112  IN     UINTN   FileOffset,
113  IN OUT UINTN   *ReadSize,
114  OUT    VOID    *Buffer
115  )
116{
117  UINTN               EndPosition;
118
119  if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {
120    return EFI_INVALID_PARAMETER;
121  }
122
123  if (MAX_ADDRESS - FileOffset < *ReadSize) {
124    return EFI_INVALID_PARAMETER;
125  }
126
127  EndPosition = FileOffset + *ReadSize;
128  if (EndPosition > mImageSize) {
129    *ReadSize = (UINT32)(mImageSize - FileOffset);
130  }
131
132  if (FileOffset >= mImageSize) {
133    *ReadSize = 0;
134  }
135
136  CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);
137
138  return EFI_SUCCESS;
139}
140
141
142/**
143  Get the image type.
144
145  @param[in]    File       This is a pointer to the device path of the file that is
146                           being dispatched.
147
148  @return UINT32           Image Type
149
150**/
151UINT32
152GetImageType (
153  IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File
154  )
155{
156  EFI_STATUS                        Status;
157  EFI_HANDLE                        DeviceHandle;
158  EFI_DEVICE_PATH_PROTOCOL          *TempDevicePath;
159  EFI_BLOCK_IO_PROTOCOL             *BlockIo;
160
161  if (File == NULL) {
162    return IMAGE_UNKNOWN;
163  }
164
165  //
166  // First check to see if File is from a Firmware Volume
167  //
168  DeviceHandle      = NULL;
169  TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
170  Status = gBS->LocateDevicePath (
171                  &gEfiFirmwareVolume2ProtocolGuid,
172                  &TempDevicePath,
173                  &DeviceHandle
174                  );
175  if (!EFI_ERROR (Status)) {
176    Status = gBS->OpenProtocol (
177                    DeviceHandle,
178                    &gEfiFirmwareVolume2ProtocolGuid,
179                    NULL,
180                    NULL,
181                    NULL,
182                    EFI_OPEN_PROTOCOL_TEST_PROTOCOL
183                    );
184    if (!EFI_ERROR (Status)) {
185      return IMAGE_FROM_FV;
186    }
187  }
188
189  //
190  // Next check to see if File is from a Block I/O device
191  //
192  DeviceHandle   = NULL;
193  TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
194  Status = gBS->LocateDevicePath (
195                  &gEfiBlockIoProtocolGuid,
196                  &TempDevicePath,
197                  &DeviceHandle
198                  );
199  if (!EFI_ERROR (Status)) {
200    BlockIo = NULL;
201    Status = gBS->OpenProtocol (
202                    DeviceHandle,
203                    &gEfiBlockIoProtocolGuid,
204                    (VOID **) &BlockIo,
205                    NULL,
206                    NULL,
207                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
208                    );
209    if (!EFI_ERROR (Status) && BlockIo != NULL) {
210      if (BlockIo->Media != NULL) {
211        if (BlockIo->Media->RemovableMedia) {
212          //
213          // Block I/O is present and specifies the media is removable
214          //
215          return IMAGE_FROM_REMOVABLE_MEDIA;
216        } else {
217          //
218          // Block I/O is present and specifies the media is not removable
219          //
220          return IMAGE_FROM_FIXED_MEDIA;
221        }
222      }
223    }
224  }
225
226  //
227  // File is not in a Firmware Volume or on a Block I/O device, so check to see if
228  // the device path supports the Simple File System Protocol.
229  //
230  DeviceHandle   = NULL;
231  TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
232  Status = gBS->LocateDevicePath (
233                  &gEfiSimpleFileSystemProtocolGuid,
234                  &TempDevicePath,
235                  &DeviceHandle
236                  );
237  if (!EFI_ERROR (Status)) {
238    //
239    // Simple File System is present without Block I/O, so assume media is fixed.
240    //
241    return IMAGE_FROM_FIXED_MEDIA;
242  }
243
244  //
245  // File is not from an FV, Block I/O or Simple File System, so the only options
246  // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
247  //
248  TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
249  while (!IsDevicePathEndType (TempDevicePath)) {
250    switch (DevicePathType (TempDevicePath)) {
251
252    case MEDIA_DEVICE_PATH:
253      if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
254        return IMAGE_FROM_OPTION_ROM;
255      }
256      break;
257
258    case MESSAGING_DEVICE_PATH:
259      if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {
260        return IMAGE_FROM_REMOVABLE_MEDIA;
261      }
262      break;
263
264    default:
265      break;
266    }
267    TempDevicePath = NextDevicePathNode (TempDevicePath);
268  }
269  return IMAGE_UNKNOWN;
270}
271
272/**
273  Calculate hash of Pe/Coff image based on the authenticode image hashing in
274  PE/COFF Specification 8.0 Appendix A
275
276  Caution: This function may receive untrusted input.
277  PE/COFF image is external input, so this function will validate its data structure
278  within this image buffer before use.
279
280  @param[in]    HashAlg   Hash algorithm type.
281
282  @retval TRUE            Successfully hash image.
283  @retval FALSE           Fail in hash image.
284
285**/
286BOOLEAN
287HashPeImage (
288  IN  UINT32              HashAlg
289  )
290{
291  BOOLEAN                   Status;
292  UINT16                    Magic;
293  EFI_IMAGE_SECTION_HEADER  *Section;
294  VOID                      *HashCtx;
295  UINTN                     CtxSize;
296  UINT8                     *HashBase;
297  UINTN                     HashSize;
298  UINTN                     SumOfBytesHashed;
299  EFI_IMAGE_SECTION_HEADER  *SectionHeader;
300  UINTN                     Index;
301  UINTN                     Pos;
302  UINT32                    CertSize;
303  UINT32                    NumberOfRvaAndSizes;
304
305  HashCtx       = NULL;
306  SectionHeader = NULL;
307  Status        = FALSE;
308
309  if ((HashAlg >= HASHALG_MAX)) {
310    return FALSE;
311  }
312
313  //
314  // Initialize context of hash.
315  //
316  ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
317
318  switch (HashAlg) {
319  case HASHALG_SHA1:
320    mImageDigestSize = SHA1_DIGEST_SIZE;
321    mCertType        = gEfiCertSha1Guid;
322    break;
323
324  case HASHALG_SHA256:
325    mImageDigestSize = SHA256_DIGEST_SIZE;
326    mCertType        = gEfiCertSha256Guid;
327    break;
328
329  case HASHALG_SHA384:
330    mImageDigestSize = SHA384_DIGEST_SIZE;
331    mCertType        = gEfiCertSha384Guid;
332    break;
333
334  case HASHALG_SHA512:
335    mImageDigestSize = SHA512_DIGEST_SIZE;
336    mCertType        = gEfiCertSha512Guid;
337    break;
338
339  default:
340    return FALSE;
341  }
342
343  CtxSize   = mHash[HashAlg].GetContextSize();
344
345  HashCtx = AllocatePool (CtxSize);
346  if (HashCtx == NULL) {
347    return FALSE;
348  }
349
350  // 1.  Load the image header into memory.
351
352  // 2.  Initialize a SHA hash context.
353  Status = mHash[HashAlg].HashInit(HashCtx);
354
355  if (!Status) {
356    goto Done;
357  }
358
359  //
360  // Measuring PE/COFF Image Header;
361  // But CheckSum field and SECURITY data directory (certificate) are excluded
362  //
363  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
364    //
365    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
366    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
367    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
368    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
369    //
370    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
371  } else {
372    //
373    // Get the magic value from the PE/COFF Optional Header
374    //
375    Magic =  mNtHeader.Pe32->OptionalHeader.Magic;
376  }
377
378  //
379  // 3.  Calculate the distance from the base of the image header to the image checksum address.
380  // 4.  Hash the image header from its base to beginning of the image checksum.
381  //
382  HashBase = mImageBase;
383  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
384    //
385    // Use PE32 offset.
386    //
387    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);
388    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
389  } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
390    //
391    // Use PE32+ offset.
392    //
393    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
394    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
395  } else {
396    //
397    // Invalid header magic number.
398    //
399    Status = FALSE;
400    goto Done;
401  }
402
403  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
404  if (!Status) {
405    goto Done;
406  }
407
408  //
409  // 5.  Skip over the image checksum (it occupies a single ULONG).
410  //
411  if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
412    //
413    // 6.  Since there is no Cert Directory in optional header, hash everything
414    //     from the end of the checksum to the end of image header.
415    //
416    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
417      //
418      // Use PE32 offset.
419      //
420      HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
421      HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
422    } else {
423      //
424      // Use PE32+ offset.
425      //
426      HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
427      HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
428    }
429
430    if (HashSize != 0) {
431      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
432      if (!Status) {
433        goto Done;
434      }
435    }
436  } else {
437    //
438    // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.
439    //
440    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
441      //
442      // Use PE32 offset.
443      //
444      HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
445      HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
446    } else {
447      //
448      // Use PE32+ offset.
449      //
450      HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
451      HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
452    }
453
454    if (HashSize != 0) {
455      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
456      if (!Status) {
457        goto Done;
458      }
459    }
460
461    //
462    // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
463    // 9.  Hash everything from the end of the Cert Directory to the end of image header.
464    //
465    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
466      //
467      // Use PE32 offset
468      //
469      HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
470      HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
471    } else {
472      //
473      // Use PE32+ offset.
474      //
475      HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
476      HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
477    }
478
479    if (HashSize != 0) {
480      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
481      if (!Status) {
482        goto Done;
483      }
484    }
485  }
486
487  //
488  // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
489  //
490  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
491    //
492    // Use PE32 offset.
493    //
494    SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
495  } else {
496    //
497    // Use PE32+ offset
498    //
499    SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
500  }
501
502
503  Section = (EFI_IMAGE_SECTION_HEADER *) (
504               mImageBase +
505               mPeCoffHeaderOffset +
506               sizeof (UINT32) +
507               sizeof (EFI_IMAGE_FILE_HEADER) +
508               mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
509               );
510
511  //
512  // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
513  //     structures in the image. The 'NumberOfSections' field of the image
514  //     header indicates how big the table should be. Do not include any
515  //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
516  //
517  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);
518  if (SectionHeader == NULL) {
519    Status = FALSE;
520    goto Done;
521  }
522  //
523  // 12.  Using the 'PointerToRawData' in the referenced section headers as
524  //      a key, arrange the elements in the table in ascending order. In other
525  //      words, sort the section headers according to the disk-file offset of
526  //      the section.
527  //
528  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
529    Pos = Index;
530    while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
531      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
532      Pos--;
533    }
534    CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
535    Section += 1;
536  }
537
538  //
539  // 13.  Walk through the sorted table, bring the corresponding section
540  //      into memory, and hash the entire section (using the 'SizeOfRawData'
541  //      field in the section header to determine the amount of data to hash).
542  // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
543  // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.
544  //
545  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
546    Section = &SectionHeader[Index];
547    if (Section->SizeOfRawData == 0) {
548      continue;
549    }
550    HashBase  = mImageBase + Section->PointerToRawData;
551    HashSize  = (UINTN) Section->SizeOfRawData;
552
553    Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
554    if (!Status) {
555      goto Done;
556    }
557
558    SumOfBytesHashed += HashSize;
559  }
560
561  //
562  // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
563  //      data in the file that needs to be added to the hash. This data begins
564  //      at file offset SUM_OF_BYTES_HASHED and its length is:
565  //             FileSize  -  (CertDirectory->Size)
566  //
567  if (mImageSize > SumOfBytesHashed) {
568    HashBase = mImageBase + SumOfBytesHashed;
569
570    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
571      CertSize = 0;
572    } else {
573      if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
574        //
575        // Use PE32 offset.
576        //
577        CertSize = mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
578      } else {
579        //
580        // Use PE32+ offset.
581        //
582        CertSize = mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
583      }
584    }
585
586    if (mImageSize > CertSize + SumOfBytesHashed) {
587      HashSize = (UINTN) (mImageSize - CertSize - SumOfBytesHashed);
588
589      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
590      if (!Status) {
591        goto Done;
592      }
593    } else if (mImageSize < CertSize + SumOfBytesHashed) {
594      Status = FALSE;
595      goto Done;
596    }
597  }
598
599  Status  = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);
600
601Done:
602  if (HashCtx != NULL) {
603    FreePool (HashCtx);
604  }
605  if (SectionHeader != NULL) {
606    FreePool (SectionHeader);
607  }
608  return Status;
609}
610
611/**
612  Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
613  Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
614  8.0 Appendix A
615
616  Caution: This function may receive untrusted input.
617  PE/COFF image is external input, so this function will validate its data structure
618  within this image buffer before use.
619
620  @param[in]  AuthData            Pointer to the Authenticode Signature retrieved from signed image.
621  @param[in]  AuthDataSize        Size of the Authenticode Signature in bytes.
622
623  @retval EFI_UNSUPPORTED             Hash algorithm is not supported.
624  @retval EFI_SUCCESS                 Hash successfully.
625
626**/
627EFI_STATUS
628HashPeImageByType (
629  IN UINT8              *AuthData,
630  IN UINTN              AuthDataSize
631  )
632{
633  UINT8                     Index;
634
635  for (Index = 0; Index < HASHALG_MAX; Index++) {
636    //
637    // Check the Hash algorithm in PE/COFF Authenticode.
638    //    According to PKCS#7 Definition:
639    //        SignedData ::= SEQUENCE {
640    //            version Version,
641    //            digestAlgorithms DigestAlgorithmIdentifiers,
642    //            contentInfo ContentInfo,
643    //            .... }
644    //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
645    //    This field has the fixed offset (+32) in final Authenticode ASN.1 data.
646    //    Fixed offset (+32) is calculated based on two bytes of length encoding.
647    //
648    if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
649      //
650      // Only support two bytes of Long Form of Length Encoding.
651      //
652      continue;
653    }
654
655    if (AuthDataSize < 32 + mHash[Index].OidLength) {
656      return EFI_UNSUPPORTED;
657    }
658
659    if (CompareMem (AuthData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
660      break;
661    }
662  }
663
664  if (Index == HASHALG_MAX) {
665    return EFI_UNSUPPORTED;
666  }
667
668  //
669  // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
670  //
671  if (!HashPeImage(Index)) {
672    return EFI_UNSUPPORTED;
673  }
674
675  return EFI_SUCCESS;
676}
677
678
679/**
680  Returns the size of a given image execution info table in bytes.
681
682  This function returns the size, in bytes, of the image execution info table specified by
683  ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
684
685  @param  ImageExeInfoTable          A pointer to a image execution info table structure.
686
687  @retval 0       If ImageExeInfoTable is NULL.
688  @retval Others  The size of a image execution info table in bytes.
689
690**/
691UINTN
692GetImageExeInfoTableSize (
693  EFI_IMAGE_EXECUTION_INFO_TABLE        *ImageExeInfoTable
694  )
695{
696  UINTN                     Index;
697  EFI_IMAGE_EXECUTION_INFO  *ImageExeInfoItem;
698  UINTN                     TotalSize;
699
700  if (ImageExeInfoTable == NULL) {
701    return 0;
702  }
703
704  ImageExeInfoItem  = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoTable + sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE));
705  TotalSize         = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
706  for (Index = 0; Index < ImageExeInfoTable->NumberOfImages; Index++) {
707    TotalSize += ReadUnaligned32 ((UINT32 *) &ImageExeInfoItem->InfoSize);
708    ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoItem + ReadUnaligned32 ((UINT32 *) &ImageExeInfoItem->InfoSize));
709  }
710
711  return TotalSize;
712}
713
714/**
715  Create signature list based on input signature data and certificate type GUID. Caller is reposible
716  to free new created SignatureList.
717
718  @param[in]   SignatureData           Signature data in SignatureList.
719  @param[in]   SignatureDataSize       Signature data size.
720  @param[in]   CertType                Certificate Type.
721  @param[out]  SignatureList           Created SignatureList.
722  @param[out]  SignatureListSize       Created SignatureListSize.
723
724  @return EFI_OUT_OF_RESOURCES         The operation is failed due to lack of resources.
725  @retval EFI_SUCCESS          Successfully create signature list.
726
727**/
728EFI_STATUS
729CreateSignatureList(
730  IN UINT8                *SignatureData,
731  IN UINTN                SignatureDataSize,
732  IN EFI_GUID             *CertType,
733  OUT EFI_SIGNATURE_LIST  **SignatureList,
734  OUT UINTN               *SignatureListSize
735  )
736{
737  EFI_SIGNATURE_LIST   *SignList;
738  UINTN                SignListSize;
739  EFI_SIGNATURE_DATA   *Signature;
740
741  SignList       = NULL;
742  *SignatureList = NULL;
743
744  SignListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + SignatureDataSize;
745  SignList     = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignListSize);
746  if (SignList == NULL) {
747    return EFI_OUT_OF_RESOURCES;
748  }
749
750  SignList->SignatureHeaderSize = 0;
751  SignList->SignatureListSize   = (UINT32) SignListSize;
752  SignList->SignatureSize       = (UINT32) SignatureDataSize + sizeof (EFI_SIGNATURE_DATA) - 1;
753  CopyMem (&SignList->SignatureType, CertType, sizeof (EFI_GUID));
754
755  DEBUG((EFI_D_INFO, "SignatureDataSize %x\n", SignatureDataSize));
756  Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignList + sizeof (EFI_SIGNATURE_LIST));
757  CopyMem (Signature->SignatureData, SignatureData, SignatureDataSize);
758
759  *SignatureList     = SignList;
760  *SignatureListSize = SignListSize;
761
762  return EFI_SUCCESS;
763
764}
765
766/**
767  Create an Image Execution Information Table entry and add it to system configuration table.
768
769  @param[in]  Action          Describes the action taken by the firmware regarding this image.
770  @param[in]  Name            Input a null-terminated, user-friendly name.
771  @param[in]  DevicePath      Input device path pointer.
772  @param[in]  Signature       Input signature info in EFI_SIGNATURE_LIST data structure.
773  @param[in]  SignatureSize   Size of signature.
774
775**/
776VOID
777AddImageExeInfo (
778  IN       EFI_IMAGE_EXECUTION_ACTION       Action,
779  IN       CHAR16                           *Name OPTIONAL,
780  IN CONST EFI_DEVICE_PATH_PROTOCOL         *DevicePath,
781  IN       EFI_SIGNATURE_LIST               *Signature OPTIONAL,
782  IN       UINTN                            SignatureSize
783  )
784{
785  EFI_IMAGE_EXECUTION_INFO_TABLE  *ImageExeInfoTable;
786  EFI_IMAGE_EXECUTION_INFO_TABLE  *NewImageExeInfoTable;
787  EFI_IMAGE_EXECUTION_INFO        *ImageExeInfoEntry;
788  UINTN                           ImageExeInfoTableSize;
789  UINTN                           NewImageExeInfoEntrySize;
790  UINTN                           NameStringLen;
791  UINTN                           DevicePathSize;
792  CHAR16                          *NameStr;
793
794  ImageExeInfoTable     = NULL;
795  NewImageExeInfoTable  = NULL;
796  ImageExeInfoEntry     = NULL;
797  NameStringLen         = 0;
798  NameStr               = NULL;
799
800  if (DevicePath == NULL) {
801    return ;
802  }
803
804  if (Name != NULL) {
805    NameStringLen = StrSize (Name);
806  } else {
807    NameStringLen = sizeof (CHAR16);
808  }
809
810  EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID **) &ImageExeInfoTable);
811  if (ImageExeInfoTable != NULL) {
812    //
813    // The table has been found!
814    // We must enlarge the table to accomodate the new exe info entry.
815    //
816    ImageExeInfoTableSize = GetImageExeInfoTableSize (ImageExeInfoTable);
817  } else {
818    //
819    // Not Found!
820    // We should create a new table to append to the configuration table.
821    //
822    ImageExeInfoTableSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
823  }
824
825  DevicePathSize            = GetDevicePathSize (DevicePath);
826
827  //
828  // Signature size can be odd. Pad after signature to ensure next EXECUTION_INFO entry align
829  //
830  NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;
831
832  NewImageExeInfoTable      = (EFI_IMAGE_EXECUTION_INFO_TABLE *) AllocateRuntimePool (ImageExeInfoTableSize + NewImageExeInfoEntrySize);
833  if (NewImageExeInfoTable == NULL) {
834    return ;
835  }
836
837  if (ImageExeInfoTable != NULL) {
838    CopyMem (NewImageExeInfoTable, ImageExeInfoTable, ImageExeInfoTableSize);
839  } else {
840    NewImageExeInfoTable->NumberOfImages = 0;
841  }
842  NewImageExeInfoTable->NumberOfImages++;
843  ImageExeInfoEntry = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) NewImageExeInfoTable + ImageExeInfoTableSize);
844  //
845  // Update new item's information.
846  //
847  WriteUnaligned32 ((UINT32 *) ImageExeInfoEntry, Action);
848  WriteUnaligned32 ((UINT32 *) ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION)), (UINT32) NewImageExeInfoEntrySize);
849
850  NameStr = (CHAR16 *)(ImageExeInfoEntry + 1);
851  if (Name != NULL) {
852    CopyMem ((UINT8 *) NameStr, Name, NameStringLen);
853  } else {
854    ZeroMem ((UINT8 *) NameStr, sizeof (CHAR16));
855  }
856
857  CopyMem (
858    (UINT8 *) NameStr + NameStringLen,
859    DevicePath,
860    DevicePathSize
861    );
862  if (Signature != NULL) {
863    CopyMem (
864      (UINT8 *) NameStr + NameStringLen + DevicePathSize,
865      Signature,
866      SignatureSize
867      );
868  }
869  //
870  // Update/replace the image execution table.
871  //
872  gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);
873
874  //
875  // Free Old table data!
876  //
877  if (ImageExeInfoTable != NULL) {
878    FreePool (ImageExeInfoTable);
879  }
880}
881
882/**
883  Check whether the hash of an given X.509 certificate is in forbidden database (DBX).
884
885  @param[in]  Certificate       Pointer to X.509 Certificate that is searched for.
886  @param[in]  CertSize          Size of X.509 Certificate.
887  @param[in]  SignatureList     Pointer to the Signature List in forbidden database.
888  @param[in]  SignatureListSize Size of Signature List.
889  @param[out] RevocationTime    Return the time that the certificate was revoked.
890
891  @return TRUE   The certificate hash is found in the forbidden database.
892  @return FALSE  The certificate hash is not found in the forbidden database.
893
894**/
895BOOLEAN
896IsCertHashFoundInDatabase (
897  IN  UINT8               *Certificate,
898  IN  UINTN               CertSize,
899  IN  EFI_SIGNATURE_LIST  *SignatureList,
900  IN  UINTN               SignatureListSize,
901  OUT EFI_TIME            *RevocationTime
902  )
903{
904  BOOLEAN             IsFound;
905  BOOLEAN             Status;
906  EFI_SIGNATURE_LIST  *DbxList;
907  UINTN               DbxSize;
908  EFI_SIGNATURE_DATA  *CertHash;
909  UINTN               CertHashCount;
910  UINTN               Index;
911  UINT32              HashAlg;
912  VOID                *HashCtx;
913  UINT8               CertDigest[MAX_DIGEST_SIZE];
914  UINT8               *DbxCertHash;
915  UINTN               SiglistHeaderSize;
916  UINT8               *TBSCert;
917  UINTN               TBSCertSize;
918
919  IsFound  = FALSE;
920  DbxList  = SignatureList;
921  DbxSize  = SignatureListSize;
922  HashCtx  = NULL;
923  HashAlg  = HASHALG_MAX;
924
925  if ((RevocationTime == NULL) || (DbxList == NULL)) {
926    return FALSE;
927  }
928
929  //
930  // Retrieve the TBSCertificate from the X.509 Certificate.
931  //
932  if (!X509GetTBSCert (Certificate, CertSize, &TBSCert, &TBSCertSize)) {
933    return FALSE;
934  }
935
936  while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {
937    //
938    // Determine Hash Algorithm of Certificate in the forbidden database.
939    //
940    if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {
941      HashAlg = HASHALG_SHA256;
942    } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {
943      HashAlg = HASHALG_SHA384;
944    } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {
945      HashAlg = HASHALG_SHA512;
946    } else {
947      DbxSize -= DbxList->SignatureListSize;
948      DbxList  = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);
949      continue;
950    }
951
952    //
953    // Calculate the hash value of current TBSCertificate for comparision.
954    //
955    if (mHash[HashAlg].GetContextSize == NULL) {
956      goto Done;
957    }
958    ZeroMem (CertDigest, MAX_DIGEST_SIZE);
959    HashCtx = AllocatePool (mHash[HashAlg].GetContextSize ());
960    if (HashCtx == NULL) {
961      goto Done;
962    }
963    Status = mHash[HashAlg].HashInit (HashCtx);
964    if (!Status) {
965      goto Done;
966    }
967    Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);
968    if (!Status) {
969      goto Done;
970    }
971    Status = mHash[HashAlg].HashFinal (HashCtx, CertDigest);
972    if (!Status) {
973      goto Done;
974    }
975
976    SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;
977    CertHash          = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);
978    CertHashCount     = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;
979    for (Index = 0; Index < CertHashCount; Index++) {
980      //
981      // Iterate each Signature Data Node within this CertList for verify.
982      //
983      DbxCertHash = CertHash->SignatureData;
984      if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {
985        //
986        // Hash of Certificate is found in forbidden database.
987        //
988        IsFound = TRUE;
989
990        //
991        // Return the revocation time.
992        //
993        CopyMem (RevocationTime, (EFI_TIME *)(DbxCertHash + mHash[HashAlg].DigestLength), sizeof (EFI_TIME));
994        goto Done;
995      }
996      CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize);
997    }
998
999    DbxSize -= DbxList->SignatureListSize;
1000    DbxList  = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);
1001  }
1002
1003Done:
1004  if (HashCtx != NULL) {
1005    FreePool (HashCtx);
1006  }
1007
1008  return IsFound;
1009}
1010
1011/**
1012  Check whether signature is in specified database.
1013
1014  @param[in]  VariableName        Name of database variable that is searched in.
1015  @param[in]  Signature           Pointer to signature that is searched for.
1016  @param[in]  CertType            Pointer to hash algrithom.
1017  @param[in]  SignatureSize       Size of Signature.
1018
1019  @return TRUE                    Found the signature in the variable database.
1020  @return FALSE                   Not found the signature in the variable database.
1021
1022**/
1023BOOLEAN
1024IsSignatureFoundInDatabase (
1025  IN CHAR16             *VariableName,
1026  IN UINT8              *Signature,
1027  IN EFI_GUID           *CertType,
1028  IN UINTN              SignatureSize
1029  )
1030{
1031  EFI_STATUS          Status;
1032  EFI_SIGNATURE_LIST  *CertList;
1033  EFI_SIGNATURE_DATA  *Cert;
1034  UINTN               DataSize;
1035  UINT8               *Data;
1036  UINTN               Index;
1037  UINTN               CertCount;
1038  BOOLEAN             IsFound;
1039
1040  //
1041  // Read signature database variable.
1042  //
1043  IsFound   = FALSE;
1044  Data      = NULL;
1045  DataSize  = 0;
1046  Status    = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
1047  if (Status != EFI_BUFFER_TOO_SMALL) {
1048    return FALSE;
1049  }
1050
1051  Data = (UINT8 *) AllocateZeroPool (DataSize);
1052  if (Data == NULL) {
1053    return FALSE;
1054  }
1055
1056  Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
1057  if (EFI_ERROR (Status)) {
1058    goto Done;
1059  }
1060  //
1061  // Enumerate all signature data in SigDB to check if executable's signature exists.
1062  //
1063  CertList = (EFI_SIGNATURE_LIST *) Data;
1064  while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
1065    CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1066    Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1067    if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, CertType))) {
1068      for (Index = 0; Index < CertCount; Index++) {
1069        if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {
1070          //
1071          // Find the signature in database.
1072          //
1073          IsFound = TRUE;
1074          SecureBootHook (VariableName, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);
1075          break;
1076        }
1077
1078        Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
1079      }
1080
1081      if (IsFound) {
1082        break;
1083      }
1084    }
1085
1086    DataSize -= CertList->SignatureListSize;
1087    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
1088  }
1089
1090Done:
1091  if (Data != NULL) {
1092    FreePool (Data);
1093  }
1094
1095  return IsFound;
1096}
1097
1098/**
1099  Check whether the timestamp is valid by comparing the signing time and the revocation time.
1100
1101  @param SigningTime         A pointer to the signing time.
1102  @param RevocationTime      A pointer to the revocation time.
1103
1104  @retval  TRUE              The SigningTime is not later than the RevocationTime.
1105  @retval  FALSE             The SigningTime is later than the RevocationTime.
1106
1107**/
1108BOOLEAN
1109IsValidSignatureByTimestamp (
1110  IN EFI_TIME               *SigningTime,
1111  IN EFI_TIME               *RevocationTime
1112  )
1113{
1114  if (SigningTime->Year != RevocationTime->Year) {
1115    return (BOOLEAN) (SigningTime->Year < RevocationTime->Year);
1116  } else if (SigningTime->Month != RevocationTime->Month) {
1117    return (BOOLEAN) (SigningTime->Month < RevocationTime->Month);
1118  } else if (SigningTime->Day != RevocationTime->Day) {
1119    return (BOOLEAN) (SigningTime->Day < RevocationTime->Day);
1120  } else if (SigningTime->Hour != RevocationTime->Hour) {
1121    return (BOOLEAN) (SigningTime->Hour < RevocationTime->Hour);
1122  } else if (SigningTime->Minute != RevocationTime->Minute) {
1123    return (BOOLEAN) (SigningTime->Minute < RevocationTime->Minute);
1124  }
1125
1126  return (BOOLEAN) (SigningTime->Second <= RevocationTime->Second);
1127}
1128
1129/**
1130  Check if the given time value is zero.
1131
1132  @param[in]  Time      Pointer of a time value.
1133
1134  @retval     TRUE      The Time is Zero.
1135  @retval     FALSE     The Time is not Zero.
1136
1137**/
1138BOOLEAN
1139IsTimeZero (
1140  IN EFI_TIME               *Time
1141  )
1142{
1143  if ((Time->Year == 0) && (Time->Month == 0) &&  (Time->Day == 0) &&
1144      (Time->Hour == 0) && (Time->Minute == 0) && (Time->Second == 0)) {
1145    return TRUE;
1146  }
1147
1148  return FALSE;
1149}
1150
1151/**
1152  Record multiple certificate list & verification state of a verified image to
1153  IMAGE_EXECUTION_TABLE.
1154
1155  @param[in]  CertBuf              Certificate list buffer.
1156  @param[in]  CertBufLength        Certificate list buffer.
1157  @param[in]  Action               Certificate list action to be record.
1158  @param[in]  ImageName            Image name.
1159  @param[in]  ImageDevicePath      Image device path.
1160
1161**/
1162VOID
1163RecordCertListToImageExeuctionTable(
1164  IN UINT8                          *CertBuf,
1165  IN UINTN                           CertBufLength,
1166  IN EFI_IMAGE_EXECUTION_ACTION      Action,
1167  IN CHAR16                         *ImageName OPTIONAL,
1168  IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL
1169  )
1170{
1171  UINT8               CertNumber;
1172  UINT8               *CertPtr;
1173  UINTN               Index;
1174  UINT8               *Cert;
1175  UINTN               CertSize;
1176  EFI_STATUS          Status;
1177  EFI_SIGNATURE_LIST  *SignatureList;
1178  UINTN               SignatureListSize;
1179
1180  CertNumber = (UINT8) (*CertBuf);
1181  CertPtr    = CertBuf + 1;
1182  for (Index = 0; Index < CertNumber; Index++) {
1183    CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);
1184    Cert     = (UINT8 *)CertPtr + sizeof (UINT32);
1185
1186    //
1187    // Record all cert in cert chain to be passed
1188    //
1189    Status = CreateSignatureList(Cert, CertSize, &gEfiCertX509Guid, &SignatureList, &SignatureListSize);
1190    if (!EFI_ERROR(Status)) {
1191      AddImageExeInfo (Action, ImageName, ImageDevicePath, SignatureList, SignatureListSize);
1192      FreePool (SignatureList);
1193    }
1194  }
1195}
1196
1197
1198/**
1199  Check whether the timestamp signature is valid and the signing time is also earlier than
1200  the revocation time.
1201
1202  @param[in]  AuthData        Pointer to the Authenticode signature retrieved from signed image.
1203  @param[in]  AuthDataSize    Size of the Authenticode signature in bytes.
1204  @param[in]  RevocationTime  The time that the certificate was revoked.
1205
1206  @retval TRUE      Timestamp signature is valid and signing time is no later than the
1207                    revocation time.
1208  @retval FALSE     Timestamp signature is not valid or the signing time is later than the
1209                    revocation time.
1210
1211**/
1212BOOLEAN
1213PassTimestampCheck (
1214  IN UINT8                  *AuthData,
1215  IN UINTN                  AuthDataSize,
1216  IN EFI_TIME               *RevocationTime
1217  )
1218{
1219  EFI_STATUS                Status;
1220  BOOLEAN                   VerifyStatus;
1221  EFI_SIGNATURE_LIST        *CertList;
1222  EFI_SIGNATURE_DATA        *Cert;
1223  UINT8                     *DbtData;
1224  UINTN                     DbtDataSize;
1225  UINT8                     *RootCert;
1226  UINTN                     RootCertSize;
1227  UINTN                     Index;
1228  UINTN                     CertCount;
1229  EFI_TIME                  SigningTime;
1230
1231  //
1232  // Variable Initialization
1233  //
1234  VerifyStatus      = FALSE;
1235  DbtData           = NULL;
1236  CertList          = NULL;
1237  Cert              = NULL;
1238  RootCert          = NULL;
1239  RootCertSize      = 0;
1240
1241  //
1242  // If RevocationTime is zero, the certificate shall be considered to always be revoked.
1243  //
1244  if (IsTimeZero (RevocationTime)) {
1245    return FALSE;
1246  }
1247
1248  //
1249  // RevocationTime is non-zero, the certificate should be considered to be revoked from that time and onwards.
1250  // Using the dbt to get the trusted TSA certificates.
1251  //
1252  DbtDataSize = 0;
1253  Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, NULL);
1254  if (Status != EFI_BUFFER_TOO_SMALL) {
1255    goto Done;
1256  }
1257  DbtData = (UINT8 *) AllocateZeroPool (DbtDataSize);
1258  if (DbtData == NULL) {
1259    goto Done;
1260  }
1261  Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, (VOID *) DbtData);
1262  if (EFI_ERROR (Status)) {
1263    goto Done;
1264  }
1265
1266  CertList = (EFI_SIGNATURE_LIST *) DbtData;
1267  while ((DbtDataSize > 0) && (DbtDataSize >= CertList->SignatureListSize)) {
1268    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
1269      Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1270      CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1271      for (Index = 0; Index < CertCount; Index++) {
1272        //
1273        // Iterate each Signature Data Node within this CertList for verify.
1274        //
1275        RootCert     = Cert->SignatureData;
1276        RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);
1277        //
1278        // Get the signing time if the timestamp signature is valid.
1279        //
1280        if (ImageTimestampVerify (AuthData, AuthDataSize, RootCert, RootCertSize, &SigningTime)) {
1281          //
1282          // The signer signature is valid only when the signing time is earlier than revocation time.
1283          //
1284          if (IsValidSignatureByTimestamp (&SigningTime, RevocationTime)) {
1285            VerifyStatus = TRUE;
1286            goto Done;
1287          }
1288        }
1289        Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
1290      }
1291    }
1292    DbtDataSize -= CertList->SignatureListSize;
1293    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
1294  }
1295
1296Done:
1297  if (DbtData != NULL) {
1298    FreePool (DbtData);
1299  }
1300
1301  return VerifyStatus;
1302}
1303
1304/**
1305  Check whether the image signature is forbidden by the forbidden database (dbx).
1306  The image is forbidden to load if any certificates for signing are revoked before signing time.
1307
1308  @param[in]  AuthData             Pointer to the Authenticode signature retrieved from the signed image.
1309  @param[in]  AuthDataSize         Size of the Authenticode signature in bytes.
1310  @param[in]  IsAuditMode          Whether system Secure Boot Mode is in AuditMode.
1311  @param[in]  ImageName            Name of the image to verify.
1312  @param[in]  ImageDevicePath      DevicePath of the image to verify.
1313
1314  @retval TRUE              Image is forbidden by dbx.
1315  @retval FALSE             Image is not forbidden by dbx.
1316
1317**/
1318BOOLEAN
1319IsForbiddenByDbx (
1320  IN UINT8                          *AuthData,
1321  IN UINTN                          AuthDataSize,
1322  IN BOOLEAN                        IsAuditMode,
1323  IN CHAR16                         *ImageName OPTIONAL,
1324  IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL
1325  )
1326{
1327  EFI_STATUS                Status;
1328  BOOLEAN                   IsForbidden;
1329  UINT8                     *Data;
1330  UINTN                     DataSize;
1331  EFI_SIGNATURE_LIST        *CertList;
1332  UINTN                     CertListSize;
1333  EFI_SIGNATURE_DATA        *CertData;
1334  UINT8                     *RootCert;
1335  UINTN                     RootCertSize;
1336  UINTN                     CertCount;
1337  UINTN                     Index;
1338  UINT8                     *CertBuffer;
1339  UINTN                     BufferLength;
1340  UINT8                     *TrustedCert;
1341  UINTN                     TrustedCertLength;
1342  UINT8                     CertNumber;
1343  UINT8                     *CertPtr;
1344  UINT8                     *Cert;
1345  UINTN                     CertSize;
1346  EFI_TIME                  RevocationTime;
1347  UINT8                     *SignerCert;
1348  UINTN                     SignerCertLength;
1349  UINT8                     *UnchainCert;
1350  UINTN                     UnchainCertLength;
1351  //
1352  // Variable Initialization
1353  //
1354  IsForbidden       = FALSE;
1355  Data              = NULL;
1356  CertList          = NULL;
1357  CertData          = NULL;
1358  RootCert          = NULL;
1359  RootCertSize      = 0;
1360  Cert              = NULL;
1361  CertBuffer        = NULL;
1362  BufferLength      = 0;
1363  TrustedCert       = NULL;
1364  TrustedCertLength = 0;
1365  SignerCert        = NULL;
1366  SignerCertLength  = 0;
1367  UnchainCert       = NULL;
1368  UnchainCertLength = 0;
1369
1370  //
1371  // The image will not be forbidden if dbx can't be got.
1372  //
1373  DataSize = 0;
1374  Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
1375  if (Status != EFI_BUFFER_TOO_SMALL) {
1376    return IsForbidden;
1377  }
1378  Data = (UINT8 *) AllocateZeroPool (DataSize);
1379  if (Data == NULL) {
1380    return IsForbidden;
1381  }
1382
1383  Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);
1384  if (EFI_ERROR (Status)) {
1385    return IsForbidden;
1386  }
1387
1388  //
1389  // Verify image signature with RAW X509 certificates in DBX database.
1390  // If passed, the image will be forbidden.
1391  //
1392  CertList     = (EFI_SIGNATURE_LIST *) Data;
1393  CertListSize = DataSize;
1394  while ((CertListSize > 0) && (CertListSize >= CertList->SignatureListSize)) {
1395    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
1396      CertData  = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1397      CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1398
1399      for (Index = 0; Index < CertCount; Index++) {
1400        //
1401        // Iterate each Signature Data Node within this CertList for verify.
1402        //
1403        RootCert     = CertData->SignatureData;
1404        RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);
1405
1406        //
1407        // Call AuthenticodeVerify library to Verify Authenticode struct.
1408        //
1409        IsForbidden = AuthenticodeVerify (
1410                        AuthData,
1411                        AuthDataSize,
1412                        RootCert,
1413                        RootCertSize,
1414                        mImageDigest,
1415                        mImageDigestSize
1416                        );
1417        if (IsForbidden) {
1418          SecureBootHook (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, CertData);
1419          goto Done;
1420        }
1421
1422        CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);
1423      }
1424    }
1425
1426    CertListSize -= CertList->SignatureListSize;
1427    CertList      = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
1428  }
1429
1430  //
1431  // Check X.509 Certificate Hash & Possible Timestamp.
1432  //
1433
1434  //
1435  // Retrieve the certificate stack from AuthData
1436  // The output CertStack format will be:
1437  //       UINT8  CertNumber;
1438  //       UINT32 Cert1Length;
1439  //       UINT8  Cert1[];
1440  //       UINT32 Cert2Length;
1441  //       UINT8  Cert2[];
1442  //       ...
1443  //       UINT32 CertnLength;
1444  //       UINT8  Certn[];
1445  //
1446  Pkcs7GetSigners (AuthData, AuthDataSize, &CertBuffer, &BufferLength, &TrustedCert, &TrustedCertLength);
1447  if ((BufferLength == 0) || (CertBuffer == NULL)) {
1448    IsForbidden = TRUE;
1449    goto Done;
1450  }
1451
1452  //
1453  // Check if any hash of certificates embedded in AuthData is in the forbidden database.
1454  //
1455  CertNumber = (UINT8) (*CertBuffer);
1456  CertPtr    = CertBuffer + 1;
1457  for (Index = 0; Index < CertNumber; Index++) {
1458    CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);
1459    Cert     = (UINT8 *)CertPtr + sizeof (UINT32);
1460
1461    if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {
1462      //
1463      // Check the timestamp signature and signing time to determine if the image can be trusted.
1464      //
1465      IsForbidden = TRUE;
1466      if (PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime)) {
1467        IsForbidden = FALSE;
1468      }
1469      goto Done;
1470    }
1471
1472    CertPtr = CertPtr + sizeof (UINT32) + CertSize;
1473  }
1474
1475Done:
1476  if (IsForbidden && IsAuditMode) {
1477    Pkcs7GetCertificatesList(AuthData, AuthDataSize, &SignerCert, &SignerCertLength, &UnchainCert, &UnchainCertLength);
1478
1479    //
1480    // Record all certs in image to be failed
1481    //
1482    if ((SignerCertLength != 0) && (SignerCert != NULL)) {
1483      RecordCertListToImageExeuctionTable(
1484        SignerCert,
1485        SignerCertLength,
1486        EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,
1487        ImageName,
1488        ImageDevicePath
1489        );
1490    }
1491
1492    if ((UnchainCertLength != 0) && (UnchainCert != NULL)) {
1493      RecordCertListToImageExeuctionTable(
1494        UnchainCert,
1495        UnchainCertLength,
1496        EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,
1497        ImageName,
1498        ImageDevicePath
1499        );
1500    }
1501  }
1502
1503  if (Data != NULL) {
1504    FreePool (Data);
1505  }
1506
1507  Pkcs7FreeSigners (CertBuffer);
1508  Pkcs7FreeSigners (TrustedCert);
1509  Pkcs7FreeSigners (SignerCert);
1510  Pkcs7FreeSigners (UnchainCert);
1511
1512  return IsForbidden;
1513}
1514
1515
1516/**
1517  Check whether the image signature can be verified by the trusted certificates in DB database.
1518
1519  @param[in]  AuthData              Pointer to the Authenticode signature retrieved from signed image.
1520  @param[in]  AuthDataSize          Size of the Authenticode signature in bytes.
1521  @param[in]  IsAuditMode           Whether system Secure Boot Mode is in AuditMode.
1522  @param[in]  ImageName             Name of the image to verify.
1523  @param[in]  ImageDevicePath       DevicePath of the image to verify.
1524
1525  @retval TRUE         Image passed verification using certificate in db.
1526  @retval FALSE        Image didn't pass verification using certificate in db.
1527
1528**/
1529BOOLEAN
1530IsAllowedByDb (
1531  IN UINT8                          *AuthData,
1532  IN UINTN                          AuthDataSize,
1533  IN BOOLEAN                        IsAuditMode,
1534  IN CHAR16                         *ImageName OPTIONAL,
1535  IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL
1536  )
1537{
1538  EFI_STATUS                Status;
1539  BOOLEAN                   VerifyStatus;
1540  EFI_SIGNATURE_LIST        *CertList;
1541  EFI_SIGNATURE_DATA        *CertData;
1542  UINTN                     DataSize;
1543  UINT8                     *Data;
1544  UINT8                     *RootCert;
1545  UINTN                     RootCertSize;
1546  UINTN                     Index;
1547  UINTN                     CertCount;
1548  UINTN                     DbxDataSize;
1549  UINT8                     *DbxData;
1550  EFI_TIME                  RevocationTime;
1551  UINT8                     *SignerCert;
1552  UINTN                     SignerCertLength;
1553  UINT8                     *UnchainCert;
1554  UINTN                     UnchainCertLength;
1555
1556  Data              = NULL;
1557  CertList          = NULL;
1558  CertData          = NULL;
1559  RootCert          = NULL;
1560  DbxData           = NULL;
1561  RootCertSize      = 0;
1562  VerifyStatus      = FALSE;
1563  SignerCert        = NULL;
1564  SignerCertLength  = 0;
1565  UnchainCert       = NULL;
1566  UnchainCertLength = 0;
1567
1568  DataSize = 0;
1569  Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
1570  if (Status == EFI_BUFFER_TOO_SMALL) {
1571    Data = (UINT8 *) AllocateZeroPool (DataSize);
1572    if (Data == NULL) {
1573      return VerifyStatus;
1574    }
1575
1576    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);
1577    if (EFI_ERROR (Status)) {
1578      goto Done;
1579    }
1580
1581    //
1582    // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
1583    //
1584    CertList = (EFI_SIGNATURE_LIST *) Data;
1585    while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
1586      if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
1587        CertData  = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1588        CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1589
1590        for (Index = 0; Index < CertCount; Index++) {
1591          //
1592          // Iterate each Signature Data Node within this CertList for verify.
1593          //
1594          RootCert     = CertData->SignatureData;
1595          RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);
1596
1597          //
1598          // Call AuthenticodeVerify library to Verify Authenticode struct.
1599          //
1600          VerifyStatus = AuthenticodeVerify (
1601                           AuthData,
1602                           AuthDataSize,
1603                           RootCert,
1604                           RootCertSize,
1605                           mImageDigest,
1606                           mImageDigestSize
1607                           );
1608          if (VerifyStatus) {
1609            //
1610            // Here We still need to check if this RootCert's Hash is revoked
1611            //
1612            Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL);
1613            if (Status == EFI_BUFFER_TOO_SMALL) {
1614              goto Done;
1615            }
1616            DbxData = (UINT8 *) AllocateZeroPool (DbxDataSize);
1617            if (DbxData == NULL) {
1618              goto Done;
1619            }
1620
1621            Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData);
1622            if (EFI_ERROR (Status)) {
1623              goto Done;
1624            }
1625
1626            if (IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime)) {
1627              //
1628              // Check the timestamp signature and signing time to determine if the image can be trusted.
1629              //
1630              VerifyStatus = PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime);
1631            }
1632
1633            goto Done;
1634          }
1635
1636          CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);
1637        }
1638      }
1639
1640      DataSize -= CertList->SignatureListSize;
1641      CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
1642    }
1643  }
1644
1645Done:
1646
1647  if (VerifyStatus) {
1648    SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, CertData);
1649  }
1650
1651  if (IsAuditMode) {
1652
1653    Pkcs7GetCertificatesList(AuthData, AuthDataSize, &SignerCert, &SignerCertLength, &UnchainCert, &UnchainCertLength);
1654    if (VerifyStatus) {
1655      if ((SignerCertLength != 0) && (SignerCert != NULL)) {
1656        //
1657        // Record all cert in signer's cert chain to be passed
1658        //
1659        RecordCertListToImageExeuctionTable(
1660          SignerCert,
1661          SignerCertLength,
1662          EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED,
1663          ImageName,
1664          ImageDevicePath
1665          );
1666      }
1667
1668      if ((UnchainCertLength != 0) && (UnchainCert != NULL)) {
1669        //
1670        // Record all certs in unchained certificates lists to be failed
1671        //
1672        RecordCertListToImageExeuctionTable(
1673          UnchainCert,
1674          UnchainCertLength,
1675          EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,
1676          ImageName,
1677          ImageDevicePath
1678          );
1679      }
1680    } else {
1681      //
1682      // Record all certs in image to be failed
1683      //
1684      if ((SignerCertLength != 0) && (SignerCert != NULL)) {
1685        RecordCertListToImageExeuctionTable(
1686          SignerCert,
1687          SignerCertLength,
1688          EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,
1689          ImageName,
1690          ImageDevicePath
1691          );
1692      }
1693
1694      if ((UnchainCertLength != 0) && (UnchainCert != NULL)) {
1695        RecordCertListToImageExeuctionTable(
1696          UnchainCert,
1697          UnchainCertLength,
1698          EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,
1699          ImageName,
1700          ImageDevicePath
1701          );
1702      }
1703    }
1704  }
1705
1706
1707  if (Data != NULL) {
1708    FreePool (Data);
1709  }
1710  if (DbxData != NULL) {
1711    FreePool (DbxData);
1712  }
1713
1714  Pkcs7FreeSigners (SignerCert);
1715  Pkcs7FreeSigners (UnchainCert);
1716
1717  return VerifyStatus;
1718}
1719
1720/**
1721  Provide verification service for signed images in AuditMode, which include both signature validation
1722  and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
1723  MSFT Authenticode type signatures are supported.
1724
1725  In this implementation, only verify external executables when in AuditMode.
1726  Executables from FV is bypass, so pass in AuthenticationStatus is ignored. Other authentication status
1727  are record into IMAGE_EXECUTION_TABLE.
1728
1729  The image verification policy is:
1730    If the image is signed,
1731      At least one valid signature or at least one hash value of the image must match a record
1732      in the security database "db", and no valid signature nor any hash value of the image may
1733      be reflected in the security database "dbx".
1734    Otherwise, the image is not signed,
1735      The SHA256 hash value of the image must match a record in the security database "db", and
1736      not be reflected in the security data base "dbx".
1737
1738  Caution: This function may receive untrusted input.
1739  PE/COFF image is external input, so this function will validate its data structure
1740  within this image buffer before use.
1741
1742  @param[in]    AuthenticationStatus
1743                           This is the authentication status returned from the security
1744                           measurement services for the input file.
1745  @param[in]    File       This is a pointer to the device path of the file that is
1746                           being dispatched. This will optionally be used for logging.
1747  @param[in]    FileBuffer File buffer matches the input file device path.
1748  @param[in]    FileSize   Size of File buffer matches the input file device path.
1749  @param[in]    BootPolicy A boot policy that was used to call LoadImage() UEFI service.
1750
1751  @retval EFI_SUCCESS            The authenticate info is sucessfully stored for the file
1752                                 specified by DevicePath and non-NULL FileBuffer
1753  @retval EFI_ACCESS_DENIED      The file specified by File and FileBuffer did not
1754                                 authenticate, and the platform policy dictates that the DXE
1755                                 Foundation many not use File.
1756
1757**/
1758EFI_STATUS
1759EFIAPI
1760ImageVerificationInAuditMode (
1761  IN  UINT32                           AuthenticationStatus,
1762  IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,
1763  IN  VOID                             *FileBuffer,
1764  IN  UINTN                            FileSize,
1765  IN  BOOLEAN                          BootPolicy
1766  )
1767{
1768  EFI_STATUS                           Status;
1769  UINT16                               Magic;
1770  EFI_IMAGE_DOS_HEADER                 *DosHdr;
1771  EFI_SIGNATURE_LIST                   *SignatureList;
1772  EFI_IMAGE_EXECUTION_ACTION           Action;
1773  WIN_CERTIFICATE                      *WinCertificate;
1774  UINT32                               Policy;
1775  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;
1776  UINT32                               NumberOfRvaAndSizes;
1777  WIN_CERTIFICATE_EFI_PKCS             *PkcsCertData;
1778  WIN_CERTIFICATE_UEFI_GUID            *WinCertUefiGuid;
1779  UINT8                                *AuthData;
1780  UINTN                                AuthDataSize;
1781  EFI_IMAGE_DATA_DIRECTORY             *SecDataDir;
1782  UINT32                               OffSet;
1783  CHAR16                               *FilePathStr;
1784  UINTN                                SignatureListSize;
1785
1786  SignatureList     = NULL;
1787  WinCertificate    = NULL;
1788  SecDataDir        = NULL;
1789  PkcsCertData      = NULL;
1790  FilePathStr       = NULL;
1791  Action            = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED;
1792  Status            = EFI_ACCESS_DENIED;
1793
1794
1795  //
1796  // Check the image type and get policy setting.
1797  //
1798  switch (GetImageType (File)) {
1799
1800  case IMAGE_FROM_FV:
1801    Policy = ALWAYS_EXECUTE;
1802    break;
1803
1804  case IMAGE_FROM_OPTION_ROM:
1805    Policy = PcdGet32 (PcdOptionRomImageVerificationPolicy);
1806    break;
1807
1808  case IMAGE_FROM_REMOVABLE_MEDIA:
1809    Policy = PcdGet32 (PcdRemovableMediaImageVerificationPolicy);
1810    break;
1811
1812  case IMAGE_FROM_FIXED_MEDIA:
1813    Policy = PcdGet32 (PcdFixedMediaImageVerificationPolicy);
1814    break;
1815
1816  default:
1817    Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;
1818    break;
1819  }
1820
1821  //
1822  // If policy is always/never execute, return directly.
1823  //
1824  if (Policy == ALWAYS_EXECUTE) {
1825    return EFI_SUCCESS;
1826  }
1827
1828  //
1829  // Get Image Device Path Str
1830  //
1831  FilePathStr = ConvertDevicePathToText (File, FALSE, TRUE);
1832
1833  //
1834  // Authentication failed because of (unspecified) firmware security policy
1835  //
1836  if (Policy == NEVER_EXECUTE) {
1837    //
1838    // No signature, record FilePath/FilePathStr only
1839    //
1840    AddImageExeInfo (EFI_IMAGE_EXECUTION_POLICY_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED, FilePathStr, File, NULL, 0);
1841    goto END;
1842  }
1843
1844  //
1845  // The policy QUERY_USER_ON_SECURITY_VIOLATION and ALLOW_EXECUTE_ON_SECURITY_VIOLATION
1846  // violates the UEFI spec and has been removed.
1847  //
1848  ASSERT (Policy != QUERY_USER_ON_SECURITY_VIOLATION && Policy != ALLOW_EXECUTE_ON_SECURITY_VIOLATION);
1849  if (Policy == QUERY_USER_ON_SECURITY_VIOLATION || Policy == ALLOW_EXECUTE_ON_SECURITY_VIOLATION) {
1850    CpuDeadLoop ();
1851  }
1852
1853  //
1854  // Read the Dos header.
1855  //
1856  if (FileBuffer == NULL) {
1857    Status = EFI_INVALID_PARAMETER;
1858    goto END;
1859  }
1860
1861  mImageBase  = (UINT8 *) FileBuffer;
1862  mImageSize  = FileSize;
1863
1864  ZeroMem (&ImageContext, sizeof (ImageContext));
1865  ImageContext.Handle    = (VOID *) FileBuffer;
1866  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeImageVerificationLibImageRead;
1867
1868  //
1869  // Get information about the image being loaded
1870  //
1871  Status = PeCoffLoaderGetImageInfo (&ImageContext);
1872  if (EFI_ERROR (Status)) {
1873    //
1874    // The information can't be got from the invalid PeImage
1875    //
1876    goto END;
1877  }
1878
1879
1880  DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;
1881  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
1882    //
1883    // DOS image header is present,
1884    // so read the PE header after the DOS image header.
1885    //
1886    mPeCoffHeaderOffset = DosHdr->e_lfanew;
1887  } else {
1888    mPeCoffHeaderOffset = 0;
1889  }
1890
1891  //
1892  // Check PE/COFF image.
1893  //
1894  mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (mImageBase + mPeCoffHeaderOffset);
1895  if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
1896    //
1897    // It is not a valid Pe/Coff file.
1898    //
1899    Status = EFI_ACCESS_DENIED;
1900    goto END;
1901  }
1902
1903  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1904    //
1905    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1906    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1907    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1908    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1909    //
1910    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
1911  } else {
1912    //
1913    // Get the magic value from the PE/COFF Optional Header
1914    //
1915    Magic = mNtHeader.Pe32->OptionalHeader.Magic;
1916  }
1917
1918  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1919    //
1920    // Use PE32 offset.
1921    //
1922    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
1923    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
1924      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1925    }
1926  } else {
1927    //
1928    // Use PE32+ offset.
1929    //
1930    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
1931    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
1932      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
1933    }
1934  }
1935
1936  //
1937  // Start Image Validation.
1938  //
1939  if (SecDataDir == NULL || SecDataDir->Size == 0) {
1940    //
1941    // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db",
1942    // and not be reflected in the security data base "dbx".
1943    //
1944    if (!HashPeImage (HASHALG_SHA256)) {
1945      Status = EFI_ACCESS_DENIED;
1946      goto END;
1947    }
1948
1949    //
1950    // Image Hash is in forbidden database (DBX).
1951    //
1952    if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
1953      //
1954      // Image Hash is in allowed database (DB).
1955      //
1956      if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
1957        Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED;
1958      }
1959    }
1960
1961    //
1962    // Add HASH digest for image without signature
1963    //
1964    Status = CreateSignatureList(mImageDigest, mImageDigestSize, &mCertType, &SignatureList, &SignatureListSize);
1965    if (!EFI_ERROR(Status)) {
1966      AddImageExeInfo (Action, FilePathStr, File, SignatureList, SignatureListSize);
1967      FreePool (SignatureList);
1968    }
1969    goto END;
1970  }
1971
1972  //
1973  // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7
1974  // "Attribute Certificate Table".
1975  // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.
1976  //
1977  for (OffSet = SecDataDir->VirtualAddress;
1978       OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);
1979       OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) {
1980    WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
1981    if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||
1982        (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {
1983      break;
1984    }
1985
1986    //
1987    // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
1988    //
1989    if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
1990      //
1991      // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the
1992      // Authenticode specification.
1993      //
1994      PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;
1995      if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {
1996        break;
1997      }
1998      AuthData   = PkcsCertData->CertData;
1999      AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);
2000    } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
2001      //
2002      // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
2003      //
2004      WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;
2005      if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {
2006        break;
2007      }
2008      if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {
2009        continue;
2010      }
2011      AuthData = WinCertUefiGuid->CertData;
2012      AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
2013    } else {
2014      if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {
2015        break;
2016      }
2017      continue;
2018    }
2019
2020    Status = HashPeImageByType (AuthData, AuthDataSize);
2021    if (EFI_ERROR (Status)) {
2022      continue;
2023    }
2024
2025    Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED;
2026
2027    //
2028    // Check the digital signature against the revoked certificate in forbidden database (dbx).
2029    // Check the digital signature against the valid certificate in allowed database (db).
2030    //
2031    if (!IsForbiddenByDbx (AuthData, AuthDataSize, TRUE, FilePathStr, File)) {
2032      IsAllowedByDb (AuthData, AuthDataSize, TRUE, FilePathStr, File);
2033    }
2034
2035    //
2036    // Check the image's hash value.
2037    //
2038    if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
2039      if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
2040        Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED;
2041      }
2042    }
2043
2044    //
2045    // Add HASH digest for image with signature
2046    //
2047    Status = CreateSignatureList(mImageDigest, mImageDigestSize, &mCertType, &SignatureList, &SignatureListSize);
2048
2049    if (!EFI_ERROR(Status)) {
2050      AddImageExeInfo (Action, FilePathStr, File, SignatureList, SignatureListSize);
2051      FreePool (SignatureList);
2052    } else {
2053      goto END;
2054    }
2055  }
2056
2057
2058  if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {
2059    //
2060    // The Size in Certificate Table or the attribute certicate table is corrupted.
2061    //
2062    Status = EFI_ACCESS_DENIED;
2063  } else {
2064    Status = EFI_SUCCESS;
2065  }
2066
2067END:
2068
2069  if (FilePathStr != NULL) {
2070    FreePool(FilePathStr);
2071    FilePathStr = NULL;
2072  }
2073
2074  return Status;
2075}
2076
2077/**
2078  Provide verification service for signed images, which include both signature validation
2079  and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
2080  MSFT Authenticode type signatures are supported.
2081
2082  In this implementation, only verify external executables when in USER MODE.
2083  Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
2084
2085  The image verification policy is:
2086    If the image is signed,
2087      At least one valid signature or at least one hash value of the image must match a record
2088      in the security database "db", and no valid signature nor any hash value of the image may
2089      be reflected in the security database "dbx".
2090    Otherwise, the image is not signed,
2091      The SHA256 hash value of the image must match a record in the security database "db", and
2092      not be reflected in the security data base "dbx".
2093
2094  Caution: This function may receive untrusted input.
2095  PE/COFF image is external input, so this function will validate its data structure
2096  within this image buffer before use.
2097
2098  @param[in]    AuthenticationStatus
2099                           This is the authentication status returned from the security
2100                           measurement services for the input file.
2101  @param[in]    File       This is a pointer to the device path of the file that is
2102                           being dispatched. This will optionally be used for logging.
2103  @param[in]    FileBuffer File buffer matches the input file device path.
2104  @param[in]    FileSize   Size of File buffer matches the input file device path.
2105  @param[in]    BootPolicy A boot policy that was used to call LoadImage() UEFI service.
2106
2107  @retval EFI_SUCCESS            The file specified by DevicePath and non-NULL
2108                                 FileBuffer did authenticate, and the platform policy dictates
2109                                 that the DXE Foundation may use the file.
2110  @retval EFI_SUCCESS            The device path specified by NULL device path DevicePath
2111                                 and non-NULL FileBuffer did authenticate, and the platform
2112                                 policy dictates that the DXE Foundation may execute the image in
2113                                 FileBuffer.
2114  @retval EFI_OUT_RESOURCE       Fail to allocate memory.
2115  @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
2116                                 the platform policy dictates that File should be placed
2117                                 in the untrusted state. The image has been added to the file
2118                                 execution table.
2119  @retval EFI_ACCESS_DENIED      The file specified by File and FileBuffer did not
2120                                 authenticate, and the platform policy dictates that the DXE
2121                                 Foundation many not use File.
2122
2123**/
2124EFI_STATUS
2125EFIAPI
2126DxeImageVerificationHandler (
2127  IN  UINT32                           AuthenticationStatus,
2128  IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,
2129  IN  VOID                             *FileBuffer,
2130  IN  UINTN                            FileSize,
2131  IN  BOOLEAN                          BootPolicy
2132  )
2133{
2134  EFI_STATUS                           Status;
2135  UINT16                               Magic;
2136  EFI_IMAGE_DOS_HEADER                 *DosHdr;
2137  EFI_STATUS                           VerifyStatus;
2138  EFI_SIGNATURE_LIST                   *SignatureList;
2139  UINTN                                SignatureListSize;
2140  EFI_SIGNATURE_DATA                   *Signature;
2141  EFI_IMAGE_EXECUTION_ACTION           Action;
2142  WIN_CERTIFICATE                      *WinCertificate;
2143  UINT32                               Policy;
2144  UINT8                                *VarData;
2145  UINT8                                SecureBoot;
2146  UINT8                                AuditMode;
2147  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;
2148  UINT32                               NumberOfRvaAndSizes;
2149  WIN_CERTIFICATE_EFI_PKCS             *PkcsCertData;
2150  WIN_CERTIFICATE_UEFI_GUID            *WinCertUefiGuid;
2151  UINT8                                *AuthData;
2152  UINTN                                AuthDataSize;
2153  EFI_IMAGE_DATA_DIRECTORY             *SecDataDir;
2154  UINT32                               OffSet;
2155  CHAR16                               *NameStr;
2156
2157  SignatureList     = NULL;
2158  SignatureListSize = 0;
2159  WinCertificate    = NULL;
2160  SecDataDir        = NULL;
2161  PkcsCertData      = NULL;
2162  Action            = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
2163  Status            = EFI_ACCESS_DENIED;
2164  VerifyStatus      = EFI_ACCESS_DENIED;
2165
2166  GetEfiGlobalVariable2 (EFI_AUDIT_MODE_NAME, (VOID**)&VarData, NULL);
2167  //
2168  // Skip verification if AuditMode variable doesn't exist. AuditMode should always exist
2169  //
2170  if (VarData == NULL) {
2171    return EFI_SUCCESS;
2172  }
2173  AuditMode = *VarData;
2174  FreePool(VarData);
2175
2176  if (AuditMode == AUDIT_MODE_ENABLE) {
2177    return ImageVerificationInAuditMode(AuthenticationStatus, File, FileBuffer, FileSize, BootPolicy);
2178  }
2179
2180  //
2181  // Check the image type and get policy setting.
2182  //
2183  switch (GetImageType (File)) {
2184
2185  case IMAGE_FROM_FV:
2186    Policy = ALWAYS_EXECUTE;
2187    break;
2188
2189  case IMAGE_FROM_OPTION_ROM:
2190    Policy = PcdGet32 (PcdOptionRomImageVerificationPolicy);
2191    break;
2192
2193  case IMAGE_FROM_REMOVABLE_MEDIA:
2194    Policy = PcdGet32 (PcdRemovableMediaImageVerificationPolicy);
2195    break;
2196
2197  case IMAGE_FROM_FIXED_MEDIA:
2198    Policy = PcdGet32 (PcdFixedMediaImageVerificationPolicy);
2199    break;
2200
2201  default:
2202    Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;
2203    break;
2204  }
2205  //
2206  // If policy is always/never execute, return directly.
2207  //
2208  if (Policy == ALWAYS_EXECUTE) {
2209    return EFI_SUCCESS;
2210  } else if (Policy == NEVER_EXECUTE) {
2211    return EFI_ACCESS_DENIED;
2212  }
2213
2214  //
2215  // The policy QUERY_USER_ON_SECURITY_VIOLATION and ALLOW_EXECUTE_ON_SECURITY_VIOLATION
2216  // violates the UEFI spec and has been removed.
2217  //
2218  ASSERT (Policy != QUERY_USER_ON_SECURITY_VIOLATION && Policy != ALLOW_EXECUTE_ON_SECURITY_VIOLATION);
2219  if (Policy == QUERY_USER_ON_SECURITY_VIOLATION || Policy == ALLOW_EXECUTE_ON_SECURITY_VIOLATION) {
2220    CpuDeadLoop ();
2221  }
2222
2223  GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&VarData, NULL);
2224  //
2225  // Skip verification if SecureBoot variable doesn't exist.
2226  //
2227  if (VarData == NULL) {
2228    return EFI_SUCCESS;
2229  }
2230  SecureBoot = *VarData;
2231  FreePool(VarData);
2232
2233  //
2234  // Skip verification if SecureBoot is disabled but not AuditMode
2235  //
2236  if (SecureBoot == SECURE_BOOT_MODE_DISABLE) {
2237    return EFI_SUCCESS;
2238  }
2239
2240  //
2241  // Read the Dos header.
2242  //
2243  if (FileBuffer == NULL) {
2244    return EFI_INVALID_PARAMETER;
2245  }
2246
2247  mImageBase  = (UINT8 *) FileBuffer;
2248  mImageSize  = FileSize;
2249
2250  ZeroMem (&ImageContext, sizeof (ImageContext));
2251  ImageContext.Handle    = (VOID *) FileBuffer;
2252  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeImageVerificationLibImageRead;
2253
2254  //
2255  // Get information about the image being loaded
2256  //
2257  Status = PeCoffLoaderGetImageInfo (&ImageContext);
2258  if (EFI_ERROR (Status)) {
2259    //
2260    // The information can't be got from the invalid PeImage
2261    //
2262    goto Done;
2263  }
2264
2265  Status = EFI_ACCESS_DENIED;
2266
2267  DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;
2268  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
2269    //
2270    // DOS image header is present,
2271    // so read the PE header after the DOS image header.
2272    //
2273    mPeCoffHeaderOffset = DosHdr->e_lfanew;
2274  } else {
2275    mPeCoffHeaderOffset = 0;
2276  }
2277  //
2278  // Check PE/COFF image.
2279  //
2280  mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (mImageBase + mPeCoffHeaderOffset);
2281  if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
2282    //
2283    // It is not a valid Pe/Coff file.
2284    //
2285    goto Done;
2286  }
2287
2288  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2289    //
2290    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
2291    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
2292    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
2293    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
2294    //
2295    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
2296  } else {
2297    //
2298    // Get the magic value from the PE/COFF Optional Header
2299    //
2300    Magic = mNtHeader.Pe32->OptionalHeader.Magic;
2301  }
2302
2303  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2304    //
2305    // Use PE32 offset.
2306    //
2307    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
2308    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
2309      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
2310    }
2311  } else {
2312    //
2313    // Use PE32+ offset.
2314    //
2315    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
2316    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
2317      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
2318    }
2319  }
2320
2321  //
2322  // Start Image Validation.
2323  //
2324  if (SecDataDir == NULL || SecDataDir->Size == 0) {
2325    //
2326    // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db",
2327    // and not be reflected in the security data base "dbx".
2328    //
2329    if (!HashPeImage (HASHALG_SHA256)) {
2330      goto Done;
2331    }
2332
2333    if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
2334      //
2335      // Image Hash is in forbidden database (DBX).
2336      //
2337      goto Done;
2338    }
2339
2340    if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
2341      //
2342      // Image Hash is in allowed database (DB).
2343      //
2344      return EFI_SUCCESS;
2345    }
2346
2347    //
2348    // Image Hash is not found in both forbidden and allowed database.
2349    //
2350    goto Done;
2351  }
2352
2353  //
2354  // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7
2355  // "Attribute Certificate Table".
2356  // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.
2357  //
2358  for (OffSet = SecDataDir->VirtualAddress;
2359       OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);
2360       OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) {
2361    WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
2362    if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||
2363        (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {
2364      break;
2365    }
2366
2367    //
2368    // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
2369    //
2370    if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
2371      //
2372      // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the
2373      // Authenticode specification.
2374      //
2375      PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;
2376      if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {
2377        break;
2378      }
2379      AuthData   = PkcsCertData->CertData;
2380      AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);
2381    } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
2382      //
2383      // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
2384      //
2385      WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;
2386      if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {
2387        break;
2388      }
2389      if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {
2390        continue;
2391      }
2392      AuthData = WinCertUefiGuid->CertData;
2393      AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
2394    } else {
2395      if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {
2396        break;
2397      }
2398      continue;
2399    }
2400
2401    Status = HashPeImageByType (AuthData, AuthDataSize);
2402    if (EFI_ERROR (Status)) {
2403      continue;
2404    }
2405
2406    //
2407    // Check the digital signature against the revoked certificate in forbidden database (dbx).
2408    //
2409    if (IsForbiddenByDbx (AuthData, AuthDataSize, FALSE, NULL, NULL)) {
2410      Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
2411      VerifyStatus = EFI_ACCESS_DENIED;
2412      break;
2413    }
2414
2415    //
2416    // Check the digital signature against the valid certificate in allowed database (db).
2417    //
2418    if (EFI_ERROR (VerifyStatus)) {
2419      if (IsAllowedByDb (AuthData, AuthDataSize, FALSE, NULL, NULL)) {
2420        VerifyStatus = EFI_SUCCESS;
2421      }
2422    }
2423
2424    //
2425    // Check the image's hash value.
2426    //
2427    if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
2428      Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
2429      VerifyStatus = EFI_ACCESS_DENIED;
2430      break;
2431    } else if (EFI_ERROR (VerifyStatus)) {
2432      if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
2433        VerifyStatus = EFI_SUCCESS;
2434      }
2435    }
2436  }
2437
2438  if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {
2439    //
2440    // The Size in Certificate Table or the attribute certicate table is corrupted.
2441    //
2442    VerifyStatus = EFI_ACCESS_DENIED;
2443  }
2444
2445  if (!EFI_ERROR (VerifyStatus)) {
2446    return EFI_SUCCESS;
2447  } else {
2448    Status = EFI_ACCESS_DENIED;
2449    if (Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED || Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {
2450      //
2451      // Get image hash value as executable's signature.
2452      //
2453      SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;
2454      SignatureList     = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignatureListSize);
2455      if (SignatureList == NULL) {
2456        Status = EFI_OUT_OF_RESOURCES;
2457        goto Done;
2458      }
2459      SignatureList->SignatureHeaderSize  = 0;
2460      SignatureList->SignatureListSize    = (UINT32) SignatureListSize;
2461      SignatureList->SignatureSize        = (UINT32) (sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize);
2462      CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));
2463      Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));
2464      CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);
2465    }
2466  }
2467
2468Done:
2469  if (Status != EFI_SUCCESS) {
2470    //
2471    // Policy decides to defer or reject the image; add its information in image executable information table.
2472    //
2473    NameStr = ConvertDevicePathToText (File, FALSE, TRUE);
2474    AddImageExeInfo (Action, NameStr, File, SignatureList, SignatureListSize);
2475    if (NameStr != NULL) {
2476      DEBUG((EFI_D_INFO, "The image doesn't pass verification: %s\n", NameStr));
2477      FreePool(NameStr);
2478    }
2479    Status = EFI_SECURITY_VIOLATION;
2480  }
2481
2482  if (SignatureList != NULL) {
2483    FreePool (SignatureList);
2484  }
2485
2486  return Status;
2487}
2488
2489/**
2490  On Ready To Boot Services Event notification handler.
2491
2492  Add the image execution information table if it is not in system configuration table.
2493
2494  @param[in]  Event     Event whose notification function is being invoked
2495  @param[in]  Context   Pointer to the notification function's context
2496
2497**/
2498VOID
2499EFIAPI
2500OnReadyToBoot (
2501  IN      EFI_EVENT               Event,
2502  IN      VOID                    *Context
2503  )
2504{
2505  EFI_IMAGE_EXECUTION_INFO_TABLE  *ImageExeInfoTable;
2506  UINTN                           ImageExeInfoTableSize;
2507
2508  EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID **) &ImageExeInfoTable);
2509  if (ImageExeInfoTable != NULL) {
2510    return;
2511  }
2512
2513  ImageExeInfoTableSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
2514  ImageExeInfoTable     = (EFI_IMAGE_EXECUTION_INFO_TABLE *) AllocateRuntimePool (ImageExeInfoTableSize);
2515  if (ImageExeInfoTable == NULL) {
2516    return ;
2517  }
2518
2519  ImageExeInfoTable->NumberOfImages = 0;
2520  gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) ImageExeInfoTable);
2521
2522}
2523
2524/**
2525  Register security measurement handler.
2526
2527  @param  ImageHandle   ImageHandle of the loaded driver.
2528  @param  SystemTable   Pointer to the EFI System Table.
2529
2530  @retval EFI_SUCCESS   The handlers were registered successfully.
2531**/
2532EFI_STATUS
2533EFIAPI
2534DxeImageVerificationLibConstructor (
2535  IN EFI_HANDLE        ImageHandle,
2536  IN EFI_SYSTEM_TABLE  *SystemTable
2537  )
2538{
2539  EFI_EVENT            Event;
2540
2541  //
2542  // Register the event to publish the image execution table.
2543  //
2544  EfiCreateEventReadyToBootEx (
2545    TPL_CALLBACK,
2546    OnReadyToBoot,
2547    NULL,
2548    &Event
2549    );
2550
2551  return RegisterSecurity2Handler (
2552          DxeImageVerificationHandler,
2553          EFI_AUTH_OPERATION_VERIFY_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED
2554          );
2555}
2556