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.

xmss_core_fast.c 33 KiB

8 jaren geleden
8 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdint.h>
  4. #include "hash.h"
  5. #include "hash_address.h"
  6. #include "params.h"
  7. #include "randombytes.h"
  8. #include "wots.h"
  9. #include "utils.h"
  10. #include "xmss_commons.h"
  11. #include "xmss_core.h"
  12. typedef struct{
  13. unsigned char h;
  14. unsigned long next_idx;
  15. unsigned char stackusage;
  16. unsigned char completed;
  17. unsigned char *node;
  18. } treehash_inst;
  19. typedef struct {
  20. unsigned char *stack;
  21. unsigned int stackoffset;
  22. unsigned char *stacklevels;
  23. unsigned char *auth;
  24. unsigned char *keep;
  25. treehash_inst *treehash;
  26. unsigned char *retain;
  27. unsigned int next_leaf;
  28. } bds_state;
  29. /* These serialization functions provide a transition between the current
  30. way of storing the state in an exposed struct, and storing it as part of the
  31. byte array that is the secret key.
  32. They will probably be refactored in a non-backwards-compatible way, soon. */
  33. static void xmssmt_serialize_state(const xmss_params *params,
  34. unsigned char *sk, bds_state *states)
  35. {
  36. unsigned int i, j;
  37. /* Skip past the 'regular' sk */
  38. sk += params->index_bytes + 4*params->n;
  39. for (i = 0; i < 2*params->d - 1; i++) {
  40. sk += (params->tree_height + 1) * params->n; /* stack */
  41. ull_to_bytes(sk, 4, states[i].stackoffset);
  42. sk += 4;
  43. sk += params->tree_height + 1; /* stacklevels */
  44. sk += params->tree_height * params->n; /* auth */
  45. sk += (params->tree_height >> 1) * params->n; /* keep */
  46. for (j = 0; j < params->tree_height - params->bds_k; j++) {
  47. ull_to_bytes(sk, 1, states[i].treehash[j].h);
  48. sk += 1;
  49. ull_to_bytes(sk, 4, states[i].treehash[j].next_idx);
  50. sk += 4;
  51. ull_to_bytes(sk, 1, states[i].treehash[j].stackusage);
  52. sk += 1;
  53. ull_to_bytes(sk, 1, states[i].treehash[j].completed);
  54. sk += 1;
  55. sk += params->n; /* node */
  56. }
  57. /* retain */
  58. sk += ((1 << params->bds_k) - params->bds_k - 1) * params->n;
  59. ull_to_bytes(sk, 4, states[i].next_leaf);
  60. sk += 4;
  61. }
  62. }
  63. static void xmssmt_deserialize_state(const xmss_params *params,
  64. bds_state *states,
  65. unsigned char **wots_sigs,
  66. unsigned char *sk)
  67. {
  68. unsigned int i, j;
  69. /* Skip past the 'regular' sk */
  70. sk += params->index_bytes + 4*params->n;
  71. // TODO These data sizes follow from the (former) test xmss_core_fast.c
  72. // TODO They should be reconsidered / motivated more explicitly
  73. for (i = 0; i < 2*params->d - 1; i++) {
  74. states[i].stack = sk;
  75. sk += (params->tree_height + 1) * params->n;
  76. states[i].stackoffset = bytes_to_ull(sk, 4);
  77. sk += 4;
  78. states[i].stacklevels = sk;
  79. sk += params->tree_height + 1;
  80. states[i].auth = sk;
  81. sk += params->tree_height * params->n;
  82. states[i].keep = sk;
  83. sk += (params->tree_height >> 1) * params->n;
  84. for (j = 0; j < params->tree_height - params->bds_k; j++) {
  85. states[i].treehash[j].h = bytes_to_ull(sk, 1);
  86. sk += 1;
  87. states[i].treehash[j].next_idx = bytes_to_ull(sk, 4);
  88. sk += 4;
  89. states[i].treehash[j].stackusage = bytes_to_ull(sk, 1);
  90. sk += 1;
  91. states[i].treehash[j].completed = bytes_to_ull(sk, 1);
  92. sk += 1;
  93. states[i].treehash[j].node = sk;
  94. sk += params->n;
  95. }
  96. states[i].retain = sk;
  97. sk += ((1 << params->bds_k) - params->bds_k - 1) * params->n;
  98. states[i].next_leaf = bytes_to_ull(sk, 4);
  99. sk += 4;
  100. }
  101. if (params->d > 1) {
  102. *wots_sigs = sk;
  103. }
  104. }
  105. static void xmss_serialize_state(const xmss_params *params,
  106. unsigned char *sk, bds_state *state)
  107. {
  108. xmssmt_serialize_state(params, sk, state);
  109. }
  110. static void xmss_deserialize_state(const xmss_params *params,
  111. bds_state *state, unsigned char *sk)
  112. {
  113. xmssmt_deserialize_state(params, state, NULL, sk);
  114. }
  115. static void memswap(void *a, void *b, void *t, unsigned long long len)
  116. {
  117. memcpy(t, a, len);
  118. memcpy(a, b, len);
  119. memcpy(b, t, len);
  120. }
  121. /**
  122. * Swaps the content of two bds_state objects, swapping actual memory rather
  123. * than pointers.
  124. * As we're mapping memory chunks in the secret key to bds state objects,
  125. * it is now necessary to make swaps 'real swaps'. This could be done in the
  126. * serialization function as well, but that causes more overhead
  127. */
  128. // TODO this should not be necessary if we keep better track of the states
  129. static void deep_state_swap(const xmss_params *params,
  130. bds_state *a, bds_state *b)
  131. {
  132. // TODO this is extremely ugly and should be refactored
  133. // TODO right now, this ensures that both 'stack' and 'retain' fit
  134. unsigned char t[
  135. ((params->tree_height + 1) > ((1 << params->bds_k) - params->bds_k - 1)
  136. ? (params->tree_height + 1)
  137. : ((1 << params->bds_k) - params->bds_k - 1))
  138. * params->n];
  139. unsigned int i;
  140. memswap(a->stack, b->stack, t, (params->tree_height + 1) * params->n);
  141. memswap(&a->stackoffset, &b->stackoffset, t, sizeof(a->stackoffset));
  142. memswap(a->stacklevels, b->stacklevels, t, params->tree_height + 1);
  143. memswap(a->auth, b->auth, t, params->tree_height * params->n);
  144. memswap(a->keep, b->keep, t, (params->tree_height >> 1) * params->n);
  145. for (i = 0; i < params->tree_height - params->bds_k; i++) {
  146. memswap(&a->treehash[i].h, &b->treehash[i].h, t, sizeof(a->treehash[i].h));
  147. memswap(&a->treehash[i].next_idx, &b->treehash[i].next_idx, t, sizeof(a->treehash[i].next_idx));
  148. memswap(&a->treehash[i].stackusage, &b->treehash[i].stackusage, t, sizeof(a->treehash[i].stackusage));
  149. memswap(&a->treehash[i].completed, &b->treehash[i].completed, t, sizeof(a->treehash[i].completed));
  150. memswap(a->treehash[i].node, b->treehash[i].node, t, params->n);
  151. }
  152. memswap(a->retain, b->retain, t, ((1 << params->bds_k) - params->bds_k - 1) * params->n);
  153. memswap(&a->next_leaf, &b->next_leaf, t, sizeof(a->next_leaf));
  154. }
  155. static int treehash_minheight_on_stack(const xmss_params *params,
  156. bds_state* state,
  157. const treehash_inst *treehash)
  158. {
  159. unsigned int r = params->tree_height, i;
  160. for (i = 0; i < treehash->stackusage; i++) {
  161. if (state->stacklevels[state->stackoffset - i - 1] < r) {
  162. r = state->stacklevels[state->stackoffset - i - 1];
  163. }
  164. }
  165. return r;
  166. }
  167. /**
  168. * Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash.
  169. * Currently only used for key generation.
  170. *
  171. */
  172. static void treehash_init(const xmss_params *params,
  173. unsigned char *node, int height, int index,
  174. bds_state *state, const unsigned char *sk_seed,
  175. const unsigned char *pub_seed, const uint32_t addr[8])
  176. {
  177. unsigned int idx = index;
  178. // use three different addresses because at this point we use all three formats in parallel
  179. uint32_t ots_addr[8];
  180. uint32_t ltree_addr[8];
  181. uint32_t node_addr[8];
  182. // only copy layer and tree address parts
  183. memcpy(ots_addr, addr, 12);
  184. // type = ots
  185. set_type(ots_addr, 0);
  186. memcpy(ltree_addr, addr, 12);
  187. set_type(ltree_addr, 1);
  188. memcpy(node_addr, addr, 12);
  189. set_type(node_addr, 2);
  190. uint32_t lastnode, i;
  191. unsigned char stack[(height+1)*params->n];
  192. unsigned int stacklevels[height+1];
  193. unsigned int stackoffset=0;
  194. unsigned int nodeh;
  195. lastnode = idx+(1<<height);
  196. for (i = 0; i < params->tree_height-params->bds_k; i++) {
  197. state->treehash[i].h = i;
  198. state->treehash[i].completed = 1;
  199. state->treehash[i].stackusage = 0;
  200. }
  201. i = 0;
  202. for (; idx < lastnode; idx++) {
  203. set_ltree_addr(ltree_addr, idx);
  204. set_ots_addr(ots_addr, idx);
  205. gen_leaf_wots(params, stack+stackoffset*params->n, sk_seed, pub_seed, ltree_addr, ots_addr);
  206. stacklevels[stackoffset] = 0;
  207. stackoffset++;
  208. if (params->tree_height - params->bds_k > 0 && i == 3) {
  209. memcpy(state->treehash[0].node, stack+stackoffset*params->n, params->n);
  210. }
  211. while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) {
  212. nodeh = stacklevels[stackoffset-1];
  213. if (i >> nodeh == 1) {
  214. memcpy(state->auth + nodeh*params->n, stack+(stackoffset-1)*params->n, params->n);
  215. }
  216. else {
  217. if (nodeh < params->tree_height - params->bds_k && i >> nodeh == 3) {
  218. memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*params->n, params->n);
  219. }
  220. else if (nodeh >= params->tree_height - params->bds_k) {
  221. memcpy(state->retain + ((1 << (params->tree_height - 1 - nodeh)) + nodeh - params->tree_height + (((i >> nodeh) - 3) >> 1)) * params->n, stack+(stackoffset-1)*params->n, params->n);
  222. }
  223. }
  224. set_tree_height(node_addr, stacklevels[stackoffset-1]);
  225. set_tree_index(node_addr, (idx >> (stacklevels[stackoffset-1]+1)));
  226. hash_h(params, stack+(stackoffset-2)*params->n, stack+(stackoffset-2)*params->n, pub_seed, node_addr);
  227. stacklevels[stackoffset-2]++;
  228. stackoffset--;
  229. }
  230. i++;
  231. }
  232. for (i = 0; i < params->n; i++) {
  233. node[i] = stack[i];
  234. }
  235. }
  236. static void treehash_update(const xmss_params *params,
  237. treehash_inst *treehash, bds_state *state,
  238. const unsigned char *sk_seed,
  239. const unsigned char *pub_seed,
  240. const uint32_t addr[8])
  241. {
  242. uint32_t ots_addr[8];
  243. uint32_t ltree_addr[8];
  244. uint32_t node_addr[8];
  245. // only copy layer and tree address parts
  246. memcpy(ots_addr, addr, 12);
  247. // type = ots
  248. set_type(ots_addr, 0);
  249. memcpy(ltree_addr, addr, 12);
  250. set_type(ltree_addr, 1);
  251. memcpy(node_addr, addr, 12);
  252. set_type(node_addr, 2);
  253. set_ltree_addr(ltree_addr, treehash->next_idx);
  254. set_ots_addr(ots_addr, treehash->next_idx);
  255. unsigned char nodebuffer[2 * params->n];
  256. unsigned int nodeheight = 0;
  257. gen_leaf_wots(params, nodebuffer, sk_seed, pub_seed, ltree_addr, ots_addr);
  258. while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) {
  259. memcpy(nodebuffer + params->n, nodebuffer, params->n);
  260. memcpy(nodebuffer, state->stack + (state->stackoffset-1)*params->n, params->n);
  261. set_tree_height(node_addr, nodeheight);
  262. set_tree_index(node_addr, (treehash->next_idx >> (nodeheight+1)));
  263. hash_h(params, nodebuffer, nodebuffer, pub_seed, node_addr);
  264. nodeheight++;
  265. treehash->stackusage--;
  266. state->stackoffset--;
  267. }
  268. if (nodeheight == treehash->h) { // this also implies stackusage == 0
  269. memcpy(treehash->node, nodebuffer, params->n);
  270. treehash->completed = 1;
  271. }
  272. else {
  273. memcpy(state->stack + state->stackoffset*params->n, nodebuffer, params->n);
  274. treehash->stackusage++;
  275. state->stacklevels[state->stackoffset] = nodeheight;
  276. state->stackoffset++;
  277. treehash->next_idx++;
  278. }
  279. }
  280. /**
  281. * Performs treehash updates on the instance that needs it the most.
  282. * Returns the updated number of available updates.
  283. **/
  284. static char bds_treehash_update(const xmss_params *params,
  285. bds_state *state, unsigned int updates,
  286. const unsigned char *sk_seed,
  287. unsigned char *pub_seed,
  288. const uint32_t addr[8])
  289. {
  290. uint32_t i, j;
  291. unsigned int level, l_min, low;
  292. unsigned int used = 0;
  293. for (j = 0; j < updates; j++) {
  294. l_min = params->tree_height;
  295. level = params->tree_height - params->bds_k;
  296. for (i = 0; i < params->tree_height - params->bds_k; i++) {
  297. if (state->treehash[i].completed) {
  298. low = params->tree_height;
  299. }
  300. else if (state->treehash[i].stackusage == 0) {
  301. low = i;
  302. }
  303. else {
  304. low = treehash_minheight_on_stack(params, state, &(state->treehash[i]));
  305. }
  306. if (low < l_min) {
  307. level = i;
  308. l_min = low;
  309. }
  310. }
  311. if (level == params->tree_height - params->bds_k) {
  312. break;
  313. }
  314. treehash_update(params, &(state->treehash[level]), state, sk_seed, pub_seed, addr);
  315. used++;
  316. }
  317. return updates - used;
  318. }
  319. /**
  320. * Updates the state (typically NEXT_i) by adding a leaf and updating the stack
  321. * Returns -1 if all leaf nodes have already been processed
  322. **/
  323. static char bds_state_update(const xmss_params *params,
  324. bds_state *state, const unsigned char *sk_seed,
  325. const unsigned char *pub_seed,
  326. const uint32_t addr[8])
  327. {
  328. uint32_t ltree_addr[8];
  329. uint32_t node_addr[8];
  330. uint32_t ots_addr[8];
  331. unsigned int nodeh;
  332. int idx = state->next_leaf;
  333. if (idx == 1 << params->tree_height) {
  334. return -1;
  335. }
  336. // only copy layer and tree address parts
  337. memcpy(ots_addr, addr, 12);
  338. // type = ots
  339. set_type(ots_addr, 0);
  340. memcpy(ltree_addr, addr, 12);
  341. set_type(ltree_addr, 1);
  342. memcpy(node_addr, addr, 12);
  343. set_type(node_addr, 2);
  344. set_ots_addr(ots_addr, idx);
  345. set_ltree_addr(ltree_addr, idx);
  346. gen_leaf_wots(params, state->stack+state->stackoffset*params->n, sk_seed, pub_seed, ltree_addr, ots_addr);
  347. state->stacklevels[state->stackoffset] = 0;
  348. state->stackoffset++;
  349. if (params->tree_height - params->bds_k > 0 && idx == 3) {
  350. memcpy(state->treehash[0].node, state->stack+state->stackoffset*params->n, params->n);
  351. }
  352. while (state->stackoffset>1 && state->stacklevels[state->stackoffset-1] == state->stacklevels[state->stackoffset-2]) {
  353. nodeh = state->stacklevels[state->stackoffset-1];
  354. if (idx >> nodeh == 1) {
  355. memcpy(state->auth + nodeh*params->n, state->stack+(state->stackoffset-1)*params->n, params->n);
  356. }
  357. else {
  358. if (nodeh < params->tree_height - params->bds_k && idx >> nodeh == 3) {
  359. memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*params->n, params->n);
  360. }
  361. else if (nodeh >= params->tree_height - params->bds_k) {
  362. memcpy(state->retain + ((1 << (params->tree_height - 1 - nodeh)) + nodeh - params->tree_height + (((idx >> nodeh) - 3) >> 1)) * params->n, state->stack+(state->stackoffset-1)*params->n, params->n);
  363. }
  364. }
  365. set_tree_height(node_addr, state->stacklevels[state->stackoffset-1]);
  366. set_tree_index(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1)));
  367. hash_h(params, state->stack+(state->stackoffset-2)*params->n, state->stack+(state->stackoffset-2)*params->n, pub_seed, node_addr);
  368. state->stacklevels[state->stackoffset-2]++;
  369. state->stackoffset--;
  370. }
  371. state->next_leaf++;
  372. return 0;
  373. }
  374. /**
  375. * Returns the auth path for node leaf_idx and computes the auth path for the
  376. * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo
  377. * in "Post Quantum Cryptography", Springer 2009.
  378. */
  379. static void bds_round(const xmss_params *params,
  380. bds_state *state, const unsigned long leaf_idx,
  381. const unsigned char *sk_seed,
  382. const unsigned char *pub_seed, uint32_t addr[8])
  383. {
  384. unsigned int i;
  385. unsigned int tau = params->tree_height;
  386. unsigned int startidx;
  387. unsigned int offset, rowidx;
  388. unsigned char buf[2 * params->n];
  389. uint32_t ots_addr[8];
  390. uint32_t ltree_addr[8];
  391. uint32_t node_addr[8];
  392. // only copy layer and tree address parts
  393. memcpy(ots_addr, addr, 12);
  394. // type = ots
  395. set_type(ots_addr, 0);
  396. memcpy(ltree_addr, addr, 12);
  397. set_type(ltree_addr, 1);
  398. memcpy(node_addr, addr, 12);
  399. set_type(node_addr, 2);
  400. for (i = 0; i < params->tree_height; i++) {
  401. if (! ((leaf_idx >> i) & 1)) {
  402. tau = i;
  403. break;
  404. }
  405. }
  406. if (tau > 0) {
  407. memcpy(buf, state->auth + (tau-1) * params->n, params->n);
  408. // we need to do this before refreshing state->keep to prevent overwriting
  409. memcpy(buf + params->n, state->keep + ((tau-1) >> 1) * params->n, params->n);
  410. }
  411. if (!((leaf_idx >> (tau + 1)) & 1) && (tau < params->tree_height - 1)) {
  412. memcpy(state->keep + (tau >> 1)*params->n, state->auth + tau*params->n, params->n);
  413. }
  414. if (tau == 0) {
  415. set_ltree_addr(ltree_addr, leaf_idx);
  416. set_ots_addr(ots_addr, leaf_idx);
  417. gen_leaf_wots(params, state->auth, sk_seed, pub_seed, ltree_addr, ots_addr);
  418. }
  419. else {
  420. set_tree_height(node_addr, (tau-1));
  421. set_tree_index(node_addr, leaf_idx >> tau);
  422. hash_h(params, state->auth + tau * params->n, buf, pub_seed, node_addr);
  423. for (i = 0; i < tau; i++) {
  424. if (i < params->tree_height - params->bds_k) {
  425. memcpy(state->auth + i * params->n, state->treehash[i].node, params->n);
  426. }
  427. else {
  428. offset = (1 << (params->tree_height - 1 - i)) + i - params->tree_height;
  429. rowidx = ((leaf_idx >> i) - 1) >> 1;
  430. memcpy(state->auth + i * params->n, state->retain + (offset + rowidx) * params->n, params->n);
  431. }
  432. }
  433. for (i = 0; i < ((tau < params->tree_height - params->bds_k) ? tau : (params->tree_height - params->bds_k)); i++) {
  434. startidx = leaf_idx + 1 + 3 * (1 << i);
  435. if (startidx < 1U << params->tree_height) {
  436. state->treehash[i].h = i;
  437. state->treehash[i].next_idx = startidx;
  438. state->treehash[i].completed = 0;
  439. state->treehash[i].stackusage = 0;
  440. }
  441. }
  442. }
  443. }
  444. /**
  445. * Given a set of parameters, this function returns the size of the secret key.
  446. * This is implementation specific, as varying choices in tree traversal will
  447. * result in varying requirements for state storage.
  448. */
  449. unsigned long long xmss_core_sk_bytes(const xmss_params *params)
  450. {
  451. return xmssmt_core_sk_bytes(params);
  452. }
  453. /*
  454. * Generates a XMSS key pair for a given parameter set.
  455. * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
  456. * Format pk: [root || PUB_SEED] omitting algo oid.
  457. */
  458. int xmss_core_keypair(const xmss_params *params,
  459. unsigned char *pk, unsigned char *sk)
  460. {
  461. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  462. // TODO refactor BDS state not to need separate treehash instances
  463. bds_state state;
  464. treehash_inst treehash[params->tree_height - params->bds_k];
  465. state.treehash = treehash;
  466. xmss_deserialize_state(params, &state, sk);
  467. state.stackoffset = 0;
  468. state.next_leaf = 0;
  469. // Set idx = 0
  470. sk[0] = 0;
  471. sk[1] = 0;
  472. sk[2] = 0;
  473. sk[3] = 0;
  474. // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte)
  475. randombytes(sk + params->index_bytes, 3*params->n);
  476. // Copy PUB_SEED to public key
  477. memcpy(pk + params->n, sk + params->index_bytes + 2*params->n, params->n);
  478. // Compute root
  479. treehash_init(params, pk, params->tree_height, 0, &state, sk + params->index_bytes, sk + params->index_bytes + 2*params->n, addr);
  480. // copy root o sk
  481. memcpy(sk + params->index_bytes + 3*params->n, pk, params->n);
  482. /* Write the BDS state into sk. */
  483. xmss_serialize_state(params, sk, &state);
  484. return 0;
  485. }
  486. /**
  487. * Signs a message.
  488. * Returns
  489. * 1. an array containing the signature followed by the message AND
  490. * 2. an updated secret key!
  491. *
  492. */
  493. int xmss_core_sign(const xmss_params *params,
  494. unsigned char *sk,
  495. unsigned char *sm, unsigned long long *smlen,
  496. const unsigned char *m, unsigned long long mlen)
  497. {
  498. const unsigned char *pub_root = sk + params->index_bytes + 3*params->n;
  499. uint16_t i = 0;
  500. // TODO refactor BDS state not to need separate treehash instances
  501. bds_state state;
  502. treehash_inst treehash[params->tree_height - params->bds_k];
  503. state.treehash = treehash;
  504. /* Load the BDS state from sk. */
  505. xmss_deserialize_state(params, &state, sk);
  506. // Extract SK
  507. unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3];
  508. unsigned char sk_seed[params->n];
  509. memcpy(sk_seed, sk + params->index_bytes, params->n);
  510. unsigned char sk_prf[params->n];
  511. memcpy(sk_prf, sk + params->index_bytes + params->n, params->n);
  512. unsigned char pub_seed[params->n];
  513. memcpy(pub_seed, sk + params->index_bytes + 2*params->n, params->n);
  514. // index as 32 bytes string
  515. unsigned char idx_bytes_32[32];
  516. ull_to_bytes(idx_bytes_32, 32, idx);
  517. // Update SK
  518. sk[0] = ((idx + 1) >> 24) & 255;
  519. sk[1] = ((idx + 1) >> 16) & 255;
  520. sk[2] = ((idx + 1) >> 8) & 255;
  521. sk[3] = (idx + 1) & 255;
  522. // Secret key for this non-forward-secure version is now updated.
  523. // A production implementation should consider using a file handle instead,
  524. // and write the updated secret key at this point!
  525. // Init working params
  526. unsigned char R[params->n];
  527. unsigned char msg_h[params->n];
  528. unsigned char ots_seed[params->n];
  529. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  530. // ---------------------------------
  531. // Message Hashing
  532. // ---------------------------------
  533. // Message Hash:
  534. // First compute pseudorandom value
  535. prf(params, R, idx_bytes_32, sk_prf);
  536. /* Already put the message in the right place, to make it easier to prepend
  537. * things when computing the hash over the message. */
  538. memcpy(sm + params->sig_bytes, m, mlen);
  539. /* Compute the message hash. */
  540. hash_message(params, msg_h, R, pub_root, idx,
  541. sm + params->sig_bytes - 4*params->n, mlen);
  542. // Start collecting signature
  543. *smlen = 0;
  544. // Copy index to signature
  545. sm[0] = (idx >> 24) & 255;
  546. sm[1] = (idx >> 16) & 255;
  547. sm[2] = (idx >> 8) & 255;
  548. sm[3] = idx & 255;
  549. sm += 4;
  550. *smlen += 4;
  551. // Copy R to signature
  552. for (i = 0; i < params->n; i++) {
  553. sm[i] = R[i];
  554. }
  555. sm += params->n;
  556. *smlen += params->n;
  557. // ----------------------------------
  558. // Now we start to "really sign"
  559. // ----------------------------------
  560. // Prepare Address
  561. set_type(ots_addr, 0);
  562. set_ots_addr(ots_addr, idx);
  563. // Compute seed for OTS key pair
  564. get_seed(params, ots_seed, sk_seed, ots_addr);
  565. // Compute WOTS signature
  566. wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr);
  567. sm += params->wots_sig_bytes;
  568. *smlen += params->wots_sig_bytes;
  569. // the auth path was already computed during the previous round
  570. memcpy(sm, state.auth, params->tree_height*params->n);
  571. if (idx < (1U << params->tree_height) - 1) {
  572. bds_round(params, &state, idx, sk_seed, pub_seed, ots_addr);
  573. bds_treehash_update(params, &state, (params->tree_height - params->bds_k) >> 1, sk_seed, pub_seed, ots_addr);
  574. }
  575. sm += params->tree_height*params->n;
  576. *smlen += params->tree_height*params->n;
  577. memcpy(sm, m, mlen);
  578. *smlen += mlen;
  579. /* Write the updated BDS state back into sk. */
  580. xmss_serialize_state(params, sk, &state);
  581. return 0;
  582. }
  583. /**
  584. * Given a set of parameters, this function returns the size of the secret key.
  585. * This is implementation specific, as varying choices in tree traversal will
  586. * result in varying requirements for state storage.
  587. */
  588. unsigned long long xmssmt_core_sk_bytes(const xmss_params *params)
  589. {
  590. return params->index_bytes + 4 * params->n
  591. + (2 * params->d - 1) * (
  592. (params->tree_height + 1) * params->n
  593. + 4
  594. + params->tree_height + 1
  595. + params->tree_height * params->n
  596. + (params->tree_height >> 1) * params->n
  597. + (params->tree_height - params->bds_k) * (7 + params->n)
  598. + ((1 << params->bds_k) - params->bds_k - 1) * params->n
  599. + 4
  600. )
  601. + (params->d - 1) * params->wots_sig_bytes;
  602. }
  603. /*
  604. * Generates a XMSSMT key pair for a given parameter set.
  605. * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
  606. * Format pk: [root || PUB_SEED] omitting algo oid.
  607. */
  608. int xmssmt_core_keypair(const xmss_params *params,
  609. unsigned char *pk, unsigned char *sk)
  610. {
  611. unsigned char ots_seed[params->n];
  612. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  613. unsigned int i;
  614. unsigned char *wots_sigs;
  615. // TODO refactor BDS state not to need separate treehash instances
  616. bds_state states[2*params->d - 1];
  617. treehash_inst treehash[(2*params->d - 1) * (params->tree_height - params->bds_k)];
  618. for (i = 0; i < 2*params->d - 1; i++) {
  619. states[i].treehash = treehash + i * (params->tree_height - params->bds_k);
  620. }
  621. xmssmt_deserialize_state(params, states, &wots_sigs, sk);
  622. for (i = 0; i < 2 * params->d - 1; i++) {
  623. states[i].stackoffset = 0;
  624. states[i].next_leaf = 0;
  625. }
  626. // Set idx = 0
  627. for (i = 0; i < params->index_bytes; i++) {
  628. sk[i] = 0;
  629. }
  630. // Init SK_SEED (params->n byte), SK_PRF (params->n byte), and PUB_SEED (params->n byte)
  631. randombytes(sk+params->index_bytes, 3*params->n);
  632. // Copy PUB_SEED to public key
  633. memcpy(pk+params->n, sk+params->index_bytes+2*params->n, params->n);
  634. // Start with the bottom-most layer
  635. set_layer_addr(addr, 0);
  636. // Set up state and compute wots signatures for all but topmost tree root
  637. for (i = 0; i < params->d - 1; i++) {
  638. // Compute seed for OTS key pair
  639. treehash_init(params, pk, params->tree_height, 0, states + i, sk+params->index_bytes, pk+params->n, addr);
  640. set_layer_addr(addr, (i+1));
  641. get_seed(params, ots_seed, sk + params->index_bytes, addr);
  642. wots_sign(params, wots_sigs + i*params->wots_sig_bytes, pk, ots_seed, pk+params->n, addr);
  643. }
  644. // Address now points to the single tree on layer d-1
  645. treehash_init(params, pk, params->tree_height, 0, states + i, sk+params->index_bytes, pk+params->n, addr);
  646. memcpy(sk + params->index_bytes + 3*params->n, pk, params->n);
  647. xmssmt_serialize_state(params, sk, states);
  648. return 0;
  649. }
  650. /**
  651. * Signs a message.
  652. * Returns
  653. * 1. an array containing the signature followed by the message AND
  654. * 2. an updated secret key!
  655. *
  656. */
  657. int xmssmt_core_sign(const xmss_params *params,
  658. unsigned char *sk,
  659. unsigned char *sm, unsigned long long *smlen,
  660. const unsigned char *m, unsigned long long mlen)
  661. {
  662. const unsigned char *pub_root = sk + params->index_bytes + 3*params->n;
  663. uint64_t idx_tree;
  664. uint32_t idx_leaf;
  665. uint64_t i, j;
  666. int needswap_upto = -1;
  667. unsigned int updates;
  668. unsigned char sk_seed[params->n];
  669. unsigned char sk_prf[params->n];
  670. unsigned char pub_seed[params->n];
  671. // Init working params
  672. unsigned char R[params->n];
  673. unsigned char msg_h[params->n];
  674. unsigned char ots_seed[params->n];
  675. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  676. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  677. unsigned char idx_bytes_32[32];
  678. unsigned char *wots_sigs;
  679. // TODO refactor BDS state not to need separate treehash instances
  680. bds_state states[2*params->d - 1];
  681. treehash_inst treehash[(2*params->d - 1) * (params->tree_height - params->bds_k)];
  682. for (i = 0; i < 2*params->d - 1; i++) {
  683. states[i].treehash = treehash + i * (params->tree_height - params->bds_k);
  684. }
  685. xmssmt_deserialize_state(params, states, &wots_sigs, sk);
  686. // Extract SK
  687. unsigned long long idx = 0;
  688. for (i = 0; i < params->index_bytes; i++) {
  689. idx |= ((unsigned long long)sk[i]) << 8*(params->index_bytes - 1 - i);
  690. }
  691. memcpy(sk_seed, sk+params->index_bytes, params->n);
  692. memcpy(sk_prf, sk+params->index_bytes+params->n, params->n);
  693. memcpy(pub_seed, sk+params->index_bytes+2*params->n, params->n);
  694. // Update SK
  695. for (i = 0; i < params->index_bytes; i++) {
  696. sk[i] = ((idx + 1) >> 8*(params->index_bytes - 1 - i)) & 255;
  697. }
  698. // Secret key for this non-forward-secure version is now updated.
  699. // A production implementation should consider using a file handle instead,
  700. // and write the updated secret key at this point!
  701. // ---------------------------------
  702. // Message Hashing
  703. // ---------------------------------
  704. // Message Hash:
  705. // First compute pseudorandom value
  706. ull_to_bytes(idx_bytes_32, 32, idx);
  707. prf(params, R, idx_bytes_32, sk_prf);
  708. /* Already put the message in the right place, to make it easier to prepend
  709. * things when computing the hash over the message. */
  710. memcpy(sm + params->sig_bytes, m, mlen);
  711. /* Compute the message hash. */
  712. hash_message(params, msg_h, R, pub_root, idx,
  713. sm + params->sig_bytes - 4*params->n, mlen);
  714. // Start collecting signature
  715. *smlen = 0;
  716. // Copy index to signature
  717. for (i = 0; i < params->index_bytes; i++) {
  718. sm[i] = (idx >> 8*(params->index_bytes - 1 - i)) & 255;
  719. }
  720. sm += params->index_bytes;
  721. *smlen += params->index_bytes;
  722. // Copy R to signature
  723. for (i = 0; i < params->n; i++) {
  724. sm[i] = R[i];
  725. }
  726. sm += params->n;
  727. *smlen += params->n;
  728. // ----------------------------------
  729. // Now we start to "really sign"
  730. // ----------------------------------
  731. // Handle lowest layer separately as it is slightly different...
  732. // Prepare Address
  733. set_type(ots_addr, 0);
  734. idx_tree = idx >> params->tree_height;
  735. idx_leaf = (idx & ((1 << params->tree_height)-1));
  736. set_layer_addr(ots_addr, 0);
  737. set_tree_addr(ots_addr, idx_tree);
  738. set_ots_addr(ots_addr, idx_leaf);
  739. // Compute seed for OTS key pair
  740. get_seed(params, ots_seed, sk_seed, ots_addr);
  741. // Compute WOTS signature
  742. wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr);
  743. sm += params->wots_sig_bytes;
  744. *smlen += params->wots_sig_bytes;
  745. memcpy(sm, states[0].auth, params->tree_height*params->n);
  746. sm += params->tree_height*params->n;
  747. *smlen += params->tree_height*params->n;
  748. // prepare signature of remaining layers
  749. for (i = 1; i < params->d; i++) {
  750. // put WOTS signature in place
  751. memcpy(sm, wots_sigs + (i-1)*params->wots_sig_bytes, params->wots_sig_bytes);
  752. sm += params->wots_sig_bytes;
  753. *smlen += params->wots_sig_bytes;
  754. // put AUTH nodes in place
  755. memcpy(sm, states[i].auth, params->tree_height*params->n);
  756. sm += params->tree_height*params->n;
  757. *smlen += params->tree_height*params->n;
  758. }
  759. updates = (params->tree_height - params->bds_k) >> 1;
  760. set_tree_addr(addr, (idx_tree + 1));
  761. // mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists
  762. if ((1 + idx_tree) * (1 << params->tree_height) + idx_leaf < (1ULL << params->full_height)) {
  763. bds_state_update(params, &states[params->d], sk_seed, pub_seed, addr);
  764. }
  765. for (i = 0; i < params->d; i++) {
  766. // check if we're not at the end of a tree
  767. if (! (((idx + 1) & ((1ULL << ((i+1)*params->tree_height)) - 1)) == 0)) {
  768. idx_leaf = (idx >> (params->tree_height * i)) & ((1 << params->tree_height)-1);
  769. idx_tree = (idx >> (params->tree_height * (i+1)));
  770. set_layer_addr(addr, i);
  771. set_tree_addr(addr, idx_tree);
  772. if (i == (unsigned int) (needswap_upto + 1)) {
  773. bds_round(params, &states[i], idx_leaf, sk_seed, pub_seed, addr);
  774. }
  775. updates = bds_treehash_update(params, &states[i], updates, sk_seed, pub_seed, addr);
  776. set_tree_addr(addr, (idx_tree + 1));
  777. // if a NEXT-tree exists for this level;
  778. if ((1 + idx_tree) * (1 << params->tree_height) + idx_leaf < (1ULL << (params->full_height - params->tree_height * i))) {
  779. if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << params->full_height)) {
  780. bds_state_update(params, &states[params->d + i], sk_seed, pub_seed, addr);
  781. updates--;
  782. }
  783. }
  784. }
  785. else if (idx < (1ULL << params->full_height) - 1) {
  786. deep_state_swap(params, states+params->d + i, states + i);
  787. set_layer_addr(ots_addr, (i+1));
  788. set_tree_addr(ots_addr, ((idx + 1) >> ((i+2) * params->tree_height)));
  789. set_ots_addr(ots_addr, (((idx >> ((i+1) * params->tree_height)) + 1) & ((1 << params->tree_height)-1)));
  790. get_seed(params, ots_seed, sk+params->index_bytes, ots_addr);
  791. wots_sign(params, wots_sigs + i*params->wots_sig_bytes, states[i].stack, ots_seed, pub_seed, ots_addr);
  792. states[params->d + i].stackoffset = 0;
  793. states[params->d + i].next_leaf = 0;
  794. updates--; // WOTS-signing counts as one update
  795. needswap_upto = i;
  796. for (j = 0; j < params->tree_height-params->bds_k; j++) {
  797. states[i].treehash[j].completed = 1;
  798. }
  799. }
  800. }
  801. memcpy(sm, m, mlen);
  802. *smlen += mlen;
  803. xmssmt_serialize_state(params, sk, states);
  804. return 0;
  805. }