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.

1166 rader
34 KiB

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