您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

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