fortuna.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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. const struct _prng_descriptor fortuna_desc = {
  18. "fortuna",
  19. &fortuna_start,
  20. &fortuna_add_entropy,
  21. &fortuna_ready,
  22. &fortuna_read,
  23. &fortuna_done,
  24. &fortuna_export,
  25. &fortuna_import
  26. };
  27. /* update the IV */
  28. static void fortuna_update_iv(prng_state *prng)
  29. {
  30. int x;
  31. unsigned char *IV;
  32. /* update IV */
  33. IV = prng->fortuna.IV;
  34. for (x = 0; x < 16; x++) {
  35. IV[x] = (IV[x] + 1) & 255;
  36. if (IV[x] != 0) break;
  37. }
  38. }
  39. /* reseed the PRNG */
  40. static int fortuna_reseed(prng_state *prng)
  41. {
  42. unsigned char tmp[32];
  43. hash_state md;
  44. int err, x;
  45. ++prng->fortuna.reset_cnt;
  46. /* new K == SHA256(K || s) where s == SHA256(P0) || SHA256(P1) ... */
  47. sha256_init(&md);
  48. if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) {
  49. return err;
  50. }
  51. for (x = 0; x < 32; x++) {
  52. if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) {
  53. /* terminate this hash */
  54. if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) {
  55. return err;
  56. }
  57. /* add it to the string */
  58. if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) {
  59. return err;
  60. }
  61. /* reset this pool */
  62. sha256_init(&prng->fortuna.pool[x]);
  63. } else {
  64. break;
  65. }
  66. }
  67. /* finish key */
  68. if ((err = sha256_done(&md, prng->fortuna.K)) != CRYPT_OK) {
  69. return err;
  70. }
  71. if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
  72. return err;
  73. }
  74. fortuna_update_iv(prng);
  75. /* reset pool len */
  76. prng->fortuna.pool0_len = 0;
  77. prng->fortuna.wd = 0;
  78. #ifdef CLEAN_STACK
  79. zeromem(&md, sizeof(md));
  80. zeromem(tmp, sizeof(tmp));
  81. #endif
  82. return CRYPT_OK;
  83. }
  84. int fortuna_start(prng_state *prng)
  85. {
  86. int err, x;
  87. _ARGCHK(prng != NULL);
  88. /* initialize the pools */
  89. for (x = 0; x < 32; x++) {
  90. sha256_init(&prng->fortuna.pool[x]);
  91. }
  92. prng->fortuna.pool_idx = prng->fortuna.pool0_len = prng->fortuna.reset_cnt =
  93. prng->fortuna.wd = 0;
  94. /* reset bufs */
  95. zeromem(prng->fortuna.K, 32);
  96. if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
  97. return err;
  98. }
  99. zeromem(prng->fortuna.IV, 16);
  100. return CRYPT_OK;
  101. }
  102. int fortuna_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
  103. {
  104. unsigned char tmp[2];
  105. int err;
  106. _ARGCHK(buf != NULL);
  107. _ARGCHK(prng != NULL);
  108. /* ensure len <= 32 */
  109. if (len > 32) {
  110. return CRYPT_INVALID_ARG;
  111. }
  112. /* add s || length(buf) || buf to pool[pool_idx] */
  113. tmp[0] = 0;
  114. tmp[1] = len;
  115. if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], tmp, 2)) != CRYPT_OK) {
  116. return err;
  117. }
  118. if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], buf, len)) != CRYPT_OK) {
  119. return err;
  120. }
  121. if (prng->fortuna.pool_idx == 0) {
  122. prng->fortuna.pool0_len += len + 2;
  123. }
  124. prng->fortuna.pool_idx = (prng->fortuna.pool_idx + 1) & 31;
  125. return CRYPT_OK;
  126. }
  127. int fortuna_ready(prng_state *prng)
  128. {
  129. return fortuna_reseed(prng);
  130. }
  131. unsigned long fortuna_read(unsigned char *dst, unsigned long len, prng_state *prng)
  132. {
  133. unsigned char tmp[16];
  134. int err;
  135. unsigned long tlen, n;
  136. _ARGCHK(dst != NULL);
  137. _ARGCHK(prng != NULL);
  138. /* do we have to reseed? */
  139. if (++prng->fortuna.wd == FORTUNA_WD || prng->fortuna.pool0_len >= 64) {
  140. if ((err = fortuna_reseed(prng)) != CRYPT_OK) {
  141. return 0;
  142. }
  143. }
  144. /* now generate the blocks required */
  145. tlen = len;
  146. while (len > 0) {
  147. if (len >= 16) {
  148. /* encrypt the IV and store it */
  149. rijndael_ecb_encrypt(prng->fortuna.IV, dst, &prng->fortuna.skey);
  150. dst += 16;
  151. len -= 16;
  152. } else {
  153. rijndael_ecb_encrypt(prng->fortuna.IV, tmp, &prng->fortuna.skey);
  154. XMEMCPY(dst, tmp, len);
  155. len = 0;
  156. }
  157. fortuna_update_iv(prng);
  158. }
  159. /* generate new key */
  160. rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K , &prng->fortuna.skey); fortuna_update_iv(prng);
  161. rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K+16, &prng->fortuna.skey); fortuna_update_iv(prng);
  162. if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
  163. return 0;
  164. }
  165. #ifdef CLEAN_STACK
  166. zeromem(tmp, sizeof(tmp));
  167. #endif
  168. return tlen;
  169. }
  170. void fortuna_done(prng_state *prng)
  171. {
  172. _ARGCHK(prng != NULL);
  173. /* call cipher done when we invent one ;-) */
  174. }
  175. int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
  176. {
  177. int x;
  178. _ARGCHK(out != NULL);
  179. _ARGCHK(outlen != NULL);
  180. _ARGCHK(prng != NULL);
  181. /* we'll write 2048 bytes for s&g's */
  182. if (*outlen < 2048) {
  183. return CRYPT_BUFFER_OVERFLOW;
  184. }
  185. for (x = 0; x < 32; x++) {
  186. if (fortuna_read(out+x*64, 64, prng) != 64) {
  187. return CRYPT_ERROR_READPRNG;
  188. }
  189. }
  190. *outlen = 2048;
  191. return CRYPT_OK;
  192. }
  193. int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
  194. {
  195. int err, x;
  196. _ARGCHK(in != NULL);
  197. _ARGCHK(prng != NULL);
  198. if (inlen != 2048) {
  199. return CRYPT_INVALID_ARG;
  200. }
  201. if ((err = fortuna_start(prng)) != CRYPT_OK) {
  202. return err;
  203. }
  204. for (x = 0; x < 32; x++) {
  205. if ((err = fortuna_add_entropy(in+x*64, 64, &prng)) != CRYPT_OK) {
  206. return err;
  207. }
  208. }
  209. return fortuna_ready(&prng);
  210. }
  211. #endif