15eb7e946SCorentin Labbe // SPDX-License-Identifier: GPL-2.0
25eb7e946SCorentin Labbe /*
35eb7e946SCorentin Labbe * sun8i-ce-prng.c - hardware cryptographic offloader for
45eb7e946SCorentin Labbe * Allwinner H3/A64/H5/H2+/H6/R40 SoC
55eb7e946SCorentin Labbe *
65eb7e946SCorentin Labbe * Copyright (C) 2015-2020 Corentin Labbe <clabbe@baylibre.com>
75eb7e946SCorentin Labbe *
85eb7e946SCorentin Labbe * This file handle the PRNG
95eb7e946SCorentin Labbe *
10*39db3f15SJonathan Corbet * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
115eb7e946SCorentin Labbe */
125eb7e946SCorentin Labbe #include "sun8i-ce.h"
135eb7e946SCorentin Labbe #include <linux/dma-mapping.h>
145eb7e946SCorentin Labbe #include <linux/pm_runtime.h>
155eb7e946SCorentin Labbe #include <crypto/internal/rng.h>
165eb7e946SCorentin Labbe
sun8i_ce_prng_init(struct crypto_tfm * tfm)175eb7e946SCorentin Labbe int sun8i_ce_prng_init(struct crypto_tfm *tfm)
185eb7e946SCorentin Labbe {
195eb7e946SCorentin Labbe struct sun8i_ce_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
205eb7e946SCorentin Labbe
215eb7e946SCorentin Labbe memset(ctx, 0, sizeof(struct sun8i_ce_rng_tfm_ctx));
225eb7e946SCorentin Labbe return 0;
235eb7e946SCorentin Labbe }
245eb7e946SCorentin Labbe
sun8i_ce_prng_exit(struct crypto_tfm * tfm)255eb7e946SCorentin Labbe void sun8i_ce_prng_exit(struct crypto_tfm *tfm)
265eb7e946SCorentin Labbe {
275eb7e946SCorentin Labbe struct sun8i_ce_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
285eb7e946SCorentin Labbe
29c391714cSJason Wang kfree_sensitive(ctx->seed);
305eb7e946SCorentin Labbe ctx->seed = NULL;
315eb7e946SCorentin Labbe ctx->slen = 0;
325eb7e946SCorentin Labbe }
335eb7e946SCorentin Labbe
sun8i_ce_prng_seed(struct crypto_rng * tfm,const u8 * seed,unsigned int slen)345eb7e946SCorentin Labbe int sun8i_ce_prng_seed(struct crypto_rng *tfm, const u8 *seed,
355eb7e946SCorentin Labbe unsigned int slen)
365eb7e946SCorentin Labbe {
375eb7e946SCorentin Labbe struct sun8i_ce_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
385eb7e946SCorentin Labbe
395eb7e946SCorentin Labbe if (ctx->seed && ctx->slen != slen) {
40c391714cSJason Wang kfree_sensitive(ctx->seed);
415eb7e946SCorentin Labbe ctx->slen = 0;
425eb7e946SCorentin Labbe ctx->seed = NULL;
435eb7e946SCorentin Labbe }
445eb7e946SCorentin Labbe if (!ctx->seed)
455eb7e946SCorentin Labbe ctx->seed = kmalloc(slen, GFP_KERNEL | GFP_DMA);
465eb7e946SCorentin Labbe if (!ctx->seed)
475eb7e946SCorentin Labbe return -ENOMEM;
485eb7e946SCorentin Labbe
495eb7e946SCorentin Labbe memcpy(ctx->seed, seed, slen);
505eb7e946SCorentin Labbe ctx->slen = slen;
515eb7e946SCorentin Labbe
525eb7e946SCorentin Labbe return 0;
535eb7e946SCorentin Labbe }
545eb7e946SCorentin Labbe
sun8i_ce_prng_generate(struct crypto_rng * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int dlen)555eb7e946SCorentin Labbe int sun8i_ce_prng_generate(struct crypto_rng *tfm, const u8 *src,
565eb7e946SCorentin Labbe unsigned int slen, u8 *dst, unsigned int dlen)
575eb7e946SCorentin Labbe {
585eb7e946SCorentin Labbe struct sun8i_ce_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
595eb7e946SCorentin Labbe struct rng_alg *alg = crypto_rng_alg(tfm);
605eb7e946SCorentin Labbe struct sun8i_ce_alg_template *algt;
615eb7e946SCorentin Labbe struct sun8i_ce_dev *ce;
625eb7e946SCorentin Labbe dma_addr_t dma_iv, dma_dst;
635eb7e946SCorentin Labbe int err = 0;
645eb7e946SCorentin Labbe int flow = 3;
655eb7e946SCorentin Labbe unsigned int todo;
665eb7e946SCorentin Labbe struct sun8i_ce_flow *chan;
675eb7e946SCorentin Labbe struct ce_task *cet;
685eb7e946SCorentin Labbe u32 common, sym;
695eb7e946SCorentin Labbe void *d;
705eb7e946SCorentin Labbe
715eb7e946SCorentin Labbe algt = container_of(alg, struct sun8i_ce_alg_template, alg.rng);
725eb7e946SCorentin Labbe ce = algt->ce;
735eb7e946SCorentin Labbe
745eb7e946SCorentin Labbe if (ctx->slen == 0) {
755eb7e946SCorentin Labbe dev_err(ce->dev, "not seeded\n");
765eb7e946SCorentin Labbe return -EINVAL;
775eb7e946SCorentin Labbe }
785eb7e946SCorentin Labbe
795eb7e946SCorentin Labbe /* we want dlen + seedsize rounded up to a multiple of PRNG_DATA_SIZE */
805eb7e946SCorentin Labbe todo = dlen + ctx->slen + PRNG_DATA_SIZE * 2;
815eb7e946SCorentin Labbe todo -= todo % PRNG_DATA_SIZE;
825eb7e946SCorentin Labbe
835eb7e946SCorentin Labbe d = kzalloc(todo, GFP_KERNEL | GFP_DMA);
845eb7e946SCorentin Labbe if (!d) {
855eb7e946SCorentin Labbe err = -ENOMEM;
865eb7e946SCorentin Labbe goto err_mem;
875eb7e946SCorentin Labbe }
885eb7e946SCorentin Labbe
895eb7e946SCorentin Labbe dev_dbg(ce->dev, "%s PRNG slen=%u dlen=%u todo=%u multi=%u\n", __func__,
905eb7e946SCorentin Labbe slen, dlen, todo, todo / PRNG_DATA_SIZE);
915eb7e946SCorentin Labbe
925eb7e946SCorentin Labbe #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG
935eb7e946SCorentin Labbe algt->stat_req++;
945eb7e946SCorentin Labbe algt->stat_bytes += todo;
955eb7e946SCorentin Labbe #endif
965eb7e946SCorentin Labbe
975eb7e946SCorentin Labbe dma_iv = dma_map_single(ce->dev, ctx->seed, ctx->slen, DMA_TO_DEVICE);
985eb7e946SCorentin Labbe if (dma_mapping_error(ce->dev, dma_iv)) {
995eb7e946SCorentin Labbe dev_err(ce->dev, "Cannot DMA MAP IV\n");
10028289455SJia-Ju Bai err = -EFAULT;
1015eb7e946SCorentin Labbe goto err_iv;
1025eb7e946SCorentin Labbe }
1035eb7e946SCorentin Labbe
1045eb7e946SCorentin Labbe dma_dst = dma_map_single(ce->dev, d, todo, DMA_FROM_DEVICE);
1055eb7e946SCorentin Labbe if (dma_mapping_error(ce->dev, dma_dst)) {
1065eb7e946SCorentin Labbe dev_err(ce->dev, "Cannot DMA MAP DST\n");
1075eb7e946SCorentin Labbe err = -EFAULT;
1085eb7e946SCorentin Labbe goto err_dst;
1095eb7e946SCorentin Labbe }
1105eb7e946SCorentin Labbe
111d3bae866SMinghao Chi err = pm_runtime_resume_and_get(ce->dev);
112d3bae866SMinghao Chi if (err < 0)
1135eb7e946SCorentin Labbe goto err_pm;
1145eb7e946SCorentin Labbe
1155eb7e946SCorentin Labbe mutex_lock(&ce->rnglock);
1165eb7e946SCorentin Labbe chan = &ce->chanlist[flow];
1175eb7e946SCorentin Labbe
1185eb7e946SCorentin Labbe cet = &chan->tl[0];
1195eb7e946SCorentin Labbe memset(cet, 0, sizeof(struct ce_task));
1205eb7e946SCorentin Labbe
1215eb7e946SCorentin Labbe cet->t_id = cpu_to_le32(flow);
1225eb7e946SCorentin Labbe common = ce->variant->prng | CE_COMM_INT;
1235eb7e946SCorentin Labbe cet->t_common_ctl = cpu_to_le32(common);
1245eb7e946SCorentin Labbe
1255eb7e946SCorentin Labbe /* recent CE (H6) need length in bytes, in word otherwise */
1265eb7e946SCorentin Labbe if (ce->variant->prng_t_dlen_in_bytes)
1275eb7e946SCorentin Labbe cet->t_dlen = cpu_to_le32(todo);
1285eb7e946SCorentin Labbe else
1295eb7e946SCorentin Labbe cet->t_dlen = cpu_to_le32(todo / 4);
1305eb7e946SCorentin Labbe
1315eb7e946SCorentin Labbe sym = PRNG_LD;
1325eb7e946SCorentin Labbe cet->t_sym_ctl = cpu_to_le32(sym);
1335eb7e946SCorentin Labbe cet->t_asym_ctl = 0;
1345eb7e946SCorentin Labbe
1355eb7e946SCorentin Labbe cet->t_key = cpu_to_le32(dma_iv);
1365eb7e946SCorentin Labbe cet->t_iv = cpu_to_le32(dma_iv);
1375eb7e946SCorentin Labbe
1385eb7e946SCorentin Labbe cet->t_dst[0].addr = cpu_to_le32(dma_dst);
1395eb7e946SCorentin Labbe cet->t_dst[0].len = cpu_to_le32(todo / 4);
1405eb7e946SCorentin Labbe ce->chanlist[flow].timeout = 2000;
1415eb7e946SCorentin Labbe
1425eb7e946SCorentin Labbe err = sun8i_ce_run_task(ce, 3, "PRNG");
1435eb7e946SCorentin Labbe mutex_unlock(&ce->rnglock);
1445eb7e946SCorentin Labbe
1455eb7e946SCorentin Labbe pm_runtime_put(ce->dev);
1465eb7e946SCorentin Labbe
1475eb7e946SCorentin Labbe err_pm:
1485eb7e946SCorentin Labbe dma_unmap_single(ce->dev, dma_dst, todo, DMA_FROM_DEVICE);
1495eb7e946SCorentin Labbe err_dst:
1505eb7e946SCorentin Labbe dma_unmap_single(ce->dev, dma_iv, ctx->slen, DMA_TO_DEVICE);
1515eb7e946SCorentin Labbe
1525eb7e946SCorentin Labbe if (!err) {
1535eb7e946SCorentin Labbe memcpy(dst, d, dlen);
1545eb7e946SCorentin Labbe memcpy(ctx->seed, d + dlen, ctx->slen);
1555eb7e946SCorentin Labbe }
1565eb7e946SCorentin Labbe err_iv:
157c391714cSJason Wang kfree_sensitive(d);
1585eb7e946SCorentin Labbe err_mem:
1595eb7e946SCorentin Labbe return err;
1605eb7e946SCorentin Labbe }
161