pq_crypto 0.6.3 → 0.6.5

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +149 -17
  3. data/CHANGELOG.md +73 -0
  4. data/GET_STARTED.md +1 -1
  5. data/README.md +7 -2
  6. data/ext/pqcrypto/extconf.rb +264 -24
  7. data/ext/pqcrypto/pqcrypto_version.h +1 -1
  8. data/ext/pqcrypto/vendor/.vendored +4 -4
  9. data/ext/pqcrypto/vendor/mlkem-native/README.md +2 -4
  10. data/ext/pqcrypto/vendor/mlkem-native/RELEASE.md +98 -0
  11. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.c +8 -7
  12. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.h +21 -1
  13. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_asm.S +45 -44
  14. data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_config.h +36 -0
  15. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/common.h +13 -30
  16. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/compress.c +25 -5
  17. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/compress.h +14 -0
  18. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/context.h +42 -0
  19. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/auto.h +20 -12
  20. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_aarch64_asm.S +5 -3
  21. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_aarch64_asm.S +5 -2
  22. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_aarch64_asm.S +5 -2
  23. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_aarch64_asm.S +10 -7
  24. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_aarch64_asm.S +10 -7
  25. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_v84a.h +2 -1
  26. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x2_v84a.h +2 -1
  27. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_scalar.h +5 -0
  28. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +2 -1
  29. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/mve.h +5 -19
  30. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +8 -5
  31. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/{state_extract_bytes_x4_mve.S → keccak_f1600_x4_state_extract_bytes_mve.S} +14 -14
  32. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/{state_xor_bytes_x4_mve.S → keccak_f1600_x4_state_xor_bytes_mve.S} +12 -12
  33. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2_asm.S +36 -2
  34. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.c +22 -0
  35. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.h +6 -0
  36. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.c +11 -0
  37. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.h +25 -1
  38. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/meta.h +44 -2
  39. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/aarch64_zetas.c +2 -0
  40. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/arith_native_aarch64.h +11 -10
  41. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{intt_aarch64_asm.S → mlkem_intt_aarch64_asm.S} +16 -9
  42. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{ntt_aarch64_asm.S → mlkem_ntt_aarch64_asm.S} +10 -7
  43. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{poly_mulcache_compute_aarch64_asm.S → mlkem_poly_mulcache_compute_aarch64_asm.S} +6 -3
  44. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{poly_reduce_aarch64_asm.S → mlkem_poly_reduce_aarch64_asm.S} +6 -3
  45. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{poly_tobytes_aarch64_asm.S → mlkem_poly_tobytes_aarch64_asm.S} +12 -5
  46. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{poly_tomont_aarch64_asm.S → mlkem_poly_tomont_aarch64_asm.S} +11 -5
  47. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{polyvec_basemul_acc_montgomery_cached_k2_aarch64_asm.S → mlkem_polyvec_basemul_acc_montgomery_cached_k2_aarch64_asm.S} +6 -3
  48. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{polyvec_basemul_acc_montgomery_cached_k3_aarch64_asm.S → mlkem_polyvec_basemul_acc_montgomery_cached_k3_aarch64_asm.S} +6 -3
  49. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{polyvec_basemul_acc_montgomery_cached_k4_aarch64_asm.S → mlkem_polyvec_basemul_acc_montgomery_cached_k4_aarch64_asm.S} +6 -3
  50. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/{rej_uniform_aarch64_asm.S → mlkem_rej_uniform_aarch64_asm.S} +17 -17
  51. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/api.h +21 -8
  52. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/meta.h +1 -1
  53. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/meta.h +4 -0
  54. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/{intt_ppc_asm.S → mlkem_intt_ppc_asm.S} +29 -5
  55. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/{ntt_ppc_asm.S → mlkem_ntt_ppc_asm.S} +22 -1
  56. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/{poly_tomont_ppc_asm.S → mlkem_poly_tomont_ppc_asm.S} +25 -3
  57. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/ppc64le/src/{reduce_ppc_asm.S → mlkem_reduce_ppc_asm.S} +22 -1
  58. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/meta.h +4 -0
  59. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/arith_native_riscv64.h +4 -0
  60. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_poly.c +6 -2
  61. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/meta.h +25 -5
  62. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/arith_native_x86_64.h +20 -20
  63. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/compress_consts.c +14 -3
  64. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/compress_consts.h +8 -0
  65. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{intt_avx2_asm.S → mlkem_intt_avx2_asm.S} +27 -3
  66. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{ntt_avx2_asm.S → mlkem_ntt_avx2_asm.S} +23 -1
  67. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{nttfrombytes_avx2_asm.S → mlkem_nttfrombytes_avx2_asm.S} +27 -3
  68. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{ntttobytes_avx2_asm.S → mlkem_ntttobytes_avx2_asm.S} +27 -3
  69. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{nttunpack_avx2_asm.S → mlkem_nttunpack_avx2_asm.S} +17 -1
  70. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_compress_d10_avx2_asm.S → mlkem_poly_compress_d10_avx2_asm.S} +34 -3
  71. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_compress_d11_avx2_asm.S → mlkem_poly_compress_d11_avx2_asm.S} +33 -2
  72. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_compress_d4_avx2_asm.S → mlkem_poly_compress_d4_avx2_asm.S} +34 -3
  73. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_compress_d5_avx2_asm.S → mlkem_poly_compress_d5_avx2_asm.S} +33 -2
  74. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_decompress_d10_avx2_asm.S → mlkem_poly_decompress_d10_avx2_asm.S} +32 -3
  75. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_decompress_d11_avx2_asm.S → mlkem_poly_decompress_d11_avx2_asm.S} +32 -2
  76. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_decompress_d4_avx2_asm.S → mlkem_poly_decompress_d4_avx2_asm.S} +32 -3
  77. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_decompress_d5_avx2_asm.S → mlkem_poly_decompress_d5_avx2_asm.S} +32 -2
  78. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{poly_mulcache_compute_avx2_asm.S → mlkem_poly_mulcache_compute_avx2_asm.S} +29 -1
  79. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{polyvec_basemul_acc_montgomery_cached_k2_avx2_asm.S → mlkem_polyvec_basemul_acc_montgomery_cached_k2_avx2_asm.S} +35 -1
  80. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{polyvec_basemul_acc_montgomery_cached_k3_avx2_asm.S → mlkem_polyvec_basemul_acc_montgomery_cached_k3_avx2_asm.S} +35 -1
  81. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{polyvec_basemul_acc_montgomery_cached_k4_avx2_asm.S → mlkem_polyvec_basemul_acc_montgomery_cached_k4_avx2_asm.S} +35 -1
  82. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{reduce_avx2_asm.S → mlkem_reduce_avx2_asm.S} +17 -1
  83. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{rej_uniform_avx2_asm.S → mlkem_rej_uniform_avx2_asm.S} +40 -7
  84. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/{tomont_avx2_asm.S → mlkem_tomont_avx2_asm.S} +20 -3
  85. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly.c +7 -2
  86. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly.h +6 -0
  87. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly_k.c +25 -4
  88. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly_k.h +33 -4
  89. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sampling.c +4 -0
  90. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sampling.h +4 -0
  91. data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sys.h +19 -1
  92. data/lib/pq_crypto/version.rb +1 -1
  93. data/script/vendor_libs.rb +3 -3
  94. metadata +41 -43
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aee26c8aa17143d9a17bd24b9435f073cc5d40beff39cbc90d0685d2221ff8d9
4
- data.tar.gz: b0d51294d4639587c619fd5854d2c33d01b5aaa82929aae759dcb8f5776fefbe
3
+ metadata.gz: 68e8c2cd661300cb364be85b4939787590eb88217a2f3cb3463e262b66c4c662
4
+ data.tar.gz: fef5359500d367c68b50b2a72b54cfc8980b3c6dfd6b0e132998212e34cbd47a
5
5
  SHA512:
