caamprng.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Driver to expose SEC4 PRNG via crypto RNG API
  4. *
  5. * Copyright 2022 NXP
  6. *
  7. */
  8. #include <linux/completion.h>
  9. #include <crypto/internal/rng.h>
  10. #include <linux/dma-mapping.h>
  11. #include <linux/kernel.h>
  12. #include "compat.h"
  13. #include "regs.h"
  14. #include "intern.h"
  15. #include "desc_constr.h"
  16. #include "jr.h"
  17. #include "error.h"
  18. /*
  19. * Length of used descriptors, see caam_init_desc()
  20. */
  21. #define CAAM_PRNG_MAX_DESC_LEN (CAAM_CMD_SZ + \
  22. CAAM_CMD_SZ + \
  23. CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
  24. /* prng per-device context */
  25. struct caam_prng_ctx {
  26. int err;
  27. struct completion done;
  28. };
  29. struct caam_prng_alg {
  30. struct rng_alg rng;
  31. bool registered;
  32. };
  33. static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
  34. void *context)
  35. {
  36. struct caam_prng_ctx *jctx = context;
  37. jctx->err = err ? caam_jr_strstatus(jrdev, err) : 0;
  38. complete(&jctx->done);
  39. }
  40. static u32 *caam_init_reseed_desc(u32 *desc)
  41. {
  42. init_job_desc(desc, 0); /* + 1 cmd_sz */
  43. /* Generate random bytes: + 1 cmd_sz */
  44. append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
  45. OP_ALG_AS_FINALIZE);
  46. print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS,
  47. 16, 4, desc, desc_bytes(desc), 1);
  48. return desc;
  49. }
  50. static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len)
  51. {
  52. init_job_desc(desc, 0); /* + 1 cmd_sz */
  53. /* Generate random bytes: + 1 cmd_sz */
  54. append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
  55. /* Store bytes: + 1 cmd_sz + caam_ptr_sz */
  56. append_fifo_store(desc, dst_dma,
  57. len, FIFOST_TYPE_RNGSTORE);
  58. print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS,
  59. 16, 4, desc, desc_bytes(desc), 1);
  60. return desc;
  61. }
  62. static int caam_prng_generate(struct crypto_rng *tfm,
  63. const u8 *src, unsigned int slen,
  64. u8 *dst, unsigned int dlen)
  65. {
  66. unsigned int aligned_dlen = ALIGN(dlen, dma_get_cache_alignment());
  67. struct caam_prng_ctx ctx;
  68. struct device *jrdev;
  69. dma_addr_t dst_dma;
  70. u32 *desc;
  71. u8 *buf;
  72. int ret;
  73. if (aligned_dlen < dlen)
  74. return -EOVERFLOW;
  75. buf = kzalloc(aligned_dlen, GFP_KERNEL);
  76. if (!buf)
  77. return -ENOMEM;
  78. jrdev = caam_jr_alloc();
  79. ret = PTR_ERR_OR_ZERO(jrdev);
  80. if (ret) {
  81. pr_err("Job Ring Device allocation failed\n");
  82. kfree(buf);
  83. return ret;
  84. }
  85. desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL);
  86. if (!desc) {
  87. ret = -ENOMEM;
  88. goto out1;
  89. }
  90. dst_dma = dma_map_single(jrdev, buf, dlen, DMA_FROM_DEVICE);
  91. if (dma_mapping_error(jrdev, dst_dma)) {
  92. dev_err(jrdev, "Failed to map destination buffer memory\n");
  93. ret = -ENOMEM;
  94. goto out;
  95. }
  96. init_completion(&ctx.done);
  97. ret = caam_jr_enqueue(jrdev,
  98. caam_init_prng_desc(desc, dst_dma, dlen),
  99. caam_prng_done, &ctx);
  100. if (ret == -EINPROGRESS) {
  101. wait_for_completion(&ctx.done);
  102. ret = ctx.err;
  103. }
  104. dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
  105. if (!ret)
  106. memcpy(dst, buf, dlen);
  107. out:
  108. kfree(desc);
  109. out1:
  110. caam_jr_free(jrdev);
  111. kfree(buf);
  112. return ret;
  113. }
  114. static void caam_prng_exit(struct crypto_tfm *tfm) {}
  115. static int caam_prng_init(struct crypto_tfm *tfm)
  116. {
  117. return 0;
  118. }
  119. static int caam_prng_seed(struct crypto_rng *tfm,
  120. const u8 *seed, unsigned int slen)
  121. {
  122. struct caam_prng_ctx ctx;
  123. struct device *jrdev;
  124. u32 *desc;
  125. int ret;
  126. if (slen) {
  127. pr_err("Seed length should be zero\n");
  128. return -EINVAL;
  129. }
  130. jrdev = caam_jr_alloc();
  131. ret = PTR_ERR_OR_ZERO(jrdev);
  132. if (ret) {
  133. pr_err("Job Ring Device allocation failed\n");
  134. return ret;
  135. }
  136. desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL);
  137. if (!desc) {
  138. caam_jr_free(jrdev);
  139. return -ENOMEM;
  140. }
  141. init_completion(&ctx.done);
  142. ret = caam_jr_enqueue(jrdev,
  143. caam_init_reseed_desc(desc),
  144. caam_prng_done, &ctx);
  145. if (ret == -EINPROGRESS) {
  146. wait_for_completion(&ctx.done);
  147. ret = ctx.err;
  148. }
  149. kfree(desc);
  150. caam_jr_free(jrdev);
  151. return ret;
  152. }
  153. static struct caam_prng_alg caam_prng_alg = {
  154. .rng = {
  155. .generate = caam_prng_generate,
  156. .seed = caam_prng_seed,
  157. .seedsize = 0,
  158. .base = {
  159. .cra_name = "stdrng",
  160. .cra_driver_name = "prng-caam",
  161. .cra_priority = 500,
  162. .cra_ctxsize = sizeof(struct caam_prng_ctx),
  163. .cra_module = THIS_MODULE,
  164. .cra_init = caam_prng_init,
  165. .cra_exit = caam_prng_exit,
  166. },
  167. }
  168. };
  169. void caam_prng_unregister(void *data)
  170. {
  171. if (caam_prng_alg.registered)
  172. crypto_unregister_rng(&caam_prng_alg.rng);
  173. }
  174. int caam_prng_register(struct device *ctrldev)
  175. {
  176. struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
  177. u32 rng_inst;
  178. int ret = 0;
  179. /* Check for available RNG blocks before registration */
  180. if (priv->era < 10)
  181. rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
  182. CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
  183. else
  184. rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK;
  185. if (!rng_inst) {
  186. dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n");
  187. return ret;
  188. }
  189. ret = crypto_register_rng(&caam_prng_alg.rng);
  190. if (ret) {
  191. dev_err(ctrldev,
  192. "couldn't register rng crypto alg: %d\n",
  193. ret);
  194. return ret;
  195. }
  196. caam_prng_alg.registered = true;
  197. dev_info(ctrldev,
  198. "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_driver_name);
  199. return 0;
  200. }