sun8i-ce-prng.c 3.7 KB

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