Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 

241 lignes
12 KiB

  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "address.h"
  5. #include "fors.h"
  6. #include "hash.h"
  7. #include "hashx8.h"
  8. #include "thash.h"
  9. #include "thashx8.h"
  10. #include "utils.h"
  11. #include "utilsx8.h"
  12. static void fors_gen_skx8(unsigned char *sk0,
  13. unsigned char *sk1,
  14. unsigned char *sk2,
  15. unsigned char *sk3,
  16. unsigned char *sk4,
  17. unsigned char *sk5,
  18. unsigned char *sk6,
  19. unsigned char *sk7, const unsigned char *sk_seed,
  20. uint32_t fors_leaf_addrx8[8 * 8]) {
  21. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_prf_addrx8(sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7,
  22. sk_seed, fors_leaf_addrx8);
  23. }
  24. static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
  25. const unsigned char *pub_seed,
  26. uint32_t fors_leaf_addr[8],
  27. const hash_state *state_seeded) {
  28. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded);
  29. }
  30. static void fors_sk_to_leafx8(unsigned char *leaf0,
  31. unsigned char *leaf1,
  32. unsigned char *leaf2,
  33. unsigned char *leaf3,
  34. unsigned char *leaf4,
  35. unsigned char *leaf5,
  36. unsigned char *leaf6,
  37. unsigned char *leaf7,
  38. const unsigned char *sk0,
  39. const unsigned char *sk1,
  40. const unsigned char *sk2,
  41. const unsigned char *sk3,
  42. const unsigned char *sk4,
  43. const unsigned char *sk5,
  44. const unsigned char *sk6,
  45. const unsigned char *sk7,
  46. const unsigned char *pub_seed,
  47. uint32_t fors_leaf_addrx8[8 * 8],
  48. const hash_state *state_seeded) {
  49. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thashx8_1(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7,
  50. sk0, sk1, sk2, sk3, sk4, sk5, sk6, sk7,
  51. pub_seed, fors_leaf_addrx8, state_seeded);
  52. }
  53. static void fors_gen_leafx8(unsigned char *leaf0,
  54. unsigned char *leaf1,
  55. unsigned char *leaf2,
  56. unsigned char *leaf3,
  57. unsigned char *leaf4,
  58. unsigned char *leaf5,
  59. unsigned char *leaf6,
  60. unsigned char *leaf7,
  61. const unsigned char *sk_seed,
  62. const unsigned char *pub_seed,
  63. uint32_t addr_idx0,
  64. uint32_t addr_idx1,
  65. uint32_t addr_idx2,
  66. uint32_t addr_idx3,
  67. uint32_t addr_idx4,
  68. uint32_t addr_idx5,
  69. uint32_t addr_idx6,
  70. uint32_t addr_idx7,
  71. const uint32_t fors_tree_addr[8],
  72. const hash_state *state_seeded) {
  73. uint32_t fors_leaf_addrx8[8 * 8] = {0};
  74. unsigned int j;
  75. /* Only copy the parts that must be kept in fors_leaf_addrx8. */
  76. for (j = 0; j < 8; j++) {
  77. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr(fors_leaf_addrx8 + j * 8, fors_tree_addr);
  78. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type(fors_leaf_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE);
  79. }
  80. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 0 * 8, addr_idx0);
  81. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 1 * 8, addr_idx1);
  82. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 2 * 8, addr_idx2);
  83. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 3 * 8, addr_idx3);
  84. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 4 * 8, addr_idx4);
  85. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 5 * 8, addr_idx5);
  86. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 6 * 8, addr_idx6);
  87. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_leaf_addrx8 + 7 * 8, addr_idx7);
  88. fors_gen_skx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7,
  89. sk_seed, fors_leaf_addrx8);
  90. fors_sk_to_leafx8(leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7,
  91. leaf0, leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7,
  92. pub_seed, fors_leaf_addrx8, state_seeded);
  93. }
  94. /**
  95. * Interprets m as PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT-bit unsigned integers.
  96. * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES bits.
  97. * Assumes indices has space for PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES integers.
  98. */
  99. static void message_to_indices(uint32_t *indices, const unsigned char *m) {
  100. unsigned int i, j;
  101. unsigned int offset = 0;
  102. for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES; i++) {
  103. indices[i] = 0;
  104. for (j = 0; j < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT; j++) {
  105. indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j;
  106. offset++;
  107. }
  108. }
  109. }
  110. /**
  111. * Signs a message m, deriving the secret key from sk_seed and the FTS address.
  112. * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES bits.
  113. */
  114. void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_fors_sign(
  115. unsigned char *sig, unsigned char *pk,
  116. const unsigned char *m,
  117. const unsigned char *sk_seed, const unsigned char *pub_seed,
  118. const uint32_t fors_addr[8],
  119. const hash_state *state_seeded) {
  120. /* Round up to multiple of 8 to prevent out-of-bounds for x8 parallelism */
  121. uint32_t indices[(PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES + 7) & ~7] = {0};
  122. unsigned char roots[((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES + 7) & ~7) * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N];
  123. /* Sign to a buffer, since we may not have a nice multiple of 8 and would
  124. otherwise overrun the signature. */
  125. unsigned char sigbufx8[8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT)];
  126. uint32_t fors_tree_addrx8[8 * 8] = {0};
  127. uint32_t fors_pk_addr[8] = {0};
  128. uint32_t idx_offset[8] = {0};
  129. unsigned int i, j;
  130. for (j = 0; j < 8; j++) {
  131. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addrx8 + j * 8, fors_addr);
  132. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type(fors_tree_addrx8 + j * 8, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE);
  133. }
  134. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr);
  135. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSPK);
  136. message_to_indices(indices, m);
  137. for (i = 0; i < ((PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES + 7) & ~0x7); i += 8) {
  138. for (j = 0; j < 8; j++) {
  139. if (i + j < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES) {
  140. idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT);
  141. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_height(fors_tree_addrx8 + j * 8, 0);
  142. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_tree_addrx8 + j * 8,
  143. indices[i + j] + idx_offset[j]);
  144. }
  145. }
  146. /* Include the secret key part that produces the selected leaf nodes. */
  147. fors_gen_skx8(sigbufx8 + 0 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N,
  148. sigbufx8 + 1 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N,
  149. sigbufx8 + 2 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N,
  150. sigbufx8 + 3 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N,
  151. sigbufx8 + 4 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N,
  152. sigbufx8 + 5 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N,
  153. sigbufx8 + 6 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N,
  154. sigbufx8 + 7 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N,
  155. sk_seed, fors_tree_addrx8);
  156. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_treehashx8_FORS_HEIGHT(
  157. roots + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, sk_seed, pub_seed,
  158. &indices[i], idx_offset, fors_gen_leafx8, fors_tree_addrx8,
  159. state_seeded);
  160. for (j = 0; j < 8; j++) {
  161. if (i + j < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES) {
  162. memcpy(sig, sigbufx8 + j * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N);
  163. memcpy(sig + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N,
  164. sigbufx8 + 8 * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N + j * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT,
  165. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT);
  166. sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N * (1 + PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT);
  167. }
  168. }
  169. }
  170. /* Hash horizontally across all tree roots to derive the public key. */
  171. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded);
  172. }
  173. /**
  174. * Derives the FORS public key from a signature.
  175. * This can be used for verification by comparing to a known public key, or to
  176. * subsequently verify a signature on the derived public key. The latter is the
  177. * typical use-case when used as an FTS below an OTS in a hypertree.
  178. * Assumes m contains at least PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES bits.
  179. */
  180. void PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_fors_pk_from_sig(unsigned char *pk,
  181. const unsigned char *sig, const unsigned char *m,
  182. const unsigned char *pub_seed,
  183. const uint32_t fors_addr[8],
  184. const hash_state *state_seeded) {
  185. uint32_t indices[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES];
  186. unsigned char roots[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N];
  187. unsigned char leaf[PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N];
  188. uint32_t fors_tree_addr[8] = {0};
  189. uint32_t fors_pk_addr[8] = {0};
  190. uint32_t idx_offset;
  191. unsigned int i;
  192. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr);
  193. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr);
  194. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSTREE);
  195. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_ADDR_TYPE_FORSPK);
  196. message_to_indices(indices, m);
  197. for (i = 0; i < PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_TREES; i++) {
  198. idx_offset = i * (1 << PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT);
  199. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_height(fors_tree_addr, 0);
  200. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset);
  201. /* Derive the leaf from the included secret key part. */
  202. fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded);
  203. sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N;
  204. /* Derive the corresponding root node of this tree. */
  205. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N, leaf, indices[i], idx_offset,
  206. sig, PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr, state_seeded);
  207. sig += PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_N * PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_FORS_HEIGHT;
  208. }
  209. /* Hash horizontally across all tree roots to derive the public key. */
  210. PQCLEAN_SPHINCSSHA256192FSIMPLE_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded);
  211. }