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.

1097 lines
32 KiB

  1. /*
  2. xmss_fast.c version 20160722
  3. Andreas Hülsing
  4. Joost Rijneveld
  5. Public domain.
  6. */
  7. #include "xmss_fast.h"
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <stdint.h>
  11. #include <math.h>
  12. #include "randombytes.h"
  13. #include "wots.h"
  14. #include "hash.h"
  15. #include "xmss_commons.h"
  16. #include "hash_address.h"
  17. // For testing
  18. #include "stdio.h"
  19. /**
  20. * Used for pseudorandom keygeneration,
  21. * generates the seed for the WOTS keypair at address addr
  22. *
  23. * takes n byte sk_seed and returns n byte seed using 32 byte address addr.
  24. */
  25. static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8])
  26. {
  27. unsigned char bytes[32];
  28. // Make sure that chain addr, hash addr, and key bit are 0!
  29. setChainADRS(addr,0);
  30. setHashADRS(addr,0);
  31. setKeyAndMask(addr,0);
  32. // Generate pseudorandom value
  33. addr_to_byte(bytes, addr);
  34. prf(seed, bytes, sk_seed, n);
  35. }
  36. /**
  37. * Initialize xmss params struct
  38. * parameter names are the same as in the draft
  39. * parameter k is K as used in the BDS algorithm
  40. */
  41. int xmss_set_params(xmss_params *params, int n, int h, int w, int k)
  42. {
  43. if (k >= h || k < 2 || (h - k) % 2) {
  44. fprintf(stderr, "For BDS traversal, H - K must be even, with H > K >= 2!\n");
  45. return 1;
  46. }
  47. params->h = h;
  48. params->n = n;
  49. params->k = k;
  50. wots_params wots_par;
  51. wots_set_params(&wots_par, n, w);
  52. params->wots_par = wots_par;
  53. return 0;
  54. }
  55. /**
  56. * Initialize BDS state struct
  57. * parameter names are the same as used in the description of the BDS traversal
  58. */
  59. void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, unsigned char *stacklevels, unsigned char *auth, unsigned char *keep, treehash_inst *treehash, unsigned char *retain, int next_leaf)
  60. {
  61. state->stack = stack;
  62. state->stackoffset = stackoffset;
  63. state->stacklevels = stacklevels;
  64. state->auth = auth;
  65. state->keep = keep;
  66. state->treehash = treehash;
  67. state->retain = retain;
  68. state->next_leaf = next_leaf;
  69. }
  70. /**
  71. * Initialize xmssmt_params struct
  72. * parameter names are the same as in the draft
  73. *
  74. * Especially h is the total tree height, i.e. the XMSS trees have height h/d
  75. */
  76. int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k)
  77. {
  78. if (h % d) {
  79. fprintf(stderr, "d must divide h without remainder!\n");
  80. return 1;
  81. }
  82. params->h = h;
  83. params->d = d;
  84. params->n = n;
  85. params->index_len = (h + 7) / 8;
  86. xmss_params xmss_par;
  87. if (xmss_set_params(&xmss_par, n, (h/d), w, k)) {
  88. return 1;
  89. }
  90. params->xmss_par = xmss_par;
  91. return 0;
  92. }
  93. /**
  94. * Computes a leaf from a WOTS public key using an L-tree.
  95. */
  96. static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8])
  97. {
  98. unsigned int l = params->wots_par.len;
  99. unsigned int n = params->n;
  100. uint32_t i = 0;
  101. uint32_t height = 0;
  102. uint32_t bound;
  103. //ADRS.setTreeHeight(0);
  104. setTreeHeight(addr, height);
  105. while (l > 1) {
  106. bound = l >> 1; //floor(l / 2);
  107. for (i = 0; i < bound; i++) {
  108. //ADRS.setTreeIndex(i);
  109. setTreeIndex(addr, i);
  110. //wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS);
  111. hash_h(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n);
  112. }
  113. //if ( l % 2 == 1 ) {
  114. if (l & 1) {
  115. //pk[floor(l / 2) + 1] = pk[l];
  116. memcpy(wots_pk+(l>>1)*n, wots_pk+(l-1)*n, n);
  117. //l = ceil(l / 2);
  118. l=(l>>1)+1;
  119. }
  120. else {
  121. //l = ceil(l / 2);
  122. l=(l>>1);
  123. }
  124. //ADRS.setTreeHeight(ADRS.getTreeHeight() + 1);
  125. height++;
  126. setTreeHeight(addr, height);
  127. }
  128. //return pk[0];
  129. memcpy(leaf, wots_pk, n);
  130. }
  131. /**
  132. * Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address.
  133. */
  134. static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, uint32_t ltree_addr[8], uint32_t ots_addr[8])
  135. {
  136. unsigned char seed[params->n];
  137. unsigned char pk[params->wots_par.keysize];
  138. get_seed(seed, sk_seed, params->n, ots_addr);
  139. wots_pkgen(pk, seed, &(params->wots_par), pub_seed, ots_addr);
  140. l_tree(leaf, pk, params, pub_seed, ltree_addr);
  141. }
  142. static int treehash_minheight_on_stack(bds_state* state, const xmss_params *params, const treehash_inst *treehash) {
  143. unsigned int r = params->h, i;
  144. for (i = 0; i < treehash->stackusage; i++) {
  145. if (state->stacklevels[state->stackoffset - i - 1] < r) {
  146. r = state->stacklevels[state->stackoffset - i - 1];
  147. }
  148. }
  149. return r;
  150. }
  151. /**
  152. * Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash.
  153. * Currently only used for key generation.
  154. *
  155. */
  156. static void treehash_setup(unsigned char *node, int height, int index, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8])
  157. {
  158. unsigned int idx = index;
  159. unsigned int n = params->n;
  160. unsigned int h = params->h;
  161. unsigned int k = params->k;
  162. // use three different addresses because at this point we use all three formats in parallel
  163. uint32_t ots_addr[8];
  164. uint32_t ltree_addr[8];
  165. uint32_t node_addr[8];
  166. // only copy layer and tree address parts
  167. memcpy(ots_addr, addr, 12);
  168. // type = ots
  169. setType(ots_addr, 0);
  170. memcpy(ltree_addr, addr, 12);
  171. setType(ltree_addr, 1);
  172. memcpy(node_addr, addr, 12);
  173. setType(node_addr, 2);
  174. uint32_t lastnode, i;
  175. unsigned char stack[(height+1)*n];
  176. unsigned int stacklevels[height+1];
  177. unsigned int stackoffset=0;
  178. unsigned int nodeh;
  179. lastnode = idx+(1<<height);
  180. for (i = 0; i < h-k; i++) {
  181. state->treehash[i].h = i;
  182. state->treehash[i].completed = 1;
  183. state->treehash[i].stackusage = 0;
  184. }
  185. i = 0;
  186. for (; idx < lastnode; idx++) {
  187. setLtreeADRS(ltree_addr, idx);
  188. setOTSADRS(ots_addr, idx);
  189. gen_leaf_wots(stack+stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr);
  190. stacklevels[stackoffset] = 0;
  191. stackoffset++;
  192. if (h - k > 0 && i == 3) {
  193. memcpy(state->treehash[0].node, stack+stackoffset*n, n);
  194. }
  195. while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2])
  196. {
  197. nodeh = stacklevels[stackoffset-1];
  198. if (i >> nodeh == 1) {
  199. memcpy(state->auth + nodeh*n, stack+(stackoffset-1)*n, n);
  200. }
  201. else {
  202. if (nodeh < h - k && i >> nodeh == 3) {
  203. memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*n, n);
  204. }
  205. else if (nodeh >= h - k) {
  206. memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((i >> nodeh) - 3) >> 1)) * n, stack+(stackoffset-1)*n, n);
  207. }
  208. }
  209. setTreeHeight(node_addr, stacklevels[stackoffset-1]);
  210. setTreeIndex(node_addr, (idx >> (stacklevels[stackoffset-1]+1)));
  211. hash_h(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed,
  212. node_addr, n);
  213. stacklevels[stackoffset-2]++;
  214. stackoffset--;
  215. }
  216. i++;
  217. }
  218. for (i = 0; i < n; i++)
  219. node[i] = stack[i];
  220. }
  221. static void treehash_update(treehash_inst *treehash, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) {
  222. int n = params->n;
  223. uint32_t ots_addr[8];
  224. uint32_t ltree_addr[8];
  225. uint32_t node_addr[8];
  226. // only copy layer and tree address parts
  227. memcpy(ots_addr, addr, 12);
  228. // type = ots
  229. setType(ots_addr, 0);
  230. memcpy(ltree_addr, addr, 12);
  231. setType(ltree_addr, 1);
  232. memcpy(node_addr, addr, 12);
  233. setType(node_addr, 2);
  234. setLtreeADRS(ltree_addr, treehash->next_idx);
  235. setOTSADRS(ots_addr, treehash->next_idx);
  236. unsigned char nodebuffer[2 * n];
  237. unsigned int nodeheight = 0;
  238. gen_leaf_wots(nodebuffer, sk_seed, params, pub_seed, ltree_addr, ots_addr);
  239. while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) {
  240. memcpy(nodebuffer + n, nodebuffer, n);
  241. memcpy(nodebuffer, state->stack + (state->stackoffset-1)*n, n);
  242. setTreeHeight(node_addr, nodeheight);
  243. setTreeIndex(node_addr, (treehash->next_idx >> (nodeheight+1)));
  244. hash_h(nodebuffer, nodebuffer, pub_seed, node_addr, n);
  245. nodeheight++;
  246. treehash->stackusage--;
  247. state->stackoffset--;
  248. }
  249. if (nodeheight == treehash->h) { // this also implies stackusage == 0
  250. memcpy(treehash->node, nodebuffer, n);
  251. treehash->completed = 1;
  252. }
  253. else {
  254. memcpy(state->stack + state->stackoffset*n, nodebuffer, n);
  255. treehash->stackusage++;
  256. state->stacklevels[state->stackoffset] = nodeheight;
  257. state->stackoffset++;
  258. treehash->next_idx++;
  259. }
  260. }
  261. /**
  262. * Computes a root node given a leaf and an authapth
  263. */
  264. static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8])
  265. {
  266. unsigned int n = params->n;
  267. uint32_t i, j;
  268. unsigned char buffer[2*n];
  269. // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left.
  270. // Otherwise, it is the other way around
  271. if (leafidx & 1) {
  272. for (j = 0; j < n; j++)
  273. buffer[n+j] = leaf[j];
  274. for (j = 0; j < n; j++)
  275. buffer[j] = authpath[j];
  276. }
  277. else {
  278. for (j = 0; j < n; j++)
  279. buffer[j] = leaf[j];
  280. for (j = 0; j < n; j++)
  281. buffer[n+j] = authpath[j];
  282. }
  283. authpath += n;
  284. for (i=0; i < params->h-1; i++) {
  285. setTreeHeight(addr, i);
  286. leafidx >>= 1;
  287. setTreeIndex(addr, leafidx);
  288. if (leafidx&1) {
  289. hash_h(buffer+n, buffer, pub_seed, addr, n);
  290. for (j = 0; j < n; j++)
  291. buffer[j] = authpath[j];
  292. }
  293. else {
  294. hash_h(buffer, buffer, pub_seed, addr, n);
  295. for (j = 0; j < n; j++)
  296. buffer[j+n] = authpath[j];
  297. }
  298. authpath += n;
  299. }
  300. setTreeHeight(addr, (params->h-1));
  301. leafidx >>= 1;
  302. setTreeIndex(addr, leafidx);
  303. hash_h(root, buffer, pub_seed, addr, n);
  304. }
  305. /**
  306. * Performs one treehash update on the instance that needs it the most.
  307. * Returns 1 if such an instance was not found
  308. **/
  309. static char bds_treehash_update(bds_state *state, unsigned int updates, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) {
  310. uint32_t i, j;
  311. unsigned int level, l_min, low;
  312. unsigned int h = params->h;
  313. unsigned int k = params->k;
  314. unsigned int used = 0;
  315. for (j = 0; j < updates; j++) {
  316. l_min = h;
  317. level = h - k;
  318. for (i = 0; i < h - k; i++) {
  319. if (state->treehash[i].completed) {
  320. low = h;
  321. }
  322. else if (state->treehash[i].stackusage == 0) {
  323. low = i;
  324. }
  325. else {
  326. low = treehash_minheight_on_stack(state, params, &(state->treehash[i]));
  327. }
  328. if (low < l_min) {
  329. level = i;
  330. l_min = low;
  331. }
  332. }
  333. if (level == h - k) {
  334. break;
  335. }
  336. treehash_update(&(state->treehash[level]), state, sk_seed, params, pub_seed, addr);
  337. used++;
  338. }
  339. return updates - used;
  340. }
  341. /**
  342. * Updates the state (typically NEXT_i) by adding a leaf and updating the stack
  343. * Returns 1 if all leaf nodes have already been processed
  344. **/
  345. static char bds_state_update(bds_state *state, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) {
  346. uint32_t ltree_addr[8];
  347. uint32_t node_addr[8];
  348. uint32_t ots_addr[8];
  349. int n = params->n;
  350. int h = params->h;
  351. int k = params->k;
  352. int nodeh;
  353. int idx = state->next_leaf;
  354. if (idx == 1 << h) {
  355. return 1;
  356. }
  357. // only copy layer and tree address parts
  358. memcpy(ots_addr, addr, 12);
  359. // type = ots
  360. setType(ots_addr, 0);
  361. memcpy(ltree_addr, addr, 12);
  362. setType(ltree_addr, 1);
  363. memcpy(node_addr, addr, 12);
  364. setType(node_addr, 2);
  365. setOTSADRS(ots_addr, idx);
  366. setLtreeADRS(ltree_addr, idx);
  367. gen_leaf_wots(state->stack+state->stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr);
  368. state->stacklevels[state->stackoffset] = 0;
  369. state->stackoffset++;
  370. if (h - k > 0 && idx == 3) {
  371. memcpy(state->treehash[0].node, state->stack+state->stackoffset*n, n);
  372. }
  373. while (state->stackoffset>1 && state->stacklevels[state->stackoffset-1] == state->stacklevels[state->stackoffset-2]) {
  374. nodeh = state->stacklevels[state->stackoffset-1];
  375. if (idx >> nodeh == 1) {
  376. memcpy(state->auth + nodeh*n, state->stack+(state->stackoffset-1)*n, n);
  377. }
  378. else {
  379. if (nodeh < h - k && idx >> nodeh == 3) {
  380. memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*n, n);
  381. }
  382. else if (nodeh >= h - k) {
  383. memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((idx >> nodeh) - 3) >> 1)) * n, state->stack+(state->stackoffset-1)*n, n);
  384. }
  385. }
  386. setTreeHeight(node_addr, state->stacklevels[state->stackoffset-1]);
  387. setTreeIndex(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1)));
  388. hash_h(state->stack+(state->stackoffset-2)*n, state->stack+(state->stackoffset-2)*n, pub_seed, node_addr, n);
  389. state->stacklevels[state->stackoffset-2]++;
  390. state->stackoffset--;
  391. }
  392. state->next_leaf++;
  393. return 0;
  394. }
  395. /**
  396. * Returns the auth path for node leaf_idx and computes the auth path for the
  397. * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo
  398. * in "Post Quantum Cryptography", Springer 2009.
  399. */
  400. static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, uint32_t addr[8])
  401. {
  402. unsigned int i;
  403. unsigned int n = params->n;
  404. unsigned int h = params->h;
  405. unsigned int k = params->k;
  406. unsigned int tau = h;
  407. unsigned int startidx;
  408. unsigned int offset, rowidx;
  409. unsigned char buf[2 * n];
  410. uint32_t ots_addr[8];
  411. uint32_t ltree_addr[8];
  412. uint32_t node_addr[8];
  413. // only copy layer and tree address parts
  414. memcpy(ots_addr, addr, 12);
  415. // type = ots
  416. setType(ots_addr, 0);
  417. memcpy(ltree_addr, addr, 12);
  418. setType(ltree_addr, 1);
  419. memcpy(node_addr, addr, 12);
  420. setType(node_addr, 2);
  421. for (i = 0; i < h; i++) {
  422. if (! ((leaf_idx >> i) & 1)) {
  423. tau = i;
  424. break;
  425. }
  426. }
  427. if (tau > 0) {
  428. memcpy(buf, state->auth + (tau-1) * n, n);
  429. // we need to do this before refreshing state->keep to prevent overwriting
  430. memcpy(buf + n, state->keep + ((tau-1) >> 1) * n, n);
  431. }
  432. if (!((leaf_idx >> (tau + 1)) & 1) && (tau < h - 1)) {
  433. memcpy(state->keep + (tau >> 1)*n, state->auth + tau*n, n);
  434. }
  435. if (tau == 0) {
  436. setLtreeADRS(ltree_addr, leaf_idx);
  437. setOTSADRS(ots_addr, leaf_idx);
  438. gen_leaf_wots(state->auth, sk_seed, params, pub_seed, ltree_addr, ots_addr);
  439. }
  440. else {
  441. setTreeHeight(node_addr, (tau-1));
  442. setTreeIndex(node_addr, leaf_idx >> tau);
  443. hash_h(state->auth + tau * n, buf, pub_seed, node_addr, n);
  444. for (i = 0; i < tau; i++) {
  445. if (i < h - k) {
  446. memcpy(state->auth + i * n, state->treehash[i].node, n);
  447. }
  448. else {
  449. offset = (1 << (h - 1 - i)) + i - h;
  450. rowidx = ((leaf_idx >> i) - 1) >> 1;
  451. memcpy(state->auth + i * n, state->retain + (offset + rowidx) * n, n);
  452. }
  453. }
  454. for (i = 0; i < ((tau < h - k) ? tau : (h - k)); i++) {
  455. startidx = leaf_idx + 1 + 3 * (1 << i);
  456. if (startidx < 1U << h) {
  457. state->treehash[i].h = i;
  458. state->treehash[i].next_idx = startidx;
  459. state->treehash[i].completed = 0;
  460. state->treehash[i].stackusage = 0;
  461. }
  462. }
  463. }
  464. }
  465. /*
  466. * Generates a XMSS key pair for a given parameter set.
  467. * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
  468. * Format pk: [root || PUB_SEED] omitting algo oid.
  469. */
  470. int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params)
  471. {
  472. unsigned int n = params->n;
  473. // Set idx = 0
  474. sk[0] = 0;
  475. sk[1] = 0;
  476. sk[2] = 0;
  477. sk[3] = 0;
  478. // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte)
  479. randombytes(sk+4, 3*n);
  480. // Copy PUB_SEED to public key
  481. memcpy(pk+n, sk+4+2*n, n);
  482. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  483. // Compute root
  484. treehash_setup(pk, params->h, 0, state, sk+4, params, sk+4+2*n, addr);
  485. // copy root to sk
  486. memcpy(sk+4+3*n, pk, n);
  487. return 0;
  488. }
  489. /**
  490. * Signs a message.
  491. * Returns
  492. * 1. an array containing the signature followed by the message AND
  493. * 2. an updated secret key!
  494. *
  495. */
  496. int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmss_params *params)
  497. {
  498. unsigned int h = params->h;
  499. unsigned int n = params->n;
  500. unsigned int k = params->k;
  501. uint16_t i = 0;
  502. // Extract SK
  503. unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3];
  504. unsigned char sk_seed[n];
  505. memcpy(sk_seed, sk+4, n);
  506. unsigned char sk_prf[n];
  507. memcpy(sk_prf, sk+4+n, n);
  508. unsigned char pub_seed[n];
  509. memcpy(pub_seed, sk+4+2*n, n);
  510. // index as 32 bytes string
  511. unsigned char idx_bytes_32[32];
  512. to_byte(idx_bytes_32, idx, 32);
  513. unsigned char hash_key[3*n];
  514. // Update SK
  515. sk[0] = ((idx + 1) >> 24) & 255;
  516. sk[1] = ((idx + 1) >> 16) & 255;
  517. sk[2] = ((idx + 1) >> 8) & 255;
  518. sk[3] = (idx + 1) & 255;
  519. // -- Secret key for this non-forward-secure version is now updated.
  520. // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
  521. // Init working params
  522. unsigned char R[n];
  523. unsigned char msg_h[n];
  524. unsigned char ots_seed[n];
  525. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  526. // ---------------------------------
  527. // Message Hashing
  528. // ---------------------------------
  529. // Message Hash:
  530. // First compute pseudorandom value
  531. prf(R, idx_bytes_32, sk_prf, n);
  532. // Generate hash key (R || root || idx)
  533. memcpy(hash_key, R, n);
  534. memcpy(hash_key+n, sk+4+3*n, n);
  535. to_byte(hash_key+2*n, idx, n);
  536. // Then use it for message digest
  537. h_msg(msg_h, msg, msglen, hash_key, 3*n, n);
  538. // Start collecting signature
  539. *sig_msg_len = 0;
  540. // Copy index to signature
  541. sig_msg[0] = (idx >> 24) & 255;
  542. sig_msg[1] = (idx >> 16) & 255;
  543. sig_msg[2] = (idx >> 8) & 255;
  544. sig_msg[3] = idx & 255;
  545. sig_msg += 4;
  546. *sig_msg_len += 4;
  547. // Copy R to signature
  548. for (i = 0; i < n; i++)
  549. sig_msg[i] = R[i];
  550. sig_msg += n;
  551. *sig_msg_len += n;
  552. // ----------------------------------
  553. // Now we start to "really sign"
  554. // ----------------------------------
  555. // Prepare Address
  556. setType(ots_addr, 0);
  557. setOTSADRS(ots_addr, idx);
  558. // Compute seed for OTS key pair
  559. get_seed(ots_seed, sk_seed, n, ots_addr);
  560. // Compute WOTS signature
  561. wots_sign(sig_msg, msg_h, ots_seed, &(params->wots_par), pub_seed, ots_addr);
  562. sig_msg += params->wots_par.keysize;
  563. *sig_msg_len += params->wots_par.keysize;
  564. // the auth path was already computed during the previous round
  565. memcpy(sig_msg, state->auth, h*n);
  566. if (idx < (1U << h) - 1) {
  567. bds_round(state, idx, sk_seed, params, pub_seed, ots_addr);
  568. bds_treehash_update(state, (h - k) >> 1, sk_seed, params, pub_seed, ots_addr);
  569. }
  570. sig_msg += params->h*n;
  571. *sig_msg_len += params->h*n;
  572. //Whipe secret elements?
  573. //zerobytes(tsk, CRYPTO_SECRETKEYBYTES);
  574. memcpy(sig_msg, msg, msglen);
  575. *sig_msg_len += msglen;
  576. return 0;
  577. }
  578. /**
  579. * Verifies a given message signature pair under a given public key.
  580. */
  581. int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params)
  582. {
  583. unsigned int n = params->n;
  584. unsigned long long i, m_len;
  585. unsigned long idx=0;
  586. unsigned char wots_pk[params->wots_par.keysize];
  587. unsigned char pkhash[n];
  588. unsigned char root[n];
  589. unsigned char msg_h[n];
  590. unsigned char hash_key[3*n];
  591. unsigned char pub_seed[n];
  592. memcpy(pub_seed, pk+n, n);
  593. // Init addresses
  594. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  595. uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  596. uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  597. setType(ots_addr, 0);
  598. setType(ltree_addr, 1);
  599. setType(node_addr, 2);
  600. // Extract index
  601. idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3];
  602. printf("verify:: idx = %lu\n", idx);
  603. // Generate hash key (R || root || idx)
  604. memcpy(hash_key, sig_msg+4,n);
  605. memcpy(hash_key+n, pk, n);
  606. to_byte(hash_key+2*n, idx, n);
  607. sig_msg += (n+4);
  608. sig_msg_len -= (n+4);
  609. // hash message
  610. unsigned long long tmp_sig_len = params->wots_par.keysize+params->h*n;
  611. m_len = sig_msg_len - tmp_sig_len;
  612. h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n);
  613. //-----------------------
  614. // Verify signature
  615. //-----------------------
  616. // Prepare Address
  617. setOTSADRS(ots_addr, idx);
  618. // Check WOTS signature
  619. wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->wots_par), pub_seed, ots_addr);
  620. sig_msg += params->wots_par.keysize;
  621. sig_msg_len -= params->wots_par.keysize;
  622. // Compute Ltree
  623. setLtreeADRS(ltree_addr, idx);
  624. l_tree(pkhash, wots_pk, params, pub_seed, ltree_addr);
  625. // Compute root
  626. validate_authpath(root, pkhash, idx, sig_msg, params, pub_seed, node_addr);
  627. sig_msg += params->h*n;
  628. sig_msg_len -= params->h*n;
  629. for (i = 0; i < n; i++)
  630. if (root[i] != pk[i])
  631. goto fail;
  632. *msglen = sig_msg_len;
  633. for (i = 0; i < *msglen; i++)
  634. msg[i] = sig_msg[i];
  635. return 0;
  636. fail:
  637. *msglen = sig_msg_len;
  638. for (i = 0; i < *msglen; i++)
  639. msg[i] = 0;
  640. *msglen = -1;
  641. return -1;
  642. }
  643. /*
  644. * Generates a XMSSMT key pair for a given parameter set.
  645. * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
  646. * Format pk: [root || PUB_SEED] omitting algo oid.
  647. */
  648. int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params)
  649. {
  650. unsigned int n = params->n;
  651. unsigned int i;
  652. unsigned char ots_seed[params->n];
  653. // Set idx = 0
  654. for (i = 0; i < params->index_len; i++) {
  655. sk[i] = 0;
  656. }
  657. // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte)
  658. randombytes(sk+params->index_len, 3*n);
  659. // Copy PUB_SEED to public key
  660. memcpy(pk+n, sk+params->index_len+2*n, n);
  661. // Set address to point on the single tree on layer d-1
  662. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  663. setLayerADRS(addr, (params->d-1));
  664. // Set up state and compute wots signatures for all but topmost tree root
  665. for (i = 0; i < params->d - 1; i++) {
  666. // Compute seed for OTS key pair
  667. treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr);
  668. setLayerADRS(addr, (i+1));
  669. get_seed(ots_seed, sk+params->index_len, n, addr);
  670. wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, pk, ots_seed, &(params->xmss_par.wots_par), pk+n, addr);
  671. }
  672. treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr);
  673. memcpy(sk+params->index_len+3*n, pk, n);
  674. return 0;
  675. }
  676. /**
  677. * Signs a message.
  678. * Returns
  679. * 1. an array containing the signature followed by the message AND
  680. * 2. an updated secret key!
  681. *
  682. */
  683. int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params)
  684. {
  685. unsigned int n = params->n;
  686. unsigned int tree_h = params->xmss_par.h;
  687. unsigned int h = params->h;
  688. unsigned int k = params->xmss_par.k;
  689. unsigned int idx_len = params->index_len;
  690. uint64_t idx_tree;
  691. uint32_t idx_leaf;
  692. uint64_t i, j;
  693. int needswap_upto = -1;
  694. unsigned int updates;
  695. unsigned char sk_seed[n];
  696. unsigned char sk_prf[n];
  697. unsigned char pub_seed[n];
  698. // Init working params
  699. unsigned char R[n];
  700. unsigned char msg_h[n];
  701. unsigned char hash_key[3*n];
  702. unsigned char ots_seed[n];
  703. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  704. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  705. unsigned char idx_bytes_32[32];
  706. bds_state tmp;
  707. // Extract SK
  708. unsigned long long idx = 0;
  709. for (i = 0; i < idx_len; i++) {
  710. idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - i);
  711. }
  712. memcpy(sk_seed, sk+idx_len, n);
  713. memcpy(sk_prf, sk+idx_len+n, n);
  714. memcpy(pub_seed, sk+idx_len+2*n, n);
  715. // Update SK
  716. for (i = 0; i < idx_len; i++) {
  717. sk[i] = ((idx + 1) >> 8*(idx_len - 1 - i)) & 255;
  718. }
  719. // -- Secret key for this non-forward-secure version is now updated.
  720. // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
  721. // ---------------------------------
  722. // Message Hashing
  723. // ---------------------------------
  724. // Message Hash:
  725. // First compute pseudorandom value
  726. to_byte(idx_bytes_32, idx, 32);
  727. prf(R, idx_bytes_32, sk_prf, n);
  728. // Generate hash key (R || root || idx)
  729. memcpy(hash_key, R, n);
  730. memcpy(hash_key+n, sk+idx_len+3*n, n);
  731. to_byte(hash_key+2*n, idx, n);
  732. // Then use it for message digest
  733. h_msg(msg_h, msg, msglen, hash_key, 3*n, n);
  734. // Start collecting signature
  735. *sig_msg_len = 0;
  736. // Copy index to signature
  737. for (i = 0; i < idx_len; i++) {
  738. sig_msg[i] = (idx >> 8*(idx_len - 1 - i)) & 255;
  739. }
  740. sig_msg += idx_len;
  741. *sig_msg_len += idx_len;
  742. // Copy R to signature
  743. for (i = 0; i < n; i++)
  744. sig_msg[i] = R[i];
  745. sig_msg += n;
  746. *sig_msg_len += n;
  747. // ----------------------------------
  748. // Now we start to "really sign"
  749. // ----------------------------------
  750. // Handle lowest layer separately as it is slightly different...
  751. // Prepare Address
  752. setType(ots_addr, 0);
  753. idx_tree = idx >> tree_h;
  754. idx_leaf = (idx & ((1 << tree_h)-1));
  755. setLayerADRS(ots_addr, 0);
  756. setTreeADRS(ots_addr, idx_tree);
  757. setOTSADRS(ots_addr, idx_leaf);
  758. // Compute seed for OTS key pair
  759. get_seed(ots_seed, sk_seed, n, ots_addr);
  760. // Compute WOTS signature
  761. wots_sign(sig_msg, msg_h, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr);
  762. sig_msg += params->xmss_par.wots_par.keysize;
  763. *sig_msg_len += params->xmss_par.wots_par.keysize;
  764. memcpy(sig_msg, states[0].auth, tree_h*n);
  765. sig_msg += tree_h*n;
  766. *sig_msg_len += tree_h*n;
  767. // prepare signature of remaining layers
  768. for (i = 1; i < params->d; i++) {
  769. // put WOTS signature in place
  770. memcpy(sig_msg, wots_sigs + (i-1)*params->xmss_par.wots_par.keysize, params->xmss_par.wots_par.keysize);
  771. sig_msg += params->xmss_par.wots_par.keysize;
  772. *sig_msg_len += params->xmss_par.wots_par.keysize;
  773. // put AUTH nodes in place
  774. memcpy(sig_msg, states[i].auth, tree_h*n);
  775. sig_msg += tree_h*n;
  776. *sig_msg_len += tree_h*n;
  777. }
  778. updates = (tree_h - k) >> 1;
  779. setTreeADRS(addr, (idx_tree + 1));
  780. // mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists
  781. if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << h)) {
  782. bds_state_update(&states[params->d], sk_seed, &(params->xmss_par), pub_seed, addr);
  783. }
  784. for (i = 0; i < params->d; i++) {
  785. // check if we're not at the end of a tree
  786. if (! (((idx + 1) & ((1ULL << ((i+1)*tree_h)) - 1)) == 0)) {
  787. idx_leaf = (idx >> (tree_h * i)) & ((1 << tree_h)-1);
  788. idx_tree = (idx >> (tree_h * (i+1)));
  789. setLayerADRS(addr, i);
  790. setTreeADRS(addr, idx_tree);
  791. if (i == (unsigned int) (needswap_upto + 1)) {
  792. bds_round(&states[i], idx_leaf, sk_seed, &(params->xmss_par), pub_seed, addr);
  793. }
  794. updates = bds_treehash_update(&states[i], updates, sk_seed, &(params->xmss_par), pub_seed, addr);
  795. setTreeADRS(addr, (idx_tree + 1));
  796. // if a NEXT-tree exists for this level;
  797. if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << (h - tree_h * i))) {
  798. if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << h)) {
  799. bds_state_update(&states[params->d + i], sk_seed, &(params->xmss_par), pub_seed, addr);
  800. updates--;
  801. }
  802. }
  803. }
  804. else if (idx < (1ULL << h) - 1) {
  805. memcpy(&tmp, states+params->d + i, sizeof(bds_state));
  806. memcpy(states+params->d + i, states + i, sizeof(bds_state));
  807. memcpy(states + i, &tmp, sizeof(bds_state));
  808. setLayerADRS(ots_addr, (i+1));
  809. setTreeADRS(ots_addr, ((idx + 1) >> ((i+2) * tree_h)));
  810. setOTSADRS(ots_addr, (((idx >> ((i+1) * tree_h)) + 1) & ((1 << tree_h)-1)));
  811. get_seed(ots_seed, sk+params->index_len, n, ots_addr);
  812. wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, states[i].stack, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr);
  813. states[params->d + i].stackoffset = 0;
  814. states[params->d + i].next_leaf = 0;
  815. updates--; // WOTS-signing counts as one update
  816. needswap_upto = i;
  817. for (j = 0; j < tree_h-k; j++) {
  818. states[i].treehash[j].completed = 1;
  819. }
  820. }
  821. }
  822. //Whipe secret elements?
  823. //zerobytes(tsk, CRYPTO_SECRETKEYBYTES);
  824. memcpy(sig_msg, msg, msglen);
  825. *sig_msg_len += msglen;
  826. return 0;
  827. }
  828. /**
  829. * Verifies a given message signature pair under a given public key.
  830. */
  831. int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params)
  832. {
  833. unsigned int n = params->n;
  834. unsigned int tree_h = params->xmss_par.h;
  835. unsigned int idx_len = params->index_len;
  836. uint64_t idx_tree;
  837. uint32_t idx_leaf;
  838. unsigned long long i, m_len;
  839. unsigned long long idx=0;
  840. unsigned char wots_pk[params->xmss_par.wots_par.keysize];
  841. unsigned char pkhash[n];
  842. unsigned char root[n];
  843. unsigned char msg_h[n];
  844. unsigned char hash_key[3*n];
  845. unsigned char pub_seed[n];
  846. memcpy(pub_seed, pk+n, n);
  847. // Init addresses
  848. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  849. uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  850. uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  851. // Extract index
  852. for (i = 0; i < idx_len; i++) {
  853. idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - i));
  854. }
  855. printf("verify:: idx = %llu\n", idx);
  856. sig_msg += idx_len;
  857. sig_msg_len -= idx_len;
  858. // Generate hash key (R || root || idx)
  859. memcpy(hash_key, sig_msg,n);
  860. memcpy(hash_key+n, pk, n);
  861. to_byte(hash_key+2*n, idx, n);
  862. sig_msg += n;
  863. sig_msg_len -= n;
  864. // hash message (recall, R is now on pole position at sig_msg
  865. unsigned long long tmp_sig_len = (params->d * params->xmss_par.wots_par.keysize) + (params->h * n);
  866. m_len = sig_msg_len - tmp_sig_len;
  867. h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n);
  868. //-----------------------
  869. // Verify signature
  870. //-----------------------
  871. // Prepare Address
  872. idx_tree = idx >> tree_h;
  873. idx_leaf = (idx & ((1 << tree_h)-1));
  874. setLayerADRS(ots_addr, 0);
  875. setTreeADRS(ots_addr, idx_tree);
  876. setType(ots_addr, 0);
  877. memcpy(ltree_addr, ots_addr, 12);
  878. setType(ltree_addr, 1);
  879. memcpy(node_addr, ltree_addr, 12);
  880. setType(node_addr, 2);
  881. setOTSADRS(ots_addr, idx_leaf);
  882. // Check WOTS signature
  883. wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->xmss_par.wots_par), pub_seed, ots_addr);
  884. sig_msg += params->xmss_par.wots_par.keysize;
  885. sig_msg_len -= params->xmss_par.wots_par.keysize;
  886. // Compute Ltree
  887. setLtreeADRS(ltree_addr, idx_leaf);
  888. l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr);
  889. // Compute root
  890. validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr);
  891. sig_msg += tree_h*n;
  892. sig_msg_len -= tree_h*n;
  893. for (i = 1; i < params->d; i++) {
  894. // Prepare Address
  895. idx_leaf = (idx_tree & ((1 << tree_h)-1));
  896. idx_tree = idx_tree >> tree_h;
  897. setLayerADRS(ots_addr, i);
  898. setTreeADRS(ots_addr, idx_tree);
  899. setType(ots_addr, 0);
  900. memcpy(ltree_addr, ots_addr, 12);
  901. setType(ltree_addr, 1);
  902. memcpy(node_addr, ltree_addr, 12);
  903. setType(node_addr, 2);
  904. setOTSADRS(ots_addr, idx_leaf);
  905. // Check WOTS signature
  906. wots_pkFromSig(wots_pk, sig_msg, root, &(params->xmss_par.wots_par), pub_seed, ots_addr);
  907. sig_msg += params->xmss_par.wots_par.keysize;
  908. sig_msg_len -= params->xmss_par.wots_par.keysize;
  909. // Compute Ltree
  910. setLtreeADRS(ltree_addr, idx_leaf);
  911. l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr);
  912. // Compute root
  913. validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr);
  914. sig_msg += tree_h*n;
  915. sig_msg_len -= tree_h*n;
  916. }
  917. for (i = 0; i < n; i++)
  918. if (root[i] != pk[i])
  919. goto fail;
  920. *msglen = sig_msg_len;
  921. for (i = 0; i < *msglen; i++)
  922. msg[i] = sig_msg[i];
  923. return 0;
  924. fail:
  925. *msglen = sig_msg_len;
  926. for (i = 0; i < *msglen; i++)
  927. msg[i] = 0;
  928. *msglen = -1;
  929. return -1;
  930. }