crypto_random.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  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 "gnunet_time_lib.h"
  24. #include <gcrypt.h>
  25. #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-random", __VA_ARGS__)
  26. #define LOG_STRERROR(kind, syscall) \
  27. GNUNET_log_from_strerror (kind, "util-crypto-random", syscall)
  28. /* TODO: ndurner, move this to plibc? */
  29. /* The code is derived from glibc, obviously */
  30. #if ! HAVE_RANDOM || ! HAVE_SRANDOM
  31. #ifdef RANDOM
  32. #undef RANDOM
  33. #endif
  34. #ifdef SRANDOM
  35. #undef SRANDOM
  36. #endif
  37. #define RANDOM() glibc_weak_rand32 ()
  38. #define SRANDOM(s) glibc_weak_srand32 (s)
  39. #if defined(RAND_MAX)
  40. #undef RAND_MAX
  41. #endif
  42. #define RAND_MAX 0x7fffffff /* Hopefully this is correct */
  43. static int32_t glibc_weak_rand32_state = 1;
  44. void
  45. glibc_weak_srand32 (int32_t s)
  46. {
  47. glibc_weak_rand32_state = s;
  48. }
  49. int32_t
  50. glibc_weak_rand32 ()
  51. {
  52. int32_t val = glibc_weak_rand32_state;
  53. val = ((glibc_weak_rand32_state * 1103515245) + 12345) & 0x7fffffff;
  54. glibc_weak_rand32_state = val;
  55. return val;
  56. }
  57. #endif
  58. /**
  59. * Create a cryptographically weak pseudo-random number in the interval of 0 to 1.
  60. *
  61. * @return number between 0 and 1.
  62. */
  63. static double
  64. get_weak_random (void)
  65. {
  66. return((double) random () / RAND_MAX);
  67. }
  68. /**
  69. * Seed a weak random generator. Only #GNUNET_CRYPTO_QUALITY_WEAK-mode generator
  70. * can be seeded.
  71. *
  72. * @param seed the seed to use
  73. */
  74. void
  75. GNUNET_CRYPTO_seed_weak_random (int32_t seed)
  76. {
  77. srandom (seed);
  78. }
  79. /**
  80. * @ingroup crypto
  81. * Zero out @a buffer, securely against compiler optimizations.
  82. * Used to delete key material.
  83. *
  84. * @param buffer the buffer to zap
  85. * @param length buffer length
  86. */
  87. void
  88. GNUNET_CRYPTO_zero_keys (void *buffer, size_t length)
  89. {
  90. #if HAVE_MEMSET_S
  91. memset_s (buffer, length, 0, length);
  92. #elif HAVE_EXPLICIT_BZERO
  93. explicit_bzero (buffer, length);
  94. #else
  95. volatile unsigned char *p = buffer;
  96. while (length--)
  97. *p++ = 0;
  98. #endif
  99. }
  100. /**
  101. * @ingroup crypto
  102. * Fill block with a random values.
  103. *
  104. * @param mode desired quality of the random number
  105. * @param buffer the buffer to fill
  106. * @param length buffer length
  107. */
  108. void
  109. GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode,
  110. void *buffer,
  111. size_t length)
  112. {
  113. #ifdef gcry_fast_random_poll
  114. static unsigned int invokeCount;
  115. #endif
  116. switch (mode)
  117. {
  118. case GNUNET_CRYPTO_QUALITY_STRONG:
  119. /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
  120. #ifdef gcry_fast_random_poll
  121. if ((invokeCount++ % 256) == 0)
  122. gcry_fast_random_poll ();
  123. #endif
  124. gcry_randomize (buffer, length, GCRY_STRONG_RANDOM);
  125. return;
  126. case GNUNET_CRYPTO_QUALITY_NONCE:
  127. gcry_create_nonce (buffer, length);
  128. return;
  129. case GNUNET_CRYPTO_QUALITY_WEAK:
  130. /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
  131. #ifdef gcry_fast_random_poll
  132. if ((invokeCount++ % 256) == 0)
  133. gcry_fast_random_poll ();
  134. #endif
  135. gcry_randomize (buffer, length, GCRY_WEAK_RANDOM);
  136. return;
  137. default:
  138. GNUNET_assert (0);
  139. }
  140. }
  141. /**
  142. * Produce a random unsigned 32-bit number modulo @a i.
  143. *
  144. * @param mode desired quality of the random number
  145. * @param i the upper limit (exclusive) for the random number
  146. * @return a random value in the interval [0,i[.
  147. */
  148. uint32_t
  149. GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode,
  150. uint32_t i)
  151. {
  152. #ifdef gcry_fast_random_poll
  153. static unsigned int invokeCount;
  154. #endif
  155. uint32_t ret;
  156. uint32_t ul;
  157. GNUNET_assert (i > 0);
  158. switch (mode)
  159. {
  160. case GNUNET_CRYPTO_QUALITY_STRONG:
  161. /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */
  162. #ifdef gcry_fast_random_poll
  163. if ((invokeCount++ % 256) == 0)
  164. gcry_fast_random_poll ();
  165. #endif
  166. ul = UINT32_MAX - (UINT32_MAX % i);
  167. do
  168. {
  169. gcry_randomize ((unsigned char *) &ret,
  170. sizeof(uint32_t),
  171. GCRY_STRONG_RANDOM);
  172. }
  173. while (ret >= ul);
  174. return ret % i;
  175. case GNUNET_CRYPTO_QUALITY_NONCE:
  176. ul = UINT32_MAX - (UINT32_MAX % i);
  177. do
  178. {
  179. gcry_create_nonce (&ret, sizeof(ret));
  180. }
  181. while (ret >= ul);
  182. return ret % i;
  183. case GNUNET_CRYPTO_QUALITY_WEAK:
  184. ret = i * get_weak_random ();
  185. if (ret >= i)
  186. ret = i - 1;
  187. return ret;
  188. default:
  189. GNUNET_assert (0);
  190. }
  191. return 0;
  192. }
  193. /**
  194. * Get an array with a random permutation of the
  195. * numbers 0...n-1.
  196. * @param mode #GNUNET_RANDOM_QUALITY_STRONG if the strong (but expensive)
  197. * PRNG should be used, #GNUNET_RANDOM_QUALITY_WEAK otherwise
  198. * @param n the size of the array
  199. * @return the permutation array (allocated from heap)
  200. */
  201. unsigned int *
  202. GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode,
  203. unsigned int n)
  204. {
  205. unsigned int *ret;
  206. unsigned int i;
  207. unsigned int tmp;
  208. uint32_t x;
  209. GNUNET_assert (n > 0);
  210. ret = GNUNET_malloc (n * sizeof(unsigned int));
  211. for (i = 0; i < n; i++)
  212. ret[i] = i;
  213. for (i = n - 1; i > 0; i--)
  214. {
  215. x = GNUNET_CRYPTO_random_u32 (mode, i + 1);
  216. tmp = ret[x];
  217. ret[x] = ret[i];
  218. ret[i] = tmp;
  219. }
  220. return ret;
  221. }
  222. /**
  223. * Generate random unsigned 64-bit value.
  224. *
  225. * @param mode desired quality of the random number
  226. * @param max value returned will be in range [0,max) (exclusive)
  227. * @return random 64-bit number
  228. */
  229. uint64_t
  230. GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode,
  231. uint64_t max)
  232. {
  233. uint64_t ret;
  234. uint64_t ul;
  235. GNUNET_assert (max > 0);
  236. switch (mode)
  237. {
  238. case GNUNET_CRYPTO_QUALITY_STRONG:
  239. ul = UINT64_MAX - (UINT64_MAX % max);
  240. do
  241. {
  242. gcry_randomize ((unsigned char *) &ret,
  243. sizeof(uint64_t),
  244. GCRY_STRONG_RANDOM);
  245. }
  246. while (ret >= ul);
  247. return ret % max;
  248. case GNUNET_CRYPTO_QUALITY_NONCE:
  249. ul = UINT64_MAX - (UINT64_MAX % max);
  250. do
  251. {
  252. gcry_create_nonce (&ret, sizeof(ret));
  253. }
  254. while (ret >= ul);
  255. return ret % max;
  256. case GNUNET_CRYPTO_QUALITY_WEAK:
  257. ret = max * get_weak_random ();
  258. if (ret >= max)
  259. ret = max - 1;
  260. return ret;
  261. default:
  262. GNUNET_assert (0);
  263. }
  264. return 0;
  265. }
  266. /**
  267. * @ingroup crypto
  268. * Fill UUID with a timeflake pseudo-random value. Note that
  269. * timeflakes use only 80 bits of randomness and 48 bits
  270. * to encode a timestamp in milliseconds. So what we return
  271. * here is not a completely random number.
  272. *
  273. * @param mode desired quality of the random number
  274. * @param uuid the value to fill
  275. */
  276. void
  277. GNUNET_CRYPTO_random_timeflake (enum GNUNET_CRYPTO_Quality mode,
  278. struct GNUNET_Uuid *uuid)
  279. {
  280. struct GNUNET_TIME_Absolute now;
  281. uint64_t ms;
  282. uint64_t be;
  283. char *base;
  284. GNUNET_CRYPTO_random_block (mode,
  285. uuid,
  286. sizeof (struct GNUNET_Uuid));
  287. now = GNUNET_TIME_absolute_get ();
  288. ms = now.abs_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
  289. be = GNUNET_htonll (ms);
  290. base = (char *) &be;
  291. memcpy (uuid,
  292. base + 2,
  293. sizeof (be) - 2);
  294. }
  295. /**
  296. * Allocation wrapper for libgcrypt, used to avoid bad locking
  297. * strategy of libgcrypt implementation.
  298. */
  299. static void *
  300. w_malloc (size_t n)
  301. {
  302. return calloc (n, 1);
  303. }
  304. /**
  305. * Allocation wrapper for libgcrypt, used to avoid bad locking
  306. * strategy of libgcrypt implementation.
  307. */
  308. static int
  309. w_check (const void *p)
  310. {
  311. (void) p;
  312. return 0; /* not secure memory */
  313. }
  314. /**
  315. * Initialize libgcrypt.
  316. */
  317. void __attribute__ ((constructor))
  318. GNUNET_CRYPTO_random_init ()
  319. {
  320. gcry_error_t rc;
  321. if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
  322. {
  323. fprintf (
  324. stderr,
  325. _ ("libgcrypt has not the expected version (version %s is required).\n"),
  326. NEED_LIBGCRYPT_VERSION);
  327. GNUNET_assert (0);
  328. }
  329. /* set custom allocators */
  330. gcry_set_allocation_handler (&w_malloc, &w_malloc, &w_check, &realloc, &free);
  331. /* Disable use of secure memory */
  332. if ((rc = gcry_control (GCRYCTL_DISABLE_SECMEM, 0)))
  333. fprintf (stderr,
  334. "Failed to set libgcrypt option %s: %s\n",
  335. "DISABLE_SECMEM",
  336. gcry_strerror (rc));
  337. /* Otherwise gnunet-ecc takes forever to complete, besides
  338. we are fine with "just" using GCRY_STRONG_RANDOM */
  339. if ((rc = gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0)))
  340. fprintf (stderr,
  341. "Failed to set libgcrypt option %s: %s\n",
  342. "ENABLE_QUICK_RANDOM",
  343. gcry_strerror (rc));
  344. gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
  345. gcry_fast_random_poll ();
  346. GNUNET_CRYPTO_seed_weak_random (
  347. time (NULL)
  348. ^ GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
  349. }
  350. /**
  351. * Nicely shut down libgcrypt.
  352. */
  353. void __attribute__ ((destructor))
  354. GNUNET_CRYPTO_random_fini ()
  355. {
  356. gcry_set_progress_handler (NULL, NULL);
  357. #ifdef GCRYCTL_CLOSE_RANDOM_DEVICE
  358. (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
  359. #endif
  360. }
  361. /* end of crypto_random.c */