Thanks Wenyi. May I know how you test the new code logic?
Any unit test you can share, such as a mal-formed PE image, which may break the old implementation but is caught by this patch? Thank you Yao Jiewen > -----Original Message----- > From: Wenyi Xie <xiewen...@huawei.com> > Sent: Thursday, August 13, 2020 7:56 PM > To: devel@edk2.groups.io; Yao, Jiewen <jiewen....@intel.com>; Wang, Jian J > <jian.j.w...@intel.com>; ler...@redhat.com > Cc: huangmin...@huawei.com; songdongku...@huawei.com > Subject: [PATCH EDK2 v2 1/1] SecurityPkg/DxeImageVerificationLib:Enhanced > verification of Offset > > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2215 > > There is an integer overflow vulnerability in DxeImageVerificationHandler > function when parsing the PE files attribute certificate table. In cases > where WinCertificate->dwLength is sufficiently large, it's possible to > overflow Offset back to 0 causing an endless loop. > > Check offset inbetween VirtualAddress and VirtualAddress + Size. > Using SafeintLib to do offset addition with result check. > > Cc: Jiewen Yao <jiewen....@intel.com> > Cc: Jian J Wang <jian.j.w...@intel.com> > Cc: Laszlo Ersek <ler...@redhat.com> > Signed-off-by: Wenyi Xie <xiewen...@huawei.com> > --- > SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf | 1 > + > SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h | > 1 + > SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c | 111 > +++++++++++--------- > 3 files changed, 63 insertions(+), 50 deletions(-) > > diff --git > a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf > b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf > index 1e1a639857e0..a7ac4830b3d4 100644 > --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf > +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf > @@ -53,6 +53,7 @@ [LibraryClasses] > SecurityManagementLib > PeCoffLib > TpmMeasurementLib > + SafeIntLib > > [Protocols] > gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMES > diff --git > a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h > b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h > index 17955ff9774c..060273917d5d 100644 > --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h > +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h > @@ -23,6 +23,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > #include <Library/DevicePathLib.h> > #include <Library/SecurityManagementLib.h> > #include <Library/PeCoffLib.h> > +#include <Library/SafeIntLib.h> > #include <Protocol/FirmwareVolume2.h> > #include <Protocol/DevicePath.h> > #include <Protocol/BlockIo.h> > diff --git > a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c > b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c > index 36b87e16d53d..dbc03e28c05b 100644 > --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c > +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c > @@ -1658,6 +1658,10 @@ DxeImageVerificationHandler ( > EFI_STATUS HashStatus; > EFI_STATUS DbStatus; > BOOLEAN IsFound; > + UINT32 AlignedLength; > + UINT32 Result; > + EFI_STATUS AddStatus; > + BOOLEAN IsAuthDataAssigned; > > SignatureList = NULL; > SignatureListSize = 0; > @@ -1667,6 +1671,7 @@ DxeImageVerificationHandler ( > Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED; > IsVerified = FALSE; > IsFound = FALSE; > + Result = 0; > > // > // Check the image type and get policy setting. > @@ -1850,9 +1855,10 @@ DxeImageVerificationHandler ( > // The first certificate starts at offset (SecDataDir->VirtualAddress) > from the > start of the file. > // > for (OffSet = SecDataDir->VirtualAddress; > - OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size); > - OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate- > >dwLength))) { > + (OffSet >= SecDataDir->VirtualAddress) && (OffSet < (SecDataDir- > >VirtualAddress + SecDataDir->Size));) { > + IsAuthDataAssigned = FALSE; > WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet); > + AlignedLength = WinCertificate->dwLength + ALIGN_SIZE (WinCertificate- > >dwLength); > if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof > (WIN_CERTIFICATE) || > (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < > WinCertificate- > >dwLength) { > break; > @@ -1872,6 +1878,8 @@ DxeImageVerificationHandler ( > } > AuthData = PkcsCertData->CertData; > AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr); > + IsAuthDataAssigned = TRUE; > + HashStatus = HashPeImageByType (AuthData, AuthDataSize); > } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) { > // > // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is > described in UEFI Spec. > @@ -1880,72 +1888,75 @@ DxeImageVerificationHandler ( > if (WinCertUefiGuid->Hdr.dwLength <= > OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) { > break; > } > - if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) { > - continue; > + if (CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) { > + AuthData = WinCertUefiGuid->CertData; > + AuthDataSize = WinCertUefiGuid->Hdr.dwLength - > OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); > + IsAuthDataAssigned = TRUE; > + HashStatus = HashPeImageByType (AuthData, AuthDataSize); > } > - AuthData = WinCertUefiGuid->CertData; > - AuthDataSize = WinCertUefiGuid->Hdr.dwLength - > OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); > } else { > if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) { > break; > } > - continue; > } > > - HashStatus = HashPeImageByType (AuthData, AuthDataSize); > - if (EFI_ERROR (HashStatus)) { > - continue; > - } > - > - // > - // Check the digital signature against the revoked certificate in > forbidden > database (dbx). > - // > - if (IsForbiddenByDbx (AuthData, AuthDataSize)) { > - Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED; > - IsVerified = FALSE; > - break; > - } > - > - // > - // Check the digital signature against the valid certificate in allowed > database > (db). > - // > - if (!IsVerified) { > - if (IsAllowedByDb (AuthData, AuthDataSize)) { > - IsVerified = TRUE; > + if (IsAuthDataAssigned && !EFI_ERROR (HashStatus)) { > + // > + // Check the digital signature against the revoked certificate in > forbidden > database (dbx). > + // > + if (IsForbiddenByDbx (AuthData, AuthDataSize)) { > + Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED; > + IsVerified = FALSE; > + break; > } > - } > > - // > - // Check the image's hash value. > - // > - DbStatus = IsSignatureFoundInDatabase ( > - EFI_IMAGE_SECURITY_DATABASE1, > - mImageDigest, > - &mCertType, > - mImageDigestSize, > - &IsFound > - ); > - if (EFI_ERROR (DbStatus) || IsFound) { > - Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND; > - DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but %s > hash of image is found in DBX.\n", mHashTypeStr)); > - IsVerified = FALSE; > - break; > - } > + // > + // Check the digital signature against the valid certificate in allowed > database (db). > + // > + if (!IsVerified) { > + if (IsAllowedByDb (AuthData, AuthDataSize)) { > + IsVerified = TRUE; > + } > + } > > - if (!IsVerified) { > + // > + // Check the image's hash value. > + // > DbStatus = IsSignatureFoundInDatabase ( > - EFI_IMAGE_SECURITY_DATABASE, > + EFI_IMAGE_SECURITY_DATABASE1, > mImageDigest, > &mCertType, > mImageDigestSize, > &IsFound > ); > - if (!EFI_ERROR (DbStatus) && IsFound) { > - IsVerified = TRUE; > - } else { > - DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but > signature is not allowed by DB and %s hash of image is not found in > DB/DBX.\n", > mHashTypeStr)); > + if (EFI_ERROR (DbStatus) || IsFound) { > + Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND; > + DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but %s > hash of image is found in DBX.\n", mHashTypeStr)); > + IsVerified = FALSE; > + break; > } > + > + if (!IsVerified) { > + DbStatus = IsSignatureFoundInDatabase ( > + EFI_IMAGE_SECURITY_DATABASE, > + mImageDigest, > + &mCertType, > + mImageDigestSize, > + &IsFound > + ); > + if (!EFI_ERROR (DbStatus) && IsFound) { > + IsVerified = TRUE; > + } else { > + DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but > signature is not allowed by DB and %s hash of image is not found in > DB/DBX.\n", > mHashTypeStr)); > + } > + } > + } > + > + AddStatus = SafeUint32Add (OffSet, AlignedLength, &Result); > + if (EFI_ERROR (AddStatus)) { > + break; > } > + OffSet = Result; > } > > if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) { > -- > 2.20.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#64221): https://edk2.groups.io/g/devel/message/64221 Mute This Topic: https://groups.io/mt/76165658/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-