|
|
4210fa |
From 5f18e2e3643524c6b6b38c44c6ce4eabdcfd59d1 Mon Sep 17 00:00:00 2001
|
|
|
4210fa |
From: Gary Ching-Pang Lin <glin@suse.com>
|
|
|
4210fa |
Date: Tue, 27 May 2014 17:42:00 +0800
|
|
|
4210fa |
Subject: [PATCH 30/74] Check the first 4 bytes of the certificate
|
|
|
4210fa |
|
|
|
4210fa |
A non-DER encoding x509 certificate may be mistakenly enrolled into
|
|
|
4210fa |
db or MokList. This commit checks the first 4 bytes of the certificate
|
|
|
4210fa |
to ensure that it's DER encoding.
|
|
|
4210fa |
|
|
|
4210fa |
This commit also removes the iteration of the x509 signature list.
|
|
|
4210fa |
Per UEFI SPEC, each x509 signature list contains only one x509 certificate.
|
|
|
4210fa |
Besides, the size of certificate is incorrect. The size of the header must
|
|
|
4210fa |
be substracted from the signature size.
|
|
|
4210fa |
|
|
|
4210fa |
Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
|
|
|
4210fa |
---
|
|
|
4210fa |
MokManager.c | 23 +++++++++++++++++++++--
|
|
|
4210fa |
shim.c | 45 +++++++++++++++++++++++++++++++--------------
|
|
|
4210fa |
2 files changed, 52 insertions(+), 16 deletions(-)
|
|
|
4210fa |
|
|
|
4210fa |
diff --git a/MokManager.c b/MokManager.c
|
|
|
4210fa |
index 3da61f4..c9fbbac 100644
|
|
|
4210fa |
--- a/MokManager.c
|
|
|
4210fa |
+++ b/MokManager.c
|
|
|
4210fa |
@@ -1306,11 +1306,30 @@ static INTN mok_pw_prompt (void *MokPW, UINTN MokPWSize) {
|
|
|
4210fa |
return -1;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
-static BOOLEAN verify_certificate(void *cert, UINTN size)
|
|
|
4210fa |
+static BOOLEAN verify_certificate(UINT8 *cert, UINTN size)
|
|
|
4210fa |
{
|
|
|
4210fa |
X509 *X509Cert;
|
|
|
4210fa |
- if (!cert || size == 0)
|
|
|
4210fa |
+ UINTN length;
|
|
|
4210fa |
+ if (!cert || size < 0)
|
|
|
4210fa |
+ return FALSE;
|
|
|
4210fa |
+
|
|
|
4210fa |
+ /*
|
|
|
4210fa |
+ * A DER encoding x509 certificate starts with SEQUENCE(0x30),
|
|
|
4210fa |
+ * the number of length bytes, and the number of value bytes.
|
|
|
4210fa |
+ * The size of a x509 certificate is usually between 127 bytes
|
|
|
4210fa |
+ * and 64KB. For convenience, assume the number of value bytes
|
|
|
4210fa |
+ * is 2, i.e. the second byte is 0x82.
|
|
|
4210fa |
+ */
|
|
|
4210fa |
+ if (cert[0] != 0x30 || cert[1] != 0x82) {
|
|
|
4210fa |
+ console_notify(L"Not a DER encoding X509 certificate");
|
|
|
4210fa |
return FALSE;
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+
|
|
|
4210fa |
+ length = (cert[2]<<8 | cert[3]);
|
|
|
4210fa |
+ if (length != (size - 4)) {
|
|
|
4210fa |
+ console_notify(L"Invalid X509 certificate: Inconsistent size");
|
|
|
4210fa |
+ return FALSE;
|
|
|
4210fa |
+ }
|
|
|
4210fa |
|
|
|
4210fa |
if (!(X509ConstructCertificate(cert, size, (UINT8 **) &X509Cert)) ||
|
|
|
4210fa |
X509Cert == NULL) {
|
|
|
4210fa |
diff --git a/shim.c b/shim.c
|
|
|
4210fa |
index d8699f9..cd26ce6 100644
|
|
|
4210fa |
--- a/shim.c
|
|
|
4210fa |
+++ b/shim.c
|
|
|
4210fa |
@@ -226,44 +226,61 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
|
|
4210fa |
return EFI_SUCCESS;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
+static BOOLEAN verify_x509(UINT8 *Cert, UINTN CertSize)
|
|
|
4210fa |
+{
|
|
|
4210fa |
+ UINTN length;
|
|
|
4210fa |
+
|
|
|
4210fa |
+ if (!Cert || CertSize < 4)
|
|
|
4210fa |
+ return FALSE;
|
|
|
4210fa |
+
|
|
|
4210fa |
+ /*
|
|
|
4210fa |
+ * A DER encoding x509 certificate starts with SEQUENCE(0x30),
|
|
|
4210fa |
+ * the number of length bytes, and the number of value bytes.
|
|
|
4210fa |
+ * The size of a x509 certificate is usually between 127 bytes
|
|
|
4210fa |
+ * and 64KB. For convenience, assume the number of value bytes
|
|
|
4210fa |
+ * is 2, i.e. the second byte is 0x82.
|
|
|
4210fa |
+ */
|
|
|
4210fa |
+ if (Cert[0] != 0x30 || Cert[1] != 0x82)
|
|
|
4210fa |
+ return FALSE;
|
|
|
4210fa |
+
|
|
|
4210fa |
+ length = Cert[2]<<8 | Cert[3];
|
|
|
4210fa |
+ if (length != (CertSize - 4))
|
|
|
4210fa |
+ return FALSE;
|
|
|
4210fa |
+
|
|
|
4210fa |
+ return TRUE;
|
|
|
4210fa |
+}
|
|
|
4210fa |
+
|
|
|
4210fa |
static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
|
|
|
4210fa |
UINTN dbsize,
|
|
|
4210fa |
WIN_CERTIFICATE_EFI_PKCS *data,
|
|
|
4210fa |
UINT8 *hash)
|
|
|
4210fa |
{
|
|
|
4210fa |
EFI_SIGNATURE_DATA *Cert;
|
|
|
4210fa |
- UINTN CertCount, Index;
|
|
|
4210fa |
+ UINTN CertSize;
|
|
|
4210fa |
BOOLEAN IsFound = FALSE;
|
|
|
4210fa |
EFI_GUID CertType = X509_GUID;
|
|
|
4210fa |
|
|
|
4210fa |
while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
|
|
|
4210fa |
if (CompareGuid (&CertList->SignatureType, &CertType) == 0) {
|
|
|
4210fa |
- CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
|
|
4210fa |
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
|
|
|
4210fa |
- for (Index = 0; Index < CertCount; Index++) {
|
|
|
4210fa |
+ CertSize = CertList->SignatureSize - sizeof(EFI_GUID);
|
|
|
4210fa |
+ if (verify_x509(Cert->SignatureData, CertSize)) {
|
|
|
4210fa |
IsFound = AuthenticodeVerify (data->CertData,
|
|
|
4210fa |
data->Hdr.dwLength - sizeof(data->Hdr),
|
|
|
4210fa |
Cert->SignatureData,
|
|
|
4210fa |
- CertList->SignatureSize,
|
|
|
4210fa |
+ CertSize,
|
|
|
4210fa |
hash, SHA256_DIGEST_SIZE);
|
|
|
4210fa |
if (IsFound)
|
|
|
4210fa |
- break;
|
|
|
4210fa |
-
|
|
|
4210fa |
- Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
|
|
|
4210fa |
+ return DATA_FOUND;
|
|
|
4210fa |
+ } else if (verbose) {
|
|
|
4210fa |
+ console_notify(L"Not a DER encoding x.509 Certificate");
|
|
|
4210fa |
}
|
|
|
4210fa |
-
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
- if (IsFound)
|
|
|
4210fa |
- break;
|
|
|
4210fa |
-
|
|
|
4210fa |
dbsize -= CertList->SignatureListSize;
|
|
|
4210fa |
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
- if (IsFound)
|
|
|
4210fa |
- return DATA_FOUND;
|
|
|
4210fa |
-
|
|
|
4210fa |
return DATA_NOT_FOUND;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
--
|
|
|
4210fa |
1.9.3
|
|
|
4210fa |
|