6
- metadata.gz: a293e6386c7a350be36b271f9e26fef69f1f3e6050fd3eca5e5f69a7f039c39ad08d152cecf46918b1fa8d60908746c2784de27cae3e0351082cb1c63470fe49
7
- data.tar.gz: e12be8a7ad95c42cb27659215c4bfe9201d5b18d531c344279707c2ce74d5fb981328c28beb79e72815e182acc0790b9a5682af8adf17c8b737a12e691d830ec
6
+ metadata.gz: 12bfac65233efde5fa34a30df51494bc6da59985287ae2b3954b377dc9afa949f16b509e98db25d7af2a61a7f3b6a4e572b21f33ff85e797a153ee0e0dde10a0
7
+ data.tar.gz: 25ccfe8a57150355da41a115c401d7ccee2b10a0a6a42957f8335cd3c97024d14261188ee676bc6a122557f52a4ea5894d67062dace53f983b51b4244d9d1a6a
@@ -8,7 +8,7 @@ on:
8
8
  jobs:
9
9
  vendor-verify:
10
10
  name: vendor-verify
11
- runs-on: ubuntu-latest
11
+ runs-on: ubuntu-24.04
12
12
 
13
13
  steps:
14
14
  - name: Checkout
@@ -30,8 +30,8 @@ jobs:
30
30
  strategy:
