Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

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