pq_crypto 0.6.0 → 0.6.2

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 (154) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/SECURITY.md +7 -0
  4. data/ext/pqcrypto/extconf.rb +2 -0
  5. data/ext/pqcrypto/pqcrypto_ruby_secure.c +139 -0
  6. data/ext/pqcrypto/pqcrypto_secure.c +532 -0
  7. data/ext/pqcrypto/pqcrypto_secure.h +20 -0
  8. data/ext/pqcrypto/pqcrypto_version.h +1 -1
  9. data/ext/pqcrypto/vendor/.vendored +4 -4
  10. data/ext/pqcrypto/vendor/mldsa-native/README.md +23 -10
  11. data/ext/pqcrypto/vendor/mldsa-native/mldsa/README.md +23 -0
  12. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.c +114 -58
  13. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.h +498 -461
  14. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_asm.S +145 -85
  15. data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_config.h +456 -422
  16. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/cbmc.h +47 -25
  17. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/common.h +26 -14
  18. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/ct.h +56 -81
  19. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.h +17 -24
  20. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.c +33 -40
  21. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.h +67 -87
  22. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.c +19 -14
  23. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.h +13 -5
  24. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.c +84 -10
  25. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.h +10 -5
  26. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/auto.h +6 -0
  27. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/fips202_native_aarch64.h +22 -15
  28. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_aarch64_asm.S +376 -0
  29. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_aarch64_asm.S +204 -0
  30. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_aarch64_asm.S +259 -0
  31. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_aarch64_asm.S +1077 -0
  32. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_aarch64_asm.S +987 -0
  33. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +16 -10
  34. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_scalar.h +2 -1
  35. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_v84a.h +1 -1
  36. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x2_v84a.h +4 -2
  37. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_scalar.h +2 -2
  38. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +1 -1
  39. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/api.h +60 -0
  40. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/mve.h +48 -0
  41. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/fips202_native_armv81m.h +18 -1
  42. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +658 -582
  43. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +5 -100
  44. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +26 -25
  45. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/state_extract_bytes_x4_mve.S +334 -0
  46. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/state_xor_bytes_x4_mve.S +355 -0
  47. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/auto.h +8 -3
  48. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/{xkcp.h → keccak_f1600_x4_avx2.h} +11 -8
  49. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/fips202_native_x86_64.h +44 -0
  50. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2_asm.S +454 -0
  51. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccakf1600_constants.c +52 -0
  52. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/meta.h +37 -28
  53. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/aarch64_zetas.c +213 -196
  54. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/arith_native_aarch64.h +248 -64
  55. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/intt_aarch64_asm.S +753 -0
  56. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l4_aarch64_asm.S +129 -0
  57. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l5_aarch64_asm.S +145 -0
  58. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l7_aarch64_asm.S +177 -0
  59. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/ntt_aarch64_asm.S +653 -0
  60. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/pointwise_montgomery_aarch64_asm.S +84 -0
  61. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_caddq_aarch64_asm.S +53 -0
  62. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_chknorm_aarch64_asm.S +55 -0
  63. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_32_aarch64_asm.S +86 -0
  64. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_88_aarch64_asm.S +86 -0
  65. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_32_aarch64_asm.S +103 -0
  66. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_88_aarch64_asm.S +111 -0
  67. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_17_aarch64_asm.S +75 -0
  68. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_19_aarch64_asm.S +72 -0
  69. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_table.c +23 -11
  70. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_aarch64_asm.S +189 -0
  71. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta2_aarch64_asm.S +137 -0
  72. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta4_aarch64_asm.S +130 -0
  73. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta_table.c +520 -516
  74. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_table.c +34 -33
  75. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/api.h +202 -242
  76. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/meta.h +25 -17
  77. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/arith_native_x86_64.h +112 -28
  78. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.c +1 -1
  79. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.h +1 -1
  80. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/intt_avx2_asm.S +2311 -0
  81. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/ntt_avx2_asm.S +2383 -0
  82. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/nttunpack_avx2_asm.S +238 -0
  83. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l4_avx2_asm.S +139 -0
  84. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l5_avx2_asm.S +155 -0
  85. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l7_avx2_asm.S +187 -0
  86. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_avx2_asm.S +130 -0
  87. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_caddq_avx2_asm.S +190 -0
  88. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_32_avx2.c +6 -4
  89. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_88_avx2.c +6 -4
  90. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_32_avx2.c +9 -8
  91. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_88_avx2.c +10 -9
  92. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_17_avx2.c +8 -5
  93. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_19_avx2.c +8 -5
  94. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta2_avx2.c +6 -4
  95. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta4_avx2.c +6 -4
  96. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_table.c +130 -129
  97. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.c +109 -180
  98. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.h +169 -150
  99. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.c +56 -40
  100. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.h +149 -164
  101. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.c +52 -57
  102. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.h +132 -167
  103. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.c +57 -424
  104. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.h +167 -474
  105. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec_lazy.c +308 -0
  106. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec_lazy.h +653 -0
  107. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/reduce.h +22 -29
  108. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/rounding.h +37 -43
  109. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.c +511 -367
  110. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.h +456 -417
  111. data/lib/pq_crypto/hybrid_kem.rb +1 -1
  112. data/lib/pq_crypto/internal.rb +23 -0
  113. data/lib/pq_crypto/kem.rb +27 -34
  114. data/lib/pq_crypto/pkcs8/der.rb +68 -0
  115. data/lib/pq_crypto/pkcs8/private_key_choice.rb +186 -0
  116. data/lib/pq_crypto/pkcs8.rb +51 -468
  117. data/lib/pq_crypto/serialization.rb +19 -29
  118. data/lib/pq_crypto/signature.rb +28 -35
  119. data/lib/pq_crypto/version.rb +1 -1
  120. data/lib/pq_crypto.rb +10 -0
  121. data/script/vendor_libs.rb +3 -3
  122. metadata +44 -35
  123. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm.S +0 -376
  124. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm.S +0 -204
  125. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm.S +0 -259
  126. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm.S +0 -1077
  127. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm.S +0 -987
  128. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.c +0 -488
  129. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.h +0 -16
  130. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/intt.S +0 -753
  131. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l4.S +0 -129
  132. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l5.S +0 -145
  133. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l7.S +0 -177
  134. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/ntt.S +0 -653
  135. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/pointwise_montgomery.S +0 -79
  136. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_caddq_asm.S +0 -53
  137. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_chknorm_asm.S +0 -55
  138. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_32_asm.S +0 -85
  139. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_88_asm.S +0 -85
  140. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_32_asm.S +0 -102
  141. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_88_asm.S +0 -110
  142. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_17_asm.S +0 -72
  143. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_19_asm.S +0 -69
  144. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_asm.S +0 -189
  145. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta2_asm.S +0 -135
  146. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta4_asm.S +0 -128
  147. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/intt.S +0 -2311
  148. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/ntt.S +0 -2383
  149. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/nttunpack.S +0 -239
  150. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise.S +0 -131
  151. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l4.S +0 -139
  152. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l5.S +0 -155
  153. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l7.S +0 -187
  154. data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_caddq_avx2.c +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11bb63e90651697a30709e9621678c7a53224facc67264a331291a8c57520880
