25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

712 lines
25 KiB

  1. /*
  2. xmss_fast.c version 20160722
  3. Andreas Hülsing
  4. Joost Rijneveld
  5. Public domain.
  6. */
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdint.h>
  10. #include "hash.h"
  11. #include "hash_address.h"
  12. #include "params.h"
  13. #include "randombytes.h"
  14. #include "wots.h"
  15. #include "xmss_commons.h"
  16. #include "xmss_core_fast.h"
  17. /**
  18. * Initialize BDS state struct
  19. * parameter names are the same as used in the description of the BDS traversal
  20. */
  21. void xmss_set_bds_state(bds_state *state, unsigned char *stack,
  22. int stackoffset, unsigned char *stacklevels,
  23. unsigned char *auth, unsigned char *keep,
  24. treehash_inst *treehash, unsigned char *retain,
  25. int next_leaf)
  26. {
  27. state->stack = stack;
  28. state->stackoffset = stackoffset;
  29. state->stacklevels = stacklevels;
  30. state->auth = auth;
  31. state->keep = keep;
  32. state->treehash = treehash;
  33. state->retain = retain;
  34. state->next_leaf = next_leaf;
  35. }
  36. static int treehash_minheight_on_stack(const xmss_params *params,
  37. bds_state* state,
  38. const treehash_inst *treehash)
  39. {
  40. unsigned int r = params->tree_height, i;
  41. for (i = 0; i < treehash->stackusage; i++) {
  42. if (state->stacklevels[state->stackoffset - i - 1] < r) {
  43. r = state->stacklevels[state->stackoffset - i - 1];
  44. }
  45. }
  46. return r;
  47. }
  48. /**
  49. * Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash.
  50. * Currently only used for key generation.
  51. *
  52. */
  53. static void treehash_init(const xmss_params *params,
  54. unsigned char *node, int height, int index,
  55. bds_state *state, const unsigned char *sk_seed,
  56. const unsigned char *pub_seed, const uint32_t addr[8])
  57. {
  58. unsigned int idx = index;
  59. // use three different addresses because at this point we use all three formats in parallel
  60. uint32_t ots_addr[8];
  61. uint32_t ltree_addr[8];
  62. uint32_t node_addr[8];
  63. // only copy layer and tree address parts
  64. memcpy(ots_addr, addr, 12);
  65. // type = ots
  66. set_type(ots_addr, 0);
  67. memcpy(ltree_addr, addr, 12);
  68. set_type(ltree_addr, 1);
  69. memcpy(node_addr, addr, 12);
  70. set_type(node_addr, 2);
  71. uint32_t lastnode, i;
  72. unsigned char stack[(height+1)*params->n];
  73. unsigned int stacklevels[height+1];
  74. unsigned int stackoffset=0;
  75. unsigned int nodeh;
  76. lastnode = idx+(1<<height);
  77. for (i = 0; i < params->tree_height-params->bds_k; i++) {
  78. state->treehash[i].h = i;
  79. state->treehash[i].completed = 1;
  80. state->treehash[i].stackusage = 0;
  81. }
  82. i = 0;
  83. for (; idx < lastnode; idx++) {
  84. set_ltree_addr(ltree_addr, idx);
  85. set_ots_addr(ots_addr, idx);
  86. gen_leaf_wots(params, stack+stackoffset*params->n, sk_seed, pub_seed, ltree_addr, ots_addr);
  87. stacklevels[stackoffset] = 0;
  88. stackoffset++;
  89. if (params->tree_height - params->bds_k > 0 && i == 3) {
  90. memcpy(state->treehash[0].node, stack+stackoffset*params->n, params->n);
  91. }
  92. while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) {
  93. nodeh = stacklevels[stackoffset-1];
  94. if (i >> nodeh == 1) {
  95. memcpy(state->auth + nodeh*params->n, stack+(stackoffset-1)*params->n, params->n);
  96. }
  97. else {
  98. if (nodeh < params->tree_height - params->bds_k && i >> nodeh == 3) {
  99. memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*params->n, params->n);
  100. }
  101. else if (nodeh >= params->tree_height - params->bds_k) {
  102. 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);
  103. }
  104. }
  105. set_tree_height(node_addr, stacklevels[stackoffset-1]);
  106. set_tree_index(node_addr, (idx >> (stacklevels[stackoffset-1]+1)));
  107. hash_h(params, stack+(stackoffset-2)*params->n, stack+(stackoffset-2)*params->n, pub_seed, node_addr);
  108. stacklevels[stackoffset-2]++;
  109. stackoffset--;
  110. }
  111. i++;
  112. }
  113. for (i = 0; i < params->n; i++) {
  114. node[i] = stack[i];
  115. }
  116. }
  117. static void treehash_update(const xmss_params *params,
  118. treehash_inst *treehash, bds_state *state,
  119. const unsigned char *sk_seed,
  120. const unsigned char *pub_seed,
  121. const uint32_t addr[8])
  122. {
  123. uint32_t ots_addr[8];
  124. uint32_t ltree_addr[8];
  125. uint32_t node_addr[8];
  126. // only copy layer and tree address parts
  127. memcpy(ots_addr, addr, 12);
  128. // type = ots
  129. set_type(ots_addr, 0);
  130. memcpy(ltree_addr, addr, 12);
  131. set_type(ltree_addr, 1);
  132. memcpy(node_addr, addr, 12);
  133. set_type(node_addr, 2);
  134. set_ltree_addr(ltree_addr, treehash->next_idx);
  135. set_ots_addr(ots_addr, treehash->next_idx);
  136. unsigned char nodebuffer[2 * params->n];
  137. unsigned int nodeheight = 0;
  138. gen_leaf_wots(params, nodebuffer, sk_seed, pub_seed, ltree_addr, ots_addr);
  139. while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) {
  140. memcpy(nodebuffer + params->n, nodebuffer, params->n);
  141. memcpy(nodebuffer, state->stack + (state->stackoffset-1)*params->n, params->n);
  142. set_tree_height(node_addr, nodeheight);
  143. set_tree_index(node_addr, (treehash->next_idx >> (nodeheight+1)));
  144. hash_h(params, nodebuffer, nodebuffer, pub_seed, node_addr);
  145. nodeheight++;
  146. treehash->stackusage--;
  147. state->stackoffset--;
  148. }
  149. if (nodeheight == treehash->h) { // this also implies stackusage == 0
  150. memcpy(treehash->node, nodebuffer, params->n);
  151. treehash->completed = 1;
  152. }
  153. else {
  154. memcpy(state->stack + state->stackoffset*params->n, nodebuffer, params->n);
  155. treehash->stackusage++;
  156. state->stacklevels[state->stackoffset] = nodeheight;
  157. state->stackoffset++;
  158. treehash->next_idx++;
  159. }
  160. }
  161. /**
  162. * Performs one treehash update on the instance that needs it the most.
  163. * Returns 1 if such an instance was not found
  164. **/
  165. static char bds_treehash_update(const xmss_params *params,
  166. bds_state *state, unsigned int updates,
  167. const unsigned char *sk_seed,
  168. unsigned char *pub_seed,
  169. const uint32_t addr[8])
  170. {
  171. uint32_t i, j;
  172. unsigned int level, l_min, low;
  173. unsigned int used = 0;
  174. for (j = 0; j < updates; j++) {
  175. l_min = params->tree_height;
  176. level = params->tree_height - params->bds_k;
  177. for (i = 0; i < params->tree_height - params->bds_k; i++) {
  178. if (state->treehash[i].completed) {
  179. low = params->tree_height;
  180. }
  181. else if (state->treehash[i].stackusage == 0) {
  182. low = i;
  183. }
  184. else {
  185. low = treehash_minheight_on_stack(params, state, &(state->treehash[i]));
  186. }
  187. if (low < l_min) {
  188. level = i;
  189. l_min = low;
  190. }
  191. }
  192. if (level == params->tree_height - params->bds_k) {
  193. break;
  194. }
  195. treehash_update(params, &(state->treehash[level]), state, sk_seed, pub_seed, addr);
  196. used++;
  197. }
  198. return updates - used;
  199. }
  200. /**
  201. * Updates the state (typically NEXT_i) by adding a leaf and updating the stack
  202. * Returns 1 if all leaf nodes have already been processed
  203. **/
  204. static char bds_state_update(const xmss_params *params,
  205. bds_state *state, const unsigned char *sk_seed,
  206. const unsigned char *pub_seed,
  207. const uint32_t addr[8])
  208. {
  209. uint32_t ltree_addr[8];
  210. uint32_t node_addr[8];
  211. uint32_t ots_addr[8];
  212. int nodeh;
  213. int idx = state->next_leaf;
  214. if (idx == 1 << params->tree_height) {
  215. return 1;
  216. }
  217. // only copy layer and tree address parts
  218. memcpy(ots_addr, addr, 12);
  219. // type = ots
  220. set_type(ots_addr, 0);
  221. memcpy(ltree_addr, addr, 12);
  222. set_type(ltree_addr, 1);
  223. memcpy(node_addr, addr, 12);
  224. set_type(node_addr, 2);
  225. set_ots_addr(ots_addr, idx);
  226. set_ltree_addr(ltree_addr, idx);
  227. gen_leaf_wots(params, state->stack+state->stackoffset*params->n, sk_seed, pub_seed, ltree_addr, ots_addr);
  228. state->stacklevels[state->stackoffset] = 0;
  229. state->stackoffset++;
  230. if (params->tree_height - params->bds_k > 0 && idx == 3) {
  231. memcpy(state->treehash[0].node, state->stack+state->stackoffset*params->n, params->n);
  232. }
  233. while (state->stackoffset>1 && state->stacklevels[state->stackoffset-1] == state->stacklevels[state->stackoffset-2]) {
  234. nodeh = state->stacklevels[state->stackoffset-1];
  235. if (idx >> nodeh == 1) {
  236. memcpy(state->auth + nodeh*params->n, state->stack+(state->stackoffset-1)*params->n, params->n);
  237. }
  238. else {
  239. if (nodeh < params->tree_height - params->bds_k && idx >> nodeh == 3) {
  240. memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*params->n, params->n);
  241. }
  242. else if (nodeh >= params->tree_height - params->bds_k) {
  243. 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);
  244. }
  245. }
  246. set_tree_height(node_addr, state->stacklevels[state->stackoffset-1]);
  247. set_tree_index(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1)));
  248. hash_h(params, state->stack+(state->stackoffset-2)*params->n, state->stack+(state->stackoffset-2)*params->n, pub_seed, node_addr);
  249. state->stacklevels[state->stackoffset-2]++;
  250. state->stackoffset--;
  251. }
  252. state->next_leaf++;
  253. return 0;
  254. }
  255. /**
  256. * Returns the auth path for node leaf_idx and computes the auth path for the
  257. * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo
  258. * in "Post Quantum Cryptography", Springer 2009.
  259. */
  260. static void bds_round(const xmss_params *params,
  261. bds_state *state, const unsigned long leaf_idx,
  262. const unsigned char *sk_seed,
  263. const unsigned char *pub_seed, uint32_t addr[8])
  264. {
  265. unsigned int i;
  266. unsigned int tau = params->tree_height;
  267. unsigned int startidx;
  268. unsigned int offset, rowidx;
  269. unsigned char buf[2 * params->n];
  270. uint32_t ots_addr[8];
  271. uint32_t ltree_addr[8];
  272. uint32_t node_addr[8];
  273. // only copy layer and tree address parts
  274. memcpy(ots_addr, addr, 12);
  275. // type = ots
  276. set_type(ots_addr, 0);
  277. memcpy(ltree_addr, addr, 12);
  278. set_type(ltree_addr, 1);
  279. memcpy(node_addr, addr, 12);
  280. set_type(node_addr, 2);
  281. for (i = 0; i < params->tree_height; i++) {
  282. if (! ((leaf_idx >> i) & 1)) {
  283. tau = i;
  284. break;
  285. }
  286. }
  287. if (tau > 0) {
  288. memcpy(buf, state->auth + (tau-1) * params->n, params->n);
  289. // we need to do this before refreshing state->keep to prevent overwriting
  290. memcpy(buf + params->n, state->keep + ((tau-1) >> 1) * params->n, params->n);
  291. }
  292. if (!((leaf_idx >> (tau + 1)) & 1) && (tau < params->tree_height - 1)) {
  293. memcpy(state->keep + (tau >> 1)*params->n, state->auth + tau*params->n, params->n);
  294. }
  295. if (tau == 0) {
  296. set_ltree_addr(ltree_addr, leaf_idx);
  297. set_ots_addr(ots_addr, leaf_idx);
  298. gen_leaf_wots(params, state->auth, sk_seed, pub_seed, ltree_addr, ots_addr);
  299. }
  300. else {
  301. set_tree_height(node_addr, (tau-1));
  302. set_tree_index(node_addr, leaf_idx >> tau);
  303. hash_h(params, state->auth + tau * params->n, buf, pub_seed, node_addr);
  304. for (i = 0; i < tau; i++) {
  305. if (i < params->tree_height - params->bds_k) {
  306. memcpy(state->auth + i * params->n, state->treehash[i].node, params->n);
  307. }
  308. else {
  309. offset = (1 << (params->tree_height - 1 - i)) + i - params->tree_height;
  310. rowidx = ((leaf_idx >> i) - 1) >> 1;
  311. memcpy(state->auth + i * params->n, state->retain + (offset + rowidx) * params->n, params->n);
  312. }
  313. }
  314. for (i = 0; i < ((tau < params->tree_height - params->bds_k) ? tau : (params->tree_height - params->bds_k)); i++) {
  315. startidx = leaf_idx + 1 + 3 * (1 << i);
  316. if (startidx < 1U << params->tree_height) {
  317. state->treehash[i].h = i;
  318. state->treehash[i].next_idx = startidx;
  319. state->treehash[i].completed = 0;
  320. state->treehash[i].stackusage = 0;
  321. }
  322. }
  323. }
  324. }
  325. /*
  326. * Generates a XMSS key pair for a given parameter set.
  327. * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
  328. * Format pk: [root || PUB_SEED] omitting algo oid.
  329. */
  330. int xmss_core_keypair(const xmss_params *params,
  331. unsigned char *pk, unsigned char *sk, bds_state *state)
  332. {
  333. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  334. // Set idx = 0
  335. sk[0] = 0;
  336. sk[1] = 0;
  337. sk[2] = 0;
  338. sk[3] = 0;
  339. // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte)
  340. randombytes(sk + params->index_len, 3*params->n);
  341. // Copy PUB_SEED to public key
  342. memcpy(pk + params->n, sk + params->index_len + 2*params->n, params->n);
  343. // Compute root
  344. treehash_init(params, pk, params->tree_height, 0, state, sk + params->index_len, sk + params->index_len + 2*params->n, addr);
  345. // copy root o sk
  346. memcpy(sk + params->index_len + 3*params->n, pk, params->n);
  347. return 0;
  348. }
  349. /**
  350. * Signs a message.
  351. * Returns
  352. * 1. an array containing the signature followed by the message AND
  353. * 2. an updated secret key!
  354. *
  355. */
  356. int xmss_core_sign(const xmss_params *params,
  357. unsigned char *sk, bds_state *state,
  358. unsigned char *sm, unsigned long long *smlen,
  359. const unsigned char *m, unsigned long long mlen)
  360. {
  361. uint16_t i = 0;
  362. // Extract SK
  363. unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3];
  364. unsigned char sk_seed[params->n];
  365. memcpy(sk_seed, sk + params->index_len, params->n);
  366. unsigned char sk_prf[params->n];
  367. memcpy(sk_prf, sk + params->index_len + params->n, params->n);
  368. unsigned char pub_seed[params->n];
  369. memcpy(pub_seed, sk + params->index_len + 2*params->n, params->n);
  370. // index as 32 bytes string
  371. unsigned char idx_bytes_32[32];
  372. to_byte(idx_bytes_32, idx, 32);
  373. unsigned char hash_key[3*params->n];
  374. // Update SK
  375. sk[0] = ((idx + 1) >> 24) & 255;
  376. sk[1] = ((idx + 1) >> 16) & 255;
  377. sk[2] = ((idx + 1) >> 8) & 255;
  378. sk[3] = (idx + 1) & 255;
  379. // -- Secret key for this non-forward-secure version is now updated.
  380. // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
  381. // Init working params
  382. unsigned char R[params->n];
  383. unsigned char msg_h[params->n];
  384. unsigned char ots_seed[params->n];
  385. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  386. // ---------------------------------
  387. // Message Hashing
  388. // ---------------------------------
  389. // Message Hash:
  390. // First compute pseudorandom value
  391. prf(params, R, idx_bytes_32, sk_prf, params->n);
  392. // Generate hash key (R || root || idx)
  393. memcpy(hash_key, R, params->n);
  394. memcpy(hash_key+params->n, sk+4+3*params->n, params->n);
  395. to_byte(hash_key+2*params->n, idx, params->n);
  396. // Then use it for message digest
  397. h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
  398. // Start collecting signature
  399. *smlen = 0;
  400. // Copy index to signature
  401. sm[0] = (idx >> 24) & 255;
  402. sm[1] = (idx >> 16) & 255;
  403. sm[2] = (idx >> 8) & 255;
  404. sm[3] = idx & 255;
  405. sm += 4;
  406. *smlen += 4;
  407. // Copy R to signature
  408. for (i = 0; i < params->n; i++) {
  409. sm[i] = R[i];
  410. }
  411. sm += params->n;
  412. *smlen += params->n;
  413. // ----------------------------------
  414. // Now we start to "really sign"
  415. // ----------------------------------
  416. // Prepare Address
  417. set_type(ots_addr, 0);
  418. set_ots_addr(ots_addr, idx);
  419. // Compute seed for OTS key pair
  420. get_seed(params, ots_seed, sk_seed, ots_addr);
  421. // Compute WOTS signature
  422. wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr);
  423. sm += params->wots_keysize;
  424. *smlen += params->wots_keysize;
  425. // the auth path was already computed during the previous round
  426. memcpy(sm, state->auth, params->tree_height*params->n);
  427. if (idx < (1U << params->tree_height) - 1) {
  428. bds_round(params, state, idx, sk_seed, pub_seed, ots_addr);
  429. bds_treehash_update(params, state, (params->tree_height - params->bds_k) >> 1, sk_seed, pub_seed, ots_addr);
  430. }
  431. sm += params->tree_height*params->n;
  432. *smlen += params->tree_height*params->n;
  433. memcpy(sm, m, mlen);
  434. *smlen += mlen;
  435. return 0;
  436. }
  437. /*
  438. * Generates a XMSSMT key pair for a given parameter set.
  439. * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
  440. * Format pk: [root || PUB_SEED] omitting algo oid.
  441. */
  442. int xmssmt_core_keypair(const xmss_params *params,
  443. unsigned char *pk, unsigned char *sk,
  444. bds_state *states, unsigned char *wots_sigs)
  445. {
  446. unsigned char ots_seed[params->n];
  447. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  448. int i;
  449. // Set idx = 0
  450. for (i = 0; i < params->index_len; i++) {
  451. sk[i] = 0;
  452. }
  453. // Init SK_SEED (params->n byte), SK_PRF (params->n byte), and PUB_SEED (params->n byte)
  454. randombytes(sk+params->index_len, 3*params->n);
  455. // Copy PUB_SEED to public key
  456. memcpy(pk+params->n, sk+params->index_len+2*params->n, params->n);
  457. // Start with the bottom-most layer
  458. set_layer_addr(addr, 0);
  459. // Set up state and compute wots signatures for all but topmost tree root
  460. for (i = 0; i < params->d - 1; i++) {
  461. // Compute seed for OTS key pair
  462. treehash_init(params, pk, params->tree_height, 0, states + i, sk+params->index_len, pk+params->n, addr);
  463. set_layer_addr(addr, (i+1));
  464. get_seed(params, ots_seed, sk + params->index_len, addr);
  465. wots_sign(params, wots_sigs + i*params->wots_keysize, pk, ots_seed, pk+params->n, addr);
  466. }
  467. // Address now points to the single tree on layer d-1
  468. treehash_init(params, pk, params->tree_height, 0, states + i, sk+params->index_len, pk+params->n, addr);
  469. memcpy(sk + params->index_len + 3*params->n, pk, params->n);
  470. return 0;
  471. }
  472. /**
  473. * Signs a message.
  474. * Returns
  475. * 1. an array containing the signature followed by the message AND
  476. * 2. an updated secret key!
  477. *
  478. */
  479. int xmssmt_core_sign(const xmss_params *params,
  480. unsigned char *sk,
  481. bds_state *states, unsigned char *wots_sigs,
  482. unsigned char *sm, unsigned long long *smlen,
  483. const unsigned char *m, unsigned long long mlen)
  484. {
  485. uint64_t idx_tree;
  486. uint32_t idx_leaf;
  487. uint64_t i, j;
  488. int needswap_upto = -1;
  489. unsigned int updates;
  490. unsigned char sk_seed[params->n];
  491. unsigned char sk_prf[params->n];
  492. unsigned char pub_seed[params->n];
  493. // Init working params
  494. unsigned char R[params->n];
  495. unsigned char msg_h[params->n];
  496. unsigned char hash_key[3*params->n];
  497. unsigned char ots_seed[params->n];
  498. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  499. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  500. unsigned char idx_bytes_32[32];
  501. bds_state tmp;
  502. // Extract SK
  503. unsigned long long idx = 0;
  504. for (i = 0; i < params->index_len; i++) {
  505. idx |= ((unsigned long long)sk[i]) << 8*(params->index_len - 1 - i);
  506. }
  507. memcpy(sk_seed, sk+params->index_len, params->n);
  508. memcpy(sk_prf, sk+params->index_len+params->n, params->n);
  509. memcpy(pub_seed, sk+params->index_len+2*params->n, params->n);
  510. // Update SK
  511. for (i = 0; i < params->index_len; i++) {
  512. sk[i] = ((idx + 1) >> 8*(params->index_len - 1 - i)) & 255;
  513. }
  514. // -- Secret key for this non-forward-secure version is now updated.
  515. // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
  516. // ---------------------------------
  517. // Message Hashing
  518. // ---------------------------------
  519. // Message Hash:
  520. // First compute pseudorandom value
  521. to_byte(idx_bytes_32, idx, 32);
  522. prf(params, R, idx_bytes_32, sk_prf, params->n);
  523. // Generate hash key (R || root || idx)
  524. memcpy(hash_key, R, params->n);
  525. memcpy(hash_key+params->n, sk+params->index_len+3*params->n, params->n);
  526. to_byte(hash_key+2*params->n, idx, params->n);
  527. // Then use it for message digest
  528. h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
  529. // Start collecting signature
  530. *smlen = 0;
  531. // Copy index to signature
  532. for (i = 0; i < params->index_len; i++) {
  533. sm[i] = (idx >> 8*(params->index_len - 1 - i)) & 255;
  534. }
  535. sm += params->index_len;
  536. *smlen += params->index_len;
  537. // Copy R to signature
  538. for (i = 0; i < params->n; i++) {
  539. sm[i] = R[i];
  540. }
  541. sm += params->n;
  542. *smlen += params->n;
  543. // ----------------------------------
  544. // Now we start to "really sign"
  545. // ----------------------------------
  546. // Handle lowest layer separately as it is slightly different...
  547. // Prepare Address
  548. set_type(ots_addr, 0);
  549. idx_tree = idx >> params->tree_height;
  550. idx_leaf = (idx & ((1 << params->tree_height)-1));
  551. set_layer_addr(ots_addr, 0);
  552. set_tree_addr(ots_addr, idx_tree);
  553. set_ots_addr(ots_addr, idx_leaf);
  554. // Compute seed for OTS key pair
  555. get_seed(params, ots_seed, sk_seed, ots_addr);
  556. // Compute WOTS signature
  557. wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr);
  558. sm += params->wots_keysize;
  559. *smlen += params->wots_keysize;
  560. memcpy(sm, states[0].auth, params->tree_height*params->n);
  561. sm += params->tree_height*params->n;
  562. *smlen += params->tree_height*params->n;
  563. // prepare signature of remaining layers
  564. for (i = 1; i < params->d; i++) {
  565. // put WOTS signature in place
  566. memcpy(sm, wots_sigs + (i-1)*params->wots_keysize, params->wots_keysize);
  567. sm += params->wots_keysize;
  568. *smlen += params->wots_keysize;
  569. // put AUTH nodes in place
  570. memcpy(sm, states[i].auth, params->tree_height*params->n);
  571. sm += params->tree_height*params->n;
  572. *smlen += params->tree_height*params->n;
  573. }
  574. updates = (params->tree_height - params->bds_k) >> 1;
  575. set_tree_addr(addr, (idx_tree + 1));
  576. // mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists
  577. if ((1 + idx_tree) * (1 << params->tree_height) + idx_leaf < (1ULL << params->full_height)) {
  578. bds_state_update(params, &states[params->d], sk_seed, pub_seed, addr);
  579. }
  580. for (i = 0; i < params->d; i++) {
  581. // check if we're not at the end of a tree
  582. if (! (((idx + 1) & ((1ULL << ((i+1)*params->tree_height)) - 1)) == 0)) {
  583. idx_leaf = (idx >> (params->tree_height * i)) & ((1 << params->tree_height)-1);
  584. idx_tree = (idx >> (params->tree_height * (i+1)));
  585. set_layer_addr(addr, i);
  586. set_tree_addr(addr, idx_tree);
  587. if (i == (unsigned int) (needswap_upto + 1)) {
  588. bds_round(params, &states[i], idx_leaf, sk_seed, pub_seed, addr);
  589. }
  590. updates = bds_treehash_update(params, &states[i], updates, sk_seed, pub_seed, addr);
  591. set_tree_addr(addr, (idx_tree + 1));
  592. // if a NEXT-tree exists for this level;
  593. if ((1 + idx_tree) * (1 << params->tree_height) + idx_leaf < (1ULL << (params->full_height - params->tree_height * i))) {
  594. if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << params->full_height)) {
  595. bds_state_update(params, &states[params->d + i], sk_seed, pub_seed, addr);
  596. updates--;
  597. }
  598. }
  599. }
  600. else if (idx < (1ULL << params->full_height) - 1) {
  601. memcpy(&tmp, states+params->d + i, sizeof(bds_state));
  602. memcpy(states+params->d + i, states + i, sizeof(bds_state));
  603. memcpy(states + i, &tmp, sizeof(bds_state));
  604. set_layer_addr(ots_addr, (i+1));
  605. set_tree_addr(ots_addr, ((idx + 1) >> ((i+2) * params->tree_height)));
  606. set_ots_addr(ots_addr, (((idx >> ((i+1) * params->tree_height)) + 1) & ((1 << params->tree_height)-1)));
  607. get_seed(params, ots_seed, sk+params->index_len, ots_addr);
  608. wots_sign(params, wots_sigs + i*params->wots_keysize, states[i].stack, ots_seed, pub_seed, ots_addr);
  609. states[params->d + i].stackoffset = 0;
  610. states[params->d + i].next_leaf = 0;
  611. updates--; // WOTS-signing counts as one update
  612. needswap_upto = i;
  613. for (j = 0; j < params->tree_height-params->bds_k; j++) {
  614. states[i].treehash[j].completed = 1;
  615. }
  616. }
  617. }
  618. memcpy(sm, m, mlen);
  619. *smlen += mlen;
  620. return 0;
  621. }