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.

845 lines
23 KiB

  1. /*
  2. xmss.c version 20151120
  3. Andreas Hülsing
  4. Public domain.
  5. */
  6. #include "xmss.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) & 252);\
  24. a[5] = (a[5] & 252) | ((v >> 6) & 3);}
  25. #define SET_TREE_ADDRESS(a, v) {\
  26. a[9] = (a[9] & 3) | ((v << 2) & 252);\
  27. a[8] = (v >> 6) & 255;\
  28. a[7] = (v >> 14) & 255;\
  29. a[6] = (a[6] & 252) | ((v >> 22) & 3);}
  30. #define SET_OTS_BIT(a, b) {\
  31. a[9] = (a[9] & 253) | ((b << 1) & 2);}
  32. #define SET_OTS_ADDRESS(a, v) {\
  33. a[12] = (a[12] & 1) | ((v << 1) & 254);\
  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 & 1);}
  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) & 252);}
  50. #define SET_LTREE_TREE_INDEX(a, v) {\
  51. a[15] = (a[15] & 3) | ((v << 2) & 252);\
  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) & 252);\
  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) & 252);\
  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. * takes n byte sk_seed and returns n byte seed using 16 byte address addr.
  70. */
  71. static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, unsigned char addr[16])
  72. {
  73. // Make sure that chain addr, hash addr, and key bit are 0!
  74. ZEROISE_OTS_ADDR(addr);
  75. // Generate pseudorandom value
  76. prg_with_counter(seed, sk_seed, n, addr);
  77. }
  78. /**
  79. * Initialize xmss params struct
  80. * parameter names are the same as in the draft
  81. */
  82. void xmss_set_params(xmss_params *params, int m, int n, int h, int w)
  83. {
  84. params->h = h;
  85. params->m = m;
  86. params->n = n;
  87. wots_params wots_par;
  88. wots_set_params(&wots_par, m, n, w);
  89. params->wots_par = wots_par;
  90. }
  91. /**
  92. * Initialize xmssmt_params struct
  93. * parameter names are the same as in the draft
  94. *
  95. * Especially h is the total tree height, i.e. the XMSS trees have height h/d
  96. */
  97. void xmssmt_set_params(xmssmt_params *params, int m, int n, int h, int d, int w)
  98. {
  99. if (h % d) {
  100. fprintf(stderr, "d must devide h without remainder!\n");
  101. return;
  102. }
  103. params->h = h;
  104. params->d = d;
  105. params->m = m;
  106. params->n = n;
  107. params->index_len = (h + 7) / 8;
  108. xmss_params xmss_par;
  109. xmss_set_params(&xmss_par, m, n, (h/d), w);
  110. params->xmss_par = xmss_par;
  111. }
  112. /**
  113. * Computes a leaf from a WOTS public key using an L-tree.
  114. */
  115. static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, unsigned char addr[16])
  116. {
  117. unsigned int l = params->wots_par.len;
  118. unsigned int n = params->n;
  119. unsigned long i = 0;
  120. unsigned int height = 0;
  121. //ADRS.setTreeHeight(0);
  122. SET_LTREE_TREE_HEIGHT(addr, height);
  123. unsigned long bound;
  124. while (l > 1) {
  125. bound = l >> 1; //floor(l / 2);
  126. for (i = 0; i < bound; i++) {
  127. //ADRS.setTreeIndex(i);
  128. SET_LTREE_TREE_INDEX(addr, i);
  129. //wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS);
  130. hash_2n_n(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n);
  131. }
  132. //if ( l % 2 == 1 ) {
  133. if (l & 1) {
  134. //pk[floor(l / 2) + 1] = pk[l];
  135. memcpy(wots_pk+(l>>1)*n, wots_pk+(l-1)*n, n);
  136. //l = ceil(l / 2);
  137. l=(l>>1)+1;
  138. }
  139. else {
  140. //l = ceil(l / 2);
  141. l=(l>>1);
  142. }
  143. //ADRS.setTreeHeight(ADRS.getTreeHeight() + 1);
  144. height++;
  145. SET_LTREE_TREE_HEIGHT(addr, height);
  146. }
  147. //return pk[0];
  148. memcpy(leaf, wots_pk, n);
  149. }
  150. /**
  151. * 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.
  152. */
  153. 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])
  154. {
  155. unsigned char seed[params->n];
  156. unsigned char pk[params->wots_par.keysize];
  157. get_seed(seed, sk_seed, params->n, ots_addr);
  158. wots_pkgen(pk, seed, &(params->wots_par), pub_seed, ots_addr);
  159. l_tree(leaf, pk, params, pub_seed, ltree_addr);
  160. }
  161. /**
  162. * Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash.
  163. * Currently only used for key generation.
  164. *
  165. */
  166. static void treehash(unsigned char *node, int height, int index, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const unsigned char addr[16])
  167. {
  168. unsigned int idx = index;
  169. unsigned int n = params->n;
  170. // use three different addresses because at this point we use all three formats in parallel
  171. unsigned char ots_addr[16];
  172. unsigned char ltree_addr[16];
  173. unsigned char node_addr[16];
  174. memcpy(ots_addr, addr, 10);
  175. SET_OTS_BIT(ots_addr, 1);
  176. memcpy(ltree_addr, addr, 10);
  177. SET_OTS_BIT(ltree_addr, 0);
  178. SET_LTREE_BIT(ltree_addr, 1);
  179. memcpy(node_addr, ltree_addr, 10);
  180. SET_LTREE_BIT(node_addr, 0);
  181. SET_NODE_PADDING(node_addr);
  182. unsigned int lastnode, i;
  183. unsigned char stack[(height+1)*n];
  184. unsigned int stacklevels[height+1];
  185. unsigned int stackoffset=0;
  186. lastnode = idx+(1 << height);
  187. for (; idx < lastnode; idx++) {
  188. SET_LTREE_ADDRESS(ltree_addr, idx);
  189. SET_OTS_ADDRESS(ots_addr, idx);
  190. gen_leaf_wots(stack+stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr);
  191. stacklevels[stackoffset] = 0;
  192. stackoffset++;
  193. while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) {
  194. SET_NODE_TREE_HEIGHT(node_addr, stacklevels[stackoffset-1]);
  195. SET_NODE_TREE_INDEX(node_addr, (idx >> (stacklevels[stackoffset-1]+1)));
  196. hash_2n_n(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed,
  197. node_addr, n);
  198. stacklevels[stackoffset-2]++;
  199. stackoffset--;
  200. }
  201. }
  202. for (i=0; i < n; i++)
  203. node[i] = stack[i];
  204. }
  205. /**
  206. * Computes a root node given a leaf and an authapth
  207. */
  208. 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])
  209. {
  210. unsigned int n = params->n;
  211. unsigned int i, j;
  212. unsigned char buffer[2*n];
  213. // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left.
  214. // Otherwise, it is the other way around
  215. if (leafidx & 1) {
  216. for (j = 0; j < n; j++)
  217. buffer[n+j] = leaf[j];
  218. for (j = 0; j < n; j++)
  219. buffer[j] = authpath[j];
  220. }
  221. else {
  222. for (j = 0; j < n; j++)
  223. buffer[j] = leaf[j];
  224. for (j = 0; j < n; j++)
  225. buffer[n+j] = authpath[j];
  226. }
  227. authpath += n;
  228. for (i=0; i < params->h-1; i++) {
  229. SET_NODE_TREE_HEIGHT(addr, i);
  230. leafidx >>= 1;
  231. SET_NODE_TREE_INDEX(addr, leafidx);
  232. if (leafidx&1) {
  233. hash_2n_n(buffer+n, buffer, pub_seed, addr, n);
  234. for (j = 0; j < n; j++)
  235. buffer[j] = authpath[j];
  236. }
  237. else {
  238. hash_2n_n(buffer, buffer, pub_seed, addr, n);
  239. for (j = 0; j < n; j++)
  240. buffer[j+n] = authpath[j];
  241. }
  242. authpath += n;
  243. }
  244. SET_NODE_TREE_HEIGHT(addr, (params->h-1));
  245. leafidx >>= 1;
  246. SET_NODE_TREE_INDEX(addr, leafidx);
  247. hash_2n_n(root, buffer, pub_seed, addr, n);
  248. }
  249. /**
  250. * Computes the authpath and the root. This method is using a lot of space as we build the whole tree and then select the authpath nodes.
  251. * For more efficient algorithms see e.g. the chapter on hash-based signatures in Bernstein, Buchmann, Dahmen. "Post-quantum Cryptography", Springer 2009.
  252. * It returns the authpath in "authpath" with the node on level 0 at index 0.
  253. */
  254. static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, unsigned char addr[16])
  255. {
  256. unsigned int i, j, level;
  257. unsigned int n = params->n;
  258. unsigned int h = params->h;
  259. unsigned char tree[2*(1<<h)*n];
  260. unsigned char ots_addr[16];
  261. unsigned char ltree_addr[16];
  262. unsigned char node_addr[16];
  263. memcpy(ots_addr, addr, 10);
  264. SET_OTS_BIT(ots_addr, 1);
  265. memcpy(ltree_addr, addr, 10);
  266. SET_OTS_BIT(ltree_addr, 0);
  267. SET_LTREE_BIT(ltree_addr, 1);
  268. memcpy(node_addr, ltree_addr, 10);
  269. SET_LTREE_BIT(node_addr, 0);
  270. SET_NODE_PADDING(node_addr);
  271. // Compute all leaves
  272. for (i = 0; i < (1U << h); i++) {
  273. SET_LTREE_ADDRESS(ltree_addr, i);
  274. SET_OTS_ADDRESS(ots_addr, i);
  275. gen_leaf_wots(tree+((1<<h)*n + i*n), sk_seed, params, pub_seed, ltree_addr, ots_addr);
  276. }
  277. level = 0;
  278. // Compute tree:
  279. // Outer loop: For each inner layer
  280. for (i = (1<<h); i > 1; i>>=1) {
  281. SET_NODE_TREE_HEIGHT(node_addr, level);
  282. // Inner loop: for each pair of sibling nodes
  283. for (j = 0; j < i; j+=2) {
  284. SET_NODE_TREE_INDEX(node_addr, j>>1);
  285. hash_2n_n(tree + (i>>1)*n + (j>>1) * n, tree + i*n + j*n, pub_seed, node_addr, n);
  286. }
  287. level++;
  288. }
  289. // copy authpath
  290. for (i=0; i < h; i++)
  291. memcpy(authpath + i*n, tree + ((1<<h)>>i)*n + ((leaf_idx >> i) ^ 1) * n, n);
  292. // copy root
  293. memcpy(root, tree+n, n);
  294. }
  295. /*
  296. * Generates a XMSS key pair for a given parameter set.
  297. * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED]
  298. * Format pk: [root || PUB_SEED] omitting algo oid.
  299. */
  300. int xmss_keypair(unsigned char *pk, unsigned char *sk, xmss_params *params)
  301. {
  302. unsigned int n = params->n;
  303. unsigned int m = params->m;
  304. // Set idx = 0
  305. sk[0] = 0;
  306. sk[1] = 0;
  307. sk[2] = 0;
  308. sk[3] = 0;
  309. // Init SK_SEED (n byte), SK_PRF (m byte), and PUB_SEED (n byte)
  310. randombytes(sk+4, 2*n+m);
  311. // Copy PUB_SEED to public key
  312. memcpy(pk+n, sk+4+n+m, n);
  313. unsigned char addr[16] = {0, 0, 0, 0};
  314. // Compute root
  315. treehash(pk, params->h, 0, sk+4, params, sk+4+n+m, addr);
  316. return 0;
  317. }
  318. /**
  319. * Signs a message.
  320. * Returns
  321. * 1. an array containing the signature followed by the message AND
  322. * 2. an updated secret key!
  323. *
  324. */
  325. int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmss_params *params)
  326. {
  327. unsigned int n = params->n;
  328. unsigned int m = params->m;
  329. // Extract SK
  330. unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3];
  331. unsigned char sk_seed[n];
  332. memcpy(sk_seed, sk+4, n);
  333. unsigned char sk_prf[m];
  334. memcpy(sk_prf, sk+4+n, m);
  335. unsigned char pub_seed[n];
  336. memcpy(pub_seed, sk+4+n+m, n);
  337. // Update SK
  338. sk[0] = ((idx + 1) >> 24) & 255;
  339. sk[1] = ((idx + 1) >> 16) & 255;
  340. sk[2] = ((idx + 1) >> 8) & 255;
  341. sk[3] = (idx + 1) & 255;
  342. // -- Secret key for this non-forward-secure version is now updated.
  343. // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
  344. // Init working params
  345. unsigned long long i;
  346. unsigned char R[m];
  347. unsigned char msg_h[m];
  348. unsigned char root[n];
  349. unsigned char ots_seed[n];
  350. unsigned char ots_addr[16] = {0, 0, 0, 0};
  351. // ---------------------------------
  352. // Message Hashing
  353. // ---------------------------------
  354. // Message Hash:
  355. // First compute pseudorandom key
  356. prf_m(R, msg, msglen, sk_prf, m);
  357. // Then use it for message digest
  358. hash_m(msg_h, msg, msglen, R, m, m);
  359. // Start collecting signature
  360. *sig_msg_len = 0;
  361. // Copy index to signature
  362. sig_msg[0] = (idx >> 24) & 255;
  363. sig_msg[1] = (idx >> 16) & 255;
  364. sig_msg[2] = (idx >> 8) & 255;
  365. sig_msg[3] = idx & 255;
  366. sig_msg += 4;
  367. *sig_msg_len += 4;
  368. // Copy R to signature
  369. for (i = 0; i < m; i++)
  370. sig_msg[i] = R[i];
  371. sig_msg += m;
  372. *sig_msg_len += m;
  373. // ----------------------------------
  374. // Now we start to "really sign"
  375. // ----------------------------------
  376. // Prepare Address
  377. SET_OTS_BIT(ots_addr, 1);
  378. SET_OTS_ADDRESS(ots_addr, idx);
  379. // Compute seed for OTS key pair
  380. get_seed(ots_seed, sk_seed, n, ots_addr);
  381. // Compute WOTS signature
  382. wots_sign(sig_msg, msg_h, ots_seed, &(params->wots_par), pub_seed, ots_addr);
  383. sig_msg += params->wots_par.keysize;
  384. *sig_msg_len += params->wots_par.keysize;
  385. compute_authpath_wots(root, sig_msg, idx, sk_seed, params, pub_seed, ots_addr);
  386. sig_msg += params->h*n;
  387. *sig_msg_len += params->h*n;
  388. //Whipe secret elements?
  389. //zerobytes(tsk, CRYPTO_SECRETKEYBYTES);
  390. memcpy(sig_msg, msg, msglen);
  391. *sig_msg_len += msglen;
  392. return 0;
  393. }
  394. /**
  395. * Verifies a given message signature pair under a given public key.
  396. */
  397. 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)
  398. {
  399. unsigned int n = params->n;
  400. unsigned int m = params->m;
  401. unsigned long long i, m_len;
  402. unsigned long idx=0;
  403. unsigned char wots_pk[params->wots_par.keysize];
  404. unsigned char pkhash[n];
  405. unsigned char root[n];
  406. unsigned char msg_h[m];
  407. unsigned char pub_seed[n];
  408. memcpy(pub_seed, pk+n, n);
  409. // Init addresses
  410. unsigned char ots_addr[16] = {0, 0, 0, 0};
  411. unsigned char ltree_addr[16];
  412. unsigned char node_addr[16];
  413. SET_OTS_BIT(ots_addr, 1);
  414. memcpy(ltree_addr, ots_addr, 10);
  415. SET_OTS_BIT(ltree_addr, 0);
  416. SET_LTREE_BIT(ltree_addr, 1);
  417. memcpy(node_addr, ltree_addr, 10);
  418. SET_LTREE_BIT(node_addr, 0);
  419. SET_NODE_PADDING(node_addr);
  420. // Extract index
  421. idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3];
  422. printf("verify:: idx = %lu\n", idx);
  423. sig_msg += 4;
  424. sig_msg_len -= 4;
  425. // hash message (recall, R is now on pole position at sig_msg
  426. unsigned long long tmp_sig_len = m+params->wots_par.keysize+params->h*n;
  427. m_len = sig_msg_len - tmp_sig_len;
  428. hash_m(msg_h, sig_msg + tmp_sig_len, m_len, sig_msg, m, m);
  429. sig_msg += m;
  430. sig_msg_len -= m;
  431. //-----------------------
  432. // Verify signature
  433. //-----------------------
  434. // Prepare Address
  435. SET_OTS_ADDRESS(ots_addr, idx);
  436. // Check WOTS signature
  437. wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->wots_par), pub_seed, ots_addr);
  438. sig_msg += params->wots_par.keysize;
  439. sig_msg_len -= params->wots_par.keysize;
  440. // Compute Ltree
  441. SET_LTREE_ADDRESS(ltree_addr, idx);
  442. l_tree(pkhash, wots_pk, params, pub_seed, ltree_addr);
  443. // Compute root
  444. validate_authpath(root, pkhash, idx, sig_msg, params, pub_seed, node_addr);
  445. sig_msg += params->h*n;
  446. sig_msg_len -= params->h*n;
  447. for (i=0; i < n; i++)
  448. if (root[i] != pk[i])
  449. goto fail;
  450. *msglen = sig_msg_len;
  451. for (i=0; i < *msglen; i++)
  452. msg[i] = sig_msg[i];
  453. return 0;
  454. fail:
  455. *msglen = sig_msg_len;
  456. for (i=0; i < *msglen; i++)
  457. msg[i] = 0;
  458. *msglen = -1;
  459. return -1;
  460. }
  461. /*
  462. * Generates a XMSSMT key pair for a given parameter set.
  463. * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED]
  464. * Format pk: [root || PUB_SEED] omitting algo oid.
  465. */
  466. int xmssmt_keypair(unsigned char *pk, unsigned char *sk, xmssmt_params *params)
  467. {
  468. unsigned int n = params->n;
  469. unsigned int m = params->m;
  470. unsigned int i;
  471. // Set idx = 0
  472. for (i = 0; i < params->index_len; i++) {
  473. sk[i] = 0;
  474. }
  475. // Init SK_SEED (n byte), SK_PRF (m byte), and PUB_SEED (n byte)
  476. randombytes(sk+params->index_len, 2*n+m);
  477. // Copy PUB_SEED to public key
  478. memcpy(pk+n, sk+params->index_len+n+m, n);
  479. // Set address to point on the single tree on layer d-1
  480. unsigned char addr[16] = {0, 0, 0, 0};
  481. SET_LAYER_ADDRESS(addr, (params->d-1));
  482. // Compute root
  483. treehash(pk, params->xmss_par.h, 0, sk+params->index_len, &(params->xmss_par), pk+n, addr);
  484. return 0;
  485. }
  486. /**
  487. * Signs a message.
  488. * Returns
  489. * 1. an array containing the signature followed by the message AND
  490. * 2. an updated secret key!
  491. *
  492. */
  493. int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params)
  494. {
  495. unsigned int n = params->n;
  496. unsigned int m = params->m;
  497. unsigned int tree_h = params->xmss_par.h;
  498. unsigned int idx_len = params->index_len;
  499. unsigned long long idx_tree;
  500. unsigned long long idx_leaf;
  501. unsigned long long i;
  502. unsigned char sk_seed[n];
  503. unsigned char sk_prf[m];
  504. unsigned char pub_seed[n];
  505. // Init working params
  506. unsigned char R[m];
  507. unsigned char msg_h[m];
  508. unsigned char root[n];
  509. unsigned char ots_seed[n];
  510. unsigned char ots_addr[16] = {0, 0, 0, 0};
  511. // Extract SK
  512. unsigned long long idx = 0;
  513. for (i = 0; i < idx_len; i++) {
  514. idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - i);
  515. }
  516. memcpy(sk_seed, sk+idx_len, n);
  517. memcpy(sk_prf, sk+idx_len+n, m);
  518. memcpy(pub_seed, sk+idx_len+n+m, n);
  519. // Update SK
  520. for (i = 0; i < idx_len; i++) {
  521. sk[i] = ((idx + 1) >> 8*(idx_len - 1 - i)) & 255;
  522. }
  523. // -- Secret key for this non-forward-secure version is now updated.
  524. // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
  525. // ---------------------------------
  526. // Message Hashing
  527. // ---------------------------------
  528. // Message Hash:
  529. // First compute pseudorandom key
  530. prf_m(R, msg, msglen, sk_prf, m);
  531. // Then use it for message digest
  532. hash_m(msg_h, msg, msglen, R, m, m);
  533. // Start collecting signature
  534. *sig_msg_len = 0;
  535. // Copy index to signature
  536. for (i = 0; i < idx_len; i++) {
  537. sig_msg[i] = (idx >> 8*(idx_len - 1 - i)) & 255;
  538. }
  539. sig_msg += idx_len;
  540. *sig_msg_len += idx_len;
  541. // Copy R to signature
  542. for (i=0; i < m; i++)
  543. sig_msg[i] = R[i];
  544. sig_msg += m;
  545. *sig_msg_len += m;
  546. // ----------------------------------
  547. // Now we start to "really sign"
  548. // ----------------------------------
  549. // Handle lowest layer separately as it is slightly different...
  550. // Prepare Address
  551. SET_OTS_BIT(ots_addr, 1);
  552. idx_tree = idx >> tree_h;
  553. idx_leaf = (idx & ((1 << tree_h)-1));
  554. SET_LAYER_ADDRESS(ots_addr, 0);
  555. SET_TREE_ADDRESS(ots_addr, idx_tree);
  556. SET_OTS_ADDRESS(ots_addr, idx_leaf);
  557. // Compute seed for OTS key pair
  558. get_seed(ots_seed, sk_seed, n, ots_addr);
  559. // Compute WOTS signature
  560. wots_sign(sig_msg, msg_h, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr);
  561. sig_msg += params->xmss_par.wots_par.keysize;
  562. *sig_msg_len += params->xmss_par.wots_par.keysize;
  563. compute_authpath_wots(root, sig_msg, idx_leaf, sk_seed, &(params->xmss_par), pub_seed, ots_addr);
  564. sig_msg += tree_h*n;
  565. *sig_msg_len += tree_h*n;
  566. // Now loop over remaining layers...
  567. unsigned int j;
  568. for (j = 1; j < params->d; j++) {
  569. // Prepare Address
  570. idx_leaf = (idx_tree & ((1 << tree_h)-1));
  571. idx_tree = idx_tree >> tree_h;
  572. SET_LAYER_ADDRESS(ots_addr, j);
  573. SET_TREE_ADDRESS(ots_addr, idx_tree);
  574. SET_OTS_ADDRESS(ots_addr, idx_leaf);
  575. // Compute seed for OTS key pair
  576. get_seed(ots_seed, sk_seed, n, ots_addr);
  577. // Compute WOTS signature
  578. wots_sign(sig_msg, root, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr);
  579. sig_msg += params->xmss_par.wots_par.keysize;
  580. *sig_msg_len += params->xmss_par.wots_par.keysize;
  581. compute_authpath_wots(root, sig_msg, idx_leaf, sk_seed, &(params->xmss_par), pub_seed, ots_addr);
  582. sig_msg += tree_h*n;
  583. *sig_msg_len += tree_h*n;
  584. }
  585. //Whipe secret elements?
  586. //zerobytes(tsk, CRYPTO_SECRETKEYBYTES);
  587. memcpy(sig_msg, msg, msglen);
  588. *sig_msg_len += msglen;
  589. return 0;
  590. }
  591. /**
  592. * Verifies a given message signature pair under a given public key.
  593. */
  594. 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)
  595. {
  596. unsigned int n = params->n;
  597. unsigned int m = params->m;
  598. unsigned int tree_h = params->xmss_par.h;
  599. unsigned int idx_len = params->index_len;
  600. unsigned long long idx_tree;
  601. unsigned long long idx_leaf;
  602. unsigned long long i, m_len;
  603. unsigned long long idx=0;
  604. unsigned char wots_pk[params->xmss_par.wots_par.keysize];
  605. unsigned char pkhash[n];
  606. unsigned char root[n];
  607. unsigned char msg_h[m];
  608. unsigned char pub_seed[n];
  609. memcpy(pub_seed, pk+n, n);
  610. // Init addresses
  611. unsigned char ots_addr[16] = {0, 0, 0, 0};
  612. unsigned char ltree_addr[16];
  613. unsigned char node_addr[16];
  614. // Extract index
  615. for (i = 0; i < idx_len; i++) {
  616. idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - i));
  617. }
  618. printf("verify:: idx = %llu\n", idx);
  619. sig_msg += idx_len;
  620. sig_msg_len -= idx_len;
  621. // hash message (recall, R is now on pole position at sig_msg
  622. unsigned long long tmp_sig_len = m+ (params->d * params->xmss_par.wots_par.keysize) + (params->h * n);
  623. m_len = sig_msg_len - tmp_sig_len;
  624. hash_m(msg_h, sig_msg + tmp_sig_len, m_len, sig_msg, m, m);
  625. sig_msg += m;
  626. sig_msg_len -= m;
  627. //-----------------------
  628. // Verify signature
  629. //-----------------------
  630. // Prepare Address
  631. idx_tree = idx >> tree_h;
  632. idx_leaf = (idx & ((1 << tree_h)-1));
  633. SET_LAYER_ADDRESS(ots_addr, 0);
  634. SET_TREE_ADDRESS(ots_addr, idx_tree);
  635. SET_OTS_BIT(ots_addr, 1);
  636. memcpy(ltree_addr, ots_addr, 10);
  637. SET_OTS_BIT(ltree_addr, 0);
  638. SET_LTREE_BIT(ltree_addr, 1);
  639. memcpy(node_addr, ltree_addr, 10);
  640. SET_LTREE_BIT(node_addr, 0);
  641. SET_NODE_PADDING(node_addr);
  642. SET_OTS_ADDRESS(ots_addr, idx_leaf);
  643. // Check WOTS signature
  644. wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->xmss_par.wots_par), pub_seed, ots_addr);
  645. sig_msg += params->xmss_par.wots_par.keysize;
  646. sig_msg_len -= params->xmss_par.wots_par.keysize;
  647. // Compute Ltree
  648. SET_LTREE_ADDRESS(ltree_addr, idx_leaf);
  649. l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr);
  650. // Compute root
  651. validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr);
  652. sig_msg += tree_h*n;
  653. sig_msg_len -= tree_h*n;
  654. for (i = 1; i < params->d; i++) {
  655. // Prepare Address
  656. idx_leaf = (idx_tree & ((1 << tree_h)-1));
  657. idx_tree = idx_tree >> tree_h;
  658. SET_LAYER_ADDRESS(ots_addr, i);
  659. SET_TREE_ADDRESS(ots_addr, idx_tree);
  660. SET_OTS_BIT(ots_addr, 1);
  661. memcpy(ltree_addr, ots_addr, 10);
  662. SET_OTS_BIT(ltree_addr, 0);
  663. SET_LTREE_BIT(ltree_addr, 1);
  664. memcpy(node_addr, ltree_addr, 10);
  665. SET_LTREE_BIT(node_addr, 0);
  666. SET_NODE_PADDING(node_addr);
  667. SET_OTS_ADDRESS(ots_addr, idx_leaf);
  668. // Check WOTS signature
  669. wots_pkFromSig(wots_pk, sig_msg, root, &(params->xmss_par.wots_par), pub_seed, ots_addr);
  670. sig_msg += params->xmss_par.wots_par.keysize;
  671. sig_msg_len -= params->xmss_par.wots_par.keysize;
  672. // Compute Ltree
  673. SET_LTREE_ADDRESS(ltree_addr, idx_leaf);
  674. l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr);
  675. // Compute root
  676. validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr);
  677. sig_msg += tree_h*n;
  678. sig_msg_len -= tree_h*n;
  679. }
  680. for (i=0; i < n; i++)
  681. if (root[i] != pk[i])
  682. goto fail;
  683. *msglen = sig_msg_len;
  684. for (i=0; i < *msglen; i++)
  685. msg[i] = sig_msg[i];
  686. return 0;
  687. fail:
  688. *msglen = sig_msg_len;
  689. for (i=0; i < *msglen; i++)
  690. msg[i] = 0;
  691. *msglen = -1;
  692. return -1;
  693. }