您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

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