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
@@ -70,6 +70,12 @@ static VALUE ePQCryptoVerificationError;
70
70
 
71
71
  __attribute__((noreturn)) static void pq_raise_general_error(int err);
72
72
 
73
+ static const char *const PQC_CONTAINER_ALGORITHMS[] = {
74
+ "ml_kem_768",
75
+ "ml_kem_768_x25519_xwing",
76
+ "ml_dsa_65",
77
+ };
78
+
73
79
  static const char *pq_algorithm_symbol_to_cstr(VALUE algorithm) {
74
80
  ID id;
75
81
  if (SYMBOL_P(algorithm)) {
@@ -78,42 +84,64 @@ static const char *pq_algorithm_symbol_to_cstr(VALUE algorithm) {
78
84
  VALUE str = StringValue(algorithm);
79
85
  id = rb_intern_str(str);
80
86
  }
81
- if (id == rb_intern("ml_kem_768"))
82
- return "ml_kem_768";
83
- if (id == rb_intern("ml_kem_768_x25519_xwing"))
84
- return "ml_kem_768_x25519_xwing";
85
- if (id == rb_intern("ml_dsa_65"))
86
- return "ml_dsa_65";
87
+ for (size_t i = 0; i < sizeof(PQC_CONTAINER_ALGORITHMS) / sizeof(PQC_CONTAINER_ALGORITHMS[0]);
88
+ ++i) {
89
+ if (id == rb_intern(PQC_CONTAINER_ALGORITHMS[i])) {
90
+ return PQC_CONTAINER_ALGORITHMS[i];
91
+ }
92
+ }
87
93
  rb_raise(rb_eArgError, "Unsupported serialization algorithm");
88
94
  }
89
95
 
90
96
  static VALUE pq_algorithm_cstr_to_symbol(const char *algorithm) {
91
- if (strcmp(algorithm, "ml_kem_768") == 0)
92
- return ID2SYM(rb_intern("ml_kem_768"));
93
- if (strcmp(algorithm, "ml_kem_768_x25519_xwing") == 0)
94
- return ID2SYM(rb_intern("ml_kem_768_x25519_xwing"));
95
- if (strcmp(algorithm, "ml_dsa_65") == 0)
96
- return ID2SYM(rb_intern("ml_dsa_65"));
97
+ for (size_t i = 0; i < sizeof(PQC_CONTAINER_ALGORITHMS) / sizeof(PQC_CONTAINER_ALGORITHMS[0]);
98
+ ++i) {
99
+ if (strcmp(algorithm, PQC_CONTAINER_ALGORITHMS[i]) == 0) {
100
+ return ID2SYM(rb_intern(PQC_CONTAINER_ALGORITHMS[i]));
101
+ }
102
+ }
97
103
  rb_raise(rb_eArgError, "Unsupported serialization algorithm");
98
104
  }
99
105
 
100
- static void *pq_ml_kem_keypair_nogvl(void *arg) {
101
- kem_keypair_call_t *call = (kem_keypair_call_t *)arg;
102
- call->result = pq_mlkem_keypair(call->public_key, call->secret_key);
103
- return NULL;
104
- }
106
+ #define PQ_KEM_KEYPAIR_NOGVL_VARIANTS(X) \
107
+ X(ml_kem, mlkem) \
108
+ X(ml_kem_512, mlkem512) \
109
+ X(ml_kem_1024, mlkem1024)
110
+
111
+ #define PQ_DEFINE_KEM_KEYPAIR_NOGVL(rb_name, c_name) \
112
+ static void *pq_##rb_name##_keypair_nogvl(void *arg) { \
113
+ kem_keypair_call_t *call = (kem_keypair_call_t *)arg; \
114
+ call->result = pq_##c_name##_keypair(call->public_key, call->secret_key); \
115
+ return NULL; \
116
+ } \
117
+ static void *pq_##rb_name##_keypair_from_seed_nogvl(void *arg) { \
118
+ kem_keypair_call_t *call = (kem_keypair_call_t *)arg; \
119
+ call->result = \
120
+ pq_##c_name##_keypair_from_seed(call->public_key, call->secret_key, call->seed); \
121
+ return NULL; \
122
+ }
105
123
 
106
- static void *pq_ml_kem_encapsulate_nogvl(void *arg) {
107
- kem_encapsulate_call_t *call = (kem_encapsulate_call_t *)arg;
108
- call->result = pq_mlkem_encapsulate(call->ciphertext, call->shared_secret, call->public_key);
109
- return NULL;
110
- }
124
+ PQ_KEM_KEYPAIR_NOGVL_VARIANTS(PQ_DEFINE_KEM_KEYPAIR_NOGVL)
125
+
126
+ #undef PQ_DEFINE_KEM_KEYPAIR_NOGVL
127
+
128
+ #define PQ_DEFINE_KEM_ENCAP_DECAP_NOGVL(rb_name, c_name) \
129
+ static void *pq_##rb_name##_encapsulate_nogvl(void *arg) { \
130
+ kem_encapsulate_call_t *call = (kem_encapsulate_call_t *)arg; \
131
+ call->result = \
132
+ pq_##c_name##_encapsulate(call->ciphertext, call->shared_secret, call->public_key); \
133
+ return NULL; \
134
+ } \
135
+ static void *pq_##rb_name##_decapsulate_nogvl(void *arg) { \
136
+ kem_decapsulate_call_t *call = (kem_decapsulate_call_t *)arg; \
137
+ call->result = \
138
+ pq_##c_name##_decapsulate(call->shared_secret, call->ciphertext, call->secret_key); \
139
+ return NULL; \
140
+ }
111
141
 
112
- static void *pq_ml_kem_decapsulate_nogvl(void *arg) {
113
- kem_decapsulate_call_t *call = (kem_decapsulate_call_t *)arg;
114
- call->result = pq_mlkem_decapsulate(call->shared_secret, call->ciphertext, call->secret_key);
115
- return NULL;
116
- }
142
+ PQ_KEM_KEYPAIR_NOGVL_VARIANTS(PQ_DEFINE_KEM_ENCAP_DECAP_NOGVL)
143
+
144
+ #undef PQ_DEFINE_KEM_ENCAP_DECAP_NOGVL
117
145
 
