diff mbox series

[3/4] test: firmwware: add signature test to driver_data loader test

Message ID 20170526030609.1414-4-takahiro.akashi@linaro.org
State New
Headers show
Series firmware: signature verification | expand

Commit Message

AKASHI Takahiro May 26, 2017, 3:06 a.m. UTC
Add the following tests:
No.15 - verify loaded data witha signature
No.16 - verify loaded data witha signature under signature enforcing

For each test, there are several test cases:
* no signature provided
* valid signature provided
* invalid signature provided

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Cc: Luis R. Rodriguez <mcgrof@suse.com>
---
 lib/test_driver_data.c                          |  56 ++++-
 tools/testing/selftests/firmware/driver_data.sh | 265 +++++++++++++++++++++++-
 2 files changed, 315 insertions(+), 6 deletions(-)

-- 
2.11.1
diff mbox series

Patch

diff --git a/lib/test_driver_data.c b/lib/test_driver_data.c
index 422ea6289396..660cf9ff9ac0 100644
--- a/lib/test_driver_data.c
+++ b/lib/test_driver_data.c
@@ -85,6 +85,9 @@  int num_test_devs;
  * @api_min: API min version to use for the test.
  * @api_max: API max version to use for the test.
  * @api_name_postfix: API name postfix
+ * @no_sig_check: whether or not we wish to verify the driver_data with its
+ *      signature. If CONFIG_FIRMWARE_SIG_ENFORCE, passing the verification
+ *      is mandatory.
  * @test_result: a test may use this to collect the result from the call
  *	of the driver_data_request_async() or driver_data_request_sync() calls
  *	used in their tests. Note that for async calls this typically will be a
@@ -125,6 +128,7 @@  struct test_config {
 	u8 api_min;
 	u8 api_max;
 	char *api_name_postfix;
+	bool no_sig_check;
 
 	int test_result;
 };
@@ -345,6 +349,9 @@  static ssize_t config_show(struct device *dev,
 	len += snprintf(buf+len, PAGE_SIZE,
 			"keep:\t\t%s\n",
 			config->keep ? "true" : "false");
+	len += snprintf(buf+len, PAGE_SIZE,
+			"no_sig_check:\t%s\n",
+			config->no_sig_check ? "true" : "false");
 
 	mutex_unlock(&test_dev->config_mutex);
 
@@ -443,6 +450,9 @@  static int config_sync_req_cb(void *context,
 {
 	struct driver_data_test_device *test_dev = context;
 
+	if (unused_error)
+		return unused_error;
+
 	return config_load_data(test_dev, driver_data);
 }
 
@@ -455,14 +465,19 @@  static int trigger_config_sync(struct driver_data_test_device *test_dev)
 					      (config->optional ?
 					       DRIVER_DATA_REQ_OPTIONAL : 0) |
 					      (config->keep ?
-					       DRIVER_DATA_REQ_KEEP : 0)),
+					       DRIVER_DATA_REQ_KEEP : 0) |
+					      (config->no_sig_check ?
+					       DRIVER_DATA_REQ_NO_SIG_CHECK :
+					       0)),
 	};
 	const struct driver_data_req_params req_params_opt_cb = {
 		DRIVER_DATA_DEFAULT_SYNC(config_sync_req_cb, test_dev),
 		DRIVER_DATA_SYNC_OPT_CB(config_sync_req_default_cb,
 					     test_dev),
 		.reqs = (config->optional ? DRIVER_DATA_REQ_OPTIONAL : 0) |
-			(config->keep ? DRIVER_DATA_REQ_KEEP : 0),
+			(config->keep ? DRIVER_DATA_REQ_KEEP : 0) |
+			(config->no_sig_check ? DRIVER_DATA_REQ_NO_SIG_CHECK :
+						0),
 	};
 	const struct driver_data_req_params *req_params;
 
@@ -528,20 +543,26 @@  static int trigger_config_async(struct driver_data_test_device *test_dev)
 	const struct driver_data_req_params req_params_default = {
 		DRIVER_DATA_DEFAULT_ASYNC(config_async_req_cb, test_dev),
 		.reqs = (config->optional ? DRIVER_DATA_REQ_OPTIONAL : 0) |
-			(config->keep ? DRIVER_DATA_REQ_KEEP : 0),
+			(config->keep ? DRIVER_DATA_REQ_KEEP : 0) |
+			(config->no_sig_check ? DRIVER_DATA_REQ_NO_SIG_CHECK :
+						0),
 	};
 	const struct driver_data_req_params req_params_opt_cb = {
 		DRIVER_DATA_DEFAULT_ASYNC(config_async_req_cb, test_dev),
 		DRIVER_DATA_ASYNC_OPT_CB(config_async_req_default_cb, test_dev),
 		.reqs = (config->optional ? DRIVER_DATA_REQ_OPTIONAL : 0) |
-			(config->keep ? DRIVER_DATA_REQ_KEEP : 0),
+			(config->keep ? DRIVER_DATA_REQ_KEEP : 0) |
+			(config->no_sig_check ? DRIVER_DATA_REQ_NO_SIG_CHECK :
+						0),
 	};
 	const struct driver_data_req_params req_params_api = {
 		DRIVER_DATA_API_CB(config_async_req_api_cb, test_dev),
 		DRIVER_DATA_API(config->api_min, config->api_max, config->api_name_postfix),
 		.reqs = (config->optional ? DRIVER_DATA_REQ_OPTIONAL : 0) |
 			(config->keep ? DRIVER_DATA_REQ_KEEP : 0) |
-			(config->use_api_versioning ? DRIVER_DATA_REQ_USE_API_VERSIONING : 0),
+			(config->use_api_versioning ? DRIVER_DATA_REQ_USE_API_VERSIONING : 0) |
+			(config->no_sig_check ? DRIVER_DATA_REQ_NO_SIG_CHECK :
+						0),
 	};
 	const struct driver_data_req_params *req_params;
 
