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.
 
 
 

162 rivejä
7.5 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 "hash_state.h"
  8. #include "thash.h"
  9. #include "utils.h"
  10. static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
  11. uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) {
  12. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_prf_addr(
  13. sk, sk_seed, fors_leaf_addr, hash_state_seeded);
  14. }
  15. static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
  16. const unsigned char *pub_seed,
  17. uint32_t fors_leaf_addr[8],
  18. const hash_state *hash_state_seeded) {
  19. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_1(
  20. leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded);
  21. }
  22. static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
  23. const unsigned char *pub_seed,
  24. uint32_t addr_idx, const uint32_t fors_tree_addr[8],
  25. const hash_state *hash_state_seeded) {
  26. uint32_t fors_leaf_addr[8] = {0};
  27. /* Only copy the parts that must be kept in fors_leaf_addr. */
  28. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr(
  29. fors_leaf_addr, fors_tree_addr);
  30. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type(
  31. fors_leaf_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSTREE);
  32. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index(
  33. fors_leaf_addr, addr_idx);
  34. fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded);
  35. fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded);
  36. }
  37. /**
  38. * Interprets m as PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT-bit unsigned integers.
  39. * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES bits.
  40. * Assumes indices has space for PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES integers.
  41. */
  42. static void message_to_indices(uint32_t *indices, const unsigned char *m) {
  43. unsigned int i, j;
  44. unsigned int offset = 0;
  45. for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES; i++) {
  46. indices[i] = 0;
  47. for (j = 0; j < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT; j++) {
  48. indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j;
  49. offset++;
  50. }
  51. }
  52. }
  53. /**
  54. * Signs a message m, deriving the secret key from sk_seed and the FTS address.
  55. * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES bits.
  56. */
  57. void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_fors_sign(
  58. unsigned char *sig, unsigned char *pk,
  59. const unsigned char *m,
  60. const unsigned char *sk_seed, const unsigned char *pub_seed,
  61. const uint32_t fors_addr[8], const hash_state *hash_state_seeded) {
  62. uint32_t indices[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES];
  63. unsigned char roots[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N];
  64. uint32_t fors_tree_addr[8] = {0};
  65. uint32_t fors_pk_addr[8] = {0};
  66. uint32_t idx_offset;
  67. unsigned int i;
  68. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr(
  69. fors_tree_addr, fors_addr);
  70. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr(
  71. fors_pk_addr, fors_addr);
  72. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type(
  73. fors_tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSTREE);
  74. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type(
  75. fors_pk_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSPK);
  76. message_to_indices(indices, m);
  77. for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES; i++) {
  78. idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT);
  79. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_height(
  80. fors_tree_addr, 0);
  81. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index(
  82. fors_tree_addr, indices[i] + idx_offset);
  83. /* Include the secret key part that produces the selected leaf node. */
  84. fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded);
  85. sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N;
  86. /* Compute the authentication path for this leaf node. */
  87. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_treehash_FORS_HEIGHT(
  88. roots + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, sig, sk_seed, pub_seed,
  89. indices[i], idx_offset, fors_gen_leaf, fors_tree_addr,
  90. hash_state_seeded);
  91. sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT;
  92. }
  93. /* Hash horizontally across all tree roots to derive the public key. */
  94. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_FORS_TREES(
  95. pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
  96. }
  97. /**
  98. * Derives the FORS public key from a signature.
  99. * This can be used for verification by comparing to a known public key, or to
  100. * subsequently verify a signature on the derived public key. The latter is the
  101. * typical use-case when used as an FTS below an OTS in a hypertree.
  102. * Assumes m contains at least PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES bits.
  103. */
  104. void PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_fors_pk_from_sig(
  105. unsigned char *pk,
  106. const unsigned char *sig, const unsigned char *m,
  107. const unsigned char *pub_seed, const uint32_t fors_addr[8],
  108. const hash_state *hash_state_seeded) {
  109. uint32_t indices[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES];
  110. unsigned char roots[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N];
  111. unsigned char leaf[PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N];
  112. uint32_t fors_tree_addr[8] = {0};
  113. uint32_t fors_pk_addr[8] = {0};
  114. uint32_t idx_offset;
  115. unsigned int i;
  116. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr);
  117. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr);
  118. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSTREE);
  119. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_ADDR_TYPE_FORSPK);
  120. message_to_indices(indices, m);
  121. for (i = 0; i < PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_TREES; i++) {
  122. idx_offset = i * (1 << PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT);
  123. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_height(fors_tree_addr, 0);
  124. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset);
  125. /* Derive the leaf from the included secret key part. */
  126. fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded);
  127. sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N;
  128. /* Derive the corresponding root node of this tree. */
  129. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N, leaf, indices[i], idx_offset, sig,
  130. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded);
  131. sig += PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_N * PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_FORS_HEIGHT;
  132. }
  133. /* Hash horizontally across all tree roots to derive the public key. */
  134. PQCLEAN_SPHINCSHARAKA192SROBUST_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
  135. }