118
146
  static void *pq_testing_ml_kem_keypair_nogvl(void *arg) {
119
147
  kem_keypair_call_t *call = (kem_keypair_call_t *)arg;
@@ -122,12 +150,17 @@ static void *pq_testing_ml_kem_keypair_nogvl(void *arg) {
122
150
  return NULL;
123
151
  }
124
152
 
125
- static void *pq_testing_ml_kem_encapsulate_nogvl(void *arg) {
126
- kem_encapsulate_call_t *call = (kem_encapsulate_call_t *)arg;
127
- call->result = pq_testing_mlkem_encapsulate_from_seed(
128
- call->ciphertext, call->shared_secret, call->public_key, call->seed, call->seed_len);
129
- return NULL;
130
- }
153
+ #define PQ_DEFINE_KEM_TESTING_ENCAP_NOGVL(rb_name, c_name) \
154
+ static void *pq_testing_##rb_name##_encapsulate_nogvl(void *arg) { \
155
+ kem_encapsulate_call_t *call = (kem_encapsulate_call_t *)arg; \
156
+ call->result = pq_testing_##c_name##_encapsulate_from_seed( \
157
+ call->ciphertext, call->shared_secret, call->public_key, call->seed, call->seed_len); \
158
+ return NULL; \
159
+ }
160
+
161
+ PQ_KEM_KEYPAIR_NOGVL_VARIANTS(PQ_DEFINE_KEM_TESTING_ENCAP_NOGVL)
162
+
163
+ #undef PQ_DEFINE_KEM_TESTING_ENCAP_NOGVL
131
164
 
132
165
  static void *pq_hybrid_kem_keypair_nogvl(void *arg) {
133
166
  kem_keypair_call_t *call = (kem_keypair_call_t *)arg;
@@ -149,18 +182,45 @@ static void *pq_hybrid_kem_decapsulate_nogvl(void *arg) {
149
182
  return NULL;
150
183
  }
151
184
 
152
- static void *pq_sign_keypair_nogvl(void *arg) {
153
- sign_keypair_call_t *call = (sign_keypair_call_t *)arg;
154
- call->result = pq_sign_keypair(call->public_key, call->secret_key);
155
- return NULL;
156
- }
185
+ #define PQ_DEFINE_SIGN_KEYPAIR_NOGVL(rb_name, c_call) \
186
+ static void *pq_##rb_name##_nogvl(void *arg) { \
187
+ sign_keypair_call_t *call = (sign_keypair_call_t *)arg; \
188
+ call->result = c_call(call->public_key, call->secret_key); \
189
+ return NULL; \
190
+ }
157
191
 
158
- static void *pq_sign_nogvl(void *arg) {
159
- sign_call_t *call = (sign_call_t *)arg;
160
- call->result = pq_sign(call->signature, &call->signature_len, call->message, call->message_len,
161
- call->secret_key);
162
- return NULL;
163
- }
192
+ PQ_DEFINE_SIGN_KEYPAIR_NOGVL(sign_keypair, pq_sign_keypair)
193
+ PQ_DEFINE_SIGN_KEYPAIR_NOGVL(mldsa_44_sign_keypair, pq_mldsa44_sign_keypair)
194
+ PQ_DEFINE_SIGN_KEYPAIR_NOGVL(mldsa_87_sign_keypair, pq_mldsa87_sign_keypair)
195
+
196
+ #undef PQ_DEFINE_SIGN_KEYPAIR_NOGVL
197
+
198
+ #define PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL(rb_name, c_call) \
199
+ static void *pq_##rb_name##_nogvl(void *arg) { \
200
+ sign_keypair_call_t *call = (sign_keypair_call_t *)arg; \
201
+ call->result = c_call(call->public_key, call->secret_key, call->seed); \
202
+ return NULL; \
203
+ }
204
+
205
+ PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL(mldsa_44_keypair_from_seed, pq_mldsa44_keypair_from_seed)
206
+ PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL(mldsa_keypair_from_seed, pq_mldsa_keypair_from_seed)
207
+ PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL(mldsa_87_keypair_from_seed, pq_mldsa87_keypair_from_seed)
208
+
209
+ #undef PQ_DEFINE_SIGN_KEYPAIR_FROM_SEED_NOGVL
210
+
211
+ #define PQ_DEFINE_SIGN_NOGVL(rb_name, c_call) \
212
+ static void *pq_##rb_name##_nogvl(void *arg) { \
213
+ sign_call_t *call = (sign_call_t *)arg; \
214
+ call->result = c_call(call->signature, &call->signature_len, call->message, \
215
+ call->message_len, call->secret_key); \
216
+ return NULL; \
217
+ }
218
+
219
+ PQ_DEFINE_SIGN_NOGVL(sign, pq_sign)
220
+ PQ_DEFINE_SIGN_NOGVL(mldsa_44_sign, pq_mldsa44_sign)
221
+ PQ_DEFINE_SIGN_NOGVL(mldsa_87_sign, pq_mldsa87_sign)
222
+
223
+ #undef PQ_DEFINE_SIGN_NOGVL
164
224
 
