Home | History | Annotate | Download | only in SecureBootConfigDxe
      1 /** @file
      2   HII Config Access protocol implementation of SecureBoot configuration module.
      3 
      4 Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "SecureBootConfigImpl.h"
     16 
     17 CHAR16              mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";
     18 
     19 SECUREBOOT_CONFIG_PRIVATE_DATA         mSecureBootConfigPrivateDateTemplate = {
     20   SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,
     21   {
     22     SecureBootExtractConfig,
     23     SecureBootRouteConfig,
     24     SecureBootCallback
     25   }
     26 };
     27 
     28 HII_VENDOR_DEVICE_PATH          mSecureBootHiiVendorDevicePath = {
     29   {
     30     {
     31       HARDWARE_DEVICE_PATH,
     32       HW_VENDOR_DP,
     33       {
     34         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
     35         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
     36       }
     37     },
     38     SECUREBOOT_CONFIG_FORM_SET_GUID
     39   },
     40   {
     41     END_DEVICE_PATH_TYPE,
     42     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     43     {
     44       (UINT8) (END_DEVICE_PATH_LENGTH),
     45       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
     46     }
     47   }
     48 };
     49 
     50 
     51 BOOLEAN mIsEnterSecureBootForm = FALSE;
     52 
     53 //
     54 // OID ASN.1 Value for Hash Algorithms
     55 //
     56 UINT8 mHashOidValue[] = {
     57   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05,         // OBJ_md5
     58   0x2B, 0x0E, 0x03, 0x02, 0x1A,                           // OBJ_sha1
     59   0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,   // OBJ_sha224
     60   0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,   // OBJ_sha256
     61   0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,   // OBJ_sha384
     62   0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,   // OBJ_sha512
     63   };
     64 
     65 HASH_TABLE mHash[] = {
     66   { L"SHA1",   20, &mHashOidValue[8],  5, Sha1GetContextSize,   Sha1Init,   Sha1Update,   Sha1Final  },
     67   { L"SHA224", 28, &mHashOidValue[13], 9, NULL,                 NULL,       NULL,         NULL       },
     68   { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},
     69   { L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},
     70   { L"SHA512", 64, &mHashOidValue[40], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}
     71 };
     72 
     73 //
     74 // Variable Definitions
     75 //
     76 UINT32            mPeCoffHeaderOffset = 0;
     77 WIN_CERTIFICATE   *mCertificate = NULL;
     78 IMAGE_TYPE        mImageType;
     79 UINT8             *mImageBase = NULL;
     80 UINTN             mImageSize = 0;
     81 UINT8             mImageDigest[MAX_DIGEST_SIZE];
     82 UINTN             mImageDigestSize;
     83 EFI_GUID          mCertType;
     84 EFI_IMAGE_SECURITY_DATA_DIRECTORY    *mSecDataDir = NULL;
     85 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  mNtHeader;
     86 
     87 //
     88 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
     89 //
     90 CHAR16* mDerEncodedSuffix[] = {
     91   L".cer",
     92   L".der",
     93   L".crt",
     94   NULL
     95 };
     96 CHAR16* mSupportX509Suffix = L"*.cer/der/crt";
     97 
     98 SECUREBOOT_CONFIG_PRIVATE_DATA  *gSecureBootPrivateData = NULL;
     99 
    100 /**
    101   This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
    102 
    103   @param[in] FileSuffix            The suffix of the input certificate file
    104 
    105   @retval    TRUE           It's a DER-encoded certificate.
    106   @retval    FALSE          It's NOT a DER-encoded certificate.
    107 
    108 **/
    109 BOOLEAN
    110 IsDerEncodeCertificate (
    111   IN CONST CHAR16         *FileSuffix
    112 )
    113 {
    114   UINTN     Index;
    115   for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) {
    116     if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) {
    117       return TRUE;
    118     }
    119   }
    120   return FALSE;
    121 }
    122 
    123 /**
    124   Set Secure Boot option into variable space.
    125 
    126   @param[in] VarValue              The option of Secure Boot.
    127 
    128   @retval    EFI_SUCCESS           The operation is finished successfully.
    129   @retval    Others                Other errors as indicated.
    130 
    131 **/
    132 EFI_STATUS
    133 SaveSecureBootVariable (
    134   IN UINT8                         VarValue
    135   )
    136 {
    137   EFI_STATUS                       Status;
    138 
    139   Status = gRT->SetVariable (
    140              EFI_SECURE_BOOT_ENABLE_NAME,
    141              &gEfiSecureBootEnableDisableGuid,
    142              EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    143              sizeof (UINT8),
    144              &VarValue
    145              );
    146   return Status;
    147 }
    148 
    149 /**
    150   Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
    151   descriptor with the input data. NO authentication is required in this function.
    152 
    153   @param[in, out]   DataSize       On input, the size of Data buffer in bytes.
    154                                    On output, the size of data returned in Data
    155                                    buffer in bytes.
    156   @param[in, out]   Data           On input, Pointer to data buffer to be wrapped or
    157                                    pointer to NULL to wrap an empty payload.
    158                                    On output, Pointer to the new payload date buffer allocated from pool,
    159                                    it's caller's responsibility to free the memory when finish using it.
    160 
    161   @retval EFI_SUCCESS              Create time based payload successfully.
    162   @retval EFI_OUT_OF_RESOURCES     There are not enough memory resourses to create time based payload.
    163   @retval EFI_INVALID_PARAMETER    The parameter is invalid.
    164   @retval Others                   Unexpected error happens.
    165 
    166 **/
    167 EFI_STATUS
    168 CreateTimeBasedPayload (
    169   IN OUT UINTN            *DataSize,
    170   IN OUT UINT8            **Data
    171   )
    172 {
    173   EFI_STATUS                       Status;
    174   UINT8                            *NewData;
    175   UINT8                            *Payload;
    176   UINTN                            PayloadSize;
    177   EFI_VARIABLE_AUTHENTICATION_2    *DescriptorData;
    178   UINTN                            DescriptorSize;
    179   EFI_TIME                         Time;
    180 
    181   if (Data == NULL || DataSize == NULL) {
    182     return EFI_INVALID_PARAMETER;
    183   }
    184 
    185   //
    186   // In Setup mode or Custom mode, the variable does not need to be signed but the
    187   // parameters to the SetVariable() call still need to be prepared as authenticated
    188   // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
    189   // data in it.
    190   //
    191   Payload     = *Data;
    192   PayloadSize = *DataSize;
    193 
    194   DescriptorSize    = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
    195   NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
    196   if (NewData == NULL) {
    197     return EFI_OUT_OF_RESOURCES;
    198   }
    199 
    200   if ((Payload != NULL) && (PayloadSize != 0)) {
    201     CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
    202   }
    203 
    204   DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
    205 
    206   ZeroMem (&Time, sizeof (EFI_TIME));
    207   Status = gRT->GetTime (&Time, NULL);
    208   if (EFI_ERROR (Status)) {
    209     FreePool(NewData);
    210     return Status;
    211   }
    212   Time.Pad1       = 0;
    213   Time.Nanosecond = 0;
    214   Time.TimeZone   = 0;
    215   Time.Daylight   = 0;
    216   Time.Pad2       = 0;
    217   CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
    218 
    219   DescriptorData->AuthInfo.Hdr.dwLength         = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
    220   DescriptorData->AuthInfo.Hdr.wRevision        = 0x0200;
    221   DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
    222   CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);
    223 
    224   if (Payload != NULL) {
    225     FreePool(Payload);
    226   }
    227 
    228   *DataSize = DescriptorSize + PayloadSize;
    229   *Data     = NewData;
    230   return EFI_SUCCESS;
    231 }
    232 
    233 /**
    234   Internal helper function to delete a Variable given its name and GUID, NO authentication
    235   required.
    236 
    237   @param[in]      VariableName            Name of the Variable.
    238   @param[in]      VendorGuid              GUID of the Variable.
    239 
    240   @retval EFI_SUCCESS              Variable deleted successfully.
    241   @retval Others                   The driver failed to start the device.
    242 
    243 **/
    244 EFI_STATUS
    245 DeleteVariable (
    246   IN  CHAR16                    *VariableName,
    247   IN  EFI_GUID                  *VendorGuid
    248   )
    249 {
    250   EFI_STATUS              Status;
    251   VOID*                   Variable;
    252   UINT8                   *Data;
    253   UINTN                   DataSize;
    254   UINT32                  Attr;
    255 
    256   GetVariable2 (VariableName, VendorGuid, &Variable, NULL);
    257   if (Variable == NULL) {
    258     return EFI_SUCCESS;
    259   }
    260   FreePool (Variable);
    261 
    262   Data     = NULL;
    263   DataSize = 0;
    264   Attr     = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
    265              | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
    266 
    267   Status = CreateTimeBasedPayload (&DataSize, &Data);
    268   if (EFI_ERROR (Status)) {
    269     DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
    270     return Status;
    271   }
    272 
    273   Status = gRT->SetVariable (
    274                   VariableName,
    275                   VendorGuid,
    276                   Attr,
    277                   DataSize,
    278                   Data
    279                   );
    280   if (Data != NULL) {
    281     FreePool (Data);
    282   }
    283   return Status;
    284 }
    285 
    286 /**
    287 
    288   Set the platform secure boot mode into "Custom" or "Standard" mode.
    289 
    290   @param[in]   SecureBootMode        New secure boot mode: STANDARD_SECURE_BOOT_MODE or
    291                                      CUSTOM_SECURE_BOOT_MODE.
    292 
    293   @return EFI_SUCCESS                The platform has switched to the special mode successfully.
    294   @return other                      Fail to operate the secure boot mode.
    295 
    296 **/
    297 EFI_STATUS
    298 SetSecureBootMode (
    299   IN     UINT8         SecureBootMode
    300   )
    301 {
    302   return gRT->SetVariable (
    303                 EFI_CUSTOM_MODE_NAME,
    304                 &gEfiCustomModeEnableGuid,
    305                 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    306                 sizeof (UINT8),
    307                 &SecureBootMode
    308                 );
    309 }
    310 
    311 /**
    312   Generate the PK signature list from the X509 Certificate storing file (.cer)
    313 
    314   @param[in]   X509File              FileHandle of X509 Certificate storing file.
    315   @param[out]  PkCert                Point to the data buffer to store the signature list.
    316 
    317   @return EFI_UNSUPPORTED            Unsupported Key Length.
    318   @return EFI_OUT_OF_RESOURCES       There are not enough memory resourses to form the signature list.
    319 
    320 **/
    321 EFI_STATUS
    322 CreatePkX509SignatureList (
    323   IN    EFI_FILE_HANDLE             X509File,
    324   OUT   EFI_SIGNATURE_LIST          **PkCert
    325   )
    326 {
    327   EFI_STATUS              Status;
    328   UINT8                   *X509Data;
    329   UINTN                   X509DataSize;
    330   EFI_SIGNATURE_DATA      *PkCertData;
    331 
    332   X509Data = NULL;
    333   PkCertData = NULL;
    334   X509DataSize = 0;
    335 
    336   Status = ReadFileContent (X509File, (VOID**) &X509Data, &X509DataSize, 0);
    337   if (EFI_ERROR (Status)) {
    338     goto ON_EXIT;
    339   }
    340   ASSERT (X509Data != NULL);
    341 
    342   //
    343   // Allocate space for PK certificate list and initialize it.
    344   // Create PK database entry with SignatureHeaderSize equals 0.
    345   //
    346   *PkCert = (EFI_SIGNATURE_LIST*) AllocateZeroPool (
    347               sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1
    348               + X509DataSize
    349               );
    350   if (*PkCert == NULL) {
    351     Status = EFI_OUT_OF_RESOURCES;
    352     goto ON_EXIT;
    353   }
    354 
    355   (*PkCert)->SignatureListSize   = (UINT32) (sizeof(EFI_SIGNATURE_LIST)
    356                                     + sizeof(EFI_SIGNATURE_DATA) - 1
    357                                     + X509DataSize);
    358   (*PkCert)->SignatureSize       = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
    359   (*PkCert)->SignatureHeaderSize = 0;
    360   CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid);
    361   PkCertData                     = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert)
    362                                                           + sizeof(EFI_SIGNATURE_LIST)
    363                                                           + (*PkCert)->SignatureHeaderSize);
    364   CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);
    365   //
    366   // Fill the PK database with PKpub data from X509 certificate file.
    367   //
    368   CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize);
    369 
    370 ON_EXIT:
    371 
    372   if (X509Data != NULL) {
    373     FreePool (X509Data);
    374   }
    375 
    376   if (EFI_ERROR(Status) && *PkCert != NULL) {
    377     FreePool (*PkCert);
    378     *PkCert = NULL;
    379   }
    380 
    381   return Status;
    382 }
    383 
    384 /**
    385   Enroll new PK into the System without original PK's authentication.
    386 
    387   The SignatureOwner GUID will be the same with PK's vendorguid.
    388 
    389   @param[in] PrivateData     The module's private data.
    390 
    391   @retval   EFI_SUCCESS            New PK enrolled successfully.
    392   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
    393   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
    394 
    395 **/
    396 EFI_STATUS
    397 EnrollPlatformKey (
    398    IN  SECUREBOOT_CONFIG_PRIVATE_DATA*   Private
    399   )
    400 {
    401   EFI_STATUS                      Status;
    402   UINT32                          Attr;
    403   UINTN                           DataSize;
    404   EFI_SIGNATURE_LIST              *PkCert;
    405   UINT16*                         FilePostFix;
    406   UINTN                           NameLength;
    407 
    408   if (Private->FileContext->FileName == NULL) {
    409     return EFI_INVALID_PARAMETER;
    410   }
    411 
    412   PkCert = NULL;
    413 
    414   Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
    415   if (EFI_ERROR (Status)) {
    416     return Status;
    417   }
    418 
    419   //
    420   // Parse the file's postfix. Only support DER encoded X.509 certificate files.
    421   //
    422   NameLength = StrLen (Private->FileContext->FileName);
    423   if (NameLength <= 4) {
    424     return EFI_INVALID_PARAMETER;
    425   }
    426   FilePostFix = Private->FileContext->FileName + NameLength - 4;
    427   if (!IsDerEncodeCertificate(FilePostFix)) {
    428     DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix));
    429     return EFI_INVALID_PARAMETER;
    430   }
    431   DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName));
    432   DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix));
    433 
    434   //
    435   // Prase the selected PK file and generature PK certificate list.
    436   //
    437   Status = CreatePkX509SignatureList (
    438             Private->FileContext->FHandle,
    439             &PkCert
    440             );
    441   if (EFI_ERROR (Status)) {
    442     goto ON_EXIT;
    443   }
    444   ASSERT (PkCert != NULL);
    445 
    446   //
    447   // Set Platform Key variable.
    448   //
    449   Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
    450           | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
    451   DataSize = PkCert->SignatureListSize;
    452   Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert);
    453   if (EFI_ERROR (Status)) {
    454     DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
    455     goto ON_EXIT;
    456   }
    457 
    458   Status = gRT->SetVariable(
    459                   EFI_PLATFORM_KEY_NAME,
    460                   &gEfiGlobalVariableGuid,
    461                   Attr,
    462                   DataSize,
    463                   PkCert
    464                   );
    465   if (EFI_ERROR (Status)) {
    466     if (Status == EFI_OUT_OF_RESOURCES) {
    467       DEBUG ((EFI_D_ERROR, "Enroll PK failed with out of resource.\n"));
    468     }
    469     goto ON_EXIT;
    470   }
    471 
    472 ON_EXIT:
    473 
    474   if (PkCert != NULL) {
    475     FreePool(PkCert);
    476   }
    477 
    478   if (Private->FileContext->FHandle != NULL) {
    479     CloseFile (Private->FileContext->FHandle);
    480     Private->FileContext->FHandle = NULL;
    481   }
    482 
    483   return Status;
    484 }
    485 
    486 /**
    487   Remove the PK variable.
    488 
    489   @retval EFI_SUCCESS    Delete PK successfully.
    490   @retval Others         Could not allow to delete PK.
    491 
    492 **/
    493 EFI_STATUS
    494 DeletePlatformKey (
    495   VOID
    496 )
    497 {
    498   EFI_STATUS Status;
    499 
    500   Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
    501   if (EFI_ERROR (Status)) {
    502     return Status;
    503   }
    504 
    505   Status = DeleteVariable (
    506              EFI_PLATFORM_KEY_NAME,
    507              &gEfiGlobalVariableGuid
    508              );
    509   return Status;
    510 }
    511 
    512 /**
    513   Enroll a new KEK item from public key storing file (*.pbk).
    514 
    515   @param[in] PrivateData           The module's private data.
    516 
    517   @retval   EFI_SUCCESS            New KEK enrolled successfully.
    518   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
    519   @retval   EFI_UNSUPPORTED        Unsupported command.
    520   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
    521 
    522 **/
    523 EFI_STATUS
    524 EnrollRsa2048ToKek (
    525   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
    526   )
    527 {
    528   EFI_STATUS                      Status;
    529   UINT32                          Attr;
    530   UINTN                           DataSize;
    531   EFI_SIGNATURE_LIST              *KekSigList;
    532   UINTN                           KeyBlobSize;
    533   UINT8                           *KeyBlob;
    534   CPL_KEY_INFO                    *KeyInfo;
    535   EFI_SIGNATURE_DATA              *KEKSigData;
    536   UINTN                           KekSigListSize;
    537   UINT8                           *KeyBuffer;
    538   UINTN                           KeyLenInBytes;
    539 
    540   Attr        = 0;
    541   DataSize    = 0;
    542   KeyBuffer   = NULL;
    543   KeyBlobSize = 0;
    544   KeyBlob     = NULL;
    545   KeyInfo     = NULL;
    546   KEKSigData  = NULL;
    547   KekSigList  = NULL;
    548   KekSigListSize = 0;
    549 
    550   //
    551   // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
    552   // First, We have to parse out public key data from the pbk key file.
    553   //
    554   Status = ReadFileContent (
    555              Private->FileContext->FHandle,
    556              (VOID**) &KeyBlob,
    557              &KeyBlobSize,
    558              0
    559              );
    560   if (EFI_ERROR (Status)) {
    561     goto ON_EXIT;
    562   }
    563   ASSERT (KeyBlob != NULL);
    564   KeyInfo = (CPL_KEY_INFO *) KeyBlob;
    565   if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) {
    566     DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n"));
    567     Status = EFI_UNSUPPORTED;
    568     goto ON_EXIT;
    569   }
    570 
    571   //
    572   // Convert the Public key to fix octet string format represented in RSA PKCS#1.
    573   //
    574   KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;
    575   KeyBuffer = AllocateZeroPool (KeyLenInBytes);
    576   if (KeyBuffer == NULL) {
    577     Status = EFI_OUT_OF_RESOURCES;
    578     goto ON_EXIT;
    579   }
    580   Int2OctStr (
    581     (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)),
    582     KeyLenInBytes / sizeof (UINTN),
    583     KeyBuffer,
    584     KeyLenInBytes
    585     );
    586   CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes);
    587 
    588   //
    589   // Form an new EFI_SIGNATURE_LIST.
    590   //
    591   KekSigListSize = sizeof(EFI_SIGNATURE_LIST)
    592                      + sizeof(EFI_SIGNATURE_DATA) - 1
    593                      + WIN_CERT_UEFI_RSA2048_SIZE;
    594 
    595   KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);
    596   if (KekSigList == NULL) {
    597     Status = EFI_OUT_OF_RESOURCES;
    598     goto ON_EXIT;
    599   }
    600 
    601   KekSigList->SignatureListSize   = sizeof(EFI_SIGNATURE_LIST)
    602                                   + sizeof(EFI_SIGNATURE_DATA) - 1
    603                                   + WIN_CERT_UEFI_RSA2048_SIZE;
    604   KekSigList->SignatureHeaderSize = 0;
    605   KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;
    606   CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid);
    607 
    608   KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST));
    609   CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);
    610   CopyMem (
    611     KEKSigData->SignatureData,
    612     KeyBlob + sizeof(CPL_KEY_INFO),
    613     WIN_CERT_UEFI_RSA2048_SIZE
    614     );
    615 
    616   //
    617   // Check if KEK entry has been already existed.
    618   // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
    619   // new KEK to original variable.
    620   //
    621   Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
    622          | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
    623   Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);
    624   if (EFI_ERROR (Status)) {
    625     DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
    626     goto ON_EXIT;
    627   }
    628 
    629   Status = gRT->GetVariable(
    630                   EFI_KEY_EXCHANGE_KEY_NAME,
    631                   &gEfiGlobalVariableGuid,
    632                   NULL,
    633                   &DataSize,
    634                   NULL
    635                   );
    636   if (Status == EFI_BUFFER_TOO_SMALL) {
    637     Attr |= EFI_VARIABLE_APPEND_WRITE;
    638   } else if (Status != EFI_NOT_FOUND) {
    639     goto ON_EXIT;
    640   }
    641 
    642   //
    643   // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
    644   //
    645   Status = gRT->SetVariable(
    646                   EFI_KEY_EXCHANGE_KEY_NAME,
    647                   &gEfiGlobalVariableGuid,
    648                   Attr,
    649                   KekSigListSize,
    650                   KekSigList
    651                   );
    652   if (EFI_ERROR (Status)) {
    653     goto ON_EXIT;
    654   }
    655 
    656 ON_EXIT:
    657 
    658   CloseFile (Private->FileContext->FHandle);
    659   Private->FileContext->FHandle = NULL;
    660 
    661   if (Private->FileContext->FileName != NULL){
    662     FreePool(Private->FileContext->FileName);
    663     Private->FileContext->FileName = NULL;
    664   }
    665 
    666   if (Private->SignatureGUID != NULL) {
    667     FreePool (Private->SignatureGUID);
    668     Private->SignatureGUID = NULL;
    669   }
    670 
    671   if (KeyBlob != NULL) {
    672     FreePool (KeyBlob);
    673   }
    674   if (KeyBuffer != NULL) {
    675     FreePool (KeyBuffer);
    676   }
    677   if (KekSigList != NULL) {
    678     FreePool (KekSigList);
    679   }
    680 
    681   return Status;
    682 }
    683 
    684 /**
    685   Enroll a new KEK item from X509 certificate file.
    686 
    687   @param[in] PrivateData           The module's private data.
    688 
    689   @retval   EFI_SUCCESS            New X509 is enrolled successfully.
    690   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
    691   @retval   EFI_UNSUPPORTED        Unsupported command.
    692   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
    693 
    694 **/
    695 EFI_STATUS
    696 EnrollX509ToKek (
    697   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
    698   )
    699 {
    700   EFI_STATUS                        Status;
    701   UINTN                             X509DataSize;
    702   VOID                              *X509Data;
    703   EFI_SIGNATURE_DATA                *KEKSigData;
    704   EFI_SIGNATURE_LIST                *KekSigList;
    705   UINTN                             DataSize;
    706   UINTN                             KekSigListSize;
    707   UINT32                            Attr;
    708 
    709   X509Data       = NULL;
    710   X509DataSize   = 0;
    711   KekSigList     = NULL;
    712   KekSigListSize = 0;
    713   DataSize       = 0;
    714   KEKSigData     = NULL;
    715 
    716   Status = ReadFileContent (
    717              Private->FileContext->FHandle,
    718              &X509Data,
    719              &X509DataSize,
    720              0
    721              );
    722   if (EFI_ERROR (Status)) {
    723     goto ON_EXIT;
    724   }
    725   ASSERT (X509Data != NULL);
    726 
    727   KekSigListSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
    728   KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);
    729   if (KekSigList == NULL) {
    730     Status = EFI_OUT_OF_RESOURCES;
    731     goto ON_EXIT;
    732   }
    733 
    734   //
    735   // Fill Certificate Database parameters.
    736   //
    737   KekSigList->SignatureListSize   = (UINT32) KekSigListSize;
    738   KekSigList->SignatureHeaderSize = 0;
    739   KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
    740   CopyGuid (&KekSigList->SignatureType, &gEfiCertX509Guid);
    741 
    742   KEKSigData = (EFI_SIGNATURE_DATA*) ((UINT8*) KekSigList + sizeof (EFI_SIGNATURE_LIST));
    743   CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);
    744   CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize);
    745 
    746   //
    747   // Check if KEK been already existed.
    748   // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
    749   // new kek to original variable
    750   //
    751   Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
    752           | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
    753   Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);
    754   if (EFI_ERROR (Status)) {
    755     DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
    756     goto ON_EXIT;
    757   }
    758 
    759   Status = gRT->GetVariable(
    760                   EFI_KEY_EXCHANGE_KEY_NAME,
    761                   &gEfiGlobalVariableGuid,
    762                   NULL,
    763                   &DataSize,
    764                   NULL
    765                   );
    766   if (Status == EFI_BUFFER_TOO_SMALL) {
    767     Attr |= EFI_VARIABLE_APPEND_WRITE;
    768   } else if (Status != EFI_NOT_FOUND) {
    769     goto ON_EXIT;
    770   }
    771 
    772   Status = gRT->SetVariable(
    773                   EFI_KEY_EXCHANGE_KEY_NAME,
    774                   &gEfiGlobalVariableGuid,
    775                   Attr,
    776                   KekSigListSize,
    777                   KekSigList
    778                   );
    779   if (EFI_ERROR (Status)) {
    780     goto ON_EXIT;
    781   }
    782 
    783 ON_EXIT:
    784 
    785   CloseFile (Private->FileContext->FHandle);
    786   if (Private->FileContext->FileName != NULL){
    787     FreePool(Private->FileContext->FileName);
    788     Private->FileContext->FileName = NULL;
    789   }
    790 
    791   Private->FileContext->FHandle = NULL;
    792 
    793   if (Private->SignatureGUID != NULL) {
    794     FreePool (Private->SignatureGUID);
    795     Private->SignatureGUID = NULL;
    796   }
    797 
    798   if (KekSigList != NULL) {
    799     FreePool (KekSigList);
    800   }
    801 
    802   return Status;
    803 }
    804 
    805 /**
    806   Enroll new KEK into the System without PK's authentication.
    807   The SignatureOwner GUID will be Private->SignatureGUID.
    808 
    809   @param[in] PrivateData     The module's private data.
    810 
    811   @retval   EFI_SUCCESS            New KEK enrolled successful.
    812   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
    813   @retval   others                 Fail to enroll KEK data.
    814 
    815 **/
    816 EFI_STATUS
    817 EnrollKeyExchangeKey (
    818   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private
    819   )
    820 {
    821   UINT16*     FilePostFix;
    822   EFI_STATUS  Status;
    823   UINTN       NameLength;
    824 
    825   if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {
    826     return EFI_INVALID_PARAMETER;
    827   }
    828 
    829   Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
    830   if (EFI_ERROR (Status)) {
    831     return Status;
    832   }
    833 
    834   //
    835   // Parse the file's postfix. Supports DER-encoded X509 certificate,
    836   // and .pbk as RSA public key file.
    837   //
    838   NameLength = StrLen (Private->FileContext->FileName);
    839   if (NameLength <= 4) {
    840     return EFI_INVALID_PARAMETER;
    841   }
    842   FilePostFix = Private->FileContext->FileName + NameLength - 4;
    843   if (IsDerEncodeCertificate(FilePostFix)) {
    844     return EnrollX509ToKek (Private);
    845   } else if (CompareMem (FilePostFix, L".pbk",4) == 0) {
    846     return EnrollRsa2048ToKek (Private);
    847   } else {
    848     return EFI_INVALID_PARAMETER;
    849   }
    850 }
    851 
    852 /**
    853   Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
    854   KEK's authentication.
    855 
    856   @param[in] PrivateData     The module's private data.
    857   @param[in] VariableName    Variable name of signature database, must be
    858                              EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
    859 
    860   @retval   EFI_SUCCESS            New X509 is enrolled successfully.
    861   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
    862 
    863 **/
    864 EFI_STATUS
    865 EnrollX509toSigDB (
    866   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
    867   IN CHAR16                         *VariableName
    868   )
    869 {
    870   EFI_STATUS                        Status;
    871   UINTN                             X509DataSize;
    872   VOID                              *X509Data;
    873   EFI_SIGNATURE_LIST                *SigDBCert;
    874   EFI_SIGNATURE_DATA                *SigDBCertData;
    875   VOID                              *Data;
    876   UINTN                             DataSize;
    877   UINTN                             SigDBSize;
    878   UINT32                            Attr;
    879 
    880   X509DataSize  = 0;
    881   SigDBSize     = 0;
    882   DataSize      = 0;
    883   X509Data      = NULL;
    884   SigDBCert     = NULL;
    885   SigDBCertData = NULL;
    886   Data          = NULL;
    887 
    888   Status = ReadFileContent (
    889              Private->FileContext->FHandle,
    890              &X509Data,
    891              &X509DataSize,
    892              0
    893              );
    894   if (EFI_ERROR (Status)) {
    895     goto ON_EXIT;
    896   }
    897   ASSERT (X509Data != NULL);
    898 
    899   SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
    900 
    901   Data = AllocateZeroPool (SigDBSize);
    902   if (Data == NULL) {
    903     Status = EFI_OUT_OF_RESOURCES;
    904     goto ON_EXIT;
    905   }
    906 
    907   //
    908   // Fill Certificate Database parameters.
    909   //
    910   SigDBCert = (EFI_SIGNATURE_LIST*) Data;
    911   SigDBCert->SignatureListSize   = (UINT32) SigDBSize;
    912   SigDBCert->SignatureHeaderSize = 0;
    913   SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
    914   CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid);
    915 
    916   SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST));
    917   CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);
    918   CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize);
    919 
    920   //
    921   // Check if signature database entry has been already existed.
    922   // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
    923   // new signature data to original variable
    924   //
    925   Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
    926           | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
    927   Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);
    928   if (EFI_ERROR (Status)) {
    929     DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
    930     goto ON_EXIT;
    931   }
    932 
    933   Status = gRT->GetVariable(
    934                   VariableName,
    935                   &gEfiImageSecurityDatabaseGuid,
    936                   NULL,
    937                   &DataSize,
    938                   NULL
    939                   );
    940   if (Status == EFI_BUFFER_TOO_SMALL) {
    941     Attr |= EFI_VARIABLE_APPEND_WRITE;
    942   } else if (Status != EFI_NOT_FOUND) {
    943     goto ON_EXIT;
    944   }
    945 
    946   Status = gRT->SetVariable(
    947                   VariableName,
    948                   &gEfiImageSecurityDatabaseGuid,
    949                   Attr,
    950                   SigDBSize,
    951                   Data
    952                   );
    953   if (EFI_ERROR (Status)) {
    954     goto ON_EXIT;
    955   }
    956 
    957 ON_EXIT:
    958 
    959   CloseFile (Private->FileContext->FHandle);
    960   if (Private->FileContext->FileName != NULL){
    961     FreePool(Private->FileContext->FileName);
    962     Private->FileContext->FileName = NULL;
    963   }
    964 
    965   Private->FileContext->FHandle = NULL;
    966 
    967   if (Private->SignatureGUID != NULL) {
    968     FreePool (Private->SignatureGUID);
    969     Private->SignatureGUID = NULL;
    970   }
    971 
    972   if (Data != NULL) {
    973     FreePool (Data);
    974   }
    975 
    976   if (X509Data != NULL) {
    977     FreePool (X509Data);
    978   }
    979 
    980   return Status;
    981 }
    982 
    983 /**
    984   Check whether signature is in specified database.
    985 
    986   @param[in]  VariableName        Name of database variable that is searched in.
    987   @param[in]  Signature           Pointer to signature that is searched for.
    988   @param[in]  SignatureSize       Size of Signature.
    989 
    990   @return TRUE                    Found the signature in the variable database.
    991   @return FALSE                   Not found the signature in the variable database.
    992 
    993 **/
    994 BOOLEAN
    995 IsSignatureFoundInDatabase (
    996   IN CHAR16             *VariableName,
    997   IN UINT8              *Signature,
    998   IN UINTN              SignatureSize
    999   )
   1000 {
   1001   EFI_STATUS          Status;
   1002   EFI_SIGNATURE_LIST  *CertList;
   1003   EFI_SIGNATURE_DATA  *Cert;
   1004   UINTN               DataSize;
   1005   UINT8               *Data;
   1006   UINTN               Index;
   1007   UINTN               CertCount;
   1008   BOOLEAN             IsFound;
   1009 
   1010   //
   1011   // Read signature database variable.
   1012   //
   1013   IsFound   = FALSE;
   1014   Data      = NULL;
   1015   DataSize  = 0;
   1016   Status    = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
   1017   if (Status != EFI_BUFFER_TOO_SMALL) {
   1018     return FALSE;
   1019   }
   1020 
   1021   Data = (UINT8 *) AllocateZeroPool (DataSize);
   1022   if (Data == NULL) {
   1023     return FALSE;
   1024   }
   1025 
   1026   Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
   1027   if (EFI_ERROR (Status)) {
   1028     goto Done;
   1029   }
   1030 
   1031   //
   1032   // Enumerate all signature data in SigDB to check if executable's signature exists.
   1033   //
   1034   CertList = (EFI_SIGNATURE_LIST *) Data;
   1035   while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
   1036     CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
   1037     Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
   1038     if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, &gEfiCertX509Guid))) {
   1039       for (Index = 0; Index < CertCount; Index++) {
   1040         if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {
   1041           //
   1042           // Find the signature in database.
   1043           //
   1044           IsFound = TRUE;
   1045           break;
   1046         }
   1047         Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
   1048       }
   1049 
   1050       if (IsFound) {
   1051         break;
   1052       }
   1053     }
   1054 
   1055     DataSize -= CertList->SignatureListSize;
   1056     CertList  = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
   1057   }
   1058 
   1059 Done:
   1060   if (Data != NULL) {
   1061     FreePool (Data);
   1062   }
   1063 
   1064   return IsFound;
   1065 }
   1066 
   1067 /**
   1068   Calculate the hash of a certificate data with the specified hash algorithm.
   1069 
   1070   @param[in]    CertData  The certificate data to be hashed.
   1071   @param[in]    CertSize  The certificate size in bytes.
   1072   @param[in]    HashAlg   The specified hash algorithm.
   1073   @param[out]   CertHash  The output digest of the certificate
   1074 
   1075   @retval TRUE            Successfully got the hash of the CertData.
   1076   @retval FALSE           Failed to get the hash of CertData.
   1077 
   1078 **/
   1079 BOOLEAN
   1080 CalculateCertHash (
   1081   IN  UINT8                 *CertData,
   1082   IN  UINTN                 CertSize,
   1083   IN  UINT32                HashAlg,
   1084   OUT UINT8                 *CertHash
   1085   )
   1086 {
   1087   BOOLEAN                   Status;
   1088   VOID                      *HashCtx;
   1089   UINTN                     CtxSize;
   1090   UINT8                     *TBSCert;
   1091   UINTN                     TBSCertSize;
   1092 
   1093   HashCtx = NULL;
   1094   Status  = FALSE;
   1095 
   1096   if (HashAlg >= HASHALG_MAX) {
   1097     return FALSE;
   1098   }
   1099 
   1100   //
   1101   // Retrieve the TBSCertificate for Hash Calculation.
   1102   //
   1103   if (!X509GetTBSCert (CertData, CertSize, &TBSCert, &TBSCertSize)) {
   1104     return FALSE;
   1105   }
   1106 
   1107   //
   1108   // 1. Initialize context of hash.
   1109   //
   1110   CtxSize = mHash[HashAlg].GetContextSize ();
   1111   HashCtx = AllocatePool (CtxSize);
   1112   ASSERT (HashCtx != NULL);
   1113 
   1114   //
   1115   // 2. Initialize a hash context.
   1116   //
   1117   Status = mHash[HashAlg].HashInit (HashCtx);
   1118   if (!Status) {
   1119     goto Done;
   1120   }
   1121 
   1122   //
   1123   // 3. Calculate the hash.
   1124   //
   1125   Status  = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);
   1126   if (!Status) {
   1127     goto Done;
   1128   }
   1129 
   1130   //
   1131   // 4. Get the hash result.
   1132   //
   1133   ZeroMem (CertHash, mHash[HashAlg].DigestLength);
   1134   Status  = mHash[HashAlg].HashFinal (HashCtx, CertHash);
   1135 
   1136 Done:
   1137   if (HashCtx != NULL) {
   1138     FreePool (HashCtx);
   1139   }
   1140 
   1141   return Status;
   1142 }
   1143 
   1144 /**
   1145   Check whether the hash of an X.509 certificate is in forbidden database (DBX).
   1146 
   1147   @param[in]  Certificate       Pointer to X.509 Certificate that is searched for.
   1148   @param[in]  CertSize          Size of X.509 Certificate.
   1149 
   1150   @return TRUE               Found the certificate hash in the forbidden database.
   1151   @return FALSE              Certificate hash is Not found in the forbidden database.
   1152 
   1153 **/
   1154 BOOLEAN
   1155 IsCertHashFoundInDbx (
   1156   IN  UINT8               *Certificate,
   1157   IN  UINTN               CertSize
   1158   )
   1159 {
   1160   BOOLEAN                 IsFound;
   1161   EFI_STATUS              Status;
   1162   EFI_SIGNATURE_LIST      *DbxList;
   1163   EFI_SIGNATURE_DATA      *CertHash;
   1164   UINTN                   CertHashCount;
   1165   UINTN                   Index;
   1166   UINT32                  HashAlg;
   1167   UINT8                   CertDigest[MAX_DIGEST_SIZE];
   1168   UINT8                   *DbxCertHash;
   1169   UINTN                   SiglistHeaderSize;
   1170   UINT8                   *Data;
   1171   UINTN                   DataSize;
   1172 
   1173   IsFound  = FALSE;
   1174   HashAlg  = HASHALG_MAX;
   1175   Data     = NULL;
   1176 
   1177   //
   1178   // Read signature database variable.
   1179   //
   1180   DataSize  = 0;
   1181   Status    = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
   1182   if (Status != EFI_BUFFER_TOO_SMALL) {
   1183     return FALSE;
   1184   }
   1185 
   1186   Data = (UINT8 *) AllocateZeroPool (DataSize);
   1187   if (Data == NULL) {
   1188     return FALSE;
   1189   }
   1190 
   1191   Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
   1192   if (EFI_ERROR (Status)) {
   1193     goto Done;
   1194   }
   1195 
   1196   //
   1197   // Check whether the certificate hash exists in the forbidden database.
   1198   //
   1199   DbxList = (EFI_SIGNATURE_LIST *) Data;
   1200   while ((DataSize > 0) && (DataSize >= DbxList->SignatureListSize)) {
   1201     //
   1202     // Determine Hash Algorithm of Certificate in the forbidden database.
   1203     //
   1204     if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {
   1205       HashAlg = HASHALG_SHA256;
   1206     } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {
   1207       HashAlg = HASHALG_SHA384;
   1208     } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {
   1209       HashAlg = HASHALG_SHA512;
   1210     } else {
   1211       DataSize -= DbxList->SignatureListSize;
   1212       DbxList   = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);
   1213       continue;
   1214     }
   1215 
   1216     //
   1217     // Calculate the hash value of current db certificate for comparision.
   1218     //
   1219     if (!CalculateCertHash (Certificate, CertSize, HashAlg, CertDigest)) {
   1220       goto Done;
   1221     }
   1222 
   1223     SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;
   1224     CertHash          = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);
   1225     CertHashCount     = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;
   1226     for (Index = 0; Index < CertHashCount; Index++) {
   1227       //
   1228       // Iterate each Signature Data Node within this CertList for verify.
   1229       //
   1230       DbxCertHash = CertHash->SignatureData;
   1231       if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {
   1232         //
   1233         // Hash of Certificate is found in forbidden database.
   1234         //
   1235         IsFound = TRUE;
   1236         goto Done;
   1237       }
   1238       CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize);
   1239     }
   1240 
   1241     DataSize -= DbxList->SignatureListSize;
   1242     DbxList   = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);
   1243   }
   1244 
   1245 Done:
   1246   if (Data != NULL) {
   1247     FreePool (Data);
   1248   }
   1249 
   1250   return IsFound;
   1251 }
   1252 
   1253 /**
   1254   Check whether the signature list exists in given variable data.
   1255 
   1256   It searches the signature list for the ceritificate hash by CertType.
   1257   If the signature list is found, get the offset of Database for the
   1258   next hash of a certificate.
   1259 
   1260   @param[in]  Database      Variable data to save signature list.
   1261   @param[in]  DatabaseSize  Variable size.
   1262   @param[in]  SignatureType The type of the signature.
   1263   @param[out] Offset        The offset to save a new hash of certificate.
   1264 
   1265   @return TRUE       The signature list is found in the forbidden database.
   1266   @return FALSE      The signature list is not found in the forbidden database.
   1267 **/
   1268 BOOLEAN
   1269 GetSignaturelistOffset (
   1270   IN  EFI_SIGNATURE_LIST  *Database,
   1271   IN  UINTN               DatabaseSize,
   1272   IN  EFI_GUID            *SignatureType,
   1273   OUT UINTN               *Offset
   1274   )
   1275 {
   1276   EFI_SIGNATURE_LIST      *SigList;
   1277   UINTN                   SiglistSize;
   1278 
   1279   if ((Database == NULL) || (DatabaseSize == 0)) {
   1280     *Offset = 0;
   1281     return FALSE;
   1282   }
   1283 
   1284   SigList     = Database;
   1285   SiglistSize = DatabaseSize;
   1286   while ((SiglistSize > 0) && (SiglistSize >= SigList->SignatureListSize)) {
   1287     if (CompareGuid (&SigList->SignatureType, SignatureType)) {
   1288       *Offset = DatabaseSize - SiglistSize;
   1289       return TRUE;
   1290     }
   1291     SiglistSize -= SigList->SignatureListSize;
   1292     SigList      = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);
   1293   }
   1294   *Offset = 0;
   1295   return FALSE;
   1296 }
   1297 
   1298 /**
   1299   Enroll a new X509 certificate hash into Signature Database (dbx) without
   1300   KEK's authentication.
   1301 
   1302   @param[in] PrivateData      The module's private data.
   1303   @param[in] HashAlg          The hash algorithm to enroll the certificate.
   1304   @param[in] RevocationDate   The revocation date of the certificate.
   1305   @param[in] RevocationTime   The revocation time of the certificate.
   1306   @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
   1307 
   1308   @retval   EFI_SUCCESS            New X509 is enrolled successfully.
   1309   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
   1310   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
   1311 
   1312 **/
   1313 EFI_STATUS
   1314 EnrollX509HashtoSigDB (
   1315   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
   1316   IN UINT32                         HashAlg,
   1317   IN EFI_HII_DATE                   *RevocationDate,
   1318   IN EFI_HII_TIME                   *RevocationTime,
   1319   IN BOOLEAN                        AlwaysRevocation
   1320   )
   1321 {
   1322   EFI_STATUS          Status;
   1323   UINTN               X509DataSize;
   1324   VOID                *X509Data;
   1325   EFI_SIGNATURE_LIST  *SignatureList;
   1326   UINTN               SignatureListSize;
   1327   UINT8               *Data;
   1328   UINT8               *NewData;
   1329   UINTN               DataSize;
   1330   UINTN               DbSize;
   1331   UINT32              Attr;
   1332   EFI_SIGNATURE_DATA  *SignatureData;
   1333   UINTN               SignatureSize;
   1334   EFI_GUID            SignatureType;
   1335   UINTN               Offset;
   1336   UINT8               CertHash[MAX_DIGEST_SIZE];
   1337   UINT16*             FilePostFix;
   1338   UINTN               NameLength;
   1339   EFI_TIME            *Time;
   1340 
   1341   X509DataSize  = 0;
   1342   DbSize        = 0;
   1343   X509Data      = NULL;
   1344   SignatureData = NULL;
   1345   SignatureList = NULL;
   1346   Data          = NULL;
   1347   NewData       = NULL;
   1348 
   1349   if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {
   1350     return EFI_INVALID_PARAMETER;
   1351   }
   1352 
   1353   Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
   1354   if (EFI_ERROR (Status)) {
   1355     return Status;
   1356   }
   1357 
   1358   //
   1359   // Parse the file's postfix.
   1360   //
   1361   NameLength = StrLen (Private->FileContext->FileName);
   1362   if (NameLength <= 4) {
   1363     return EFI_INVALID_PARAMETER;
   1364   }
   1365   FilePostFix = Private->FileContext->FileName + NameLength - 4;
   1366   if (!IsDerEncodeCertificate(FilePostFix)) {
   1367     //
   1368     // Only supports DER-encoded X509 certificate.
   1369     //
   1370     return EFI_INVALID_PARAMETER;
   1371   }
   1372 
   1373   //
   1374   // Get the certificate from file and calculate its hash.
   1375   //
   1376   Status = ReadFileContent (
   1377              Private->FileContext->FHandle,
   1378              &X509Data,
   1379              &X509DataSize,
   1380              0
   1381              );
   1382   if (EFI_ERROR (Status)) {
   1383     goto ON_EXIT;
   1384   }
   1385   ASSERT (X509Data != NULL);
   1386 
   1387   if (!CalculateCertHash (X509Data, X509DataSize, HashAlg, CertHash)) {
   1388     goto ON_EXIT;
   1389   }
   1390 
   1391   //
   1392   // Get the variable for enrollment.
   1393   //
   1394   DataSize = 0;
   1395   Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
   1396   if (Status == EFI_BUFFER_TOO_SMALL) {
   1397     Data = (UINT8 *) AllocateZeroPool (DataSize);
   1398     if (Data == NULL) {
   1399       return EFI_OUT_OF_RESOURCES;
   1400     }
   1401 
   1402     Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
   1403     if (EFI_ERROR (Status)) {
   1404       goto ON_EXIT;
   1405     }
   1406   }
   1407 
   1408   //
   1409   // Allocate memory for Signature and fill the Signature
   1410   //
   1411   SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + sizeof (EFI_TIME) + mHash[HashAlg].DigestLength;
   1412   SignatureData = (EFI_SIGNATURE_DATA *) AllocateZeroPool (SignatureSize);
   1413   if (SignatureData == NULL) {
   1414     return EFI_OUT_OF_RESOURCES;
   1415   }
   1416   CopyGuid (&SignatureData->SignatureOwner, Private->SignatureGUID);
   1417   CopyMem (SignatureData->SignatureData, CertHash, mHash[HashAlg].DigestLength);
   1418 
   1419   //
   1420   // Fill the time.
   1421   //
   1422   if (!AlwaysRevocation) {
   1423     Time = (EFI_TIME *)(&SignatureData->SignatureData + mHash[HashAlg].DigestLength);
   1424     Time->Year   = RevocationDate->Year;
   1425     Time->Month  = RevocationDate->Month;
   1426     Time->Day    = RevocationDate->Day;
   1427     Time->Hour   = RevocationTime->Hour;
   1428     Time->Minute = RevocationTime->Minute;
   1429     Time->Second = RevocationTime->Second;
   1430   }
   1431 
   1432   //
   1433   // Determine the GUID for certificate hash.
   1434   //
   1435   switch (HashAlg) {
   1436   case HASHALG_SHA256:
   1437     SignatureType = gEfiCertX509Sha256Guid;
   1438     break;
   1439   case HASHALG_SHA384:
   1440     SignatureType = gEfiCertX509Sha384Guid;
   1441     break;
   1442   case HASHALG_SHA512:
   1443     SignatureType = gEfiCertX509Sha512Guid;
   1444     break;
   1445   default:
   1446     return FALSE;
   1447   }
   1448 
   1449   //
   1450   // Add signature into the new variable data buffer
   1451   //
   1452   if (GetSignaturelistOffset((EFI_SIGNATURE_LIST *)Data, DataSize, &SignatureType, &Offset)) {
   1453     //
   1454     // Add the signature to the found signaturelist.
   1455     //
   1456     DbSize  = DataSize + SignatureSize;
   1457     NewData = AllocateZeroPool (DbSize);
   1458     if (NewData == NULL) {
   1459       Status = EFI_OUT_OF_RESOURCES;
   1460       goto ON_EXIT;
   1461     }
   1462 
   1463     SignatureList     = (EFI_SIGNATURE_LIST *)(Data + Offset);
   1464     SignatureListSize = (UINTN) ReadUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize);
   1465     CopyMem (NewData, Data, Offset + SignatureListSize);
   1466 
   1467     SignatureList = (EFI_SIGNATURE_LIST *)(NewData + Offset);
   1468     WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32)(SignatureListSize + SignatureSize));
   1469 
   1470     Offset += SignatureListSize;
   1471     CopyMem (NewData + Offset, SignatureData, SignatureSize);
   1472     CopyMem (NewData + Offset + SignatureSize, Data + Offset, DataSize - Offset);
   1473 
   1474     FreePool (Data);
   1475     Data     = NewData;
   1476     DataSize = DbSize;
   1477   } else {
   1478     //
   1479     // Create a new signaturelist, and add the signature into the signaturelist.
   1480     //
   1481     DbSize  = DataSize + sizeof(EFI_SIGNATURE_LIST) + SignatureSize;
   1482     NewData = AllocateZeroPool (DbSize);
   1483     if (NewData == NULL) {
   1484       Status = EFI_OUT_OF_RESOURCES;
   1485       goto ON_EXIT;
   1486     }
   1487     //
   1488     // Fill Certificate Database parameters.
   1489     //
   1490     SignatureList     = (EFI_SIGNATURE_LIST*) (NewData + DataSize);
   1491     SignatureListSize = sizeof(EFI_SIGNATURE_LIST) + SignatureSize;
   1492     WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32) SignatureListSize);
   1493     WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureSize, (UINT32) SignatureSize);
   1494     CopyGuid (&SignatureList->SignatureType, &SignatureType);
   1495     CopyMem ((UINT8* ) SignatureList + sizeof (EFI_SIGNATURE_LIST), SignatureData, SignatureSize);
   1496     if ((DataSize != 0) && (Data != NULL)) {
   1497       CopyMem (NewData, Data, DataSize);
   1498       FreePool (Data);
   1499     }
   1500     Data     = NewData;
   1501     DataSize = DbSize;
   1502   }
   1503 
   1504   Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &Data);
   1505   if (EFI_ERROR (Status)) {
   1506     goto ON_EXIT;
   1507   }
   1508 
   1509   Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
   1510           | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
   1511   Status = gRT->SetVariable(
   1512                   EFI_IMAGE_SECURITY_DATABASE1,
   1513                   &gEfiImageSecurityDatabaseGuid,
   1514                   Attr,
   1515                   DataSize,
   1516                   Data
   1517                   );
   1518   if (EFI_ERROR (Status)) {
   1519     goto ON_EXIT;
   1520   }
   1521 
   1522 ON_EXIT:
   1523   CloseFile (Private->FileContext->FHandle);
   1524   if (Private->FileContext->FileName != NULL){
   1525     FreePool(Private->FileContext->FileName);
   1526     Private->FileContext->FileName = NULL;
   1527   }
   1528 
   1529   Private->FileContext->FHandle = NULL;
   1530 
   1531   if (Private->SignatureGUID != NULL) {
   1532     FreePool (Private->SignatureGUID);
   1533     Private->SignatureGUID = NULL;
   1534   }
   1535 
   1536   if (Data != NULL) {
   1537     FreePool (Data);
   1538   }
   1539 
   1540   if (SignatureData != NULL) {
   1541     FreePool (SignatureData);
   1542   }
   1543 
   1544   if (X509Data != NULL) {
   1545     FreePool (X509Data);
   1546   }
   1547 
   1548   return Status;
   1549 }
   1550 
   1551 /**
   1552   Check whether a certificate from a file exists in dbx.
   1553 
   1554   @param[in] PrivateData     The module's private data.
   1555   @param[in] VariableName    Variable name of signature database, must be
   1556                              EFI_IMAGE_SECURITY_DATABASE1.
   1557 
   1558   @retval   TRUE             The X509 certificate is found in dbx successfully.
   1559   @retval   FALSE            The X509 certificate is not found in dbx.
   1560 **/
   1561 BOOLEAN
   1562 IsX509CertInDbx (
   1563   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
   1564   IN CHAR16                         *VariableName
   1565   )
   1566 {
   1567   EFI_STATUS          Status;
   1568   UINTN               X509DataSize;
   1569   VOID                *X509Data;
   1570   BOOLEAN             IsFound;
   1571 
   1572   //
   1573   //  Read the certificate from file
   1574   //
   1575   X509DataSize  = 0;
   1576   X509Data      = NULL;
   1577   Status = ReadFileContent (
   1578              Private->FileContext->FHandle,
   1579              &X509Data,
   1580              &X509DataSize,
   1581              0
   1582              );
   1583   if (EFI_ERROR (Status)) {
   1584     return FALSE;
   1585   }
   1586 
   1587   //
   1588   // Check the raw certificate.
   1589   //
   1590   IsFound = FALSE;
   1591   if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, X509Data, X509DataSize)) {
   1592     IsFound = TRUE;
   1593     goto ON_EXIT;
   1594   }
   1595 
   1596   //
   1597   // Check the hash of certificate.
   1598   //
   1599   if (IsCertHashFoundInDbx (X509Data, X509DataSize)) {
   1600     IsFound = TRUE;
   1601     goto ON_EXIT;
   1602   }
   1603 
   1604 ON_EXIT:
   1605   if (X509Data != NULL) {
   1606     FreePool (X509Data);
   1607   }
   1608 
   1609   return IsFound;
   1610 }
   1611 
   1612 /**
   1613   Reads contents of a PE/COFF image in memory buffer.
   1614 
   1615   Caution: This function may receive untrusted input.
   1616   PE/COFF image is external input, so this function will make sure the PE/COFF image content
   1617   read is within the image buffer.
   1618 
   1619   @param  FileHandle      Pointer to the file handle to read the PE/COFF image.
   1620   @param  FileOffset      Offset into the PE/COFF image to begin the read operation.
   1621   @param  ReadSize        On input, the size in bytes of the requested read operation.
   1622                           On output, the number of bytes actually read.
   1623   @param  Buffer          Output buffer that contains the data read from the PE/COFF image.
   1624 
   1625   @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size
   1626 **/
   1627 EFI_STATUS
   1628 EFIAPI
   1629 SecureBootConfigImageRead (
   1630   IN     VOID    *FileHandle,
   1631   IN     UINTN   FileOffset,
   1632   IN OUT UINTN   *ReadSize,
   1633   OUT    VOID    *Buffer
   1634   )
   1635 {
   1636   UINTN               EndPosition;
   1637 
   1638   if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {
   1639     return EFI_INVALID_PARAMETER;
   1640   }
   1641 
   1642   if (MAX_ADDRESS - FileOffset < *ReadSize) {
   1643     return EFI_INVALID_PARAMETER;
   1644   }
   1645 
   1646   EndPosition = FileOffset + *ReadSize;
   1647   if (EndPosition > mImageSize) {
   1648     *ReadSize = (UINT32)(mImageSize - FileOffset);
   1649   }
   1650 
   1651   if (FileOffset >= mImageSize) {
   1652     *ReadSize = 0;
   1653   }
   1654 
   1655   CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);
   1656 
   1657   return EFI_SUCCESS;
   1658 }
   1659 
   1660 /**
   1661   Load PE/COFF image information into internal buffer and check its validity.
   1662 
   1663   @retval   EFI_SUCCESS         Successful
   1664   @retval   EFI_UNSUPPORTED     Invalid PE/COFF file
   1665   @retval   EFI_ABORTED         Serious error occurs, like file I/O error etc.
   1666 
   1667 **/
   1668 EFI_STATUS
   1669 LoadPeImage (
   1670   VOID
   1671   )
   1672 {
   1673   EFI_IMAGE_DOS_HEADER                  *DosHdr;
   1674   EFI_IMAGE_NT_HEADERS32                *NtHeader32;
   1675   EFI_IMAGE_NT_HEADERS64                *NtHeader64;
   1676   PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;
   1677   EFI_STATUS                            Status;
   1678 
   1679   NtHeader32 = NULL;
   1680   NtHeader64 = NULL;
   1681 
   1682   ZeroMem (&ImageContext, sizeof (ImageContext));
   1683   ImageContext.Handle    = (VOID *) mImageBase;
   1684   ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecureBootConfigImageRead;
   1685 
   1686   //
   1687   // Get information about the image being loaded
   1688   //
   1689   Status = PeCoffLoaderGetImageInfo (&ImageContext);
   1690   if (EFI_ERROR (Status)) {
   1691     //
   1692     // The information can't be got from the invalid PeImage
   1693     //
   1694     DEBUG ((DEBUG_INFO, "SecureBootConfigDxe: PeImage invalid. \n"));
   1695     return Status;
   1696   }
   1697 
   1698   //
   1699   // Read the Dos header
   1700   //
   1701   DosHdr = (EFI_IMAGE_DOS_HEADER*)(mImageBase);
   1702   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
   1703   {
   1704     //
   1705     // DOS image header is present,
   1706     // So read the PE header after the DOS image header
   1707     //
   1708     mPeCoffHeaderOffset = DosHdr->e_lfanew;
   1709   }
   1710   else
   1711   {
   1712     mPeCoffHeaderOffset = 0;
   1713   }
   1714 
   1715   //
   1716   // Read PE header and check the signature validity and machine compatibility
   1717   //
   1718   NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (mImageBase + mPeCoffHeaderOffset);
   1719   if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE)
   1720   {
   1721     return EFI_UNSUPPORTED;
   1722   }
   1723 
   1724   mNtHeader.Pe32 = NtHeader32;
   1725 
   1726   //
   1727   // Check the architecture field of PE header and get the Certificate Data Directory data
   1728   // Note the size of FileHeader field is constant for both IA32 and X64 arch
   1729   //
   1730   if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32)
   1731       || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)
   1732       || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)) {
   1733     //
   1734     // 32-bits Architecture
   1735     //
   1736     mImageType = ImageType_IA32;
   1737     mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
   1738   }
   1739   else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)
   1740           || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)
   1741           || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_AARCH64)) {
   1742     //
   1743     // 64-bits Architecture
   1744     //
   1745     mImageType = ImageType_X64;
   1746     NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset);
   1747     mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
   1748   } else {
   1749     return EFI_UNSUPPORTED;
   1750   }
   1751 
   1752   return EFI_SUCCESS;
   1753 }
   1754 
   1755 /**
   1756   Calculate hash of Pe/Coff image based on the authenticode image hashing in
   1757   PE/COFF Specification 8.0 Appendix A
   1758 
   1759   Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
   1760   the function LoadPeImage ().
   1761 
   1762   @param[in]    HashAlg   Hash algorithm type.
   1763 
   1764   @retval TRUE            Successfully hash image.
   1765   @retval FALSE           Fail in hash image.
   1766 
   1767 **/
   1768 BOOLEAN
   1769 HashPeImage (
   1770   IN  UINT32                HashAlg
   1771   )
   1772 {
   1773   BOOLEAN                   Status;
   1774   UINT16                    Magic;
   1775   EFI_IMAGE_SECTION_HEADER  *Section;
   1776   VOID                      *HashCtx;
   1777   UINTN                     CtxSize;
   1778   UINT8                     *HashBase;
   1779   UINTN                     HashSize;
   1780   UINTN                     SumOfBytesHashed;
   1781   EFI_IMAGE_SECTION_HEADER  *SectionHeader;
   1782   UINTN                     Index;
   1783   UINTN                     Pos;
   1784 
   1785   HashCtx       = NULL;
   1786   SectionHeader = NULL;
   1787   Status        = FALSE;
   1788 
   1789   if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {
   1790     return FALSE;
   1791   }
   1792 
   1793   //
   1794   // Initialize context of hash.
   1795   //
   1796   ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
   1797 
   1798   if (HashAlg == HASHALG_SHA1) {
   1799     mImageDigestSize  = SHA1_DIGEST_SIZE;
   1800     mCertType         = gEfiCertSha1Guid;
   1801   } else if (HashAlg == HASHALG_SHA256) {
   1802     mImageDigestSize  = SHA256_DIGEST_SIZE;
   1803     mCertType         = gEfiCertSha256Guid;
   1804   }
   1805 
   1806   CtxSize   = mHash[HashAlg].GetContextSize();
   1807 
   1808   HashCtx = AllocatePool (CtxSize);
   1809   ASSERT (HashCtx != NULL);
   1810 
   1811   // 1.  Load the image header into memory.
   1812 
   1813   // 2.  Initialize a SHA hash context.
   1814   Status = mHash[HashAlg].HashInit(HashCtx);
   1815   if (!Status) {
   1816     goto Done;
   1817   }
   1818   //
   1819   // Measuring PE/COFF Image Header;
   1820   // But CheckSum field and SECURITY data directory (certificate) are excluded
   1821   //
   1822   if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
   1823     //
   1824     // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
   1825     //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
   1826     //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
   1827     //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
   1828     //
   1829     Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
   1830   } else {
   1831     //
   1832     // Get the magic value from the PE/COFF Optional Header
   1833     //
   1834     Magic = mNtHeader.Pe32->OptionalHeader.Magic;
   1835   }
   1836 
   1837   //
   1838   // 3.  Calculate the distance from the base of the image header to the image checksum address.
   1839   // 4.  Hash the image header from its base to beginning of the image checksum.
   1840   //
   1841   HashBase = mImageBase;
   1842   if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
   1843     //
   1844     // Use PE32 offset.
   1845     //
   1846     HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);
   1847   } else {
   1848     //
   1849     // Use PE32+ offset.
   1850     //
   1851     HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
   1852   }
   1853 
   1854   Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
   1855   if (!Status) {
   1856     goto Done;
   1857   }
   1858   //
   1859   // 5.  Skip over the image checksum (it occupies a single ULONG).
   1860   // 6.  Get the address of the beginning of the Cert Directory.
   1861   // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.
   1862   //
   1863   if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
   1864     //
   1865     // Use PE32 offset.
   1866     //
   1867     HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
   1868     HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
   1869   } else {
   1870     //
   1871     // Use PE32+ offset.
   1872     //
   1873     HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
   1874     HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
   1875   }
   1876 
   1877   Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
   1878   if (!Status) {
   1879     goto Done;
   1880   }
   1881   //
   1882   // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
   1883   // 9.  Hash everything from the end of the Cert Directory to the end of image header.
   1884   //
   1885   if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
   1886     //
   1887     // Use PE32 offset
   1888     //
   1889     HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
   1890     HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);
   1891   } else {
   1892     //
   1893     // Use PE32+ offset.
   1894     //
   1895     HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
   1896     HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);
   1897   }
   1898 
   1899   Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
   1900   if (!Status) {
   1901     goto Done;
   1902   }
   1903   //
   1904   // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
   1905   //
   1906   if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
   1907     //
   1908     // Use PE32 offset.
   1909     //
   1910     SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
   1911   } else {
   1912     //
   1913     // Use PE32+ offset
   1914     //
   1915     SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
   1916   }
   1917 
   1918   //
   1919   // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
   1920   //     structures in the image. The 'NumberOfSections' field of the image
   1921   //     header indicates how big the table should be. Do not include any
   1922   //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
   1923   //
   1924   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);
   1925   ASSERT (SectionHeader != NULL);
   1926   //
   1927   // 12.  Using the 'PointerToRawData' in the referenced section headers as
   1928   //      a key, arrange the elements in the table in ascending order. In other
   1929   //      words, sort the section headers according to the disk-file offset of
   1930   //      the section.
   1931   //
   1932   Section = (EFI_IMAGE_SECTION_HEADER *) (
   1933                mImageBase +
   1934                mPeCoffHeaderOffset +
   1935                sizeof (UINT32) +
   1936                sizeof (EFI_IMAGE_FILE_HEADER) +
   1937                mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
   1938                );
   1939   for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
   1940     Pos = Index;
   1941     while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
   1942       CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
   1943       Pos--;
   1944     }
   1945     CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
   1946     Section += 1;
   1947   }
   1948 
   1949   //
   1950   // 13.  Walk through the sorted table, bring the corresponding section
   1951   //      into memory, and hash the entire section (using the 'SizeOfRawData'
   1952   //      field in the section header to determine the amount of data to hash).
   1953   // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
   1954   // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.
   1955   //
   1956   for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
   1957     Section = &SectionHeader[Index];
   1958     if (Section->SizeOfRawData == 0) {
   1959       continue;
   1960     }
   1961     HashBase  = mImageBase + Section->PointerToRawData;
   1962     HashSize  = (UINTN) Section->SizeOfRawData;
   1963 
   1964     Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
   1965     if (!Status) {
   1966       goto Done;
   1967     }
   1968 
   1969     SumOfBytesHashed += HashSize;
   1970   }
   1971 
   1972   //
   1973   // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
   1974   //      data in the file that needs to be added to the hash. This data begins
   1975   //      at file offset SUM_OF_BYTES_HASHED and its length is:
   1976   //             FileSize  -  (CertDirectory->Size)
   1977   //
   1978   if (mImageSize > SumOfBytesHashed) {
   1979     HashBase = mImageBase + SumOfBytesHashed;
   1980     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
   1981       //
   1982       // Use PE32 offset.
   1983       //
   1984       HashSize = (UINTN)(
   1985                  mImageSize -
   1986                  mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
   1987                  SumOfBytesHashed);
   1988     } else {
   1989       //
   1990       // Use PE32+ offset.
   1991       //
   1992       HashSize = (UINTN)(
   1993                  mImageSize -
   1994                  mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
   1995                  SumOfBytesHashed);
   1996     }
   1997 
   1998     Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
   1999     if (!Status) {
   2000       goto Done;
   2001     }
   2002   }
   2003 
   2004   Status  = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);
   2005 
   2006 Done:
   2007   if (HashCtx != NULL) {
   2008     FreePool (HashCtx);
   2009   }
   2010   if (SectionHeader != NULL) {
   2011     FreePool (SectionHeader);
   2012   }
   2013   return Status;
   2014 }
   2015 
   2016 /**
   2017   Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of
   2018   Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
   2019   8.0 Appendix A
   2020 
   2021   @retval EFI_UNSUPPORTED             Hash algorithm is not supported.
   2022   @retval EFI_SUCCESS                 Hash successfully.
   2023 
   2024 **/
   2025 EFI_STATUS
   2026 HashPeImageByType (
   2027   VOID
   2028   )
   2029 {
   2030   UINT8                     Index;
   2031   WIN_CERTIFICATE_EFI_PKCS  *PkcsCertData;
   2032 
   2033   PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);
   2034 
   2035   for (Index = 0; Index < HASHALG_MAX; Index++) {
   2036     //
   2037     // Check the Hash algorithm in PE/COFF Authenticode.
   2038     //    According to PKCS#7 Definition:
   2039     //        SignedData ::= SEQUENCE {
   2040     //            version Version,
   2041     //            digestAlgorithms DigestAlgorithmIdentifiers,
   2042     //            contentInfo ContentInfo,
   2043     //            .... }
   2044     //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
   2045     //    This field has the fixed offset (+32) in final Authenticode ASN.1 data.
   2046     //    Fixed offset (+32) is calculated based on two bytes of length encoding.
   2047      //
   2048     if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
   2049       //
   2050       // Only support two bytes of Long Form of Length Encoding.
   2051       //
   2052       continue;
   2053     }
   2054 
   2055     //
   2056     if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
   2057       break;
   2058     }
   2059   }
   2060 
   2061   if (Index == HASHALG_MAX) {
   2062     return EFI_UNSUPPORTED;
   2063   }
   2064 
   2065   //
   2066   // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
   2067   //
   2068   if (!HashPeImage(Index)) {
   2069     return EFI_UNSUPPORTED;
   2070   }
   2071 
   2072   return EFI_SUCCESS;
   2073 }
   2074 
   2075 /**
   2076   Enroll a new executable's signature into Signature Database.
   2077 
   2078   @param[in] PrivateData     The module's private data.
   2079   @param[in] VariableName    Variable name of signature database, must be
   2080                              EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
   2081                              or EFI_IMAGE_SECURITY_DATABASE2.
   2082 
   2083   @retval   EFI_SUCCESS            New signature is enrolled successfully.
   2084   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
   2085   @retval   EFI_UNSUPPORTED        Unsupported command.
   2086   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
   2087 
   2088 **/
   2089 EFI_STATUS
   2090 EnrollImageSignatureToSigDB (
   2091   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
   2092   IN CHAR16                         *VariableName
   2093   )
   2094 {
   2095   EFI_STATUS                        Status;
   2096   EFI_SIGNATURE_LIST                *SigDBCert;
   2097   EFI_SIGNATURE_DATA                *SigDBCertData;
   2098   VOID                              *Data;
   2099   UINTN                             DataSize;
   2100   UINTN                             SigDBSize;
   2101   UINT32                            Attr;
   2102   WIN_CERTIFICATE_UEFI_GUID         *GuidCertData;
   2103 
   2104   Data = NULL;
   2105   GuidCertData = NULL;
   2106 
   2107   if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {
   2108     return EFI_UNSUPPORTED;
   2109   }
   2110 
   2111   //
   2112   // Form the SigDB certificate list.
   2113   // Format the data item into EFI_SIGNATURE_LIST type.
   2114   //
   2115   // We need to parse executable's signature data from specified signed executable file.
   2116   // In current implementation, we simply trust the pass-in signed executable file.
   2117   // In reality, it's OS's responsibility to verify the signed executable file.
   2118   //
   2119 
   2120   //
   2121   // Read the whole file content
   2122   //
   2123   Status = ReadFileContent(
   2124              Private->FileContext->FHandle,
   2125              (VOID **) &mImageBase,
   2126              &mImageSize,
   2127              0
   2128              );
   2129   if (EFI_ERROR (Status)) {
   2130     goto ON_EXIT;
   2131   }
   2132   ASSERT (mImageBase != NULL);
   2133 
   2134   Status = LoadPeImage ();
   2135   if (EFI_ERROR (Status)) {
   2136     goto ON_EXIT;
   2137   }
   2138 
   2139   if (mSecDataDir->SizeOfCert == 0) {
   2140     if (!HashPeImage (HASHALG_SHA256)) {
   2141       Status =  EFI_SECURITY_VIOLATION;
   2142       goto ON_EXIT;
   2143     }
   2144   } else {
   2145 
   2146     //
   2147     // Read the certificate data
   2148     //
   2149     mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);
   2150 
   2151     if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
   2152       GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate;
   2153       if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) {
   2154         Status = EFI_ABORTED;
   2155         goto ON_EXIT;
   2156       }
   2157 
   2158       if (!HashPeImage (HASHALG_SHA256)) {
   2159         Status = EFI_ABORTED;
   2160         goto ON_EXIT;;
   2161       }
   2162 
   2163     } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
   2164 
   2165       Status = HashPeImageByType ();
   2166       if (EFI_ERROR (Status)) {
   2167         goto ON_EXIT;;
   2168       }
   2169     } else {
   2170       Status = EFI_ABORTED;
   2171       goto ON_EXIT;
   2172     }
   2173   }
   2174 
   2175   //
   2176   // Create a new SigDB entry.
   2177   //
   2178   SigDBSize = sizeof(EFI_SIGNATURE_LIST)
   2179               + sizeof(EFI_SIGNATURE_DATA) - 1
   2180               + (UINT32) mImageDigestSize;
   2181 
   2182   Data = (UINT8*) AllocateZeroPool (SigDBSize);
   2183   if (Data == NULL) {
   2184     Status = EFI_OUT_OF_RESOURCES;
   2185     goto ON_EXIT;
   2186   }
   2187 
   2188   //
   2189   // Adjust the Certificate Database parameters.
   2190   //
   2191   SigDBCert = (EFI_SIGNATURE_LIST*) Data;
   2192   SigDBCert->SignatureListSize   = (UINT32) SigDBSize;
   2193   SigDBCert->SignatureHeaderSize = 0;
   2194   SigDBCert->SignatureSize       = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize;
   2195   CopyGuid (&SigDBCert->SignatureType, &mCertType);
   2196 
   2197   SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));
   2198   CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);
   2199   CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);
   2200 
   2201   Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
   2202           | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
   2203   Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);
   2204   if (EFI_ERROR (Status)) {
   2205     DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
   2206     goto ON_EXIT;
   2207   }
   2208 
   2209   //
   2210   // Check if SigDB variable has been already existed.
   2211   // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
   2212   // new signature data to original variable
   2213   //
   2214   DataSize = 0;
   2215   Status = gRT->GetVariable(
   2216                   VariableName,
   2217                   &gEfiImageSecurityDatabaseGuid,
   2218                   NULL,
   2219                   &DataSize,
   2220                   NULL
   2221                   );
   2222   if (Status == EFI_BUFFER_TOO_SMALL) {
   2223     Attr |= EFI_VARIABLE_APPEND_WRITE;
   2224   } else if (Status != EFI_NOT_FOUND) {
   2225     goto ON_EXIT;
   2226   }
   2227 
   2228   //
   2229   // Enroll the variable.
   2230   //
   2231   Status = gRT->SetVariable(
   2232                   VariableName,
   2233                   &gEfiImageSecurityDatabaseGuid,
   2234                   Attr,
   2235                   SigDBSize,
   2236                   Data
   2237                   );
   2238   if (EFI_ERROR (Status)) {
   2239     goto ON_EXIT;
   2240   }
   2241 
   2242 ON_EXIT:
   2243 
   2244   CloseFile (Private->FileContext->FHandle);
   2245   Private->FileContext->FHandle = NULL;
   2246 
   2247   if (Private->FileContext->FileName != NULL){
   2248     FreePool(Private->FileContext->FileName);
   2249     Private->FileContext->FileName = NULL;
   2250   }
   2251 
   2252   if (Private->SignatureGUID != NULL) {
   2253     FreePool (Private->SignatureGUID);
   2254     Private->SignatureGUID = NULL;
   2255   }
   2256 
   2257   if (Data != NULL) {
   2258     FreePool (Data);
   2259   }
   2260 
   2261   if (mImageBase != NULL) {
   2262     FreePool (mImageBase);
   2263     mImageBase = NULL;
   2264   }
   2265 
   2266   return Status;
   2267 }
   2268 
   2269 /**
   2270   Enroll signature into DB/DBX/DBT without KEK's authentication.
   2271   The SignatureOwner GUID will be Private->SignatureGUID.
   2272 
   2273   @param[in] PrivateData     The module's private data.
   2274   @param[in] VariableName    Variable name of signature database, must be
   2275                              EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
   2276 
   2277   @retval   EFI_SUCCESS            New signature enrolled successfully.
   2278   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
   2279   @retval   others                 Fail to enroll signature data.
   2280 
   2281 **/
   2282 EFI_STATUS
   2283 EnrollSignatureDatabase (
   2284   IN SECUREBOOT_CONFIG_PRIVATE_DATA     *Private,
   2285   IN CHAR16                             *VariableName
   2286   )
   2287 {
   2288   UINT16*      FilePostFix;
   2289   EFI_STATUS   Status;
   2290   UINTN        NameLength;
   2291 
   2292   if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {
   2293     return EFI_INVALID_PARAMETER;
   2294   }
   2295 
   2296   Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
   2297   if (EFI_ERROR (Status)) {
   2298     return Status;
   2299   }
   2300 
   2301   //
   2302   // Parse the file's postfix.
   2303   //
   2304   NameLength = StrLen (Private->FileContext->FileName);
   2305   if (NameLength <= 4) {
   2306     return EFI_INVALID_PARAMETER;
   2307   }
   2308   FilePostFix = Private->FileContext->FileName + NameLength - 4;
   2309   if (IsDerEncodeCertificate (FilePostFix)) {
   2310     //
   2311     // Supports DER-encoded X509 certificate.
   2312     //
   2313     return EnrollX509toSigDB (Private, VariableName);
   2314   }
   2315 
   2316   return EnrollImageSignatureToSigDB (Private, VariableName);
   2317 }
   2318 
   2319 /**
   2320   List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
   2321   by GUID in the page for user to select and delete as needed.
   2322 
   2323   @param[in]    PrivateData         Module's private data.
   2324   @param[in]    VariableName        The variable name of the vendor's signature database.
   2325   @param[in]    VendorGuid          A unique identifier for the vendor.
   2326   @param[in]    LabelNumber         Label number to insert opcodes.
   2327   @param[in]    FormId              Form ID of current page.
   2328   @param[in]    QuestionIdBase      Base question id of the signature list.
   2329 
   2330   @retval   EFI_SUCCESS             Success to update the signature list page
   2331   @retval   EFI_OUT_OF_RESOURCES    Unable to allocate required resources.
   2332 
   2333 **/
   2334 EFI_STATUS
   2335 UpdateDeletePage (
   2336   IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,
   2337   IN CHAR16                           *VariableName,
   2338   IN EFI_GUID                         *VendorGuid,
   2339   IN UINT16                           LabelNumber,
   2340   IN EFI_FORM_ID                      FormId,
   2341   IN EFI_QUESTION_ID                  QuestionIdBase
   2342   )
   2343 {
   2344   EFI_STATUS                  Status;
   2345   UINT32                      Index;
   2346   UINTN                       CertCount;
   2347   UINTN                       GuidIndex;
   2348   VOID                        *StartOpCodeHandle;
   2349   VOID                        *EndOpCodeHandle;
   2350   EFI_IFR_GUID_LABEL          *StartLabel;
   2351   EFI_IFR_GUID_LABEL          *EndLabel;
   2352   UINTN                       DataSize;
   2353   UINT8                       *Data;
   2354   EFI_SIGNATURE_LIST          *CertList;
   2355   EFI_SIGNATURE_DATA          *Cert;
   2356   UINT32                      ItemDataSize;
   2357   CHAR16                      *GuidStr;
   2358   EFI_STRING_ID               GuidID;
   2359   EFI_STRING_ID               Help;
   2360 
   2361   Data     = NULL;
   2362   CertList = NULL;
   2363   Cert     = NULL;
   2364   GuidStr  = NULL;
   2365   StartOpCodeHandle = NULL;
   2366   EndOpCodeHandle   = NULL;
   2367 
   2368   //
   2369   // Initialize the container for dynamic opcodes.
   2370   //
   2371   StartOpCodeHandle = HiiAllocateOpCodeHandle ();
   2372   if (StartOpCodeHandle == NULL) {
   2373     Status = EFI_OUT_OF_RESOURCES;
   2374     goto ON_EXIT;
   2375   }
   2376 
   2377   EndOpCodeHandle = HiiAllocateOpCodeHandle ();
   2378   if (EndOpCodeHandle == NULL) {
   2379     Status = EFI_OUT_OF_RESOURCES;
   2380     goto ON_EXIT;
   2381   }
   2382 
   2383   //
   2384   // Create Hii Extend Label OpCode.
   2385   //
   2386   StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
   2387                                         StartOpCodeHandle,
   2388                                         &gEfiIfrTianoGuid,
   2389                                         NULL,
   2390                                         sizeof (EFI_IFR_GUID_LABEL)
   2391                                         );
   2392   StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
   2393   StartLabel->Number        = LabelNumber;
   2394 
   2395   EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
   2396                                       EndOpCodeHandle,
   2397                                       &gEfiIfrTianoGuid,
   2398                                       NULL,
   2399                                       sizeof (EFI_IFR_GUID_LABEL)
   2400                                       );
   2401   EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
   2402   EndLabel->Number        = LABEL_END;
   2403 
   2404   //
   2405   // Read Variable.
   2406   //
   2407   DataSize = 0;
   2408   Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
   2409   if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
   2410     goto ON_EXIT;
   2411   }
   2412 
   2413   Data = (UINT8 *) AllocateZeroPool (DataSize);
   2414   if (Data == NULL) {
   2415     Status = EFI_OUT_OF_RESOURCES;
   2416     goto ON_EXIT;
   2417   }
   2418 
   2419   Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
   2420   if (EFI_ERROR (Status)) {
   2421     goto ON_EXIT;
   2422   }
   2423 
   2424   GuidStr = AllocateZeroPool (100);
   2425   if (GuidStr == NULL) {
   2426     Status = EFI_OUT_OF_RESOURCES;
   2427     goto ON_EXIT;
   2428   }
   2429 
   2430   //
   2431   // Enumerate all KEK pub data.
   2432   //
   2433   ItemDataSize = (UINT32) DataSize;
   2434   CertList = (EFI_SIGNATURE_LIST *) Data;
   2435   GuidIndex = 0;
   2436 
   2437   while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
   2438 
   2439     if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {
   2440       Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);
   2441     } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
   2442       Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);
   2443     } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {
   2444       Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);
   2445     } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {
   2446       Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);
   2447     } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) {
   2448       Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID);
   2449     } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) {
   2450       Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID);
   2451     } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) {
   2452       Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID);
   2453     } else {
   2454       //
   2455       // The signature type is not supported in current implementation.
   2456       //
   2457       ItemDataSize -= CertList->SignatureListSize;
   2458       CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
   2459       continue;
   2460     }
   2461 
   2462     CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
   2463     for (Index = 0; Index < CertCount; Index++) {
   2464       Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList
   2465                                               + sizeof (EFI_SIGNATURE_LIST)
   2466                                               + CertList->SignatureHeaderSize
   2467                                               + Index * CertList->SignatureSize);
   2468       //
   2469       // Display GUID and help
   2470       //
   2471       GuidToString (&Cert->SignatureOwner, GuidStr, 100);
   2472       GuidID  = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);
   2473       HiiCreateCheckBoxOpCode (
   2474         StartOpCodeHandle,
   2475         (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),
   2476         0,
   2477         0,
   2478         GuidID,
   2479         Help,
   2480         EFI_IFR_FLAG_CALLBACK,
   2481         0,
   2482         NULL
   2483         );
   2484     }
   2485 
   2486     ItemDataSize -= CertList->SignatureListSize;
   2487     CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
   2488   }
   2489 
   2490 ON_EXIT:
   2491   HiiUpdateForm (
   2492     PrivateData->HiiHandle,
   2493     &gSecureBootConfigFormSetGuid,
   2494     FormId,
   2495     StartOpCodeHandle,
   2496     EndOpCodeHandle
   2497     );
   2498 
   2499   if (StartOpCodeHandle != NULL) {
   2500     HiiFreeOpCodeHandle (StartOpCodeHandle);
   2501   }
   2502 
   2503   if (EndOpCodeHandle != NULL) {
   2504     HiiFreeOpCodeHandle (EndOpCodeHandle);
   2505   }
   2506 
   2507   if (Data != NULL) {
   2508     FreePool (Data);
   2509   }
   2510 
   2511   if (GuidStr != NULL) {
   2512     FreePool (GuidStr);
   2513   }
   2514 
   2515   return EFI_SUCCESS;
   2516 }
   2517 
   2518 /**
   2519   Delete a KEK entry from KEK database.
   2520 
   2521   @param[in]    PrivateData         Module's private data.
   2522   @param[in]    QuestionId          Question id of the KEK item to delete.
   2523 
   2524   @retval   EFI_SUCCESS            Delete kek item successfully.
   2525   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
   2526 
   2527 **/
   2528 EFI_STATUS
   2529 DeleteKeyExchangeKey (
   2530   IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,
   2531   IN EFI_QUESTION_ID                  QuestionId
   2532   )
   2533 {
   2534   EFI_STATUS                  Status;
   2535   UINTN                       DataSize;
   2536   UINT8                       *Data;
   2537   UINT8                       *OldData;
   2538   UINT32                      Attr;
   2539   UINT32                      Index;
   2540   EFI_SIGNATURE_LIST          *CertList;
   2541   EFI_SIGNATURE_LIST          *NewCertList;
   2542   EFI_SIGNATURE_DATA          *Cert;
   2543   UINTN                       CertCount;
   2544   UINT32                      Offset;
   2545   BOOLEAN                     IsKEKItemFound;
   2546   UINT32                      KekDataSize;
   2547   UINTN                       DeleteKekIndex;
   2548   UINTN                       GuidIndex;
   2549 
   2550   Data            = NULL;
   2551   OldData         = NULL;
   2552   CertList        = NULL;
   2553   Cert            = NULL;
   2554   Attr            = 0;
   2555   DeleteKekIndex  = QuestionId - OPTION_DEL_KEK_QUESTION_ID;
   2556 
   2557   Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
   2558   if (EFI_ERROR (Status)) {
   2559     return Status;
   2560   }
   2561 
   2562   //
   2563   // Get original KEK variable.
   2564   //
   2565   DataSize = 0;
   2566   Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);
   2567   if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
   2568     goto ON_EXIT;
   2569   }
   2570 
   2571   OldData = (UINT8*)AllocateZeroPool(DataSize);
   2572   if (OldData == NULL) {
   2573     Status = EFI_OUT_OF_RESOURCES;
   2574     goto ON_EXIT;
   2575   }
   2576 
   2577   Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);
   2578   if (EFI_ERROR(Status)) {
   2579     goto ON_EXIT;
   2580   }
   2581 
   2582   //
   2583   // Allocate space for new variable.
   2584   //
   2585   Data = (UINT8*) AllocateZeroPool (DataSize);
   2586   if (Data == NULL) {
   2587     Status  =  EFI_OUT_OF_RESOURCES;
   2588     goto ON_EXIT;
   2589   }
   2590 
   2591   //
   2592   // Enumerate all KEK pub data and erasing the target item.
   2593   //
   2594   IsKEKItemFound = FALSE;
   2595   KekDataSize = (UINT32) DataSize;
   2596   CertList = (EFI_SIGNATURE_LIST *) OldData;
   2597   Offset = 0;
   2598   GuidIndex = 0;
   2599   while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
   2600     if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||
   2601         CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
   2602       CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
   2603       NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);
   2604       Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
   2605       Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
   2606       CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
   2607       for (Index = 0; Index < CertCount; Index++) {
   2608         if (GuidIndex == DeleteKekIndex ) {
   2609           //
   2610           // Find it! Skip it!
   2611           //
   2612           NewCertList->SignatureListSize -= CertList->SignatureSize;
   2613           IsKEKItemFound = TRUE;
   2614         } else {
   2615           //
   2616           // This item doesn't match. Copy it to the Data buffer.
   2617           //
   2618           CopyMem (Data + Offset, Cert, CertList->SignatureSize);
   2619           Offset += CertList->SignatureSize;
   2620         }
   2621         GuidIndex++;
   2622         Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize);
   2623       }
   2624     } else {
   2625       //
   2626       // This List doesn't match. Copy it to the Data buffer.
   2627       //
   2628       CopyMem (Data + Offset, CertList, CertList->SignatureListSize);
   2629       Offset += CertList->SignatureListSize;
   2630     }
   2631 
   2632     KekDataSize -= CertList->SignatureListSize;
   2633     CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize);
   2634   }
   2635 
   2636   if (!IsKEKItemFound) {
   2637     //
   2638     // Doesn't find the Kek Item!
   2639     //
   2640     Status = EFI_NOT_FOUND;
   2641     goto ON_EXIT;
   2642   }
   2643 
   2644   //
   2645   // Delete the Signature header if there is no signature in the list.
   2646   //
   2647   KekDataSize = Offset;
   2648   CertList = (EFI_SIGNATURE_LIST*) Data;
   2649   Offset = 0;
   2650   ZeroMem (OldData, KekDataSize);
   2651   while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
   2652     CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
   2653     DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));
   2654     if (CertCount != 0) {
   2655       CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);
   2656       Offset += CertList->SignatureListSize;
   2657     }
   2658     KekDataSize -= CertList->SignatureListSize;
   2659     CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
   2660   }
   2661 
   2662   DataSize = Offset;
   2663   if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
   2664     Status = CreateTimeBasedPayload (&DataSize, &OldData);
   2665     if (EFI_ERROR (Status)) {
   2666       DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
   2667       goto ON_EXIT;
   2668     }
   2669   }
   2670 
   2671   Status = gRT->SetVariable(
   2672                   EFI_KEY_EXCHANGE_KEY_NAME,
   2673                   &gEfiGlobalVariableGuid,
   2674                   Attr,
   2675                   DataSize,
   2676                   OldData
   2677                   );
   2678   if (EFI_ERROR (Status)) {
   2679     DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
   2680     goto ON_EXIT;
   2681   }
   2682 
   2683 ON_EXIT:
   2684   if (Data != NULL) {
   2685     FreePool(Data);
   2686   }
   2687 
   2688   if (OldData != NULL) {
   2689     FreePool(OldData);
   2690   }
   2691 
   2692   return UpdateDeletePage (
   2693            PrivateData,
   2694            EFI_KEY_EXCHANGE_KEY_NAME,
   2695            &gEfiGlobalVariableGuid,
   2696            LABEL_KEK_DELETE,
   2697            FORMID_DELETE_KEK_FORM,
   2698            OPTION_DEL_KEK_QUESTION_ID
   2699            );
   2700 }
   2701 
   2702 /**
   2703   Delete a signature entry from siganture database.
   2704 
   2705   @param[in]    PrivateData         Module's private data.
   2706   @param[in]    VariableName        The variable name of the vendor's signature database.
   2707   @param[in]    VendorGuid          A unique identifier for the vendor.
   2708   @param[in]    LabelNumber         Label number to insert opcodes.
   2709   @param[in]    FormId              Form ID of current page.
   2710   @param[in]    QuestionIdBase      Base question id of the signature list.
   2711   @param[in]    DeleteIndex         Signature index to delete.
   2712 
   2713   @retval   EFI_SUCCESS             Delete siganture successfully.
   2714   @retval   EFI_NOT_FOUND           Can't find the signature item,
   2715   @retval   EFI_OUT_OF_RESOURCES    Could not allocate needed resources.
   2716 **/
   2717 EFI_STATUS
   2718 DeleteSignature (
   2719   IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,
   2720   IN CHAR16                           *VariableName,
   2721   IN EFI_GUID                         *VendorGuid,
   2722   IN UINT16                           LabelNumber,
   2723   IN EFI_FORM_ID                      FormId,
   2724   IN EFI_QUESTION_ID                  QuestionIdBase,
   2725   IN UINTN                            DeleteIndex
   2726   )
   2727 {
   2728   EFI_STATUS                  Status;
   2729   UINTN                       DataSize;
   2730   UINT8                       *Data;
   2731   UINT8                       *OldData;
   2732   UINT32                      Attr;
   2733   UINT32                      Index;
   2734   EFI_SIGNATURE_LIST          *CertList;
   2735   EFI_SIGNATURE_LIST          *NewCertList;
   2736   EFI_SIGNATURE_DATA          *Cert;
   2737   UINTN                       CertCount;
   2738   UINT32                      Offset;
   2739   BOOLEAN                     IsItemFound;
   2740   UINT32                      ItemDataSize;
   2741   UINTN                       GuidIndex;
   2742 
   2743   Data            = NULL;
   2744   OldData         = NULL;
   2745   CertList        = NULL;
   2746   Cert            = NULL;
   2747   Attr            = 0;
   2748 
   2749   Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
   2750   if (EFI_ERROR (Status)) {
   2751     return Status;
   2752   }
   2753 
   2754   //
   2755   // Get original signature list data.
   2756   //
   2757   DataSize = 0;
   2758   Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
   2759   if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
   2760     goto ON_EXIT;
   2761   }
   2762 
   2763   OldData = (UINT8 *) AllocateZeroPool (DataSize);
   2764   if (OldData == NULL) {
   2765     Status = EFI_OUT_OF_RESOURCES;
   2766     goto ON_EXIT;
   2767   }
   2768 
   2769   Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);
   2770   if (EFI_ERROR(Status)) {
   2771     goto ON_EXIT;
   2772   }
   2773 
   2774   //
   2775   // Allocate space for new variable.
   2776   //
   2777   Data = (UINT8*) AllocateZeroPool (DataSize);
   2778   if (Data == NULL) {
   2779     Status  =  EFI_OUT_OF_RESOURCES;
   2780     goto ON_EXIT;
   2781   }
   2782 
   2783   //
   2784   // Enumerate all signature data and erasing the target item.
   2785   //
   2786   IsItemFound = FALSE;
   2787   ItemDataSize = (UINT32) DataSize;
   2788   CertList = (EFI_SIGNATURE_LIST *) OldData;
   2789   Offset = 0;
   2790   GuidIndex = 0;
   2791   while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
   2792     if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||
   2793         CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||
   2794         CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||
   2795         CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) ||
   2796         CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) ||
   2797         CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) ||
   2798         CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)
   2799         ) {
   2800       //
   2801       // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
   2802       //
   2803       CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
   2804       NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);
   2805       Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
   2806       Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
   2807       CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
   2808       for (Index = 0; Index < CertCount; Index++) {
   2809         if (GuidIndex == DeleteIndex) {
   2810           //
   2811           // Find it! Skip it!
   2812           //
   2813           NewCertList->SignatureListSize -= CertList->SignatureSize;
   2814           IsItemFound = TRUE;
   2815         } else {
   2816           //
   2817           // This item doesn't match. Copy it to the Data buffer.
   2818           //
   2819           CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);
   2820           Offset += CertList->SignatureSize;
   2821         }
   2822         GuidIndex++;
   2823         Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
   2824       }
   2825     } else {
   2826       //
   2827       // This List doesn't match. Just copy it to the Data buffer.
   2828       //
   2829       CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
   2830       Offset += CertList->SignatureListSize;
   2831     }
   2832 
   2833     ItemDataSize -= CertList->SignatureListSize;
   2834     CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
   2835   }
   2836 
   2837   if (!IsItemFound) {
   2838     //
   2839     // Doesn't find the signature Item!
   2840     //
   2841     Status = EFI_NOT_FOUND;
   2842     goto ON_EXIT;
   2843   }
   2844 
   2845   //
   2846   // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
   2847   //
   2848   ItemDataSize = Offset;
   2849   CertList = (EFI_SIGNATURE_LIST *) Data;
   2850   Offset = 0;
   2851   ZeroMem (OldData, ItemDataSize);
   2852   while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
   2853     CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
   2854     DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));
   2855     if (CertCount != 0) {
   2856       CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
   2857       Offset += CertList->SignatureListSize;
   2858     }
   2859     ItemDataSize -= CertList->SignatureListSize;
   2860     CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
   2861   }
   2862 
   2863   DataSize = Offset;
   2864   if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
   2865     Status = CreateTimeBasedPayload (&DataSize, &OldData);
   2866     if (EFI_ERROR (Status)) {
   2867       DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
   2868       goto ON_EXIT;
   2869     }
   2870   }
   2871 
   2872   Status = gRT->SetVariable(
   2873                   VariableName,
   2874                   VendorGuid,
   2875                   Attr,
   2876                   DataSize,
   2877                   OldData
   2878                   );
   2879   if (EFI_ERROR (Status)) {
   2880     DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
   2881     goto ON_EXIT;
   2882   }
   2883 
   2884 ON_EXIT:
   2885   if (Data != NULL) {
   2886     FreePool(Data);
   2887   }
   2888 
   2889   if (OldData != NULL) {
   2890     FreePool(OldData);
   2891   }
   2892 
   2893   return UpdateDeletePage (
   2894            PrivateData,
   2895            VariableName,
   2896            VendorGuid,
   2897            LabelNumber,
   2898            FormId,
   2899            QuestionIdBase
   2900            );
   2901 }
   2902 
   2903 /**
   2904 
   2905   Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT
   2906  and STR_CUR_SECURE_BOOT_MODE_CONTENT.
   2907 
   2908   @param[in]    PrivateData         Module's private data.
   2909 
   2910   @return EFI_SUCCESS              Update secure boot strings successfully.
   2911   @return other                          Fail to update secure boot strings.
   2912 
   2913 **/
   2914 EFI_STATUS
   2915 UpdateSecureBootString(
   2916   IN SECUREBOOT_CONFIG_PRIVATE_DATA  *Private
   2917   )
   2918 {
   2919   UINT8       *SecureBoot;
   2920 
   2921   SecureBoot = NULL;
   2922 
   2923   //
   2924   // Get current secure boot state.
   2925   //
   2926   GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);
   2927   if (SecureBoot == NULL) {
   2928     return EFI_NOT_FOUND;
   2929   }
   2930 
   2931   if (*SecureBoot == SECURE_BOOT_MODE_ENABLE) {
   2932     HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);
   2933   } else {
   2934     HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);
   2935   }
   2936 
   2937   FreePool(SecureBoot);
   2938 
   2939   return EFI_SUCCESS;
   2940 }
   2941 
   2942 /**
   2943   This function extracts configuration from variable.
   2944 
   2945   @param[in, out]  ConfigData   Point to SecureBoot configuration private data.
   2946 
   2947 **/
   2948 VOID
   2949 SecureBootExtractConfigFromVariable (
   2950   IN OUT SECUREBOOT_CONFIGURATION    *ConfigData
   2951   )
   2952 {
   2953   UINT8     *SecureBootEnable;
   2954   UINT8     *SetupMode;
   2955   UINT8     *SecureBootMode;
   2956   EFI_TIME  CurrTime;
   2957 
   2958   SecureBootEnable = NULL;
   2959   SetupMode        = NULL;
   2960   SecureBootMode   = NULL;
   2961 
   2962   //
   2963   // Initilize the Date and Time using system time.
   2964   //
   2965   ConfigData->CertificateFormat = HASHALG_RAW;
   2966   ConfigData->AlwaysRevocation = TRUE;
   2967   gRT->GetTime (&CurrTime, NULL);
   2968   ConfigData->RevocationDate.Year   = CurrTime.Year;
   2969   ConfigData->RevocationDate.Month  = CurrTime.Month;
   2970   ConfigData->RevocationDate.Day    = CurrTime.Day;
   2971   ConfigData->RevocationTime.Hour   = CurrTime.Hour;
   2972   ConfigData->RevocationTime.Minute = CurrTime.Minute;
   2973   ConfigData->RevocationTime.Second = 0;
   2974 
   2975 
   2976   //
   2977   // If it is Physical Presence User, set the PhysicalPresent to true.
   2978   //
   2979   if (UserPhysicalPresent()) {
   2980     ConfigData->PhysicalPresent = TRUE;
   2981   } else {
   2982     ConfigData->PhysicalPresent = FALSE;
   2983   }
   2984 
   2985   //
   2986   // If there is no PK then the Delete Pk button will be gray.
   2987   //
   2988   GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);
   2989   if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {
   2990     ConfigData->HasPk = FALSE;
   2991   } else  {
   2992     ConfigData->HasPk = TRUE;
   2993   }
   2994 
   2995   //
   2996   // Check SecureBootEnable & Pk status, fix the inconsistence.
   2997   // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
   2998   // Checkbox.
   2999   //
   3000   ConfigData->AttemptSecureBoot = FALSE;
   3001   GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
   3002 
   3003   //
   3004   // Fix Pk, SecureBootEnable inconsistence
   3005   //
   3006   if ((SetupMode != NULL) && (*SetupMode) == USER_MODE) {
   3007     ConfigData->HideSecureBoot = FALSE;
   3008     if ((SecureBootEnable != NULL) && (*SecureBootEnable == SECURE_BOOT_ENABLE)) {
   3009       ConfigData->AttemptSecureBoot = TRUE;
   3010     }
   3011   } else {
   3012     ConfigData->HideSecureBoot = TRUE;
   3013   }
   3014 
   3015   //
   3016   // Get the SecureBootMode from CustomMode variable.
   3017   //
   3018   GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);
   3019   if (SecureBootMode == NULL) {
   3020     ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;
   3021   } else {
   3022     ConfigData->SecureBootMode = *(SecureBootMode);
   3023   }
   3024 
   3025   if (SecureBootEnable != NULL) {
   3026     FreePool (SecureBootEnable);
   3027   }
   3028   if (SetupMode != NULL) {
   3029     FreePool (SetupMode);
   3030   }
   3031   if (SecureBootMode != NULL) {
   3032     FreePool (SecureBootMode);
   3033   }
   3034 }
   3035 
   3036 /**
   3037   This function allows a caller to extract the current configuration for one
   3038   or more named elements from the target driver.
   3039 
   3040   @param[in]   This              Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
   3041   @param[in]   Request           A null-terminated Unicode string in
   3042                                  <ConfigRequest> format.
   3043   @param[out]  Progress          On return, points to a character in the Request
   3044                                  string. Points to the string's null terminator if
   3045                                  request was successful. Points to the most recent
   3046                                  '&' before the first failing name/value pair (or
   3047                                  the beginning of the string if the failure is in
   3048                                  the first name/value pair) if the request was not
   3049                                  successful.
   3050   @param[out]  Results           A null-terminated Unicode string in
   3051                                  <ConfigAltResp> format which has all values filled
   3052                                  in for the names in the Request string. String to
   3053                                  be allocated by the called function.
   3054 
   3055   @retval EFI_SUCCESS            The Results is filled with the requested values.
   3056   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
   3057   @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
   3058   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
   3059                                  driver.
   3060 
   3061 **/
   3062 EFI_STATUS
   3063 EFIAPI
   3064 SecureBootExtractConfig (
   3065   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL        *This,
   3066   IN CONST EFI_STRING                            Request,
   3067        OUT EFI_STRING                            *Progress,
   3068        OUT EFI_STRING                            *Results
   3069   )
   3070 {
   3071   EFI_STATUS                        Status;
   3072   UINTN                             BufferSize;
   3073   UINTN                             Size;
   3074   SECUREBOOT_CONFIGURATION          Configuration;
   3075   EFI_STRING                        ConfigRequest;
   3076   EFI_STRING                        ConfigRequestHdr;
   3077   SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData;
   3078   BOOLEAN                           AllocatedRequest;
   3079 
   3080   if (Progress == NULL || Results == NULL) {
   3081     return EFI_INVALID_PARAMETER;
   3082   }
   3083 
   3084   AllocatedRequest = FALSE;
   3085   ConfigRequestHdr = NULL;
   3086   ConfigRequest    = NULL;
   3087   Size             = 0;
   3088 
   3089   ZeroMem (&Configuration, sizeof (Configuration));
   3090   PrivateData      = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
   3091   *Progress        = Request;
   3092 
   3093   if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {
   3094     return EFI_NOT_FOUND;
   3095   }
   3096 
   3097   //
   3098   // Get Configuration from Variable.
   3099   //
   3100   SecureBootExtractConfigFromVariable (&Configuration);
   3101 
   3102   BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
   3103   ConfigRequest = Request;
   3104   if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
   3105     //
   3106     // Request is set to NULL or OFFSET is NULL, construct full request string.
   3107     //
   3108     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
   3109     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
   3110     //
   3111     ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);
   3112     Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
   3113     ConfigRequest = AllocateZeroPool (Size);
   3114     ASSERT (ConfigRequest != NULL);
   3115     AllocatedRequest = TRUE;
   3116     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
   3117     FreePool (ConfigRequestHdr);
   3118     ConfigRequestHdr = NULL;
   3119   }
   3120 
   3121   Status = gHiiConfigRouting->BlockToConfig (
   3122                                 gHiiConfigRouting,
   3123                                 ConfigRequest,
   3124                                 (UINT8 *) &Configuration,
   3125                                 BufferSize,
   3126                                 Results,
   3127                                 Progress
   3128                                 );
   3129 
   3130   //
   3131   // Free the allocated config request string.
   3132   //
   3133   if (AllocatedRequest) {
   3134     FreePool (ConfigRequest);
   3135   }
   3136 
   3137   //
   3138   // Set Progress string to the original request string.
   3139   //
   3140   if (Request == NULL) {
   3141     *Progress = NULL;
   3142   } else if (StrStr (Request, L"OFFSET") == NULL) {
   3143     *Progress = Request + StrLen (Request);
   3144   }
   3145 
   3146   return Status;
   3147 }
   3148 
   3149 /**
   3150   This function processes the results of changes in configuration.
   3151 
   3152   @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
   3153   @param[in]  Configuration      A null-terminated Unicode string in <ConfigResp>
   3154                                  format.
   3155   @param[out] Progress           A pointer to a string filled in with the offset of
   3156                                  the most recent '&' before the first failing
   3157                                  name/value pair (or the beginning of the string if
   3158                                  the failure is in the first name/value pair) or
   3159                                  the terminating NULL if all was successful.
   3160 
   3161   @retval EFI_SUCCESS            The Results is processed successfully.
   3162   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
   3163   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
   3164                                  driver.
   3165 
   3166 **/
   3167 EFI_STATUS
   3168 EFIAPI
   3169 SecureBootRouteConfig (
   3170   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,
   3171   IN CONST EFI_STRING                          Configuration,
   3172        OUT EFI_STRING                          *Progress
   3173   )
   3174 {
   3175   SECUREBOOT_CONFIGURATION   IfrNvData;
   3176   UINTN                      BufferSize;
   3177   EFI_STATUS                 Status;
   3178 
   3179   if (Configuration == NULL || Progress == NULL) {
   3180     return EFI_INVALID_PARAMETER;
   3181   }
   3182 
   3183   *Progress = Configuration;
   3184   if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {
   3185     return EFI_NOT_FOUND;
   3186   }
   3187 
   3188   //
   3189   // Get Configuration from Variable.
   3190   //
   3191   SecureBootExtractConfigFromVariable (&IfrNvData);
   3192 
   3193   //
   3194   // Map the Configuration to the configuration block.
   3195   //
   3196   BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
   3197   Status = gHiiConfigRouting->ConfigToBlock (
   3198                                 gHiiConfigRouting,
   3199                                 Configuration,
   3200                                 (UINT8 *)&IfrNvData,
   3201                                 &BufferSize,
   3202                                 Progress
   3203                                 );
   3204   if (EFI_ERROR (Status)) {
   3205     return Status;
   3206   }
   3207 
   3208   //
   3209   // Store Buffer Storage back to EFI variable if needed
   3210   //
   3211   if (!IfrNvData.HideSecureBoot) {
   3212     Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot);
   3213     if (EFI_ERROR (Status)) {
   3214       return Status;
   3215     }
   3216   }
   3217 
   3218   *Progress = Configuration + StrLen (Configuration);
   3219   return EFI_SUCCESS;
   3220 }
   3221 
   3222 /**
   3223   This function is called to provide results data to the driver.
   3224 
   3225   @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
   3226   @param[in]  Action             Specifies the type of action taken by the browser.
   3227   @param[in]  QuestionId         A unique value which is sent to the original
   3228                                  exporting driver so that it can identify the type
   3229                                  of data to expect.
   3230   @param[in]  Type               The type of value for the question.
   3231   @param[in]  Value              A pointer to the data being sent to the original
   3232                                  exporting driver.
   3233   @param[out] ActionRequest      On return, points to the action requested by the
   3234                                  callback function.
   3235 
   3236   @retval EFI_SUCCESS            The callback successfully handled the action.
   3237   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
   3238                                  variable and its data.
   3239   @retval EFI_DEVICE_ERROR       The variable could not be saved.
   3240   @retval EFI_UNSUPPORTED        The specified Action is not supported by the
   3241                                  callback.
   3242 
   3243 **/
   3244 EFI_STATUS
   3245 EFIAPI
   3246 SecureBootCallback (
   3247   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,
   3248   IN     EFI_BROWSER_ACTION                    Action,
   3249   IN     EFI_QUESTION_ID                       QuestionId,
   3250   IN     UINT8                                 Type,
   3251   IN     EFI_IFR_TYPE_VALUE                    *Value,
   3252      OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest
   3253   )
   3254 {
   3255   EFI_INPUT_KEY                   Key;
   3256   EFI_STATUS                      Status;
   3257   SECUREBOOT_CONFIG_PRIVATE_DATA  *Private;
   3258   UINTN                           BufferSize;
   3259   SECUREBOOT_CONFIGURATION        *IfrNvData;
   3260   UINT16                          LabelId;
   3261   UINT8                           *SecureBootEnable;
   3262   UINT8                           *Pk;
   3263   UINT8                           *SecureBootMode;
   3264   UINT8                           *SetupMode;
   3265   CHAR16                          PromptString[100];
   3266   EFI_DEVICE_PATH_PROTOCOL        *File;
   3267 
   3268   Status           = EFI_SUCCESS;
   3269   SecureBootEnable = NULL;
   3270   SecureBootMode   = NULL;
   3271   SetupMode        = NULL;
   3272   File             = NULL;
   3273 
   3274   if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
   3275     return EFI_INVALID_PARAMETER;
   3276   }
   3277 
   3278   Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);
   3279 
   3280   gSecureBootPrivateData = Private;
   3281 
   3282   //
   3283   // Retrieve uncommitted data from Browser
   3284   //
   3285   BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
   3286   IfrNvData = AllocateZeroPool (BufferSize);
   3287   if (IfrNvData == NULL) {
   3288     return EFI_OUT_OF_RESOURCES;
   3289   }
   3290 
   3291   HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData);
   3292 
   3293   if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
   3294     if (QuestionId == KEY_SECURE_BOOT_MODE) {
   3295       //
   3296       // Update secure boot strings when opening this form
   3297       //
   3298       Status = UpdateSecureBootString(Private);
   3299       SecureBootExtractConfigFromVariable (IfrNvData);
   3300       mIsEnterSecureBootForm = TRUE;
   3301     }
   3302     goto EXIT;
   3303   }
   3304 
   3305   if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
   3306     Status = EFI_UNSUPPORTED;
   3307     if (QuestionId == KEY_SECURE_BOOT_MODE) {
   3308       if (mIsEnterSecureBootForm) {
   3309         Value->u8 = SECURE_BOOT_MODE_STANDARD;
   3310         Status = EFI_SUCCESS;
   3311       }
   3312     }
   3313     goto EXIT;
   3314   }
   3315 
   3316   if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
   3317       (Action != EFI_BROWSER_ACTION_CHANGING) &&
   3318       (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&
   3319       (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) {
   3320     Status = EFI_UNSUPPORTED;
   3321     goto EXIT;
   3322   }
   3323 
   3324   if (Action == EFI_BROWSER_ACTION_CHANGING) {
   3325 
   3326     switch (QuestionId) {
   3327     case KEY_SECURE_BOOT_ENABLE:
   3328       GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);
   3329       if (NULL != SecureBootEnable) {
   3330         FreePool (SecureBootEnable);
   3331         if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {
   3332           CreatePopUp (
   3333             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   3334             &Key,
   3335             L"Only Physical Presence User could disable secure boot!",
   3336             NULL
   3337             );
   3338           Status = EFI_UNSUPPORTED;
   3339         } else {
   3340           CreatePopUp (
   3341             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   3342             &Key,
   3343             L"Configuration changed, please reset the platform to take effect!",
   3344             NULL
   3345             );
   3346         }
   3347       }
   3348       break;
   3349 
   3350     case KEY_SECURE_BOOT_KEK_OPTION:
   3351     case KEY_SECURE_BOOT_DB_OPTION:
   3352     case KEY_SECURE_BOOT_DBX_OPTION:
   3353     case KEY_SECURE_BOOT_DBT_OPTION:
   3354       //
   3355       // Clear Signature GUID.
   3356       //
   3357       ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid));
   3358       if (Private->SignatureGUID == NULL) {
   3359         Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));
   3360         if (Private->SignatureGUID == NULL) {
   3361           return EFI_OUT_OF_RESOURCES;
   3362         }
   3363       }
   3364 
   3365       if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) {
   3366         LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;
   3367       } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {
   3368         LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
   3369       } else if (QuestionId == KEY_SECURE_BOOT_DBT_OPTION) {
   3370         LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;
   3371       } else {
   3372         LabelId = FORMID_ENROLL_KEK_FORM;
   3373       }
   3374 
   3375       //
   3376       // Refresh selected file.
   3377       //
   3378       CleanUpPage (LabelId, Private);
   3379       break;
   3380     case KEY_SECURE_BOOT_PK_OPTION:
   3381       LabelId = FORMID_ENROLL_PK_FORM;
   3382       //
   3383       // Refresh selected file.
   3384       //
   3385       CleanUpPage (LabelId, Private);
   3386       break;
   3387 
   3388     case FORMID_ENROLL_PK_FORM:
   3389       ChooseFile (NULL, NULL, UpdatePKFromFile, &File);
   3390       break;
   3391 
   3392     case FORMID_ENROLL_KEK_FORM:
   3393       ChooseFile (NULL, NULL, UpdateKEKFromFile, &File);
   3394       break;
   3395 
   3396     case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:
   3397       ChooseFile (NULL, NULL, UpdateDBFromFile, &File);
   3398       break;
   3399 
   3400     case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:
   3401       ChooseFile (NULL, NULL, UpdateDBXFromFile, &File);
   3402       break;
   3403 
   3404     case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT:
   3405       ChooseFile (NULL, NULL, UpdateDBTFromFile, &File);
   3406       break;
   3407 
   3408     case KEY_SECURE_BOOT_DELETE_PK:
   3409       if (Value->u8) {
   3410         CreatePopUp (
   3411           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   3412           &Key,
   3413           L"Are you sure you want to delete PK? Secure boot will be disabled!",
   3414           L"Press 'Y' to delete PK and exit, 'N' to discard change and return",
   3415           NULL
   3416           );
   3417         if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {
   3418           Status = DeletePlatformKey ();
   3419           if (EFI_ERROR (Status)) {
   3420             CreatePopUp (
   3421               EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   3422               &Key,
   3423               L"Only Physical Presence User could delete PK in custom mode!",
   3424               NULL
   3425               );
   3426           }
   3427         }
   3428       }
   3429       break;
   3430 
   3431     case KEY_DELETE_KEK:
   3432       UpdateDeletePage (
   3433         Private,
   3434         EFI_KEY_EXCHANGE_KEY_NAME,
   3435         &gEfiGlobalVariableGuid,
   3436         LABEL_KEK_DELETE,
   3437         FORMID_DELETE_KEK_FORM,
   3438         OPTION_DEL_KEK_QUESTION_ID
   3439         );
   3440       break;
   3441 
   3442     case SECUREBOOT_DELETE_SIGNATURE_FROM_DB:
   3443       UpdateDeletePage (
   3444         Private,
   3445         EFI_IMAGE_SECURITY_DATABASE,
   3446         &gEfiImageSecurityDatabaseGuid,
   3447         LABEL_DB_DELETE,
   3448         SECUREBOOT_DELETE_SIGNATURE_FROM_DB,
   3449         OPTION_DEL_DB_QUESTION_ID
   3450         );
   3451        break;
   3452 
   3453     case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX:
   3454       UpdateDeletePage (
   3455         Private,
   3456         EFI_IMAGE_SECURITY_DATABASE1,
   3457         &gEfiImageSecurityDatabaseGuid,
   3458         LABEL_DBX_DELETE,
   3459         SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,
   3460         OPTION_DEL_DBX_QUESTION_ID
   3461         );
   3462 
   3463       break;
   3464 
   3465     case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT:
   3466       UpdateDeletePage (
   3467         Private,
   3468         EFI_IMAGE_SECURITY_DATABASE2,
   3469         &gEfiImageSecurityDatabaseGuid,
   3470         LABEL_DBT_DELETE,
   3471         SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,
   3472         OPTION_DEL_DBT_QUESTION_ID
   3473         );
   3474 
   3475       break;
   3476 
   3477     case KEY_VALUE_SAVE_AND_EXIT_KEK:
   3478       Status = EnrollKeyExchangeKey (Private);
   3479       if (EFI_ERROR (Status)) {
   3480         CreatePopUp (
   3481           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   3482           &Key,
   3483           L"ERROR: Unsupported file type!",
   3484           L"Only supports DER-encoded X509 certificate",
   3485           NULL
   3486           );
   3487       }
   3488       break;
   3489 
   3490     case KEY_VALUE_SAVE_AND_EXIT_DB:
   3491       Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);
   3492       if (EFI_ERROR (Status)) {
   3493         CreatePopUp (
   3494           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   3495           &Key,
   3496           L"ERROR: Unsupported file type!",
   3497           L"Only supports DER-encoded X509 certificate and executable EFI image",
   3498           NULL
   3499           );
   3500       }
   3501       break;
   3502 
   3503     case KEY_VALUE_SAVE_AND_EXIT_DBX:
   3504       if (IsX509CertInDbx (Private, EFI_IMAGE_SECURITY_DATABASE1)) {
   3505         CreatePopUp (
   3506           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   3507           &Key,
   3508           L"Enrollment failed! Same certificate had already been in the dbx!",
   3509           NULL
   3510           );
   3511           break;
   3512       }
   3513 
   3514       if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) {
   3515         Status = EnrollX509HashtoSigDB (
   3516                    Private,
   3517                    IfrNvData->CertificateFormat,
   3518                    &IfrNvData->RevocationDate,
   3519                    &IfrNvData->RevocationTime,
   3520                    IfrNvData->AlwaysRevocation
   3521                    );
   3522       } else {
   3523         Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);
   3524       }
   3525       if (EFI_ERROR (Status)) {
   3526         CreatePopUp (
   3527           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   3528           &Key,
   3529           L"ERROR: Unsupported file type!",
   3530           L"Only supports DER-encoded X509 certificate and executable EFI image",
   3531           NULL
   3532           );
   3533       }
   3534       break;
   3535 
   3536     case KEY_VALUE_SAVE_AND_EXIT_DBT:
   3537       Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE2);
   3538       if (EFI_ERROR (Status)) {
   3539         CreatePopUp (
   3540           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   3541           &Key,
   3542           L"ERROR: Unsupported file type!",
   3543           L"Only supports DER-encoded X509 certificate.",
   3544           NULL
   3545           );
   3546       }
   3547       break;
   3548     case KEY_VALUE_SAVE_AND_EXIT_PK:
   3549       Status = EnrollPlatformKey (Private);
   3550       if (EFI_ERROR (Status)) {
   3551         UnicodeSPrint (
   3552           PromptString,
   3553           sizeof (PromptString),
   3554           L"Only DER encoded certificate file (%s) is supported.",
   3555           mSupportX509Suffix
   3556           );
   3557         CreatePopUp (
   3558           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
   3559           &Key,
   3560           L"ERROR: Unsupported file type!",
   3561           PromptString,
   3562           NULL
   3563           );
   3564       }
   3565       break;
   3566     default:
   3567       if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&
   3568                  (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) {
   3569         DeleteKeyExchangeKey (Private, QuestionId);
   3570       } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) &&
   3571                  (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) {
   3572         DeleteSignature (
   3573           Private,
   3574           EFI_IMAGE_SECURITY_DATABASE,
   3575           &gEfiImageSecurityDatabaseGuid,
   3576           LABEL_DB_DELETE,
   3577           SECUREBOOT_DELETE_SIGNATURE_FROM_DB,
   3578           OPTION_DEL_DB_QUESTION_ID,
   3579           QuestionId - OPTION_DEL_DB_QUESTION_ID
   3580           );
   3581       } else if ((QuestionId >= OPTION_DEL_DBX_QUESTION_ID) &&
   3582                  (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) {
   3583         DeleteSignature (
   3584           Private,
   3585           EFI_IMAGE_SECURITY_DATABASE1,
   3586           &gEfiImageSecurityDatabaseGuid,
   3587           LABEL_DBX_DELETE,
   3588           SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,
   3589           OPTION_DEL_DBX_QUESTION_ID,
   3590           QuestionId - OPTION_DEL_DBX_QUESTION_ID
   3591           );
   3592       } else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) &&
   3593                  (QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE))) {
   3594         DeleteSignature (
   3595           Private,
   3596           EFI_IMAGE_SECURITY_DATABASE2,
   3597           &gEfiImageSecurityDatabaseGuid,
   3598           LABEL_DBT_DELETE,
   3599           SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,
   3600           OPTION_DEL_DBT_QUESTION_ID,
   3601           QuestionId - OPTION_DEL_DBT_QUESTION_ID
   3602           );
   3603       }
   3604       break;
   3605 
   3606     case KEY_VALUE_NO_SAVE_AND_EXIT_PK:
   3607     case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:
   3608     case KEY_VALUE_NO_SAVE_AND_EXIT_DB:
   3609     case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:
   3610     case KEY_VALUE_NO_SAVE_AND_EXIT_DBT:
   3611       if (Private->FileContext->FHandle != NULL) {
   3612         CloseFile (Private->FileContext->FHandle);
   3613         Private->FileContext->FHandle = NULL;
   3614         if (Private->FileContext->FileName!= NULL){
   3615           FreePool(Private->FileContext->FileName);
   3616           Private->FileContext->FileName = NULL;
   3617         }
   3618       }
   3619 
   3620       if (Private->SignatureGUID != NULL) {
   3621         FreePool (Private->SignatureGUID);
   3622         Private->SignatureGUID = NULL;
   3623       }
   3624       break;
   3625     }
   3626   } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
   3627     switch (QuestionId) {
   3628     case KEY_SECURE_BOOT_ENABLE:
   3629       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
   3630       break;
   3631     case KEY_SECURE_BOOT_MODE:
   3632       mIsEnterSecureBootForm = FALSE;
   3633       break;
   3634     case KEY_SECURE_BOOT_KEK_GUID:
   3635     case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:
   3636     case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:
   3637     case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT:
   3638       ASSERT (Private->SignatureGUID != NULL);
   3639       Status = StringToGuid (
   3640                  IfrNvData->SignatureGuid,
   3641                  StrLen (IfrNvData->SignatureGuid),
   3642                  Private->SignatureGUID
   3643                  );
   3644       if (EFI_ERROR (Status)) {
   3645         break;
   3646       }
   3647 
   3648       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
   3649       break;
   3650 
   3651     case KEY_SECURE_BOOT_DELETE_PK:
   3652       GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);
   3653       if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {
   3654         IfrNvData->DeletePk = TRUE;
   3655         IfrNvData->HasPk    = FALSE;
   3656         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
   3657       } else  {
   3658         IfrNvData->DeletePk = FALSE;
   3659         IfrNvData->HasPk    = TRUE;
   3660         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
   3661       }
   3662       if (SetupMode != NULL) {
   3663         FreePool (SetupMode);
   3664       }
   3665       break;
   3666     default:
   3667       break;
   3668     }
   3669   } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) {
   3670     if (QuestionId == KEY_HIDE_SECURE_BOOT) {
   3671       GetVariable2 (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID**)&Pk, NULL);
   3672       if (Pk == NULL) {
   3673         IfrNvData->HideSecureBoot = TRUE;
   3674       } else {
   3675         FreePool (Pk);
   3676         IfrNvData->HideSecureBoot = FALSE;
   3677       }
   3678       Value->b = IfrNvData->HideSecureBoot;
   3679     }
   3680   } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
   3681     //
   3682     // Force the platform back to Standard Mode once user leave the setup screen.
   3683     //
   3684     GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);
   3685     if (NULL != SecureBootMode && *SecureBootMode == CUSTOM_SECURE_BOOT_MODE) {
   3686       IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;
   3687       SetSecureBootMode(STANDARD_SECURE_BOOT_MODE);
   3688     }
   3689     if (SecureBootMode != NULL) {
   3690       FreePool (SecureBootMode);
   3691     }
   3692   }
   3693 
   3694 EXIT:
   3695 
   3696   if (!EFI_ERROR (Status)) {
   3697     BufferSize = sizeof (SECUREBOOT_CONFIGURATION);
   3698     HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL);
   3699   }
   3700 
   3701   FreePool (IfrNvData);
   3702 
   3703   if (File != NULL){
   3704     FreePool(File);
   3705     File = NULL;
   3706   }
   3707 
   3708   return EFI_SUCCESS;
   3709 }
   3710 
   3711 /**
   3712   This function publish the SecureBoot configuration Form.
   3713 
   3714   @param[in, out]  PrivateData   Points to SecureBoot configuration private data.
   3715 
   3716   @retval EFI_SUCCESS            HII Form is installed successfully.
   3717   @retval EFI_OUT_OF_RESOURCES   Not enough resource for HII Form installation.
   3718   @retval Others                 Other errors as indicated.
   3719 
   3720 **/
   3721 EFI_STATUS
   3722 InstallSecureBootConfigForm (
   3723   IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA  *PrivateData
   3724   )
   3725 {
   3726   EFI_STATUS                      Status;
   3727   EFI_HII_HANDLE                  HiiHandle;
   3728   EFI_HANDLE                      DriverHandle;
   3729   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
   3730 
   3731   DriverHandle = NULL;
   3732   ConfigAccess = &PrivateData->ConfigAccess;
   3733   Status = gBS->InstallMultipleProtocolInterfaces (
   3734                   &DriverHandle,
   3735                   &gEfiDevicePathProtocolGuid,
   3736                   &mSecureBootHiiVendorDevicePath,
   3737                   &gEfiHiiConfigAccessProtocolGuid,
   3738                   ConfigAccess,
   3739                   NULL
   3740                   );
   3741   if (EFI_ERROR (Status)) {
   3742     return Status;
   3743   }
   3744 
   3745   PrivateData->DriverHandle = DriverHandle;
   3746 
   3747   //
   3748   // Publish the HII package list
   3749   //
   3750   HiiHandle = HiiAddPackages (
   3751                 &gSecureBootConfigFormSetGuid,
   3752                 DriverHandle,
   3753                 SecureBootConfigDxeStrings,
   3754                 SecureBootConfigBin,
   3755                 NULL
   3756                 );
   3757   if (HiiHandle == NULL) {
   3758     gBS->UninstallMultipleProtocolInterfaces (
   3759            DriverHandle,
   3760            &gEfiDevicePathProtocolGuid,
   3761            &mSecureBootHiiVendorDevicePath,
   3762            &gEfiHiiConfigAccessProtocolGuid,
   3763            ConfigAccess,
   3764            NULL
   3765            );
   3766     return EFI_OUT_OF_RESOURCES;
   3767   }
   3768 
   3769   PrivateData->HiiHandle = HiiHandle;
   3770 
   3771   PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));
   3772 
   3773   if (PrivateData->FileContext == NULL) {
   3774     UninstallSecureBootConfigForm (PrivateData);
   3775     return EFI_OUT_OF_RESOURCES;
   3776   }
   3777 
   3778   //
   3779   // Init OpCode Handle and Allocate space for creation of Buffer
   3780   //
   3781   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
   3782   if (mStartOpCodeHandle == NULL) {
   3783     UninstallSecureBootConfigForm (PrivateData);
   3784     return EFI_OUT_OF_RESOURCES;
   3785   }
   3786 
   3787   mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
   3788   if (mEndOpCodeHandle == NULL) {
   3789     UninstallSecureBootConfigForm (PrivateData);
   3790     return EFI_OUT_OF_RESOURCES;
   3791   }
   3792 
   3793   //
   3794   // Create Hii Extend Label OpCode as the start opcode
   3795   //
   3796   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
   3797                                          mStartOpCodeHandle,
   3798                                          &gEfiIfrTianoGuid,
   3799                                          NULL,
   3800                                          sizeof (EFI_IFR_GUID_LABEL)
   3801                                          );
   3802   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
   3803 
   3804   //
   3805   // Create Hii Extend Label OpCode as the end opcode
   3806   //
   3807   mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
   3808                                        mEndOpCodeHandle,
   3809                                        &gEfiIfrTianoGuid,
   3810                                        NULL,
   3811                                        sizeof (EFI_IFR_GUID_LABEL)
   3812                                        );
   3813   mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
   3814   mEndLabel->Number       = LABEL_END;
   3815 
   3816   return EFI_SUCCESS;
   3817 }
   3818 
   3819 /**
   3820   This function removes SecureBoot configuration Form.
   3821 
   3822   @param[in, out]  PrivateData   Points to SecureBoot configuration private data.
   3823 
   3824 **/
   3825 VOID
   3826 UninstallSecureBootConfigForm (
   3827   IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData
   3828   )
   3829 {
   3830   //
   3831   // Uninstall HII package list
   3832   //
   3833   if (PrivateData->HiiHandle != NULL) {
   3834     HiiRemovePackages (PrivateData->HiiHandle);
   3835     PrivateData->HiiHandle = NULL;
   3836   }
   3837 
   3838   //
   3839   // Uninstall HII Config Access Protocol
   3840   //
   3841   if (PrivateData->DriverHandle != NULL) {
   3842     gBS->UninstallMultipleProtocolInterfaces (
   3843            PrivateData->DriverHandle,
   3844            &gEfiDevicePathProtocolGuid,
   3845            &mSecureBootHiiVendorDevicePath,
   3846            &gEfiHiiConfigAccessProtocolGuid,
   3847            &PrivateData->ConfigAccess,
   3848            NULL
   3849            );
   3850     PrivateData->DriverHandle = NULL;
   3851   }
   3852 
   3853   if (PrivateData->SignatureGUID != NULL) {
   3854     FreePool (PrivateData->SignatureGUID);
   3855   }
   3856 
   3857   if (PrivateData->FileContext != NULL) {
   3858     FreePool (PrivateData->FileContext);
   3859   }
   3860 
   3861   FreePool (PrivateData);
   3862 
   3863   if (mStartOpCodeHandle != NULL) {
   3864     HiiFreeOpCodeHandle (mStartOpCodeHandle);
   3865   }
   3866 
   3867   if (mEndOpCodeHandle != NULL) {
   3868     HiiFreeOpCodeHandle (mEndOpCodeHandle);
   3869   }
   3870 }
   3871