Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

278 rader
9.0 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 "wots.h"
  8. #include "xmss_commons.h"
  9. /**
  10. * Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
  11. */
  12. void ull_to_bytes(unsigned char *out, unsigned int outlen,
  13. unsigned long long in)
  14. {
  15. int i;
  16. /* Iterate over out in decreasing order, for big-endianness. */
  17. for (i = outlen - 1; i >= 0; i--) {
  18. out[i] = in & 0xff;
  19. in = in >> 8;
  20. }
  21. }
  22. /**
  23. * Converts the inlen bytes in 'in' from big-endian byte order to an integer.
  24. */
  25. unsigned long long bytes_to_ull(const unsigned char *in, unsigned int inlen)
  26. {
  27. unsigned long long retval = 0;
  28. unsigned int i;
  29. for (i = 0; i < inlen; i++) {
  30. retval |= ((unsigned long long)in[i]) << (8*(inlen - 1 - i));
  31. }
  32. return retval;
  33. }
  34. /**
  35. * Computes the leaf at a given address. First generates the WOTS key pair,
  36. * then computes leaf using l_tree. As this happens position independent, we
  37. * only require that addr encodes the right ltree-address.
  38. */
  39. void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
  40. const unsigned char *sk_seed, const unsigned char *pub_seed,
  41. uint32_t ltree_addr[8], uint32_t ots_addr[8])
  42. {
  43. unsigned char seed[params->n];
  44. unsigned char pk[params->wots_sig_bytes];
  45. get_seed(params, seed, sk_seed, ots_addr);
  46. wots_pkgen(params, pk, seed, pub_seed, ots_addr);
  47. l_tree(params, leaf, pk, pub_seed, ltree_addr);
  48. }
  49. /**
  50. * Used for pseudo-random key generation.
  51. * Generates the seed for the WOTS key pair at address 'addr'.
  52. *
  53. * Takes n-byte sk_seed and returns n-byte seed using 32 byte address 'addr'.
  54. */
  55. void get_seed(const xmss_params *params, unsigned char *seed,
  56. const unsigned char *sk_seed, uint32_t addr[8])
  57. {
  58. unsigned char bytes[32];
  59. /* Make sure that chain addr, hash addr, and key bit are zeroed. */
  60. set_chain_addr(addr, 0);
  61. set_hash_addr(addr, 0);
  62. set_key_and_mask(addr, 0);
  63. /* Generate seed. */
  64. addr_to_bytes(bytes, addr);
  65. prf(params, seed, bytes, sk_seed, params->n);
  66. }
  67. /**
  68. * Computes a leaf node from a WOTS public key using an L-tree.
  69. * Note that this destroys the used WOTS public key.
  70. */
  71. void l_tree(const xmss_params *params,
  72. unsigned char *leaf, unsigned char *wots_pk,
  73. const unsigned char *pub_seed, uint32_t addr[8])
  74. {
  75. unsigned int l = params->wots_len;
  76. unsigned int parent_nodes;
  77. uint32_t i;
  78. uint32_t height = 0;
  79. set_tree_height(addr, height);
  80. while (l > 1) {
  81. parent_nodes = l >> 1;
  82. for (i = 0; i < parent_nodes; i++) {
  83. set_tree_index(addr, i);
  84. /* Hashes the nodes at (i*2)*params->n and (i*2)*params->n + 1 */
  85. hash_h(params, wots_pk + i*params->n,
  86. wots_pk + (i*2)*params->n, pub_seed, addr);
  87. }
  88. /* If the row contained an odd number of nodes, the last node was not
  89. hashed. Instead, we pull it up to the next layer. */
  90. if (l & 1) {
  91. memcpy(wots_pk + (l >> 1)*params->n,
  92. wots_pk + (l - 1)*params->n, params->n);
  93. l = (l >> 1) + 1;
  94. }
  95. else {
  96. l = l >> 1;
  97. }
  98. height++;
  99. set_tree_height(addr, height);
  100. }
  101. memcpy(leaf, wots_pk, params->n);
  102. }
  103. /**
  104. * Computes the randomized message hash.
  105. */
  106. void hash_message(const xmss_params *params, unsigned char *mhash,
  107. const unsigned char *R, const unsigned char *root,
  108. unsigned long long idx,
  109. const unsigned char *m, unsigned long long mlen)
  110. {
  111. unsigned char hash_key[3*params->n];
  112. /* Compute hash key. */
  113. memcpy(hash_key, R, params->n);
  114. memcpy(hash_key + params->n, root, params->n);
  115. ull_to_bytes(hash_key + 2*params->n, params->n, idx);
  116. /* Hash the message using the randomized hash key. */
  117. h_msg(params, mhash, m, mlen, hash_key, 3*params->n);
  118. }
  119. /**
  120. * Computes a root node given a leaf and an auth path
  121. */
  122. static void compute_root(const xmss_params *params, unsigned char *root,
  123. const unsigned char *leaf, unsigned long leafidx,
  124. const unsigned char *auth_path,
  125. const unsigned char *pub_seed, uint32_t addr[8])
  126. {
  127. uint32_t i;
  128. unsigned char buffer[2*params->n];
  129. /* If leafidx is odd (last bit = 1), current path element is a right child
  130. and auth_path has to go left. Otherwise it is the other way around. */
  131. if (leafidx & 1) {
  132. memcpy(buffer + params->n, leaf, params->n);
  133. memcpy(buffer, auth_path, params->n);
  134. }
  135. else {
  136. memcpy(buffer, leaf, params->n);
  137. memcpy(buffer + params->n, auth_path, params->n);
  138. }
  139. auth_path += params->n;
  140. for (i = 0; i < params->tree_height - 1; i++) {
  141. set_tree_height(addr, i);
  142. leafidx >>= 1;
  143. set_tree_index(addr, leafidx);
  144. /* Pick the right or left neighbor, depending on parity of the node. */
  145. if (leafidx & 1) {
  146. hash_h(params, buffer + params->n, buffer, pub_seed, addr);
  147. memcpy(buffer, auth_path, params->n);
  148. }
  149. else {
  150. hash_h(params, buffer, buffer, pub_seed, addr);
  151. memcpy(buffer + params->n, auth_path, params->n);
  152. }
  153. auth_path += params->n;
  154. }
  155. /* The last iteration is exceptional; we do not copy an auth)path node. */
  156. set_tree_height(addr, params->tree_height - 1);
  157. leafidx >>= 1;
  158. set_tree_index(addr, leafidx);
  159. hash_h(params, root, buffer, pub_seed, addr);
  160. }
  161. /**
  162. * Verifies a given message signature pair under a given public key.
  163. * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  164. */
  165. int xmss_core_sign_open(const xmss_params *params,
  166. unsigned char *m, unsigned long long *mlen,
  167. const unsigned char *sm, unsigned long long smlen,
  168. const unsigned char *pk)
  169. {
  170. /* XMSS signatures are fundamentally an instance of XMSSMT signatures.
  171. For d=1, as is the case with XMSS, some of the calls in the XMSSMT
  172. routine become vacuous (i.e. the loop only iterates once, and address
  173. management can be simplified a bit).*/
  174. return xmssmt_core_sign_open(params, m, mlen, sm, smlen, pk);
  175. }
  176. /**
  177. * Verifies a given message signature pair under a given public key.
  178. * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  179. */
  180. int xmssmt_core_sign_open(const xmss_params *params,
  181. unsigned char *m, unsigned long long *mlen,
  182. const unsigned char *sm, unsigned long long smlen,
  183. const unsigned char *pk)
  184. {
  185. const unsigned char *pub_seed = pk + params->n;
  186. unsigned char wots_pk[params->wots_sig_bytes];
  187. unsigned char leaf[params->n];
  188. unsigned char root[params->n];
  189. unsigned char *mhash = root;
  190. unsigned long long idx = 0;
  191. unsigned int i;
  192. uint32_t idx_leaf;
  193. uint32_t ots_addr[8] = {0};
  194. uint32_t ltree_addr[8] = {0};
  195. uint32_t node_addr[8] = {0};
  196. set_type(ots_addr, XMSS_ADDR_TYPE_OTS);
  197. set_type(ltree_addr, XMSS_ADDR_TYPE_LTREE);
  198. set_type(node_addr, XMSS_ADDR_TYPE_HASHTREE);
  199. *mlen = smlen - params->sig_bytes;
  200. /* Convert the index bytes from the signature to an integer. */
  201. idx = bytes_to_ull(sm, params->index_bytes);
  202. /* Compute the message hash. */
  203. hash_message(params, mhash, sm + params->index_bytes, pk, idx,
  204. sm + params->sig_bytes, *mlen);
  205. sm += params->index_bytes + params->n;
  206. /* For each subtree.. */
  207. for (i = 0; i < params->d; i++) {
  208. idx_leaf = (idx & ((1 << params->tree_height)-1));
  209. idx = idx >> params->tree_height;
  210. set_layer_addr(ots_addr, i);
  211. set_layer_addr(ltree_addr, i);
  212. set_layer_addr(node_addr, i);
  213. set_tree_addr(ltree_addr, idx);
  214. set_tree_addr(ots_addr, idx);
  215. set_tree_addr(node_addr, idx);
  216. /* The WOTS public key is only correct if the signature was correct. */
  217. set_ots_addr(ots_addr, idx_leaf);
  218. /* Initially, root = mhash, but on subsequent iterations it is the root
  219. of the subtree below the currently processed subtree. */
  220. wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr);
  221. sm += params->wots_sig_bytes;
  222. /* Compute the leaf node using the WOTS public key. */
  223. set_ltree_addr(ltree_addr, idx_leaf);
  224. l_tree(params, leaf, wots_pk, pub_seed, ltree_addr);
  225. /* Compute the root node of this subtree. */
  226. compute_root(params, root, leaf, idx_leaf, sm, pub_seed, node_addr);
  227. sm += params->tree_height*params->n;
  228. }
  229. /* Check if the root node equals the root node in the public key. */
  230. if (memcmp(root, pk, params->n)) {
  231. /* If not, zero the message */
  232. memset(m, 0, *mlen);
  233. *mlen = -1;
  234. return -1;
  235. }
  236. /* If verification was successful, copy the message from the signature. */
  237. memcpy(m, sm, *mlen);
  238. return 0;
  239. }