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.

366 lines
9.5 KiB

  1. /*
  2. xmss_commons.c 20160722
  3. Andreas Hülsing
  4. Joost Rijneveld
  5. Public domain.
  6. */
  7. #include "xmss_commons.h"
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include <stdint.h>
  12. #include "wots.h"
  13. #include "hash.h"
  14. #include "hash_address.h"
  15. #include "params.h"
  16. void to_byte(unsigned char *out, unsigned long long in, uint32_t bytes)
  17. {
  18. int32_t i;
  19. for (i = bytes-1; i >= 0; i--) {
  20. out[i] = in & 0xff;
  21. in = in >> 8;
  22. }
  23. }
  24. /**
  25. * 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.
  26. */
  27. 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])
  28. {
  29. unsigned char seed[XMSS_N];
  30. unsigned char pk[XMSS_WOTS_KEYSIZE];
  31. get_seed(seed, sk_seed, ots_addr);
  32. wots_pkgen(pk, seed, pub_seed, ots_addr);
  33. l_tree(leaf, pk, pub_seed, ltree_addr);
  34. }
  35. /**
  36. * Used for pseudorandom keygeneration,
  37. * generates the seed for the WOTS keypair at address addr
  38. *
  39. * takes XMSS_N byte sk_seed and returns XMSS_N byte seed using 32 byte address addr.
  40. */
  41. void get_seed(unsigned char *seed, const unsigned char *sk_seed, uint32_t addr[8])
  42. {
  43. unsigned char bytes[32];
  44. // Make sure that chain addr, hash addr, and key bit are 0!
  45. setChainADRS(addr, 0);
  46. setHashADRS(addr, 0);
  47. setKeyAndMask(addr, 0);
  48. // Generate pseudorandom value
  49. addr_to_byte(bytes, addr);
  50. prf(seed, bytes, sk_seed, XMSS_N);
  51. }
  52. /**
  53. * Computes a leaf from a WOTS public key using an L-tree.
  54. */
  55. void l_tree(unsigned char *leaf, unsigned char *wots_pk, const unsigned char *pub_seed, uint32_t addr[8])
  56. {
  57. unsigned int l = XMSS_WOTS_LEN;
  58. uint32_t i = 0;
  59. uint32_t height = 0;
  60. uint32_t bound;
  61. //ADRS.setTreeHeight(0);
  62. setTreeHeight(addr, height);
  63. while (l > 1) {
  64. bound = l >> 1; //floor(l / 2);
  65. for (i = 0; i < bound; i++) {
  66. //ADRS.setTreeIndex(i);
  67. setTreeIndex(addr, i);
  68. //wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS);
  69. hash_h(wots_pk+i*XMSS_N, wots_pk+i*2*XMSS_N, pub_seed, addr, XMSS_N);
  70. }
  71. //if ( l % 2 == 1 ) {
  72. if (l & 1) {
  73. //pk[floor(l / 2) + 1] = pk[l];
  74. memcpy(wots_pk+(l>>1)*XMSS_N, wots_pk+(l-1)*XMSS_N, XMSS_N);
  75. //l = ceil(l / 2);
  76. l=(l>>1)+1;
  77. }
  78. else {
  79. //l = ceil(l / 2);
  80. l=(l>>1);
  81. }
  82. //ADRS.setTreeHeight(ADRS.getTreeHeight() + 1);
  83. height++;
  84. setTreeHeight(addr, height);
  85. }
  86. //return pk[0];
  87. memcpy(leaf, wots_pk, XMSS_N);
  88. }
  89. /**
  90. * Computes a root node given a leaf and an authapth
  91. */
  92. 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])
  93. {
  94. uint32_t i, j;
  95. unsigned char buffer[2*XMSS_N];
  96. // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left.
  97. // Otherwise, it is the other way around
  98. if (leafidx & 1) {
  99. for (j = 0; j < XMSS_N; j++)
  100. buffer[XMSS_N+j] = leaf[j];
  101. for (j = 0; j < XMSS_N; j++)
  102. buffer[j] = authpath[j];
  103. }
  104. else {
  105. for (j = 0; j < XMSS_N; j++)
  106. buffer[j] = leaf[j];
  107. for (j = 0; j < XMSS_N; j++)
  108. buffer[XMSS_N+j] = authpath[j];
  109. }
  110. authpath += XMSS_N;
  111. for (i=0; i < XMSS_TREEHEIGHT-1; i++) {
  112. setTreeHeight(addr, i);
  113. leafidx >>= 1;
  114. setTreeIndex(addr, leafidx);
  115. if (leafidx&1) {
  116. hash_h(buffer+XMSS_N, buffer, pub_seed, addr, XMSS_N);
  117. for (j = 0; j < XMSS_N; j++)
  118. buffer[j] = authpath[j];
  119. }
  120. else {
  121. hash_h(buffer, buffer, pub_seed, addr, XMSS_N);
  122. for (j = 0; j < XMSS_N; j++)
  123. buffer[j+XMSS_N] = authpath[j];
  124. }
  125. authpath += XMSS_N;
  126. }
  127. setTreeHeight(addr, (XMSS_TREEHEIGHT-1));
  128. leafidx >>= 1;
  129. setTreeIndex(addr, leafidx);
  130. hash_h(root, buffer, pub_seed, addr, XMSS_N);
  131. }
  132. /**
  133. * Verifies a given message signature pair under a given public key.
  134. */
  135. 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)
  136. {
  137. unsigned long long i, m_len;
  138. unsigned long idx=0;
  139. unsigned char wots_pk[XMSS_WOTS_KEYSIZE];
  140. unsigned char pkhash[XMSS_N];
  141. unsigned char root[XMSS_N];
  142. unsigned char msg_h[XMSS_N];
  143. unsigned char hash_key[3*XMSS_N];
  144. unsigned char pub_seed[XMSS_N];
  145. memcpy(pub_seed, pk+XMSS_N, XMSS_N);
  146. // Init addresses
  147. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  148. uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  149. uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  150. setType(ots_addr, 0);
  151. setType(ltree_addr, 1);
  152. setType(node_addr, 2);
  153. // Extract index
  154. idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3];
  155. printf("verify:: idx = %lu\n", idx);
  156. // Generate hash key (R || root || idx)
  157. memcpy(hash_key, sig_msg+4,XMSS_N);
  158. memcpy(hash_key+XMSS_N, pk, XMSS_N);
  159. to_byte(hash_key+2*XMSS_N, idx, XMSS_N);
  160. sig_msg += (XMSS_N+4);
  161. sig_msg_len -= (XMSS_N+4);
  162. // hash message
  163. unsigned long long tmp_sig_len = XMSS_WOTS_KEYSIZE+XMSS_TREEHEIGHT*XMSS_N;
  164. m_len = sig_msg_len - tmp_sig_len;
  165. h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*XMSS_N, XMSS_N);
  166. //-----------------------
  167. // Verify signature
  168. //-----------------------
  169. // Prepare Address
  170. setOTSADRS(ots_addr, idx);
  171. // Check WOTS signature
  172. wots_pkFromSig(wots_pk, sig_msg, msg_h, pub_seed, ots_addr);
  173. sig_msg += XMSS_WOTS_KEYSIZE;
  174. sig_msg_len -= XMSS_WOTS_KEYSIZE;
  175. // Compute Ltree
  176. setLtreeADRS(ltree_addr, idx);
  177. l_tree(pkhash, wots_pk, pub_seed, ltree_addr);
  178. // Compute root
  179. validate_authpath(root, pkhash, idx, sig_msg, pub_seed, node_addr);
  180. sig_msg += XMSS_TREEHEIGHT*XMSS_N;
  181. sig_msg_len -= XMSS_TREEHEIGHT*XMSS_N;
  182. for (i=0; i < XMSS_N; i++)
  183. if (root[i] != pk[i])
  184. goto fail;
  185. *msglen = sig_msg_len;
  186. for (i=0; i < *msglen; i++)
  187. msg[i] = sig_msg[i];
  188. return 0;
  189. fail:
  190. *msglen = sig_msg_len;
  191. for (i=0; i < *msglen; i++)
  192. msg[i] = 0;
  193. *msglen = -1;
  194. return -1;
  195. }
  196. /**
  197. * Verifies a given message signature pair under a given public key.
  198. */
  199. 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)
  200. {
  201. uint64_t idx_tree;
  202. uint32_t idx_leaf;
  203. unsigned long long i, m_len;
  204. unsigned long long idx=0;
  205. unsigned char wots_pk[XMSS_WOTS_KEYSIZE];
  206. unsigned char pkhash[XMSS_N];
  207. unsigned char root[XMSS_N];
  208. unsigned char msg_h[XMSS_N];
  209. unsigned char hash_key[3*XMSS_N];
  210. unsigned char pub_seed[XMSS_N];
  211. memcpy(pub_seed, pk+XMSS_N, XMSS_N);
  212. // Init addresses
  213. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  214. uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  215. uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  216. // Extract index
  217. for (i = 0; i < XMSS_INDEX_LEN; i++) {
  218. idx |= ((unsigned long long)sig_msg[i]) << (8*(XMSS_INDEX_LEN - 1 - i));
  219. }
  220. printf("verify:: idx = %llu\n", idx);
  221. sig_msg += XMSS_INDEX_LEN;
  222. sig_msg_len -= XMSS_INDEX_LEN;
  223. // Generate hash key (R || root || idx)
  224. memcpy(hash_key, sig_msg,XMSS_N);
  225. memcpy(hash_key+XMSS_N, pk, XMSS_N);
  226. to_byte(hash_key+2*XMSS_N, idx, XMSS_N);
  227. sig_msg += XMSS_N;
  228. sig_msg_len -= XMSS_N;
  229. // hash message
  230. unsigned long long tmp_sig_len = (XMSS_D * XMSS_WOTS_KEYSIZE) + (XMSS_FULLHEIGHT * XMSS_N);
  231. m_len = sig_msg_len - tmp_sig_len;
  232. h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*XMSS_N, XMSS_N);
  233. //-----------------------
  234. // Verify signature
  235. //-----------------------
  236. // Prepare Address
  237. idx_tree = idx >> XMSS_TREEHEIGHT;
  238. idx_leaf = (idx & ((1 << XMSS_TREEHEIGHT)-1));
  239. setLayerADRS(ots_addr, 0);
  240. setTreeADRS(ots_addr, idx_tree);
  241. setType(ots_addr, 0);
  242. memcpy(ltree_addr, ots_addr, 12);
  243. setType(ltree_addr, 1);
  244. memcpy(node_addr, ltree_addr, 12);
  245. setType(node_addr, 2);
  246. setOTSADRS(ots_addr, idx_leaf);
  247. // Check WOTS signature
  248. wots_pkFromSig(wots_pk, sig_msg, msg_h, pub_seed, ots_addr);
  249. sig_msg += XMSS_WOTS_KEYSIZE;
  250. sig_msg_len -= XMSS_WOTS_KEYSIZE;
  251. // Compute Ltree
  252. setLtreeADRS(ltree_addr, idx_leaf);
  253. l_tree(pkhash, wots_pk, pub_seed, ltree_addr);
  254. // Compute root
  255. validate_authpath(root, pkhash, idx_leaf, sig_msg, pub_seed, node_addr);
  256. sig_msg += XMSS_TREEHEIGHT*XMSS_N;
  257. sig_msg_len -= XMSS_TREEHEIGHT*XMSS_N;
  258. for (i = 1; i < XMSS_D; i++) {
  259. // Prepare Address
  260. idx_leaf = (idx_tree & ((1 << XMSS_TREEHEIGHT)-1));
  261. idx_tree = idx_tree >> XMSS_TREEHEIGHT;
  262. setLayerADRS(ots_addr, i);
  263. setTreeADRS(ots_addr, idx_tree);
  264. setType(ots_addr, 0);
  265. memcpy(ltree_addr, ots_addr, 12);
  266. setType(ltree_addr, 1);
  267. memcpy(node_addr, ltree_addr, 12);
  268. setType(node_addr, 2);
  269. setOTSADRS(ots_addr, idx_leaf);
  270. // Check WOTS signature
  271. wots_pkFromSig(wots_pk, sig_msg, root, pub_seed, ots_addr);
  272. sig_msg += XMSS_WOTS_KEYSIZE;
  273. sig_msg_len -= XMSS_WOTS_KEYSIZE;
  274. // Compute Ltree
  275. setLtreeADRS(ltree_addr, idx_leaf);
  276. l_tree(pkhash, wots_pk, pub_seed, ltree_addr);
  277. // Compute root
  278. validate_authpath(root, pkhash, idx_leaf, sig_msg, pub_seed, node_addr);
  279. sig_msg += XMSS_TREEHEIGHT*XMSS_N;
  280. sig_msg_len -= XMSS_TREEHEIGHT*XMSS_N;
  281. }
  282. for (i=0; i < XMSS_N; i++)
  283. if (root[i] != pk[i])
  284. goto fail;
  285. *msglen = sig_msg_len;
  286. for (i=0; i < *msglen; i++)
  287. msg[i] = sig_msg[i];
  288. return 0;
  289. fail:
  290. *msglen = sig_msg_len;
  291. for (i=0; i < *msglen; i++)
  292. msg[i] = 0;
  293. *msglen = -1;
  294. return -1;
  295. }