You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

186 lines
5.5 KiB

  1. /**
  2. * @cond internal
  3. * @file spongerng.c
  4. * @copyright
  5. * Copyright (c) 2015-2017 Cryptography Research, Inc. \n
  6. * Released under the MIT License. See LICENSE.txt for license information.
  7. * @author Mike Hamburg
  8. * @brief Spongerng instances (STROBE removed)
  9. * @warning The SpongeRNG code isn't stable. Future versions are likely to
  10. * have different outputs. Of course, this only matters in deterministic mode.
  11. */
  12. #define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */
  13. #include <assert.h>
  14. #include <stdint.h>
  15. #include <string.h>
  16. #include "keccak_internal.h"
  17. #include <decaf/spongerng.h>
  18. /* to open and read from /dev/urandom */
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <fcntl.h>
  22. #if defined(_MSC_VER)
  23. # include <io.h>
  24. #include <BaseTsd.h>
  25. typedef SSIZE_T ssize_t;
  26. #else
  27. # include <unistd.h>
  28. #endif
  29. /** Get entropy from a CPU, preferably in the form of RDRAND, but possibly instead from RDTSC. */
  30. static void get_cpu_entropy(uint8_t *entropy, size_t len) {
  31. # if (defined(__i386__) || defined(__x86_64__))
  32. static char tested = 0, have_rdrand = 0;
  33. if (!tested) {
  34. uint32_t a,b,c,d;
  35. #if defined(__i386__) && defined(__PIC__)
  36. /* Don't clobber ebx. The compiler doesn't like when when __PIC__ */
  37. __asm__("mov %%ebx, %[not_ebx]\n\t"
  38. "cpuid\n\t"
  39. "xchg %%ebx, %[not_ebx]" : "=a"(a), [not_ebx]"=r"(b), "=c"(c), "=d"(d) : "0"(1));
  40. #elif defined(__x86_64__) && defined(__PIC__)
  41. /* Don't clobber rbx. The compiler doesn't like when when __PIC__ */
  42. uint64_t b64;
  43. __asm__("mov %%rbx, %[not_rbx]\n\t"
  44. "cpuid\n\t"
  45. "xchg %%rbx, %[not_rbx]" : "=a"(a), [not_rbx]"=r"(b64), "=c"(c), "=d"(d) : "0"(1));
  46. b = b64;
  47. #else
  48. __asm__("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(1));
  49. #endif
  50. (void)a; (void)b; (void)d;
  51. have_rdrand = (c>>30)&1;
  52. tested = 1;
  53. }
  54. if (have_rdrand) {
  55. # if defined(__x86_64__)
  56. uint64_t out, a=0, *eo = (uint64_t *)entropy;
  57. # elif defined(__i386__)
  58. uint32_t out, a=0, *eo = (uint32_t *)entropy;
  59. #endif
  60. len /= sizeof(out);
  61. uint32_t tries;
  62. for (tries = 100+len; tries && len; len--, eo++) {
  63. for (a = 0; tries && !a; tries--) {
  64. __asm__ __volatile__ ("rdrand %0\n\tsetc %%al" : "=r"(out), "+a"(a) :: "cc" );
  65. }
  66. *eo ^= out;
  67. }
  68. } else if (len>=8) {
  69. #ifndef __has_builtin
  70. #define __has_builtin(X) 0
  71. #endif
  72. #if defined(__clang__) && __has_builtin(__builtin_readcyclecounter)
  73. *(uint64_t*) entropy ^= __builtin_readcyclecounter();
  74. #elif defined(__x86_64__)
  75. uint32_t lobits, hibits;
  76. __asm__ __volatile__ ("rdtsc" : "=a"(lobits), "=d"(hibits));
  77. *(uint64_t*) entropy ^= (lobits | ((uint64_t)(hibits) << 32));
  78. #elif defined(__i386__)
  79. uint64_t __value;
  80. __asm__ __volatile__ ("rdtsc" : "=A"(__value));
  81. *(uint64_t*) entropy ^= __value;
  82. #endif
  83. }
  84. #else
  85. (void) entropy;
  86. (void) len;
  87. #endif
  88. }
  89. void decaf_spongerng_next (
  90. decaf_keccak_prng_t prng,
  91. uint8_t * __restrict__ out,
  92. size_t len
  93. ) {
  94. if (prng->sponge->params->remaining) {
  95. /* nondet */
  96. uint8_t cpu_entropy[32] = {0};
  97. get_cpu_entropy(cpu_entropy, sizeof(cpu_entropy));
  98. decaf_spongerng_stir(prng,cpu_entropy,sizeof(cpu_entropy));
  99. decaf_bzero(cpu_entropy,sizeof(cpu_entropy));
  100. }
  101. uint8_t lenx[8];
  102. size_t len1 = len;
  103. for (unsigned i=0; i<sizeof(lenx); i++) {
  104. lenx[i] = len1;
  105. len1 >>= 8;
  106. }
  107. decaf_sha3_update(prng->sponge,lenx,sizeof(lenx));
  108. decaf_sha3_output(prng->sponge,out,len);
  109. const uint8_t nope;
  110. decaf_spongerng_stir(prng,&nope,0);
  111. }
  112. void decaf_spongerng_stir (
  113. decaf_keccak_prng_t prng,
  114. const uint8_t * __restrict__ in,
  115. size_t len
  116. ) {
  117. uint8_t seed[32];
  118. decaf_sha3_output(prng->sponge,seed,sizeof(seed));
  119. uint8_t nondet = prng->sponge->params->remaining;
  120. decaf_sha3_reset(prng->sponge);
  121. decaf_sha3_update(prng->sponge,seed,sizeof(seed));
  122. decaf_sha3_update(prng->sponge,in,len);
  123. prng->sponge->params->remaining = nondet;
  124. decaf_bzero(seed,sizeof(seed));
  125. }
  126. void decaf_spongerng_init_from_buffer (
  127. decaf_keccak_prng_t prng,
  128. const uint8_t * __restrict__ in,
  129. size_t len,
  130. int deterministic
  131. ) {
  132. decaf_sha3_init(prng->sponge,&DECAF_SHAKE256_params_s);
  133. prng->sponge->params->remaining = !deterministic; /* A bit of a hack; this param is ignored for SHAKE */
  134. decaf_spongerng_stir(prng, in, len);
  135. }
  136. decaf_error_t decaf_spongerng_init_from_file (
  137. decaf_keccak_prng_t prng,
  138. const char *file,
  139. size_t len,
  140. int deterministic
  141. ) {
  142. decaf_sha3_init(prng->sponge,&DECAF_SHAKE256_params_s);
  143. prng->sponge->params->remaining = !deterministic; /* A bit of a hack; this param is ignored for SHAKE */
  144. if (!len) return DECAF_FAILURE;
  145. int fd = open(file, O_RDONLY);
  146. if (fd < 0) return DECAF_FAILURE;
  147. uint8_t buffer[128];
  148. while (len) {
  149. ssize_t red = read(fd, buffer, (len > sizeof(buffer)) ? sizeof(buffer) : len);
  150. if (red <= 0) {
  151. close(fd);
  152. return DECAF_FAILURE;
  153. }
  154. decaf_sha3_update(prng->sponge,buffer,red);
  155. len -= red;
  156. };
  157. close(fd);
  158. const uint8_t nope;
  159. decaf_spongerng_stir(prng,&nope,0);
  160. return DECAF_SUCCESS;
  161. }
  162. decaf_error_t decaf_spongerng_init_from_dev_urandom (
  163. decaf_keccak_prng_t decaf_sponge
  164. ) {
  165. return decaf_spongerng_init_from_file(decaf_sponge, "/dev/urandom", 64, 0);
  166. }