summaryrefslogtreecommitdiff
path: root/shim.c
diff options
context:
space:
mode:
Diffstat (limited to 'shim.c')
-rw-r--r--shim.c122
1 files changed, 89 insertions, 33 deletions
diff --git a/shim.c b/shim.c
index 6e040c4f..bd314b31 100644
--- a/shim.c
+++ b/shim.c
@@ -40,7 +40,6 @@
#include "shim.h"
#include "netboot.h"
#include "httpboot.h"
-#include "shim_cert.h"
#include "replacements.h"
#include "tpm.h"
#include "ucs2.h"
@@ -52,6 +51,10 @@
#include "console.h"
#include "version.h"
+#ifdef ENABLE_SHIM_CERT
+#include "shim_cert.h"
+#endif
+
#include <stdarg.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
@@ -428,7 +431,8 @@ static BOOLEAN verify_eku(UINT8 *Cert, UINTN CertSize)
static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
UINTN dbsize,
WIN_CERTIFICATE_EFI_PKCS *data,
- UINT8 *hash)
+ UINT8 *hash, CHAR16 *dbname,
+ EFI_GUID guid)
{
EFI_SIGNATURE_DATA *Cert;
UINTN CertSize;
@@ -446,8 +450,10 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
Cert->SignatureData,
CertSize,
hash, SHA256_DIGEST_SIZE);
- if (IsFound)
+ if (IsFound) {
+ tpm_measure_variable(dbname, guid, CertSize, Cert->SignatureData);
return DATA_FOUND;
+ }
}
} else if (verbose) {
console_notify(L"Not a DER encoding x.509 Certificate");
@@ -477,7 +483,7 @@ static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
CertList = (EFI_SIGNATURE_LIST *)db;
- rc = check_db_cert_in_ram(CertList, dbsize, data, hash);
+ rc = check_db_cert_in_ram(CertList, dbsize, data, hash, dbname, guid);
FreePool(db);
@@ -489,7 +495,8 @@ static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
*/
static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList,
UINTN dbsize, UINT8 *data,
- int SignatureSize, EFI_GUID CertType)
+ int SignatureSize, EFI_GUID CertType,
+ CHAR16 *dbname, EFI_GUID guid)
{
EFI_SIGNATURE_DATA *Cert;
UINTN CertCount, Index;
@@ -505,6 +512,7 @@ static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList,
// Find the signature in database.
//
IsFound = TRUE;
+ tpm_measure_variable(dbname, guid, SignatureSize, data);
break;
}
@@ -545,7 +553,8 @@ static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data,
CertList = (EFI_SIGNATURE_LIST *)db;
CHECK_STATUS rc = check_db_hash_in_ram(CertList, dbsize, data,
- SignatureSize, CertType);
+ SignatureSize, CertType,
+ dbname, guid);
FreePool(db);
return rc;
@@ -563,15 +572,18 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx;
if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash,
- SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) ==
+ SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID,
+ L"dbx", secure_var) ==
DATA_FOUND)
return EFI_SECURITY_VIOLATION;
if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash,
- SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID) ==
+ SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID,
+ L"dbx", secure_var) ==
DATA_FOUND)
return EFI_SECURITY_VIOLATION;
if (cert && check_db_cert_in_ram(dbx, vendor_dbx_size, cert,
- sha256hash) == DATA_FOUND)
+ sha256hash, L"dbx",
+ secure_var) == DATA_FOUND)
return EFI_SECURITY_VIOLATION;
if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE,
@@ -953,13 +965,13 @@ static EFI_STATUS verify_mok (void) {
* Check that the signature is valid and matches the binary
*/
static EFI_STATUS verify_buffer (char *data, int datasize,
- PE_COFF_LOADER_IMAGE_CONTEXT *context)
+ PE_COFF_LOADER_IMAGE_CONTEXT *context,
+ UINT8 *sha256hash, UINT8 *sha1hash)
{
- UINT8 sha256hash[SHA256_DIGEST_SIZE];
- UINT8 sha1hash[SHA1_DIGEST_SIZE];
EFI_STATUS status = EFI_SECURITY_VIOLATION;
WIN_CERTIFICATE_EFI_PKCS *cert = NULL;
unsigned int size = datasize;
+ EFI_GUID shim_var = SHIM_LOCK_GUID;
if (context->SecDir->Size != 0) {
if (context->SecDir->Size >= size) {
@@ -1017,6 +1029,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
return status;
if (cert) {
+#if defined(ENABLE_SHIM_CERT)
/*
* Check against the shim build key
*/
@@ -1026,9 +1039,11 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
shim_cert, sizeof(shim_cert), sha256hash,
SHA256_DIGEST_SIZE)) {
update_verification_method(VERIFIED_BY_CERT);
+ tpm_measure_variable(L"Shim", shim_var, sizeof(shim_cert), shim_cert);
status = EFI_SUCCESS;
return status;
}
+#endif /* defined(ENABLE_SHIM_CERT) */
/*
* And finally, check against shim's built-in key
@@ -1039,6 +1054,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
vendor_cert, vendor_cert_size,
sha256hash, SHA256_DIGEST_SIZE)) {
update_verification_method(VERIFIED_BY_CERT);
+ tpm_measure_variable(L"Shim", shim_var, vendor_cert_size, vendor_cert);
status = EFI_SUCCESS;
return status;
}
@@ -1194,6 +1210,8 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize,
unsigned int alignment, alloc_size;
EFI_PHYSICAL_ADDRESS alloc_address;
int found_entry_point = 0;
+ UINT8 sha1hash[SHA1_DIGEST_SIZE];
+ UINT8 sha256hash[SHA256_DIGEST_SIZE];
/*
* The binary header contains relevant context and section pointers
@@ -1207,8 +1225,17 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize,
/*
* We only need to verify the binary if we're in secure mode
*/
+ efi_status = generate_hash(data, datasize, &context, sha256hash,
+ sha1hash);
+ if (efi_status != EFI_SUCCESS)
+ return efi_status;
+
+ /* Measure the binary into the TPM */
+ tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize, sha1hash, 4);
+
if (secure_mode ()) {
- efi_status = verify_buffer(data, datasize, &context);
+ efi_status = verify_buffer(data, datasize, &context,
+ sha256hash, sha1hash);
if (EFI_ERROR(efi_status)) {
console_error(L"Verification failed", efi_status);
@@ -1699,6 +1726,8 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size)
{
EFI_STATUS status = EFI_SUCCESS;
PE_COFF_LOADER_IMAGE_CONTEXT context;
+ UINT8 sha1hash[SHA1_DIGEST_SIZE];
+ UINT8 sha256hash[SHA256_DIGEST_SIZE];
loader_is_participating = 1;
in_protocol = 1;
@@ -1710,7 +1739,11 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size)
if (status != EFI_SUCCESS)
goto done;
- status = verify_buffer(buffer, size, &context);
+ status = generate_hash(buffer, size, &context, sha256hash, sha1hash);
+ if (status != EFI_SUCCESS)
+ goto done;
+
+ status = verify_buffer(buffer, size, &context, sha256hash, sha1hash);
done:
in_protocol = 0;
return status;
@@ -1814,10 +1847,6 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
}
}
- /* Measure the binary into the TPM */
- tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize,
- 9, (CHAR8 *)"Second stage bootloader");
-
/*
* We need to modify the loaded image protocol entry before running
* the new binary, so back it up
@@ -1888,37 +1917,64 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle)
}
/*
- * Measure some of the MOK variables into the TPM
+ * Measure some of the MOK variables into the TPM. We measure the entirety
+ * of MokList into PCR 14, and also measure the raw MokSBState there. PCR 7
+ * will be extended with MokSBState in the Microsoft format, and we'll
+ * measure any matching hashes or certificates later on in order to behave
+ * consistently with the PCR 7 spec.
*/
EFI_STATUS measure_mok()
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
- EFI_STATUS efi_status;
+ EFI_STATUS efi_status, ret = EFI_SUCCESS;
UINT8 *Data = NULL;
UINTN DataSize = 0;
efi_status = get_variable(L"MokList", &Data, &DataSize, shim_lock_guid);
- if (efi_status != EFI_SUCCESS)
- return efi_status;
+ if (!EFI_ERROR(efi_status)) {
+ efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
+ DataSize, 14, (CHAR8 *)"MokList");
+ FreePool(Data);
- efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
- DataSize, 14, (CHAR8 *)"MokList");
+ if (EFI_ERROR(efi_status))
+ ret = efi_status;
- FreePool(Data);
+ } else {
+ ret = efi_status;
+ }
- if (efi_status != EFI_SUCCESS)
- return efi_status;
+ efi_status = get_variable(L"MokListX", &Data, &DataSize, shim_lock_guid);
+ if (!EFI_ERROR(efi_status)) {
+ efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
+ DataSize, 14, (CHAR8 *)"MokListX");
+ FreePool(Data);
+
+ if (EFI_ERROR(efi_status) && !EFI_ERROR(ret))
+ ret = efi_status;
+
+ } else if (!EFI_ERROR(ret)) {
+ ret = efi_status;
+ }
efi_status = get_variable(L"MokSBState", &Data, &DataSize,
shim_lock_guid);
+ if (!EFI_ERROR(efi_status)) {
+ efi_status = tpm_measure_variable(L"MokSBState",
+ shim_lock_guid,
+ DataSize, Data);
+ if (!EFI_ERROR(efi_status)) {
+ efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)
+ (UINTN)Data, DataSize, 14,
+ (CHAR8 *)"MokSBState");
+ }
- if (efi_status != EFI_SUCCESS)
- return efi_status;
-
- efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
- DataSize, 14, (CHAR8 *)"MokSBState");
+ FreePool(Data);
- FreePool(Data);
+ if (EFI_ERROR(efi_status) && !EFI_ERROR(ret))
+ ret = efi_status;
+ } else if (!EFI_ERROR(ret)) {
+ ret = efi_status;
+ }
return efi_status;
}