mldsa_gh 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +88 -0
  4. data/ext/mldsa_gh_native/extconf.rb +14 -0
  5. data/ext/mldsa_gh_native/mldsa_gh_native.c +222 -0
  6. data/ext/mldsa_gh_native/mldsa_gh_native_all.c +24 -0
  7. data/ext/mldsa_gh_native/mldsa_gh_native_all.h +26 -0
  8. data/ext/mldsa_gh_native/vendor/mldsa-native/BUILDING.md +108 -0
  9. data/ext/mldsa_gh_native/vendor/mldsa-native/LICENSE +305 -0
  10. data/ext/mldsa_gh_native/vendor/mldsa-native/README.md +247 -0
  11. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/README.md +23 -0
  12. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native.c +803 -0
  13. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native.h +956 -0
  14. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native_asm.S +830 -0
  15. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/mldsa_native_config.h +855 -0
  16. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/cbmc.h +233 -0
  17. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/common.h +301 -0
  18. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/context.h +152 -0
  19. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/ct.c +21 -0
  20. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/ct.h +373 -0
  21. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/debug.c +75 -0
  22. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/debug.h +125 -0
  23. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202.c +270 -0
  24. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202.h +224 -0
  25. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202x4.c +187 -0
  26. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/fips202x4.h +125 -0
  27. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.c +510 -0
  28. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.h +110 -0
  29. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/auto.h +85 -0
  30. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/fips202_native_aarch64.h +69 -0
  31. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_aarch64_asm.S +378 -0
  32. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_aarch64_asm.S +207 -0
  33. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_aarch64_asm.S +262 -0
  34. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_aarch64_asm.S +1080 -0
  35. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_aarch64_asm.S +990 -0
  36. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +47 -0
  37. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_scalar.h +27 -0
  38. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_v84a.h +36 -0
  39. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x2_v84a.h +40 -0
  40. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_scalar.h +32 -0
  41. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +37 -0
  42. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/api.h +129 -0
  43. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/README.md +10 -0
  44. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/mve.h +67 -0
  45. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/fips202_native_armv81m.h +37 -0
  46. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +717 -0
  47. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +42 -0
  48. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_state_extract_bytes_mve.S +334 -0
  49. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_state_xor_bytes_mve.S +355 -0
  50. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +53 -0
  51. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/auto.h +35 -0
  52. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/keccak_f1600_x4_avx2.h +34 -0
  53. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/fips202_native_x86_64.h +45 -0
  54. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2_asm.S +488 -0
  55. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccakf1600_constants.c +52 -0
  56. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/meta.h +314 -0
  57. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/aarch64_zetas.c +248 -0
  58. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/arith_native_aarch64.h +367 -0
  59. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_intt_aarch64_asm.S +786 -0
  60. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_ntt_aarch64_asm.S +686 -0
  61. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_pointwise_montgomery_aarch64_asm.S +106 -0
  62. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_caddq_aarch64_asm.S +69 -0
  63. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_chknorm_aarch64_asm.S +76 -0
  64. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_decompose_32_aarch64_asm.S +108 -0
  65. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_decompose_88_aarch64_asm.S +108 -0
  66. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_use_hint_32_aarch64_asm.S +125 -0
  67. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_poly_use_hint_88_aarch64_asm.S +133 -0
  68. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyvecl_pointwise_acc_montgomery_l4_aarch64_asm.S +157 -0
  69. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyvecl_pointwise_acc_montgomery_l5_aarch64_asm.S +173 -0
  70. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyvecl_pointwise_acc_montgomery_l7_aarch64_asm.S +205 -0
  71. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyz_unpack_17_aarch64_asm.S +103 -0
  72. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_polyz_unpack_19_aarch64_asm.S +100 -0
  73. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_rej_uniform_aarch64_asm.S +222 -0
  74. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_rej_uniform_eta2_aarch64_asm.S +170 -0
  75. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/mldsa_rej_uniform_eta4_aarch64_asm.S +163 -0
  76. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_table.c +52 -0
  77. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta_table.c +547 -0
  78. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_table.c +63 -0
  79. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/api.h +617 -0
  80. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/meta.h +24 -0
  81. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/meta.h +323 -0
  82. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/arith_native_x86_64.h +330 -0
  83. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.c +157 -0
  84. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.h +27 -0
  85. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_intt_avx2_asm.S +2333 -0
  86. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_ntt_avx2_asm.S +2405 -0
  87. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_nttunpack_avx2_asm.S +254 -0
  88. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_acc_l4_avx2_asm.S +173 -0
  89. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_acc_l5_avx2_asm.S +189 -0
  90. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_acc_l7_avx2_asm.S +221 -0
  91. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_pointwise_avx2_asm.S +158 -0
  92. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_caddq_avx2_asm.S +199 -0
  93. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_chknorm_avx2_asm.S +176 -0
  94. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_decompose_32_avx2_asm.S +490 -0
  95. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_decompose_88_avx2_asm.S +489 -0
  96. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_use_hint_32_avx2_asm.S +123 -0
  97. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_poly_use_hint_88_avx2_asm.S +125 -0
  98. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_polyz_unpack_17_avx2_asm.S +355 -0
  99. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_polyz_unpack_19_avx2_asm.S +355 -0
  100. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_avx2_asm.S +132 -0
  101. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_eta2_avx2_asm.S +205 -0
  102. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/mldsa_rej_uniform_eta4_avx2_asm.S +176 -0
  103. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_table.c +161 -0
  104. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/packing.c +213 -0
  105. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/packing.h +277 -0
  106. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/params.h +153 -0
  107. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly.c +1066 -0
  108. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly.h +464 -0
  109. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly_kl.c +910 -0
  110. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/poly_kl.h +367 -0
  111. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec.c +509 -0
  112. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec.h +435 -0
  113. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec_lazy.c +311 -0
  114. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/polyvec_lazy.h +652 -0
  115. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/randombytes.h +26 -0
  116. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/reduce.h +144 -0
  117. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/rounding.h +265 -0
  118. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/sign.c +1720 -0
  119. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/sign.h +850 -0
  120. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/symmetric.h +68 -0
  121. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/sys.h +327 -0
  122. data/ext/mldsa_gh_native/vendor/mldsa-native/mldsa/src/zetas.inc +55 -0
  123. data/lib/mldsa/parameter_set.rb +82 -0
  124. data/lib/mldsa/signing_key.rb +147 -0
  125. data/lib/mldsa/verify_key.rb +72 -0
  126. data/lib/mldsa/version.rb +7 -0
  127. data/lib/mldsa_gh.rb +93 -0
  128. metadata +225 -0
@@ -0,0 +1,850 @@
1
+ /*
2
+ * Copyright (c) The mldsa-native project authors
3
+ * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
4
+ */
5
+
6
+ /* References
7
+ * ==========
8
+ *
9
+ * - [FIPS204]
10
+ * FIPS 204 Module-Lattice-Based Digital Signature Standard
11
+ * National Institute of Standards and Technology
12
+ * https://csrc.nist.gov/pubs/fips/204/final
13
+ */
14
+
15
+ #ifndef MLD_SIGN_H
16
+ #define MLD_SIGN_H
17
+
18
+ #include <stddef.h>
19
+ #include "cbmc.h"
20
+ #include "common.h"
21
+ #include "poly.h"
22
+ #include "polyvec.h"
23
+ #include "sys.h"
24
+
25
+ #if defined(MLD_CHECK_APIS)
26
+ /* Include to ensure consistency between internal sign.h
27
+ * and external mldsa_native.h. */
28
+ #include "mldsa_native.h"
29
+
30
+ #if MLDSA_CRYPTO_SECRETKEYBYTES != \
31
+ MLDSA_SECRETKEYBYTES(MLD_CONFIG_PARAMETER_SET)
32
+ #error Mismatch for SECRETKEYBYTES between sign.h and mldsa_native.h
33
+ #endif
34
+
35
+ #if MLDSA_CRYPTO_PUBLICKEYBYTES != \
36
+ MLDSA_PUBLICKEYBYTES(MLD_CONFIG_PARAMETER_SET)
37
+ #error Mismatch for PUBLICKEYBYTES between sign.h and mldsa_native.h
38
+ #endif
39
+
40
+ #if MLDSA_CRYPTO_BYTES != MLDSA_BYTES(MLD_CONFIG_PARAMETER_SET)
41
+ #error Mismatch for BYTES between sign.h and mldsa_native.h
42
+ #endif
43
+
44
+ #endif /* MLD_CHECK_APIS */
45
+
46
+ #define mld_sign_keypair_internal \
47
+ MLD_NAMESPACE_KL(keypair_internal) MLD_CONTEXT_PARAMETERS_3
48
+ #define mld_sign_keypair MLD_NAMESPACE_KL(keypair) MLD_CONTEXT_PARAMETERS_2
49
+ #define mld_sign_signature_internal \
50
+ MLD_NAMESPACE_KL(signature_internal) MLD_CONTEXT_PARAMETERS_8
51
+ #define mld_sign_signature MLD_NAMESPACE_KL(signature) MLD_CONTEXT_PARAMETERS_6
52
+ #define mld_sign_signature_extmu \
53
+ MLD_NAMESPACE_KL(signature_extmu) MLD_CONTEXT_PARAMETERS_3
54
+ #define mld_sign_verify_internal \
55
+ MLD_NAMESPACE_KL(verify_internal) MLD_CONTEXT_PARAMETERS_7
56
+ #define mld_sign_verify MLD_NAMESPACE_KL(verify) MLD_CONTEXT_PARAMETERS_6
57
+ #define mld_sign_verify_extmu \
58
+ MLD_NAMESPACE_KL(verify_extmu) MLD_CONTEXT_PARAMETERS_3
59
+ #define mld_sign_signature_pre_hash_internal \
60
+ MLD_NAMESPACE_KL(signature_pre_hash_internal) MLD_CONTEXT_PARAMETERS_8
61
+ #define mld_sign_verify_pre_hash_internal \
62
+ MLD_NAMESPACE_KL(verify_pre_hash_internal) MLD_CONTEXT_PARAMETERS_7
63
+ #define mld_sign_signature_pre_hash_shake256 \
64
+ MLD_NAMESPACE_KL(signature_pre_hash_shake256) MLD_CONTEXT_PARAMETERS_7
65
+ #define mld_sign_verify_pre_hash_shake256 \
66
+ MLD_NAMESPACE_KL(verify_pre_hash_shake256) MLD_CONTEXT_PARAMETERS_6
67
+ #define mld_prepare_domain_separation_prefix \
68
+ MLD_NAMESPACE_KL(prepare_domain_separation_prefix)
69
+ #define mld_sign_pk_from_sk \
70
+ MLD_NAMESPACE_KL(pk_from_sk) MLD_CONTEXT_PARAMETERS_2
71
+
72
+ /* Hash algorithm constants for domain separation */
73
+ #define MLD_PREHASH_NONE 0
74
+ #define MLD_PREHASH_SHA2_224 1
75
+ #define MLD_PREHASH_SHA2_256 2
76
+ #define MLD_PREHASH_SHA2_384 3
77
+ #define MLD_PREHASH_SHA2_512 4
78
+ #define MLD_PREHASH_SHA2_512_224 5
79
+ #define MLD_PREHASH_SHA2_512_256 6
80
+ #define MLD_PREHASH_SHA3_224 7
81
+ #define MLD_PREHASH_SHA3_256 8
82
+ #define MLD_PREHASH_SHA3_384 9
83
+ #define MLD_PREHASH_SHA3_512 10
84
+ #define MLD_PREHASH_SHAKE_128 11
85
+ #define MLD_PREHASH_SHAKE_256 12
86
+
87
+ #if !defined(MLD_CONFIG_NO_KEYPAIR_API)
88
+ /**
89
+ * Generate a public-private key pair from a seed.
90
+ *
91
+ * When MLD_CONFIG_KEYGEN_PCT is set, performs a Pairwise Consistency Test
92
+ * (PCT) as required by FIPS 140-3 IG.
93
+ *
94
+ * @spec{Implements @[FIPS204, Algorithm 6, ML-DSA.KeyGen_internal].}
95
+ *
96
+ * @param[out] pk Output public key.
97
+ * @param[out] sk Output private key.
98
+ * @param[in] seed Input random seed.
99
+ * @param context Application context. Only present when
100
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
101
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
102
+ *
103
+ * @retval 0 Success.
104
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
105
+ * used and an allocation via
106
+ * MLD_CUSTOM_ALLOC returned NULL.
107
+ * @retval MLD_ERR_RNG_FAIL Random number generation failed
108
+ * during the PCT. Only possible when
109
+ * MLD_CONFIG_KEYGEN_PCT is enabled.
110
+ * @retval MLD_ERR_SIGNING_PAUSED The PCT's signing step was paused by
111
+ * a MLD_CONFIG_SIGN_HOOK_ATTEMPT hook.
112
+ * This should currently never happen:
113
+ * signing hooks require
114
+ * MLD_CONFIG_NO_RANDOMIZED_API, which
115
+ * is incompatible with
116
+ * MLD_CONFIG_KEYGEN_PCT, so the two
117
+ * cannot be enabled simultaneously.
118
+ * @retval MLD_ERR_PCT_FAIL MLD_CONFIG_KEYGEN_PCT is enabled and
119
+ * the PCT check failed.
120
+ */
121
+ MLD_MUST_CHECK_RETURN_VALUE
122
+ MLD_EXTERNAL_API
123
+ int mld_sign_keypair_internal(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
124
+ uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
125
+ const uint8_t seed[MLDSA_SEEDBYTES],
126
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
127
+ __contract__(
128
+ requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
129
+ requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
130
+ requires(memory_no_alias(seed, MLDSA_SEEDBYTES))
131
+ assigns(object_whole(pk))
132
+ assigns(object_whole(sk))
133
+ ensures(return_value == 0 || return_value == MLD_ERR_OUT_OF_MEMORY ||
134
+ return_value == MLD_ERR_RNG_FAIL ||
135
+ return_value == MLD_ERR_SIGNING_PAUSED ||
136
+ return_value == MLD_ERR_PCT_FAIL)
137
+ /* Output buffers on error, per API-CONVENTIONS.md */
138
+ ensures(return_value != 0 ==>
139
+ array_unchanged_or_zeroized_u8(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
140
+ ensures(return_value != 0 ==>
141
+ array_unchanged_or_zeroized_u8(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
142
+ );
143
+
144
+ #if !defined(MLD_CONFIG_CORE_API_ONLY)
145
+ #if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
146
+ /**
147
+ * Generate a public-private key pair.
148
+ *
149
+ * When MLD_CONFIG_KEYGEN_PCT is set, performs a Pairwise Consistency Test
150
+ * (PCT) as required by FIPS 140-3 IG.
151
+ *
152
+ * @spec{Implements @[FIPS204, Algorithm 1, ML-DSA.KeyGen].}
153
+ *
154
+ * @param[out] pk Output public key.
155
+ * @param[out] sk Output private key.
156
+ * @param context Application context. Only present when
157
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
158
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
159
+ *
160
+ * @retval 0 Success.
161
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
162
+ * used and an allocation via
163
+ * MLD_CUSTOM_ALLOC returned NULL.
164
+ * @retval MLD_ERR_RNG_FAIL Random number generation failed.
165
+ * @retval MLD_ERR_SIGNING_PAUSED The PCT's signing step was paused by
166
+ * a MLD_CONFIG_SIGN_HOOK_ATTEMPT hook.
167
+ * This should currently never happen:
168
+ * signing hooks require
169
+ * MLD_CONFIG_NO_RANDOMIZED_API, which
170
+ * is incompatible with
171
+ * MLD_CONFIG_KEYGEN_PCT, so the two
172
+ * cannot be enabled simultaneously.
173
+ * @retval MLD_ERR_PCT_FAIL MLD_CONFIG_KEYGEN_PCT is enabled and
174
+ * the PCT check failed.
175
+ */
176
+ MLD_MUST_CHECK_RETURN_VALUE
177
+ MLD_EXTERNAL_API
178
+ int mld_sign_keypair(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
179
+ uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
180
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
181
+ __contract__(
182
+ requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
183
+ requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
184
+ assigns(object_whole(pk))
185
+ assigns(object_whole(sk))
186
+ ensures(return_value == 0 || return_value == MLD_ERR_OUT_OF_MEMORY ||
187
+ return_value == MLD_ERR_RNG_FAIL ||
188
+ return_value == MLD_ERR_SIGNING_PAUSED ||
189
+ return_value == MLD_ERR_PCT_FAIL)
190
+ /* Output buffers on error, per API-CONVENTIONS.md */
191
+ ensures(return_value != 0 ==>
192
+ array_unchanged_or_zeroized_u8(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
193
+ ensures(return_value != 0 ==>
194
+ array_unchanged_or_zeroized_u8(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
195
+ );
196
+ #endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
197
+ #endif /* !MLD_CONFIG_CORE_API_ONLY */
198
+ #endif /* !MLD_CONFIG_NO_KEYPAIR_API */
199
+
200
+ #if !defined(MLD_CONFIG_NO_SIGN_API)
201
+ /**
202
+ * Compute signature using a caller-supplied random seed and prefix.
203
+ *
204
+ * On error (non-zero return value), the signature buffer sig is zeroized.
205
+ *
206
+ * @spec{Implements @[FIPS204, Algorithm 7, ML-DSA.Sign_internal].}
207
+ *
208
+ * @warning This function does not perform secret key validation.
209
+ * Callers importing serialized keys can use mld_sign_pk_from_sk
210
+ * to validate them before signing.
211
+ *
212
+ * @param[out] sig Pointer to buffer to hold the generated signature of
213
+ * MLDSA_CRYPTO_BYTES bytes.
214
+ * @param[in] m Pointer to message to be signed (when
215
+ * externalmu == 0), or to a precomputed
216
+ * message representative mu (when externalmu != 0).
217
+ * @param mlen Length of m. Must equal MLDSA_CRHBYTES when
218
+ * externalmu != 0.
219
+ * @param[in] pre Pointer to prefix string. Ignored when
220
+ * externalmu != 0.
221
+ * @param prelen Length of prefix string. Ignored when
222
+ * externalmu != 0.
223
+ * @param[in] rnd Random seed.
224
+ * @param[in] sk Bit-packed secret key; assumed to be valid.
225
+ * @param externalmu 0: m/mlen is the raw message; mu = H(tr, pre, m) is
226
+ * computed internally.
227
+ * non-zero: m points to a precomputed mu of
228
+ * MLDSA_CRHBYTES bytes; pre/prelen unused.
229
+ * @param context Application context. Only present when
230
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
231
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
232
+ *
233
+ * @retval 0 Success.
234
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
235
+ * used and an allocation via
236
+ * MLD_CUSTOM_ALLOC returned NULL.
237
+ * @retval MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED The rejection-sampling loop exceeded
238
+ * MLD_CONFIG_MAX_SIGNING_ATTEMPTS
239
+ * iterations.
240
+ * @retval MLD_ERR_SIGNING_PAUSED A MLD_CONFIG_SIGN_HOOK_ATTEMPT hook
241
+ * paused signing; re-invoke to resume.
242
+ */
243
+ MLD_MUST_CHECK_RETURN_VALUE
244
+ MLD_EXTERNAL_API
245
+ int mld_sign_signature_internal(uint8_t sig[MLDSA_CRYPTO_BYTES],
246
+ const uint8_t *m, size_t mlen,
247
+ const uint8_t *pre, size_t prelen,
248
+ const uint8_t rnd[MLDSA_RNDBYTES],
249
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
250
+ int externalmu,
251
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
252
+ __contract__(
253
+ requires(mlen <= MLD_MAX_BUFFER_SIZE)
254
+ requires(prelen <= MLD_MAX_BUFFER_SIZE)
255
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
256
+ requires(memory_no_alias(m, mlen))
257
+ requires(memory_no_alias(rnd, MLDSA_RNDBYTES))
258
+ requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
259
+ requires((externalmu == 0) ==> ((prelen == 0) || memory_no_alias(pre, prelen)))
260
+ requires((externalmu != 0) ==> (mlen == MLDSA_CRHBYTES))
261
+ assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
262
+ ensures(return_value == 0 ||
263
+ return_value == MLD_ERR_OUT_OF_MEMORY ||
264
+ return_value == MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED ||
265
+ return_value == MLD_ERR_SIGNING_PAUSED)
266
+ /* Output buffers on error, per API-CONVENTIONS.md */
267
+ ensures(return_value != 0 ==>
268
+ array_unchanged_or_zeroized_u8(sig, MLDSA_CRYPTO_BYTES)));
269
+
270
+ #if !defined(MLD_CONFIG_CORE_API_ONLY)
271
+ #if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
272
+ /**
273
+ * Compute signature. This function implements the randomized variant of
274
+ * ML-DSA. If you require the deterministic variant, use
275
+ * mld_sign_signature_internal directly.
276
+ *
277
+ * @spec{Implements @[FIPS204, Algorithm 2, ML-DSA.Sign].}
278
+ *
279
+ * @warning This function does not perform secret key validation.
280
+ * Callers importing serialized keys can use mld_sign_pk_from_sk
281
+ * to validate them before signing.
282
+ *
283
+ * @param[out] sig Output signature.
284
+ * @param[in] m Pointer to message to be signed.
285
+ * @param mlen Length of message.
286
+ * @param[in] ctx Pointer to context string. May be NULL if ctxlen == 0.
287
+ * @param ctxlen Length of context string. Should be <= 255.
288
+ * @param[in] sk Bit-packed secret key; assumed to be valid.
289
+ * @param context Application context. Only present when
290
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
291
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
292
+ *
293
+ * @retval 0 Success.
294
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
295
+ * used and an allocation via
296
+ * MLD_CUSTOM_ALLOC returned NULL.
297
+ * @retval MLD_ERR_RNG_FAIL Random number generation failed.
298
+ * @retval MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED The rejection-sampling loop exceeded
299
+ * MLD_CONFIG_MAX_SIGNING_ATTEMPTS
300
+ * iterations.
301
+ * @retval MLD_ERR_SIGNING_PAUSED A MLD_CONFIG_SIGN_HOOK_ATTEMPT hook
302
+ * paused signing; re-invoke to resume.
303
+ * @retval MLD_ERR_INVALID_ARG The context string exceeded 255
304
+ * bytes.
305
+ */
306
+ MLD_MUST_CHECK_RETURN_VALUE
307
+ MLD_EXTERNAL_API
308
+ int mld_sign_signature(uint8_t sig[MLDSA_CRYPTO_BYTES], const uint8_t *m,
309
+ size_t mlen, const uint8_t *ctx, size_t ctxlen,
310
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
311
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
312
+ __contract__(
313
+ requires(mlen <= MLD_MAX_BUFFER_SIZE)
314
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
315
+ requires(memory_no_alias(m, mlen))
316
+ requires(ctxlen <= MLD_MAX_BUFFER_SIZE)
317
+ requires(ctxlen == 0 || memory_no_alias(ctx, ctxlen))
318
+ requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
319
+ assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
320
+ ensures(return_value == 0 || return_value == MLD_ERR_OUT_OF_MEMORY ||
321
+ return_value == MLD_ERR_RNG_FAIL ||
322
+ return_value == MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED ||
323
+ return_value == MLD_ERR_SIGNING_PAUSED ||
324
+ return_value == MLD_ERR_INVALID_ARG)
325
+ ensures((return_value == MLD_ERR_INVALID_ARG) ==> (ctxlen > 255))
326
+ /* Output buffers on error, per API-CONVENTIONS.md */
327
+ ensures(return_value != 0 ==>
328
+ array_unchanged_or_zeroized_u8(sig, MLDSA_CRYPTO_BYTES))
329
+ );
330
+
331
+ /**
332
+ * Compute signature in "external mu" mode: the caller has already computed
333
+ * the message representative mu = SHAKE256(tr || M', 64), where
334
+ * tr = SHAKE256(pk, 64) and M' is the FIPS 204 formatted message (e.g.
335
+ * 0x00 || ctxlen || ctx || msg for pure ML-DSA). This is the randomized
336
+ * variant; for the deterministic variant, use mld_sign_signature_internal
337
+ * directly with externalmu set to non-zero and an all-zero rnd.
338
+ *
339
+ * @spec{Implements @[FIPS204, Algorithm 2, ML-DSA.Sign external mu variant].}
340
+ *
341
+ * @warning This function does not perform secret key validation.
342
+ * Callers importing serialized keys can use mld_sign_pk_from_sk
343
+ * to validate them before signing.
344
+ *
345
+ * @param[out] sig Output signature.
346
+ * @param[in] mu Precomputed message representative.
347
+ * @param[in] sk Bit-packed secret key; assumed to be valid.
348
+ * @param context Application context. Only present when
349
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
350
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
351
+ *
352
+ * @retval 0 Success.
353
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
354
+ * used and an allocation via
355
+ * MLD_CUSTOM_ALLOC returned NULL.
356
+ * @retval MLD_ERR_RNG_FAIL Random number generation failed.
357
+ * @retval MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED The rejection-sampling loop exceeded
358
+ * MLD_CONFIG_MAX_SIGNING_ATTEMPTS
359
+ * iterations.
360
+ * @retval MLD_ERR_SIGNING_PAUSED A MLD_CONFIG_SIGN_HOOK_ATTEMPT hook
361
+ * paused signing; re-invoke to resume.
362
+ */
363
+ MLD_MUST_CHECK_RETURN_VALUE
364
+ MLD_EXTERNAL_API
365
+ int mld_sign_signature_extmu(uint8_t sig[MLDSA_CRYPTO_BYTES],
366
+ const uint8_t mu[MLDSA_CRHBYTES],
367
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
368
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
369
+ __contract__(
370
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
371
+ requires(memory_no_alias(mu, MLDSA_CRHBYTES))
372
+ requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
373
+ assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
374
+ ensures(return_value == 0 || return_value == MLD_ERR_OUT_OF_MEMORY ||
375
+ return_value == MLD_ERR_RNG_FAIL ||
376
+ return_value == MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED ||
377
+ return_value == MLD_ERR_SIGNING_PAUSED)
378
+ /* Output buffers on error, per API-CONVENTIONS.md */
379
+ ensures(return_value != 0 ==>
380
+ array_unchanged_or_zeroized_u8(sig, MLDSA_CRYPTO_BYTES))
381
+ );
382
+
383
+ #endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
384
+ #endif /* !MLD_CONFIG_CORE_API_ONLY */
385
+ #endif /* !MLD_CONFIG_NO_SIGN_API */
386
+
387
+ #if !defined(MLD_CONFIG_NO_VERIFY_API)
388
+ /**
389
+ * Verify signature.
390
+ *
391
+ * @spec{Implements @[FIPS204, Algorithm 8, ML-DSA.Verify_internal].}
392
+ *
393
+ * @param[in] sig Pointer to input signature of
394
+ * MLDSA_CRYPTO_BYTES bytes.
395
+ * @param[in] m Pointer to message (when externalmu == 0), or to a
396
+ * precomputed message representative mu (when
397
+ * externalmu != 0).
398
+ * @param mlen Length of m. Must equal MLDSA_CRHBYTES when
399
+ * externalmu != 0.
400
+ * @param[in] pre Pointer to prefix string. Ignored when externalmu != 0.
401
+ * @param prelen Length of prefix string. Ignored when externalmu != 0.
402
+ * @param[in] pk Bit-packed public key.
403
+ * @param externalmu 0: m/mlen is the raw message; mu = H(H(pk), pre, m) is
404
+ * computed internally.
405
+ * non-zero: m points to a precomputed mu of
406
+ * MLDSA_CRHBYTES bytes; pre/prelen unused.
407
+ * @param context Application context. Only present when
408
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
409
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
410
+ *
411
+ * @retval 0 Success.
412
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
413
+ * used and an allocation via
414
+ * MLD_CUSTOM_ALLOC returned NULL.
415
+ * @retval MLD_ERR_INVALID_SIGNATURE Signature verification failed.
416
+ */
417
+ MLD_MUST_CHECK_RETURN_VALUE
418
+ MLD_EXTERNAL_API
419
+ int mld_sign_verify_internal(const uint8_t sig[MLDSA_CRYPTO_BYTES],
420
+ const uint8_t *m, size_t mlen, const uint8_t *pre,
421
+ size_t prelen,
422
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
423
+ int externalmu,
424
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
425
+ __contract__(
426
+ requires(prelen <= MLD_MAX_BUFFER_SIZE)
427
+ requires(mlen <= MLD_MAX_BUFFER_SIZE)
428
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
429
+ requires(memory_no_alias(m, mlen))
430
+ requires((externalmu == 0) ==> ((prelen == 0) || memory_no_alias(pre, prelen)))
431
+ requires((externalmu != 0) ==> (mlen == MLDSA_CRHBYTES))
432
+ requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
433
+ ensures(return_value == 0 || return_value == MLD_ERR_INVALID_SIGNATURE || return_value == MLD_ERR_OUT_OF_MEMORY)
434
+ );
435
+
436
+ #if !defined(MLD_CONFIG_CORE_API_ONLY)
437
+ /**
438
+ * Verify signature.
439
+ *
440
+ * @spec{Implements @[FIPS204, Algorithm 3, ML-DSA.Verify].}
441
+ *
442
+ * @param[in] sig Pointer to input signature.
443
+ * @param[in] m Pointer to message.
444
+ * @param mlen Length of message.
445
+ * @param[in] ctx Pointer to context string. May be NULL if ctxlen == 0.
446
+ * @param ctxlen Length of context string.
447
+ * @param[in] pk Bit-packed public key.
448
+ * @param context Application context. Only present when
449
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
450
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
451
+ *
452
+ * @retval 0 Success.
453
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
454
+ * used and an allocation via
455
+ * MLD_CUSTOM_ALLOC returned NULL.
456
+ * @retval MLD_ERR_INVALID_SIGNATURE Signature verification failed.
457
+ * @retval MLD_ERR_INVALID_ARG The context string exceeded 255 bytes.
458
+ */
459
+ MLD_MUST_CHECK_RETURN_VALUE
460
+ MLD_EXTERNAL_API
461
+ int mld_sign_verify(const uint8_t sig[MLDSA_CRYPTO_BYTES], const uint8_t *m,
462
+ size_t mlen, const uint8_t *ctx, size_t ctxlen,
463
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
464
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
465
+ __contract__(
466
+ requires(mlen <= MLD_MAX_BUFFER_SIZE)
467
+ requires(ctxlen <= MLD_MAX_BUFFER_SIZE)
468
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
469
+ requires(memory_no_alias(m, mlen))
470
+ requires(ctxlen == 0 || memory_no_alias(ctx, ctxlen))
471
+ requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
472
+ ensures(return_value == 0 || return_value == MLD_ERR_INVALID_SIGNATURE || return_value == MLD_ERR_INVALID_ARG || return_value == MLD_ERR_OUT_OF_MEMORY)
473
+ ensures((return_value == MLD_ERR_INVALID_ARG) ==> (ctxlen > 255))
474
+ );
475
+
476
+ /**
477
+ * Verify signature in "external mu" mode: the caller has already computed
478
+ * the message representative mu = SHAKE256(tr || M', 64), where
479
+ * tr = SHAKE256(pk, 64) and M' is the FIPS 204 formatted message (e.g.
480
+ * 0x00 || ctxlen || ctx || msg for pure ML-DSA). The same mu must have been
481
+ * used at signing time.
482
+ *
483
+ * @spec{Implements @[FIPS204, Algorithm 3, ML-DSA.Verify external mu variant].}
484
+ *
485
+ * @param[in] sig Pointer to input signature.
486
+ * @param[in] mu Precomputed message representative.
487
+ * @param[in] pk Bit-packed public key.
488
+ * @param context Application context. Only present when
489
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
490
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
491
+ *
492
+ * @retval 0 Success.
493
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
494
+ * used and an allocation via
495
+ * MLD_CUSTOM_ALLOC returned NULL.
496
+ * @retval MLD_ERR_INVALID_SIGNATURE Signature verification failed.
497
+ */
498
+ MLD_MUST_CHECK_RETURN_VALUE
499
+ MLD_EXTERNAL_API
500
+ int mld_sign_verify_extmu(const uint8_t sig[MLDSA_CRYPTO_BYTES],
501
+ const uint8_t mu[MLDSA_CRHBYTES],
502
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
503
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
504
+ __contract__( requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
505
+ requires(memory_no_alias(mu, MLDSA_CRHBYTES))
506
+ requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
507
+ ensures(return_value == 0 || return_value == MLD_ERR_INVALID_SIGNATURE || return_value == MLD_ERR_OUT_OF_MEMORY)
508
+ );
509
+
510
+ #endif /* !MLD_CONFIG_CORE_API_ONLY */
511
+ #endif /* !MLD_CONFIG_NO_VERIFY_API */
512
+
513
+ #if !defined(MLD_CONFIG_CORE_API_ONLY)
514
+ #if !defined(MLD_CONFIG_NO_SIGN_API)
515
+ /**
516
+ * Compute signature with pre-hashed message.
517
+ *
518
+ * @spec{Implements @[FIPS204, Algorithm 4, HashML-DSA.Sign].}
519
+ *
520
+ * Supported hash algorithm constants:
521
+ * MLD_PREHASH_SHA2_224, MLD_PREHASH_SHA2_256, MLD_PREHASH_SHA2_384,
522
+ * MLD_PREHASH_SHA2_512, MLD_PREHASH_SHA2_512_224, MLD_PREHASH_SHA2_512_256,
523
+ * MLD_PREHASH_SHA3_224, MLD_PREHASH_SHA3_256, MLD_PREHASH_SHA3_384,
524
+ * MLD_PREHASH_SHA3_512, MLD_PREHASH_SHAKE_128, MLD_PREHASH_SHAKE_256.
525
+ *
526
+ * MLD_PREHASH_NONE is rejected by this API.
527
+ *
528
+ * @warning This is an unstable API that may change in the future. If you need
529
+ * a stable API use mld_sign_signature_pre_hash_shake256.
530
+ *
531
+ * @warning This function does not perform secret key validation.
532
+ * Callers importing serialized keys can use mld_sign_pk_from_sk
533
+ * to validate them before signing.
534
+ *
535
+ * @param[out] sig Output signature.
536
+ * @param[in] ph Pointer to pre-hashed message.
537
+ * @param phlen Length of pre-hashed message. Must match the output
538
+ * length of hashalg (the digest size for SHA-2/SHA-3,
539
+ * 32 bytes for MLD_PREHASH_SHAKE_128, 64 bytes for
540
+ * MLD_PREHASH_SHAKE_256).
541
+ * @param[in] ctx Pointer to context string. May be NULL if ctxlen == 0.
542
+ * @param ctxlen Length of context string.
543
+ * @param[in] rnd Random seed.
544
+ * @param[in] sk Bit-packed secret key; assumed to be valid.
545
+ * @param hashalg Hash algorithm constant (one of MLD_PREHASH_*).
546
+ * @param context Application context. Only present when
547
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
548
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
549
+ *
550
+ * @retval 0 Success.
551
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
552
+ * used and an allocation via
553
+ * MLD_CUSTOM_ALLOC returned NULL.
554
+ * @retval MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED The rejection-sampling loop exceeded
555
+ * MLD_CONFIG_MAX_SIGNING_ATTEMPTS
556
+ * iterations.
557
+ * @retval MLD_ERR_SIGNING_PAUSED A MLD_CONFIG_SIGN_HOOK_ATTEMPT hook
558
+ * paused signing; re-invoke to resume.
559
+ * @retval MLD_ERR_INVALID_ARG The pre-hash algorithm was
560
+ * MLD_PREHASH_NONE or unsupported,
561
+ * phlen did not match the output
562
+ * length of hashalg, or the context
563
+ * string exceeded 255 bytes.
564
+ */
565
+ MLD_MUST_CHECK_RETURN_VALUE
566
+ MLD_EXTERNAL_API
567
+ int mld_sign_signature_pre_hash_internal(
568
+ uint8_t sig[MLDSA_CRYPTO_BYTES], const uint8_t *ph, size_t phlen,
569
+ const uint8_t *ctx, size_t ctxlen, const uint8_t rnd[MLDSA_RNDBYTES],
570
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES], int hashalg,
571
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
572
+ __contract__(
573
+ requires(ctxlen <= MLD_MAX_BUFFER_SIZE)
574
+ requires(phlen <= MLD_MAX_BUFFER_SIZE)
575
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
576
+ requires(memory_no_alias(ph, phlen))
577
+ requires(ctxlen == 0 || memory_no_alias(ctx, ctxlen))
578
+ requires(memory_no_alias(rnd, MLDSA_RNDBYTES))
579
+ requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
580
+ assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
581
+ ensures(return_value == 0 || return_value == MLD_ERR_OUT_OF_MEMORY || return_value == MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED || return_value == MLD_ERR_SIGNING_PAUSED || return_value == MLD_ERR_INVALID_ARG)
582
+ /* Output buffers on error, per API-CONVENTIONS.md */
583
+ ensures(return_value != 0 ==>
584
+ array_unchanged_or_zeroized_u8(sig, MLDSA_CRYPTO_BYTES))
585
+ );
586
+ #endif /* !MLD_CONFIG_NO_SIGN_API */
587
+
588
+ #if !defined(MLD_CONFIG_NO_VERIFY_API)
589
+ /**
590
+ * Verify signature with pre-hashed message.
591
+ *
592
+ * @spec{Implements @[FIPS204, Algorithm 5, HashML-DSA.Verify].}
593
+ *
594
+ * Supported hash algorithm constants:
595
+ * MLD_PREHASH_SHA2_224, MLD_PREHASH_SHA2_256, MLD_PREHASH_SHA2_384,
596
+ * MLD_PREHASH_SHA2_512, MLD_PREHASH_SHA2_512_224, MLD_PREHASH_SHA2_512_256,
597
+ * MLD_PREHASH_SHA3_224, MLD_PREHASH_SHA3_256, MLD_PREHASH_SHA3_384,
598
+ * MLD_PREHASH_SHA3_512, MLD_PREHASH_SHAKE_128, MLD_PREHASH_SHAKE_256.
599
+ *
600
+ * MLD_PREHASH_NONE is rejected by this API.
601
+ *
602
+ * @warning This is an unstable API that may change in the future. If you need
603
+ * a stable API use mld_sign_verify_pre_hash_shake256.
604
+ *
605
+ * @param[in] sig Pointer to input signature.
606
+ * @param[in] ph Pointer to pre-hashed message.
607
+ * @param phlen Length of pre-hashed message. Must match the output
608
+ * length of hashalg (the digest size for SHA-2/SHA-3,
609
+ * 32 bytes for MLD_PREHASH_SHAKE_128, 64 bytes for
610
+ * MLD_PREHASH_SHAKE_256).
611
+ * @param[in] ctx Pointer to context string. May be NULL if ctxlen == 0.
612
+ * @param ctxlen Length of context string.
613
+ * @param[in] pk Bit-packed public key.
614
+ * @param hashalg Hash algorithm constant (one of MLD_PREHASH_*).
615
+ * @param context Application context. Only present when
616
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
617
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
618
+ *
619
+ * @retval 0 Success.
620
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
621
+ * used and an allocation via
622
+ * MLD_CUSTOM_ALLOC returned NULL.
623
+ * @retval MLD_ERR_INVALID_SIGNATURE Signature verification failed.
624
+ * @retval MLD_ERR_INVALID_ARG The pre-hash algorithm was
625
+ * MLD_PREHASH_NONE or unsupported, phlen
626
+ * did not match the output length of
627
+ * hashalg, or the context string exceeded
628
+ * 255 bytes.
629
+ */
630
+ MLD_MUST_CHECK_RETURN_VALUE
631
+ MLD_EXTERNAL_API
632
+ int mld_sign_verify_pre_hash_internal(
633
+ const uint8_t sig[MLDSA_CRYPTO_BYTES], const uint8_t *ph, size_t phlen,
634
+ const uint8_t *ctx, size_t ctxlen,
635
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES], int hashalg,
636
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
637
+ __contract__(
638
+ requires(phlen <= MLD_MAX_BUFFER_SIZE)
639
+ requires(ctxlen <= MLD_MAX_BUFFER_SIZE - 77)
640
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
641
+ requires(memory_no_alias(ph, phlen))
642
+ requires(ctxlen == 0 || memory_no_alias(ctx, ctxlen))
643
+ requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
644
+ ensures(return_value == 0 || return_value == MLD_ERR_INVALID_SIGNATURE || return_value == MLD_ERR_INVALID_ARG || return_value == MLD_ERR_OUT_OF_MEMORY)
645
+ );
646
+ #endif /* !MLD_CONFIG_NO_VERIFY_API */
647
+
648
+ #if !defined(MLD_CONFIG_NO_SIGN_API)
649
+ /**
650
+ * Compute signature with pre-hashed message using SHAKE256. This function
651
+ * computes the SHAKE256 hash of the message internally.
652
+ *
653
+ * @spec{Implements @[FIPS204, Algorithm 4, HashML-DSA.Sign] with SHAKE256 as
654
+ * the pre-hash.}
655
+ *
656
+ * @warning This function does not perform secret key validation.
657
+ * Callers importing serialized keys can use mld_sign_pk_from_sk
658
+ * to validate them before signing.
659
+ *
660
+ * @param[out] sig Output signature.
661
+ * @param[in] m Pointer to message to be hashed and signed.
662
+ * @param mlen Length of message.
663
+ * @param[in] ctx Pointer to context string. May be NULL if ctxlen == 0.
664
+ * @param ctxlen Length of context string.
665
+ * @param[in] rnd Random seed.
666
+ * @param[in] sk Bit-packed secret key; assumed to be valid.
667
+ * @param context Application context. Only present when
668
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
669
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
670
+ *
671
+ * @retval 0 Success.
672
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
673
+ * used and an allocation via
674
+ * MLD_CUSTOM_ALLOC returned NULL.
675
+ * @retval MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED The rejection-sampling loop exceeded
676
+ * MLD_CONFIG_MAX_SIGNING_ATTEMPTS
677
+ * iterations.
678
+ * @retval MLD_ERR_SIGNING_PAUSED A MLD_CONFIG_SIGN_HOOK_ATTEMPT hook
679
+ * paused signing; re-invoke to resume.
680
+ * @retval MLD_ERR_INVALID_ARG The context string exceeded 255
681
+ * bytes.
682
+ */
683
+ MLD_MUST_CHECK_RETURN_VALUE
684
+ MLD_EXTERNAL_API
685
+ int mld_sign_signature_pre_hash_shake256(
686
+ uint8_t sig[MLDSA_CRYPTO_BYTES], const uint8_t *m, size_t mlen,
687
+ const uint8_t *ctx, size_t ctxlen, const uint8_t rnd[MLDSA_RNDBYTES],
688
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
689
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
690
+ __contract__(
691
+ requires(mlen <= MLD_MAX_BUFFER_SIZE)
692
+ requires(ctxlen <= MLD_MAX_BUFFER_SIZE)
693
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
694
+ requires(memory_no_alias(m, mlen))
695
+ requires(ctxlen == 0 || memory_no_alias(ctx, ctxlen))
696
+ requires(memory_no_alias(rnd, MLDSA_RNDBYTES))
697
+ requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
698
+ assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
699
+ ensures(return_value == 0 || return_value == MLD_ERR_OUT_OF_MEMORY || return_value == MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED || return_value == MLD_ERR_SIGNING_PAUSED || return_value == MLD_ERR_INVALID_ARG)
700
+ /* Output buffers on error, per API-CONVENTIONS.md */
701
+ ensures(return_value != 0 ==>
702
+ array_unchanged_or_zeroized_u8(sig, MLDSA_CRYPTO_BYTES))
703
+ );
704
+ #endif /* !MLD_CONFIG_NO_SIGN_API */
705
+
706
+ #if !defined(MLD_CONFIG_NO_VERIFY_API)
707
+ /**
708
+ * Verify signature with pre-hashed message using SHAKE256. This function
709
+ * computes the SHAKE256 hash of the message internally.
710
+ *
711
+ * @spec{Implements @[FIPS204, Algorithm 5, HashML-DSA.Verify] with SHAKE256 as
712
+ * the pre-hash.}
713
+ *
714
+ * @param[in] sig Pointer to input signature.
715
+ * @param[in] m Pointer to message to be hashed and verified.
716
+ * @param mlen Length of message.
717
+ * @param[in] ctx Pointer to context string. May be NULL if ctxlen == 0.
718
+ * @param ctxlen Length of context string.
719
+ * @param[in] pk Bit-packed public key.
720
+ * @param context Application context. Only present when
721
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
722
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
723
+ *
724
+ * @retval 0 Success.
725
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was
726
+ * used and an allocation via
727
+ * MLD_CUSTOM_ALLOC returned NULL.
728
+ * @retval MLD_ERR_INVALID_SIGNATURE Signature verification failed.
729
+ * @retval MLD_ERR_INVALID_ARG The context string exceeded 255 bytes.
730
+ */
731
+ MLD_MUST_CHECK_RETURN_VALUE
732
+ MLD_EXTERNAL_API
733
+ int mld_sign_verify_pre_hash_shake256(
734
+ const uint8_t sig[MLDSA_CRYPTO_BYTES], const uint8_t *m, size_t mlen,
735
+ const uint8_t *ctx, size_t ctxlen,
736
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
737
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
738
+ __contract__(
739
+ requires(mlen <= MLD_MAX_BUFFER_SIZE)
740
+ requires(ctxlen <= MLD_MAX_BUFFER_SIZE - 77)
741
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
742
+ requires(memory_no_alias(m, mlen))
743
+ requires(ctxlen == 0 || memory_no_alias(ctx, ctxlen))
744
+ requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
745
+ ensures(return_value == 0 || return_value == MLD_ERR_INVALID_SIGNATURE || return_value == MLD_ERR_INVALID_ARG || return_value == MLD_ERR_OUT_OF_MEMORY)
746
+ );
747
+ #endif /* !MLD_CONFIG_NO_VERIFY_API */
748
+
749
+ #if !defined(MLD_CONFIG_NO_SIGN_API) || !defined(MLD_CONFIG_NO_VERIFY_API)
750
+ /* Maximum formatted domain separation message length:
751
+ * - Pure ML-DSA: 0x00 || ctxlen || ctx (max 255)
752
+ * - HashML-DSA: 0x01 || ctxlen || ctx (max 255) || oid (11) || ph (max 64) */
753
+ #define MLD_DOMAIN_SEPARATION_MAX_BYTES (2 + 255 + 11 + 64)
754
+
755
+ /**
756
+ * Prepare domain separation prefix for ML-DSA signing.
757
+ *
758
+ * For pure ML-DSA (hashalg == MLD_PREHASH_NONE):
759
+ * Format: 0x00 || ctxlen (1 byte) || ctx.
760
+ *
761
+ * For HashML-DSA (hashalg != MLD_PREHASH_NONE):
762
+ * Format: 0x01 || ctxlen (1 byte) || ctx || oid (11 bytes) || ph.
763
+ *
764
+ * This function is useful for building incremental signing APIs.
765
+ *
766
+ * @spec{For HashML-DSA (hashalg != MLD_PREHASH_NONE), implements
767
+ * @[FIPS204, Algorithm 4, line 23]. For Pure ML-DSA
768
+ * (hashalg == MLD_PREHASH_NONE), implements
769
+ * ```
770
+ * M' <- BytesToBits(IntegerToBytes(0, 1)
771
+ * || IntegerToBytes(|ctx|, 1)
772
+ * || ctx
773
+ * ```
774
+ * which is part of @[FIPS204, Algorithm 2, ML-DSA.Sign, line 10] and
775
+ * @[FIPS204, Algorithm 3, ML-DSA.Verify, line 5].}
776
+ *
777
+ * @param[out] prefix Output domain separation prefix buffer.
778
+ * @param[in] ph Pointer to pre-hashed message (ignored for pure
779
+ * ML-DSA).
780
+ * @param phlen Length of pre-hashed message; must match the output
781
+ * length of hashalg (ignored for pure ML-DSA).
782
+ * @param[in] ctx Pointer to context string. May be NULL if ctxlen == 0.
783
+ * @param ctxlen Length of context string.
784
+ * @param hashalg Hash algorithm constant (MLD_PREHASH_NONE for pure
785
+ * ML-DSA, or MLD_PREHASH_* for HashML-DSA).
786
+ *
787
+ * @return The total length of the formatted prefix, or 0 on error.
788
+ * Errors are:
789
+ * - The context string exceeded 255 bytes.
790
+ * - For HashML-DSA: hashalg was unsupported, ph was NULL, or phlen
791
+ * did not match the output length of hashalg.
792
+ */
793
+ MLD_MUST_CHECK_RETURN_VALUE
794
+ MLD_EXTERNAL_API
795
+ size_t mld_prepare_domain_separation_prefix(
796
+ uint8_t prefix[MLD_DOMAIN_SEPARATION_MAX_BYTES], const uint8_t *ph,
797
+ size_t phlen, const uint8_t *ctx, size_t ctxlen, int hashalg)
798
+ __contract__(
799
+ requires(ctxlen <= 255)
800
+ requires(phlen <= MLD_MAX_BUFFER_SIZE)
801
+ requires(ctxlen == 0 || memory_no_alias(ctx, ctxlen))
802
+ requires(hashalg == MLD_PREHASH_NONE || memory_no_alias(ph, phlen))
803
+ requires(memory_no_alias(prefix, MLD_DOMAIN_SEPARATION_MAX_BYTES))
804
+ assigns(memory_slice(prefix, MLD_DOMAIN_SEPARATION_MAX_BYTES))
805
+ ensures(return_value <= MLD_DOMAIN_SEPARATION_MAX_BYTES)
806
+ );
807
+ #endif /* !MLD_CONFIG_NO_SIGN_API || !MLD_CONFIG_NO_VERIFY_API */
808
+
809
+ #if !defined(MLD_CONFIG_NO_KEYPAIR_API)
810
+ /**
811
+ * Perform basic validity checks on secret key, and derive public key.
812
+ *
813
+ * Referring to the decoding of the secret key `sk=(rho, K, tr, s1, s2, t0)`
814
+ * (cf. @[FIPS204, Algorithm 25, skDecode]), the following checks are
815
+ * performed:
816
+ * - Check that s1 and s2 have coefficients in [-MLDSA_ETA, MLDSA_ETA].
817
+ * - Check that t0 and tr stored in sk match recomputed values.
818
+ *
819
+ * @note This function leaks whether the secret key is valid or invalid
820
+ * through its return value and timing.
821
+ *
822
+ * @param[out] pk Output public key.
823
+ * @param[in] sk Input secret key.
824
+ * @param context Application context. Only present when
825
+ * MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
826
+ * MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
827
+ *
828
+ * @retval 0 Success.
829
+ * @retval MLD_ERR_OUT_OF_MEMORY MLD_CONFIG_CUSTOM_ALLOC_FREE was used and an
830
+ * allocation via MLD_CUSTOM_ALLOC returned NULL.
831
+ * @retval MLD_ERR_INVALID_KEY Secret key validation failed.
832
+ */
833
+ MLD_MUST_CHECK_RETURN_VALUE
834
+ MLD_EXTERNAL_API
835
+ int mld_sign_pk_from_sk(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
836
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
837
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
838
+ __contract__(
839
+ requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
840
+ requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
841
+ assigns(memory_slice(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
842
+ ensures(return_value == 0 || return_value == MLD_ERR_INVALID_KEY || return_value == MLD_ERR_OUT_OF_MEMORY)
843
+ /* Output buffers on error, per API-CONVENTIONS.md */
844
+ ensures(return_value != 0 ==>
845
+ array_unchanged_or_zeroized_u8(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
846
+ );
847
+ #endif /* !MLD_CONFIG_NO_KEYPAIR_API */
848
+ #endif /* !MLD_CONFIG_CORE_API_ONLY */
849
+
850
+ #endif /* !MLD_SIGN_H */