From patchwork Mon Dec 5 10:48:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corentin Labbe X-Patchwork-Id: 9460815 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2AA9160236 for ; Mon, 5 Dec 2016 10:53:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1CA9C25250 for ; Mon, 5 Dec 2016 10:53:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0DEA826247; Mon, 5 Dec 2016 10:53:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 83F4F25250 for ; Mon, 5 Dec 2016 10:53:04 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1cDqri-0006TN-HT; Mon, 05 Dec 2016 10:51:22 +0000 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1cDqre-0006Km-L2 for linux-arm-kernel@lists.infradead.org; Mon, 05 Dec 2016 10:51:20 +0000 Received: by mail-wm0-x241.google.com with SMTP id m203so15070360wma.3 for ; Mon, 05 Dec 2016 02:50:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=H7OajElKzgk4L3ClHKNzbvQQ24FCJgv/ssN3u8mSDNM=; b=mZut9E1flY28sNklWNTAJSy6ItXv1qOqj6cxKU0NuMCkhSs5Ld4bsRA6Y7p3sEMqFm XXUrUfltFNN3+XxC3nJ4vf8w2z09VsCaCq2FfSLvPcXdE4wjUBdbCSjl0QW8m7c+ZWlv +d2AVQ4fDOPA1Uk1cDBcm8SGr/8aP4IR05hADZuzDr1jPTK/OvQaTM0+VbOs+990qCB1 j2KzUEvJcryW2ajC7OJjPcWDcShUcgLh9QUWyx1eaka0TK1xodF64q/OuyblEXlKn5R2 EJ6gCIrEmC5Ix9qIHbuucWbjAl5UC9YAa9F0R/Om91TrdFUK61Uuk7ceLfcU5jkjVL8c NhOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=H7OajElKzgk4L3ClHKNzbvQQ24FCJgv/ssN3u8mSDNM=; b=eysOYGE7IjfbaNZqkEWYx1MUb//DITFZ0PrNrD7Rmv3wqwNJluMco5LB9BXWKHLZ4a XLvD/lPTzr+N4RuxBDdhP+D4Y+u6KkLP1A+hIwcJJX1tJNAcr9z1xyjMJ1znwFyfkeP+ kpJea9oEC8fcb9lxAgtB8U22HyY9rNgsTvBLHZOfDueyMNkLgb3p7lyoFBidcsATihrq X52IolXNxYxpKMIekV9FOS6otat8Esp/mhQqIU/sfzxBzlPEehnsF67hxZpTBILKDAZf 2k2t4XV6lnMM6k9472gVmSjlgfpt2ZFBgB3KlP9gLfTk7wO+navsIQyh+GYgbOb74++6 ba5w== X-Gm-Message-State: AKaTC02wHBpD2NKlGKFMr/mgSCoFAdrD3nCuN6B9klDWiA+XR/Bhp/g19oAoZctq9wg6XQ== X-Received: by 10.28.227.215 with SMTP id a206mr9488298wmh.84.1480935056647; Mon, 05 Dec 2016 02:50:56 -0800 (PST) Received: from Red.local (LFbn-1-7035-57.w90-116.abo.wanadoo.fr. [90.116.208.57]) by smtp.googlemail.com with ESMTPSA id bf2sm19689152wjc.48.2016.12.05.02.50.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 05 Dec 2016 02:50:56 -0800 (PST) From: Corentin Labbe To: herbert@gondor.apana.org.au, davem@davemloft.net, maxime.ripard@free-electrons.com, wens@csie.org Subject: [PATCH v2] crypto: sun4i-ss: support the Security System PRNG Date: Mon, 5 Dec 2016 11:48:42 +0100 Message-Id: <1480934922-20732-1-git-send-email-clabbe.montjoie@gmail.com> X-Mailer: git-send-email 2.7.3 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161205_025118_979467_EBF30DC3 X-CRM114-Status: GOOD ( 22.85 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: LABBE Corentin , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-crypto@vger.kernel.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: LABBE Corentin The Security System have a PRNG. This patch add support for it as an hwrng. Signed-off-by: Corentin Labbe --- Changes since v1: - Replaced all spin_lock_bh by simple spin_lock - Removed handling of size not modulo 4 which will never happen - Added add_random_ready_callback() drivers/crypto/Kconfig | 8 +++ drivers/crypto/sunxi-ss/Makefile | 1 + drivers/crypto/sunxi-ss/sun4i-ss-core.c | 14 +++++ drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c | 99 ++++++++++++++++++++++++++++++++ drivers/crypto/sunxi-ss/sun4i-ss.h | 9 +++ 5 files changed, 131 insertions(+) create mode 100644 drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 4d2b81f..38f7aca 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -538,6 +538,14 @@ config CRYPTO_DEV_SUN4I_SS To compile this driver as a module, choose M here: the module will be called sun4i-ss. +config CRYPTO_DEV_SUN4I_SS_PRNG + bool "Support for Allwinner Security System PRNG" + depends on CRYPTO_DEV_SUN4I_SS + select HW_RANDOM + help + This driver provides kernel-side support for the Pseudo-Random + Number Generator found in the Security System. + config CRYPTO_DEV_ROCKCHIP tristate "Rockchip's Cryptographic Engine driver" depends on OF && ARCH_ROCKCHIP diff --git a/drivers/crypto/sunxi-ss/Makefile b/drivers/crypto/sunxi-ss/Makefile index 8f4c7a2..ca049ee 100644 --- a/drivers/crypto/sunxi-ss/Makefile +++ b/drivers/crypto/sunxi-ss/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o +sun4i-ss-$(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) += sun4i-ss-hwrng.o diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-core.c b/drivers/crypto/sunxi-ss/sun4i-ss-core.c index 3ac6c6c..fa739de 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c @@ -359,6 +359,16 @@ static int sun4i_ss_probe(struct platform_device *pdev) } } platform_set_drvdata(pdev, ss); + +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG + /* Voluntarily made the PRNG optional */ + err = sun4i_ss_hwrng_register(&ss->hwrng); + if (!err) + dev_info(ss->dev, "sun4i-ss PRNG loaded"); + else + dev_err(ss->dev, "sun4i-ss PRNG failed"); +#endif + return 0; error_alg: i--; @@ -386,6 +396,10 @@ static int sun4i_ss_remove(struct platform_device *pdev) int i; struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev); +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG + sun4i_ss_hwrng_remove(&ss->hwrng); +#endif + for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { switch (ss_algs[i].type) { case CRYPTO_ALG_TYPE_ABLKCIPHER: diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c b/drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c new file mode 100644 index 0000000..8319cae --- /dev/null +++ b/drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c @@ -0,0 +1,99 @@ +#include "sun4i-ss.h" + +static void sun4i_ss_seed(struct random_ready_callback *rdy) +{ + struct sun4i_ss_ctx *ss; + + ss = container_of(rdy, struct sun4i_ss_ctx, random_ready); + get_random_bytes(ss->seed, SS_SEED_LEN); + ss->random_ready.func = NULL; +} + +static int sun4i_ss_hwrng_init(struct hwrng *hwrng) +{ + struct sun4i_ss_ctx *ss; + int ret; + + ss = container_of(hwrng, struct sun4i_ss_ctx, hwrng); + + ss->random_ready.owner = THIS_MODULE; + ss->random_ready.func = sun4i_ss_seed; + + ret = add_random_ready_callback(&ss->random_ready); + switch (ret) { + case 0: + break; + case -EALREADY: + get_random_bytes(ss->seed, SS_SEED_LEN); + ss->random_ready.func = NULL; + ret = 0; + break; + default: + ss->random_ready.func = NULL; + } + + return ret; +} + +static int sun4i_ss_hwrng_read(struct hwrng *hwrng, void *buf, + size_t max, bool wait) +{ + int i; + u32 v; + u32 *data = buf; + const u32 mode = SS_OP_PRNG | SS_PRNG_CONTINUE | SS_ENABLED; + size_t len; + struct sun4i_ss_ctx *ss; + + ss = container_of(hwrng, struct sun4i_ss_ctx, hwrng); + len = min_t(size_t, SS_DATA_LEN, max); + + /* If the PRNG is not seeded */ + if (ss->random_ready.func) + return -EAGAIN; + + spin_lock(&ss->slock); + + writel(mode, ss->base + SS_CTL); + + /* write the seed */ + for (i = 0; i < SS_SEED_LEN / 4; i++) + writel(ss->seed[i], ss->base + SS_KEY0 + i * 4); + writel(mode | SS_PRNG_START, ss->base + SS_CTL); + + /* Read the random data */ + readsl(ss->base + SS_TXFIFO, data, len / 4); + + /* Update the seed */ + for (i = 0; i < SS_SEED_LEN / 4; i++) { + v = readl(ss->base + SS_KEY0 + i * 4); + ss->seed[i] = v; + } + + writel(0, ss->base + SS_CTL); + spin_unlock(&ss->slock); + return len; +} + +int sun4i_ss_hwrng_register(struct hwrng *hwrng) +{ + hwrng->name = "sun4i Security System PRNG"; + hwrng->init = sun4i_ss_hwrng_init; + hwrng->read = sun4i_ss_hwrng_read; + hwrng->quality = 1000; + + /* Cannot use devm_hwrng_register() since we need to hwrng_unregister + * before stopping clocks/regulator + */ + return hwrng_register(hwrng); +} + +void sun4i_ss_hwrng_remove(struct hwrng *hwrng) +{ + struct sun4i_ss_ctx *ss; + + ss = container_of(hwrng, struct sun4i_ss_ctx, hwrng); + if (ss->random_ready.func) + del_random_ready_callback(&ss->random_ready); + hwrng_unregister(hwrng); +} diff --git a/drivers/crypto/sunxi-ss/sun4i-ss.h b/drivers/crypto/sunxi-ss/sun4i-ss.h index f04c0f8..85772d7 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss.h +++ b/drivers/crypto/sunxi-ss/sun4i-ss.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -125,6 +126,9 @@ #define SS_RXFIFO_EMP_INT_ENABLE (1 << 2) #define SS_TXFIFO_AVA_INT_ENABLE (1 << 0) +#define SS_SEED_LEN (192 / 8) +#define SS_DATA_LEN (160 / 8) + struct sun4i_ss_ctx { void __iomem *base; int irq; @@ -134,6 +138,9 @@ struct sun4i_ss_ctx { struct device *dev; struct resource *res; spinlock_t slock; /* control the use of the device */ + struct random_ready_callback random_ready; + struct hwrng hwrng; + u32 seed[SS_SEED_LEN / 4]; }; struct sun4i_ss_alg_template { @@ -199,3 +206,5 @@ int sun4i_ss_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen); int sun4i_ss_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen); +int sun4i_ss_hwrng_register(struct hwrng *hwrng); +void sun4i_ss_hwrng_remove(struct hwrng *hwrng);