From patchwork Wed Jun 1 08:27:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Etienne Carriere X-Patchwork-Id: 1637797 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=p8NfmMVw; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4LCj315kYJz9s1l for ; Wed, 1 Jun 2022 18:28:29 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id C720284287; Wed, 1 Jun 2022 10:28:00 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="p8NfmMVw"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4FE92840FD; Wed, 1 Jun 2022 10:27:52 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 102438424E for ; Wed, 1 Jun 2022 10:27:42 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=etienne.carriere@linaro.org Received: by mail-wr1-x434.google.com with SMTP id h5so1302169wrb.0 for ; Wed, 01 Jun 2022 01:27:42 -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 :mime-version:content-transfer-encoding; bh=LJ/WWhpl5OI8RGj7K0DfGofA/Ewp4fbDnG9FSAdzqP4=; b=p8NfmMVwi5zC9BXFiqprBxcOQIM7mmxWQUgyMc8mSc0f89ZJf1GBPGKEtCSfuWHNlw klbLegLqi5IulUwjQxdkf5a9n8Uwt0QizgbiDhBQiFejdXnoYibRcHkLjy/QNWl/8Jaj Ti6XssbfdRdzwFVhztow+ID0BvB93kN8h73M849erlSe92BSxwj2ylL6gaU2cWaPr9u4 8Ob3Remy3IcVuaUJtN6sAb6ifTp04e8eTibFXN+HAirii2DOniNGDSJHJJCO0TA8E1lR 25XixHxjhfpdINjrTbarhGhPfGReFkBevfXFisF43KxzVI9K0R4MoJQfqOexnNSjg9+p hmpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LJ/WWhpl5OI8RGj7K0DfGofA/Ewp4fbDnG9FSAdzqP4=; b=kTxf5hHhUGHIYup/9UScJJE38VitBO5m2+RXLhPU+S3qh9jEVhcHYUBWgmykMm3GcJ jX4lAVzfi/DlIFm3/ZMHUCkLU1T/aiwI3rDlTgK01X3xKL9J62sZwUGqofGYezke0xRS wKxkJFO+ljJDgQ3ERUJixufpRCwk/rtl+z/gYOz2+C7r21cx4xVZnl0mqt9x3Rkath2f GAp7Ss6sKnWbljEgbQHUKL+G4yQ4MBcBI/gkpXSAkrw8ZDzy8mkfA2HsP4Xai/o6kAme BVHryhQ/baHOf3HjYPXFZ206RjQ4bZ7FKoAJ8AxlCRcOZk33lpajn6miIZVkUSYWmf3C vr8g== X-Gm-Message-State: AOAM5324tM7bZ827N1uDA+SIjA415WUXmmZo6rhFYVZyRIRBNRexuS+e FqEw7Xde3SOnQSu5pO1IiN8JaxYx3mSsSg== X-Google-Smtp-Source: ABdhPJwljdpmDSwa68cm3CXU49LoFnddc7rxPzlGTw8RzI1ZG4pYy2Ey1AxTrDKOa7TA2sm/R3d86w== X-Received: by 2002:a05:6000:36f:b0:210:2b39:632 with SMTP id f15-20020a056000036f00b002102b390632mr15294230wrf.669.1654072061306; Wed, 01 Jun 2022 01:27:41 -0700 (PDT) Received: from lmecxl1178.lme.st.com ([2a04:cec0:117a:a94e:2216:1d3f:505:2dfb]) by smtp.gmail.com with ESMTPSA id i6-20020a05600c290600b00397470a8226sm1166140wmd.15.2022.06.01.01.27.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Jun 2022 01:27:40 -0700 (PDT) From: Etienne Carriere To: u-boot@lists.denx.de Cc: Etienne Carriere , Sughosh Ganu , Heinrich Schuchardt Subject: [PATCH 4/4] drivers: rng: add smccc trng driver Date: Wed, 1 Jun 2022 10:27:34 +0200 Message-Id: <20220601082734.301474-4-etienne.carriere@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220601082734.301474-1-etienne.carriere@linaro.org> References: <20220601082734.301474-1-etienne.carriere@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 Adds random number generator driver using Arm SMCCC TRNG interface to get entropy bytes from secure monitor. The driver registers as an Arm SMCCC feature driver to allow PSCI driver to bind a device for when secure monitor exposes RNG support from Arm SMCCC TRNG interface. Cc: Sughosh Ganu Cc: Heinrich Schuchardt Signed-off-by: Etienne Carriere --- MAINTAINERS | 5 + drivers/rng/Kconfig | 9 ++ drivers/rng/Makefile | 1 + drivers/rng/smccc_trng.c | 207 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+) create mode 100644 drivers/rng/smccc_trng.c diff --git a/MAINTAINERS b/MAINTAINERS index 56be0bfad0..5a92b8bfcb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1231,6 +1231,11 @@ F: drivers/gpio/sl28cpld-gpio.c F: drivers/misc/sl28cpld.c F: drivers/watchdog/sl28cpld-wdt.c +SMCCC TRNG +M: Etienne Carriere +S: Maintained +F: drivers/rng/smccc_trng.c + SPI M: Jagan Teki S: Maintained diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig index c10f7d345b..6f73be8f9b 100644 --- a/drivers/rng/Kconfig +++ b/drivers/rng/Kconfig @@ -58,4 +58,13 @@ config RNG_IPROC200 depends on DM_RNG help Enable random number generator for RPI4. + +config RNG_SMCCC_TRNG + bool "Arm SMCCC TRNG interface" + depends on DM_RNG && ARM_PSCI_FW + default y if ARM_SMCCC_FEATURES + help + Enable random number generator for platforms that support Arm + SMCCC TRNG interface. + endif diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile index 435b3b965a..20c40a964c 100644 --- a/drivers/rng/Makefile +++ b/drivers/rng/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_RNG_OPTEE) += optee_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_RNG_SMCCC_TRNG) += smccc_trng.o diff --git a/drivers/rng/smccc_trng.c b/drivers/rng/smccc_trng.c new file mode 100644 index 0000000000..3a4bb33941 --- /dev/null +++ b/drivers/rng/smccc_trng.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022, Linaro Limited + */ + +#define LOG_CATEGORY UCLASS_RNG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "smccc-trng" + +/** + * Arm SMCCC TRNG firmware interface specification: + * https://developer.arm.com/documentation/den0098/latest/ + */ +#define ARM_SMCCC_TRNG_VERSION 0x84000050 +#define ARM_SMCCC_TRNG_FEATURES 0x84000051 +#define ARM_SMCCC_TRNG_GET_UUID 0x84000052 +#define ARM_SMCCC_TRNG_RND_32 0x84000053 +#define ARM_SMCCC_TRNG_RND_64 0xC4000053 + +#define ARM_SMCCC_RET_TRNG_SUCCESS ((ulong)0) +#define ARM_SMCCC_RET_TRNG_NOT_SUPPORTED ((ulong)-1) +#define ARM_SMCCC_RET_TRNG_INVALID_PARAMETER ((ulong)-2) +#define ARM_SMCCC_RET_TRNG_NO_ENTROPY ((ulong)-3) + +#define TRNG_MAJOR_MASK GENMASK(30, 16) +#define TRNG_MAJOR_SHIFT 16 +#define TRNG_MINOR_MASK GENMASK(15, 0) +#define TRNG_MINOR_SHIFT 0 + +#define TRNG_MAX_RND_64 (192 / 8) +#define TRNG_MAX_RND_32 (96 / 8) + +/** + * struct smccc_trng_priv - Private data for SMCCC TRNG support + * + * @smc64 - True if TRNG_RND_64 is supported, false if TRNG_RND_32 is supported + */ +struct smccc_trng_priv { + bool smc64; +}; + +/* + * Copy random bytes from ulong SMCCC output register to target buffer + * Defines 2 function flavors for whether ARM_SMCCC_TRNG_RND_32 or + * ARM_SMCCC_TRNG_RND_64 was used to invoke the service. + */ +static size_t smc32_copy_sample(u8 **ptr, size_t size, ulong *rnd) +{ + size_t len = min(size, sizeof(u32)); + u32 sample = *rnd; + + memcpy(*ptr, &sample, len); + *ptr += len; + + return size - len; +} + +static size_t smc64_copy_sample(u8 **ptr, size_t size, ulong *rnd) +{ + size_t len = min(size, sizeof(u64)); + u64 sample = *rnd; + + memcpy(*ptr, &sample, len); + *ptr += len; + + return size - len; +} + +static int smccc_trng_read(struct udevice *dev, void *data, size_t len) +{ + struct psci_plat_data *smccc = dev_get_parent_plat(dev); + struct smccc_trng_priv *priv = dev_get_priv(dev); + struct arm_smccc_res res; + u32 func_id; + u8 *ptr = data; + size_t rem = len; + size_t max_sz; + size_t (*copy_sample)(u8 **ptr, size_t size, ulong *rnd); + + if (priv->smc64) { + copy_sample = smc64_copy_sample; + func_id = ARM_SMCCC_TRNG_RND_64; + max_sz = TRNG_MAX_RND_64; + } else { + copy_sample = smc32_copy_sample; + func_id = ARM_SMCCC_TRNG_RND_32; + max_sz = TRNG_MAX_RND_32; + } + + while (rem) { + size_t sz = min(rem, max_sz); + + smccc->invoke_fn(func_id, sz * 8, 0, 0, 0, 0, 0, 0, &res); + + switch (res.a0) { + case ARM_SMCCC_RET_TRNG_SUCCESS: + break; + case ARM_SMCCC_RET_TRNG_NO_ENTROPY: + continue; + default: + return -EIO; + } + + rem -= sz; + + sz = copy_sample(&ptr, sz, &res.a3); + if (sz) + sz = copy_sample(&ptr, sz, &res.a2); + if (sz) + sz = copy_sample(&ptr, sz, &res.a1); + } + + return 0; +} + +static const struct dm_rng_ops smccc_trng_ops = { + .read = smccc_trng_read, +}; + +static bool smccc_trng_is_supported(void (*invoke_fn)(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4, unsigned long a5, + unsigned long a6, unsigned long a7, + struct arm_smccc_res *res)) +{ + struct arm_smccc_res res; + + (*invoke_fn)(ARM_SMCCC_ARCH_FEATURES, ARM_SMCCC_TRNG_VERSION, 0, 0, 0, 0, 0, 0, &res); + if (res.a0 == ARM_SMCCC_RET_NOT_SUPPORTED) + return false; + + (*invoke_fn)(ARM_SMCCC_TRNG_VERSION, 0, 0, 0, 0, 0, 0, 0, &res); + if (res.a0 & BIT(31)) + return false; + + /* Test 64bit interface and fallback to 32bit interface */ + invoke_fn(ARM_SMCCC_TRNG_FEATURES, ARM_SMCCC_TRNG_RND_64, + 0, 0, 0, 0, 0, 0, &res); + + if (res.a0 == ARM_SMCCC_RET_TRNG_NOT_SUPPORTED) + invoke_fn(ARM_SMCCC_TRNG_FEATURES, ARM_SMCCC_TRNG_RND_32, + 0, 0, 0, 0, 0, 0, &res); + + return res.a0 == ARM_SMCCC_RET_TRNG_SUCCESS; +} + +ARM_SMCCC_FEATURE_DRIVER(smccc_trng) = { + .driver_name = DRIVER_NAME, + .is_supported = smccc_trng_is_supported, +}; + +static int smccc_trng_probe(struct udevice *dev) +{ + struct psci_plat_data *smccc = dev_get_parent_plat(dev); + struct smccc_trng_priv *priv = dev_get_priv(dev); + struct arm_smccc_res res; + + if (!(smccc_trng_is_supported(smccc->invoke_fn))) + return -ENODEV; + + /* At least one of 64bit and 32bit interfaces is available */ + smccc->invoke_fn(ARM_SMCCC_TRNG_FEATURES, ARM_SMCCC_TRNG_RND_64, + 0, 0, 0, 0, 0, 0, &res); + priv->smc64 = (res.a0 == ARM_SMCCC_RET_TRNG_SUCCESS); + +#ifdef DEBUG + smccc->invoke_fn(ARM_SMCCC_TRNG_GET_UUID, 0, 0, 0, 0, 0, 0, 0, &res); + if (res.a0 != ARM_SMCCC_RET_TRNG_NOT_SUPPORTED) { + unsigned long uuid_a0 = res.a0; + unsigned long uuid_a1 = res.a1; + unsigned long uuid_a2 = res.a2; + unsigned long uuid_a3 = res.a3; + unsigned long major, minor; + + smccc->invoke_fn(ARM_SMCCC_TRNG_VERSION, 0, 0, 0, 0, 0, 0, 0, &res); + major = (res.a0 & TRNG_MAJOR_MASK) >> TRNG_MAJOR_SHIFT; + minor = (res.a0 & TRNG_MINOR_MASK) >> TRNG_MINOR_SHIFT; + + dev_dbg(dev, "Version %lu.%lu, UUID %08lx-%04lx-%04lx-%04lx-%04lx%08lx\n", + major, minor, uuid_a0, uuid_a1 >> 16, uuid_a1 & GENMASK(16, 0), + uuid_a2 >> 16, uuid_a2 & GENMASK(16, 0), uuid_a3); + } else { + dev_warn(dev, "Can't get TRNG UUID\n"); + } +#endif + + return 0; +} + +U_BOOT_DRIVER(smccc_trng) = { + .name = DRIVER_NAME, + .id = UCLASS_RNG, + .ops = &smccc_trng_ops, + .probe = smccc_trng_probe, + .priv_auto = sizeof(struct smccc_trng_priv), +};