[1/2] securebootcert: add checking read-only for the AuditMode and DeployedMode

Message ID 1515396249-7923-1-git-send-email-ivan.hu@canonical.com
State Accepted
Headers show
Series
  • [1/2] securebootcert: add checking read-only for the AuditMode and DeployedMode
Related show

Commit Message

ivanhu Jan. 8, 2018, 7:24 a.m.
UEFI spec 2.7 add the update of AuditMode and DeplyedMode variable, these two
global variables should be always becomes read-only after ExitBootServices() is
called.

Add the testing read-only by setting variables, no EFI_SUCCESS return is
expected.

Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
---
 src/uefi/securebootcert/securebootcert.c | 131 +++++++++++++++++++++++++++++--
 1 file changed, 124 insertions(+), 7 deletions(-)

Comments

Alex Hung Jan. 9, 2018, 1:34 a.m. | #1
On 2018-01-07 11:24 PM, Ivan Hu wrote:
> UEFI spec 2.7 add the update of AuditMode and DeplyedMode variable, these two
> global variables should be always becomes read-only after ExitBootServices() is
> called.
> 
> Add the testing read-only by setting variables, no EFI_SUCCESS return is
> expected.
> 
> Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
> ---
>   src/uefi/securebootcert/securebootcert.c | 131 +++++++++++++++++++++++++++++--
>   1 file changed, 124 insertions(+), 7 deletions(-)
> 
> diff --git a/src/uefi/securebootcert/securebootcert.c b/src/uefi/securebootcert/securebootcert.c
> index a74c55d..60fc489 100644
> --- a/src/uefi/securebootcert/securebootcert.c
> +++ b/src/uefi/securebootcert/securebootcert.c
> @@ -22,10 +22,16 @@
>   
>   #include <stddef.h>
>   #include <inttypes.h>
> +#include <sys/ioctl.h>
>   
>   #include "fwts_uefi.h"
>   #include "sbkeydefs.h"
>   
> +#include "fwts_efi_runtime.h"
> +#include "fwts_efi_module.h"
> +
> +static int fd;
> +
>   typedef void (*securebootcert_func)(fwts_framework *fw, fwts_uefi_var *var, char *varname);
>   
>   typedef struct {
> @@ -33,13 +39,6 @@ typedef struct {
>   	securebootcert_func	func;	/* Function to dump this variable */
>   } securebootcert_info;
>   
> -typedef struct {
> -	uint32_t	Data1;
> -	uint16_t	Data2;
> -	uint16_t	Data3;
> -	uint8_t		Data4[8];
> -} __attribute__ ((packed)) EFI_GUID;
> -
>   typedef struct _EFI_SIGNATURE_LIST {
>   	EFI_GUID	SignatureType;
>   	uint32_t	SignatureListSize;
> @@ -70,6 +69,11 @@ static uint8_t var_found;
>   static bool securebooted = false;
>   static bool deployed = false;
>   
> +static EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
> +
> +static uint16_t varauditmode[] = {'A', 'u', 'd', 'i', 't', 'M', 'o', 'd', 'e', '\0'};
> +static uint16_t vardeploymode[] = {'D', 'e', 'p', 'l', 'o', 'y', 'e', 'd', 'M', 'o', 'd', 'e', '\0'};
> +
>   static bool compare_guid(EFI_GUID *guid1, uint8_t *guid2)
>   {
>   	bool ident = true;
> @@ -429,6 +433,25 @@ static int securebootcert_init(fwts_framework *fw)
>   		return FWTS_ABORTED;
>   	}
>   
> +	if (fwts_lib_efi_runtime_load_module(fw) != FWTS_OK) {
> +		fwts_log_info(fw, "Cannot load efi_runtime module. Aborted.");
> +		return FWTS_ABORTED;
> +	}
> +
> +	fd = fwts_lib_efi_runtime_open();
> +	if (fd == -1) {
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
> +		return FWTS_ABORTED;
> +	}
> +
> +	return FWTS_OK;
> +}
> +
> +static int securebootcert_deinit(fwts_framework *fw)
> +{
> +	fwts_lib_efi_runtime_close(fd);
> +	fwts_lib_efi_runtime_unload_module(fw);
> +
>   	return FWTS_OK;
>   }
>   
> @@ -492,14 +515,108 @@ static int securebootcert_test1(fwts_framework *fw)
>   	return FWTS_OK;
>   }
>   
> +static int securebootcert_setvar(
> +	fwts_framework *fw,
> +	const uint32_t attributes,
> +	uint16_t *varname,
> +	EFI_GUID *guid,
> +	uint8_t *data)
> +{
> +	long ioret;
> +	struct efi_setvariable setvariable;
> +
> +	uint64_t status;
> +	uint64_t datasize = 1;
> +
> +	setvariable.VariableName = varname;
> +	setvariable.VendorGuid = guid;
> +	setvariable.Attributes = attributes;
> +	setvariable.DataSize = datasize;
> +	setvariable.Data = data;
> +	setvariable.status = &status;
> +	ioret = ioctl(fd, EFI_RUNTIME_SET_VARIABLE, &setvariable);
> +
> +	if (ioret == -1) {
> +		if (status == EFI_OUT_OF_RESOURCES) {
> +			fwts_uefi_print_status_info(fw, status);
> +			fwts_skipped(fw,
> +				"Run out of resources for SetVariable "
> +				"UEFI runtime interface: cannot test.");
> +			fwts_advice(fw,
> +				"Firmware may reclaim some resources "
> +				"after rebooting. Reboot and test "
> +				"again may be helpful to continue "
> +				"the test.");
> +			return FWTS_SKIP;
> +		}
> +	}
> +
> +	if (status == EFI_SUCCESS) {
> +		fwts_failed(fw, LOG_LEVEL_HIGH,
> +			"UEFISecurebooCertVar",
> +			"Variable is ready only, return status of setvariable "
> +			"should not EFI_SUCCESS.");
> +	} else
> +		fwts_passed(fw, "Variable read-only test passed.");
> +	return FWTS_OK;
> +}
> +
> +static int securebootcert_test2(fwts_framework *fw)
> +{
> +	int ret;
> +	uint8_t data = 0;
> +	static uint32_t attributes = FWTS_UEFI_VAR_NON_VOLATILE |
> +					FWTS_UEFI_VAR_BOOTSERVICE_ACCESS |
> +					FWTS_UEFI_VAR_RUNTIME_ACCESS;
> +
> +	if (!(var_found & VAR_AUDITMODE_FOUND)) {
> +		fwts_skipped(fw,
> +			"No AuditMode variable found, skip the varaible test.");
> +		return FWTS_SKIP;
> +	}
> +
> +	fwts_log_info(fw, "AuditMode variable read-only test, set to 0.");
> +	ret = securebootcert_setvar(fw, attributes, varauditmode, &global_guid, &data);
> +	if (ret != FWTS_OK)
> +		return ret;
> +
> +	data = 1;
> +	fwts_log_info(fw, "AuditMode variable read-only test, set to 1.");
> +	ret = securebootcert_setvar(fw, attributes, varauditmode, &global_guid, &data);
> +	if (ret != FWTS_OK)
> +		return ret;
> +
> +	if (!(var_found & VAR_AUDITMODE_FOUND)) {
> +		fwts_skipped(fw,
> +			"No DeployedMode variable found, skip the varaible test.");
> +		return FWTS_SKIP;
> +	}
> +
> +	data = 0;
> +	fwts_log_info(fw, "DeployedMode variable read-only test, set to 0.");
> +	ret = securebootcert_setvar(fw, attributes, vardeploymode, &global_guid, &data);
> +	if (ret != FWTS_OK)
> +		return ret;
> +
> +	data = 1;
> +	fwts_log_info(fw, "DeployedMode variable read-only test, set to 1.");
> +	ret = securebootcert_setvar(fw, attributes, vardeploymode, &global_guid, &data);
> +	if (ret != FWTS_OK)
> +		return ret;
> +
> +	return FWTS_OK;
> +}
> +
>   static fwts_framework_minor_test securebootcert_tests[] = {
>   	{ securebootcert_test1, "UEFI secure boot test." },
> +	{ securebootcert_test2, "UEFI secure boot variable test." },
>   	{ NULL, NULL }
>   };
>   
>   static fwts_framework_ops securebootcert_ops = {
>   	.description = "UEFI secure boot test.",
>   	.init        = securebootcert_init,
> +	.deinit	     = securebootcert_deinit,
>   	.minor_tests = securebootcert_tests
>   };
>   
> 

