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.
 
 
 

193 line
7.2 KiB

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