pq_crypto 0.3.2 → 0.5.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 (328) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +56 -0
  3. data/CHANGELOG.md +62 -0
  4. data/GET_STARTED.md +366 -40
  5. data/README.md +76 -233
  6. data/SECURITY.md +107 -82
  7. data/ext/pqcrypto/extconf.rb +169 -87
  8. data/ext/pqcrypto/mldsa_api.h +1 -48
  9. data/ext/pqcrypto/mlkem_api.h +1 -18
  10. data/ext/pqcrypto/pq_externalmu.c +89 -204
  11. data/ext/pqcrypto/pqcrypto_native_api.h +129 -0
  12. data/ext/pqcrypto/pqcrypto_ruby_secure.c +484 -84
  13. data/ext/pqcrypto/pqcrypto_secure.c +203 -78
  14. data/ext/pqcrypto/pqcrypto_secure.h +53 -14
  15. data/ext/pqcrypto/pqcrypto_version.h +7 -0
  16. data/ext/pqcrypto/randombytes.h +9 -0
  17. data/ext/pqcrypto/vendor/.vendored +10 -5
  18. data/ext/pqcrypto/vendor/mldsa-native/BUILDING.md +105 -0
  19. data/ext/pqcrypto/vendor/mldsa-native/LICENSE +286 -0
  20. data/ext/pqcrypto/vendor/mldsa-native/META.yml +24 -0
  21. data/ext/pqcrypto/vendor/mldsa-native/README.md +221 -0
  22. data/ext/pqcrypto/vendor/mldsa-native/SECURITY.md +8 -0
  23. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.c +721 -0
  24. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.h +975 -0
  25. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_asm.S +724 -0
  26. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_config.h +723 -0
  27. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/cbmc.h +166 -0
  28. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/common.h +321 -0
  29. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/ct.c +21 -0
  30. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/ct.h +385 -0
  31. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.c +73 -0
  32. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.h +130 -0
  33. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.c +277 -0
  34. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.h +244 -0
  35. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.c +182 -0
  36. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.h +117 -0
  37. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.c +438 -0
  38. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.h +105 -0
  39. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/auto.h +71 -0
  40. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/fips202_native_aarch64.h +62 -0
  41. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm.S +376 -0
  42. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm.S +204 -0
  43. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm.S +259 -0
  44. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm.S +1077 -0
  45. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm.S +987 -0
  46. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +41 -0
  47. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_scalar.h +26 -0
  48. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_v84a.h +35 -0
  49. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x2_v84a.h +37 -0
  50. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_scalar.h +27 -0
  51. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +36 -0
  52. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/api.h +69 -0
  53. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/README.md +10 -0
  54. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/mve.h +32 -0
  55. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/fips202_native_armv81m.h +20 -0
  56. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +638 -0
  57. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +136 -0
  58. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +52 -0
  59. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/auto.h +29 -0
  60. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.c +488 -0
  61. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.h +16 -0
  62. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/xkcp.h +31 -0
  63. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/meta.h +247 -0
  64. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/aarch64_zetas.c +231 -0
  65. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/arith_native_aarch64.h +150 -0
  66. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/intt.S +753 -0
  67. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l4.S +129 -0
  68. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l5.S +145 -0
  69. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l7.S +177 -0
  70. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/ntt.S +653 -0
  71. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/pointwise_montgomery.S +79 -0
  72. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_caddq_asm.S +53 -0
  73. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_chknorm_asm.S +55 -0
  74. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_32_asm.S +85 -0
  75. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_88_asm.S +85 -0
  76. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_32_asm.S +102 -0
  77. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_88_asm.S +110 -0
  78. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_17_asm.S +72 -0
  79. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_19_asm.S +69 -0
  80. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_table.c +40 -0
  81. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_asm.S +189 -0
  82. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta2_asm.S +135 -0
  83. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta4_asm.S +128 -0
  84. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta_table.c +543 -0
  85. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_table.c +62 -0
  86. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/api.h +649 -0
  87. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/meta.h +23 -0
  88. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/meta.h +315 -0
  89. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/arith_native_x86_64.h +124 -0
  90. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.c +157 -0
  91. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.h +27 -0
  92. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/intt.S +2311 -0
  93. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/ntt.S +2383 -0
  94. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/nttunpack.S +239 -0
  95. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise.S +131 -0
  96. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l4.S +139 -0
  97. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l5.S +155 -0
  98. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l7.S +187 -0
  99. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_caddq_avx2.c +61 -0
  100. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_chknorm_avx2.c +52 -0
  101. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_32_avx2.c +155 -0
  102. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_88_avx2.c +155 -0
  103. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_32_avx2.c +102 -0
  104. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_88_avx2.c +104 -0
  105. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_17_avx2.c +91 -0
  106. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_19_avx2.c +93 -0
  107. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_avx2.c +126 -0
  108. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta2_avx2.c +155 -0
  109. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta4_avx2.c +139 -0
  110. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_table.c +160 -0
  111. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.c +293 -0
  112. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.h +224 -0
  113. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/params.h +77 -0
  114. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.c +991 -0
  115. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.h +393 -0
  116. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.c +946 -0
  117. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.h +360 -0
  118. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.c +877 -0
  119. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.h +725 -0
  120. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/randombytes.h +26 -0
  121. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/reduce.h +139 -0
  122. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/rounding.h +249 -0
  123. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.c +1511 -0
  124. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.h +806 -0
  125. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/symmetric.h +68 -0
  126. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sys.h +268 -0
  127. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/zetas.inc +55 -0
  128. data/ext/pqcrypto/vendor/mlkem-native/BUILDING.md +104 -0
  129. data/ext/pqcrypto/vendor/mlkem-native/LICENSE +294 -0
  130. data/ext/pqcrypto/vendor/mlkem-native/META.yml +30 -0
  131. data/ext/pqcrypto/vendor/mlkem-native/README.md +223 -0
  132. data/ext/pqcrypto/vendor/mlkem-native/RELEASE.md +86 -0
  133. data/ext/pqcrypto/vendor/mlkem-native/SECURITY.md +8 -0
  134. data/ext/pqcrypto/vendor/mlkem-native/mlkem/README.md +23 -0
  135. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.c +660 -0
  136. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.h +538 -0
  137. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_asm.S +681 -0
  138. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_config.h +709 -0
  139. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/cbmc.h +174 -0
  140. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/common.h +274 -0
  141. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/compress.c +717 -0
  142. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/compress.h +688 -0
  143. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/debug.c +64 -0
  144. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/debug.h +128 -0
  145. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202.c +251 -0
  146. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202.h +158 -0
  147. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202x4.c +208 -0
  148. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202x4.h +80 -0
  149. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/keccakf1600.c +463 -0
  150. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/keccakf1600.h +98 -0
  151. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/auto.h +70 -0
  152. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/fips202_native_aarch64.h +69 -0
  153. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm.S +375 -0
  154. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm.S +203 -0
  155. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm.S +258 -0
  156. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm.S +1076 -0
  157. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm.S +986 -0
  158. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +46 -0
  159. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_scalar.h +25 -0
  160. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_v84a.h +34 -0
  161. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x2_v84a.h +35 -0
  162. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_scalar.h +26 -0
  163. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +35 -0
  164. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/api.h +117 -0
  165. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/README.md +10 -0
  166. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/mve.h +79 -0
  167. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/fips202_native_armv81m.h +35 -0
  168. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +667 -0
  169. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +40 -0
  170. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +51 -0
  171. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/state_extract_bytes_x4_mve.S +290 -0
  172. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/state_xor_bytes_x4_mve.S +314 -0
  173. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/auto.h +28 -0
  174. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/keccak_f1600_x4_avx2.h +33 -0
  175. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/fips202_native_x86_64.h +41 -0
  176. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2.S +451 -0
  177. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/keccakf1600_constants.c +51 -0
  178. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.c +622 -0
  179. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.h +156 -0
  180. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.c +446 -0
  181. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.h +326 -0
  182. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/README.md +16 -0
  183. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/meta.h +122 -0
  184. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/aarch64_zetas.c +174 -0
  185. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/arith_native_aarch64.h +177 -0
  186. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/intt.S +628 -0
  187. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/ntt.S +562 -0
  188. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_mulcache_compute_asm.S +127 -0
  189. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_reduce_asm.S +150 -0
  190. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_tobytes_asm.S +117 -0
  191. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_tomont_asm.S +98 -0
  192. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/polyvec_basemul_acc_montgomery_cached_asm_k2.S +261 -0
  193. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/polyvec_basemul_acc_montgomery_cached_asm_k3.S +314 -0
  194. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/polyvec_basemul_acc_montgomery_cached_asm_k4.S +368 -0
  195. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/rej_uniform_asm.S +226 -0
  196. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/rej_uniform_table.c +542 -0
  197. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/api.h +637 -0
  198. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/meta.h +25 -0
  199. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/README.md +11 -0
  200. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/meta.h +128 -0
  201. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/arith_native_riscv64.h +45 -0
  202. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_debug.c +81 -0
  203. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_debug.h +145 -0
  204. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_izetas.inc +27 -0
  205. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_poly.c +805 -0
  206. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_zetas.inc +27 -0
  207. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_zetas_basemul.inc +39 -0
  208. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/README.md +4 -0
  209. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/meta.h +304 -0
  210. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/arith_native_x86_64.h +309 -0
  211. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/compress_consts.c +94 -0
  212. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/compress_consts.h +45 -0
  213. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/consts.c +102 -0
  214. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/consts.h +25 -0
  215. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/intt.S +719 -0
  216. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/mulcache_compute.S +90 -0
  217. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/ntt.S +639 -0
  218. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/nttfrombytes.S +193 -0
  219. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/ntttobytes.S +181 -0
  220. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/nttunpack.S +174 -0
  221. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d10.S +382 -0
  222. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d11.S +448 -0
  223. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d4.S +163 -0
  224. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d5.S +220 -0
  225. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d10.S +228 -0
  226. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d11.S +277 -0
  227. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d4.S +180 -0
  228. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d5.S +192 -0
  229. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/polyvec_basemul_acc_montgomery_cached_asm_k2.S +502 -0
  230. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/polyvec_basemul_acc_montgomery_cached_asm_k3.S +750 -0
  231. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/polyvec_basemul_acc_montgomery_cached_asm_k4.S +998 -0
  232. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/reduce.S +218 -0
  233. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/rej_uniform_asm.S +103 -0
  234. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/rej_uniform_table.c +544 -0
  235. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/tomont.S +155 -0
  236. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/params.h +76 -0
  237. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly.c +572 -0
  238. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly.h +317 -0
  239. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly_k.c +502 -0
  240. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly_k.h +668 -0
  241. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/randombytes.h +60 -0
  242. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sampling.c +362 -0
  243. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sampling.h +118 -0
  244. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/symmetric.h +70 -0
  245. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sys.h +260 -0
  246. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/verify.c +20 -0
  247. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/verify.h +464 -0
  248. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/zetas.inc +30 -0
  249. data/lib/pq_crypto/algorithm_registry.rb +200 -0
  250. data/lib/pq_crypto/hybrid_kem.rb +1 -12
  251. data/lib/pq_crypto/kem.rb +104 -13
  252. data/lib/pq_crypto/pkcs8.rb +387 -0
  253. data/lib/pq_crypto/serialization.rb +1 -14
  254. data/lib/pq_crypto/signature.rb +123 -17
  255. data/lib/pq_crypto/spki.rb +131 -0
  256. data/lib/pq_crypto/version.rb +1 -1
  257. data/lib/pq_crypto.rb +79 -20
  258. data/script/vendor_libs.rb +88 -155
  259. metadata +241 -73
  260. data/ext/pqcrypto/vendor/pqclean/common/aes.c +0 -639
  261. data/ext/pqcrypto/vendor/pqclean/common/aes.h +0 -64
  262. data/ext/pqcrypto/vendor/pqclean/common/compat.h +0 -73
  263. data/ext/pqcrypto/vendor/pqclean/common/crypto_declassify.h +0 -7
  264. data/ext/pqcrypto/vendor/pqclean/common/fips202.c +0 -928
  265. data/ext/pqcrypto/vendor/pqclean/common/fips202.h +0 -166
  266. data/ext/pqcrypto/vendor/pqclean/common/keccak2x/feat.S +0 -168
  267. data/ext/pqcrypto/vendor/pqclean/common/keccak2x/fips202x2.c +0 -684
  268. data/ext/pqcrypto/vendor/pqclean/common/keccak2x/fips202x2.h +0 -60
  269. data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-times4-SIMD256.c +0 -1028
  270. data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-times4-SnP.h +0 -50
  271. data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-unrolling.macros +0 -198
  272. data/ext/pqcrypto/vendor/pqclean/common/keccak4x/Makefile +0 -8
  273. data/ext/pqcrypto/vendor/pqclean/common/keccak4x/Makefile.Microsoft_nmake +0 -8
  274. data/ext/pqcrypto/vendor/pqclean/common/keccak4x/SIMD256-config.h +0 -3
  275. data/ext/pqcrypto/vendor/pqclean/common/keccak4x/align.h +0 -34
  276. data/ext/pqcrypto/vendor/pqclean/common/keccak4x/brg_endian.h +0 -142
  277. data/ext/pqcrypto/vendor/pqclean/common/nistseedexpander.c +0 -101
  278. data/ext/pqcrypto/vendor/pqclean/common/nistseedexpander.h +0 -39
  279. data/ext/pqcrypto/vendor/pqclean/common/randombytes.c +0 -355
  280. data/ext/pqcrypto/vendor/pqclean/common/randombytes.h +0 -27
  281. data/ext/pqcrypto/vendor/pqclean/common/sha2.c +0 -769
  282. data/ext/pqcrypto/vendor/pqclean/common/sha2.h +0 -173
  283. data/ext/pqcrypto/vendor/pqclean/common/sp800-185.c +0 -156
  284. data/ext/pqcrypto/vendor/pqclean/common/sp800-185.h +0 -27
  285. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/LICENSE +0 -5
  286. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/Makefile +0 -19
  287. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/Makefile.Microsoft_nmake +0 -23
  288. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/api.h +0 -18
  289. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/cbd.c +0 -83
  290. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/cbd.h +0 -11
  291. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/indcpa.c +0 -327
  292. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/indcpa.h +0 -22
  293. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/kem.c +0 -164
  294. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/kem.h +0 -23
  295. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/ntt.c +0 -146
  296. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/ntt.h +0 -14
  297. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/params.h +0 -36
  298. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/poly.c +0 -299
  299. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/poly.h +0 -37
  300. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/polyvec.c +0 -188
  301. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/polyvec.h +0 -26
  302. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/reduce.c +0 -41
  303. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/reduce.h +0 -13
  304. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/symmetric-shake.c +0 -71
  305. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/symmetric.h +0 -30
  306. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/verify.c +0 -67
  307. data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/verify.h +0 -13
  308. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/LICENSE +0 -5
  309. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/Makefile +0 -19
  310. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/Makefile.Microsoft_nmake +0 -23
  311. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/api.h +0 -50
  312. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/ntt.c +0 -98
  313. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/ntt.h +0 -10
  314. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/packing.c +0 -261
  315. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/packing.h +0 -31
  316. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/params.h +0 -44
  317. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/poly.c +0 -799
  318. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/poly.h +0 -52
  319. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/polyvec.c +0 -415
  320. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/polyvec.h +0 -65
  321. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/reduce.c +0 -69
  322. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/reduce.h +0 -17
  323. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/rounding.c +0 -92
  324. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/rounding.h +0 -14
  325. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/sign.c +0 -407
  326. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/sign.h +0 -47
  327. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/symmetric-shake.c +0 -26
  328. data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/symmetric.h +0 -34