4
- data.tar.gz: 111c87fa0809924f0c2997fc0d9c2ea41c43e88044c2802d35370c01ed5f88ca
3
+ metadata.gz: 94d0fc254c0169b1e49ce177e0bf9830c9a1140dc425be9e917e8b2acfb870ed
4
+ data.tar.gz: 148381930753a4d6eb850522619ddf43b602cf9ae9966190c91f276c56f0d426
5
5
  SHA512:
6
- metadata.gz: c95c38ec77fce342cb92febfbdbecdee5c35495323e7f153a2e263e04b89dc6cb13e8bd2874b8abb0b5e19e5b26cde13fb7f6b9d99ef107c5d6e3e41b20d819c
7
- data.tar.gz: 1aa62a91a03203fcd6253e3175d1166b5bf2a3590889509517b8b5eaa57ff6fac49023b253f0859b45c7c2e0f4b28b849a657a5d089890b328da8a234ef7b5c9
6
+ metadata.gz: bb8d4c4683429e99d0147ece542dabdb2276ec3933482d03e3dae81a8bd55b3ed2e617c89221dcdec4dbc34c134027dc406ab7d5e814af2ceef91aa1fb1a0240
7
+ data.tar.gz: 1e911b991634858610ceea12d5cb3a7efbb3a2f480f7ccb531e9afd1e4d01befe673ebec0f1935500dafed37b595d9c9a11a5b9a12adf1ff0720a0a76bf95c96
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.2] - 2026-05-24
4
+
5
+ ### Changed
6
+ - update native mldsa `v1.0.0-beta` → `v1.0.0-beta2`
7
+
8
+ ## [0.6.1] - 2026-05-14
9
+
10
+ ### Security
11
+
12
+ - Moved PKCS#8 PEM handling, PrivateKeyInfo wrapping/unwrapping, and encrypted PKCS#8 encryption/decryption to native C/OpenSSL helpers.
13
+ - Removed Ruby `OpenSSL::ASN1` parsing/building from the PKCS#8 path while preserving the existing Ruby API.
14
+
3
15
  ## [0.6.0] - 2026-05-14
