shim/shim-bsc991885-fix-sig-length.patch

66 lines
2.7 KiB
Diff

From 6c12c7bf522d032922abb799cdf0d6f525de3c38 Mon Sep 17 00:00:00 2001
From: Sachin Agrawal <sachin.agrawal@intel.com>
Date: Tue, 2 Aug 2016 16:46:31 -0700
Subject: [PATCH] Use authenticode signature length from WIN_CERTIFICATE
structure.
Authenticode Certificate length is available in Certificate Table
(inside PE header) and also in signature header(WIN_CERTIFICATE) itself.
Code in 'check_backlist()' method uses length from signature header,
whereas, AuthenticodeVerify() call inside 'verify_buffer()' method uses
the length in signature header. This causes a security vulnerability issue :
Good Scenario : Assume shim1.crt is used for signing grub.efi and
shim1.crt is embedded inside shim.efi. Also, assume shim1.crt got
compromised and therefore it was added in 'dbx' database. Now, when
shim.efi will attempt to load grub.efi, it will fail loading with
log message "Binary is blacklisted" because 'check_blacklist' call
will detect the presence of 'shim1.crt' in 'dbx'.
Vulnerable Scenario : Similar as above. Add 'shim1.crt' in dbx database.
Also, tamper the earlier signed grub.efi file by placing 0x0000 in the
WIN_CERTIFICATE.dwLength.
(Open grub.efi/vmlinuz signed binary with hex editor.
Go to 0x128 address and read out the address from 0x128 until
0x12B in little Indian order from right to left.
Jump to the address from 0x128 address area.
First 8bytes are the signature header area which consist of
signature size(4bytes), revision(2bytes) and type(2bytes).
So tamper the first 4 bytes for signature size and save the binary.
)
With this tampered grub.efi, shim.efi loads it successfully because
'check_blacklist()' call fails to detect the presence of shim1.crt in 'dbx'
database.
Signed-off-by: Sachin Agrawal <sachin.agrawal@intel.com>
---
shim.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/shim.c b/shim.c
index ed01899..03a5604 100644
--- a/shim.c
+++ b/shim.c
@@ -966,7 +966,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
*/
if (sizeof(shim_cert) &&
AuthenticodeVerify(cert->CertData,
- context->SecDir->Size - sizeof(cert->Hdr),
+ cert->Hdr.dwLength - sizeof(cert->Hdr),
shim_cert, sizeof(shim_cert), sha256hash,
SHA256_DIGEST_SIZE)) {
status = EFI_SUCCESS;
@@ -977,7 +977,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
* And finally, check against shim's built-in key
*/
if (vendor_cert_size && AuthenticodeVerify(cert->CertData,
- context->SecDir->Size - sizeof(cert->Hdr),
+ cert->Hdr.dwLength - sizeof(cert->Hdr),
vendor_cert, vendor_cert_size, sha256hash,
SHA256_DIGEST_SIZE)) {
status = EFI_SUCCESS;
--
2.9.2