evutil_rand.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * 3. The name of the author may not be used to endorse or promote products
  13. * derived from this software without specific prior written permission.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. /* This file has our secure PRNG code. On platforms that have arc4random(),
  27. * we just use that. Otherwise, we include arc4random.c as a bunch of static
  28. * functions, and wrap it lightly. We don't expose the arc4random*() APIs
  29. * because A) they aren't in our namespace, and B) it's not nice to name your
  30. * APIs after their implementations. We keep them in a separate file
  31. * so that other people can rip it out and use it for whatever.
  32. */
  33. #include "event2/event-config.h"
  34. #include "evconfig-private.h"
  35. #include <limits.h>
  36. #include "util-internal.h"
  37. #include "evthread-internal.h"
  38. #ifdef EVENT__HAVE_ARC4RANDOM
  39. #include <stdlib.h>
  40. #include <string.h>
  41. int
  42. evutil_secure_rng_set_urandom_device_file(char *fname)
  43. {
  44. (void) fname;
  45. return -1;
  46. }
  47. int
  48. evutil_secure_rng_init(void)
  49. {
  50. /* call arc4random() now to force it to self-initialize */
  51. (void) arc4random();
  52. return 0;
  53. }
  54. #ifndef EVENT__DISABLE_THREAD_SUPPORT
  55. int
  56. evutil_secure_rng_global_setup_locks_(const int enable_locks)
  57. {
  58. return 0;
  59. }
  60. #endif
  61. static void
  62. evutil_free_secure_rng_globals_locks(void)
  63. {
  64. }
  65. static void
  66. ev_arc4random_buf(void *buf, size_t n)
  67. {
  68. #if defined(EVENT__HAVE_ARC4RANDOM_BUF) && !defined(__APPLE__)
  69. arc4random_buf(buf, n);
  70. return;
  71. #else
  72. unsigned char *b = buf;
  73. #if defined(EVENT__HAVE_ARC4RANDOM_BUF)
  74. /* OSX 10.7 introducd arc4random_buf, so if you build your program
  75. * there, you'll get surprised when older versions of OSX fail to run.
  76. * To solve this, we can check whether the function pointer is set,
  77. * and fall back otherwise. (OSX does this using some linker
  78. * trickery.)
  79. */
  80. {
  81. void (*tptr)(void *,size_t) =
  82. (void (*)(void*,size_t))arc4random_buf;
  83. if (tptr != NULL) {
  84. arc4random_buf(buf, n);
  85. return;
  86. }
  87. }
  88. #endif
  89. /* Make sure that we start out with b at a 4-byte alignment; plenty
  90. * of CPUs care about this for 32-bit access. */
  91. if (n >= 4 && ((ev_uintptr_t)b) & 3) {
  92. ev_uint32_t u = arc4random();
  93. int n_bytes = 4 - (((ev_uintptr_t)b) & 3);
  94. memcpy(b, &u, n_bytes);
  95. b += n_bytes;
  96. n -= n_bytes;
  97. }
  98. while (n >= 4) {
  99. *(ev_uint32_t*)b = arc4random();
  100. b += 4;
  101. n -= 4;
  102. }
  103. if (n) {
  104. ev_uint32_t u = arc4random();
  105. memcpy(b, &u, n);
  106. }
  107. #endif
  108. }
  109. #else /* !EVENT__HAVE_ARC4RANDOM { */
  110. #ifdef EVENT__ssize_t
  111. #define ssize_t EVENT__ssize_t
  112. #endif
  113. #define ARC4RANDOM_EXPORT static
  114. #define ARC4_LOCK_() EVLOCK_LOCK(arc4rand_lock, 0)
  115. #define ARC4_UNLOCK_() EVLOCK_UNLOCK(arc4rand_lock, 0)
  116. #ifndef EVENT__DISABLE_THREAD_SUPPORT
  117. static void *arc4rand_lock;
  118. #endif
  119. #define ARC4RANDOM_UINT32 ev_uint32_t
  120. #define ARC4RANDOM_NOSTIR
  121. #define ARC4RANDOM_NORANDOM
  122. #define ARC4RANDOM_NOUNIFORM
  123. #include "./arc4random.c"
  124. #ifndef EVENT__DISABLE_THREAD_SUPPORT
  125. int
  126. evutil_secure_rng_global_setup_locks_(const int enable_locks)
  127. {
  128. EVTHREAD_SETUP_GLOBAL_LOCK(arc4rand_lock, 0);
  129. return 0;
  130. }
  131. #endif
  132. static void
  133. evutil_free_secure_rng_globals_locks(void)
  134. {
  135. #ifndef EVENT__DISABLE_THREAD_SUPPORT
  136. if (arc4rand_lock != NULL) {
  137. EVTHREAD_FREE_LOCK(arc4rand_lock, 0);
  138. arc4rand_lock = NULL;
  139. }
  140. #endif
  141. return;
  142. }
  143. int
  144. evutil_secure_rng_set_urandom_device_file(char *fname)
  145. {
  146. #ifdef TRY_SEED_URANDOM
  147. ARC4_LOCK_();
  148. arc4random_urandom_filename = fname;
  149. ARC4_UNLOCK_();
  150. #endif
  151. return 0;
  152. }
  153. int
  154. evutil_secure_rng_init(void)
  155. {
  156. int val;
  157. ARC4_LOCK_();
  158. val = (!arc4_stir()) ? 0 : -1;
  159. ARC4_UNLOCK_();
  160. return val;
  161. }
  162. static void
  163. ev_arc4random_buf(void *buf, size_t n)
  164. {
  165. arc4random_buf(buf, n);
  166. }
  167. #endif /* } !EVENT__HAVE_ARC4RANDOM */
  168. void
  169. evutil_secure_rng_get_bytes(void *buf, size_t n)
  170. {
  171. ev_arc4random_buf(buf, n);
  172. }
  173. #if !defined(EVENT__HAVE_ARC4RANDOM) || defined(EVENT__HAVE_ARC4RANDOM_ADDRANDOM)
  174. void
  175. evutil_secure_rng_add_bytes(const char *buf, size_t n)
  176. {
  177. arc4random_addrandom((unsigned char*)buf,
  178. n>(size_t)INT_MAX ? INT_MAX : (int)n);
  179. }
  180. #endif
  181. void
  182. evutil_free_secure_rng_globals_(void)
  183. {
  184. evutil_free_secure_rng_globals_locks();
  185. }