From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mx.groups.io with SMTP id smtpd.web09.4126.1581587062648958850 for ; Thu, 13 Feb 2020 01:44:22 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.93, mailfrom: jiewen.yao@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Feb 2020 01:44:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,436,1574150400"; d="scan'208";a="381058058" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by orsmga004.jf.intel.com with ESMTP; 13 Feb 2020 01:44:21 -0800 Received: from fmsmsx119.amr.corp.intel.com (10.18.124.207) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 13 Feb 2020 01:44:21 -0800 Received: from shsmsx108.ccr.corp.intel.com (10.239.4.97) by FMSMSX119.amr.corp.intel.com (10.18.124.207) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 13 Feb 2020 01:44:20 -0800 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.126]) by SHSMSX108.ccr.corp.intel.com ([169.254.8.98]) with mapi id 14.03.0439.000; Thu, 13 Feb 2020 17:44:19 +0800 From: "Yao, Jiewen" To: "Wang, Jian J" , "devel@edk2.groups.io" CC: "Zhang, Chao B" Subject: Re: [PATCH 5/9] SecurityPkg/DxeImageVerificationLib: refactor db/dbx fetching code in IsAllowedByDb(CVE-2019-14575) Thread-Topic: [PATCH 5/9] SecurityPkg/DxeImageVerificationLib: refactor db/dbx fetching code in IsAllowedByDb(CVE-2019-14575) Thread-Index: AQHV3Ph8h9cQJis9IkeauPhu5Ylqd6gY6kvQ Date: Thu, 13 Feb 2020 09:44:18 +0000 Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503F92CBC3@shsmsx102.ccr.corp.intel.com> References: <20200206141933.356-1-jian.j.wang@intel.com> <20200206141933.356-6-jian.j.wang@intel.com> In-Reply-To: <20200206141933.356-6-jian.j.wang@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: jiewen.yao@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Good enhancement. Reviewed-by: Jiewen Yao > -----Original Message----- > From: Wang, Jian J > Sent: Thursday, February 6, 2020 10:19 PM > To: devel@edk2.groups.io > Cc: Yao, Jiewen ; Zhang, Chao B > > Subject: [PATCH 5/9] SecurityPkg/DxeImageVerificationLib: refactor db/dbx > fetching code in IsAllowedByDb(CVE-2019-14575) >=20 > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1608 >=20 > 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. >=20 > More comments are also added or refined to explain more details. >=20 > Cc: Jiewen Yao > Cc: Chao Zhang > Signed-off-by: Jian J Wang > --- > .../DxeImageVerificationLib.c | 144 ++++++++++-------- > 1 file changed, 83 insertions(+), 61 deletions(-) >=20 > diff --git > a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c > b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.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; >=20 > VerifyStatus =3D FALSE; >=20 >=20 >=20 > + // >=20 > + // Fetch 'db' content. If 'db' doesn't exist or encounters problem to = get the >=20 > + // data, return not-allowed-by-db (FALSE). >=20 > + // >=20 > DataSize =3D 0; >=20 > Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, > &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL); >=20 > - if (Status =3D=3D EFI_BUFFER_TOO_SMALL) { >=20 > - Data =3D (UINT8 *) AllocateZeroPool (DataSize); >=20 > - if (Data =3D=3D NULL) { >=20 > - return VerifyStatus; >=20 > + ASSERT (EFI_ERROR (Status)); >=20 > + if (Status !=3D EFI_BUFFER_TOO_SMALL) { >=20 > + return VerifyStatus; >=20 > + } >=20 > + >=20 > + Data =3D (UINT8 *) AllocateZeroPool (DataSize); >=20 > + if (Data =3D=3D NULL) { >=20 > + return VerifyStatus; >=20 > + } >=20 > + >=20 > + Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, > &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data); >=20 > + if (EFI_ERROR (Status)) { >=20 > + goto Done; >=20 > + } >=20 > + >=20 > + // >=20 > + // Fetch 'dbx' content. If 'dbx' doesn't exist, continue to check 'db'= . >=20 > + // If any other errors occured, no need to check 'db' but just return >=20 > + // not-allowed-by-db (FALSE) to avoid bypass. >=20 > + // >=20 > + DbxDataSize =3D 0; >=20 > + Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, > &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL); >=20 > + ASSERT (EFI_ERROR (Status)); >=20 > + if (Status !=3D EFI_BUFFER_TOO_SMALL) { >=20 > + if (Status !=3D EFI_NOT_FOUND) { >=20 > + goto Done; >=20 > + } >=20 > + // >=20 > + // 'dbx' does not exist. Continue to check 'db'. >=20 > + // >=20 > + } else { >=20 > + // >=20 > + // 'dbx' exists. Get its content. >=20 > + // >=20 > + DbxData =3D (UINT8 *) AllocateZeroPool (DbxDataSize); >=20 > + if (DbxData =3D=3D NULL) { >=20 > + goto Done; >=20 > } >=20 >=20 >=20 > - Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, > &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data); >=20 > + Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, > &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData); >=20 > if (EFI_ERROR (Status)) { >=20 > goto Done; >=20 > } >=20 > + } >=20 >=20 >=20 > - // >=20 > - // Find X509 certificate in Signature List to verify the signature i= n pkcs7 signed > data. >=20 > - // >=20 > - CertList =3D (EFI_SIGNATURE_LIST *) Data; >=20 > - while ((DataSize > 0) && (DataSize >=3D CertList->SignatureListSize)= ) { >=20 > - if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { >=20 > - CertData =3D (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeo= f > (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); >=20 > - CertCount =3D (CertList->SignatureListSize - sizeof (EFI_SIGNATU= RE_LIST) - > CertList->SignatureHeaderSize) / CertList->SignatureSize; >=20 > + // >=20 > + // Find X509 certificate in Signature List to verify the signature in = pkcs7 signed > data. >=20 > + // >=20 > + CertList =3D (EFI_SIGNATURE_LIST *) Data; >=20 > + while ((DataSize > 0) && (DataSize >=3D CertList->SignatureListSize)) = { >=20 > + if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { >=20 > + CertData =3D (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof > (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); >=20 > + CertCount =3D (CertList->SignatureListSize - sizeof (EFI_SIGNATURE= _LIST) - > CertList->SignatureHeaderSize) / CertList->SignatureSize; >=20 >=20 >=20 > - for (Index =3D 0; Index < CertCount; Index++) { >=20 > - // >=20 > - // Iterate each Signature Data Node within this CertList for v= erify. >=20 > - // >=20 > - RootCert =3D CertData->SignatureData; >=20 > - RootCertSize =3D CertList->SignatureSize - sizeof (EFI_GUID); >=20 > + for (Index =3D 0; Index < CertCount; Index++) { >=20 > + // >=20 > + // Iterate each Signature Data Node within this CertList for ver= ify. >=20 > + // >=20 > + RootCert =3D CertData->SignatureData; >=20 > + RootCertSize =3D CertList->SignatureSize - sizeof (EFI_GUID); >=20 >=20 >=20 > + // >=20 > + // Call AuthenticodeVerify library to Verify Authenticode struct= . >=20 > + // >=20 > + VerifyStatus =3D AuthenticodeVerify ( >=20 > + AuthData, >=20 > + AuthDataSize, >=20 > + RootCert, >=20 > + RootCertSize, >=20 > + mImageDigest, >=20 > + mImageDigestSize >=20 > + ); >=20 > + if (VerifyStatus) { >=20 > // >=20 > - // Call AuthenticodeVerify library to Verify Authenticode stru= ct. >=20 > + // The image is signed and its signature is found in 'db'. >=20 > // >=20 > - VerifyStatus =3D AuthenticodeVerify ( >=20 > - AuthData, >=20 > - AuthDataSize, >=20 > - RootCert, >=20 > - RootCertSize, >=20 > - mImageDigest, >=20 > - mImageDigestSize >=20 > - ); >=20 > - if (VerifyStatus) { >=20 > + if (DbxData !=3D NULL) { >=20 > // >=20 > // Here We still need to check if this RootCert's Hash is re= voked >=20 > // >=20 > - DbxDataSize =3D 0; >=20 > - Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, > &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL); >=20 > - if (Status !=3D EFI_BUFFER_TOO_SMALL) { >=20 > - if (Status !=3D EFI_NOT_FOUND) { >=20 > - VerifyStatus =3D FALSE; >=20 > - } >=20 > - goto Done; >=20 > - } >=20 > - DbxData =3D (UINT8 *) AllocateZeroPool (DbxDataSize); >=20 > - if (DbxData =3D=3D NULL) { >=20 > - // >=20 > - // Force not-allowed-by-db to avoid bypass >=20 > - // >=20 > - VerifyStatus =3D FALSE; >=20 > - goto Done; >=20 > - } >=20 > - >=20 > - Status =3D gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, > &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData); >=20 > - if (EFI_ERROR (Status)) { >=20 > - // >=20 > - // Force not-allowed-by-db to avoid bypass >=20 > - // >=20 > - VerifyStatus =3D FALSE; >=20 > - goto Done; >=20 > - } >=20 > - >=20 > if (IsCertHashFoundInDatabase (RootCert, RootCertSize, > (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime)) { >=20 > // >=20 > // Check the timestamp signature and signing time to deter= mine if the > RootCert can be trusted. >=20 > @@ -1491,17 +1507,23 @@ IsAllowedByDb ( > DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is s= igned and > signature is accepted by DB, but its root cert failed the timestamp check= .\n")); >=20 > } >=20 > } >=20 > - >=20 > - goto Done; >=20 > } >=20 >=20 >=20 > - CertData =3D (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + Cert= List- > >SignatureSize); >=20 > + // >=20 > + // There's no 'dbx' to check revocation time against (must-be = pass), >=20 > + // or, there's revocation time found in 'dbx' and checked agai= nt 'dbt' >=20 > + // (maybe pass or fail, depending on timestamp compare result)= . Either >=20 > + // way the verification job has been completed at this point. >=20 > + // >=20 > + goto Done; >=20 > } >=20 > - } >=20 >=20 >=20 > - DataSize -=3D CertList->SignatureListSize; >=20 > - CertList =3D (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList= - > >SignatureListSize); >=20 > + CertData =3D (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertLi= st- > >SignatureSize); >=20 > + } >=20 > } >=20 > + >=20 > + DataSize -=3D CertList->SignatureListSize; >=20 > + CertList =3D (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList- > >SignatureListSize); >=20 > } >=20 >=20 >=20 > Done: >=20 > -- > 2.24.0.windows.2