Commit e22471c2 authored by Jia Jie Ho's avatar Jia Jie Ho Committed by Herbert Xu
Browse files

crypto: starfive - Add AES skcipher and aead support



Adding AES skcipher and aead support to Starfive crypto module.
Skcipher modes of operation include ecb, cbc, ctr, ofb, cfb. Aead modes
include ccm and gcm.

v1->v2:
- Add include interrupt.h to fix compile error. (Herbert)

Co-developed-by: default avatarHuan Feng <huan.feng@starfivetech.com>
Signed-off-by: default avatarHuan Feng <huan.feng@starfivetech.com>
Signed-off-by: default avatarJia Jie Ho <jiajie.ho@starfivetech.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent dd105461
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@ config CRYPTO_DEV_JH7110
	select CRYPTO_SHA512
	select CRYPTO_SM3_GENERIC
	select CRYPTO_RSA
	select CRYPTO_AES
	select CRYPTO_CCM
	help
	  Support for StarFive JH7110 crypto hardware acceleration engine.
	  This module provides acceleration for public key algo,
+1 −1
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0

obj-$(CONFIG_CRYPTO_DEV_JH7110) += jh7110-crypto.o
jh7110-crypto-objs := jh7110-cryp.o jh7110-hash.o jh7110-rsa.o
jh7110-crypto-objs := jh7110-cryp.o jh7110-hash.o jh7110-rsa.o jh7110-aes.o
+1034 −0

File added.

Preview size limit exceeded, changes collapsed.

+30 −6
Original line number Diff line number Diff line
@@ -51,6 +51,13 @@ struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx)
	return cryp;
}

static u16 side_chan;
module_param(side_chan, ushort, 0);
MODULE_PARM_DESC(side_chan, "Enable side channel mitigation for AES module.\n"
			    "Enabling this feature will reduce speed performance.\n"
			    " 0 - Disabled\n"
			    " other - Enabled");