4
16
 
5
17
  ### Added
data/SECURITY.md CHANGED
@@ -23,6 +23,13 @@ PKCS#8 encodings where the linked OpenSSL exposes the corresponding ML-KEM /
23
23
  ML-DSA EVP support. These tests improve compatibility coverage but are not a
24
24
  substitute for a security audit.
25
25
 
26
+ The test surface also includes libFuzzer targets for PKCS#8 DER/PEM decoding
27
+ and pq_crypto-local container decoding, built with AddressSanitizer and
28
+ UndefinedBehaviorSanitizer. A representative clang-17 run executed
29
+ approximately 253 million inputs across these targets and produced no crash
30
+ artifacts. This improves malformed-input parser coverage but is not a proof of
31
+ memory safety and is not a substitute for a security audit.
32
+
26
33
  ## Algorithm notes
27
34
 
28
35
  ### ML-KEM / ML-DSA
@@ -201,6 +201,8 @@ def configure_openssl!
201
201
  abort "openssl/evp.h is required" unless have_header("openssl/evp.h")
202
202
  abort "openssl/rand.h is required" unless have_header("openssl/rand.h")
203
203
  abort "openssl/crypto.h is required" unless have_header("openssl/crypto.h")
204
+ abort "openssl/x509.h is required" unless have_header("openssl/x509.h")
205
+ abort "openssl/pkcs12.h is required" unless have_header("openssl/pkcs12.h")
204
206
 
205
207
  version_check = <<~SRC
206
208
  #include <openssl/opensslv.h>
@@ -1741,6 +1741,136 @@ static VALUE pqcrypto__native_mldsa_verify_mu(int argc, VALUE *argv, VALUE self)
1741
1741
  pq_raise_general_error(call.result);
1742
1742
  }
1743
1743
 
