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.

858 lines
23 KiB

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