From patchwork Thu Jan 17 12:13:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Opaniuk X-Patchwork-Id: 155822 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp1892306jaa; Thu, 17 Jan 2019 04:13:32 -0800 (PST) X-Google-Smtp-Source: ALg8bN54yvOO16banB6IKWuW2gA0Pul4pWVzuMVyrxUBR0D/pl/X+KvxON8ZkrTv7+Dowew6fCno X-Received: by 2002:a50:d002:: with SMTP id j2mr11321118edf.123.1547727212204; Thu, 17 Jan 2019 04:13:32 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1547727212; cv=none; d=google.com; s=arc-20160816; b=j0VhRxtvVRHHJVKvpA/xQDmMtrcfMM44JVf4IQdTUWlqo6zVphSI5bEgIW4tQ95T2R jX7E1wNnpiXPkZNM7aLzPjcuhYCTmET4R5fyLZFfhBBM0VsjllIrH/JrmzZ/fCdtHmZm Tptn9DVrpWvLKybE7MybGrbSeECgHAamjUlh55y1RG0GuNnZdfzjLvhIliJ5GSelitom nZHdNYpiyh25ivEMHoEYN4NRa3/iPFFXXRP4dISGkUrc2q63b4jQb/AeG4/2r/X9so1B TXX5eGmsGAmy3aB9+C3X1Zgx3tTTr0UjA62/BmcSF7X0HcMLU0MSifpyRTb600uBhu41 cbLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:cc:message-id:date:to:from :dkim-signature; bh=6XAii7fbHs/ayDHpaJB+Q6MKqPGYzfsdL6Q7PBMlGsA=; b=q9YRsJm+M1M9zzCMrBw5LBuINBWmElsgNwqf5wXJeHb9+MnJG/PEcBoou1bF6emiwZ u4936EMu3uur70CKjRwpKwDBaIgMQ+U3cEcDWguVGnvlkm3oGphxYTZBLj6NQODrqj1M 4IDw/3S4xVsdKedMmwd7j9ZR2Yp+tF1sa/xvoCnaKM0PwXlW+zyOnoQp2f2WfwYu3vdC 5IVeOmSgQLPbOfw6sEODBwRn+NIRtECwdSi8V+XrM1PXail97nZFeU3tOz9d3BjSdWJ/ G/3G3EAyd64qVP8/Px3bR0aYLJUiY4rMCi7QSqfKwc2Muax0vnbp5QJB4IF948avzUau mHPw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=dy0kMiQk; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.denx.de (dione.denx.de. [81.169.180.215]) by mx.google.com with ESMTP id v22-v6si3330228ejr.314.2019.01.17.04.13.31; Thu, 17 Jan 2019 04:13:32 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) client-ip=81.169.180.215; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=dy0kMiQk; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by lists.denx.de (Postfix, from userid 105) id F10A7C220AE; Thu, 17 Jan 2019 12:13:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id D3619C21E63; Thu, 17 Jan 2019 12:13:26 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 65D77C21E63; Thu, 17 Jan 2019 12:13:25 +0000 (UTC) Received: from mail-lf1-f53.google.com (mail-lf1-f53.google.com [209.85.167.53]) by lists.denx.de (Postfix) with ESMTPS id A06DBC21D8A for ; Thu, 17 Jan 2019 12:13:24 +0000 (UTC) Received: by mail-lf1-f53.google.com with SMTP id i26so7646279lfc.0 for ; Thu, 17 Jan 2019 04:13:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=YEwVGq7T2sTnmQt/m1kcummu14GY2Xdf1a51sw5eRFo=; b=dy0kMiQkLYFLlT6iH8LEo0pzEDAGfUx/rinxkNunodZZWIVAy3eNUq5b20tywSy1oU KBNwCeiwSM6P+xGycdRjn7VjYUrjNEZ+MHDewqDgTjpjh9iAJu9VwqoGq7hCYfeW8Hhf VQkInRov7IPN9l1sLJVFAa2sec2TKYgaND6Bo= 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; bh=YEwVGq7T2sTnmQt/m1kcummu14GY2Xdf1a51sw5eRFo=; b=O/3lxq8RZzoyhC8w/kKx0WahzvBA4JbPQJUTuHy4Ktaz4+v5Q60UUIPjSfzGQpzoPo W7GkdhEgpkh/loRb8Qujc2KjbKBYmheI2sctfLwd0YRpLWLwsCZtqNSCFWUYu2ciy1e3 2kureaMJqatOlDAx42mX/92g6UybdwobklnppB7IyeIW3PdzvZJXhHf8Lpt26Bzja8uK 0crR+jtuUojRxpLxT1C8CEtkVP6N92/5/nWsbVXmE6W+EBiR7eutT0ml/9iitQm0spHU /cBZfVWsYQErUJafbOolsnp9eB3hxQyiGK7qvM5ojQisd+4GCTphfT4aJEXqh9EZYnbq WIyw== X-Gm-Message-State: AJcUukfr6W4s/e20IGzV8k8DHpvMWJXLtZ0SwuY4OedirCKaU8hl3GZd 7xw8BD6NIvhq7zhPL1d6612vMxuGk5e9Dw== X-Received: by 2002:a19:9dd1:: with SMTP id g200mr9851912lfe.127.1547727203360; Thu, 17 Jan 2019 04:13:23 -0800 (PST) Received: from localhost ([195.238.92.223]) by smtp.gmail.com with ESMTPSA id x16sm253241lff.26.2019.01.17.04.13.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Jan 2019 04:13:22 -0800 (PST) From: Igor Opaniuk To: u-boot@lists.denx.de Date: Thu, 17 Jan 2019 14:13:21 +0200 Message-Id: <1547727201-23322-1-git-send-email-igor.opaniuk@linaro.org> X-Mailer: git-send-email 2.7.4 Cc: trini@konsulko.com, praneeth@ti.com, misael.lopez@ti.com, erosca@de.adit-jv.com, joakim.bech@linaro.org Subject: [U-Boot] [PATCH v3 1/1] avb: add support for named persistent values X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" AVB version 1.1 introduces support for named persistent values that must be tamper evident and allows AVB to store arbitrary key-value pairs [1]. Introduce implementation of two additional AVB operations read_persistent_value()/write_persistent_value() for retrieving/storing named persistent values. Correspondent pull request in the OP-TEE OS project repo [2]. [1]: https://android.googlesource.com/platform/external/avb/+/android-9.0.0_r22 [2]: https://github.com/OP-TEE/optee_os/pull/2699 Signed-off-by: Igor Opaniuk --- Changes in v3: - fix possible mem lick in avb_read_persistent/avb_write_persistent - add additional sanity checks - cover avb read_pvalue/write_pvalue commands with python tests Changes in v2: - fix output format for avb read_pvalue/write_pvalue commands - fix issue with named value buffer size cmd/avb.c | 78 ++++++++++++++++++++++++++++ common/avb_verify.c | 125 +++++++++++++++++++++++++++++++++++++++++++++ include/tee.h | 2 + include/tee/optee_ta_avb.h | 16 ++++++ test/py/tests/test_avb.py | 16 ++++++ 5 files changed, 237 insertions(+) diff --git a/cmd/avb.c b/cmd/avb.c index ff00be4..c5af4a2 100644 --- a/cmd/avb.c +++ b/cmd/avb.c @@ -340,6 +340,76 @@ int do_avb_is_unlocked(cmd_tbl_t *cmdtp, int flag, return CMD_RET_FAILURE; } +int do_avb_read_pvalue(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + const char *name; + size_t bytes; + size_t bytes_read; + void *buffer; + char *endp; + + if (!avb_ops) { + printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + return CMD_RET_FAILURE; + } + + if (argc != 3) + return CMD_RET_USAGE; + + name = argv[1]; + bytes = simple_strtoul(argv[2], &endp, 10); + if (*endp && *endp != '\n') + return CMD_RET_USAGE; + + buffer = malloc(bytes); + if (!buffer) + return CMD_RET_FAILURE; + + if (avb_ops->read_persistent_value(avb_ops, name, bytes, buffer, + &bytes_read) == AVB_IO_RESULT_OK) { + printf("Read %ld bytes, value = %s\n", bytes_read, + (char *)buffer); + free(buffer); + return CMD_RET_SUCCESS; + } + + printf("Failed to read persistent value\n"); + + free(buffer); + + return CMD_RET_FAILURE; +} + +int do_avb_write_pvalue(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + const char *name; + const char *value; + + if (!avb_ops) { + printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + return CMD_RET_FAILURE; + } + + if (argc != 3) + return CMD_RET_USAGE; + + name = argv[1]; + value = argv[2]; + + if (avb_ops->write_persistent_value(avb_ops, name, strlen(value) + 1, + (const uint8_t *)value) == + AVB_IO_RESULT_OK) { + printf("Wrote %ld bytes\n", strlen(value) + 1); + return CMD_RET_SUCCESS; + } + + printf("Failed to write persistent value\n"); + + return CMD_RET_FAILURE; +} + static cmd_tbl_t cmd_avb[] = { U_BOOT_CMD_MKENT(init, 2, 0, do_avb_init, "", ""), U_BOOT_CMD_MKENT(read_rb, 2, 0, do_avb_read_rb, "", ""), @@ -350,6 +420,10 @@ static cmd_tbl_t cmd_avb[] = { U_BOOT_CMD_MKENT(read_part_hex, 4, 0, do_avb_read_part_hex, "", ""), U_BOOT_CMD_MKENT(write_part, 5, 0, do_avb_write_part, "", ""), U_BOOT_CMD_MKENT(verify, 1, 0, do_avb_verify_part, "", ""), +#ifdef CONFIG_OPTEE_TA_AVB + U_BOOT_CMD_MKENT(read_pvalue, 3, 0, do_avb_read_pvalue, "", ""), + U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_avb_write_pvalue, "", ""), +#endif }; static int do_avb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) @@ -384,6 +458,10 @@ U_BOOT_CMD( " partition and print to stdout\n" "avb write_part - write bytes to\n" " by using data from \n" +#ifdef CONFIG_OPTEE_TA_AVB + "avb read_pvalue - read a persistent value \n" + "avb write_pvalue - write a persistent value \n" +#endif "avb verify - run verification process using hash data\n" " from vbmeta structure\n" ); diff --git a/common/avb_verify.c b/common/avb_verify.c index a8c5a3e..584e235 100644 --- a/common/avb_verify.c +++ b/common/avb_verify.c @@ -647,6 +647,10 @@ static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func, return AVB_IO_RESULT_OK; case TEE_ERROR_OUT_OF_MEMORY: return AVB_IO_RESULT_ERROR_OOM; + case TEE_ERROR_STORAGE_NO_SPACE: + return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE; + case TEE_ERROR_ITEM_NOT_FOUND: + return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; case TEE_ERROR_TARGET_DEAD: /* * The TA has paniced, close the session to reload the TA @@ -847,6 +851,123 @@ static AvbIOResult get_size_of_partition(AvbOps *ops, return AVB_IO_RESULT_OK; } +static AvbIOResult read_persistent_value(AvbOps *ops, + const char *name, + size_t buffer_size, + u8 *out_buffer, + size_t *out_num_bytes_read) +{ + AvbIOResult rc; + struct tee_shm *shm_name; + struct tee_shm *shm_buf; + struct tee_param param[2]; + struct udevice *tee; + size_t name_size = strlen(name) + 1; + + if (get_open_session(ops->user_data)) + return AVB_IO_RESULT_ERROR_IO; + + tee = ((struct AvbOpsData *)ops->user_data)->tee; + + rc = tee_shm_alloc(tee, name_size, + TEE_SHM_ALLOC, &shm_name); + if (rc) + return AVB_IO_RESULT_ERROR_OOM; + + rc = tee_shm_alloc(tee, buffer_size, + TEE_SHM_ALLOC, &shm_buf); + if (rc) { + rc = AVB_IO_RESULT_ERROR_OOM; + goto free_name; + } + + memcpy(shm_name->addr, name, name_size); + + memset(param, 0, sizeof(param)); + param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; + param[0].u.memref.shm = shm_name; + param[0].u.memref.size = name_size;; + param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT; + param[1].u.memref.shm = shm_buf; + param[1].u.memref.size = buffer_size; + + rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE, + 2, param); + if (rc) + goto out; + + if (param[1].u.memref.size > buffer_size) { + rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; + goto out; + } + + *out_num_bytes_read = param[1].u.memref.size; + + memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read); + +out: + tee_shm_free(shm_buf); +free_name: + tee_shm_free(shm_name); + + return rc; +} + +static AvbIOResult write_persistent_value(AvbOps *ops, + const char *name, + size_t value_size, + const u8 *value) +{ + AvbIOResult rc; + struct tee_shm *shm_name; + struct tee_shm *shm_buf; + struct tee_param param[2]; + struct udevice *tee; + size_t name_size = strlen(name) + 1; + + if (get_open_session(ops->user_data)) + return AVB_IO_RESULT_ERROR_IO; + + tee = ((struct AvbOpsData *)ops->user_data)->tee; + + if (!value_size) + return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE; + + rc = tee_shm_alloc(tee, name_size, + TEE_SHM_ALLOC, &shm_name); + if (rc) + return AVB_IO_RESULT_ERROR_OOM; + + rc = tee_shm_alloc(tee, value_size, + TEE_SHM_ALLOC, &shm_buf); + if (rc) { + rc = AVB_IO_RESULT_ERROR_OOM; + goto free_name; + } + + memcpy(shm_name->addr, name, name_size); + memcpy(shm_buf->addr, value, value_size); + + memset(param, 0, sizeof(param)); + param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; + param[0].u.memref.shm = shm_name; + param[0].u.memref.size = name_size; + param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; + param[1].u.memref.shm = shm_buf; + param[1].u.memref.size = value_size; + + rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE, + 2, param); + if (rc) + goto out; + +out: + tee_shm_free(shm_buf); +free_name: + tee_shm_free(shm_name); + + return rc; +} /** * ============================================================================ * AVB2.0 AvbOps alloc/initialisation/free @@ -870,6 +991,10 @@ AvbOps *avb_ops_alloc(int boot_device) ops_data->ops.read_is_device_unlocked = read_is_device_unlocked; ops_data->ops.get_unique_guid_for_partition = get_unique_guid_for_partition; +#ifdef CONFIG_OPTEE_TA_AVB + ops_data->ops.write_persistent_value = write_persistent_value; + ops_data->ops.read_persistent_value = read_persistent_value; +#endif ops_data->ops.get_size_of_partition = get_size_of_partition; ops_data->mmc_dev = boot_device; diff --git a/include/tee.h b/include/tee.h index edd9f9b..02bcd9e 100644 --- a/include/tee.h +++ b/include/tee.h @@ -43,7 +43,9 @@ #define TEE_ERROR_COMMUNICATION 0xffff000e #define TEE_ERROR_SECURITY 0xffff000f #define TEE_ERROR_OUT_OF_MEMORY 0xffff000c +#define TEE_ERROR_OVERFLOW 0xffff300f #define TEE_ERROR_TARGET_DEAD 0xffff3024 +#define TEE_ERROR_STORAGE_NO_SPACE 0xffff3041 #define TEE_ORIGIN_COMMS 0x00000002 #define TEE_ORIGIN_TEE 0x00000003 diff --git a/include/tee/optee_ta_avb.h b/include/tee/optee_ta_avb.h index 074386a..949875a 100644 --- a/include/tee/optee_ta_avb.h +++ b/include/tee/optee_ta_avb.h @@ -45,4 +45,20 @@ */ #define TA_AVB_CMD_WRITE_LOCK_STATE 3 +/* + * Reads a persistent value corresponding to the given name. + * + * in params[0].u.memref: persistent value name + * out params[1].u.memref: read persistent value buffer + */ +#define TA_AVB_CMD_READ_PERSIST_VALUE 4 + +/* + * Writes a persistent value corresponding to the given name. + * + * in params[0].u.memref: persistent value name + * in params[1].u.memref: persistent value buffer to write + */ +#define TA_AVB_CMD_WRITE_PERSIST_VALUE 5 + #endif /* __TA_AVB_H */ diff --git a/test/py/tests/test_avb.py b/test/py/tests/test_avb.py index e70a010..770e6ff 100644 --- a/test/py/tests/test_avb.py +++ b/test/py/tests/test_avb.py @@ -116,3 +116,19 @@ def test_avb_mmc_read(u_boot_console): response = u_boot_console.run_command('cmp 0x%x 0x%x 40' % (temp_addr, temp_addr2)) assert response.find('64 word') + + +@pytest.mark.buildconfigspec('cmd_avb') +@pytest.mark.buildconfigspec('optee_ta_avb') +def test_avb_is_unlocked(u_boot_console): + """Test reading/writing persistent storage to avb + """ + + response = u_boot_console.run_command('avb init %s' % str(mmc_dev)) + assert response == '' + + response = u_boot_console.run_command('avb write_pvalue test value_value') + assert response == 'Wrote 12 bytes' + + response = u_boot_console.run_command('avb read_pvalue test 12') + assert response == 'Read 12 bytes, value = value_value'