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.

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