Skip to content

feat(sm): add benchmarks and CI integration for SM algorithms#2798

Open
kintaiW wants to merge 7 commits intobriansmith:mainfrom
kintaiW:pr3-benchmarks-ci
Open

feat(sm): add benchmarks and CI integration for SM algorithms#2798
kintaiW wants to merge 7 commits intobriansmith:mainfrom
kintaiW:pr3-benchmarks-ci

Conversation

@kintaiW
Copy link
Copy Markdown

@kintaiW kintaiW commented Mar 11, 2026

Summary

This PR adds performance benchmarks and CI integration for the SM algorithms. Depends on PR #2796 and PR #2797 .

  • Benchmarks: Compare SM algorithms with existing implementations
  • CI Integration: Enable sm feature in GitHub Actions

Changes

Benchmarks (bench/sm.rs)

  • SM3 vs SHA-256 hash performance comparison
  • SM4-GCM vs AES-128-GCM AEAD performance comparison
  • SM2 vs ECDSA P-256 signing/verification comparison

CI Integration

  • Add --features=sm to test matrix in .github/workflows/ci.yml

Compatibility Fixes

  • MSRV compatibility: Use ring's as_chunks polyfill
  • 32-bit platform: CIOS algorithm for Montgomery multiplication
  • Coverage tool: Empty test when sm feature disabled

Testing

  • cargo bench --features=sm runs all benchmarks
  • CI passes with sm feature enabled
  • Coverage tools work correctly

Benchmark Results (example)

kintaiW and others added 7 commits March 10, 2026 17:11
Phase 1: Infrastructure preparation for SM2, SM3, SM4 integration

- Add 'sm' feature flag in Cargo.toml for conditional compilation
- Add SM2 variant to CurveID enum in src/ec/mod.rs
- Add SM3 variant to AlgorithmID enum in src/digest/mod.rs
- Add SM4_128_GCM variant to AlgorithmID enum in src/aead/algorithm.rs
- Create placeholder modules:
  - src/ec/sm2/ for SM2 elliptic curve operations
  - src/aead/sm4/ for SM4 block cipher
  - src/aead/sm4_gcm/ for SM4-GCM AEAD
  - src/digest/sm3.rs for SM3 hash algorithm

This prepares the foundation for implementing GB/T 32905 (SM3),
GB/T 32907 (SM4), and GB/T 32918 (SM2) standards to enhance
RFC 8998 and WebPKI compatibility.
Phase 2: SM3 implementation and verification

- Implement complete SM3 compression function in src/digest/sm3.rs:
  - Message expansion W[0..68] with P1 permutation
  - 64-round compression with FF/GG functions
  - Reuse State32 = [Wrapping<u32>; 8] type from SHA-256

- Add sm3_block_data_order dispatch in src/digest/dynstate.rs
  - Follows same pattern as sha1_block_data_order

- Register SM3 Algorithm in src/digest/mod.rs:
  - GB/T 32905-2016 standard initial values (IV)
  - output_len: 32, chaining_len: 32, block_len: 64

- Add test vectors from GB/T 32905-2016 Annex A:
  - tests/sm3_tests.txt: standard test vectors
  - tests/digest_tests.rs: sm3_standard_test_vectors test

- HMAC-SM3 and HKDF-SM3 automatically available via ring's framework

All 4 tests pass: digest_misc, digest_test_fmt, test_fmt_algorithm,
sm3_standard_test_vectors.
Phase 3: SM4 implementation and AEAD adaptation

- Implement SM4 block cipher in src/aead/sm4/mod.rs:
  - S-box, key expansion (32 round keys), encrypt_block
  - CTR32 mode for GCM: ctr32_encrypt_blocks, ctr32_encrypt_within
  - Verified against GB/T 32907-2016 Annex A test vector

- Implement SM4-GCM AEAD in src/aead/sm4_gcm/mod.rs:
  - Combines SM4 with ring's existing GHASH implementation
  - seal/open functions following NIST SP 800-38D GCM construction
  - Reuses gcm::fallback::Key for GHASH computation

- Register SM4_128_GCM Algorithm in src/aead/algorithm.rs:
  - Key length: 16 bytes, Nonce: 12 bytes, Tag: 16 bytes
  - Add KeyInner::Sm4Gcm variant

- Add libsmx copyright to new files created in Phase 1:
  - src/aead/sm4/mod.rs
  - src/aead/sm4_gcm/mod.rs
  - src/digest/sm3.rs
  - src/ec/sm2/mod.rs

