diff --git a/.clippy.toml b/.clippy.toml new file mode 100644 index 0000000..2e06d15 --- /dev/null +++ b/.clippy.toml @@ -0,0 +1,2 @@ +allow-unwrap-in-consts = true +allow-unwrap-in-tests = true diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index bce9354..e9491db 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -26,7 +26,7 @@ jobs: timeout-minutes: 45 steps: - uses: actions/checkout@v6 - - uses: dtolnay/rust-toolchain@1.85 + - uses: dtolnay/rust-toolchain@1.93 with: components: clippy - run: cargo clippy --all-features --all-targets -- -D warnings diff --git a/Cargo.toml b/Cargo.toml index 254da3f..0815a29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,49 @@ members = [ "x-wing" ] +[workspace.lints.clippy] +borrow_as_ptr = "warn" +cast_lossless = "warn" +cast_possible_truncation = "warn" +cast_possible_wrap = "warn" +cast_precision_loss = "warn" +cast_sign_loss = "warn" +checked_conversions = "warn" +doc_markdown = "warn" +from_iter_instead_of_collect = "warn" +implicit_saturating_sub = "warn" +integer_division_remainder_used = "warn" +manual_assert = "warn" +map_unwrap_or = "warn" +missing_errors_doc = "warn" +missing_panics_doc = "warn" +mod_module_files = "warn" +must_use_candidate = "warn" +needless_range_loop = "allow" +panic_in_result_fn = "warn" +ptr_as_ptr = "warn" +redundant_closure_for_method_calls = "warn" +ref_as_ptr = "warn" +return_self_not_must_use = "warn" +semicolon_if_nothing_returned = "warn" +trivially_copy_pass_by_ref = "warn" +std_instead_of_alloc = "warn" +std_instead_of_core = "warn" +undocumented_unsafe_blocks = "warn" +unnecessary_safety_comment = "warn" +unwrap_in_result = "warn" +unwrap_used = "warn" + +[workspace.lints.rust] +missing_copy_implementations = "warn" +missing_debug_implementations = "warn" +missing_docs = "warn" +trivial_casts = "warn" +trivial_numeric_casts = "warn" +unsafe_code = "deny" +unused_lifetimes = "warn" +unused_qualifications = "warn" + [profile.bench] debug = true diff --git a/ml-kem/Cargo.toml b/ml-kem/Cargo.toml index 9e489a4..ee322de 100644 --- a/ml-kem/Cargo.toml +++ b/ml-kem/Cargo.toml @@ -50,5 +50,8 @@ serde_json = "1.0.125" name = "mlkem" harness = false +[lints] +workspace = true + [package.metadata.docs.rs] all-features = true diff --git a/ml-kem/benches/mlkem.rs b/ml-kem/benches/mlkem.rs index fef4e5b..740d857 100644 --- a/ml-kem/benches/mlkem.rs +++ b/ml-kem/benches/mlkem.rs @@ -1,3 +1,7 @@ +//! ML-KEM benchmarks. + +#![allow(missing_docs, clippy::unwrap_used)] + use ::kem::{Decapsulate, Encapsulate, Kem, KeyExport, KeyInit}; use core::hint::black_box; use criterion::{Criterion, criterion_group, criterion_main}; @@ -14,7 +18,7 @@ fn criterion_benchmark(c: &mut Criterion) { let (dk, ek) = MlKem768::generate_keypair_from_rng(&mut rng); let _dk_bytes = black_box(dk.to_seed().unwrap()); let _ek_bytes = black_box(ek.to_bytes()); - }) + }); }); let (dk, ek) = MlKem768::generate_keypair_from_rng(&mut rng); @@ -24,7 +28,7 @@ fn criterion_benchmark(c: &mut Criterion) { // Encapsulation c.bench_function("encapsulate", |b| { - b.iter(|| ek.encapsulate_with_rng(&mut rng)) + b.iter(|| ek.encapsulate_with_rng(&mut rng)); }); let (ct, _sk) = ek.encapsulate_with_rng(&mut rng); @@ -34,7 +38,7 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function("decapsulate", |b| { b.iter(|| { dk.decapsulate(&ct); - }) + }); }); // Round trip @@ -43,7 +47,7 @@ fn criterion_benchmark(c: &mut Criterion) { let (dk, ek) = MlKem768::generate_keypair_from_rng(&mut rng); let (ct, _sk) = ek.encapsulate_with_rng(&mut rng); dk.decapsulate(&ct); - }) + }); }); } diff --git a/ml-kem/src/algebra.rs b/ml-kem/src/algebra.rs index 6436604..d4a38f7 100644 --- a/ml-kem/src/algebra.rs +++ b/ml-kem/src/algebra.rs @@ -74,7 +74,7 @@ pub fn sample_ntt(B: &mut impl XofReader) -> NttPolynomial { self.start = end; let d1 = Int::from(b[0]) + ((Int::from(b[1]) & 0xf) << 8); - let d2 = (Int::from(b[1]) >> 4) + ((Int::from(b[2]) as Int) << 4); + let d2 = (Int::from(b[1]) >> 4) + (Int::from(b[2]) << 4); if d1 < BaseField::Q { if d2 < BaseField::Q { @@ -315,7 +315,10 @@ const GAMMA: [Elem; 128] = { #[cfg(test)] mod test { - use super::*; + use super::{ + Array, ArraySize, B32, BaseField, Elem, Field, Int, Ntt, NttInverse, NttMatrix, + NttPolynomial, NttVector, PRF, Polynomial, U256, XOF, + }; use array::typenum::{U2, U3, U8}; use module_lattice::utils::Flatten; @@ -519,14 +522,14 @@ mod test { let rho = B32::default(); let sample: Array, U8> = Array::from_fn(|i| { let mut xof = XOF(&rho, 0, i as u8); - sample_ntt(&mut xof).into() + super::sample_ntt(&mut xof).into() }); test_sample(&sample.flatten(), &UNIFORM); } #[test] - fn sample_cbd() { + fn sample_poly_cbd() { // Eta = 2 let sigma = B32::default(); let prf_output = PRF::(&sigma, 0); diff --git a/ml-kem/src/compress.rs b/ml-kem/src/compress.rs index 0e27981..5eaff8e 100644 --- a/ml-kem/src/compress.rs +++ b/ml-kem/src/compress.rs @@ -15,7 +15,7 @@ where T: EncodingSize, { const POW2_HALF: u32 = 1 << (T::USIZE - 1); - const MASK: Int = ((1 as Int) << T::USIZE) - 1; + const MASK: Int = (1 << T::USIZE) - 1; const DIV_SHIFT: usize = 34; #[allow(clippy::integer_division_remainder_used, reason = "constant")] const DIV_MUL: u64 = (1 << T::DIV_SHIFT) / BaseField::QLL; diff --git a/ml-kem/src/lib.rs b/ml-kem/src/lib.rs index 728a1f2..446b7a9 100644 --- a/ml-kem/src/lib.rs +++ b/ml-kem/src/lib.rs @@ -7,9 +7,6 @@ )] #![allow(non_snake_case)] // Allow notation matching the spec #![allow(clippy::clone_on_copy)] // Be explicit about moving data -#![deny(missing_docs)] // Require all public interfaces to be documented -#![warn(clippy::pedantic)] // Be pedantic by default -#![warn(clippy::integer_division_remainder_used)] // Be judicious about using `/` and `%` //! # Usage //! diff --git a/ml-kem/src/pkcs8.rs b/ml-kem/src/pkcs8.rs index 4fd7646..1910969 100644 --- a/ml-kem/src/pkcs8.rs +++ b/ml-kem/src/pkcs8.rs @@ -93,7 +93,7 @@ where } #[cfg(feature = "alloc")] -impl

