From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga02.intel.com (mga02.intel.com []) by mx.groups.io with SMTP id smtpd.web11.12696.1580998775768725774 for ; Thu, 06 Feb 2020 06:19:39 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: jian.j.wang@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 06 Feb 2020 06:19:39 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,409,1574150400"; d="scan'208";a="226160683" Received: from shwdeopensfp777.ccr.corp.intel.com ([10.239.158.78]) by fmsmga008.fm.intel.com with ESMTP; 06 Feb 2020 06:19:38 -0800 From: "Wang, Jian J" To: devel@edk2.groups.io Cc: Jiewen Yao , Chao Zhang Subject: [PATCH 5/9] SecurityPkg/DxeImageVerificationLib: refactor db/dbx fetching code in IsAllowedByDb(CVE-2019-14575) Date: Thu, 6 Feb 2020 22:19:29 +0800 Message-Id: <20200206141933.356-6-jian.j.wang@intel.com> X-Mailer: git-send-email 2.24.0.windows.2 In-Reply-To: <20200206141933.356-1-jian.j.wang@intel.com> References: <20200206141933.356-1-jian.j.wang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1608 The dbx fetching code inside the while/for-loop causes code hard to understand. Since there's no need to get dbx more than once, this patch simplify the code logic by moving related code to be outside the while- loop. db fetching code is also refined accordingly to reduce the indent level of code. More comments are also added or refined to explain more details. Cc: Jiewen Yao Cc: Chao Zhang Signed-off-by: Jian J Wang --- .../DxeImageVerificationLib.c | 144 ++++++++++-------- 1 file changed, 83 insertions(+), 61 deletions(-) diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificati= onLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationL= ib.c index ed5dbf26b0..8739d1fa29 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -1412,76 +1412,92 @@ IsAllowedByDb ( RootCertSize =3D 0;=0D VerifyStatus =3D FALSE;=0D =0D + //=0D + // Fetch 'db' content. If 'db' doesn't exist or encounters problem to ge= t the=0D + // data, return not-allowed-by-db (FALSE).=0D + //=0D DataSize =3D 0;=0D Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSe= curityDatabaseGuid, NULL, &DataSize, NULL);=0D - if (Status =3D=3D EFI_BUFFER_TOO_SMALL) {=0D - Data =3D (UINT8 *) AllocateZeroPool (DataSize);=0D - if (Data =3D=3D NULL) {=0D - return VerifyStatus;=0D + ASSERT (EFI_ERROR (Status));=0D + if (Status !=3D EFI_BUFFER_TOO_SMALL) {=0D + return VerifyStatus;=0D + }=0D +=0D + Data =3D (UINT8 *) AllocateZeroPool (DataSize);=0D + if (Data =3D=3D NULL) {=0D + return VerifyStatus;=0D + }=0D +=0D + Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecu= rityDatabaseGuid, NULL, &DataSize, (VOID *) Data);=0D + if (EFI_ERROR (Status)) {=0D + goto Done;=0D + }=0D +=0D + //=0D + // Fetch 'dbx' content. If 'dbx' doesn't exist, continue to check 'db'.= =0D + // If any other errors occured, no need to check 'db' but just return=0D + // not-allowed-by-db (FALSE) to avoid bypass.=0D + //=0D + DbxDataSize =3D 0;=0D + Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiIma= geSecurityDatabaseGuid, NULL, &DbxDataSize, NULL);=0D + ASSERT (EFI_ERROR (Status));=0D + if (Status !=3D EFI_BUFFER_TOO_SMALL) {=0D + if (Status !=3D EFI_NOT_FOUND) {=0D + goto Done;=0D + }=0D + //=0D + // 'dbx' does not exist. Continue to check 'db'.=0D + //=0D + } else {=0D + //=0D + // 'dbx' exists. Get its content.=0D + //=0D + DbxData =3D (UINT8 *) AllocateZeroPool (DbxDataSize);=0D + if (DbxData =3D=3D NULL) {=0D + goto Done;=0D }=0D =0D - Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSe= curityDatabaseGuid, NULL, &DataSize, (VOID *) Data);=0D + Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageS= ecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData);=0D if (EFI_ERROR (Status)) {=0D goto Done;=0D }=0D + }=0D =0D - //=0D - // Find X509 certificate in Signature List to verify the signature in = pkcs7 signed data.=0D - //=0D - CertList =3D (EFI_SIGNATURE_LIST *) Data;=0D - while ((DataSize > 0) && (DataSize >=3D CertList->SignatureListSize)) = {=0D - if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {=0D - CertData =3D (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof = (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);=0D - CertCount =3D (CertList->SignatureListSize - sizeof (EFI_SIGNATURE= _LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;=0D + //=0D + // Find X509 certificate in Signature List to verify the signature in pk= cs7 signed data.=0D + //=0D + CertList =3D (EFI_SIGNATURE_LIST *) Data;=0D + while ((DataSize > 0) && (DataSize >=3D CertList->SignatureListSize)) {= =0D + if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {=0D + CertData =3D (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (E= FI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);=0D + CertCount =3D (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_L= IST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;=0D =0D - for (Index =3D 0; Index < CertCount; Index++) {=0D - //=0D - // Iterate each Signature Data Node within this CertList for ver= ify.=0D - //=0D - RootCert =3D CertData->SignatureData;=0D - RootCertSize =3D CertList->SignatureSize - sizeof (EFI_GUID);=0D + for (Index =3D 0; Index < CertCount; Index++) {=0D + //=0D + // Iterate each Signature Data Node within this CertList for verif= y.=0D + //=0D + RootCert =3D CertData->SignatureData;=0D + RootCertSize =3D CertList->SignatureSize - sizeof (EFI_GUID);=0D =0D + //=0D + // Call AuthenticodeVerify library to Verify Authenticode struct.= =0D + //=0D + VerifyStatus =3D AuthenticodeVerify (=0D + AuthData,=0D + AuthDataSize,=0D + RootCert,=0D + RootCertSize,=0D + mImageDigest,=0D + mImageDigestSize=0D + );=0D + if (VerifyStatus) {=0D //=0D - // Call AuthenticodeVerify library to Verify Authenticode struct= .=0D + // The image is signed and its signature is found in 'db'.=0D //=0D - VerifyStatus =3D AuthenticodeVerify (=0D - AuthData,=0D - AuthDataSize,=0D - RootCert,=0D - RootCertSize,=0D - mImageDigest,=0D - mImageDigestSize=0D - );=0D - if (VerifyStatus) {=0D + if (DbxData !=3D NULL) {=0D //=0D // Here We still need to check if this RootCert's Hash is revo= ked=0D //=0D - DbxDataSize =3D 0;=0D - Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &= gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL);=0D - if (Status !=3D EFI_BUFFER_TOO_SMALL) {=0D - if (Status !=3D EFI_NOT_FOUND) {=0D - VerifyStatus =3D FALSE;=0D - }=0D - goto Done;=0D - }=0D - DbxData =3D (UINT8 *) AllocateZeroPool (DbxDataSize);=0D - if (DbxData =3D=3D NULL) {=0D - //=0D - // Force not-allowed-by-db to avoid bypass=0D - //=0D - VerifyStatus =3D FALSE;=0D - goto Done;=0D - }=0D -=0D - Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gE= fiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData);=0D - if (EFI_ERROR (Status)) {=0D - //=0D - // Force not-allowed-by-db to avoid bypass=0D - //=0D - VerifyStatus =3D FALSE;=0D - goto Done;=0D - }=0D -=0D if (IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SI= GNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime)) {=0D //=0D // Check the timestamp signature and signing time to determi= ne if the RootCert can be trusted.=0D @@ -1491,17 +1507,23 @@ IsAllowedByDb ( DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is sig= ned and signature is accepted by DB, but its root cert failed the timestamp= check.\n"));=0D }=0D }=0D -=0D - goto Done;=0D }=0D =0D - CertData =3D (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertLi= st->SignatureSize);=0D + //=0D + // There's no 'dbx' to check revocation time against (must-be pa= ss),=0D + // or, there's revocation time found in 'dbx' and checked againt= 'dbt'=0D + // (maybe pass or fail, depending on timestamp compare result). = Either=0D + // way the verification job has been completed at this point.=0D + //=0D + goto Done;=0D }=0D - }=0D =0D - DataSize -=3D CertList->SignatureListSize;=0D - CertList =3D (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->= SignatureListSize);=0D + CertData =3D (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList= ->SignatureSize);=0D + }=0D }=0D +=0D + DataSize -=3D CertList->SignatureListSize;=0D + CertList =3D (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->Si= gnatureListSize);=0D }=0D =0D Done:=0D --=20 2.24.0.windows.2