fips_drbg.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. * Copyright (c) 2014, The Linux Foundation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/init.h>
  17. #include <linux/device.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/hw_random.h>
  20. #include <linux/clk.h>
  21. #include <linux/slab.h>
  22. #include <linux/io.h>
  23. #include <linux/err.h>
  24. #include <linux/types.h>
  25. #include <mach/msm_bus.h>
  26. #include <linux/qrng.h>
  27. #include <linux/fs.h>
  28. #include <linux/cdev.h>
  29. #include <linux/errno.h>
  30. #include <linux/crypto.h>
  31. #include <linux/scatterlist.h>
  32. #include <linux/dma-mapping.h>
  33. #include <linux/gfp.h>
  34. #include <linux/string.h>
  35. #include "msm_rng.h"
  36. #include "fips_drbg.h"
  37. /* The fips-140 random number generator is a wrapper around the CTR_DRBG
  38. * random number generator, which is built according to the
  39. * specifications in NIST SP 800-90 using AES-128.
  40. *
  41. * This wrapper has the following functionality
  42. * a. Entropy collection is via a callback.
  43. * b. A failure of CTR_DRBG because reseeding is needed invisibly
  44. * causes the underlying CTR_DRBG instance to be reseeded with
  45. * new random data and then the generate request is retried.
  46. * c. Limitations in CTR_DRBG (like not allowed more than 65536 bytes
  47. * to be genrated in one request) are worked around. At this level
  48. * it just works.
  49. * d. On success the return value is zero. If the callback was invoked
  50. * and returned a non-zero value, that value is returned. On all other
  51. * errors -1 is returned.
  52. */
  53. #ifndef NULL
  54. #define NULL 0
  55. #endif
  56. /* 32 bytes = 256 bits = seed length */
  57. #define MAGIC 0xab10d161
  58. #define RESEED_INTERVAL (1 << 31)
  59. int get_entropy_callback(void *ctx, void *buf)
  60. {
  61. struct msm_rng_device *msm_rng_dev = (struct msm_rng_device *)ctx;
  62. int ret_val = -1;
  63. if (NULL == ctx)
  64. return FIPS140_PRNG_ERR;
  65. if (NULL == buf)
  66. return FIPS140_PRNG_ERR;
  67. ret_val = msm_rng_direct_read(msm_rng_dev, buf);
  68. if ((size_t)ret_val != Q_HW_DRBG_BLOCK_BYTES)
  69. return ret_val;
  70. return 0;
  71. }
  72. /* Initialize *ctx. Automatically reseed after reseed_interval calls
  73. * to fips_drbg_gen. The underlying CTR_DRBG will automatically be
  74. * reseeded every reseed_interval requests. Values over
  75. * CTR_DRBG_MAX_RESEED_INTERVAL (2^48) or that are zero are silently
  76. * converted to CTR_DRBG_MAX_RESEED_INTERVAL. (It is easy to justify
  77. * lowering values that are too large to CTR_DRBG_MAX_RESEED_INTERVAL
  78. * (the NIST SP800-90 limit): just silently enforcing the rules.
  79. * Silently converted 0 to to CTR_DRBG_MAX_RESEED_INTERVAL is harder.
  80. * The alternative is to return an error. But since
  81. * CTR_DRBG_MAX_RESEED is safe, we relieve the caller of one more
  82. * error to worry about.)
  83. */
  84. static int
  85. do_fips_drbg_init(struct fips_drbg_ctx_s *ctx,
  86. get_entropy_callback_t callback,
  87. void *callback_ctx,
  88. unsigned long long reseed_interval)
  89. {
  90. uint8_t entropy_pool[Q_HW_DRBG_BLOCK_BYTES];
  91. enum ctr_drbg_status_t init_rv;
  92. int rv = -1;
  93. if (ctx == NULL)
  94. return FIPS140_PRNG_ERR;
  95. if (callback == NULL)
  96. return FIPS140_PRNG_ERR;
  97. if (reseed_interval == 0 ||
  98. reseed_interval > CTR_DRBG_MAX_RESEED_INTERVAL)
  99. reseed_interval = CTR_DRBG_MAX_RESEED_INTERVAL;
  100. /* fill in callback related fields in ctx */
  101. ctx->get_entropy_callback = callback;
  102. ctx->get_entropy_callback_ctx = callback_ctx;
  103. if (!ctx->fips_drbg_started) {
  104. rv = (*ctx->get_entropy_callback)(ctx->get_entropy_callback_ctx,
  105. ctx->prev_hw_drbg_block
  106. );
  107. if (rv != 0)
  108. return FIPS140_PRNG_ERR;
  109. ctx->fips_drbg_started = 1;
  110. }
  111. rv = (*ctx->get_entropy_callback)(ctx->get_entropy_callback_ctx,
  112. entropy_pool
  113. );
  114. if (rv != 0) {
  115. memset(entropy_pool, 0, Q_HW_DRBG_BLOCK_BYTES);
  116. return FIPS140_PRNG_ERR;
  117. }
  118. if (!memcmp(entropy_pool,
  119. ctx->prev_hw_drbg_block,
  120. Q_HW_DRBG_BLOCK_BYTES)) {
  121. memset(entropy_pool, 0, Q_HW_DRBG_BLOCK_BYTES);
  122. return FIPS140_PRNG_ERR;
  123. } else
  124. memcpy(ctx->prev_hw_drbg_block,
  125. entropy_pool,
  126. Q_HW_DRBG_BLOCK_BYTES);
  127. init_rv = ctr_drbg_instantiate(&ctx->ctr_drbg_ctx,
  128. entropy_pool,
  129. 8 * MSM_ENTROPY_BUFFER_SIZE,
  130. entropy_pool + MSM_ENTROPY_BUFFER_SIZE,
  131. 8 * 8,
  132. reseed_interval);
  133. memset(entropy_pool, 0, Q_HW_DRBG_BLOCK_BYTES);
  134. if (init_rv == 0)
  135. ctx->magic = MAGIC;
  136. return 0;
  137. }
  138. int fips_drbg_init(struct msm_rng_device *msm_rng_ctx)
  139. {
  140. uint32_t ret_val = 0;
  141. ret_val = do_fips_drbg_init(msm_rng_ctx->drbg_ctx,
  142. get_entropy_callback,
  143. msm_rng_ctx,
  144. RESEED_INTERVAL
  145. );
  146. if (ret_val != 0)
  147. ret_val = FIPS140_PRNG_ERR;
  148. return ret_val;
  149. }
  150. /* Push new entropy into the CTR_DRBG instance in ctx, combining
  151. * it with the entropy already there. On success, 0 is returned. If
  152. * the callback returns a non-zero value, that value is returned.
  153. * Other errors return -1.
  154. */
  155. static int
  156. fips_drbg_reseed(struct fips_drbg_ctx_s *ctx)
  157. {
  158. uint8_t entropy_pool[Q_HW_DRBG_BLOCK_BYTES];
  159. int rv;
  160. enum ctr_drbg_status_t init_rv;
  161. if (ctx == NULL)
  162. return FIPS140_PRNG_ERR;
  163. if (!ctx->fips_drbg_started) {
  164. rv = (*ctx->get_entropy_callback)(ctx->get_entropy_callback_ctx,
  165. ctx->prev_hw_drbg_block
  166. );
  167. if (rv != 0)
  168. return FIPS140_PRNG_ERR;
  169. ctx->fips_drbg_started = 1;
  170. }
  171. rv = (*ctx->get_entropy_callback)(ctx->get_entropy_callback_ctx,
  172. entropy_pool
  173. );
  174. if (rv != 0) {
  175. memset(entropy_pool, 0, Q_HW_DRBG_BLOCK_BYTES);
  176. return FIPS140_PRNG_ERR;
  177. }
  178. if (!memcmp(entropy_pool,
  179. ctx->prev_hw_drbg_block,
  180. Q_HW_DRBG_BLOCK_BYTES)) {
  181. memset(entropy_pool, 0, Q_HW_DRBG_BLOCK_BYTES);
  182. return FIPS140_PRNG_ERR;
  183. } else
  184. memcpy(ctx->prev_hw_drbg_block,
  185. entropy_pool,
  186. Q_HW_DRBG_BLOCK_BYTES);
  187. init_rv = ctr_drbg_reseed(&ctx->ctr_drbg_ctx,
  188. entropy_pool,
  189. 8 * MSM_ENTROPY_BUFFER_SIZE);
  190. /* Zeroize the buffer for security. */
  191. memset(entropy_pool, 0, Q_HW_DRBG_BLOCK_BYTES);
  192. return (init_rv == CTR_DRBG_SUCCESS ?
  193. FIPS140_PRNG_OK :
  194. FIPS140_PRNG_ERR);
  195. }
  196. /* generate random bytes. len is in bytes On success returns 0. If
  197. * the callback returns a non-zero value, that is returned. Other
  198. * errors return -1. */
  199. int
  200. fips_drbg_gen(struct fips_drbg_ctx_s *ctx, void *tgt, size_t len)
  201. {
  202. /* The contorted flow in this function is so that the CTR_DRBG
  203. stuff can follow NIST SP 800-90, which has the generate function
  204. fail and return a special code if a reseed is needed. We also work
  205. around the CTR_DRBG limitation of the maximum request sized being
  206. 2^19 bits. */
  207. enum ctr_drbg_status_t gen_rv;
  208. int rv;
  209. if (ctx == NULL || ctx->magic != MAGIC)
  210. return FIPS140_PRNG_ERR;
  211. if (tgt == NULL && len > 0)
  212. return FIPS140_PRNG_ERR;
  213. while (len > 0) {
  214. size_t req_len;
  215. if (len < (CTR_DRBG_MAX_REQ_LEN_BITS / 8))
  216. req_len = len;
  217. else
  218. req_len = CTR_DRBG_MAX_REQ_LEN_BITS / 8;
  219. gen_rv = ctr_drbg_generate(&ctx->ctr_drbg_ctx,
  220. tgt,
  221. 8*req_len);
  222. switch (gen_rv) {
  223. case CTR_DRBG_SUCCESS:
  224. tgt = (uint8_t *)tgt + req_len;
  225. len -= req_len;
  226. break;
  227. case CTR_DRBG_NEEDS_RESEED:
  228. rv = fips_drbg_reseed(ctx);
  229. if (rv != 0)
  230. return rv;
  231. break;
  232. default:
  233. return FIPS140_PRNG_ERR;
  234. }
  235. }
  236. return 0;
  237. }
  238. /* free resources and zeroize state */
  239. void
  240. fips_drbg_final(struct fips_drbg_ctx_s *ctx)
  241. {
  242. ctr_drbg_uninstantiate(&ctx->ctr_drbg_ctx);
  243. ctx->get_entropy_callback = 0;
  244. ctx->get_entropy_callback_ctx = 0;
  245. ctx->fips_drbg_started = 0;
  246. memset(ctx->prev_hw_drbg_block, 0, Q_HW_DRBG_BLOCK_BYTES);
  247. ctx->magic = 0;
  248. }