31
31
  fail-fast: false
32
32
  matrix:
33
- os: [ubuntu-latest, macos-latest]
34
- ruby: ["3.1", "3.4", "4.0"]
33
+ os: [ubuntu-24.04, macos-latest]
34
+ ruby: ["2.7.2", "3.1", "3.4", "4.0"]
35
35
 
36
36
  steps:
37
37
  - name: Checkout
@@ -48,15 +48,139 @@ jobs:
48
48
  with:
49
49
  go-version: "1.26.0"
50
50
 
51
+ - name: Select system OpenSSL 3 for Ruby 2.7 on Linux
52
+ if: matrix.os == 'ubuntu-24.04' && matrix.ruby == '2.7.2'
53
+ shell: bash
54
+ run: |
55
+ set -euxo pipefail
56
+
57
+ sudo apt-get update
58
+ sudo apt-get install -y libssl-dev pkg-config
59
+
60
+ multiarch="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
61
+ system_pc_path="/usr/lib/${multiarch}/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig"
62
+
63
+ version="$(
64
+ PKG_CONFIG_PATH="${system_pc_path}" \
65
+ PKG_CONFIG_LIBDIR="${system_pc_path}" \
66
+ pkg-config --modversion openssl
67
+ )"
68
+
69
+ case "${version}" in
70
+ 3.*) ;;
71
+ *)
72
+ echo "Expected system OpenSSL 3.x, got ${version}"
73
+ exit 1
74
+ ;;
75
+ esac
76
+
77
+ {
78
+ echo "OPENSSL_ROOT_DIR=/usr"
79
+ echo "OPENSSL_DIR="
80
+ echo "PKG_CONFIG_PATH=${system_pc_path}"
81
+ echo "PKG_CONFIG_LIBDIR=${system_pc_path}"
82
+ } >> "${GITHUB_ENV}"
83
+
84
+ echo "System OpenSSL selected: ${version}"
85
+ PKG_CONFIG_PATH="${system_pc_path}" PKG_CONFIG_LIBDIR="${system_pc_path}" \
86
+ pkg-config --variable=includedir openssl
87
+ PKG_CONFIG_PATH="${system_pc_path}" PKG_CONFIG_LIBDIR="${system_pc_path}" \
88
+ pkg-config --variable=libdir openssl
89
+
51
90
  - name: Verify vendored sources
