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.

323 lines
10 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_keysize];
  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. const unsigned char *pub_seed = pk + params->n;
  171. unsigned char wots_pk[params->wots_keysize];
  172. unsigned char leaf[params->n];
  173. unsigned char root[params->n];
  174. unsigned char mhash[params->n];
  175. unsigned long idx;
  176. uint32_t ots_addr[8] = {0};
  177. uint32_t ltree_addr[8] = {0};
  178. uint32_t node_addr[8] = {0};
  179. set_type(ots_addr, XMSS_ADDR_TYPE_OTS);
  180. set_type(ltree_addr, XMSS_ADDR_TYPE_LTREE);
  181. set_type(node_addr, XMSS_ADDR_TYPE_HASHTREE);
  182. *mlen = smlen - params->bytes;
  183. /* Convert the index bytes from the signature to an integer. */
  184. idx = (unsigned long)bytes_to_ull(sm, params->index_len);
  185. /* Compute the message hash. */
  186. hash_message(params, mhash, sm + params->index_len, pk, idx,
  187. sm + params->bytes, *mlen);
  188. sm += params->index_len + params->n;
  189. /* The WOTS public key is only correct if the signature was correct. */
  190. set_ots_addr(ots_addr, idx);
  191. wots_pk_from_sig(params, wots_pk, sm, mhash, pub_seed, ots_addr);
  192. sm += params->wots_keysize;
  193. /* Compute the leaf node using the WOTS public key. */
  194. set_ltree_addr(ltree_addr, idx);
  195. l_tree(params, leaf, wots_pk, pub_seed, ltree_addr);
  196. /* Compute the root node. */
  197. compute_root(params, root, leaf, idx, sm, pub_seed, node_addr);
  198. sm += params->tree_height*params->n;
  199. /* Check if the root node equals the root node in the public key. */
  200. if (memcmp(root, pk, params->n)) {
  201. /* If not, zero the message */
  202. memset(m, 0, *mlen);
  203. *mlen = -1;
  204. return -1;
  205. }
  206. /* If verification was successful, copy the message from the signature. */
  207. memcpy(m, sm, *mlen);
  208. return 0;
  209. }
  210. /**
  211. * Verifies a given message signature pair under a given public key.
  212. * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  213. */
  214. int xmssmt_core_sign_open(const xmss_params *params,
  215. unsigned char *m, unsigned long long *mlen,
  216. const unsigned char *sm, unsigned long long smlen,
  217. const unsigned char *pk)
  218. {
  219. const unsigned char *pub_seed = pk + params->n;
  220. unsigned char wots_pk[params->wots_keysize];
  221. unsigned char leaf[params->n];
  222. unsigned char root[params->n];
  223. unsigned char *mhash = root;
  224. unsigned long long idx = 0;
  225. unsigned int i;
  226. uint32_t idx_leaf;
  227. uint32_t ots_addr[8] = {0};
  228. uint32_t ltree_addr[8] = {0};
  229. uint32_t node_addr[8] = {0};
  230. set_type(ots_addr, XMSS_ADDR_TYPE_OTS);
  231. set_type(ltree_addr, XMSS_ADDR_TYPE_LTREE);
  232. set_type(node_addr, XMSS_ADDR_TYPE_HASHTREE);
  233. *mlen = smlen - params->bytes;
  234. /* Convert the index bytes from the signature to an integer. */
  235. idx = bytes_to_ull(sm, params->index_len);
  236. /* Compute the message hash. */
  237. hash_message(params, mhash, sm + params->index_len, pk, idx,
  238. sm + params->bytes, *mlen);
  239. sm += params->index_len + params->n;
  240. /* For each subtree.. */
  241. for (i = 0; i < params->d; i++) {
  242. idx_leaf = (idx & ((1 << params->tree_height)-1));
  243. idx = idx >> params->tree_height;
  244. set_layer_addr(ots_addr, i);
  245. set_layer_addr(ltree_addr, i);
  246. set_layer_addr(node_addr, i);
  247. set_tree_addr(ltree_addr, idx);
  248. set_tree_addr(ots_addr, idx);
  249. set_tree_addr(node_addr, idx);
  250. /* The WOTS public key is only correct if the signature was correct. */
  251. set_ots_addr(ots_addr, idx_leaf);
  252. /* Initially, root = mhash, but on subsequent iterations it is the root
  253. of the subtree below the currently processed subtree. */
  254. wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr);
  255. sm += params->wots_keysize;
  256. /* Compute the leaf node using the WOTS public key. */
  257. set_ltree_addr(ltree_addr, idx_leaf);
  258. l_tree(params, leaf, wots_pk, pub_seed, ltree_addr);
  259. /* Compute the root node of this subtree. */
  260. compute_root(params, root, leaf, idx_leaf, sm, pub_seed, node_addr);
  261. sm += params->tree_height*params->n;
  262. }
  263. /* Check if the root node equals the root node in the public key. */
  264. if (memcmp(root, pk, params->n)) {
  265. /* If not, zero the message */
  266. memset(m, 0, *mlen);
  267. *mlen = -1;
  268. return -1;
  269. }
  270. /* If verification was successful, copy the message from the signature. */
  271. memcpy(m, sm, *mlen);
  272. return 0;
  273. }