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.
 
 
 

207 lignes
11 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 "hashx4.h"
  8. #include "thash.h"
  9. #include "thashx4.h"
  10. #include "utils.h"
  11. #include "utilsx4.h"
  12. static void fors_gen_skx4(unsigned char *sk0,
  13. unsigned char *sk1,
  14. unsigned char *sk2,
  15. unsigned char *sk3, const unsigned char *sk_seed,
  16. uint32_t fors_leaf_addrx4[4 * 8],
  17. const hash_state *state_seeded) {
  18. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_prf_addrx4(sk0, sk1, sk2, sk3, sk_seed, fors_leaf_addrx4, state_seeded);
  19. }
  20. static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
  21. const unsigned char *pub_seed,
  22. uint32_t fors_leaf_addr[8], const hash_state *state_seeded) {
  23. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_1(leaf, sk, pub_seed, fors_leaf_addr, state_seeded);
  24. }
  25. static void fors_sk_to_leafx4(unsigned char *leaf0,
  26. unsigned char *leaf1,
  27. unsigned char *leaf2,
  28. unsigned char *leaf3,
  29. const unsigned char *sk0,
  30. const unsigned char *sk1,
  31. const unsigned char *sk2,
  32. const unsigned char *sk3,
  33. const unsigned char *pub_seed,
  34. uint32_t fors_leaf_addrx4[4 * 8],
  35. const hash_state *state_seeded) {
  36. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thashx4_1(leaf0, leaf1, leaf2, leaf3,
  37. sk0, sk1, sk2, sk3, pub_seed, fors_leaf_addrx4, state_seeded);
  38. }
  39. static void fors_gen_leafx4(unsigned char *leaf0,
  40. unsigned char *leaf1,
  41. unsigned char *leaf2,
  42. unsigned char *leaf3,
  43. const unsigned char *sk_seed,
  44. const unsigned char *pub_seed,
  45. uint32_t addr_idx0,
  46. uint32_t addr_idx1,
  47. uint32_t addr_idx2,
  48. uint32_t addr_idx3,
  49. const uint32_t fors_tree_addr[8],
  50. const hash_state *state_seeded) {
  51. uint32_t fors_leaf_addrx4[4 * 8] = {0};
  52. unsigned int j;
  53. /* Only copy the parts that must be kept in fors_leaf_addrx4. */
  54. for (j = 0; j < 4; j++) {
  55. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr(fors_leaf_addrx4 + j * 8, fors_tree_addr);
  56. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type(fors_leaf_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE);
  57. }
  58. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 0 * 8, addr_idx0);
  59. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 1 * 8, addr_idx1);
  60. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 2 * 8, addr_idx2);
  61. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_leaf_addrx4 + 3 * 8, addr_idx3);
  62. fors_gen_skx4(leaf0, leaf1, leaf2, leaf3, sk_seed, fors_leaf_addrx4, state_seeded);
  63. fors_sk_to_leafx4(leaf0, leaf1, leaf2, leaf3,
  64. leaf0, leaf1, leaf2, leaf3, pub_seed, fors_leaf_addrx4, state_seeded);
  65. }
  66. /**
  67. * Interprets m as PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT-bit unsigned integers.
  68. * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES bits.
  69. * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES integers.
  70. */
  71. static void message_to_indices(uint32_t *indices, const unsigned char *m) {
  72. unsigned int i, j;
  73. unsigned int offset = 0;
  74. for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES; i++) {
  75. indices[i] = 0;
  76. for (j = 0; j < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT; j++) {
  77. indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j;
  78. offset++;
  79. }
  80. }
  81. }
  82. /**
  83. * Signs a message m, deriving the secret key from sk_seed and the FTS address.
  84. * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES bits.
  85. */
  86. void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_fors_sign(unsigned char *sig, unsigned char *pk,
  87. const unsigned char *m,
  88. const unsigned char *sk_seed, const unsigned char *pub_seed,
  89. const uint32_t fors_addr[8], const hash_state *state_seeded) {
  90. /* Round up to multiple of 4 to prevent out-of-bounds for x4 parallelism */
  91. uint32_t indices[(PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES + 3) & ~3] = {0};
  92. unsigned char roots[((PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES + 3) & ~3) * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N];
  93. /* Sign to a buffer, since we may not have a nice multiple of 4 and would
  94. otherwise overrun the signature. */
  95. unsigned char sigbufx4[4 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT)];
  96. uint32_t fors_tree_addrx4[4 * 8] = {0};
  97. uint32_t fors_pk_addr[8] = {0};
  98. uint32_t idx_offset[4] = {0};
  99. unsigned int i, j;
  100. for (j = 0; j < 4; j++) {
  101. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr(fors_tree_addrx4 + j * 8, fors_addr);
  102. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type(fors_tree_addrx4 + j * 8, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE);
  103. }
  104. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr);
  105. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSPK);
  106. message_to_indices(indices, m);
  107. for (i = 0; i < ((PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES + 3) & ~0x3); i += 4) {
  108. for (j = 0; j < 4; j++) {
  109. if (i + j < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES) {
  110. idx_offset[j] = (i + j) * (1 << PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT);
  111. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_height(fors_tree_addrx4 + j * 8, 0);
  112. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_tree_addrx4 + j * 8,
  113. indices[i + j] + idx_offset[j]);
  114. }
  115. }
  116. /* Include the secret key part that produces the selected leaf nodes. */
  117. fors_gen_skx4(sigbufx4 + 0 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N,
  118. sigbufx4 + 1 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N,
  119. sigbufx4 + 2 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N,
  120. sigbufx4 + 3 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N,
  121. sk_seed, fors_tree_addrx4, state_seeded);
  122. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_treehashx4_FORS_HEIGHT(roots + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, sk_seed, pub_seed,
  123. &indices[i], idx_offset, fors_gen_leafx4, fors_tree_addrx4,
  124. state_seeded);
  125. for (j = 0; j < 4; j++) {
  126. if (i + j < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES) {
  127. memcpy(sig, sigbufx4 + j * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N);
  128. memcpy(sig + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N,
  129. sigbufx4 + 4 * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N + j * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT,
  130. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT);
  131. sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N * (1 + PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT);
  132. }
  133. }
  134. }
  135. /* Hash horizontally across all tree roots to derive the public key. */
  136. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded);
  137. }
  138. /**
  139. * Derives the FORS public key from a signature.
  140. * This can be used for verification by comparing to a known public key, or to
  141. * subsequently verify a signature on the derived public key. The latter is the
  142. * typical use-case when used as an FTS below an OTS in a hypertree.
  143. * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES bits.
  144. */
  145. void PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_fors_pk_from_sig(unsigned char *pk,
  146. const unsigned char *sig, const unsigned char *m,
  147. const unsigned char *pub_seed,
  148. const uint32_t fors_addr[8],
  149. const hash_state *state_seeded) {
  150. uint32_t indices[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES];
  151. unsigned char roots[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N];
  152. unsigned char leaf[PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N];
  153. uint32_t fors_tree_addr[8] = {0};
  154. uint32_t fors_pk_addr[8] = {0};
  155. uint32_t idx_offset;
  156. unsigned int i;
  157. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr(fors_tree_addr, fors_addr);
  158. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_copy_keypair_addr(fors_pk_addr, fors_addr);
  159. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSTREE);
  160. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_ADDR_TYPE_FORSPK);
  161. message_to_indices(indices, m);
  162. for (i = 0; i < PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_TREES; i++) {
  163. idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT);
  164. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_height(fors_tree_addr, 0);
  165. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_set_tree_index(fors_tree_addr, indices[i] + idx_offset);
  166. /* Derive the leaf from the included secret key part. */
  167. fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, state_seeded);
  168. sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N;
  169. /* Derive the corresponding root node of this tree. */
  170. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N, leaf, indices[i], idx_offset,
  171. sig, PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT, pub_seed, fors_tree_addr,
  172. state_seeded);
  173. sig += PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_N * PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_FORS_HEIGHT;
  174. }
  175. /* Hash horizontally across all tree roots to derive the public key. */
  176. PQCLEAN_SPHINCSSHAKE256256FROBUST_AVX2_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, state_seeded);
  177. }