52
91
  run: bundle exec rake vendor:verify
53
92
 
54
93
  - name: Compile extension
55
- run: bundle exec rake compile
94
+ run: bundle exec rake clean compile
95
+
96
+ - name: Verify linked OpenSSL 3 on Linux Ruby 2.7
97
+ if: matrix.os == 'ubuntu-24.04' && matrix.ruby == '2.7.2'
98
+ shell: bash
99
+ run: |
100
+ set -euxo pipefail
101
+
102
+ extension="lib/pqcrypto/pqcrypto_secure.so"
103
+ test -f "${extension}"
104
+ ldd "${extension}" | tee linked-libraries.txt
105
+ # The extension uses libcrypto only (SHA3/SHAKE/EVP/RAND); it links no
106
+ # TLS symbols, so libssl is intentionally not a dependency.
107
+ grep -E 'libcrypto\.so\.3([[:space:]]|$)' linked-libraries.txt
108
+ if grep -E 'libssl\.so' linked-libraries.txt; then
109
+ echo "Unexpected libssl linkage; the extension should need libcrypto only" >&2
110
+ exit 1
111
+ fi
112
+
113
+ - name: Verify linked OpenSSL 3 on macOS Ruby 2.7
114
+ if: matrix.os == 'macos-latest' && matrix.ruby == '2.7.2'
115
+ shell: bash
116
+ run: |
117
+ set -euxo pipefail
118
+
119
+ extension="lib/pqcrypto/pqcrypto_secure.bundle"
120
+ test -f "${extension}"
121
+ otool -L "${extension}" | tee linked-libraries.txt
122
+ # libcrypto only; the extension links no TLS symbols, so libssl is
123
+ # intentionally not a dependency.
124
+ grep -E 'libcrypto\.3\.dylib' linked-libraries.txt
125
+ if grep -E 'libssl\.3\.dylib' linked-libraries.txt; then
126
+ echo "Unexpected libssl linkage; the extension should need libcrypto only" >&2
127
+ exit 1
128
+ fi
56
129
 
57
130
  - name: Run tests
58
131
  run: bundle exec rake test
59
132
 
133
+ - name: Build and install source gem on Linux Ruby 2.7
134
+ if: matrix.os == 'ubuntu-24.04' && matrix.ruby == '2.7.2'
135
+ shell: bash
136
+ run: |
137
+ set -euxo pipefail
138
+
139
+ gem build pq_crypto.gemspec
140
+
141
+ gem_file="$(
142
+ ruby -Ilib -rpq_crypto/version \
143
+ -e 'print "pq_crypto-#{PQCrypto::VERSION}.gem"'
144
+ )"
145
+
146
+ gem install "./${gem_file}" --no-document
147
+
148
+ ruby -e '
149
+ require "pq_crypto"
150
+
151
+ kem = PQCrypto::KEM.generate(:ml_kem_768)
152
+ encapsulation = kem.public_key.encapsulate
153
+ shared_secret = kem.secret_key.decapsulate(encapsulation.ciphertext)
154
+ raise "ML-KEM mismatch" unless shared_secret == encapsulation.shared_secret
155
+
156
+ signature_key = PQCrypto::Signature.generate(:ml_dsa_65)
157
+ message = "ruby-2.7.2-built-gem".b
158
+ signature = signature_key.secret_key.sign(message)
159
+ raise "ML-DSA verify failed" unless signature_key.public_key.verify(message, signature)
160
+ '
161
+
162
+ installed_extension="$(
163
+ ruby -e '
164
+ spec = Gem::Specification.find_by_name("pq_crypto")
165
+ path = Dir[File.join(spec.full_gem_path, "lib", "pqcrypto", "pqcrypto_secure.so")].first
166
+ abort "installed extension not found" unless path
167
+ print path
168
+ '
169
+ )"
170
+
171
+ ldd "${installed_extension}" | tee installed-linked-libraries.txt
172
+ grep -E 'libcrypto\.so\.3([[:space:]]|$)' installed-linked-libraries.txt
173
+ if grep -E 'libssl\.so' installed-linked-libraries.txt; then
174
+ echo "Unexpected libssl linkage; the extension should need libcrypto only" >&2
175
+ exit 1
176
+ fi
177
+
178
+ - name: Show mkmf logs on failure
179
+ if: failure()
180
+ shell: bash
181
+ run: |
182
+ find tmp -name mkmf.log -print -exec cat {} \; || true
183
+
60
184
  interop-openssl-3-5-required:
