crypto_random.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /*
  2. This file is part of GNUnet. Copyright (C) 2001-2014 Christian Grothoff
  3. (and other contributing authors)
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file util/crypto_random.c
  18. * @brief functions to gather random numbers
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_crypto_lib.h"
  23. #include <gcrypt.h>
  24. #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-random", __VA_ARGS__)
  25. #define LOG_STRERROR(kind, syscall) \
  26. GNUNET_log_from_strerror (kind, "util-crypto-random", syscall)
  27. /* TODO: ndurner, move this to plibc? */
  28. /* The code is derived from glibc, obviously */
  29. #if ! HAVE_RANDOM || ! HAVE_SRANDOM
  30. #ifdef RANDOM
  31. #undef RANDOM
  32. #endif
  33. #ifdef SRANDOM
  34. #undef SRANDOM
  35. #endif
  36. #define RANDOM() glibc_weak_rand32 ()
  37. #define SRANDOM(s) glibc_weak_srand32 (s)
  38. #if defined(RAND_MAX)
  39. #undef RAND_MAX
  40. #endif
  41. #define RAND_MAX 0x7fffffff /* Hopefully this is correct */
  42. static int32_t glibc_weak_rand32_state = 1;
  43. void
  44. glibc_weak_srand32 (int32_t s)
  45. {
  46. glibc_weak_rand32_state = s;
  47. }
  48. int32_t
  49. glibc_weak_rand32 ()
  50. {
  51. int32_t val = glibc_weak_rand32_state;
  52. val = ((glibc_weak_rand32_state * 1103515245) + 12345) & 0x7fffffff;
  53. glibc_weak_rand32_state = val;
  54. return val;
  55. }
  56. #endif
  57. /**
  58. * Create a cryptographically weak pseudo-random number in the interval of 0 to 1.
  59. *
  60. * @return number between 0 and 1.
  61. */
  62. static double
  63. get_weak_random ()
  64. {
  65. return((double) random () / RAND_MAX);
  66. }
  67. /**
  68. * Seed a weak random generator. Only #GNUNET_CRYPTO_QUALITY_WEAK-mode generator
  69. * can be seeded.
  70. *
  71. * @param seed the seed to use
  72. */
  73. void
  74. GNUNET_CRYPTO_seed_weak_random (int32_t seed)
  75. {
  76. srandom (seed);
  77. }
  78. /**
  79. * @ingroup crypto
  80. * Zero out @a buffer, securely against compiler optimizations.
  81. * Used to delete key material.
  82. *
  83. * @param buffer the buffer to zap
  84. * @param length buffer length
  85. */
  86. void
  87. GNUNET_CRYPTO_zero_keys (void *buffer, size_t length)
  88. {
  89. #if HAVE_MEMSET_S
  90. memset_s (buffer, length, 0, length);
  91. #elif HAVE_EXPLICIT_BZERO
  92. explicit_bzero (buffer, length);
  93. #else
  94. volatile unsigned char *p = buffer;
  95. while (length--)
  96. *p++ = 0;
  97. #endif
  98. }
  99. /**
  100. * @ingroup crypto
  101. * Fill block with a random values.
  102. *
  103. * @param mode desired quality of the random number
  104. * @param buffer the buffer to fill
  105. * @param length buffer length
  106. */
  107. void
  108. GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode,
  109. void *buffer,
  110. size_t length)
  111. {
  112. #ifdef gcry_fast_random_poll
  113. static unsigned int invokeCount;
  114. #endif
  115. switch (mode)
  116. {
  117. case GNUNET_CRYPTO_QUALITY_STRONG:
  118. /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
  119. #ifdef gcry_fast_random_poll
  120. if ((invokeCount++ % 256) == 0)
  121. gcry_fast_random_poll ();
  122. #endif
  123. gcry_randomize (buffer, length, GCRY_STRONG_RANDOM);
  124. return;
  125. case GNUNET_CRYPTO_QUALITY_NONCE:
  126. gcry_create_nonce (buffer, length);
  127. return;
  128. case GNUNET_CRYPTO_QUALITY_WEAK:
  129. /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
  130. #ifdef gcry_fast_random_poll
  131. if ((invokeCount++ % 256) == 0)
  132. gcry_fast_random_poll ();
  133. #endif
  134. gcry_randomize (buffer, length, GCRY_WEAK_RANDOM);
  135. return;
  136. default:
  137. GNUNET_assert (0);
  138. }
  139. }
  140. /**
  141. * Produce a random unsigned 32-bit number modulo @a i.
  142. *
  143. * @param mode desired quality of the random number
  144. * @param i the upper limit (exclusive) for the random number
  145. * @return a random value in the interval [0,i[.
  146. */
  147. uint32_t
  148. GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i)
  149. {
  150. #ifdef gcry_fast_random_poll
  151. static unsigned int invokeCount;
  152. #endif
  153. uint32_t ret;
  154. uint32_t ul;
  155. GNUNET_assert (i > 0);
  156. switch (mode)
  157. {
  158. case GNUNET_CRYPTO_QUALITY_STRONG:
  159. /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
  160. #ifdef gcry_fast_random_poll
  161. if ((invokeCount++ % 256) == 0)
  162. gcry_fast_random_poll ();
  163. #endif
  164. ul = UINT32_MAX - (UINT32_MAX % i);
  165. do
  166. {
  167. gcry_randomize ((unsigned char *) &ret,
  168. sizeof(uint32_t),
  169. GCRY_STRONG_RANDOM);
  170. }
  171. while (ret >= ul);
  172. return ret % i;
  173. case GNUNET_CRYPTO_QUALITY_NONCE:
  174. ul = UINT32_MAX - (UINT32_MAX % i);
  175. do
  176. {
  177. gcry_create_nonce (&ret, sizeof(ret));
  178. }
  179. while (ret >= ul);
  180. return ret % i;
  181. case GNUNET_CRYPTO_QUALITY_WEAK:
  182. ret = i * get_weak_random ();
  183. if (ret >= i)
  184. ret = i - 1;
  185. return ret;
  186. default:
  187. GNUNET_assert (0);
  188. }
  189. return 0;
  190. }
  191. /**
  192. * Get an array with a random permutation of the
  193. * numbers 0...n-1.
  194. * @param mode #GNUNET_RANDOM_QUALITY_STRONG if the strong (but expensive)
  195. * PRNG should be used, #GNUNET_RANDOM_QUALITY_WEAK otherwise
  196. * @param n the size of the array
  197. * @return the permutation array (allocated from heap)
  198. */
  199. unsigned int *
  200. GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n)
  201. {
  202. unsigned int *ret;
  203. unsigned int i;
  204. unsigned int tmp;
  205. uint32_t x;
  206. GNUNET_assert (n > 0);
  207. ret = GNUNET_malloc (n * sizeof(unsigned int));
  208. for (i = 0; i < n; i++)
  209. ret[i] = i;
  210. for (i = n - 1; i > 0; i--)
  211. {
  212. x = GNUNET_CRYPTO_random_u32 (mode, i + 1);
  213. tmp = ret[x];
  214. ret[x] = ret[i];
  215. ret[i] = tmp;
  216. }
  217. return ret;
  218. }
  219. /**
  220. * Generate random unsigned 64-bit value.
  221. *
  222. * @param mode desired quality of the random number
  223. * @param max value returned will be in range [0,max) (exclusive)
  224. * @return random 64-bit number
  225. */
  226. uint64_t
  227. GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max)
  228. {
  229. uint64_t ret;
  230. uint64_t ul;
  231. GNUNET_assert (max > 0);
  232. switch (mode)
  233. {
  234. case GNUNET_CRYPTO_QUALITY_STRONG:
  235. ul = UINT64_MAX - (UINT64_MAX % max);
  236. do
  237. {
  238. gcry_randomize ((unsigned char *) &ret,
  239. sizeof(uint64_t),
  240. GCRY_STRONG_RANDOM);
  241. }
  242. while (ret >= ul);
  243. return ret % max;
  244. case GNUNET_CRYPTO_QUALITY_NONCE:
  245. ul = UINT64_MAX - (UINT64_MAX % max);
  246. do
  247. {
  248. gcry_create_nonce (&ret, sizeof(ret));
  249. }
  250. while (ret >= ul);
  251. return ret % max;
  252. case GNUNET_CRYPTO_QUALITY_WEAK:
  253. ret = max * get_weak_random ();
  254. if (ret >= max)
  255. ret = max - 1;
  256. return ret;
  257. default:
  258. GNUNET_assert (0);
  259. }
  260. return 0;
  261. }
  262. /**
  263. * Allocation wrapper for libgcrypt, used to avoid bad locking
  264. * strategy of libgcrypt implementation.
  265. */
  266. static void *
  267. w_malloc (size_t n)
  268. {
  269. return calloc (n, 1);
  270. }
  271. /**
  272. * Allocation wrapper for libgcrypt, used to avoid bad locking
  273. * strategy of libgcrypt implementation.
  274. */
  275. static int
  276. w_check (const void *p)
  277. {
  278. (void) p;
  279. return 0; /* not secure memory */
  280. }
  281. /**
  282. * Initialize libgcrypt.
  283. */
  284. void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init ()
  285. {
  286. gcry_error_t rc;
  287. if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
  288. {
  289. fprintf (
  290. stderr,
  291. _ ("libgcrypt has not the expected version (version %s is required).\n"),
  292. NEED_LIBGCRYPT_VERSION);
  293. GNUNET_assert (0);
  294. }
  295. /* set custom allocators */
  296. gcry_set_allocation_handler (&w_malloc, &w_malloc, &w_check, &realloc, &free);
  297. /* Disable use of secure memory */
  298. if ((rc = gcry_control (GCRYCTL_DISABLE_SECMEM, 0)))
  299. fprintf (stderr,
  300. "Failed to set libgcrypt option %s: %s\n",
  301. "DISABLE_SECMEM",
  302. gcry_strerror (rc));
  303. /* Otherwise gnunet-ecc takes forever to complete, besides
  304. we are fine with "just" using GCRY_STRONG_RANDOM */
  305. if ((rc = gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0)))
  306. fprintf (stderr,
  307. "Failed to set libgcrypt option %s: %s\n",
  308. "ENABLE_QUICK_RANDOM",
  309. gcry_strerror (rc));
  310. gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
  311. gcry_fast_random_poll ();
  312. GNUNET_CRYPTO_seed_weak_random (
  313. time (NULL)
  314. ^ GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
  315. }
  316. /**
  317. * Nicely shut down libgcrypt.
  318. */
  319. void __attribute__ ((destructor)) GNUNET_CRYPTO_random_fini ()
  320. {
  321. gcry_set_progress_handler (NULL, NULL);
  322. #ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
  323. (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
  324. #endif
  325. }
  326. /* end of crypto_random.c */