Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

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