61
185
  needs: vendor-verify
62
186
  name: interop-openssl-3.5-required
@@ -81,12 +205,12 @@ jobs:
81
205
  sudo ldconfig
82
206
  /opt/openssl-3.5/bin/openssl version
83
207
  /opt/openssl-3.5/bin/openssl version | grep -E '^OpenSSL 3\.(5|[6-9]|[1-9][0-9])\.'
84
- echo /opt/openssl-3.5/bin >> "$GITHUB_PATH"
208
+ echo /opt/openssl-3.5/bin >> "${GITHUB_PATH}"
85
209
  {
86
210
  echo "OPENSSL_ROOT_DIR=/opt/openssl-3.5"
87
211
  echo "PKG_CONFIG_PATH=/opt/openssl-3.5/lib64/pkgconfig"
88
212
  echo "LD_LIBRARY_PATH=/opt/openssl-3.5/lib64"
89
- } >> "$GITHUB_ENV"
213
+ } >> "${GITHUB_ENV}"
90
214
 
91
215
  - name: Set up Ruby
92
216
  uses: ruby/setup-ruby@v1
@@ -103,7 +227,7 @@ jobs:
103
227
  run: bundle exec rake vendor:verify
104
228
 
105
229
  - name: Compile extension
106
- run: bundle exec rake compile
230
+ run: bundle exec rake clean compile
107
231
 
108
232
  - name: Run tests
109
233
  run: |
@@ -117,10 +241,17 @@ jobs:
117
241
  exit 1
118
242
  fi
119
243
 
244
+ - name: Show mkmf logs on failure
245
+ if: failure()
246
+ shell: bash
247
+ run: |
248
+ find tmp -name mkmf.log -print -exec cat {} \; || true
249
+
120
250
  linux-native-backend:
121
251
  needs: test
122
252
  name: linux-native-backend
123
- runs-on: ubuntu-latest
253
+ runs-on: ubuntu-24.04
254
+
124
255
  env:
125
256
  PQCRYPTO_NATIVE_ASM: "1"
126
257
 
@@ -148,18 +279,19 @@ jobs:
148
279
  require "pq_crypto"
149
280
 
150
281
  kem = PQCrypto::KEM.generate(:ml_kem_768)
151
- enc = kem.public_key.encapsulate
152
- raise "ML-KEM mismatch" unless kem.secret_key.decapsulate(enc.ciphertext) == enc.shared_secret
282
+ encapsulation = kem.public_key.encapsulate
283
+ shared_secret = kem.secret_key.decapsulate(encapsulation.ciphertext)
284
+ raise "ML-KEM mismatch" unless shared_secret == encapsulation.shared_secret
153
285
 
154
- sig = PQCrypto::Signature.generate(:ml_dsa_65)
155
- msg = "linux-native-backend".b
156
- signature = sig.secret_key.sign(msg)
157
- raise "ML-DSA verify failed" unless sig.public_key.verify(msg, signature)
286
+ signature_key = PQCrypto::Signature.generate(:ml_dsa_65)
287
+ message = "linux-native-backend".b
288
+ signature = signature_key.secret_key.sign(message)
289
+ raise "ML-DSA verify failed" unless signature_key.public_key.verify(message, signature)
158
290
  '
159
291
 
