Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

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