@@ -670,6 +691,7 @@  static int __driver_data_config_init(struct test_config *config)
 	config->use_api_versioning = false;
 	config->api_min = 0;
 	config->api_max = 0;
+	config->no_sig_check = false;
 	config->test_result = 0;
 
 	return 0;
@@ -1108,6 +1130,29 @@  static ssize_t config_api_name_postfix_show(struct device *dev,
 static DEVICE_ATTR(config_api_name_postfix, 0644, config_api_name_postfix_show,
 		   config_api_name_postfix_store);
 
+static ssize_t config_no_sig_check_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	struct driver_data_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return test_dev_config_update_bool(test_dev, buf, count,
+					   &config->no_sig_check);
+}
+
+static ssize_t config_no_sig_check_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct driver_data_test_device *test_dev = dev_to_test_dev(dev);
+	struct test_config *config = &test_dev->config;
+
+	return test_dev_config_show_bool(test_dev, buf, config->no_sig_check);
+}
+static DEVICE_ATTR(config_no_sig_check, 0644, config_no_sig_check_show,
+		   config_no_sig_check_store);
+
 static ssize_t test_result_store(struct device *dev,
 				 struct device_attribute *attr,
 				 const char *buf, size_t count)
@@ -1147,6 +1192,7 @@  static struct attribute *test_dev_attrs[] = {
 	TEST_DRIVER_DATA_DEV_ATTR(config_api_min),
 	TEST_DRIVER_DATA_DEV_ATTR(config_api_max),
 	TEST_DRIVER_DATA_DEV_ATTR(config_api_name_postfix),
+	TEST_DRIVER_DATA_DEV_ATTR(config_no_sig_check),
 	TEST_DRIVER_DATA_DEV_ATTR(test_result),
 
 	NULL,
diff --git a/tools/testing/selftests/firmware/driver_data.sh b/tools/testing/selftests/firmware/driver_data.sh
index bfd0436cce47..f9c52a87b9d0 100755
--- a/tools/testing/selftests/firmware/driver_data.sh
+++ b/tools/testing/selftests/firmware/driver_data.sh
@@ -54,6 +54,10 @@  ALL_TESTS="$ALL_TESTS 0013:1:1"
 # system_wakeupakeup | socat - /dev/pts/7,raw,echo=0,crnl
 #ALL_TESTS="$ALL_TESTS 0014:0:1"
 
+# Before running these tests, we must prepare an appropriate signature.
+#ALL_TESTS="$ALL_TESTS 0015:1:1"
+#ALL_TESTS="$ALL_TESTS 0016:1:1"
+
 test_modprobe()
 {
        if [ ! -d $DIR ]; then
@@ -100,6 +104,10 @@  function allow_user_defaults()
 
 	# This is an unlikely real-world firmware content. :)
 	echo "ABCD0123" >"$FW"
+
+	# TODO: some set-up is necessary in advance
+	cp ${TEST_DIR}/fwbin/*sig*-*.bin ${FWPATH}
+	cp ${TEST_DIR}/fwbin/*sig*-*.bin.p7s ${FWPATH}
 }
 
 test_reqs()
@@ -133,7 +141,7 @@  test_finish()
 {
 	echo -n "$OLD_PATH" >/sys/module/firmware_class/parameters/path
 	rm -f "$FW"
-	rmdir "$FWPATH"
+	rm -rf "$FWPATH"
 }
 
 errno_name_to_val()
@@ -147,6 +155,12 @@  errno_name_to_val()
 		echo -2;;
 	-EINVAL)
 		echo -22;;
+	-EBADMSG)
+		echo -74;;
+	-ENOKEY)
+		echo -126;;
+	-EKEYREJECTED)
+		echo -129;;
 	-ERR_ANY)
 		echo -123456;;
 	*)
@@ -164,12 +178,37 @@  errno_val_to_name()
 		echo -ENOENT;;
 	-22)
 		echo -EINVAL;;
+	-74)
+		echo -EBADMSG;;
+	-126)
+		echo -ENOKEY;;
+	-129)
+		echo -EKEYREJECTED;;
 	-123456)
 		echo -ERR_ANY;;
 	*)
 		echo invalid;;
 	esac
 
+is_not_sig_enforced()
+{
+	if [ "Y" == \
+		$(cat /sys/module/firmware_class/parameters/fw_sig_enforce) ]
+	then
+		echo "$0: Signature enforced. Cannot run this test." >&2
+		exit 1
+	fi
+}
+
+enforce_sig_check()
+{
+	if ! echo -n 1 >/sys/module/firmware_class/parameters/fw_sig_enforce
+	then
+		echo "$0: Unable to set to fw_sig_enforce" >&2
+		exit 1
+	fi
+}
+
 config_set_async()
 {
 	if ! echo -n 1 >$DIR/config_async ; then
@@ -202,6 +241,22 @@  config_disable_optional()
 	fi
 }
 
+config_set_sig_check()
+{
+	if ! echo -n 0 >$DIR/config_no_sig_check ; then
+		echo "$0: Unable to set to sig_check" >&2
+		exit 1
+	fi
+}
+
+config_disable_sig_check()
+{
+	if ! echo -n 1 >$DIR/config_no_sig_check ; then
+		echo "$0: Unable to disable sig_check" >&2
+		exit 1
+	fi
+}
+
 config_set_keep()
 {
 	if ! echo -n 1 >$DIR/config_keep; then
@@ -820,6 +875,212 @@  driver_data_test_0014()
 	driver_data_test_0014a
 }
 
+# no signature provided, with driver not requiring it
+driver_data_test_0015_1_1()
+{
+	NAME=nosig-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_disable_sig_check
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+# good signature, with driver not requiring it
+driver_data_test_0015_1_2()
+{
+	NAME=goodsig-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_disable_sig_check
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+# no signature provided (ENOENT)
+driver_data_test_0015_2()
+{
+	NAME=nosig-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_set_sig_check
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+# good signature
+driver_data_test_0015_3()
+{
+	NAME=goodsig-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_set_sig_check
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+# signature not signed with a trusted key (ENOKEY)
+driver_data_test_0015_4()
+{
+	NAME=badsig1-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_set_sig_check
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+# digest doens't match (wrong hash value) (EKEYREJECTED)
+driver_data_test_0015_5()
+{
+	NAME=badsig2-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_set_sig_check
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+# signature corrupted/parsing error (EBADMSG)
+driver_data_test_0015_6()
+{
+	NAME=badsig3-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_set_sig_check
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+driver_data_test_0015()
+{
+	is_not_sig_enforced
+
+	driver_data_test_0015_1_1
+	driver_data_test_0015_1_2
+	driver_data_test_0015_2
+	driver_data_test_0015_3
+	driver_data_test_0015_4
+	driver_data_test_0015_5
+	driver_data_test_0015_6
+}
+
+# no signature provided, with driver not requiring it
+driver_data_test_0016_1_1()
+{
+	NAME=nosig-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_disable_sig_check
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+# good signature, with driver not requiring it
+driver_data_test_0016_1_2()
+{
+	NAME=goodsig-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_disable_sig_check
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+# no signature provided (ENOENT)
+driver_data_test_0016_2()
+{
+	NAME=nosig-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_set_sig_check
+	config_trigger_want_fail ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} -ENOENT
+}
+
+# good signature
+driver_data_test_0016_3()
+{
+	NAME=goodsig-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_set_sig_check
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+# signature not signed with a trusted key (ENOKEY)
+driver_data_test_0016_4()
+{
+	NAME=badsig1-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_set_sig_check
+	config_trigger_want_fail ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} -ENOKEY
+}
+
+# digest doens't match (wrong hash value) (EKEYREJECTED)
+driver_data_test_0016_5()
+{
+	NAME=badsig2-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_set_sig_check
+	config_trigger_want_fail ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} -EKEYREJECTED
+}
+
+# signature corrupted/parsing error (EBADMSG)
+driver_data_test_0016_6()
+{
+	NAME=badsig3-$DEFAULT_DRIVER_DATA
+
+	driver_data_set_sync_defaults
+	config_set_name $NAME
+	config_set_sig_check
+	config_trigger_want_fail ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} -EBADMSG
+}
+
+# This test case must be run at the last.
+# Otherwe we must reboot the kernel to reset fw_sig_enforce.
+driver_data_test_0016()
+{
+	enforce_sig_check
+
+	driver_data_test_0016_1_1
+	driver_data_test_0016_1_2
+	driver_data_test_0016_2
+	driver_data_test_0016_3
+	driver_data_test_0016_4
+	driver_data_test_0016_5
+	driver_data_test_0016_6
+}
+
 list_tests()
 {
 	echo "Test ID list:"
@@ -842,6 +1103,8 @@  list_tests()
 	echo "0012 x $(get_test_count 0012) - Verify api call wills will hunt for files, ignore file"
 	echo "0013 x $(get_test_count 0013) - Verify api call works"
 	echo "0014 x $(get_test_count 0013) - Verify api call works with suspend + resume"
+	echo "0015 x $(get_test_count 0015) - Verify loaded data with signature"
+	echo "0016 x $(get_test_count 0016) - Verify loaded data with signature under signature enforcing"
 }
 
 test_reqs