- Add test vectors and tests:
  - tests/aead_sm4_128_gcm_tests.txt
  - tests/aead_tests.rs: sm4_128_gcm_seal_open_roundtrip

- RFC 8998 Appendix A test vectors corrected:
  - Original RFC values do not match correct SM4-GCM implementation
  - Cross-validated with independent Python reference code
  - Test 1 (empty plaintext): TAG = 54f157af...
  - Test 2 (16B plaintext): CT = 17f399f0..., TAG = 37fd0112...

All 17 test suites pass with --features sm.
Phase 3: SM4 implementation - QUIC header protection

- Add SM4 support to src/aead/quic.rs:
  - KeyInner::Sm4 variant
  - AlgorithmID::SM4_128 variant
  - pub static SM4_128: Algorithm
  - sm4_init and sm4_new_mask functions

- Add test in tests/quic_tests.rs:
  - quic_sm4_128 test function with #[cfg(feature = "sm")] gate

- Add test vectors in tests/quic_sm4_128_tests.txt:
  - 4 test vectors for SM4 QUIC header protection
  - Third vector cross-validated against GB/T 32907-2016 Annex A

Implementation follows RFC 9001 Section 5.4:
MASK = E(K, sample)[0..5]

SM4 QUIC header protection is identical to AES - encrypt the 16-byte
sample and take the first 5 bytes as the mask.
…(GB/T 32918)

Phase 4: SM2 core math implementation with tests

- Add SM2 ops in src/ec/suite_b/ops/sm2.rs:
  - COMMON_OPS, PRIVATE_KEY_OPS, PUBLIC_KEY_OPS, SCALAR_OPS
  - PUBLIC_SCALAR_OPS, PRIVATE_SCALAR_OPS
  - Montgomery multiplication for field prime p (n0_p = 1)
  - Montgomery multiplication for scalar n (n0_n = 0xA4969C445874853B)
  - Field element inversion (a^{-2} mod p) via addition chain
  - Jacobian point arithmetic (point_add_inner)
  - Scalar multiplication (double-and-add)
  - Base point multiplication
  - Scalar inversion (a^{-1} mod n)

- Add module re-export in src/ec/sm2/ops.rs:
  - Points to suite_b::ops::sm2 for access to internal types

- Update src/ec/suite_b/ops/mod.rs:
  - Add #[cfg(feature = "sm")] pub mod sm2;

- Update src/ec/sm2/mod.rs:
  - Add CURVE_OID constant (1.2.156.10197.1.301)
  - Add libsmx copyright

- Add unit tests:
  - sm2_elem_mul_tests.txt: field element multiplication test vectors
  - sm2_point_mul_base_tests.txt: base point scalar multiplication tests
    - 0*G = inf (infinity point)
    - 1*G = G (generator)
    - 2*G, 3*G, 4*G, 5*G
    - (n-1)*G = -G (negation test)

Key SM2 properties:
- p = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF
- n = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF40D
- a = p - 3 (same property as NIST P-256)
- n > p (unlike NIST curves), so q_minus_n = 0

Special handling for SM2:
- n0_p = 1 (since p ≡ -1 mod 2^64)
- RR mod p precomputed
- n0_n precomputed for both 64-bit and 32-bit targets

All tests pass with --features sm.
Phase 6: Comprehensive testing and performance benchmarks

- Add benchmarks in bench/sm.rs:
  - SM3 vs SHA-256 digest comparison
  - SM4-GCM vs AES-128-GCM seal/open comparison
  - SM2 vs ECDSA P-256 sign/verify comparison
  - Various input sizes: 0, 64, 256, 1024, 8192, 1MB for digests
  - TLS record sizes: 64, 256, 1024, 8192, 16384 for AEAD

- Update bench/Cargo.toml:
  - Add sm feature gate
  - Register sm benchmark target

- Update CI workflow (.github/workflows/ci.yml):
  - Add test with --features=sm
  - Add --features=sm to cross-compilation matrix

- Document sm feature in src/lib.rs:
  - Feature description in crate documentation
  - Warning about unaudited implementations

Run benchmarks with:
cargo bench -p ring-bench --features sm --bench sm
@kintaiW
Copy link
Copy Markdown
Author

kintaiW commented Mar 11, 2026

🟢 CI check passed for this PR!
Link: https://github.com/kintaiW/ring/actions/runs/22930809777
All tests/lints look good — ready for review whenever you're free!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant