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.

821 lines
22 KiB

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