1744
+ static VALUE pqcrypto_pkcs8_private_key_info_to_der(VALUE self, VALUE oid_text, VALUE private_key) {
1745
+ (void)self;
1746
+ uint8_t *out = NULL;
1747
+ size_t out_len = 0;
1748
+ VALUE result;
1749
+ int ret;
1750
+
1751
+ StringValue(oid_text);
1752
+ StringValue(private_key);
1753
+ ret = pq_pkcs8_private_key_info_to_der(&out, &out_len, RSTRING_PTR(oid_text),
1754
+ (const uint8_t *)RSTRING_PTR(private_key),
1755
+ (size_t)RSTRING_LEN(private_key));
1756
+ if (ret != PQ_SUCCESS)
1757
+ pq_raise_general_error(ret);
1758
+ result = pq_string_from_buffer(out, out_len);
1759
+ pq_wipe_and_free(out, out_len);
1760
+ return result;
1761
+ }
1762
+
1763
+ static VALUE pqcrypto_pkcs8_private_key_info_from_der(VALUE self, VALUE der) {
1764
+ (void)self;
1765
+ char *oid_text = NULL;
1766
+ uint8_t *private_key = NULL;
1767
+ size_t private_key_len = 0;
1768
+ VALUE result;
1769
+ int ret;
1770
+
1771
+ StringValue(der);
1772
+ ret = pq_pkcs8_private_key_info_from_der(&oid_text, &private_key, &private_key_len,
1773
+ (const uint8_t *)RSTRING_PTR(der),
1774
+ (size_t)RSTRING_LEN(der));
1775
+ if (ret != PQ_SUCCESS)
1776
+ pq_raise_general_error(ret);
1777
+
1778
+ result = rb_ary_new_capa(2);
1779
+ rb_ary_push(result, rb_str_new_cstr(oid_text));
1780
+ rb_ary_push(result, pq_string_from_buffer(private_key, private_key_len));
1781
+ free(oid_text);
1782
+ pq_wipe_and_free(private_key, private_key_len);
1783
+ return result;
1784
+ }
1785
+
1786
+ static VALUE pqcrypto_pkcs8_encrypt_der(VALUE self, VALUE der, VALUE passphrase,
1787
+ VALUE iterations_value) {
1788
+ (void)self;
1789
+ uint8_t *out = NULL;
1790
+ size_t out_len = 0;
1791
+ int iterations;
1792
+ VALUE result;
1793
+ int ret;
1794
+
1795
+ StringValue(der);
1796
+ StringValue(passphrase);
1797
+ iterations = NUM2INT(iterations_value);
1798
+ ret = pq_pkcs8_encrypt_private_key_info_der(&out, &out_len, (const uint8_t *)RSTRING_PTR(der),
1799
+ (size_t)RSTRING_LEN(der), RSTRING_PTR(passphrase),
1800
+ (size_t)RSTRING_LEN(passphrase), iterations);
1801
+ if (ret != PQ_SUCCESS)
1802
+ pq_raise_general_error(ret);
1803
+ result = pq_string_from_buffer(out, out_len);
1804
+ pq_wipe_and_free(out, out_len);
1805
+ return result;
1806
+ }
1807
+
1808
+ static VALUE pqcrypto_pkcs8_decrypt_der(VALUE self, VALUE der, VALUE passphrase) {
1809
+ (void)self;
1810
+ uint8_t *out = NULL;
1811
+ size_t out_len = 0;
1812
+ VALUE result;
1813
+ int ret;
1814
+
1815
+ StringValue(der);
1816
+ StringValue(passphrase);
1817
+ ret = pq_pkcs8_decrypt_private_key_info_der(&out, &out_len, (const uint8_t *)RSTRING_PTR(der),
1818
+ (size_t)RSTRING_LEN(der), RSTRING_PTR(passphrase),
1819
+ (size_t)RSTRING_LEN(passphrase));
1820
+ if (ret != PQ_SUCCESS)
1821
+ pq_raise_general_error(ret);
1822
+ result = pq_string_from_buffer(out, out_len);
1823
+ pq_wipe_and_free(out, out_len);
1824
+ return result;
1825
+ }
1826
+
1827
+ static VALUE pqcrypto_pkcs8_encrypted_der_p(VALUE self, VALUE der) {
1828
+ (void)self;
1829
+ StringValue(der);
1830
+ return pq_pkcs8_der_is_encrypted_private_key_info((const uint8_t *)RSTRING_PTR(der),
1831
+ (size_t)RSTRING_LEN(der))
1832
+ ? Qtrue
1833
+ : Qfalse;
1834
+ }
1835
+
1836
+ static VALUE pqcrypto_pkcs8_der_to_pem(VALUE self, VALUE der, VALUE encrypted_value) {
1837
+ (void)self;
1838
+ char *pem = NULL;
1839
+ size_t pem_len = 0;
1840
+ VALUE result;
1841
+ int ret;
1842
+
1843
+ StringValue(der);
1844
+ ret = pq_pkcs8_der_to_pem(&pem, &pem_len, (const uint8_t *)RSTRING_PTR(der),
1845
+ (size_t)RSTRING_LEN(der), RTEST(encrypted_value) ? 1 : 0);
1846
+ if (ret != PQ_SUCCESS)
1847
+ pq_raise_general_error(ret);
1848
+ result = rb_str_new(pem, (long)pem_len);
1849
+ pq_secure_wipe(pem, pem_len);
1850
+ free(pem);
1851
+ return result;
1852
+ }
1853
+
1854
+ static VALUE pqcrypto_pkcs8_pem_to_der(VALUE self, VALUE pem) {
1855
+ (void)self;
1856
+ uint8_t *der = NULL;
1857
+ size_t der_len = 0;
1858
+ int encrypted = 0;
1859
+ VALUE result;
1860
+ int ret;
1861
+
1862
+ StringValue(pem);
1863
+ ret =
1864
+ pq_pkcs8_pem_to_der(&der, &der_len, &encrypted, RSTRING_PTR(pem), (size_t)RSTRING_LEN(pem));
1865
+ if (ret != PQ_SUCCESS)
1866
+ pq_raise_general_error(ret);
1867
+ result = rb_ary_new_capa(2);
1868
+ rb_ary_push(result, encrypted ? Qtrue : Qfalse);
1869
+ rb_ary_push(result, pq_string_from_buffer(der, der_len));
1870
+ pq_wipe_and_free(der, der_len);
1871
+ return result;
1872
+ }
1873
+
1744
1874
  static void define_constants(void) {
1745
1875
  rb_define_const(mPQCrypto, "ML_KEM_512_PUBLIC_KEY_BYTES", INT2NUM(MLKEM512_PUBLICKEYBYTES));
1746
1876
  rb_define_const(mPQCrypto, "ML_KEM_512_SECRET_KEY_BYTES", INT2NUM(MLKEM512_SECRETKEYBYTES));
@@ -1911,6 +2041,15 @@ void Init_pqcrypto_secure(void) {
1911
2041
  pqcrypto_secret_key_from_pqc_container_der, 1);
1912
2042
  rb_define_module_function(mPQCrypto, "secret_key_from_pqc_container_pem",
1913
2043
  pqcrypto_secret_key_from_pqc_container_pem, 1);
2044
+ rb_define_module_function(mPQCrypto, "pkcs8_private_key_info_to_der",
2045
+ pqcrypto_pkcs8_private_key_info_to_der, 2);
2046
+ rb_define_module_function(mPQCrypto, "pkcs8_private_key_info_from_der",
2047
+ pqcrypto_pkcs8_private_key_info_from_der, 1);
2048
+ rb_define_module_function(mPQCrypto, "pkcs8_encrypt_der", pqcrypto_pkcs8_encrypt_der, 3);
2049
+ rb_define_module_function(mPQCrypto, "pkcs8_decrypt_der", pqcrypto_pkcs8_decrypt_der, 2);
2050
+ rb_define_module_function(mPQCrypto, "pkcs8_encrypted_der?", pqcrypto_pkcs8_encrypted_der_p, 1);
2051
+ rb_define_module_function(mPQCrypto, "pkcs8_der_to_pem", pqcrypto_pkcs8_der_to_pem, 2);
2052
+ rb_define_module_function(mPQCrypto, "pkcs8_pem_to_der", pqcrypto_pkcs8_pem_to_der, 1);
1914
2053
  rb_define_module_function(mPQCrypto, "_native_mldsa_extract_tr",
1915
2054
  pqcrypto__native_mldsa_extract_tr, -1);
1916
2055
  rb_define_module_function(mPQCrypto, "_native_mldsa_compute_tr",