diff --git a/Cargo.toml b/Cargo.toml index 36218ed1a..e97e58053 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,3 +26,42 @@ members = [ [profile.dev] opt-level = 2 + +[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" +implicit_saturating_sub = "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" +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" +unused_lifetimes = "warn" +unused_qualifications = "warn" diff --git a/aes/Cargo.toml b/aes/Cargo.toml index 460bbf018..98cbb2261 100644 --- a/aes/Cargo.toml +++ b/aes/Cargo.toml @@ -36,3 +36,41 @@ check-cfg = [ [package.metadata.docs.rs] all-features = true + +[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" +implicit_saturating_sub = "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" +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" + +[lints.rust] +missing_copy_implementations = "warn" +missing_debug_implementations = "warn" +missing_docs = "warn" +trivial_casts = "warn" +trivial_numeric_casts = "warn" +unused_lifetimes = "warn" +unused_qualifications = "warn" diff --git a/aes/benches/mod.rs b/aes/benches/mod.rs index 8dd47a210..f4f12275f 100644 --- a/aes/benches/mod.rs +++ b/aes/benches/mod.rs @@ -1,4 +1,5 @@ #![feature(test)] +#![allow(missing_docs)] extern crate test; use cipher::{KeyInit, block_decryptor_bench, block_encryptor_bench}; diff --git a/aes/src/backends/fixslice/hazmat.rs b/aes/src/backends/fixslice/hazmat.rs index 1cddc34a6..6b6e1acfe 100644 --- a/aes/src/backends/fixslice/hazmat.rs +++ b/aes/src/backends/fixslice/hazmat.rs @@ -104,35 +104,35 @@ fn inv_mix_columns_generic(block: &mut Block) { /// AES cipher (encrypt) round function. #[inline] pub(crate) fn cipher_round(block: &mut Block, round_key: &Block) { - cipher_round_generic::(block, round_key) + cipher_round_generic::(block, round_key); } /// AES cipher (encrypt) round function: parallel version. #[inline] pub(crate) fn cipher_round_par(blocks: &mut Block8, round_keys: &Block8) { - cipher_round_par_generic::(blocks, round_keys) + cipher_round_par_generic::(blocks, round_keys); } /// AES cipher (encrypt) inverse round function. #[inline] pub(crate) fn equiv_inv_cipher_round(block: &mut Block, round_key: &Block) { - equiv_inv_cipher_round_generic::(block, round_key) + equiv_inv_cipher_round_generic::(block, round_key); } /// AES cipher (encrypt) inverse round function: parallel version. #[inline] pub(crate) fn equiv_inv_cipher_round_par(blocks: &mut Block8, round_keys: &Block8) { - equiv_inv_cipher_round_par_generic::(blocks, round_keys) + equiv_inv_cipher_round_par_generic::(blocks, round_keys); } /// AES mix columns function. #[inline] pub(crate) fn mix_columns(block: &mut Block) { - mix_columns_generic::(block) + mix_columns_generic::(block); } /// AES inverse mix columns function. #[inline] pub(crate) fn inv_mix_columns(block: &mut Block) { - inv_mix_columns_generic::(block) + inv_mix_columns_generic::(block); } diff --git a/aes/src/backends/fixslice/word.rs b/aes/src/backends/fixslice/word.rs index 696edc6cb..da356f4a8 100644 --- a/aes/src/backends/fixslice/word.rs +++ b/aes/src/backends/fixslice/word.rs @@ -1,3 +1,4 @@ +#![allow(clippy::cast_possible_truncation)] use crate::{Block, backends::soft::MinWord}; use cipher::{ Array, @@ -72,17 +73,17 @@ impl Word for u16 { #[inline(always)] fn uniform_row(b: u8) -> u16 { - (b as u16) * 0x1111 + u16::from(b) * 0x1111 } #[inline(always)] fn pack_rows(r0: u8, r1: u8, r2: u8, r3: u8) -> u16 { - (r0 as u16) | ((r1 as u16) << 4) | ((r2 as u16) << 8) | ((r3 as u16) << 12) + u16::from(r0) | (u16::from(r1) << 4) | (u16::from(r2) << 8) | (u16::from(r3) << 12) } #[inline(always)] fn byte_repeat(b: u8) -> u16 { - (b as u16) * 0x0101 + u16::from(b) * 0x0101 } /// Bitslice one 128-bit input block into a 128-bit internal state. @@ -226,27 +227,29 @@ impl Word for u32 { #[inline(always)] fn uniform_row(b: u8) -> u32 { - double_bits_8_to_16(b) as u32 * 0x01010101 + u32::from(double_bits_8_to_16(b)) * 0x01010101 } #[inline(always)] fn pack_rows(r0: u8, r1: u8, r2: u8, r3: u8) -> u32 { - (double_bits_8_to_16(r0) as u32) - | ((double_bits_8_to_16(r1) as u32) << 8) - | ((double_bits_8_to_16(r2) as u32) << 16) - | ((double_bits_8_to_16(r3) as u32) << 24) + u32::from(double_bits_8_to_16(r0)) + | (u32::from(double_bits_8_to_16(r1)) << 8) + | (u32::from(double_bits_8_to_16(r2)) << 16) + | (u32::from(double_bits_8_to_16(r3)) << 24) } #[inline(always)] fn byte_repeat(b: u8) -> u32 { - (b as u32) * 0x01010101 + u32::from(b) * 0x01010101 } /// Bitslice two 128-bit input blocks into a 256-bit internal state. fn bitslice(output: &mut [u32], input: &Array) { debug_assert_eq!(output.len(), 8); - let input0 = input[0].as_slice(); - let input1 = input[1].as_slice(); + let (input0, tail) = input[0].as_chunks(); + assert!(tail.is_empty()); + let (input1, tail) = input[1].as_chunks(); + assert!(tail.is_empty()); // Bitslicing is a bit index manipulation. 256 bits of data means each bit is positioned at // an 8-bit index. AES data is 2 blocks, each one a 4x4 column-major matrix of bytes, so the @@ -259,14 +262,14 @@ impl Word for u32 { // Interleave the columns on input (note the order of input) // b0 c1 c0 __ __ __ __ __ => c1 c0 b0 __ __ __ __ __ let mut t = [ - u32::from_le_bytes(input0[0x00..0x04].try_into().unwrap()), - u32::from_le_bytes(input1[0x00..0x04].try_into().unwrap()), - u32::from_le_bytes(input0[0x04..0x08].try_into().unwrap()), - u32::from_le_bytes(input1[0x04..0x08].try_into().unwrap()), - u32::from_le_bytes(input0[0x08..0x0c].try_into().unwrap()), - u32::from_le_bytes(input1[0x08..0x0c].try_into().unwrap()), - u32::from_le_bytes(input0[0x0c..0x10].try_into().unwrap()), - u32::from_le_bytes(input1[0x0c..0x10].try_into().unwrap()), + u32::from_le_bytes(input0[0]), + u32::from_le_bytes(input1[0]), + u32::from_le_bytes(input0[1]), + u32::from_le_bytes(input1[1]), + u32::from_le_bytes(input0[2]), + u32::from_le_bytes(input1[2]), + u32::from_le_bytes(input0[3]), + u32::from_le_bytes(input1[3]), ]; bitslice_swaps(&mut t); @@ -326,20 +329,20 @@ impl Word for u64 { #[inline(always)] fn uniform_row(b: u8) -> u64 { - quad_bits_16_to_64(b as u16) * 0x0001_0001_0001_0001 + quad_bits_16_to_64(u16::from(b)) * 0x0001_0001_0001_0001 } #[inline(always)] fn pack_rows(r0: u8, r1: u8, r2: u8, r3: u8) -> u64 { - quad_bits_16_to_64(r0 as u16) - | (quad_bits_16_to_64(r1 as u16) << 16) - | (quad_bits_16_to_64(r2 as u16) << 32) - | (quad_bits_16_to_64(r3 as u16) << 48) + quad_bits_16_to_64(u16::from(r0)) + | (quad_bits_16_to_64(u16::from(r1)) << 16) + | (quad_bits_16_to_64(u16::from(r2)) << 32) + | (quad_bits_16_to_64(u16::from(r3)) << 48) } #[inline(always)] fn byte_repeat(b: u8) -> u64 { - (b as u64) * 0x0101010101010101 + u64::from(b) * 0x0101010101010101 } /// Bitslice four 128-bit input blocks into a 512-bit internal state. diff --git a/aes/src/backends/x86_aes.rs b/aes/src/backends/x86_aes.rs index a329db324..482b45c00 100644 --- a/aes/src/backends/x86_aes.rs +++ b/aes/src/backends/x86_aes.rs @@ -62,7 +62,7 @@ impl BlockCipherEncBackend for Aes { fn encrypt_block(&self, block: InOut<'_, '_, Block>) { // SAFETY: this trait impl is used only by the `Self::encrypt` method marked with // `#[target_feature(enable = "aes")]` - unsafe { encdec::encrypt(&self.enc_rk, block) }; + unsafe { encrypt(&self.enc_rk, block) }; } #[inline(always)] @@ -78,7 +78,7 @@ impl BlockCipherDecBackend for Aes { fn decrypt_block(&self, block: InOut<'_, '_, Block>) { // SAFETY: this trait impl is used only by the `Self::decrypt` method marked with // `#[target_feature(enable = "aes")]` - unsafe { encdec::decrypt(&self.dec_rk, block) }; + unsafe { decrypt(&self.dec_rk, block) }; } #[inline(always)] @@ -113,7 +113,7 @@ impl AesEnc { #[inline] #[target_feature(enable = "aes")] pub(crate) fn encrypt(&self, f: impl BlockCipherEncClosure) { - f.call(self) + f.call(self); } } @@ -130,7 +130,7 @@ impl BlockCipherEncBackend for AesEnc { fn encrypt_block(&self, block: InOut<'_, '_, Block>) { // SAFETY: this trait impl is used only by the `Self::encrypt` method marked with // `#[target_feature(enable = "aes")]` - unsafe { encdec::encrypt(&self.enc_rk, block) }; + unsafe { encrypt(&self.enc_rk, block) }; } #[inline(always)] @@ -167,7 +167,7 @@ impl BlockCipherDecBackend for AesDec { fn decrypt_block(&self, block: InOut<'_, '_, Block>) { // SAFETY: this trait impl is used only by the `Self::decrypt` method marked with // `#[target_feature(enable = "aes")]` - unsafe { encdec::decrypt(&self.dec_rk, block) }; + unsafe { decrypt(&self.dec_rk, block) }; } #[inline(always)] diff --git a/aes/src/backends/x86_aes/hazmat.rs b/aes/src/backends/x86_aes/hazmat.rs index 07c5485ec..01ae5737c 100644 --- a/aes/src/backends/x86_aes/hazmat.rs +++ b/aes/src/backends/x86_aes/hazmat.rs @@ -14,7 +14,6 @@ use core::arch::x86_64::*; /// AES cipher (encrypt) round function. #[target_feature(enable = "aes")] pub(crate) fn cipher_round(block: &mut Block, round_key: &Block) { - // Safety: `loadu` and `storeu` support unaligned access let b = utils::load_block(block); let k = utils::load_block(round_key); let b = _mm_aesenc_si128(b, k); @@ -59,7 +58,6 @@ pub(crate) fn equiv_inv_cipher_round_par(blocks: &mut Block8, round_keys: &Block /// AES mix columns function. #[target_feature(enable = "aes")] pub(crate) fn mix_columns(block: &mut Block) { - // Safety: `loadu` and `storeu` support unaligned access let mut state = utils::load_block(block); // Emulate mix columns by performing three inverse mix columns operations diff --git a/aes/src/backends/x86_vaes256.rs b/aes/src/backends/x86_vaes256.rs index 5c40a3dfa..82ac93118 100644 --- a/aes/src/backends/x86_vaes256.rs +++ b/aes/src/backends/x86_vaes256.rs @@ -24,7 +24,7 @@ impl<'a, const RK: usize> Aes<'a, RK> { pub(crate) fn encrypt(rk: &'a RoundKeys, f: impl BlockCipherEncClosure) { let rk2 = encdec::broadcast_keys(rk); let backend = Self { rk, rk2 }; - f.call(&backend) + f.call(&backend); } #[inline] @@ -32,7 +32,7 @@ impl<'a, const RK: usize> Aes<'a, RK> { pub(crate) fn decrypt(rk: &'a RoundKeys, f: impl BlockCipherDecClosure) { let rk2 = encdec::broadcast_keys(rk); let backend = Self { rk, rk2 }; - f.call(&backend) + f.call(&backend); } } diff --git a/aes/src/backends/x86_vaes512.rs b/aes/src/backends/x86_vaes512.rs index bf0974e98..ea7d0c409 100644 --- a/aes/src/backends/x86_vaes512.rs +++ b/aes/src/backends/x86_vaes512.rs @@ -24,7 +24,7 @@ impl<'a, const RK: usize> Aes<'a, RK> { pub(crate) fn encrypt(rk: &'a RoundKeys, f: impl BlockCipherEncClosure) { let rk4 = encdec::broadcast_keys(rk); let backend = Self { rk, rk4 }; - f.call(&backend) + f.call(&backend); } #[inline] @@ -32,7 +32,7 @@ impl<'a, const RK: usize> Aes<'a, RK> { pub(crate) fn decrypt(rk: &'a RoundKeys, f: impl BlockCipherDecClosure) { let rk4 = encdec::broadcast_keys(rk); let backend = Self { rk, rk4 }; - f.call(&backend) + f.call(&backend); } } diff --git a/aes/src/lib.rs b/aes/src/lib.rs index 5b52c98fe..470c97268 100644 --- a/aes/src/lib.rs +++ b/aes/src/lib.rs @@ -118,7 +118,6 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![cfg_attr(docsrs, feature(doc_cfg))] -#![warn(missing_docs, rust_2018_idioms)] pub use cipher; @@ -196,6 +195,7 @@ cfg_if! { /// println!("WARNING: using software fallback for AES"); /// } /// ``` +#[must_use] pub fn hardware_accelerated() -> bool { cfg_if! { if #[cfg(aes_backend = "soft")] { @@ -420,6 +420,7 @@ macro_rules! common_impls { #[inline] fn drop(&mut self) { #[cfg(feature = "zeroize")] + // SAFETY: the type satisfies the function safety conditions unsafe { zeroize::zeroize_flat_type(self); } diff --git a/aes/tests/hazmat.rs b/aes/tests/hazmat.rs index 7fc593292..53a9189a4 100644 --- a/aes/tests/hazmat.rs +++ b/aes/tests/hazmat.rs @@ -144,12 +144,12 @@ fn equiv_inv_cipher_round_par_fips197_vectors() { fn mix_columns_fips197_vector() { let mut block = Block::from(hex!("6353e08c0960e104cd70b751bacad0e7")); aes::hazmat::mix_columns(&mut block); - assert_eq!(block.as_slice(), &hex!("5f72641557f5bc92f7be3b291db9f91a")) + assert_eq!(block.as_slice(), &hex!("5f72641557f5bc92f7be3b291db9f91a")); } #[test] fn inv_mix_columns_fips197_vector() { let mut block = Block::from(hex!("bd6e7c3df2b5779e0b61216e8b10b689")); aes::hazmat::inv_mix_columns(&mut block); - assert_eq!(block.as_slice(), &hex!("4773b91ff72f354361cb018ea1e6cf2c")) + assert_eq!(block.as_slice(), &hex!("4773b91ff72f354361cb018ea1e6cf2c")); } diff --git a/aes/tests/mod.rs b/aes/tests/mod.rs index cb2169352..fe3d906b2 100644 --- a/aes/tests/mod.rs +++ b/aes/tests/mod.rs @@ -1,5 +1,5 @@ //! Test vectors are from NESSIE: -//! https://www.cosic.esat.kuleuven.be/nessie/testvectors/ +//! #![cfg(not(miri))] cipher::block_cipher_test!(aes128, aes::Aes128); diff --git a/blowfish/Cargo.toml b/blowfish/Cargo.toml index c96961808..d27c855a3 100644 --- a/blowfish/Cargo.toml +++ b/blowfish/Cargo.toml @@ -24,3 +24,6 @@ zeroize = ["cipher/zeroize"] [package.metadata.docs.rs] all-features = true + +[lints] +workspace = true diff --git a/blowfish/benches/mod.rs b/blowfish/benches/mod.rs index 00078c83a..3d189e9db 100644 --- a/blowfish/benches/mod.rs +++ b/blowfish/benches/mod.rs @@ -1,4 +1,5 @@ #![feature(test)] +#![allow(missing_docs)] extern crate test; use blowfish::Blowfish; diff --git a/blowfish/src/lib.rs b/blowfish/src/lib.rs index e657769fd..498ea48f6 100644 --- a/blowfish/src/lib.rs +++ b/blowfish/src/lib.rs @@ -15,9 +15,8 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] -#![deny(unsafe_code)] #![cfg_attr(docsrs, feature(doc_cfg))] -#![warn(missing_docs, rust_2018_idioms)] +#![deny(unsafe_code)] pub use cipher; @@ -53,7 +52,7 @@ fn next_u32_wrap(buf: &[u8], offset: &mut usize) -> u32 { if *offset >= buf.len() { *offset = 0; } - v = (v << 8) | buf[*offset] as u32; + v = (v << 8) | u32::from(buf[*offset]); *offset += 1; } v @@ -128,7 +127,7 @@ impl KeySizeUser for Blowfish { impl KeyInit for Blowfish { fn new(key: &Key) -> Self { - Self::new_from_slice(&key[..]).unwrap() + Self::new_from_slice(&key[..]).expect("key has correct size") } fn new_from_slice(key: &[u8]) -> Result { @@ -152,7 +151,7 @@ impl ParBlocksSizeUser for Blowfish { impl BlockCipherEncrypt for Blowfish { #[inline] fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { - f.call(self) + f.call(self); } } @@ -169,7 +168,7 @@ impl BlockCipherEncBackend for Blowfish { impl BlockCipherDecrypt for Blowfish { #[inline] fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { - f.call(self) + f.call(self); } } @@ -259,17 +258,19 @@ impl Blowfish { } /// Init state + #[must_use] pub fn bc_init_state() -> Blowfish { Blowfish::init_state() } /// Encrypt + #[must_use] pub fn bc_encrypt(&self, lr: [u32; 2]) -> [u32; 2] { self.encrypt(lr) } /// Expand key pub fn bc_expand_key(&mut self, key: &[u8]) { - self.expand_key(key) + self.expand_key(key); } } diff --git a/blowfish/tests/mod.rs b/blowfish/tests/mod.rs index 28d3b18b5..73afdb5f9 100644 --- a/blowfish/tests/mod.rs +++ b/blowfish/tests/mod.rs @@ -1,4 +1,5 @@ -// TODO(tarcieri): update tests to support RustCrypto/traits#1916 +//! Basic tests + cipher::block_cipher_test!(blowfish, blowfish::Blowfish); // Tests for BlowfishLE were randomly generated using implementation in this crate cipher::block_cipher_test!(blowfish_le, blowfish::BlowfishLE); diff --git a/magma/Cargo.toml b/magma/Cargo.toml index 7634ababb..1d02669af 100644 --- a/magma/Cargo.toml +++ b/magma/Cargo.toml @@ -23,3 +23,6 @@ zeroize = ["cipher/zeroize"] [package.metadata.docs.rs] all-features = true + +[lints] +workspace = true diff --git a/magma/benches/mod.rs b/magma/benches/mod.rs index 2a7976ca5..e551dc060 100644 --- a/magma/benches/mod.rs +++ b/magma/benches/mod.rs @@ -1,4 +1,5 @@ #![feature(test)] +#![allow(missing_docs)] extern crate test; use cipher::{block_decryptor_bench, block_encryptor_bench}; diff --git a/magma/src/lib.rs b/magma/src/lib.rs index 3e5dfff2c..fa6725db0 100644 --- a/magma/src/lib.rs +++ b/magma/src/lib.rs @@ -58,8 +58,10 @@ use core::{fmt, marker::PhantomData}; use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; mod sboxes; +mod variants; pub use sboxes::Sbox; +pub use variants::*; use sboxes::SboxExt; @@ -117,7 +119,7 @@ impl BlockCipherEncBackend for Gost89 { impl BlockCipherEncrypt for Gost89 { #[inline] fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { - f.call(self) + f.call(self); } } @@ -145,7 +147,7 @@ impl BlockCipherDecBackend for Gost89 { impl BlockCipherDecrypt for Gost89 { #[inline] fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { - f.call(self) + f.call(self); } } @@ -192,20 +194,8 @@ impl Drop for Gost89 { #[cfg(feature = "zeroize")] impl ZeroizeOnDrop for Gost89 {} -/// Block cipher defined in GOST R 34.12-2015 (Magma) -pub type Magma = Gost89; -/// Block cipher defined in GOST 28147-89 with test S-box -pub type Gost89Test = Gost89; -/// Block cipher defined in GOST 28147-89 with CryptoPro S-box version A -pub type Gost89CryptoProA = Gost89; -/// Block cipher defined in GOST 28147-89 with CryptoPro S-box version B -pub type Gost89CryptoProB = Gost89; -/// Block cipher defined in GOST 28147-89 with CryptoPro S-box version C -pub type Gost89CryptoProC = Gost89; -/// Block cipher defined in GOST 28147-89 with CryptoPro S-box version D -pub type Gost89CryptoProD = Gost89; - #[inline(always)] +#[allow(clippy::unwrap_used)] fn to_u32(chunk: &[u8]) -> u32 { u32::from_be_bytes(chunk.try_into().unwrap()) } diff --git a/magma/src/sboxes.rs b/magma/src/sboxes.rs index 8563cd42f..1c9f0862c 100644 --- a/magma/src/sboxes.rs +++ b/magma/src/sboxes.rs @@ -43,7 +43,7 @@ pub(crate) trait SboxExt: Sbox { for i in 0..4 { let shift = 8 * i; let k = ((a & (0xffu32 << shift)) >> shift) as usize; - v += (Self::EXP_SBOX[i][k] as u32) << shift; + v += u32::from(Self::EXP_SBOX[i][k]) << shift; } v } @@ -56,6 +56,7 @@ pub(crate) trait SboxExt: Sbox { impl SboxExt for T {} +#[derive(Clone, Copy, Debug)] pub enum Tc26 {} impl Sbox for Tc26 { @@ -72,6 +73,7 @@ impl Sbox for Tc26 { ]; } +#[derive(Clone, Copy, Debug)] pub enum TestSbox {} impl Sbox for TestSbox { @@ -88,6 +90,7 @@ impl Sbox for TestSbox { ]; } +#[derive(Clone, Copy, Debug)] pub enum CryptoProA {} impl Sbox for CryptoProA { @@ -104,6 +107,7 @@ impl Sbox for CryptoProA { ]; } +#[derive(Clone, Copy, Debug)] pub enum CryptoProB {} impl Sbox for CryptoProB { @@ -120,6 +124,7 @@ impl Sbox for CryptoProB { ]; } +#[derive(Clone, Copy, Debug)] pub enum CryptoProC {} impl Sbox for CryptoProC { @@ -136,6 +141,7 @@ impl Sbox for CryptoProC { ]; } +#[derive(Clone, Copy, Debug)] pub enum CryptoProD {} impl Sbox for CryptoProD { diff --git a/magma/src/variants.rs b/magma/src/variants.rs new file mode 100644 index 000000000..aafed05dc --- /dev/null +++ b/magma/src/variants.rs @@ -0,0 +1,15 @@ +#![allow(clippy::doc_markdown)] +use crate::{Gost89, sboxes}; + +/// Block cipher defined in GOST R 34.12-2015 (Magma) +pub type Magma = Gost89; +/// Block cipher defined in GOST 28147-89 with test S-box +pub type Gost89Test = Gost89; +/// Block cipher defined in GOST 28147-89 with CryptoPro S-box version A +pub type Gost89CryptoProA = Gost89; +/// Block cipher defined in GOST 28147-89 with CryptoPro S-box version B +pub type Gost89CryptoProB = Gost89; +/// Block cipher defined in GOST 28147-89 with CryptoPro S-box version C +pub type Gost89CryptoProC = Gost89; +/// Block cipher defined in GOST 28147-89 with CryptoPro S-box version D +pub type Gost89CryptoProD = Gost89; diff --git a/threefish/Cargo.toml b/threefish/Cargo.toml index 7f6bfac28..9d9b212d2 100644 --- a/threefish/Cargo.toml +++ b/threefish/Cargo.toml @@ -24,3 +24,6 @@ default = ["cipher"] [package.metadata.docs.rs] all-features = true + +[lints] +workspace = true diff --git a/threefish/benches/mod.rs b/threefish/benches/mod.rs index 84f2d33c5..9021ad46e 100644 --- a/threefish/benches/mod.rs +++ b/threefish/benches/mod.rs @@ -1,4 +1,5 @@ #![feature(test)] +#![allow(missing_docs)] extern crate test; use cipher::{block_decryptor_bench, block_encryptor_bench}; diff --git a/threefish/src/lib.rs b/threefish/src/lib.rs index d27788ca6..41960c76c 100644 --- a/threefish/src/lib.rs +++ b/threefish/src/lib.rs @@ -15,9 +15,8 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] -#![deny(unsafe_code)] #![cfg_attr(docsrs, feature(doc_cfg))] -#![warn(missing_docs, rust_2018_idioms)] +#![deny(unsafe_code)] #[cfg(feature = "cipher")] pub use cipher; @@ -41,12 +40,12 @@ use zeroize::{Zeroize, ZeroizeOnDrop}; fn mix(r: u8, x: (u64, u64)) -> (u64, u64) { let y0 = x.0.wrapping_add(x.1); - let y1 = x.1.rotate_left(r as u32) ^ y0; + let y1 = x.1.rotate_left(u32::from(r)) ^ y0; (y0, y1) } fn inv_mix(r: u8, y: (u64, u64)) -> (u64, u64) { - let x1 = (y.0 ^ y.1).rotate_right(r as u32); + let x1 = (y.0 ^ y.1).rotate_right(u32::from(r)); let x0 = y.0.wrapping_sub(x1); (x0, x1) } diff --git a/threefish/tests/mod.rs b/threefish/tests/mod.rs index 47f5ff618..e295917e0 100644 --- a/threefish/tests/mod.rs +++ b/threefish/tests/mod.rs @@ -1,5 +1,5 @@ //! Test vectors from: -//! https://github.com/weidai11/cryptopp/blob/master/TestVectors/threefish.txt +//! #![cfg(feature = "cipher")] use cipher::{Block, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; use hex_literal::hex; diff --git a/twofish/Cargo.toml b/twofish/Cargo.toml index 2bd37bf88..afde4b375 100644 --- a/twofish/Cargo.toml +++ b/twofish/Cargo.toml @@ -3,7 +3,7 @@ name = "twofish" version = "0.8.0" authors = ["RustCrypto Developers"] edition = "2024" -rust-version = "1.85" +rust-version = "1.88" documentation = "https://docs.rs/twofish" repository = "https://github.com/RustCrypto/block-ciphers" license = "MIT OR Apache-2.0" @@ -23,3 +23,6 @@ zeroize = ["cipher/zeroize"] [package.metadata.docs.rs] all-features = true + +[lints] +workspace = true diff --git a/twofish/benches/mod.rs b/twofish/benches/mod.rs index b780788d5..da9889587 100644 --- a/twofish/benches/mod.rs +++ b/twofish/benches/mod.rs @@ -1,4 +1,5 @@ #![feature(test)] +#![allow(missing_docs)] extern crate test; use cipher::{block_decryptor_bench, block_encryptor_bench}; diff --git a/twofish/src/lib.rs b/twofish/src/lib.rs index cc9a99300..1e94ab0b8 100644 --- a/twofish/src/lib.rs +++ b/twofish/src/lib.rs @@ -15,10 +15,8 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] -#![deny(unsafe_code)] #![cfg_attr(docsrs, feature(doc_cfg))] -#![warn(missing_docs, rust_2018_idioms)] -#![allow(clippy::needless_range_loop, clippy::unreadable_literal)] +#![deny(unsafe_code)] pub use cipher; @@ -135,7 +133,7 @@ impl Twofish { fn g_func(&self, x: u32) -> u32 { let mut result: u32 = 0; for y in 0..4 { - let mut g = sbox(QORD[y][self.start], (x >> (8 * y)) as u8); + let mut g = sbox(QORD[y][self.start], x.to_le_bytes()[y]); for z in self.start + 1..5 { g ^= self.s[4 * (z - self.start - 1) + y]; @@ -180,7 +178,7 @@ impl KeySizeUser for Twofish { impl KeyInit for Twofish { #[inline] fn new(key: &Key) -> Self { - Self::new_from_slice(key).unwrap() + Self::new_from_slice(key).expect("key has correct size") } #[inline] @@ -210,20 +208,16 @@ impl ParBlocksSizeUser for Twofish { impl BlockCipherEncrypt for Twofish { #[inline] fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { - f.call(self) + f.call(self); } } impl BlockCipherEncBackend for Twofish { #[inline] fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { - let b = block.get_in(); - let mut p = [ - u32::from_le_bytes(b[0..4].try_into().unwrap()), - u32::from_le_bytes(b[4..8].try_into().unwrap()), - u32::from_le_bytes(b[8..12].try_into().unwrap()), - u32::from_le_bytes(b[12..16].try_into().unwrap()), - ]; + let (chunks, tail) = block.get_in().as_chunks(); + assert!(tail.is_empty()); + let mut p: [u32; 4] = core::array::from_fn(|i| u32::from_le_bytes(chunks[i])); // Input whitening for i in 0..4 { @@ -263,19 +257,21 @@ impl BlockCipherEncBackend for Twofish { impl BlockCipherDecrypt for Twofish { #[inline] fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { - f.call(self) + f.call(self); } } impl BlockCipherDecBackend for Twofish { #[inline] fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { - let b = block.get_in(); + let (chunks, tail) = block.get_in().as_chunks(); + assert!(tail.is_empty()); + let mut c = [ - u32::from_le_bytes(b[8..12].try_into().unwrap()) ^ self.k[6], - u32::from_le_bytes(b[12..16].try_into().unwrap()) ^ self.k[7], - u32::from_le_bytes(b[0..4].try_into().unwrap()) ^ self.k[4], - u32::from_le_bytes(b[4..8].try_into().unwrap()) ^ self.k[5], + u32::from_le_bytes(chunks[2]) ^ self.k[6], + u32::from_le_bytes(chunks[3]) ^ self.k[7], + u32::from_le_bytes(chunks[0]) ^ self.k[4], + u32::from_le_bytes(chunks[1]) ^ self.k[5], ]; for r in (0..8).rev() { diff --git a/twofish/src/tests.rs b/twofish/src/tests.rs index bd47f7b85..5b396e2d5 100644 --- a/twofish/src/tests.rs +++ b/twofish/src/tests.rs @@ -3,7 +3,7 @@ use super::*; #[test] fn intermediate128() { let key = [0u8; 16]; - let twofish = Twofish::new_from_slice(&key).unwrap(); + let twofish = Twofish::new_from_slice(&key).expect("key has correct size"); let subkeys: [u32; 40] = [ 0x52C54DDE, 0x11F0626D, 0x7CAC9D4A, 0x4D1B4AAA, 0xB7B83A10, 0x1E7D0BEB, 0xEE9C341F, 0xCFE14BE4, 0xF98FFEF9, 0x9C5B3C17, 0x15A48310, 0x342A4D81, 0x424D89FE, 0xC14724A7, @@ -21,7 +21,7 @@ fn intermediate192() { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, ]; - let twofish = Twofish::new_from_slice(&key).unwrap(); + let twofish = Twofish::new_from_slice(&key).expect("key has correct size"); let sboxkey: [u8; 12] = [ 0xf2, 0xf6, 0x9f, 0xb8, 0x4b, 0xbc, 0x55, 0xb2, 0x61, 0x10, 0x66, 0x45, ]; @@ -44,7 +44,7 @@ fn intermediate256() { 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, ]; - let twofish = Twofish::new_from_slice(&key).unwrap(); + let twofish = Twofish::new_from_slice(&key).expect("key has correct size"); let sboxkey: [u8; 16] = [ 0xf2, 0xf6, 0x9f, 0xb8, 0x4b, 0xbc, 0x55, 0xb2, 0x61, 0x10, 0x66, 0x45, 0xf7, 0x47, 0x44, 0x8e, diff --git a/twofish/tests/mod.rs b/twofish/tests/mod.rs index aa324c586..5e1789f3a 100644 --- a/twofish/tests/mod.rs +++ b/twofish/tests/mod.rs @@ -1,3 +1,4 @@ +//! Basic tests use cipher::{BlockCipherDecrypt, BlockCipherEncrypt, KeyInit, array::Array}; use hex_literal::hex; use twofish::Twofish; diff --git a/xtea/Cargo.toml b/xtea/Cargo.toml index e7d23b11e..3b141894a 100644 --- a/xtea/Cargo.toml +++ b/xtea/Cargo.toml @@ -3,7 +3,7 @@ name = "xtea" version = "0.1.0" authors = ["RustCrypto Developers"] edition = "2024" -rust-version = "1.85" +rust-version = "1.88" documentation = "https://docs.rs/xtea" repository = "https://github.com/RustCrypto/block-ciphers" license = "MIT OR Apache-2.0" @@ -22,3 +22,6 @@ zeroize = ["cipher/zeroize"] [package.metadata.docs.rs] all-features = true + +[lints] +workspace = true diff --git a/xtea/benches/mod.rs b/xtea/benches/mod.rs index 1105734da..bc868d39e 100644 --- a/xtea/benches/mod.rs +++ b/xtea/benches/mod.rs @@ -1,4 +1,5 @@ #![feature(test)] +#![allow(missing_docs)] extern crate test; use cipher::{block_decryptor_bench, block_encryptor_bench}; diff --git a/xtea/src/consts.rs b/xtea/src/consts.rs index d5bba793d..df0238292 100644 --- a/xtea/src/consts.rs +++ b/xtea/src/consts.rs @@ -1,2 +1,2 @@ pub const DELTA: u32 = 0x9e3779b9; -pub const ROUNDS: usize = 32; +pub const ROUNDS: u32 = 32; diff --git a/xtea/src/lib.rs b/xtea/src/lib.rs index e37cf5c4d..6f6279f66 100644 --- a/xtea/src/lib.rs +++ b/xtea/src/lib.rs @@ -15,16 +15,15 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] -#![deny(unsafe_code)] #![cfg_attr(docsrs, feature(doc_cfg))] -#![warn(missing_docs, rust_2018_idioms)] +#![deny(unsafe_code)] pub use cipher; use cipher::{ AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, - BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, - InvalidLength, Key, KeyInit, KeySizeUser, ParBlocksSizeUser, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key, + KeyInit, KeySizeUser, ParBlocksSizeUser, consts::{U1, U8, U16}, }; use core::fmt; @@ -37,7 +36,7 @@ use consts::{DELTA, ROUNDS}; /// XTEA block self. pub struct Xtea { - k: [u32; 4], + key: [u32; 4], } impl KeySizeUser for Xtea { @@ -45,21 +44,10 @@ impl KeySizeUser for Xtea { } impl KeyInit for Xtea { + #[inline] fn new(key: &Key) -> Self { - Self::new_from_slice(key).unwrap() - } - - fn new_from_slice(key: &[u8]) -> Result { - if key.len() != 16 { - return Err(InvalidLength); - } - let key = [ - u32::from_le_bytes(key[0..4].try_into().unwrap()), - u32::from_le_bytes(key[4..8].try_into().unwrap()), - u32::from_le_bytes(key[8..12].try_into().unwrap()), - u32::from_le_bytes(key[12..16].try_into().unwrap()), - ]; - Ok(Xtea { k: key }) + let key = read_u32_le(key); + Self { key } } } @@ -74,134 +62,126 @@ impl ParBlocksSizeUser for Xtea { impl BlockCipherEncrypt for Xtea { #[inline] fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { - f.call(self) + f.call(self); } } impl BlockCipherEncBackend for Xtea { #[inline] fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { - let v = block.get_in(); - let mut v0 = u32::from_le_bytes(v[0..4].try_into().unwrap()); - let mut v1 = u32::from_le_bytes(v[4..8].try_into().unwrap()); + let [mut v0, mut v1] = read_u32_le(block.get_in()); let mut sum = 0u32; // Use 4 loops as otherwise unrolling will not be performed by default for _ in 0..8 { v0 = v0.wrapping_add( (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) - ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ^ sum.wrapping_add(self.key[(sum & 3) as usize]), ); sum = sum.wrapping_add(DELTA); v1 = v1.wrapping_add( (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) - ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ^ sum.wrapping_add(self.key[((sum >> 11) & 3) as usize]), ); } for _ in 0..8 { v0 = v0.wrapping_add( (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) - ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ^ sum.wrapping_add(self.key[(sum & 3) as usize]), ); sum = sum.wrapping_add(DELTA); v1 = v1.wrapping_add( (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) - ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ^ sum.wrapping_add(self.key[((sum >> 11) & 3) as usize]), ); } for _ in 0..8 { v0 = v0.wrapping_add( (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) - ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ^ sum.wrapping_add(self.key[(sum & 3) as usize]), ); sum = sum.wrapping_add(DELTA); v1 = v1.wrapping_add( (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) - ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ^ sum.wrapping_add(self.key[((sum >> 11) & 3) as usize]), ); } for _ in 0..8 { v0 = v0.wrapping_add( (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) - ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ^ sum.wrapping_add(self.key[(sum & 3) as usize]), ); sum = sum.wrapping_add(DELTA); v1 = v1.wrapping_add( (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) - ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ^ sum.wrapping_add(self.key[((sum >> 11) & 3) as usize]), ); } - let v = block.get_out(); - v[0..4].copy_from_slice(&v0.to_le_bytes()); - v[4..8].copy_from_slice(&v1.to_le_bytes()); + write_u32_le(block.get_out(), [v0, v1]); } } impl BlockCipherDecrypt for Xtea { #[inline] fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { - f.call(self) + f.call(self); } } impl BlockCipherDecBackend for Xtea { #[inline] fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { - let v = block.get_in(); - let mut v0 = u32::from_le_bytes(v[0..4].try_into().unwrap()); - let mut v1 = u32::from_le_bytes(v[4..8].try_into().unwrap()); - let mut sum = DELTA.wrapping_mul(ROUNDS as u32); + let [mut v0, mut v1] = read_u32_le(block.get_in()); + let mut sum = DELTA.wrapping_mul(ROUNDS); // Same as encrypt, just in reverse for _ in 0..8 { v1 = v1.wrapping_sub( (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) - ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ^ sum.wrapping_add(self.key[((sum >> 11) & 3) as usize]), ); sum = sum.wrapping_sub(DELTA); v0 = v0.wrapping_sub( (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) - ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ^ sum.wrapping_add(self.key[(sum & 3) as usize]), ); } for _ in 0..8 { v1 = v1.wrapping_sub( (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) - ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ^ sum.wrapping_add(self.key[((sum >> 11) & 3) as usize]), ); sum = sum.wrapping_sub(DELTA); v0 = v0.wrapping_sub( (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) - ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ^ sum.wrapping_add(self.key[(sum & 3) as usize]), ); } for _ in 0..8 { v1 = v1.wrapping_sub( (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) - ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ^ sum.wrapping_add(self.key[((sum >> 11) & 3) as usize]), ); sum = sum.wrapping_sub(DELTA); v0 = v0.wrapping_sub( (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) - ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ^ sum.wrapping_add(self.key[(sum & 3) as usize]), ); } for _ in 0..8 { v1 = v1.wrapping_sub( (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) - ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ^ sum.wrapping_add(self.key[((sum >> 11) & 3) as usize]), ); sum = sum.wrapping_sub(DELTA); v0 = v0.wrapping_sub( (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) - ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ^ sum.wrapping_add(self.key[(sum & 3) as usize]), ); } - let v = block.get_out(); - v[0..4].copy_from_slice(&v0.to_le_bytes()); - v[4..8].copy_from_slice(&v1.to_le_bytes()); + write_u32_le(block.get_out(), [v0, v1]); } } @@ -220,9 +200,25 @@ impl AlgorithmName for Xtea { impl Drop for Xtea { fn drop(&mut self) { #[cfg(feature = "zeroize")] - self.k.zeroize(); + self.key.zeroize(); } } #[cfg(feature = "zeroize")] impl ZeroizeOnDrop for Xtea {} + +fn read_u32_le(src: &[u8]) -> [u32; N] { + assert_eq!(size_of_val(src), size_of::<[u32; N]>()); + let (chunks, tail) = src.as_chunks(); + assert!(tail.is_empty()); + core::array::from_fn(|i| u32::from_le_bytes(chunks[i])) +} + +fn write_u32_le(dst: &mut [u8], val: [u32; N]) { + assert_eq!(size_of_val(dst), size_of_val(&val)); + let (chunks, tail) = dst.as_chunks_mut(); + assert!(tail.is_empty()); + for i in 0..N { + chunks[i] = val[i].to_le_bytes(); + } +} diff --git a/xtea/tests/mod.rs b/xtea/tests/mod.rs index 0b266bb69..576d6a641 100644 --- a/xtea/tests/mod.rs +++ b/xtea/tests/mod.rs @@ -1,3 +1,4 @@ +//! Basic tests use cipher::{BlockCipherDecrypt, BlockCipherEncrypt, KeyInit, array::Array}; use xtea::Xtea; @@ -7,7 +8,7 @@ fn xtea() { let key = b"0123456789012345"; let plaintext = b"ABCDEFGH"; let ciphertext = [0xea, 0x0c, 0x3d, 0x7c, 0x1c, 0x22, 0x55, 0x7f]; - let cipher = Xtea::new_from_slice(key).unwrap(); + let cipher = Xtea::new(key.into()); let mut block = Array(*plaintext); cipher.encrypt_block(&mut block);