From patchwork Fri May 24 16:26:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 165140 Delivered-To: patch@linaro.org Received: by 2002:a92:9e1a:0:0:0:0:0 with SMTP id q26csp3814281ili; Fri, 24 May 2019 09:27:45 -0700 (PDT) X-Google-Smtp-Source: APXvYqyO2x2lwuBEHalLp4vi3CcokhBfojqR21ILMB0Fg6t1+IQ5qdvU/mg5R2mKw5WBwqw2B3XR X-Received: by 2002:a65:530d:: with SMTP id m13mr11728140pgq.68.1558715265687; Fri, 24 May 2019 09:27:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1558715265; cv=none; d=google.com; s=arc-20160816; b=vKzaqjUL8OPBkc83a96us690LI8QH75ET9Z/yvCVM+s0BL7efntYW81aXSmlE+3Pcg fTXuZbcH/TVXUDbHbo/3XT/7VG2C17omKiH/1//v2XEmrH0HmZzjODqXzRX73lRuLhmN LbHAe5QPvKHaI8GPoHw/aYtlV7d2a3n3/Ea7Q6aogF/3e2FvYKNfy/pouf36YLeOapZR ZaE48OsV5uy38aUgTqCcYTDZbw43hy/hV7a8z+I5G1f0cZPyp8iEU/kjgCQLbe7cMD3y mvKTUWED6BKvG0eBA+jV6K1CkbPvqrT9dEzzfI7rlaViFISzAZYt8pZ1amO4r9Mid2ZA scTA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=fEjtPdaBAqYRZI8UVsqNWtXwmYQF0pkPjODsBVdhtdo=; b=vlDc03d1QoU3mnCdeNLq2B+cEfokA6pUlo6a7intGBGDwdmzPEfhO7hAQ27eTtZQ0f L0BtUuEUPeAYxm+xWANf07FpgAW5X2JY//MtiGHeepfqTEklmSQ2aKOYW+EEyOkLPkwp vOlY/sBFPsq+Np7cLFqgM9jHyR4LtBFjzH5B3zXdl9Hb5w9Vln47TQ7uFccG1Fa4v7BJ 6RbHDFvw0ZHUBxqx2mfrDxHrqBHo1YBW3HfE5nV/5znYqRRGS5NgbyKYsRkK0CYPeQge eJKbOnFb7dS/6OEGjAa//10D1FEU22Qexy4A/y5JGz5RkFcNnQcndKET8tWUWmUP+GjG QX7A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=EAEiG0Sl; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-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 r69si4906966pgr.120.2019.05.24.09.27.45; Fri, 24 May 2019 09:27:45 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-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 header.s=google header.b=EAEiG0Sl; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-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 S2390623AbfEXQ1o (ORCPT + 7 others); Fri, 24 May 2019 12:27:44 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:39770 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390662AbfEXQ1o (ORCPT ); Fri, 24 May 2019 12:27:44 -0400 Received: by mail-wr1-f68.google.com with SMTP id e2so1861543wrv.6 for ; Fri, 24 May 2019 09: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=fEjtPdaBAqYRZI8UVsqNWtXwmYQF0pkPjODsBVdhtdo=; b=EAEiG0Slgf2dbGN1ZsAmwlM5Tw6BOTdlwNxgjGUJjZGjGBni+Sdfph0avf/Abgm9mT n5wtJEO5hw2Myhpzx6upQtWmbH0ERyZh548xHOu+Px9Dtlf8JfMBxR9ttiteYr3rbsZM zZ+lGgHGfvzQOt1nFnBYNhts8lWC3rwwbZb0l1dXNiZt3lt8sGXy463gfoFkQUQmtIjY cFKNC9uNUbeTRlM5fSu75uhD0Q1JzKWdV7gjXLbkdzHO5FEkX13F3RN5oqK3x7vgHakT EPpweoBzV0y/C0Hp4i/mno1z7lac7yQqZEfvU3EMzAMmFOqpEvzh/FDbJ7oNXjp2ezzO xBwg== 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:mime-version:content-transfer-encoding; bh=fEjtPdaBAqYRZI8UVsqNWtXwmYQF0pkPjODsBVdhtdo=; b=mO951NUZ/GnxcsfkTP9nLeVkjyPWl706P1E+4BfIaxsHEuGxa5pZMg7DST89i7nmcd PBTcmJwo96JiOOTl+sCahcqAaRPlvsG91th2KSfEpCx8BULGjsEWeyaHqdkI1aHDeSMy pJ61Y2KRxnjfS8GkP830/hdlKFLZ6Y1a/chzi/B22wPrAyu6M2Kw+H9Xu713I+JanNYL 2ZsfCLVDZ35dPMz9QkWlG9HgEUd+BezNd/pDPhqXftjOaNhVKceIqmEoW353jFAu/hE2 4Trm/NZhGeQhxOX5J7DNHwZmBJod7g2tu0XHcpIPIR3yLpE20oe3IhOqQEWuQZ9sRp+O LeqA== X-Gm-Message-State: APjAAAXgO7gdzko+oIXb6ClkgN000zsgl/oyDlc6pGlsdSabHFKewSuF DmW5CLLjVFoLcGN6gpKik07e9A== X-Received: by 2002:a5d:68d2:: with SMTP id p18mr59634313wrw.56.1558715262003; Fri, 24 May 2019 09:27:42 -0700 (PDT) Received: from sudo.home ([2a01:cb1d:112:6f00:2042:d8f2:ded8:fa95]) by smtp.gmail.com with ESMTPSA id l6sm2200320wmi.24.2019.05.24.09.27.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 24 May 2019 09:27:41 -0700 (PDT) From: Ard Biesheuvel To: linux-crypto@vger.kernel.org Cc: devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Ard Biesheuvel , Herbert Xu , Tudor Ambarus , Linus Walleij , Mika Westerberg Subject: [PATCH v2 4/6] crypto: atmel-i2c: add support for SHA204A random number generator Date: Fri, 24 May 2019 18:26:49 +0200 Message-Id: <20190524162651.28189-5-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190524162651.28189-1-ard.biesheuvel@linaro.org> References: <20190524162651.28189-1-ard.biesheuvel@linaro.org> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The Linaro/96boards Secure96 mezzanine contains (among other things) an Atmel SHA204A symmetric crypto processor. This chip implements a number of different functionalities, but one that is highly useful for many different 96boards platforms is the random number generator. So let's implement a driver for the SHA204A, and for the time being, implement support for the random number generator only. Reviewed-by: Linus Walleij Signed-off-by: Ard Biesheuvel --- drivers/crypto/Kconfig | 14 ++ drivers/crypto/Makefile | 1 + drivers/crypto/atmel-i2c.c | 15 ++ drivers/crypto/atmel-i2c.h | 10 ++ drivers/crypto/atmel-sha204a.c | 171 ++++++++++++++++++++ 5 files changed, 211 insertions(+) -- 2.20.1 diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index ca7a5564e9ce..fe01a9905ab1 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -537,6 +537,20 @@ config CRYPTO_DEV_ATMEL_ECC To compile this driver as a module, choose M here: the module will be called atmel-ecc. +config CRYPTO_DEV_ATMEL_SHA204A + tristate "Support for Microchip / Atmel SHA accelerator and RNG" + depends on I2C + select CRYPTO_DEV_ATMEL_I2C + select HW_RANDOM + help + Microhip / Atmel SHA accelerator and RNG. + Select this if you want to use the Microchip / Atmel SHA204A + module as a random number generator. (Other functions of the + chip are currently not exposed by this driver) + + To compile this driver as a module, choose M here: the module + will be called atmel-sha204a. + config CRYPTO_DEV_CCP bool "Support for AMD Secure Processor" depends on ((X86 && PCI) || (ARM64 && (OF_ADDRESS || ACPI))) && HAS_IOMEM diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 394e84089924..afc4753b5d28 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA) += atmel-sha.o obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o obj-$(CONFIG_CRYPTO_DEV_ATMEL_I2C) += atmel-i2c.o obj-$(CONFIG_CRYPTO_DEV_ATMEL_ECC) += atmel-ecc.o +obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA204A) += atmel-sha204a.o obj-$(CONFIG_CRYPTO_DEV_CAVIUM_ZIP) += cavium/ obj-$(CONFIG_CRYPTO_DEV_CCP) += ccp/ obj-$(CONFIG_CRYPTO_DEV_CCREE) += ccree/ diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 5e099368d120..be49ab7f4338 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -58,6 +58,21 @@ void atmel_i2c_init_read_cmd(struct atmel_i2c_cmd *cmd) } EXPORT_SYMBOL(atmel_i2c_init_read_cmd); +void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd) +{ + cmd->word_addr = COMMAND; + cmd->opcode = OPCODE_RANDOM; + cmd->param1 = 0; + cmd->param2 = 0; + cmd->count = RANDOM_COUNT; + + atmel_i2c_checksum(cmd); + + cmd->msecs = MAX_EXEC_TIME_RANDOM; + cmd->rxsize = RANDOM_RSP_SIZE; +} +EXPORT_SYMBOL(atmel_i2c_init_random_cmd); + void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid) { cmd->word_addr = COMMAND; diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index 82de5166acfa..c6bd43b78f33 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -7,6 +7,8 @@ #ifndef __ATMEL_I2C_H__ #define __ATMEL_I2C_H__ +#include + #define ATMEL_ECC_PRIORITY 300 #define COMMAND 0x03 /* packet function */ @@ -28,6 +30,7 @@ #define GENKEY_RSP_SIZE (ATMEL_ECC_PUBKEY_SIZE + \ CMD_OVERHEAD_SIZE) #define READ_RSP_SIZE (4 + CMD_OVERHEAD_SIZE) +#define RANDOM_RSP_SIZE (32 + CMD_OVERHEAD_SIZE) #define MAX_RSP_SIZE GENKEY_RSP_SIZE /** @@ -96,15 +99,20 @@ static const struct { #define MAX_EXEC_TIME_ECDH 58 #define MAX_EXEC_TIME_GENKEY 115 #define MAX_EXEC_TIME_READ 1 +#define MAX_EXEC_TIME_RANDOM 50 /* Command opcode */ #define OPCODE_ECDH 0x43 #define OPCODE_GENKEY 0x40 #define OPCODE_READ 0x02 +#define OPCODE_RANDOM 0x1b /* Definitions for the READ Command */ #define READ_COUNT 7 +/* Definitions for the RANDOM Command */ +#define RANDOM_COUNT 7 + /* Definitions for the GenKey Command */ #define GENKEY_COUNT 7 #define GENKEY_MODE_PRIVATE 0x04 @@ -142,6 +150,7 @@ struct atmel_i2c_client_priv { u8 wake_token[WAKE_TOKEN_MAX_SIZE]; size_t wake_token_sz; atomic_t tfm_count ____cacheline_aligned; + struct hwrng hwrng; }; /** @@ -179,6 +188,7 @@ void atmel_i2c_enqueue(struct atmel_i2c_work_data *work_data, int atmel_i2c_send_receive(struct i2c_client *client, struct atmel_i2c_cmd *cmd); void atmel_i2c_init_read_cmd(struct atmel_i2c_cmd *cmd); +void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd); void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid); int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, struct scatterlist *pubkey); diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c new file mode 100644 index 000000000000..ea0d2068ea4f --- /dev/null +++ b/drivers/crypto/atmel-sha204a.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Microchip / Atmel SHA204A (I2C) driver. + * + * Copyright (c) 2019 Linaro, Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "atmel-i2c.h" + +static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data, + void *areq, int status) +{ + struct atmel_i2c_client_priv *i2c_priv = work_data->ctx; + struct hwrng *rng = areq; + + if (status) + dev_warn_ratelimited(&i2c_priv->client->dev, + "i2c transaction failed (%d)\n", + status); + + rng->priv = (unsigned long)work_data; + atomic_dec(&i2c_priv->tfm_count); +} + +static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data, + size_t max) +{ + struct atmel_i2c_client_priv *i2c_priv; + struct atmel_i2c_work_data *work_data; + + i2c_priv = container_of(rng, struct atmel_i2c_client_priv, hwrng); + + /* keep maximum 1 asynchronous read in flight at any time */ + if (!atomic_add_unless(&i2c_priv->tfm_count, 1, 1)) + return 0; + + if (rng->priv) { + work_data = (struct atmel_i2c_work_data *)rng->priv; + max = min(sizeof(work_data->cmd.data), max); + memcpy(data, &work_data->cmd.data, max); + rng->priv = 0; + } else { + work_data = kmalloc(sizeof(*work_data), GFP_ATOMIC); + if (!work_data) + return -ENOMEM; + + work_data->ctx = i2c_priv; + work_data->client = i2c_priv->client; + + max = 0; + } + + atmel_i2c_init_random_cmd(&work_data->cmd); + atmel_i2c_enqueue(work_data, atmel_sha204a_rng_done, rng); + + return max; +} + +static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max, + bool wait) +{ + struct atmel_i2c_client_priv *i2c_priv; + struct atmel_i2c_cmd cmd; + int ret; + + if (!wait) + return atmel_sha204a_rng_read_nonblocking(rng, data, max); + + i2c_priv = container_of(rng, struct atmel_i2c_client_priv, hwrng); + + atmel_i2c_init_random_cmd(&cmd); + + ret = atmel_i2c_send_receive(i2c_priv->client, &cmd); + if (ret) + return ret; + + max = min(sizeof(cmd.data), max); + memcpy(data, cmd.data, max); + + return max; +} + +static int atmel_sha204a_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct atmel_i2c_client_priv *i2c_priv; + int ret; + + ret = atmel_i2c_probe(client, id); + if (ret) + return ret; + + i2c_priv = i2c_get_clientdata(client); + + memset(&i2c_priv->hwrng, 0, sizeof(i2c_priv->hwrng)); + + i2c_priv->hwrng.name = dev_name(&client->dev); + i2c_priv->hwrng.read = atmel_sha204a_rng_read; + i2c_priv->hwrng.quality = 1024; + + ret = hwrng_register(&i2c_priv->hwrng); + if (ret) + dev_warn(&client->dev, "failed to register RNG (%d)\n", ret); + + return ret; +} + +static int atmel_sha204a_remove(struct i2c_client *client) +{ + struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client); + + if (atomic_read(&i2c_priv->tfm_count)) { + dev_err(&client->dev, "Device is busy\n"); + return -EBUSY; + } + + if (i2c_priv->hwrng.priv) + kfree((void *)i2c_priv->hwrng.priv); + hwrng_unregister(&i2c_priv->hwrng); + + return 0; +} + +static const struct of_device_id atmel_sha204a_dt_ids[] = { + { .compatible = "atmel,atsha204a", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, atmel_sha204a_dt_ids); + +static const struct i2c_device_id atmel_sha204a_id[] = { + { "atsha204a", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, atmel_sha204a_id); + +static struct i2c_driver atmel_sha204a_driver = { + .probe = atmel_sha204a_probe, + .remove = atmel_sha204a_remove, + .id_table = atmel_sha204a_id, + + .driver.name = "atmel-sha204a", + .driver.of_match_table = of_match_ptr(atmel_sha204a_dt_ids), +}; + +static int __init atmel_sha204a_init(void) +{ + return i2c_add_driver(&atmel_sha204a_driver); +} + +static void __exit atmel_sha204a_exit(void) +{ + flush_scheduled_work(); + i2c_del_driver(&atmel_sha204a_driver); +} + +module_init(atmel_sha204a_init); +module_exit(atmel_sha204a_exit); + +MODULE_AUTHOR("Ard Biesheuvel "); +MODULE_LICENSE("GPL v2");