From 864f459567be3d9fd2f16d34fc44eef8091e220c Mon Sep 17 00:00:00 2001 From: ty Date: Fri, 1 May 2026 23:37:07 +0800 Subject: [PATCH] chore(deps): upgrade RustCrypto stack to latest versions Upgrade all cryptography dependencies to their latest versions and migrate the codebase to the new RustCrypto 0.11 ecosystem APIs. Dependency updates: - aes-gcm 0.10 -> 0.11.0-rc.3 - aes-gcm-siv 0.11 -> 0.12.0-rc.3 - ccm 0.5 -> 0.6.0-rc.3 - chacha20poly1305 0.10 -> 0.11.0-rc.3 - aead 0.5 -> 0.6.0-rc.10 - aes 0.8 -> 0.9 - chacha20 0.9 -> 0.10 - ctr 0.9 -> 0.10 - camellia 0.1 -> 0.2 - sm4 0.5 -> 0.6 - ghash 0.5 -> 0.6 - subtle 2.5 -> 2.6 - bytes 1.3 -> 1.11 - blake3 1.3 -> 1.8 The AEAD crates remain on their 0.11 rc releases because the stable 0.10 line still pins aes 0.8 and ghash 0.5, which would conflict with the upgraded block/universal-hash stack. API migration: - Replace aead::generic_array with aead::array (hybrid-array) - Replace AeadInPlace with AeadInOut (encrypt_inout_detached / decrypt_inout_detached take InOutBuf) - Update AeadCore impl for SM4-GCM: drop CiphertextOverhead, add TAG_POSITION constant - Replace deprecated Array::from_slice / from_mut_slice with TryFrom - Rename cipher::{BlockEncrypt, BlockDecrypt} imports to their BlockCipher{Encrypt,Decrypt} counterparts - Import Unsigned from typenum (cipher::typenum / aead::array::typenum) - Use cipher::Iv for chacha20 nonce (Nonce is no longer re-exported) Also bump rust-version to 1.85 to match the MSRV of the new RustCrypto crates. --- Cargo.toml | 30 ++++++++--------- src/v1/aeadcipher/aes_ccm.rs | 28 +++++++++------ src/v1/aeadcipher/aes_gcm.rs | 43 +++++++++++++---------- src/v1/aeadcipher/aes_gcm_siv.rs | 36 +++++++++++--------- src/v1/aeadcipher/chacha20_poly1305.rs | 19 ++++++----- src/v1/aeadcipher/sm4_ccm.rs | 19 ++++++----- src/v1/aeadcipher/sm4_gcm.rs | 20 ++++++----- src/v1/aeadcipher/sm4_gcm_cipher.rs | 45 ++++++++++++++----------- src/v1/aeadcipher/xchacha20_poly1305.rs | 19 ++++++----- src/v1/streamcipher/chacha20.rs | 9 +++-- src/v1/streamcipher/crypto/aes.rs | 14 ++++---- src/v1/streamcipher/crypto/camellia.rs | 14 ++++---- src/v1/streamcipher/ctr.rs | 20 +++++------ src/v2/crypto/chacha8_poly1305.rs | 19 ++++++----- src/v2/crypto/xchacha8_poly1305.rs | 19 ++++++----- 15 files changed, 198 insertions(+), 156 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6c225f4..91def05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["Cryptography"] description = "Shadowsocks Crypto" repository = "https://github.com/shadowsocks/shadowsocks-crypto" documentation = "https://docs.rs/shadowsocks-crypto" -rust-version = "1.71" +rust-version = "1.85" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] @@ -39,10 +39,10 @@ aws-lc = ["dep:aws-lc-rs"] [dependencies] cfg-if = { version = "1.0", optional = true } rand = "0.10" -aes-gcm = { version = "0.10", optional = true } -aes-gcm-siv = { version = "0.11", optional = true } -ccm = { version = "0.5", optional = true } -chacha20poly1305 = { version = "0.10", optional = true } +aes-gcm = { version = "0.11.0-rc.3", optional = true } +aes-gcm-siv = { version = "0.12.0-rc.3", optional = true } +ccm = { version = "0.6.0-rc.3", optional = true } +chacha20poly1305 = { version = "0.11.0-rc.3", optional = true } ring-compat = { version = "0.8", default-features = false, features = [ "aead", "alloc", @@ -51,16 +51,16 @@ aws-lc-rs = { version = "1.16", optional = true } md-5 = { version = "0.11", optional = true } hkdf = { version = "0.13", optional = true } sha1 = { version = "0.11", optional = true } -blake3 = { version = "1.3", optional = true } -chacha20 = { version = "0.9", features = [], optional = true } -aes = { version = "0.8", optional = true } -ctr = { version = "0.9", optional = true } -bytes = { version = "1.3", optional = true } -camellia = { version = "0.1", optional = true } -sm4 = { version = "0.5", optional = true } -ghash = { version = "0.5", optional = true } -aead = { version = "0.5", optional = true } -subtle = { version = "2.5", optional = true } +blake3 = { version = "1.8", optional = true } +chacha20 = { version = "0.10", features = [], optional = true } +aes = { version = "0.9", optional = true } +ctr = { version = "0.10", optional = true } +bytes = { version = "1.11", optional = true } +camellia = { version = "0.2", optional = true } +sm4 = { version = "0.6", optional = true } +ghash = { version = "0.6", optional = true } +aead = { version = "0.6.0-rc.10", optional = true } +subtle = { version = "2.6", optional = true } #[target.'cfg(all(unix, any(target_arch = "x86", target_arch = "x86_64")))'.dependencies] #md-5 = { version = "0.10", features = ["asm"] } diff --git a/src/v1/aeadcipher/aes_ccm.rs b/src/v1/aeadcipher/aes_ccm.rs index 1c3a7ad..3a47e92 100644 --- a/src/v1/aeadcipher/aes_ccm.rs +++ b/src/v1/aeadcipher/aes_ccm.rs @@ -1,6 +1,6 @@ use aes::{Aes128, Aes256}; use ccm::{ - aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser}, + aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser}, consts::{U12, U16}, Ccm, Nonce, @@ -27,22 +27,25 @@ impl Aes128Ccm { } pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::::try_from(nonce).expect("AES_128_CCM nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("AES_128_CCM encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::::try_from(nonce).expect("AES_128_CCM nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } @@ -66,21 +69,24 @@ impl Aes256Ccm { } pub fn encrypt(&mut self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::::try_from(nonce).expect("AES_256_CCM nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("AES_256_CCM encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&mut self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::::try_from(nonce).expect("AES_256_CCM nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } diff --git a/src/v1/aeadcipher/aes_gcm.rs b/src/v1/aeadcipher/aes_gcm.rs index 324e9be..b1101bf 100644 --- a/src/v1/aeadcipher/aes_gcm.rs +++ b/src/v1/aeadcipher/aes_gcm.rs @@ -99,19 +99,20 @@ cfg_if! { } } else { use aes_gcm::{ - aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeySizeUser, KeyInit}, - Key, - Nonce, - Tag, + aead::{self, array::typenum::Unsigned, AeadCore, AeadInOut, KeySizeUser, KeyInit}, }; use aes_gcm::{Aes128Gcm as CryptoAes128Gcm, Aes256Gcm as CryptoAes256Gcm}; + type Key = aead::Key; + type Nonce = aead::Nonce; + type Tag = aead::Tag; + pub struct Aes128Gcm(Box); impl Aes128Gcm { pub fn new(key: &[u8]) -> Aes128Gcm { - let key = Key::::from_slice(key); - Aes128Gcm(Box::new(CryptoAes128Gcm::new(key))) + let key = Key::::try_from(key).expect("AES_128_GCM key"); + Aes128Gcm(Box::new(CryptoAes128Gcm::new(&key))) } pub fn key_size() -> usize { @@ -127,22 +128,25 @@ cfg_if! { } pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::::try_from(nonce).expect("AES_128_GCM nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("AES_128_GCM encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::::try_from(nonce).expect("AES_128_GCM nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } @@ -150,8 +154,8 @@ cfg_if! { impl Aes256Gcm { pub fn new(key: &[u8]) -> Aes256Gcm { - let key = Key::::from_slice(key); - Aes256Gcm(Box::new(CryptoAes256Gcm::new(key))) + let key = Key::::try_from(key).expect("AES_256_GCM key"); + Aes256Gcm(Box::new(CryptoAes256Gcm::new(&key))) } pub fn key_size() -> usize { @@ -167,22 +171,25 @@ cfg_if! { } pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::::try_from(nonce).expect("AES_256_GCM nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("AES_256_GCM encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::::try_from(nonce).expect("AES_256_GCM nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } } diff --git a/src/v1/aeadcipher/aes_gcm_siv.rs b/src/v1/aeadcipher/aes_gcm_siv.rs index 2015d19..7fe1d31 100644 --- a/src/v1/aeadcipher/aes_gcm_siv.rs +++ b/src/v1/aeadcipher/aes_gcm_siv.rs @@ -66,7 +66,7 @@ cfg_if! { aead_gcm_siv_cipher!(Aes256GcmSiv, AES_256_GCM_SIV); } else { use aes_gcm_siv::{ - aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser}, + aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser}, Aes128GcmSiv as CryptoAes128GcmSiv, Aes256GcmSiv as CryptoAes256GcmSiv, Key, @@ -78,8 +78,8 @@ cfg_if! { impl Aes128GcmSiv { pub fn new(key: &[u8]) -> Aes128GcmSiv { - let key = Key::::from_slice(key); - Aes128GcmSiv(CryptoAes128GcmSiv::new(key)) + let key = Key::::try_from(key).expect("AES_128_GCM_SIV key"); + Aes128GcmSiv(CryptoAes128GcmSiv::new(&key)) } pub fn key_size() -> usize { @@ -95,22 +95,25 @@ cfg_if! { } pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::try_from(nonce).expect("AES_128_GCM_SIV nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("AES_128_GCM_SIV encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::try_from(nonce).expect("AES_128_GCM_SIV nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } @@ -118,8 +121,8 @@ cfg_if! { impl Aes256GcmSiv { pub fn new(key: &[u8]) -> Aes256GcmSiv { - let key = Key::::from_slice(key); - Aes256GcmSiv(CryptoAes256GcmSiv::new(key)) + let key = Key::::try_from(key).expect("AES_256_GCM_SIV key"); + Aes256GcmSiv(CryptoAes256GcmSiv::new(&key)) } pub fn key_size() -> usize { @@ -135,22 +138,25 @@ cfg_if! { } pub fn encrypt(&mut self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::try_from(nonce).expect("AES_256_GCM_SIV nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("AES_256_GCM_SIV encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&mut self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::try_from(nonce).expect("AES_256_GCM_SIV nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } } diff --git a/src/v1/aeadcipher/chacha20_poly1305.rs b/src/v1/aeadcipher/chacha20_poly1305.rs index 0dd714d..15fd08f 100644 --- a/src/v1/aeadcipher/chacha20_poly1305.rs +++ b/src/v1/aeadcipher/chacha20_poly1305.rs @@ -76,7 +76,7 @@ cfg_if! { } else { use chacha20poly1305::ChaCha20Poly1305 as CryptoChaCha20Poly1305; use chacha20poly1305::{ - aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeySizeUser, KeyInit}, + aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeySizeUser, KeyInit}, Key, Nonce, Tag, @@ -86,8 +86,8 @@ cfg_if! { impl ChaCha20Poly1305 { pub fn new(key: &[u8]) -> ChaCha20Poly1305 { - let key = Key::from_slice(key); - ChaCha20Poly1305(CryptoChaCha20Poly1305::new(key)) + let key = Key::try_from(key).expect("CHACHA20_POLY1305 key"); + ChaCha20Poly1305(CryptoChaCha20Poly1305::new(&key)) } pub fn key_size() -> usize { @@ -103,22 +103,25 @@ cfg_if! { } pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::try_from(nonce).expect("CHACHA20_POLY1305 nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("CHACHA20_POLY1305 encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::try_from(nonce).expect("CHACHA20_POLY1305 nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } } diff --git a/src/v1/aeadcipher/sm4_ccm.rs b/src/v1/aeadcipher/sm4_ccm.rs index d4cffb3..24d2eb1 100644 --- a/src/v1/aeadcipher/sm4_ccm.rs +++ b/src/v1/aeadcipher/sm4_ccm.rs @@ -3,7 +3,7 @@ //! https://datatracker.ietf.org/doc/html/rfc8998 use ccm::{ - aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser}, + aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser}, consts::{U12, U16}, Ccm, Nonce, @@ -31,22 +31,25 @@ impl Sm4Ccm { } pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::::try_from(nonce).expect("SM4_CCM nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("SM4_CCM encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::::try_from(nonce).expect("SM4_CCM nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } @@ -69,14 +72,14 @@ mod test { let mut tag = hex::decode("16842D4FA186F56AB33256971FA110F4").unwrap(); cipher_text.append(&mut tag); // postfix tag - let nonce = super::Nonce::from_slice(&iv); + let nonce = super::Nonce::::try_from(&iv[..]).unwrap(); let cipher = Ccm::::new_from_slice(&key).unwrap(); let plain_text_payload = Payload { msg: &plain_text, aad: &aad, }; - let result = cipher.encrypt(nonce, plain_text_payload).unwrap(); + let result = cipher.encrypt(&nonce, plain_text_payload).unwrap(); assert_eq!(result, cipher_text); } diff --git a/src/v1/aeadcipher/sm4_gcm.rs b/src/v1/aeadcipher/sm4_gcm.rs index e11d1b1..6135feb 100644 --- a/src/v1/aeadcipher/sm4_gcm.rs +++ b/src/v1/aeadcipher/sm4_gcm.rs @@ -1,7 +1,6 @@ //! SM4-GCM -use aead::{AeadCore, AeadInPlace, Key, KeyInit, KeySizeUser}; -use sm4::cipher::Unsigned; +use aead::{array::typenum::Unsigned, AeadCore, AeadInOut, Key, KeyInit, KeySizeUser}; use super::sm4_gcm_cipher::{Nonce, Sm4Gcm as CryptoSm4Gcm, Tag}; @@ -9,8 +8,8 @@ pub struct Sm4Gcm(CryptoSm4Gcm); impl Sm4Gcm { pub fn new(key: &[u8]) -> Sm4Gcm { - let key = Key::::from_slice(key); - Sm4Gcm(CryptoSm4Gcm::new(key)) + let key = Key::::try_from(key).expect("SM4_GCM key"); + Sm4Gcm(CryptoSm4Gcm::new(&key)) } pub fn key_size() -> usize { @@ -26,21 +25,24 @@ impl Sm4Gcm { } pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::try_from(nonce).expect("SM4_GCM nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("SM4_GCM encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::try_from(nonce).expect("SM4_GCM nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } diff --git a/src/v1/aeadcipher/sm4_gcm_cipher.rs b/src/v1/aeadcipher/sm4_gcm_cipher.rs index 5a69c7e..5137d3b 100644 --- a/src/v1/aeadcipher/sm4_gcm_cipher.rs +++ b/src/v1/aeadcipher/sm4_gcm_cipher.rs @@ -3,17 +3,19 @@ //! https://datatracker.ietf.org/doc/html/rfc8998 use aead::{ - consts::{U0, U12, U16}, - generic_array::GenericArray, + array::{typenum::Unsigned, Array}, + consts::{U12, U16}, + inout::InOutBuf, AeadCore, - AeadInPlace, + AeadInOut, Key, KeyInit, KeySizeUser, + TagPosition, }; use ghash::{universal_hash::UniversalHash, GHash}; use sm4::{ - cipher::{BlockEncrypt, InnerIvInit, StreamCipherCore, Unsigned}, + cipher::{BlockCipherEncrypt, InnerIvInit, StreamCipherCore}, Sm4, }; @@ -27,13 +29,13 @@ pub const P_MAX: u64 = 1 << 36; pub const C_MAX: u64 = (1 << 36) + 16; /// SM4-GCM nonces. -pub type Nonce = GenericArray; +pub type Nonce = Array; /// SM4-GCM tags. -pub type Tag = GenericArray; +pub type Tag = Array; /// SM4 block. -type Block = GenericArray; +type Block = Array; /// Counter mode with a 32-bit big endian counter. type Ctr32BE<'a> = ctr::CtrCore<&'a Sm4, ctr::flavors::Ctr32BE>; @@ -67,13 +69,18 @@ impl From for Sm4Gcm { } impl AeadCore for Sm4Gcm { - type CiphertextOverhead = U0; type NonceSize = U12; type TagSize = U16; + const TAG_POSITION: TagPosition = TagPosition::Postfix; } -impl AeadInPlace for Sm4Gcm { - fn encrypt_in_place_detached(&self, nonce: &Nonce, associated_data: &[u8], buffer: &mut [u8]) -> aead::Result { +impl AeadInOut for Sm4Gcm { + fn encrypt_inout_detached( + &self, + nonce: &Nonce, + associated_data: &[u8], + mut buffer: InOutBuf<'_, '_, u8>, + ) -> aead::Result { if buffer.len() as u64 > P_MAX || associated_data.len() as u64 > A_MAX { return Err(aead::Error); } @@ -82,17 +89,17 @@ impl AeadInPlace for Sm4Gcm { // TODO(tarcieri): interleave encryption with GHASH // See: - ctr.apply_keystream_partial(buffer.into()); + ctr.apply_keystream_partial(buffer.reborrow()); - let full_tag = self.compute_tag(mask, associated_data, buffer); - Ok(Tag::clone_from_slice(&full_tag[..Self::TagSize::to_usize()])) + let full_tag = self.compute_tag(mask, associated_data, buffer.get_out()); + Ok(Tag::try_from(&full_tag[..Self::TagSize::to_usize()]).expect("tag size")) } - fn decrypt_in_place_detached( + fn decrypt_inout_detached( &self, nonce: &Nonce, associated_data: &[u8], - buffer: &mut [u8], + mut buffer: InOutBuf<'_, '_, u8>, tag: &Tag, ) -> aead::Result<()> { if buffer.len() as u64 > C_MAX || associated_data.len() as u64 > A_MAX { @@ -103,14 +110,14 @@ impl AeadInPlace for Sm4Gcm { // TODO(tarcieri): interleave encryption with GHASH // See: - let expected_tag = self.compute_tag(mask, associated_data, buffer); + let expected_tag = self.compute_tag(mask, associated_data, buffer.get_in()); use subtle::ConstantTimeEq; if expected_tag[..::TagSize::to_usize()] .ct_eq(tag) .into() { - ctr.apply_keystream_partial(buffer.into()); + ctr.apply_keystream_partial(buffer.reborrow()); Ok(()) } else { Err(aead::Error) @@ -188,14 +195,14 @@ mod test { let mut tag = hex::decode("83DE3541E4C2B58177E065A9BF7B62EC").unwrap(); cipher_text.append(&mut tag); // postfix tag - let nonce = super::Nonce::from_slice(&iv); + let nonce = super::Nonce::try_from(&iv[..]).unwrap(); let cipher = super::Sm4Gcm::new_from_slice(&key).unwrap(); let plain_text_payload = Payload { msg: &plain_text, aad: &aad, }; - let result = cipher.encrypt(nonce, plain_text_payload).unwrap(); + let result = cipher.encrypt(&nonce, plain_text_payload).unwrap(); assert_eq!(result, cipher_text); } diff --git a/src/v1/aeadcipher/xchacha20_poly1305.rs b/src/v1/aeadcipher/xchacha20_poly1305.rs index aa77499..86912ac 100644 --- a/src/v1/aeadcipher/xchacha20_poly1305.rs +++ b/src/v1/aeadcipher/xchacha20_poly1305.rs @@ -1,6 +1,6 @@ pub use chacha20poly1305::XChaCha20Poly1305 as CryptoXChaCha20Poly1305; use chacha20poly1305::{ - aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser}, + aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser}, Key, Tag, XNonce, @@ -10,8 +10,8 @@ pub struct XChaCha20Poly1305(CryptoXChaCha20Poly1305); impl XChaCha20Poly1305 { pub fn new(key: &[u8]) -> XChaCha20Poly1305 { - let key = Key::from_slice(key); - XChaCha20Poly1305(CryptoXChaCha20Poly1305::new(key)) + let key = Key::try_from(key).expect("XCHACHA20_POLY1305 key"); + XChaCha20Poly1305(CryptoXChaCha20Poly1305::new(&key)) } pub fn key_size() -> usize { @@ -27,21 +27,24 @@ impl XChaCha20Poly1305 { } pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = XNonce::from_slice(nonce); + let nonce = XNonce::try_from(nonce).expect("XCHACHA20_POLY1305 nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("XCHACHA20_POLY1305 encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = XNonce::from_slice(nonce); + let nonce = XNonce::try_from(nonce).expect("XCHACHA20_POLY1305 nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } diff --git a/src/v1/streamcipher/chacha20.rs b/src/v1/streamcipher/chacha20.rs index b30386c..721329a 100644 --- a/src/v1/streamcipher/chacha20.rs +++ b/src/v1/streamcipher/chacha20.rs @@ -1,8 +1,7 @@ use chacha20::{ - cipher::{IvSizeUser, KeyIvInit, KeySizeUser, StreamCipher, Unsigned}, + cipher::{IvSizeUser, Iv, KeyIvInit, KeySizeUser, StreamCipher, typenum::Unsigned}, ChaCha20, Key, - Nonce, }; /// ChaCha20 for IETF Protocols @@ -14,9 +13,9 @@ pub struct Chacha20 { impl Chacha20 { pub fn new(key: &[u8], nonce: &[u8]) -> Self { - let key = Key::from_slice(key); - let nonce = Nonce::from_slice(nonce); - let cipher = ChaCha20::new(key, nonce); + let key = Key::try_from(key).expect("chacha20 key"); + let nonce = Iv::::try_from(nonce).expect("chacha20 nonce"); + let cipher = ChaCha20::new(&key, &nonce); Self { cipher } } diff --git a/src/v1/streamcipher/crypto/aes.rs b/src/v1/streamcipher/crypto/aes.rs index ed11342..2809b3f 100644 --- a/src/v1/streamcipher/crypto/aes.rs +++ b/src/v1/streamcipher/crypto/aes.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] use aes::{ - cipher::{BlockDecrypt, BlockEncrypt, BlockSizeUser, KeyInit, Unsigned}, + cipher::{BlockCipherDecrypt, BlockCipherEncrypt, BlockSizeUser, KeyInit, typenum::Unsigned}, Aes128 as CryptoAes128, Aes192 as CryptoAes192, Aes256 as CryptoAes256, @@ -20,12 +20,12 @@ impl Aes128 { } pub fn encrypt(&self, block: &mut [u8]) { - let block = Block::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.encrypt_block(block); } pub fn decrypt(&self, block: &mut [u8]) { - let block = Block::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.decrypt_block(block); } } @@ -42,12 +42,12 @@ impl Aes192 { } pub fn encrypt(&self, block: &mut [u8]) { - let block = Block::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.encrypt_block(block); } pub fn decrypt(&self, block: &mut [u8]) { - let block = Block::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.decrypt_block(block); } } @@ -64,12 +64,12 @@ impl Aes256 { } pub fn encrypt(&self, block: &mut [u8]) { - let block = Block::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.encrypt_block(block); } pub fn decrypt(&self, block: &mut [u8]) { - let block = Block::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.decrypt_block(block); } } diff --git a/src/v1/streamcipher/crypto/camellia.rs b/src/v1/streamcipher/crypto/camellia.rs index 38e929c..844b96f 100644 --- a/src/v1/streamcipher/crypto/camellia.rs +++ b/src/v1/streamcipher/crypto/camellia.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] use camellia::{ - cipher::{Block, BlockDecrypt, BlockEncrypt, BlockSizeUser, KeyInit, KeySizeUser, Unsigned}, + cipher::{Block, BlockCipherDecrypt, BlockCipherEncrypt, BlockSizeUser, KeyInit, KeySizeUser, typenum::Unsigned}, Camellia128 as CryptoCamellia128, Camellia192 as CryptoCamellia192, Camellia256 as CryptoCamellia256, @@ -19,12 +19,12 @@ impl Camellia128 { } pub fn encrypt(&self, block: &mut [u8]) { - let block = Block::::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.encrypt_block(block); } pub fn decrypt(&self, block: &mut [u8]) { - let block = Block::::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.decrypt_block(block); } } @@ -41,12 +41,12 @@ impl Camellia192 { } pub fn encrypt(&self, block: &mut [u8]) { - let block = Block::::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.encrypt_block(block); } pub fn decrypt(&self, block: &mut [u8]) { - let block = Block::::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.decrypt_block(block); } } @@ -63,12 +63,12 @@ impl Camellia256 { } pub fn encrypt(&self, block: &mut [u8]) { - let block = Block::::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.encrypt_block(block); } pub fn decrypt(&self, block: &mut [u8]) { - let block = Block::::from_mut_slice(block); + let block = <&mut Block>::try_from(block).expect("block size"); self.0.decrypt_block(block); } } diff --git a/src/v1/streamcipher/ctr.rs b/src/v1/streamcipher/ctr.rs index 37650e2..3777a0d 100644 --- a/src/v1/streamcipher/ctr.rs +++ b/src/v1/streamcipher/ctr.rs @@ -2,7 +2,7 @@ // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf use aes::{ - cipher::{Iv, IvSizeUser, Key, KeyIvInit, StreamCipher, Unsigned}, + cipher::{Iv, IvSizeUser, Key, KeyIvInit, StreamCipher, typenum::Unsigned}, Aes128 as CryptoAes128, Aes192 as CryptoAes192, Aes256 as CryptoAes256, @@ -25,9 +25,9 @@ impl Aes128Ctr { pub const KEY_LEN: usize = Aes128::KEY_LEN; pub fn new(key: &[u8], iv: &[u8]) -> Aes128Ctr { - let key = Key::::from_slice(key); - let iv = Iv::::from_slice(iv); - let ctr = CryptoAes128Ctr::new(key, iv); + let key = Key::::try_from(key).expect("Aes128Ctr key"); + let iv = Iv::::try_from(iv).expect("Aes128Ctr iv"); + let ctr = CryptoAes128Ctr::new(&key, &iv); Aes128Ctr(ctr) } @@ -47,9 +47,9 @@ impl Aes192Ctr { pub const KEY_LEN: usize = Aes192::KEY_LEN; pub fn new(key: &[u8], iv: &[u8]) -> Aes192Ctr { - let key = Key::::from_slice(key); - let iv = Iv::::from_slice(iv); - let ctr = CryptoAes192Ctr::new(key, iv); + let key = Key::::try_from(key).expect("Aes192Ctr key"); + let iv = Iv::::try_from(iv).expect("Aes192Ctr iv"); + let ctr = CryptoAes192Ctr::new(&key, &iv); Aes192Ctr(ctr) } @@ -69,9 +69,9 @@ impl Aes256Ctr { pub const KEY_LEN: usize = Aes256::KEY_LEN; pub fn new(key: &[u8], iv: &[u8]) -> Aes256Ctr { - let key = Key::::from_slice(key); - let iv = Iv::::from_slice(iv); - let ctr = CryptoAes256Ctr::new(key, iv); + let key = Key::::try_from(key).expect("Aes256Ctr key"); + let iv = Iv::::try_from(iv).expect("Aes256Ctr iv"); + let ctr = CryptoAes256Ctr::new(&key, &iv); Aes256Ctr(ctr) } diff --git a/src/v2/crypto/chacha8_poly1305.rs b/src/v2/crypto/chacha8_poly1305.rs index 341f307..ce02bc0 100644 --- a/src/v2/crypto/chacha8_poly1305.rs +++ b/src/v2/crypto/chacha8_poly1305.rs @@ -1,6 +1,6 @@ pub use chacha20poly1305::ChaCha8Poly1305 as CryptoChaCha8Poly1305; use chacha20poly1305::{ - aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser}, + aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser}, Key, Nonce, Tag, @@ -10,8 +10,8 @@ pub struct ChaCha8Poly1305(CryptoChaCha8Poly1305); impl ChaCha8Poly1305 { pub fn new(key: &[u8]) -> ChaCha8Poly1305 { - let key = Key::from_slice(key); - ChaCha8Poly1305(CryptoChaCha8Poly1305::new(key)) + let key = Key::try_from(key).expect("CHACHA8_POLY1305 key"); + ChaCha8Poly1305(CryptoChaCha8Poly1305::new(&key)) } pub fn key_size() -> usize { @@ -27,21 +27,24 @@ impl ChaCha8Poly1305 { } pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::try_from(nonce).expect("CHACHA8_POLY1305 nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("CHACHA8_POLY1305 encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = Nonce::from_slice(nonce); + let nonce = Nonce::try_from(nonce).expect("CHACHA8_POLY1305 nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } } diff --git a/src/v2/crypto/xchacha8_poly1305.rs b/src/v2/crypto/xchacha8_poly1305.rs index a38751d..420f76b 100644 --- a/src/v2/crypto/xchacha8_poly1305.rs +++ b/src/v2/crypto/xchacha8_poly1305.rs @@ -1,6 +1,6 @@ pub use chacha20poly1305::XChaCha8Poly1305 as CryptoXChaCha8Poly1305; use chacha20poly1305::{ - aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser}, + aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser}, Key, Tag, XNonce, @@ -10,8 +10,8 @@ pub struct XChaCha8Poly1305(CryptoXChaCha8Poly1305); impl XChaCha8Poly1305 { pub fn new(key: &[u8]) -> XChaCha8Poly1305 { - let key = Key::from_slice(key); - XChaCha8Poly1305(CryptoXChaCha8Poly1305::new(key)) + let key = Key::try_from(key).expect("XCHACHA8_POLY1305 key"); + XChaCha8Poly1305(CryptoXChaCha8Poly1305::new(&key)) } pub fn key_size() -> usize { @@ -27,21 +27,24 @@ impl XChaCha8Poly1305 { } pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) { - let nonce = XNonce::from_slice(nonce); + let nonce = XNonce::try_from(nonce).expect("XCHACHA8_POLY1305 nonce"); let (plaintext, out_tag) = plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size()); let tag = self .0 - .encrypt_in_place_detached(nonce, &[], plaintext) + .encrypt_inout_detached(&nonce, &[], plaintext.into()) .expect("XCHACHA8_POLY1305 encrypt"); out_tag.copy_from_slice(tag.as_slice()) } pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool { - let nonce = XNonce::from_slice(nonce); + let nonce = XNonce::try_from(nonce).expect("XCHACHA8_POLY1305 nonce"); let (ciphertext, in_tag) = ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size()); - let in_tag = Tag::from_slice(in_tag); - self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok() + let in_tag = match Tag::try_from(&*in_tag) { + Ok(t) => t, + Err(_) => return false, + }; + self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok() } }