diff mbox series

[U-Boot,RFC,09/15] efi_loader: variable: add VendorKeys and SignatureSupport variables

Message ID 20190918012643.25192-10-takahiro.akashi@linaro.org
State RFC
Delegated to: Heinrich Schuchardt
Headers show
Series efi_loader: add secure boot support | expand

Commit Message

AKASHI Takahiro Sept. 18, 2019, 1:26 a.m. UTC
Those two variables are well defined UEFI variables:
SignatureSupport: array of GUIDs representing the type of signatures
		  supported by the platform firmware
VendorKeys: whether the system is configured to use only vendor-provided
	    keys or not

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_loader/efi_variable.c | 85 ++++++++++++++++++++++++++++++++---
 1 file changed, 79 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index fa706f1ad6b8..9b7654bde017 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -28,8 +28,14 @@  enum efi_secure_mode {
 	EFI_MODE_DEPLOYED,
 };
 
+static const efi_guid_t signature_types[] = {
+	/* EFI_CERT_SHA256_GUID, */
+	EFI_CERT_X509_GUID,
+};
 const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
 static bool efi_secure_boot;
+static int efi_secure_mode;
+static u8 efi_vendor_keys;
 
 #define READ_ONLY BIT(31)
 
@@ -337,6 +343,8 @@  static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
 		return EFI_INVALID_PARAMETER;
 	}
 
+	efi_secure_mode = mode;
+
 	return EFI_SUCCESS;
 
 err:
@@ -347,16 +355,57 @@  err:
 
 efi_status_t efi_init_secure_boot(void)
 {
-	efi_uintn_t size = 0;
+	enum efi_secure_mode mode;
+	efi_uintn_t size;
 	efi_status_t ret;
 
+	ret = efi_set_variable_internal(L"SignatureSupport",
+					&efi_global_variable_guid,
+					EFI_VARIABLE_BOOTSERVICE_ACCESS
+					 | EFI_VARIABLE_RUNTIME_ACCESS
+					 | READ_ONLY,
+					sizeof(signature_types),
+					&signature_types,
+					false);
+	if (ret != EFI_SUCCESS)
+		goto err;
+
+	/*
+	 * TODO:
+	 * Since there is currently no "platform-specific" installation
+	 * method of Platform Key, we can't say if VendorKeys is 0 or 1
+	 * precisely.
+	 */
+
+	size = 0;
 	ret = EFI_CALL(efi_get_variable(L"PK", &efi_global_variable_guid,
 					NULL, &size, NULL));
-	if (ret == EFI_BUFFER_TOO_SMALL && IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
-		ret = efi_transfer_secure_state(EFI_MODE_USER);
-	else
-		ret = efi_transfer_secure_state(EFI_MODE_SETUP);
+	if (ret == EFI_BUFFER_TOO_SMALL) {
+		if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
+			mode = EFI_MODE_USER;
+		else
+			mode = EFI_MODE_SETUP;
+
+		efi_vendor_keys = 0;
+	} else if (ret == EFI_NOT_FOUND) {
+		mode = EFI_MODE_SETUP;
+		efi_vendor_keys = 1;
+	} else {
+		goto err;
+	}
 
+	ret = efi_transfer_secure_state(mode);
+	if (ret == EFI_SUCCESS)
+		ret = efi_set_variable_internal(L"VendorKeys",
+						&efi_global_variable_guid,
+						EFI_VARIABLE_BOOTSERVICE_ACCESS
+						 | EFI_VARIABLE_RUNTIME_ACCESS
+						 | READ_ONLY,
+						sizeof(efi_vendor_keys),
+						&efi_vendor_keys,
+						false);
+
+err:
 	return ret;
 }
 
@@ -1086,6 +1135,8 @@  out:
 	if (env_set(native_name, val)) {
 		ret = EFI_DEVICE_ERROR;
 	} else {
+		bool vendor_keys_modified = false;
+
 		if ((u16_strcmp(variable_name, L"PK") == 0 &&
 		     guidcmp(vendor, &efi_global_variable_guid) == 0)) {
 			ret = efi_transfer_secure_state(
@@ -1093,8 +1144,30 @@  out:
 						  EFI_MODE_USER));
 			if (ret != EFI_SUCCESS)
 				goto err;
+
+			if (efi_secure_mode != EFI_MODE_SETUP)
+				vendor_keys_modified = true;
+		} else if ((u16_strcmp(variable_name, L"KEK") == 0 &&
+		     guidcmp(vendor, &efi_global_variable_guid) == 0)) {
+			if (efi_secure_mode != EFI_MODE_SETUP)
+				vendor_keys_modified = true;
+		}
+
+		/* update VendorKeys */
+		if (vendor_keys_modified & efi_vendor_keys) {
+			efi_vendor_keys = 0;
+			ret = efi_set_variable_internal(
+						L"VendorKeys",
+						&efi_global_variable_guid,
+						EFI_VARIABLE_BOOTSERVICE_ACCESS
+						 | EFI_VARIABLE_RUNTIME_ACCESS
+						 | READ_ONLY,
+						sizeof(efi_vendor_keys),
+						&efi_vendor_keys,
+						false);
+		} else {
+			ret = EFI_SUCCESS;
 		}
-		ret = EFI_SUCCESS;
 	}
 
 err: