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.

806 lines
22 KiB

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