Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

402 linhas
12 KiB

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdint.h>
  4. #include "hash.h"
  5. #include "hash_address.h"
  6. #include "params.h"
  7. #include "randombytes.h"
  8. #include "wots.h"
  9. #include "xmss_commons.h"
  10. #include "xmss_core.h"
  11. /**
  12. * Merkle's TreeHash algorithm. Currently only used for key generation.
  13. * Computes the root node of the top-most subtree.
  14. */
  15. static void treehash_root(const xmss_params *params, unsigned char *root,
  16. const unsigned char *sk_seed,
  17. const unsigned char *pub_seed)
  18. {
  19. unsigned char stack[(params->tree_height+1)*params->n];
  20. unsigned int heights[params->tree_height+1];
  21. unsigned int offset = 0;
  22. /* The subtree has at most 2^20 leafs, so uint32_t suffices. */
  23. uint32_t idx;
  24. /* We need all three types of addresses in parallel. */
  25. uint32_t ots_addr[8] = {0};
  26. uint32_t ltree_addr[8] = {0};
  27. uint32_t node_addr[8] = {0};
  28. /* To support the multi-tree setting, select the top tree. */
  29. set_layer_addr(ots_addr, params->d - 1);
  30. set_layer_addr(ltree_addr, params->d - 1);
  31. set_layer_addr(node_addr, params->d - 1);
  32. set_type(ots_addr, 0);
  33. set_type(ltree_addr, 1);
  34. set_type(node_addr, 2);
  35. for (idx = 0; idx < (uint32_t)(1 << params->tree_height); idx++) {
  36. /* Add the next leaf node to the stack. */
  37. set_ltree_addr(ltree_addr, idx);
  38. set_ots_addr(ots_addr, idx);
  39. gen_leaf_wots(params, stack + offset*params->n,
  40. sk_seed, pub_seed, ltree_addr, ots_addr);
  41. heights[offset] = 0;
  42. offset++;
  43. /* While the top-most nodes are of equal height.. */
  44. while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) {
  45. /* Hash the top-most nodes from the stack together. */
  46. set_tree_height(node_addr, heights[offset - 1]);
  47. set_tree_index(node_addr, (idx >> (heights[offset - 1] + 1)));
  48. hash_h(params, stack + (offset-2)*params->n,
  49. stack + (offset-2)*params->n, pub_seed, node_addr);
  50. /* Note that the top-most node is now one layer higher. */
  51. heights[offset-2]++;
  52. offset--;
  53. }
  54. }
  55. memcpy(root, stack, params->n);
  56. }
  57. /**
  58. * Computes the authpath and the root. This method is using a lot of space as we
  59. * build the whole tree and then select the authpath nodes. For more efficient
  60. * algorithms see e.g. the chapter on hash-based signatures in Bernstein,
  61. * Buchmann, Dahmen. "Post-quantum Cryptography", Springer 2009.
  62. *
  63. * Returns the authpath in "authpath" with the node on level 0 at index 0.
  64. */
  65. static void compute_authpath_wots(const xmss_params *params, unsigned char *root, unsigned char *authpath, unsigned long leaf_idx, const unsigned char *sk_seed, unsigned char *pub_seed, uint32_t addr[8])
  66. {
  67. uint32_t i, j, level;
  68. unsigned char tree[2*(1 << params->tree_height)*params->n];
  69. uint32_t ots_addr[8];
  70. uint32_t ltree_addr[8];
  71. uint32_t node_addr[8];
  72. memcpy(ots_addr, addr, 12);
  73. set_type(ots_addr, 0);
  74. memcpy(ltree_addr, addr, 12);
  75. set_type(ltree_addr, 1);
  76. memcpy(node_addr, addr, 12);
  77. set_type(node_addr, 2);
  78. // Compute all leaves
  79. for (i = 0; i < (1U << params->tree_height); i++) {
  80. set_ltree_addr(ltree_addr, i);
  81. set_ots_addr(ots_addr, i);
  82. gen_leaf_wots(params, tree+((1 << params->tree_height)*params->n + i*params->n), sk_seed, pub_seed, ltree_addr, ots_addr);
  83. }
  84. level = 0;
  85. // Compute tree:
  86. // Outer loop: For each inner layer
  87. for (i = (1 << params->tree_height); i > 1; i>>=1) {
  88. set_tree_height(node_addr, level);
  89. // Inner loop: for each pair of sibling nodes
  90. for (j = 0; j < i; j+=2) {
  91. set_tree_index(node_addr, j>>1);
  92. hash_h(params, tree + (i>>1)*params->n + (j>>1) * params->n, tree + i*params->n + j*params->n, pub_seed, node_addr);
  93. }
  94. level++;
  95. }
  96. // copy authpath
  97. for (i = 0; i < params->tree_height; i++) {
  98. memcpy(authpath + i*params->n, tree + ((1 << params->tree_height)>>i)*params->n + ((leaf_idx >> i) ^ 1) * params->n, params->n);
  99. }
  100. // copy root
  101. memcpy(root, tree+params->n, params->n);
  102. }
  103. /*
  104. * Generates a XMSS key pair for a given parameter set.
  105. * Format sk: [(32bit) index || SK_SEED || SK_PRF || PUB_SEED || root]
  106. * Format pk: [root || PUB_SEED], omitting algorithm OID.
  107. */
  108. int xmss_core_keypair(const xmss_params *params,
  109. unsigned char *pk, unsigned char *sk)
  110. {
  111. /* Initialize index to 0. */
  112. memset(sk, 0, params->index_len);
  113. sk += 4;
  114. /* Initialize SK_SEED, SK_PRF and PUB_SEED. */
  115. randombytes(sk, 3 * params->n);
  116. memcpy(pk + params->n, sk + 2*params->n, params->n);
  117. /* Compute root node. */
  118. treehash_root(params, pk, sk, pk + params->n);
  119. memcpy(sk + 3*params->n, pk, params->n);
  120. return 0;
  121. }
  122. /**
  123. * Signs a message.
  124. * Returns
  125. * 1. an array containing the signature followed by the message AND
  126. * 2. an updated secret key!
  127. *
  128. */
  129. int xmss_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen)
  130. {
  131. uint16_t i = 0;
  132. // Extract SK
  133. uint32_t idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3];
  134. unsigned char sk_seed[params->n];
  135. unsigned char sk_prf[params->n];
  136. unsigned char pub_seed[params->n];
  137. unsigned char hash_key[3*params->n];
  138. // index as 32 bytes string
  139. unsigned char idx_bytes_32[32];
  140. ull_to_bytes(idx_bytes_32, 32, idx);
  141. memcpy(sk_seed, sk+4, params->n);
  142. memcpy(sk_prf, sk+4+params->n, params->n);
  143. memcpy(pub_seed, sk+4+2*params->n, params->n);
  144. // Update SK
  145. sk[0] = ((idx + 1) >> 24) & 255;
  146. sk[1] = ((idx + 1) >> 16) & 255;
  147. sk[2] = ((idx + 1) >> 8) & 255;
  148. sk[3] = (idx + 1) & 255;
  149. // Secret key for this non-forward-secure version is now updated.
  150. // A production implementation should consider using a file handle instead,
  151. // and write the updated secret key at this point!
  152. // Init working params
  153. unsigned char R[params->n];
  154. unsigned char msg_h[params->n];
  155. unsigned char root[params->n];
  156. unsigned char ots_seed[params->n];
  157. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  158. // ---------------------------------
  159. // Message Hashing
  160. // ---------------------------------
  161. // Message Hash:
  162. // First compute pseudorandom value
  163. prf(params, R, idx_bytes_32, sk_prf, params->n);
  164. // Generate hash key (R || root || idx)
  165. memcpy(hash_key, R, params->n);
  166. memcpy(hash_key+params->n, sk+4+3*params->n, params->n);
  167. ull_to_bytes(hash_key+2*params->n, params->n, idx);
  168. // Then use it for message digest
  169. h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
  170. // Start collecting signature
  171. *smlen = 0;
  172. // Copy index to signature
  173. sm[0] = (idx >> 24) & 255;
  174. sm[1] = (idx >> 16) & 255;
  175. sm[2] = (idx >> 8) & 255;
  176. sm[3] = idx & 255;
  177. sm += 4;
  178. *smlen += 4;
  179. // Copy R to signature
  180. for (i = 0; i < params->n; i++)
  181. sm[i] = R[i];
  182. sm += params->n;
  183. *smlen += params->n;
  184. // ----------------------------------
  185. // Now we start to "really sign"
  186. // ----------------------------------
  187. // Prepare Address
  188. set_type(ots_addr, 0);
  189. set_ots_addr(ots_addr, idx);
  190. // Compute seed for OTS key pair
  191. get_seed(params, ots_seed, sk_seed, ots_addr);
  192. // Compute WOTS signature
  193. wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr);
  194. sm += params->wots_keysize;
  195. *smlen += params->wots_keysize;
  196. compute_authpath_wots(params, root, sm, idx, sk_seed, pub_seed, ots_addr);
  197. sm += params->tree_height*params->n;
  198. *smlen += params->tree_height*params->n;
  199. memcpy(sm, m, mlen);
  200. *smlen += mlen;
  201. return 0;
  202. }
  203. /*
  204. * Generates a XMSSMT key pair for a given parameter set.
  205. * Format sk: [(ceil(h/8) bit) index || SK_SEED || SK_PRF || PUB_SEED]
  206. * Format pk: [root || PUB_SEED] omitting algorithm OID.
  207. */
  208. int xmssmt_core_keypair(const xmss_params *params, unsigned char *pk, unsigned char *sk)
  209. {
  210. /* Initialize index to 0. */
  211. memset(sk, 0, params->index_len);
  212. sk += 4;
  213. /* Initialize SK_SEED, SK_PRF and PUB_SEED. */
  214. randombytes(sk, 3 * params->n);
  215. memcpy(pk + params->n, sk + 2*params->n, params->n);
  216. /* Compute root node of the top-most subtree. */
  217. treehash_root(params, pk, sk, pk + params->n);
  218. memcpy(sk + 3*params->n, pk, params->n);
  219. return 0;
  220. }
  221. /**
  222. * Signs a message.
  223. * Returns
  224. * 1. an array containing the signature followed by the message AND
  225. * 2. an updated secret key!
  226. *
  227. */
  228. int xmssmt_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen)
  229. {
  230. uint64_t idx_tree;
  231. uint32_t idx_leaf;
  232. uint64_t i;
  233. unsigned char sk_seed[params->n];
  234. unsigned char sk_prf[params->n];
  235. unsigned char pub_seed[params->n];
  236. // Init working params
  237. unsigned char R[params->n];
  238. unsigned char hash_key[3*params->n];
  239. unsigned char msg_h[params->n];
  240. unsigned char root[params->n];
  241. unsigned char ots_seed[params->n];
  242. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  243. unsigned char idx_bytes_32[32];
  244. // Extract SK
  245. unsigned long long idx = 0;
  246. for (i = 0; i < params->index_len; i++) {
  247. idx |= ((unsigned long long)sk[i]) << 8*(params->index_len - 1 - i);
  248. }
  249. memcpy(sk_seed, sk+params->index_len, params->n);
  250. memcpy(sk_prf, sk+params->index_len+params->n, params->n);
  251. memcpy(pub_seed, sk+params->index_len+2*params->n, params->n);
  252. // Update SK
  253. for (i = 0; i < params->index_len; i++) {
  254. sk[i] = ((idx + 1) >> 8*(params->index_len - 1 - i)) & 255;
  255. }
  256. // Secret key for this non-forward-secure version is now updated.
  257. // A production implementation should consider using a file handle instead,
  258. // and write the updated secret key at this point!
  259. // ---------------------------------
  260. // Message Hashing
  261. // ---------------------------------
  262. // Message Hash:
  263. // First compute pseudorandom value
  264. ull_to_bytes(idx_bytes_32, 32, idx);
  265. prf(params, R, idx_bytes_32, sk_prf, params->n);
  266. // Generate hash key (R || root || idx)
  267. memcpy(hash_key, R, params->n);
  268. memcpy(hash_key+params->n, sk+params->index_len+3*params->n, params->n);
  269. ull_to_bytes(hash_key+2*params->n, params->n, idx);
  270. // Then use it for message digest
  271. h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
  272. // Start collecting signature
  273. *smlen = 0;
  274. // Copy index to signature
  275. for (i = 0; i < params->index_len; i++) {
  276. sm[i] = (idx >> 8*(params->index_len - 1 - i)) & 255;
  277. }
  278. sm += params->index_len;
  279. *smlen += params->index_len;
  280. // Copy R to signature
  281. for (i = 0; i < params->n; i++) {
  282. sm[i] = R[i];
  283. }
  284. sm += params->n;
  285. *smlen += params->n;
  286. // ----------------------------------
  287. // Now we start to "really sign"
  288. // ----------------------------------
  289. // Handle lowest layer separately as it is slightly different...
  290. // Prepare Address
  291. set_type(ots_addr, 0);
  292. idx_tree = idx >> params->tree_height;
  293. idx_leaf = (idx & ((1 << params->tree_height)-1));
  294. set_layer_addr(ots_addr, 0);
  295. set_tree_addr(ots_addr, idx_tree);
  296. set_ots_addr(ots_addr, idx_leaf);
  297. // Compute seed for OTS key pair
  298. get_seed(params, ots_seed, sk_seed, ots_addr);
  299. // Compute WOTS signature
  300. wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr);
  301. sm += params->wots_keysize;
  302. *smlen += params->wots_keysize;
  303. compute_authpath_wots(params, root, sm, idx_leaf, sk_seed, pub_seed, ots_addr);
  304. sm += params->tree_height*params->n;
  305. *smlen += params->tree_height*params->n;
  306. // Now loop over remaining layers...
  307. unsigned int j;
  308. for (j = 1; j < params->d; j++) {
  309. // Prepare Address
  310. idx_leaf = (idx_tree & ((1 << params->tree_height)-1));
  311. idx_tree = idx_tree >> params->tree_height;
  312. set_layer_addr(ots_addr, j);
  313. set_tree_addr(ots_addr, idx_tree);
  314. set_ots_addr(ots_addr, idx_leaf);
  315. // Compute seed for OTS key pair
  316. get_seed(params, ots_seed, sk_seed, ots_addr);
  317. // Compute WOTS signature
  318. wots_sign(params, sm, root, ots_seed, pub_seed, ots_addr);
  319. sm += params->wots_keysize;
  320. *smlen += params->wots_keysize;
  321. compute_authpath_wots(params, root, sm, idx_leaf, sk_seed, pub_seed, ots_addr);
  322. sm += params->tree_height*params->n;
  323. *smlen += params->tree_height*params->n;
  324. }
  325. memcpy(sm, m, mlen);
  326. *smlen += mlen;
  327. return 0;
  328. }