Acked-by: Alex Hung <alex.hung@canonical.com>
Colin Ian King Jan. 16, 2018, 2:33 p.m. | #2
On 08/01/18 07:24, Ivan Hu wrote:
> UEFI spec 2.7 add the update of AuditMode and DeplyedMode variable, these two
> global variables should be always becomes read-only after ExitBootServices() is
> called.
> 
> Add the testing read-only by setting variables, no EFI_SUCCESS return is
> expected.
> 
> Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
> ---
>  src/uefi/securebootcert/securebootcert.c | 131 +++++++++++++++++++++++++++++--
>  1 file changed, 124 insertions(+), 7 deletions(-)
> 
> diff --git a/src/uefi/securebootcert/securebootcert.c b/src/uefi/securebootcert/securebootcert.c
> index a74c55d..60fc489 100644
> --- a/src/uefi/securebootcert/securebootcert.c
> +++ b/src/uefi/securebootcert/securebootcert.c
> @@ -22,10 +22,16 @@
>  
>  #include <stddef.h>
>  #include <inttypes.h>
> +#include <sys/ioctl.h>
>  
>  #include "fwts_uefi.h"
>  #include "sbkeydefs.h"
>  
> +#include "fwts_efi_runtime.h"
> +#include "fwts_efi_module.h"
> +
> +static int fd;
> +
>  typedef void (*securebootcert_func)(fwts_framework *fw, fwts_uefi_var *var, char *varname);
>  
>  typedef struct {
> @@ -33,13 +39,6 @@ typedef struct {
>  	securebootcert_func	func;	/* Function to dump this variable */
>  } securebootcert_info;
>  
> -typedef struct {
> -	uint32_t	Data1;
> -	uint16_t	Data2;
> -	uint16_t	Data3;
> -	uint8_t		Data4[8];
> -} __attribute__ ((packed)) EFI_GUID;
> -
>  typedef struct _EFI_SIGNATURE_LIST {
>  	EFI_GUID	SignatureType;
>  	uint32_t	SignatureListSize;
> @@ -70,6 +69,11 @@ static uint8_t var_found;
>  static bool securebooted = false;
>  static bool deployed = false;
>  
> +static EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
> +
> +static uint16_t varauditmode[] = {'A', 'u', 'd', 'i', 't', 'M', 'o', 'd', 'e', '\0'};
> +static uint16_t vardeploymode[] = {'D', 'e', 'p', 'l', 'o', 'y', 'e', 'd', 'M', 'o', 'd', 'e', '\0'};
> +
>  static bool compare_guid(EFI_GUID *guid1, uint8_t *guid2)
>  {
>  	bool ident = true;
> @@ -429,6 +433,25 @@ static int securebootcert_init(fwts_framework *fw)
>  		return FWTS_ABORTED;
>  	}
>  
> +	if (fwts_lib_efi_runtime_load_module(fw) != FWTS_OK) {
> +		fwts_log_info(fw, "Cannot load efi_runtime module. Aborted.");
> +		return FWTS_ABORTED;
> +	}
> +
> +	fd = fwts_lib_efi_runtime_open();
> +	if (fd == -1) {
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
> +		return FWTS_ABORTED;
> +	}
> +
> +	return FWTS_OK;
> +}
> +
> +static int securebootcert_deinit(fwts_framework *fw)
> +{
> +	fwts_lib_efi_runtime_close(fd);
> +	fwts_lib_efi_runtime_unload_module(fw);
> +
>  	return FWTS_OK;
>  }
>  
> @@ -492,14 +515,108 @@ static int securebootcert_test1(fwts_framework *fw)
>  	return FWTS_OK;
>  }
>  
> +static int securebootcert_setvar(
> +	fwts_framework *fw,
> +	const uint32_t attributes,
> +	uint16_t *varname,
> +	EFI_GUID *guid,
> +	uint8_t *data)
> +{
> +	long ioret;
> +	struct efi_setvariable setvariable;
> +
> +	uint64_t status;
> +	uint64_t datasize = 1;
> +
> +	setvariable.VariableName = varname;
> +	setvariable.VendorGuid = guid;
> +	setvariable.Attributes = attributes;
> +	setvariable.DataSize = datasize;
> +	setvariable.Data = data;
> +	setvariable.status = &status;
> +	ioret = ioctl(fd, EFI_RUNTIME_SET_VARIABLE, &setvariable);
> +
> +	if (ioret == -1) {
> +		if (status == EFI_OUT_OF_RESOURCES) {
> +			fwts_uefi_print_status_info(fw, status);
> +			fwts_skipped(fw,
> +				"Run out of resources for SetVariable "
> +				"UEFI runtime interface: cannot test.");
> +			fwts_advice(fw,
> +				"Firmware may reclaim some resources "
> +				"after rebooting. Reboot and test "
> +				"again may be helpful to continue "
> +				"the test.");
> +			return FWTS_SKIP;
> +		}
> +	}
> +
> +	if (status == EFI_SUCCESS) {
> +		fwts_failed(fw, LOG_LEVEL_HIGH,
> +			"UEFISecurebooCertVar",
> +			"Variable is ready only, return status of setvariable "
> +			"should not EFI_SUCCESS.");
> +	} else
> +		fwts_passed(fw, "Variable read-only test passed.");
> +	return FWTS_OK;
> +}
> +
> +static int securebootcert_test2(fwts_framework *fw)
> +{
> +	int ret;
> +	uint8_t data = 0;
> +	static uint32_t attributes = FWTS_UEFI_VAR_NON_VOLATILE |
> +					FWTS_UEFI_VAR_BOOTSERVICE_ACCESS |
> +					FWTS_UEFI_VAR_RUNTIME_ACCESS;
> +
> +	if (!(var_found & VAR_AUDITMODE_FOUND)) {
> +		fwts_skipped(fw,
> +			"No AuditMode variable found, skip the varaible test.");
> +		return FWTS_SKIP;
> +	}
> +
> +	fwts_log_info(fw, "AuditMode variable read-only test, set to 0.");
> +	ret = securebootcert_setvar(fw, attributes, varauditmode, &global_guid, &data);
> +	if (ret != FWTS_OK)
> +		return ret;
> +
> +	data = 1;
> +	fwts_log_info(fw, "AuditMode variable read-only test, set to 1.");
> +	ret = securebootcert_setvar(fw, attributes, varauditmode, &global_guid, &data);
> +	if (ret != FWTS_OK)
> +		return ret;
> +
> +	if (!(var_found & VAR_AUDITMODE_FOUND)) {
> +		fwts_skipped(fw,
> +			"No DeployedMode variable found, skip the varaible test.");
> +		return FWTS_SKIP;
> +	}
> +
> +	data = 0;
> +	fwts_log_info(fw, "DeployedMode variable read-only test, set to 0.");
> +	ret = securebootcert_setvar(fw, attributes, vardeploymode, &global_guid, &data);
> +	if (ret != FWTS_OK)
> +		return ret;
> +
> +	data = 1;
> +	fwts_log_info(fw, "DeployedMode variable read-only test, set to 1.");
> +	ret = securebootcert_setvar(fw, attributes, vardeploymode, &global_guid, &data);
> +	if (ret != FWTS_OK)
> +		return ret;
> +
> +	return FWTS_OK;
> +}
> +
>  static fwts_framework_minor_test securebootcert_tests[] = {
>  	{ securebootcert_test1, "UEFI secure boot test." },
> +	{ securebootcert_test2, "UEFI secure boot variable test." },
>  	{ NULL, NULL }
>  };
>  
>  static fwts_framework_ops securebootcert_ops = {
>  	.description = "UEFI secure boot test.",
>  	.init        = securebootcert_init,
> +	.deinit	     = securebootcert_deinit,
>  	.minor_tests = securebootcert_tests
>  };
>  
> 
Acked-by: Colin Ian King <colin.king@canonical.com>

