From patchwork Tue May 18 07:09:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Stanley X-Patchwork-Id: 1480059 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=mGpVhyjs; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FknFP0VV2z9sW1 for ; Tue, 18 May 2021 17:10:01 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 52CC782D52; Tue, 18 May 2021 09:09:49 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=jms.id.au Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="mGpVhyjs"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 21F0582D52; Tue, 18 May 2021 09:09:48 +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=1.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_SBL_CSS,SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.2 Received: from mail-pf1-x42a.google.com (mail-pf1-x42a.google.com [IPv6:2607:f8b0:4864:20::42a]) (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 D3BD782E56 for ; Tue, 18 May 2021 09:09:38 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=jms.id.au Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=joel.stan@gmail.com Received: by mail-pf1-x42a.google.com with SMTP id d16so6713553pfn.12 for ; Tue, 18 May 2021 00:09:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=XI3w6x/unPu8z+bHFiKw9PwjebBNAo8KWHx+7e1Elng=; b=mGpVhyjsrNng9L1hTNgGvZU9G+QOLLXlxpxkatfg6EtqqtrM15SKcF/vXsiYiO0YXZ tSGvna9Ue7YD3ETzO9f2Uk6l1f06x3SnQ1J0jZR+WIUuzGENOvXsDV77te/sQh1UYaUC htnj0vbw43ohdk+AY4JWzhNNf0OJooy+/nR4qrCy0dIeam4oLxnDYIevAVBLTJkRxWpg lx9Po5H1ilC7dc7R88tQ4YFGxWut8hqnb1ynBwK6KTOLPc6/TxFpVrQN7BU84Zg66GTU mEqYGCmGBQBn+5/TS6kwOYejWrFhF4hC14EppJqET0a+uvefFb2+ENhPrqpWcxRz25Ry IbFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :mime-version:content-transfer-encoding; bh=XI3w6x/unPu8z+bHFiKw9PwjebBNAo8KWHx+7e1Elng=; b=j3qR9ckHPShcX+qhxRwZAgQgsufvlOefo7jYQ/GG6J/koedmLgEfZ4eJKtRzULVRrq t7KNUNR2oB+iqdrKsZ/X/8+UrmujtWCxPTSuRlHfUnIRvD3QdQ5io5ZOaU/HYWJYeSym xf7VNVcqBDKJIdc4CjKj/cmc71dDPW78tDyFzEg1bjHBEtzgT5UGdcdAw8St16Kky8aj Q9SgPKqyIxPzOdFjwqVVeVGZ2T9iznEua5c9vhSkeNaEBDao8GNRiESe00oOSsJciX+O kIPZEPZOPevyoizua17o3zn0f5BKxWjgDHSHI253vlcqlnaaKELfkHcjd9wgQzUwmGcP Cd2w== X-Gm-Message-State: AOAM533otpmatM0CTZjMzR9kNqX8yCMmyLEa/u4Cnx7/Ct7Vr705AL/B IDgl5vXXURvFmL22jPERGUs= X-Google-Smtp-Source: ABdhPJydLRbQuF14gOZPQNX1fFz9595yiQJ2rJI0ZpU28UQa5Ba/DN2X1gy+PeW8Ic48EElP7co3vg== X-Received: by 2002:aa7:954d:0:b029:29f:d9a6:63d7 with SMTP id w13-20020aa7954d0000b029029fd9a663d7mr3625488pfq.58.1621321777067; Tue, 18 May 2021 00:09:37 -0700 (PDT) Received: from localhost.localdomain ([45.124.203.14]) by smtp.gmail.com with ESMTPSA id m17sm11408381pfo.2.2021.05.18.00.09.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 May 2021 00:09:35 -0700 (PDT) From: Joel Stanley To: Chia-Wei Wang , Ryan Chen , Simon Glass , u-boot@lists.denx.de Cc: BMC-SW@aspeedtech.com, klaus@linux.vnet.ibm.com, Andrew Jeffery , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [PATCH] crypto: Add driver for Aspeed HACE Date: Tue, 18 May 2021 16:39:26 +0930 Message-Id: <20210518070926.604053-1-joel@jms.id.au> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.4 at phobos.denx.de X-Virus-Status: Clean The HACE supports MD5, SHA1 and SHA2 family hash functions. This driver uses it in a polling mode to perform hash calculations over buffers placed in DRAM. It registers a driver to allow the hardware's clocking to be enabled using the clock framework. Co-developed-by: Klaus Heinrich Kiwi Signed-off-by: Klaus Heinrich Kiwi Signed-off-by: Joel Stanley --- configs/evb-ast2600_defconfig | 1 + drivers/crypto/Kconfig | 19 +++ drivers/crypto/Makefile | 1 + drivers/crypto/aspeed_hace.c | 256 ++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+) create mode 100644 drivers/crypto/aspeed_hace.c diff --git a/configs/evb-ast2600_defconfig b/configs/evb-ast2600_defconfig index 91518dbe3589..52ae8e423bfd 100644 --- a/configs/evb-ast2600_defconfig +++ b/configs/evb-ast2600_defconfig @@ -45,6 +45,7 @@ CONFIG_REGMAP=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_CLK=y CONFIG_SPL_CLK=y +CONFIG_ASPEED_HACE=y CONFIG_DM_I2C=y CONFIG_MISC=y CONFIG_SPL_MISC=y diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 1ea116be7503..e92037d88906 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -2,4 +2,23 @@ menu "Hardware crypto devices" source drivers/crypto/fsl/Kconfig +config ASPEED_HACE + bool "ASPEED Hash and Crypto Engine" + depends on ASPEED_AST2600 + imply SHA_HW_ACCEL + imply SHA_PROG_HW_ACCEL + imply SHA512 + imply SHA512_ALGO + imply CMD_HASH + help + Select this option to enable a driver for using the SHA engine in + the ASPEED BMC SoCs. + + Enabling this allows the use of SHA operations in hardware without requiring the + SHA software implementations, saving code size. + + Due to hardware limitations it cannot be used with a FIT placed in SPI + FLASH. Data can only be hashed if it is in SDRAM, making this relevant + for MMC and network boot only. + endmenu diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index efbd1d3fca05..ac93b1295954 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -4,5 +4,6 @@ # http://www.samsung.com obj-$(CONFIG_EXYNOS_ACE_SHA) += ace_sha.o +obj-$(CONFIG_ASPEED_HACE) += aspeed_hace.o obj-y += rsa_mod_exp/ obj-y += fsl/ diff --git a/drivers/crypto/aspeed_hace.c b/drivers/crypto/aspeed_hace.c new file mode 100644 index 000000000000..941c1555fe5c --- /dev/null +++ b/drivers/crypto/aspeed_hace.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// +// (C) Copyright ASPEED Technology Inc. +// Copyright 2021 IBM Corp. + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#define ASPEED_HACE_STS 0x1C +#define HACE_RSA_ISR BIT(13) +#define HACE_CRYPTO_ISR BIT(12) +#define HACE_HASH_ISR BIT(9) +#define HACE_RSA_BUSY BIT(2) +#define HACE_CRYPTO_BUSY BIT(1) +#define HACE_HASH_BUSY BIT(0) +#define ASPEED_HACE_HASH_SRC 0x20 +#define ASPEED_HACE_HASH_DIGEST_BUFF 0x24 +#define ASPEED_HACE_HASH_KEY_BUFF 0x28 +#define ASPEED_HACE_HASH_DATA_LEN 0x2C +#define HACE_SG_LAST BIT(31) +#define ASPEED_HACE_HASH_CMD 0x30 +#define HACE_SHA_BE_EN BIT(3) +#define HACE_MD5_LE_EN BIT(2) +#define HACE_ALGO_MD5 0 +#define HACE_ALGO_SHA1 BIT(5) +#define HACE_ALGO_SHA224 BIT(6) +#define HACE_ALGO_SHA256 (BIT(4) | BIT(6)) +#define HACE_ALGO_SHA512 (BIT(5) | BIT(6)) +#define HACE_ALGO_SHA384 (BIT(5) | BIT(6) | BIT(10)) +#define HACE_SG_EN BIT(18) + +#define ASPEED_MAX_SG 32 + +struct aspeed_sg { + u32 len; + u32 addr; +}; + +struct aspeed_hash_ctx { + u32 method; + u32 digest_size; + u32 len; + u32 count; + struct aspeed_sg list[ASPEED_MAX_SG]; /* Must be 8 byte aligned */ +}; + +struct aspeed_hace { + struct clk clk; +}; + +static phys_addr_t base; + +static int aspeed_hace_wait_completion(u32 reg, u32 flag, int timeout_us) +{ + u32 val; + + return readl_poll_timeout(reg, val, (val & flag) == flag, timeout_us); +} + +static int digest_object(const void *src, unsigned int length, void *digest, u32 method) +{ + if (!((u32)src & BIT(31))) { + debug("HACE src out of bounds: can only copy from SDRAM\n"); + return -EINVAL; + } + + if ((u32)digest & 0x7) { + debug("HACE dest alignment incorrect: %p\n", digest); + return -EINVAL; + } + + if (readl(base + ASPEED_HACE_STS) & HACE_HASH_BUSY) { + debug("HACE error: engine busy\n"); + return -EBUSY; + } + + /* Clear pending completion status */ + writel(HACE_HASH_ISR, base + ASPEED_HACE_STS); + + writel((u32)src, base + ASPEED_HACE_HASH_SRC); + writel((u32)digest, base + ASPEED_HACE_HASH_DIGEST_BUFF); + writel(length, base + ASPEED_HACE_HASH_DATA_LEN); + writel(HACE_SHA_BE_EN | method, base + ASPEED_HACE_HASH_CMD); + + /* SHA512 hashing appears to have a througput of about 12MB/s */ + return aspeed_hace_wait_completion(base + ASPEED_HACE_STS, + HACE_HASH_ISR, + 1000 + (length >> 3)); +} + +void hw_sha1(const unsigned char *pbuf, unsigned int buf_len, + unsigned char *pout, unsigned int chunk_size) +{ + int rc; + + rc = digest_object(pbuf, buf_len, pout, HACE_ALGO_SHA1); + if (rc) + debug("HACE failure: %d\n", rc); +} + +void hw_sha256(const unsigned char *pbuf, unsigned int buf_len, + unsigned char *pout, unsigned int chunk_size) +{ + int rc; + + rc = digest_object(pbuf, buf_len, pout, HACE_ALGO_SHA256); + if (rc) + debug("HACE failure: %d\n", rc); +} + +void hw_sha512(const unsigned char *pbuf, unsigned int buf_len, + unsigned char *pout, unsigned int chunk_size) +{ + int rc; + + rc = digest_object(pbuf, buf_len, pout, HACE_ALGO_SHA512); + if (rc) + debug("HACE failure: %d\n", rc); +} + +int hw_sha_init(struct hash_algo *algo, void **ctxp) +{ + struct aspeed_hash_ctx *ctx; + u32 method; + + if (!strcmp(algo->name, "sha1")) + method = HACE_ALGO_SHA1; + else if (!strcmp(algo->name, "sha256")) + method = HACE_ALGO_SHA256; + else if (!strcmp(algo->name, "sha512")) + method = HACE_ALGO_SHA512; + else + return -ENOTSUPP; + } + + ctx = memalign(8, sizeof(*ctx)); + if (!ctx) { + debug("HACE error: Cannot allocate memory for context\n"); + return -ENOMEM; + } + + memset(ctx, '\0', sizeof(*ctx)); + + if (((uintptr_t)ctx->list & 0x3) != 0) { + printf("HACE error: Invalid alignment for input data\n"); + return -EINVAL; + } + + ctx->method = method | HACE_SG_EN; + ctx->digest_size = algo->digest_size; + *ctxp = ctx; + + return 0; +} + +int hw_sha_update(struct hash_algo *algo, void *hash_ctx, const void *buf, + unsigned int size, int is_last) +{ + struct aspeed_hash_ctx *ctx = hash_ctx; + struct aspeed_sg *sg = &ctx->list[ctx->count]; + + if (ctx->count >= ARRAY_SIZE(ctx->list)) { + debug("HACE error: Reached maximum number of hash segments\n"); + free(ctx); + return -EINVAL; + } + + sg->addr = (u32)buf; + sg->len = size; + if (is_last) + sg->len |= HACE_SG_LAST; + + ctx->count++; + ctx->len += size; + + return 0; +} + +int hw_sha_finish(struct hash_algo *algo, void *hash_ctx, void *dest_buf, int size) +{ + struct aspeed_hash_ctx *ctx = hash_ctx; + int rc; + + if (size < ctx->digest_size) { + debug("HACE error: insufficient size on destination buffer\n"); + free(ctx); + return -EINVAL; + } + + rc = digest_object(ctx->list, ctx->len, dest_buf, ctx->method); + if (rc) + debug("HACE Scatter-Gather failure\n"); + + free(ctx); + + return rc; +} + +static int aspeed_hace_probe(struct udevice *dev) +{ + struct aspeed_hace *hace = dev_get_priv(dev); + int ret; + + ret = clk_get_by_index(dev, 0, &hace->clk); + if (ret < 0) { + debug("Can't get clock for %s: %d\n", dev->name, ret); + return ret; + } + + ret = clk_enable(&hace->clk); + if (ret) { + debug("Failed to enable fsi clock (%d)\n", ret); + return ret; + } + + /* As the crypto code does not pass us any driver state */ + base = devfdt_get_addr(dev); + + return ret; +} + +static int aspeed_hace_remove(struct udevice *dev) +{ + struct aspeed_hace *hace = dev_get_priv(dev); + + clk_disable(&hace->clk); + + return 0; +} + +static const struct udevice_id aspeed_hace_ids[] = { + { .compatible = "aspeed,ast2600-hace" }, + { } +}; + +U_BOOT_DRIVER(aspeed_hace) = { + .name = "aspeed_hace", + .id = UCLASS_MISC, + .of_match = aspeed_hace_ids, + .probe = aspeed_hace_probe, + .remove = aspeed_hace_remove, + .priv_auto = sizeof(struct aspeed_hace), +};