X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=SecurityPkg%2FVariableAuthenticated%2FSecureBootConfigDxe%2FSecureBootConfigImpl.c;h=517d9d9904c48e09f44551a23fd89e862808c916;hp=c6356143bc66721ed7c5fd1ef1b687d4a799194a;hb=20333c6d566748d7c78c1b546ba8f37c6d253dea;hpb=33985e3b52ee2e4b5064331134d983e55a7da904 diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index c6356143bc..517d9d9904 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -17,7 +17,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. CHAR16 mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION"; SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate = { - SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE, + SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE, { SecureBootExtractConfig, SecureBootRouteConfig, @@ -63,16 +63,16 @@ UINT8 mHashOidValue[] = { }; HASH_TABLE mHash[] = { - { L"SHA1", 20, &mHashOidValue[8], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final }, - { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL }, - { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize,Sha256Init, Sha256Update, Sha256Final}, - { L"SHA384", 48, &mHashOidValue[31], 9, NULL, NULL, NULL, NULL }, - { L"SHA512", 64, &mHashOidValue[40], 9, NULL, NULL, NULL, NULL } + { L"SHA1", 20, &mHashOidValue[8], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final }, + { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL }, + { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final}, + { L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final}, + { L"SHA512", 64, &mHashOidValue[40], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final} }; // -// Variable Definitions -// +// Variable Definitions +// UINT32 mPeCoffHeaderOffset = 0; WIN_CERTIFICATE *mCertificate = NULL; IMAGE_TYPE mImageType; @@ -109,7 +109,7 @@ IsDerEncodeCertificate ( IN CONST CHAR16 *FileSuffix ) { - UINTN Index; + UINTN Index; for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) { if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) { return TRUE; @@ -147,14 +147,14 @@ SaveSecureBootVariable ( /** Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2 descriptor with the input data. NO authentication is required in this function. - + @param[in, out] DataSize On input, the size of Data buffer in bytes. On output, the size of data returned in Data buffer in bytes. - @param[in, out] Data On input, Pointer to data buffer to be wrapped or + @param[in, out] Data On input, Pointer to data buffer to be wrapped or pointer to NULL to wrap an empty payload. On output, Pointer to the new payload date buffer allocated from pool, - it's caller's responsibility to free the memory when finish using it. + it's caller's responsibility to free the memory when finish using it. @retval EFI_SUCCESS Create time based payload successfully. @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload. @@ -175,20 +175,20 @@ CreateTimeBasedPayload ( EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; UINTN DescriptorSize; EFI_TIME Time; - + if (Data == NULL || DataSize == NULL) { return EFI_INVALID_PARAMETER; } - + // - // In Setup mode or Custom mode, the variable does not need to be signed but the + // In Setup mode or Custom mode, the variable does not need to be signed but the // parameters to the SetVariable() call still need to be prepared as authenticated // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate // data in it. // Payload = *Data; PayloadSize = *DataSize; - + DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize); if (NewData == NULL) { @@ -213,16 +213,16 @@ CreateTimeBasedPayload ( Time.Daylight = 0; Time.Pad2 = 0; CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME)); - + DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); DescriptorData->AuthInfo.Hdr.wRevision = 0x0200; DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid); - + if (Payload != NULL) { FreePool(Payload); } - + *DataSize = DescriptorSize + PayloadSize; *Data = NewData; return EFI_SUCCESS; @@ -287,17 +287,17 @@ DeleteVariable ( @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or CUSTOM_SECURE_BOOT_MODE. - + @return EFI_SUCCESS The platform has switched to the special mode successfully. @return other Fail to operate the secure boot mode. - + **/ EFI_STATUS SetSecureBootMode ( IN UINT8 SecureBootMode ) { - return gRT->SetVariable ( + return gRT->SetVariable ( EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, @@ -311,26 +311,26 @@ SetSecureBootMode ( @param[in] X509File FileHandle of X509 Certificate storing file. @param[out] PkCert Point to the data buffer to store the signature list. - + @return EFI_UNSUPPORTED Unsupported Key Length. @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list. - + **/ EFI_STATUS CreatePkX509SignatureList ( - IN EFI_FILE_HANDLE X509File, - OUT EFI_SIGNATURE_LIST **PkCert + IN EFI_FILE_HANDLE X509File, + OUT EFI_SIGNATURE_LIST **PkCert ) { - EFI_STATUS Status; + EFI_STATUS Status; UINT8 *X509Data; UINTN X509DataSize; EFI_SIGNATURE_DATA *PkCertData; X509Data = NULL; PkCertData = NULL; - X509DataSize = 0; - + X509DataSize = 0; + Status = ReadFileContent (X509File, (VOID**) &X509Data, &X509DataSize, 0); if (EFI_ERROR (Status)) { goto ON_EXIT; @@ -350,32 +350,32 @@ CreatePkX509SignatureList ( goto ON_EXIT; } - (*PkCert)->SignatureListSize = (UINT32) (sizeof(EFI_SIGNATURE_LIST) + (*PkCert)->SignatureListSize = (UINT32) (sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); (*PkCert)->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); (*PkCert)->SignatureHeaderSize = 0; CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid); - PkCertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert) + PkCertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert) + sizeof(EFI_SIGNATURE_LIST) + (*PkCert)->SignatureHeaderSize); - CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid); + CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid); // // Fill the PK database with PKpub data from X509 certificate file. - // + // CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize); - + ON_EXIT: - + if (X509Data != NULL) { FreePool (X509Data); } - + if (EFI_ERROR(Status) && *PkCert != NULL) { FreePool (*PkCert); *PkCert = NULL; } - + return Status; } @@ -389,12 +389,12 @@ ON_EXIT: @retval EFI_SUCCESS New PK enrolled successfully. @retval EFI_INVALID_PARAMETER The parameter is invalid. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - + **/ EFI_STATUS EnrollPlatformKey ( IN SECUREBOOT_CONFIG_PRIVATE_DATA* Private - ) + ) { EFI_STATUS Status; UINT32 Attr; @@ -402,7 +402,7 @@ EnrollPlatformKey ( EFI_SIGNATURE_LIST *PkCert; UINT16* FilePostFix; UINTN NameLength; - + if (Private->FileContext->FileName == NULL) { return EFI_INVALID_PARAMETER; } @@ -433,18 +433,18 @@ EnrollPlatformKey ( // Prase the selected PK file and generature PK certificate list. // Status = CreatePkX509SignatureList ( - Private->FileContext->FHandle, - &PkCert + Private->FileContext->FHandle, + &PkCert ); if (EFI_ERROR (Status)) { goto ON_EXIT; } ASSERT (PkCert != NULL); - + // // Set Platform Key variable. - // - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + // + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; DataSize = PkCert->SignatureListSize; Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert); @@ -452,12 +452,12 @@ EnrollPlatformKey ( DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); goto ON_EXIT; } - + Status = gRT->SetVariable( - EFI_PLATFORM_KEY_NAME, - &gEfiGlobalVariableGuid, - Attr, - DataSize, + EFI_PLATFORM_KEY_NAME, + &gEfiGlobalVariableGuid, + Attr, + DataSize, PkCert ); if (EFI_ERROR (Status)) { @@ -466,13 +466,13 @@ EnrollPlatformKey ( } goto ON_EXIT; } - + ON_EXIT: if (PkCert != NULL) { FreePool(PkCert); } - + if (Private->FileContext->FHandle != NULL) { CloseFile (Private->FileContext->FHandle); Private->FileContext->FHandle = NULL; @@ -486,7 +486,7 @@ ON_EXIT: @retval EFI_SUCCESS Delete PK successfully. @retval Others Could not allow to delete PK. - + **/ EFI_STATUS DeletePlatformKey ( @@ -532,7 +532,7 @@ EnrollRsa2048ToKek ( CPL_KEY_INFO *KeyInfo; EFI_SIGNATURE_DATA *KEKSigData; UINTN KekSigListSize; - UINT8 *KeyBuffer; + UINT8 *KeyBuffer; UINTN KeyLenInBytes; Attr = 0; @@ -544,11 +544,11 @@ EnrollRsa2048ToKek ( KEKSigData = NULL; KekSigList = NULL; KekSigListSize = 0; - + // // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type. // First, We have to parse out public key data from the pbk key file. - // + // Status = ReadFileContent ( Private->FileContext->FHandle, (VOID**) &KeyBlob, @@ -565,10 +565,10 @@ EnrollRsa2048ToKek ( Status = EFI_UNSUPPORTED; goto ON_EXIT; } - + // // Convert the Public key to fix octet string format represented in RSA PKCS#1. - // + // KeyLenInBytes = KeyInfo->KeyLengthInBits / 8; KeyBuffer = AllocateZeroPool (KeyLenInBytes); if (KeyBuffer == NULL) { @@ -576,13 +576,13 @@ EnrollRsa2048ToKek ( goto ON_EXIT; } Int2OctStr ( - (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)), - KeyLenInBytes / sizeof (UINTN), - KeyBuffer, + (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)), + KeyLenInBytes / sizeof (UINTN), + KeyBuffer, KeyLenInBytes ); CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes); - + // // Form an new EFI_SIGNATURE_LIST. // @@ -602,7 +602,7 @@ EnrollRsa2048ToKek ( KekSigList->SignatureHeaderSize = 0; KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE; CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid); - + KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST)); CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID); CopyMem ( @@ -610,13 +610,13 @@ EnrollRsa2048ToKek ( KeyBlob + sizeof(CPL_KEY_INFO), WIN_CERT_UEFI_RSA2048_SIZE ); - + // - // Check if KEK entry has been already existed. - // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the + // Check if KEK entry has been already existed. + // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the // new KEK to original variable. - // - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + // + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList); if (EFI_ERROR (Status)) { @@ -625,10 +625,10 @@ EnrollRsa2048ToKek ( } Status = gRT->GetVariable( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - NULL, - &DataSize, + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, NULL ); if (Status == EFI_BUFFER_TOO_SMALL) { @@ -636,21 +636,21 @@ EnrollRsa2048ToKek ( } else if (Status != EFI_NOT_FOUND) { goto ON_EXIT; } - + // // Done. Now we have formed the correct KEKpub database item, just set it into variable storage, - // + // Status = gRT->SetVariable( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - Attr, - KekSigListSize, + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + Attr, + KekSigListSize, KekSigList ); if (EFI_ERROR (Status)) { goto ON_EXIT; } - + ON_EXIT: CloseFile (Private->FileContext->FHandle); @@ -671,7 +671,7 @@ ON_EXIT: if (KekSigList != NULL) { FreePool (KekSigList); } - + return Status; } @@ -689,7 +689,7 @@ ON_EXIT: EFI_STATUS EnrollX509ToKek ( IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private - ) + ) { EFI_STATUS Status; UINTN X509DataSize; @@ -727,7 +727,7 @@ EnrollX509ToKek ( // // Fill Certificate Database parameters. - // + // KekSigList->SignatureListSize = (UINT32) KekSigListSize; KekSigList->SignatureHeaderSize = 0; KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); @@ -738,35 +738,35 @@ EnrollX509ToKek ( CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize); // - // Check if KEK been already existed. - // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the + // Check if KEK been already existed. + // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the // new kek to original variable - // - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + // + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); goto ON_EXIT; } - + Status = gRT->GetVariable( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - NULL, - &DataSize, + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, NULL ); if (Status == EFI_BUFFER_TOO_SMALL) { Attr |= EFI_VARIABLE_APPEND_WRITE; } else if (Status != EFI_NOT_FOUND) { goto ON_EXIT; - } + } Status = gRT->SetVariable( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - Attr, + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + Attr, KekSigListSize, KekSigList ); @@ -775,7 +775,728 @@ EnrollX509ToKek ( } ON_EXIT: - + + CloseFile (Private->FileContext->FHandle); + Private->FileContext->FileName = NULL; + Private->FileContext->FHandle = NULL; + + if (Private->SignatureGUID != NULL) { + FreePool (Private->SignatureGUID); + Private->SignatureGUID = NULL; + } + + if (KekSigList != NULL) { + FreePool (KekSigList); + } + + return Status; +} + +/** + Enroll new KEK into the System without PK's authentication. + The SignatureOwner GUID will be Private->SignatureGUID. + + @param[in] PrivateData The module's private data. + + @retval EFI_SUCCESS New KEK enrolled successful. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval others Fail to enroll KEK data. + +**/ +EFI_STATUS +EnrollKeyExchangeKey ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private + ) +{ + UINT16* FilePostFix; + EFI_STATUS Status; + UINTN NameLength; + + if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Parse the file's postfix. Supports DER-encoded X509 certificate, + // and .pbk as RSA public key file. + // + NameLength = StrLen (Private->FileContext->FileName); + if (NameLength <= 4) { + return EFI_INVALID_PARAMETER; + } + FilePostFix = Private->FileContext->FileName + NameLength - 4; + if (IsDerEncodeCertificate(FilePostFix)) { + return EnrollX509ToKek (Private); + } else if (CompareMem (FilePostFix, L".pbk",4) == 0) { + return EnrollRsa2048ToKek (Private); + } else { + return EFI_INVALID_PARAMETER; + } +} + +/** + Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without + KEK's authentication. + + @param[in] PrivateData The module's private data. + @param[in] VariableName Variable name of signature database, must be + EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1. + + @retval EFI_SUCCESS New X509 is enrolled successfully. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +EnrollX509toSigDB ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, + IN CHAR16 *VariableName + ) +{ + EFI_STATUS Status; + UINTN X509DataSize; + VOID *X509Data; + EFI_SIGNATURE_LIST *SigDBCert; + EFI_SIGNATURE_DATA *SigDBCertData; + VOID *Data; + UINTN DataSize; + UINTN SigDBSize; + UINT32 Attr; + + X509DataSize = 0; + SigDBSize = 0; + DataSize = 0; + X509Data = NULL; + SigDBCert = NULL; + SigDBCertData = NULL; + Data = NULL; + + Status = ReadFileContent ( + Private->FileContext->FHandle, + &X509Data, + &X509DataSize, + 0 + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + ASSERT (X509Data != NULL); + + SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize; + + Data = AllocateZeroPool (SigDBSize); + if (Data == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + // + // Fill Certificate Database parameters. + // + SigDBCert = (EFI_SIGNATURE_LIST*) Data; + SigDBCert->SignatureListSize = (UINT32) SigDBSize; + SigDBCert->SignatureHeaderSize = 0; + SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); + CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid); + + SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST)); + CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID); + CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize); + + // + // Check if signature database entry has been already existed. + // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the + // new signature data to original variable + // + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); + goto ON_EXIT; + } + + Status = gRT->GetVariable( + VariableName, + &gEfiImageSecurityDatabaseGuid, + NULL, + &DataSize, + NULL + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + Attr |= EFI_VARIABLE_APPEND_WRITE; + } else if (Status != EFI_NOT_FOUND) { + goto ON_EXIT; + } + + Status = gRT->SetVariable( + VariableName, + &gEfiImageSecurityDatabaseGuid, + Attr, + SigDBSize, + Data + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + +ON_EXIT: + + CloseFile (Private->FileContext->FHandle); + Private->FileContext->FileName = NULL; + Private->FileContext->FHandle = NULL; + + if (Private->SignatureGUID != NULL) { + FreePool (Private->SignatureGUID); + Private->SignatureGUID = NULL; + } + + if (Data != NULL) { + FreePool (Data); + } + + if (X509Data != NULL) { + FreePool (X509Data); + } + + return Status; +} + +/** + Check whether signature is in specified database. + + @param[in] VariableName Name of database variable that is searched in. + @param[in] Signature Pointer to signature that is searched for. + @param[in] SignatureSize Size of Signature. + + @return TRUE Found the signature in the variable database. + @return FALSE Not found the signature in the variable database. + +**/ +BOOLEAN +IsSignatureFoundInDatabase ( + IN CHAR16 *VariableName, + IN UINT8 *Signature, + IN UINTN SignatureSize + ) +{ + EFI_STATUS Status; + EFI_SIGNATURE_LIST *CertList; + EFI_SIGNATURE_DATA *Cert; + UINTN DataSize; + UINT8 *Data; + UINTN Index; + UINTN CertCount; + BOOLEAN IsFound; + + // + // Read signature database variable. + // + IsFound = FALSE; + Data = NULL; + DataSize = 0; + Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL); + if (Status != EFI_BUFFER_TOO_SMALL) { + return FALSE; + } + + Data = (UINT8 *) AllocateZeroPool (DataSize); + if (Data == NULL) { + return FALSE; + } + + Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Enumerate all signature data in SigDB to check if executable's signature exists. + // + CertList = (EFI_SIGNATURE_LIST *) Data; + while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) { + CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; + Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); + if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, &gEfiCertX509Guid))) { + for (Index = 0; Index < CertCount; Index++) { + if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) { + // + // Find the signature in database. + // + IsFound = TRUE; + break; + } + Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize); + } + + if (IsFound) { + break; + } + } + + DataSize -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); + } + +Done: + if (Data != NULL) { + FreePool (Data); + } + + return IsFound; +} + +/** + Calculate the hash of a certificate data with the specified hash algorithm. + + @param[in] CertData The certificate data to be hashed. + @param[in] CertSize The certificate size in bytes. + @param[in] HashAlg The specified hash algorithm. + @param[out] CertHash The output digest of the certificate + + @retval TRUE Successfully got the hash of the CertData. + @retval FALSE Failed to get the hash of CertData. + +**/ +BOOLEAN +CalculateCertHash ( + IN UINT8 *CertData, + IN UINTN CertSize, + IN UINT32 HashAlg, + OUT UINT8 *CertHash + ) +{ + BOOLEAN Status; + VOID *HashCtx; + UINTN CtxSize; + + HashCtx = NULL; + Status = FALSE; + + if (HashAlg >= HASHALG_MAX) { + return FALSE; + } + + // + // 1. Initialize context of hash. + // + CtxSize = mHash[HashAlg].GetContextSize (); + HashCtx = AllocatePool (CtxSize); + ASSERT (HashCtx != NULL); + + // + // 2. Initialize a hash context. + // + Status = mHash[HashAlg].HashInit (HashCtx); + if (!Status) { + goto Done; + } + + // + // 3. Calculate the hash. + // + Status = mHash[HashAlg].HashUpdate (HashCtx, CertData, CertSize); + if (!Status) { + goto Done; + } + + // + // 4. Get the hash result. + // + ZeroMem (CertHash, mHash[HashAlg].DigestLength); + Status = mHash[HashAlg].HashFinal (HashCtx, CertHash); + +Done: + if (HashCtx != NULL) { + FreePool (HashCtx); + } + + return Status; +} + +/** + Check whether the hash of an X.509 certificate is in forbidden database (DBX). + + @param[in] Certificate Pointer to X.509 Certificate that is searched for. + @param[in] CertSize Size of X.509 Certificate. + + @return TRUE Found the certificate hash in the forbidden database. + @return FALSE Certificate hash is Not found in the forbidden database. + +**/ +BOOLEAN +IsCertHashFoundInDbx ( + IN UINT8 *Certificate, + IN UINTN CertSize + ) +{ + BOOLEAN IsFound; + EFI_STATUS Status; + EFI_SIGNATURE_LIST *DbxList; + EFI_SIGNATURE_DATA *CertHash; + UINTN CertHashCount; + UINTN Index; + UINT32 HashAlg; + UINT8 CertDigest[MAX_DIGEST_SIZE]; + UINT8 *DbxCertHash; + UINTN SiglistHeaderSize; + UINT8 *Data; + UINTN DataSize; + + IsFound = FALSE; + HashAlg = HASHALG_MAX; + Data = NULL; + + // + // Read signature database variable. + // + DataSize = 0; + Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL); + if (Status != EFI_BUFFER_TOO_SMALL) { + return FALSE; + } + + Data = (UINT8 *) AllocateZeroPool (DataSize); + if (Data == NULL) { + return FALSE; + } + + Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Check whether the certificate hash exists in the forbidden database. + // + DbxList = (EFI_SIGNATURE_LIST *) Data; + while ((DataSize > 0) && (DataSize >= DbxList->SignatureListSize)) { + // + // Determine Hash Algorithm of Certificate in the forbidden database. + // + if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) { + HashAlg = HASHALG_SHA256; + } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) { + HashAlg = HASHALG_SHA384; + } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) { + HashAlg = HASHALG_SHA512; + } else { + DataSize -= DbxList->SignatureListSize; + DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize); + continue; + } + + // + // Calculate the hash value of current db certificate for comparision. + // + if (!CalculateCertHash (Certificate, CertSize, HashAlg, CertDigest)) { + goto Done; + } + + SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize; + CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize); + CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize; + for (Index = 0; Index < CertHashCount; Index++) { + // + // Iterate each Signature Data Node within this CertList for verify. + // + DbxCertHash = CertHash->SignatureData; + if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) { + // + // Hash of Certificate is found in forbidden database. + // + IsFound = TRUE; + goto Done; + } + CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize); + } + + DataSize -= DbxList->SignatureListSize; + DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize); + } + +Done: + if (Data != NULL) { + FreePool (Data); + } + + return IsFound; +} + +/** + Check whether the signature list exists in given variable data. + + It searches the signature list for the ceritificate hash by CertType. + If the signature list is found, get the offset of Database for the + next hash of a certificate. + + @param[in] Database Variable data to save signature list. + @param[in] DatabaseSize Variable size. + @param[in] SignatureType The type of the signature. + @param[out] Offset The offset to save a new hash of certificate. + + @return TRUE The signature list is found in the forbidden database. + @return FALSE The signature list is not found in the forbidden database. +**/ +BOOLEAN +GetSignaturelistOffset ( + IN EFI_SIGNATURE_LIST *Database, + IN UINTN DatabaseSize, + IN EFI_GUID *SignatureType, + OUT UINTN *Offset + ) +{ + EFI_SIGNATURE_LIST *SigList; + UINTN SiglistSize; + + if ((Database == NULL) || (DatabaseSize == 0)) { + *Offset = 0; + return FALSE; + } + + SigList = Database; + SiglistSize = DatabaseSize; + while ((SiglistSize > 0) && (SiglistSize >= SigList->SignatureListSize)) { + if (CompareGuid (&SigList->SignatureType, SignatureType)) { + *Offset = DatabaseSize - SiglistSize; + return TRUE; + } + SiglistSize -= SigList->SignatureListSize; + SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize); + } + *Offset = 0; + return FALSE; +} + +/** + Enroll a new X509 certificate hash into Signature Database (dbx) without + KEK's authentication. + + @param[in] PrivateData The module's private data. + @param[in] HashAlg The hash algorithm to enroll the certificate. + @param[in] RevocationDate The revocation date of the certificate. + @param[in] RevocationTime The revocation time of the certificate. + @param[in] AlwaysRevocation Indicate whether the certificate is always revoked. + + @retval EFI_SUCCESS New X509 is enrolled successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +EnrollX509HashtoSigDB ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, + IN UINT32 HashAlg, + IN EFI_HII_DATE *RevocationDate, + IN EFI_HII_TIME *RevocationTime, + IN BOOLEAN AlwaysRevocation + ) +{ + EFI_STATUS Status; + UINTN X509DataSize; + VOID *X509Data; + EFI_SIGNATURE_LIST *SignatureList; + UINTN SignatureListSize; + UINT8 *Data; + UINT8 *NewData; + UINTN DataSize; + UINTN DbSize; + UINT32 Attr; + EFI_SIGNATURE_DATA *SignatureData; + UINTN SignatureSize; + EFI_GUID SignatureType; + UINTN Offset; + UINT8 CertHash[MAX_DIGEST_SIZE]; + UINT16* FilePostFix; + UINTN NameLength; + EFI_TIME *Time; + + X509DataSize = 0; + DbSize = 0; + X509Data = NULL; + SignatureData = NULL; + SignatureList = NULL; + Data = NULL; + NewData = NULL; + + if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Parse the file's postfix. + // + NameLength = StrLen (Private->FileContext->FileName); + if (NameLength <= 4) { + return EFI_INVALID_PARAMETER; + } + FilePostFix = Private->FileContext->FileName + NameLength - 4; + if (!IsDerEncodeCertificate(FilePostFix)) { + // + // Only supports DER-encoded X509 certificate. + // + return EFI_INVALID_PARAMETER; + } + + // + // Get the certificate from file and calculate its hash. + // + Status = ReadFileContent ( + Private->FileContext->FHandle, + &X509Data, + &X509DataSize, + 0 + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + ASSERT (X509Data != NULL); + + if (!CalculateCertHash (X509Data, X509DataSize, HashAlg, CertHash)) { + goto ON_EXIT; + } + + // + // Get the variable for enrollment. + // + DataSize = 0; + Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL); + if (Status == EFI_BUFFER_TOO_SMALL) { + Data = (UINT8 *) AllocateZeroPool (DataSize); + if (Data == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + } + + // + // Allocate memory for Signature and fill the Signature + // + SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + sizeof (EFI_TIME) + mHash[HashAlg].DigestLength; + SignatureData = (EFI_SIGNATURE_DATA *) AllocateZeroPool (SignatureSize); + if (SignatureData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyGuid (&SignatureData->SignatureOwner, Private->SignatureGUID); + CopyMem (SignatureData->SignatureData, CertHash, mHash[HashAlg].DigestLength); + + // + // Fill the time. + // + if (!AlwaysRevocation) { + Time = (EFI_TIME *)(&SignatureData->SignatureData + mHash[HashAlg].DigestLength); + Time->Year = RevocationDate->Year; + Time->Month = RevocationDate->Month; + Time->Day = RevocationDate->Day; + Time->Hour = RevocationTime->Hour; + Time->Minute = RevocationTime->Minute; + Time->Second = RevocationTime->Second; + } + + // + // Determine the GUID for certificate hash. + // + switch (HashAlg) { + case HASHALG_SHA256: + SignatureType = gEfiCertX509Sha256Guid; + break; + case HASHALG_SHA384: + SignatureType = gEfiCertX509Sha384Guid; + break; + case HASHALG_SHA512: + SignatureType = gEfiCertX509Sha512Guid; + break; + default: + return FALSE; + } + + // + // Add signature into the new variable data buffer + // + if (GetSignaturelistOffset((EFI_SIGNATURE_LIST *)Data, DataSize, &SignatureType, &Offset)) { + // + // Add the signature to the found signaturelist. + // + DbSize = DataSize + SignatureSize; + NewData = AllocateZeroPool (DbSize); + if (NewData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + SignatureList = (EFI_SIGNATURE_LIST *)(Data + Offset); + SignatureListSize = (UINTN) ReadUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize); + CopyMem (NewData, Data, Offset + SignatureListSize); + + SignatureList = (EFI_SIGNATURE_LIST *)(NewData + Offset); + WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32)(SignatureListSize + SignatureSize)); + + Offset += SignatureListSize; + CopyMem (NewData + Offset, SignatureData, SignatureSize); + CopyMem (NewData + Offset + SignatureSize, Data + Offset, DataSize - Offset); + + FreePool (Data); + Data = NewData; + DataSize = DbSize; + } else { + // + // Create a new signaturelist, and add the signature into the signaturelist. + // + DbSize = DataSize + sizeof(EFI_SIGNATURE_LIST) + SignatureSize; + NewData = AllocateZeroPool (DbSize); + if (NewData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + // + // Fill Certificate Database parameters. + // + SignatureList = (EFI_SIGNATURE_LIST*) (NewData + DataSize); + SignatureListSize = sizeof(EFI_SIGNATURE_LIST) + SignatureSize; + WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32) SignatureListSize); + WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureSize, (UINT32) SignatureSize); + CopyGuid (&SignatureList->SignatureType, &SignatureType); + CopyMem ((UINT8* ) SignatureList + sizeof (EFI_SIGNATURE_LIST), SignatureData, SignatureSize); + if ((DataSize != 0) && (Data != NULL)) { + CopyMem (NewData, Data, DataSize); + FreePool (Data); + } + Data = NewData; + DataSize = DbSize; + } + + Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &Data); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + Status = gRT->SetVariable( + EFI_IMAGE_SECURITY_DATABASE1, + &gEfiImageSecurityDatabaseGuid, + Attr, + DataSize, + Data + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + +ON_EXIT: CloseFile (Private->FileContext->FHandle); Private->FileContext->FileName = NULL; Private->FileContext->FHandle = NULL; @@ -785,96 +1506,47 @@ ON_EXIT: Private->SignatureGUID = NULL; } - if (KekSigList != NULL) { - FreePool (KekSigList); + if (Data != NULL) { + FreePool (Data); } - return Status; -} - -/** - Enroll new KEK into the System without PK's authentication. - The SignatureOwner GUID will be Private->SignatureGUID. - - @param[in] PrivateData The module's private data. - - @retval EFI_SUCCESS New KEK enrolled successful. - @retval EFI_INVALID_PARAMETER The parameter is invalid. - @retval others Fail to enroll KEK data. - -**/ -EFI_STATUS -EnrollKeyExchangeKey ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private - ) -{ - UINT16* FilePostFix; - EFI_STATUS Status; - UINTN NameLength; - - if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) { - return EFI_INVALID_PARAMETER; + if (SignatureData != NULL) { + FreePool (SignatureData); } - Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); - if (EFI_ERROR (Status)) { - return Status; + if (X509Data != NULL) { + FreePool (X509Data); } - // - // Parse the file's postfix. Supports DER-encoded X509 certificate, - // and .pbk as RSA public key file. - // - NameLength = StrLen (Private->FileContext->FileName); - if (NameLength <= 4) { - return EFI_INVALID_PARAMETER; - } - FilePostFix = Private->FileContext->FileName + NameLength - 4; - if (IsDerEncodeCertificate(FilePostFix)) { - return EnrollX509ToKek (Private); - } else if (CompareMem (FilePostFix, L".pbk",4) == 0) { - return EnrollRsa2048ToKek (Private); - } else { - return EFI_INVALID_PARAMETER; - } + return Status; } /** - Enroll a new X509 certificate into Signature Database (DB or DBX) without - KEK's authentication. + Check whether a certificate from a file exists in dbx. @param[in] PrivateData The module's private data. - @param[in] VariableName Variable name of signature database, must be - EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1. - - @retval EFI_SUCCESS New X509 is enrolled successfully. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + @param[in] VariableName Variable name of signature database, must be + EFI_IMAGE_SECURITY_DATABASE1. + @retval TRUE The X509 certificate is found in dbx successfully. + @retval FALSE The X509 certificate is not found in dbx. **/ -EFI_STATUS -EnrollX509toSigDB ( +BOOLEAN +IsX509CertInDbx ( IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, IN CHAR16 *VariableName - ) + ) { - EFI_STATUS Status; - UINTN X509DataSize; - VOID *X509Data; - EFI_SIGNATURE_LIST *SigDBCert; - EFI_SIGNATURE_DATA *SigDBCertData; - VOID *Data; - UINTN DataSize; - UINTN SigDBSize; - UINT32 Attr; + EFI_STATUS Status; + UINTN X509DataSize; + VOID *X509Data; + BOOLEAN IsFound; + // + // Read the certificate from file + // X509DataSize = 0; - SigDBSize = 0; - DataSize = 0; X509Data = NULL; - SigDBCert = NULL; - SigDBCertData = NULL; - Data = NULL; - Status = ReadFileContent ( Private->FileContext->FHandle, &X509Data, @@ -882,88 +1554,32 @@ EnrollX509toSigDB ( 0 ); if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - ASSERT (X509Data != NULL); - - SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize; - - Data = AllocateZeroPool (SigDBSize); - if (Data == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; + return FALSE; } // - // Fill Certificate Database parameters. - // - SigDBCert = (EFI_SIGNATURE_LIST*) Data; - SigDBCert->SignatureListSize = (UINT32) SigDBSize; - SigDBCert->SignatureHeaderSize = 0; - SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); - CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid); - - SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST)); - CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID); - CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize); - + // Check the raw certificate. // - // Check if signature database entry has been already existed. - // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the - // new signature data to original variable - // - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS - | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; - Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); + IsFound = FALSE; + if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, X509Data, X509DataSize)) { + IsFound = TRUE; goto ON_EXIT; } - Status = gRT->GetVariable( - VariableName, - &gEfiImageSecurityDatabaseGuid, - NULL, - &DataSize, - NULL - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - Attr |= EFI_VARIABLE_APPEND_WRITE; - } else if (Status != EFI_NOT_FOUND) { - goto ON_EXIT; - } - - Status = gRT->SetVariable( - VariableName, - &gEfiImageSecurityDatabaseGuid, - Attr, - SigDBSize, - Data - ); - if (EFI_ERROR (Status)) { + // + // Check the hash of certificate. + // + if (IsCertHashFoundInDbx (X509Data, X509DataSize)) { + IsFound = TRUE; goto ON_EXIT; } ON_EXIT: - - CloseFile (Private->FileContext->FHandle); - Private->FileContext->FileName = NULL; - Private->FileContext->FHandle = NULL; - - if (Private->SignatureGUID != NULL) { - FreePool (Private->SignatureGUID); - Private->SignatureGUID = NULL; - } - - if (Data != NULL) { - FreePool (Data); - } - if (X509Data != NULL) { FreePool (X509Data); } - return Status; + return IsFound; } /** @@ -976,8 +1592,8 @@ ON_EXIT: **/ EFI_STATUS LoadPeImage ( - VOID - ) + VOID + ) { EFI_IMAGE_DOS_HEADER *DosHdr; EFI_IMAGE_NT_HEADERS32 *NtHeader32; @@ -992,7 +1608,7 @@ LoadPeImage ( if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { // - // DOS image header is present, + // DOS image header is present, // So read the PE header after the DOS image header // mPeCoffHeaderOffset = DosHdr->e_lfanew; @@ -1017,7 +1633,7 @@ LoadPeImage ( // Check the architecture field of PE header and get the Certificate Data Directory data // Note the size of FileHeader field is constant for both IA32 and X64 arch // - if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) + if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)) { // // IA-32 Architecture @@ -1045,12 +1661,12 @@ LoadPeImage ( PE/COFF Specification 8.0 Appendix A @param[in] HashAlg Hash algorithm type. - + @retval TRUE Successfully hash image. @retval FALSE Fail in hash image. **/ -BOOLEAN +BOOLEAN HashPeImage ( IN UINT32 HashAlg ) @@ -1074,7 +1690,7 @@ HashPeImage ( if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) { return FALSE; } - + // // Initialize context of hash. // @@ -1082,14 +1698,14 @@ HashPeImage ( if (HashAlg == HASHALG_SHA1) { mImageDigestSize = SHA1_DIGEST_SIZE; - mCertType = gEfiCertSha1Guid; + mCertType = gEfiCertSha1Guid; } else if (HashAlg == HASHALG_SHA256) { mImageDigestSize = SHA256_DIGEST_SIZE; mCertType = gEfiCertSha256Guid; } CtxSize = mHash[HashAlg].GetContextSize(); - + HashCtx = AllocatePool (CtxSize); ASSERT (HashCtx != NULL); @@ -1106,8 +1722,8 @@ HashPeImage ( // if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // - // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value - // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the + // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value + // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC // @@ -1118,7 +1734,7 @@ HashPeImage ( // Magic = mNtHeader.Pe32->OptionalHeader.Magic; } - + // // 3. Calculate the distance from the base of the image header to the image checksum address. // 4. Hash the image header from its base to beginning of the image checksum. @@ -1154,7 +1770,7 @@ HashPeImage ( } else { // // Use PE32+ offset. - // + // HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32); HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); } @@ -1277,7 +1893,7 @@ HashPeImage ( HashSize = (UINTN)( mImageSize - mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - - SumOfBytesHashed); + SumOfBytesHashed); } Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); @@ -1299,15 +1915,15 @@ Done: } /** - Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of - Pe/Coff image based on the authenticated image hashing in PE/COFF Specification + Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of + Pe/Coff image based on the authenticated image hashing in PE/COFF Specification 8.0 Appendix A @retval EFI_UNSUPPORTED Hash algorithm is not supported. @retval EFI_SUCCESS Hash successfully. **/ -EFI_STATUS +EFI_STATUS HashPeImageByType ( VOID ) @@ -1317,10 +1933,10 @@ HashPeImageByType ( PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset); - for (Index = 0; Index < HASHALG_MAX; Index++) { + for (Index = 0; Index < HASHALG_MAX; Index++) { // // Check the Hash algorithm in PE/COFF Authenticode. - // According to PKCS#7 Definition: + // According to PKCS#7 Definition: // SignedData ::= SEQUENCE { // version Version, // digestAlgorithms DigestAlgorithmIdentifiers, @@ -1337,7 +1953,7 @@ HashPeImageByType ( continue; } - // + // if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) { break; } @@ -1358,11 +1974,12 @@ HashPeImageByType ( } /** - Enroll a new executable's signature into Signature Database. + Enroll a new executable's signature into Signature Database. @param[in] PrivateData The module's private data. - @param[in] VariableName Variable name of signature database, must be - EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1. + @param[in] VariableName Variable name of signature database, must be + EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1 + or EFI_IMAGE_SECURITY_DATABASE2. @retval EFI_SUCCESS New signature is enrolled successfully. @retval EFI_INVALID_PARAMETER The parameter is invalid. @@ -1388,6 +2005,10 @@ EnrollImageSignatureToSigDB ( Data = NULL; GuidCertData = NULL; + if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) { + return EFI_UNSUPPORTED; + } + // // Form the SigDB certificate list. // Format the data item into EFI_SIGNATURE_LIST type. @@ -1402,13 +2023,13 @@ EnrollImageSignatureToSigDB ( // Status = ReadFileContent( Private->FileContext->FHandle, - (VOID **) &mImageBase, - &mImageSize, + (VOID **) &mImageBase, + &mImageSize, 0 ); if (EFI_ERROR (Status)) { goto ON_EXIT; - } + } ASSERT (mImageBase != NULL); Status = LoadPeImage (); @@ -1422,7 +2043,7 @@ EnrollImageSignatureToSigDB ( goto ON_EXIT; } } else { - + // // Read the certificate data // @@ -1439,7 +2060,7 @@ EnrollImageSignatureToSigDB ( Status = EFI_ABORTED; goto ON_EXIT;; } - + } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) { Status = HashPeImageByType (); @@ -1455,7 +2076,7 @@ EnrollImageSignatureToSigDB ( // // Create a new SigDB entry. // - SigDBSize = sizeof(EFI_SIGNATURE_LIST) + SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize; @@ -1464,10 +2085,10 @@ EnrollImageSignatureToSigDB ( Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } - + // // Adjust the Certificate Database parameters. - // + // SigDBCert = (EFI_SIGNATURE_LIST*) Data; SigDBCert->SignatureListSize = (UINT32) SigDBSize; SigDBCert->SignatureHeaderSize = 0; @@ -1478,41 +2099,41 @@ EnrollImageSignatureToSigDB ( CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID); CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize); - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); goto ON_EXIT; } - + // - // Check if SigDB variable has been already existed. - // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the + // Check if SigDB variable has been already existed. + // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the // new signature data to original variable - // + // DataSize = 0; Status = gRT->GetVariable( - VariableName, - &gEfiImageSecurityDatabaseGuid, - NULL, - &DataSize, + VariableName, + &gEfiImageSecurityDatabaseGuid, + NULL, + &DataSize, NULL ); if (Status == EFI_BUFFER_TOO_SMALL) { Attr |= EFI_VARIABLE_APPEND_WRITE; } else if (Status != EFI_NOT_FOUND) { goto ON_EXIT; - } + } // // Enroll the variable. // Status = gRT->SetVariable( - VariableName, - &gEfiImageSecurityDatabaseGuid, - Attr, - SigDBSize, + VariableName, + &gEfiImageSecurityDatabaseGuid, + Attr, + SigDBSize, Data ); if (EFI_ERROR (Status)) { @@ -1543,23 +2164,23 @@ ON_EXIT: } /** - Enroll signature into DB/DBX without KEK's authentication. + Enroll signature into DB/DBX/DBT without KEK's authentication. The SignatureOwner GUID will be Private->SignatureGUID. - + @param[in] PrivateData The module's private data. - @param[in] VariableName Variable name of signature database, must be + @param[in] VariableName Variable name of signature database, must be EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1. - + @retval EFI_SUCCESS New signature enrolled successfully. @retval EFI_INVALID_PARAMETER The parameter is invalid. @retval others Fail to enroll signature data. - + **/ EFI_STATUS EnrollSignatureDatabase ( IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, IN CHAR16 *VariableName - ) + ) { UINT16* FilePostFix; EFI_STATUS Status; @@ -1569,20 +2190,20 @@ EnrollSignatureDatabase ( return EFI_INVALID_PARAMETER; } - Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); + Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE); if (EFI_ERROR (Status)) { return Status; } - + // - // Parse the file's postfix. + // Parse the file's postfix. // NameLength = StrLen (Private->FileContext->FileName); if (NameLength <= 4) { return EFI_INVALID_PARAMETER; } FilePostFix = Private->FileContext->FileName + NameLength - 4; - if (IsDerEncodeCertificate(FilePostFix)) { + if (IsDerEncodeCertificate (FilePostFix)) { // // Supports DER-encoded X509 certificate. // @@ -1593,7 +2214,7 @@ EnrollSignatureDatabase ( } /** - List all signatures in specified signature database (e.g. KEK/DB/DBX) + List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT) by GUID in the page for user to select and delete as needed. @param[in] PrivateData Module's private data. @@ -1605,7 +2226,7 @@ EnrollSignatureDatabase ( @retval EFI_SUCCESS Success to update the signature list page @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. - + **/ EFI_STATUS UpdateDeletePage ( @@ -1624,7 +2245,7 @@ UpdateDeletePage ( VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; - EFI_IFR_GUID_LABEL *EndLabel; + EFI_IFR_GUID_LABEL *EndLabel; UINTN DataSize; UINT8 *Data; EFI_SIGNATURE_LIST *CertList; @@ -1640,20 +2261,20 @@ UpdateDeletePage ( GuidStr = NULL; StartOpCodeHandle = NULL; EndOpCodeHandle = NULL; - + // // Initialize the container for dynamic opcodes. // StartOpCodeHandle = HiiAllocateOpCodeHandle (); if (StartOpCodeHandle == NULL) { Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; + goto ON_EXIT; } EndOpCodeHandle = HiiAllocateOpCodeHandle (); if (EndOpCodeHandle == NULL) { Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; + goto ON_EXIT; } // @@ -1681,7 +2302,7 @@ UpdateDeletePage ( // Read Variable. // DataSize = 0; - Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data); + Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data); if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { goto ON_EXIT; } @@ -1720,6 +2341,12 @@ UpdateDeletePage ( Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID); } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) { Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID); + } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) { + Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID); + } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) { + Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID); + } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) { + Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID); } else { // // The signature type is not supported in current implementation. @@ -1731,26 +2358,26 @@ UpdateDeletePage ( CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; for (Index = 0; Index < CertCount; Index++) { - Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList - + sizeof (EFI_SIGNATURE_LIST) - + CertList->SignatureHeaderSize + Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + + sizeof (EFI_SIGNATURE_LIST) + + CertList->SignatureHeaderSize + Index * CertList->SignatureSize); // - // Display GUID and help + // Display GUID and help // GuidToString (&Cert->SignatureOwner, GuidStr, 100); GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL); HiiCreateCheckBoxOpCode ( StartOpCodeHandle, (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++), - 0, - 0, - GuidID, + 0, + 0, + GuidID, Help, EFI_IFR_FLAG_CALLBACK, 0, NULL - ); + ); } ItemDataSize -= CertList->SignatureListSize; @@ -1773,7 +2400,7 @@ ON_EXIT: if (EndOpCodeHandle != NULL) { HiiFreeOpCodeHandle (EndOpCodeHandle); } - + if (Data != NULL) { FreePool (Data); } @@ -1786,14 +2413,14 @@ ON_EXIT: } /** - Delete a KEK entry from KEK database. + Delete a KEK entry from KEK database. @param[in] PrivateData Module's private data. @param[in] QuestionId Question id of the KEK item to delete. @retval EFI_SUCCESS Delete kek item successfully. @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - + **/ EFI_STATUS DeleteKeyExchangeKey ( @@ -1821,18 +2448,18 @@ DeleteKeyExchangeKey ( OldData = NULL; CertList = NULL; Cert = NULL; - Attr = 0; + Attr = 0; DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID; Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); if (EFI_ERROR (Status)) { return Status; } - + // // Get original KEK variable. - // - DataSize = 0; + // + DataSize = 0; Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL); if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) { goto ON_EXIT; @@ -1840,7 +2467,7 @@ DeleteKeyExchangeKey ( OldData = (UINT8*)AllocateZeroPool(DataSize); if (OldData == NULL) { - Status = EFI_OUT_OF_RESOURCES; + Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } @@ -1850,7 +2477,7 @@ DeleteKeyExchangeKey ( } // - // Allocate space for new variable. + // Allocate space for new variable. // Data = (UINT8*) AllocateZeroPool (DataSize); if (Data == NULL) { @@ -1880,7 +2507,7 @@ DeleteKeyExchangeKey ( // Find it! Skip it! // NewCertList->SignatureListSize -= CertList->SignatureSize; - IsKEKItemFound = TRUE; + IsKEKItemFound = TRUE; } else { // // This item doesn't match. Copy it to the Data buffer. @@ -1898,7 +2525,7 @@ DeleteKeyExchangeKey ( CopyMem (Data + Offset, CertList, CertList->SignatureListSize); Offset += CertList->SignatureListSize; } - + KekDataSize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize); } @@ -1924,7 +2551,7 @@ DeleteKeyExchangeKey ( if (CertCount != 0) { CopyMem (OldData + Offset, CertList, CertList->SignatureListSize); Offset += CertList->SignatureListSize; - } + } KekDataSize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); } @@ -1939,17 +2566,17 @@ DeleteKeyExchangeKey ( } Status = gRT->SetVariable( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - Attr, - DataSize, + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + Attr, + DataSize, OldData ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status)); goto ON_EXIT; } - + ON_EXIT: if (Data != NULL) { FreePool(Data); @@ -1960,7 +2587,7 @@ ON_EXIT: } return UpdateDeletePage ( - PrivateData, + PrivateData, EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, LABEL_KEK_DELETE, @@ -1979,7 +2606,7 @@ ON_EXIT: @param[in] FormId Form ID of current page. @param[in] QuestionIdBase Base question id of the signature list. @param[in] DeleteIndex Signature index to delete. - + @retval EFI_SUCCESS Delete siganture successfully. @retval EFI_NOT_FOUND Can't find the signature item, @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. @@ -2014,7 +2641,7 @@ DeleteSignature ( OldData = NULL; CertList = NULL; Cert = NULL; - Attr = 0; + Attr = 0; Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); if (EFI_ERROR (Status)) { @@ -2023,7 +2650,7 @@ DeleteSignature ( // // Get original signature list data. - // + // DataSize = 0; Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL); if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { @@ -2032,17 +2659,17 @@ DeleteSignature ( OldData = (UINT8 *) AllocateZeroPool (DataSize); if (OldData == NULL) { - Status = EFI_OUT_OF_RESOURCES; + Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData); if (EFI_ERROR(Status)) { goto ON_EXIT; - } + } // - // Allocate space for new variable. + // Allocate space for new variable. // Data = (UINT8*) AllocateZeroPool (DataSize); if (Data == NULL) { @@ -2062,7 +2689,10 @@ DeleteSignature ( if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) || CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) || CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) || - CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) + CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid) ) { // // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list. @@ -2078,7 +2708,7 @@ DeleteSignature ( // Find it! Skip it! // NewCertList->SignatureListSize -= CertList->SignatureSize; - IsItemFound = TRUE; + IsItemFound = TRUE; } else { // // This item doesn't match. Copy it to the Data buffer. @@ -2096,7 +2726,7 @@ DeleteSignature ( CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize); Offset += CertList->SignatureListSize; } - + ItemDataSize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); } @@ -2122,7 +2752,7 @@ DeleteSignature ( if (CertCount != 0) { CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize); Offset += CertList->SignatureListSize; - } + } ItemDataSize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); } @@ -2137,17 +2767,17 @@ DeleteSignature ( } Status = gRT->SetVariable( - VariableName, - VendorGuid, - Attr, - DataSize, + VariableName, + VendorGuid, + Attr, + DataSize, OldData ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status)); goto ON_EXIT; } - + ON_EXIT: if (Data != NULL) { FreePool(Data); @@ -2158,7 +2788,7 @@ ON_EXIT: } return UpdateDeletePage ( - PrivateData, + PrivateData, VariableName, VendorGuid, LabelNumber, @@ -2169,23 +2799,37 @@ ON_EXIT: /** This function extracts configuration from variable. - + @param[in, out] ConfigData Point to SecureBoot configuration private data. **/ VOID SecureBootExtractConfigFromVariable ( IN OUT SECUREBOOT_CONFIGURATION *ConfigData - ) + ) { - UINT8 *SecureBootEnable; - UINT8 *SetupMode; - UINT8 *SecureBootMode; + UINT8 *SecureBootEnable; + UINT8 *SetupMode; + UINT8 *SecureBootMode; + EFI_TIME CurrTime; SecureBootEnable = NULL; SetupMode = NULL; SecureBootMode = NULL; - + + // + // Initilize the Date and Time using system time. + // + ConfigData->CertificateFormat = HASHALG_RAW; + ConfigData->AlwaysRevocation = TRUE; + gRT->GetTime (&CurrTime, NULL); + ConfigData->RevocationDate.Year = CurrTime.Year; + ConfigData->RevocationDate.Month = CurrTime.Month; + ConfigData->RevocationDate.Day = CurrTime.Day; + ConfigData->RevocationTime.Hour = CurrTime.Hour; + ConfigData->RevocationTime.Minute = CurrTime.Minute; + ConfigData->RevocationTime.Second = 0; + // // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable // Checkbox. @@ -2200,7 +2844,7 @@ SecureBootExtractConfigFromVariable ( ConfigData->AttemptSecureBoot = TRUE; } } - + // // If it is Physical Presence User, set the PhysicalPresent to true. // @@ -2209,7 +2853,7 @@ SecureBootExtractConfigFromVariable ( } else { ConfigData->PhysicalPresent = FALSE; } - + // // If there is no PK then the Delete Pk button will be gray. // @@ -2289,17 +2933,17 @@ SecureBootExtractConfig ( if (Progress == NULL || Results == NULL) { return EFI_INVALID_PARAMETER; } - + AllocatedRequest = FALSE; ConfigRequestHdr = NULL; ConfigRequest = NULL; Size = 0; SecureBoot = NULL; - + ZeroMem (&Configuration, sizeof (Configuration)); PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); *Progress = Request; - + if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) { return EFI_NOT_FOUND; } @@ -2321,7 +2965,7 @@ SecureBootExtractConfig ( if (SecureBoot != NULL) { FreePool (SecureBoot); } - + BufferSize = sizeof (SECUREBOOT_CONFIGURATION); ConfigRequest = Request; if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { @@ -2399,7 +3043,7 @@ SecureBootRouteConfig ( SECUREBOOT_CONFIGURATION IfrNvData; UINTN BufferSize; EFI_STATUS Status; - + if (Configuration == NULL || Progress == NULL) { return EFI_INVALID_PARAMETER; } @@ -2480,7 +3124,7 @@ SecureBootCallback ( ) { EFI_INPUT_KEY Key; - EFI_STATUS Status; + EFI_STATUS Status; SECUREBOOT_CONFIG_PRIVATE_DATA *Private; UINTN BufferSize; SECUREBOOT_CONFIGURATION *IfrNvData; @@ -2505,7 +3149,7 @@ SecureBootCallback ( return EFI_SUCCESS; } - + if (Action == EFI_BROWSER_ACTION_RETRIEVE) { Status = EFI_UNSUPPORTED; if (QuestionId == KEY_SECURE_BOOT_MODE) { @@ -2516,14 +3160,14 @@ SecureBootCallback ( } return Status; } - + if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE) && (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) { return EFI_UNSUPPORTED; } - + Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); // @@ -2538,7 +3182,7 @@ SecureBootCallback ( Status = EFI_SUCCESS; HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData); - + if (Action == EFI_BROWSER_ACTION_CHANGING) { switch (QuestionId) { @@ -2573,6 +3217,7 @@ SecureBootCallback ( case KEY_SECURE_BOOT_KEK_OPTION: case KEY_SECURE_BOOT_DB_OPTION: case KEY_SECURE_BOOT_DBX_OPTION: + case KEY_SECURE_BOOT_DBT_OPTION: // // Clear Signature GUID. // @@ -2588,6 +3233,8 @@ SecureBootCallback ( LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB; } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) { LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX; + } else if (QuestionId == KEY_SECURE_BOOT_DBT_OPTION) { + LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT; } else { LabelId = FORMID_ENROLL_KEK_FORM; } @@ -2595,21 +3242,25 @@ SecureBootCallback ( // // Refresh selected file. // - CleanUpPage (LabelId, Private); + CleanUpPage (LabelId, Private); break; - + case SECUREBOOT_ADD_PK_FILE_FORM_ID: case FORMID_ENROLL_KEK_FORM: case SECUREBOOT_ENROLL_SIGNATURE_TO_DB: case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX: + case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT: if (QuestionId == SECUREBOOT_ADD_PK_FILE_FORM_ID) { Private->FeCurrentState = FileExplorerStateEnrollPkFile; } else if (QuestionId == FORMID_ENROLL_KEK_FORM) { Private->FeCurrentState = FileExplorerStateEnrollKekFile; } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DB) { Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDb; - } else { + } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DBX) { Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbx; + IfrNvData->CertificateFormat = HASHALG_SHA256; + } else { + Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbt; } Private->FeDisplayContext = FileExplorerDisplayUnknown; @@ -2617,7 +3268,7 @@ SecureBootCallback ( UpdateFileExplorer (Private, 0); break; - case KEY_SECURE_BOOT_DELETE_PK: + case KEY_SECURE_BOOT_DELETE_PK: if (Value->u8) { CreatePopUp ( EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, @@ -2642,16 +3293,16 @@ SecureBootCallback ( case KEY_DELETE_KEK: UpdateDeletePage ( - Private, + Private, EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, LABEL_KEK_DELETE, FORMID_DELETE_KEK_FORM, - OPTION_DEL_KEK_QUESTION_ID + OPTION_DEL_KEK_QUESTION_ID ); break; - case SECUREBOOT_DELETE_SIGNATURE_FROM_DB: + case SECUREBOOT_DELETE_SIGNATURE_FROM_DB: UpdateDeletePage ( Private, EFI_IMAGE_SECURITY_DATABASE, @@ -2674,6 +3325,18 @@ SecureBootCallback ( break; + case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT: + UpdateDeletePage ( + Private, + EFI_IMAGE_SECURITY_DATABASE2, + &gEfiImageSecurityDatabaseGuid, + LABEL_DBT_DELETE, + SECUREBOOT_DELETE_SIGNATURE_FROM_DBT, + OPTION_DEL_DBT_QUESTION_ID + ); + + break; + case KEY_VALUE_SAVE_AND_EXIT_KEK: Status = EnrollKeyExchangeKey (Private); if (EFI_ERROR (Status)) { @@ -2701,7 +3364,27 @@ SecureBootCallback ( break; case KEY_VALUE_SAVE_AND_EXIT_DBX: - Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1); + if (IsX509CertInDbx (Private, EFI_IMAGE_SECURITY_DATABASE1)) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Enrollment failed! Same certificate had already been in the dbx!", + NULL + ); + break; + } + + if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) { + Status = EnrollX509HashtoSigDB ( + Private, + IfrNvData->CertificateFormat, + &IfrNvData->RevocationDate, + &IfrNvData->RevocationTime, + IfrNvData->AlwaysRevocation + ); + } else { + Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1); + } if (EFI_ERROR (Status)) { CreatePopUp ( EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, @@ -2713,6 +3396,19 @@ SecureBootCallback ( } break; + case KEY_VALUE_SAVE_AND_EXIT_DBT: + Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE2); + if (EFI_ERROR (Status)) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"ERROR: Unsupported file type!", + L"Only supports DER-encoded X509 certificate.", + NULL + ); + } + break; + default: if (QuestionId >= FILE_OPTION_GOTO_OFFSET) { UpdateFileExplorer (Private, QuestionId); @@ -2725,7 +3421,7 @@ SecureBootCallback ( Private, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, - LABEL_DB_DELETE, + LABEL_DB_DELETE, SECUREBOOT_DELETE_SIGNATURE_FROM_DB, OPTION_DEL_DB_QUESTION_ID, QuestionId - OPTION_DEL_DB_QUESTION_ID @@ -2736,11 +3432,22 @@ SecureBootCallback ( Private, EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, - LABEL_DBX_DELETE, + LABEL_DBX_DELETE, SECUREBOOT_DELETE_SIGNATURE_FROM_DBX, OPTION_DEL_DBX_QUESTION_ID, QuestionId - OPTION_DEL_DBX_QUESTION_ID ); + } else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) && + (QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE))) { + DeleteSignature ( + Private, + EFI_IMAGE_SECURITY_DATABASE2, + &gEfiImageSecurityDatabaseGuid, + LABEL_DBT_DELETE, + SECUREBOOT_DELETE_SIGNATURE_FROM_DBT, + OPTION_DEL_DBT_QUESTION_ID, + QuestionId - OPTION_DEL_DBT_QUESTION_ID + ); } break; } @@ -2748,7 +3455,7 @@ SecureBootCallback ( switch (QuestionId) { case KEY_SECURE_BOOT_ENABLE: *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; - break; + break; case KEY_VALUE_SAVE_AND_EXIT_PK: Status = EnrollPlatformKey (Private); if (EFI_ERROR (Status)) { @@ -2766,27 +3473,28 @@ SecureBootCallback ( NULL ); } else { - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET; - } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET; + } break; case KEY_VALUE_NO_SAVE_AND_EXIT_PK: case KEY_VALUE_NO_SAVE_AND_EXIT_KEK: case KEY_VALUE_NO_SAVE_AND_EXIT_DB: case KEY_VALUE_NO_SAVE_AND_EXIT_DBX: + case KEY_VALUE_NO_SAVE_AND_EXIT_DBT: if (Private->FileContext->FHandle != NULL) { CloseFile (Private->FileContext->FHandle); Private->FileContext->FHandle = NULL; Private->FileContext->FileName = NULL; } - + if (Private->SignatureGUID != NULL) { FreePool (Private->SignatureGUID); Private->SignatureGUID = NULL; } *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; break; - + case KEY_SECURE_BOOT_MODE: mIsEnterSecureBootForm = FALSE; break; @@ -2794,6 +3502,7 @@ SecureBootCallback ( case KEY_SECURE_BOOT_KEK_GUID: case KEY_SECURE_BOOT_SIGNATURE_GUID_DB: case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX: + case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT: ASSERT (Private->SignatureGUID != NULL); Status = StringToGuid ( IfrNvData->SignatureGuid, @@ -2854,13 +3563,13 @@ SecureBootCallback ( FreePool (SecureBootMode); } } - + if (!EFI_ERROR (Status)) { BufferSize = sizeof (SECUREBOOT_CONFIGURATION); HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL); } FreePool (IfrNvData); - + return EFI_SUCCESS; } @@ -2926,15 +3635,15 @@ InstallSecureBootConfigForm ( PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT)); PrivateData->MenuEntry = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY)); - + if (PrivateData->FileContext == NULL || PrivateData->MenuEntry == NULL) { UninstallSecureBootConfigForm (PrivateData); return EFI_OUT_OF_RESOURCES; } - + PrivateData->FeCurrentState = FileExplorerStateInActive; PrivateData->FeDisplayContext = FileExplorerDisplayUnknown; - + InitializeListHead (&FsOptionMenu.Head); InitializeListHead (&DirectoryMenu.Head); @@ -2975,7 +3684,7 @@ InstallSecureBootConfigForm ( ); mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; mEndLabel->Number = LABEL_END; - + return EFI_SUCCESS; }