fortuna.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /* LibTomCrypt, modular cryptographic library -- Tom St Denis
  2. *
  3. * LibTomCrypt is a library that provides various cryptographic
  4. * algorithms in a highly modular and flexible manner.
  5. *
  6. * The library is free for all purposes without any express
  7. * guarantee it works.
  8. *
  9. * Tom St Denis, [email protected], http://libtomcrypt.org
  10. */
  11. /* Implementation of Fortuna by Tom St Denis
  12. We deviate slightly here for reasons of simplicity [and to fit in the API]. First all "sources"
  13. in the AddEntropy function are fixed to 0. Second since no reliable timer is provided
  14. we reseed automatically when len(pool0) >= 64 or every FORTUNA_WD calls to the read function */
  15. #include "mycrypt.h"
  16. #ifdef FORTUNA
  17. /* requries SHA256 and AES */
  18. #if !(defined(RIJNDAEL) && defined(SHA256))
  19. #error FORTUNA requires SHA256 and RIJNDAEL (AES)
  20. #endif
  21. #ifndef FORTUNA_POOLS
  22. #warning FORTUNA_POOLS was not previously defined (old headers?)
  23. #define FORTUNA_POOLS 32
  24. #endif
  25. #if FORTUNA_POOLS < 4 || FORTUNA_POOLS > 32
  26. #error FORTUNA_POOLS must be in [4..32]
  27. #endif
  28. const struct _prng_descriptor fortuna_desc = {
  29. "fortuna", 1024,
  30. &fortuna_start,
  31. &fortuna_add_entropy,
  32. &fortuna_ready,
  33. &fortuna_read,
  34. &fortuna_done,
  35. &fortuna_export,
  36. &fortuna_import,
  37. &fortuna_test
  38. };
  39. /* update the IV */
  40. static void fortuna_update_iv(prng_state *prng)
  41. {
  42. int x;
  43. unsigned char *IV;
  44. /* update IV */
  45. IV = prng->fortuna.IV;
  46. for (x = 0; x < 16; x++) {
  47. IV[x] = (IV[x] + 1) & 255;
  48. if (IV[x] != 0) break;
  49. }
  50. }
  51. /* reseed the PRNG */
  52. static int fortuna_reseed(prng_state *prng)
  53. {
  54. unsigned char tmp[MAXBLOCKSIZE];
  55. hash_state md;
  56. int err, x;
  57. ++prng->fortuna.reset_cnt;
  58. /* new K == SHA256(K || s) where s == SHA256(P0) || SHA256(P1) ... */
  59. sha256_init(&md);
  60. if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) {
  61. return err;
  62. }
  63. for (x = 0; x < FORTUNA_POOLS; x++) {
  64. if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) {
  65. /* terminate this hash */
  66. if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) {
  67. return err;
  68. }
  69. /* add it to the string */
  70. if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) {
  71. return err;
  72. }
  73. /* reset this pool */
  74. sha256_init(&prng->fortuna.pool[x]);
  75. } else {
  76. break;
  77. }
  78. }
  79. /* finish key */
  80. if ((err = sha256_done(&md, prng->fortuna.K)) != CRYPT_OK) {
  81. return err;
  82. }
  83. if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
  84. return err;
  85. }
  86. fortuna_update_iv(prng);
  87. /* reset pool len */
  88. prng->fortuna.pool0_len = 0;
  89. prng->fortuna.wd = 0;
  90. #ifdef CLEAN_STACK
  91. zeromem(&md, sizeof(md));
  92. zeromem(tmp, sizeof(tmp));
  93. #endif
  94. return CRYPT_OK;
  95. }
  96. int fortuna_start(prng_state *prng)
  97. {
  98. int err, x;
  99. _ARGCHK(prng != NULL);
  100. /* initialize the pools */
  101. for (x = 0; x < FORTUNA_POOLS; x++) {
  102. sha256_init(&prng->fortuna.pool[x]);
  103. }
  104. prng->fortuna.pool_idx = prng->fortuna.pool0_len = prng->fortuna.reset_cnt =
  105. prng->fortuna.wd = 0;
  106. /* reset bufs */
  107. zeromem(prng->fortuna.K, 32);
  108. if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
  109. return err;
  110. }
  111. zeromem(prng->fortuna.IV, 16);
  112. return CRYPT_OK;
  113. }
  114. int fortuna_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
  115. {
  116. unsigned char tmp[2];
  117. int err;
  118. _ARGCHK(buf != NULL);
  119. _ARGCHK(prng != NULL);
  120. /* ensure len <= 32 */
  121. if (len > 32) {
  122. return CRYPT_INVALID_ARG;
  123. }
  124. /* add s || length(buf) || buf to pool[pool_idx] */
  125. tmp[0] = 0;
  126. tmp[1] = len;
  127. if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], tmp, 2)) != CRYPT_OK) {
  128. return err;
  129. }
  130. if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], buf, len)) != CRYPT_OK) {
  131. return err;
  132. }
  133. if (prng->fortuna.pool_idx == 0) {
  134. prng->fortuna.pool0_len += len;
  135. }
  136. if (++(prng->fortuna.pool_idx) == FORTUNA_POOLS) {
  137. prng->fortuna.pool_idx = 0;
  138. }
  139. return CRYPT_OK;
  140. }
  141. int fortuna_ready(prng_state *prng)
  142. {
  143. return fortuna_reseed(prng);
  144. }
  145. unsigned long fortuna_read(unsigned char *dst, unsigned long len, prng_state *prng)
  146. {
  147. unsigned char tmp[16];
  148. int err;
  149. unsigned long tlen;
  150. _ARGCHK(dst != NULL);
  151. _ARGCHK(prng != NULL);
  152. /* do we have to reseed? */
  153. if (++prng->fortuna.wd == FORTUNA_WD || prng->fortuna.pool0_len >= 64) {
  154. if ((err = fortuna_reseed(prng)) != CRYPT_OK) {
  155. return 0;
  156. }
  157. }
  158. /* now generate the blocks required */
  159. tlen = len;
  160. /* handle whole blocks without the extra memcpy */
  161. while (len >= 16) {
  162. /* encrypt the IV and store it */
  163. rijndael_ecb_encrypt(prng->fortuna.IV, dst, &prng->fortuna.skey);
  164. dst += 16;
  165. len -= 16;
  166. fortuna_update_iv(prng);
  167. }
  168. /* left over bytes? */
  169. if (len > 0) {
  170. rijndael_ecb_encrypt(prng->fortuna.IV, tmp, &prng->fortuna.skey);
  171. XMEMCPY(dst, tmp, len);
  172. fortuna_update_iv(prng);
  173. }
  174. /* generate new key */
  175. rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K , &prng->fortuna.skey); fortuna_update_iv(prng);
  176. rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K+16, &prng->fortuna.skey); fortuna_update_iv(prng);
  177. if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
  178. return 0;
  179. }
  180. #ifdef CLEAN_STACK
  181. zeromem(tmp, sizeof(tmp));
  182. #endif
  183. return tlen;
  184. }
  185. int fortuna_done(prng_state *prng)
  186. {
  187. int err, x;
  188. unsigned char tmp[32];
  189. _ARGCHK(prng != NULL);
  190. /* terminate all the hashes */
  191. for (x = 0; x < FORTUNA_POOLS; x++) {
  192. if ((err = sha256_done(&(prng->fortuna.pool[x]), tmp)) != CRYPT_OK) {
  193. return err;
  194. }
  195. }
  196. /* call cipher done when we invent one ;-) */
  197. #ifdef CLEAN_STACK
  198. zeromem(tmp, sizeof(tmp));
  199. #endif
  200. return CRYPT_OK;
  201. }
  202. int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
  203. {
  204. int x, err;
  205. hash_state *md;
  206. _ARGCHK(out != NULL);
  207. _ARGCHK(outlen != NULL);
  208. _ARGCHK(prng != NULL);
  209. /* we'll write bytes for s&g's */
  210. if (*outlen < 32*FORTUNA_POOLS) {
  211. return CRYPT_BUFFER_OVERFLOW;
  212. }
  213. md = XMALLOC(sizeof(hash_state));
  214. if (md == NULL) {
  215. return CRYPT_MEM;
  216. }
  217. /* to emit the state we copy each pool, terminate it then hash it again so
  218. * an attacker who sees the state can't determine the current state of the PRNG
  219. */
  220. for (x = 0; x < FORTUNA_POOLS; x++) {
  221. /* copy the PRNG */
  222. XMEMCPY(md, &(prng->fortuna.pool[x]), sizeof(*md));
  223. /* terminate it */
  224. if ((err = sha256_done(md, out+x*32)) != CRYPT_OK) {
  225. goto __ERR;
  226. }
  227. /* now hash it */
  228. sha256_init(md);
  229. if ((err = sha256_process(md, out+x*32, 32)) != CRYPT_OK) {
  230. goto __ERR;
  231. }
  232. if ((err = sha256_done(md, out+x*32)) != CRYPT_OK) {
  233. goto __ERR;
  234. }
  235. }
  236. *outlen = 32*FORTUNA_POOLS;
  237. err = CRYPT_OK;
  238. __ERR:
  239. #ifdef CLEAN_STACK
  240. zeromem(md, sizeof(*md));
  241. #endif
  242. XFREE(md);
  243. return err;
  244. }
  245. int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
  246. {
  247. int err, x;
  248. _ARGCHK(in != NULL);
  249. _ARGCHK(prng != NULL);
  250. if (inlen != 32*FORTUNA_POOLS) {
  251. return CRYPT_INVALID_ARG;
  252. }
  253. if ((err = fortuna_start(prng)) != CRYPT_OK) {
  254. return err;
  255. }
  256. for (x = 0; x < FORTUNA_POOLS; x++) {
  257. if ((err = fortuna_add_entropy(in+x*32, 32, prng)) != CRYPT_OK) {
  258. return err;
  259. }
  260. }
  261. return err;
  262. }
  263. int fortuna_test(void)
  264. {
  265. #ifndef LTC_TEST
  266. return CRYPT_NOP;
  267. #else
  268. int err;
  269. if ((err = sha256_test()) != CRYPT_OK) {
  270. return err;
  271. }
  272. return rijndael_test();
  273. #endif
  274. }
  275. #endif