From 99bfab8b5832273d66d724f906be43fe5bd7c1ba Mon Sep 17 00:00:00 2001
From: Heinrich Schuchardt <xypron.glpk@gmx.de>
Date: Wed, 15 Jul 2020 12:40:35 +0200
Subject: [PATCH] efi_loader: identify PK, KEK, db, dbx correctly

To determine if a varible is on the of the authentication variables
PK, KEK, db, dbx we have to check both the name and the GUID.

Provide a function converting the variable-name/guid pair to an enum and
use it consistently.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 include/efi_variable.h          | 19 +++++++++++++++++++
 lib/efi_loader/efi_var_common.c | 27 +++++++++++++++++++++++++++
 lib/efi_loader/efi_variable.c   | 27 ++++++++++++++-------------
 3 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/include/efi_variable.h b/include/efi_variable.h
index 5eec407a2b..021a74f309 100644
--- a/include/efi_variable.h
+++ b/include/efi_variable.h
@@ -10,6 +10,16 @@
 
 #define EFI_VARIABLE_READ_ONLY BIT(31)
 
+enum efi_auth_var_type {
+	EFI_AUTH_VAR_NONE = 0,
+	EFI_AUTH_VAR_PK,
+	EFI_AUTH_VAR_KEK,
+	EFI_AUTH_VAR_DB,
+	EFI_AUTH_VAR_DBX,
+	EFI_AUTH_VAR_DBT,
+	EFI_AUTH_VAR_DBR,
+};
+
 /**
  * efi_get_variable() - retrieve value of a UEFI variable
  *
@@ -202,4 +212,13 @@ u64 efi_var_mem_free(void);
  */
 efi_status_t efi_init_secure_state(void);
 
+/**
+ * efi_auth_var_get_type() - convert variable name and guid to enum
+ *
+ * @name:	name of UEFI variable
+ * @guid:	guid of UEFI variable
+ * Return:	identifier for authentication related variables
+ */
+enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid);
+
 #endif
diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c
index 36e31b4d45..ee2e67bc8c 100644
--- a/lib/efi_loader/efi_var_common.c
+++ b/lib/efi_loader/efi_var_common.c
@@ -16,6 +16,23 @@ enum efi_secure_mode {
 	EFI_MODE_DEPLOYED,
 };
 
+struct efi_auth_var_name_type {
+	const u16 *name;
+	const efi_guid_t *guid;
+	const enum efi_auth_var_type type;
+};
+
+static const struct efi_auth_var_name_type name_type[] = {
+	{u"PK", &efi_global_variable_guid, EFI_AUTH_VAR_PK},
+	{u"KEK", &efi_global_variable_guid, EFI_AUTH_VAR_KEK},
+	{u"db",  &efi_guid_image_security_database, EFI_AUTH_VAR_DB},
+	{u"dbx",  &efi_guid_image_security_database, EFI_AUTH_VAR_DBX},
+	/* not used yet
+	{u"dbt",  &efi_guid_image_security_database, EFI_AUTH_VAR_DBT},
+	{u"dbr",  &efi_guid_image_security_database, EFI_AUTH_VAR_DBR},
+	*/
+};
+
 static bool efi_secure_boot;
 static enum efi_secure_mode efi_secure_mode;
 
@@ -293,3 +310,13 @@ bool efi_secure_boot_enabled(void)
 {
 	return efi_secure_boot;
 }
+
+enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
+		if (!u16_strcmp(name, name_type[i].name) &&
+		    !guidcmp(guid, name_type[i].guid))
+			return name_type[i].type;
+	}
+	return EFI_AUTH_VAR_NONE;
+}
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index 64dc3d6df9..ecbc4f7f54 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -133,6 +133,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
 	struct efi_time timestamp;
 	struct rtc_time tm;
 	u64 new_time;
+	enum efi_auth_var_type var_type;
 	efi_status_t ret;
 
 	var_sig = NULL;
@@ -209,18 +210,20 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
 	}
 
 	/* signature database used for authentication */
-	if (u16_strcmp(variable, L"PK") == 0 ||
-	    u16_strcmp(variable, L"KEK") == 0) {
+	var_type = efi_auth_var_get_type(variable, vendor);
+	switch (var_type) {
+	case EFI_AUTH_VAR_PK:
+	case EFI_AUTH_VAR_KEK:
 		/* with PK */
 		truststore = efi_sigstore_parse_sigdb(L"PK");
 		if (!truststore)
 			goto err;
-	} else if (u16_strcmp(variable, L"db") == 0 ||
-		   u16_strcmp(variable, L"dbx") == 0) {
+		break;
+	case EFI_AUTH_VAR_DB:
+	case EFI_AUTH_VAR_DBX:
 		/* with PK and KEK */
 		truststore = efi_sigstore_parse_sigdb(L"KEK");
 		truststore2 = efi_sigstore_parse_sigdb(L"PK");
-
 		if (!truststore) {
 			if (!truststore2)
 				goto err;
@@ -228,7 +231,8 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
 			truststore = truststore2;
 			truststore2 = NULL;
 		}
-	} else {
+		break;
+	default:
 		/* TODO: support private authenticated variables */
 		goto err;
 	}
@@ -347,6 +351,7 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
 	efi_uintn_t ret;
 	bool append, delete;
 	u64 time = 0;
+	enum efi_auth_var_type var_type;
 
 	if (!variable_name || !*variable_name || !vendor ||
 	    ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
@@ -381,12 +386,8 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
 			return EFI_NOT_FOUND;
 	}
 
-	if (((!u16_strcmp(variable_name, L"PK") ||
-	      !u16_strcmp(variable_name, L"KEK")) &&
-		!guidcmp(vendor, &efi_global_variable_guid)) ||
-	    ((!u16_strcmp(variable_name, L"db") ||
-	      !u16_strcmp(variable_name, L"dbx")) &&
-		!guidcmp(vendor, &efi_guid_image_security_database))) {
+	var_type = efi_auth_var_get_type(variable_name, vendor);
+	if (var_type != EFI_AUTH_VAR_NONE) {
 		/* authentication is mandatory */
 		if (!(attributes &
 		      EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
@@ -445,7 +446,7 @@ efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
 	if (ret != EFI_SUCCESS)
 		return ret;
 
-	if (!u16_strcmp(variable_name, L"PK"))
+	if (var_type == EFI_AUTH_VAR_PK)
 		ret = efi_init_secure_state();
 	else
 		ret = EFI_SUCCESS;
-- 
2.39.5