aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <JBottomley@Parallels.com>2012-12-11 13:51:05 +0000
committerJames Bottomley <JBottomley@Parallels.com>2012-12-11 13:51:05 +0000
commit456d3e5656d853115101cd3f0c26519cf2124c75 (patch)
tree433e6140cba1922ff2c0a255d88cfc1659f81a0a
parentaf3d3d5724e0c977e0183917d5ecdb87d2f3b17a (diff)
downloadefitools-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.c39
-rw-r--r--KeyTool.c138
-rw-r--r--include/sha256.h2
-rw-r--r--include/variables.h5
-rw-r--r--lib/sha256.c13
-rw-r--r--lib/variables.c34
6 files changed, 168 insertions, 63 deletions
diff --git a/HashTool.c b/HashTool.c
index 2ca16c1..780f6a9 100644
--- a/HashTool.c
+++ b/HashTool.c
@@ -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;
diff --git a/KeyTool.c b/KeyTool.c
index beb496c..d058652 100644
--- a/KeyTool.c
+++ b/KeyTool.c
@@ -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;
+}