160
292
  - name: Verify AVX2 native symbols
161
293
  run: |
162
294
  set -euxo pipefail
163
- so="lib/pqcrypto/pqcrypto_secure.so"
164
- test -f "$so"
165
- nm "$so" | grep -E "pqcr_(mlkem|mldsa).*avx2|keccak.*avx2"
295
+ extension="lib/pqcrypto/pqcrypto_secure.so"
296
+ test -f "${extension}"
297
+ nm "${extension}" | grep -E "pqcr_(mlkem|mldsa).*avx2|keccak.*avx2"
data/CHANGELOG.md CHANGED
@@ -1,5 +1,78 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.5] - 2026-08-04
4
+
5
+ ### Changed
6
+
7
+ - update native mlkem `v1.2.0` -> `v1.3.0`
8
+
9
+ Upstream is a feature/integration release with no security fixes and no
10
+ changes to the ML-KEM algorithm implementation. Everything relevant to this
11
+ gem is unchanged: the exported symbol set, all key/ciphertext/shared-secret
12
+ sizes, and the derived key material for ML-KEM-512/768/1024 (verified
13
+ byte-for-byte against `v1.2.0` for both the portable and the AVX2 build,
14
+ including the implicit-rejection path and the SHAKE256/SHA3-256 helpers used
15
+ by the X-Wing combiner).
16
+
17
+ What upstream changed that is visible in the vendored tree:
18
+ - new opt-in `MLK_CONFIG_NO_{KEYPAIR,ENCAPS,DECAPS}_API` build options; the
19
+ gem needs all three operations and does not set them
20
+ - the AArch64 arithmetic and FIPS-202 backends are now gated on compile-time
21
+ NEON availability (`MLK_SYS_AARCH64_NEON`) and on the new `MLK_SYS_CAP_NEON`
22
+ runtime capability, which defaults to "available"
23
+ - new opt-in `MLK_SYS_AARCH64_FAST_SHA3` for CPUs with high SHA3 throughput
24
+ - backend assembly files renamed with an `mlkem_` prefix and assembly-local
25
+ labels namespaced with `mlk_`; both are internal to the vendored aggregator
26
+ `mlkem_native_asm.S` and transparent to this build
27
+ - context-parameter machinery moved into the new `mlkem/src/context.h`
28
+
29
+ Note that `mlkem-native` v1.3.0 is the last release before a breaking v2;
30
+ `release/v1.3` is the upstream support branch.
31
+
32
+ - `mldsa-native` remains pinned at `v1.0.0-beta2`, which is still the latest
33
+ upstream tag.
34
+
35
+ ### Testing
36
+
37
+ - Added `test/native_api_conformance`, a compile-only check that validates the
38
+ hand-written declarations in `ext/pqcrypto/pqcrypto_native_api.h` against the
39
+ vendored upstream headers. The extension deliberately never includes
40
+ `mlkem_native.h` / `mldsa_native.h`, so nothing else in the build could catch
41
+ size or prototype drift after a vendor bump.
42
+
43
+ ### CI
44
+
45
+ - Run the native API conformance check right after `vendor:verify`.
46
+ - Verify that the AArch64 assembly backends are actually compiled in on
47
+ macOS ARM runners, and smoke-test ML-KEM and ML-DSA against that build.
48
+
49
+ ## [0.6.4] - 2026-07-18
50
+
51
+ ### Compatibility
52
+
53
+ - Lowered the minimum supported Ruby version from `>= 3.1` to `>= 2.7.1`.
54
+ - Kept the Ruby 3.4+ scheduler-aware `RB_NOGVL_OFFLOAD_SAFE` path unchanged.
55
+ - Ruby 2.7.1-3.3 use the existing no-GVL compatibility path without claiming Fiber Scheduler offload guarantees.
56
+ - Made the test-only `async` dependency conditional so development dependencies resolve on Ruby 2.7.1.
57
+
58
+ ### CI
59
+
60
+ - Added an Ubuntu Ruby 2.7 compatibility job on Ruby 2.7.2, including the full test suite and a built-gem install smoke test. Ruby 2.7.1 remains the declared floor; the hosted Linux job uses 2.7.2 because exact 2.7.1 is not available through the runner toolchain.
61
+
62
+ ### Build
63
+
64
+ - Fixed OpenSSL 3 discovery on Intel and Apple Silicon macOS by resolving the Homebrew `openssl@3` prefix dynamically.
65
+ - Ignore stale OpenSSL 1.1 `pkg-config` metadata instead of injecting incompatible headers into native builds.
66
+ - Validate the selected OpenSSL prefix and link against the OpenSSL 3 API during configuration, preventing mixed headers/library builds.
67
+ - Link the validated OpenSSL libraries by absolute path, preventing Ruby 2.7 Linux toolchains from selecting their bundled OpenSSL 1.1 while preserving mkmf's libruby-safe default path precedence.
68
+ - Prefer Linux multiarch OpenSSL library directories over generic `lib` directories when resolving an explicit installation prefix.
69
+ - Avoid Clang macro-expansion warnings on Ruby 2.7 by using the function-form `rb_intern2` API without changing symbol semantics.
70
+ - Remove only Ruby 2.7's obsolete macOS `-multiply_defined,suppress` linker option, preserving all other inherited linker flags including `-undefined,dynamic_lookup`.
71
+
72
+ ### Documentation
73
+
74
+ - Documented the Ruby 2.7.1+ support policy and the concurrency guarantees for compatibility runtimes.
75
+
3
76
  ## [0.6.3] - 2026-06-24