static int starfive_dma_init(struct starfive_cryp_dev *cryp)
{
	dma_cap_mask_t mask;
@@ -82,20 +89,26 @@ static void starfive_dma_cleanup(struct starfive_cryp_dev *cryp)
static irqreturn_t starfive_cryp_irq(int irq, void *priv)
{
	u32 status;
	u32 mask;
	struct starfive_cryp_dev *cryp = (struct starfive_cryp_dev *)priv;

	mask = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
	status = readl(cryp->base + STARFIVE_IE_FLAG_OFFSET);
	if (status & STARFIVE_IE_FLAG_AES_DONE) {
		mask |= STARFIVE_IE_MASK_AES_DONE;
		writel(mask, cryp->base + STARFIVE_IE_MASK_OFFSET);
		tasklet_schedule(&cryp->aes_done);
	}

	if (status & STARFIVE_IE_FLAG_HASH_DONE) {
		status = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
		status |= STARFIVE_IE_MASK_HASH_DONE;
		writel(status, cryp->base + STARFIVE_IE_MASK_OFFSET);
		mask |= STARFIVE_IE_MASK_HASH_DONE;
		writel(mask, cryp->base + STARFIVE_IE_MASK_OFFSET);
		tasklet_schedule(&cryp->hash_done);
	}

	if (status & STARFIVE_IE_FLAG_PKA_DONE) {
		status = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
		status |= STARFIVE_IE_MASK_PKA_DONE;
		writel(status, cryp->base + STARFIVE_IE_MASK_OFFSET);
		mask |= STARFIVE_IE_MASK_PKA_DONE;
		writel(mask, cryp->base + STARFIVE_IE_MASK_OFFSET);
		complete(&cryp->pka_done);
	}

@@ -121,10 +134,12 @@ static int starfive_cryp_probe(struct platform_device *pdev)
		return dev_err_probe(&pdev->dev, PTR_ERR(cryp->base),
				     "Error remapping memory for platform device\n");

	tasklet_init(&cryp->aes_done, starfive_aes_done_task, (unsigned long)cryp);
	tasklet_init(&cryp->hash_done, starfive_hash_done_task, (unsigned long)cryp);

	cryp->phys_base = res->start;
	cryp->dma_maxburst = 32;
	cryp->side_chan = side_chan;

	cryp->hclk = devm_clk_get(&pdev->dev, "hclk");
	if (IS_ERR(cryp->hclk))
@@ -180,6 +195,10 @@ static int starfive_cryp_probe(struct platform_device *pdev)
	if (ret)
		goto err_engine_start;

	ret = starfive_aes_register_algs();
	if (ret)
		goto err_algs_aes;

	ret = starfive_hash_register_algs();
	if (ret)
		goto err_algs_hash;
@@ -193,6 +212,8 @@ static int starfive_cryp_probe(struct platform_device *pdev)
err_algs_rsa:
	starfive_hash_unregister_algs();
err_algs_hash:
	starfive_aes_unregister_algs();
err_algs_aes:
	crypto_engine_stop(cryp->engine);
err_engine_start:
	crypto_engine_exit(cryp->engine);
@@ -207,6 +228,7 @@ static int starfive_cryp_probe(struct platform_device *pdev)
	clk_disable_unprepare(cryp->ahb);
	reset_control_assert(cryp->rst);

	tasklet_kill(&cryp->aes_done);
	tasklet_kill(&cryp->hash_done);
err_probe_defer:
	return ret;
@@ -216,9 +238,11 @@ static void starfive_cryp_remove(struct platform_device *pdev)
{
	struct starfive_cryp_dev *cryp = platform_get_drvdata(pdev);

	starfive_aes_unregister_algs();
	starfive_hash_unregister_algs();
	starfive_rsa_unregister_algs();

	tasklet_kill(&cryp->aes_done);
	tasklet_kill(&cryp->hash_done);

	crypto_engine_stop(cryp->engine);
+65 −0
Original line number Diff line number Diff line
@@ -5,7 +5,9 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/interrupt.h>

#include <crypto/aes.h>
#include <crypto/engine.h>
#include <crypto/sha2.h>
#include <crypto/sm3.h>
@@ -17,13 +19,56 @@
#define STARFIVE_DMA_IN_LEN_OFFSET		0x10
#define STARFIVE_DMA_OUT_LEN_OFFSET		0x14

#define STARFIVE_IE_MASK_AES_DONE		0x1
#define STARFIVE_IE_MASK_HASH_DONE		0x4
#define STARFIVE_IE_MASK_PKA_DONE		0x8
#define STARFIVE_IE_FLAG_AES_DONE		0x1
#define STARFIVE_IE_FLAG_HASH_DONE		0x4
#define STARFIVE_IE_FLAG_PKA_DONE		0x8

#define STARFIVE_MSG_BUFFER_SIZE		SZ_16K
#define MAX_KEY_SIZE				SHA512_BLOCK_SIZE
#define STARFIVE_AES_IV_LEN			AES_BLOCK_SIZE
#define STARFIVE_AES_CTR_LEN			AES_BLOCK_SIZE

union starfive_aes_csr {
	u32 v;
	struct {
		u32 cmode			:1;
#define STARFIVE_AES_KEYMODE_128		0x0
#define STARFIVE_AES_KEYMODE_192		0x1
#define STARFIVE_AES_KEYMODE_256		0x2
		u32 keymode			:2;
#define STARFIVE_AES_BUSY			BIT(3)
		u32 busy			:1;
		u32 done			:1;
#define STARFIVE_AES_KEY_DONE			BIT(5)
		u32 krdy			:1;
		u32 aesrst			:1;
		u32 ie				:1;
#define STARFIVE_AES_CCM_START			BIT(8)
		u32 ccm_start			:1;
#define STARFIVE_AES_MODE_ECB			0x0
#define STARFIVE_AES_MODE_CBC			0x1
#define STARFIVE_AES_MODE_CFB			0x2
#define STARFIVE_AES_MODE_OFB			0x3
#define STARFIVE_AES_MODE_CTR			0x4
#define STARFIVE_AES_MODE_CCM			0x5
#define STARFIVE_AES_MODE_GCM			0x6
		u32 mode			:3;
#define STARFIVE_AES_GCM_START			BIT(12)
		u32 gcm_start			:1;
#define STARFIVE_AES_GCM_DONE			BIT(13)
		u32 gcm_done			:1;
		u32 delay_aes			:1;
		u32 vaes_start			:1;
		u32 rsvd_0			:8;
#define STARFIVE_AES_MODE_XFB_1			0x0
#define STARFIVE_AES_MODE_XFB_128		0x5
		u32 stmode			:3;
		u32 rsvd_1			:5;
	};
};

union starfive_hash_csr {
	u32 v;
@@ -116,6 +161,7 @@ struct starfive_cryp_ctx {
	struct starfive_rsa_key			rsa_key;
	struct crypto_akcipher			*akcipher_fbk;
	struct crypto_ahash			*ahash_fbk;
	struct crypto_aead			*aead_fbk;
};

struct starfive_cryp_dev {
@@ -133,13 +179,26 @@ struct starfive_cryp_dev {
	struct dma_chan				*rx;
	struct dma_slave_config			cfg_in;
	struct dma_slave_config			cfg_out;
	struct scatter_walk			in_walk;
	struct scatter_walk			out_walk;
	struct crypto_engine			*engine;
	struct tasklet_struct			aes_done;
	struct tasklet_struct			hash_done;
	struct completion			pka_done;
	size_t					assoclen;
	size_t					total_in;
	size_t					total_out;
	u32					tag_in[4];
	u32					tag_out[4];
	unsigned int				authsize;
	unsigned long				flags;
	int					err;
	bool					side_chan;
	union starfive_alg_cr			alg_cr;
	union {
		struct ahash_request		*hreq;
		struct aead_request		*areq;
		struct skcipher_request		*sreq;
	} req;
};

@@ -147,6 +206,7 @@ struct starfive_cryp_request_ctx {
	union {
		union starfive_hash_csr		hash;
		union starfive_pka_cacr		pka;
		union starfive_aes_csr		aes;
	} csr;

	struct scatterlist			*in_sg;
@@ -157,6 +217,7 @@ struct starfive_cryp_request_ctx {
	unsigned int				blksize;
	unsigned int				digsize;
	unsigned long				in_sg_len;
	unsigned char				*adata;
	u8 rsa_data[] __aligned(sizeof(u32));
};

@@ -168,5 +229,9 @@ void starfive_hash_unregister_algs(void);
int starfive_rsa_register_algs(void);
void starfive_rsa_unregister_algs(void);

int starfive_aes_register_algs(void);
void starfive_aes_unregister_algs(void);

void starfive_hash_done_task(unsigned long param);
void starfive_aes_done_task(unsigned long param);
#endif