rng.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Cryptographic API.
  4. *
  5. * RNG operations.
  6. *
  7. * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com>
  8. * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
  9. */
  10. #include <crypto/internal/rng.h>
  11. #include <linux/atomic.h>
  12. #include <linux/cryptouser.h>
  13. #include <linux/err.h>
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/mutex.h>
  17. #include <linux/random.h>
  18. #include <linux/seq_file.h>
  19. #include <linux/slab.h>
  20. #include <linux/string.h>
  21. #include <net/netlink.h>
  22. #include "internal.h"
  23. static DEFINE_MUTEX(crypto_default_rng_lock);
  24. struct crypto_rng *crypto_default_rng;
  25. EXPORT_SYMBOL_GPL(crypto_default_rng);
  26. static int crypto_default_rng_refcnt;
  27. int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
  28. {
  29. u8 *buf = NULL;
  30. int err;
  31. if (!seed && slen) {
  32. buf = kmalloc(slen, GFP_KERNEL);
  33. if (!buf)
  34. return -ENOMEM;
  35. err = get_random_bytes_wait(buf, slen);
  36. if (err)
  37. goto out;
  38. seed = buf;
  39. }
  40. err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);
  41. out:
  42. kfree_sensitive(buf);
  43. return err;
  44. }
  45. EXPORT_SYMBOL_GPL(crypto_rng_reset);
  46. static int crypto_rng_init_tfm(struct crypto_tfm *tfm)
  47. {
  48. return 0;
  49. }
  50. static unsigned int seedsize(struct crypto_alg *alg)
  51. {
  52. struct rng_alg *ralg = container_of(alg, struct rng_alg, base);
  53. return ralg->seedsize;
  54. }
  55. static int __maybe_unused crypto_rng_report(
  56. struct sk_buff *skb, struct crypto_alg *alg)
  57. {
  58. struct crypto_report_rng rrng;
  59. memset(&rrng, 0, sizeof(rrng));
  60. strscpy(rrng.type, "rng", sizeof(rrng.type));
  61. rrng.seedsize = seedsize(alg);
  62. return nla_put(skb, CRYPTOCFGA_REPORT_RNG, sizeof(rrng), &rrng);
  63. }
  64. static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
  65. __maybe_unused;
  66. static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
  67. {
  68. seq_printf(m, "type : rng\n");
  69. seq_printf(m, "seedsize : %u\n", seedsize(alg));
  70. }
  71. static const struct crypto_type crypto_rng_type = {
  72. .extsize = crypto_alg_extsize,
  73. .init_tfm = crypto_rng_init_tfm,
  74. #ifdef CONFIG_PROC_FS
  75. .show = crypto_rng_show,
  76. #endif
  77. #if IS_ENABLED(CONFIG_CRYPTO_USER)
  78. .report = crypto_rng_report,
  79. #endif
  80. .maskclear = ~CRYPTO_ALG_TYPE_MASK,
  81. .maskset = CRYPTO_ALG_TYPE_MASK,
  82. .type = CRYPTO_ALG_TYPE_RNG,
  83. .tfmsize = offsetof(struct crypto_rng, base),
  84. };
  85. struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask)
  86. {
  87. return crypto_alloc_tfm(alg_name, &crypto_rng_type, type, mask);
  88. }
  89. EXPORT_SYMBOL_GPL(crypto_alloc_rng);
  90. int crypto_get_default_rng(void)
  91. {
  92. struct crypto_rng *rng;
  93. int err;
  94. mutex_lock(&crypto_default_rng_lock);
  95. if (!crypto_default_rng) {
  96. rng = crypto_alloc_rng("stdrng", 0, 0);
  97. err = PTR_ERR(rng);
  98. if (IS_ERR(rng))
  99. goto unlock;
  100. err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
  101. if (err) {
  102. crypto_free_rng(rng);
  103. goto unlock;
  104. }
  105. crypto_default_rng = rng;
  106. }
  107. crypto_default_rng_refcnt++;
  108. err = 0;
  109. unlock:
  110. mutex_unlock(&crypto_default_rng_lock);
  111. return err;
  112. }
  113. EXPORT_SYMBOL_GPL(crypto_get_default_rng);
  114. void crypto_put_default_rng(void)
  115. {
  116. mutex_lock(&crypto_default_rng_lock);
  117. crypto_default_rng_refcnt--;
  118. mutex_unlock(&crypto_default_rng_lock);
  119. }
  120. EXPORT_SYMBOL_GPL(crypto_put_default_rng);
  121. #if defined(CONFIG_CRYPTO_RNG) || defined(CONFIG_CRYPTO_RNG_MODULE)
  122. int crypto_del_default_rng(void)
  123. {
  124. int err = -EBUSY;
  125. mutex_lock(&crypto_default_rng_lock);
  126. if (crypto_default_rng_refcnt)
  127. goto out;
  128. crypto_free_rng(crypto_default_rng);
  129. crypto_default_rng = NULL;
  130. err = 0;
  131. out:
  132. mutex_unlock(&crypto_default_rng_lock);
  133. return err;
  134. }
  135. EXPORT_SYMBOL_GPL(crypto_del_default_rng);
  136. #endif
  137. int crypto_register_rng(struct rng_alg *alg)
  138. {
  139. struct crypto_alg *base = &alg->base;
  140. if (alg->seedsize > PAGE_SIZE / 8)
  141. return -EINVAL;
  142. base->cra_type = &crypto_rng_type;
  143. base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
  144. base->cra_flags |= CRYPTO_ALG_TYPE_RNG;
  145. return crypto_register_alg(base);
  146. }
  147. EXPORT_SYMBOL_GPL(crypto_register_rng);
  148. void crypto_unregister_rng(struct rng_alg *alg)
  149. {
  150. crypto_unregister_alg(&alg->base);
  151. }
  152. EXPORT_SYMBOL_GPL(crypto_unregister_rng);
  153. int crypto_register_rngs(struct rng_alg *algs, int count)
  154. {
  155. int i, ret;
  156. for (i = 0; i < count; i++) {
  157. ret = crypto_register_rng(algs + i);
  158. if (ret)
  159. goto err;
  160. }
  161. return 0;
  162. err:
  163. for (--i; i >= 0; --i)
  164. crypto_unregister_rng(algs + i);
  165. return ret;
  166. }
  167. EXPORT_SYMBOL_GPL(crypto_register_rngs);
  168. void crypto_unregister_rngs(struct rng_alg *algs, int count)
  169. {
  170. int i;
  171. for (i = count - 1; i >= 0; --i)
  172. crypto_unregister_rng(algs + i);
  173. }
  174. EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
  175. MODULE_LICENSE("GPL");
  176. MODULE_DESCRIPTION("Random Number Generator");