From patchwork Mon Feb 28 12:06:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sughosh Ganu X-Patchwork-Id: 546695 Delivered-To: patch@linaro.org Received: by 2002:ac0:9f50:0:0:0:0:0 with SMTP id l16csp2676145imf; Mon, 28 Feb 2022 04:09:19 -0800 (PST) X-Google-Smtp-Source: ABdhPJz2SvqdqI9TngKUauz5b2kZiw/ZLyEJSB5922zV8a0Q/HB5JahER4BvWwMHqx0Rhrqmh015 X-Received: by 2002:a17:906:b887:b0:6ce:36cb:1e18 with SMTP id hb7-20020a170906b88700b006ce36cb1e18mr15099296ejb.95.1646050158945; Mon, 28 Feb 2022 04:09:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1646050158; cv=none; d=google.com; s=arc-20160816; b=c4m02K8k13qUSd+JbYq0yqfT/4W54Ojxml46ilZAlP/S8gZzkYefqQ31wh/87mfu7p 28jyoCXCKgM/8dWhEiWyAC6nnAxvblqWmjZ/HaQxo3RGpfX5MXINiXeqzoInGZFdlBEO B3CeOQc8zRRQ8UlmZA0UJuPmfIH47S4+X23YINTWja0HtteJM8YQAWl3csAoiSy5xEnC CaP/HDmTFW+hREUVvLnlb0Ls/CqvV+kgsGNv4GOfi/DlQBe6IkNH03wVWZxW81kjaI/8 oOUFRDOnY31TXgcq+n+S8on8h11hEvUZ8BD2+NBJq+Kuun7bLEIQdRVAjAtbgJ8h70g9 2YaA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from; bh=GTqkQ+DZCAnVVBJ5BzQziF6p1rJu/aa09LP083eMvuE=; b=J6cmKGJpgm+fnGRmxrZ6qoSLfJq8uoKLmjVr6Np3NU91g1PbVYbfzQwzVhk9CuRvzS 368jNnHkhEiG8khtYTGI6RkmQJgbHDB7ncHfQq6leXUKnmbBIKjIRdVjQ6y09/6pqQWO XhI62KpayOwtClo5/wHrg7574RetW0r3+OzcWyQ7Iz/LBMFp9z1UaJicmTFC5n29Xw+2 ECeD8mwa6mxjZUHfYo14SmRbb6tva6uNyWodSb5l4kQcaslTwdvhWFUMV5I6ww0mDTud 4RNCsjzqUqgscSI0D5yMm/TTkHKE9BKM+fQlw1LpK79O+QlEk/TTVaWAtl59ZTZSMCmu U13g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 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 phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id a13-20020a1709065f8d00b006d08ca424b4si6047826eju.46.2022.02.28.04.09.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Feb 2022 04:09:18 -0800 (PST) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6762583C8E; Mon, 28 Feb 2022 13:08:55 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id A25DD838D6; Mon, 28 Feb 2022 13:08:07 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.2 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_SOFTFAIL,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id C817883C63 for ; Mon, 28 Feb 2022 13:07:43 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=fail smtp.mailfrom=sughosh.ganu@linaro.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C04A1ED1; Mon, 28 Feb 2022 04:07:42 -0800 (PST) Received: from a076522.blr.arm.com (a076522.blr.arm.com [10.162.16.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A24ED3F73D; Mon, 28 Feb 2022 04:07:40 -0800 (PST) From: Sughosh Ganu To: u-boot@lists.denx.de Cc: Ilias Apalodimas , Simon Glass , Heinrich Schuchardt , Mario Six , Sughosh Ganu Subject: [PATCH v2 07/10] tpm: rng: Move the TPM RNG functionality to driver model Date: Mon, 28 Feb 2022 17:36:35 +0530 Message-Id: <20220228120638.678137-8-sughosh.ganu@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220228120638.678137-1-sughosh.ganu@linaro.org> References: <20220228120638.678137-1-sughosh.ganu@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean Currently, the TPM random number generator(RNG) functions are defined as part of the library functions under the corresponding tpm files for tpmv1 and tpmv2. Move the RNG functionality under TPM RNG drivers complying with the driver model. Also make changes to the tpm_get_random function to have it call the TPM RNG driver functions instead of the library functions. Signed-off-by: Sughosh Ganu --- Changes since V1: * Added existing copyrights for the rng functions taken from the tpm library routines * Return -EIO for TPM command returning an error * Simplify the logic in tpm_get_random based on the review comments from Ilias drivers/rng/Makefile | 1 + drivers/rng/tpm1_rng.c | 87 ++++++++++++++++++++++++++++++++++++++++++ drivers/rng/tpm2_rng.c | 86 +++++++++++++++++++++++++++++++++++++++++ lib/tpm-v1.c | 44 --------------------- lib/tpm-v2.c | 44 --------------------- lib/tpm_api.c | 23 +++++++++-- 6 files changed, 193 insertions(+), 92 deletions(-) create mode 100644 drivers/rng/tpm1_rng.c create mode 100644 drivers/rng/tpm2_rng.c diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile index 39f7ee3f03..129cfbd006 100644 --- a/drivers/rng/Makefile +++ b/drivers/rng/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_RNG_MSM) += msm_rng.o obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o obj-$(CONFIG_RNG_IPROC200) += iproc_rng200.o +obj-$(CONFIG_TPM) += tpm1_rng.o tpm2_rng.o diff --git a/drivers/rng/tpm1_rng.c b/drivers/rng/tpm1_rng.c new file mode 100644 index 0000000000..7e629756b3 --- /dev/null +++ b/drivers/rng/tpm1_rng.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013 The Chromium OS Authors. + * Coypright (c) 2013 Guntermann & Drunck GmbH + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include + +#define TPM_HEADER_SIZE 10 + +#define TPMV1_DATA_OFFSET 14 + +/** + * tpm1_rng_read() - Read the random bytes from TPMv1 device + * @param dev TPMv1 RNG device + * @param data data buffer to write random bytes + * @param count number of random bytes to read from + * the device + * + * Function to read the random bytes from the RNG pseudo device + * built into the TPMv1 device. Reads 'count' number of bytes + * from the random number generator and copies them into the + * 'data' buffer. + * + * Return: 0 if OK, -ve on error. + * + */ +static int tpm1_rng_read(struct udevice *dev, void *data, size_t count) +{ + const u8 command[14] = { + 0x0, 0xc1, /* TPM_TAG */ + 0x0, 0x0, 0x0, 0xe, /* parameter size */ + 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */ + }; + const size_t length_offset = TPM_HEADER_SIZE; + const size_t data_size_offset = TPM_HEADER_SIZE; + const size_t data_offset = TPMV1_DATA_OFFSET; + u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + size_t response_length = sizeof(response); + u32 data_size; + u8 *out = data; + + while (count > 0) { + u32 this_bytes = min(count, + sizeof(response) - data_offset); + u32 err; + + if (pack_byte_string(buf, sizeof(buf), "sd", + 0, command, sizeof(command), + length_offset, this_bytes)) + return -EIO; + err = tpm_sendrecv_command(dev->parent, buf, response, + &response_length); + if (err) + return err; + if (unpack_byte_string(response, response_length, "d", + data_size_offset, &data_size)) + return -EIO; + if (data_size > count) + return TPM_LIB_ERROR; + if (unpack_byte_string(response, response_length, "s", + data_offset, out, data_size)) + return -EIO; + + count -= data_size; + out += data_size; + } + + return 0; +} + +static const struct dm_rng_ops tpm1_rng_ops = { + .read = tpm1_rng_read, +}; + +U_BOOT_DRIVER(tpm1_rng) = { + .name = "tpm1-rng", + .id = UCLASS_RNG, + .ops = &tpm1_rng_ops, +}; diff --git a/drivers/rng/tpm2_rng.c b/drivers/rng/tpm2_rng.c new file mode 100644 index 0000000000..e7f6be46e4 --- /dev/null +++ b/drivers/rng/tpm2_rng.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2018 Bootlin + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include + +#define TPM_HEADER_SIZE 10 + +#define TPMV2_DATA_OFFSET 12 + +/** + * tpm2_rng_read() - Read the random bytes from TPMv2 device + * @param dev TPMv2 RNG device + * @param data data buffer to write random bytes + * @param count number of random bytes to read from + * the device + * + * Function to read the random bytes from the RNG pseudo device + * built into the TPMv2 device. Reads 'count' number of bytes + * from the random number generator and copies them into the + * 'data' buffer. + * + * Return: 0 if OK, -ve on error. + * + */ +static int tpm2_rng_read(struct udevice *dev, void *data, size_t count) +{ + const u8 command_v2[10] = { + tpm_u16(TPM2_ST_NO_SESSIONS), + tpm_u32(12), + tpm_u32(TPM2_CC_GET_RANDOM), + }; + u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; + + const size_t data_size_offset = TPM_HEADER_SIZE; + const size_t data_offset = TPMV2_DATA_OFFSET; + size_t response_length = sizeof(response); + u32 data_size; + u8 *out = data; + + while (count > 0) { + u32 this_bytes = min((size_t)count, + sizeof(response) - data_offset); + u32 err; + + if (pack_byte_string(buf, sizeof(buf), "sw", + 0, command_v2, sizeof(command_v2), + sizeof(command_v2), this_bytes)) + return -EIO; + err = tpm_sendrecv_command(dev->parent, buf, response, + &response_length); + if (err) + return err; + if (unpack_byte_string(response, response_length, "w", + data_size_offset, &data_size)) + return -EIO; + if (data_size > this_bytes) + return TPM_LIB_ERROR; + if (unpack_byte_string(response, response_length, "s", + data_offset, out, data_size)) + return -EIO; + + count -= data_size; + out += data_size; + } + + return 0; +} + +static const struct dm_rng_ops tpm2_rng_ops = { + .read = tpm2_rng_read, +}; + +U_BOOT_DRIVER(tpm2_rng) = { + .name = "tpm2-rng", + .id = UCLASS_RNG, + .ops = &tpm2_rng_ops, +}; diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c index 467992e04e..71cc90a2ab 100644 --- a/lib/tpm-v1.c +++ b/lib/tpm-v1.c @@ -868,47 +868,3 @@ u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20], #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ #endif /* CONFIG_TPM_AUTH_SESSIONS */ - -u32 tpm1_get_random(struct udevice *dev, void *data, u32 count) -{ - const u8 command[14] = { - 0x0, 0xc1, /* TPM_TAG */ - 0x0, 0x0, 0x0, 0xe, /* parameter size */ - 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */ - }; - const size_t length_offset = 10; - const size_t data_size_offset = 10; - const size_t data_offset = 14; - u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; - size_t response_length = sizeof(response); - u32 data_size; - u8 *out = data; - - while (count > 0) { - u32 this_bytes = min((size_t)count, - sizeof(response) - data_offset); - u32 err; - - if (pack_byte_string(buf, sizeof(buf), "sd", - 0, command, sizeof(command), - length_offset, this_bytes)) - return TPM_LIB_ERROR; - err = tpm_sendrecv_command(dev, buf, response, - &response_length); - if (err) - return err; - if (unpack_byte_string(response, response_length, "d", - data_size_offset, &data_size)) - return TPM_LIB_ERROR; - if (data_size > count) - return TPM_LIB_ERROR; - if (unpack_byte_string(response, response_length, "s", - data_offset, out, data_size)) - return TPM_LIB_ERROR; - - count -= data_size; - out += data_size; - } - - return 0; -} diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c index 2f16b0007b..c1456c1974 100644 --- a/lib/tpm-v2.c +++ b/lib/tpm-v2.c @@ -562,50 +562,6 @@ u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw, return tpm_sendrecv_command(dev, command_v2, NULL, NULL); } -u32 tpm2_get_random(struct udevice *dev, void *data, u32 count) -{ - const u8 command_v2[10] = { - tpm_u16(TPM2_ST_NO_SESSIONS), - tpm_u32(12), - tpm_u32(TPM2_CC_GET_RANDOM), - }; - u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; - - const size_t data_size_offset = 10; - const size_t data_offset = 12; - size_t response_length = sizeof(response); - u32 data_size; - u8 *out = data; - - while (count > 0) { - u32 this_bytes = min((size_t)count, - sizeof(response) - data_offset); - u32 err; - - if (pack_byte_string(buf, sizeof(buf), "sw", - 0, command_v2, sizeof(command_v2), - sizeof(command_v2), this_bytes)) - return TPM_LIB_ERROR; - err = tpm_sendrecv_command(dev, buf, response, - &response_length); - if (err) - return err; - if (unpack_byte_string(response, response_length, "w", - data_size_offset, &data_size)) - return TPM_LIB_ERROR; - if (data_size > this_bytes) - return TPM_LIB_ERROR; - if (unpack_byte_string(response, response_length, "s", - data_offset, out, data_size)) - return TPM_LIB_ERROR; - - count -= data_size; - out += data_size; - } - - return 0; -} - u32 tpm2_write_lock(struct udevice *dev, u32 index) { u8 command_v2[COMMAND_BUFFER_SIZE] = { diff --git a/lib/tpm_api.c b/lib/tpm_api.c index 9dd9606fa8..5492f89959 100644 --- a/lib/tpm_api.c +++ b/lib/tpm_api.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -264,12 +265,26 @@ u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm) return -ENOSYS; } +#if CONFIG_IS_ENABLED(DM_RNG) int tpm_get_random(struct udevice *dev, void *data, u32 count) { + int ret = -ENOSYS; + struct udevice *rng_dev; + if (is_tpm1(dev)) - return tpm1_get_random(dev, data, count); + ret = uclass_get_device_by_driver(UCLASS_RNG, + DM_DRIVER_GET(tpm1_rng), + &rng_dev); else if (is_tpm2(dev)) - return -ENOSYS; /* not implemented yet */ - else - return -ENOSYS; + ret = uclass_get_device_by_driver(UCLASS_RNG, + DM_DRIVER_GET(tpm2_rng), + &rng_dev); + + if (ret) { + log_err("Getting tpm rng device failed\n"); + return ret; + } + + return dm_rng_read(rng_dev, data, (size_t)count); } +#endif /* DM_RNG */