diff options
author | James Bottomley <JBottomley@Parallels.com> | 2012-12-11 13:51:05 +0000 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-12-11 13:51:05 +0000 |
commit | 456d3e5656d853115101cd3f0c26519cf2124c75 (patch) | |
tree | 433e6140cba1922ff2c0a255d88cfc1659f81a0a | |
parent | af3d3d5724e0c977e0183917d5ecdb87d2f3b17a (diff) | |
download | efitools-456d3e5656d853115101cd3f0c26519cf2124c75.tar.gz |
KeyTool: Add ability to enrol hash
Split out hash enrollment functionality from HashTool into library functions
and add it to KeyTool. Also add showing of hash when examining keys.
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | HashTool.c | 39 | ||||
-rw-r--r-- | KeyTool.c | 138 | ||||
-rw-r--r-- | include/sha256.h | 2 | ||||
-rw-r--r-- | include/variables.h | 5 | ||||
-rw-r--r-- | lib/sha256.c | 13 | ||||
-rw-r--r-- | lib/variables.c | 34 |
6 files changed, 168 insertions, 63 deletions
@@ -54,7 +54,7 @@ change_setup_mode(int user_mode) } static void -enrol_hash(void) +enroll_hash(void) { EFI_STATUS efi_status; CHAR16 *file_name = NULL, *title[6], buf0[256], buf1[256], buf2[256], @@ -78,7 +78,7 @@ enrol_hash(void) sha256_get_pecoff_digest(im, file_name, hash); - StrCpy(buf0, L"Enrol this hash into "); + StrCpy(buf0, L"Enroll this hash into "); if (setupmode) StrCat(buf0, L"UEFI signature database?"); else @@ -89,12 +89,7 @@ enrol_hash(void) StrCat(buf1, file_name); title[2] = buf1; StrCpy(buf2, L"Hash: "); - for (i=0; i<SHA256_DIGEST_SIZE; i++) { - CHAR16 buf3[10]; - - SPrint(buf3, sizeof(buf3), L"%02x", hash[i]); - StrCat(buf2, buf3); - } + sha256_StrCat_hash(buf2, hash); title[3] = buf2; title[4] = NULL; i = console_yes_no(title); @@ -110,31 +105,9 @@ enrol_hash(void) var = L"MokList"; owner = &MOK_OWNER; } - - if (find_in_variable_esl(var, *owner, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS) - /* hash already present */ - return; - - UINT8 sig[sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + SHA256_DIGEST_SIZE]; - EFI_SIGNATURE_LIST *l = (void *)sig; - EFI_SIGNATURE_DATA *d = (void *)sig + sizeof(EFI_SIGNATURE_LIST); - SetMem(sig, 0, sizeof(sig)); - l->SignatureType = EFI_CERT_SHA256_GUID; - l->SignatureListSize = sizeof(sig); - l->SignatureSize = 16 +32; /* UEFI defined */ - CopyMem(&d->SignatureData, hash, sizeof(hash)); - - if (setupmode) - efi_status = SetSecureVariable(var, sig, sizeof(sig), *owner, - EFI_VARIABLE_APPEND_WRITE, 0); - else - efi_status = uefi_call_wrapper(RT->SetVariable, 5, var, owner, - EFI_VARIABLE_NON_VOLATILE - | EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_APPEND_WRITE, - sizeof(sig), sig); - if (efi_status != EFI_SUCCESS) { + efi_status = variable_enroll_hash(var, *owner, hash); + if (efi_status != EFI_SUCCESS && efi_status != EFI_ALREADY_STARTED) { console_error(L"Failed to add signature to db", efi_status); return; } @@ -246,7 +219,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) option = console_select(title, options, option); if (option == 0) { - enrol_hash(); + enroll_hash(); } else if (option == keytool) { EFI_STATUS status; @@ -19,36 +19,55 @@ static UINT8 SetupMode, SecureBoot; #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) +enum { + KEY_PK = 0, + KEY_KEK = 1, + KEY_DB = 2, + KEY_DBX = 3, + KEY_MOK = 4, +}; + static struct { CHAR16 *name; CHAR16 *text; EFI_GUID *guid; - int authenticated; + int authenticated:1; + int hash:1; } keyinfo[] = { - { .name = L"PK", - .text = L"The Platform Key (PK)", - .guid = &GV_GUID, - .authenticated = 1, + [KEY_PK] = { + .name = L"PK", + .text = L"The Platform Key (PK)", + .guid = &GV_GUID, + .authenticated = 1, + .hash = 0, }, - { .name = L"KEK", - .text = L"The Key Exchange Key Database (KEK)", - .guid = &GV_GUID, - .authenticated = 1, + [KEY_KEK] = { + .name = L"KEK", + .text = L"The Key Exchange Key Database (KEK)", + .guid = &GV_GUID, + .authenticated = 1, + .hash = 0, }, - { .name = L"db", - .text = L"The Allowed Signatures Database (db)", - .guid = &SIG_DB, - .authenticated = 1, + [KEY_DB] = { + .name = L"db", + .text = L"The Allowed Signatures Database (db)", + .guid = &SIG_DB, + .authenticated = 1, + .hash = 1, }, - { .name = L"dbx", - .text = L"The Forbidden Signatures Database (dbx)", - .guid = &SIG_DB, - .authenticated = 1, + [KEY_DBX] = { + .name = L"dbx", + .text = L"The Forbidden Signatures Database (dbx)", + .guid = &SIG_DB, + .authenticated = 1, + .hash = 1, }, - { .name = L"MokList", - .text = L"The Machine Owner Key List (MokList)", - .guid = &MOK_OWNER, - .authenticated = 0, + [KEY_MOK] = { + .name = L"MokList", + .text = L"The Machine Owner Key List (MokList)", + .guid = &MOK_OWNER, + .authenticated = 0, + .hash = 1, } }; static const int keyinfo_size = ARRAY_SIZE(keyinfo); @@ -137,7 +156,7 @@ show_key(int key, int offset, void *Data, int DataSize) EFI_SIGNATURE_DATA *Cert = NULL; int cert_count = 0, i, Size, option = 0, offs = 0; CHAR16 *title[6], *options[4]; - CHAR16 str[256], str1[256]; + CHAR16 str[256], str1[256], str2[256]; title[0] = keyinfo[key].text; @@ -159,20 +178,26 @@ show_key(int key, int offset, void *Data, int DataSize) SPrint(str, sizeof(str), L"Sig[%d] - owner: %g", offset, &Cert->SignatureOwner); - title[1] = str; - title[2] = L"Unknown"; + int c = 0; + title[c++] = str; + title[c] = L"Unknown"; for (i = 0; i < signatures_size; i++) { if (CompareGuid(signatures[i].guid, &CertList->SignatureType) == 0) { SPrint(str1, sizeof(str1), L"Type: %s", signatures[i].name); - title[2] = str1; + title[c] = str1; break; } } - title[3] = NULL; + if (CompareGuid(&CertList->SignatureType, &EFI_CERT_SHA256_GUID) == 0) { + StrCpy(str2, L"Hash: "); + sha256_StrCat_hash(str2, Cert->SignatureData); + title[++c] = str2; + } + title[++c] = NULL; options[0] = L"Delete"; options[1] = L"Save to File"; - if (key == 0) { + if (key == KEY_PK) { options[2] = L"Delete with .auth File"; options[3] = NULL; } else { @@ -286,10 +311,58 @@ add_new_key(int key, UINTN options) } static void +enroll_hash(int key) +{ + EFI_STATUS efi_status; + CHAR16 *file_name = NULL, *title[6], buf0[256], buf1[256], buf2[256]; + UINT8 hash[SHA256_DIGEST_SIZE]; + int i; + EFI_HANDLE h = NULL; + + simple_file_selector(&h, (CHAR16 *[]){ + L"Select Binary", + L"", + L"The Selected Binary will have its hash Enrolled", + L"This means it will Subsequently Boot with no prompting", + L"Remember to make sure it is a genuine binary before Enrolling its hash", + NULL + }, L"\\", NULL, &file_name); + + if (!file_name) + /* user pressed ESC */ + return; + + sha256_get_pecoff_digest(h, file_name, hash); + + StrCpy(buf0, L"Enroll hash into "); + StrCat(buf0, keyinfo[key].text); + title[0] = buf0; + title[1] = L""; + StrCpy(buf1, L"File: "); + StrCat(buf1, file_name); + title[2] = buf1; + StrCpy(buf2, L"Hash: "); + sha256_StrCat_hash(buf2, hash); + title[3] = buf2; + title[4] = NULL; + i = console_yes_no(title); + if (i == 0) + return; + + efi_status = variable_enroll_hash(keyinfo[key].name, + *keyinfo[key].guid, hash); + if (efi_status != EFI_SUCCESS && efi_status != EFI_ALREADY_STARTED) { + console_error(L"Failed to add signature to db", efi_status); + return; + } +} + +static void manipulate_key(int key) { CHAR16 *title[5]; EFI_STATUS efi_status; + int setup_mode = variable_is_setupmode(); title[0] = L"Manipulating Contents of"; title[1] = keyinfo[key].text; @@ -315,7 +388,7 @@ manipulate_key(int key) if (efi_status == EFI_NOT_FOUND) { int t = 2; title[t++] = L"Variable is Empty"; - if (key == 0) + if (key == KEY_PK) title[t++] = L"WARNING: Setting PK will take the platform out of Setup Mode"; title[t++] = NULL; } else if (efi_status != EFI_SUCCESS) { @@ -332,7 +405,7 @@ manipulate_key(int key) cert_count += (CertList->SignatureListSize - sizeof(EFI_SIGNATURE_LIST)) / CertList->SignatureSize; } - CHAR16 **guids = (CHAR16 **)AllocatePool((cert_count + 3)*sizeof(void *)); + CHAR16 **guids = (CHAR16 **)AllocatePool((cert_count + 4)*sizeof(void *)); cert_count = 0; for (CertList = (EFI_SIGNATURE_LIST *) Data, Size = DataSize; Size > 0 @@ -351,13 +424,18 @@ manipulate_key(int key) if (key != 0) guids[replace++] = L"Add New Key"; guids[replace] = L"Replace Key(s)"; - guids[replace + 1] = NULL; + int hash = replace; + if (keyinfo[key].hash && (!keyinfo[key].authenticated || setup_mode)) + guids[++hash] = L"Enroll hash of binary"; + guids[hash + 1] = NULL; int select = console_select(title, guids, 0); FreePool(guids); if (select == replace) add_new_key(key, 0); else if (select == add) add_new_key(key, EFI_VARIABLE_APPEND_WRITE); + else if (select == hash) + enroll_hash(key); else if (select >= 0) show_key(key, select, Data, DataSize); FreePool(Data); diff --git a/include/sha256.h b/include/sha256.h index 6456307..07c531d 100644 --- a/include/sha256.h +++ b/include/sha256.h @@ -25,6 +25,8 @@ void sha256_finish( sha256_context *ctx, uint8 digest[32] ); EFI_STATUS sha256_get_pecoff_digest_mem(void *buffer, UINTN DataSize, UINT8 hash[SHA256_DIGEST_SIZE]); +void +sha256_StrCat_hash(CHAR16 *str, UINT8 hash[SHA256_DIGEST_SIZE]); EFI_STATUS sha256_get_pecoff_digest(EFI_HANDLE device, CHAR16 *name, uint8 digest[SHA256_DIGEST_SIZE]); #endif /* sha256.h */ diff --git a/include/variables.h b/include/variables.h index af882cc..643de29 100644 --- a/include/variables.h +++ b/include/variables.h @@ -1,5 +1,7 @@ #include <efiauthenticated.h> +#include <sha256.h> /* for SHA256_DIGEST_SIZE */ + EFI_STATUS CreatePkX509SignatureList ( IN UINT8 *X509Data, @@ -34,3 +36,6 @@ int variable_is_secureboot(void); int variable_is_setupmode(void); +EFI_STATUS +variable_enroll_hash(CHAR16 *var, EFI_GUID owner, + UINT8 hash[SHA256_DIGEST_SIZE]); diff --git a/lib/sha256.c b/lib/sha256.c index 1cfce1e..a34cab0 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -351,6 +351,19 @@ sha256_get_pecoff_digest_mem(void *buffer, UINTN DataSize, } #ifdef BUILD_EFI +void +sha256_StrCat_hash(CHAR16 *str, UINT8 hash[SHA256_DIGEST_SIZE]) +{ + int i; + + for (i = 0; i < SHA256_DIGEST_SIZE; i++) { + CHAR16 buf[10]; + + SPrint(buf, sizeof(buf), L"%02x", hash[i]); + StrCat(str, buf); + } +} + EFI_STATUS sha256_get_pecoff_digest(EFI_HANDLE device, CHAR16 *name, uint8 hash[SHA256_DIGEST_SIZE]) { diff --git a/lib/variables.c b/lib/variables.c index e662fde..933a5a8 100644 --- a/lib/variables.c +++ b/lib/variables.c @@ -27,6 +27,7 @@ #include <variables.h> #include <guid.h> #include <console.h> +#include <sha256.h> EFI_STATUS CreatePkX509SignatureList ( @@ -317,3 +318,36 @@ variable_is_secureboot(void) return SecureBoot; } + +EFI_STATUS +variable_enroll_hash(CHAR16 *var, EFI_GUID owner, + UINT8 hash[SHA256_DIGEST_SIZE]) +{ + EFI_STATUS status; + + if (find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE) + == EFI_SUCCESS) + /* hash already present */ + return EFI_ALREADY_STARTED; + + UINT8 sig[sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + SHA256_DIGEST_SIZE]; + EFI_SIGNATURE_LIST *l = (void *)sig; + EFI_SIGNATURE_DATA *d = (void *)sig + sizeof(EFI_SIGNATURE_LIST); + SetMem(sig, 0, sizeof(sig)); + l->SignatureType = EFI_CERT_SHA256_GUID; + l->SignatureListSize = sizeof(sig); + l->SignatureSize = 16 +32; /* UEFI defined */ + CopyMem(&d->SignatureData, hash, SHA256_DIGEST_SIZE); + d->SignatureOwner = MOK_OWNER; + + if (CompareGuid(&owner, &SIG_DB) == 0) + status = SetSecureVariable(var, sig, sizeof(sig), owner, + EFI_VARIABLE_APPEND_WRITE, 0); + else + status = uefi_call_wrapper(RT->SetVariable, 5, var, &owner, + EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_APPEND_WRITE, + sizeof(sig), sig); + return status; +} |