^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * sun8i-ce-prng.c - hardware cryptographic offloader for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Allwinner H3/A64/H5/H2+/H6/R40 SoC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2015-2020 Corentin Labbe <clabbe@baylibre.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file handle the PRNG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * You could find a link for the datasheet in Documentation/arm/sunxi.rst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "sun8i-ce.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <crypto/internal/rng.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) int sun8i_ce_prng_init(struct crypto_tfm *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct sun8i_ce_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) memset(ctx, 0, sizeof(struct sun8i_ce_rng_tfm_ctx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) void sun8i_ce_prng_exit(struct crypto_tfm *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct sun8i_ce_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) memzero_explicit(ctx->seed, ctx->slen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) kfree(ctx->seed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ctx->seed = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) ctx->slen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int sun8i_ce_prng_seed(struct crypto_rng *tfm, const u8 *seed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) unsigned int slen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct sun8i_ce_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (ctx->seed && ctx->slen != slen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) memzero_explicit(ctx->seed, ctx->slen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) kfree(ctx->seed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ctx->slen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ctx->seed = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (!ctx->seed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ctx->seed = kmalloc(slen, GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (!ctx->seed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) memcpy(ctx->seed, seed, slen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ctx->slen = slen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int sun8i_ce_prng_generate(struct crypto_rng *tfm, const u8 *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned int slen, u8 *dst, unsigned int dlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct sun8i_ce_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct rng_alg *alg = crypto_rng_alg(tfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct sun8i_ce_alg_template *algt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct sun8i_ce_dev *ce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) dma_addr_t dma_iv, dma_dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int flow = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned int todo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct sun8i_ce_flow *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct ce_task *cet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u32 common, sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) void *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) algt = container_of(alg, struct sun8i_ce_alg_template, alg.rng);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ce = algt->ce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ctx->slen == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) dev_err(ce->dev, "not seeded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* we want dlen + seedsize rounded up to a multiple of PRNG_DATA_SIZE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) todo = dlen + ctx->slen + PRNG_DATA_SIZE * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) todo -= todo % PRNG_DATA_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) d = kzalloc(todo, GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) goto err_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) dev_dbg(ce->dev, "%s PRNG slen=%u dlen=%u todo=%u multi=%u\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) slen, dlen, todo, todo / PRNG_DATA_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) algt->stat_req++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) algt->stat_bytes += todo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dma_iv = dma_map_single(ce->dev, ctx->seed, ctx->slen, DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (dma_mapping_error(ce->dev, dma_iv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) dev_err(ce->dev, "Cannot DMA MAP IV\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) goto err_iv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) dma_dst = dma_map_single(ce->dev, d, todo, DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (dma_mapping_error(ce->dev, dma_dst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) dev_err(ce->dev, "Cannot DMA MAP DST\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) goto err_dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) err = pm_runtime_get_sync(ce->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) pm_runtime_put_noidle(ce->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) goto err_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) mutex_lock(&ce->rnglock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) chan = &ce->chanlist[flow];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) cet = &chan->tl[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) memset(cet, 0, sizeof(struct ce_task));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) cet->t_id = cpu_to_le32(flow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) common = ce->variant->prng | CE_COMM_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) cet->t_common_ctl = cpu_to_le32(common);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* recent CE (H6) need length in bytes, in word otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (ce->variant->prng_t_dlen_in_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) cet->t_dlen = cpu_to_le32(todo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) cet->t_dlen = cpu_to_le32(todo / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) sym = PRNG_LD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) cet->t_sym_ctl = cpu_to_le32(sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) cet->t_asym_ctl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) cet->t_key = cpu_to_le32(dma_iv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) cet->t_iv = cpu_to_le32(dma_iv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) cet->t_dst[0].addr = cpu_to_le32(dma_dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) cet->t_dst[0].len = cpu_to_le32(todo / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ce->chanlist[flow].timeout = 2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) err = sun8i_ce_run_task(ce, 3, "PRNG");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) mutex_unlock(&ce->rnglock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) pm_runtime_put(ce->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) err_pm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) dma_unmap_single(ce->dev, dma_dst, todo, DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) err_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) dma_unmap_single(ce->dev, dma_iv, ctx->slen, DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) memcpy(dst, d, dlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) memcpy(ctx->seed, d + dlen, ctx->slen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) memzero_explicit(d, todo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) err_iv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) kfree(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) err_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }