X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=SecurityPkg%2FLibrary%2FDxeImageVerificationLib%2FDxeImageVerificationLib.c;h=2a54296134b5835ed7f5645f58fd79fbf6d9a189;hp=a591970e45cceefeac06dfb6b75e942f601f47e9;hb=de2447dd4ca93ca37ff067c325e478dc586235ca;hpb=551d808116c09d88d68edef5d2454bdd268fcf1d diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c index a591970e45..2a54296134 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -251,8 +251,6 @@ HashPeImage ( EFI_IMAGE_SECTION_HEADER *SectionHeader; UINTN Index; UINTN Pos; - UINTN SumOfSectionBytes; - EFI_IMAGE_SECTION_HEADER *SectionCache; UINT32 CertSize; UINT32 NumberOfRvaAndSizes; @@ -299,7 +297,21 @@ HashPeImage ( // Measuring PE/COFF Image Header; // But CheckSum field and SECURITY data directory (certificate) are excluded // - Magic = mNtHeader.Pe32->OptionalHeader.Magic; + 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 + // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC + // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else { + // + // Get the magic value from the PE/COFF Optional Header + // + 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. @@ -433,11 +445,6 @@ HashPeImage ( mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader ); - SectionCache = Section; - for (Index = 0, SumOfSectionBytes = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++, SectionCache++) { - SumOfSectionBytes += SectionCache->SizeOfRawData; - } - // // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER // structures in the image. The 'NumberOfSections' field of the image @@ -557,6 +564,10 @@ HashPeImageByType ( PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress); + if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32) { + return EFI_UNSUPPORTED; + } + for (Index = 0; Index < HASHALG_MAX; Index++) { // // Check the Hash algorithm in PE/COFF Authenticode. @@ -577,6 +588,10 @@ HashPeImageByType ( continue; } + if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32 + mHash[Index].OidLength) { + return EFI_UNSUPPORTED; + } + if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) { break; } @@ -945,7 +960,7 @@ IsPkcsSignedDataVerifiedBySignatureList ( // VerifyStatus = AuthenticodeVerify ( PkcsCertData->CertData, - mSecDataDir->Size - sizeof(PkcsCertData->Hdr), + PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr), RootCert, RootCertSize, mImageDigest, @@ -1064,7 +1079,7 @@ VerifyCertUefiGuid ( // // Get KEK database variable. // - KekList = GetEfiGlobalVariable (EFI_KEY_EXCHANGE_KEY_NAME); + GetEfiGlobalVariable2 (EFI_KEY_EXCHANGE_KEY_NAME, (VOID**)&KekList, NULL); if (KekList == NULL) { return EFI_SECURITY_VIOLATION; } @@ -1214,6 +1229,7 @@ DxeImageVerificationHandler ( UINT8 *SecureBootEnable; PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; UINT32 NumberOfRvaAndSizes; + UINT32 CertSize; if (File == NULL) { return EFI_INVALID_PARAMETER; @@ -1258,7 +1274,7 @@ DxeImageVerificationHandler ( return EFI_ACCESS_DENIED; } - SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid); + GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL); // // Skip verification if SecureBootEnable variable doesn't exist. // @@ -1276,7 +1292,7 @@ DxeImageVerificationHandler ( FreePool (SecureBootEnable); - SetupMode = GetEfiGlobalVariable (EFI_SETUP_MODE_NAME); + GetEfiGlobalVariable2 (EFI_SETUP_MODE_NAME, (VOID**)&SetupMode, NULL); // // SetupMode doesn't exist means no AuthVar driver is dispatched, @@ -1321,7 +1337,9 @@ DxeImageVerificationHandler ( goto Done; } - DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase; + Status = EFI_ACCESS_DENIED; + + DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase; if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { // // DOS image header is present, @@ -1339,11 +1357,24 @@ DxeImageVerificationHandler ( // // It is not a valid Pe/Coff file. // - Status = EFI_ACCESS_DENIED; goto Done; } - Magic = mNtHeader.Pe32->OptionalHeader.Magic; + 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 + // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC + // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } else { + // + // Get the magic value from the PE/COFF Optional Header + // + Magic = mNtHeader.Pe32->OptionalHeader.Magic; + } + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset. @@ -1374,8 +1405,6 @@ DxeImageVerificationHandler ( // // Image Hash is in forbidden database (DBX). // - Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED; - Status = EFI_ACCESS_DENIED; goto Done; } @@ -1389,8 +1418,6 @@ DxeImageVerificationHandler ( // // Image Hash is not found in both forbidden and allowed database. // - Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED; - Status = EFI_ACCESS_DENIED; goto Done; } @@ -1399,9 +1426,20 @@ DxeImageVerificationHandler ( // WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress); + CertSize = sizeof (WIN_CERTIFICATE); + + if ((mSecDataDir->Size <= CertSize) || (mSecDataDir->Size < WinCertificate->dwLength)) { + goto Done; + } + switch (WinCertificate->wCertificateType) { case WIN_CERT_TYPE_EFI_GUID: + CertSize = sizeof (WIN_CERTIFICATE_UEFI_GUID) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256) - sizeof (UINT8); + if (WinCertificate->dwLength < CertSize) { + goto Done; + } + // // Verify UEFI GUID type. // @@ -1416,7 +1454,7 @@ DxeImageVerificationHandler ( // // Verify Pkcs signed data type. // - Status = HashPeImageByType(); + Status = HashPeImageByType(); if (EFI_ERROR (Status)) { goto Done; } @@ -1435,7 +1473,6 @@ DxeImageVerificationHandler ( break; default: - Status = EFI_ACCESS_DENIED; goto Done; } // @@ -1535,7 +1572,7 @@ VariableWriteCallBack ( // If this library is built-in, it means firmware has capability to perform // driver signing verification. // - SecureBootModePtr = GetEfiGlobalVariable (EFI_SECURE_BOOT_MODE_NAME); + GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBootModePtr, NULL); if (SecureBootModePtr == NULL) { SecureBootMode = SECURE_BOOT_MODE_DISABLE; //