Patch

diff --git a/src/uefi/securebootcert/securebootcert.c b/src/uefi/securebootcert/securebootcert.c
index a74c55d..60fc489 100644
--- a/src/uefi/securebootcert/securebootcert.c
+++ b/src/uefi/securebootcert/securebootcert.c
@@ -22,10 +22,16 @@ 
 
 #include <stddef.h>
 #include <inttypes.h>
+#include <sys/ioctl.h>
 
 #include "fwts_uefi.h"
 #include "sbkeydefs.h"
 
+#include "fwts_efi_runtime.h"
+#include "fwts_efi_module.h"
+
+static int fd;
+
 typedef void (*securebootcert_func)(fwts_framework *fw, fwts_uefi_var *var, char *varname);
 
 typedef struct {
@@ -33,13 +39,6 @@  typedef struct {
 	securebootcert_func	func;	/* Function to dump this variable */
 } securebootcert_info;
 
-typedef struct {
-	uint32_t	Data1;
-	uint16_t	Data2;
-	uint16_t	Data3;
-	uint8_t		Data4[8];
-} __attribute__ ((packed)) EFI_GUID;
-
 typedef struct _EFI_SIGNATURE_LIST {
 	EFI_GUID	SignatureType;
 	uint32_t	SignatureListSize;
@@ -70,6 +69,11 @@  static uint8_t var_found;
 static bool securebooted = false;
 static bool deployed = false;
 
+static EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
+
+static uint16_t varauditmode[] = {'A', 'u', 'd', 'i', 't', 'M', 'o', 'd', 'e', '\0'};
+static uint16_t vardeploymode[] = {'D', 'e', 'p', 'l', 'o', 'y', 'e', 'd', 'M', 'o', 'd', 'e', '\0'};
+
 static bool compare_guid(EFI_GUID *guid1, uint8_t *guid2)
 {
 	bool ident = true;
@@ -429,6 +433,25 @@  static int securebootcert_init(fwts_framework *fw)
 		return FWTS_ABORTED;
 	}
 
+	if (fwts_lib_efi_runtime_load_module(fw) != FWTS_OK) {
+		fwts_log_info(fw, "Cannot load efi_runtime module. Aborted.");
+		return FWTS_ABORTED;
+	}
+
+	fd = fwts_lib_efi_runtime_open();
+	if (fd == -1) {
+		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
+		return FWTS_ABORTED;
+	}
+
+	return FWTS_OK;
+}
+
+static int securebootcert_deinit(fwts_framework *fw)
+{
+	fwts_lib_efi_runtime_close(fd);
+	fwts_lib_efi_runtime_unload_module(fw);
+
 	return FWTS_OK;
 }
 
@@ -492,14 +515,108 @@  static int securebootcert_test1(fwts_framework *fw)
 	return FWTS_OK;
 }
 