165
225
  static void *pq_testing_sign_keypair_nogvl(void *arg) {
166
226
  sign_keypair_call_t *call = (sign_keypair_call_t *)arg;
@@ -177,12 +237,43 @@ static void *pq_testing_sign_nogvl(void *arg) {
177
237
  return NULL;
178
238
  }
179
239
 
180
- static void *pq_verify_nogvl(void *arg) {
181
- verify_call_t *call = (verify_call_t *)arg;
182
- call->result = pq_verify(call->signature, call->signature_len, call->message, call->message_len,
183
- call->public_key);
184
- return NULL;
185
- }
240
+ #define PQ_DEFINE_TESTING_KEYPAIR_FROM_SEED(rb_name, c_call) \
241
+ static void *pq_testing_##rb_name##_keypair_nogvl(void *arg) { \
242
+ sign_keypair_call_t *call = (sign_keypair_call_t *)arg; \
243
+ call->result = c_call(call->public_key, call->secret_key, call->seed, call->seed_len); \
244
+ return NULL; \
245
+ }
246
+
247
+ #define PQ_DEFINE_TESTING_SIGN_FROM_SEED(rb_name, c_call) \
248
+ static void *pq_testing_##rb_name##_sign_nogvl(void *arg) { \
249
+ sign_call_t *call = (sign_call_t *)arg; \
250
+ call->result = c_call(call->signature, &call->signature_len, call->message, \
251
+ call->message_len, call->secret_key, call->seed, call->seed_len); \
252
+ return NULL; \
253
+ }
254
+
255
+ PQ_DEFINE_TESTING_KEYPAIR_FROM_SEED(mldsa_44, pq_testing_mldsa44_keypair_from_seed)
256
+ PQ_DEFINE_TESTING_KEYPAIR_FROM_SEED(mldsa_87, pq_testing_mldsa87_keypair_from_seed)
257
+
258
+ PQ_DEFINE_TESTING_SIGN_FROM_SEED(mldsa_44, pq_testing_mldsa44_sign_from_seed)
259
+ PQ_DEFINE_TESTING_SIGN_FROM_SEED(mldsa_87, pq_testing_mldsa87_sign_from_seed)
260
+
261
+ #undef PQ_DEFINE_TESTING_KEYPAIR_FROM_SEED
262
+ #undef PQ_DEFINE_TESTING_SIGN_FROM_SEED
263
+
264
+ #define PQ_DEFINE_VERIFY_NOGVL(rb_name, c_call) \
265
+ static void *pq_##rb_name##_nogvl(void *arg) { \
266
+ verify_call_t *call = (verify_call_t *)arg; \
267
+ call->result = c_call(call->signature, call->signature_len, call->message, \
268
+ call->message_len, call->public_key); \
269
+ return NULL; \
270
+ }
271
+
272
+ PQ_DEFINE_VERIFY_NOGVL(verify, pq_verify)
273
+ PQ_DEFINE_VERIFY_NOGVL(mldsa_44_verify, pq_mldsa44_verify)
274
+ PQ_DEFINE_VERIFY_NOGVL(mldsa_87_verify, pq_mldsa87_verify)
275
+
276
+ #undef PQ_DEFINE_VERIFY_NOGVL
186
277
 
