From patchwork Fri May 26 03:06:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 100540 Delivered-To: patch@linaro.org Received: by 10.140.96.100 with SMTP id j91csp59002qge; Thu, 25 May 2017 20:03:16 -0700 (PDT) X-Received: by 10.98.130.1 with SMTP id w1mr49071620pfd.128.1495767796726; Thu, 25 May 2017 20:03:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1495767796; cv=none; d=google.com; s=arc-20160816; b=tmakFN81bedPhalvC08zsG/zdSFJaUIKi4TdpfDmmM0ME18ed2c9e50LDPNAbq/d2Q MZZgnYcLgOytKF0TqSs+kBOxYS3xIH6JgRKGYBlZJdNKlmq9CVsYbBkCJcXV5Ygbu7am dlPLZZtbiE5aO7LezARKeTTkA2rRDDVSJDBq/K2hXAvKabJBxC6PpAVDSzCKassChF1x rKoBtpv0sFuSv3+CTBIkRj4c28by4vLc3bUXyY2ccmvKNUWkNyKBp8MPHfLwkKxfqetx 4hVpNXlVPs3vP+1PyqLvjnNNcHAxQny7hQoEpuB12Zbn3seNhwdFljUEzALsMMZL0Hif XkSQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=AOGbZwMy6mkdVrA3XiiVYGNbtrXuJdy/7jUtrUo0SV4=; b=ohjDrk/QyGUE2GmAlY+RChaqxZgDytnTHi+HQ3KKw2J1pYk6z2uNIqG4nsshu5hMSz XAZ3MknaSx2g5v4b6nk/MxYGR69CDlH8XvEGUNy0Qn4DTB9ChOc7yMDkeaWNIaCe33Rh HlrAyy5/OEOg0rVeknYf3EJJji4uSq08mojskWW6YGVGT+6zibpmQphuo764pBksi8QX vu8jteFAicHsM5kcneeWEYM97BggehwklRlQV0At8zcF/D+EejbzkjNq/phxx0duVr6c IvubBkSOhFQANUzhM+j8kwnLo0zkEfsp8jwgqVm72m4iWmT/YT/n5G81upHOwWERAfXV 0cCA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t141si30678767pgb.103.2017.05.25.20.03.16; Thu, 25 May 2017 20:03:16 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1946731AbdEZDDN (ORCPT + 25 others); Thu, 25 May 2017 23:03:13 -0400 Received: from mail-pf0-f173.google.com ([209.85.192.173]:33283 "EHLO mail-pf0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1946685AbdEZDCd (ORCPT ); Thu, 25 May 2017 23:02:33 -0400 Received: by mail-pf0-f173.google.com with SMTP id e193so184458850pfh.0 for ; Thu, 25 May 2017 20:02:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=AOGbZwMy6mkdVrA3XiiVYGNbtrXuJdy/7jUtrUo0SV4=; b=YfXlCpeetijQj75kWMp7QUPdr7X60RkiY0hW5A70zBb879b2jhIXiYdaY6JmVWFpdU gPW+tVXE7UrZX5+BzJ/g0XswahEBcg2YXkpDm+4+XMZ7lM733YBfouoF/sresSsDqLod u68h8Lxbl0UvfyQRNlMkuSy2Bm/x6t62Veonc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=AOGbZwMy6mkdVrA3XiiVYGNbtrXuJdy/7jUtrUo0SV4=; b=G41Fi2kZjlZVOk9871VWV1HzsfIig0i2Ouu2jVdUsiR3fh+eI0SH4N0JOM2o2REGt7 vkzHx9MIpyiie+n26Vhkbf3vwyYYCvD/SC2tD0arvzdT8UjncJuWQHjz5nLP5kl6QoUl 44bQ/mauAjx7E9xmrEmBGXIEOLegrfLeMALpTL14irDuRbhtXotvusAAyQ+HTkkAHQqr MJX7uWFrOuS3dZehxKg2Eq4ORLEB37ggKJ5UrxvSjsXB2kVS2BL2okwJL0XJLf6D1T4n bRej2JmeMKkyJeMhFkGqF6jDL9w9v675EaeO/Tn7Bt4tvS0lWvi8891BfB8KvKd9B9it 0uag== X-Gm-Message-State: AODbwcAsD1ExowCQqoLdjFBpwm6Aio7dYAkCzGHjE67F1VzqMDsNUJNE +o1OwlQZZox5z4LA X-Received: by 10.98.147.199 with SMTP id r68mr48435323pfk.168.1495767752190; Thu, 25 May 2017 20:02:32 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id i67sm16231808pfk.87.2017.05.25.20.02.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 May 2017 20:02:31 -0700 (PDT) From: AKASHI Takahiro To: mcgrof@kernel.org Cc: rusty@rustcorp.com.au, dhowells@redhat.com, ming.lei@canonical.com, seth.forshee@canonical.com, kyle@kernel.org, David.Woodhouse@intel.com, linux-kernel@vger.kernel.org, AKASHI Takahiro , "Luis R . Rodriguez" Subject: [PATCH 3/4] test: firmwware: add signature test to driver_data loader test Date: Fri, 26 May 2017 12:06:08 +0900 Message-Id: <20170526030609.1414-4-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20170526030609.1414-1-takahiro.akashi@linaro.org> References: <20170526030609.1414-1-takahiro.akashi@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 Cc: Luis R. Rodriguez --- 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 --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