drbg.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /*
  2. * cifra - embedded cryptography library
  3. * Written in 2016 by Joseph Birr-Pixton <jpixton@gmail.com>
  4. *
  5. * To the extent possible under law, the author(s) have dedicated all
  6. * copyright and related and neighboring rights to this software to the
  7. * public domain worldwide. This software is distributed without any
  8. * warranty.
  9. *
  10. * You should have received a copy of the CC0 Public Domain Dedication
  11. * along with this software. If not, see
  12. * <http://creativecommons.org/publicdomain/zero/1.0/>.
  13. */
  14. #include "drbg.h"
  15. #include "handy.h"
  16. #include "bitops.h"
  17. #include "sha2.h"
  18. #include "tassert.h"
  19. #include <string.h>
  20. #define MAX_DRBG_GENERATE 0x10000ul
  21. static void hash_df(const cf_chash *H,
  22. const void *in1, size_t nin1,
  23. const void *in2, size_t nin2,
  24. const void *in3, size_t nin3,
  25. const void *in4, size_t nin4,
  26. uint8_t *out, size_t nout)
  27. {
  28. uint8_t counter = 1;
  29. uint32_t bits_to_return = nout * 8;
  30. uint8_t cbuf[4];
  31. uint8_t block[CF_MAXHASH];
  32. write32_be(bits_to_return, cbuf);
  33. while (nout)
  34. {
  35. /* Make a block. This is the hash of:
  36. * counter || bits_to_return || in1 || in2 || in3 | in4
  37. */
  38. cf_chash_ctx ctx;
  39. H->init(&ctx);
  40. H->update(&ctx, &counter, sizeof counter);
  41. H->update(&ctx, cbuf, sizeof cbuf);
  42. H->update(&ctx, in1, nin1);
  43. H->update(&ctx, in2, nin2);
  44. H->update(&ctx, in3, nin3);
  45. H->update(&ctx, in4, nin4);
  46. H->digest(&ctx, block);
  47. size_t take = MIN(H->hashsz, nout);
  48. memcpy(out, block, take);
  49. out += take;
  50. nout -= take;
  51. counter += 1;
  52. }
  53. }
  54. void cf_hash_drbg_sha256_init(cf_hash_drbg_sha256 *ctx,
  55. const void *entropy, size_t nentropy,
  56. const void *nonce, size_t nnonce,
  57. const void *persn, size_t npersn)
  58. {
  59. mem_clean(ctx, sizeof *ctx);
  60. /* 1. seed_material = entropy_input || nonce || personalization_string
  61. * 2. seed = Hash_df(seed_material, seedlen)
  62. * 3. V = seed */
  63. hash_df(&cf_sha256,
  64. entropy, nentropy,
  65. nonce, nnonce,
  66. persn, npersn,
  67. NULL, 0,
  68. ctx->V, sizeof ctx->V);
  69. /* 4. C = Hash_df(0x00 || V, seedlen) */
  70. uint8_t zero = 0;
  71. hash_df(&cf_sha256,
  72. &zero, sizeof zero,
  73. ctx->V, sizeof ctx->V,
  74. NULL, 0,
  75. NULL, 0,
  76. ctx->C, sizeof ctx->C);
  77. /* 5. reseed_counter = 1 */
  78. ctx->reseed_counter = 1;
  79. }
  80. /* Add out += in, mod 2^nout.
  81. * Runs in time dependent on nout and nin, but not the contents of out or in.
  82. */
  83. static void add(uint8_t *out, size_t nout, const uint8_t *in, size_t nin)
  84. {
  85. assert(nout >= nin);
  86. uint16_t carry = 0;
  87. int oi, ii;
  88. for (oi = nout - 1, ii = nin - 1;
  89. oi >= 0;
  90. ii--, oi--)
  91. {
  92. carry += out[oi];
  93. if (ii >= 0)
  94. carry += in[ii];
  95. out[oi] = carry & 0xff;
  96. carry >>= 8;
  97. }
  98. }
  99. static void hash_process_addnl(const cf_chash *H,
  100. const void *input, size_t ninput,
  101. uint8_t *V, size_t nV)
  102. {
  103. if (!ninput)
  104. return;
  105. /* 2.1. w = Hash(0x02 || V || additional_input) */
  106. uint8_t two = 2;
  107. uint8_t w[CF_MAXHASH];
  108. cf_chash_ctx ctx;
  109. H->init(&ctx);
  110. H->update(&ctx, &two, sizeof two);
  111. H->update(&ctx, V, nV);
  112. H->update(&ctx, input, ninput);
  113. H->digest(&ctx, w);
  114. /* 2.2. V = (V + w) mod 2 ^ seedlen */
  115. add(V, nV, w, H->hashsz);
  116. }
  117. static void hash_generate(const cf_chash *H,
  118. uint8_t *data, size_t ndata, /* initialised with V */
  119. void *out, size_t nout)
  120. {
  121. cf_chash_ctx ctx;
  122. uint8_t w[CF_MAXHASH];
  123. uint8_t *bout = out;
  124. uint8_t one = 1;
  125. while (nout)
  126. {
  127. /* 4.1. w = Hash(data) */
  128. H->init(&ctx);
  129. H->update(&ctx, data, ndata);
  130. H->digest(&ctx, w);
  131. /* 4.2. W = W || w */
  132. size_t take = MIN(H->hashsz, nout);
  133. memcpy(bout, w, take);
  134. bout += take;
  135. nout -= take;
  136. /* 4.3. data = (data + 1) mod 2 ^ seedlen */
  137. add(data, ndata, &one, sizeof one);
  138. }
  139. }
  140. static void hash_step(const cf_chash *H,
  141. uint8_t *V, size_t nV,
  142. const uint8_t *C, size_t nC,
  143. uint32_t *reseed_counter)
  144. {
  145. /* 4. h = Hash(0x03 || V) */
  146. uint8_t h[CF_MAXHASH];
  147. uint8_t three = 3;
  148. cf_chash_ctx ctx;
  149. H->init(&ctx);
  150. H->update(&ctx, &three, sizeof three);
  151. H->update(&ctx, V, nV);
  152. H->digest(&ctx, h);
  153. /* 5. V = (V + h + C + reseed_counter) mod 2 ^ seedlen */
  154. uint8_t reseed_counter_buf[4];
  155. write32_be(*reseed_counter, reseed_counter_buf);
  156. add(V, nV, h, H->hashsz);
  157. add(V, nV, C, nC);
  158. add(V, nV, reseed_counter_buf, sizeof reseed_counter_buf);
  159. /* 6. reseed_counter = reseed_counter + 1 */
  160. *reseed_counter = *reseed_counter + 1;
  161. }
  162. /* This is Hash_DRBG_Generate_algorithm.
  163. * nout is a maximum of MAX_DRBG_GENERATE */
  164. static void hash_gen_request(cf_hash_drbg_sha256 *ctx,
  165. const void *addnl, size_t naddnl,
  166. void *out, size_t nout)
  167. {
  168. uint8_t data[440/8]; /* a temporary copy of V, which gets incremented by generate */
  169. assert(!cf_hash_drbg_sha256_needs_reseed(ctx));
  170. hash_process_addnl(&cf_sha256, addnl, naddnl, ctx->V, sizeof ctx->V);
  171. assert(sizeof data == sizeof ctx->V);
  172. memcpy(data, ctx->V, sizeof ctx->V);
  173. hash_generate(&cf_sha256, data, sizeof data, out, nout);
  174. hash_step(&cf_sha256, ctx->V, sizeof ctx->V, ctx->C, sizeof ctx->C, &ctx->reseed_counter);
  175. }
  176. void cf_hash_drbg_sha256_gen_additional(cf_hash_drbg_sha256 *ctx,
  177. const void *addnl, size_t naddnl,
  178. void *out, size_t nout)
  179. {
  180. uint8_t *bout = out;
  181. /* Generate output in requests of MAX_DRBG_GENERATE in size. */
  182. while (nout != 0)
  183. {
  184. size_t take = MIN(MAX_DRBG_GENERATE, nout);
  185. hash_gen_request(ctx, addnl, naddnl, bout, take);
  186. bout += take;
  187. nout -= take;
  188. /* Add additional data only once. */
  189. addnl = NULL;
  190. naddnl = 0;
  191. }
  192. }
  193. void cf_hash_drbg_sha256_gen(cf_hash_drbg_sha256 *ctx,
  194. void *out, size_t nout)
  195. {
  196. cf_hash_drbg_sha256_gen_additional(ctx,
  197. NULL, 0,
  198. out, nout);
  199. }
  200. void cf_hash_drbg_sha256_reseed(cf_hash_drbg_sha256 *ctx,
  201. const void *entropy, size_t nentropy,
  202. const void *addnl, size_t naddnl)
  203. {
  204. /* 1. seed_material = 0x01 || V || entropy_input || additional_input
  205. * 2. seed = Hash_df(seed_material, seedlen)
  206. * 3. V = seed */
  207. uint8_t one = 1;
  208. /* stash V in C, because it cannot alias output */
  209. memcpy(ctx->C, ctx->V, sizeof ctx->C);
  210. hash_df(&cf_sha256,
  211. &one, sizeof one,
  212. ctx->C, sizeof ctx->C,
  213. entropy, nentropy,
  214. addnl, naddnl,
  215. ctx->V, sizeof ctx->V);
  216. /* 4. C = Hash_df(0x00 || V, seedlen) */
  217. uint8_t zero = 0;
  218. hash_df(&cf_sha256,
  219. &zero, sizeof zero,
  220. ctx->V, sizeof ctx->V,
  221. NULL, 0,
  222. NULL, 0,
  223. ctx->C, sizeof ctx->C);
  224. /* 5. reseed_counter = 1 */
  225. ctx->reseed_counter = 1;
  226. }
  227. uint32_t cf_hash_drbg_sha256_needs_reseed(const cf_hash_drbg_sha256 *ctx)
  228. {
  229. /* we need reseeding after 2 ^ 32 - 1 requests. */
  230. return ctx->reseed_counter == 0;
  231. }
  232. /* --- HMAC_DRBG --- */
  233. /* provided_data is in1 || in2 || in3.
  234. * K is already scheduled in ctx->hmac. */
  235. static void hmac_drbg_update(cf_hmac_drbg *ctx,
  236. const void *in1, size_t nin1,
  237. const void *in2, size_t nin2,
  238. const void *in3, size_t nin3)
  239. {
  240. cf_hmac_ctx local;
  241. const cf_chash *H = ctx->hmac.hash;
  242. uint8_t new_key[CF_MAXHASH];
  243. uint8_t zero = 0;
  244. /* 1. K = HMAC(K, V || 0x00 || provided_data) */
  245. local = ctx->hmac;
  246. cf_hmac_update(&local, ctx->V, H->hashsz);
  247. cf_hmac_update(&local, &zero, sizeof zero);
  248. cf_hmac_update(&local, in1, nin1);
  249. cf_hmac_update(&local, in2, nin2);
  250. cf_hmac_update(&local, in3, nin3);
  251. cf_hmac_finish(&local, new_key);
  252. cf_hmac_init(&ctx->hmac, H, new_key, H->hashsz);
  253. mem_clean(new_key, sizeof new_key);
  254. /* 2. V = HMAC(K, V) */
  255. local = ctx->hmac;
  256. cf_hmac_update(&local, ctx->V, H->hashsz);
  257. cf_hmac_finish(&local, ctx->V);
  258. /* 3. if (provided_data = null) then return K and V */
  259. if (nin1 == 0 && nin2 == 0 && nin3 == 0)
  260. return;
  261. /* 4. K = HMAC(K, V || 0x01 || provided_data) */
  262. uint8_t one = 1;
  263. local = ctx->hmac;
  264. cf_hmac_update(&local, ctx->V, H->hashsz);
  265. cf_hmac_update(&local, &one, sizeof one);
  266. cf_hmac_update(&local, in1, nin1);
  267. cf_hmac_update(&local, in2, nin2);
  268. cf_hmac_update(&local, in3, nin3);
  269. cf_hmac_finish(&local, new_key);
  270. cf_hmac_init(&ctx->hmac, H, new_key, H->hashsz);
  271. mem_clean(new_key, sizeof new_key);
  272. /* 5. V = HMAC(K, V) */
  273. local = ctx->hmac;
  274. cf_hmac_update(&local, ctx->V, H->hashsz);
  275. cf_hmac_finish(&local, ctx->V);
  276. }
  277. void cf_hmac_drbg_init(cf_hmac_drbg *ctx,
  278. const cf_chash *hash,
  279. const void *entropy, size_t nentropy,
  280. const void *nonce, size_t nnonce,
  281. const void *persn, size_t npersn)
  282. {
  283. mem_clean(ctx, sizeof *ctx);
  284. assert(hash->hashsz <= CF_MAXHASH);
  285. /* 2. Key = 0x00 00 ... 00
  286. * 3. V = 0x01 01 ... 01 */
  287. uint8_t initial_key[CF_MAXHASH];
  288. memset(initial_key, 0x00, hash->hashsz);
  289. memset(ctx->V, 0x01, hash->hashsz);
  290. cf_hmac_init(&ctx->hmac, hash, initial_key, hash->hashsz);
  291. /* 1. seed_material = entropy_input || nonce || personalization_string
  292. * 4. (Key, V) = HMAC_DRBG_Update(seed_material, Key, V) */
  293. hmac_drbg_update(ctx, entropy, nentropy, nonce, nnonce, persn, npersn);
  294. /* 5. reseed_counter = 1 */
  295. ctx->reseed_counter = 1;
  296. }
  297. uint32_t cf_hmac_drbg_needs_reseed(const cf_hmac_drbg *ctx)
  298. {
  299. return ctx->reseed_counter == 0;
  300. }
  301. static void hmac_drbg_generate(cf_hmac_drbg *ctx,
  302. const void *addnl, size_t naddnl,
  303. void *out, size_t nout)
  304. {
  305. /* 1. If reseed_counter > reseed_interval, then return an indication
  306. * that a reseed is required */
  307. assert(!cf_hmac_drbg_needs_reseed(ctx));
  308. /* 2. If additional_input != null, then
  309. * (Key, V) = HMAC_DRBG_Update(additional_input, Key, V)
  310. */
  311. if (naddnl)
  312. hmac_drbg_update(ctx, addnl, naddnl, NULL, 0, NULL, 0);
  313. /* 3. temp = Null
  314. * 4. While (len(temp) < requested_number_of_bits) do:
  315. * 4.1. V = HMAC(Key, V)
  316. * 4.2. temp = temp || V
  317. * 5. returned_bits = leftmost(temp, requested_number_of_bits)
  318. *
  319. * We write the contents of temp directly into the caller's
  320. * out buffer.
  321. */
  322. uint8_t *bout = out;
  323. cf_hmac_ctx local;
  324. while (nout)
  325. {
  326. local = ctx->hmac;
  327. cf_hmac_update(&local, ctx->V, ctx->hmac.hash->hashsz);
  328. cf_hmac_finish(&local, ctx->V);
  329. size_t take = MIN(ctx->hmac.hash->hashsz, nout);
  330. memcpy(bout, ctx->V, take);
  331. bout += take;
  332. nout -= take;
  333. }
  334. /* 6. (Key, V) = HMAC_DRBG_Update(additional_input, Key, V) */
  335. hmac_drbg_update(ctx, addnl, naddnl, NULL, 0, NULL, 0);
  336. /* 7. reseed_counter = reseed_counter + 1 */
  337. ctx->reseed_counter++;
  338. }
  339. void cf_hmac_drbg_gen_additional(cf_hmac_drbg *ctx,
  340. const void *addnl, size_t naddnl,
  341. void *out, size_t nout)
  342. {
  343. uint8_t *bout = out;
  344. while (nout != 0)
  345. {
  346. size_t take = MIN(MAX_DRBG_GENERATE, nout);
  347. hmac_drbg_generate(ctx, addnl, naddnl, bout, take);
  348. bout += take;
  349. nout -= take;
  350. /* Add additional data only once. */
  351. addnl = NULL;
  352. naddnl = 0;
  353. }
  354. }
  355. void cf_hmac_drbg_gen(cf_hmac_drbg *ctx, void *out, size_t nout)
  356. {
  357. cf_hmac_drbg_gen_additional(ctx,
  358. NULL, 0,
  359. out, nout);
  360. }
  361. void cf_hmac_drbg_reseed(cf_hmac_drbg *ctx,
  362. const void *entropy, size_t nentropy,
  363. const void *addnl, size_t naddnl)
  364. {
  365. /* 1. seed_material = entropy_input || additional_input
  366. * 2. (Key, V) = HMAC_DRBG_Update(seed_material, Key, V) */
  367. hmac_drbg_update(ctx, entropy, nentropy, addnl, naddnl, NULL, 0);
  368. /* 3. reseed_counter = 1 */
  369. ctx->reseed_counter = 1;
  370. }