Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

216 righe
7.3 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 "utils.h"
  9. #include "xmss_commons.h"
  10. /**
  11. * Computes a leaf node from a WOTS public key using an L-tree.
  12. * Note that this destroys the used WOTS public key.
  13. */
  14. static void l_tree(const xmss_params *params,
  15. unsigned char *leaf, unsigned char *wots_pk,
  16. const unsigned char *pub_seed, uint32_t addr[8])
  17. {
  18. unsigned int l = params->wots_len;
  19. unsigned int parent_nodes;
  20. uint32_t i;
  21. uint32_t height = 0;
  22. set_tree_height(addr, height);
  23. while (l > 1) {
  24. parent_nodes = l >> 1;
  25. for (i = 0; i < parent_nodes; i++) {
  26. set_tree_index(addr, i);
  27. /* Hashes the nodes at (i*2)*params->n and (i*2)*params->n + 1 */
  28. thash_h(params, wots_pk + i*params->n,
  29. wots_pk + (i*2)*params->n, pub_seed, addr);
  30. }
  31. /* If the row contained an odd number of nodes, the last node was not
  32. hashed. Instead, we pull it up to the next layer. */
  33. if (l & 1) {
  34. memcpy(wots_pk + (l >> 1)*params->n,
  35. wots_pk + (l - 1)*params->n, params->n);
  36. l = (l >> 1) + 1;
  37. }
  38. else {
  39. l = l >> 1;
  40. }
  41. height++;
  42. set_tree_height(addr, height);
  43. }
  44. memcpy(leaf, wots_pk, params->n);
  45. }
  46. /**
  47. * Computes a root node given a leaf and an auth path
  48. */
  49. static void compute_root(const xmss_params *params, unsigned char *root,
  50. const unsigned char *leaf, unsigned long leafidx,
  51. const unsigned char *auth_path,
  52. const unsigned char *pub_seed, uint32_t addr[8])
  53. {
  54. uint32_t i;
  55. unsigned char buffer[2*params->n];
  56. /* If leafidx is odd (last bit = 1), current path element is a right child
  57. and auth_path has to go left. Otherwise it is the other way around. */
  58. if (leafidx & 1) {
  59. memcpy(buffer + params->n, leaf, params->n);
  60. memcpy(buffer, auth_path, params->n);
  61. }
  62. else {
  63. memcpy(buffer, leaf, params->n);
  64. memcpy(buffer + params->n, auth_path, params->n);
  65. }
  66. auth_path += params->n;
  67. for (i = 0; i < params->tree_height - 1; i++) {
  68. set_tree_height(addr, i);
  69. leafidx >>= 1;
  70. set_tree_index(addr, leafidx);
  71. /* Pick the right or left neighbor, depending on parity of the node. */
  72. if (leafidx & 1) {
  73. thash_h(params, buffer + params->n, buffer, pub_seed, addr);
  74. memcpy(buffer, auth_path, params->n);
  75. }
  76. else {
  77. thash_h(params, buffer, buffer, pub_seed, addr);
  78. memcpy(buffer + params->n, auth_path, params->n);
  79. }
  80. auth_path += params->n;
  81. }
  82. /* The last iteration is exceptional; we do not copy an auth_path node. */
  83. set_tree_height(addr, params->tree_height - 1);
  84. leafidx >>= 1;
  85. set_tree_index(addr, leafidx);
  86. thash_h(params, root, buffer, pub_seed, addr);
  87. }
  88. /**
  89. * Computes the leaf at a given address. First generates the WOTS key pair,
  90. * then computes leaf using l_tree. As this happens position independent, we
  91. * only require that addr encodes the right ltree-address.
  92. */
  93. void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
  94. const unsigned char *sk_seed, const unsigned char *pub_seed,
  95. uint32_t ltree_addr[8], uint32_t ots_addr[8])
  96. {
  97. unsigned char pk[params->wots_sig_bytes];
  98. wots_pkgen(params, pk, sk_seed, pub_seed, ots_addr);
  99. l_tree(params, leaf, pk, pub_seed, ltree_addr);
  100. }
  101. /**
  102. * Verifies a given message signature pair under a given public key.
  103. * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  104. */
  105. int xmss_core_sign_open(const xmss_params *params,
  106. unsigned char *m, unsigned long long *mlen,
  107. const unsigned char *sm, unsigned long long smlen,
  108. const unsigned char *pk)
  109. {
  110. /* XMSS signatures are fundamentally an instance of XMSSMT signatures.
  111. For d=1, as is the case with XMSS, some of the calls in the XMSSMT
  112. routine become vacuous (i.e. the loop only iterates once, and address
  113. management can be simplified a bit).*/
  114. return xmssmt_core_sign_open(params, m, mlen, sm, smlen, pk);
  115. }
  116. /**
  117. * Verifies a given message signature pair under a given public key.
  118. * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  119. */
  120. int xmssmt_core_sign_open(const xmss_params *params,
  121. unsigned char *m, unsigned long long *mlen,
  122. const unsigned char *sm, unsigned long long smlen,
  123. const unsigned char *pk)
  124. {
  125. const unsigned char *pub_root = pk;
  126. const unsigned char *pub_seed = pk + params->n;
  127. unsigned char wots_pk[params->wots_sig_bytes];
  128. unsigned char leaf[params->n];
  129. unsigned char root[params->n];
  130. unsigned char *mhash = root;
  131. unsigned long long idx = 0;
  132. unsigned int i;
  133. uint32_t idx_leaf;
  134. uint32_t ots_addr[8] = {0};
  135. uint32_t ltree_addr[8] = {0};
  136. uint32_t node_addr[8] = {0};
  137. set_type(ots_addr, XMSS_ADDR_TYPE_OTS);
  138. set_type(ltree_addr, XMSS_ADDR_TYPE_LTREE);
  139. set_type(node_addr, XMSS_ADDR_TYPE_HASHTREE);
  140. *mlen = smlen - params->sig_bytes;
  141. /* Convert the index bytes from the signature to an integer. */
  142. idx = bytes_to_ull(sm, params->index_bytes);
  143. /* Put the message all the way at the end of the m buffer, so that we can
  144. * prepend the required other inputs for the hash function. */
  145. memcpy(m + params->sig_bytes, sm + params->sig_bytes, *mlen);
  146. /* Compute the message hash. */
  147. hash_message(params, mhash, sm + params->index_bytes, pk, idx,
  148. m + params->sig_bytes - params->padding_len - 3*params->n,
  149. *mlen);
  150. sm += params->index_bytes + params->n;
  151. /* For each subtree.. */
  152. for (i = 0; i < params->d; i++) {
  153. idx_leaf = (idx & ((1 << params->tree_height)-1));
  154. idx = idx >> params->tree_height;
  155. set_layer_addr(ots_addr, i);
  156. set_layer_addr(ltree_addr, i);
  157. set_layer_addr(node_addr, i);
  158. set_tree_addr(ltree_addr, idx);
  159. set_tree_addr(ots_addr, idx);
  160. set_tree_addr(node_addr, idx);
  161. /* The WOTS public key is only correct if the signature was correct. */
  162. set_ots_addr(ots_addr, idx_leaf);
  163. /* Initially, root = mhash, but on subsequent iterations it is the root
  164. of the subtree below the currently processed subtree. */
  165. wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr);
  166. sm += params->wots_sig_bytes;
  167. /* Compute the leaf node using the WOTS public key. */
  168. set_ltree_addr(ltree_addr, idx_leaf);
  169. l_tree(params, leaf, wots_pk, pub_seed, ltree_addr);
  170. /* Compute the root node of this subtree. */
  171. compute_root(params, root, leaf, idx_leaf, sm, pub_seed, node_addr);
  172. sm += params->tree_height*params->n;
  173. }
  174. /* Check if the root node equals the root node in the public key. */
  175. if (memcmp(root, pub_root, params->n)) {
  176. /* If not, zero the message */
  177. memset(m, 0, *mlen);
  178. *mlen = 0;
  179. return -1;
  180. }
  181. /* If verification was successful, copy the message from the signature. */
  182. memcpy(m, sm, *mlen);
  183. return 0;
  184. }