187
278
  static uint8_t *pq_alloc_buffer(size_t len) {
188
279
  if (len == 0) {
@@ -469,24 +560,73 @@ __attribute__((noreturn)) static void pq_raise_general_error(int err) {
469
560
  }
470
561
  }
471
562
 
472
- static VALUE pqcrypto_ml_kem_keypair(VALUE self) {
473
- (void)self;
474
- return pq_run_kem_keypair(pq_ml_kem_keypair_nogvl, PQ_MLKEM_PUBLICKEYBYTES,
475
- PQ_MLKEM_SECRETKEYBYTES);
476
- }
563
+ static VALUE pq_run_kem_keypair_from_seed(void *(*nogvl)(void *), VALUE seed, size_t public_key_len,
564
+ size_t secret_key_len) {
565
+ StringValue(seed);
477
566
 
478
- static VALUE pqcrypto_ml_kem_encapsulate(VALUE self, VALUE public_key) {
479
- (void)self;
480
- return pq_run_kem_encapsulate(pq_ml_kem_encapsulate_nogvl, public_key, PQ_MLKEM_PUBLICKEYBYTES,
481
- PQ_MLKEM_CIPHERTEXTBYTES, PQ_MLKEM_SHAREDSECRETBYTES);
482
- }
567
+ if ((size_t)RSTRING_LEN(seed) != 64) {
568
+ rb_raise(rb_eArgError, "ML-KEM seed must be 64 bytes (FIPS 203 d||z)");
569
+ }
483
570
 
484
- static VALUE pqcrypto_ml_kem_decapsulate(VALUE self, VALUE ciphertext, VALUE secret_key) {
485
- (void)self;
486
- return pq_run_kem_decapsulate(pq_ml_kem_decapsulate_nogvl, ciphertext, PQ_MLKEM_CIPHERTEXTBYTES,
487
- secret_key, PQ_MLKEM_SECRETKEYBYTES, PQ_MLKEM_SHAREDSECRETBYTES);
571
+ kem_keypair_call_t call = {0};
572
+ size_t seed_len = 0;
573
+ call.public_key = pq_alloc_buffer(public_key_len);
574
+ call.secret_key = pq_alloc_buffer(secret_key_len);
575
+ call.seed = pq_copy_ruby_string(seed, &seed_len);
576
+ call.seed_len = seed_len;
577
+
578
+ rb_thread_call_without_gvl(nogvl, &call, NULL, NULL);
579
+ pq_wipe_and_free((uint8_t *)call.seed, call.seed_len);
580
+
581
+ if (call.result != PQ_SUCCESS) {
582
+ pq_wipe_and_free(call.secret_key, secret_key_len);
583
+ free(call.public_key);
584
+ pq_raise_general_error(call.result);
585
+ }
586
+
587
+ VALUE result = rb_ary_new2(2);
588
+ rb_ary_push(result, pq_string_from_buffer(call.public_key, public_key_len));
589
+ rb_ary_push(result, pq_string_from_buffer(call.secret_key, secret_key_len));
590
+
591
+ free(call.public_key);
592
+ pq_wipe_and_free(call.secret_key, secret_key_len);
593
+ return result;
488
594
  }
489
595
 
596
+ #define PQ_RUBY_KEM_VARIANTS(X) \
597
+ X(ml_kem, PQ_MLKEM_PUBLICKEYBYTES, PQ_MLKEM_SECRETKEYBYTES, PQ_MLKEM_CIPHERTEXTBYTES, \
598
+ PQ_MLKEM_SHAREDSECRETBYTES) \
599
+ X(ml_kem_512, MLKEM512_PUBLICKEYBYTES, MLKEM512_SECRETKEYBYTES, MLKEM512_CIPHERTEXTBYTES, \
600
+ MLKEM512_SHAREDSECRETBYTES) \
601
+ X(ml_kem_1024, MLKEM1024_PUBLICKEYBYTES, MLKEM1024_SECRETKEYBYTES, MLKEM1024_CIPHERTEXTBYTES, \
602
+ MLKEM1024_SHAREDSECRETBYTES)
603
+
604
+ #define PQ_DEFINE_RUBY_KEM(rb_name, pk_bytes, sk_bytes, ct_bytes, ss_bytes) \
605
+ static VALUE pqcrypto_##rb_name##_keypair(VALUE self) { \
606
+ (void)self; \
607
+ return pq_run_kem_keypair(pq_##rb_name##_keypair_nogvl, pk_bytes, sk_bytes); \
608
+ } \
609
+ static VALUE pqcrypto_##rb_name##_keypair_from_seed(VALUE self, VALUE seed) { \
610
+ (void)self; \
611
+ return pq_run_kem_keypair_from_seed(pq_##rb_name##_keypair_from_seed_nogvl, seed, \
612
+ pk_bytes, sk_bytes); \
613
+ } \
614
+ static VALUE pqcrypto_##rb_name##_encapsulate(VALUE self, VALUE public_key) { \
615
+ (void)self; \
616
+ return pq_run_kem_encapsulate(pq_##rb_name##_encapsulate_nogvl, public_key, pk_bytes, \
617
+ ct_bytes, ss_bytes); \
618
+ } \
619
+ static VALUE pqcrypto_##rb_name##_decapsulate(VALUE self, VALUE ciphertext, \
620
+ VALUE secret_key) { \
621
+ (void)self; \
622
+ return pq_run_kem_decapsulate(pq_##rb_name##_decapsulate_nogvl, ciphertext, ct_bytes, \
623
+ secret_key, sk_bytes, ss_bytes); \
624
+ }
625
+
626
+ PQ_RUBY_KEM_VARIANTS(PQ_DEFINE_RUBY_KEM)
627
+
628
+ #undef PQ_DEFINE_RUBY_KEM
629
+
490
630
  static VALUE pqcrypto_hybrid_kem_keypair(VALUE self) {
491
631
  (void)self;
492
632
  return pq_run_kem_keypair(pq_hybrid_kem_keypair_nogvl, PQ_HYBRID_PUBLICKEYBYTES,
@@ -577,6 +717,61 @@ static VALUE pqcrypto__test_ml_kem_encapsulate_from_seed(VALUE self, VALUE publi
577
717
  return result;
578
718
  }
579
719
 
720
+ static VALUE pq_run_test_kem_encapsulate_from_seed(void *(*nogvl)(void *), VALUE public_key,
721
+ VALUE seed, size_t public_key_len,
722
+ size_t ciphertext_len,
723
+ size_t shared_secret_len) {
724
+ pq_validate_bytes_argument(public_key, public_key_len, "public key");
725
+ StringValue(seed);
726
+
727
+ if ((size_t)RSTRING_LEN(seed) != 32) {
728
+ rb_raise(rb_eArgError, "Deterministic test seed must be 32 bytes");
729
+ }
730
+
731
+ kem_encapsulate_call_t call = {0};
732
+ size_t public_key_copy_len = 0;
733
+ size_t seed_len = 0;
734
+ call.public_key = pq_copy_ruby_string(public_key, &public_key_copy_len);
735
+ call.ciphertext = pq_alloc_buffer(ciphertext_len);
736
+ call.shared_secret = pq_alloc_buffer(shared_secret_len);
737
+ call.seed = pq_copy_ruby_string(seed, &seed_len);
738
+ call.seed_len = seed_len;
739
+
740
+ rb_thread_call_without_gvl(nogvl, &call, NULL, NULL);
741
+ pq_wipe_and_free((uint8_t *)call.public_key, public_key_copy_len);
742
+ pq_wipe_and_free((uint8_t *)call.seed, call.seed_len);
743
+
744
+ if (call.result != PQ_SUCCESS) {
745
+ pq_wipe_and_free(call.shared_secret, shared_secret_len);
746
+ free(call.ciphertext);
747
+ pq_raise_general_error(call.result);
748
+ }
749
+
750
+ VALUE result = rb_ary_new2(2);
751
+ rb_ary_push(result, pq_string_from_buffer(call.ciphertext, ciphertext_len));
752
+ rb_ary_push(result, pq_string_from_buffer(call.shared_secret, shared_secret_len));
753
+
754
+ free(call.ciphertext);
755
+ pq_wipe_and_free(call.shared_secret, shared_secret_len);
756
+ return result;
757
+ }
758
+
759
+ static VALUE pqcrypto__test_ml_kem_512_encapsulate_from_seed(VALUE self, VALUE public_key,
760
+ VALUE seed) {
761
+ (void)self;
762
+ return pq_run_test_kem_encapsulate_from_seed(
763
+ pq_testing_ml_kem_512_encapsulate_nogvl, public_key, seed, MLKEM512_PUBLICKEYBYTES,
764
+ MLKEM512_CIPHERTEXTBYTES, MLKEM512_SHAREDSECRETBYTES);
765
+ }
766
+
767
+ static VALUE pqcrypto__test_ml_kem_1024_encapsulate_from_seed(VALUE self, VALUE public_key,
768
+ VALUE seed) {
769
+ (void)self;
770
+ return pq_run_test_kem_encapsulate_from_seed(
771
+ pq_testing_ml_kem_1024_encapsulate_nogvl, public_key, seed, MLKEM1024_PUBLICKEYBYTES,
772
+ MLKEM1024_CIPHERTEXTBYTES, MLKEM1024_SHAREDSECRETBYTES);
773
+ }
774
+
580
775
  static VALUE pqcrypto__test_sign_keypair_from_seed(VALUE self, VALUE seed) {
581
776
  (void)self;
582
777
  StringValue(seed);
@@ -646,24 +841,143 @@ static VALUE pqcrypto__test_sign_from_seed(VALUE self, VALUE message, VALUE secr
646
841
  return result;
647
842
  }
648
843
 
649
- static VALUE pqcrypto_sign_keypair(VALUE self) {
844
+ static VALUE pq_run_test_sign_keypair_from_seed(void *(*nogvl)(void *), VALUE seed,
845
+ size_t public_key_len, size_t secret_key_len) {
846
+ StringValue(seed);
847
+
848
+ if ((size_t)RSTRING_LEN(seed) != 32) {
849
+ rb_raise(rb_eArgError, "Deterministic test seed must be 32 bytes");
850
+ }
851
+
852
+ sign_keypair_call_t call = {0};
853
+ size_t seed_len = 0;
854
+ call.public_key = pq_alloc_buffer(public_key_len);
855
+ call.secret_key = pq_alloc_buffer(secret_key_len);
856
+ call.seed = pq_copy_ruby_string(seed, &seed_len);
857
+ call.seed_len = seed_len;
858
+
859
+ rb_thread_call_without_gvl(nogvl, &call, NULL, NULL);
860
+ pq_wipe_and_free((uint8_t *)call.seed, call.seed_len);
861
+
862
+ if (call.result != PQ_SUCCESS) {
863
+ pq_wipe_and_free(call.secret_key, secret_key_len);
864
+ free(call.public_key);
865
+ pq_raise_general_error(call.result);
866
+ }
867
+
868
+ VALUE result = rb_ary_new2(2);
869
+ rb_ary_push(result, pq_string_from_buffer(call.public_key, public_key_len));
870
+ rb_ary_push(result, pq_string_from_buffer(call.secret_key, secret_key_len));
871
+
872
+ free(call.public_key);
873
+ pq_wipe_and_free(call.secret_key, secret_key_len);
874
+ return result;
875
+ }
876
+
877
+ static VALUE pqcrypto__test_ml_dsa_44_keypair_from_seed(VALUE self, VALUE seed) {
650
878
  (void)self;
651
- return pq_run_sign_keypair(pq_sign_keypair_nogvl, PQ_MLDSA_PUBLICKEYBYTES,
652
- PQ_MLDSA_SECRETKEYBYTES);
879
+ return pq_run_test_sign_keypair_from_seed(pq_testing_mldsa_44_keypair_nogvl, seed,
880
+ MLDSA44_PUBLICKEYBYTES, MLDSA44_SECRETKEYBYTES);
653
881
  }
654
882
 
655
- static VALUE pqcrypto_sign(VALUE self, VALUE message, VALUE secret_key) {
883
+ static VALUE pqcrypto__test_ml_dsa_87_keypair_from_seed(VALUE self, VALUE seed) {
656
884
  (void)self;
657
- pq_validate_bytes_argument(secret_key, PQ_MLDSA_SECRETKEYBYTES, "secret key");
885
+ return pq_run_test_sign_keypair_from_seed(pq_testing_mldsa_87_keypair_nogvl, seed,
886
+ MLDSA87_PUBLICKEYBYTES, MLDSA87_SECRETKEYBYTES);
887
+ }
888
+
889
+ #define PQ_RUBY_MLDSA_KEYPAIR_FROM_SEED_VARIANTS(X) \
890
+ X(ml_dsa_44, mldsa_44_keypair_from_seed, MLDSA44_PUBLICKEYBYTES, MLDSA44_SECRETKEYBYTES) \
891
+ X(ml_dsa, mldsa_keypair_from_seed, PQ_MLDSA_PUBLICKEYBYTES, PQ_MLDSA_SECRETKEYBYTES) \
892
+ X(ml_dsa_87, mldsa_87_keypair_from_seed, MLDSA87_PUBLICKEYBYTES, MLDSA87_SECRETKEYBYTES)
893
+
894
+ #define PQ_DEFINE_RUBY_MLDSA_KEYPAIR_FROM_SEED(rb_name, nogvl_suffix, pk_bytes, sk_bytes) \
895
+ static VALUE pqcrypto_##rb_name##_keypair_from_seed(VALUE self, VALUE seed) { \
896
+ (void)self; \
897
+ return pq_run_test_sign_keypair_from_seed(pq_##nogvl_suffix##_nogvl, seed, pk_bytes, \
898
+ sk_bytes); \
899
+ }
900
+
901
+ PQ_RUBY_MLDSA_KEYPAIR_FROM_SEED_VARIANTS(PQ_DEFINE_RUBY_MLDSA_KEYPAIR_FROM_SEED)
902
+
903
+ #undef PQ_DEFINE_RUBY_MLDSA_KEYPAIR_FROM_SEED
904
+
905
+ static VALUE pq_run_test_sign_from_seed(void *(*nogvl)(void *), VALUE message, VALUE secret_key,
906
+ VALUE seed, size_t secret_key_len, size_t signature_len) {
907
+ pq_validate_bytes_argument(secret_key, secret_key_len, "secret key");
908
+ StringValue(seed);
909
+
910
+ if ((size_t)RSTRING_LEN(seed) != 32) {
911
+ rb_raise(rb_eArgError, "Deterministic test seed must be 32 bytes");
912
+ }
913
+
914
+ sign_call_t call = {0};
915
+ size_t secret_key_copy_len = 0;
916
+ size_t seed_len = 0;
917
+ call.secret_key = pq_copy_ruby_string(secret_key, &secret_key_copy_len);
918
+ call.signature_len = signature_len;
919
+ call.signature = pq_alloc_buffer(signature_len);
920
+ call.message = pq_copy_ruby_string(message, &call.message_len);
921
+ call.seed = pq_copy_ruby_string(seed, &seed_len);
922
+ call.seed_len = seed_len;
923
+
924
+ rb_thread_call_without_gvl(nogvl, &call, NULL, NULL);
925
+
926
+ pq_free_buffer(call.message);
927
+ pq_wipe_and_free((uint8_t *)call.secret_key, secret_key_copy_len);
928
+ pq_wipe_and_free((uint8_t *)call.seed, call.seed_len);
929
+
930
+ if (call.result != PQ_SUCCESS) {
931
+ pq_free_buffer(call.signature);
932
+ pq_raise_general_error(call.result);
933
+ }
934
+
935
+ VALUE result = pq_string_from_buffer(call.signature, call.signature_len);
936
+ pq_free_buffer(call.signature);
937
+ return result;
938
+ }
939
+
940
+ static VALUE pqcrypto__test_ml_dsa_44_sign_from_seed(VALUE self, VALUE message, VALUE secret_key,
941
+ VALUE seed) {
942
+ (void)self;
943
+ return pq_run_test_sign_from_seed(pq_testing_mldsa_44_sign_nogvl, message, secret_key, seed,
944
+ MLDSA44_SECRETKEYBYTES, MLDSA44_BYTES);
945
+ }
946
+
947
+ static VALUE pqcrypto__test_ml_dsa_87_sign_from_seed(VALUE self, VALUE message, VALUE secret_key,
948
+ VALUE seed) {
949
+ (void)self;
950
+ return pq_run_test_sign_from_seed(pq_testing_mldsa_87_sign_nogvl, message, secret_key, seed,
951
+ MLDSA87_SECRETKEYBYTES, MLDSA87_BYTES);
952
+ }
953
+
954
+ #define PQ_DEFINE_RUBY_MLDSA_KEYPAIR(rb_name, nogvl_stem, pk_bytes, sk_bytes) \
955
+ static VALUE pqcrypto_##rb_name(VALUE self) { \
956
+ (void)self; \
957
+ return pq_run_sign_keypair(pq_##nogvl_stem##_nogvl, pk_bytes, sk_bytes); \
958
+ }
959
+
960
+ PQ_DEFINE_RUBY_MLDSA_KEYPAIR(sign_keypair, sign_keypair, PQ_MLDSA_PUBLICKEYBYTES,
961
+ PQ_MLDSA_SECRETKEYBYTES)
962
+ PQ_DEFINE_RUBY_MLDSA_KEYPAIR(ml_dsa_44_keypair, mldsa_44_sign_keypair, MLDSA44_PUBLICKEYBYTES,
963
+ MLDSA44_SECRETKEYBYTES)
964
+ PQ_DEFINE_RUBY_MLDSA_KEYPAIR(ml_dsa_87_keypair, mldsa_87_sign_keypair, MLDSA87_PUBLICKEYBYTES,
965
+ MLDSA87_SECRETKEYBYTES)
966
+
967
+ #undef PQ_DEFINE_RUBY_MLDSA_KEYPAIR
968
+
969
+ static VALUE pq_run_sign(void *(*nogvl)(void *), VALUE message, VALUE secret_key,
970
+ size_t secret_key_len_expected, size_t signature_len_expected) {
971
+ pq_validate_bytes_argument(secret_key, secret_key_len_expected, "secret key");
658
972
 
659
973
  sign_call_t call = {0};
660
974
  size_t secret_key_len = 0;
661
975
  call.secret_key = pq_copy_ruby_string(secret_key, &secret_key_len);
662
- call.signature_len = PQ_MLDSA_BYTES;
663
- call.signature = pq_alloc_buffer(PQ_MLDSA_BYTES);
976
+ call.signature_len = signature_len_expected;
977
+ call.signature = pq_alloc_buffer(signature_len_expected);
664
978
  call.message = pq_copy_ruby_string(message, &call.message_len);
665
979
 
666
- rb_nogvl(pq_sign_nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
980
+ rb_nogvl(nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
667
981
 
668
982
  pq_free_buffer(call.message);
669
983
  pq_wipe_and_free((uint8_t *)call.secret_key, secret_key_len);
@@ -678,10 +992,22 @@ static VALUE pqcrypto_sign(VALUE self, VALUE message, VALUE secret_key) {
678
992
  return result;
679
993
  }
680
994
 
681
- static VALUE pqcrypto_verify(VALUE self, VALUE message, VALUE signature, VALUE public_key) {
682
- (void)self;
995
+ #define PQ_DEFINE_RUBY_MLDSA_SIGN(rb_name, nogvl_stem, sk_bytes, sig_bytes) \
996
+ static VALUE pqcrypto_##rb_name(VALUE self, VALUE message, VALUE secret_key) { \
997
+ (void)self; \
998
+ return pq_run_sign(pq_##nogvl_stem##_nogvl, message, secret_key, sk_bytes, sig_bytes); \
999
+ }
1000
+
1001
+ PQ_DEFINE_RUBY_MLDSA_SIGN(sign, sign, PQ_MLDSA_SECRETKEYBYTES, PQ_MLDSA_BYTES)
1002
+ PQ_DEFINE_RUBY_MLDSA_SIGN(ml_dsa_44_sign, mldsa_44_sign, MLDSA44_SECRETKEYBYTES, MLDSA44_BYTES)
1003
+ PQ_DEFINE_RUBY_MLDSA_SIGN(ml_dsa_87_sign, mldsa_87_sign, MLDSA87_SECRETKEYBYTES, MLDSA87_BYTES)
1004
+
1005
+ #undef PQ_DEFINE_RUBY_MLDSA_SIGN
1006
+
1007
+ static VALUE pq_run_verify(void *(*nogvl)(void *), VALUE message, VALUE signature, VALUE public_key,
1008
+ size_t public_key_len_expected) {
683
1009
  StringValue(signature);
684
- pq_validate_bytes_argument(public_key, PQ_MLDSA_PUBLICKEYBYTES, "public key");
1010
+ pq_validate_bytes_argument(public_key, public_key_len_expected, "public key");
685
1011
 
686
1012
  verify_call_t call = {0};
687
1013
  size_t public_key_len = 0;
@@ -691,7 +1017,7 @@ static VALUE pqcrypto_verify(VALUE self, VALUE message, VALUE signature, VALUE p
691
1017
  call.signature_len = signature_len;
692
1018
  call.message = pq_copy_ruby_string(message, &call.message_len);
693
1019
 
694
- rb_nogvl(pq_verify_nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
1020
+ rb_nogvl(nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
695
1021
 
696
1022
  pq_free_buffer(call.message);
697
1023
  pq_free_buffer((uint8_t *)call.public_key);
@@ -706,6 +1032,19 @@ static VALUE pqcrypto_verify(VALUE self, VALUE message, VALUE signature, VALUE p
706
1032
  pq_raise_general_error(call.result);
707
1033
  }
708
1034
 
1035
+ #define PQ_DEFINE_RUBY_MLDSA_VERIFY(rb_name, nogvl_stem, pk_bytes) \
1036
+ static VALUE pqcrypto_##rb_name(VALUE self, VALUE message, VALUE signature, \
1037
+ VALUE public_key) { \
1038
+ (void)self; \
1039
+ return pq_run_verify(pq_##nogvl_stem##_nogvl, message, signature, public_key, pk_bytes); \
1040
+ }
1041
+
1042
+ PQ_DEFINE_RUBY_MLDSA_VERIFY(verify, verify, PQ_MLDSA_PUBLICKEYBYTES)
1043
+ PQ_DEFINE_RUBY_MLDSA_VERIFY(ml_dsa_44_verify, mldsa_44_verify, MLDSA44_PUBLICKEYBYTES)
1044
+ PQ_DEFINE_RUBY_MLDSA_VERIFY(ml_dsa_87_verify, mldsa_87_verify, MLDSA87_PUBLICKEYBYTES)
1045
+
1046
+ #undef PQ_DEFINE_RUBY_MLDSA_VERIFY
1047
+
709
1048
  static VALUE pqcrypto_ct_equals(VALUE self, VALUE a, VALUE b) {
710
1049
  (void)self;
711
1050
  StringValue(a);
@@ -786,11 +1125,19 @@ static size_t mu_builder_wrapper_size(const void *ptr) {
786
1125
  }
787
1126
 
788
1127
  static const rb_data_type_t mu_builder_data_type = {
789
- "PQCrypto::MLDSA::MuBuilder",
790
- {NULL, mu_builder_wrapper_free, mu_builder_wrapper_size},
791
- NULL,
792
- NULL,
793
- RUBY_TYPED_FREE_IMMEDIATELY};
1128
+ .wrap_struct_name = "PQCrypto::MLDSA::MuBuilder",
1129
+ .function =
1130
+ {
1131
+ .dmark = NULL,
1132
+ .dfree = mu_builder_wrapper_free,
1133
+ .dsize = mu_builder_wrapper_size,
1134
+ .dcompact = NULL,
1135
+ .reserved = {NULL},
1136
+ },
1137
+ .parent = NULL,
1138
+ .data = NULL,
1139
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1140
+ };
794
1141
 
795
1142
  static mu_builder_wrapper_t *mu_builder_unwrap(VALUE obj) {
796
1143
  mu_builder_wrapper_t *wrapper;
@@ -908,9 +1255,6 @@ static VALUE pqcrypto__native_mldsa_mu_builder_finalize(VALUE self, VALUE builde
908
1255
 
909
1256
  rb_nogvl(pq_mu_finalize_nogvl, &call, NULL, NULL, RB_NOGVL_OFFLOAD_SAFE);
910
1257
 
911
- if (call.result != PQ_SUCCESS) {
912
- pq_mu_builder_release(wrapper->builder);
913
- }
914
1258
  wrapper->builder = NULL;
915
1259
 
916
1260
  if (call.result != PQ_SUCCESS) {
@@ -1012,18 +1356,34 @@ static VALUE pqcrypto__native_mldsa_verify_mu(VALUE self, VALUE mu, VALUE signat
1012
1356
  }
1013
1357
 
1014
1358
  static void define_constants(void) {
1359
+ rb_define_const(mPQCrypto, "ML_KEM_512_PUBLIC_KEY_BYTES", INT2NUM(MLKEM512_PUBLICKEYBYTES));
1360
+ rb_define_const(mPQCrypto, "ML_KEM_512_SECRET_KEY_BYTES", INT2NUM(MLKEM512_SECRETKEYBYTES));
1361
+ rb_define_const(mPQCrypto, "ML_KEM_512_CIPHERTEXT_BYTES", INT2NUM(MLKEM512_CIPHERTEXTBYTES));
1362
+ rb_define_const(mPQCrypto, "ML_KEM_512_SHARED_SECRET_BYTES",
1363
+ INT2NUM(MLKEM512_SHAREDSECRETBYTES));
1015
1364
  rb_define_const(mPQCrypto, "ML_KEM_PUBLIC_KEY_BYTES", INT2NUM(PQ_MLKEM_PUBLICKEYBYTES));
1016
1365
  rb_define_const(mPQCrypto, "ML_KEM_SECRET_KEY_BYTES", INT2NUM(PQ_MLKEM_SECRETKEYBYTES));
1017
1366
  rb_define_const(mPQCrypto, "ML_KEM_CIPHERTEXT_BYTES", INT2NUM(PQ_MLKEM_CIPHERTEXTBYTES));
1018
1367
  rb_define_const(mPQCrypto, "ML_KEM_SHARED_SECRET_BYTES", INT2NUM(PQ_MLKEM_SHAREDSECRETBYTES));
1368
+ rb_define_const(mPQCrypto, "ML_KEM_1024_PUBLIC_KEY_BYTES", INT2NUM(MLKEM1024_PUBLICKEYBYTES));
1369
+ rb_define_const(mPQCrypto, "ML_KEM_1024_SECRET_KEY_BYTES", INT2NUM(MLKEM1024_SECRETKEYBYTES));
1370
+ rb_define_const(mPQCrypto, "ML_KEM_1024_CIPHERTEXT_BYTES", INT2NUM(MLKEM1024_CIPHERTEXTBYTES));
1371
+ rb_define_const(mPQCrypto, "ML_KEM_1024_SHARED_SECRET_BYTES",
1372
+ INT2NUM(MLKEM1024_SHAREDSECRETBYTES));
1019
1373
  rb_define_const(mPQCrypto, "HYBRID_KEM_PUBLIC_KEY_BYTES", INT2NUM(PQ_HYBRID_PUBLICKEYBYTES));
1020
1374
  rb_define_const(mPQCrypto, "HYBRID_KEM_SECRET_KEY_BYTES", INT2NUM(PQ_HYBRID_SECRETKEYBYTES));
1021
1375
  rb_define_const(mPQCrypto, "HYBRID_KEM_CIPHERTEXT_BYTES", INT2NUM(PQ_HYBRID_CIPHERTEXTBYTES));
1022
1376
  rb_define_const(mPQCrypto, "HYBRID_KEM_SHARED_SECRET_BYTES",
1023
1377
  INT2NUM(PQ_HYBRID_SHAREDSECRETBYTES));
1378
+ rb_define_const(mPQCrypto, "SIGN_44_PUBLIC_KEY_BYTES", INT2NUM(MLDSA44_PUBLICKEYBYTES));
1379
+ rb_define_const(mPQCrypto, "SIGN_44_SECRET_KEY_BYTES", INT2NUM(MLDSA44_SECRETKEYBYTES));
1380
+ rb_define_const(mPQCrypto, "SIGN_44_BYTES", INT2NUM(MLDSA44_BYTES));
1024
1381
  rb_define_const(mPQCrypto, "SIGN_PUBLIC_KEY_BYTES", INT2NUM(PQ_MLDSA_PUBLICKEYBYTES));
1025
1382
  rb_define_const(mPQCrypto, "SIGN_SECRET_KEY_BYTES", INT2NUM(PQ_MLDSA_SECRETKEYBYTES));
1026
1383
  rb_define_const(mPQCrypto, "SIGN_BYTES", INT2NUM(PQ_MLDSA_BYTES));
1384
+ rb_define_const(mPQCrypto, "SIGN_87_PUBLIC_KEY_BYTES", INT2NUM(MLDSA87_PUBLICKEYBYTES));
1385
+ rb_define_const(mPQCrypto, "SIGN_87_SECRET_KEY_BYTES", INT2NUM(MLDSA87_SECRETKEYBYTES));
1386
+ rb_define_const(mPQCrypto, "SIGN_87_BYTES", INT2NUM(MLDSA87_BYTES));
1027
1387
  }
1028
1388
 
1029
1389
  static VALUE pqcrypto_public_key_to_pqc_container_der(VALUE self, VALUE algorithm,
@@ -1081,12 +1441,40 @@ void Init_pqcrypto_secure(void) {
1081
1441
  pqcrypto__test_ml_kem_keypair_from_seed, 1);
1082
1442
  rb_define_module_function(mPQCrypto, "__test_ml_kem_encapsulate_from_seed",
1083
1443
  pqcrypto__test_ml_kem_encapsulate_from_seed, 2);
1444
+ rb_define_module_function(mPQCrypto, "__test_ml_kem_512_encapsulate_from_seed",
1445
+ pqcrypto__test_ml_kem_512_encapsulate_from_seed, 2);
1446
+ rb_define_module_function(mPQCrypto, "__test_ml_kem_1024_encapsulate_from_seed",
1447
+ pqcrypto__test_ml_kem_1024_encapsulate_from_seed, 2);
1084
1448
  rb_define_module_function(mPQCrypto, "__test_sign_keypair_from_seed",
1085
1449
  pqcrypto__test_sign_keypair_from_seed, 1);
1450
+ rb_define_module_function(mPQCrypto, "__test_ml_dsa_44_keypair_from_seed",
1451
+ pqcrypto__test_ml_dsa_44_keypair_from_seed, 1);
1452
+ rb_define_module_function(mPQCrypto, "__test_ml_dsa_87_keypair_from_seed",
1453
+ pqcrypto__test_ml_dsa_87_keypair_from_seed, 1);
1086
1454
  rb_define_module_function(mPQCrypto, "__test_sign_from_seed", pqcrypto__test_sign_from_seed, 3);
1455
+ rb_define_module_function(mPQCrypto, "__test_ml_dsa_44_sign_from_seed",
1456
+ pqcrypto__test_ml_dsa_44_sign_from_seed, 3);
1457
+ rb_define_module_function(mPQCrypto, "__test_ml_dsa_87_sign_from_seed",
1458
+ pqcrypto__test_ml_dsa_87_sign_from_seed, 3);
1087
1459
  rb_define_module_function(mPQCrypto, "ml_kem_keypair", pqcrypto_ml_kem_keypair, 0);
1460
+ rb_define_module_function(mPQCrypto, "ml_kem_keypair_from_seed",
1461
+ pqcrypto_ml_kem_keypair_from_seed, 1);
1088
1462
  rb_define_module_function(mPQCrypto, "ml_kem_encapsulate", pqcrypto_ml_kem_encapsulate, 1);
1089
1463
  rb_define_module_function(mPQCrypto, "ml_kem_decapsulate", pqcrypto_ml_kem_decapsulate, 2);
1464
+ rb_define_module_function(mPQCrypto, "ml_kem_512_keypair", pqcrypto_ml_kem_512_keypair, 0);
1465
+ rb_define_module_function(mPQCrypto, "ml_kem_512_keypair_from_seed",
1466
+ pqcrypto_ml_kem_512_keypair_from_seed, 1);
1467
+ rb_define_module_function(mPQCrypto, "ml_kem_512_encapsulate", pqcrypto_ml_kem_512_encapsulate,
1468
+ 1);
1469
+ rb_define_module_function(mPQCrypto, "ml_kem_512_decapsulate", pqcrypto_ml_kem_512_decapsulate,
1470
+ 2);
1471
+ rb_define_module_function(mPQCrypto, "ml_kem_1024_keypair", pqcrypto_ml_kem_1024_keypair, 0);
1472
+ rb_define_module_function(mPQCrypto, "ml_kem_1024_keypair_from_seed",
1473
+ pqcrypto_ml_kem_1024_keypair_from_seed, 1);
1474
+ rb_define_module_function(mPQCrypto, "ml_kem_1024_encapsulate",
1475
+ pqcrypto_ml_kem_1024_encapsulate, 1);
1476
+ rb_define_module_function(mPQCrypto, "ml_kem_1024_decapsulate",
1477
+ pqcrypto_ml_kem_1024_decapsulate, 2);
1090
1478
  rb_define_module_function(mPQCrypto, "hybrid_kem_keypair", pqcrypto_hybrid_kem_keypair, 0);
1091
1479
  rb_define_module_function(mPQCrypto, "hybrid_kem_encapsulate", pqcrypto_hybrid_kem_encapsulate,
1092
1480
  1);
@@ -1095,6 +1483,18 @@ void Init_pqcrypto_secure(void) {
1095
1483
  rb_define_module_function(mPQCrypto, "sign_keypair", pqcrypto_sign_keypair, 0);
1096
1484
  rb_define_module_function(mPQCrypto, "sign", pqcrypto_sign, 2);
1097
1485
  rb_define_module_function(mPQCrypto, "verify", pqcrypto_verify, 3);
1486
+ rb_define_module_function(mPQCrypto, "ml_dsa_44_keypair", pqcrypto_ml_dsa_44_keypair, 0);
1487
+ rb_define_module_function(mPQCrypto, "ml_dsa_44_keypair_from_seed",
1488
+ pqcrypto_ml_dsa_44_keypair_from_seed, 1);
1489
+ rb_define_module_function(mPQCrypto, "ml_dsa_keypair_from_seed",
1490
+ pqcrypto_ml_dsa_keypair_from_seed, 1);
1491
+ rb_define_module_function(mPQCrypto, "ml_dsa_44_sign", pqcrypto_ml_dsa_44_sign, 2);
1492
+ rb_define_module_function(mPQCrypto, "ml_dsa_44_verify", pqcrypto_ml_dsa_44_verify, 3);
1493
+ rb_define_module_function(mPQCrypto, "ml_dsa_87_keypair", pqcrypto_ml_dsa_87_keypair, 0);
1494
+ rb_define_module_function(mPQCrypto, "ml_dsa_87_keypair_from_seed",
1495
+ pqcrypto_ml_dsa_87_keypair_from_seed, 1);
1496
+ rb_define_module_function(mPQCrypto, "ml_dsa_87_sign", pqcrypto_ml_dsa_87_sign, 2);
1497
+ rb_define_module_function(mPQCrypto, "ml_dsa_87_verify", pqcrypto_ml_dsa_87_verify, 3);
1098
1498
  rb_define_module_function(mPQCrypto, "ct_equals", pqcrypto_ct_equals, 2);
1099
1499
  rb_define_module_function(mPQCrypto, "secure_wipe", pqcrypto_secure_wipe, 1);
1100
1500
  rb_define_module_function(mPQCrypto, "version", pqcrypto_version, 0);