sun8i-ss-prng.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * sun8i-ss-prng.c - hardware cryptographic offloader for
  4. * Allwinner A80/A83T SoC
  5. *
  6. * Copyright (C) 2015-2020 Corentin Labbe <[email protected]>
  7. *
  8. * This file handle the PRNG found in the SS
  9. *
  10. * You could find a link for the datasheet in Documentation/arm/sunxi.rst
  11. */
  12. #include "sun8i-ss.h"
  13. #include <linux/dma-mapping.h>
  14. #include <linux/pm_runtime.h>
  15. #include <crypto/internal/rng.h>
  16. int sun8i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed,
  17. unsigned int slen)
  18. {
  19. struct sun8i_ss_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
  20. if (ctx->seed && ctx->slen != slen) {
  21. kfree_sensitive(ctx->seed);
  22. ctx->slen = 0;
  23. ctx->seed = NULL;
  24. }
  25. if (!ctx->seed)
  26. ctx->seed = kmalloc(slen, GFP_KERNEL | GFP_DMA);
  27. if (!ctx->seed)
  28. return -ENOMEM;
  29. memcpy(ctx->seed, seed, slen);
  30. ctx->slen = slen;
  31. return 0;
  32. }
  33. int sun8i_ss_prng_init(struct crypto_tfm *tfm)
  34. {
  35. struct sun8i_ss_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
  36. memset(ctx, 0, sizeof(struct sun8i_ss_rng_tfm_ctx));
  37. return 0;
  38. }
  39. void sun8i_ss_prng_exit(struct crypto_tfm *tfm)
  40. {
  41. struct sun8i_ss_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
  42. kfree_sensitive(ctx->seed);
  43. ctx->seed = NULL;
  44. ctx->slen = 0;
  45. }
  46. int sun8i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
  47. unsigned int slen, u8 *dst, unsigned int dlen)
  48. {
  49. struct sun8i_ss_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
  50. struct rng_alg *alg = crypto_rng_alg(tfm);
  51. struct sun8i_ss_alg_template *algt;
  52. struct sun8i_ss_dev *ss;
  53. dma_addr_t dma_iv, dma_dst;
  54. unsigned int todo;
  55. int err = 0;
  56. int flow;
  57. void *d;
  58. u32 v;
  59. algt = container_of(alg, struct sun8i_ss_alg_template, alg.rng);
  60. ss = algt->ss;
  61. if (ctx->slen == 0) {
  62. dev_err(ss->dev, "The PRNG is not seeded\n");
  63. return -EINVAL;
  64. }
  65. /* The SS does not give an updated seed, so we need to get a new one.
  66. * So we will ask for an extra PRNG_SEED_SIZE data.
  67. * We want dlen + seedsize rounded up to a multiple of PRNG_DATA_SIZE
  68. */
  69. todo = dlen + PRNG_SEED_SIZE + PRNG_DATA_SIZE;
  70. todo -= todo % PRNG_DATA_SIZE;
  71. d = kzalloc(todo, GFP_KERNEL | GFP_DMA);
  72. if (!d)
  73. return -ENOMEM;
  74. flow = sun8i_ss_get_engine_number(ss);
  75. #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG
  76. algt->stat_req++;
  77. algt->stat_bytes += todo;
  78. #endif
  79. v = SS_ALG_PRNG | SS_PRNG_CONTINUE | SS_START;
  80. if (flow)
  81. v |= SS_FLOW1;
  82. else
  83. v |= SS_FLOW0;
  84. dma_iv = dma_map_single(ss->dev, ctx->seed, ctx->slen, DMA_TO_DEVICE);
  85. if (dma_mapping_error(ss->dev, dma_iv)) {
  86. dev_err(ss->dev, "Cannot DMA MAP IV\n");
  87. err = -EFAULT;
  88. goto err_free;
  89. }
  90. dma_dst = dma_map_single(ss->dev, d, todo, DMA_FROM_DEVICE);
  91. if (dma_mapping_error(ss->dev, dma_dst)) {
  92. dev_err(ss->dev, "Cannot DMA MAP DST\n");
  93. err = -EFAULT;
  94. goto err_iv;
  95. }
  96. err = pm_runtime_resume_and_get(ss->dev);
  97. if (err < 0)
  98. goto err_pm;
  99. err = 0;
  100. mutex_lock(&ss->mlock);
  101. writel(dma_iv, ss->base + SS_IV_ADR_REG);
  102. /* the PRNG act badly (failing rngtest) without SS_KEY_ADR_REG set */
  103. writel(dma_iv, ss->base + SS_KEY_ADR_REG);
  104. writel(dma_dst, ss->base + SS_DST_ADR_REG);
  105. writel(todo / 4, ss->base + SS_LEN_ADR_REG);
  106. reinit_completion(&ss->flows[flow].complete);
  107. ss->flows[flow].status = 0;
  108. /* Be sure all data is written before enabling the task */
  109. wmb();
  110. writel(v, ss->base + SS_CTL_REG);
  111. wait_for_completion_interruptible_timeout(&ss->flows[flow].complete,
  112. msecs_to_jiffies(todo));
  113. if (ss->flows[flow].status == 0) {
  114. dev_err(ss->dev, "DMA timeout for PRNG (size=%u)\n", todo);
  115. err = -EFAULT;
  116. }
  117. /* Since cipher and hash use the linux/cryptoengine and that we have
  118. * a cryptoengine per flow, we are sure that they will issue only one
  119. * request per flow.
  120. * Since the cryptoengine wait for completion before submitting a new
  121. * one, the mlock could be left just after the final writel.
  122. * But cryptoengine cannot handle crypto_rng, so we need to be sure
  123. * nothing will use our flow.
  124. * The easiest way is to grab mlock until the hardware end our requests.
  125. * We could have used a per flow lock, but this would increase
  126. * complexity.
  127. * The drawback is that no request could be handled for the other flow.
  128. */
  129. mutex_unlock(&ss->mlock);
  130. pm_runtime_put(ss->dev);
  131. err_pm:
  132. dma_unmap_single(ss->dev, dma_dst, todo, DMA_FROM_DEVICE);
  133. err_iv:
  134. dma_unmap_single(ss->dev, dma_iv, ctx->slen, DMA_TO_DEVICE);
  135. if (!err) {
  136. memcpy(dst, d, dlen);
  137. /* Update seed */
  138. memcpy(ctx->seed, d + dlen, ctx->slen);
  139. }
  140. err_free:
  141. kfree_sensitive(d);
  142. return err;
  143. }