fips_drbg_rand.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /* fips/rand/fips_drbg_rand.c */
  2. /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  3. * project.
  4. */
  5. /* ====================================================================
  6. * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. All advertising materials mentioning features or use of this
  21. * software must display the following acknowledgment:
  22. * "This product includes software developed by the OpenSSL Project
  23. * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  24. *
  25. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  26. * endorse or promote products derived from this software without
  27. * prior written permission. For written permission, please contact
  28. * licensing@OpenSSL.org.
  29. *
  30. * 5. Products derived from this software may not be called "OpenSSL"
  31. * nor may "OpenSSL" appear in their names without prior written
  32. * permission of the OpenSSL Project.
  33. *
  34. * 6. Redistributions of any form whatsoever must retain the following
  35. * acknowledgment:
  36. * "This product includes software developed by the OpenSSL Project
  37. * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  38. *
  39. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  40. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  41. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  42. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  43. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  45. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  46. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  48. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  49. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  50. * OF THE POSSIBILITY OF SUCH DAMAGE.
  51. * ====================================================================
  52. */
  53. #define OPENSSL_FIPSAPI
  54. #include <string.h>
  55. #include <openssl/crypto.h>
  56. #include <openssl/evp.h>
  57. #include <openssl/aes.h>
  58. #include <openssl/err.h>
  59. #include <openssl/rand.h>
  60. #include <openssl/fips_rand.h>
  61. #include "fips_rand_lcl.h"
  62. /* Mapping of SP800-90 DRBGs to OpenSSL RAND_METHOD */
  63. /* Since we only have one global PRNG used at any time in OpenSSL use a global
  64. * variable to store context.
  65. */
  66. static DRBG_CTX ossl_dctx;
  67. DRBG_CTX *FIPS_get_default_drbg(void)
  68. {
  69. return &ossl_dctx;
  70. }
  71. static int fips_drbg_bytes(unsigned char *out, int count)
  72. {
  73. DRBG_CTX *dctx = &ossl_dctx;
  74. int rv = 0;
  75. unsigned char *adin = NULL;
  76. size_t adinlen = 0;
  77. CRYPTO_w_lock(CRYPTO_LOCK_RAND);
  78. do
  79. {
  80. size_t rcnt;
  81. if (count > (int)dctx->max_request)
  82. rcnt = dctx->max_request;
  83. else
  84. rcnt = count;
  85. if (dctx->get_adin)
  86. {
  87. adinlen = dctx->get_adin(dctx, &adin);
  88. if (adinlen && !adin)
  89. {
  90. FIPSerr(FIPS_F_FIPS_DRBG_BYTES, FIPS_R_ERROR_RETRIEVING_ADDITIONAL_INPUT);
  91. goto err;
  92. }
  93. }
  94. rv = FIPS_drbg_generate(dctx, out, rcnt, 0, 0, adin, adinlen);
  95. if (adin)
  96. {
  97. if (dctx->cleanup_adin)
  98. dctx->cleanup_adin(dctx, adin, adinlen);
  99. adin = NULL;
  100. }
  101. if (!rv)
  102. goto err;
  103. out += rcnt;
  104. count -= rcnt;
  105. }
  106. while (count);
  107. rv = 1;
  108. err:
  109. CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
  110. return rv;
  111. }
  112. static int fips_drbg_pseudo(unsigned char *out, int count)
  113. {
  114. if (fips_drbg_bytes(out, count) <= 0)
  115. return -1;
  116. return 1;
  117. }
  118. static int fips_drbg_status(void)
  119. {
  120. DRBG_CTX *dctx = &ossl_dctx;
  121. int rv;
  122. CRYPTO_r_lock(CRYPTO_LOCK_RAND);
  123. rv = dctx->status == DRBG_STATUS_READY ? 1 : 0;
  124. CRYPTO_r_unlock(CRYPTO_LOCK_RAND);
  125. return rv;
  126. }
  127. static void fips_drbg_cleanup(void)
  128. {
  129. DRBG_CTX *dctx = &ossl_dctx;
  130. CRYPTO_w_lock(CRYPTO_LOCK_RAND);
  131. FIPS_drbg_uninstantiate(dctx);
  132. CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
  133. }
  134. static int fips_drbg_seed(const void *seed, int seedlen)
  135. {
  136. DRBG_CTX *dctx = &ossl_dctx;
  137. if (dctx->rand_seed_cb)
  138. return dctx->rand_seed_cb(dctx, seed, seedlen);
  139. return 1;
  140. }
  141. static int fips_drbg_add(const void *seed, int seedlen,
  142. double add_entropy)
  143. {
  144. DRBG_CTX *dctx = &ossl_dctx;
  145. if (dctx->rand_add_cb)
  146. return dctx->rand_add_cb(dctx, seed, seedlen, add_entropy);
  147. return 1;
  148. }
  149. static const RAND_METHOD rand_drbg_meth =
  150. {
  151. fips_drbg_seed,
  152. fips_drbg_bytes,
  153. fips_drbg_cleanup,
  154. fips_drbg_add,
  155. fips_drbg_pseudo,
  156. fips_drbg_status
  157. };
  158. const RAND_METHOD *FIPS_drbg_method(void)
  159. {
  160. return &rand_drbg_meth;
  161. }