4
77
 
5
78
  ### Changed
data/GET_STARTED.md CHANGED
@@ -445,7 +445,7 @@ On Ruby 3.4 and later, signing and verification keep Ruby's scheduler-aware
445
445
  that implements `blocking_operation_wait`, blocking native work can be moved
446
446
  off the event loop.
447
447
 
448
- Ruby 3.1-3.3 are supported as a compatibility path: native operations still
448
+ Ruby 2.7.1-3.3 are supported as a compatibility path: native operations still
449
449
  release the GVL, but `RB_NOGVL_OFFLOAD_SAFE` is not available there, so the gem
450
450
  does not claim Fiber Scheduler offload guarantees on those runtimes.
451
451
 
data/README.md CHANGED
@@ -63,9 +63,9 @@ original algorithms:
63
63
 
64
64
  ## Requirements
65
65
 
66
- - Ruby 3.1 or later
66
+ - Ruby 2.7.1 or later
67
67
  - Ruby 3.4+ keeps the optimized Fiber Scheduler offload path via `RB_NOGVL_OFFLOAD_SAFE`
68
- - Ruby 3.1-3.3 use the compatibility no-GVL path without scheduler offload guarantees
68
+ - Ruby 2.7.1-3.3 use the compatibility no-GVL path without scheduler offload guarantees
69
69
  - a C toolchain with C11 support
70
70
  - OpenSSL 3.0 or later with SHA3-256 and SHAKE256 available
71
71
  - vendored minimal PQ Code Package native snapshot in `ext/pqcrypto/vendor`
@@ -87,6 +87,11 @@ bundle exec rake vendor
87
87
  bundle exec rake compile
88
88
  ```
89
89
 
90
+ Upstream pins are recorded in `ext/pqcrypto/vendor/.vendored` and enforced by
91
+ `bundle exec rake vendor:verify`. `mlkem-native` is pinned at `v1.3.0`, which
92
+ upstream describes as the last release before a breaking `v2`; `release/v1.3` is
93
+ the upstream support branch. `mldsa-native` is pinned at `v1.0.0-beta2`.
94
+
90
95
  The default build uses the portable native source path. Upstream native assembly
91
96
  can be tested explicitly with:
92
97