From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=helo; client-ip=104.47.40.71; helo=nam03-co1-obe.outbound.protection.outlook.com; envelope-from=wojciech.zmuda@cavium.com; receiver=edk2-devel@lists.01.org Received: from NAM03-CO1-obe.outbound.protection.outlook.com (mail-co1nam03on0071.outbound.protection.outlook.com [104.47.40.71]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id DDB4D21F38849 for ; Tue, 17 Oct 2017 12:04:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=CAVIUMNETWORKS.onmicrosoft.com; s=selector1-cavium-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=5l5rAtaHojVFRfsbdwIj3fzfJBnUMqHxgbaEJDVe+H4=; b=KrproxmaaH9a7SYYMwLXVofZHZS9Bs2xcO3ivz2KEcAv1+izIggPhrH2i9JF5fVgqeYtpaJX0Z25681Ki8snHKYdt1MHDpNoiKxEcrUdbCh0uMKUHWfjd5mad5gYZDpE6i1VBxhBj1brJW2t2Tc/mSvAr2QnhBa/IDBwOmklwK0= Received: from CY1PR0701MB1852.namprd07.prod.outlook.com (10.163.42.18) by BN3PR07MB2531.namprd07.prod.outlook.com (10.167.4.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.77.7; Tue, 17 Oct 2017 19:07:57 +0000 Received: from CY1PR0701MB1852.namprd07.prod.outlook.com ([10.163.42.18]) by CY1PR0701MB1852.namprd07.prod.outlook.com ([10.163.42.18]) with mapi id 15.20.0077.020; Tue, 17 Oct 2017 19:07:55 +0000 From: "Zmuda, Wojciech" To: Laszlo Ersek CC: "edk2-devel@lists.01.org" , "Zhang, Jonathan" , "Dabros, Jan" Thread-Topic: [edk2] SecurityPkg: untrusted OptionRom is loaded despite DENY_EXECUTE_ON_SECURITY_VIOLATION set. Thread-Index: AQHTRpsJYllILr1R/kWdPFlk6zLQlqLmsODRgAAWKICAAaAUKw== Date: Tue, 17 Oct 2017 19:07:55 +0000 Message-ID: References: , <205fa9c0-5717-c20d-a5c1-260be05ee8c6@redhat.com> In-Reply-To: <205fa9c0-5717-c20d-a5c1-260be05ee8c6@redhat.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=none (sender IP is ) smtp.mailfrom=Wojciech.Zmuda@cavium.com; x-originating-ip: [31.172.191.173] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; BN3PR07MB2531; 6:CYbqkO8dm8Lj9BDgwgNpgz9wPcuPgwjMRODLST4KlLvUnx8hHgBjNB6X8ZVJ6AeLZPFUEoVzESKG848AVpPMIKSdlSLlnLcrpGMzN7EptsMZxYS6Jo7NwlKOfuiSvbwBh7xy744n3etigUiZjr7gVPTXOG/4hV4VvW8gtL8sQdoj6/1v0O+5uxvqI7aCGOEcNDIGaKrZH8z3Kqb7oCgqgmOQThOD9OLlCArQLIXeRDVVaYmSCCEWO9AvCrBD0m8vU19y+qiQCTLlfd8ODIkx9lwjiZ3bio/rzOEp5C9Uo2KzVZAImHqLscKdfnfHYcy8EeJjSUYgBgmei70vI9I9AA==; 5:QPosnfWc6fO7sO/iFypEVGgGEdMEVsTgRW5hFWq/dGs/vOmkDSHS2CP5QsIfKl4EjKzrxVbENDQYIKRoNP97VNY5NAJJfulBlMD7g1mXPVUjMLU6VBlYjClRlh4o0GzJS2SN4bNTomcVcXxjjsM69w==; 24:d9sD8ceBo7bKOovsFHYHdRwFdsTduNZre0rwxwtA+D/h4RpMok1fHOvKR3mxtRQY46tYVHGez094ALPpeAn3Wf+kHU03VhsJ7BCV6z28hu8=; 7:DYO3qIu2Cr4KWu9JImjGuMH5JfsKElu3BFfRqqRNvqz4yODCO5exwGhssQOt+8lpxNZj3yrLFmObae0Olx7VUt2fvkxatm4KSMhyAbcHcln7YgpaFZ3nh8KtLhgN14Q58hWD48PjR4I6JcOXUctWjr/TEcwFVKyShHRh30Xu1Otvb9q52piZch4BntCfQD1IGGz5EcACBUM7BcYhnVDORErZ5p3cYyDjintGcMnf4d4= x-ms-exchange-antispam-srfa-diagnostics: SSOS;SSOR; x-forefront-antispam-report: SFV:SKI; SCL:-1; SFV:NSPM; SFS:(10009020)(6009001)(376002)(346002)(24454002)(377424004)(52314003)(45984002)(189002)(199003)(377454003)(33656002)(3660700001)(5660300001)(7696004)(6916009)(53546010)(86362001)(72206003)(66066001)(68736007)(101416001)(2950100002)(4326008)(50986999)(189998001)(6116002)(54356999)(102836003)(8676002)(105586002)(3846002)(478600001)(15650500001)(76176999)(229853002)(81166006)(14454004)(6436002)(2900100001)(7736002)(77096006)(106356001)(74316002)(25786009)(6506006)(81156014)(54906003)(6246003)(99286003)(2906002)(316002)(53936002)(54896002)(9686003)(97736004)(107886003)(8936002)(55016002)(3280700002); DIR:OUT; SFP:1101; SCL:1; SRVR:BN3PR07MB2531; H:CY1PR0701MB1852.namprd07.prod.outlook.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; x-ms-office365-filtering-correlation-id: 82a98986-e3a0-4380-8437-08d515925fb3 x-microsoft-antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(2017030254152)(2017052603199)(201703131423075)(201703031133081)(201702281549075); SRVR:BN3PR07MB2531; x-ms-traffictypediagnostic: BN3PR07MB2531: x-exchange-antispam-report-test: UriScan:(190756311086443)(158342451672863)(192374486261705)(162533806227266); x-microsoft-antispam-prvs: x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(8121501046)(5005006)(3002001)(100000703101)(100105400095)(93006095)(93001095)(10201501046)(6041248)(20161123562025)(20161123558100)(20161123560025)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:BN3PR07MB2531; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:BN3PR07MB2531; x-forefront-prvs: 04631F8F77 received-spf: None (protection.outlook.com: cavium.com does not designate permitted sender hosts) spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-originalarrivaltime: 17 Oct 2017 19:07:55.6551 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 711e4ccf-2e9b-4bcf-a551-4094005b6194 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR07MB2531 X-Content-Filtered-By: Mailman/MimeDel 2.1.22 Subject: Re: SecurityPkg: untrusted OptionRom is loaded despite DENY_EXECUTE_ON_SECURITY_VIOLATION set. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 17 Oct 2017 19:04:23 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Laszlo, Thanks for this detailed explanation. I repeated the experiment with EBC in= terpreter included, this time stepping much further in the code, and I actu= ally can see that with Secure Boot enabled the EFI_SECURITY_VIOLATION statu= s is propagated, which does not let the image to load. With Secure Boot dis= abled, I get early EFI_SUCCESS and the image is loaded, as far as I can see= in the debugger. Everything seems to work as designed, then. I have one more question in this matter, if I may ask: why doesn't this pat= h terminate immediately after finding that the OptionROM is untrusted? It w= ouldn't be executed anyway, with or without EBC interpreter, so why bother = with further checking? Thank you very much, Wojciech ________________________________ From: Laszlo Ersek Sent: Monday, October 16, 2017 11:11:01 AM To: Zmuda, Wojciech Cc: edk2-devel@lists.01.org Subject: Re: [edk2] SecurityPkg: untrusted OptionRom is loaded despite DENY= _EXECUTE_ON_SECURITY_VIOLATION set. On 10/16/17 18:57, Zmuda, Wojciech wrote: > Hello, > > I'd like to ask you for help with understanding Secure Boot policy > mechanism, specifically DENY_EXECUTE_ON_SECURITY_VIOLATION for > PcdOptionRomImageVerificationPolicy. The OptionROM in my setup is > loaded while, in my opinion, it should be rejected. > > I'm testing the following scenario: Secure Boot is enabled with my own > PK and KEK enrolled, but with no db, to make sure nothing unsigned or > signed by somebody else but me can be executed. A PCIe card with > OptionROM (some EBC code) is installed. > gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy is > set to 0x04 in my platform's package. What I expect, is the OptionROM > execution being denied, as it is not signed by my certificate. What I > observe, on the other hand, is a message on the console, that no EBC > interpreter is found, which suggest, that the OptionROM is loaded, > just fails at the execution of EBC. The same message is printed when > Secure Boot is disabled. > > I tried to understand the code by stepping through it in the DS-5. The > following part of > SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c > seems suspicious to me: > > SecurityStatus =3D gSecurity->FileAuthenticationState ( > gSecurity, > AuthenticationStatus, > OriginalFilePath > ); > } This code is not from "DxeImageVerificationLib.c"; it is from CoreLoadImageCommon() in "MdeModulePkg/Core/Dxe/Image/Image.c". With more context: } else if ((gSecurity !=3D NULL) && (OriginalFilePath !=3D NULL)) { // // Verify the Authentication Status through the Security Architectural = Protocol // SecurityStatus =3D gSecurity->FileAuthenticationState ( gSecurity, AuthenticationStatus, OriginalFilePath ); } > > // > // Check Security Status. > // > if (EFI_ERROR (SecurityStatus) && SecurityStatus !=3D EFI_SECURITY_VIOL= ATION) { > if (SecurityStatus =3D=3D EFI_ACCESS_DENIED) { > // > // Image was not loaded because the platform policy prohibits the i= mage from being loaded. > // It's the only place we could meet EFI_ACCESS_DENIED. > // > *ImageHandle =3D NULL; > } > Status =3D SecurityStatus; > Image =3D NULL; > goto Done; > } > > The return code of gSecurity->FileAuthenticationState () (which is > implemented in > MdeModulePkg/Core/Dxe/Image/Image.c:DxeImageVerificationHandler ()), > is EFI_SECURITY_VIOLATION. Such return code skips this if-statement, > that prevents the image to be loaded. According to the comment in the > if-statement: for the policy to be respected, > gSecurity->FileAuthenticationState () should return EFI_ACCESS_DENIED. No, that's a different kind of "platform policy". The PCD that you mention is indeed platform policy, but only for DxeImageVerificationLib. The platform policy being referred-to in this comment is on the level of the gSecurity->FileAuthenticationState() function call; and for that, we have to review the type definition of the EFI_SECURITY_ARCH_PROTOCOL.FileAuthenticationState member function. The type name for this member function is EFI_SECURITY_FILE_AUTHENTICATION_STATE, and it is defined in "MdePkg/Include/Protocol/Security.h". I will not quote the entire description from said header file, just the part that explains the difference: > @retval EFI_SECURITY_VIOLATION The file specified by File did not authe= nticate, and > the platform policy dictates that File sh= ould be placed > in the untrusted state. A file may be pro= moted from > the untrusted to the trusted state at a f= uture time > with a call to the Trust() DXE Service. > @retval EFI_ACCESS_DENIED The file specified by File did not authen= ticate, and > the platform policy dictates that File sh= ould not be > used for any purpose. Back to your email: On 10/16/17 18:57, Zmuda, Wojciech wrote: > That being said, I stepped through DxeImageVerificationHandler (). The > PCD with OptionROM policy is checked correctly. The function handles > ALWAYS_EXECUTE and NEVER_EXECUTE policies properly and hangs on > QUERY_USER_ and ALLOW_EXECUTE_ON_SECURITY_VIOLATION. This seems fine, > however there is no code handling the > DENY_EXECUTE_ON_SECURITY_VIOLATION (0x04) case. Stepping through this > function shows that the image to be loaded cannot be found in the db > (correct, as there's no db). Then, the function jumps to its very end > and returns EFI_SECURITY_VIOLATION, which skips the aforementioned > if-statement: > > Done: > if (Status !=3D EFI_SUCCESS) { > // > // Policy decides to defer or reject the image; add its information i= n image executable information table. > // > NameStr =3D ConvertDevicePathToText (File, FALSE, TRUE); > AddImageExeInfo (Action, NameStr, File, SignatureList, SignatureListS= ize); > if (NameStr !=3D NULL) { > DEBUG((EFI_D_INFO, "The image doesn't pass verification: %s\n", Nam= eStr)); > FreePool(NameStr); > } > Status =3D EFI_SECURITY_VIOLATION; > } > > if (SignatureList !=3D NULL) { > FreePool (SignatureList); > } > > return Status; > } This quote is indeed from "SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c", and indeed the EFI_SECURITY_VIOLATION value returned by it causes the "if" statement you quoted from "MdeModulePkg/Core/Dxe/Image/Image.c" to be skipped. However, that's not the whole story. In "MdeModulePkg/Core/Dxe/Image/Image.c", in the CoreLoadImageCommon() function, track the "SecurityStatus" variable from the point where the EFI_ACCESS_DENIED branch is *not* taken, to the end of the function. Near the end of the function, "Status" is EFI_SUCCESS, and thus "SecurityStatus" will be assigned to it (and the function will ultimately return EFI_SECURITY_VIOLATION): Done: // // All done accessing the source file // If we allocated the Source buffer, free it // if (FHand.FreeBuffer) { CoreFreePool (FHand.Source); } if (OriginalFilePath !=3D InputFilePath) { CoreFreePool (OriginalFilePath); } // // There was an error. If there's an Image structure, free it // if (EFI_ERROR (Status)) { if (Image !=3D NULL) { CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer =3D=3D 0)); Image =3D NULL; } } else if (EFI_ERROR (SecurityStatus)) { Status =3D SecurityStatus; } // // Track the return status from LoadImage. // if (Image !=3D NULL) { Image->LoadImageStatus =3D Status; } return Status; } Back to your email: On 10/16/17 18:57, Zmuda, Wojciech wrote: > Is there anything I'm doing wrong trying to prevent untrusted > OptionROM execution? If my understanding is correct, my case should > make DxeImageVerificationHandler () return EFI_ACCESS_DENIED here. For > example, in the snippet above, Status should be set to > EFI_ACCESS_DENIED if Policy =3D=3D DENY_EXECUTE_ON_SECURITY_VIOLATION. To me it seems like everything is working by design. The image is loaded and the security violation is recorded. Please see the documentation of the EFI_SECURITY_VIOLATION return code in the UEFI-2.7 spec, under EFI_BOOT_SERVICES.LoadImage(): Image was loaded and an ImageHandle was created with a valid EFI_LOADED_IMAGE_PROTOCOL.. However, the current platform policy specifies that the image should not be started. (This section also has a pointer to "35.1.5 Deferred Execution".) I believe the misunderstanding comes from the facts that (a) the message CoreLoadPeImage: There is no EBC interpreter for an EBC image. is printed by the CoreLoadPeImage() function, and (b) that CoreLoadImageCommon() calls CoreLoadPeImage() *between* the EFI_ACCESS_DENIED check that you thought should have been taken -- which is not the case -- and the final setting of Status to EFI_SECURITY_VIOLATION (from "SecurityStatus"), which actually *would* occur, if you had an EBC driver included in your platform firmware. In other words, CoreLoadImageCommon() identifies (and prepares to return) the EFI_SECURITY_VIOLATION status code, based on PcdOptionRomImageVerificationPolicy. However, before the function could finish processing (and return this error code), it comes across a more severe error -- no EBC interpreter -- which takes priority both with and without the Secure Boot operational mode. If you want to be completely sure, I suggest including the EBC interpreter in your platform, and retesting. (Based on commit 81d9f86f8a71 ("ArmVirtPkg: enable EBC interpreter for AArch64", 2016-07-29), adding the EBC interpreter should be easy.) Again, to me it looks like everything is working by design. Thanks Laszlo