+static int securebootcert_setvar(
+	fwts_framework *fw,
+	const uint32_t attributes,
+	uint16_t *varname,
+	EFI_GUID *guid,
+	uint8_t *data)
+{
+	long ioret;
+	struct efi_setvariable setvariable;
+
+	uint64_t status;
+	uint64_t datasize = 1;
+
+	setvariable.VariableName = varname;
+	setvariable.VendorGuid = guid;
+	setvariable.Attributes = attributes;
+	setvariable.DataSize = datasize;
+	setvariable.Data = data;
+	setvariable.status = &status;
+	ioret = ioctl(fd, EFI_RUNTIME_SET_VARIABLE, &setvariable);
+
+	if (ioret == -1) {
+		if (status == EFI_OUT_OF_RESOURCES) {
+			fwts_uefi_print_status_info(fw, status);
+			fwts_skipped(fw,
+				"Run out of resources for SetVariable "
+				"UEFI runtime interface: cannot test.");
+			fwts_advice(fw,
+				"Firmware may reclaim some resources "
+				"after rebooting. Reboot and test "
+				"again may be helpful to continue "
+				"the test.");
+			return FWTS_SKIP;
+		}
+	}
+
+	if (status == EFI_SUCCESS) {
+		fwts_failed(fw, LOG_LEVEL_HIGH,
+			"UEFISecurebooCertVar",
+			"Variable is ready only, return status of setvariable "
+			"should not EFI_SUCCESS.");
+	} else
+		fwts_passed(fw, "Variable read-only test passed.");
+	return FWTS_OK;
+}
+
+static int securebootcert_test2(fwts_framework *fw)
+{
+	int ret;
+	uint8_t data = 0;
+	static uint32_t attributes = FWTS_UEFI_VAR_NON_VOLATILE |
+					FWTS_UEFI_VAR_BOOTSERVICE_ACCESS |
+					FWTS_UEFI_VAR_RUNTIME_ACCESS;
+
+	if (!(var_found & VAR_AUDITMODE_FOUND)) {
+		fwts_skipped(fw,
+			"No AuditMode variable found, skip the varaible test.");
+		return FWTS_SKIP;
+	}
+
+	fwts_log_info(fw, "AuditMode variable read-only test, set to 0.");
+	ret = securebootcert_setvar(fw, attributes, varauditmode, &global_guid, &data);
+	if (ret != FWTS_OK)
+		return ret;
+
+	data = 1;
+	fwts_log_info(fw, "AuditMode variable read-only test, set to 1.");
+	ret = securebootcert_setvar(fw, attributes, varauditmode, &global_guid, &data);
+	if (ret != FWTS_OK)
+		return ret;
+
+	if (!(var_found & VAR_AUDITMODE_FOUND)) {
+		fwts_skipped(fw,
+			"No DeployedMode variable found, skip the varaible test.");
+		return FWTS_SKIP;
+	}
+
+	data = 0;
+	fwts_log_info(fw, "DeployedMode variable read-only test, set to 0.");
+	ret = securebootcert_setvar(fw, attributes, vardeploymode, &global_guid, &data);
+	if (ret != FWTS_OK)
+		return ret;
+
+	data = 1;
+	fwts_log_info(fw, "DeployedMode variable read-only test, set to 1.");
+	ret = securebootcert_setvar(fw, attributes, vardeploymode, &global_guid, &data);
+	if (ret != FWTS_OK)
+		return ret;
+
+	return FWTS_OK;
+}
+
 static fwts_framework_minor_test securebootcert_tests[] = {
 	{ securebootcert_test1, "UEFI secure boot test." },
+	{ securebootcert_test2, "UEFI secure boot variable test." },
 	{ NULL, NULL }
 };
 
 static fwts_framework_ops securebootcert_ops = {
 	.description = "UEFI secure boot test.",
 	.init        = securebootcert_init,
+	.deinit	     = securebootcert_deinit,
 	.minor_tests = securebootcert_tests
 };