diff --git a/.github/workflows/esp32-test.yml b/.github/workflows/esp32-test.yml new file mode 100644 index 0000000..4c3a487 --- /dev/null +++ b/.github/workflows/esp32-test.yml @@ -0,0 +1,74 @@ +name: ESP32 Test Build + +on: + push: + branches: [ master ] + paths: + - 'validation/esp32-test/**' + - '.github/workflows/esp32-test.yml' + pull_request: + paths: + - 'validation/esp32-test/**' + - '.github/workflows/esp32-test.yml' + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + + env: + ESP_IDF_VERSION: v5.4.2 + ESP_IDF_TOOLS_INSTALL_DIR: custom:/opt/esp + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Cache ESP-IDF + uses: actions/cache@v4 + with: + path: | + ~/.espressif + /opt/esp + key: ${{ runner.os }}-espidf-${{ env.ESP_IDF_VERSION }}- + restore-keys: | + ${{ runner.os }}-espidf-${{ env.ESP_IDF_VERSION }}- + ${{ runner.os }}-espidf- + + - name: Set up Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: nightly + components: rust-src + target: riscv32imac-unknown-none-elf + - name: Setup SCCache + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Cache Cargo + uses: Swatinem/rust-cache@v2 + with: + workspaces: "validation/esp32-test" + + - name: Setup ldproxy + uses: taiki-e/cache-cargo-install-action@v2 + with: + tool: ldproxy + + - name: Build ESP32 test + working-directory: validation/esp32-test + run: | + cargo build --release + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: esp32-test-build + path: | + validation/esp32-test/target/riscv32imac-esp-espidf/release/partition-table.bin + validation/esp32-test/target/riscv32imac-esp-espidf/release/esp32-test + validation/esp32-test/target/riscv32imac-esp-espidf/release/bootloader.bin + retention-days: 30 \ No newline at end of file diff --git a/.github/workflows/local_openssl.yml b/.github/workflows/local_openssl.yml index 1fdd9fa..b696a76 100644 --- a/.github/workflows/local_openssl.yml +++ b/.github/workflows/local_openssl.yml @@ -1,37 +1,41 @@ -name: validate-local-openssl - -defaults: - run: - working-directory: validation/local_ping_pong_openssl - -on: - pull_request: - paths-ignore: - - README.md - push: - branches: master - paths-ignore: - - README.md - -permissions: - contents: read - -env: - CARGO_INCREMENTAL: 0 - RUSTFLAGS: "-Dwarnings" - -jobs: - test: - strategy: - matrix: - toolchain: - - stable - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: RustCrypto/actions/cargo-cache@master - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ matrix.toolchain }} - - name: Test against OpenSSL locally - run: cargo test +name: OpenSSL Local Comparison Tests + +defaults: + run: + working-directory: validation/local_ping_pong_openssl + +on: + pull_request: + paths-ignore: + - README.md + push: + branches: [master] + paths-ignore: + - README.md + +permissions: + contents: read + +env: + CARGO_INCREMENTAL: 0 + RUSTFLAGS: "-Dwarnings" + +jobs: + test: + strategy: + matrix: + toolchain: + - stable + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.toolchain }} + - uses: mozilla-actions/sccache-action@v0.0.9 + - uses: Swatinem/rust-cache@v2 + - name: Test against OpenSSL locally + run: cargo test + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" diff --git a/.github/workflows/rustls-real-socket-test.yml b/.github/workflows/rustls-real-socket-test.yml new file mode 100644 index 0000000..19926d9 --- /dev/null +++ b/.github/workflows/rustls-real-socket-test.yml @@ -0,0 +1,60 @@ +name: Rustls Real World Test + +on: + push: + branches: [ master ] + paths: + - 'validation/rustls-real-socket-test/**' + - 'validation/quic-test/**' + - '.github/workflows/rustls-real-socket-test.yml' + pull_request: + paths: + - 'validation/rustls-real-socket-test/**' + - 'validation/quic-test/**' + - '.github/workflows/rustls-real-socket-test.yml' + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + + - name: Setup SCCache + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Cache Cargo + uses: Swatinem/rust-cache@v2 + with: + workspaces: | + validation/rustls-real-socket-test + validation/quic-test + + - name: Run in real socket test release mode + working-directory: validation/rustls-real-socket-test + run: cargo run --release + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + + - name: Run in QUIC test release mode + working-directory: validation/quic-test + run: cargo run --release + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: rustls-real-socket-test-release + path: | + validation/rustls-real-socket-test/target/release/ + retention-days: 30 \ No newline at end of file diff --git a/.github/workflows/rustls-rustcrypto.yml b/.github/workflows/rustls-rustcrypto.yml index 37e374a..82b4070 100644 --- a/.github/workflows/rustls-rustcrypto.yml +++ b/.github/workflows/rustls-rustcrypto.yml @@ -1,102 +1,156 @@ -name: rustls-rustcrypto - -on: - pull_request: - paths-ignore: - - README.md - push: - branches: master - paths-ignore: - - README.md - -permissions: - contents: read - -env: - CARGO_INCREMENTAL: 0 - RUSTFLAGS: "-Dwarnings" - -jobs: - clippy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: 1.75.0 - components: clippy - - run: cargo clippy --all --all-features -- -D warnings - - doc: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - - run: cargo doc --all-features --no-deps - - rustfmt: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - components: rustfmt - - run: cargo fmt --all -- --check - - no_std: - runs-on: ubuntu-latest - strategy: - matrix: - rust: - - 1.75.0 # MSRV - - stable - target: - - armv7a-none-eabi - - thumbv7em-none-eabi - - wasm32-unknown-unknown - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ matrix.rust }} - targets: ${{ matrix.target }} - - run: cargo build --no-default-features --features tls12,alloc --release --target ${{ matrix.target }} - - test: - strategy: - matrix: - toolchain: - - 1.75.0 # MSRV - - stable - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: RustCrypto/actions/cargo-cache@master - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ matrix.toolchain }} - - run: cargo test --features tls12 - - name: Test no_std with alloc - run: cargo test --no-default-features --features tls12,alloc - - cross: - strategy: - matrix: - include: - - target: powerpc-unknown-linux-gnu - rust: 1.75.0 # MSRV - - target: powerpc-unknown-linux-gnu - rust: stable - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: ${{ matrix.deps }} - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ matrix.rust }} - targets: ${{ matrix.target }} - - uses: RustCrypto/actions/cross-install@master - - run: cross test --release --target ${{ matrix.target }} --all-features +name: Unit Tests + +on: + pull_request: + paths-ignore: + - README.md + push: + branches: [master] + paths-ignore: + - README.md + +permissions: + contents: read + +env: + RUSTFLAGS: "-Dwarnings" + +jobs: + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: 1.88.0 + components: clippy + - uses: mozilla-actions/sccache-action@v0.0.9 + - uses: Swatinem/rust-cache@v2 + - run: cargo clippy --all --all-features -- -D warnings + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + + doc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + - uses: mozilla-actions/sccache-action@v0.0.9 + - uses: Swatinem/rust-cache@v2 + - run: cargo doc --all-features --no-deps + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + + rustfmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: rustfmt + - run: cargo fmt --all -- --check + + no_std: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - rust: 1.88.0 + target: armv7a-none-eabi + - rust: stable + target: armv7a-none-eabi + - rust: 1.88.0 + target: thumbv7em-none-eabi + - rust: stable + target: thumbv7em-none-eabi + - rust: 1.88.0 + target: wasm32-unknown-unknown + - rust: stable + target: wasm32-unknown-unknown + - rust: 1.88.0 + target: riscv32imac-unknown-none-elf + - rust: stable + target: riscv32imac-unknown-none-elf + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: ${{ matrix.target }} + - uses: mozilla-actions/sccache-action@v0.0.9 + - uses: Swatinem/rust-cache@v2 + with: + key: ${{ matrix.target }} + - run: cargo build --no-default-features --features tls12,full,alloc --release --target ${{ matrix.target }} + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + RUSTFLAGS: --cfg getrandom_backend="custom" + test: + strategy: + matrix: + toolchain: + - 1.88.0 # MSRV + - stable + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.toolchain }} + - uses: mozilla-actions/sccache-action@v0.0.9 + - uses: Swatinem/rust-cache@v2 + with: + key: ${{ matrix.toolchain }} + - run: cargo test --features tls12 + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + - name: Test no_std with alloc + run: cargo test --no-default-features --features tls12,full,alloc + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + + cross: + strategy: + matrix: + include: + - target: powerpc-unknown-linux-gnu + rust: 1.88.0 # MSRV + - target: powerpc-unknown-linux-gnu + rust: stable + - target: aarch64-unknown-linux-gnu + rust: 1.88.0 + - target: aarch64-unknown-linux-gnu + rust: stable + - target: armv7-unknown-linux-gnueabihf + rust: 1.88.0 + - target: armv7-unknown-linux-gnueabihf + rust: stable + - target: riscv64gc-unknown-linux-gnu + rust: 1.88.0 + - target: riscv64gc-unknown-linux-gnu + rust: stable + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cross-compile library + uses: houseabsolute/actions-rust-cross@v1 + with: + command: build + target: ${{ matrix.target }} + toolchain: ${{ matrix.rust }} + args: "--release --all-features" + - name: Cross-test library + uses: houseabsolute/actions-rust-cross@v1 + with: + command: test + target: ${{ matrix.target }} + toolchain: ${{ matrix.rust }} + args: "--release --all-features" diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..88e9712 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,423 @@ +# rustls-rustcrypto Architecture Documentation + +## High-Level System Overview + +rustls-rustcrypto is a modular cryptographic provider implementation for the Rustls TLS library, utilizing algorithm implementations from the RustCrypto organization. The project serves as a bridge between Rustls' cryptographic interface and RustCrypto's pure-Rust cryptographic implementations, providing a fully Rust-based alternative to traditional C-based cryptographic libraries like OpenSSL or BoringSSL. + +### Core Mission +- Provide a pure Rust cryptographic backend for Rustls +- Support both `std` and `no_std` environments +- Enable cross-platform TLS functionality +- Maintain high performance through optimized RustCrypto implementations +- Ensure security through formal verification and extensive testing + +### Architectural Principles +- **Modularity**: Feature-gated components for minimal binary size +- **Zero-Copy**: Efficient data handling with minimal allocations +- **Type Safety**: Compile-time guarantees through Rust's type system +- **Performance**: Optimized algorithms with hardware acceleration where available +- **Security**: Defense-in-depth with constant-time operations + +## System Architecture + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Application Layer │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ Rustls Library │ │ +│ │ ┌─────────────────────────────────────────────────────┐ │ │ +│ │ │ rustls-rustcrypto Provider │ │ │ +│ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ +│ │ │ │ Cryptographic Modules │ │ │ │ +│ │ │ │ ┌─────────────┬─────────────┬─────────────┐ │ │ │ │ +│ │ │ │ │ AEAD │ Hash │ Sign │ │ │ │ │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ │ │ │ │ AES-GCM │ SHA-256 │ ECDSA │ │ │ │ │ +│ │ │ │ │ ChaCha20 │ SHA-384 │ Ed25519 │ │ │ │ │ +│ │ │ │ │ AES-CCM │ SHA-512 │ RSA │ │ │ │ │ +│ │ │ │ └─────────────┴─────────────┴─────────────┘ │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ │ ┌─────────────┬─────────────┬─────────────┐ │ │ │ │ +│ │ │ │ │ KX │ Verify │ TLS 1.2 │ │ │ │ │ +│ │ │ │ │ │ │ TLS 1.3 │ │ │ │ │ +│ │ │ │ │ X25519 │ WebPKI │ Suites │ │ │ │ │ +│ │ │ │ │ X448 │ Algorithms │ │ │ │ │ │ +│ │ │ │ │ P-256 │ │ │ │ │ │ │ +│ │ │ │ │ P-384 │ │ │ │ │ │ │ +│ │ │ │ │ P-521 │ │ │ │ │ │ │ +│ │ │ │ └─────────────┴─────────────┴─────────────┘ │ │ │ │ +│ │ │ └─────────────────────────────────────────────────┘ │ │ +│ │ └─────────────────────────────────────────────────────┘ │ +│ └─────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Key Components and Modules + +### 1. Core Provider (`src/lib.rs`) + +**Purpose**: Main entry point that implements the `CryptoProvider` trait for Rustls. + +**Key Responsibilities**: +- Initialize and configure the cryptographic provider +- Aggregate all enabled cipher suites and algorithms +- Provide secure random number generation +- Handle private key loading and management + +**Architecture Patterns**: +- **Facade Pattern**: Single entry point hiding complexity +- **Builder Pattern**: Feature-gated configuration +- **Strategy Pattern**: Pluggable cryptographic implementations + +### 2. Authenticated Encryption with Associated Data (AEAD) (`src/aead/`) + +**Purpose**: Implements symmetric encryption algorithms for TLS record protection. + +**Components**: +- **AES-GCM**: Galois/Counter Mode encryption (high performance) +- **AES-CCM**: Counter with CBC-MAC (constrained environments) +- **ChaCha20-Poly1305**: Stream cipher with authentication + +**Key Features**: +- Zero-copy buffer management +- Hardware acceleration support +- Constant-time operations for security + +### 3. Hash Functions (`src/hash.rs`) + +**Purpose**: Provides cryptographic hash functions for TLS operations. + +**Supported Algorithms**: +- SHA-224, SHA-256, SHA-384, SHA-512 +- Generic implementation using RustCrypto's `digest` crate +- Context management for incremental hashing + +**Architecture**: +```rust +pub struct GenericHash { + _phantom: PhantomData, +} +``` + +### 4. Digital Signatures (`src/sign.rs`) + +**Purpose**: Handles digital signature creation and verification. + +**Supported Algorithms**: +- **ECDSA**: Elliptic Curve Digital Signature Algorithm (NIST curves) +- **EdDSA**: Edwards-curve Digital Signature Algorithm (Ed25519) +- **RSA**: RSA with PKCS#1 and PSS padding + +**Key Design**: +- Generic signer implementation with type safety +- Algorithm-specific key handling +- Unified interface for different signature schemes + +### 5. Key Exchange (`src/kx/`) + +**Purpose**: Implements key exchange algorithms for TLS handshake. + +**Supported Groups**: +- **X25519/X448**: Elliptic curve Diffie-Hellman +- **NIST P-256/P-384/P-521**: ECDH over NIST curves + +**Architecture**: +- Generic key exchange framework +- Ephemeral key generation +- Shared secret derivation + +### 6. Signature Verification (`src/verify.rs`) + +**Purpose**: Validates digital signatures during TLS handshake. + +**Integration**: +- Uses WebPKI for certificate validation +- Supports all signature algorithms from signing module +- Algorithm mapping for TLS signature schemes + +### 7. TLS Protocol Support (`src/tls12.rs`, `src/tls13.rs`) + +**Purpose**: Defines cipher suites for TLS 1.2 and TLS 1.3. + +**TLS 1.2 Suites**: +- ECDHE_ECDSA with AES-GCM, AES-CCM, ChaCha20 +- ECDHE_RSA with AES-GCM, ChaCha20 + +**TLS 1.3 Suites**: +- AES-GCM with SHA-256/SHA-384 +- ChaCha20-Poly1305 with SHA-256 + +## Data Flow Diagrams + +### TLS Handshake Flow + +``` +Client Hello + ↓ +Server Hello + Certificate + ↓ +[Key Exchange Module] + ↓ +Client Key Exchange + Certificate Verify + ↓ +[Signature Module] + ↓ +Finished Messages + ↓ +[AEAD Module] + ↓ +Application Data +``` + +### Cryptographic Operation Flow + +``` +Input Data → [Hash Module] → Digest + ↓ + [Signature Module] → Signature + ↓ + [Verification Module] → Validation Result +``` + +### Record Protection Flow + +``` +Plaintext → [AEAD Module] → Ciphertext + Authentication Tag + ↑ + [Key Derivation] + ↑ + [Key Exchange] +``` + +## Dependencies and External Integrations + +### Core Dependencies + +| Component | Purpose | Version | +|-----------|---------|---------| +| `rustls` | TLS library interface | 0.23.x | +| `aead` | AEAD algorithm traits | 0.6.0-rc.2 | +| `digest` | Hash function traits | 0.11.0-rc.1 | +| `signature` | Digital signature traits | 3.0.0-rc.3 | +| `elliptic-curve` | ECC algorithm support | 0.14.0-rc.13 | + +### RustCrypto Ecosystem + +``` +rustls-rustcrypto +├── AEAD: aes-gcm, chacha20poly1305, ccm +├── Hash: sha2 +├── Sign: ecdsa, ed25519-dalek, rsa +├── KX: p256, p384, p521, x25519-dalek, x448 +├── Utils: hmac, pkcs8, sec1, der +└── WebPKI: rustls-webpki +``` + +### External Integrations + +- **Rustls**: Primary integration point via `CryptoProvider` trait +- **WebPKI**: Certificate validation and chain verification +- **Rand**: Cryptographically secure random number generation +- **Zeroize**: Secure memory wiping for sensitive data + +## Architectural Patterns Employed + +### 1. Feature Gates and Conditional Compilation + +```rust +#[cfg(feature = "tls12")] +pub mod tls12; + +#[cfg(feature = "aead")] +pub mod aead; +``` + +**Benefits**: +- Minimal binary size for constrained environments +- Optional dependencies reduce attack surface +- Compile-time optimization + +### 2. Generic Programming with Traits + +```rust +pub trait HashAlgorithm { + const ALGORITHM: hash::HashAlgorithm; +} + +pub struct GenericHash { + _phantom: PhantomData, +} +``` + +**Benefits**: +- Type safety at compile time +- Zero-cost abstractions +- Extensible algorithm support + +### 3. Builder Pattern for Configuration + +```rust +pub fn provider() -> CryptoProvider { + CryptoProvider { + cipher_suites: ALL_CIPHER_SUITES.to_vec(), + kx_groups: kx::ALL_KX_GROUPS.to_vec(), + // ... + } +} +``` + +**Benefits**: +- Declarative configuration +- Immutable construction +- Clear separation of concerns + +### 4. Strategy Pattern for Algorithms + +```rust +pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ + #[cfg(feature = "kx-x25519")] + &x25519::X25519, + #[cfg(feature = "kx-p256")] + &nist::SEC_P256_R1, + // ... +]; +``` + +**Benefits**: +- Runtime algorithm selection +- Easy addition of new algorithms +- Consistent interfaces + +## Scalability Considerations + +### Memory Management + +**Design Decisions**: +- `no_std` support for embedded systems +- Minimal heap allocations +- Stack-based operations where possible +- Zero-copy data handling + +**Trade-offs**: +- Performance vs. memory usage +- Stack size limitations in embedded environments +- Buffer management complexity + +### Performance Optimization + +**Techniques**: +- Hardware acceleration detection +- Precomputed tables for ECC operations +- Constant-time implementations +- SIMD optimizations where available + +**Considerations**: +- CPU architecture-specific optimizations +- Memory bandwidth limitations +- Cache efficiency + +### Concurrency + +**Current State**: +- Single-threaded design +- No internal locking mechanisms +- External synchronization required + +**Future Considerations**: +- Thread-local storage for key material +- Lock-free algorithms where applicable +- Async/await support for I/O operations + +## Security Architecture + +### Threat Model + +**Assumptions**: +- Adversary has access to network traffic +- Side-channel attacks possible +- Implementation bugs exist +- Supply chain attacks possible + +**Mitigations**: +- Constant-time operations +- Secure memory wiping +- Input validation +- Formal verification of algorithms + +### Cryptographic Agility + +**Design Principles**: +- Algorithm negotiation +- Version compatibility +- Migration paths for deprecated algorithms +- Extensible algorithm registration + +## Potential Improvements and Recommendations + +### Developer Experience + +**Enhancements**: +- Better error messages and debugging +- Comprehensive documentation +- Example applications +- Performance benchmarking suite + +### Architecture Modernization + +**Recommendations**: +- Async trait support +- GAT (Generic Associated Types) adoption +- Const generics for compile-time computation +- Procedural macro generation of boilerplate + +### 5. Ecosystem Integration + +**Opportunities**: +- Integration with other Rust TLS libraries +- WebAssembly support +- Mobile platform optimizations +- Cloud-native optimizations + +## Testing and Validation Strategy + +### Unit Testing +- Algorithm correctness verification +- Edge case handling +- Property-based testing + +### Integration Testing +- End-to-end TLS handshake validation +- Cross-platform compatibility +- Performance regression detection + +### Fuzz Testing +- Input fuzzing for cryptographic operations +- TLS protocol fuzzing +- Memory safety verification + +## Deployment and Distribution + +### Binary Size Optimization +- Feature gate analysis +- Link-time optimization +- Dead code elimination + +### Platform Support +- Tier 1 platform coverage +- Embedded system support +- WebAssembly compilation + +### Package Management +- Cargo feature ecosystem +- Version compatibility matrix +- Dependency management + +## Conclusion + +rustls-rustcrypto represents a sophisticated approach to cryptographic provider implementation, balancing performance, security, and flexibility. Its modular architecture enables fine-grained control over functionality while maintaining a clean, type-safe interface. The extensive use of Rust's type system and compile-time features ensures both correctness and performance. + +The project's design demonstrates best practices in Rust cryptography implementation, serving as a reference for secure, efficient cryptographic software development. Future enhancements should focus on expanding algorithm support, improving performance, and enhancing developer experience while maintaining the core principles of security and correctness. + +--- + +*This architecture documentation is maintained alongside the codebase and should be updated with significant architectural changes.* \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c55f92e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,34 @@ +## Contributing + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +## Tips +When contributing to this test crate: + +1. Maintain compatibility with ESP32 variants +2. Keep memory usage optimized +3. Add comprehensive logging +4. Update documentation for any changes +5. Test on physical hardware when possible + +## Related Documentation + +- [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/) +- [Rust on ESP32](https://esp-rs.github.io/book/) +- [rustls Documentation](https://docs.rs/rustls/) +- [RustCrypto Documentation](https://docs.rs/rustcrypto/) +- [RustCrypto GitHub organization](https://github.com/RustCrypto) + +## Testing Strategy + +### Unit Tests +```bash +cargo test -p rustls-real-socket-test +``` + +### Integration Tests +```bash +cargo test --test integration +``` diff --git a/Cargo.lock b/Cargo.lock index 2643e4a..c8a0b4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,47 +1,48 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aead" -version = "0.5.2" +version = "0.6.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" dependencies = [ - "crypto-common", - "generic-array", + "crypto-common 0.2.0-rc.4", + "inout", ] [[package]] name = "aes" -version = "0.8.4" +version = "0.9.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +checksum = "7e713c57c2a2b19159e7be83b9194600d7e8eb3b7c2cd67e671adf47ce189a05" dependencies = [ "cfg-if", "cipher", "cpufeatures", + "zeroize", ] [[package]] name = "aes-gcm" -version = "0.10.3" +version = "0.11.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +checksum = "0686ba04dc80c816104c96cd7782b748f6ad58c5dd4ee619ff3258cf68e83d54" dependencies = [ "aead", - "aes", "cipher", "ctr", "ghash", "subtle", + "zeroize", ] [[package]] name = "autocfg" -version = "1.0.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base16ct" @@ -49,11 +50,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base16ct" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" + [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "block-buffer" @@ -64,29 +71,59 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.11.0-rc.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" +dependencies = [ + "hybrid-array", +] + [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + [[package]] name = "cc" -version = "1.0.90" +version = "1.2.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "ccm" +version = "0.6.0-pre" +source = "git+https://github.com/RustCrypto/AEADs/#b7efce0e5ef4ce1d53a0ae4c73e2cf97087f0efc" +dependencies = [ + "aead", + "cipher", + "ctr", + "subtle", +] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "chacha20" -version = "0.9.1" +version = "0.10.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +checksum = "9bd162f2b8af3e0639d83f28a637e4e55657b7a74508dba5a9bf4da523d5c9e9" dependencies = [ "cfg-if", "cipher", @@ -95,26 +132,25 @@ dependencies = [ [[package]] name = "chacha20poly1305" -version = "0.10.1" +version = "0.11.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +checksum = "ecc260dd2c69bf5581e9603fff348843363a649edde02768e84c0088f21c3f52" dependencies = [ "aead", "chacha20", "cipher", "poly1305", - "zeroize", ] [[package]] name = "cipher" -version = "0.4.4" +version = "0.5.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" dependencies = [ - "crypto-common", + "block-buffer 0.11.0-rc.5", + "crypto-common 0.2.0-rc.4", "inout", - "zeroize", ] [[package]] @@ -123,11 +159,17 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-oid" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" + [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -139,7 +181,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.7.0-rc.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4113edbc9f68c0a64d5b911f803eb245d04bb812680fd56776411f69c670f3e0" +dependencies = [ + "hybrid-array", + "num-traits", + "rand_core 0.9.3", + "serdect", "subtle", "zeroize", ] @@ -154,27 +210,46 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "crypto-primes" +version = "0.7.0-pre.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f2523fbb68811c8710829417ad488086720a6349e337c38d12fa81e09e50bf" +dependencies = [ + "crypto-bigint 0.7.0-rc.8", + "libm", + "rand_core 0.9.3", +] + [[package]] name = "ctr" -version = "0.9.2" +version = "0.10.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +checksum = "27e41d01c6f73b9330177f5cf782ae5b581b5f2c7840e298e0275ceee5001434" dependencies = [ "cipher", ] [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "5.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "6f9200d1d13637f15a6acb71e758f64624048d85b31a5fdbfd8eca1e2687d0b7" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "digest", + "digest 0.11.0-rc.3", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -193,24 +268,60 @@ dependencies = [ [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid", - "pem-rfc7468", + "const-oid 0.9.6", + "der_derive", + "flagset", + "pem-rfc7468 0.7.0", "zeroize", ] +[[package]] +name = "der" +version = "0.8.0-rc.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d8dd2f26c86b27a2a8ea2767ec7f9df7a89516e4794e54ac01ee618dda3aa4" +dependencies = [ + "const-oid 0.10.1", + "pem-rfc7468 1.0.0-rc.3", + "zeroize", +] + +[[package]] +name = "der_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", + "block-buffer 0.10.4", + "const-oid 0.9.6", + "crypto-common 0.1.6", + "subtle", +] + +[[package]] +name = "digest" +version = "0.11.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac89f8a64533a9b0eaa73a68e424db0fb1fd6271c74cc0125336a05f090568d" +dependencies = [ + "block-buffer 0.11.0-rc.5", + "const-oid 0.10.1", + "crypto-common 0.2.0-rc.4", "subtle", ] @@ -220,74 +331,176 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der", - "digest", - "elliptic-curve", - "rfc6979", - "signature", - "spki", + "der 0.7.10", + "digest 0.10.7", + "elliptic-curve 0.13.8", + "rfc6979 0.4.0", + "signature 2.2.0", + "spki 0.7.3", +] + +[[package]] +name = "ecdsa" +version = "0.17.0-rc.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ab355ec063f7a110eb627471058093aba00eb7f4e70afbd15e696b79d1077b" +dependencies = [ + "der 0.8.0-rc.9", + "digest 0.11.0-rc.3", + "elliptic-curve 0.14.0-rc.15", + "rfc6979 0.5.0-rc.1", + "signature 3.0.0-rc.4", + "spki 0.8.0-rc.4", + "zeroize", ] [[package]] name = "ed25519" -version = "2.2.3" +version = "3.0.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +checksum = "9ef49c0b20c0ad088893ad2a790a29c06a012b3f05bcfc66661fd22a94b32129" dependencies = [ - "pkcs8", - "signature", + "pkcs8 0.11.0-rc.7", + "signature 3.0.0-rc.4", ] [[package]] name = "ed25519-dalek" -version = "2.1.1" +version = "3.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +checksum = "ad207ed88a133091f83224265eac21109930db09bedcad05d5252f2af2de20a1" dependencies = [ "curve25519-dalek", "ed25519", "serde", - "sha2", + "sha2 0.11.0-rc.2", + "signature 3.0.0-rc.4", "subtle", "zeroize", ] +[[package]] +name = "ed448" +version = "0.5.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812bad302d88d3e1774df473dffc64f18fedc4be6b6066c470ae3c733b9f9765" +dependencies = [ + "pkcs8 0.11.0-rc.7", + "signature 3.0.0-rc.4", +] + +[[package]] +name = "ed448-goldilocks" +version = "0.14.0-pre.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6640f5292892cf2f68d41e85739e4488271c041c877f60921e267a135d3186af" +dependencies = [ + "ed448", + "elliptic-curve 0.14.0-rc.15", + "hash2curve", + "rand_core 0.9.3", + "serdect", + "sha3", + "signature 3.0.0-rc.4", + "subtle", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "elliptic-curve" version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base16ct", - "crypto-bigint", - "digest", - "ff", + "base16ct 0.2.0", + "crypto-bigint 0.5.5", + "digest 0.10.7", + "ff 0.13.1", "generic-array", - "group", + "group 0.13.0", + "pem-rfc7468 0.7.0", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "sec1 0.7.3", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.14.0-rc.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e3be87c458d756141f3b6ee188828132743bf90c7d14843e2835d6443e5fb03" +dependencies = [ + "base16ct 0.3.0", + "crypto-bigint 0.7.0-rc.8", + "digest 0.11.0-rc.3", + "ff 0.14.0-pre.0", + "group 0.14.0-pre.0", "hkdf", - "pem-rfc7468", - "pkcs8", - "rand_core", - "sec1", + "hybrid-array", + "pem-rfc7468 1.0.0-rc.3", + "pkcs8 0.11.0-rc.7", + "rand_core 0.9.3", + "sec1 0.8.0-rc.10", "subtle", "zeroize", ] +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ - "rand_core", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "ff" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d42dd26f5790eda47c1a2158ea4120e32c35ddc9a7743c98a292accc01b54ef3" +dependencies = [ + "rand_core 0.9.3", "subtle", ] [[package]] name = "fiat-crypto" -version = "0.2.6" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + +[[package]] +name = "find-msvc-tools" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" + +[[package]] +name = "flagset" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" +checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" [[package]] name = "generic-array" @@ -302,22 +515,33 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "wasi", + "r-efi", + "wasi 0.14.7+wasi-0.2.4", ] [[package]] name = "ghash" -version = "0.5.1" +version = "0.6.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +checksum = "4f88107cb02ed63adcc4282942e60c4d09d80208d33b360ce7c729ce6dae1739" dependencies = [ - "opaque-debug", "polyval", ] @@ -327,18 +551,41 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff", - "rand_core", + "ff 0.13.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff6a0b2dd4b981b1ae9e3e6830ab146771f3660d31d57bafd9018805a91b0f1" +dependencies = [ + "ff 0.14.0-pre.0", + "rand_core 0.9.3", + "subtle", +] + +[[package]] +name = "hash2curve" +version = "0.14.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4dc9fc1e7c8838651b0541e9af3ae5d39114bed92d199fcace0d1c684c752c9" +dependencies = [ + "digest 0.11.0-rc.3", + "elliptic-curve 0.14.0-rc.15", + "ff 0.14.0-pre.0", "subtle", ] [[package]] name = "hkdf" -version = "0.12.4" +version = "0.13.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +checksum = "d8ef30358b03ca095a5b910547f4f8d4b9f163e4057669c5233ef595b1ecf008" dependencies = [ - "hmac", + "hmac 0.13.0-rc.2", ] [[package]] @@ -347,44 +594,82 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", +] + +[[package]] +name = "hmac" +version = "0.13.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3fd4dc94c318c1ede8a2a48341c250d6ddecd3ba793da2820301a9f92417ad9" +dependencies = [ + "digest 0.11.0-rc.3", +] + +[[package]] +name = "hybrid-array" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +dependencies = [ + "subtle", + "typenum", + "zeroize", ] [[package]] name = "inout" -version = "0.1.3" +version = "0.2.0-rc.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "1603f76010ff924b616c8f44815a42eb10fb0b93d308b41deaa8da6d4251fd4b" dependencies = [ - "generic-array", + "hybrid-array", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "keccak" +version = "0.2.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d546793a04a1d3049bd192856f804cfe96356e2cf36b54b4e575155babe9f41" +dependencies = [ + "cpufeatures", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] name = "libc" -version = "0.2.154" +version = "0.2.176" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "log" -version = "0.4.21" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "num-bigint-dig" @@ -414,9 +699,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -425,9 +710,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -435,45 +720,62 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "opaque-debug" -version = "0.3.1" +name = "p256" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "primeorder 0.13.6", + "sha2 0.10.9", +] [[package]] name = "p256" -version = "0.13.2" +version = "0.14.0-pre.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +checksum = "81b374901df34ee468167a58e2a49e468cb059868479cafebeb804f6b855423d" dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", + "ecdsa 0.17.0-rc.7", + "elliptic-curve 0.14.0-rc.15", + "primefield", + "primeorder 0.14.0-pre.9", + "sha2 0.11.0-rc.2", ] [[package]] name = "p384" -version = "0.13.0" +version = "0.14.0-pre.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +checksum = "701032b3730df6b882496d6cee8221de0ce4bc11ddc64e6d89784aa5b8a6de30" dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", + "ecdsa 0.17.0-rc.7", + "elliptic-curve 0.14.0-rc.15", + "fiat-crypto", + "primefield", + "primeorder 0.14.0-pre.9", + "sha2 0.11.0-rc.2", ] [[package]] -name = "paste" -version = "1.0.15" +name = "p521" +version = "0.14.0-pre.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "40ba29c2906eb5c89a8c411c4f11243ee4e5517ee7d71d9a13fedc877a6057b1" +dependencies = [ + "base16ct 0.3.0", + "ecdsa 0.17.0-rc.7", + "elliptic-curve 0.14.0-rc.15", + "primefield", + "primeorder 0.14.0-pre.9", + "sha2 0.11.0-rc.2", +] [[package]] name = "pem-rfc7468" @@ -484,25 +786,34 @@ dependencies = [ "base64ct", ] +[[package]] +name = "pem-rfc7468" +version = "1.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e58fab693c712c0d4e88f8eb3087b6521d060bcaf76aeb20cb192d809115ba" +dependencies = [ + "base64ct", +] + [[package]] name = "pkcs1" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der", - "pkcs8", - "spki", + "der 0.7.10", + "pkcs8 0.10.2", + "spki 0.7.3", ] [[package]] -name = "pkcs5" -version = "0.7.1" +name = "pkcs1" +version = "0.8.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" +checksum = "986d2e952779af96ea048f160fd9194e1751b4faea78bcf3ceb456efe008088e" dependencies = [ - "der", - "spki", + "der 0.8.0-rc.9", + "spki 0.8.0-rc.4", ] [[package]] @@ -511,45 +822,63 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der", - "pkcs5", - "spki", + "der 0.7.10", + "spki 0.7.3", ] [[package]] -name = "platforms" -version = "3.3.0" +name = "pkcs8" +version = "0.11.0-rc.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" +checksum = "93eac55f10aceed84769df670ea4a32d2ffad7399400d41ee1c13b1cd8e1b478" +dependencies = [ + "der 0.8.0-rc.9", + "spki 0.8.0-rc.4", + "subtle", +] [[package]] name = "poly1305" -version = "0.8.0" +version = "0.9.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +checksum = "fb78a635f75d76d856374961deecf61031c0b6f928c83dc9c0924ab6c019c298" dependencies = [ "cpufeatures", - "opaque-debug", "universal-hash", ] [[package]] name = "polyval" -version = "0.6.2" +version = "0.7.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +checksum = "1ffd40cc99d0fbb02b4b3771346b811df94194bc103983efa0203c8893755085" dependencies = [ "cfg-if", "cpufeatures", - "opaque-debug", "universal-hash", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "primefield" +version = "0.14.0-pre.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "d7fcd4a163053332fd93f39b81c133e96a98567660981654579c90a99062fbf5" +dependencies = [ + "crypto-bigint 0.7.0-rc.8", + "ff 0.14.0-pre.0", + "rand_core 0.9.3", + "subtle", + "zeroize", +] [[package]] name = "primeorder" @@ -557,27 +886,42 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ - "elliptic-curve", + "elliptic-curve 0.13.8", +] + +[[package]] +name = "primeorder" +version = "0.14.0-pre.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c36e8766fcd270fa9c665b9dc364f570695f5a59240949441b077a397f15b74" +dependencies = [ + "elliptic-curve 0.14.0-rc.15", ] [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.5" @@ -585,7 +929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -595,7 +939,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -604,7 +948,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", ] [[package]] @@ -613,60 +966,89 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "hmac", + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "rfc6979" +version = "0.5.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369f9c4f79388704648e7bcb92749c0d6cf4397039293a9b747694fa4fb4bae" +dependencies = [ + "hmac 0.13.0-rc.2", "subtle", ] [[package]] name = "ring" -version = "0.17.8" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.16", "libc", - "spin 0.9.8", "untrusted", "windows-sys", ] [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" dependencies = [ - "const-oid", - "digest", + "const-oid 0.9.6", + "digest 0.10.7", "num-bigint-dig", "num-integer", "num-traits", - "pkcs1", - "pkcs8", - "rand_core", - "sha2", - "signature", - "spki", + "pkcs1 0.7.5", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "sha2 0.10.9", + "signature 2.2.0", + "spki 0.7.3", + "subtle", + "zeroize", +] + +[[package]] +name = "rsa" +version = "0.10.0-rc.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf8955ab399f6426998fde6b76ae27233cce950705e758a6c17afd2f6d0e5d52" +dependencies = [ + "const-oid 0.10.1", + "crypto-bigint 0.7.0-rc.8", + "crypto-primes", + "digest 0.11.0-rc.3", + "pkcs1 0.8.0-rc.4", + "pkcs8 0.11.0-rc.7", + "rand_core 0.9.3", + "sha2 0.11.0-rc.2", + "signature 3.0.0-rc.4", + "spki 0.8.0-rc.4", "subtle", "zeroize", ] [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" dependencies = [ "log", "once_cell", @@ -678,44 +1060,65 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-rustcrypto" version = "0.0.2-alpha" dependencies = [ "aead", + "aes", "aes-gcm", + "bytes", + "ccm", + "chacha20", "chacha20poly1305", - "crypto-common", - "der", - "digest", - "ecdsa", + "cipher", + "crypto-common 0.2.0-rc.4", + "der 0.8.0-rc.9", + "digest 0.11.0-rc.3", + "ecdsa 0.17.0-rc.7", "ed25519-dalek", - "getrandom", - "hmac", - "p256", + "ed448-goldilocks", + "elliptic-curve 0.14.0-rc.15", + "enum_dispatch", + "hmac 0.13.0-rc.2", + "itertools", + "p256 0.13.2", + "p256 0.14.0-pre.11", "p384", - "paste", - "pkcs8", - "rand_core", - "rsa", + "p521", + "pkcs1 0.8.0-rc.4", + "pkcs8 0.11.0-rc.7", + "rand_core 0.6.4", + "rand_core 0.9.3", + "rsa 0.10.0-rc.9", + "rsa 0.9.8", "rustls", "rustls-pki-types", "rustls-webpki", - "sec1", - "sha2", - "signature", + "sec1 0.8.0-rc.10", + "sha2 0.11.0-rc.2", + "signature 2.2.0", + "signature 3.0.0-rc.4", + "thiserror", + "tinyvec", + "typenum", "x25519-dalek", + "x448", + "x509-cert", ] [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.103.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" dependencies = [ "ring", "rustls-pki-types", @@ -728,72 +1131,146 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "base16ct", - "der", + "base16ct 0.2.0", + "der 0.7.10", "generic-array", - "pkcs8", + "pkcs8 0.10.2", + "subtle", + "zeroize", +] + +[[package]] +name = "sec1" +version = "0.8.0-rc.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dff52f6118bc9f0ac974a54a639d499ac26a6cad7a6e39bc0990c19625e793b" +dependencies = [ + "base16ct 0.3.0", + "der 0.8.0-rc.9", + "hybrid-array", "subtle", "zeroize", ] [[package]] name = "semver" -version = "1.0.22" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "serdect" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" +dependencies = [ + "base16ct 0.3.0", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha2" -version = "0.10.8" +version = "0.11.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "d1e3878ab0f98e35b2df35fe53201d088299b41a6bb63e3e34dada2ac4abd924" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.11.0-rc.3", +] + +[[package]] +name = "sha3" +version = "0.11.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2103ca0e6f4e9505eae906de5e5883e06fc3b2232fb5d6914890c7bbcb62f478" +dependencies = [ + "digest 0.11.0-rc.3", + "keccak", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signature" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", - "rand_core", + "digest 0.10.7", + "rand_core 0.6.4", ] [[package]] -name = "smallvec" -version = "1.13.1" +name = "signature" +version = "3.0.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "fc280a6ff65c79fbd6622f64d7127f32b85563bca8c53cd2e9141d6744a9056d" +dependencies = [ + "digest 0.11.0-rc.3", + "rand_core 0.9.3", +] [[package]] -name = "spin" -version = "0.5.2" +name = "smallvec" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "spin" @@ -808,45 +1285,111 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der", + "der 0.7.10", +] + +[[package]] +name = "spki" +version = "0.8.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" +dependencies = [ + "base64ct", + "der 0.8.0-rc.9", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.52" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tls_codec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" +dependencies = [ + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "universal-hash" -version = "0.5.1" +version = "0.6.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" dependencies = [ - "crypto-common", + "crypto-common 0.2.0-rc.4", "subtle", ] @@ -858,15 +1401,33 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] [[package]] name = "windows-sys" @@ -879,13 +1440,14 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -894,62 +1456,119 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "x25519-dalek" -version = "2.0.1" +version = "3.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +checksum = "3a45998121837fd8c92655d2334aa8f3e5ef0645cdfda5b321b13760c548fd55" dependencies = [ "curve25519-dalek", - "rand_core", + "rand_core 0.9.3", "zeroize", ] +[[package]] +name = "x448" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20e03d60707405e830d70c431a837b0df7a04450e50caee26a5a5a1bb78b7c9" +dependencies = [ + "ed448-goldilocks", + "rand_core 0.9.3", + "zeroize", +] + +[[package]] +name = "x509-cert" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" +dependencies = [ + "const-oid 0.9.6", + "der 0.7.10", + "sha1", + "signature 2.2.0", + "spki 0.7.3", + "tls_codec", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] diff --git a/Cargo.toml b/Cargo.toml index 01ab6b0..1d0cec3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,49 +11,249 @@ readme = "README.md" repository = "https://github.com/RustCrypto/rustls-rustcrypto" categories = ["cryptography", "no-std"] keywords = ["rustls", "tls"] -edition = "2021" -rust-version = "1.75" -resolver = "1" # Hack to enable the `custom` feature of `getrandom` +edition = "2024" +rust-version = "1.88.0" +resolver = "2" # Ensure all dependencies + feats are mapped to crate features for correct usage # default features often have std breaking no_std and potentially other unwanted [dependencies] -aead = { version = "0.5.2", default-features = false } -aes-gcm = { version = "0.10.3", default-features = false, features = ["aes", "alloc"] } -chacha20poly1305 = { version = "0.10.1", default-features = false } -crypto-common = { version = "0.1.6", default-features = false } -der = { version = "0.7.9", default-features = false } -digest = { version = "0.10.7", default-features = false } -ecdsa = { version = "0.16.8", default-features = false, features = ["alloc"] } -ed25519-dalek = { version = "2", default-features = false, features = ["pkcs8"] } -hmac = { version = "0.12.1", default-features = false } -p256 = { version = "0.13.2", default-features = false, features = ["pem", "ecdsa", "ecdh"] } -p384 = { version = "0.13.0", default-features = false, features = ["pem", "ecdsa", "ecdh"] } -paste = { version = "1.0.15", default-features = false } -pkcs8 = { version = "0.10.2", default-features = false, features = ["pem", "pkcs5"] } -pki-types = { package = "rustls-pki-types", version = "1.0.1", default-features = false } -rand_core = { version = "0.6.4", default-features = false, features = ["getrandom"] } -rsa = { version = "0.9.2", default-features = false, features = ["sha2"] } -rustls = { version = "0.23.12", default-features = false } -sec1 = { version = "0.7.3", default-features = false, features = ["pkcs8", "pem"] } -sha2 = { version = "0.10.7", default-features = false } -signature = { version = "2.1.0", default-features = false } -webpki = { package = "rustls-webpki", version = "0.102.0", default-features = false } -x25519-dalek = { version = "2", default-features = false } +# Cryptographic dependencies +aead = { version = "0.6.0-rc.2", default-features = false, optional = true } +aes = { version = "0.9.0-rc.1", default-features = false, optional = true } +aes-gcm = { version = "0.11.0-rc.1", default-features = false, optional = true } +ccm = { version = "0.6.0-pre", default-features = false, optional = true, git = "https://github.com/RustCrypto/AEADs/" } +chacha20 = { version = "0.10.0-rc.2", default-features = false, optional = true } +chacha20poly1305 = { version = "0.11.0-rc.1", default-features = false, optional = true } +cipher = "0.5.0-rc.1" +crypto-common = { version = "0.2.0-rc.4", default-features = false } +der = { version = "0.8.0-rc.9", default-features = false, optional = true } +digest = { version = "0.11.0-rc.3", default-features = false } +ecdsa = { version = "0.17.0-rc.7", default-features = false, optional = true } +ed25519-dalek = { version = "3.0.0-pre.1", default-features = false, optional = true } +ed448-goldilocks = { version = "0.14.0-pre.4", default-features = false, optional = true } +elliptic-curve = { version = "0.14.0-rc.15", default-features = false, optional = true } +hmac = { version = "0.13.0-rc.2", default-features = false } +p256 = { version = "0.14.0-pre.11", default-features = false, optional = true } +p384 = { version = "0.14.0-pre.11", default-features = false, optional = true } +p521 = { version = "0.14.0-pre.11", default-features = false, optional = true } +pkcs1 = { version = "0.8.0-rc.4", default-features = false, optional = true } +pkcs8 = { version = "0.11.0-rc.7", default-features = false, optional = true } +rsa = { version = "0.10.0-rc.9", default-features = false, optional = true } +sec1 = { version = "0.8.0-rc.10", default-features = false, optional = true } +sha2 = { version = "0.11.0-rc.2", default-features = false } +signature = { version = "3.0.0-rc.4", default-features = false, optional = true } +typenum = { version = "1.18.0", features = ["no_std", "const-generics"] } +x25519-dalek = { version = "3.0.0-pre.1", default-features = false, optional = true } +x448 = { version = "=0.14.0-pre.0", default-features = false, optional = true } + +# External groups +pki-types = { package = "rustls-pki-types", version = "1.12.0", default-features = false } +rand_core = { version = "0.9.3", default-features = false, features = [ + "os_rng", +], optional = true } +rustls = { version = "0.23.32", default-features = false } +webpki = { package = "rustls-webpki", version = "0.103.6", default-features = false, optional = true } +enum_dispatch = "0.3.13" +tinyvec = { version = "1.10.0", default-features = false, optional = true } +thiserror = { version = "2.0.17", default-features = false } [dev-dependencies] -getrandom = { version = "0.2", features = ["custom"] } # workaround to build on no_std targets +bytes = { version = "1.10.1", default-features = false } +itertools = { version = "0.14.0", default-features = false } +rsa_098 = { package = "rsa", version = "0.9.8", features = ["sha2"] } +signature_220 = { package = "signature", version = "2.2.0" } +rustls = { version = "0.23.32", default-features = false, features = ["std"] } +x509-cert = { version = "0.2.5", default-features = false, features = [ + "builder", +] } +rand_core_064 = { package = "rand_core", version = "0.6.4" } +p256_0132 = { package = "p256", version = "0.13.2" } [features] -default = ["std", "tls12", "zeroize"] +default = ["std", "tls12", "zeroize", "full", "fast", "quic", "ticketer"] +full = [ + "aead-full", + "sign-full", + "verify-full", + "kx-full", + "hash-full", + "format", +] +format = ["pem", "pkcs1", "pkcs8", "sec1"] logging = ["rustls/logging"] tls12 = ["rustls/tls12"] -# Only enable feature in upstream if there is an overall effect e.g. aead/alloc in-place -# zeroize is another typical that can be turned off +# RustCrypto is preparing to migrate to core::error::Error +# and in before most of the use case for std is just std::error::Error +std = ["alloc", "rustls/std", "ed448-goldilocks?/std", "tinyvec?/std", "thiserror/std"] +alloc = [ + "ecdsa?/alloc", + "ed448-goldilocks?/alloc", + "elliptic-curve?/alloc", + "pkcs8?/alloc", + "sec1?/alloc", + "signature?/alloc", +] +zeroize = [ + "aes-gcm?/zeroize", + "aes?/zeroize", + "der?/zeroize", + "ed25519-dalek?/zeroize", + "pkcs1?/zeroize", + "sec1?/zeroize", + "x25519-dalek?/zeroize", +] +subtle = ["digest/subtle", "pkcs8?/subtle", "sec1?/subtle"] +fast = [ + "ed25519-dalek?/fast", + # "rsa?/u64_digit", + "x25519-dalek?/precomputed-tables", +] + +nist = [] +p256 = ["dep:p256", "nist", "p256/pkcs8"] +p384 = ["dep:p384", "nist", "p384/pkcs8"] +p521 = ["dep:p521", "nist"] +ed25519 = ["dep:ed25519-dalek"] +ed448 = ["dep:ed448-goldilocks"] + +ecdsa = ["dep:ecdsa", "verify", "signature", "rand", "der", "elliptic-curve"] +ecdsa-p256 = ["ecdsa", "p256", "p256/ecdsa"] +ecdsa-p384 = ["ecdsa", "p384", "p384/ecdsa"] +ecdsa-p521 = ["ecdsa", "p521", "p521/ecdsa"] +ecdsa-full = ["ecdsa-p256", "ecdsa-p384", "ecdsa-p521"] + +eddsa = ["verify", "signature", "elliptic-curve"] +eddsa-ed25519 = ["eddsa", "ed25519"] +eddsa-ed448 = ["eddsa", "ed448"] +eddsa-full = ["eddsa-ed25519", "eddsa-ed448"] + +kx = ["rand", "elliptic-curve"] +kx-x448 = ["kx", "x448"] +kx-x25519 = ["kx", "dep:x25519-dalek"] +kx-nist = ["sec1"] +kx-p256 = ["kx", "p256", "kx-nist", "p256/ecdh"] +kx-p384 = ["kx", "p384", "kx-nist", "p384/ecdh"] +kx-p521 = ["kx", "p521", "kx-nist", "p521/ecdh"] +kx-full = ["kx-x448", "kx-x25519", "kx-p256", "kx-p384", "kx-p521"] + +rsa = ["dep:rsa", "rsa/sha2", "pkcs1"] +rsa-pkcs1 = ["rsa", "pkcs1"] +rsa-pss = ["rsa"] + +aead = ["dep:aead"] +aead-aes-gcm = ["aead", "aes-gcm"] +aead-aes-ccm = ["aead", "aes-ccm"] +aead-chacha20poly1305 = ["aead", "chacha20poly1305"] +aead-full = ["aead-aes-gcm", "aead-aes-ccm", "aead-chacha20poly1305"] + +sign = ["signature", "der"] +sign-ecdsa-nist = ["sign"] +sign-ecdsa-p256 = ["sign-ecdsa-nist", "ecdsa-p256"] +sign-ecdsa-p384 = ["sign-ecdsa-nist", "ecdsa-p384"] +sign-ecdsa-p521 = ["sign-ecdsa-nist", "ecdsa-p521"] +sign-eddsa = ["sign"] +sign-eddsa-ed25519 = ["sign-eddsa", "eddsa-ed25519"] +sign-eddsa-ed448 = ["sign-eddsa", "eddsa-ed448", "ed448-goldilocks?/signing"] +sign-rsa = ["sign", "rsa"] +sign-rsa-pkcs1 = ["sign-rsa", "rsa-pkcs1"] +sign-rsa-pss = ["sign-rsa", "rsa-pss"] +sign-full = [ + "sign-ecdsa-p256", + "sign-ecdsa-p384", + "sign-ecdsa-p521", + "sign-eddsa-ed25519", + "sign-eddsa-ed448", + "sign-rsa-pkcs1", + "sign-rsa-pss", +] + +verify = ["dep:webpki"] +verify-ecdsa-nist = ["verify"] +verify-ecdsa-p256 = ["verify-ecdsa-nist", "ecdsa-p256"] +verify-ecdsa-p256-sha256 = ["verify-ecdsa-p256", "hash-sha256"] +verify-ecdsa-p256-sha384 = ["verify-ecdsa-p256", "hash-sha384"] +verify-ecdsa-p256-sha512 = ["verify-ecdsa-p256", "hash-sha512"] +verify-ecdsa-p384 = ["verify-ecdsa-nist", "ecdsa-p384"] +verify-ecdsa-p384-sha256 = ["verify-ecdsa-p384", "hash-sha256"] +verify-ecdsa-p384-sha384 = ["verify-ecdsa-p384", "hash-sha384"] +verify-ecdsa-p384-sha512 = ["verify-ecdsa-p384", "hash-sha512"] +verify-ecdsa-p521 = ["verify-ecdsa-nist", "ecdsa-p521"] +verify-ecdsa-p521-sha256 = ["verify-ecdsa-p521", "hash-sha256"] +verify-ecdsa-p521-sha384 = ["verify-ecdsa-p521", "hash-sha384"] +verify-ecdsa-p521-sha512 = ["verify-ecdsa-p521", "hash-sha512"] +verify-eddsa = ["verify"] +verify-eddsa-ed25519 = ["verify-eddsa", "eddsa-ed25519"] +verify-eddsa-ed448 = ["verify-eddsa", "eddsa-ed448"] +verify-rsa = ["verify"] +verify-rsa-pkcs1 = ["verify-rsa", "rsa-pkcs1"] +verify-rsa-pkcs1-sha256 = ["verify-rsa-pkcs1", "hash-sha256"] +verify-rsa-pkcs1-sha384 = ["verify-rsa-pkcs1", "hash-sha384"] +verify-rsa-pkcs1-sha512 = ["verify-rsa-pkcs1", "hash-sha512"] +verify-rsa-pss = ["verify-rsa", "rsa-pss"] +verify-rsa-pss-sha256 = ["verify-rsa-pss", "hash-sha256"] +verify-rsa-pss-sha384 = ["verify-rsa-pss", "hash-sha384"] +verify-rsa-pss-sha512 = ["verify-rsa-pss", "hash-sha512"] +verify-full = [ + "verify-ecdsa-p256-sha256", + "verify-ecdsa-p256-sha384", + "verify-ecdsa-p384-sha256", + "verify-ecdsa-p384-sha384", + "verify-ecdsa-p256-sha512", + "verify-ecdsa-p384-sha512", + "verify-ecdsa-p521-sha256", + "verify-ecdsa-p521-sha384", + "verify-ecdsa-p521-sha512", + "verify-eddsa-ed25519", + "verify-eddsa-ed448", + "verify-rsa-pkcs1-sha256", + "verify-rsa-pkcs1-sha384", + "verify-rsa-pkcs1-sha512", + "verify-rsa-pss-sha256", + "verify-rsa-pss-sha384", + "verify-rsa-pss-sha512", +] + +hash = [] +hash-sha224 = ["hash"] +hash-sha256 = ["hash"] +hash-sha384 = ["hash"] +hash-sha512 = ["hash"] +hash-full = ["hash-sha224", "hash-sha256", "hash-sha384", "hash-sha512"] + +quic = ["aead", "chacha20?/cipher", "tinyvec"] +ticketer = ["aead", "chacha20poly1305", "rand"] + +# Formats +der = ["dep:der", "sec1?/der"] +sec1 = ["dep:sec1", "elliptic-curve?/sec1"] +pem = ["elliptic-curve?/pem", "ecdsa?/pem", "ed25519-dalek?/pem"] +pkcs1 = ["dep:pkcs1", "rsa?/encoding"] +pkcs8 = [ + "dep:pkcs8", + "ecdsa?/pkcs8", + "ed25519-dalek?/pkcs8", + "ed448-goldilocks?/pkcs8", + "elliptic-curve?/pkcs8", + "p256?/pkcs8", + "p384?/pkcs8", + "p521?/pkcs8", +] -# TODO: go through all of these that what gets exposed re: std error type -std = ["alloc", "webpki/std", "pki-types/std", "rustls/std", "ed25519-dalek/std"] -# TODO: go through all of these to ensure to_vec etc. impls are exposed -alloc = ["webpki/alloc", "pki-types/alloc", "aead/alloc", "ed25519-dalek/alloc"] -zeroize = ["ed25519-dalek/zeroize", "x25519-dalek/zeroize"] +aes = ["dep:aes"] +aes-ccm = ["aes", "ccm"] +aes-gcm = ["dep:aes-gcm", "aes", "gcm"] +ccm = ["dep:ccm"] +chacha20 = ["dep:chacha20"] +chacha20poly1305 = ["dep:chacha20poly1305", "chacha20"] +elliptic-curve = [ + "dep:elliptic-curve", + "elliptic-curve/ecdh", + "elliptic-curve/sec1", +] +gcm = [] +rand = ["dep:rand_core", "signature?/rand_core", "x25519-dalek?/os_rng"] +signature = ["dep:signature"] +x448 = ["dep:x448"] +tinyvec = ["dep:tinyvec"] diff --git a/README.md b/README.md index 39739a7..4e4a723 100644 --- a/README.md +++ b/README.md @@ -9,23 +9,147 @@ [RustCrypto]-based provider implementation for version 0.23 of [rustls], maintained by the RustCrypto organization. -## ⚠️USE THIS AT YOUR OWN RISK! DO NOT USE THIS IN PRODUCTION⚠️ +## ⚠️CAUTION⚠️ -Not only that this is incomplete that only few selected TLS suites implemented (it should be well enough to cover 70% of the usage), but the elephant in the room is that neither did rustls nor RustCrypto packages were formally verified and certified with FIPS compliance. +While a basic test suite that tests all available cipher suites and key exchange combinations passes, and it is cross-validated with OpenSSL, and is also running in ESP32 for experimental (but near-production) secure communication, please be reminded that (as of 2024) not all RustCrypto packages are formally verified and optimized for specific architecture, and none of the packages in RustCrypto are certified with FIPS compliance. Note that RustCrypto performance is generally inferior than ring, but in exchange you got a pure Rust implementation that theoretically compiles everywhere Rust was ported to. In our case, we need to have `std` but foundational support for future `no_std` expansion is already here. ## Supported Cipher Suites -- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 -- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -- TLS13_AES_128_GCM_SHA256 -- TLS13_AES_256_GCM_SHA384 -- TLS13_CHACHA20_POLY1305_SHA256 +Only the recommended ([TLS1.2](https://ciphersuite.info/cs/?security=recommended&singlepage=true&tls=tls12), [TLS1.3](https://ciphersuite.info/cs/?security=recommended&singlepage=true&tls=tls13)) and secure ([TLS1.2](https://ciphersuite.info/cs/?security=secure&singlepage=true&tls=tls12), [TLS1.3](https://ciphersuite.info/cs/?security=secure&singlepage=true&tls=tls13)) suites will be chosen + +### TLS 1.3 Cipher Suites + +| Cipher Suite | Status | Required Features | +|-------------|--------|-------------------| +| TLS_AES_128_GCM_SHA256 | ✅ Recommended | `tls13`, `aead-aes-gcm`, `hash-sha256` | +| TLS_AES_256_GCM_SHA384 | ✅ Recommended | `tls13`, `aead-aes-gcm`, `hash-sha384` | +| TLS_CHACHA20_POLY1305_SHA256 | ✅ Recommended | `tls13`, `aead-aes-chacha20poly1305`, `hash-sha256` | +| TLS_AES_128_CCM_8_SHA256 | ✅ Secure | `tls13`, `aead-aes-ccm`, `hash-sha256` | +| TLS_AES_128_CCM_SHA256 | ✅ Secure | `tls13`, `aead-aes-ccm`, `hash-sha256` | + +### TLS 1.2 Cipher Suites + +| Cipher Suite | Status | Required Features | +|-------------|--------|-------------------| +| TLS_ECCPWD_WITH_AES_128_GCM_SHA256 | ❌ Not supported | N/A (ECCPWD not implemented) | +| TLS_ECCPWD_WITH_AES_256_GCM_SHA384 | ❌ Not supported | N/A (ECCPWD not implemented) | +| TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 | ✅ Recommended | `tls12`, `verify-ecdsa-p256-sha256`, `aead-aes-gcm`, `kx-p256` | +| TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 | ✅ Recommended | `tls12`, `verify-ecdsa-p384-sha384`, `aead-aes-gcm`, `kx-p384` | +| TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 | ❌ Not supported | N/A (ARIA not production-ready) | +| TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 | ❌ Not supported | N/A (ARIA not production-ready) | +| TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 | ❌ Not supported | N/A (CAMELLIA not production-ready) | +| TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 | ❌ Not supported | N/A (CAMELLIA not production-ready) | +| TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 | ✅ Recommended | `tls12`, `verify-ecdsa-p256-sha256`, `aead-chacha20poly1305`, `kx-p256` | +| TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 | ❌ Not supported | N/A (PSK not supported in Rustls) | +| TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 | ❌ Not supported | N/A (PSK not supported in Rustls) | +| TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 | ❌ Not supported | N/A (PSK not supported in Rustls) | +| TLS_ECCPWD_WITH_AES_128_CCM_SHA256 | ❌ Not supported | N/A (ECCPWD not implemented) | +| TLS_ECCPWD_WITH_AES_256_CCM_SHA384 | ❌ Not supported | N/A (ECCPWD not implemented) | +| TLS_ECDHE_ECDSA_WITH_AES_128_CCM | ✅ Secure | `tls12`, `verify-ecdsa-p256-sha256`, `aead-aes-ccm`, `kx-p256` | +| TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 | ✅ Secure | `tls12`, `verify-ecdsa-p256-sha256`, `aead-aes-ccm`, `kx-p256` | +| TLS_ECDHE_ECDSA_WITH_AES_256_CCM | ✅ Secure | `tls12`, `verify-ecdsa-p384-sha384`, `aead-aes-ccm`, `kx-p384` | +| TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 | ✅ Secure | `tls12`, `verify-ecdsa-p384-sha384`, `aead-aes-ccm`, `kx-p384` | +| TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256 | ❌ Not supported | N/A (PSK not supported in Rustls) | +| TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 | ❌ Not supported | N/A (PSK not supported in Rustls) | +| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 | ✅ Secure | `tls12`, `verify-rsa-pkcs1-sha256`, `aead-aes-gcm`, `kx-p256` | +| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 | ✅ Secure | `tls12`, `verify-rsa-pkcs1-sha384`, `aead-aes-gcm`, `kx-p384` | +| TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 | ❌ Not supported | N/A (ARIA not production-ready) | +| TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 | ❌ Not supported | N/A (ARIA not production-ready) | +| TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 | ❌ Not supported | N/A (CAMELLIA not production-ready) | +| TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 | ❌ Not supported | N/A (CAMELLIA not production-ready) | +| TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 | ✅ Secure | `tls12`, `verify-rsa-pkcs1-sha256`, `aead-chacha20poly1305`, `kx-p256` | + +### Feature Usage Examples + +To enable TLS 1.3 with AES-GCM support: +```toml +rustls-rustcrypto = { version = "0.0.2-alpha", features = ["tls13", "gcm", "hash-sha256"] } +``` + +To enable TLS 1.2 with ECDSA and AES-GCM: +```toml +rustls-rustcrypto = { version = "0.0.2-alpha", features = ["tls12", "verify-ecdsa-p256-sha256", "aead-aes-gcm", "kx-p256"] } +``` + +To enable TLS 1.2 with RSA and AES-GCM: +```toml +rustls-rustcrypto = { version = "0.0.2-alpha", features = ["tls12", "verify-rsa-pkcs1-sha256", "aead-aes-gcm", "kx-p256"] } +``` + +To enable both TLS 1.2 and TLS 1.3 with full algorithm support: +```toml +rustls-rustcrypto = { version = "0.0.2-alpha", features = ["full"] } +``` + +### Simplified Feature Sets + +For common use cases, you can use these simplified configurations: + +**TLS 1.3 Only (Recommended for new applications):** +```toml +rustls-rustcrypto = { version = "0.0.2-alpha", features = ["tls13", "aead-full", "hash-full"] } +``` + +**TLS 1.2 + ECDSA (Legacy compatibility):** +```toml +rustls-rustcrypto = { version = "0.0.2-alpha", features = ["tls12", "verify-ecdsa-p256-sha256", "aead-full", "kx-p256"] } +``` + +**TLS 1.2 + RSA (Maximum compatibility):** +```toml +rustls-rustcrypto = { version = "0.0.2-alpha", features = ["tls12", "verify-rsa-pkcs1-sha256", "aead-full", "kx-p256"] } +``` + +### Using Compound Features + +You can also use compound features that automatically include related dependencies: + +**AEAD Compound Features:** +- `aead-aes-gcm` = includes `aead` + `aes-gcm` +- `aead-aes-ccm` = includes `aead` + `aes-ccm` +- `aead-chacha20poly1305` = includes `aead` + `chacha20poly1305` +- `aead-full` = includes all AEAD algorithms + +**Signing Compound Features:** +- `sign-ecdsa-p256` = includes `sign-ecdsa-nist` + `ecdsa-p256` +- `sign-rsa-pkcs1` = includes `sign-rsa` + `rsa-pkcs1` +- `sign-full` = includes all signing algorithms + +**Example using compound features:** +```toml +# Base features: ["tls12", "verify-ecdsa-p256-sha256", "aead-aes-gcm", "kx-p256"] +# Compound features: ["tls12", "verify-ecdsa-p256-sha256", "aead-aes-gcm", "kx-p256"] +rustls-rustcrypto = { version = "0.0.2-alpha", features = ["tls12", "verify-ecdsa-p256-sha256", "aead-aes-gcm", "kx-p256"] } +``` + +**Note:** The base features (like `aes-gcm`) are still required for conditional compilation in the source code. Compound features are primarily for convenience and ensuring all dependencies are included. + +### Understanding Feature Dependencies + +The verification features have hierarchical dependencies that automatically include required components: + +- `verify-ecdsa-p256-sha256` automatically includes: + - `verify-ecdsa-p256` (includes `ecdsa-p256`) + - `verify-ecdsa-nist` + - `verify` (includes `webpki`) + - `hash-sha256` + +- `verify-rsa-pkcs1-sha256` automatically includes: + - `verify-rsa-pkcs1` (includes `rsa-pkcs1`) + - `verify-rsa` + - `verify` (includes `webpki`) + - `hash-sha256` + +This hierarchical structure means you only need to specify the highest-level feature for your use case. + +\* PSK support is currently blocked due to [it not currently being supported in Rustls as of 2024](https://github.com/rustls/rustls/issues/174). +If you want this feature, consider financially supporting the Rustls project by being a funder in [Prossimo](https://www.memorysafety.org/initiative/rustls/) + +\* While both [CAMELLIA](https://github.com/RustCrypto/block-ciphers/tree/master/camellia) and [ARIA](https://github.com/RustCrypto/block-ciphers/tree/master/aria) block cipher are in RustCrypto, they are still in 0.1.0 and not currently viable for production use + +\* As RustCrypto do not have a [Dragonfly](https://www.ietf.org/proceedings/83/slides/slides-83-cfrg-0.pdf) implementation, nor it is planned yet, [RFC8492](https://datatracker.ietf.org/doc/html/rfc8492) and thus ECCPWD family of cipher suites would be hard to implement for the known future ## License @@ -38,14 +162,7 @@ at your option. Some code authored by [@ctz](https://github.com/ctz) was adapted from upstream rustls. Licensed as above with permission. -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions. - -[//]: # (badges) - +[//]: # "badges" [crate-image]: https://img.shields.io/crates/v/rustls-rustcrypto [crate-link]: https://crates.io/crates/rustls-rustcrypto [docs-image]: https://docs.rs/rustls-rustcrypto/badge.svg @@ -56,8 +173,6 @@ dual licensed as above, without any additional terms or conditions. [rustc-image]: https://img.shields.io/badge/rustc-1.75+-blue.svg [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/434751-TLS - -[//]: # (links) - +[//]: # "links" [RustCrypto]: https://github.com/RustCrypto/ -[rustls]: https://github.com/rustls/rustls/ +[rustls]: https://github.com/rustls/rustls/ \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..39bce0c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,22 @@ +### Certificates + +The two tests (real socket test and ESP32 test) uses embedded certificates (for now): +- **Server Certificate**: `cert.der` - ECDSA P-256 certificate +- **Private Key**: `key.der` - PKCS#8 encoded private key +- **Certificate Verification**: Custom verifier (accepts all for testing) + +### Security Notes + +⚠️ **WARNING**: The tests uses a dummy certificate verifier that accepts all certificates. This is for testing purposes only and should NEVER be used in production code. + +## Performance Considerations for embedded + +### Memory Usage +- Optimized for ESP32's limited RAM +- Uses static allocations where possible +- Minimal heap allocation during runtime + +### CPU Usage +- ECC operations are computationally intensive +- Consider using hardware acceleration if available +- Profile with ESP-IDF tools for optimization \ No newline at end of file diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md new file mode 100644 index 0000000..ccff5d2 --- /dev/null +++ b/TROUBLESHOOTING.md @@ -0,0 +1,43 @@ +## Troubleshooting (for ESP32 integration test) + +### Common Issues + +#### Build Failures +- Ensure ESP-IDF is properly installed and sourced +- Check Rust toolchain version compatibility +- Verify target architecture matches your ESP32 variant + +#### Flashing Issues +- Check USB port permissions +- Ensure no other processes are using the serial port +- Try different USB cables or ports + +#### Runtime Errors +- Verify network connectivity if using WiFi +- Check ESP32 power supply stability +- Monitor serial output for detailed error messages + +#### TLS Handshake Failures +- Ensure certificates are properly embedded +- Check cipher suite compatibility +- Verify TLS version support + +### Debugging + +Enable detailed logging: +```bash +# Set log level +espmonitor /dev/ttyUSB0 -e "RUST_LOG=trace" +``` + +Common debug commands: +```bash +# Check ESP32 connection +ls /dev/ttyUSB* + +# Monitor with specific baud rate +espmonitor /dev/ttyUSB0 --baud 115200 + +# Flash with verbose output +cargo espflash flash --release --verbose +``` \ No newline at end of file diff --git a/examples-external/client.rs b/examples-external/client.rs deleted file mode 100644 index 2493c61..0000000 --- a/examples-external/client.rs +++ /dev/null @@ -1,47 +0,0 @@ -use std::str::FromStr; - -use anyhow::anyhow; -use http_body_util::{BodyExt, Empty}; -use hyper::{body::Bytes, Uri}; -use hyper_util::{client::legacy::Client, rt::TokioExecutor}; -use rustls_rustcrypto::provider; - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - env_logger::init(); - - // Prepare the HTTPS connector - let https = hyper_rustls::HttpsConnectorBuilder::new() - .with_provider_and_webpki_roots(provider())? - .https_or_http() - .enable_all_versions() - .build(); - - // Build the hyper client from the HTTPS connector. - let client: Client<_, Empty> = Client::builder(TokioExecutor::new()).build(https); - - // Prepare a chain of futures which sends a GET request, inspects - // the returned headers, collects the whole body and prints it to - // stdout. - let fut = async move { - let res = client - .get(Uri::from_str("https://ecc256.badssl.com/")?) - .await - .map_err(|e| anyhow!("Could not get: {:?}", e))?; - println!("Status:\n{}", res.status()); - println!("Headers:\n{:#?}", res.headers()); - - let body = res - .into_body() - .collect() - .await - .map_err(|e| anyhow!("Could not get body: {:?}", e))? - .to_bytes(); - - println!("Body:\n{}", String::from_utf8_lossy(&body)); - - Ok(()) - }; - - fut.await -} diff --git a/examples-external/server.rs b/examples-external/server.rs deleted file mode 100644 index d31745b..0000000 --- a/examples-external/server.rs +++ /dev/null @@ -1,126 +0,0 @@ -use std::{net::ToSocketAddrs, sync::Arc}; - -use futures_util::StreamExt; -use http_body_util::{BodyExt, Full}; -use hyper::{ - body::{Bytes, Incoming}, - service::service_fn, - Method, Request, Response, StatusCode, -}; -use hyper_util::{ - rt::{TokioExecutor, TokioIo}, - server::conn::auto::Builder, -}; -use pki_types::PrivateKeyDer; -use rustls::ServerConfig; -use rustls_rustcrypto::provider; -use tls_listener::{SpawningHandshakes, TlsListener}; -use tokio::{net::TcpListener, signal::ctrl_c}; -use tokio_rustls::TlsAcceptor; -struct TestPki { - server_cert_der: Vec, - server_key_der: Vec, -} - -impl TestPki { - fn new() -> Self { - let alg = &rcgen::PKCS_ECDSA_P384_SHA384; - let mut ca_params = rcgen::CertificateParams::new(Vec::new()); - ca_params - .distinguished_name - .push(rcgen::DnType::OrganizationName, "Rustls Server Acceptor"); - ca_params - .distinguished_name - .push(rcgen::DnType::CommonName, "Example CA"); - ca_params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - ca_params.key_usages = vec![ - rcgen::KeyUsagePurpose::KeyCertSign, - rcgen::KeyUsagePurpose::DigitalSignature, - rcgen::KeyUsagePurpose::CrlSign, - ]; - ca_params.alg = alg; - let ca_cert = rcgen::Certificate::from_params(ca_params).unwrap(); - - // Create a server end entity cert issued by the CA. - let mut server_ee_params = rcgen::CertificateParams::new(vec!["localhost".to_string()]); - server_ee_params.is_ca = rcgen::IsCa::NoCa; - server_ee_params.extended_key_usages = vec![rcgen::ExtendedKeyUsagePurpose::ServerAuth]; - server_ee_params.alg = alg; - let server_cert = rcgen::Certificate::from_params(server_ee_params).unwrap(); - let server_cert_der = server_cert.serialize_der_with_signer(&ca_cert).unwrap(); - let server_key_der = server_cert.serialize_private_key_der(); - Self { - server_cert_der, - server_key_der, - } - } -} - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - env_logger::init(); - - let pki = TestPki::new(); - let addr = "0.0.0.0:4443" - .to_socket_addrs()? - .next() - .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::AddrNotAvailable))?; - - let incoming = TcpListener::bind(&addr).await?; - - let mut server_config = ServerConfig::builder_with_provider(Arc::new(provider())) - .with_safe_default_protocol_versions()? - .with_no_client_auth() - .with_single_cert( - vec![pki.server_cert_der.clone().into()], - PrivateKeyDer::Pkcs8(pki.server_key_der.clone().into()), - )?; - server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()]; - let tls_acceptor = TlsAcceptor::from(Arc::new(server_config)); - let service = service_fn(echo); - - println!("Starting to serve on https://{}.", addr); - - TlsListener::new(SpawningHandshakes(tls_acceptor), incoming) - .take_until(ctrl_c()) - .for_each_concurrent(None, |s| async { - match s { - Ok((stream, remote_addr)) => { - println!("accepted client from {}", remote_addr); - if let Err(err) = Builder::new(TokioExecutor::new()) - .serve_connection(TokioIo::new(stream), service) - .await - { - eprintln!("failed to serve connection: {err:#}"); - } - } - Err(e) => { - eprintln!("failed to perform tls handshake: {:?}", e); - } - } - }) - .await; - - Ok(()) -} - -// Custom echo service, handling two different routes and a -// catch-all 404 responder. -async fn echo(req: Request) -> Result>, hyper::Error> { - let mut response = Response::new(Full::default()); - match (req.method(), req.uri().path()) { - // Help route. - (&Method::GET, "/") => { - *response.body_mut() = Full::from("Try POST /echo\n"); - } - // Echo service route. - (&Method::POST, "/echo") => { - *response.body_mut() = Full::from(req.into_body().collect().await?.to_bytes()); - } - // Catch-all 404. - _ => { - *response.status_mut() = StatusCode::NOT_FOUND; - } - }; - Ok(response) -} diff --git a/examples-xsmall/.cargo/config.toml b/examples-xsmall/.cargo/config.toml deleted file mode 100644 index 9203efd..0000000 --- a/examples-xsmall/.cargo/config.toml +++ /dev/null @@ -1,3 +0,0 @@ -[unstable] -build-std = ["core", "alloc", "std", "compiler_builtins"] -build-std-features = ["compiler-builtins-mem"] diff --git a/examples-xsmall/Cargo.lock b/examples-xsmall/Cargo.lock deleted file mode 100644 index 331859c..0000000 --- a/examples-xsmall/Cargo.lock +++ /dev/null @@ -1,1597 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aes" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "aes-gcm" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "ccm" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae3c82e4355234767756212c570e29833699ab63e6ffd161887314cc5b43847" -dependencies = [ - "aead", - "cipher", - "ctr", - "subtle", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - -[[package]] -name = "const-oid" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" - -[[package]] -name = "constcat" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f272d0c4cf831b4fa80ee529c7707f76585986e910e1fbce1d7921970bc1a241" - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" -dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core", - "typenum", -] - -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622178105f911d937a42cdb140730ba4a3ed2becd8ae6ce39c7d28b5d75d4588" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest", - "fiat-crypto", - "platforms", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "der" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "ecdsa" -version = "0.16.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" -dependencies = [ - "der", - "digest", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - -[[package]] -name = "ed25519" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" -dependencies = [ - "pkcs8", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" -dependencies = [ - "curve25519-dalek", - "ed25519", - "serde", - "sha2", - "zeroize", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest", - "ff", - "generic-array", - "group", - "hkdf", - "pem-rfc7468", - "pkcs8", - "rand_core", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "examples-xsmall" -version = "0.1.0" -dependencies = [ - "anyhow", - "hyper", - "hyper-rustls", - "rcgen", - "rustls", - "rustls-pki-types", - "rustls-provider-rustcrypto", - "tokio", - "vc-ltl", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "ghash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" -dependencies = [ - "opaque-debug", - "polyval", -] - -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hermit-abi" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" - -[[package]] -name = "hkdf" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" -dependencies = [ - "hmac", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "http" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.9", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.25.0-alpha.1" -source = "git+https://github.com/stevefan1999-personal/hyper-rustls#f0bb1651fc010d9e993687006d92b10dcdd99c2d" -dependencies = [ - "futures-util", - "http", - "hyper", - "log", - "rustls", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "webpki-roots", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin 0.5.2", -] - -[[package]] -name = "libc" -version = "0.2.148" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" - -[[package]] -name = "libm" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" -dependencies = [ - "libc", - "wasi", - "windows-sys", -] - -[[package]] -name = "num-bigint-dig" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" -dependencies = [ - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "p384" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "p521" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2808cdb09072e3b966f5da8280cd29b252988afb898f688074d8dd1d26c0db" -dependencies = [ - "elliptic-curve", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "pem" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" -dependencies = [ - "base64", - "serde", -] - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs5" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "pkcs5", - "spki", -] - -[[package]] -name = "platforms" -version = "3.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "primeorder" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3" -dependencies = [ - "elliptic-curve", -] - -[[package]] -name = "proc-macro2" -version = "1.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rcgen" -version = "0.11.3" -source = "git+https://github.com/rustls/rcgen#0318d2f0a4bb9e65c84d284acff8587bd418d837" -dependencies = [ - "pem", - "ring", - "time", - "yasna", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ring" -version = "0.17.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" -dependencies = [ - "cc", - "getrandom", - "libc", - "spin 0.9.8", - "untrusted", - "windows-sys", -] - -[[package]] -name = "rsa" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" -dependencies = [ - "byteorder", - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-iter", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core", - "sha2", - "signature", - "spki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustls" -version = "0.22.0-alpha.4" -source = "git+https://github.com/rustls/rustls#b7a6091ab458467a554d62a57c4ff9cf48a552af" -dependencies = [ - "log", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.7.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f84fefc2b087ffd1677ed5910ec4b2650b1eb45ed083d38630304f48496b69" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.0.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aaa4fe93b39faddb6a8f99568c3e5880680156da0d46818e884a071381f67fe" -dependencies = [ - "base64", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47003264dea418db67060fa420ad16d0d2f8f0a0360d825c00e177ac52cb5d8" - -[[package]] -name = "rustls-provider-rustcrypto" -version = "0.0.2" -dependencies = [ - "aead", - "aes-gcm", - "block-buffer", - "ccm", - "chacha20poly1305", - "constcat", - "crypto-common", - "der", - "digest", - "ecdsa", - "ed25519-dalek", - "elliptic-curve", - "generic-array", - "hmac", - "p256", - "p384", - "p521", - "paste", - "pkcs8", - "rand_core", - "rsa", - "rustls", - "rustls-pki-types", - "rustls-webpki", - "sec1", - "sha2", - "signature", - "subtle", - "typenum", - "x25519-dalek", -] - -[[package]] -name = "rustls-webpki" -version = "0.102.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d9ed3a8267782ba32d257ff5b197b63eef19a467dbd1be011caaae35ee416e" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" - -[[package]] -name = "serde" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sha2" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "signature" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" -dependencies = [ - "digest", - "rand_core", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - -[[package]] -name = "syn" -version = "2.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9caece70c63bfba29ec2fed841a09851b14a235c60010fa4de58089b6c025668" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "time" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" -dependencies = [ - "deranged", - "serde", - "time-core", -] - -[[package]] -name = "time-core" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" - -[[package]] -name = "tokio" -version = "1.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "pin-project-lite", - "socket2 0.5.4", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.25.0-alpha.2" -source = "git+https://github.com/rustls/tokio-rustls#82d32c410f2364332c5df656717193f278769e1c" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "vc-ltl" -version = "5.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e98ae3481f41a314867586b0bfbd20eabf5b196a420b1750a69d1a37b80d25" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "webpki-roots" -version = "0.26.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42157929d7ca9c353222a4d1763c52ef86d25d0fd2eca66076df5975fd4e25ed" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "x25519-dalek" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" -dependencies = [ - "curve25519-dalek", - "rand_core", - "serde", - "zeroize", -] - -[[package]] -name = "yasna" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" -dependencies = [ - "time", -] - -[[package]] -name = "zeroize" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/examples-xsmall/Cargo.toml b/examples-xsmall/Cargo.toml deleted file mode 100644 index eaaa4f1..0000000 --- a/examples-xsmall/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "examples-xsmall" -version = "0.1.0" -edition = "2021" - -[dev-dependencies] -anyhow = "1.0.75" -hyper = "0.14.27" -hyper-rustls = { version = "=0.25.0-alpha.1", features = ["http2", "webpki-roots"] } -pki-types = { package = "rustls-pki-types", version = "0.2.1", default-features = false } -rcgen = "0.11.1" -rustls = { version = "=0.22.0-alpha.4", default-features = false } -rustls-provider-rustcrypto = { path = "../" } -tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "io-std", "io-util", "net"] } -vc-ltl = "5.0.8" - -[features] -tls12 = ["rustls-provider-rustcrypto/tls12"] - -[profile.release] -strip = true -opt-level = "s" -lto = true -codegen-units = 1 - -[patch.crates-io] -rustls = { git = 'https://github.com/rustls/rustls' } -tokio-rustls = { git = 'https://github.com/rustls/tokio-rustls' } -hyper-rustls = { git = "https://github.com/stevefan1999-personal/hyper-rustls" } -rcgen = { git = "https://github.com/rustls/rcgen" } \ No newline at end of file diff --git a/examples-xsmall/README.md b/examples-xsmall/README.md deleted file mode 100644 index 8704344..0000000 --- a/examples-xsmall/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# examples-xsmall - -This is identical to the examples one level above, except it is using some Rust techniques known to man to generate small binaries as a mean to test the compactness of RustTLS \ No newline at end of file diff --git a/examples-xsmall/examples/client.rs b/examples-xsmall/examples/client.rs deleted file mode 100644 index d396acd..0000000 --- a/examples-xsmall/examples/client.rs +++ /dev/null @@ -1,97 +0,0 @@ -use std::str::FromStr; - -use anyhow::anyhow; -use hyper::{body::to_bytes, client, Body, Uri}; -use pki_types::CertificateDer; -use rustls::{ - client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}, - DigitallySignedStruct, ServerName, SignatureScheme, -}; -use rustls_provider_rustcrypto::Provider; - -#[derive(Debug)] -struct NoopServerVerifier; - -impl ServerCertVerifier for NoopServerVerifier { - fn verify_server_cert( - &self, - _end_entity: &CertificateDer<'_>, - _intermediates: &[CertificateDer<'_>], - _server_name: &ServerName, - _ocsp_response: &[u8], - _now: pki_types::UnixTime, - ) -> Result { - Ok(ServerCertVerified::assertion()) - } - - fn verify_tls12_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - - fn verify_tls13_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - - fn supported_verify_schemes(&self) -> Vec { - vec![ - SignatureScheme::RSA_PKCS1_SHA1, - SignatureScheme::ECDSA_SHA1_Legacy, - SignatureScheme::RSA_PKCS1_SHA256, - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::RSA_PKCS1_SHA384, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::RSA_PKCS1_SHA512, - SignatureScheme::ECDSA_NISTP521_SHA512, - SignatureScheme::RSA_PSS_SHA256, - SignatureScheme::RSA_PSS_SHA384, - SignatureScheme::RSA_PSS_SHA512, - SignatureScheme::ED25519, - SignatureScheme::ED448, - ] - } -} - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - // Prepare the HTTPS connector - let https = hyper_rustls::HttpsConnectorBuilder::new() - .with_provider_and_webpki_roots(&Provider) - .https_or_http() - .enable_all_versions() - .build(); - - // Build the hyper client from the HTTPS connector. - let client: client::Client<_, hyper::Body> = client::Client::builder().build(https); - - // Prepare a chain of futures which sends a GET request, inspects - // the returned headers, collects the whole body and prints it to - // stdout. - let fut = async move { - let res = client - .get(Uri::from_str("https://ecc256.badssl.com/")?) - .await - .map_err(|e| anyhow!("Could not get: {:?}", e))?; - println!("Status:\n{}", res.status()); - println!("Headers:\n{:#?}", res.headers()); - - let body: Body = res.into_body(); - let body = to_bytes(body) - .await - .map_err(|e| anyhow!("Could not get body: {:?}", e))?; - println!("Body:\n{}", String::from_utf8_lossy(&body)); - - Ok(()) - }; - - fut.await -} diff --git a/examples-xsmall/examples/server.rs b/examples-xsmall/examples/server.rs deleted file mode 100644 index 93c504f..0000000 --- a/examples-xsmall/examples/server.rs +++ /dev/null @@ -1,97 +0,0 @@ -use std::{ - io::{self}, - net::ToSocketAddrs, -}; - -use hyper::{ - server::conn::AddrIncoming, - service::{make_service_fn, service_fn}, - Body, Method, Request, Response, Server, StatusCode, -}; -use hyper_rustls::TlsAcceptor; -use pki_types::PrivateKeyDer; -use rustls_provider_rustcrypto::Provider; -struct TestPki { - server_cert_der: Vec, - server_key_der: Vec, -} - -impl TestPki { - fn new() -> Self { - let alg = &rcgen::PKCS_ECDSA_P256_SHA256; - let mut ca_params = rcgen::CertificateParams::new(Vec::new()); - ca_params - .distinguished_name - .push(rcgen::DnType::OrganizationName, "Rustls Server Acceptor"); - ca_params - .distinguished_name - .push(rcgen::DnType::CommonName, "Example CA"); - ca_params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - ca_params.key_usages = vec![ - rcgen::KeyUsagePurpose::KeyCertSign, - rcgen::KeyUsagePurpose::DigitalSignature, - rcgen::KeyUsagePurpose::CrlSign, - ]; - ca_params.alg = alg; - let ca_cert = rcgen::Certificate::from_params(ca_params).unwrap(); - - // Create a server end entity cert issued by the CA. - let mut server_ee_params = rcgen::CertificateParams::new(vec!["localhost".to_string()]); - server_ee_params.is_ca = rcgen::IsCa::NoCa; - server_ee_params.extended_key_usages = vec![rcgen::ExtendedKeyUsagePurpose::ServerAuth]; - server_ee_params.alg = alg; - let server_cert = rcgen::Certificate::from_params(server_ee_params).unwrap(); - let server_cert_der = server_cert.serialize_der_with_signer(&ca_cert).unwrap(); - let server_key_der = server_cert.serialize_private_key_der(); - Self { - server_cert_der, - server_key_der, - } - } -} - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - let pki = TestPki::new(); - let addr = "0.0.0.0:4443" - .to_socket_addrs()? - .next() - .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::AddrNotAvailable))?; - let incoming = AddrIncoming::bind(&addr)?; - let acceptor = TlsAcceptor::builder() - .with_provider_and_single_cert( - &Provider, - vec![pki.server_cert_der.clone().into()], - PrivateKeyDer::Pkcs8(pki.server_key_der.clone().into()), - )? - .with_all_versions_alpn() - .with_incoming(incoming); - let service = make_service_fn(|_| async { Ok::<_, io::Error>(service_fn(echo)) }); - let server = Server::builder(acceptor).serve(service); - - // Run the future, keep going until an error occurs. - println!("Starting to serve on https://{}.", addr); - server.await?; - Ok(()) -} - -// Custom echo service, handling two different routes and a -// catch-all 404 responder. -async fn echo(req: Request) -> Result, hyper::Error> { - let mut response = Response::new(Body::empty()); - match (req.method(), req.uri().path()) { - // Help route. - (&Method::GET, "/") => { - *response.body_mut() = Body::from("Try POST /echo\n"); - } - // Echo service route. - (&Method::POST, "/echo") => { - *response.body_mut() = req.into_body(); - } - // Catch-all 404. - _ => { - *response.status_mut() = StatusCode::NOT_FOUND; - } - }; - Ok(response) -} diff --git a/src/aead.rs b/src/aead.rs index 6ff57b7..40ab042 100644 --- a/src/aead.rs +++ b/src/aead.rs @@ -1,45 +1,89 @@ use aead::Buffer; use rustls::crypto::cipher::{BorrowedPayload, PrefixedPayload}; -pub mod chacha20; +#[cfg(all(feature = "quic", feature = "alloc"))] +use alloc::vec::Vec; + +#[cfg(feature = "gcm")] pub mod gcm; -pub(crate) struct EncryptBufferAdapter<'a>(&'a mut PrefixedPayload); +#[cfg(feature = "ccm")] +pub mod ccm; + +#[macro_use] +pub(crate) mod common; + +#[cfg(feature = "tinyvec")] +use tinyvec::SliceVec; + +pub(crate) enum EncryptBufferAdapter<'a> { + PrefixedPayload(&'a mut PrefixedPayload), + #[cfg(feature = "quic")] + Vec(Vec), +} impl AsRef<[u8]> for EncryptBufferAdapter<'_> { fn as_ref(&self) -> &[u8] { - self.0.as_ref() + match self { + EncryptBufferAdapter::PrefixedPayload(payload) => payload.as_ref(), + #[cfg(feature = "quic")] + EncryptBufferAdapter::Vec(payload) => payload.as_ref(), + } } } impl AsMut<[u8]> for EncryptBufferAdapter<'_> { fn as_mut(&mut self) -> &mut [u8] { - self.0.as_mut() + match self { + EncryptBufferAdapter::PrefixedPayload(payload) => payload.as_mut(), + #[cfg(feature = "quic")] + EncryptBufferAdapter::Vec(payload) => payload.as_mut(), + } } } impl Buffer for EncryptBufferAdapter<'_> { fn extend_from_slice(&mut self, other: &[u8]) -> aead::Result<()> { - self.0.extend_from_slice(other); + match self { + EncryptBufferAdapter::PrefixedPayload(payload) => payload.extend_from_slice(other), + #[cfg(feature = "quic")] + EncryptBufferAdapter::Vec(payload) => payload.extend_from_slice(other), + } Ok(()) } fn truncate(&mut self, len: usize) { - self.0.truncate(len) + match self { + EncryptBufferAdapter::PrefixedPayload(payload) => payload.truncate(len), + #[cfg(feature = "quic")] + EncryptBufferAdapter::Vec(payload) => payload.truncate(len), + } } } -pub(crate) struct DecryptBufferAdapter<'a, 'p>(&'a mut BorrowedPayload<'p>); +pub(crate) enum DecryptBufferAdapter<'a, 'p> { + BorrowedPayload(&'a mut BorrowedPayload<'p>), + #[cfg(feature = "tinyvec")] + Slice(SliceVec<'a, u8>), +} impl AsRef<[u8]> for DecryptBufferAdapter<'_, '_> { fn as_ref(&self) -> &[u8] { - self.0 + match self { + DecryptBufferAdapter::BorrowedPayload(payload) => payload, + #[cfg(feature = "tinyvec")] + DecryptBufferAdapter::Slice(slice) => slice, + } } } impl AsMut<[u8]> for DecryptBufferAdapter<'_, '_> { fn as_mut(&mut self) -> &mut [u8] { - self.0 + match self { + DecryptBufferAdapter::BorrowedPayload(payload) => payload, + #[cfg(feature = "tinyvec")] + DecryptBufferAdapter::Slice(slice) => slice, + } } } @@ -49,6 +93,13 @@ impl Buffer for DecryptBufferAdapter<'_, '_> { } fn truncate(&mut self, len: usize) { - self.0.truncate(len) + match self { + DecryptBufferAdapter::BorrowedPayload(payload) => payload.truncate(len), + #[cfg(feature = "tinyvec")] + DecryptBufferAdapter::Slice(payload) => payload.truncate(len), + } } } + +#[cfg(feature = "aes")] +pub mod aes; diff --git a/src/aead/aes.rs b/src/aead/aes.rs new file mode 100644 index 0000000..04c3e8e --- /dev/null +++ b/src/aead/aes.rs @@ -0,0 +1,42 @@ +use ::aes::{Aes128, Aes256}; + +#[cfg(feature = "gcm")] +use aes_gcm::AesGcm; + +#[cfg(feature = "ccm")] +use { + ccm::Ccm, + typenum::{U8, U16}, +}; + +#[cfg(any(feature = "gcm", feature = "ccm"))] +use typenum::U12; + +// The AEAD_AES_128_CCM authenticated encryption algorithm works as +// specified in [CCM], using AES-128 as the block cipher, by providing +// the key, nonce, associated data, and plaintext to that mode of +// operation. The formatting and counter generation function are as +// specified in Appendix A of that reference, and the values of the +// parameters identified in that appendix are as follows: +// the nonce length n is 12, +// the tag length t is 16, and +// the value of q is 3. +#[cfg(feature = "ccm")] +pub type Aes128Ccm = Ccm; +#[cfg(feature = "ccm")] +pub type Aes256Ccm = Ccm; + +// The AEAD_AES_128_CCM_8 authenticated encryption algorithm is +// identical to the AEAD_AES_128_CCM algorithm (see Section 5.3 of +// [RFC5116]), except that it uses 8 octets for authentication, instead +// of the full 16 octets used by AEAD_AES_128_CCM. +#[cfg(feature = "ccm")] +pub type Aes128Ccm8 = Ccm; +#[cfg(feature = "ccm")] +pub type Aes256Ccm8 = Ccm; + +#[cfg(feature = "gcm")] +pub type Aes128Gcm = AesGcm; + +#[cfg(feature = "gcm")] +pub type Aes256Gcm = AesGcm; diff --git a/src/aead/ccm.rs b/src/aead/ccm.rs new file mode 100644 index 0000000..caa9fe2 --- /dev/null +++ b/src/aead/ccm.rs @@ -0,0 +1,11 @@ +#[cfg(feature = "aes-ccm")] +pub struct Aes128Ccm; + +#[cfg(feature = "aes-ccm")] +pub struct Aes256Ccm; + +#[cfg(feature = "aes-ccm")] +pub struct Aes128Ccm8; + +#[cfg(feature = "aes-ccm")] +pub struct Aes256Ccm8; diff --git a/src/aead/chacha20.rs b/src/aead/chacha20.rs deleted file mode 100644 index 995b79e..0000000 --- a/src/aead/chacha20.rs +++ /dev/null @@ -1,197 +0,0 @@ -#[cfg(feature = "alloc")] -use alloc::boxed::Box; - -use super::{DecryptBufferAdapter, EncryptBufferAdapter}; - -use chacha20poly1305::{AeadInPlace, KeyInit, KeySizeUser}; -use rustls::crypto::cipher::{ - self, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, - MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, - Tls13AeadAlgorithm, UnsupportedOperationError, -}; -use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; - -#[cfg(feature = "tls12")] -use rustls::crypto::cipher::{KeyBlockShape, Tls12AeadAlgorithm, NONCE_LEN}; - -pub struct Chacha20Poly1305; - -impl Tls13AeadAlgorithm for Chacha20Poly1305 { - fn encrypter(&self, key: AeadKey, iv: Iv) -> Box { - Box::new(Tls13Cipher( - chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) - .expect("key should be valid"), - iv, - )) - } - - fn decrypter(&self, key: AeadKey, iv: Iv) -> Box { - Box::new(Tls13Cipher( - chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) - .expect("key should be valid"), - iv, - )) - } - - fn key_len(&self) -> usize { - chacha20poly1305::ChaCha20Poly1305::key_size() - } - - fn extract_keys( - &self, - key: AeadKey, - iv: Iv, - ) -> Result { - Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }) - } -} - -#[cfg(feature = "tls12")] -impl Tls12AeadAlgorithm for Chacha20Poly1305 { - fn encrypter(&self, key: AeadKey, iv: &[u8], _: &[u8]) -> Box { - Box::new(Tls12Cipher( - chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) - .expect("key should be valid"), - Iv::copy(iv), - )) - } - - fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box { - Box::new(Tls12Cipher( - chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) - .expect("key should be valid"), - Iv::copy(iv), - )) - } - - fn key_block_shape(&self) -> KeyBlockShape { - KeyBlockShape { - enc_key_len: 32, - fixed_iv_len: 12, - explicit_nonce_len: 0, - } - } - - fn extract_keys( - &self, - key: AeadKey, - iv: &[u8], - _explicit: &[u8], - ) -> Result { - // This should always be true because KeyBlockShape and the Iv nonce len are in - // agreement. - debug_assert_eq!(NONCE_LEN, iv.len()); - Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { - key, - iv: Iv::new(iv[..].try_into().expect("conversion should succeed")), - }) - } -} - -struct Tls13Cipher(chacha20poly1305::ChaCha20Poly1305, Iv); - -impl MessageEncrypter for Tls13Cipher { - fn encrypt( - &mut self, - m: OutboundPlainMessage<'_>, - seq: u64, - ) -> Result { - let total_len = self.encrypted_payload_len(m.payload.len()); - let mut payload = PrefixedPayload::with_capacity(total_len); - - payload.extend_from_chunks(&m.payload); - payload.extend_from_slice(&m.typ.to_array()); - - let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); - let aad = cipher::make_tls13_aad(total_len); - - self.0 - .encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload)) - .map_err(|_| rustls::Error::EncryptError) - .map(|()| { - OutboundOpaqueMessage::new( - ContentType::ApplicationData, - ProtocolVersion::TLSv1_2, - payload, - ) - }) - } - - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len + 1 + CHACHAPOLY1305_OVERHEAD - } -} - -impl MessageDecrypter for Tls13Cipher { - fn decrypt<'a>( - &mut self, - mut m: InboundOpaqueMessage<'a>, - seq: u64, - ) -> Result, rustls::Error> { - let payload = &mut m.payload; - let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); - let aad = cipher::make_tls13_aad(payload.len()); - - self.0 - .decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload)) - .map_err(|_| rustls::Error::DecryptError)?; - - m.into_tls13_unpadded_message() - } -} - -#[cfg(feature = "tls12")] -struct Tls12Cipher(chacha20poly1305::ChaCha20Poly1305, Iv); - -#[cfg(feature = "tls12")] -impl MessageEncrypter for Tls12Cipher { - fn encrypt( - &mut self, - m: OutboundPlainMessage<'_>, - seq: u64, - ) -> Result { - let total_len = self.encrypted_payload_len(m.payload.len()); - let mut payload = PrefixedPayload::with_capacity(total_len); - - payload.extend_from_chunks(&m.payload); - - let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); - let aad = cipher::make_tls12_aad(seq, m.typ, m.version, m.payload.len()); - - self.0 - .encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload)) - .map_err(|_| rustls::Error::EncryptError) - .map(|_| OutboundOpaqueMessage::new(m.typ, m.version, payload)) - } - - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len + CHACHAPOLY1305_OVERHEAD - } -} - -#[cfg(feature = "tls12")] -impl MessageDecrypter for Tls12Cipher { - fn decrypt<'a>( - &mut self, - mut m: InboundOpaqueMessage<'a>, - seq: u64, - ) -> Result, rustls::Error> { - let payload = &m.payload; - let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); - let aad = cipher::make_tls12_aad( - seq, - m.typ, - m.version, - payload.len() - CHACHAPOLY1305_OVERHEAD, - ); - - let payload = &mut m.payload; - self.0 - .decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload)) - .map_err(|_| rustls::Error::DecryptError)?; - - Ok(m.into_plain_message()) - } -} - -const CHACHAPOLY1305_OVERHEAD: usize = 16; diff --git a/src/aead/common.rs b/src/aead/common.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/aead/common.rs @@ -0,0 +1 @@ + diff --git a/src/aead/gcm.rs b/src/aead/gcm.rs index 14be62b..5dbdfbf 100644 --- a/src/aead/gcm.rs +++ b/src/aead/gcm.rs @@ -1,235 +1,5 @@ -#[cfg(feature = "alloc")] -use alloc::boxed::Box; +#[cfg(feature = "aes-gcm")] +pub struct Aes128Gcm; -use super::{DecryptBufferAdapter, EncryptBufferAdapter}; - -use aead::AeadInPlace; -use crypto_common::{KeyInit, KeySizeUser}; -use paste::paste; -use rustls::crypto::cipher::{ - self, AeadKey, InboundOpaqueMessage, InboundPlainMessage, MessageDecrypter, MessageEncrypter, - OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, Tls13AeadAlgorithm, -}; -use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; - -#[cfg(feature = "tls12")] -use { - aead::AeadCore, - crypto_common::typenum::Unsigned, - rustls::crypto::cipher::{Iv, KeyBlockShape, Tls12AeadAlgorithm}, -}; - -#[cfg(feature = "tls12")] -const TLS12_GCM_EXPLICIT_NONCE_LEN: usize = 8; - -#[cfg(feature = "tls12")] -const TLS12_GCM_OVERHEAD: usize = TLS12_GCM_EXPLICIT_NONCE_LEN + 16; - -macro_rules! impl_gcm_tls13 { - ($name: ident, $aead: ty, $overhead: expr) => { - paste! { - pub struct []; - - impl Tls13AeadAlgorithm for [] { - fn encrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { - Box::new([]( - $aead::new_from_slice(key.as_ref()).unwrap(), - iv, - )) - } - - fn decrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { - Box::new([]( - $aead::new_from_slice(key.as_ref()).unwrap(), - iv, - )) - } - - fn key_len(&self) -> usize { - $aead::key_size() - } - fn extract_keys( - &self, - key: AeadKey, - iv: cipher::Iv, - ) -> Result { - Ok(ConnectionTrafficSecrets::Aes256Gcm { key, iv }) - } - } - - struct []($aead, cipher::Iv); - - impl MessageEncrypter for [] { - fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { - let total_len = self.encrypted_payload_len(m.payload.len()); - let mut payload = PrefixedPayload::with_capacity(total_len); - - let nonce = cipher::Nonce::new(&self.1, seq).0; - let aad = cipher::make_tls13_aad(total_len); - payload.extend_from_chunks(&m.payload); - payload.extend_from_slice(&m.typ.to_array()); - - self.0 - .encrypt_in_place(&nonce.into(), &aad, &mut EncryptBufferAdapter(&mut payload)) - .map_err(|_| rustls::Error::EncryptError) - .map(|_| OutboundOpaqueMessage::new( - ContentType::ApplicationData, - ProtocolVersion::TLSv1_2, - payload, - )) - } - - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len + 1 + $overhead - } - } - - impl MessageDecrypter for [] { - fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { - let payload = &mut m.payload; - let nonce = cipher::Nonce::new(&self.1, seq).0; - let aad = cipher::make_tls13_aad(payload.len()); - - self.0 - .decrypt_in_place(&nonce.into(), &aad, &mut DecryptBufferAdapter(payload)) - .map_err(|_| rustls::Error::DecryptError)?; - - m.into_tls13_unpadded_message() - } - } - - } - }; -} - -#[cfg(feature = "tls12")] -macro_rules! impl_gcm_tls12 { - ($name: ident, $aead: ty, $nonce: expr, $overhead: expr) => { - paste! { - #[cfg(feature = "tls12")] - pub struct []; - - #[cfg(feature = "tls12")] - impl Tls12AeadAlgorithm for [] { - fn encrypter(&self, key: AeadKey, write_iv: &[u8], explicit: &[u8]) -> Box { - Box::new([]( - $aead::new_from_slice(key.as_ref()).unwrap(), - { - let mut iv: [u8; 12] = [0; 12]; - iv[..4].copy_from_slice(write_iv); - iv[4..].copy_from_slice(explicit); - iv - }, - )) - } - - fn decrypter(&self, dec_key: AeadKey, dec_iv: &[u8]) -> Box { - Box::new([]( - $aead::new_from_slice(dec_key.as_ref()).unwrap(), - dec_iv.try_into().unwrap(), - )) - } - - fn key_block_shape(&self) -> KeyBlockShape { - KeyBlockShape { - enc_key_len: $aead::key_size(), - fixed_iv_len: 4, - explicit_nonce_len: 8, - } - } - - fn extract_keys( - &self, - key: AeadKey, - iv: &[u8], - _explicit: &[u8], - ) -> Result { - Ok(ConnectionTrafficSecrets::Aes128Gcm { - key, - iv: Iv::new(iv[..].try_into().unwrap()), - }) - } - } - - #[cfg(feature = "tls12")] - struct []($aead, [u8; 12]); - - #[cfg(feature = "tls12")] - impl MessageEncrypter for [] { - fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { - let total_len = self.encrypted_payload_len(m.payload.len()); - let mut payload = PrefixedPayload::with_capacity(total_len); - - let nonce = cipher::Nonce::new(&self.1.into(), seq).0; - let aad = cipher::make_tls12_aad(seq, m.typ, m.version, m.payload.len()); - payload.extend_from_slice(&nonce.as_ref()[4..]); // explicit - payload.extend_from_chunks(&m.payload); - - self.0 - .encrypt_in_place_detached(&nonce.into(), &aad, &mut payload.as_mut()[$nonce..]) - .map(|tag| payload.extend(tag.as_ref() as &[u8])) - .map_err(|_| rustls::Error::EncryptError) - .map(|_| OutboundOpaqueMessage::new(m.typ, m.version, payload)) - } - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len + $nonce + <$aead as AeadCore>::TagSize::USIZE - } - } - - #[cfg(feature = "tls12")] - struct []($aead, [u8; 4]); - - #[cfg(feature = "tls12")] - impl MessageDecrypter for [] { - fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { - type TagSize = <$aead as AeadCore>::TagSize; - - let payload = &m.payload; - - if payload.len() < $overhead { - return Err(rustls::Error::DecryptError); - } - - let nonce: aead::Nonce<$aead> = { - let mut nonce = [0u8; 12]; - nonce[..4].copy_from_slice(&self.1); // dec_iv - nonce[4..].copy_from_slice(&payload[..$nonce]); - nonce.into() - }; - - let aad = cipher::make_tls12_aad(seq, m.typ, m.version, payload.len() - $overhead); - - let payload = &mut m.payload; - let tag_pos = { - let payload = &mut payload[$nonce..]; - let tag_pos = payload.len() - TagSize::to_usize(); - let (msg, tag) = payload.split_at_mut(tag_pos); - - let tag = aes_gcm::Tag::::from_slice(tag); - self.0 - .decrypt_in_place_detached(&nonce, &aad, msg, tag) - .map_err(|_| rustls::Error::DecryptError)?; - tag_pos - }; - - // We defer the truncation to here, because we may inadvertently shifted the - // original data if the decryption failed. Another way to avoid this is - // to clone the payload slice starting after the explicit nonce, - // but this will cause an additional cloning and copying - payload.rotate_left($nonce); - payload.truncate(tag_pos); - Ok(m.into_plain_message()) - } - } - } - }; -} - -impl_gcm_tls13! {Aes128Gcm, aes_gcm::Aes128Gcm, 16} -impl_gcm_tls13! {Aes256Gcm, aes_gcm::Aes256Gcm, 16} - -#[cfg(feature = "tls12")] -impl_gcm_tls12! {Aes128Gcm, aes_gcm::Aes128Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} - -#[cfg(feature = "tls12")] -impl_gcm_tls12! {Aes256Gcm, aes_gcm::Aes256Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} +#[cfg(feature = "aes-gcm")] +pub struct Aes256Gcm; diff --git a/src/hash.rs b/src/hash.rs index dfa58e1..ccbbf95 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -1,62 +1,88 @@ #[cfg(feature = "alloc")] use alloc::boxed::Box; +use core::marker::PhantomData; use digest::{Digest, OutputSizeUser}; -use paste::paste; -use rustls::crypto::{self, hash}; -use sha2::{Sha256, Sha384}; +/// Trait to provide hash algorithm for different hash types +pub trait HashAlgorithm { + const ALGORITHM: rustls::crypto::hash::HashAlgorithm; +} + +// Generic hash implementation +#[derive(Default)] +pub struct GenericHash { + _phantom: PhantomData, +} + +impl GenericHash { + pub const DEFAULT: Self = Self { + _phantom: PhantomData, + }; +} + +impl rustls::crypto::hash::Hash for GenericHash +where + H: Digest + OutputSizeUser + Clone + Send + Sync + 'static + HashAlgorithm, +{ + fn start(&self) -> Box { + Box::new(GenericHashContext(H::new())) + } + + fn hash(&self, data: &[u8]) -> rustls::crypto::hash::Output { + rustls::crypto::hash::Output::new(&H::digest(data)[..]) + } + + fn output_len(&self) -> usize { + ::output_size() + } + + fn algorithm(&self) -> rustls::crypto::hash::HashAlgorithm { + H::ALGORITHM + } +} + +pub struct GenericHashContext(H); + +impl rustls::crypto::hash::Context for GenericHashContext +where + H: Digest + Clone + Send + Sync + 'static, +{ + fn fork_finish(&self) -> rustls::crypto::hash::Output { + rustls::crypto::hash::Output::new(&self.0.clone().finalize()[..]) + } + + fn fork(&self) -> Box { + Box::new(GenericHashContext(self.0.clone())) + } + + fn finish(self: Box) -> rustls::crypto::hash::Output { + rustls::crypto::hash::Output::new(&self.0.finalize()[..]) + } + + fn update(&mut self, data: &[u8]) { + self.0.update(data); + } +} + +/// Macro to generate hash constants macro_rules! impl_hash { - ($name:ident, $ty:ty, $algo:ty) => { - paste! { - #[allow(non_camel_case_types)] - struct []; - - impl hash::Hash for [] { - fn start(&self) -> Box { - Box::new([]($ty::new())) - } - - fn hash(&self, data: &[u8]) -> hash::Output { - hash::Output::new(&$ty::digest(data)[..]) - } - - fn output_len(&self) -> usize { - <$ty as OutputSizeUser>::output_size() - } - - fn algorithm(&self) -> hash::HashAlgorithm { - $algo - } - } - - #[allow(non_camel_case_types)] - struct []($ty); - - impl hash::Context for [] { - fn fork_finish(&self) -> hash::Output { - hash::Output::new(&self.0.clone().finalize()[..]) - } - - fn fork(&self) -> Box { - Box::new([](self.0.clone())) - } - - fn finish(self: Box) -> hash::Output { - hash::Output::new(&self.0.finalize()[..]) - } - - fn update(&mut self, data: &[u8]) { - self.0.update(data); - } - } - - pub const $name: &dyn crypto::hash::Hash = &[]; + ($name:ident, $hash:ty) => { + impl HashAlgorithm for $hash { + const ALGORITHM: rustls::crypto::hash::HashAlgorithm = + rustls::crypto::hash::HashAlgorithm::$name; } + + pub const $name: &dyn rustls::crypto::hash::Hash = &GenericHash::<$hash>::DEFAULT; }; } -// impl_hash! {SHA224, Sha224, hash::HashAlgorithm::SHA224} -impl_hash! {SHA256, Sha256, hash::HashAlgorithm::SHA256} -impl_hash! {SHA384, Sha384, hash::HashAlgorithm::SHA384} -// impl_hash! {SHA512, Sha512, hash::HashAlgorithm::SHA512} +// Generate hash constants using macro +#[cfg(feature = "hash-sha224")] +impl_hash!(SHA224, ::sha2::Sha224); +#[cfg(feature = "hash-sha256")] +impl_hash!(SHA256, ::sha2::Sha256); +#[cfg(feature = "hash-sha384")] +impl_hash!(SHA384, ::sha2::Sha384); +#[cfg(feature = "hash-sha512")] +impl_hash!(SHA512, ::sha2::Sha512); diff --git a/src/hmac.rs b/src/hmac.rs index 8388c27..8e113f2 100644 --- a/src/hmac.rs +++ b/src/hmac.rs @@ -1,56 +1,73 @@ #[cfg(feature = "alloc")] use alloc::boxed::Box; +use core::marker::PhantomData; use crypto_common::OutputSizeUser; -use hmac::Mac; -use paste::paste; -use rustls::crypto; -use sha2::{Sha256, Sha384}; - -macro_rules! impl_hmac { - ( - $name: ident, - $ty: ty - ) => { - paste! { - #[allow(non_camel_case_types)] - struct []; - - impl crypto::hmac::Hmac for [] { - fn with_key(&self, key: &[u8]) -> Box { - Box::new([]( - hmac::Hmac::<$ty>::new_from_slice(key).unwrap(), - )) - } - - fn hash_output_len(&self) -> usize { - $ty::output_size() - } - } - - #[allow(non_camel_case_types)] - struct [](hmac::Hmac<$ty>); - - impl crypto::hmac::Key for [] { - fn sign_concat(&self, first: &[u8], middle: &[&[u8]], last: &[u8]) -> crypto::hmac::Tag { - let mut ctx = self.0.clone(); - ctx.update(first); - for m in middle { - ctx.update(m); - } - ctx.update(last); - crypto::hmac::Tag::new(&ctx.finalize().into_bytes()[..]) - } - - fn tag_len(&self) -> usize { - $ty::output_size() - } - } - pub const $name: &dyn crypto::hmac::Hmac = &[]; +use hmac::{EagerHash, Hmac}; +use rustls::crypto::hmac::{Hmac as RustlsHmac, Key, Tag}; + +pub trait HmacHash: EagerHash + Send + Sync + 'static {} + +impl HmacHash for T where T: EagerHash + Send + Sync + 'static {} + +pub struct GenericHmac { + _phantom: PhantomData, +} + +impl GenericHmac { + pub const DEFAULT: Self = Self { + _phantom: PhantomData, + }; +} + +impl RustlsHmac for GenericHmac +where + H: HmacHash, + ::Core: Send + Sync, +{ + fn with_key(&self, key: &[u8]) -> Box { + Box::new(GenericHmacKey::( + <::hmac::Hmac as hmac::KeyInit>::new_from_slice(key) + .expect("Invalid key length for HMAC"), + )) + } + + fn hash_output_len(&self) -> usize { + ::output_size() + } +} + +pub struct GenericHmacKey(Hmac); + +impl Key for GenericHmacKey +where + H: HmacHash, + ::Core: Send + Sync, +{ + fn sign_concat(&self, first: &[u8], middle: &[&[u8]], last: &[u8]) -> Tag { + use ::hmac::Mac; + let mut ctx = self.0.clone(); + ctx.update(first); + for m in middle { + ctx.update(m); } + ctx.update(last); + Tag::new(&ctx.finalize().into_bytes()[..]) + } + + fn tag_len(&self) -> usize { + ::output_size() + } +} + +/// Macro to generate HMAC constants +macro_rules! hmac_const { + ($name:ident, $hash:ty) => { + pub const $name: &GenericHmac<$hash> = &GenericHmac::DEFAULT; }; } -impl_hmac! {SHA256, Sha256} -impl_hmac! {SHA384, Sha384} -// impl_hmac! {SHA512, Sha512} +// Generate HMAC constants using macro +hmac_const!(SHA256, ::sha2::Sha256); +hmac_const!(SHA384, ::sha2::Sha384); +hmac_const!(SHA512, ::sha2::Sha512); diff --git a/src/kx.rs b/src/kx.rs index 66341f2..49ba074 100644 --- a/src/kx.rs +++ b/src/kx.rs @@ -1,108 +1,23 @@ -#[cfg(feature = "alloc")] -use alloc::boxed::Box; - -use crypto::{SharedSecret, SupportedKxGroup}; -use paste::paste; -use rustls::crypto; - -#[derive(Debug)] -pub struct X25519; - -impl crypto::SupportedKxGroup for X25519 { - fn name(&self) -> rustls::NamedGroup { - rustls::NamedGroup::X25519 - } - - fn start(&self) -> Result, rustls::Error> { - let priv_key = x25519_dalek::EphemeralSecret::random_from_rng(rand_core::OsRng); - let pub_key = (&priv_key).into(); - Ok(Box::new(X25519KeyExchange { priv_key, pub_key })) - } -} - -pub struct X25519KeyExchange { - priv_key: x25519_dalek::EphemeralSecret, - pub_key: x25519_dalek::PublicKey, -} - -impl crypto::ActiveKeyExchange for X25519KeyExchange { - fn complete(self: Box, peer: &[u8]) -> Result { - let peer_array: [u8; 32] = peer - .try_into() - .map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?; - Ok(self - .priv_key - .diffie_hellman(&peer_array.into()) - .as_ref() - .into()) - } - - fn pub_key(&self) -> &[u8] { - self.pub_key.as_bytes() - } - - fn group(&self) -> rustls::NamedGroup { - X25519.name() - } -} - -macro_rules! impl_kx { - ($name:ident, $kx_name:ty, $secret:ty, $public_key:ty) => { - paste! { - - #[derive(Debug)] - #[allow(non_camel_case_types)] - pub struct $name; - - impl crypto::SupportedKxGroup for $name { - fn name(&self) -> rustls::NamedGroup { - $kx_name - } - - fn start(&self) -> Result, rustls::Error> { - let priv_key = $secret::random(&mut rand_core::OsRng); - let pub_key: $public_key = (&priv_key).into(); - Ok(Box::new([<$name KeyExchange>] { - priv_key, - pub_key: pub_key.to_sec1_bytes(), - })) - } - } - - #[allow(non_camel_case_types)] - pub struct [<$name KeyExchange>] { - priv_key: $secret, - pub_key: Box<[u8]>, - } - - impl crypto::ActiveKeyExchange for [<$name KeyExchange>] { - fn complete( - self: Box<[<$name KeyExchange>]>, - peer: &[u8], - ) -> Result { - let their_pub = $public_key::from_sec1_bytes(peer) - .map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?; - Ok(self - .priv_key - .diffie_hellman(&their_pub) - .raw_secret_bytes() - .as_slice() - .into()) - } - - fn pub_key(&self) -> &[u8] { - &self.pub_key - } - - fn group(&self) -> rustls::NamedGroup { - $name.name() - } - } - } - }; -} - -impl_kx! {SecP256R1, rustls::NamedGroup::secp256r1, p256::ecdh::EphemeralSecret, p256::PublicKey} -impl_kx! {SecP384R1, rustls::NamedGroup::secp384r1, p384::ecdh::EphemeralSecret, p384::PublicKey} - -pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[&X25519, &SecP256R1, &SecP384R1]; +use rustls::crypto::SupportedKxGroup; + +pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ + #[cfg(feature = "kx-x448")] + &x448::X448, + #[cfg(feature = "kx-x25519")] + &x25519::X25519, + #[cfg(feature = "kx-p256")] + &nist::SEC_P256_R1, + #[cfg(feature = "kx-p384")] + &nist::SEC_P384_R1, + #[cfg(feature = "kx-p521")] + &nist::SEC_P521_R1, +]; + +#[cfg(feature = "kx-nist")] +pub mod nist; + +#[cfg(feature = "kx-x25519")] +pub mod x25519; + +#[cfg(feature = "kx-x448")] +pub mod x448; diff --git a/src/kx/nist.rs b/src/kx/nist.rs new file mode 100644 index 0000000..56229b9 --- /dev/null +++ b/src/kx/nist.rs @@ -0,0 +1,125 @@ +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, string::ToString}; +use core::fmt::Debug; +use core::marker::PhantomData; + +use crypto::{ActiveKeyExchange, SharedSecret, SupportedKxGroup}; +use elliptic_curve::{ + Curve, CurveArithmetic, PublicKey, + ecdh::EphemeralSecret, + point::PointCompression, + sec1::{FromEncodedPoint, ToEncodedPoint}, +}; +use rand_core::OsRng; +use rustls::{Error, NamedGroup, crypto}; +use sec1::point::ModulusSize; + +/// Errors that can occur in NIST key exchange +#[derive(Debug, thiserror::Error)] +pub enum NistKxError { + /// Failed to generate private key + #[error("failed to generate private key: {0}")] + KeyGenerationFailed(rand_core::OsError), +} + +impl From for NistKxError { + fn from(e: rand_core::OsError) -> Self { + Self::KeyGenerationFailed(e) + } +} + +impl From for rustls::Error { + fn from(e: NistKxError) -> Self { + rustls::Error::General(e.to_string()) + } +} + +pub trait NistCurve: Curve + CurveArithmetic + PointCompression { + const NAMED_GROUP: NamedGroup; +} + +#[derive(Debug)] +pub struct NistKxGroup(PhantomData) +where + C: NistCurve; + +impl NistKxGroup +where + C: NistCurve, +{ + const DEFAULT: Self = Self(PhantomData); +} + +impl SupportedKxGroup for NistKxGroup +where + ::AffinePoint: FromEncodedPoint + ToEncodedPoint, + ::FieldBytesSize: ModulusSize, + C: NistCurve, +{ + fn name(&self) -> NamedGroup { + C::NAMED_GROUP + } + + fn start(&self) -> Result, Error> { + let priv_key = EphemeralSecret::::try_from_rng(&mut OsRng).map_err(NistKxError::from)?; + + Ok(Box::new(NistKeyExchange:: { + pub_key: priv_key.public_key().to_sec1_bytes(), + priv_key, + })) + } +} + +#[allow(non_camel_case_types)] +pub struct NistKeyExchange +where + C: NistCurve, +{ + priv_key: EphemeralSecret, + pub_key: Box<[u8]>, +} + +impl ActiveKeyExchange for NistKeyExchange +where + ::AffinePoint: FromEncodedPoint + ToEncodedPoint, + ::FieldBytesSize: ModulusSize, + C: NistCurve, +{ + fn complete(self: Box, peer: &[u8]) -> Result { + let their_pub = PublicKey::::from_sec1_bytes(peer) + .map_err(|_| rustls::PeerMisbehaved::InvalidKeyShare)?; + Ok(self + .priv_key + .diffie_hellman(&their_pub) + .raw_secret_bytes() + .as_slice() + .into()) + } + + fn pub_key(&self) -> &[u8] { + &self.pub_key + } + + fn group(&self) -> NamedGroup { + C::NAMED_GROUP + } +} + +macro_rules! impl_nist_curve { + ($ty:ty, $named_group:expr, $const_name:ident) => { + impl NistCurve for $ty { + const NAMED_GROUP: NamedGroup = $named_group; + } + + pub const $const_name: NistKxGroup<$ty> = NistKxGroup::DEFAULT; + }; +} + +#[cfg(feature = "kx-p256")] +impl_nist_curve!(::p256::NistP256, NamedGroup::secp256r1, SEC_P256_R1); + +#[cfg(feature = "kx-p384")] +impl_nist_curve!(::p384::NistP384, NamedGroup::secp384r1, SEC_P384_R1); + +#[cfg(feature = "kx-p521")] +impl_nist_curve!(::p521::NistP521, NamedGroup::secp521r1, SEC_P521_R1); diff --git a/src/kx/x25519.rs b/src/kx/x25519.rs new file mode 100644 index 0000000..cb14203 --- /dev/null +++ b/src/kx/x25519.rs @@ -0,0 +1,47 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crypto::{SharedSecret, SupportedKxGroup}; +use rustls::crypto::{self, ActiveKeyExchange}; +use x25519_dalek::{EphemeralSecret, PublicKey}; + +#[derive(Debug)] +pub struct X25519; + +impl crypto::SupportedKxGroup for X25519 { + fn name(&self) -> rustls::NamedGroup { + rustls::NamedGroup::X25519 + } + + fn start(&self) -> Result, rustls::Error> { + let priv_key = EphemeralSecret::random(); + let pub_key = PublicKey::from(&priv_key); + Ok(Box::new(X25519KeyExchange { priv_key, pub_key })) + } +} + +pub struct X25519KeyExchange { + priv_key: EphemeralSecret, + pub_key: PublicKey, +} + +impl ActiveKeyExchange for X25519KeyExchange { + fn complete(self: Box, peer: &[u8]) -> Result { + let peer_array: [u8; 32] = peer + .try_into() + .map_err(|_| rustls::PeerMisbehaved::InvalidKeyShare)?; + Ok(self + .priv_key + .diffie_hellman(&peer_array.into()) + .as_ref() + .into()) + } + + fn pub_key(&self) -> &[u8] { + self.pub_key.as_bytes() + } + + fn group(&self) -> rustls::NamedGroup { + X25519.name() + } +} diff --git a/src/kx/x448.rs b/src/kx/x448.rs new file mode 100644 index 0000000..02e9430 --- /dev/null +++ b/src/kx/x448.rs @@ -0,0 +1,54 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crypto::{SharedSecret, SupportedKxGroup}; +use rand_core::TryRngCore; +use rustls::crypto::{self, ActiveKeyExchange}; + +#[derive(Debug)] +pub struct X448; + +impl crypto::SupportedKxGroup for X448 { + fn name(&self) -> rustls::NamedGroup { + rustls::NamedGroup::X448 + } + + fn start(&self) -> Result, rustls::Error> { + let mut priv_key = [0u8; 56]; + rand_core::OsRng + .try_fill_bytes(&mut priv_key) + .map_err(|_| rustls::Error::FailedToGetRandomBytes)?; + let priv_key: x448::Secret = priv_key.into(); + let pub_key = x448::PublicKey::from(&priv_key); + + Ok(Box::new(X448KeyExchange { priv_key, pub_key })) + } +} + +pub struct X448KeyExchange { + priv_key: x448::Secret, + pub_key: x448::PublicKey, +} + +impl ActiveKeyExchange for X448KeyExchange { + fn complete(self: Box, peer: &[u8]) -> Result { + Ok(self + .priv_key + .as_diffie_hellman( + &x448::PublicKey::from_bytes(peer) + .ok_or(rustls::PeerMisbehaved::InvalidKeyShare)?, + ) + .ok_or(rustls::PeerMisbehaved::InvalidKeyShare)? + .as_bytes() + .as_ref() + .into()) + } + + fn pub_key(&self) -> &[u8] { + self.pub_key.as_bytes() + } + + fn group(&self) -> rustls::NamedGroup { + X448.name() + } +} diff --git a/src/lib.rs b/src/lib.rs index 1b108b8..551eeb6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,11 +27,6 @@ unused_lifetimes )] -//! # Usage -//! -//! See [`examples-xsmall`](https://github.com/RustCrypto/rustls-rustcrypto/tree/master/examples-xsmall) -//! for a usage example. - #[cfg(not(feature = "alloc"))] compile_error!("Rustls currently does not support alloc-less environments"); @@ -41,13 +36,10 @@ extern crate alloc; #[cfg(feature = "alloc")] use alloc::sync::Arc; -use rustls::crypto::{ - CipherSuiteCommon, CryptoProvider, GetRandomFailed, KeyProvider, SecureRandom, -}; -use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; - -#[cfg(feature = "tls12")] -use rustls::SignatureScheme; +use pki_types::PrivateKeyDer; +use rustls::SupportedCipherSuite; +use rustls::crypto::{CryptoProvider, GetRandomFailed, KeyProvider, SecureRandom}; +use rustls::sign::SigningKey; #[derive(Debug)] pub struct Provider; @@ -63,209 +55,68 @@ pub fn provider() -> CryptoProvider { } impl SecureRandom for Provider { - fn fill(&self, bytes: &mut [u8]) -> Result<(), GetRandomFailed> { - use rand_core::RngCore; - rand_core::OsRng - .try_fill_bytes(bytes) - .map_err(|_| GetRandomFailed) + fn fill(&self, #[allow(unused_variables)] bytes: &mut [u8]) -> Result<(), GetRandomFailed> { + feature_eval_expr!( + [feature = "rand"], + { + use rand_core::TryRngCore; + rand_core::OsRng + .try_fill_bytes(bytes) + .map_err(|_| GetRandomFailed) + }, + else Err(GetRandomFailed) + ) } } impl KeyProvider for Provider { fn load_private_key( &self, - key_der: pki_types::PrivateKeyDer<'static>, - ) -> Result, rustls::Error> { - sign::any_supported_type(&key_der) + #[allow(unused_variables)] key_der: PrivateKeyDer<'static>, + ) -> Result, rustls::Error> { + feature_eval_expr!( + [feature = "sign"], + sign::any_supported_type(&key_der).map_err(Into::into), + else Err(rustls::Error::General("no key providers supported".into())) + ) } } -#[cfg(feature = "tls12")] -const TLS12_ECDSA_SCHEMES: [SignatureScheme; 4] = [ - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::ECDSA_NISTP521_SHA512, - SignatureScheme::ED25519, -]; - -#[cfg(feature = "tls12")] -const TLS12_RSA_SCHEMES: [SignatureScheme; 6] = [ - SignatureScheme::RSA_PKCS1_SHA256, - SignatureScheme::RSA_PKCS1_SHA384, - SignatureScheme::RSA_PKCS1_SHA512, - SignatureScheme::RSA_PSS_SHA256, - SignatureScheme::RSA_PSS_SHA384, - SignatureScheme::RSA_PSS_SHA512, -]; - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_ECDSA_SCHEMES, - aead_alg: &aead::gcm::Tls12Aes128Gcm, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA256), - }); - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - hash_provider: hash::SHA384, - confidentiality_limit: u64::MAX, - }, - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_ECDSA_SCHEMES, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA384), - aead_alg: &aead::gcm::Tls12Aes256Gcm, - }); - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA256), - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_ECDSA_SCHEMES, - aead_alg: &aead::chacha20::Chacha20Poly1305, - }); - -#[cfg(feature = "tls12")] -const TLS_ECDHE_ECDSA_SUITES: &[SupportedCipherSuite] = &[ - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, -]; - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_RSA_SCHEMES, - aead_alg: &aead::gcm::Tls12Aes128Gcm, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA256), - }); - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - hash_provider: hash::SHA384, - confidentiality_limit: u64::MAX, - }, - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_RSA_SCHEMES, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA384), - aead_alg: &aead::gcm::Tls12Aes256Gcm, - }); - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_RSA_SCHEMES, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA256), - aead_alg: &aead::chacha20::Chacha20Poly1305, - }); - -#[cfg(feature = "tls12")] -const TLS_ECDHE_RSA_SUITES: &[SupportedCipherSuite] = &[ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, -]; - -#[cfg(feature = "tls12")] -const TLS12_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( +pub const ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( SupportedCipherSuite, - TLS_ECDHE_ECDSA_SUITES, - TLS_ECDHE_RSA_SUITES + feature_slice!([feature = "tls12"], tls12::suites::TLS12_SUITES), + tls13::suites::TLS13_SUITES ); -#[cfg(not(feature = "tls12"))] -const TLS12_SUITES: &[SupportedCipherSuite] = &[]; - -pub const TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls13(&Tls13CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS13_AES_128_GCM_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - hkdf_provider: &rustls::crypto::tls13::HkdfUsingHmac(hmac::SHA256), - aead_alg: &aead::gcm::Tls13Aes128Gcm, - quic: None, - }); - -pub const TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = - SupportedCipherSuite::Tls13(&Tls13CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS13_AES_256_GCM_SHA384, - hash_provider: hash::SHA384, - confidentiality_limit: u64::MAX, - }, - hkdf_provider: &rustls::crypto::tls13::HkdfUsingHmac(hmac::SHA384), - aead_alg: &aead::gcm::Tls13Aes256Gcm, - quic: None, - }); +#[cfg(feature = "aead")] +pub mod aead; +#[cfg(feature = "hash")] +pub mod hash; +#[cfg(feature = "hash")] +pub mod hmac; +#[cfg(feature = "kx")] +pub mod kx; +pub mod misc; +#[cfg(feature = "sign")] +pub mod sign; +#[cfg(feature = "tls12")] +pub mod tls12; +pub mod tls13; +#[cfg(feature = "verify")] +pub mod verify; -const TLS13_AES_SUITES: &[SupportedCipherSuite] = - &[TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384]; +#[cfg(feature = "quic")] +pub mod quic; -pub const TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls13(&Tls13CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - hkdf_provider: &rustls::crypto::tls13::HkdfUsingHmac(hmac::SHA256), - aead_alg: &aead::chacha20::Chacha20Poly1305, - quic: None, - }); +#[cfg(feature = "ticketer")] +pub mod ticketer; -const TLS13_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( - SupportedCipherSuite, - TLS13_AES_SUITES, - &[TLS13_CHACHA20_POLY1305_SHA256] +const _: () = assert!( + !ALL_CIPHER_SUITES.is_empty(), + "At least one cipher suite should be enabled" ); -static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( - SupportedCipherSuite, - if cfg!(feature = "tls12") { - TLS12_SUITES - } else { - &[] - }, - TLS13_SUITES, +const _: () = assert!( + !kx::ALL_KX_GROUPS.is_empty(), + "At least one key exchange algorithm should be enabled" ); - -mod aead; -mod hash; -mod hmac; -mod kx; -mod misc; -pub mod quic; -pub mod sign; -mod verify; diff --git a/src/misc.rs b/src/misc.rs index 8e25563..2130fca 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,36 +1,88 @@ #[macro_export] macro_rules! const_concat_slices { - ($ty:ty, $a:expr, $b:expr $(,)*) => {{ - const A: &[$ty] = $a; - const B: &[$ty] = $b; - const __LEN: usize = A.len() + B.len(); - const __CONCATENATED: &[$ty; __LEN] = &{ - let mut out: [$ty; __LEN] = if __LEN == 0 { - unsafe { core::mem::transmute([0u8; core::mem::size_of::<$ty>() * __LEN]) } - } else if A.len() == 0 { - [B[0]; __LEN] - } else { - [A[0]; __LEN] - }; - let mut i = 0; - while i < A.len() { - out[i] = A[i]; - i += 1; + ($ty:ty, $($s:expr),* $(,)*) => { + const { + use ::core::mem::{MaybeUninit, transmute}; + const TOTAL_LEN: usize = $(const {const VALUE: &[$ty] = $s; VALUE.len()} + )* 0; + const SLICES: &[&[$ty]] = &[$($s),*]; + + let mut out: [MaybeUninit<$ty>; TOTAL_LEN] = unsafe { MaybeUninit::uninit().assume_init() }; + let mut offset = 0; + let mut slice_idx = 0; + while slice_idx < SLICES.len() { + let slice = SLICES[slice_idx]; + let mut i = 0; + while i < slice.len() { + out[offset] = MaybeUninit::new(slice[i]); + offset += 1; + i += 1; + } + slice_idx += 1; } - i = 0; - while i < B.len() { - out[i + A.len()] = B[i]; - i += 1; + &unsafe { transmute::<[MaybeUninit<$ty>; TOTAL_LEN], [$ty; TOTAL_LEN]>(out) } + } + }; +} + +#[macro_export] +macro_rules! feature_eval_expr { + ( + [$($cfg:tt)*], + $on_true:expr, + else $on_false:expr + ) => { + { + #[cfg($($cfg)*)] + { + $on_true } - out + #[cfg(not($($cfg)*))] + { + $on_false + } + } + }; +} + +#[macro_export] +macro_rules! feature_slice { + ( + [$($cfg:tt)*], + $slice:expr + ) => { $crate::feature_eval_expr!([$($cfg)*], $slice, else &[]) }; +} + +#[macro_export] +macro_rules! tls13_cipher_suite { + ($name:ident, $suite:expr, $hash:expr, $hkdf:expr, $aead:expr, $quic:expr) => { + pub const $name: Tls13CipherSuite = Tls13CipherSuite { + common: CipherSuiteCommon { + suite: $suite, + hash_provider: $hash, + confidentiality_limit: u64::MAX, + }, + hkdf_provider: &$hkdf, + aead_alg: $aead, + quic: $quic, }; + }; +} - __CONCATENATED - }}; - ($ty:ty, $a:expr, $b:expr, $($c:expr), + $(,)* ) => {{ - const CON: &[$ty] = const_concat_slices!($ty, $a, $b); - const_concat_slices!($ty, CON, $($c), +) - }} +#[macro_export] +macro_rules! tls12_ecdhe_cipher_suite { + ($name:ident, $suite:expr, $hash:expr, $prf:expr, $sign:expr, $aead:expr) => { + pub const $name: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: $suite, + hash_provider: $hash, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: $sign, + aead_alg: $aead, + prf_provider: &$prf, + }; + }; } pub(crate) use const_concat_slices; diff --git a/src/quic.rs b/src/quic.rs index f849835..d59f5e2 100644 --- a/src/quic.rs +++ b/src/quic.rs @@ -1,142 +1,445 @@ -#![allow(clippy::duplicate_mod)] - #[cfg(feature = "alloc")] -use alloc::boxed::Box; +use alloc::{boxed::Box, string::ToString}; + +use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; +use aead::{AeadCore, AeadInOut, KeyInit}; +use enum_dispatch::enum_dispatch; +use rustls::Error; +use rustls::crypto::cipher::{AeadKey, Iv, Nonce}; +use rustls::quic; +use typenum::Unsigned; + +#[cfg(feature = "aes-ccm")] +use crate::aead::aes::Aes128Ccm; +#[cfg(feature = "aes-gcm")] +use crate::aead::aes::{Aes128Gcm, Aes256Gcm}; +#[cfg(feature = "chacha20")] +use chacha20::{ + ChaCha20, + cipher::{KeyIvInit, StreamCipher}, +}; +#[cfg(feature = "chacha20poly1305")] +use chacha20poly1305::ChaCha20Poly1305; +#[cfg(feature = "aes")] +use cipher::BlockCipherEncrypt; +#[cfg(feature = "chacha20")] +use cipher::StreamCipherSeek; + +/// Errors that can occur in QUIC operations +#[derive(Debug, thiserror::Error)] +pub enum QuicError { + /// Failed to convert sample to block + #[error("failed to convert sample to block: {0}")] + SampleToBlock(#[from] core::array::TryFromSliceError), + + /// Failed to convert encrypted block to mask + #[error("failed to convert encrypted block to mask: {0}")] + BlockToMask(core::array::TryFromSliceError), + + /// Failed to convert first 4 bytes of sample to counter + #[error("failed to convert first 4 bytes of sample to counter: {0}")] + SampleToCounter(core::array::TryFromSliceError), + + /// Invalid ChaCha20 nonce length + #[error("invalid ChaCha20 nonce length: {0}")] + InvalidNonceLength(core::array::TryFromSliceError), + + /// ChaCha20 seek failed + #[cfg(feature = "chacha20")] + #[error("ChaCha20 seek failed: {0}")] + SeekFailed(#[from] cipher::StreamCipherError), + + /// ChaCha20 keystream failed + #[cfg(feature = "chacha20")] + #[error("ChaCha20 keystream failed: {0}")] + KeystreamFailed(cipher::StreamCipherError), + + /// Invalid AES key + #[cfg(feature = "aes")] + #[error("invalid AES key: {0}")] + InvalidAesKey(#[from] cipher::InvalidLength), + + /// Invalid ChaCha20-Poly1305 key + #[cfg(feature = "chacha20")] + #[error("invalid ChaCha20-Poly1305 key: {0}")] + InvalidChaCha20Key(core::array::TryFromSliceError), + + /// Invalid QUIC header protection mask length + #[error("invalid QUIC header protection mask length")] + InvalidMaskLength, + + /// Invalid QUIC header protection packet number length + #[error("invalid QUIC header protection packet number length")] + InvalidPacketNumberLength, + + /// Invalid nonce for AEAD operation + #[error("invalid nonce for AEAD operation: {0}")] + InvalidNonce(core::array::TryFromSliceError), + + #[error("Encryption failed: {0}")] + Encrypt(aead::Error), + + #[error("Decryption failed: {0}")] + Decrypt(aead::Error), +} + +impl From for rustls::Error { + fn from(e: QuicError) -> Self { + match e { + QuicError::Encrypt(_) => rustls::Error::EncryptError, + QuicError::Decrypt(_) => rustls::Error::DecryptError, + _ => rustls::Error::General(e.to_string()), + } + } +} + +trait HasHeaderKey { + #[allow(clippy::new_ret_no_self)] + fn new(key: AeadKey) -> Result; +} + +#[cfg(feature = "aes-gcm")] +impl HasHeaderKey for Aes128Gcm { + fn new(key: AeadKey) -> Result { + Ok(HeaderProtectionKey::Aes128Ecb(aes::Aes128::new_from_slice( + key.as_ref(), + )?)) + } +} + +#[cfg(feature = "aes-gcm")] +impl HasHeaderKey for Aes256Gcm { + fn new(key: AeadKey) -> Result { + Ok(HeaderProtectionKey::Aes256Ecb(aes::Aes256::new_from_slice( + key.as_ref(), + )?)) + } +} + +#[cfg(feature = "aes-ccm")] +impl HasHeaderKey for Aes128Ccm { + fn new(key: AeadKey) -> Result { + Ok(HeaderProtectionKey::Aes128Ecb(aes::Aes128::new_from_slice( + key.as_ref(), + )?)) + } +} + +#[cfg(feature = "chacha20poly1305")] +impl HasHeaderKey for ChaCha20Poly1305 { + fn new(key: AeadKey) -> Result { + let key = chacha20::Key::try_from(key.as_ref()).map_err(QuicError::InvalidChaCha20Key)?; + Ok(HeaderProtectionKey::ChaCha20(key)) + } +} + +#[enum_dispatch(MaskSample)] +#[allow(clippy::large_enum_variant)] +pub enum HeaderProtectionKey { + #[cfg(feature = "aes")] + Aes128Ecb(aes::Aes128), + #[cfg(feature = "aes")] + Aes256Ecb(aes::Aes256), + #[cfg(feature = "chacha20")] + ChaCha20(chacha20::Key), +} + +#[enum_dispatch] +trait MaskSample { + fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5], QuicError>; +} + +// 5.4.3. AES-Based Header Protection +// This section defines the packet protection algorithm for AEAD_AES_128_GCM, AEAD_AES_128_CCM, and AEAD_AES_256_GCM. AEAD_AES_128_GCM and AEAD_AES_128_CCM use 128-bit AES in Electronic Codebook (ECB) mode. +// AEAD_AES_256_GCM uses 256-bit AES in ECB mode. AES is defined in [AES]. + +// This algorithm samples 16 bytes from the packet ciphertext. This value is used as the input to AES-ECB. In pseudocode, the header protection function is defined as: + +// header_protection(hp_key, sample): +// mask = AES-ECB(hp_key, sample) +#[cfg(feature = "aes")] +impl MaskSample for aes::Aes128 { + fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5], QuicError> { + let mut block = (&sample[..16]) + .try_into() + .map_err(QuicError::SampleToBlock)?; + + self.encrypt_block(&mut block); + block[..5].try_into().map_err(QuicError::BlockToMask) + } +} + +#[cfg(feature = "aes")] +impl MaskSample for aes::Aes256 { + fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5], QuicError> { + let mut block = (&sample[..16]) + .try_into() + .map_err(QuicError::SampleToBlock)?; + + self.encrypt_block(&mut block); + block[..5].try_into().map_err(QuicError::BlockToMask) + } +} + +#[cfg(feature = "chacha20")] +impl MaskSample for chacha20::Key { + fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5], QuicError> { + // 5.4.4. ChaCha20-Based Header Protection + // When AEAD_CHACHA20_POLY1305 is in use, header protection uses the raw ChaCha20 function as defined in Section 2.4 of [CHACHA]. This uses a 256-bit key and 16 bytes sampled from the packet protection output. + // + // The first 4 bytes of the sampled ciphertext are the block counter. A ChaCha20 implementation could take a 32-bit integer in place of a byte sequence, in which case, the byte sequence is interpreted as a little-endian value. + // + // The remaining 12 bytes are used as the nonce. A ChaCha20 implementation might take an array of three 32-bit integers in place of a byte sequence, in which case, the nonce bytes are interpreted as a sequence of 32-bit little-endian integers. + // + // The encryption mask is produced by invoking ChaCha20 to protect 5 zero bytes. In pseudocode, the header protection function is defined as: + // + // header_protection(hp_key, sample): + // counter = sample[0..3] + // nonce = sample[4..15] + // mask = ChaCha20(hp_key, counter, nonce, {0,0,0,0,0}) + + let counter = u32::from_le_bytes( + sample[0..4] + .try_into() + .map_err(QuicError::SampleToCounter)?, + ); + let nonce = &sample[4..16]; + let mut chacha = ChaCha20::new( + self, + nonce.try_into().map_err(QuicError::InvalidNonceLength)?, + ); + + chacha.try_seek(counter).map_err(QuicError::SeekFailed)?; + + let mut mask = [0u8; 5]; + chacha + .apply_keystream_b2b(&[0u8; 5], &mut mask) + .map_err(QuicError::KeystreamFailed)?; + + Ok(mask) + } +} + +trait XorInPlace { + fn xor_in_place( + &self, + sample: &[u8], + first: &mut u8, + packet_number: &mut [u8], + masked: bool, + ) -> Result<(), QuicError>; +} + +impl XorInPlace for T { + fn xor_in_place( + &self, + sample: &[u8], + first: &mut u8, + packet_number: &mut [u8], + masked: bool, + ) -> Result<(), QuicError> { + // This implements "Header Protection Application" almost verbatim. + // + + let mask = self.new_mask(sample)?; + + // The `unwrap()` will not panic because `new_mask` returns a + // non-empty result. + let (first_mask, pn_mask) = mask.split_first().ok_or(QuicError::InvalidMaskLength)?; + + // It is OK for the `mask` to be longer than `packet_number`, + // but a valid `packet_number` will never be longer than `mask`. + if packet_number.len() > pn_mask.len() { + return Err(QuicError::InvalidPacketNumberLength); + } + + // Infallible from this point on. Before this point, `first` and + // `packet_number` are unchanged. -use aead::AeadCore; -use chacha20poly1305::{AeadInPlace, KeyInit, KeySizeUser}; -use crypto_common::typenum::Unsigned; -use rustls::crypto::cipher::{self, AeadKey, Iv}; -use rustls::{quic, Error, Tls13CipherSuite}; + const LONG_HEADER_FORM: u8 = 0x80; + let bits = match *first & LONG_HEADER_FORM == LONG_HEADER_FORM { + true => 0x0f, // Long header: 4 bits masked + false => 0x1f, // Short header: 5 bits masked + }; -#[allow(dead_code)] // TODO -pub struct HeaderProtectionKey(AeadKey); + let first_plain = *first ^ if masked { first_mask & bits } else { 0 }; + let pn_len = (first_plain & 0x03) as usize + 1; -impl HeaderProtectionKey { - pub fn new(key: AeadKey) -> Self { - Self(key) + *first ^= first_mask & bits; + for (dst, m) in packet_number.iter_mut().zip(pn_mask).take(pn_len) { + *dst ^= m; + } + + Ok(()) } } impl quic::HeaderProtectionKey for HeaderProtectionKey { fn encrypt_in_place( &self, - _sample: &[u8], - _first: &mut u8, - _packet_number: &mut [u8], + sample: &[u8], + first: &mut u8, + packet_number: &mut [u8], ) -> Result<(), Error> { - todo!() + self.xor_in_place(sample, first, packet_number, false) + .map_err(Into::into) } fn decrypt_in_place( &self, - _sample: &[u8], - _first: &mut u8, - _packet_number: &mut [u8], + sample: &[u8], + first: &mut u8, + packet_number: &mut [u8], ) -> Result<(), Error> { - todo!() + self.xor_in_place(sample, first, packet_number, true) + .map_err(Into::into) } #[inline] fn sample_len(&self) -> usize { - todo!() + 16 } } -pub struct PacketKey { +pub(crate) struct PacketKey { + /// Encrypts or decrypts a packet's payload + key: A, /// Computes unique nonces for each packet iv: Iv, - - /// The cipher suite used for this packet key - #[allow(dead_code)] - suite: &'static Tls13CipherSuite, - - crypto: chacha20poly1305::ChaCha20Poly1305, + /// Confidentiality limit (see [`quic::PacketKey::confidentiality_limit`]) + confidentiality_limit: u64, + /// Integrity limit (see [`quic::PacketKey::integrity_limit`]) + integrity_limit: u64, } -impl PacketKey { - pub fn new(suite: &'static Tls13CipherSuite, key: AeadKey, iv: Iv) -> Self { +impl PacketKey +where + A: KeyInit + AeadInOut + Send + Sync, +{ + pub(crate) fn new( + key: AeadKey, + iv: Iv, + confidentiality_limit: u64, + integrity_limit: u64, + ) -> Self { Self { + key: A::new_from_slice(key.as_ref()).expect("Invalid key length for AEAD algorithm"), iv, - suite, - crypto: chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) - .expect("key should be valid"), + confidentiality_limit, + integrity_limit, } } } -impl quic::PacketKey for PacketKey { +impl quic::PacketKey for PacketKey +where + A: AeadInOut + Send + Sync, +{ fn encrypt_in_place( &self, packet_number: u64, - aad: &[u8], + header: &[u8], payload: &mut [u8], ) -> Result { - let nonce = cipher::Nonce::new(&self.iv, packet_number).0; - - let tag = self - .crypto - .encrypt_in_place_detached(&nonce.into(), aad, payload) - .map_err(|_| rustls::Error::EncryptError)?; - Ok(quic::Tag::from(tag.as_ref())) - } - - /// Decrypt a QUIC packet - /// - /// Takes the packet `header`, which is used as the additional authenticated - /// data, and the `payload`, which includes the authentication tag. - /// - /// If the return value is `Ok`, the decrypted payload can be found in - /// `payload`, up to the length found in the return value. + let nonce_aead: cipher::Array::NonceSize> = + aead::Nonce::::try_from(&Nonce::new(&self.iv, packet_number).0[..]) + .map_err(QuicError::InvalidNonce)?; + + // Create a buffer with the payload + let mut buffer = EncryptBufferAdapter::Vec(payload.to_vec()); + + self.key + .encrypt_in_place(&nonce_aead, header, &mut buffer) + .map_err(QuicError::Encrypt)?; + + let buffer = buffer.as_ref(); + + // Copy the encrypted payload back + payload.copy_from_slice(&buffer[..payload.len()]); + + // Extract the tag from the end + Ok(quic::Tag::from(&buffer[payload.len()..])) + } + fn decrypt_in_place<'a>( &self, packet_number: u64, - aad: &[u8], + header: &[u8], payload: &'a mut [u8], ) -> Result<&'a [u8], Error> { - let mut payload_ = payload.to_vec(); - let payload_len = payload_.len(); - let nonce = chacha20poly1305::Nonce::from(cipher::Nonce::new(&self.iv, packet_number).0); + let nonce_aead = aead::Nonce::::try_from(&Nonce::new(&self.iv, packet_number).0[..]) + .map_err(QuicError::InvalidNonce)?; - self.crypto - .decrypt_in_place(&nonce, aad, &mut payload_) - .map_err(|_| rustls::Error::DecryptError)?; + // Append the tag to the payload for decryption + if payload.len() < A::TagSize::USIZE { + return Err(QuicError::Decrypt(aead::Error).into()); + } + let plaintext_len = payload.len() - A::TagSize::USIZE; - // Unfortunately the lifetime bound on decrypt_in_place sucks - payload.copy_from_slice(&payload_); + self.key + .decrypt_in_place( + &nonce_aead, + header, + &mut DecryptBufferAdapter::Slice(payload.into()), + ) + .map_err(QuicError::Decrypt)?; - let plain_len = payload_len - self.tag_len(); - Ok(&payload[..plain_len]) + Ok(&payload[..plaintext_len]) } /// Tag length for the underlying AEAD algorithm #[inline] fn tag_len(&self) -> usize { - ::TagSize::to_usize() + A::TagSize::USIZE } - fn integrity_limit(&self) -> u64 { - 1 << 36 + /// Confidentiality limit (see [`quic::PacketKey::confidentiality_limit`]) + fn confidentiality_limit(&self) -> u64 { + self.confidentiality_limit } - fn confidentiality_limit(&self) -> u64 { - u64::MAX + /// Integrity limit (see [`quic::PacketKey::integrity_limit`]) + fn integrity_limit(&self) -> u64 { + self.integrity_limit } } -#[allow(dead_code)] // TODO -pub struct KeyBuilder(AeadKey); +pub(crate) struct QuicCrypto { + pub(crate) packet_alg: core::marker::PhantomData, + pub(crate) confidentiality_limit: u64, + pub(crate) integrity_limit: u64, +} -impl rustls::quic::Algorithm for KeyBuilder { - fn packet_key(&self, _key: AeadKey, _iv: Iv) -> Box { - todo!() +impl QuicCrypto { + pub const DEFAULT: Self = Self { + packet_alg: core::marker::PhantomData, + confidentiality_limit: u64::MAX, + integrity_limit: u64::MAX, + }; +} + +impl quic::Algorithm for QuicCrypto +where + A: AeadCore + AeadInOut + KeyInit + HasHeaderKey + Send + Sync + 'static, +{ + fn packet_key(&self, key: AeadKey, iv: Iv) -> Box { + Box::new(PacketKey::::new( + key, + iv, + self.confidentiality_limit, + self.integrity_limit, + )) } fn header_protection_key(&self, key: AeadKey) -> Box { - Box::new(HeaderProtectionKey::new(key)) + Box::new(::new(key).expect("Invalid key length for header protection")) } fn aead_key_len(&self) -> usize { - chacha20poly1305::ChaCha20Poly1305::key_size() + A::key_size() + } + + fn fips(&self) -> bool { + false // RustCrypto doesn't have FIPS certification } } diff --git a/src/sign.rs b/src/sign.rs index e6109f5..9e7ed17 100644 --- a/src/sign.rs +++ b/src/sign.rs @@ -1,41 +1,33 @@ #[cfg(feature = "alloc")] -use alloc::{sync::Arc, vec::Vec}; +use alloc::{string::ToString, sync::Arc, vec::Vec}; use core::marker::PhantomData; -use self::ecdsa::{EcdsaSigningKeyP256, EcdsaSigningKeyP384}; -use self::eddsa::Ed25519SigningKey; -use self::rsa::RsaSigningKey; - use pki_types::PrivateKeyDer; use rustls::sign::{Signer, SigningKey}; use rustls::{Error, SignatureScheme}; -use signature::{RandomizedSigner, SignatureEncoding}; +use signature::SignatureEncoding; -#[derive(Debug)] -pub struct GenericRandomizedSigner -where - S: SignatureEncoding, - T: RandomizedSigner, -{ - _marker: PhantomData, - key: Arc, - scheme: SignatureScheme, +/// Errors that can occur in the signing module +#[derive(Debug, thiserror::Error)] +pub enum SignError { + /// Signing operation failed + #[error("signing failed: {0}")] + SigningFailed(signature::Error), + + /// Key type not supported + #[error("key type not supported")] + NotSupported, } -impl Signer for GenericRandomizedSigner -where - S: SignatureEncoding + Send + Sync + core::fmt::Debug, - T: RandomizedSigner + Send + Sync + core::fmt::Debug, -{ - fn sign(&self, message: &[u8]) -> Result, Error> { - self.key - .try_sign_with_rng(&mut rand_core::OsRng, message) - .map_err(|_| rustls::Error::General("signing failed".into())) - .map(|sig: S| sig.to_vec()) +impl From for SignError { + fn from(e: signature::Error) -> Self { + Self::SigningFailed(e) } +} - fn scheme(&self) -> SignatureScheme { - self.scheme +impl From for rustls::Error { + fn from(e: SignError) -> Self { + rustls::Error::General(e.to_string()) } } @@ -58,8 +50,9 @@ where fn sign(&self, message: &[u8]) -> Result, Error> { self.key .try_sign(message) - .map_err(|_| rustls::Error::General("signing failed".into())) + .map_err(SignError::SigningFailed) .map(|sig: S| sig.to_vec()) + .map_err(Into::into) } fn scheme(&self) -> SignatureScheme { @@ -72,11 +65,24 @@ where /// # Errors /// /// Returns an error if the key couldn't be decoded. -pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { - RsaSigningKey::try_from(der) - .map(|x| Arc::new(x) as _) - .or_else(|_| any_ecdsa_type(der)) - .or_else(|_| any_eddsa_type(der)) +#[allow(unused_variables)] +pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result, SignError> { + #[cfg(feature = "sign-rsa")] + if let Ok(key) = rsa::RsaSigningKey::try_from(der) { + return Ok(Arc::new(key) as _); + } + + #[cfg(feature = "sign-ecdsa-nist")] + if let Ok(key) = any_ecdsa_type(der) { + return Ok(key); + } + + #[cfg(feature = "sign-eddsa")] + if let Ok(key) = any_eddsa_type(der) { + return Ok(key); + } + + Err(SignError::NotSupported) } /// Extract any supported ECDSA key from the given DER input. @@ -84,10 +90,19 @@ pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result /// # Errors /// /// Returns an error if the key couldn't be decoded. -pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { - let p256 = |_| EcdsaSigningKeyP256::try_from(der).map(|x| Arc::new(x) as _); - let p384 = |_| EcdsaSigningKeyP384::try_from(der).map(|x| Arc::new(x) as _); - p256(()).or_else(p384) +#[allow(unused_variables)] +#[cfg(feature = "sign-ecdsa-nist")] +pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result, SignError> { + #[cfg(all(feature = "der", feature = "ecdsa-p256"))] + if let Ok(key) = ecdsa::nist::EcdsaSigningKeyP256::try_from(der) { + return Ok(Arc::new(key) as _); + } + #[cfg(all(feature = "der", feature = "ecdsa-p384"))] + if let Ok(key) = ecdsa::nist::EcdsaSigningKeyP384::try_from(der) { + return Ok(Arc::new(key) as _); + } + + Err(SignError::NotSupported) } /// Extract any supported EDDSA key from the given DER input. @@ -95,11 +110,28 @@ pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result, ru /// # Errors /// /// Returns an error if the key couldn't be decoded. -pub fn any_eddsa_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { - // TODO: Add support for Ed448 - Ed25519SigningKey::try_from(der).map(|x| Arc::new(x) as _) +#[allow(unused_variables)] +#[cfg(feature = "sign-eddsa")] +pub fn any_eddsa_type(der: &PrivateKeyDer<'_>) -> Result, SignError> { + #[cfg(all(feature = "der", feature = "eddsa-ed25519"))] + if let Ok(key) = eddsa::ed25519::Ed25519SigningKey::try_from(der) { + return Ok(Arc::new(key) as _); + } + + #[cfg(all(feature = "der", feature = "eddsa-ed448"))] + if let Ok(key) = eddsa::ed448::Ed448SigningKey::try_from(der) { + return Ok(Arc::new(key) as _); + } + + Err(SignError::NotSupported) } +#[cfg(feature = "ecdsa")] pub mod ecdsa; +#[cfg(feature = "eddsa")] pub mod eddsa; +#[cfg(feature = "rsa")] pub mod rsa; + +#[cfg(feature = "rand")] +pub mod rand; diff --git a/src/sign/ecdsa.rs b/src/sign/ecdsa.rs index 3f4a2bc..1931d6e 100644 --- a/src/sign/ecdsa.rs +++ b/src/sign/ecdsa.rs @@ -1,66 +1,2 @@ -#[cfg(feature = "alloc")] -use alloc::{boxed::Box, format, sync::Arc}; -use core::marker::PhantomData; - -use paste::paste; -use pkcs8::DecodePrivateKey; -use pki_types::PrivateKeyDer; -use rustls::sign::SigningKey; -use rustls::{SignatureAlgorithm, SignatureScheme}; -use sec1::DecodeEcPrivateKey; - -macro_rules! impl_ecdsa { - ($name: ident, $scheme: expr, $signing_key: ty, $signature: ty) => { - paste! { - #[derive(Debug)] - pub struct [] { - key: Arc<$signing_key>, - scheme: SignatureScheme, - } - - impl TryFrom<&PrivateKeyDer<'_>> for [] { - type Error = rustls::Error; - - fn try_from(value: &PrivateKeyDer<'_>) -> Result { - let pkey = match value { - PrivateKeyDer::Pkcs8(der) => { - $signing_key::from_pkcs8_der(der.secret_pkcs8_der()).map_err(|e| format!("failed to decrypt private key: {e}")) - }, - PrivateKeyDer::Sec1(sec1) => { - $signing_key::from_sec1_der(sec1.secret_sec1_der()).map_err(|e| format!("failed to decrypt private key: {e}")) - }, - PrivateKeyDer::Pkcs1(_) => Err(format!("ECDSA does not support PKCS#1 key")), - _ => Err("not supported".into()), - }; - pkey.map(|kp| { - Self { - key: Arc::new(kp), - scheme: $scheme, - } - }).map_err(rustls::Error::General) - } - } - - impl SigningKey for [] { - fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { - if offered.contains(&self.scheme) { - Some(Box::new(super::GenericRandomizedSigner::<$signature, _> { - _marker: PhantomData, - key: self.key.clone(), - scheme: self.scheme, - })) - } else { - None - } - } - - fn algorithm(&self) -> SignatureAlgorithm { - SignatureAlgorithm::ECDSA - } - } - } - }; -} - -impl_ecdsa! {P256, SignatureScheme::ECDSA_NISTP256_SHA256, p256::ecdsa::SigningKey, p256::ecdsa::DerSignature} -impl_ecdsa! {P384, SignatureScheme::ECDSA_NISTP384_SHA384, p384::ecdsa::SigningKey, p384::ecdsa::DerSignature} +#[cfg(feature = "sign-ecdsa-nist")] +pub mod nist; diff --git a/src/sign/ecdsa/nist.rs b/src/sign/ecdsa/nist.rs new file mode 100644 index 0000000..361ac66 --- /dev/null +++ b/src/sign/ecdsa/nist.rs @@ -0,0 +1,160 @@ +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, string::ToString, sync::Arc}; +use core::fmt::Debug; +use core::marker::PhantomData; + +use crate::sign::rand::GenericRandomizedSigner; +use rustls::sign::SigningKey; +use rustls::{SignatureAlgorithm, SignatureScheme}; + +#[cfg(feature = "der")] +use ::pki_types::PrivateKeyDer; + +/// Errors that can occur when loading an ECDSA private key +#[derive(Debug, thiserror::Error)] +pub enum EcdsaKeyError { + /// Failed to decode PKCS#8 private key + #[cfg(feature = "pkcs8")] + #[error("failed to decrypt PKCS#8 private key: {0}")] + Pkcs8(::pkcs8::Error), + + /// Failed to decode SEC1 private key + #[cfg(feature = "sec1")] + #[error("failed to decrypt SEC1 private key: {0}")] + Sec1(#[from] ::sec1::Error), + + /// ECDSA does not support PKCS#1 keys + #[error("ECDSA does not support PKCS#1 key")] + Pkcs1NotSupported, + + /// Key format not supported + #[error("key format not supported")] + NotSupported, +} + +#[cfg(feature = "pkcs8")] +impl From<::pkcs8::Error> for EcdsaKeyError { + fn from(e: ::pkcs8::Error) -> Self { + Self::Pkcs8(e) + } +} + +impl From for rustls::Error { + fn from(e: EcdsaKeyError) -> Self { + rustls::Error::General(e.to_string()) + } +} + +trait EcdsaKey: Sized { + const SCHEME: SignatureScheme; +} + +#[cfg(all(feature = "pkcs8", not(feature = "sec1")))] +trait DecodePrivateKey: ::pkcs8::DecodePrivateKey {} + +#[cfg(all(feature = "sec1", not(feature = "pkcs8")))] +trait DecodePrivateKey: ::sec1::DecodeEcPrivateKey {} + +#[cfg(all(feature = "pkcs8", feature = "sec1"))] +trait DecodePrivateKey: ::pkcs8::DecodePrivateKey + ::sec1::DecodeEcPrivateKey {} + +#[cfg(feature = "der")] +impl TryFrom<&PrivateKeyDer<'_>> + for EcdsaSigningKey +where + SecretKey: Debug + DecodePrivateKey, + SigningKey: EcdsaKey + Send + Sync + 'static + From, + Signature: Send + Sync + 'static, +{ + type Error = rustls::Error; + + fn try_from(value: &PrivateKeyDer<'_>) -> Result { + let pkey = match value { + #[cfg(feature = "pkcs8")] + PrivateKeyDer::Pkcs8(der) => { + SecretKey::from_pkcs8_der(der.secret_pkcs8_der()).map_err(Into::into) + } + #[cfg(feature = "sec1")] + PrivateKeyDer::Sec1(sec1) => { + SecretKey::from_sec1_der(sec1.secret_sec1_der()).map_err(Into::into) + } + PrivateKeyDer::Pkcs1(_) => Err(EcdsaKeyError::Pkcs1NotSupported), + _ => Err(EcdsaKeyError::NotSupported), + }; + pkey.map(|kp| Self { + key: Arc::new(kp.into()), + scheme: SigningKey::SCHEME, + _phantom: PhantomData, + _phantom_sk: PhantomData, + }) + .map_err(Into::into) + } +} + +#[derive(Debug)] +pub struct EcdsaSigningKey { + key: Arc, + scheme: SignatureScheme, + _phantom: PhantomData, + _phantom_sk: PhantomData, +} + +impl SigningKey for EcdsaSigningKey +where + SecretKey: Debug + Send + Sync, + SK: Send + Sync + 'static + Debug + ecdsa::signature::RandomizedSigner, + SIG: Send + Sync + 'static + Debug + ecdsa::signature::SignatureEncoding, +{ + fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { + if offered.contains(&self.scheme) { + Some(Box::new(GenericRandomizedSigner:: { + _marker: PhantomData, + key: self.key.clone(), + scheme: self.scheme, + })) + } else { + None + } + } + + fn algorithm(&self) -> SignatureAlgorithm { + SignatureAlgorithm::ECDSA + } +} + +macro_rules! impl_ecdsa_curve { + ($curve:ident, $scheme:expr, $type_name:ident) => { + pub type $type_name = EcdsaSigningKey< + ::$curve::SecretKey, + ::$curve::ecdsa::SigningKey, + ::$curve::ecdsa::DerSignature, + >; + + impl EcdsaKey for ::$curve::ecdsa::SigningKey { + const SCHEME: SignatureScheme = $scheme; + } + + impl DecodePrivateKey for ::$curve::SecretKey {} + }; +} + +#[cfg(all(feature = "ecdsa-p256", feature = "hash-sha256"))] +impl_ecdsa_curve!( + p256, + SignatureScheme::ECDSA_NISTP256_SHA256, + EcdsaSigningKeyP256 +); + +#[cfg(all(feature = "ecdsa-p384", feature = "hash-sha384"))] +impl_ecdsa_curve!( + p384, + SignatureScheme::ECDSA_NISTP384_SHA384, + EcdsaSigningKeyP384 +); + +#[cfg(all(feature = "ecdsa-p521", feature = "hash-sha512"))] +impl_ecdsa_curve!( + p521, + SignatureScheme::ECDSA_NISTP521_SHA512, + EcdsaSigningKeyP521 +); diff --git a/src/sign/eddsa.rs b/src/sign/eddsa.rs index e6f0d1a..fb7e140 100644 --- a/src/sign/eddsa.rs +++ b/src/sign/eddsa.rs @@ -1,57 +1,5 @@ -#[cfg(feature = "alloc")] -use alloc::{boxed::Box, format, string::ToString, sync::Arc}; -use core::marker::PhantomData; +#[cfg(feature = "ed25519")] +pub mod ed25519; -use pkcs8::DecodePrivateKey; -use pki_types::PrivateKeyDer; -use rustls::sign::{Signer, SigningKey}; -use rustls::{SignatureAlgorithm, SignatureScheme}; -use sec1::DecodeEcPrivateKey; - -#[derive(Debug)] -pub struct Ed25519SigningKey { - key: Arc, - scheme: SignatureScheme, -} - -impl TryFrom<&PrivateKeyDer<'_>> for Ed25519SigningKey { - type Error = rustls::Error; - - fn try_from(value: &PrivateKeyDer<'_>) -> Result { - let pkey = match value { - PrivateKeyDer::Pkcs8(der) => { - ed25519_dalek::SigningKey::from_pkcs8_der(der.secret_pkcs8_der()) - .map_err(|e| format!("failed to decrypt private key: {e}")) - } - PrivateKeyDer::Sec1(sec1) => { - ed25519_dalek::SigningKey::from_sec1_der(sec1.secret_sec1_der()) - .map_err(|e| format!("failed to decrypt private key: {e}")) - } - PrivateKeyDer::Pkcs1(_) => Err("ED25519 does not support PKCS#1 key".to_string()), - _ => Err("not supported".into()), - }; - pkey.map(|kp| Self { - key: Arc::new(kp), - scheme: SignatureScheme::ED25519, - }) - .map_err(rustls::Error::General) - } -} - -impl SigningKey for Ed25519SigningKey { - fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { - if offered.contains(&self.scheme) { - Some(Box::new(super::GenericSigner { - _marker: PhantomData, - key: self.key.clone(), - scheme: self.scheme, - })) - } else { - None - } - } - - fn algorithm(&self) -> SignatureAlgorithm { - SignatureAlgorithm::ED25519 - } -} +#[cfg(feature = "ed448")] +pub mod ed448; diff --git a/src/sign/eddsa/ed25519.rs b/src/sign/eddsa/ed25519.rs new file mode 100644 index 0000000..394fc43 --- /dev/null +++ b/src/sign/eddsa/ed25519.rs @@ -0,0 +1,90 @@ +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, string::ToString, sync::Arc}; + +use crate::sign::GenericSigner; +use core::marker::PhantomData; +use ed25519_dalek::SigningKey; +use rustls::{SignatureAlgorithm, SignatureScheme, sign::Signer}; + +#[cfg(feature = "der")] +use pki_types::PrivateKeyDer; + +/// Errors that can occur when loading an Ed25519 private key +#[derive(Debug, thiserror::Error)] +pub enum Ed25519KeyError { + /// Failed to decode PKCS#8 private key + #[cfg(feature = "pkcs8")] + #[error("failed to decrypt PKCS#8 private key: {0}")] + Pkcs8(::pkcs8::Error), + + /// ED25519 does not support SEC-1 keys + #[error("ED25519 does not support SEC-1 key")] + Sec1NotSupported, + + /// ED25519 does not support PKCS#1 keys + #[error("ED25519 does not support PKCS#1 key")] + Pkcs1NotSupported, + + /// Key format not supported + #[error("key format not supported")] + NotSupported, +} + +#[cfg(feature = "pkcs8")] +impl From<::pkcs8::Error> for Ed25519KeyError { + fn from(e: ::pkcs8::Error) -> Self { + Self::Pkcs8(e) + } +} + +impl From for rustls::Error { + fn from(e: Ed25519KeyError) -> Self { + rustls::Error::General(e.to_string()) + } +} + +#[derive(Debug)] +pub struct Ed25519SigningKey(Arc); + +#[cfg(feature = "der")] +impl TryFrom<&PrivateKeyDer<'_>> for Ed25519SigningKey { + type Error = Ed25519KeyError; + + fn try_from(value: &PrivateKeyDer<'_>) -> Result { + let pkey = match value { + #[cfg(feature = "pkcs8")] + PrivateKeyDer::Pkcs8(der) => { + use pkcs8::DecodePrivateKey; + SigningKey::from_pkcs8_der(der.secret_pkcs8_der()).map_err(Into::into) + } + + // (chat log from tony in zulip) + // Per RFC 8410, only PKCS#8 is supported for ED25519 keys + // https://datatracker.ietf.org/doc/html/rfc8410#section-7 + // So no SEC 1 support for ED25519 (despite we do have it compile before?!) + PrivateKeyDer::Sec1(_) => Err(Ed25519KeyError::Sec1NotSupported), + PrivateKeyDer::Pkcs1(_) => Err(Ed25519KeyError::Pkcs1NotSupported), + _ => Err(Ed25519KeyError::NotSupported), + }; + pkey.map(|kp| Self(Arc::new(kp))) + } +} + +impl rustls::sign::SigningKey for Ed25519SigningKey { + fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { + const SCHEME: SignatureScheme = SignatureScheme::ED25519; + if offered.contains(&SCHEME) { + Some(Box::new(GenericSigner { + _marker: PhantomData, + key: self.0.clone(), + scheme: SCHEME, + })) + } else { + None + } + } + + fn algorithm(&self) -> SignatureAlgorithm { + SignatureAlgorithm::ED25519 + } +} diff --git a/src/sign/eddsa/ed448.rs b/src/sign/eddsa/ed448.rs new file mode 100644 index 0000000..10c8f38 --- /dev/null +++ b/src/sign/eddsa/ed448.rs @@ -0,0 +1,134 @@ +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, string::ToString, sync::Arc, vec::Vec}; + +use ed448_goldilocks::{Signature, SigningKey}; +use rustls::{SignatureAlgorithm, SignatureScheme, sign::Signer}; +use signature::{SignatureEncoding, Signer as SignatureSigner}; + +#[cfg(feature = "der")] +use pki_types::PrivateKeyDer; + +/// Errors that can occur when loading an Ed448 private key +#[derive(Debug, thiserror::Error)] +pub enum Ed448KeyError { + /// Failed to decode PKCS#8 private key + #[cfg(feature = "pkcs8")] + #[error("failed to decrypt PKCS#8 private key: {0}")] + Pkcs8(::pkcs8::Error), + + /// ED448 does not support SEC-1 keys + #[error("ED448 does not support SEC-1 key")] + Sec1NotSupported, + + /// ED448 does not support PKCS#1 keys + #[error("ED448 does not support PKCS#1 key")] + Pkcs1NotSupported, + + /// Key format not supported + #[error("key format not supported")] + NotSupported, +} + +#[cfg(feature = "pkcs8")] +impl From<::pkcs8::Error> for Ed448KeyError { + fn from(e: ::pkcs8::Error) -> Self { + Self::Pkcs8(e) + } +} + +impl From for rustls::Error { + fn from(e: Ed448KeyError) -> Self { + rustls::Error::General(e.to_string()) + } +} + +// Wrapper for Ed448 signature to implement SignatureEncoding +#[derive(Debug, Clone)] +pub struct Ed448Signature(Signature); + +impl SignatureEncoding for Ed448Signature { + type Repr = [u8; Signature::BYTE_SIZE]; // Ed448 signature is 114 bytes + + fn to_bytes(&self) -> Self::Repr { + self.0.to_bytes() + } + + fn encoded_len(&self) -> usize { + Signature::BYTE_SIZE + } +} + +impl TryFrom<&[u8]> for Ed448Signature { + type Error = signature::Error; + + fn try_from(bytes: &[u8]) -> Result { + Signature::from_slice(bytes).map(Self) + } +} + +impl From for [u8; Signature::BYTE_SIZE] { + fn from(sig: Ed448Signature) -> Self { + sig.0.to_bytes() + } +} + +#[derive(Debug)] +pub struct Ed448SigningKey(Arc); + +#[cfg(feature = "der")] +impl TryFrom<&PrivateKeyDer<'_>> for Ed448SigningKey { + type Error = rustls::Error; + + fn try_from(value: &PrivateKeyDer<'_>) -> Result { + let pkey = match value { + #[cfg(feature = "pkcs8")] + PrivateKeyDer::Pkcs8(der) => { + use pkcs8::DecodePrivateKey; + SigningKey::from_pkcs8_der(der.secret_pkcs8_der()).map_err(Into::into) + } + + // Per RFC 8410, only PKCS#8 is supported for ED448 keys + // https://datatracker.ietf.org/doc/html/rfc8410#section-7 + PrivateKeyDer::Sec1(_) => Err(Ed448KeyError::Sec1NotSupported), + PrivateKeyDer::Pkcs1(_) => Err(Ed448KeyError::Pkcs1NotSupported), + _ => Err(Ed448KeyError::NotSupported), + }; + pkey.map(|kp| Self(Arc::new(kp))).map_err(Into::into) + } +} + +impl rustls::sign::SigningKey for Ed448SigningKey { + fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { + const SCHEME: SignatureScheme = SignatureScheme::ED448; + if offered.contains(&SCHEME) { + Some(Box::new(Ed448Signer { + key: self.0.clone(), + scheme: SCHEME, + })) + } else { + None + } + } + + fn algorithm(&self) -> SignatureAlgorithm { + SignatureAlgorithm::ED448 + } +} + +// Custom signer for Ed448 +#[derive(Debug)] +pub struct Ed448Signer { + key: Arc, + scheme: SignatureScheme, +} + +impl Signer for Ed448Signer { + fn sign(&self, message: &[u8]) -> Result, rustls::Error> { + let sig = self.key.sign(message); + Ok(sig.to_bytes().to_vec()) + } + + fn scheme(&self) -> SignatureScheme { + self.scheme + } +} diff --git a/src/sign/rand.rs b/src/sign/rand.rs new file mode 100644 index 0000000..981378a --- /dev/null +++ b/src/sign/rand.rs @@ -0,0 +1,53 @@ +#[cfg(feature = "alloc")] +use alloc::{string::ToString, sync::Arc, vec::Vec}; +use core::marker::PhantomData; + +use rustls::sign::Signer; +use rustls::{Error, SignatureScheme}; +use signature::{RandomizedSigner, SignatureEncoding}; + +/// Error that occurs during signing +#[derive(Debug, thiserror::Error)] +#[error("signing failed: {0}")] +pub struct SigningError(signature::Error); + +impl From for SigningError { + fn from(e: signature::Error) -> Self { + Self(e) + } +} + +impl From for rustls::Error { + fn from(e: SigningError) -> Self { + rustls::Error::General(e.to_string()) + } +} + +#[derive(Debug)] +pub struct GenericRandomizedSigner +where + S: SignatureEncoding, + T: RandomizedSigner, +{ + pub(crate) _marker: PhantomData, + pub(crate) key: Arc, + pub(crate) scheme: SignatureScheme, +} + +impl Signer for GenericRandomizedSigner +where + S: SignatureEncoding + Send + Sync + core::fmt::Debug, + T: RandomizedSigner + Send + Sync + core::fmt::Debug, +{ + fn sign(&self, message: &[u8]) -> Result, Error> { + self.key + .try_sign_with_rng(&mut rand_core::OsRng, message) + .map_err(SigningError::from) + .map(|sig: S| sig.to_vec()) + .map_err(Into::into) + } + + fn scheme(&self) -> SignatureScheme { + self.scheme + } +} diff --git a/src/sign/rsa.rs b/src/sign/rsa.rs index ab27d36..50e5bda 100644 --- a/src/sign/rsa.rs +++ b/src/sign/rsa.rs @@ -1,40 +1,94 @@ #[cfg(feature = "alloc")] -use alloc::{boxed::Box, format, string::ToString, sync::Arc}; +use alloc::{boxed::Box, string::ToString, sync::Arc}; -use pkcs8::DecodePrivateKey; -use pki_types::PrivateKeyDer; -use rsa::pkcs1::DecodeRsaPrivateKey; use rsa::RsaPrivateKey; use rustls::sign::{Signer, SigningKey}; use rustls::{SignatureAlgorithm, SignatureScheme}; -use sha2::{Sha256, Sha384, Sha512}; + +#[cfg(feature = "hash-sha256")] +use sha2::Sha256; +#[cfg(feature = "hash-sha384")] +use sha2::Sha384; +#[cfg(feature = "hash-sha512")] +use sha2::Sha512; + +#[cfg(feature = "der")] +use pki_types::PrivateKeyDer; + +/// Errors that can occur when loading an RSA private key +#[derive(Debug, thiserror::Error)] +pub enum RsaKeyError { + /// Failed to decode PKCS#8 private key + #[cfg(feature = "pkcs8")] + #[error("failed to decrypt PKCS#8 private key: {0}")] + Pkcs8(::pkcs8::Error), + + /// Failed to decode PKCS#1 private key + #[cfg(all(feature = "pkcs8", feature = "pkcs1"))] + #[error("failed to decrypt PKCS#1 private key: {0}")] + Pkcs1(#[from] ::pkcs1::Error), + + /// RSA does not support SEC-1 keys + #[error("RSA does not support SEC-1 key")] + Sec1NotSupported, + + /// Key format not supported + #[error("key format not supported")] + NotSupported, +} + +#[cfg(feature = "pkcs8")] +impl From<::pkcs8::Error> for RsaKeyError { + fn from(e: ::pkcs8::Error) -> Self { + Self::Pkcs8(e) + } +} + +impl From for rustls::Error { + fn from(e: RsaKeyError) -> Self { + rustls::Error::General(e.to_string()) + } +} const ALL_RSA_SCHEMES: &[SignatureScheme] = &[ + #[cfg(all(feature = "rsa-pss", feature = "hash-sha512"))] SignatureScheme::RSA_PSS_SHA512, + #[cfg(all(feature = "rsa-pss", feature = "hash-sha384"))] SignatureScheme::RSA_PSS_SHA384, + #[cfg(all(feature = "rsa-pss", feature = "hash-sha256"))] SignatureScheme::RSA_PSS_SHA256, + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha512"))] SignatureScheme::RSA_PKCS1_SHA512, + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha384"))] SignatureScheme::RSA_PKCS1_SHA384, + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha256"))] SignatureScheme::RSA_PKCS1_SHA256, ]; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct RsaSigningKey(RsaPrivateKey); +#[cfg(feature = "der")] impl TryFrom<&PrivateKeyDer<'_>> for RsaSigningKey { type Error = rustls::Error; fn try_from(value: &PrivateKeyDer<'_>) -> Result { let pkey = match value { - PrivateKeyDer::Pkcs8(der) => RsaPrivateKey::from_pkcs8_der(der.secret_pkcs8_der()) - .map_err(|e| format!("failed to decrypt private key: {e}")), - PrivateKeyDer::Pkcs1(der) => RsaPrivateKey::from_pkcs1_der(der.secret_pkcs1_der()) - .map_err(|e| format!("failed to decrypt private key: {e}")), - PrivateKeyDer::Sec1(_) => Err("RSA does not support SEC-1 key".to_string()), - _ => Err("not supported".into()), + #[cfg(feature = "pkcs8")] + PrivateKeyDer::Pkcs8(der) => { + use pkcs8::DecodePrivateKey; + RsaPrivateKey::from_pkcs8_der(der.secret_pkcs8_der()).map_err(Into::into) + } + #[cfg(all(feature = "pkcs8", feature = "pkcs1"))] + PrivateKeyDer::Pkcs1(der) => { + use pkcs1::DecodeRsaPrivateKey; + RsaPrivateKey::from_pkcs1_der(der.secret_pkcs1_der()).map_err(Into::into) + } + PrivateKeyDer::Sec1(_) => Err(RsaKeyError::Sec1NotSupported), + _ => Err(RsaKeyError::NotSupported), }; - pkey.map(Self).map_err(rustls::Error::General) + pkey.map(Self).map_err(Into::into) } } @@ -46,7 +100,7 @@ impl SigningKey for RsaSigningKey { .and_then(|&scheme| { macro_rules! signer { ($key:ty) => {{ - Some(Box::new(super::GenericRandomizedSigner { + Some(Box::new(super::rand::GenericRandomizedSigner { _marker: Default::default(), key: Arc::new(<$key>::new(self.0.clone())), scheme, @@ -55,17 +109,23 @@ impl SigningKey for RsaSigningKey { } match scheme { - SignatureScheme::RSA_PSS_SHA512 => signer! {rsa::pss::SigningKey::}, - SignatureScheme::RSA_PSS_SHA384 => signer! {rsa::pss::SigningKey::}, - SignatureScheme::RSA_PSS_SHA256 => signer! {rsa::pss::SigningKey::}, + #[cfg(all(feature = "rsa-pss", feature = "hash-sha512"))] + SignatureScheme::RSA_PSS_SHA512 => signer! {::rsa::pss::SigningKey::}, + #[cfg(all(feature = "rsa-pss", feature = "hash-sha384"))] + SignatureScheme::RSA_PSS_SHA384 => signer! {::rsa::pss::SigningKey::}, + #[cfg(all(feature = "rsa-pss", feature = "hash-sha256"))] + SignatureScheme::RSA_PSS_SHA256 => signer! {::rsa::pss::SigningKey::}, + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha512"))] SignatureScheme::RSA_PKCS1_SHA512 => { - signer! {rsa::pkcs1v15::SigningKey::} + signer! {::rsa::pkcs1v15::SigningKey::} } + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha384"))] SignatureScheme::RSA_PKCS1_SHA384 => { - signer! {rsa::pkcs1v15::SigningKey::} + signer! {::rsa::pkcs1v15::SigningKey::} } + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha256"))] SignatureScheme::RSA_PKCS1_SHA256 => { - signer! {rsa::pkcs1v15::SigningKey::} + signer! {::rsa::pkcs1v15::SigningKey::} } _ => None, } diff --git a/src/ticketer.rs b/src/ticketer.rs new file mode 100644 index 0000000..ce4148e --- /dev/null +++ b/src/ticketer.rs @@ -0,0 +1,164 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; +#[cfg(feature = "alloc")] +use alloc::sync::Arc; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use core::fmt::{Debug, Formatter}; +use core::sync::atomic::{AtomicUsize, Ordering}; +use core::{fmt, time}; + +use aead::{AeadInOut, KeyInit}; +use elliptic_curve::subtle::ConstantTimeEq; +use rand_core::{OsRng, TryRngCore}; +use rustls::crypto::GetRandomFailed; +use rustls::server::ProducesTickets; +use rustls::{Error, ticketer::TicketRotator}; + +#[cfg(feature = "chacha20poly1305")] +use chacha20poly1305::ChaCha20Poly1305; + +fn try_split_at(data: &[u8], at: usize) -> Option<(&[u8], &[u8])> { + if data.len() < at { + None + } else { + Some(data.split_at(at)) + } +} + +/// A concrete, safe ticket creation mechanism. +#[non_exhaustive] +pub struct Ticketer {} + +impl Ticketer { + #[allow(clippy::new_ret_no_self, clippy::missing_errors_doc)] + pub fn new() -> Result, Error> { + Ok(Arc::new(TicketRotator::new( + #[allow(clippy::cast_possible_truncation)] + { + time::Duration::from_secs(6 * 60 * 60).as_secs() as u32 + }, + || Ok(Box::new(AeadTicketProducer::new()?)), + )?)) + } +} + +struct AeadTicketProducer { + key: ChaCha20Poly1305, + key_name: [u8; 16], + maximum_ciphertext_len: AtomicUsize, +} + +impl AeadTicketProducer { + fn new() -> Result { + let mut key_bytes = [0u8; 32]; + OsRng + .try_fill_bytes(&mut key_bytes) + .map_err(|_| GetRandomFailed)?; + + let key = ChaCha20Poly1305::new_from_slice(&key_bytes).map_err(|_| GetRandomFailed)?; + + let mut key_name = [0u8; 16]; + OsRng + .try_fill_bytes(&mut key_name) + .map_err(|_| GetRandomFailed)?; + + Ok(Self { + key, + key_name, + maximum_ciphertext_len: AtomicUsize::new(0), + }) + } +} + +impl ProducesTickets for AeadTicketProducer { + fn enabled(&self) -> bool { + true + } + + fn lifetime(&self) -> u32 { + // this is not used, as this ticketer is only used via a `TicketRotator` + // that is responsible for defining and managing the lifetime of tickets. + 0 + } + + /// Encrypt `message` and return the ciphertext. + fn encrypt(&self, message: &[u8]) -> Option> { + // Random nonce, because a counter is a privacy leak. + let mut nonce_buf = [0u8; 12]; + OsRng.try_fill_bytes(&mut nonce_buf).ok()?; + let nonce = nonce_buf.into(); + + // ciphertext structure is: + // key_name: [u8; 16] + // nonce: [u8; 12] + // message: [u8, _] + // tag: [u8; 16] + + let mut ciphertext = + Vec::with_capacity(self.key_name.len() + nonce_buf.len() + message.len() + 16); + ciphertext.extend(self.key_name); + ciphertext.extend(nonce_buf); + ciphertext.extend(message); + let tag = self + .key + .encrypt_inout_detached( + &nonce, + &self.key_name, + (&mut ciphertext[self.key_name.len() + nonce_buf.len()..]).into(), + ) + .ok()?; + ciphertext.extend(tag); + + self.maximum_ciphertext_len + .fetch_max(ciphertext.len(), Ordering::SeqCst); + Some(ciphertext) + } + + /// Decrypt `ciphertext` and recover the original message. + fn decrypt(&self, ciphertext: &[u8]) -> Option> { + if ciphertext.len() > self.maximum_ciphertext_len.load(Ordering::SeqCst) { + return None; + } + + let (alleged_key_name, ciphertext) = try_split_at(ciphertext, self.key_name.len())?; + + let (nonce_bytes, ciphertext) = try_split_at(ciphertext, 12)?; + + // checking the key_name is the expected one, *and* then putting it into the + // additionally authenticated data is duplicative. this check quickly rejects + // tickets for a different ticketer (see `TicketRotator`), while including it + // in the AAD ensures it is authenticated independent of that check and that + // any attempted attack on the integrity such as [^1] must happen for each + // `key_label`, not over a population of potential keys. this approach + // is overall similar to [^2]. + // + // [^1]: https://eprint.iacr.org/2020/1491.pdf + // [^2]: "Authenticated Encryption with Key Identification", fig 6 + // + if ConstantTimeEq::ct_ne(&self.key_name[..], alleged_key_name).into() { + return None; + } + + let nonce = nonce_bytes.try_into().ok()?; + + let mut out = Vec::from(ciphertext); + let tag_vec = out.split_off(out.len() - 16); + let tag = tag_vec.try_into().ok()?; + + self.key + .decrypt_inout_detached(&nonce, alleged_key_name, (&mut out[..]).into(), &tag) + .ok()?; + let plain_len = out.len(); + out.truncate(plain_len); + + Some(out) + } +} + +impl Debug for AeadTicketProducer { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + // Note: we deliberately omit the key from the debug output. + f.debug_struct("AeadTicketer").finish() + } +} diff --git a/src/tls12.rs b/src/tls12.rs new file mode 100644 index 0000000..3864c43 --- /dev/null +++ b/src/tls12.rs @@ -0,0 +1,3 @@ +#[cfg(feature = "aead")] +pub mod aead; +pub mod suites; diff --git a/src/tls12/aead.rs b/src/tls12/aead.rs new file mode 100644 index 0000000..8be18e7 --- /dev/null +++ b/src/tls12/aead.rs @@ -0,0 +1,11 @@ +#[cfg(feature = "chacha20poly1305")] +pub mod chacha20; + +#[cfg(feature = "gcm")] +pub mod gcm; + +#[cfg(feature = "ccm")] +pub mod ccm; + +#[cfg(any(feature = "aes-gcm", feature = "aes-ccm"))] +pub(crate) mod explicit_nonce; diff --git a/src/tls12/aead/ccm.rs b/src/tls12/aead/ccm.rs new file mode 100644 index 0000000..e3fc468 --- /dev/null +++ b/src/tls12/aead/ccm.rs @@ -0,0 +1,13 @@ +use super::explicit_nonce::Tls12AeadAlgorithmWithExplicitNonce; + +macro_rules! impl_ccm { + ($name:ident, $type:ty) => { + pub const $name: &Tls12AeadAlgorithmWithExplicitNonce<$type> = + &Tls12AeadAlgorithmWithExplicitNonce::DEFAULT; + }; +} + +impl_ccm!(AES_128_CCM, crate::aead::aes::Aes128Ccm); +impl_ccm!(AES_256_CCM, crate::aead::aes::Aes256Ccm); +impl_ccm!(AES_128_CCM_8, crate::aead::aes::Aes128Ccm8); +impl_ccm!(AES_256_CCM_8, crate::aead::aes::Aes256Ccm8); diff --git a/src/tls12/aead/chacha20.rs b/src/tls12/aead/chacha20.rs new file mode 100644 index 0000000..0d8764b --- /dev/null +++ b/src/tls12/aead/chacha20.rs @@ -0,0 +1,107 @@ +use aead::AeadInOut; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; + +use ::chacha20poly1305::KeyInit; +use rustls::{ + ConnectionTrafficSecrets, + crypto::cipher::{ + self, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, KeyBlockShape, + MessageDecrypter, MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, + PrefixedPayload, Tls12AeadAlgorithm, UnsupportedOperationError, make_tls12_aad, + }, +}; + +pub const CHACHAPOLY1305_OVERHEAD: usize = 16; +pub struct ChaCha20Poly1305; + +pub struct Tls12AeadAlgorithmChacha20Poly1305Adapter(chacha20poly1305::ChaCha20Poly1305, Iv); + +impl Tls12AeadAlgorithm for ChaCha20Poly1305 { + fn encrypter(&self, key: AeadKey, iv: &[u8], _: &[u8]) -> Box { + Box::new(Tls12AeadAlgorithmChacha20Poly1305Adapter( + ::chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) + .expect("key should be valid"), + Iv::copy(iv), + )) + } + + fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box { + Box::new(Tls12AeadAlgorithmChacha20Poly1305Adapter( + chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) + .expect("key should be valid"), + Iv::copy(iv), + )) + } + + fn key_block_shape(&self) -> KeyBlockShape { + KeyBlockShape { + enc_key_len: 32, + fixed_iv_len: 12, + explicit_nonce_len: 0, + } + } + + fn extract_keys( + &self, + key: AeadKey, + iv: &[u8], + _explicit: &[u8], + ) -> Result { + Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { + key, + iv: Iv::copy(iv), + }) + } +} + +impl MessageEncrypter for Tls12AeadAlgorithmChacha20Poly1305Adapter { + fn encrypt( + &mut self, + m: OutboundPlainMessage<'_>, + seq: u64, + ) -> Result { + let mut payload = + PrefixedPayload::with_capacity(self.encrypted_payload_len(m.payload.len())); + + payload.extend_from_chunks(&m.payload); + + self.0 + .encrypt_in_place( + &cipher::Nonce::new(&self.1, seq).0.into(), + &make_tls12_aad(seq, m.typ, m.version, m.payload.len()), + &mut EncryptBufferAdapter::PrefixedPayload(&mut payload), + ) + .map(|_| OutboundOpaqueMessage::new(m.typ, m.version, payload)) + .map_err(|_| rustls::Error::EncryptError) + } + + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + CHACHAPOLY1305_OVERHEAD + } +} + +impl MessageDecrypter for Tls12AeadAlgorithmChacha20Poly1305Adapter { + fn decrypt<'a>( + &mut self, + mut m: InboundOpaqueMessage<'a>, + seq: u64, + ) -> Result, rustls::Error> { + self.0 + .decrypt_in_place( + &cipher::Nonce::new(&self.1, seq).0.into(), + &make_tls12_aad( + seq, + m.typ, + m.version, + m.payload.len() - CHACHAPOLY1305_OVERHEAD, + ), + &mut DecryptBufferAdapter::BorrowedPayload(&mut m.payload), + ) + .map_err(|_| rustls::Error::DecryptError)?; + + Ok(m.into_plain_message()) + } +} diff --git a/src/tls12/aead/explicit_nonce.rs b/src/tls12/aead/explicit_nonce.rs new file mode 100644 index 0000000..faa32b3 --- /dev/null +++ b/src/tls12/aead/explicit_nonce.rs @@ -0,0 +1,187 @@ +use core::marker::PhantomData; + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use ::aead::{AeadInOut, Nonce, Tag}; +use ::crypto_common::KeyInit; +use rustls::ConnectionTrafficSecrets; +use rustls::crypto::cipher::{ + self, AeadKey, InboundOpaqueMessage, InboundPlainMessage, KeyBlockShape, MessageDecrypter, + MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, + Tls12AeadAlgorithm, make_tls12_aad, +}; +use typenum::Unsigned; + +/// Length of the explicit nonce in TLS 1.2 AEAD. +const EXPLICIT_NONCE_LEN: usize = 8; + +/// TLS 1.2 AEAD Encrypter. +/// Wraps an AEAD cipher and the initialization vector for encryption. +pub struct Tls12AeadEncrypterWithExplicitNonce { + /// The underlying AEAD cipher. + pub aead: A, + /// The initialization vector (12 bytes). + pub iv: [u8; 12], +} + +impl MessageEncrypter for Tls12AeadEncrypterWithExplicitNonce +where + A: AeadInOut + Send + Sync, +{ + fn encrypt( + &mut self, + m: OutboundPlainMessage<'_>, + seq: u64, + ) -> Result { + let total_len = self.encrypted_payload_len(m.payload.len()); + let mut payload = PrefixedPayload::with_capacity(total_len); + let aad = make_tls12_aad(seq, m.typ, m.version, m.payload.len()); + + let nonce = cipher::Nonce::new(&self.iv.into(), seq).0; + payload.extend_from_slice(&nonce.as_ref()[4..]); // explicit nonce + payload.extend_from_chunks(&m.payload); + + let tag = self + .aead + .encrypt_inout_detached( + &Nonce::::try_from(&nonce[..]).map_err(|_| rustls::Error::EncryptError)?, + &aad, + (&mut payload.as_mut()[EXPLICIT_NONCE_LEN..]).into(), + ) + .map_err(|_| rustls::Error::EncryptError)?; + payload.extend(&tag); + Ok(OutboundOpaqueMessage::new(m.typ, m.version, payload)) + } + + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + EXPLICIT_NONCE_LEN + A::TagSize::USIZE + } +} + +pub struct Tls12AeadDecrypterWithExplicitNonce { + /// The underlying AEAD cipher. + pub aead: A, + /// The decryption initialization vector (4 bytes). + pub dec_iv: [u8; 4], +} + +impl MessageDecrypter for Tls12AeadDecrypterWithExplicitNonce +where + A: AeadInOut + Send + Sync, +{ + fn decrypt<'a>( + &mut self, + mut m: InboundOpaqueMessage<'a>, + seq: u64, + ) -> Result, rustls::Error> { + macro_rules! nonce_tag_len { + () => {{ EXPLICIT_NONCE_LEN + A::TagSize::USIZE }}; + } + + // The payload must be large enough to hold the explicit nonce and the AEAD tag. + if m.payload.len() < nonce_tag_len!() { + return Err(rustls::Error::DecryptError); + } + // Calculate the length of the plaintext. + let plaintext_len = m.payload.len() - nonce_tag_len!(); + + // Split the payload into the ciphertext and tag. + if let Some((nonce, ciphertext_and_tag)) = + m.payload.split_at_mut_checked(EXPLICIT_NONCE_LEN) + && let Some((ciphertext, tag)) = ciphertext_and_tag.split_at_mut_checked(plaintext_len) + { + // Decrypt the ciphertext in place. + self.aead + .decrypt_inout_detached( + &Nonce::::from_iter([self.dec_iv.as_ref(), nonce].concat()), + &make_tls12_aad(seq, m.typ, m.version, plaintext_len), + ciphertext.into(), + &Tag::::try_from(&tag[..]).map_err(|_| rustls::Error::DecryptError)?, + ) + .map_err(|_| rustls::Error::DecryptError)?; + + // The plaintext is now at an offset in the payload buffer. We need to move it + // to the beginning of the buffer to conform to the `InboundPlainMessage` requirements. + m.payload + .copy_within(EXPLICIT_NONCE_LEN..EXPLICIT_NONCE_LEN + plaintext_len, 0); + m.payload.truncate(plaintext_len); + + Ok(m.into_plain_message()) + } else { + Err(rustls::Error::DecryptError) + } + } +} + +pub trait Extractor { + fn extract( + _key: AeadKey, + _iv: &[u8], + _explicit: &[u8], + ) -> Result { + Err(cipher::UnsupportedOperationError) + } +} + +impl Extractor for () {} + +#[derive(Default)] +pub struct Tls12AeadAlgorithmWithExplicitNonce { + _aead: PhantomData, + _extractor: PhantomData, +} + +impl Tls12AeadAlgorithmWithExplicitNonce { + pub const DEFAULT: Self = Self { + _aead: PhantomData, + _extractor: PhantomData, + }; +} + +impl Tls12AeadAlgorithm for Tls12AeadAlgorithmWithExplicitNonce +where + A: KeyInit + AeadInOut + Send + Sync + 'static, + E: Extractor + Send + Sync + 'static, +{ + fn encrypter( + &self, + key: AeadKey, + write_iv: &[u8], + explicit: &[u8], + ) -> Box { + Box::new(Tls12AeadEncrypterWithExplicitNonce:: { + aead: A::new_from_slice(key.as_ref()).expect("key should be valid"), + iv: { + let mut iv: [u8; 12] = [0; 12]; + iv[..4].copy_from_slice(write_iv); + iv[4..].copy_from_slice(explicit); + iv + }, + }) + } + + fn decrypter(&self, dec_key: AeadKey, dec_iv: &[u8]) -> Box { + Box::new(Tls12AeadDecrypterWithExplicitNonce:: { + aead: A::new_from_slice(dec_key.as_ref()).expect("key should be valid"), + dec_iv: dec_iv.try_into().expect("iv should be valid"), + }) + } + + fn key_block_shape(&self) -> KeyBlockShape { + KeyBlockShape { + enc_key_len: A::key_size(), + fixed_iv_len: 4, + explicit_nonce_len: EXPLICIT_NONCE_LEN, + } + } + + fn extract_keys( + &self, + key: AeadKey, + iv: &[u8], + explicit: &[u8], + ) -> Result { + E::extract(key, iv, explicit) + } +} diff --git a/src/tls12/aead/gcm.rs b/src/tls12/aead/gcm.rs new file mode 100644 index 0000000..0726214 --- /dev/null +++ b/src/tls12/aead/gcm.rs @@ -0,0 +1,38 @@ +use rustls::ConnectionTrafficSecrets; +use rustls::crypto::cipher::{self, AeadKey, Iv}; + +use super::explicit_nonce::{Extractor, Tls12AeadAlgorithmWithExplicitNonce}; + +macro_rules! tls12_gcm_aead { + ($const_name:ident, $extractor_name:ident, $variant:ident, $type:ty) => { + pub struct $extractor_name; + impl Extractor for $extractor_name { + fn extract( + key: AeadKey, + iv: &[u8], + _explicit: &[u8], + ) -> Result { + Ok(ConnectionTrafficSecrets::$variant { + key, + iv: Iv::copy(iv), + }) + } + } + + pub const $const_name: &Tls12AeadAlgorithmWithExplicitNonce<$type, $extractor_name> = + &Tls12AeadAlgorithmWithExplicitNonce::DEFAULT; + }; +} + +tls12_gcm_aead!( + AES_128_GCM, + Aes128GcmExtractor, + Aes128Gcm, + crate::aead::aes::Aes128Gcm +); +tls12_gcm_aead!( + AES_256_GCM, + Aes256GcmExtractor, + Aes256Gcm, + crate::aead::aes::Aes256Gcm +); diff --git a/src/tls12/suites.rs b/src/tls12/suites.rs new file mode 100644 index 0000000..c755275 --- /dev/null +++ b/src/tls12/suites.rs @@ -0,0 +1,18 @@ +use crate::feature_slice; +use crate::misc::const_concat_slices; +use rustls::SupportedCipherSuite; + +pub const TLS12_SUITES: &[SupportedCipherSuite] = const_concat_slices!( + SupportedCipherSuite, + feature_slice!([feature = "ecdsa"], ecdsa::TLS_ECDHE_ECDSA_SUITES), + feature_slice!( + [any(feature = "rsa-pss", feature = "rsa-pkcs1")], + rsa::TLS_ECDHE_RSA_SUITES + ) +); + +#[cfg(feature = "ecdsa")] +pub mod ecdsa; +#[cfg(any(feature = "rsa-pss", feature = "rsa-pkcs1"))] +pub mod rsa; +pub mod schemes; diff --git a/src/tls12/suites/ecdsa.rs b/src/tls12/suites/ecdsa.rs new file mode 100644 index 0000000..82a68a1 --- /dev/null +++ b/src/tls12/suites/ecdsa.rs @@ -0,0 +1,110 @@ +use rustls::SupportedCipherSuite; + +#[cfg(feature = "aead")] +use crate::tls12::suites::schemes::TLS12_ECDSA_SCHEMES; +#[cfg(feature = "aead")] +use crate::{hash, hmac, tls12_ecdhe_cipher_suite}; +#[cfg(feature = "aead")] +use rustls::crypto::{CipherSuiteCommon, KeyExchangeAlgorithm, tls12::PrfUsingHmac}; +#[cfg(feature = "aead")] +use rustls::{CipherSuite, Tls12CipherSuite}; + +#[cfg(feature = "aes-gcm")] +use crate::tls12::aead::gcm::{AES_128_GCM, AES_256_GCM}; + +#[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] +use crate::tls12::aead::ccm::{AES_128_CCM, AES_128_CCM_8, AES_256_CCM, AES_256_CCM_8}; + +#[cfg(all(feature = "chacha20poly1305", feature = "hash-sha256"))] +use crate::tls12::aead::chacha20::ChaCha20Poly1305; + +#[cfg(all(feature = "aes-gcm", feature = "hash-sha256"))] +tls12_ecdhe_cipher_suite!( + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + hash::SHA256, + PrfUsingHmac(hmac::SHA256), + TLS12_ECDSA_SCHEMES, + AES_128_GCM +); + +#[cfg(all(feature = "aes-gcm", feature = "hash-sha384"))] +tls12_ecdhe_cipher_suite!( + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + hash::SHA384, + PrfUsingHmac(hmac::SHA384), + TLS12_ECDSA_SCHEMES, + AES_256_GCM +); + +// https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_128_CCM/ +#[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] +tls12_ecdhe_cipher_suite!( + TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + hash::SHA256, + PrfUsingHmac(hmac::SHA256), + TLS12_ECDSA_SCHEMES, + AES_128_CCM +); + +// https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_256_CCM/ +#[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] +tls12_ecdhe_cipher_suite!( + TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + hash::SHA256, + PrfUsingHmac(hmac::SHA256), + TLS12_ECDSA_SCHEMES, + AES_256_CCM +); + +// https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8/ +#[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] +tls12_ecdhe_cipher_suite!( + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + hash::SHA256, + PrfUsingHmac(hmac::SHA256), + TLS12_ECDSA_SCHEMES, + AES_128_CCM_8 +); + +// https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8/ +#[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] +tls12_ecdhe_cipher_suite!( + TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + hash::SHA256, + PrfUsingHmac(hmac::SHA256), + TLS12_ECDSA_SCHEMES, + AES_256_CCM_8 +); + +#[cfg(all(feature = "chacha20poly1305", feature = "hash-sha256"))] +tls12_ecdhe_cipher_suite!( + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + hash::SHA256, + PrfUsingHmac(hmac::SHA256), + TLS12_ECDSA_SCHEMES, + &ChaCha20Poly1305 +); + +pub const TLS_ECDHE_ECDSA_SUITES: &[SupportedCipherSuite] = &[ + #[cfg(all(feature = "aes-gcm", feature = "hash-sha256"))] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), + #[cfg(all(feature = "aes-gcm", feature = "hash-sha384"))] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), + #[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_CCM), + #[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_CCM), + #[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8), + #[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8), + #[cfg(all(feature = "chacha20poly1305", feature = "hash-sha256"))] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), +]; diff --git a/src/tls12/suites/rsa.rs b/src/tls12/suites/rsa.rs new file mode 100644 index 0000000..a76b580 --- /dev/null +++ b/src/tls12/suites/rsa.rs @@ -0,0 +1,55 @@ +use rustls::SupportedCipherSuite; + +#[cfg(feature = "aead")] +use crate::tls12::suites::schemes::TLS12_RSA_SCHEMES; +#[cfg(feature = "aead")] +use crate::{hash, hmac, tls12_ecdhe_cipher_suite}; +#[cfg(feature = "aead")] +use rustls::crypto::{CipherSuiteCommon, KeyExchangeAlgorithm, tls12::PrfUsingHmac}; +#[cfg(feature = "aead")] +use rustls::{CipherSuite, Tls12CipherSuite}; + +#[cfg(feature = "gcm")] +use crate::tls12::aead::gcm::{AES_128_GCM, AES_256_GCM}; + +#[cfg(feature = "chacha20poly1305")] +use crate::tls12::aead::chacha20::ChaCha20Poly1305; + +#[cfg(all(feature = "aes-gcm", feature = "hash-sha256"))] +tls12_ecdhe_cipher_suite!( + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + hash::SHA256, + PrfUsingHmac(hmac::SHA256), + TLS12_RSA_SCHEMES, + AES_128_GCM +); + +#[cfg(all(feature = "aes-gcm", feature = "hash-sha384"))] +tls12_ecdhe_cipher_suite!( + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + hash::SHA384, + PrfUsingHmac(hmac::SHA384), + TLS12_RSA_SCHEMES, + AES_256_GCM +); + +#[cfg(all(feature = "chacha20poly1305", feature = "hash-sha256"))] +tls12_ecdhe_cipher_suite!( + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + hash::SHA256, + PrfUsingHmac(hmac::SHA256), + TLS12_RSA_SCHEMES, + &ChaCha20Poly1305 +); + +pub const TLS_ECDHE_RSA_SUITES: &[SupportedCipherSuite] = &[ + #[cfg(all(feature = "aes-gcm", feature = "hash-sha256"))] + SupportedCipherSuite::Tls12(&TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), + #[cfg(all(feature = "aes-gcm", feature = "hash-sha384"))] + SupportedCipherSuite::Tls12(&TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), + #[cfg(all(feature = "chacha20poly1305", feature = "hash-sha256"))] + SupportedCipherSuite::Tls12(&TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), +]; diff --git a/src/tls12/suites/schemes.rs b/src/tls12/suites/schemes.rs new file mode 100644 index 0000000..36a12aa --- /dev/null +++ b/src/tls12/suites/schemes.rs @@ -0,0 +1,32 @@ +#[cfg(any(feature = "ecdsa", feature = "rsa"))] +use rustls::SignatureScheme; + +#[cfg(feature = "ecdsa")] +pub const TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[ + #[cfg(all(feature = "ecdsa-p256", feature = "hash-sha256"))] + SignatureScheme::ECDSA_NISTP256_SHA256, + #[cfg(all(feature = "ecdsa-p384", feature = "hash-sha384"))] + SignatureScheme::ECDSA_NISTP384_SHA384, + #[cfg(all(feature = "ecdsa-p521", feature = "hash-sha512"))] + SignatureScheme::ECDSA_NISTP521_SHA512, + #[cfg(feature = "eddsa-ed25519")] + SignatureScheme::ED25519, + #[cfg(feature = "eddsa-ed448")] + SignatureScheme::ED448, +]; + +#[cfg(feature = "rsa")] +pub const TLS12_RSA_SCHEMES: &[SignatureScheme] = &[ + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha256"))] + SignatureScheme::RSA_PKCS1_SHA256, + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha384"))] + SignatureScheme::RSA_PKCS1_SHA384, + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha512"))] + SignatureScheme::RSA_PKCS1_SHA512, + #[cfg(all(feature = "rsa-pss", feature = "hash-sha256"))] + SignatureScheme::RSA_PSS_SHA256, + #[cfg(all(feature = "rsa-pss", feature = "hash-sha384"))] + SignatureScheme::RSA_PSS_SHA384, + #[cfg(all(feature = "rsa-pss", feature = "hash-sha512"))] + SignatureScheme::RSA_PSS_SHA512, +]; diff --git a/src/tls13.rs b/src/tls13.rs new file mode 100644 index 0000000..3864c43 --- /dev/null +++ b/src/tls13.rs @@ -0,0 +1,3 @@ +#[cfg(feature = "aead")] +pub mod aead; +pub mod suites; diff --git a/src/tls13/aead.rs b/src/tls13/aead.rs new file mode 100644 index 0000000..3de7f60 --- /dev/null +++ b/src/tls13/aead.rs @@ -0,0 +1,12 @@ +#[cfg(feature = "chacha20poly1305")] +pub mod chacha20; +#[cfg(feature = "chacha20poly1305")] +pub use chacha20::CHACHA20_POLY1305; + +#[cfg(feature = "gcm")] +pub mod gcm; + +#[cfg(feature = "ccm")] +pub mod ccm; + +pub(crate) mod common; diff --git a/src/tls13/aead/ccm.rs b/src/tls13/aead/ccm.rs new file mode 100644 index 0000000..a79e978 --- /dev/null +++ b/src/tls13/aead/ccm.rs @@ -0,0 +1,6 @@ +use super::common::Tls13AeadAlgorithmCommon; + +pub const AES_128_CCM: &Tls13AeadAlgorithmCommon = + &Tls13AeadAlgorithmCommon::DEFAULT; +pub const AES_128_CCM_8: &Tls13AeadAlgorithmCommon = + &Tls13AeadAlgorithmCommon::DEFAULT; diff --git a/src/tls13/aead/chacha20.rs b/src/tls13/aead/chacha20.rs new file mode 100644 index 0000000..f796480 --- /dev/null +++ b/src/tls13/aead/chacha20.rs @@ -0,0 +1,20 @@ +use rustls::ConnectionTrafficSecrets; +use rustls::crypto::cipher::{AeadKey, Iv, UnsupportedOperationError}; + +use crate::tls13::aead::common::{Extractor, Tls13AeadAlgorithmCommon}; + +pub struct ChaCha20Poly1305Extractor; + +impl Extractor for ChaCha20Poly1305Extractor { + fn extract( + key: AeadKey, + iv: Iv, + ) -> Result { + Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }) + } +} + +pub const CHACHA20_POLY1305: &Tls13AeadAlgorithmCommon< + chacha20poly1305::ChaCha20Poly1305, + ChaCha20Poly1305Extractor, +> = &Tls13AeadAlgorithmCommon::DEFAULT; diff --git a/src/tls13/aead/common.rs b/src/tls13/aead/common.rs new file mode 100644 index 0000000..04befec --- /dev/null +++ b/src/tls13/aead/common.rs @@ -0,0 +1,142 @@ +use core::marker::PhantomData; + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use aead::{AeadInOut, KeyInit, Nonce}; +use rustls::{ + ConnectionTrafficSecrets, ContentType, ProtocolVersion, + crypto::cipher::{ + self, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, + MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, + Tls13AeadAlgorithm, make_tls13_aad, + }, +}; +use typenum::Unsigned; + +use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; + +pub struct Tls13AeadEncrypter { + aead: A, + iv: Iv, +} + +impl MessageEncrypter for Tls13AeadEncrypter +where + A: AeadInOut + Send + Sync, +{ + fn encrypt( + &mut self, + m: OutboundPlainMessage<'_>, + seq: u64, + ) -> Result { + let total_len = self.encrypted_payload_len(m.payload.len()); + let mut payload = PrefixedPayload::with_capacity(total_len); + + payload.extend_from_chunks(&m.payload); + payload.extend_from_slice(&m.typ.to_array()); + + self.aead + .encrypt_in_place( + &Nonce::::try_from(&cipher::Nonce::new(&self.iv, seq).0[..]) + .map_err(|_| rustls::Error::EncryptError)?, + &make_tls13_aad(total_len), + &mut EncryptBufferAdapter::PrefixedPayload(&mut payload), + ) + .map_err(|_| rustls::Error::EncryptError) + .map(|_| { + OutboundOpaqueMessage::new( + ContentType::ApplicationData, + ProtocolVersion::TLSv1_2, + payload, + ) + }) + } + + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + 1 + A::TagSize::USIZE + } +} + +pub struct Tls13AeadDecrypter { + aead: A, + iv: Iv, +} + +impl MessageDecrypter for Tls13AeadDecrypter +where + A: AeadInOut + Send + Sync, +{ + fn decrypt<'a>( + &mut self, + mut m: InboundOpaqueMessage<'a>, + seq: u64, + ) -> Result, rustls::Error> { + self.aead + .decrypt_in_place( + &Nonce::::try_from(&cipher::Nonce::new(&self.iv, seq).0[..]) + .map_err(|_| rustls::Error::DecryptError)?, + &make_tls13_aad(m.payload.len()), + &mut DecryptBufferAdapter::BorrowedPayload(&mut m.payload), + ) + .map_err(|_| rustls::Error::DecryptError)?; + + m.into_tls13_unpadded_message() + } +} + +pub trait Extractor { + fn extract( + _key: AeadKey, + _iv: Iv, + ) -> Result { + Err(cipher::UnsupportedOperationError) + } +} + +impl Extractor for () {} + +#[derive(Default)] +pub struct Tls13AeadAlgorithmCommon { + _aead: PhantomData, + _extractor: PhantomData, +} + +impl Tls13AeadAlgorithmCommon { + pub const DEFAULT: Self = Self { + _aead: PhantomData, + _extractor: PhantomData, + }; +} + +impl Tls13AeadAlgorithm for Tls13AeadAlgorithmCommon +where + A: KeyInit + AeadInOut + Send + Sync + 'static, + E: Extractor + Send + Sync + 'static, +{ + fn encrypter(&self, key: AeadKey, iv: Iv) -> Box { + Box::new(Tls13AeadEncrypter:: { + aead: A::new_from_slice(key.as_ref()).expect("Invalid key length for AEAD algorithm"), + iv, + }) + } + + fn decrypter(&self, key: AeadKey, iv: Iv) -> Box { + Box::new(Tls13AeadDecrypter:: { + aead: A::new_from_slice(key.as_ref()).expect("Invalid key length for AEAD algorithm"), + iv, + }) + } + + fn key_len(&self) -> usize { + A::key_size() + } + + fn extract_keys( + &self, + key: AeadKey, + iv: Iv, + ) -> Result { + E::extract(key, iv) + } +} diff --git a/src/tls13/aead/gcm.rs b/src/tls13/aead/gcm.rs new file mode 100644 index 0000000..0d69674 --- /dev/null +++ b/src/tls13/aead/gcm.rs @@ -0,0 +1,36 @@ +use crate::tls13::aead::common::{Extractor, Tls13AeadAlgorithmCommon}; +use rustls::{ + ConnectionTrafficSecrets, + crypto::cipher::{self, AeadKey, Iv}, +}; + +macro_rules! impl_gcm_aead { + ($const_name:ident, $extractor_name:ident, $variant:ident, $type:ty) => { + pub struct $extractor_name; + + impl Extractor for $extractor_name { + fn extract( + key: AeadKey, + iv: Iv, + ) -> Result { + Ok(ConnectionTrafficSecrets::$variant { key, iv }) + } + } + + pub const $const_name: &Tls13AeadAlgorithmCommon<$type, $extractor_name> = + &Tls13AeadAlgorithmCommon::DEFAULT; + }; +} + +impl_gcm_aead!( + AES_128_GCM, + Aes128GcmExtractor, + Aes128Gcm, + crate::aead::aes::Aes128Gcm +); +impl_gcm_aead!( + AES_256_GCM, + Aes256GcmExtractor, + Aes256Gcm, + crate::aead::aes::Aes256Gcm +); diff --git a/src/tls13/suites.rs b/src/tls13/suites.rs new file mode 100644 index 0000000..b8bcfb6 --- /dev/null +++ b/src/tls13/suites.rs @@ -0,0 +1,21 @@ +use crate::const_concat_slices; +use crate::feature_slice; +use rustls::SupportedCipherSuite; + +pub const TLS13_SUITES: &[SupportedCipherSuite] = const_concat_slices!( + SupportedCipherSuite, + feature_slice!([feature = "aes"], aes::TLS13_AES_SUITES), + feature_slice!( + [feature = "chacha20poly1305"], + &[ + #[cfg(feature = "hash-sha256")] + SupportedCipherSuite::Tls13(&chacha20::TLS13_CHACHA20_POLY1305_SHA256), + ] + ) +); + +#[cfg(feature = "aes")] +pub mod aes; + +#[cfg(feature = "chacha20poly1305")] +pub mod chacha20; diff --git a/src/tls13/suites/aes.rs b/src/tls13/suites/aes.rs new file mode 100644 index 0000000..7cdc763 --- /dev/null +++ b/src/tls13/suites/aes.rs @@ -0,0 +1,87 @@ +use crate::const_concat_slices; +use crate::feature_eval_expr; +use crate::feature_slice; +use crate::tls13_cipher_suite; +use crate::{hash, hmac}; +use rustls::crypto::{CipherSuiteCommon, tls13::HkdfUsingHmac}; +use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; + +#[cfg(all(feature = "ccm", feature = "hash-sha256", feature = "quic"))] +use crate::aead::aes::Aes128Ccm; +#[cfg(all(feature = "gcm", feature = "hash-sha256", feature = "quic"))] +use crate::aead::aes::Aes128Gcm; +#[cfg(all(feature = "gcm", feature = "hash-sha384", feature = "quic"))] +use crate::aead::aes::Aes256Gcm; +#[cfg(all(feature = "ccm", feature = "hash-sha256"))] +use crate::tls13::aead::ccm::{AES_128_CCM, AES_128_CCM_8}; +#[cfg(all(feature = "gcm", feature = "hash-sha256"))] +use crate::tls13::aead::gcm::AES_128_GCM; +#[cfg(all(feature = "gcm", feature = "hash-sha384"))] +use crate::tls13::aead::gcm::AES_256_GCM; + +#[cfg(all(feature = "gcm", feature = "hash-sha256"))] +tls13_cipher_suite!( + TLS13_AES_128_GCM_SHA256, + CipherSuite::TLS13_AES_128_GCM_SHA256, + hash::SHA256, + HkdfUsingHmac(hmac::SHA256), + AES_128_GCM, + feature_eval_expr!([feature = "quic"], Some(&crate::quic::QuicCrypto::::DEFAULT), else None) +); + +#[cfg(all(feature = "gcm", feature = "hash-sha384"))] +tls13_cipher_suite!( + TLS13_AES_256_GCM_SHA384, + CipherSuite::TLS13_AES_256_GCM_SHA384, + hash::SHA384, + HkdfUsingHmac(hmac::SHA384), + AES_256_GCM, + feature_eval_expr!([feature = "quic"], Some(&crate::quic::QuicCrypto::::DEFAULT), else None) +); + +#[cfg(all(feature = "ccm", feature = "hash-sha256"))] +tls13_cipher_suite!( + TLS13_AES_128_CCM_SHA256, + CipherSuite::TLS13_AES_128_CCM_SHA256, + hash::SHA256, + HkdfUsingHmac(hmac::SHA256), + AES_128_CCM, + feature_eval_expr!([feature = "quic"], Some(&crate::quic::QuicCrypto::::DEFAULT), else None) +); + +#[cfg(all(feature = "ccm", feature = "hash-sha256"))] +tls13_cipher_suite!( + TLS13_AES_128_CCM_8_SHA256, + CipherSuite::TLS13_AES_128_CCM_8_SHA256, + hash::SHA256, + HkdfUsingHmac(hmac::SHA256), + AES_128_CCM_8, + // The AEAD for that ciphersuite, AEAD_AES_128_CCM_8 [CCM], does not produce a large + // enough authentication tag for use with the header protection designs + // provided (see Section 5.4). All other ciphersuites defined in + // [TLS13] have a 16-byte authentication tag and produce an output 16 + // bytes larger than their input. + None +); + +pub const TLS13_AES_SUITES: &[SupportedCipherSuite] = const_concat_slices!( + SupportedCipherSuite, + feature_slice!( + [feature = "gcm"], + &[ + #[cfg(feature = "hash-sha256")] + SupportedCipherSuite::Tls13(&TLS13_AES_128_GCM_SHA256), + #[cfg(feature = "hash-sha384")] + SupportedCipherSuite::Tls13(&TLS13_AES_256_GCM_SHA384), + ] + ), + feature_slice!( + [feature = "ccm"], + &[ + #[cfg(feature = "hash-sha256")] + SupportedCipherSuite::Tls13(&TLS13_AES_128_CCM_SHA256), + #[cfg(feature = "hash-sha256")] + SupportedCipherSuite::Tls13(&TLS13_AES_128_CCM_8_SHA256), + ] + ) +); diff --git a/src/tls13/suites/chacha20.rs b/src/tls13/suites/chacha20.rs new file mode 100644 index 0000000..b86bdae --- /dev/null +++ b/src/tls13/suites/chacha20.rs @@ -0,0 +1,20 @@ +use crate::feature_eval_expr; +#[cfg(feature = "hash-sha256")] +use crate::tls13::aead::CHACHA20_POLY1305; +use crate::{hash, hmac, tls13_cipher_suite}; + +use rustls::crypto::{CipherSuiteCommon, tls13::HkdfUsingHmac}; +use rustls::{CipherSuite, Tls13CipherSuite}; + +#[cfg(feature = "quic")] +use chacha20poly1305::ChaCha20Poly1305; + +#[cfg(feature = "hash-sha256")] +tls13_cipher_suite!( + TLS13_CHACHA20_POLY1305_SHA256, + CipherSuite::TLS13_CHACHA20_POLY1305_SHA256, + hash::SHA256, + HkdfUsingHmac(hmac::SHA256), + CHACHA20_POLY1305, + feature_eval_expr!([feature = "quic"], Some(&crate::quic::QuicCrypto::::DEFAULT), else None) +); diff --git a/src/verify.rs b/src/verify.rs index 2043b64..f4f84e3 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -1,46 +1,214 @@ -use rustls::crypto::WebPkiSupportedAlgorithms; +use core::array::TryFromSliceError; + +use crate::const_concat_slices; +use crate::feature_slice; + +use pki_types::SignatureVerificationAlgorithm; use rustls::SignatureScheme; +use rustls::crypto::WebPkiSupportedAlgorithms; -use self::ecdsa::{ECDSA_P256_SHA256, ECDSA_P256_SHA384, ECDSA_P384_SHA256, ECDSA_P384_SHA384}; -use self::eddsa::ED25519; -use self::rsa::{ - RSA_PKCS1_SHA256, RSA_PKCS1_SHA384, RSA_PKCS1_SHA512, RSA_PSS_SHA256, RSA_PSS_SHA384, - RSA_PSS_SHA512, -}; +pub(crate) enum Error { + #[cfg(feature = "signature")] + Signature, + TryFromSlice, + #[cfg(feature = "der")] + Der, + #[cfg(feature = "pkcs1")] + Pkcs1, +} + +#[cfg(feature = "signature")] +impl From for Error { + fn from(_: signature::Error) -> Self { + Self::Signature + } +} + +#[cfg(feature = "der")] +impl From for Error { + fn from(_: der::Error) -> Self { + Self::Der + } +} -pub static ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { - all: &[ - ECDSA_P256_SHA256, - ECDSA_P256_SHA384, - ECDSA_P384_SHA256, - ECDSA_P384_SHA384, - ED25519, - RSA_PKCS1_SHA256, - RSA_PKCS1_SHA384, - RSA_PKCS1_SHA512, - RSA_PSS_SHA256, - RSA_PSS_SHA384, - RSA_PSS_SHA512, - ], - mapping: &[ - ( - SignatureScheme::ECDSA_NISTP384_SHA384, - &[ECDSA_P384_SHA384, ECDSA_P256_SHA384], - ), - ( - SignatureScheme::ECDSA_NISTP256_SHA256, - &[ECDSA_P256_SHA256, ECDSA_P384_SHA256], - ), - (SignatureScheme::ED25519, &[ED25519]), - (SignatureScheme::RSA_PKCS1_SHA256, &[RSA_PKCS1_SHA256]), - (SignatureScheme::RSA_PKCS1_SHA384, &[RSA_PKCS1_SHA384]), - (SignatureScheme::RSA_PKCS1_SHA512, &[RSA_PKCS1_SHA512]), - (SignatureScheme::RSA_PSS_SHA256, &[RSA_PSS_SHA256]), - (SignatureScheme::RSA_PSS_SHA384, &[RSA_PSS_SHA384]), - (SignatureScheme::RSA_PSS_SHA512, &[RSA_PSS_SHA512]), - ], +#[cfg(feature = "pkcs1")] +impl From for Error { + fn from(_: pkcs1::Error) -> Self { + Self::Pkcs1 + } +} + +impl From for Error { + fn from(_: TryFromSliceError) -> Self { + Self::TryFromSlice + } +} + +pub const ALL: &[&dyn SignatureVerificationAlgorithm] = const_concat_slices!( + &dyn SignatureVerificationAlgorithm, + feature_slice!( + [feature = "verify-ecdsa-nist"], + &[ + #[cfg(all(feature = "ecdsa-p256", feature = "hash-sha256"))] + ecdsa::nist::ECDSA_P256_SHA256, + #[cfg(all(feature = "ecdsa-p256", feature = "hash-sha384"))] + ecdsa::nist::ECDSA_P256_SHA384, + #[cfg(all(feature = "ecdsa-p256", feature = "hash-sha512"))] + ecdsa::nist::ECDSA_P256_SHA512, + #[cfg(all(feature = "ecdsa-p384", feature = "hash-sha256"))] + ecdsa::nist::ECDSA_P384_SHA256, + #[cfg(all(feature = "ecdsa-p384", feature = "hash-sha384"))] + ecdsa::nist::ECDSA_P384_SHA384, + #[cfg(all(feature = "ecdsa-p384", feature = "hash-sha512"))] + ecdsa::nist::ECDSA_P384_SHA512, + #[cfg(all(feature = "ecdsa-p521", feature = "hash-sha256"))] + ecdsa::nist::ECDSA_P521_SHA256, + #[cfg(all(feature = "ecdsa-p521", feature = "hash-sha384"))] + ecdsa::nist::ECDSA_P521_SHA384, + #[cfg(all(feature = "ecdsa-p521", feature = "hash-sha512"))] + ecdsa::nist::ECDSA_P521_SHA512, + ] + ), + feature_slice!( + [feature = "verify-eddsa"], + &[ + #[cfg(all(feature = "eddsa-ed25519", feature = "hash-sha256"))] + eddsa::ed25519::ED25519, + #[cfg(all(feature = "eddsa-ed448", feature = "hash-sha512"))] + eddsa::ed448::ED448, + ] + ), + feature_slice!( + [feature = "rsa-pkcs1"], + &[ + #[cfg(feature = "hash-sha256")] + rsa::RSA_PKCS1_SHA256, + #[cfg(feature = "hash-sha384")] + rsa::RSA_PKCS1_SHA384, + #[cfg(feature = "hash-sha512")] + rsa::RSA_PKCS1_SHA512, + ] + ), + feature_slice!( + [feature = "rsa-pss"], + &[ + #[cfg(feature = "hash-sha256")] + rsa::RSA_PSS_SHA256, + #[cfg(feature = "hash-sha384")] + rsa::RSA_PSS_SHA384, + #[cfg(feature = "hash-sha512")] + rsa::RSA_PSS_SHA512, + ] + ), +); + +pub const MAPPING: &[(SignatureScheme, &[&dyn SignatureVerificationAlgorithm])] = const_concat_slices!( + (SignatureScheme, &[&dyn SignatureVerificationAlgorithm],), + feature_slice!( + [feature = "verify-ecdsa-nist"], + &[ + #[cfg(all(feature = "ecdsa-p384", feature = "hash-sha384"))] + ( + SignatureScheme::ECDSA_NISTP384_SHA384, + &[ + ecdsa::nist::ECDSA_P384_SHA384, + #[cfg(feature = "ecdsa-p256")] + ecdsa::nist::ECDSA_P256_SHA384, + #[cfg(feature = "ecdsa-p521")] + ecdsa::nist::ECDSA_P521_SHA384, + ], + ), + #[cfg(all(feature = "ecdsa-p521", feature = "hash-sha512"))] + ( + SignatureScheme::ECDSA_NISTP521_SHA512, + &[ + ecdsa::nist::ECDSA_P521_SHA512, + #[cfg(feature = "ecdsa-p256")] + ecdsa::nist::ECDSA_P256_SHA512, + #[cfg(feature = "ecdsa-p384")] + ecdsa::nist::ECDSA_P384_SHA512, + ], + ), + #[cfg(all(feature = "ecdsa-p256", feature = "hash-sha256"))] + ( + SignatureScheme::ECDSA_NISTP256_SHA256, + &[ + ecdsa::nist::ECDSA_P256_SHA256, + #[cfg(feature = "ecdsa-p384")] + ecdsa::nist::ECDSA_P384_SHA256, + #[cfg(feature = "ecdsa-p521")] + ecdsa::nist::ECDSA_P521_SHA256, + ], + ), + ] + ), + feature_slice!( + [all(feature = "rsa-pkcs1", feature = "verify-rsa")], + &[ + #[cfg(feature = "hash-sha256")] + (SignatureScheme::RSA_PKCS1_SHA256, &[rsa::RSA_PKCS1_SHA256]), + #[cfg(feature = "hash-sha384")] + (SignatureScheme::RSA_PKCS1_SHA384, &[rsa::RSA_PKCS1_SHA384]), + #[cfg(feature = "hash-sha512")] + (SignatureScheme::RSA_PKCS1_SHA512, &[rsa::RSA_PKCS1_SHA512]), + ] + ), + feature_slice!( + [all(feature = "rsa-pss", feature = "verify-rsa")], + &[ + #[cfg(feature = "hash-sha256")] + (SignatureScheme::RSA_PSS_SHA256, &[rsa::RSA_PSS_SHA256]), + #[cfg(feature = "hash-sha384")] + (SignatureScheme::RSA_PSS_SHA384, &[rsa::RSA_PSS_SHA384]), + #[cfg(feature = "hash-sha512")] + (SignatureScheme::RSA_PSS_SHA512, &[rsa::RSA_PSS_SHA512]), + ] + ), + feature_slice!( + [feature = "verify-eddsa"], + &[ + #[cfg(all(feature = "eddsa-ed25519", feature = "hash-sha256"))] + (SignatureScheme::ED25519, &[eddsa::ed25519::ED25519]), + #[cfg(all(feature = "eddsa-ed448", feature = "hash-sha512"))] + (SignatureScheme::ED448, &[eddsa::ed448::ED448]), + ] + ), +); + +pub const ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { + all: const_concat_slices!( + &dyn SignatureVerificationAlgorithm, + ALL, + feature_slice!( + [feature = "eddsa"], + &[ + #[cfg(feature = "eddsa-ed25519")] + eddsa::ed25519::ED25519, + #[cfg(feature = "eddsa-ed448")] + eddsa::ed448::ED448, + ] + ) + ), + mapping: const_concat_slices!( + (SignatureScheme, &[&dyn SignatureVerificationAlgorithm],), + MAPPING, + feature_slice!( + [feature = "eddsa"], + &[ + #[cfg(feature = "eddsa-ed25519")] + (SignatureScheme::ED25519, &[eddsa::ed25519::ED25519]), + #[cfg(feature = "eddsa-ed448")] + (SignatureScheme::ED448, &[eddsa::ed448::ED448]), + ] + ) + ), }; +#[cfg(feature = "ecdsa")] pub mod ecdsa; + +#[cfg(feature = "eddsa")] pub mod eddsa; + +#[cfg(feature = "rsa")] pub mod rsa; diff --git a/src/verify/ecdsa.rs b/src/verify/ecdsa.rs index 669f03d..2d5c7c7 100644 --- a/src/verify/ecdsa.rs +++ b/src/verify/ecdsa.rs @@ -1,54 +1,2 @@ -use der::Decode; -use digest::Digest; -use paste::paste; -use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; -use signature::hazmat::PrehashVerifier; -use webpki::alg_id; - -macro_rules! impl_generic_ecdsa_verifer { - ( - $name:ident, - $public_key_algo:expr, - $signature_alg_id:expr, - $verifying_key:ty, - $signature:ty, - $hash:ty - ) => { - paste! { - #[allow(non_camel_case_types)] - #[derive(Debug)] - struct []; - - impl SignatureVerificationAlgorithm for [] { - fn public_key_alg_id(&self) -> AlgorithmIdentifier { - $public_key_algo - } - - fn signature_alg_id(&self) -> AlgorithmIdentifier { - $signature_alg_id - } - - fn verify_signature( - &self, - public_key: &[u8], - message: &[u8], - signature: &[u8], - ) -> Result<(), InvalidSignature> { - let signature = <$signature>::from_der(signature).map_err(|_| InvalidSignature)?; - let verifying_key = <$verifying_key>::from_sec1_bytes(public_key).map_err(|_| InvalidSignature)?; - let digest = &<$hash>::digest(&message); - verifying_key - .verify_prehash(digest, &signature) - .map_err(|_| InvalidSignature) - } - } - - pub const $name: &dyn SignatureVerificationAlgorithm = &[]; - } - }; -} - -impl_generic_ecdsa_verifer! {ECDSA_P256_SHA256, alg_id::ECDSA_P256, alg_id::ECDSA_SHA256, p256::ecdsa::VerifyingKey, p256::ecdsa::DerSignature, sha2::Sha256} -impl_generic_ecdsa_verifer! {ECDSA_P256_SHA384, alg_id::ECDSA_P256, alg_id::ECDSA_SHA384, p256::ecdsa::VerifyingKey, p256::ecdsa::DerSignature, sha2::Sha384} -impl_generic_ecdsa_verifer! {ECDSA_P384_SHA256, alg_id::ECDSA_P384, alg_id::ECDSA_SHA256, p384::ecdsa::VerifyingKey, p384::ecdsa::DerSignature, sha2::Sha256} -impl_generic_ecdsa_verifer! {ECDSA_P384_SHA384, alg_id::ECDSA_P384, alg_id::ECDSA_SHA384, p384::ecdsa::VerifyingKey, p384::ecdsa::DerSignature, sha2::Sha384} +#[cfg(feature = "verify-ecdsa-nist")] +pub mod nist; diff --git a/src/verify/ecdsa/nist.rs b/src/verify/ecdsa/nist.rs new file mode 100644 index 0000000..b550d07 --- /dev/null +++ b/src/verify/ecdsa/nist.rs @@ -0,0 +1,158 @@ +use core::marker::PhantomData; + +use ::aead::array::ArraySize; +use ::digest::Digest; +use ::ecdsa::EcdsaCurve; +use ::ecdsa::VerifyingKey; +use ::ecdsa::der::{MaxOverhead, MaxSize, Signature}; +use ::elliptic_curve::ops::Add; +use ::elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint}; +use ::elliptic_curve::{Curve, CurveArithmetic, FieldBytesSize}; +use ::pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm, alg_id}; +use ::sec1::point::ModulusSize; +use ::signature::hazmat::PrehashVerifier; +use core::fmt::Debug; + +/// Trait for ECDSA curve algorithm identifiers. +pub trait EcdsaCurveAlgId { + const PUBLIC_KEY_ALG_ID: AlgorithmIdentifier; +} + +/// Trait for ECDSA hash algorithm identifiers. +pub trait EcdsaHashAlgId { + const SIGNATURE_ALG_ID: AlgorithmIdentifier; +} + +/// Trait to simplify generic bounds for ECDSA curve types. +pub trait EcdsaVerifierCurve: EcdsaCurve + CurveArithmetic + EcdsaCurveAlgId +where + H: EcdsaHashAlgId, +{ +} + +impl EcdsaVerifierCurve for C +where + C: EcdsaCurve + CurveArithmetic + EcdsaCurveAlgId, + H: EcdsaHashAlgId, +{ +} + +#[derive(Debug, Default)] +pub struct EcdsaVerifier +where + C: EcdsaVerifierCurve, + H: Digest + EcdsaHashAlgId, +{ + _curve: PhantomData, + _hash: PhantomData, +} + +impl EcdsaVerifier +where + C: EcdsaVerifierCurve, + H: Digest + EcdsaHashAlgId, +{ + pub const DEFAULT: Self = Self { + _curve: PhantomData, + _hash: PhantomData, + }; +} + +impl EcdsaVerifier +where + C: EcdsaVerifierCurve, + ::AffinePoint: FromEncodedPoint + ToEncodedPoint, + ::FieldBytesSize: Debug + ModulusSize, + MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, + H: Digest + EcdsaHashAlgId, +{ + fn verify_inner( + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), crate::verify::Error> { + use der::Decode; + let signature = Signature::::from_der(signature)?; + let verifying_key = VerifyingKey::::from_sec1_bytes(public_key)?; + let digest = &H::digest(message); + verifying_key.verify_prehash(digest, &signature)?; + Ok(()) + } +} +impl SignatureVerificationAlgorithm for EcdsaVerifier +where + C: EcdsaVerifierCurve, + ::AffinePoint: FromEncodedPoint + ToEncodedPoint, + ::FieldBytesSize: Debug + ModulusSize, + MaxSize: ArraySize, + as Add>::Output: Add + ArraySize, + H: Digest + Debug + Send + Sync + EcdsaHashAlgId, +{ + fn public_key_alg_id(&self) -> AlgorithmIdentifier { + C::PUBLIC_KEY_ALG_ID + } + fn signature_alg_id(&self) -> AlgorithmIdentifier { + H::SIGNATURE_ALG_ID + } + fn verify_signature( + &self, + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), InvalidSignature> { + Self::verify_inner(public_key, message, signature).map_err(|_| InvalidSignature) + } +} + +/// Macro to generate all ECDSA hash impls, curve impls, and constants +macro_rules! ecdsa_setup { + ( + hashes: $( ($hash_ty:ty, $hash_alg:expr, $hash_feat:literal) ),* $(,)? ; + curves: $( ($curve_ty:ty, $curve_alg:expr, $curve_feat:literal, $( ($const_name:ident, $hash_for_const:ty, $hash_feat_for_const:literal) ),* $(,)? ) ),* $(,)? + ) => { + $( + #[cfg(feature = $hash_feat)] + impl EcdsaHashAlgId for $hash_ty { + const SIGNATURE_ALG_ID: AlgorithmIdentifier = $hash_alg; + } + )* + + $( + #[cfg(feature = $curve_feat)] + impl EcdsaCurveAlgId for $curve_ty { + const PUBLIC_KEY_ALG_ID: AlgorithmIdentifier = $curve_alg; + } + + $( + #[cfg(all(feature = $curve_feat, feature = $hash_feat_for_const))] + pub const $const_name: &dyn SignatureVerificationAlgorithm = + &EcdsaVerifier::<$curve_ty, $hash_for_const>::DEFAULT; + )* + )* + }; +} + +ecdsa_setup! { + hashes: + (::sha2::Sha256, alg_id::ECDSA_SHA256, "hash-sha256"), + (::sha2::Sha384, alg_id::ECDSA_SHA384, "hash-sha384"), + (::sha2::Sha512, alg_id::ECDSA_SHA512, "hash-sha512"); + + curves: + (::p256::NistP256, alg_id::ECDSA_P256, "ecdsa-p256", + (ECDSA_P256_SHA256, ::sha2::Sha256, "hash-sha256"), + (ECDSA_P256_SHA384, ::sha2::Sha384, "hash-sha384"), + (ECDSA_P256_SHA512, ::sha2::Sha512, "hash-sha512") + ), + (::p384::NistP384, alg_id::ECDSA_P384, "ecdsa-p384", + (ECDSA_P384_SHA256, ::sha2::Sha256, "hash-sha256"), + (ECDSA_P384_SHA384, ::sha2::Sha384, "hash-sha384"), + (ECDSA_P384_SHA512, ::sha2::Sha512, "hash-sha512") + ), + (::p521::NistP521, alg_id::ECDSA_P521, "ecdsa-p521", + (ECDSA_P521_SHA256, ::sha2::Sha256, "hash-sha256"), + (ECDSA_P521_SHA384, ::sha2::Sha384, "hash-sha384"), + (ECDSA_P521_SHA512, ::sha2::Sha512, "hash-sha512") + ) +} diff --git a/src/verify/eddsa.rs b/src/verify/eddsa.rs index 334321c..e3018eb 100644 --- a/src/verify/eddsa.rs +++ b/src/verify/eddsa.rs @@ -1,33 +1,5 @@ -use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; -use signature::Verifier; -use webpki::alg_id; +#[cfg(feature = "verify-eddsa-ed25519")] +pub mod ed25519; -#[derive(Debug)] -struct Ed25519Verify; - -impl SignatureVerificationAlgorithm for Ed25519Verify { - fn public_key_alg_id(&self) -> AlgorithmIdentifier { - alg_id::ED25519 - } - - fn signature_alg_id(&self) -> AlgorithmIdentifier { - alg_id::ED25519 - } - - fn verify_signature( - &self, - public_key: &[u8], - message: &[u8], - signature: &[u8], - ) -> Result<(), InvalidSignature> { - let public_key = public_key.try_into().map_err(|_| InvalidSignature)?; - let signature = - ed25519_dalek::Signature::from_slice(signature).map_err(|_| InvalidSignature)?; - ed25519_dalek::VerifyingKey::from_bytes(public_key) - .map_err(|_| InvalidSignature)? - .verify(message, &signature) - .map_err(|_| InvalidSignature) - } -} - -pub const ED25519: &dyn SignatureVerificationAlgorithm = &Ed25519Verify; +#[cfg(feature = "verify-eddsa-ed448")] +pub mod ed448; diff --git a/src/verify/eddsa/ed25519.rs b/src/verify/eddsa/ed25519.rs new file mode 100644 index 0000000..9435ca7 --- /dev/null +++ b/src/verify/eddsa/ed25519.rs @@ -0,0 +1,42 @@ +use ed25519_dalek::{Signature, VerifyingKey}; +use pki_types::alg_id; +use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; +use signature::Verifier; + +#[derive(Debug)] +pub struct Ed25519Verify; + +impl Ed25519Verify { + fn verify_inner( + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), crate::verify::Error> { + let public_key = public_key.try_into()?; + let signature = Signature::from_slice(signature)?; + let verifying_key = VerifyingKey::from_bytes(public_key)?; + verifying_key.verify(message, &signature)?; + Ok(()) + } +} + +impl SignatureVerificationAlgorithm for Ed25519Verify { + fn public_key_alg_id(&self) -> AlgorithmIdentifier { + alg_id::ED25519 + } + + fn signature_alg_id(&self) -> AlgorithmIdentifier { + alg_id::ED25519 + } + + fn verify_signature( + &self, + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), InvalidSignature> { + Self::verify_inner(public_key, message, signature).map_err(|_| InvalidSignature) + } +} + +pub const ED25519: &dyn SignatureVerificationAlgorithm = &Ed25519Verify; diff --git a/src/verify/eddsa/ed448.rs b/src/verify/eddsa/ed448.rs new file mode 100644 index 0000000..269c8ab --- /dev/null +++ b/src/verify/eddsa/ed448.rs @@ -0,0 +1,45 @@ +use ed448_goldilocks::{Signature, VerifyingKey}; +use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; +use signature::Verifier; + +#[derive(Debug)] +pub struct Ed448Verify; + +impl Ed448Verify { + fn verify_inner( + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), crate::verify::Error> { + let public_key = public_key.try_into()?; + let signature = Signature::from_slice(signature)?; + let verifying_key = VerifyingKey::from_bytes(public_key)?; + verifying_key.verify(message, &signature)?; + Ok(()) + } +} + +// Until https://github.com/rustls/pki-types/pull/87 was released, we need to use this hack +const ED448_IDENTIFIER: AlgorithmIdentifier = + AlgorithmIdentifier::from_slice(&[0x06, 0x03, 0x2B, 0x65, 0x71]); + +impl SignatureVerificationAlgorithm for Ed448Verify { + fn public_key_alg_id(&self) -> AlgorithmIdentifier { + ED448_IDENTIFIER + } + + fn signature_alg_id(&self) -> AlgorithmIdentifier { + ED448_IDENTIFIER + } + + fn verify_signature( + &self, + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), InvalidSignature> { + Self::verify_inner(public_key, message, signature).map_err(|_| InvalidSignature) + } +} + +pub const ED448: &dyn SignatureVerificationAlgorithm = &Ed448Verify; diff --git a/src/verify/rsa.rs b/src/verify/rsa.rs index f7a1889..f594b89 100644 --- a/src/verify/rsa.rs +++ b/src/verify/rsa.rs @@ -1,92 +1,176 @@ -use paste::paste; +use core::fmt::Debug; +use core::marker::PhantomData; +use digest::{Digest, FixedOutputReset}; +use pkcs1::DecodeRsaPublicKey; +use pkcs8::AssociatedOid; +use pki_types::alg_id; use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; -use rsa::pkcs1::DecodeRsaPublicKey; -use rsa::{pkcs1v15, pss, RsaPublicKey}; -use sha2::{Sha256, Sha384, Sha512}; +use rsa::RsaPublicKey; use signature::Verifier; -use webpki::alg_id; -macro_rules! impl_generic_rsa_verifer { +pub trait RsaHash: Digest + FixedOutputReset + AssociatedOid + Debug + Send + Sync { + const PKCS1_ALG_ID: AlgorithmIdentifier; + const PSS_ALG_ID: AlgorithmIdentifier; +} + +pub trait RsaScheme { + type VerifyingKey; + type Signature: for<'a> TryFrom<&'a [u8], Error = signature::Error>; + + fn signature_alg_id() -> AlgorithmIdentifier; + fn new_verifying_key(public_key: rsa::RsaPublicKey) -> Self::VerifyingKey; + /// Verifies the signature. + /// + /// # Errors + /// Returns an error if the signature verification fails. + fn verify( + key: &Self::VerifyingKey, + message: &[u8], + signature: &Self::Signature, + ) -> Result<(), signature::Error>; +} + +#[derive(Debug)] +pub struct Pkcs1; + +impl RsaScheme for Pkcs1 { + type VerifyingKey = rsa::pkcs1v15::VerifyingKey; + type Signature = rsa::pkcs1v15::Signature; + + fn signature_alg_id() -> AlgorithmIdentifier { + H::PKCS1_ALG_ID + } + + fn new_verifying_key(public_key: rsa::RsaPublicKey) -> Self::VerifyingKey { + rsa::pkcs1v15::VerifyingKey::new(public_key) + } + + fn verify( + key: &Self::VerifyingKey, + message: &[u8], + signature: &Self::Signature, + ) -> Result<(), signature::Error> { + key.verify(message, signature) + } +} + +#[derive(Debug)] +pub struct Pss; + +impl RsaScheme for Pss { + type VerifyingKey = rsa::pss::VerifyingKey; + type Signature = rsa::pss::Signature; + + fn signature_alg_id() -> AlgorithmIdentifier { + H::PSS_ALG_ID + } + + fn new_verifying_key(public_key: rsa::RsaPublicKey) -> Self::VerifyingKey { + rsa::pss::VerifyingKey::new(public_key) + } + + fn verify( + key: &Self::VerifyingKey, + message: &[u8], + signature: &Self::Signature, + ) -> Result<(), signature::Error> { + key.verify(message, signature) + } +} + +#[derive(Debug, Default)] +pub struct RsaVerifier { + _phantom: PhantomData<(H, S)>, +} + +impl RsaVerifier { + pub const DEFAULT: Self = Self { + _phantom: PhantomData, + }; +} + +impl RsaVerifier { + fn verify_inner( + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), crate::verify::Error> { + let public_key = RsaPublicKey::from_pkcs1_der(public_key)?; + let signature = ::try_from(signature)?; + let key = S::new_verifying_key::(public_key); + S::verify::(&key, message, &signature)?; + Ok(()) + } +} + +impl SignatureVerificationAlgorithm + for RsaVerifier +{ + fn public_key_alg_id(&self) -> AlgorithmIdentifier { + alg_id::RSA_ENCRYPTION + } + + fn signature_alg_id(&self) -> AlgorithmIdentifier { + S::signature_alg_id::() + } + + fn verify_signature( + &self, + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), InvalidSignature> { + Self::verify_inner(public_key, message, signature).map_err(|_| InvalidSignature) + } +} + +/// Macro to generate RSA hash impl and verifier constants +macro_rules! rsa_hash_and_consts { ( - $name:ident, - $public_key_algo:expr, - $signature_alg_id:expr, - $verifying_key:ty, - $signature:ty + $hash:ty, + $pkcs1_const:ident, + $pss_const:ident, + $pkcs1_alg:expr, + $pss_alg:expr, + $hash_feat:literal ) => { - paste! { - #[allow(non_camel_case_types)] - #[derive(Debug)] - struct []; - - impl SignatureVerificationAlgorithm for [] { - fn public_key_alg_id(&self) -> AlgorithmIdentifier { - $public_key_algo - } - - fn signature_alg_id(&self) -> AlgorithmIdentifier { - $signature_alg_id - } - - fn verify_signature( - &self, - public_key: &[u8], - message: &[u8], - signature: &[u8], - ) -> Result<(), InvalidSignature> { - let public_key = RsaPublicKey::from_pkcs1_der(public_key).map_err(|_| InvalidSignature)?; - let signature = <$signature>::try_from(signature).map_err(|_| InvalidSignature)?; - <$verifying_key>::new(public_key) - .verify(message, &signature) - .map_err(|_| InvalidSignature) - } - } - - pub const $name: &dyn SignatureVerificationAlgorithm = &[]; + #[cfg(feature = $hash_feat)] + impl RsaHash for $hash { + const PKCS1_ALG_ID: AlgorithmIdentifier = $pkcs1_alg; + const PSS_ALG_ID: AlgorithmIdentifier = $pss_alg; } + + #[cfg(all(feature = "rsa-pkcs1", feature = $hash_feat))] + pub const $pkcs1_const: &dyn SignatureVerificationAlgorithm = + &RsaVerifier::<$hash, Pkcs1>::DEFAULT; + + #[cfg(all(feature = "rsa-pss", feature = $hash_feat))] + pub const $pss_const: &dyn SignatureVerificationAlgorithm = + &RsaVerifier::<$hash, Pss>::DEFAULT; }; } -impl_generic_rsa_verifer!( +rsa_hash_and_consts!( + sha2::Sha256, RSA_PKCS1_SHA256, - alg_id::RSA_ENCRYPTION, - alg_id::RSA_PKCS1_SHA256, - pkcs1v15::VerifyingKey, - pkcs1v15::Signature -); -impl_generic_rsa_verifer!( - RSA_PKCS1_SHA384, - alg_id::RSA_ENCRYPTION, - alg_id::RSA_PKCS1_SHA384, - pkcs1v15::VerifyingKey, - pkcs1v15::Signature -); -impl_generic_rsa_verifer!( - RSA_PKCS1_SHA512, - alg_id::RSA_ENCRYPTION, - alg_id::RSA_PKCS1_SHA512, - pkcs1v15::VerifyingKey, - pkcs1v15::Signature -); - -impl_generic_rsa_verifer!( RSA_PSS_SHA256, - alg_id::RSA_ENCRYPTION, + alg_id::RSA_PKCS1_SHA256, alg_id::RSA_PSS_SHA256, - pss::VerifyingKey, - pss::Signature + "hash-sha256" ); -impl_generic_rsa_verifer!( +rsa_hash_and_consts!( + sha2::Sha384, + RSA_PKCS1_SHA384, RSA_PSS_SHA384, - alg_id::RSA_ENCRYPTION, + alg_id::RSA_PKCS1_SHA384, alg_id::RSA_PSS_SHA384, - pss::VerifyingKey, - pss::Signature + "hash-sha384" ); -impl_generic_rsa_verifer!( +rsa_hash_and_consts!( + sha2::Sha512, + RSA_PKCS1_SHA512, RSA_PSS_SHA512, - alg_id::RSA_ENCRYPTION, + alg_id::RSA_PKCS1_SHA512, alg_id::RSA_PSS_SHA512, - pss::VerifyingKey, - pss::Signature + "hash-sha512" ); diff --git a/tests-external/badssl.rs b/tests-external/badssl.rs deleted file mode 100644 index 7da3a4d..0000000 --- a/tests-external/badssl.rs +++ /dev/null @@ -1,53 +0,0 @@ -use claim::{assert_err, assert_ok}; -use test_case::test_case; - -// For the available tests check out here: https://badssl.com/dashboard/ - -#[cfg(feature = "tls12")] -#[test_case("https://ecc256.badssl.com/", Ok(()); "test ECC256 verification")] -#[test_case("https://ecc384.badssl.com/", Ok(()); "test ECC384 verification")] -#[test_case("https://rsa2048.badssl.com/", Ok(()); "test RSA-2048 verification")] -#[test_case("https://rsa4096.badssl.com/", Ok(()); "test RSA-4096 verification")] -#[cfg_attr(TODO, test_case("https://rsa8192.badssl.com/", Err(()); "test RSA-8192 verification"))] -#[test_case("https://sha256.badssl.com/", Ok(()); "test SHA-256 hash")] -#[test_case("https://sha384.badssl.com/", Err(()); "test SHA-384 hash (but expired)")] -#[test_case("https://sha512.badssl.com/", Err(()); "test SHA-512 hash (but expired)")] -#[test_case("https://tls-v1-2.badssl.com/", Ok(()); "test general TLS1.2 verification")] -#[test_case("https://mozilla-intermediate.badssl.com/", Ok(()); "test Mozilla intermediate compatibility (TLS 1.2 only)")] -#[test_case("https://long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com/", Ok(()); "test long name with dashes")] -#[test_case("https://longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com/", Ok(()); "test long name")] -#[tokio::test] -async fn test_badssl_tls12(uri: &str, expected: Result<(), ()>) { - if expected.is_ok() { - assert_ok!(client::run_request(uri).await); - } else { - assert_err!(client::run_request(uri).await); - } -} - -#[test_case("https://hsts.badssl.com/", Ok(()); "test HSTS (TODO)")] -#[test_case("https://mozilla-intermediate.badssl.com/", Ok(()); "test Mozilla intermediate compatibility (TLS 1.3 preferred)")] -#[test_case("https://mozilla-modern.badssl.com/", Ok(()); "test Mozilla modern compatibility (TLS 1.3 required)")] -#[test_case("https://upgrade.badssl.com/", Ok(()); "test upgrade-insecure-requests")] -#[test_case("https://1000-sans.badssl.com/", Err(()); "test 1000-sans")] -#[test_case("https://10000-sans.badssl.com/", Err(()); "test 10000-sans")] -#[test_case("https://expired.badssl.com/", Err(()); "test expired")] -#[test_case("https://incomplete-chain.badssl.com/", Err(()); "test incomplete chain")] -#[test_case("https://no-common-name.badssl.com/", Err(()); "test no common name")] -#[test_case("https://no-subject.badssl.com/", Err(()); "test no subject")] -#[test_case("https://revoked.badssl.com/", Err(()); "test revoked")] -#[test_case("https://self-signed.badssl.com/", Err(()); "test self signed")] -#[test_case("https://untrusted-root.badssl.com/", Err(()); "test untrusted root")] -#[test_case("https://wrong.host.badssl.com/", Err(()); "test wrong host")] -#[test_case("https://no-sct.badssl.com/", Err(()); "test Signed Certificate Timestamp")] // NET::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED -#[cfg_attr(TODO, test_case("https://pinning-test.badssl.com/", Err(()); "test pinning test"))] // NET::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN -#[tokio::test] -async fn test_badssl(uri: &str, expected: Result<(), ()>) { - if expected.is_ok() { - assert_ok!(client::run_request(uri).await); - } else { - assert_err!(client::run_request(uri).await); - } -} - -mod client; diff --git a/tests-external/client.rs b/tests-external/client.rs deleted file mode 100644 index addae02..0000000 --- a/tests-external/client.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::str::FromStr; - -use http_body_util::{BodyExt, Empty}; -use hyper::{body::Bytes, Uri}; -use hyper_rustls::HttpsConnector; -use hyper_util::{ - client::legacy::{connect::HttpConnector, Client}, - rt::TokioExecutor, -}; -use rustls_rustcrypto::provider; - -pub fn build_hyper_client() -> anyhow::Result, Empty>> { - let https = hyper_rustls::HttpsConnectorBuilder::new() - .with_provider_and_webpki_roots(provider())? - .https_or_http() - .enable_all_versions() - .build(); - let client: Client<_, Empty> = Client::builder(TokioExecutor::new()).build(https); - - Ok(client) -} - -// I'm not sure how to exactly extract the hyper TLS error result to pinpoint -// what error it should match For now treating it as a grand result is alright -pub async fn run_request(uri: &str) -> anyhow::Result<()> { - let client = build_hyper_client()?; - let uri = Uri::from_str(uri)?; - let res = client.get(uri).await?; - - // We could definite check whether this is a HTML, but for now we don't really - // care about the body content - let bytes = res.into_body().collect().await?.to_bytes(); - - println!("{:?}", bytes); - - Ok(()) -} diff --git a/tests-external/generic.rs b/tests-external/generic.rs deleted file mode 100644 index 28f23da..0000000 --- a/tests-external/generic.rs +++ /dev/null @@ -1,30 +0,0 @@ -use claim::{assert_err, assert_ok}; -use test_case::test_case; - -// For the available tests check out here: https://badssl.com/dashboard/ - -#[test_case("https://codeforces.com/", Ok(()))] -#[test_case("https://crates.io/", Ok(()))] -#[test_case("https://doc.rust-lang.org/", Ok(()))] -#[test_case("https://github.com/", Ok(()))] -#[test_case("https://twitter.com/", Ok(()))] -#[test_case("https://wikipedia.org/", Ok(()))] -#[test_case("https://www.facebook.com/", Ok(()))] -#[test_case("https://www.google.com/", Ok(()))] -#[test_case("https://www.hackerrank.com/", Ok(()))] -#[test_case("https://www.instagram.com/", Ok(()))] -#[test_case("https://www.reddit.com/", Ok(()))] -#[test_case("https://stackoverflow.com/", Ok(()))] -#[test_case("https://www.youtube.com/", Ok(()))] -#[test_case("https://leetcode.com/", Ok(()))] -#[cfg_attr(feature = "tls12", test_case("https://www.topcoder.com/", Ok(())))] -#[tokio::test] -async fn test_generic_sites(uri: &str, expected: Result<(), ()>) { - if expected.is_ok() { - assert_ok!(client::run_request(uri).await); - } else { - assert_err!(client::run_request(uri).await); - } -} - -mod client; diff --git a/tests/builder.rs b/tests/builder.rs index bab5d85..a879a08 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -1,83 +1,164 @@ -use std::sync::Arc; +use std::io::{Read, Write}; +use std::sync::{Arc, OnceLock}; -use rustls::ClientConfig as RusTlsClientConfig; -use rustls::ServerConfig as RusTlsServerConfig; - -use rustls_rustcrypto::provider as rustcrypto_provider; - -mod fake_time; +use fake_cert_server_resolver::FakeServerCertResolver; use fake_time::FakeTime; - -mod fake_cert_server_verifier; -use fake_cert_server_verifier::FakeServerCertVerifier; - -mod fake_cert_client_verifier; -use fake_cert_client_verifier::FakeClientCertVerifier; +use itertools::iproduct; +use mem_socket::MemorySocket; +use rand_core::{OsRng, TryRngCore}; +use rustls::crypto::CryptoProvider; +use rustls::{ + ClientConfig as RusTlsClientConfig, RootCertStore, ServerConfig as RusTlsServerConfig, +}; +use rustls_rustcrypto::{Provider, provider as rustcrypto_provider, verify}; mod fake_cert_server_resolver; -use fake_cert_server_resolver::FakeServerCertResolver; +mod fake_time; -// Test integration between rustls and rustls in Client builder context -#[test] -fn integrate_client_builder_with_details_fake() { - let provider = rustcrypto_provider(); - let time_provider = FakeTime {}; +static SERVER_RESOLVER: OnceLock> = OnceLock::new(); - let fake_server_cert_verifier = FakeServerCertVerifier {}; +fn make_client_config(provider: CryptoProvider) -> RusTlsClientConfig { + let resolver = SERVER_RESOLVER.get_or_init(|| Arc::new(FakeServerCertResolver::new())); + let mut store = RootCertStore::empty(); - let builder_init = - RusTlsClientConfig::builder_with_details(Arc::new(provider), Arc::new(time_provider)); + store.add(resolver.rsa_root_cert()).unwrap(); + store.add(resolver.ecdsa_root_cert()).unwrap(); - let builder_default_versions = builder_init + RusTlsClientConfig::builder_with_details(Arc::new(provider), Arc::new(FakeTime {})) .with_safe_default_protocol_versions() - .expect("Default protocol versions error?"); + .expect("Default protocol versions error?") + .with_root_certificates(store) + // .dangerous() + // .with_custom_certificate_verifier(Arc::new(FakeServerCertVerifier {})) + .with_no_client_auth() +} - let dangerous_verifier = builder_default_versions - .dangerous() - .with_custom_certificate_verifier(Arc::new(fake_server_cert_verifier)); +fn make_server_config(provider: CryptoProvider) -> RusTlsServerConfig { + let resolver = SERVER_RESOLVER + .get_or_init(|| Arc::new(FakeServerCertResolver::new())) + .clone(); + RusTlsServerConfig::builder_with_details(Arc::new(provider), Arc::new(FakeTime {})) + .with_safe_default_protocol_versions() + .expect("Default protocol versions error?") + .with_no_client_auth() + .with_cert_resolver(resolver) +} +// Test integration between rustls and rustls in Client builder context +#[test] +fn integrate_client_builder_with_details_fake() { // Out of scope - let rustls_client_config = dangerous_verifier.with_no_client_auth(); + let rustls_client_config = make_client_config(rustcrypto_provider()); // RustCrypto is not fips assert!(!rustls_client_config.fips()); } -use rustls::DistinguishedName; - // Test integration between rustls and rustls in Server builder context #[test] fn integrate_server_builder_with_details_fake() { - let provider = rustcrypto_provider(); - let time_provider = FakeTime {}; - - let builder_init = - RusTlsServerConfig::builder_with_details(Arc::new(provider), Arc::new(time_provider)); - - let builder_default_versions = builder_init - .with_safe_default_protocol_versions() - .expect("Default protocol versions error?"); - - // A DistinguishedName is a Vec wrapped in internal types. - // DER or BER encoded Subject field from RFC 5280 for a single certificate. - // The Subject field is encoded as an RFC 5280 Name - //let b_wrap_in: &[u8] = b""; // TODO: should have constant somewhere - - let dummy_entry: &[u8] = b""; - - let client_dn = [DistinguishedName::in_sequence(dummy_entry)]; - - let client_cert_verifier = FakeClientCertVerifier { dn: client_dn }; + let rustls_server_config = make_server_config(rustcrypto_provider()); - let dangerous_verifier = - builder_default_versions.with_client_cert_verifier(Arc::new(client_cert_verifier)); + // RustCrypto is not fips + assert!(!rustls_server_config.fips()); +} - let server_cert_resolver = FakeServerCertResolver {}; +const CLIENT_MAGIC: &[u8; 18] = b"Hello from Client!"; +const SERVER_MAGIC: &[u8; 18] = b"Hello from Server!"; - // Out of scope - let rustls_client_config = - dangerous_verifier.with_cert_resolver(Arc::new(server_cert_resolver)); +// Test integration +#[test] +fn test_basic_round_trip() { + std::thread::scope(move |s| { + for provider in generate_providers() { + let base_name = format!( + "{:?}-{:?}", + provider.cipher_suites[0], provider.kx_groups[0] + ); + println!("Testing with {base_name}"); + // Creates a pair of sockets that interconnect from client to server, and server to client + let (socket_c2s, socket_s2c) = MemorySocket::new_pair(); + + let mut random_data: [u8; 64 * 1024] = [0; 64 * 1024]; + OsRng.try_fill_bytes(&mut random_data).unwrap(); + + std::thread::Builder::new() + .name(format!("{base_name}-server")) + .spawn_scoped(s, { + let provider: CryptoProvider = provider.clone(); + move || { + let config = Arc::new(make_server_config(provider)); + let mut stream = socket_s2c; + let mut conn = rustls::ServerConnection::new(config.clone()) + .expect("failed to create server config"); + + let mut tls = rustls::Stream::new(&mut conn, &mut stream); + + { + let mut buf = [0; CLIENT_MAGIC.len()]; + tls.read_exact(&mut buf).unwrap(); + assert_eq!(&buf, CLIENT_MAGIC); + } + + tls.write_all(SERVER_MAGIC) + .expect("failed to write to client"); + tls.write_all(&random_data) + .expect("failed to write random data to client"); + tls.conn.send_close_notify(); + tls.flush().expect("failed to flush connection"); + } + }) + .unwrap(); + + std::thread::Builder::new() + .name(format!("{base_name}-client")) + .spawn_scoped(s, move || { + let mut sock = socket_c2s; + let server_name = "acme.com".try_into().expect("failed to get server name"); + let mut conn = rustls::ClientConnection::new( + Arc::new(make_client_config(provider)), + server_name, + ) + .expect("failed to create client config"); + let mut tls = rustls::Stream::new(&mut conn, &mut sock); + tls.write_all(CLIENT_MAGIC) + .expect("failed to write to server"); + + { + let mut buf = [0; SERVER_MAGIC.len()]; + tls.read_exact(&mut buf) + .expect("failed to read from server"); + assert_eq!(&buf, SERVER_MAGIC); + } + + { + let mut plaintext = Vec::new(); + tls.write_all(&random_data) + .expect("failed to write random data to server"); + tls.read_to_end(&mut plaintext) + .expect("failed to read from server"); + assert_eq!(plaintext, random_data); + } + }) + .unwrap(); + } + }); +} - // RustCrypto is not fips - assert!(!rustls_client_config.fips()); +fn generate_providers() -> impl Iterator { + let CryptoProvider { + cipher_suites, + kx_groups, + .. + } = rustcrypto_provider(); + + iproduct!(cipher_suites, kx_groups).map(|(cipher_suite, kx_group)| CryptoProvider { + cipher_suites: vec![cipher_suite], + kx_groups: vec![kx_group], + signature_verification_algorithms: verify::ALGORITHMS, + secure_random: &Provider, + key_provider: &Provider, + }) } + +mod mem_socket; diff --git a/tests/fake_cert_client_verifier.rs b/tests/fake_cert_client_verifier.rs deleted file mode 100644 index a8dc9cc..0000000 --- a/tests/fake_cert_client_verifier.rs +++ /dev/null @@ -1,71 +0,0 @@ -use rustls::DistinguishedName; -use rustls::Error; - -use rustls::SignatureScheme; - -use rustls::pki_types::CertificateDer; -use rustls::pki_types::UnixTime; -use rustls::DigitallySignedStruct; - -use rustls::client::danger::HandshakeSignatureValid; -use rustls::server::danger::ClientCertVerified; -use rustls::server::danger::ClientCertVerifier; - -#[derive(Debug)] -pub struct FakeClientCertVerifier { - pub dn: [DistinguishedName; 1], -} - -impl ClientCertVerifier for FakeClientCertVerifier { - fn root_hint_subjects(&self) -> &[DistinguishedName] { - &self.dn - } - fn verify_client_cert( - &self, - _end_entity: &CertificateDer<'_>, - _intermediates: &[CertificateDer<'_>], - _now: UnixTime, - ) -> Result { - Ok(ClientCertVerified::assertion()) - } - fn verify_tls12_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - fn verify_tls13_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - fn supported_verify_schemes(&self) -> Vec { - vec![ - SignatureScheme::RSA_PKCS1_SHA1, - SignatureScheme::ECDSA_SHA1_Legacy, - SignatureScheme::RSA_PKCS1_SHA256, - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::RSA_PKCS1_SHA384, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::RSA_PKCS1_SHA512, - SignatureScheme::ECDSA_NISTP521_SHA512, - SignatureScheme::RSA_PSS_SHA256, - SignatureScheme::RSA_PSS_SHA384, - SignatureScheme::RSA_PSS_SHA512, - SignatureScheme::ED25519, - SignatureScheme::ED448, - //SignatureScheme::Unknown(u16), - ] - } - fn offer_client_auth(&self) -> bool { - true - } - fn client_auth_mandatory(&self) -> bool { - false - } -} diff --git a/tests/fake_cert_server_resolver.rs b/tests/fake_cert_server_resolver.rs index 7028c8b..3b49ee4 100644 --- a/tests/fake_cert_server_resolver.rs +++ b/tests/fake_cert_server_resolver.rs @@ -1,15 +1,196 @@ +use core::time::Duration; +use std::str::FromStr; use std::sync::Arc; -use rustls::server::ClientHello; - -use rustls::server::ResolvesServerCert; +use itertools::iproduct; +use pki_types::{CertificateDer, PrivateKeyDer}; +use rand_core_064::{OsRng, RngCore}; +use rsa_098::pkcs8::{EncodePrivateKey, EncodePublicKey}; +use rustls::CipherSuite::{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +}; +use rustls::server::{ClientHello, ResolvesServerCert}; use rustls::sign::CertifiedKey; +use rustls_rustcrypto::sign::any_supported_type; +use signature_220::{Keypair, Signer}; +use x509_cert::builder::{Builder, CertificateBuilder, Profile, RequestBuilder}; +use x509_cert::der::{ + Encode, + asn1::{GeneralizedTime, Ia5String}, +}; +use x509_cert::ext::pkix::{SubjectAltName, name::GeneralName}; +use x509_cert::name::Name; +use x509_cert::serial_number::SerialNumber; +use x509_cert::spki::{ + SignatureAlgorithmIdentifier, SignatureBitStringEncoding, SubjectPublicKeyInfoOwned, +}; +use x509_cert::time::{Time, Validity}; #[derive(Debug)] -pub struct FakeServerCertResolver; +pub struct FakeServerCertResolver { + rsa_cert_key: Arc, + ecdsa_cert_key: Arc, + rsa_root_cert: CertificateDer<'static>, + ecdsa_root_cert: CertificateDer<'static>, +} + +impl FakeServerCertResolver { + pub fn new() -> Self { + let (rsa_root_cert, rsa_root_key) = Self::generate_root_cert(|| { + // by running a binary search between 1024 bit and 2048 bit, 1034 bit is the first possible bit size after 1024 bit + rsa_098::pkcs1v15::SigningKey::::random(&mut OsRng, 1034) + .unwrap() + }); + let (ecdsa_root_cert, ecdsa_root_key) = + Self::generate_root_cert::<_, p256_0132::ecdsa::DerSignature>(|| { + p256_0132::ecdsa::SigningKey::random(&mut OsRng) + }); + + let (rsa_cert, rsa_key) = Self::generate_cert( + || { + // by running a binary search between 1024 bit and 2048 bit, 1034 bit is the first possible bit size after 1024 bit + rsa_098::pkcs1v15::SigningKey::::random(&mut OsRng, 1034) + .unwrap() + }, + rsa_root_key, + ); + let (ecdsa_cert, ecdsa_key) = Self::generate_cert::<_, _, p256_0132::ecdsa::DerSignature>( + || p256_0132::ecdsa::SigningKey::random(&mut OsRng), + ecdsa_root_key, + ); + + Self { + rsa_root_cert: rsa_root_cert.clone(), + ecdsa_root_cert: ecdsa_root_cert.clone(), + rsa_cert_key: Arc::new(CertifiedKey::new( + vec![rsa_cert], + any_supported_type(&rsa_key).unwrap(), + )), + ecdsa_cert_key: Arc::new(CertifiedKey::new( + vec![ecdsa_cert], + any_supported_type(&ecdsa_key).unwrap(), + )), + } + } + + pub fn rsa_root_cert(&self) -> CertificateDer<'static> { + self.rsa_root_cert.clone() + } + + pub fn ecdsa_root_cert(&self) -> CertificateDer<'static> { + self.ecdsa_root_cert.clone() + } + + fn generate_root_cert( + key_fn: impl Fn() -> Key, + ) -> (CertificateDer<'static>, Key) + where + Key: Signer + Keypair + SignatureAlgorithmIdentifier + EncodePrivateKey, + Signature: SignatureBitStringEncoding, + ::VerifyingKey: EncodePublicKey, + { + let signing_key = key_fn(); + ( + CertificateBuilder::new( + Profile::Root, + SerialNumber::from(OsRng.next_u64()), + Validity { + not_before: Time::GeneralTime( + GeneralizedTime::from_unix_duration(Duration::ZERO).unwrap(), + ), + not_after: Time::INFINITY, + }, + Name::from_str("CN=ACME Corporation CA,O=ACME Corporation,C=US").unwrap(), + SubjectPublicKeyInfoOwned::from_key(signing_key.verifying_key()).unwrap(), + &signing_key, + ) + .unwrap() + .build::() + .unwrap() + .to_der() + .unwrap() + .into(), + signing_key, + ) + } + fn generate_cert( + key_fn: impl Fn() -> Key, + ca_key: CaKey, + ) -> (CertificateDer<'static>, PrivateKeyDer<'static>) + where + Key: Signer + Keypair + SignatureAlgorithmIdentifier + EncodePrivateKey, + CaKey: Signer + Keypair + SignatureAlgorithmIdentifier + EncodePrivateKey, + Signature: SignatureBitStringEncoding, + ::VerifyingKey: EncodePublicKey, + ::VerifyingKey: EncodePublicKey, + { + let signing_key = key_fn(); + + let request = RequestBuilder::new(Name::from_str("CN=acme.com").unwrap(), &signing_key) + .unwrap() + .build() + .unwrap(); + + let mut builder = CertificateBuilder::new( + Profile::Leaf { + issuer: Name::from_str("CN=ACME Corporation CA,O=ACME Corporation,C=US").unwrap(), + enable_key_agreement: true, + enable_key_encipherment: true, + }, + SerialNumber::from(OsRng.next_u64()), + Validity { + not_before: Time::GeneralTime( + GeneralizedTime::from_unix_duration(Duration::ZERO).unwrap(), + ), + not_after: Time::INFINITY, + }, + request.info.subject, + request.info.public_key, + &ca_key, + ) + .unwrap(); + builder + .add_extension(&SubjectAltName(vec![GeneralName::DnsName( + Ia5String::new(b"acme.com").unwrap(), + )])) + .unwrap(); + ( + builder + .build::() + .unwrap() + .to_der() + .unwrap() + .into(), + PrivateKeyDer::Pkcs8( + signing_key + .to_pkcs8_der() + .unwrap() + .as_bytes() + .to_vec() + .into(), + ), + ) + } +} impl ResolvesServerCert for FakeServerCertResolver { - fn resolve(&self, _client_hello: ClientHello<'_>) -> Option> { - None + fn resolve(&self, hello: ClientHello<'_>) -> Option> { + Some( + if iproduct!( + [ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + ], + hello.cipher_suites() + ) + .any(|(a, &b)| a == b) + { + self.rsa_cert_key.clone() + } else { + self.ecdsa_cert_key.clone() + }, + ) } } diff --git a/tests/fake_cert_server_verifier.rs b/tests/fake_cert_server_verifier.rs deleted file mode 100644 index 2786058..0000000 --- a/tests/fake_cert_server_verifier.rs +++ /dev/null @@ -1,59 +0,0 @@ -use rustls::client::danger::HandshakeSignatureValid; -use rustls::client::danger::ServerCertVerified; -use rustls::client::danger::ServerCertVerifier; -use rustls::pki_types::CertificateDer; -use rustls::pki_types::ServerName; -use rustls::pki_types::UnixTime; -use rustls::DigitallySignedStruct; -use rustls::Error; -use rustls::SignatureScheme; - -#[derive(Debug)] -pub struct FakeServerCertVerifier; - -impl ServerCertVerifier for FakeServerCertVerifier { - fn verify_server_cert( - &self, - _end_entity: &CertificateDer<'_>, - _intermediates: &[CertificateDer<'_>], - _server_name: &ServerName<'_>, - _ocsp_response: &[u8], - _now: UnixTime, - ) -> Result { - Ok(ServerCertVerified::assertion()) - } - fn verify_tls12_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - fn verify_tls13_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - fn supported_verify_schemes(&self) -> Vec { - vec![ - SignatureScheme::RSA_PKCS1_SHA1, - SignatureScheme::ECDSA_SHA1_Legacy, - SignatureScheme::RSA_PKCS1_SHA256, - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::RSA_PKCS1_SHA384, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::RSA_PKCS1_SHA512, - SignatureScheme::ECDSA_NISTP521_SHA512, - SignatureScheme::RSA_PSS_SHA256, - SignatureScheme::RSA_PSS_SHA384, - SignatureScheme::RSA_PSS_SHA512, - SignatureScheme::ED25519, - SignatureScheme::ED448, - //SignatureScheme::Unknown(u16), - ] - } -} diff --git a/tests/fake_time.rs b/tests/fake_time.rs index 83dc3fa..12d82e9 100644 --- a/tests/fake_time.rs +++ b/tests/fake_time.rs @@ -1,3 +1,5 @@ +use core::time::Duration; + use rustls::pki_types::UnixTime; use rustls::time_provider::TimeProvider; @@ -6,6 +8,6 @@ pub struct FakeTime; impl TimeProvider for FakeTime { fn current_time(&self) -> Option { - None + Some(UnixTime::since_unix_epoch(Duration::ZERO)) } } diff --git a/tests/mem_socket.rs b/tests/mem_socket.rs new file mode 100644 index 0000000..63e3fc7 --- /dev/null +++ b/tests/mem_socket.rs @@ -0,0 +1,102 @@ +use std::{ + io::{self, ErrorKind, Read, Write}, + sync::mpsc::{Receiver, Sender, channel}, +}; + +use bytes::{Buf, Bytes, BytesMut}; + +// The code is derived from: https://github.com/bmwill/memory-socket/blob/74110b18318c261e86d08aa53a7abe3e2a881538/src/lib.rs#L271-L405 +pub struct MemorySocket { + incoming: Receiver, + outgoing: Sender, + write_buffer: BytesMut, + current_buffer: Option, + seen_eof: bool, +} + +impl MemorySocket { + fn new(incoming: Receiver, outgoing: Sender) -> Self { + Self { + incoming, + outgoing, + write_buffer: BytesMut::new(), + current_buffer: None, + seen_eof: false, + } + } + + pub fn new_pair() -> (Self, Self) { + let (a_tx, a_rx) = channel(); + let (b_tx, b_rx) = channel(); + let a = Self::new(a_rx, b_tx); + let b = Self::new(b_rx, a_tx); + + (a, b) + } +} + +impl Read for MemorySocket { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let mut bytes_read = 0; + + loop { + // If we've already filled up the buffer then we can return + if bytes_read == buf.len() { + return Ok(bytes_read); + } + + match self.current_buffer { + // We still have data to copy to `buf` + Some(ref mut current_buffer) if current_buffer.has_remaining() => { + let bytes_to_read = current_buffer.remaining().min(buf.len() - bytes_read); + debug_assert!(bytes_to_read > 0); + + current_buffer + .take(bytes_to_read) + .copy_to_slice(&mut buf[bytes_read..(bytes_read + bytes_to_read)]); + bytes_read += bytes_to_read; + } + + // Either we've exhausted our current buffer or we don't have one + _ => { + // If we've read anything up to this point return the bytes read + if bytes_read > 0 { + return Ok(bytes_read); + } + + self.current_buffer = match self.incoming.recv() { + Ok(buf) => Some(buf), + + // The remote side hung up, if this is the first time we've seen EOF then + // we should return `Ok(0)` otherwise an UnexpectedEof Error + Err(_) if self.seen_eof => { + return Err(ErrorKind::UnexpectedEof.into()); + } + + Err(_) => { + self.seen_eof = true; + return Ok(0); + } + } + } + } + } + } +} + +impl Write for MemorySocket { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.write_buffer.extend_from_slice(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + if !self.write_buffer.is_empty() { + self.outgoing + .send(self.write_buffer.split().freeze()) + .map_err(|_| ErrorKind::BrokenPipe.into()) + } else { + Ok(()) + } + } +} diff --git a/validation/README.md b/validation/README.md index 913e210..3ead642 100644 --- a/validation/README.md +++ b/validation/README.md @@ -1,16 +1,169 @@ # rustls-rustcrypto Validation -These are collection of crates that can be used to validate integration -between rustls and rustcrypto-rustcrypto provider under different targets. +This directory contains a collection of validation crates designed to thoroughly test the integration between [rustls](https://github.com/rustls/rustls) and the [rustcrypto-rustcrypto](https://github.com/RustCrypto/rustls-rustcrypto) provider across different environments and targets. -| Crate | Description | -| :--- | :--- | -| consumer-no_std | Basic consumer library aiming no_std environment | -| local_ping_pong_openssl | Local tests against OpenSSL reference | +## Purpose -These live in the workspace due to different dependency requirements between -tests where development-deps may pollute the integration under test. +These validation crates serve multiple critical purposes: -This is aimed for internal validation without requiring further upstream -dependencies which are may or may not be in lock-step with current version of -rustls the provider targets in any given time. +- **Integration Testing**: Ensure seamless compatibility between rustls and the RustCrypto provider +- **Cross-Platform Validation**: Test functionality across different architectures and environments (e.g., ESP32, no_std) +- **Reference Implementation Comparison**: Validate against established TLS implementations like OpenSSL +- **Real-World Scenarios**: Test with actual network sockets and certificates +- **Build Verification**: Confirm builds work in constrained environments (no_std) + +## Validation Crates + +| Crate | Description | Target Environment | +| :---------------------- | :------------------------------------------------------- | :----------------- | +| consumer-no_std | Basic consumer library for no_std environments | no_std | +| local_ping_pong_openssl | Local tests against OpenSSL reference | Standard Rust | +| esp32-test | Test for ESP32 microcontroller target using real sockets | ESP32 | +| rustls-real-socket-test | Test using real sockets for TLS integration | Standard Rust | +| quic-test | Battle-test using QUIC to do roundtrip calls | Standard Rust | + +### Detailed Crate Descriptions + +#### consumer-no_std + +A minimal self-testing crate that validates the no_std build capability of rustls-rustcrypto. This crate ensures that the provider can be compiled and used in environments without the standard library, which is crucial for embedded systems and constrained environments. + +**Key Features:** + +- Validates no_std compilation +- Minimal dependencies +- Self-contained testing + +#### local_ping_pong_openssl + +This crate performs comprehensive compatibility testing between rustls-rustcrypto and OpenSSL. It includes tests with OpenSSL-generated certificates and keys to ensure interoperability and correct TLS handshake behavior. + +**Key Features:** + +- OpenSSL compatibility testing +- Certificate and key validation +- TLS handshake verification +- Cross-implementation validation + +#### esp32-test + +A specialized test crate for the ESP32 microcontroller platform. It performs end-to-end TLS testing using real network sockets, validating the rustcrypto provider's functionality in an embedded environment. + +**Key Features:** + +- ESP32-specific testing +- Real socket communication +- TLS client/server implementation +- Embedded target validation + +#### rustls-real-socket-test + +Similar to esp32-test but designed for standard Rust environments. This crate tests TLS functionality using actual network sockets, providing realistic validation of the provider's capabilities. + +**Key Features:** + +- Real socket testing +- TLS client/server implementation +- Network communication validation +- Standard Rust environment testing + +## Installation and Setup + +### Prerequisites + +- Rust 1.88.0 or later +- Cargo package manager +- For ESP32 testing: ESP-IDF development environment +- For OpenSSL testing: OpenSSL development libraries + +### Building All Crates + +```bash +# From the workspace root +cargo build --workspace +``` + +### Building Individual Crates + +```bash +# consumer-no_std +cargo build -p consumer-no_std --no-default-features + +# local_ping_pong_openssl +cargo build -p local_ping_pong_openssl + +# rustls-real-socket-test +cargo build -p rustls-real-socket-test + +# esp32-test (requires ESP32 toolchain) +cargo build -p esp32-test +``` + +## Usage Examples + +### Running consumer-no_std Tests + +```bash +cargo test -p consumer-no_std --no-default-features +``` + +### Running OpenSSL Compatibility Tests + +```bash +# Generate test certificates (if needed) +cd validation/local_ping_pong_openssl/certs +make + +# Run the tests +cargo run -p local_ping_pong_openssl +``` + +### Running Real Socket Tests + +```bash +# Standard Rust +cargo run -p rustls-real-socket-test + +# ESP32 (requires appropriate hardware/toolchain) +cargo run -p esp32-test +``` + +## Dependencies + +### Common Dependencies + +- `rustls` 0.23.x +- `rustls-rustcrypto` (workspace) +- `anyhow` for error handling +- `log` for logging + +### ESP32-Specific + +- `esp-idf-svc` for ESP32 services +- `esp-idf-hal` for hardware abstraction + +### OpenSSL-Specific + +- OpenSSL development libraries +- Custom certificate generation tools + +### Environment Variables + +- `RUST_LOG`: Set logging level (e.g., `RUST_LOG=trace`) +- ESP32-specific: Various ESP-IDF environment variables for toolchain setup + +## Architecture and Design + +These validation crates are designed with the following principles: + +1. **Isolation**: Each crate has its own Cargo.toml to avoid dependency pollution +2. **Minimalism**: Focused on specific validation scenarios +3. **Realism**: Use actual network communication where possible +4. **Cross-Platform**: Support multiple target architectures +5. **Extensibility**: Easy to add new test scenarios + +--- + +These live in the workspace due to different dependency requirements between tests where development-deps may pollute the integration under test. + +This is aimed for internal validation without requiring further upstream dependencies which may or may not be in lock-step with current version of rustls the provider targets in any given time. diff --git a/validation/esp32-test/.cargo/config.toml b/validation/esp32-test/.cargo/config.toml new file mode 100644 index 0000000..f3032bb --- /dev/null +++ b/validation/esp32-test/.cargo/config.toml @@ -0,0 +1,14 @@ +[build] +target = "riscv32imac-esp-espidf" + +[target.riscv32imac-esp-espidf] +linker = "ldproxy" +runner = "espflash flash --monitor" +rustflags = [ "--cfg", "espidf_time64"] + +[unstable] +build-std = ["std", "panic_abort"] + +[env] +MCU="esp32c6" +ESP_IDF_VERSION="v5.5.1" \ No newline at end of file diff --git a/validation/esp32-test/.gitignore b/validation/esp32-test/.gitignore new file mode 100644 index 0000000..4387b9d --- /dev/null +++ b/validation/esp32-test/.gitignore @@ -0,0 +1,3 @@ +/.vscode +/.embuild +/Cargo.lock diff --git a/validation/esp32-test/Cargo.toml b/validation/esp32-test/Cargo.toml new file mode 100644 index 0000000..b276b16 --- /dev/null +++ b/validation/esp32-test/Cargo.toml @@ -0,0 +1,52 @@ +[package] +name = "esp32-test" +version = "0.1.0" +authors = ["Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com>"] +edition = "2024" +resolver = "2" +rust-version = "1.88.0" + +[[bin]] +name = "esp32-test" +harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors + +[profile.release] +opt-level = "s" + +[profile.dev] +debug = true # Symbols are nice and they don't increase the size on Flash +opt-level = "z" + +[features] +default = [] + +experimental = ["esp-idf-svc/experimental"] + +[dependencies] +anyhow = { version = "1.0", default-features = false } +esp-idf-svc = "0.51" +log = "0.4" +rustls = { version = "0.23.31", default-features = false, features = [ + "std" +] } +rustls-rustcrypto = { version = "0.0.2-alpha", path = "../..", default-features = false, features = ["aead-chacha20poly1305", "alloc", "der", "ecdsa-p256", "fast", "kx-p256", "pkcs8", "sign-ecdsa-p256", "tls12", "verify-ecdsa-p256", "verify-ecdsa-p256-sha256"] } + +# --- Optional Embassy Integration --- +# esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync"] } + +# If you enable embassy-time-driver, you MUST also add one of: + +# a) Standalone Embassy libs ( embassy-time, embassy-sync etc) with a foreign async runtime: +# embassy-time = { version = "0.4.0", features = ["generic-queue-8"] } # NOTE: any generic-queue variant will work + +# b) With embassy-executor: +# embassy-executor = { version = "0.7", features = ["executor-thread", "arch-std"] } + +# NOTE: if you use embassy-time with embassy-executor you don't need the generic-queue-8 feature + +# --- Temporary workaround for embassy-executor < 0.8 --- +# esp-idf-svc = { version = "0.51", features = ["embassy-time-driver", "embassy-sync"] } +# critical-section = { version = "1.1", features = ["std"], default-features = false } + +[build-dependencies] +embuild = "0.33" diff --git a/validation/esp32-test/README.md b/validation/esp32-test/README.md new file mode 100644 index 0000000..5e841ea --- /dev/null +++ b/validation/esp32-test/README.md @@ -0,0 +1,106 @@ +# ESP32 TLS Test + +A comprehensive test suite for validating TLS functionality on ESP32 microcontrollers using the rustls-rustcrypto provider. This crate performs end-to-end TLS testing with real network sockets, ensuring secure communication works correctly in embedded environments. + +## Overview + +This test crate demonstrates and validates: + +- TLS 1.2 and TLS 1.3 handshake completion +- Secure communication over real TCP sockets +- Certificate-based authentication +- Client-server TLS communication +- RustCrypto provider integration with ESP32 +- Embedded system TLS capabilities + +## Architecture + +The test implements a complete TLS client-server architecture: + +1. **TLS Server**: Runs on ESP32, accepts connections, performs TLS handshake +2. **TLS Client**: Also runs on ESP32, connects to server, sends test messages +3. **Real Sockets**: Uses actual TCP sockets (not mock implementations) +4. **Embedded Certificates**: Includes test certificates compiled into the binary + +## Features + +- ✅ TLS 1.2 and TLS 1.3 support +- ✅ ECDSA certificate authentication +- ✅ AES-GCM and ChaCha20-Poly1305 ciphers +- ✅ Real network socket communication +- ✅ Embedded certificate validation +- ✅ ESP32-specific optimizations +- ✅ Comprehensive logging + +## Prerequisites + +### Hardware Requirements +- ESP32 microcontroller (ESP32, ESP32-S2, ESP32-S3, etc.) +- USB connection for flashing and monitoring + +### Software Requirements +- Rust 1.88.0 or later +- ESP-IDF development environment +- ESP32 Rust toolchain +- OpenSSL (for certificate generation if needed) + +### ESP-IDF Setup + +1. Install ESP-IDF: +```bash +# Using espup (recommended) +cargo install espup +espup install + +# Or manual installation following ESP-IDF docs +``` + +2. Set up the environment: +```bash +# Add to your shell profile +. $HOME/export-esp.sh +``` + +3. Install ESP32 Rust toolchain: +```bash +rustup target add riscv32imc-esp-espidf +# or for ESP32-S2/S3 +rustup target add xtensa-esp32-espidf +``` + +## Usage + +### Running the Test + +1. **Flash to ESP32**: +```bash +cargo run --release +``` + +2. **Monitor Output**: +```bash +# In another terminal +espmonitor /dev/ttyUSB0 # Adjust port as needed +``` + +### Expected Output + +The test will show: +``` +ESP32 Rustls Real Socket TLS Test Starting... +Rustcrypto provider initialized +TLS client config created successfully +TLS server config created successfully +TLS server listening on 127.0.0.1:xxxxx +Accepted connection from 127.0.0.1:xxxxx +TLS handshake completed successfully +Server received: Hello from ESP32 TLS client! +Client received: Echo: Hello from ESP32 TLS client! +TLS client shutting down +TLS server shutting down +ESP32 Rustls Real Socket TLS Test completed! +``` + +## License + +Licensed under the same terms as the rustls-rustcrypto project: Apache-2.0 or MIT. diff --git a/validation/esp32-test/build.rs b/validation/esp32-test/build.rs new file mode 100644 index 0000000..112ec3f --- /dev/null +++ b/validation/esp32-test/build.rs @@ -0,0 +1,3 @@ +fn main() { + embuild::espidf::sysenv::output(); +} diff --git a/validation/esp32-test/rust-toolchain.toml b/validation/esp32-test/rust-toolchain.toml new file mode 100644 index 0000000..f70d225 --- /dev/null +++ b/validation/esp32-test/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly" +components = ["rust-src"] diff --git a/validation/esp32-test/sdkconfig.defaults b/validation/esp32-test/sdkconfig.defaults new file mode 100644 index 0000000..c25b89d --- /dev/null +++ b/validation/esp32-test/sdkconfig.defaults @@ -0,0 +1,10 @@ +# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000 + +# Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). +# This allows to use 1 ms granularity for thread sleeps (10 ms by default). +#CONFIG_FREERTOS_HZ=1000 + +# Workaround for https://github.com/espressif/esp-idf/issues/7631 +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n diff --git a/validation/esp32-test/src/cert.der b/validation/esp32-test/src/cert.der new file mode 100644 index 0000000..f399cd3 Binary files /dev/null and b/validation/esp32-test/src/cert.der differ diff --git a/validation/esp32-test/src/key.der b/validation/esp32-test/src/key.der new file mode 100644 index 0000000..bdb93a9 Binary files /dev/null and b/validation/esp32-test/src/key.der differ diff --git a/validation/esp32-test/src/main.rs b/validation/esp32-test/src/main.rs new file mode 100644 index 0000000..339489f --- /dev/null +++ b/validation/esp32-test/src/main.rs @@ -0,0 +1,240 @@ +use std::io::{Read, Write}; +use std::net::{TcpListener, TcpStream}; +use std::sync::{mpsc, Arc}; +use std::thread; +use std::time::Duration; + +use esp_idf_svc::log::EspLogger; +use esp_idf_svc::sys::link_patches; +use log::{error, info}; + +use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; +use rustls::client::ClientConfig; +use rustls::pki_types::{CertificateDer, PrivateKeyDer, ServerName, UnixTime}; +use rustls::server::ServerConfig; +use rustls::{ClientConnection, ServerConnection, SignatureScheme, Stream}; +use rustls_rustcrypto::provider as rustcrypto_provider; + +fn main() -> anyhow::Result<()> { + // It is necessary to call this function once. Otherwise some patches to the runtime + // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71 + link_patches(); + + // Bind the log crate to the ESP Logging facilities + EspLogger::initialize_default(); + + info!("ESP32 Rustls Real Socket TLS Test Starting..."); + + // Initialize rustls with rustcrypto provider + let provider = Arc::new(rustcrypto_provider()); + info!("Rustcrypto provider initialized"); + + // Create TLS configurations + let client_config = ClientConfig::builder_with_provider(provider.clone()) + .with_safe_default_protocol_versions()? + .dangerous() + .with_custom_certificate_verifier(Arc::new(NoCertificateVerification)) + .with_no_client_auth(); + info!("TLS client config created successfully"); + + let server_config = ServerConfig::builder_with_provider(provider) + .with_safe_default_protocol_versions()? + .with_no_client_auth() + .with_single_cert( + vec![const { CertificateDer::from_slice(include_bytes!("cert.der")) }], + PrivateKeyDer::Pkcs8(include_bytes!("key.der").as_slice().into()), + )?; + info!("TLS server config created successfully"); + + let (tx, rx) = mpsc::channel(); + + // Start TLS server in a separate thread + let server_handle = thread::spawn(move || { + run_tls_server(server_config, tx); + }); + + // Give server time to start + thread::sleep(Duration::from_millis(100)); + + // Start TLS client in another thread + let client_handle = thread::spawn(move || { + if let Ok(port) = rx.recv() { + run_tls_client(client_config, port); + } else { + error!("Failed to receive port from server thread"); + } + }); + + // Wait for both threads to complete + if let Err(e) = server_handle.join() { + error!("Server thread panicked: {:?}", e); + } + + if let Err(e) = client_handle.join() { + error!("Client thread panicked: {:?}", e); + } + + info!("ESP32 Rustls Real Socket TLS Test completed!"); + Ok(()) +} + +fn run_tls_server(server_config: ServerConfig, tx: mpsc::Sender) { + info!("Starting TLS server..."); + + // Bind to a random port and send it to the client thread + let listener = match TcpListener::bind("127.0.0.1:0") { + Ok(listener) => { + let addr = listener.local_addr().unwrap(); + info!("TLS server listening on {}", addr); + if tx.send(addr.port()).is_err() { + error!("Failed to send port to client thread"); + return; + } + listener + } + Err(e) => { + error!("Failed to bind server: {:?}", e); + return; + } + }; + + // Accept one connection for testing + match listener.accept() { + Ok((mut tcp_stream, addr)) => { + info!("Accepted connection from {}", addr); + + let mut tls_conn = match ServerConnection::new(Arc::new(server_config)) { + Ok(conn) => conn, + Err(e) => { + error!("Failed to create TLS server connection: {:?}", e); + return; + } + }; + + let mut tls_stream = Stream::new(&mut tls_conn, &mut tcp_stream); + + info!("TLS handshake completed successfully"); + + // Read and echo data + let mut buffer = [0; 1024]; + match tls_stream.read(&mut buffer) { + Ok(n) if n > 0 => { + let received = String::from_utf8_lossy(&buffer[..n]); + info!("Server received: {}", received.trim()); + + // Echo back + if let Err(e) = tls_stream.write_all(format!("Echo: {}", received).as_bytes()) { + error!("Failed to write response: {:?}", e); + } + } + Ok(_) => info!("Connection closed by client"), + Err(e) => error!("Read error: {:?}", e), + } + } + Err(e) => { + error!("Accept failed: {:?}", e); + } + } + + info!("TLS server shutting down"); +} + +fn run_tls_client(client_config: ClientConfig, port: u16) { + info!("Starting TLS client..."); + + // Connect to the server on the port received from the channel + let server_addr = format!("127.0.0.1:{}", port); + + let mut tcp_stream = match TcpStream::connect(&server_addr) { + Ok(stream) => { + info!("Connected to server at {}", server_addr); + stream + } + Err(e) => { + error!("Failed to connect to server: {:?}", e); + return; + } + }; + + let server_name = match ServerName::try_from("localhost") { + Ok(name) => name, + Err(e) => { + error!("Invalid server name: {:?}", e); + return; + } + }; + + let mut tls_conn = match ClientConnection::new(Arc::new(client_config), server_name) { + Ok(conn) => conn, + Err(e) => { + error!("Failed to create TLS client connection: {:?}", e); + return; + } + }; + + let mut tls_stream = Stream::new(&mut tls_conn, &mut tcp_stream); + + info!("TLS handshake completed successfully"); + + // Send test message + let test_message = "Hello from ESP32 TLS client!"; + if let Err(e) = tls_stream.write_all(test_message.as_bytes()) { + error!("Failed to send message: {:?}", e); + return; + } + + // Read response + let mut buffer = [0; 1024]; + match tls_stream.read(&mut buffer) { + Ok(n) if n > 0 => { + let response = String::from_utf8_lossy(&buffer[..n]); + info!("Client received: {}", response.trim()); + } + Ok(_) => info!("Server closed connection"), + Err(e) => error!("Read error: {:?}", e), + } + + info!("TLS client shutting down"); +} + +// Dummy certificate verifier for testing (DO NOT USE IN PRODUCTION) +#[derive(Debug)] +struct NoCertificateVerification; + +impl ServerCertVerifier for NoCertificateVerification { + fn verify_server_cert( + &self, + _end_entity: &CertificateDer, + _intermediates: &[CertificateDer], + _server_name: &ServerName, + _ocsp_response: &[u8], + _now: UnixTime, + ) -> Result { + Ok(ServerCertVerified::assertion()) + } + + fn verify_tls12_signature( + &self, + _message: &[u8], + _cert: &CertificateDer, + _dss: &rustls::DigitallySignedStruct, + ) -> Result { + Ok(HandshakeSignatureValid::assertion()) + } + + fn verify_tls13_signature( + &self, + _message: &[u8], + _cert: &CertificateDer, + _dss: &rustls::DigitallySignedStruct, + ) -> Result { + Ok(HandshakeSignatureValid::assertion()) + } + + fn supported_verify_schemes(&self) -> Vec { + vec![ + SignatureScheme::RSA_PKCS1_SHA256, + SignatureScheme::ECDSA_NISTP256_SHA256, + ] + } +} diff --git a/validation/local_ping_pong_openssl/Cargo.lock b/validation/local_ping_pong_openssl/Cargo.lock index d6eebf0..07f69b7 100644 --- a/validation/local_ping_pong_openssl/Cargo.lock +++ b/validation/local_ping_pong_openssl/Cargo.lock @@ -1,98 +1,108 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aead" -version = "0.5.2" +version = "0.6.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" dependencies = [ "crypto-common", - "generic-array", + "inout", ] [[package]] name = "aes" -version = "0.8.4" +version = "0.9.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +checksum = "7e713c57c2a2b19159e7be83b9194600d7e8eb3b7c2cd67e671adf47ce189a05" dependencies = [ "cfg-if", "cipher", "cpufeatures", + "zeroize", ] [[package]] name = "aes-gcm" -version = "0.10.3" +version = "0.11.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +checksum = "0686ba04dc80c816104c96cd7782b748f6ad58c5dd4ee619ff3258cf68e83d54" dependencies = [ "aead", - "aes", "cipher", "ctr", "ghash", "subtle", + "zeroize", ] [[package]] name = "autocfg" -version = "1.2.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base16ct" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" [[package]] name = "block-buffer" -version = "0.10.4" +version = "0.11.0-rc.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] -name = "byteorder" -version = "1.5.0" +name = "cc" +version = "1.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44" +dependencies = [ + "find-msvc-tools", + "shlex", +] [[package]] -name = "cc" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +name = "ccm" +version = "0.6.0-pre" +source = "git+https://github.com/RustCrypto/AEADs/#faac9cf5697336d05f3c252a57833f751e3f7f45" +dependencies = [ + "aead", + "cipher", + "ctr", + "subtle", +] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "chacha20" -version = "0.9.1" +version = "0.10.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +checksum = "9bd162f2b8af3e0639d83f28a637e4e55657b7a74508dba5a9bf4da523d5c9e9" dependencies = [ "cfg-if", "cipher", @@ -101,86 +111,96 @@ dependencies = [ [[package]] name = "chacha20poly1305" -version = "0.10.1" +version = "0.11.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +checksum = "ecc260dd2c69bf5581e9603fff348843363a649edde02768e84c0088f21c3f52" dependencies = [ "aead", "chacha20", "cipher", "poly1305", - "zeroize", ] [[package]] name = "cipher" -version = "0.4.4" +version = "0.5.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" dependencies = [ + "block-buffer", "crypto-common", "inout", - "zeroize", ] [[package]] name = "const-oid" -version = "0.9.6" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crypto-bigint" -version = "0.5.5" +version = "0.7.0-rc.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +checksum = "f2966eb7f877e5cdac7e808e71010d0bef6321d58b8e58bf01b8bbbe44f77ea0" dependencies = [ - "generic-array", + "hybrid-array", + "num-traits", "rand_core", + "serdect", "subtle", "zeroize", ] [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.2.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" dependencies = [ - "generic-array", - "typenum", + "hybrid-array", +] + +[[package]] +name = "crypto-primes" +version = "0.7.0-pre.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f2523fbb68811c8710829417ad488086720a6349e337c38d12fa81e09e50bf" +dependencies = [ + "crypto-bigint", + "libm", + "rand_core", ] [[package]] name = "ctr" -version = "0.9.2" +version = "0.10.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +checksum = "27e41d01c6f73b9330177f5cf782ae5b581b5f2c7840e298e0275ceee5001434" dependencies = [ "cipher", ] [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "5.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "6f9200d1d13637f15a6acb71e758f64624048d85b31a5fdbfd8eca1e2687d0b7" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -199,20 +219,20 @@ dependencies = [ [[package]] name = "der" -version = "0.7.9" +version = "0.8.0-rc.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "7050e8041c28720851f7db83183195b6acf375bb7bb28e3b86f0fe6cbd69459d" dependencies = [ "const-oid", - "pem-rfc7468", + "pem-rfc7468 1.0.0-rc.3", "zeroize", ] [[package]] name = "digest" -version = "0.10.7" +version = "0.11.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "3a4aae35a0fcbe22ff1be50fe96df72002d5a4a6fb4aae9193cf2da0daa36da2" dependencies = [ "block-buffer", "const-oid", @@ -222,9 +242,9 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.9" +version = "0.17.0-rc.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +checksum = "b4ab355ec063f7a110eb627471058093aba00eb7f4e70afbd15e696b79d1077b" dependencies = [ "der", "digest", @@ -232,13 +252,14 @@ dependencies = [ "rfc6979", "signature", "spki", + "zeroize", ] [[package]] name = "ed25519" -version = "2.2.3" +version = "3.0.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +checksum = "9ef49c0b20c0ad088893ad2a790a29c06a012b3f05bcfc66661fd22a94b32129" dependencies = [ "pkcs8", "signature", @@ -246,32 +267,59 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.1" +version = "3.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +checksum = "ad207ed88a133091f83224265eac21109930db09bedcad05d5252f2af2de20a1" dependencies = [ "curve25519-dalek", "ed25519", "serde", "sha2", + "signature", "subtle", "zeroize", ] +[[package]] +name = "ed448" +version = "0.5.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812bad302d88d3e1774df473dffc64f18fedc4be6b6066c470ae3c733b9f9765" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed448-goldilocks" +version = "0.14.0-pre.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6640f5292892cf2f68d41e85739e4488271c041c877f60921e267a135d3186af" +dependencies = [ + "ed448", + "elliptic-curve", + "hash2curve", + "rand_core", + "serdect", + "sha3", + "signature", + "subtle", +] + [[package]] name = "elliptic-curve" -version = "0.13.8" +version = "0.14.0-rc.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +checksum = "6ae7ba52b8bca06caab3e74b7cf8858a2934e6e75d80b03dbe48d2d394a4489c" dependencies = [ "base16ct", "crypto-bigint", "digest", "ff", - "generic-array", "group", "hkdf", - "pem-rfc7468", + "hybrid-array", + "pem-rfc7468 1.0.0-rc.3", "pkcs8", "rand_core", "sec1", @@ -281,9 +329,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.13.0" +version = "0.14.0-pre.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "d42dd26f5790eda47c1a2158ea4120e32c35ddc9a7743c98a292accc01b54ef3" dependencies = [ "rand_core", "subtle", @@ -291,9 +339,15 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.8" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + +[[package]] +name = "find-msvc-tools" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38793c55593b33412e3ae40c2c9781ffaa6f438f6f8c10f24e71846fbd7ae01e" +checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" [[package]] name = "foreign-types" @@ -311,170 +365,148 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] -name = "generic-array" -version = "0.14.7" +name = "getrandom" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "typenum", - "version_check", - "zeroize", + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.2.14" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "wasi", + "r-efi", + "wasi 0.14.6+wasi-0.2.4", ] [[package]] name = "ghash" -version = "0.5.1" +version = "0.6.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +checksum = "4f88107cb02ed63adcc4282942e60c4d09d80208d33b360ce7c729ce6dae1739" dependencies = [ - "opaque-debug", "polyval", ] [[package]] name = "group" -version = "0.13.0" +version = "0.14.0-pre.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +checksum = "1ff6a0b2dd4b981b1ae9e3e6830ab146771f3660d31d57bafd9018805a91b0f1" dependencies = [ "ff", "rand_core", "subtle", ] +[[package]] +name = "hash2curve" +version = "0.14.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4dc9fc1e7c8838651b0541e9af3ae5d39114bed92d199fcace0d1c684c752c9" +dependencies = [ + "digest", + "elliptic-curve", + "ff", + "subtle", +] + [[package]] name = "hkdf" -version = "0.12.4" +version = "0.13.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +checksum = "7984b5d6605e93b2787c95aef698b3c28933a4d7f9fd09d46f54130da1efaee0" dependencies = [ "hmac", ] [[package]] name = "hmac" -version = "0.12.1" +version = "0.13.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "49e206bca159aebaaed410f5e78b2fe56bfc0dd5b19ecae922813b8556b8b07e" dependencies = [ "digest", ] +[[package]] +name = "hybrid-array" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7116c472cf19838450b1d421b4e842569f52b519d640aee9ace1ebcf5b21051" +dependencies = [ + "typenum", + "zeroize", +] + [[package]] name = "inout" -version = "0.1.3" +version = "0.2.0-rc.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "1603f76010ff924b616c8f44815a42eb10fb0b93d308b41deaa8da6d4251fd4b" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "keccak" +version = "0.2.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "3d546793a04a1d3049bd192856f804cfe96356e2cf36b54b4e575155babe9f41" dependencies = [ - "spin 0.5.2", + "cpufeatures", ] [[package]] name = "libc" -version = "0.2.153" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "local_ping_pong_openssl" version = "0.0.0" dependencies = [ "openssl", - "pem-rfc7468", + "pem-rfc7468 0.7.0", "rustls", "rustls-rustcrypto", ] -[[package]] -name = "num-bigint-dig" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" -dependencies = [ - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "opaque-debug" -version = "0.3.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ "bitflags", "cfg-if", @@ -498,9 +530,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -510,33 +542,44 @@ dependencies = [ [[package]] name = "p256" -version = "0.13.2" +version = "0.14.0-pre.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +checksum = "81b374901df34ee468167a58e2a49e468cb059868479cafebeb804f6b855423d" dependencies = [ "ecdsa", "elliptic-curve", + "primefield", "primeorder", "sha2", ] [[package]] name = "p384" -version = "0.13.0" +version = "0.14.0-pre.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +checksum = "701032b3730df6b882496d6cee8221de0ce4bc11ddc64e6d89784aa5b8a6de30" dependencies = [ "ecdsa", "elliptic-curve", + "fiat-crypto", + "primefield", "primeorder", "sha2", ] [[package]] -name = "paste" -version = "1.0.14" +name = "p521" +version = "0.14.0-pre.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "40ba29c2906eb5c89a8c411c4f11243ee4e5517ee7d71d9a13fedc877a6057b1" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primefield", + "primeorder", + "sha2", +] [[package]] name = "pem-rfc7468" @@ -548,21 +591,19 @@ dependencies = [ ] [[package]] -name = "pkcs1" -version = "0.7.5" +name = "pem-rfc7468" +version = "1.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +checksum = "a8e58fab693c712c0d4e88f8eb3087b6521d060bcaf76aeb20cb192d809115ba" dependencies = [ - "der", - "pkcs8", - "spki", + "base64ct", ] [[package]] -name = "pkcs5" -version = "0.7.1" +name = "pkcs1" +version = "0.8.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" +checksum = "b2345503b65d9be13aac96ddbec3eed60def8bc83869f9a519789afbcf3c2bea" dependencies = [ "der", "spki", @@ -570,117 +611,101 @@ dependencies = [ [[package]] name = "pkcs8" -version = "0.10.2" +version = "0.11.0-rc.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +checksum = "c53e5d0804fa4070b1b2a5b320102f2c1c094920a7533d5d87c2630609bcbd34" dependencies = [ "der", - "pkcs5", "spki", ] [[package]] name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "platforms" -version = "3.4.0" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "poly1305" -version = "0.8.0" +version = "0.9.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +checksum = "fb78a635f75d76d856374961deecf61031c0b6f928c83dc9c0924ab6c019c298" dependencies = [ "cpufeatures", - "opaque-debug", "universal-hash", ] [[package]] name = "polyval" -version = "0.6.2" +version = "0.7.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +checksum = "1ffd40cc99d0fbb02b4b3771346b811df94194bc103983efa0203c8893755085" dependencies = [ "cfg-if", "cpufeatures", - "opaque-debug", "universal-hash", ] [[package]] -name = "ppv-lite86" -version = "0.2.17" +name = "primefield" +version = "0.14.0-pre.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "d7fcd4a163053332fd93f39b81c133e96a98567660981654579c90a99062fbf5" +dependencies = [ + "crypto-bigint", + "ff", + "rand_core", + "subtle", + "zeroize", +] [[package]] name = "primeorder" -version = "0.13.6" +version = "0.14.0-pre.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +checksum = "1c36e8766fcd270fa9c665b9dc364f570695f5a59240949441b077a397f15b74" dependencies = [ "elliptic-curve", ] [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom", + "getrandom 0.3.3", ] [[package]] name = "rfc6979" -version = "0.4.0" +version = "0.5.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +checksum = "d369f9c4f79388704648e7bcb92749c0d6cf4397039293a9b747694fa4fb4bae" dependencies = [ "hmac", "subtle", @@ -688,30 +713,28 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.8" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.16", "libc", - "spin 0.9.8", "untrusted", "windows-sys", ] [[package]] name = "rsa" -version = "0.9.6" +version = "0.10.0-rc.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "fd8c26d4f6d0d2689c1cc822ac369edb64b4a090bc53141ae563bfa19c797300" dependencies = [ "const-oid", + "crypto-bigint", + "crypto-primes", "digest", - "num-bigint-dig", - "num-integer", - "num-traits", "pkcs1", "pkcs8", "rand_core", @@ -724,18 +747,18 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustls" -version = "0.23.5" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afabcee0551bd1aa3e18e5adbf2c0544722014b899adb31bd186ec638d3da97e" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "once_cell", "rustls-pki-types", @@ -746,26 +769,35 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.5.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-rustcrypto" -version = "0.1.0" +version = "0.0.2-alpha" dependencies = [ "aead", + "aes", "aes-gcm", + "ccm", "chacha20poly1305", + "cipher", "crypto-common", "der", "digest", "ecdsa", "ed25519-dalek", + "ed448-goldilocks", + "elliptic-curve", "hmac", "p256", "p384", - "paste", + "p521", + "pkcs1", "pkcs8", "rand_core", "rsa", @@ -775,14 +807,16 @@ dependencies = [ "sec1", "sha2", "signature", + "typenum", "x25519-dalek", + "x448", ] [[package]] name = "rustls-webpki" -version = "0.102.3" +version = "0.103.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" dependencies = [ "ring", "rustls-pki-types", @@ -791,49 +825,67 @@ dependencies = [ [[package]] name = "sec1" -version = "0.7.3" +version = "0.8.0-rc.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +checksum = "f5e67a3c9fb9a8f065af9fa30d65812fcc16a66cbf911eff1f6946957ce48f16" dependencies = [ "base16ct", "der", - "generic-array", - "pkcs8", + "hybrid-array", "subtle", "zeroize", ] [[package]] name = "semver" -version = "1.0.22" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.199" +version = "1.0.224" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aaeb1e94f53b16384af593c71e20b095e958dab1d26939c1b70645c5cfbcc0b" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.224" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" +checksum = "32f39390fa6346e24defbcdd3d9544ba8a19985d0af74df8501fbfe9a64341ab" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.199" +version = "1.0.224" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" +checksum = "87ff78ab5e8561c9a675bfc1785cb07ae721f0ee53329a595cefd8c04c2ac4e0" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "serdect" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha2" -version = "0.10.8" +version = "0.11.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "d1e3878ab0f98e35b2df35fe53201d088299b41a6bb63e3e34dada2ac4abd924" dependencies = [ "cfg-if", "cpufeatures", @@ -841,38 +893,36 @@ dependencies = [ ] [[package]] -name = "signature" -version = "2.2.0" +name = "sha3" +version = "0.11.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +checksum = "2103ca0e6f4e9505eae906de5e5883e06fc3b2232fb5d6914890c7bbcb62f478" dependencies = [ "digest", - "rand_core", + "keccak", ] [[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "spin" -version = "0.5.2" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "spin" -version = "0.9.8" +name = "signature" +version = "3.0.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "fc280a6ff65c79fbd6622f64d7127f32b85563bca8c53cd2e9141d6744a9056d" +dependencies = [ + "digest", + "rand_core", +] [[package]] name = "spki" -version = "0.7.3" +version = "0.8.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" dependencies = [ "base64ct", "der", @@ -880,15 +930,15 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.60" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -897,21 +947,21 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "universal-hash" -version = "0.5.1" +version = "0.6.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" dependencies = [ "crypto-common", "subtle", @@ -930,16 +980,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] -name = "version_check" -version = "0.9.4" +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.14.6+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "7f71243a3f320c00a8459e455c046ce571229c2f31fd11645d9dc095e3068ca0" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] [[package]] name = "windows-sys" @@ -952,9 +1014,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -968,68 +1030,85 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "x25519-dalek" -version = "2.0.1" +version = "3.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +checksum = "3a45998121837fd8c92655d2334aa8f3e5ef0645cdfda5b321b13760c548fd55" dependencies = [ "curve25519-dalek", "rand_core", "zeroize", ] +[[package]] +name = "x448" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20e03d60707405e830d70c431a837b0df7a04450e50caee26a5a5a1bb78b7c9" +dependencies = [ + "ed448-goldilocks", + "rand_core", + "zeroize", +] + [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] diff --git a/validation/local_ping_pong_openssl/Cargo.toml b/validation/local_ping_pong_openssl/Cargo.toml index 9b224ac..5f60365 100644 --- a/validation/local_ping_pong_openssl/Cargo.toml +++ b/validation/local_ping_pong_openssl/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "MIT OR Apache-2.0" [dependencies] -rustls = { version = "0.23.0", default-features = false, features = ["std"] } +rustls = { version = "0.23.31", default-features = false, features = ["std"] } rustls-rustcrypto = { path = "../../" } openssl = { version = "0.10", default-features = false } pem-rfc7468 = { version = "0.7", default-features = false, features = ["alloc"] } diff --git a/validation/local_ping_pong_openssl/src/lib.rs b/validation/local_ping_pong_openssl/src/lib.rs index e4b659d..a76579f 100644 --- a/validation/local_ping_pong_openssl/src/lib.rs +++ b/validation/local_ping_pong_openssl/src/lib.rs @@ -74,7 +74,6 @@ mod test { } #[test] - #[should_panic] // no_shared_cipher fn vs_openssl_as_client_ccm_sha256() { let cipher_suites = OpenSslCipherSuites { TLS_AES_128_GCM_SHA256: false, @@ -87,7 +86,6 @@ mod test { } #[test] - #[should_panic] // no_shared_cipher fn vs_openssl_as_client_ccm8_sha256() { let cipher_suites = OpenSslCipherSuites { TLS_AES_128_GCM_SHA256: false, @@ -118,7 +116,6 @@ mod test { vs_openssl_as_client(group_list, OpenSslCipherSuites::default()); } #[test] - #[should_panic] // no support fn vs_openssl_as_client_group_p521() { let mut group_list = OpenSslGroupsList::all_false(); group_list.P521 = true; @@ -131,7 +128,6 @@ mod test { vs_openssl_as_client(group_list, OpenSslCipherSuites::default()); } #[test] - #[should_panic] // no support fn vs_openssl_as_client_group_x448() { let mut group_list = OpenSslGroupsList::all_false(); group_list.X448 = true; diff --git a/validation/quic-test/Cargo.lock b/validation/quic-test/Cargo.lock new file mode 100644 index 0000000..8ef1623 --- /dev/null +++ b/validation/quic-test/Cargo.lock @@ -0,0 +1,2662 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aead" +version = "0.6.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "aes" +version = "0.9.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e713c57c2a2b19159e7be83b9194600d7e8eb3b7c2cd67e671adf47ce189a05" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.11.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0686ba04dc80c816104c96cd7782b748f6ad58c5dd4ee619ff3258cf68e83d54" +dependencies = [ + "aead", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "anyhow" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base16ct" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" + +[[package]] +name = "block-buffer" +version = "0.11.0-rc.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cc" +version = "1.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chacha20" +version = "0.10.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd162f2b8af3e0639d83f28a637e4e55657b7a74508dba5a9bf4da523d5c9e9" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.11.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc260dd2c69bf5581e9603fff348843363a649edde02768e84c0088f21c3f52" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", +] + +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link 0.2.0", +] + +[[package]] +name = "cipher" +version = "0.5.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" +dependencies = [ + "block-buffer", + "crypto-common", + "inout", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "const-oid" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-bigint" +version = "0.7.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c069823f41bdc75e99546bfd59eb1ed27d69dc720e5c949fe502b82926f8448" +dependencies = [ + "hybrid-array", + "num-traits", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.2.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "ctr" +version = "0.10.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27e41d01c6f73b9330177f5cf782ae5b581b5f2c7840e298e0275ceee5001434" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "5.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f9200d1d13637f15a6acb71e758f64624048d85b31a5fdbfd8eca1e2687d0b7" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", + "quote", + "syn", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "der" +version = "0.8.0-rc.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7050e8041c28720851f7db83183195b6acf375bb7bb28e3b86f0fe6cbd69459d" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.11.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4aae35a0fcbe22ff1be50fe96df72002d5a4a6fb4aae9193cf2da0daa36da2" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dlopen2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +dependencies = [ + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "ecdsa" +version = "0.17.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aa27d88fe1d40a293286027c9306393094d9b36ccd91f2ac4d647870dc0042" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", + "zeroize", +] + +[[package]] +name = "ed25519" +version = "3.0.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe639324ff99c3bf32144aaf79dc7e048305a6e82b6409644ddcbe7e0f5f5be9" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "3.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad207ed88a133091f83224265eac21109930db09bedcad05d5252f2af2de20a1" +dependencies = [ + "curve25519-dalek", + "ed25519", + "sha2", + "subtle", +] + +[[package]] +name = "ed448" +version = "0.5.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f3621b15eb4095d0e7c2502abd44291413b8a638f88dc08f1188993143332b" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed448-goldilocks" +version = "0.14.0-pre.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c1833a8f682ff0628f3b7ae755c5ea17854d7bdadf90c017feef4e84b78bb2" +dependencies = [ + "ed448", + "elliptic-curve", + "hash2curve", + "rand_core", + "serdect", + "sha3", + "signature", + "subtle", +] + +[[package]] +name = "elliptic-curve" +version = "0.14.0-rc.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b95fd42abd85018a59f5dbe05551e9eed19edfd1182a415cd98f90ca5af1422" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "group", + "hkdf", + "hybrid-array", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "ff" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d42dd26f5790eda47c1a2158ea4120e32c35ddc9a7743c98a292accc01b54ef3" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + +[[package]] +name = "find-msvc-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.5+wasi-0.2.4", +] + +[[package]] +name = "getset" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ghash" +version = "0.6.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f88107cb02ed63adcc4282942e60c4d09d80208d33b360ce7c729ce6dae1739" +dependencies = [ + "polyval", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gm-quic" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03aa5a709fb0a534c7d1ebd48cd2d3d7058f774d90d6657808e6333641b8fdd2" +dependencies = [ + "bytes", + "dashmap", + "derive_more", + "futures", + "qbase", + "qcongestion", + "qconnection", + "qevent", + "qinterface", + "qrecovery", + "qunreliable", + "rustls", + "thiserror 2.0.16", + "tokio", + "tracing", +] + +[[package]] +name = "group" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff6a0b2dd4b981b1ae9e3e6830ab146771f3660d31d57bafd9018805a91b0f1" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hash2curve" +version = "0.14.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d3a227db59d3140ef8cfcf56a8c5c3bd7c10f7363100bc0e430628d3e3bfc6" +dependencies = [ + "digest", + "elliptic-curve", + "ff", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.13.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7984b5d6605e93b2787c95aef698b3c28933a4d7f9fd09d46f54130da1efaee0" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.13.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e206bca159aebaaed410f5e78b2fe56bfc0dd5b19ecae922813b8556b8b07e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "hybrid-array" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7116c472cf19838450b1d421b4e842569f52b519d640aee9ace1ebcf5b21051" +dependencies = [ + "typenum", + "zeroize", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", + "serde", + "serde_core", +] + +[[package]] +name = "inout" +version = "0.2.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1603f76010ff924b616c8f44815a42eb10fb0b93d308b41deaa8da6d4251fd4b" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "io-uring" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "libc", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "js-sys" +version = "0.3.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.2.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d546793a04a1d3049bd192856f804cfe96356e2cf36b54b4e575155babe9f41" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "netdev" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f901362e84cd407be6f8cd9d3a46bccf09136b095792785401ea7d283c79b91d" +dependencies = [ + "dlopen2", + "ipnet", + "libc", + "netlink-packet-core", + "netlink-packet-route", + "netlink-sys", + "once_cell", + "system-configuration", + "windows-sys 0.52.0", +] + +[[package]] +name = "netlink-packet-core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +dependencies = [ + "anyhow", + "byteorder", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "byteorder", + "libc", + "netlink-packet-core", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-utils" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +dependencies = [ + "anyhow", + "byteorder", + "paste", + "thiserror 1.0.69", +] + +[[package]] +name = "netlink-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16c903aa70590cb93691bf97a767c8d1d6122d2cc9070433deb3bbf36ce8bd23" +dependencies = [ + "bytes", + "libc", + "log", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "p256" +version = "0.14.0-pre.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa93e068b773d56fe26be53accf127d6eb0fde35e4116b7a9276db97b6a50ec9" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primefield", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.14.0-pre.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d17e7d4276af996c6c52de52db4df6b676c5efc3a4269e56c9473edee1786d" +dependencies = [ + "ecdsa", + "elliptic-curve", +] + +[[package]] +name = "p521" +version = "0.14.0-pre.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a70f4308991bf35f1632d55155c3ca137f9ce05c6de00be51705bbaa3451cfe" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.11.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c53e5d0804fa4070b1b2a5b320102f2c1c094920a7533d5d87c2630609bcbd34" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "poly1305" +version = "0.9.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb78a635f75d76d856374961deecf61031c0b6f928c83dc9c0924ab6c019c298" +dependencies = [ + "cpufeatures", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.7.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffd40cc99d0fbb02b4b3771346b811df94194bc103983efa0203c8893755085" +dependencies = [ + "cfg-if", + "cpufeatures", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "primefield" +version = "0.14.0-pre.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049f40103b7e4b0da4e20ed8556805efa740f7104c48991c5f9ab8e09e10ee21" +dependencies = [ + "crypto-bigint", + "ff", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "primeorder" +version = "0.14.0-pre.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9257332cf7e56fa8183f719977b92f1878cb1447275d0ee280a08bcd6fad158f" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "qbase" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6badb9f22ba4f63aa955bc3b3a53812e8df68b5e67e796f6e828277f021ab44" +dependencies = [ + "bitflags 2.9.4", + "bytes", + "derive_more", + "enum_dispatch", + "futures", + "getset", + "http", + "netdev", + "nom", + "qmacro", + "rand", + "rustls", + "serde", + "thiserror 2.0.16", + "tracing", +] + +[[package]] +name = "qcongestion" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a9298ef93c20564dacae45a409d112a9dc21d7f9a666f8fa593729e611d3c" +dependencies = [ + "qbase", + "qevent", + "rand", + "thiserror 2.0.16", + "tokio", + "tracing", +] + +[[package]] +name = "qconnection" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5d08b9bf155480ded36015369e4ec5983e9d3de4fa6467a3e4088dc9fb6f81" +dependencies = [ + "bytes", + "dashmap", + "derive_more", + "enum_dispatch", + "futures", + "qbase", + "qcongestion", + "qevent", + "qinterface", + "qrecovery", + "qunreliable", + "rustls", + "thiserror 2.0.16", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "qevent" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8490732161a7ad50f8144dadc156f2bcaef8a2b7355f7f51020066b43912dd7" +dependencies = [ + "bytes", + "derive_builder", + "derive_more", + "enum_dispatch", + "pin-project-lite", + "qbase", + "serde", + "serde_json", + "serde_with", + "tokio", + "tracing", +] + +[[package]] +name = "qinterface" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f7a45f4ce12b22c93e017398e9f13a3004691551358bc735d6a57c830467bb" +dependencies = [ + "bytes", + "dashmap", + "derive_more", + "futures", + "netdev", + "qbase", + "qevent", + "qudp", + "rustls", + "serde", + "thiserror 2.0.16", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "qmacro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3477b644b00437d36c42d40111f97726594454c678bc0ea6abc534ff2391f5be" +dependencies = [ + "darling 0.21.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "qrecovery" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07b4718e6f278c3d1d42af5d0c966d8815e4ae96b961a78fda47fbf2d4d472f5" +dependencies = [ + "bytes", + "derive_more", + "enum_dispatch", + "futures", + "qbase", + "qevent", + "rand", + "rustls", + "thiserror 2.0.16", + "tokio", + "tracing", +] + +[[package]] +name = "qudp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2af017cdc55341e051e0fb31b47490067f0b622121562b7d8548fd3de7bdb07" +dependencies = [ + "bytes", + "cfg-if", + "libc", + "nix", + "socket2", + "tokio", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quic-test" +version = "0.1.0" +dependencies = [ + "anyhow", + "env_logger", + "gm-quic", + "log", + "rustls", + "rustls-rustcrypto", + "tokio", +] + +[[package]] +name = "qunreliable" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89addff4ac6f475be4378e1fa544ea28e0f9797f4039d78ff511c99c75816985" +dependencies = [ + "bytes", + "futures", + "qbase", + "tokio", + "tracing", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "redox_syscall" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +dependencies = [ + "bitflags 2.9.4", +] + +[[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "regex" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + +[[package]] +name = "rfc6979" +version = "0.5.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369f9c4f79388704648e7bcb92749c0d6cf4397039293a9b747694fa4fb4bae" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.23.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +dependencies = [ + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-rustcrypto" +version = "0.0.2-alpha" +dependencies = [ + "aead", + "aes", + "aes-gcm", + "chacha20", + "chacha20poly1305", + "cipher", + "crypto-common", + "der", + "digest", + "ecdsa", + "ed25519-dalek", + "ed448-goldilocks", + "elliptic-curve", + "enum_dispatch", + "hmac", + "p256", + "p384", + "p521", + "pkcs8", + "rand_core", + "rustls", + "rustls-pki-types", + "rustls-webpki", + "sec1", + "sha2", + "signature", + "tinyvec", + "typenum", + "x25519-dalek", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a37813727b78798e53c2bec3f5e8fe12a6d6f8389bf9ca7802add4c9905ad8" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.8.0-rc.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e67a3c9fb9a8f065af9fa30d65812fcc16a66cbf911eff1f6946957ce48f16" +dependencies = [ + "base16ct", + "der", + "hybrid-array", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.226" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.226" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.226" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_with" +version = "3.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.11.4", + "schemars 0.9.0", + "schemars 1.0.4", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327ada00f7d64abaac1e55a6911e90cf665aa051b9a561c7006c157f4633135e" +dependencies = [ + "darling 0.21.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serdect" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha2" +version = "0.11.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1e3878ab0f98e35b2df35fe53201d088299b41a6bb63e3e34dada2ac4abd924" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.11.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2103ca0e6f4e9505eae906de5e5883e06fc3b2232fb5d6914890c7bbcb62f478" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "3.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39195ff4c0dc41c93e123825ca1f0d11b856df8b26d5fe140a522355632c4345" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "spki" +version = "0.8.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.9.4", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +dependencies = [ + "thiserror-impl 2.0.16", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.47.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +dependencies = [ + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "pin-project-lite", + "slab", + "socket2", + "tokio-macros", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-util" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "universal-hash" +version = "0.6.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.5+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4494f6290a82f5fe584817a676a34b9d6763e8d9d18204009fb31dceca98fd4" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.0+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fe7168f7de578d2d8a05b07fd61870d2e73b4020e9f49aa00da8471723497c" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.0", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-result" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" +dependencies = [ + "windows-link 0.2.0", +] + +[[package]] +name = "windows-strings" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" +dependencies = [ + "windows-link 0.2.0", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link 0.1.3", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" + +[[package]] +name = "x25519-dalek" +version = "3.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a45998121837fd8c92655d2334aa8f3e5ef0645cdfda5b321b13760c548fd55" +dependencies = [ + "curve25519-dalek", + "rand_core", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/validation/quic-test/Cargo.toml b/validation/quic-test/Cargo.toml new file mode 100644 index 0000000..c1740a4 --- /dev/null +++ b/validation/quic-test/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "quic-test" +version = "0.1.0" +authors = ["Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com>"] +edition = "2024" +resolver = "2" +rust-version = "1.88.0" + +[dependencies] +rustls-rustcrypto = { path = "../..", default-features = false, features = [ + "aead-full", + "der", + "fast", + "kx-p256", + "pkcs8", + "sign-ecdsa-p256", + "std", + "verify-ecdsa-p256-sha256", + "hash-sha384", + "quic" +] } +rustls = { version = "0.23.31", default-features = false, features = [ + "std" +] } +anyhow = { version = "1.0", default-features = false } +log = "0.4" +env_logger = "0.11" +tokio = { version = "1.47.1", features = ["rt-multi-thread", "macros", "io-std"] } +gm-quic = "0.3.0" \ No newline at end of file diff --git a/validation/quic-test/src/cert.der b/validation/quic-test/src/cert.der new file mode 100644 index 0000000..f399cd3 Binary files /dev/null and b/validation/quic-test/src/cert.der differ diff --git a/validation/quic-test/src/key.der b/validation/quic-test/src/key.der new file mode 100644 index 0000000..bdb93a9 Binary files /dev/null and b/validation/quic-test/src/key.der differ diff --git a/validation/quic-test/src/main.rs b/validation/quic-test/src/main.rs new file mode 100644 index 0000000..f0ae0aa --- /dev/null +++ b/validation/quic-test/src/main.rs @@ -0,0 +1,129 @@ +use env_logger::Env; +use gm_quic::handy::{client_parameters, server_parameters}; +use gm_quic::{QuicClient, QuicListeners}; +use log::{debug, error, info, trace}; +use rustls::crypto::CryptoProvider; +use rustls_rustcrypto::provider as rustcrypto_provider; +use std::net::SocketAddr; +use std::sync::Arc; +use std::time::Duration; +use tokio::io::{self, AsyncWriteExt}; +use tokio::task::JoinSet; + +const CLIENT_COUNT: usize = 16; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + env_logger::Builder::from_env(Env::default().default_filter_or("trace")).init(); + + info!("Rustls Real Socket TLS Test Starting..."); + // Initialize rustls with rustcrypto provider + let provider = Arc::new(rustcrypto_provider()); + info!("Rustcrypto provider initialized"); + + let mut set = JoinSet::new(); + + set.spawn({ + let provider = provider.clone(); + async move { + if let Err(e) = run_quic_server(provider.clone()).await { + error!("QUIC server error: {}", e); + } + } + }); + + for i in 0..CLIENT_COUNT { + set.spawn({ + let provider = provider.clone(); + async move { + if let Err(e) = run_quic_client(provider, i).await { + error!("QUIC client error: {}", e); + } + } + }); + } + + set.join_all().await; + + Ok(()) +} + +async fn run_quic_server(provider: Arc) -> anyhow::Result<()> { + let listeners = QuicListeners::builder_with_crypto_provieder(provider)? + .without_client_cert_verifier() + .with_parameters(server_parameters()) + .defer_idle_timeout(Duration::from_secs(0)) + .enable_0rtt() + .listen(4096); + listeners.add_server( + "foo", + include_bytes!("cert.der"), + include_bytes!("key.der"), + ["127.0.0.1:4443", "[::1]:4443"], + None, + )?; + + let mut total_conn = 0; + + loop { + if total_conn >= CLIENT_COUNT { + break Ok(()); + } + let (connection, _server, pathway, ..) = listeners.accept().await?; + info!("accepted new connection from {:?}", pathway.remote()); + total_conn += 1; + tokio::spawn(async move { + while let Ok((_sid, (mut reader, mut writer))) = connection.accept_bi_stream().await { + tokio::spawn(async move { + let mut buf = vec![]; + io::copy(&mut reader, &mut buf).await?; + + let str = String::from_utf8(buf)?; + trace!("received echo from client: {str}"); + + io::copy( + &mut format!("server welcomes {total_conn} back {str}").as_bytes(), + &mut writer, + ) + .await?; + writer.shutdown().await?; + + Ok::<_, anyhow::Error>(()) + }); + } + }); + } +} + +async fn run_quic_client(provider: Arc, ordinal: usize) -> anyhow::Result<()> { + let client = QuicClient::builder_with_crypto_provieder(provider) + .without_verifier() + .without_cert() + .with_parameters(client_parameters()) + .defer_idle_timeout(Duration::from_secs(60)) + .enable_0rtt() + .build(); + + let server_addr: SocketAddr = "127.0.0.1:4443".parse()?; + + debug!("client {ordinal}: connecting to server at {server_addr}"); + let connection = client.connect("foo", [server_addr])?; + let (_sid, (mut reader, mut writer)) = connection + .open_bi_stream() + .await? + .ok_or_else(|| anyhow::anyhow!("Failed to open bi-stream"))?; + debug!("client {ordinal}: opened stream"); + + writer.write_all("hello world!".as_bytes()).await?; + writer.shutdown().await?; + debug!("client {ordinal}: sent hello world"); + + let mut buf = vec![]; + io::copy(&mut reader, &mut buf).await?; + trace!( + "client {ordinal}: received echo from server: {}", + String::from_utf8(buf)? + ); + + Ok(()) +} diff --git a/validation/rustls-real-socket-test/Cargo.lock b/validation/rustls-real-socket-test/Cargo.lock new file mode 100644 index 0000000..e024a6d --- /dev/null +++ b/validation/rustls-real-socket-test/Cargo.lock @@ -0,0 +1,1171 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aead" +version = "0.6.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "anyhow" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base16ct" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" + +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "block-buffer" +version = "0.11.0-rc.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "cc" +version = "1.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "chacha20" +version = "0.10.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd162f2b8af3e0639d83f28a637e4e55657b7a74508dba5a9bf4da523d5c9e9" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.11.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc260dd2c69bf5581e9603fff348843363a649edde02768e84c0088f21c3f52" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", +] + +[[package]] +name = "cipher" +version = "0.5.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" +dependencies = [ + "block-buffer", + "crypto-common", + "inout", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "const-oid" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.7.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c069823f41bdc75e99546bfd59eb1ed27d69dc720e5c949fe502b82926f8448" +dependencies = [ + "hybrid-array", + "num-traits", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.2.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "curve25519-dalek" +version = "5.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f9200d1d13637f15a6acb71e758f64624048d85b31a5fdbfd8eca1e2687d0b7" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "der" +version = "0.8.0-rc.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7050e8041c28720851f7db83183195b6acf375bb7bb28e3b86f0fe6cbd69459d" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.11.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4aae35a0fcbe22ff1be50fe96df72002d5a4a6fb4aae9193cf2da0daa36da2" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.17.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aa27d88fe1d40a293286027c9306393094d9b36ccd91f2ac4d647870dc0042" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", + "zeroize", +] + +[[package]] +name = "ed25519" +version = "3.0.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe639324ff99c3bf32144aaf79dc7e048305a6e82b6409644ddcbe7e0f5f5be9" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "3.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad207ed88a133091f83224265eac21109930db09bedcad05d5252f2af2de20a1" +dependencies = [ + "curve25519-dalek", + "ed25519", + "sha2", + "subtle", +] + +[[package]] +name = "ed448" +version = "0.5.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f3621b15eb4095d0e7c2502abd44291413b8a638f88dc08f1188993143332b" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed448-goldilocks" +version = "0.14.0-pre.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c1833a8f682ff0628f3b7ae755c5ea17854d7bdadf90c017feef4e84b78bb2" +dependencies = [ + "ed448", + "elliptic-curve", + "hash2curve", + "rand_core", + "serdect", + "sha3", + "signature", + "subtle", +] + +[[package]] +name = "elliptic-curve" +version = "0.14.0-rc.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b95fd42abd85018a59f5dbe05551e9eed19edfd1182a415cd98f90ca5af1422" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "group", + "hkdf", + "hybrid-array", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "ff" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d42dd26f5790eda47c1a2158ea4120e32c35ddc9a7743c98a292accc01b54ef3" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + +[[package]] +name = "find-msvc-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.5+wasi-0.2.4", +] + +[[package]] +name = "group" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff6a0b2dd4b981b1ae9e3e6830ab146771f3660d31d57bafd9018805a91b0f1" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hash2curve" +version = "0.14.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d3a227db59d3140ef8cfcf56a8c5c3bd7c10f7363100bc0e430628d3e3bfc6" +dependencies = [ + "digest", + "elliptic-curve", + "ff", + "subtle", +] + +[[package]] +name = "hkdf" +version = "0.13.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7984b5d6605e93b2787c95aef698b3c28933a4d7f9fd09d46f54130da1efaee0" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.13.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e206bca159aebaaed410f5e78b2fe56bfc0dd5b19ecae922813b8556b8b07e" +dependencies = [ + "digest", +] + +[[package]] +name = "hybrid-array" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7116c472cf19838450b1d421b4e842569f52b519d640aee9ace1ebcf5b21051" +dependencies = [ + "typenum", + "zeroize", +] + +[[package]] +name = "inout" +version = "0.2.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1603f76010ff924b616c8f44815a42eb10fb0b93d308b41deaa8da6d4251fd4b" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "keccak" +version = "0.2.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d546793a04a1d3049bd192856f804cfe96356e2cf36b54b4e575155babe9f41" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "p256" +version = "0.14.0-pre.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa93e068b773d56fe26be53accf127d6eb0fde35e4116b7a9276db97b6a50ec9" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primefield", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.14.0-pre.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d17e7d4276af996c6c52de52db4df6b676c5efc3a4269e56c9473edee1786d" +dependencies = [ + "ecdsa", + "elliptic-curve", +] + +[[package]] +name = "p521" +version = "0.14.0-pre.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a70f4308991bf35f1632d55155c3ca137f9ce05c6de00be51705bbaa3451cfe" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", +] + +[[package]] +name = "pkcs8" +version = "0.11.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c53e5d0804fa4070b1b2a5b320102f2c1c094920a7533d5d87c2630609bcbd34" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "poly1305" +version = "0.9.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb78a635f75d76d856374961deecf61031c0b6f928c83dc9c0924ab6c019c298" +dependencies = [ + "cpufeatures", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "primefield" +version = "0.14.0-pre.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049f40103b7e4b0da4e20ed8556805efa740f7104c48991c5f9ab8e09e10ee21" +dependencies = [ + "crypto-bigint", + "ff", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "primeorder" +version = "0.14.0-pre.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9257332cf7e56fa8183f719977b92f1878cb1447275d0ee280a08bcd6fad158f" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "regex" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + +[[package]] +name = "rfc6979" +version = "0.5.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369f9c4f79388704648e7bcb92749c0d6cf4397039293a9b747694fa4fb4bae" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.23.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-real-socket-test" +version = "0.1.0" +dependencies = [ + "anyhow", + "env_logger", + "log", + "rustls", + "rustls-rustcrypto", +] + +[[package]] +name = "rustls-rustcrypto" +version = "0.0.2-alpha" +dependencies = [ + "aead", + "chacha20", + "chacha20poly1305", + "cipher", + "crypto-common", + "der", + "digest", + "ecdsa", + "ed25519-dalek", + "ed448-goldilocks", + "elliptic-curve", + "enum_dispatch", + "hmac", + "p256", + "p384", + "p521", + "pkcs8", + "rand_core", + "rustls", + "rustls-pki-types", + "rustls-webpki", + "sec1", + "sha2", + "signature", + "tinyvec", + "typenum", + "x25519-dalek", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a37813727b78798e53c2bec3f5e8fe12a6d6f8389bf9ca7802add4c9905ad8" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.8.0-rc.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e67a3c9fb9a8f065af9fa30d65812fcc16a66cbf911eff1f6946957ce48f16" +dependencies = [ + "base16ct", + "der", + "hybrid-array", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serdect" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha2" +version = "0.11.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1e3878ab0f98e35b2df35fe53201d088299b41a6bb63e3e34dada2ac4abd924" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.11.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2103ca0e6f4e9505eae906de5e5883e06fc3b2232fb5d6914890c7bbcb62f478" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "3.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39195ff4c0dc41c93e123825ca1f0d11b856df8b26d5fe140a522355632c4345" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "spki" +version = "0.8.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "universal-hash" +version = "0.6.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.5+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4494f6290a82f5fe584817a676a34b9d6763e8d9d18204009fb31dceca98fd4" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.0+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" + +[[package]] +name = "x25519-dalek" +version = "3.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a45998121837fd8c92655d2334aa8f3e5ef0645cdfda5b321b13760c548fd55" +dependencies = [ + "curve25519-dalek", + "rand_core", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/validation/rustls-real-socket-test/Cargo.toml b/validation/rustls-real-socket-test/Cargo.toml new file mode 100644 index 0000000..4fb0a04 --- /dev/null +++ b/validation/rustls-real-socket-test/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "rustls-real-socket-test" +version = "0.1.0" +authors = ["Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com>"] +edition = "2024" +resolver = "2" +rust-version = "1.88.0" + +[dependencies] +rustls-rustcrypto = { path = "../..", default-features = false, features = [ + "aead-chacha20poly1305", + "der", + "fast", + "kx-p256", + "pkcs8", + "sign-ecdsa-p256", + "std", + "tls12", + "verify-ecdsa-p256-sha256", + "quic" +] } +rustls = { version = "0.23.31", default-features = false, features = [ + "std" +] } +anyhow = { version = "1.0", default-features = false } +log = "0.4" +env_logger = "0.11" diff --git a/validation/rustls-real-socket-test/README.md b/validation/rustls-real-socket-test/README.md new file mode 100644 index 0000000..09976bd --- /dev/null +++ b/validation/rustls-real-socket-test/README.md @@ -0,0 +1,84 @@ +# Rustls Real Socket Test + +A comprehensive test suite for validating TLS functionality using real network sockets with the rustls-rustcrypto provider. This crate performs end-to-end TLS testing in standard Rust environments, ensuring secure communication works correctly across different platforms. + +## Overview + +This test crate demonstrates and validates: + +- TLS 1.2 and TLS 1.3 handshake completion +- Secure communication over real TCP sockets +- Certificate-based authentication +- Client-server TLS communication +- RustCrypto provider integration +- Cross-platform TLS capabilities + +## Features + +- ✅ TLS 1.2 and TLS 1.3 support +- ✅ ECDSA certificate authentication +- ✅ AES-GCM and ChaCha20-Poly1305 ciphers +- ✅ Real network socket communication +- ✅ Embedded certificate validation +- ✅ Cross-platform compatibility +- ✅ Comprehensive logging +- ✅ Environment variable configuration + +## Prerequisites + +### Software Requirements +- Rust 1.88.0 or later +- Cargo package manager +- OpenSSL (for certificate generation if needed) + +### System Requirements +- Most operating system where Rust works +- Loopback interface available + +## Installation + +### Clone and Setup +```bash +# From the rustls-rustcrypto workspace root +cd validation/rustls-real-socket-test + +# Build the test +cargo build --release +``` + +### Dependencies + +The crate uses the following key dependencies: + +- `rustls` 0.23.x - TLS library +- `rustls-rustcrypto` - RustCrypto provider (workspace) +- `anyhow` - Error handling +- `log` - Logging framework +- `env_logger` - Environment-based logging + +### Debugging + +Enable detailed logging: +```bash +# Debug level +RUST_LOG=debug cargo run + +# Trace level (very verbose) +RUST_LOG=trace cargo run + +# Specific module logging +RUST_LOG=rustls=debug,rustls_rustcrypto=trace cargo run +``` + +Common debug commands: +```bash +# Check network connectivity +ping 127.0.0.1 + +# Check port availability +netstat -an | grep LISTEN + +# Monitor with system tools +strace cargo run # Linux +dtruss cargo run # macOS +``` diff --git a/validation/rustls-real-socket-test/src/cert.der b/validation/rustls-real-socket-test/src/cert.der new file mode 100644 index 0000000..f399cd3 Binary files /dev/null and b/validation/rustls-real-socket-test/src/cert.der differ diff --git a/validation/rustls-real-socket-test/src/key.der b/validation/rustls-real-socket-test/src/key.der new file mode 100644 index 0000000..bdb93a9 Binary files /dev/null and b/validation/rustls-real-socket-test/src/key.der differ diff --git a/validation/rustls-real-socket-test/src/main.rs b/validation/rustls-real-socket-test/src/main.rs new file mode 100644 index 0000000..ae285f1 --- /dev/null +++ b/validation/rustls-real-socket-test/src/main.rs @@ -0,0 +1,231 @@ +use std::io::{Read, Write}; +use std::net::{TcpListener, TcpStream}; +use std::sync::{mpsc, Arc}; +use std::thread; + +use env_logger::Env; +use log::{error, info}; + +use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; +use rustls::client::ClientConfig; +use rustls::pki_types::{CertificateDer, PrivateKeyDer, ServerName, UnixTime}; +use rustls::server::ServerConfig; +use rustls::{ClientConnection, ServerConnection, SignatureScheme, Stream}; +use rustls_rustcrypto::provider as rustcrypto_provider; + +fn main() -> anyhow::Result<()> { + env_logger::Builder::from_env(Env::default().default_filter_or("trace")).init(); + + info!("Rustls Real Socket TLS Test Starting..."); + + // Initialize rustls with rustcrypto provider + let provider = Arc::new(rustcrypto_provider()); + info!("Rustcrypto provider initialized"); + + // Create TLS configurations + let client_config = ClientConfig::builder_with_provider(provider.clone()) + .with_safe_default_protocol_versions()? + .dangerous() + .with_custom_certificate_verifier(Arc::new(NoCertificateVerification)) + .with_no_client_auth(); + info!("TLS client config created successfully"); + + let server_config = ServerConfig::builder_with_provider(provider) + .with_safe_default_protocol_versions()? + .with_no_client_auth() + .with_single_cert( + vec![const { CertificateDer::from_slice(include_bytes!("cert.der")) }], + PrivateKeyDer::Pkcs8(include_bytes!("key.der").as_slice().into()), + )?; + info!("TLS server config created successfully"); + + let (tx, rx) = mpsc::channel(); + + // Start TLS server in a separate thread + let server_handle = thread::spawn(move || { + run_tls_server(server_config, tx); + }); + + // Start TLS client in another thread + let client_handle = thread::spawn(move || { + if let Ok(port) = rx.recv() { + run_tls_client(client_config, port); + } else { + error!("Failed to receive port from server thread"); + } + }); + + // Wait for both threads to complete + if let Err(e) = server_handle.join() { + error!("Server thread panicked: {:?}", e); + } + + if let Err(e) = client_handle.join() { + error!("Client thread panicked: {:?}", e); + } + + info!("Rustls Real Socket TLS Test completed!"); + Ok(()) +} + +fn run_tls_server(server_config: ServerConfig, tx: mpsc::Sender) { + info!("Starting TLS server..."); + + // Bind to a random port and send it to the client thread + let listener = match TcpListener::bind("127.0.0.1:0") { + Ok(listener) => { + let addr = listener.local_addr().unwrap(); + info!("TLS server listening on {}", addr); + if tx.send(addr.port()).is_err() { + error!("Failed to send port to client thread"); + return; + } + listener + } + Err(e) => { + error!("Failed to bind server: {:?}", e); + return; + } + }; + + // Accept one connection for testing + match listener.accept() { + Ok((mut tcp_stream, addr)) => { + info!("Accepted connection from {}", addr); + + let mut tls_conn = match ServerConnection::new(Arc::new(server_config)) { + Ok(conn) => conn, + Err(e) => { + error!("Failed to create TLS server connection: {:?}", e); + return; + } + }; + + let mut tls_stream = Stream::new(&mut tls_conn, &mut tcp_stream); + + info!("TLS handshake completed successfully"); + + // Read and echo data + let mut buffer = [0; 1024]; + match tls_stream.read(&mut buffer) { + Ok(n) if n > 0 => { + let received = String::from_utf8_lossy(&buffer[..n]); + info!("Server received: {}", received.trim()); + + // Echo back + if let Err(e) = tls_stream.write_all(format!("Echo: {}", received).as_bytes()) { + error!("Failed to write response: {:?}", e); + } + } + Ok(_) => info!("Connection closed by client"), + Err(e) => error!("Read error: {:?}", e), + } + } + Err(e) => { + error!("Accept failed: {:?}", e); + } + } + + info!("TLS server shutting down"); +} + +fn run_tls_client(client_config: ClientConfig, port: u16) { + info!("Starting TLS client..."); + + // Connect to the server on the port received from the channel + let server_addr = format!("127.0.0.1:{}", port); + + let mut tcp_stream = match TcpStream::connect(&server_addr) { + Ok(stream) => { + info!("Connected to server at {}", server_addr); + stream + } + Err(e) => { + error!("Failed to connect to server: {:?}", e); + return; + } + }; + + let server_name = match ServerName::try_from("localhost") { + Ok(name) => name, + Err(e) => { + error!("Invalid server name: {:?}", e); + return; + } + }; + + let mut tls_conn = match ClientConnection::new(Arc::new(client_config), server_name) { + Ok(conn) => conn, + Err(e) => { + error!("Failed to create TLS client connection: {:?}", e); + return; + } + }; + + let mut tls_stream = Stream::new(&mut tls_conn, &mut tcp_stream); + + info!("TLS handshake completed successfully"); + + // Send test message + let test_message = "Hello from Rustls client!"; + if let Err(e) = tls_stream.write_all(test_message.as_bytes()) { + error!("Failed to send message: {:?}", e); + return; + } + + // Read response + let mut buffer = [0; 1024]; + match tls_stream.read(&mut buffer) { + Ok(n) if n > 0 => { + let response = String::from_utf8_lossy(&buffer[..n]); + info!("Client received: {}", response.trim()); + } + Ok(_) => info!("Server closed connection"), + Err(e) => error!("Read error: {:?}", e), + } + + info!("TLS client shutting down"); +} + +// Dummy certificate verifier for testing (DO NOT USE IN PRODUCTION) +#[derive(Debug)] +struct NoCertificateVerification; + +impl ServerCertVerifier for NoCertificateVerification { + fn verify_server_cert( + &self, + _end_entity: &CertificateDer, + _intermediates: &[CertificateDer], + _server_name: &ServerName, + _ocsp_response: &[u8], + _now: UnixTime, + ) -> Result { + Ok(ServerCertVerified::assertion()) + } + + fn verify_tls12_signature( + &self, + _message: &[u8], + _cert: &CertificateDer, + _dss: &rustls::DigitallySignedStruct, + ) -> Result { + Ok(HandshakeSignatureValid::assertion()) + } + + fn verify_tls13_signature( + &self, + _message: &[u8], + _cert: &CertificateDer, + _dss: &rustls::DigitallySignedStruct, + ) -> Result { + Ok(HandshakeSignatureValid::assertion()) + } + + fn supported_verify_schemes(&self) -> Vec { + vec![ + SignatureScheme::RSA_PKCS1_SHA256, + SignatureScheme::ECDSA_NISTP256_SHA256, + ] + } +} +