@@ -0,0 +1,1511 @@
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
+ * - [FIPS140_3_IG]
10
+ * Implementation Guidance for FIPS 140-3 and the Cryptographic Module
11
+ * Validation Program
12
+ * National Institute of Standards and Technology
13
+ * https://csrc.nist.gov/projects/cryptographic-module-validation-program/fips-140-3-ig-announcements
14
+ *
15
+ * - [FIPS204]
16
+ * FIPS 204 Module-Lattice-Based Digital Signature Standard
17
+ * National Institute of Standards and Technology
18
+ * https://csrc.nist.gov/pubs/fips/204/final
19
+ *
20
+ * - [Round3_Spec]
21
+ * CRYSTALS-Dilithium Algorithm Specifications and Supporting Documentation
22
+ * (Version 3.1)
23
+ * Bai, Ducas, Kiltz, Lepoint, Lyubashevsky, Schwabe, Seiler, Stehlé
24
+ * https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf
25
+ */
26
+
27
+ #include "sign.h"
28
+
29
+ #include "cbmc.h"
30
+ #include "ct.h"
31
+ #include "debug.h"
32
+ #include "packing.h"
33
+ #include "poly.h"
34
+ #include "poly_kl.h"
35
+ #include "polyvec.h"
36
+ #include "randombytes.h"
37
+ #include "symmetric.h"
38
+
39
+ /* Parameter set namespacing
40
+ * This is to facilitate building multiple instances
41
+ * of mldsa-native (e.g. with varying parameter sets)
42
+ * within a single compilation unit. */
43
+ #define mld_check_pct MLD_ADD_PARAM_SET(mld_check_pct) MLD_CONTEXT_PARAMETERS_2
44
+ #define mld_sample_s1_s2 MLD_ADD_PARAM_SET(mld_sample_s1_s2)
45
+ #define mld_validate_hash_length MLD_ADD_PARAM_SET(mld_validate_hash_length)
46
+ #define mld_get_hash_oid MLD_ADD_PARAM_SET(mld_get_hash_oid)
47
+ #define mld_H MLD_ADD_PARAM_SET(mld_H)
48
+ #define mld_compute_pack_z MLD_ADD_PARAM_SET(mld_compute_pack_z)
49
+ #define mld_attempt_signature_generation \
50
+ MLD_ADD_PARAM_SET(mld_attempt_signature_generation) MLD_CONTEXT_PARAMETERS_8
51
+ #define mld_compute_t0_t1_tr_from_sk_components \
52
+ MLD_ADD_PARAM_SET(mld_compute_t0_t1_tr_from_sk_components) \
53
+ MLD_CONTEXT_PARAMETERS_7
54
+ /* End of parameter set namespacing */
55
+
56
+
57
+ static int mld_check_pct(uint8_t const pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
58
+ uint8_t const sk[MLDSA_CRYPTO_SECRETKEYBYTES],
59
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
60
+ __contract__(
61
+ requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
62
+ requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
63
+ ensures(return_value == 0
64
+ || return_value == MLD_ERR_FAIL
65
+ || return_value == MLD_ERR_OUT_OF_MEMORY
66
+ || return_value == MLD_ERR_RNG_FAIL)
67
+ );
68
+
69
+ #if defined(MLD_CONFIG_KEYGEN_PCT)
70
+ /*************************************************
71
+ * @[FIPS140_3_IG]
72
+ * (https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf)
73
+ *
74
+ * TE10.35.02: Pair-wise Consistency Test (PCT) for DSA keypairs
75
+ *
76
+ * Purpose: Validates that a generated public/private key pair can correctly
77
+ * sign and verify data. Test performs signature generation using the private
78
+ * key (sk), followed by signature verification using the public key (pk).
79
+ * Returns 0 if the signature was successfully verified, non-zero if it cannot.
80
+ *
81
+ * Note: @[FIPS204] requires that public/private key pairs are to be used only
82
+ * for the calculation and/of verification of digital signatures.
83
+ **************************************************/
84
+ static int mld_check_pct(uint8_t const pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
85
+ uint8_t const sk[MLDSA_CRYPTO_SECRETKEYBYTES],
86
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
87
+ {
88
+ MLD_ALIGN uint8_t message[1] = {0};
89
+ size_t siglen;
90
+ int ret;
91
+ MLD_ALLOC(signature, uint8_t, MLDSA_CRYPTO_BYTES, context);
92
+ MLD_ALLOC(pk_test, uint8_t, MLDSA_CRYPTO_PUBLICKEYBYTES, context);
93
+
94
+ if (signature == NULL || pk_test == NULL)
95
+ {
96
+ ret = MLD_ERR_OUT_OF_MEMORY;
97
+ goto cleanup;
98
+ }
99
+
100
+ /* Copy public key for testing */
101
+ mld_memcpy(pk_test, pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
102
+
103
+ /* Sign a test message using the original secret key */
104
+ ret = mld_sign_signature(signature, &siglen, message, sizeof(message), NULL,
105
+ 0, sk, context);
106
+ if (ret != 0)
107
+ {
108
+ goto cleanup;
109
+ }
110
+
111
+ #if defined(MLD_CONFIG_KEYGEN_PCT_BREAKAGE_TEST)
112
+ /* Deliberately break public key for testing purposes */
113
+ if (mld_break_pct())
114
+ {
115
+ pk_test[0] = ~pk_test[0];
116
+ }
117
+ #endif /* MLD_CONFIG_KEYGEN_PCT_BREAKAGE_TEST */
118
+
119
+ /* Verify the signature using the (potentially corrupted) public key */
120
+ ret = mld_sign_verify(signature, siglen, message, sizeof(message), NULL, 0,
121
+ pk_test, context);
122
+
123
+ cleanup:
124
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
125
+ MLD_FREE(pk_test, uint8_t, MLDSA_CRYPTO_PUBLICKEYBYTES, context);
126
+ MLD_FREE(signature, uint8_t, MLDSA_CRYPTO_BYTES, context);
127
+
128
+ return ret;
129
+ }
130
+ #else /* MLD_CONFIG_KEYGEN_PCT */
131
+ static int mld_check_pct(uint8_t const pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
132
+ uint8_t const sk[MLDSA_CRYPTO_SECRETKEYBYTES],
133
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
134
+ {
135
+ /* Skip PCT */
136
+ ((void)pk);
137
+ ((void)sk);
138
+ #if defined(MLD_CONFIG_CONTEXT_PARAMETER)
139
+ ((void)context);
140
+ #endif
141
+ return 0;
142
+ }
143
+ #endif /* !MLD_CONFIG_KEYGEN_PCT */
144
+
145
+ static void mld_sample_s1_s2(mld_polyvecl *s1, mld_polyveck *s2,
146
+ const uint8_t seed[MLDSA_CRHBYTES])
147
+ __contract__(
148
+ requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
149
+ requires(memory_no_alias(s2, sizeof(mld_polyveck)))
150
+ requires(memory_no_alias(seed, MLDSA_CRHBYTES))
151
+ assigns(object_whole(s1), object_whole(s2))
152
+ ensures(forall(l0, 0, MLDSA_L, array_abs_bound(s1->vec[l0].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
153
+ ensures(forall(k0, 0, MLDSA_K, array_abs_bound(s2->vec[k0].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
154
+ )
155
+ {
156
+ /* Sample short vectors s1 and s2 */
157
+ #if defined(MLD_CONFIG_SERIAL_FIPS202_ONLY)
158
+ int i;
159
+ uint16_t nonce = 0;
160
+ /* Safety: The nonces are at most 14 (MLDSA_L + MLDSA_K - 1), and, hence, the
161
+ * casts are safe. */
162
+ for (i = 0; i < MLDSA_L; i++)
163
+ {
164
+ mld_poly_uniform_eta(&s1->vec[i], seed, (uint8_t)(nonce + i));
165
+ }
166
+ for (i = 0; i < MLDSA_K; i++)
167
+ {
168
+ mld_poly_uniform_eta(&s2->vec[i], seed, (uint8_t)(nonce + MLDSA_L + i));
169
+ }
170
+ #else /* MLD_CONFIG_SERIAL_FIPS202_ONLY */
171
+ #if MLD_CONFIG_PARAMETER_SET == 44
172
+ mld_poly_uniform_eta_4x(&s1->vec[0], &s1->vec[1], &s1->vec[2], &s1->vec[3],
173
+ seed, 0, 1, 2, 3);
174
+ mld_poly_uniform_eta_4x(&s2->vec[0], &s2->vec[1], &s2->vec[2], &s2->vec[3],
175
+ seed, 4, 5, 6, 7);
176
+ #elif MLD_CONFIG_PARAMETER_SET == 65
177
+ mld_poly_uniform_eta_4x(&s1->vec[0], &s1->vec[1], &s1->vec[2], &s1->vec[3],
178
+ seed, 0, 1, 2, 3);
179
+ mld_poly_uniform_eta_4x(&s1->vec[4], &s2->vec[0], &s2->vec[1],
180
+ &s2->vec[2] /* irrelevant */, seed, 4, 5, 6,
181
+ 0xFF /* irrelevant */);
182
+ mld_poly_uniform_eta_4x(&s2->vec[2], &s2->vec[3], &s2->vec[4], &s2->vec[5],
183
+ seed, 7, 8, 9, 10);
184
+ #elif MLD_CONFIG_PARAMETER_SET == 87
185
+ mld_poly_uniform_eta_4x(&s1->vec[0], &s1->vec[1], &s1->vec[2], &s1->vec[3],
186
+ seed, 0, 1, 2, 3);
187
+ mld_poly_uniform_eta_4x(&s1->vec[4], &s1->vec[5], &s1->vec[6],
188
+ &s2->vec[0] /* irrelevant */, seed, 4, 5, 6,
189
+ 0xFF /* irrelevant */);
190
+ mld_poly_uniform_eta_4x(&s2->vec[0], &s2->vec[1], &s2->vec[2], &s2->vec[3],
191
+ seed, 7, 8, 9, 10);
192
+ mld_poly_uniform_eta_4x(&s2->vec[4], &s2->vec[5], &s2->vec[6], &s2->vec[7],
193
+ seed, 11, 12, 13, 14);
194
+ #endif /* MLD_CONFIG_PARAMETER_SET == 87 */
195
+ #endif /* !MLD_CONFIG_SERIAL_FIPS202_ONLY */
196
+ }
197
+
198
+ /*************************************************
199
+ * Name: mld_compute_t0_t1_tr_from_sk_components
200
+ *
201
+ * Description: Computes t0, t1, tr, and pk from secret key components
202
+ * rho, s1, s2. This is the shared computation used by
203
+ * both keygen and generating the public key from the
204
+ * secret key.
205
+ *
206
+ * Arguments: - mld_polyveck *t0: output t0
207
+ * - mld_polyveck *t1: output t1
208
+ * - uint8_t tr[MLDSA_TRBYTES]: output tr
209
+ * - uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES]: output public key
210
+ * - const uint8_t rho[MLDSA_SEEDBYTES]: input rho
211
+ * - const mld_polyvecl *s1: input s1
212
+ * - const mld_polyveck *s2: input s2
213
+ **************************************************/
214
+ MLD_MUST_CHECK_RETURN_VALUE
215
+ static int mld_compute_t0_t1_tr_from_sk_components(
216
+ mld_polyveck *t0, mld_polyveck *t1, uint8_t tr[MLDSA_TRBYTES],
217
+ uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES], const uint8_t rho[MLDSA_SEEDBYTES],
218
+ const mld_polyvecl *s1, const mld_polyveck *s2,
219
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
220
+ __contract__(
221
+ requires(memory_no_alias(t0, sizeof(mld_polyveck)))
222
+ requires(memory_no_alias(t1, sizeof(mld_polyveck)))
223
+ requires(memory_no_alias(tr, MLDSA_TRBYTES))
224
+ requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
225
+ requires(memory_no_alias(rho, MLDSA_SEEDBYTES))
226
+ requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
227
+ requires(memory_no_alias(s2, sizeof(mld_polyveck)))
228
+ requires(forall(l0, 0, MLDSA_L, array_bound(s1->vec[l0].coeffs, 0, MLDSA_N, MLD_POLYETA_UNPACK_LOWER_BOUND, MLDSA_ETA + 1)))
229
+ requires(forall(k0, 0, MLDSA_K, array_bound(s2->vec[k0].coeffs, 0, MLDSA_N, MLD_POLYETA_UNPACK_LOWER_BOUND, MLDSA_ETA + 1)))
230
+ assigns(memory_slice(t0, sizeof(mld_polyveck)))
231
+ assigns(memory_slice(t1, sizeof(mld_polyveck)))
232
+ assigns(memory_slice(tr, MLDSA_TRBYTES))
233
+ assigns(memory_slice(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
234
+ ensures(forall(k1, 0, MLDSA_K, array_bound(t0->vec[k1].coeffs, 0, MLDSA_N, -(1<<(MLDSA_D-1)) + 1, (1<<(MLDSA_D-1)) + 1)))
235
+ ensures(forall(k2, 0, MLDSA_K, array_bound(t1->vec[k2].coeffs, 0, MLDSA_N, 0, 1 << 10)))
236
+ ensures(return_value == 0 || return_value == MLD_ERR_OUT_OF_MEMORY))
237
+ {
238
+ int ret;
239
+ MLD_ALLOC(mat, mld_polymat, 1, context);
240
+ MLD_ALLOC(s1hat, mld_polyvecl, 1, context);
241
+ MLD_ALLOC(t, mld_polyveck, 1, context);
242
+
243
+ if (mat == NULL || s1hat == NULL || t == NULL)
244
+ {
245
+ ret = MLD_ERR_OUT_OF_MEMORY;
246
+ goto cleanup;
247
+ }
248
+
249
+ /* Expand matrix */
250
+ mld_polyvec_matrix_expand(mat, rho);
251
+
252
+ /* Matrix-vector multiplication */
253
+ *s1hat = *s1;
254
+ mld_polyvecl_ntt(s1hat);
255
+ mld_polyvec_matrix_pointwise_montgomery(t, mat, s1hat);
256
+ mld_polyveck_invntt_tomont(t);
257
+
258
+ /* Add error vector s2 */
259
+ mld_polyveck_add(t, s2);
260
+
261
+ /* Reference: The following reduction is not present in the reference
262
+ * implementation. Omitting this reduction requires the output of
263
+ * the invntt to be small enough such that the addition of s2 does
264
+ * not result in absolute values >= MLDSA_Q. While our C, x86_64,
265
+ * and AArch64 invntt implementations produce small enough
266
+ * values for this to work out, it complicates the bounds
267
+ * reasoning. We instead add an additional reduction, and can
268
+ * consequently, relax the bounds requirements for the invntt.
269
+ */
270
+ mld_polyveck_reduce(t);
271
+
272
+ /* Decompose to get t1, t0 */
273
+ mld_polyveck_caddq(t);
274
+ mld_polyveck_power2round(t1, t0, t);
275
+
276
+ /* Pack public key and compute tr */
277
+ mld_pack_pk(pk, rho, t1);
278
+ mld_shake256(tr, MLDSA_TRBYTES, pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
279
+
280
+ ret = 0;
281
+
282
+ cleanup:
283
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
284
+ MLD_FREE(t, mld_polyveck, 1, context);
285
+ MLD_FREE(s1hat, mld_polyvecl, 1, context);
286
+ MLD_FREE(mat, mld_polymat, 1, context);
287
+ return ret;
288
+ }
289
+
290
+ MLD_MUST_CHECK_RETURN_VALUE
291
+ MLD_EXTERNAL_API
292
+ int mld_sign_keypair_internal(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
293
+ uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
294
+ const uint8_t seed[MLDSA_SEEDBYTES],
295
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
296
+ {
297
+ int ret;
298
+ const uint8_t *rho, *rhoprime, *key;
299
+ MLD_ALLOC(seedbuf, uint8_t, 2 * MLDSA_SEEDBYTES + MLDSA_CRHBYTES, context);
300
+ MLD_ALLOC(inbuf, uint8_t, MLDSA_SEEDBYTES + 2, context);
301
+ MLD_ALLOC(tr, uint8_t, MLDSA_TRBYTES, context);
302
+ MLD_ALLOC(s1, mld_polyvecl, 1, context);
303
+ MLD_ALLOC(s2, mld_polyveck, 1, context);
304
+ MLD_ALLOC(t1, mld_polyveck, 1, context);
305
+ MLD_ALLOC(t0, mld_polyveck, 1, context);
306
+
307
+ if (seedbuf == NULL || inbuf == NULL || tr == NULL || s1 == NULL ||
308
+ s2 == NULL || t1 == NULL || t0 == NULL)
309
+ {
310
+ ret = MLD_ERR_OUT_OF_MEMORY;
311
+ goto cleanup;
312
+ }
313
+
314
+ /* Get randomness for rho, rhoprime and key */
315
+ mld_memcpy(inbuf, seed, MLDSA_SEEDBYTES);
316
+ inbuf[MLDSA_SEEDBYTES + 0] = MLDSA_K;
317
+ inbuf[MLDSA_SEEDBYTES + 1] = MLDSA_L;
318
+ mld_shake256(seedbuf, 2 * MLDSA_SEEDBYTES + MLDSA_CRHBYTES, inbuf,
319
+ MLDSA_SEEDBYTES + 2);
320
+ rho = seedbuf;
321
+ rhoprime = rho + MLDSA_SEEDBYTES;
322
+ key = rhoprime + MLDSA_CRHBYTES;
323
+
324
+ /* Constant time: rho is part of the public key and, hence, public. */
325
+ MLD_CT_TESTING_DECLASSIFY(rho, MLDSA_SEEDBYTES);
326
+
327
+ /* Sample s1 and s2 */
328
+ mld_sample_s1_s2(s1, s2, rhoprime);
329
+
330
+ /* Compute t0, t1, tr, and pk from rho, s1, s2 */
331
+ ret = mld_compute_t0_t1_tr_from_sk_components(t0, t1, tr, pk, rho, s1, s2,
332
+ context);
333
+ if (ret != 0)
334
+ {
335
+ goto cleanup;
336
+ }
337
+
338
+ /* Pack secret key */
339
+ mld_pack_sk(sk, rho, tr, key, t0, s1, s2);
340
+
341
+ /* Constant time: pk is the public key, inherently public data */
342
+ MLD_CT_TESTING_DECLASSIFY(pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
343
+
344
+ cleanup:
345
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
346
+ MLD_FREE(t0, mld_polyveck, 1, context);
347
+ MLD_FREE(t1, mld_polyveck, 1, context);
348
+ MLD_FREE(s2, mld_polyveck, 1, context);
349
+ MLD_FREE(s1, mld_polyvecl, 1, context);
350
+ MLD_FREE(tr, uint8_t, MLDSA_TRBYTES, context);
351
+ MLD_FREE(inbuf, uint8_t, MLDSA_SEEDBYTES + 2, context);
352
+ MLD_FREE(seedbuf, uint8_t, 2 * MLDSA_SEEDBYTES + MLDSA_CRHBYTES, context);
353
+
354
+ if (ret != 0)
355
+ {
356
+ return ret;
357
+ }
358
+
359
+ /* Pairwise Consistency Test (PCT) @[FIPS140_3_IG, p.87] */
360
+ /* Do this after freeing all temporaries. */
361
+ return mld_check_pct(pk, sk, context);
362
+ }
363
+
364
+ #if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
365
+ MLD_MUST_CHECK_RETURN_VALUE
366
+ MLD_EXTERNAL_API
367
+ int mld_sign_keypair(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
368
+ uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
369
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
370
+ {
371
+ MLD_ALIGN uint8_t seed[MLDSA_SEEDBYTES];
372
+ int ret;
373
+ if (mld_randombytes(seed, MLDSA_SEEDBYTES) != 0)
374
+ {
375
+ ret = MLD_ERR_RNG_FAIL;
376
+ goto cleanup;
377
+ }
378
+ MLD_CT_TESTING_SECRET(seed, sizeof(seed));
379
+ ret = mld_sign_keypair_internal(pk, sk, seed, context);
380
+
381
+ cleanup:
382
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
383
+ mld_zeroize(seed, sizeof(seed));
384
+ return ret;
385
+ }
386
+ #endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
387
+
388
+ /*************************************************
389
+ * Name: mld_H
390
+ *
391
+ * Description: Abstracts application of SHAKE256 to
392
+ * one, two or three blocks of data,
393
+ * yielding a user-requested size of
394
+ * output.
395
+ *
396
+ * Arguments: - uint8_t *out: pointer to output
397
+ * - size_t outlen: requested output length in bytes
398
+ * - const uint8_t *in1: pointer to input block 1
399
+ * Must NOT be NULL
400
+ * - size_t in1len: length of input in1 bytes
401
+ * - const uint8_t *in2: pointer to input block 2
402
+ * May be NULL if in2len=0, in which case
403
+ * this block is ignored
404
+ * - size_t in2len: length of input in2 bytes
405
+ * - const uint8_t *in3: pointer to input block 3
406
+ * May be NULL if in3len=0, in which case
407
+ * this block is ignored
408
+ * - size_t in3len: length of input in3 bytes
409
+ **************************************************/
410
+ static void mld_H(uint8_t *out, size_t outlen, const uint8_t *in1,
411
+ size_t in1len, const uint8_t *in2, size_t in2len,
412
+ const uint8_t *in3, size_t in3len)
413
+ __contract__(
414
+ requires(in1len <= MLD_MAX_BUFFER_SIZE)
415
+ requires(in2len <= MLD_MAX_BUFFER_SIZE)
416
+ requires(in3len <= MLD_MAX_BUFFER_SIZE)
417
+ requires(outlen <= 8 * SHAKE256_RATE /* somewhat arbitrary bound */)
418
+ requires(memory_no_alias(in1, in1len))
419
+ requires(in2len == 0 || memory_no_alias(in2, in2len))
420
+ requires(in3len == 0 || memory_no_alias(in3, in3len))
421
+ requires(memory_no_alias(out, outlen))
422
+ assigns(memory_slice(out, outlen))
423
+ )
424
+ {
425
+ mld_shake256ctx state;
426
+ mld_shake256_init(&state);
427
+ mld_shake256_absorb(&state, in1, in1len);
428
+ if (in2len != 0)
429
+ {
430
+ mld_shake256_absorb(&state, in2, in2len);
431
+ }
432
+ if (in3len != 0)
433
+ {
434
+ mld_shake256_absorb(&state, in3, in3len);
435
+ }
436
+ mld_shake256_finalize(&state);
437
+ mld_shake256_squeeze(out, outlen, &state);
438
+ mld_shake256_release(&state);
439
+
440
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
441
+ mld_zeroize(&state, sizeof(state));
442
+ }
443
+
444
+ /*************************************************
445
+ * Name: mld_compute_pack_z
446
+ *
447
+ * Description: Computes z = y + s1*c, checks that z has coefficients smaller
448
+ * than MLDSA_GAMMA1 - MLDSA_BETA, and packs z into the
449
+ * signature buffer.
450
+ *
451
+ * Arguments: - uint8_t *sig: output signature
452
+ * - const mld_poly *cp: challenge polynomial
453
+ * - const polyvecl *s1: secret vector s1
454
+ * - const polyvecl *y: masking vector y
455
+ *
456
+ * Returns: - 0: Success (z has coefficients smaller than
457
+ * MLDSA_GAMMA1 - MLDSA_BETA,)
458
+ * - MLD_ERR_FAIL: z rejected (norm check failed)
459
+ * - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is
460
+ * used and an allocation via MLD_CUSTOM_ALLOC returned NULL.
461
+ *
462
+ * Reference: This function is inlined into mld_sign_signature in the
463
+ * reference implementation.
464
+ **************************************************/
465
+ MLD_MUST_CHECK_RETURN_VALUE
466
+ static int mld_compute_pack_z(uint8_t sig[MLDSA_CRYPTO_BYTES],
467
+ const mld_poly *cp, const mld_polyvecl *s1,
468
+ const mld_polyvecl *y, mld_poly *z)
469
+ __contract__(
470
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
471
+ requires(memory_no_alias(cp, sizeof(mld_poly)))
472
+ requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
473
+ requires(memory_no_alias(y, sizeof(mld_polyvecl)))
474
+ requires(memory_no_alias(z, sizeof(mld_poly)))
475
+ requires(array_abs_bound(cp->coeffs, 0, MLDSA_N, MLD_NTT_BOUND))
476
+ requires(forall(k0, 0, MLDSA_L,
477
+ array_bound(y->vec[k0].coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1)))
478
+ requires(forall(k1, 0, MLDSA_L, array_abs_bound(s1->vec[k1].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
479
+ assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
480
+ assigns(memory_slice(z, sizeof(mld_poly)))
481
+ ensures(return_value == 0 || return_value == MLD_ERR_FAIL ||
482
+ return_value == MLD_ERR_OUT_OF_MEMORY)
483
+ )
484
+ {
485
+ unsigned int i;
486
+ uint32_t z_invalid;
487
+ for (i = 0; i < MLDSA_L; i++)
488
+ __loop__(
489
+ assigns(i, memory_slice(z, sizeof(mld_poly)), memory_slice(sig, MLDSA_CRYPTO_BYTES))
490
+ invariant(i <= MLDSA_L)
491
+ decreases(MLDSA_L - i)
492
+ )
493
+ {
494
+ mld_poly_pointwise_montgomery(z, cp, &s1->vec[i]);
495
+ mld_poly_invntt_tomont(z);
496
+ mld_poly_add(z, &y->vec[i]);
497
+ mld_poly_reduce(z);
498
+
499
+ z_invalid = mld_poly_chknorm(z, MLDSA_GAMMA1 - MLDSA_BETA);
500
+ /* Constant time: It is fine (and prohibitively expensive to avoid)
501
+ * to leak the result of the norm check and which polynomial in z caused a
502
+ * rejection. It would even be okay to leak which coefficient led to
503
+ * rejection as the candidate signature will be discarded anyway.
504
+ * See Section 5.5 of @[Round3_Spec]. */
505
+ MLD_CT_TESTING_DECLASSIFY(&z_invalid, sizeof(uint32_t));
506
+ if (z_invalid)
507
+ {
508
+ return MLD_ERR_FAIL; /* reject */
509
+ }
510
+ /* If z is valid, then its coefficients are bounded by
511
+ * MLDSA_GAMMA1 - MLDSA_BETA. This will be needed below
512
+ * to prove the pre-condition of pack_sig_z() */
513
+ mld_assert_abs_bound(z, MLDSA_N, (MLDSA_GAMMA1 - MLDSA_BETA));
514
+
515
+ /* After the norm check, the distribution of each coefficient of z is
516
+ * independent of the secret key and it can, hence, be considered
517
+ * public. It is, hence, okay to immediately pack it into the user-provided
518
+ * signature buffer. */
519
+ mld_pack_sig_z(sig, z, i);
520
+ }
521
+ return 0;
522
+ }
523
+
524
+ /* Reference: The reference implementation does not explicitly check the
525
+ * maximum nonce value, but instead loops indefinitely (even when the nonce
526
+ * would overflow). Internally, sampling of y uses
527
+ * (nonceL), (nonceL+1), ... (nonce*L+L-1).
528
+ * Hence, there are no overflows if nonce < (UINT16_MAX - L)/L.
529
+ * Explicitly checking for this explicitly allows us to prove type-safety.
530
+ * Note that FIPS204 explicitly allows an upper-bound this loop of
531
+ * 814 (< (UINT16_MAX - L)/L) - see @[FIPS204, Appendix C]. */
532
+ #define MLD_NONCE_UB ((UINT16_MAX - MLDSA_L) / MLDSA_L)
533
+
534
+ /*************************************************
535
+ * Name: attempt_signature_generation
536
+ *
537
+ * Description: Attempts to generate a single signature.
538
+ *
539
+ * Arguments: - uint8_t *sig: pointer to output signature
540
+ * - const uint8_t *mu: pointer to message or hash
541
+ * of exactly MLDSA_CRHBYTES bytes
542
+ * - const uint8_t *rhoprime: pointer to randomness seed
543
+ * - uint16_t nonce: current nonce value
544
+ * - const mld_polymat *mat: expanded matrix
545
+ * - const polyvecl *s1: secret vector s1
546
+ * - const polyveck *s2: secret vector s2
547
+ * - const polyveck *t0: vector t0
548
+ *
549
+ * Returns: - 0: Signature generation succeeded
550
+ * - MLD_ERR_FAIL: Signature rejected (norm check failed)
551
+ * - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is
552
+ * used and an allocation via MLD_CUSTOM_ALLOC returned NULL.
553
+ *
554
+ * Reference: This code differs from the reference implementation
555
+ * in that it factors out the core signature generation
556
+ * step into a distinct function here in order to improve
557
+ * efficiency of CBMC proof.
558
+ **************************************************/
559
+ MLD_MUST_CHECK_RETURN_VALUE
560
+ static int mld_attempt_signature_generation(
561
+ uint8_t sig[MLDSA_CRYPTO_BYTES], const uint8_t *mu,
562
+ const uint8_t rhoprime[MLDSA_CRHBYTES], uint16_t nonce, mld_polymat *mat,
563
+ const mld_polyvecl *s1, const mld_polyveck *s2, const mld_polyveck *t0,
564
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
565
+ __contract__(
566
+ requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
567
+ requires(memory_no_alias(mu, MLDSA_CRHBYTES))
568
+ requires(memory_no_alias(rhoprime, MLDSA_CRHBYTES))
569
+ requires(memory_no_alias(mat, sizeof(mld_polymat)))
570
+ requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
571
+ requires(memory_no_alias(s2, sizeof(mld_polyveck)))
572
+ requires(memory_no_alias(t0, sizeof(mld_polyveck)))
573
+ requires(nonce <= MLD_NONCE_UB)
574
+ requires(forall(k1, 0, MLDSA_K, forall(l1, 0, MLDSA_L,
575
+ array_bound(mat->vec[k1].vec[l1].coeffs, 0, MLDSA_N, 0, MLDSA_Q))))
576
+ requires(forall(k2, 0, MLDSA_K, array_abs_bound(t0->vec[k2].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
577
+ requires(forall(k3, 0, MLDSA_L, array_abs_bound(s1->vec[k3].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
578
+ requires(forall(k4, 0, MLDSA_K, array_abs_bound(s2->vec[k4].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
579
+ assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
580
+ ensures(return_value == 0 || return_value == MLD_ERR_FAIL ||
581
+ return_value == MLD_ERR_OUT_OF_MEMORY)
582
+ )
583
+ {
584
+ unsigned int n;
585
+ uint32_t w0_invalid, h_invalid;
586
+ int ret;
587
+ /* TODO: Remove the following workaround for
588
+ * https://github.com/diffblue/cbmc/issues/8813 */
589
+ typedef MLD_UNION_OR_STRUCT
590
+ {
591
+ mld_polyvecl y;
592
+ mld_polyveck h;
593
+ }
594
+ yh_u;
595
+ mld_polyvecl *y;
596
+ mld_polyveck *h;
597
+
598
+ /* TODO: Remove the following workaround for
599
+ * https://github.com/diffblue/cbmc/issues/8813 */
600
+ typedef MLD_UNION_OR_STRUCT
601
+ {
602
+ mld_polyveck w1;
603
+ mld_polyvecl tmp;
604
+ }
605
+ w1tmp_u;
606
+ mld_polyveck *w1;
607
+ mld_polyvecl *tmp;
608
+
609
+ MLD_ALLOC(challenge_bytes, uint8_t, MLDSA_CTILDEBYTES, context);
610
+ MLD_ALLOC(yh, yh_u, 1, context);
611
+ MLD_ALLOC(z, mld_poly, 1, context);
612
+ MLD_ALLOC(w1tmp, w1tmp_u, 1, context);
613
+ MLD_ALLOC(w0, mld_polyveck, 1, context);
614
+ MLD_ALLOC(cp, mld_poly, 1, context);
615
+ MLD_ALLOC(t, mld_poly, 1, context);
616
+
617
+ if (challenge_bytes == NULL || yh == NULL || z == NULL || w1tmp == NULL ||
618
+ w0 == NULL || cp == NULL || t == NULL)
619
+ {
620
+ ret = MLD_ERR_OUT_OF_MEMORY;
621
+ goto cleanup;
622
+ }
623
+ y = &yh->y;
624
+ h = &yh->h;
625
+ w1 = &w1tmp->w1;
626
+ tmp = &w1tmp->tmp;
627
+
628
+ /* Sample intermediate vector y */
629
+ mld_polyvecl_uniform_gamma1(y, rhoprime, nonce);
630
+
631
+ /* Matrix-vector multiplication */
632
+ *tmp = *y;
633
+ mld_polyvecl_ntt(tmp);
634
+ mld_polyvec_matrix_pointwise_montgomery(w0, mat, tmp);
635
+ mld_polyveck_invntt_tomont(w0);
636
+
637
+ /* Decompose w and call the random oracle */
638
+ mld_polyveck_caddq(w0);
639
+ mld_polyveck_decompose(w1, w0);
640
+ mld_polyveck_pack_w1(sig, w1);
641
+
642
+ mld_H(challenge_bytes, MLDSA_CTILDEBYTES, mu, MLDSA_CRHBYTES, sig,
643
+ MLDSA_K * MLDSA_POLYW1_PACKEDBYTES, NULL, 0);
644
+ /* Constant time: Leaking challenge_bytes does not reveal any information
645
+ * about the secret key as H() is modelled as random oracle.
646
+ * This also applies to challenges for rejected signatures.
647
+ * See Section 5.5 of @[Round3_Spec]. */
648
+ MLD_CT_TESTING_DECLASSIFY(challenge_bytes, MLDSA_CTILDEBYTES);
649
+ mld_poly_challenge(cp, challenge_bytes);
650
+ mld_poly_ntt(cp);
651
+
652
+ /* Compute z, reject if it reveals secret */
653
+ ret = mld_compute_pack_z(sig, cp, s1, y, t);
654
+ if (ret)
655
+ {
656
+ goto cleanup;
657
+ }
658
+
659
+ /* Check that subtracting cs2 does not change high bits of w and low bits
660
+ * do not reveal secret information */
661
+ mld_polyveck_pointwise_poly_montgomery(h, cp, s2);
662
+ mld_polyveck_invntt_tomont(h);
663
+ mld_polyveck_sub(w0, h);
664
+ mld_polyveck_reduce(w0);
665
+
666
+ w0_invalid = mld_polyveck_chknorm(w0, MLDSA_GAMMA2 - MLDSA_BETA);
667
+ /* Constant time: w0_invalid may be leaked - see comment for z_invalid. */
668
+ MLD_CT_TESTING_DECLASSIFY(&w0_invalid, sizeof(uint32_t));
669
+ if (w0_invalid)
670
+ {
671
+ ret = MLD_ERR_FAIL; /* reject */
672
+ goto cleanup;
673
+ }
674
+
675
+ /* Compute hints for w1 */
676
+ mld_polyveck_pointwise_poly_montgomery(h, cp, t0);
677
+ mld_polyveck_invntt_tomont(h);
678
+ mld_polyveck_reduce(h);
679
+
680
+ h_invalid = mld_polyveck_chknorm(h, MLDSA_GAMMA2);
681
+ /* Constant time: h_invalid may be leaked - see comment for z_invalid. */
682
+ MLD_CT_TESTING_DECLASSIFY(&h_invalid, sizeof(uint32_t));
683
+ if (h_invalid)
684
+ {
685
+ ret = MLD_ERR_FAIL; /* reject */
686
+ goto cleanup;
687
+ }
688
+
689
+ mld_polyveck_add(w0, h);
690
+
691
+ /* Constant time: At this point all norm checks have passed and we, hence,
692
+ * know that the signature does not leak any secret information.
693
+ * Consequently, any value that can be computed from the signature and public
694
+ * key is considered public.
695
+ * w0 and w1 are public as they can be computed from Az - ct = \alpha w1 + w0.
696
+ * h=c*t0 is public as both c and t0 are public.
697
+ * For a more detailed discussion, refer to https://eprint.iacr.org/2022/1406.
698
+ */
699
+ MLD_CT_TESTING_DECLASSIFY(w0, sizeof(*w0));
700
+ MLD_CT_TESTING_DECLASSIFY(w1, sizeof(*w1));
701
+ n = mld_polyveck_make_hint(h, w0, w1);
702
+ if (n > MLDSA_OMEGA)
703
+ {
704
+ ret = MLD_ERR_FAIL; /* reject */
705
+ goto cleanup;
706
+ }
707
+
708
+ /* All is well - write signature */
709
+ mld_pack_sig_c_h(sig, challenge_bytes, h, n);
710
+ /* Constant time: At this point it is clear that the signature is valid - it
711
+ * can, hence, be considered public. */
712
+ MLD_CT_TESTING_DECLASSIFY(sig, MLDSA_CRYPTO_BYTES);
713
+ ret = 0; /* success */
714
+
715
+ cleanup:
716
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
717
+ MLD_FREE(t, mld_poly, 1, context);
718
+ MLD_FREE(cp, mld_poly, 1, context);
719
+ MLD_FREE(w0, mld_polyveck, 1, context);
720
+ MLD_FREE(w1tmp, w1tmp_u, 1, context);
721
+ MLD_FREE(z, mld_poly, 1, context);
722
+ MLD_FREE(yh, yh_u, 1, context);
723
+ MLD_FREE(challenge_bytes, uint8_t, MLDSA_CTILDEBYTES, context);
724
+
725
+ return ret;
726
+ }
727
+ MLD_MUST_CHECK_RETURN_VALUE
728
+ MLD_EXTERNAL_API
729
+ int mld_sign_signature_internal(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
730
+ const uint8_t *m, size_t mlen,
731
+ const uint8_t *pre, size_t prelen,
732
+ const uint8_t rnd[MLDSA_RNDBYTES],
733
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
734
+ int externalmu,
735
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
736
+ {
737
+ int ret;
738
+ uint8_t *rho, *tr, *key, *mu, *rhoprime;
739
+ uint16_t nonce = 0;
740
+ MLD_ALLOC(seedbuf, uint8_t,
741
+ 2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES + 2 * MLDSA_CRHBYTES, context);
742
+ MLD_ALLOC(mat, mld_polymat, 1, context);
743
+ MLD_ALLOC(s1, mld_polyvecl, 1, context);
744
+ MLD_ALLOC(t0, mld_polyveck, 1, context);
745
+ MLD_ALLOC(s2, mld_polyveck, 1, context);
746
+
747
+ if (seedbuf == NULL || mat == NULL || s1 == NULL || t0 == NULL || s2 == NULL)
748
+ {
749
+ ret = MLD_ERR_OUT_OF_MEMORY;
750
+ goto cleanup;
751
+ }
752
+
753
+ rho = seedbuf;
754
+ tr = rho + MLDSA_SEEDBYTES;
755
+ key = tr + MLDSA_TRBYTES;
756
+ mu = key + MLDSA_SEEDBYTES;
757
+ rhoprime = mu + MLDSA_CRHBYTES;
758
+ mld_unpack_sk(rho, tr, key, t0, s1, s2, sk);
759
+
760
+ if (!externalmu)
761
+ {
762
+ /* Compute mu = CRH(tr, pre, msg) */
763
+ mld_H(mu, MLDSA_CRHBYTES, tr, MLDSA_TRBYTES, pre, prelen, m, mlen);
764
+ }
765
+ else
766
+ {
767
+ /* mu has been provided directly */
768
+ mld_memcpy(mu, m, MLDSA_CRHBYTES);
769
+ }
770
+
771
+ /* Compute rhoprime = CRH(key, rnd, mu) */
772
+ mld_H(rhoprime, MLDSA_CRHBYTES, key, MLDSA_SEEDBYTES, rnd, MLDSA_RNDBYTES, mu,
773
+ MLDSA_CRHBYTES);
774
+
775
+ /* Constant time: rho is part of the public key and, hence, public. */
776
+ MLD_CT_TESTING_DECLASSIFY(rho, MLDSA_SEEDBYTES);
777
+ /* Expand matrix and transform vectors */
778
+ mld_polyvec_matrix_expand(mat, rho);
779
+ mld_polyvecl_ntt(s1);
780
+ mld_polyveck_ntt(s2);
781
+ mld_polyveck_ntt(t0);
782
+
783
+ /* By default, return failure. Flip to success and write output
784
+ * once signature generation succeeds. */
785
+ ret = MLD_ERR_FAIL;
786
+
787
+ /* Reference: This code is re-structured using a while(1), */
788
+ /* with explicit "continue" statements (rather than "goto") */
789
+ /* to implement rejection of invalid signatures. */
790
+ while (1)
791
+ __loop__(
792
+ assigns(nonce, ret, object_whole(siglen), memory_slice(sig, MLDSA_CRYPTO_BYTES))
793
+ invariant(nonce <= MLD_NONCE_UB)
794
+
795
+ /* t0, s1, s2, and mat are initialized above and are NOT changed by this */
796
+ /* loop. We can therefore re-assert their bounds here as part of the */
797
+ /* loop invariant. This makes proof noticeably faster with CBMC */
798
+ invariant(forall(k1, 0, MLDSA_K, forall(l1, 0, MLDSA_L,
799
+ array_bound(mat->vec[k1].vec[l1].coeffs, 0, MLDSA_N, 0, MLDSA_Q))))
800
+ invariant(forall(k2, 0, MLDSA_K, array_abs_bound(t0->vec[k2].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
801
+ invariant(forall(k3, 0, MLDSA_L, array_abs_bound(s1->vec[k3].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
802
+ invariant(forall(k4, 0, MLDSA_K, array_abs_bound(s2->vec[k4].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
803
+ invariant(ret == MLD_ERR_FAIL)
804
+ decreases(MLD_NONCE_UB - nonce)
805
+ )
806
+ {
807
+ /* Reference: this code explicitly checks for exhaustion of nonce */
808
+ /* values to provide predictable termination and results in that case */
809
+ /* Checking here also means that incrementing nonce below can also */
810
+ /* be proven to be type-safe. */
811
+ if (nonce == MLD_NONCE_UB)
812
+ {
813
+ /* Note that ret == MLD_ERR_FAIL by default, so we
814
+ * don't need to set it here. */
815
+ break;
816
+ }
817
+
818
+ ret = mld_attempt_signature_generation(sig, mu, rhoprime, nonce, mat, s1,
819
+ s2, t0, context);
820
+ nonce++;
821
+ if (ret == 0)
822
+ {
823
+ *siglen = MLDSA_CRYPTO_BYTES;
824
+ break;
825
+ }
826
+ else if (ret != MLD_ERR_FAIL)
827
+ {
828
+ /* For failures such as out-of-memory, propagate and exit immediately. */
829
+ break;
830
+ }
831
+
832
+ /* Otherwise, try again. */
833
+ }
834
+
835
+ cleanup:
836
+
837
+ if (ret != 0)
838
+ {
839
+ /* To be on the safe-side, we zeroize the signature buffer. */
840
+ *siglen = 0;
841
+ mld_memset(sig, 0, MLDSA_CRYPTO_BYTES);
842
+ }
843
+
844
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
845
+ MLD_FREE(s2, mld_polyveck, 1, context);
846
+ MLD_FREE(t0, mld_polyveck, 1, context);
847
+ MLD_FREE(s1, mld_polyvecl, 1, context);
848
+ MLD_FREE(mat, mld_polymat, 1, context);
849
+ MLD_FREE(seedbuf, uint8_t,
850
+ 2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES + 2 * MLDSA_CRHBYTES, context);
851
+ return ret;
852
+ }
853
+
854
+ #if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
855
+ MLD_MUST_CHECK_RETURN_VALUE
856
+ MLD_EXTERNAL_API
857
+ int mld_sign_signature(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
858
+ const uint8_t *m, size_t mlen, const uint8_t *ctx,
859
+ size_t ctxlen,
860
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
861
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
862
+ {
863
+ size_t pre_len;
864
+ int ret;
865
+ MLD_ALLOC(pre, uint8_t, MLD_DOMAIN_SEPARATION_MAX_BYTES, context);
866
+ MLD_ALLOC(rnd, uint8_t, MLDSA_RNDBYTES, context);
867
+
868
+ if (pre == NULL || rnd == NULL)
869
+ {
870
+ ret = MLD_ERR_OUT_OF_MEMORY;
871
+ goto cleanup;
872
+ }
873
+
874
+ /* Prepare domain separation prefix for pure ML-DSA */
875
+ pre_len = mld_prepare_domain_separation_prefix(pre, NULL, 0, ctx, ctxlen,
876
+ MLD_PREHASH_NONE);
877
+ if (pre_len == 0)
878
+ {
879
+ ret = MLD_ERR_FAIL;
880
+ goto cleanup;
881
+ }
882
+
883
+ /* Randomized variant of ML-DSA. If you need the deterministic variant,
884
+ * call mld_sign_signature_internal directly with all-zero rnd. */
885
+ if (mld_randombytes(rnd, MLDSA_RNDBYTES) != 0)
886
+ {
887
+ ret = MLD_ERR_RNG_FAIL;
888
+ goto cleanup;
889
+ }
890
+ MLD_CT_TESTING_SECRET(rnd, sizeof(rnd));
891
+
892
+ ret = mld_sign_signature_internal(sig, siglen, m, mlen, pre, pre_len, rnd, sk,
893
+ 0, context);
894
+
895
+ cleanup:
896
+ if (ret != 0)
897
+ {
898
+ /* To be on the safe-side, make sure *siglen and sig have a well-defined
899
+ * value, even in the case of error.
900
+ *
901
+ * If we come from mld_sign_signature_internal, both are redundant,
902
+ * but the error case should not be the norm, and the added cost of the
903
+ * memset insignificant. */
904
+ *siglen = 0;
905
+ mld_memset(sig, 0, MLDSA_CRYPTO_BYTES);
906
+ }
907
+
908
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
909
+ MLD_FREE(rnd, uint8_t, MLDSA_RNDBYTES, context);
910
+ MLD_FREE(pre, uint8_t, MLD_DOMAIN_SEPARATION_MAX_BYTES, context);
911
+
912
+ return ret;
913
+ }
914
+ #endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
915
+
916
+ #if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
917
+ MLD_MUST_CHECK_RETURN_VALUE
918
+ MLD_EXTERNAL_API
919
+ int mld_sign_signature_extmu(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
920
+ const uint8_t mu[MLDSA_CRHBYTES],
921
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
922
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
923
+ {
924
+ MLD_ALIGN uint8_t rnd[MLDSA_RNDBYTES];
925
+ int ret;
926
+
927
+ /* Randomized variant of ML-DSA. If you need the deterministic variant,
928
+ * call mld_sign_signature_internal directly with all-zero rnd. */
929
+ if (mld_randombytes(rnd, MLDSA_RNDBYTES) != 0)
930
+ {
931
+ *siglen = 0;
932
+ ret = MLD_ERR_RNG_FAIL;
933
+ goto cleanup;
934
+ }
935
+ MLD_CT_TESTING_SECRET(rnd, sizeof(rnd));
936
+
937
+ ret = mld_sign_signature_internal(sig, siglen, mu, MLDSA_CRHBYTES, NULL, 0,
938
+ rnd, sk, 1, context);
939
+
940
+ cleanup:
941
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
942
+ mld_zeroize(rnd, sizeof(rnd));
943
+
944
+ return ret;
945
+ }
946
+ #endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
947
+
948
+ #if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
949
+ MLD_MUST_CHECK_RETURN_VALUE
950
+ MLD_EXTERNAL_API
951
+ int mld_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen,
952
+ const uint8_t *ctx, size_t ctxlen,
953
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
954
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
955
+ {
956
+ int ret;
957
+ size_t i;
958
+
959
+ for (i = 0; i < mlen; ++i)
960
+ __loop__(
961
+ assigns(i, object_whole(sm))
962
+ invariant(i <= mlen)
963
+ decreases(mlen - i)
964
+ )
965
+ {
966
+ sm[MLDSA_CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i];
967
+ }
968
+ ret = mld_sign_signature(sm, smlen, sm + MLDSA_CRYPTO_BYTES, mlen, ctx,
969
+ ctxlen, sk, context);
970
+ *smlen += mlen;
971
+ return ret;
972
+ }
973
+ #endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
974
+
975
+ MLD_MUST_CHECK_RETURN_VALUE
976
+ MLD_EXTERNAL_API
977
+ int mld_sign_verify_internal(const uint8_t *sig, size_t siglen,
978
+ const uint8_t *m, size_t mlen, const uint8_t *pre,
979
+ size_t prelen,
980
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
981
+ int externalmu,
982
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
983
+ {
984
+ int ret, cmp;
985
+
986
+ /* TODO: Remove the following workaround for
987
+ * https://github.com/diffblue/cbmc/issues/8813 */
988
+ typedef MLD_UNION_OR_STRUCT
989
+ {
990
+ mld_polyveck t1;
991
+ mld_polyveck w1;
992
+ }
993
+ t1w1_u;
994
+ mld_polyveck *t1;
995
+ mld_polyveck *w1;
996
+
997
+ MLD_ALLOC(buf, uint8_t, (MLDSA_K * MLDSA_POLYW1_PACKEDBYTES), context);
998
+ MLD_ALLOC(rho, uint8_t, MLDSA_SEEDBYTES, context);
999
+ MLD_ALLOC(mu, uint8_t, MLDSA_CRHBYTES, context);
1000
+ MLD_ALLOC(c, uint8_t, MLDSA_CTILDEBYTES, context);
1001
+ MLD_ALLOC(c2, uint8_t, MLDSA_CTILDEBYTES, context);
1002
+ MLD_ALLOC(cp, mld_poly, 1, context);
1003
+ MLD_ALLOC(mat, mld_polymat, 1, context);
1004
+ MLD_ALLOC(z, mld_polyvecl, 1, context);
1005
+ MLD_ALLOC(t1w1, t1w1_u, 1, context);
1006
+ MLD_ALLOC(tmp, mld_polyveck, 1, context);
1007
+ MLD_ALLOC(h, mld_polyveck, 1, context);
1008
+
1009
+ if (buf == NULL || rho == NULL || mu == NULL || c == NULL || c2 == NULL ||
1010
+ cp == NULL || mat == NULL || z == NULL || t1w1 == NULL || tmp == NULL ||
1011
+ h == NULL)
1012
+ {
1013
+ ret = MLD_ERR_OUT_OF_MEMORY;
1014
+ goto cleanup;
1015
+ }
1016
+ t1 = &t1w1->t1;
1017
+ w1 = &t1w1->w1;
1018
+
1019
+ if (siglen != MLDSA_CRYPTO_BYTES)
1020
+ {
1021
+ ret = MLD_ERR_FAIL;
1022
+ goto cleanup;
1023
+ }
1024
+
1025
+ mld_unpack_pk(rho, t1, pk);
1026
+
1027
+ /* mld_unpack_sig and mld_polyvecl_chknorm signal failure through a
1028
+ * single non-zero error code that's not yet aligned with MLD_ERR_XXX.
1029
+ * Map it to MLD_ERR_FAIL explicitly. */
1030
+ if (mld_unpack_sig(c, z, h, sig))
1031
+ {
1032
+ ret = MLD_ERR_FAIL;
1033
+ goto cleanup;
1034
+ }
1035
+ if (mld_polyvecl_chknorm(z, MLDSA_GAMMA1 - MLDSA_BETA))
1036
+ {
1037
+ ret = MLD_ERR_FAIL;
1038
+ goto cleanup;
1039
+ }
1040
+
1041
+ if (!externalmu)
1042
+ {
1043
+ /* Compute CRH(H(rho, t1), pre, msg) */
1044
+ MLD_ALIGN uint8_t hpk[MLDSA_CRHBYTES];
1045
+ mld_H(hpk, MLDSA_TRBYTES, pk, MLDSA_CRYPTO_PUBLICKEYBYTES, NULL, 0, NULL,
1046
+ 0);
1047
+ mld_H(mu, MLDSA_CRHBYTES, hpk, MLDSA_TRBYTES, pre, prelen, m, mlen);
1048
+
1049
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
1050
+ mld_zeroize(hpk, sizeof(hpk));
1051
+ }
1052
+ else
1053
+ {
1054
+ /* mu has been provided directly */
1055
+ mld_memcpy(mu, m, MLDSA_CRHBYTES);
1056
+ }
1057
+
1058
+ /* Matrix-vector multiplication; compute Az - c2^dt1 */
1059
+ mld_poly_challenge(cp, c);
1060
+ mld_poly_ntt(cp);
1061
+ mld_polyveck_shiftl(t1);
1062
+ mld_polyveck_ntt(t1);
1063
+ mld_polyveck_pointwise_poly_montgomery(tmp, cp, t1);
1064
+
1065
+ mld_polyvec_matrix_expand(mat, rho);
1066
+ mld_polyvecl_ntt(z);
1067
+ mld_polyvec_matrix_pointwise_montgomery(w1, mat, z);
1068
+ mld_polyveck_sub(w1, tmp);
1069
+ mld_polyveck_reduce(w1);
1070
+ mld_polyveck_invntt_tomont(w1);
1071
+
1072
+ /* Reconstruct w1 */
1073
+ mld_polyveck_caddq(w1);
1074
+ mld_polyveck_use_hint(tmp, w1, h);
1075
+ mld_polyveck_pack_w1(buf, tmp);
1076
+ /* Call random oracle and verify challenge */
1077
+ mld_H(c2, MLDSA_CTILDEBYTES, mu, MLDSA_CRHBYTES, buf,
1078
+ MLDSA_K * MLDSA_POLYW1_PACKEDBYTES, NULL, 0);
1079
+
1080
+ cmp = mld_ct_memcmp(c, c2, MLDSA_CTILDEBYTES);
1081
+
1082
+ /* Declassify the result of the verification. */
1083
+ MLD_CT_TESTING_DECLASSIFY(&cmp, sizeof(cmp));
1084
+
1085
+ ret = cmp == 0 ? 0 : MLD_ERR_FAIL;
1086
+
1087
+ cleanup:
1088
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
1089
+ MLD_FREE(h, mld_polyveck, 1, context);
1090
+ MLD_FREE(tmp, mld_polyveck, 1, context);
1091
+ MLD_FREE(t1w1, t1w1_u, 1, context);
1092
+ MLD_FREE(z, mld_polyvecl, 1, context);
1093
+ MLD_FREE(mat, mld_polymat, 1, context);
1094
+ MLD_FREE(cp, mld_poly, 1, context);
1095
+ MLD_FREE(c2, uint8_t, MLDSA_CTILDEBYTES, context);
1096
+ MLD_FREE(c, uint8_t, MLDSA_CTILDEBYTES, context);
1097
+ MLD_FREE(mu, uint8_t, MLDSA_CRHBYTES, context);
1098
+ MLD_FREE(rho, uint8_t, MLDSA_SEEDBYTES, context);
1099
+ MLD_FREE(buf, uint8_t, (MLDSA_K * MLDSA_POLYW1_PACKEDBYTES), context);
1100
+ return ret;
1101
+ }
1102
+
1103
+ MLD_MUST_CHECK_RETURN_VALUE
1104
+ MLD_EXTERNAL_API
1105
+ int mld_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m,
1106
+ size_t mlen, const uint8_t *ctx, size_t ctxlen,
1107
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
1108
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
1109
+ {
1110
+ MLD_ALIGN uint8_t pre[MLD_DOMAIN_SEPARATION_MAX_BYTES];
1111
+ size_t pre_len;
1112
+ int ret;
1113
+
1114
+ pre_len = mld_prepare_domain_separation_prefix(pre, NULL, 0, ctx, ctxlen,
1115
+ MLD_PREHASH_NONE);
1116
+ if (pre_len == 0)
1117
+ {
1118
+ ret = MLD_ERR_FAIL;
1119
+ goto cleanup;
1120
+ }
1121
+
1122
+ ret = mld_sign_verify_internal(sig, siglen, m, mlen, pre, pre_len, pk, 0,
1123
+ context);
1124
+
1125
+ cleanup:
1126
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
1127
+ mld_zeroize(pre, sizeof(pre));
1128
+
1129
+ return ret;
1130
+ }
1131
+
1132
+ MLD_MUST_CHECK_RETURN_VALUE
1133
+ MLD_EXTERNAL_API
1134
+ int mld_sign_verify_extmu(const uint8_t *sig, size_t siglen,
1135
+ const uint8_t mu[MLDSA_CRHBYTES],
1136
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
1137
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
1138
+ {
1139
+ return mld_sign_verify_internal(sig, siglen, mu, MLDSA_CRHBYTES, NULL, 0, pk,
1140
+ 1, context);
1141
+ }
1142
+
1143
+ MLD_MUST_CHECK_RETURN_VALUE
1144
+ MLD_EXTERNAL_API
1145
+ int mld_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen,
1146
+ const uint8_t *ctx, size_t ctxlen,
1147
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
1148
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
1149
+ {
1150
+ int ret;
1151
+ size_t i;
1152
+
1153
+ if (smlen < MLDSA_CRYPTO_BYTES)
1154
+ {
1155
+ ret = MLD_ERR_FAIL;
1156
+ goto cleanup;
1157
+ }
1158
+
1159
+ *mlen = smlen - MLDSA_CRYPTO_BYTES;
1160
+ ret = mld_sign_verify(sm, MLDSA_CRYPTO_BYTES, sm + MLDSA_CRYPTO_BYTES, *mlen,
1161
+ ctx, ctxlen, pk, context);
1162
+ if (ret == 0)
1163
+ {
1164
+ /* All good, copy msg, return 0 */
1165
+ for (i = 0; i < *mlen; ++i)
1166
+ __loop__(
1167
+ assigns(i, memory_slice(m, *mlen))
1168
+ invariant(i <= *mlen)
1169
+ decreases(*mlen - i)
1170
+ )
1171
+ {
1172
+ m[i] = sm[MLDSA_CRYPTO_BYTES + i];
1173
+ }
1174
+ }
1175
+
1176
+ cleanup:
1177
+
1178
+ if (ret != 0)
1179
+ {
1180
+ /* To be on the safe-side, we zeroize the message buffer. */
1181
+ *mlen = 0;
1182
+ mld_memset(m, 0, smlen);
1183
+ }
1184
+
1185
+ return ret;
1186
+ }
1187
+
1188
+
1189
+ MLD_MUST_CHECK_RETURN_VALUE
1190
+ MLD_EXTERNAL_API
1191
+ int mld_sign_signature_pre_hash_internal(
1192
+ uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen, const uint8_t *ph,
1193
+ size_t phlen, const uint8_t *ctx, size_t ctxlen,
1194
+ const uint8_t rnd[MLDSA_RNDBYTES],
1195
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES], int hashalg,
1196
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
1197
+ {
1198
+ MLD_ALIGN uint8_t pre[MLD_DOMAIN_SEPARATION_MAX_BYTES];
1199
+ size_t pre_len;
1200
+ int ret;
1201
+
1202
+ pre_len = mld_prepare_domain_separation_prefix(pre, ph, phlen, ctx, ctxlen,
1203
+ hashalg);
1204
+ if (pre_len == 0)
1205
+ {
1206
+ ret = MLD_ERR_FAIL;
1207
+ goto cleanup;
1208
+ }
1209
+
1210
+ ret = mld_sign_signature_internal(sig, siglen, pre, pre_len, NULL, 0, rnd, sk,
1211
+ 0, context);
1212
+ cleanup:
1213
+ if (ret != 0)
1214
+ {
1215
+ /* To be on the safe-side, make sure *siglen and sig have a well-defined
1216
+ * value, even in the case of error.
1217
+ *
1218
+ * If we come from mld_sign_signature_internal, both are redundant,
1219
+ * but the error case should not be the norm, and the added cost of the
1220
+ * memset insignificant. */
1221
+ *siglen = 0;
1222
+ mld_memset(sig, 0, MLDSA_CRYPTO_BYTES);
1223
+ }
1224
+
1225
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
1226
+ mld_zeroize(pre, sizeof(pre));
1227
+ return ret;
1228
+ }
1229
+
1230
+ MLD_MUST_CHECK_RETURN_VALUE
1231
+ MLD_EXTERNAL_API
1232
+ int mld_sign_verify_pre_hash_internal(
1233
+ const uint8_t *sig, size_t siglen, const uint8_t *ph, size_t phlen,
1234
+ const uint8_t *ctx, size_t ctxlen,
1235
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES], int hashalg,
1236
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
1237
+ {
1238
+ MLD_ALIGN uint8_t pre[MLD_DOMAIN_SEPARATION_MAX_BYTES];
1239
+ size_t pre_len;
1240
+ int ret;
1241
+
1242
+ pre_len = mld_prepare_domain_separation_prefix(pre, ph, phlen, ctx, ctxlen,
1243
+ hashalg);
1244
+ if (pre_len == 0)
1245
+ {
1246
+ ret = MLD_ERR_FAIL;
1247
+ goto cleanup;
1248
+ }
1249
+
1250
+ ret = mld_sign_verify_internal(sig, siglen, pre, pre_len, NULL, 0, pk, 0,
1251
+ context);
1252
+
1253
+ cleanup:
1254
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
1255
+ mld_zeroize(pre, sizeof(pre));
1256
+ return ret;
1257
+ }
1258
+
1259
+ MLD_MUST_CHECK_RETURN_VALUE
1260
+ MLD_EXTERNAL_API
1261
+ int mld_sign_signature_pre_hash_shake256(
1262
+ uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen, const uint8_t *m,
1263
+ size_t mlen, const uint8_t *ctx, size_t ctxlen,
1264
+ const uint8_t rnd[MLDSA_RNDBYTES],
1265
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
1266
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
1267
+ {
1268
+ MLD_ALIGN uint8_t ph[64];
1269
+ int ret;
1270
+ mld_shake256(ph, sizeof(ph), m, mlen);
1271
+ ret = mld_sign_signature_pre_hash_internal(sig, siglen, ph, sizeof(ph), ctx,
1272
+ ctxlen, rnd, sk,
1273
+ MLD_PREHASH_SHAKE_256, context);
1274
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
1275
+ mld_zeroize(ph, sizeof(ph));
1276
+ return ret;
1277
+ }
1278
+
1279
+ MLD_MUST_CHECK_RETURN_VALUE
1280
+ MLD_EXTERNAL_API
1281
+ int mld_sign_verify_pre_hash_shake256(
1282
+ const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen,
1283
+ const uint8_t *ctx, size_t ctxlen,
1284
+ const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
1285
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
1286
+ {
1287
+ MLD_ALIGN uint8_t ph[64];
1288
+ int ret;
1289
+ mld_shake256(ph, sizeof(ph), m, mlen);
1290
+ ret = mld_sign_verify_pre_hash_internal(sig, siglen, ph, sizeof(ph), ctx,
1291
+ ctxlen, pk, MLD_PREHASH_SHAKE_256,
1292
+ context);
1293
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
1294
+ mld_zeroize(ph, sizeof(ph));
1295
+ return ret;
1296
+ }
1297
+
1298
+
1299
+ #define MLD_PRE_HASH_OID_LEN 11
1300
+
1301
+ /*************************************************
1302
+ * Name: mld_get_hash_oid
1303
+ *
1304
+ * Description: Returns the OID of a given SHA-2/SHA-3 hash function.
1305
+ *
1306
+ * Arguments: - uint8_t oid[11]: pointer to output oid
1307
+ * - int hashalg: hash algorithm constant (MLD_PREHASH_*)
1308
+ *
1309
+ ***************************************************/
1310
+ static void mld_get_hash_oid(uint8_t oid[MLD_PRE_HASH_OID_LEN], int hashalg)
1311
+ {
1312
+ unsigned int i;
1313
+ static const struct
1314
+ {
1315
+ int alg;
1316
+ uint8_t oid[MLD_PRE_HASH_OID_LEN];
1317
+ } oid_map[] = {
1318
+ {MLD_PREHASH_SHA2_224,
1319
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}},
1320
+ {MLD_PREHASH_SHA2_256,
1321
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}},
1322
+ {MLD_PREHASH_SHA2_384,
1323
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02}},
1324
+ {MLD_PREHASH_SHA2_512,
1325
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}},
1326
+ {MLD_PREHASH_SHA2_512_224,
1327
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05}},
1328
+ {MLD_PREHASH_SHA2_512_256,
1329
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06}},
1330
+ {MLD_PREHASH_SHA3_224,
1331
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x07}},
1332
+ {MLD_PREHASH_SHA3_256,
1333
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08}},
1334
+ {MLD_PREHASH_SHA3_384,
1335
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09}},
1336
+ {MLD_PREHASH_SHA3_512,
1337
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0A}},
1338
+ {MLD_PREHASH_SHAKE_128,
1339
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0B}},
1340
+ {MLD_PREHASH_SHAKE_256,
1341
+ {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0C}}};
1342
+
1343
+ for (i = 0; i < sizeof(oid_map) / sizeof(oid_map[0]); i++)
1344
+ __loop__(
1345
+ invariant(i <= sizeof(oid_map) / sizeof(oid_map[0]))
1346
+ decreases(sizeof(oid_map) / sizeof(oid_map[0]) - i)
1347
+ )
1348
+ {
1349
+ if (oid_map[i].alg == hashalg)
1350
+ {
1351
+ mld_memcpy(oid, oid_map[i].oid, MLD_PRE_HASH_OID_LEN);
1352
+ return;
1353
+ }
1354
+ }
1355
+ }
1356
+
1357
+ static int mld_validate_hash_length(int hashalg, size_t len)
1358
+ {
1359
+ switch (hashalg)
1360
+ {
1361
+ case MLD_PREHASH_SHA2_224:
1362
+ return (len == 224 / 8) ? 0 : -1;
1363
+ case MLD_PREHASH_SHA2_256:
1364
+ return (len == 256 / 8) ? 0 : -1;
1365
+ case MLD_PREHASH_SHA2_384:
1366
+ return (len == 384 / 8) ? 0 : -1;
1367
+ case MLD_PREHASH_SHA2_512:
1368
+ return (len == 512 / 8) ? 0 : -1;
1369
+ case MLD_PREHASH_SHA2_512_224:
1370
+ return (len == 224 / 8) ? 0 : -1;
1371
+ case MLD_PREHASH_SHA2_512_256:
1372
+ return (len == 256 / 8) ? 0 : -1;
1373
+ case MLD_PREHASH_SHA3_224:
1374
+ return (len == 224 / 8) ? 0 : -1;
1375
+ case MLD_PREHASH_SHA3_256:
1376
+ return (len == 256 / 8) ? 0 : -1;
1377
+ case MLD_PREHASH_SHA3_384:
1378
+ return (len == 384 / 8) ? 0 : -1;
1379
+ case MLD_PREHASH_SHA3_512:
1380
+ return (len == 512 / 8) ? 0 : -1;
1381
+ case MLD_PREHASH_SHAKE_128:
1382
+ return (len == 256 / 8) ? 0 : -1;
1383
+ case MLD_PREHASH_SHAKE_256:
1384
+ return (len == 512 / 8) ? 0 : -1;
1385
+ }
1386
+ return -1;
1387
+ }
1388
+
1389
+ size_t mld_prepare_domain_separation_prefix(
1390
+ uint8_t prefix[MLD_DOMAIN_SEPARATION_MAX_BYTES], const uint8_t *ph,
1391
+ size_t phlen, const uint8_t *ctx, size_t ctxlen, int hashalg)
1392
+ {
1393
+ if (ctxlen > 255)
1394
+ {
1395
+ return 0;
1396
+ }
1397
+
1398
+ if (hashalg != MLD_PREHASH_NONE)
1399
+ {
1400
+ if (ph == NULL || mld_validate_hash_length(hashalg, phlen) != 0)
1401
+ {
1402
+ return 0;
1403
+ }
1404
+ }
1405
+
1406
+ /* Common prefix: 0x00/0x01 || ctxlen || ctx */
1407
+ prefix[0] = (hashalg == MLD_PREHASH_NONE) ? 0 : 1;
1408
+ prefix[1] = (uint8_t)ctxlen;
1409
+ if (ctxlen > 0)
1410
+ {
1411
+ mld_memcpy(prefix + 2, ctx, ctxlen);
1412
+ }
1413
+
1414
+ if (hashalg == MLD_PREHASH_NONE)
1415
+ {
1416
+ return 2 + ctxlen;
1417
+ }
1418
+
1419
+ /* HashML-DSA: append oid || ph */
1420
+ mld_get_hash_oid(prefix + 2 + ctxlen, hashalg);
1421
+ mld_memcpy(prefix + 2 + ctxlen + MLD_PRE_HASH_OID_LEN, ph, phlen);
1422
+ return 2 + ctxlen + MLD_PRE_HASH_OID_LEN + phlen;
1423
+ }
1424
+
1425
+ MLD_EXTERNAL_API
1426
+ int mld_sign_pk_from_sk(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
1427
+ const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
1428
+ MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
1429
+ {
1430
+ uint8_t check, cmp0, cmp1, chk1, chk2;
1431
+ int ret;
1432
+ MLD_ALLOC(rho, uint8_t, MLDSA_SEEDBYTES, context);
1433
+ MLD_ALLOC(tr, uint8_t, MLDSA_TRBYTES, context);
1434
+ MLD_ALLOC(tr_computed, uint8_t, MLDSA_TRBYTES, context);
1435
+ MLD_ALLOC(key, uint8_t, MLDSA_SEEDBYTES, context);
1436
+ MLD_ALLOC(s1, mld_polyvecl, 1, context);
1437
+ MLD_ALLOC(s2, mld_polyveck, 1, context);
1438
+ MLD_ALLOC(t0, mld_polyveck, 1, context);
1439
+ MLD_ALLOC(t0_computed, mld_polyveck, 1, context);
1440
+ MLD_ALLOC(t1, mld_polyveck, 1, context);
1441
+
1442
+ if (rho == NULL || tr == NULL || tr_computed == NULL || key == NULL ||
1443
+ s1 == NULL || s2 == NULL || t0 == NULL || t0_computed == NULL ||
1444
+ t1 == NULL)
1445
+ {
1446
+ ret = MLD_ERR_OUT_OF_MEMORY;
1447
+ goto cleanup;
1448
+ }
1449
+
1450
+ /* Unpack secret key */
1451
+ mld_unpack_sk(rho, tr, key, t0, s1, s2, sk);
1452
+
1453
+ /* Validate s1 and s2 coefficients are within [-MLDSA_ETA, MLDSA_ETA] */
1454
+ chk1 = mld_polyvecl_chknorm(s1, MLDSA_ETA + 1) & 0xFF;
1455
+ chk2 = mld_polyveck_chknorm(s2, MLDSA_ETA + 1) & 0xFF;
1456
+
1457
+ /* Recompute t0, t1, tr, and pk from rho, s1, s2 */
1458
+ ret = mld_compute_t0_t1_tr_from_sk_components(t0_computed, t1, tr_computed,
1459
+ pk, rho, s1, s2, context);
1460
+ if (ret != 0)
1461
+ {
1462
+ goto cleanup;
1463
+ }
1464
+
1465
+ /* Validate t0 and tr using constant-time comparisons */
1466
+ cmp0 = mld_ct_memcmp((const uint8_t *)t0, (const uint8_t *)t0_computed,
1467
+ sizeof(mld_polyveck));
1468
+ cmp1 = mld_ct_memcmp((const uint8_t *)tr, (const uint8_t *)tr_computed,
1469
+ MLDSA_TRBYTES);
1470
+ check = mld_value_barrier_u8(cmp0 | cmp1 | chk1 | chk2);
1471
+
1472
+ /* Declassify the final result of the validity check. */
1473
+ MLD_CT_TESTING_DECLASSIFY(&check, sizeof(check));
1474
+ ret = (check != 0) ? MLD_ERR_FAIL : 0;
1475
+
1476
+ cleanup:
1477
+
1478
+ if (ret != 0)
1479
+ {
1480
+ mld_zeroize(pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
1481
+ }
1482
+
1483
+ /* Constant time: pk is either the valid public key or zeroed on error */
1484
+ MLD_CT_TESTING_DECLASSIFY(pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
1485
+
1486
+ /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
1487
+ MLD_FREE(t1, mld_polyveck, 1, context);
1488
+ MLD_FREE(t0_computed, mld_polyveck, 1, context);
1489
+ MLD_FREE(t0, mld_polyveck, 1, context);
1490
+ MLD_FREE(s2, mld_polyveck, 1, context);
1491
+ MLD_FREE(s1, mld_polyvecl, 1, context);
1492
+ MLD_FREE(key, uint8_t, MLDSA_SEEDBYTES, context);
1493
+ MLD_FREE(tr_computed, uint8_t, MLDSA_TRBYTES, context);
1494
+ MLD_FREE(tr, uint8_t, MLDSA_TRBYTES, context);
1495
+ MLD_FREE(rho, uint8_t, MLDSA_SEEDBYTES, context);
1496
+
1497
+ return ret;
1498
+ }
1499
+
1500
+ /* To facilitate single-compilation-unit (SCU) builds, undefine all macros.
1501
+ * Don't modify by hand -- this is auto-generated by scripts/autogen. */
1502
+ #undef mld_check_pct
1503
+ #undef mld_sample_s1_s2
1504
+ #undef mld_validate_hash_length
1505
+ #undef mld_get_hash_oid
1506
+ #undef mld_H
1507
+ #undef mld_compute_pack_z
1508
+ #undef mld_attempt_signature_generation
1509
+ #undef mld_compute_t0_t1_tr_from_sk_components
1510
+ #undef MLD_NONCE_UB
1511
+ #undef MLD_PRE_HASH_OID_LEN