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.

xmss_commons.c 8.6 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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 a root node given a leaf and an auth path
  105. */
  106. static void compute_root(const xmss_params *params, unsigned char *root,
  107. const unsigned char *leaf, unsigned long leafidx,
  108. const unsigned char *auth_path,
  109. const unsigned char *pub_seed, uint32_t addr[8])
  110. {
  111. uint32_t i;
  112. unsigned char buffer[2*params->n];
  113. /* If leafidx is odd (last bit = 1), current path element is a right child
  114. and auth_path has to go left. Otherwise it is the other way around. */
  115. if (leafidx & 1) {
  116. memcpy(buffer + params->n, leaf, params->n);
  117. memcpy(buffer, auth_path, params->n);
  118. }
  119. else {
  120. memcpy(buffer, leaf, params->n);
  121. memcpy(buffer + params->n, auth_path, params->n);
  122. }
  123. auth_path += params->n;
  124. for (i = 0; i < params->tree_height - 1; i++) {
  125. set_tree_height(addr, i);
  126. leafidx >>= 1;
  127. set_tree_index(addr, leafidx);
  128. /* Pick the right or left neighbor, depending on parity of the node. */
  129. if (leafidx & 1) {
  130. hash_h(params, buffer + params->n, buffer, pub_seed, addr);
  131. memcpy(buffer, auth_path, params->n);
  132. }
  133. else {
  134. hash_h(params, buffer, buffer, pub_seed, addr);
  135. memcpy(buffer + params->n, auth_path, params->n);
  136. }
  137. auth_path += params->n;
  138. }
  139. /* The last iteration is exceptional; we do not copy an auth)path node. */
  140. set_tree_height(addr, params->tree_height - 1);
  141. leafidx >>= 1;
  142. set_tree_index(addr, leafidx);
  143. hash_h(params, root, buffer, pub_seed, addr);
  144. }
  145. /**
  146. * Verifies a given message signature pair under a given public key.
  147. * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  148. */
  149. int xmss_core_sign_open(const xmss_params *params,
  150. unsigned char *m, unsigned long long *mlen,
  151. const unsigned char *sm, unsigned long long smlen,
  152. const unsigned char *pk)
  153. {
  154. /* XMSS signatures are fundamentally an instance of XMSSMT signatures.
  155. For d=1, as is the case with XMSS, some of the calls in the XMSSMT
  156. routine become vacuous (i.e. the loop only iterates once, and address
  157. management can be simplified a bit).*/
  158. return xmssmt_core_sign_open(params, m, mlen, sm, smlen, pk);
  159. }
  160. /**
  161. * Verifies a given message signature pair under a given public key.
  162. * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  163. */
  164. int xmssmt_core_sign_open(const xmss_params *params,
  165. unsigned char *m, unsigned long long *mlen,
  166. const unsigned char *sm, unsigned long long smlen,
  167. const unsigned char *pk)
  168. {
  169. const unsigned char *pub_seed = pk + params->n;
  170. unsigned char wots_pk[params->wots_sig_bytes];
  171. unsigned char leaf[params->n];
  172. unsigned char root[params->n];
  173. unsigned char *mhash = root;
  174. unsigned long long idx = 0;
  175. unsigned int i;
  176. uint32_t idx_leaf;
  177. uint32_t ots_addr[8] = {0};
  178. uint32_t ltree_addr[8] = {0};
  179. uint32_t node_addr[8] = {0};
  180. set_type(ots_addr, XMSS_ADDR_TYPE_OTS);
  181. set_type(ltree_addr, XMSS_ADDR_TYPE_LTREE);
  182. set_type(node_addr, XMSS_ADDR_TYPE_HASHTREE);
  183. *mlen = smlen - params->sig_bytes;
  184. /* Convert the index bytes from the signature to an integer. */
  185. idx = bytes_to_ull(sm, params->index_bytes);
  186. /* Put the message all the way at the end of the m buffer, so that we can
  187. * prepend the required other inputs for the hash function. */
  188. memcpy(m + params->sig_bytes, sm + params->sig_bytes, *mlen);
  189. /* Compute the message hash. */
  190. hash_message(params, mhash, sm + params->index_bytes, pk, idx,
  191. m + params->sig_bytes - 4*params->n, *mlen);
  192. sm += params->index_bytes + params->n;
  193. /* For each subtree.. */
  194. for (i = 0; i < params->d; i++) {
  195. idx_leaf = (idx & ((1 << params->tree_height)-1));
  196. idx = idx >> params->tree_height;
  197. set_layer_addr(ots_addr, i);
  198. set_layer_addr(ltree_addr, i);
  199. set_layer_addr(node_addr, i);
  200. set_tree_addr(ltree_addr, idx);
  201. set_tree_addr(ots_addr, idx);
  202. set_tree_addr(node_addr, idx);
  203. /* The WOTS public key is only correct if the signature was correct. */
  204. set_ots_addr(ots_addr, idx_leaf);
  205. /* Initially, root = mhash, but on subsequent iterations it is the root
  206. of the subtree below the currently processed subtree. */
  207. wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr);
  208. sm += params->wots_sig_bytes;
  209. /* Compute the leaf node using the WOTS public key. */
  210. set_ltree_addr(ltree_addr, idx_leaf);
  211. l_tree(params, leaf, wots_pk, pub_seed, ltree_addr);
  212. /* Compute the root node of this subtree. */
  213. compute_root(params, root, leaf, idx_leaf, sm, pub_seed, node_addr);
  214. sm += params->tree_height*params->n;
  215. }
  216. /* Check if the root node equals the root node in the public key. */
  217. if (memcmp(root, pk, params->n)) {
  218. /* If not, zero the message */
  219. memset(m, 0, *mlen);
  220. *mlen = 0;
  221. return -1;
  222. }
  223. /* If verification was successful, copy the message from the signature. */
  224. memcpy(m, sm, *mlen);
  225. return 0;
  226. }