Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

200 Zeilen
8.6 KiB

  1. #include <stddef.h>
  2. #include <string.h>
  3. #include "address.h"
  4. #include "hash.h"
  5. #include "hash_state.h"
  6. #include "params.h"
  7. #include "thash.h"
  8. #include "utils.h"
  9. /**
  10. * Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
  11. */
  12. void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ull_to_bytes(
  13. unsigned char *out, size_t outlen, unsigned long long in) {
  14. /* Iterate over out in decreasing order, for big-endianness. */
  15. for (size_t i = outlen; i > 0; i--) {
  16. out[i - 1] = in & 0xff;
  17. in = in >> 8;
  18. }
  19. }
  20. /**
  21. * Converts the inlen bytes in 'in' from big-endian byte order to an integer.
  22. */
  23. unsigned long long PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_bytes_to_ull(
  24. const unsigned char *in, size_t inlen) {
  25. unsigned long long retval = 0;
  26. for (size_t i = 0; i < inlen; i++) {
  27. retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i));
  28. }
  29. return retval;
  30. }
  31. /**
  32. * Computes a root node given a leaf and an auth path.
  33. * Expects address to be complete other than the tree_height and tree_index.
  34. */
  35. void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_compute_root(
  36. unsigned char *root, const unsigned char *leaf,
  37. uint32_t leaf_idx, uint32_t idx_offset,
  38. const unsigned char *auth_path, uint32_t tree_height,
  39. const unsigned char *pub_seed, uint32_t addr[8],
  40. const hash_state *hash_state_seeded) {
  41. uint32_t i;
  42. unsigned char buffer[2 * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N];
  43. /* If leaf_idx is odd (last bit = 1), current path element is a right child
  44. and auth_path has to go left. Otherwise it is the other way around. */
  45. if (leaf_idx & 1) {
  46. memcpy(buffer + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, leaf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N);
  47. memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N);
  48. } else {
  49. memcpy(buffer, leaf, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N);
  50. memcpy(buffer + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N);
  51. }
  52. auth_path += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N;
  53. for (i = 0; i < tree_height - 1; i++) {
  54. leaf_idx >>= 1;
  55. idx_offset >>= 1;
  56. /* Set the address of the node we're creating. */
  57. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height(addr, i + 1);
  58. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(
  59. addr, leaf_idx + idx_offset);
  60. /* Pick the right or left neighbor, depending on parity of the node. */
  61. if (leaf_idx & 1) {
  62. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_2(
  63. buffer + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, buffer, pub_seed, addr, hash_state_seeded);
  64. memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N);
  65. } else {
  66. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_2(
  67. buffer, buffer, pub_seed, addr, hash_state_seeded);
  68. memcpy(buffer + PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, auth_path, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N);
  69. }
  70. auth_path += PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N;
  71. }
  72. /* The last iteration is exceptional; we do not copy an auth_path node. */
  73. leaf_idx >>= 1;
  74. idx_offset >>= 1;
  75. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height(addr, tree_height);
  76. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(
  77. addr, leaf_idx + idx_offset);
  78. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_2(
  79. root, buffer, pub_seed, addr, hash_state_seeded);
  80. }
  81. /**
  82. * For a given leaf index, computes the authentication path and the resulting
  83. * root node using Merkle's TreeHash algorithm.
  84. * Expects the layer and tree parts of the tree_addr to be set, as well as the
  85. * tree type (i.e. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_ADDR_TYPE_FORSTREE).
  86. * Applies the offset idx_offset to indices before building addresses, so that
  87. * it is possible to continue counting indices across trees.
  88. */
  89. static void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash(
  90. unsigned char *root, unsigned char *auth_path,
  91. unsigned char *stack, unsigned int *heights,
  92. const unsigned char *sk_seed, const unsigned char *pub_seed,
  93. uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height,
  94. void (*gen_leaf)(
  95. unsigned char * /* leaf */,
  96. const unsigned char * /* sk_seed */,
  97. const unsigned char * /* pub_seed */,
  98. uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
  99. const hash_state * /* hash_state_seeded */),
  100. uint32_t tree_addr[8],
  101. const hash_state *hash_state_seeded) {
  102. unsigned int offset = 0;
  103. uint32_t idx;
  104. uint32_t tree_idx;
  105. for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) {
  106. /* Add the next leaf node to the stack. */
  107. gen_leaf(stack + offset * PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N,
  108. sk_seed, pub_seed, idx + idx_offset, tree_addr,
  109. hash_state_seeded);
  110. offset++;
  111. heights[offset - 1] = 0;
  112. /* If this is a node we need for the auth path.. */
  113. if ((leaf_idx ^ 0x1) == idx) {
  114. memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N);
  115. }
  116. /* While the top-most nodes are of equal height.. */
  117. while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) {
  118. /* Compute index of the new node, in the next layer. */
  119. tree_idx = (idx >> (heights[offset - 1] + 1));
  120. /* Set the address of the node we're creating. */
  121. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_height(
  122. tree_addr, heights[offset - 1] + 1);
  123. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_set_tree_index(
  124. tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1)));
  125. /* Hash the top-most nodes from the stack together. */
  126. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_thash_2(
  127. stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N,
  128. pub_seed, tree_addr, hash_state_seeded);
  129. offset--;
  130. /* Note that the top-most node is now one layer higher. */
  131. heights[offset - 1]++;
  132. /* If this is a node we need for the auth path.. */
  133. if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) {
  134. memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N,
  135. stack + (offset - 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N);
  136. }
  137. }
  138. }
  139. memcpy(root, stack, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N);
  140. }
  141. /* The wrappers below ensure that we use fixed-size buffers on the stack */
  142. void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash_FORS_HEIGHT(
  143. unsigned char *root, unsigned char *auth_path,
  144. const unsigned char *sk_seed, const unsigned char *pub_seed,
  145. uint32_t leaf_idx, uint32_t idx_offset,
  146. void (*gen_leaf)(
  147. unsigned char * /* leaf */,
  148. const unsigned char * /* sk_seed */,
  149. const unsigned char * /* pub_seed */,
  150. uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
  151. const hash_state * /* hash_state_seeded */),
  152. uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
  153. unsigned char stack[(PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N];
  154. unsigned int heights[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT + 1];
  155. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash(
  156. root, auth_path, stack, heights, sk_seed, pub_seed,
  157. leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
  158. }
  159. void PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash_TREE_HEIGHT(
  160. unsigned char *root, unsigned char *auth_path,
  161. const unsigned char *sk_seed, const unsigned char *pub_seed,
  162. uint32_t leaf_idx, uint32_t idx_offset,
  163. void (*gen_leaf)(
  164. unsigned char * /* leaf */,
  165. const unsigned char * /* sk_seed */,
  166. const unsigned char * /* pub_seed */,
  167. uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
  168. const hash_state * /* hash_state_seeded */),
  169. uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
  170. unsigned char stack[(PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_N];
  171. unsigned int heights[PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT + 1];
  172. PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_treehash(
  173. root, auth_path, stack, heights, sk_seed, pub_seed,
  174. leaf_idx, idx_offset, PQCLEAN_SPHINCSSHA256128SROBUST_AVX2_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
  175. }