pkcs8::EncodePublicKey for EncapsulationKey

+impl

EncodePublicKey for EncapsulationKey

where P: KemParams + AssociatedAlgorithmIdentifier>, { @@ -152,7 +152,7 @@ where } #[cfg(feature = "alloc")] -impl

pkcs8::EncodePrivateKey for DecapsulationKey

+impl

EncodePrivateKey for DecapsulationKey

where P: KemParams + AssociatedAlgorithmIdentifier>, { diff --git a/ml-kem/tests/encap-decap.rs b/ml-kem/tests/encap-decap.rs index f3f9eab..909e101 100644 --- a/ml-kem/tests/encap-decap.rs +++ b/ml-kem/tests/encap-decap.rs @@ -1,12 +1,15 @@ -use ml_kem::*; +//! Encapsulation/decapsulation tests, including ones against the NIST ACVP test vectors. + +#![allow(clippy::unwrap_used)] use ::kem::Decapsulate; use array::{Array, ArrayN}; +use ml_kem::*; use std::{fs::read_to_string, path::PathBuf}; -// A helper trait for deterministic encapsulation tests +/// A helper trait for deterministic encapsulation tests pub trait EncapsulateDeterministic { - // Returns (ciphertext, shared_secret) + /// Returns `(ciphertext, shared_secret)`. fn encapsulate_deterministic(&self, m: &ArrayN) -> (Vec, Vec); } diff --git a/ml-kem/tests/key-gen.rs b/ml-kem/tests/key-gen.rs index 5945975..39b1365 100644 --- a/ml-kem/tests/key-gen.rs +++ b/ml-kem/tests/key-gen.rs @@ -1,3 +1,7 @@ +//! Key generation tests. + +#![allow(clippy::unwrap_used)] + use array::ArrayN; use core::fmt::Debug; use ml_kem::*; diff --git a/ml-kem/tests/pkcs8.rs b/ml-kem/tests/pkcs8.rs index 8095b18..1db239b 100644 --- a/ml-kem/tests/pkcs8.rs +++ b/ml-kem/tests/pkcs8.rs @@ -1,6 +1,7 @@ //! PKCS#8 tests. #![cfg(all(feature = "pkcs8", feature = "alloc"))] +#![allow(clippy::unwrap_used)] use core::fmt::Debug; use getrandom::SysRng;