From 0ce5b88511d7e63666d1a2be2404e6ee15444f6b Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 14 Aug 2024 19:22:03 +0300 Subject: [PATCH] Migrate to cipher v0.5.0-pre.7 (#446) --- .github/workflows/aes.yml | 1 + .github/workflows/aria.yml | 1 + .github/workflows/belt-block.yml | 1 + .github/workflows/blowfish.yml | 1 + .github/workflows/camellia.yml | 1 + .github/workflows/cast5.yml | 1 + .github/workflows/cast6.yml | 1 + .github/workflows/des.yml | 1 + .github/workflows/gift.yml | 1 + .github/workflows/idea.yml | 1 + .github/workflows/kuznyechik.yml | 1 + .github/workflows/magma.yml | 1 + .github/workflows/rc2.yml | 1 + .github/workflows/rc5.yml | 1 + .github/workflows/serpent.yml | 1 + .github/workflows/sm4.yml | 1 + .github/workflows/threefish.yml | 1 + .github/workflows/twofish.yml | 1 + .github/workflows/xtea.yml | 1 + Cargo.lock | 27 +- aes/Cargo.toml | 6 +- aes/LICENSE-MIT | 1 + aes/src/armv8.rs | 36 +- aes/src/autodetect.rs | 42 +- aes/src/lib.rs | 8 +- aes/src/macros.rs | 30 +- aes/src/ni.rs | 24 +- aes/src/soft.rs | 39 +- aria/Cargo.toml | 4 +- aria/LICENSE-MIT | 2 +- aria/src/aria128.rs | 69 ++++ aria/src/aria192.rs | 74 ++++ aria/src/aria256.rs | 77 ++++ aria/src/lib.rs | 367 ++++------------- aria/src/utils.rs | 82 ++++ aria/tests/mod.rs | 2 +- belt-block/Cargo.toml | 6 +- belt-block/src/cipher_impl.rs | 78 ++-- belt-block/src/lib.rs | 2 +- blowfish/Cargo.toml | 6 +- blowfish/LICENSE-MIT | 3 +- blowfish/src/lib.rs | 78 ++-- camellia/Cargo.toml | 5 +- camellia/LICENSE-MIT | 1 + camellia/src/camellia.rs | 352 ----------------- camellia/src/camellia128.rs | 35 ++ camellia/src/camellia192.rs | 37 ++ camellia/src/camellia256.rs | 39 ++ camellia/src/lib.rs | 143 ++++++- camellia/src/utils.rs | 178 +++++++++ cast5/Cargo.toml | 4 +- cast5/LICENSE-MIT | 2 +- cast5/src/lib.rs | 99 +++-- cast5/tests/mod.rs | 2 +- cast6/Cargo.toml | 4 +- cast6/LICENSE-MIT | 2 +- cast6/src/lib.rs | 93 +++-- des/CHANGELOG.md | 1 - des/Cargo.toml | 6 +- des/LICENSE-MIT | 1 + des/src/des.rs | 222 +++-------- des/src/lib.rs | 4 +- des/src/tdes.rs | 268 +++++++++---- des/src/utils.rs | 152 +++++++ gift/Cargo.toml | 6 +- gift/LICENSE-MIT | 1 + gift/src/key_schedule.rs | 86 ++-- gift/src/lib.rs | 193 ++++----- gift/src/primitives.rs | 4 +- gift/tests/mod.rs | 35 ++ gift/tests/test.rs | 67 ---- idea/Cargo.toml | 4 +- idea/LICENSE-MIT | 1 + idea/src/lib.rs | 67 +++- kuznyechik/Cargo.toml | 6 +- kuznyechik/LICENSE-MIT | 1 + kuznyechik/src/big_soft/backends.rs | 13 +- kuznyechik/src/big_soft/mod.rs | 12 +- kuznyechik/src/compact_soft/backends.rs | 30 +- kuznyechik/src/compact_soft/mod.rs | 12 +- kuznyechik/src/lib.rs | 12 +- kuznyechik/src/neon/backends.rs | 24 +- kuznyechik/src/neon/mod.rs | 20 +- kuznyechik/src/sse2/backends.rs | 14 +- kuznyechik/src/sse2/mod.rs | 20 +- magma/Cargo.toml | 6 +- magma/LICENSE-MIT | 1 + magma/src/lib.rs | 122 +++--- rc2/Cargo.toml | 4 +- rc2/LICENSE-MIT | 1 + rc2/src/lib.rs | 86 ++-- rc5/Cargo.toml | 11 +- rc5/LICENSE-MIT | 1 + rc5/src/block_cipher.rs | 361 ----------------- rc5/src/core/backend.rs | 229 ----------- rc5/src/core/mod.rs | 8 - rc5/src/lib.rs | 502 +++++++++++++++++++++++- rc5/src/{core => }/primitives.rs | 16 +- rc5/tests/mod.rs | 188 ++++----- serpent/Cargo.toml | 5 +- serpent/LICENSE-MIT | 1 + serpent/src/lib.rs | 228 ++++++----- sm4/Cargo.toml | 4 +- sm4/LICENSE-MIT | 4 +- sm4/src/lib.rs | 83 ++-- speck/Cargo.toml | 11 +- speck/LICENSE-MIT | 4 +- speck/src/lib.rs | 90 +++-- threefish/Cargo.toml | 4 +- threefish/LICENSE-MIT | 1 + threefish/src/lib.rs | 92 +++-- twofish/Cargo.toml | 4 +- twofish/LICENSE-MIT | 1 + twofish/src/lib.rs | 136 ++++--- xtea/Cargo.toml | 4 +- xtea/LICENSE-MIT | 1 + xtea/src/lib.rs | 160 +++++--- 117 files changed, 3096 insertions(+), 2633 deletions(-) create mode 100644 aria/src/aria128.rs create mode 100644 aria/src/aria192.rs create mode 100644 aria/src/aria256.rs create mode 100644 aria/src/utils.rs delete mode 100644 camellia/src/camellia.rs create mode 100644 camellia/src/camellia128.rs create mode 100644 camellia/src/camellia192.rs create mode 100644 camellia/src/camellia256.rs create mode 100644 camellia/src/utils.rs create mode 100644 des/src/utils.rs create mode 100644 gift/tests/mod.rs delete mode 100644 gift/tests/test.rs delete mode 100644 rc5/src/block_cipher.rs delete mode 100644 rc5/src/core/backend.rs delete mode 100644 rc5/src/core/mod.rs rename rc5/src/{core => }/primitives.rs (94%) diff --git a/.github/workflows/aes.yml b/.github/workflows/aes.yml index d461617d..dd2a2e70 100644 --- a/.github/workflows/aes.yml +++ b/.github/workflows/aes.yml @@ -57,6 +57,7 @@ jobs: cargo build --target ${{ matrix.target }} --features hazmat minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/aria.yml b/.github/workflows/aria.yml index e89c550b..ea24e61a 100644 --- a/.github/workflows/aria.yml +++ b/.github/workflows/aria.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/belt-block.yml b/.github/workflows/belt-block.yml index 7f090b07..af0e5f54 100644 --- a/.github/workflows/belt-block.yml +++ b/.github/workflows/belt-block.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/blowfish.yml b/.github/workflows/blowfish.yml index fd69e1ee..f94bfc3d 100644 --- a/.github/workflows/blowfish.yml +++ b/.github/workflows/blowfish.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/camellia.yml b/.github/workflows/camellia.yml index f0af972f..191a25e5 100644 --- a/.github/workflows/camellia.yml +++ b/.github/workflows/camellia.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/cast5.yml b/.github/workflows/cast5.yml index 1abde59f..a595a616 100644 --- a/.github/workflows/cast5.yml +++ b/.github/workflows/cast5.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/cast6.yml b/.github/workflows/cast6.yml index 93847c40..6d02202a 100644 --- a/.github/workflows/cast6.yml +++ b/.github/workflows/cast6.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/des.yml b/.github/workflows/des.yml index 6d35337c..ddc7bf7b 100644 --- a/.github/workflows/des.yml +++ b/.github/workflows/des.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/gift.yml b/.github/workflows/gift.yml index 0c1a4679..4222ef54 100644 --- a/.github/workflows/gift.yml +++ b/.github/workflows/gift.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/idea.yml b/.github/workflows/idea.yml index bfb9d2d0..4dcb2e42 100644 --- a/.github/workflows/idea.yml +++ b/.github/workflows/idea.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/kuznyechik.yml b/.github/workflows/kuznyechik.yml index e45f0bab..05321fc8 100644 --- a/.github/workflows/kuznyechik.yml +++ b/.github/workflows/kuznyechik.yml @@ -45,6 +45,7 @@ jobs: run: cargo build --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/magma.yml b/.github/workflows/magma.yml index b1abab2c..9ac3fbf1 100644 --- a/.github/workflows/magma.yml +++ b/.github/workflows/magma.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/rc2.yml b/.github/workflows/rc2.yml index 5693fc98..4f988948 100644 --- a/.github/workflows/rc2.yml +++ b/.github/workflows/rc2.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/rc5.yml b/.github/workflows/rc5.yml index 9ccc25b0..9a62811d 100644 --- a/.github/workflows/rc5.yml +++ b/.github/workflows/rc5.yml @@ -37,6 +37,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/serpent.yml b/.github/workflows/serpent.yml index 964dbb9f..3e5c41da 100644 --- a/.github/workflows/serpent.yml +++ b/.github/workflows/serpent.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/sm4.yml b/.github/workflows/sm4.yml index d401ad20..9365f2fc 100644 --- a/.github/workflows/sm4.yml +++ b/.github/workflows/sm4.yml @@ -37,6 +37,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/threefish.yml b/.github/workflows/threefish.yml index 028fad70..f73bdd23 100644 --- a/.github/workflows/threefish.yml +++ b/.github/workflows/threefish.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/twofish.yml b/.github/workflows/twofish.yml index 10db6fd2..bf7b7fe9 100644 --- a/.github/workflows/twofish.yml +++ b/.github/workflows/twofish.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/.github/workflows/xtea.yml b/.github/workflows/xtea.yml index 82faca3c..9ce9ba75 100644 --- a/.github/workflows/xtea.yml +++ b/.github/workflows/xtea.yml @@ -38,6 +38,7 @@ jobs: - run: cargo build --no-default-features --release --target ${{ matrix.target }} minimal-versions: + if: false # TODO: temp disabled due to unpublished prerelease dependencies uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/Cargo.lock b/Cargo.lock index 25e0977c..afedf1b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "aes" -version = "0.9.0-pre.1" +version = "0.9.0-pre.2" dependencies = [ "cfg-if", "cipher", @@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "belt-block" -version = "0.2.0-pre.1" +version = "0.2.0-pre.2" dependencies = [ "cipher", "hex-literal", @@ -37,7 +37,7 @@ checksum = "847495c209977a90e8aad588b959d0ca9f5dc228096d29a6bd3defd53f35eaec" [[package]] name = "blowfish" -version = "0.10.0-pre.1" +version = "0.10.0-pre.2" dependencies = [ "byteorder", "cipher", @@ -81,9 +81,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cipher" -version = "0.5.0-pre.6" +version = "0.5.0-pre.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71c893d5a1e8257048dbb29954d2e1f85f091a150304f1defe4ca2806da5d3f" +checksum = "5b1425e6ce000f05a73096556cabcfb6a10a3ffe3bb4d75416ca8f00819c0b6a" dependencies = [ "blobby", "crypto-common", @@ -93,25 +93,25 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] [[package]] name = "crypto-common" -version = "0.2.0-rc.0" +version = "0.2.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c070b79a496dccd931229780ad5bbedd535ceff6c3565605a8e440e18e1aa2b" +checksum = "b0b8ce8218c97789f16356e7896b3714f26c2ee1079b79c0b7ae7064bb9089fa" dependencies = [ "hybrid-array", ] [[package]] name = "des" -version = "0.9.0-pre.1" +version = "0.9.0-pre.2" dependencies = [ "cipher", ] @@ -121,6 +121,7 @@ name = "gift-cipher" version = "0.0.1-pre.0" dependencies = [ "cipher", + "hex-literal", ] [[package]] @@ -156,7 +157,7 @@ dependencies = [ [[package]] name = "kuznyechik" -version = "0.9.0-pre.1" +version = "0.9.0-pre.2" dependencies = [ "cfg-if", "cipher", @@ -171,7 +172,7 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "magma" -version = "0.10.0-pre.1" +version = "0.10.0-pre.2" dependencies = [ "cipher", "hex-literal", @@ -189,13 +190,13 @@ name = "rc5" version = "0.1.0-pre" dependencies = [ "cipher", + "hex-literal", ] [[package]] name = "serpent" version = "0.6.0-pre" dependencies = [ - "byteorder", "cipher", ] diff --git a/aes/Cargo.toml b/aes/Cargo.toml index 28b64a41..cbe2c1ce 100644 --- a/aes/Cargo.toml +++ b/aes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aes" -version = "0.9.0-pre.1" +version = "0.9.0-pre.2" description = "Pure Rust implementation of the Advanced Encryption Standard (a.k.a. Rijndael)" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -14,7 +14,7 @@ categories = ["cryptography", "no-std"] [dependencies] cfg-if = "1" -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" zeroize = { version = "1.5.6", optional = true, default-features = false, features = [ "aarch64", ] } @@ -23,7 +23,7 @@ zeroize = { version = "1.5.6", optional = true, default-features = false, featur cpufeatures = "0.2" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" [features] diff --git a/aes/LICENSE-MIT b/aes/LICENSE-MIT index f5b157a6..a85fb15a 100644 --- a/aes/LICENSE-MIT +++ b/aes/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2018-2024 The RustCrypto Project Developers Copyright (c) 2018 Artyom Pavlov Permission is hereby granted, free of charge, to any diff --git a/aes/src/armv8.rs b/aes/src/armv8.rs index 07634feb..f0de41fa 100644 --- a/aes/src/armv8.rs +++ b/aes/src/armv8.rs @@ -19,8 +19,8 @@ mod test_expand; use cipher::{ consts::{self, U16, U24, U32}, - AlgorithmName, BlockCipher, BlockCipherDecrypt, BlockCipherEncrypt, BlockClosure, - BlockSizeUser, Key, KeyInit, KeySizeUser, + AlgorithmName, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure, + BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, KeySizeUser, }; use core::fmt; @@ -97,8 +97,6 @@ macro_rules! define_aes_impl { } } - impl BlockCipher for $name {} - impl KeySizeUser for $name { type KeySize = $key_size; } @@ -107,7 +105,7 @@ macro_rules! define_aes_impl { #[inline] fn new(key: &Key) -> Self { let encrypt = $name_back_enc::new(key); - let decrypt = $name_back_dec::from(&encrypt); + let decrypt = $name_back_dec::from(encrypt.clone()); Self { encrypt, decrypt } } } @@ -116,7 +114,7 @@ macro_rules! define_aes_impl { #[inline] fn from(encrypt: $name_enc) -> $name { let encrypt = encrypt.backend.clone(); - let decrypt = (&encrypt).into(); + let decrypt = encrypt.clone().into(); Self { encrypt, decrypt } } } @@ -125,7 +123,7 @@ macro_rules! define_aes_impl { #[inline] fn from(encrypt: &$name_enc) -> $name { let encrypt = encrypt.backend.clone(); - let decrypt = (&encrypt).into(); + let decrypt = encrypt.clone().into(); Self { encrypt, decrypt } } } @@ -135,14 +133,14 @@ macro_rules! define_aes_impl { } impl BlockCipherEncrypt for $name { - fn encrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut &self.encrypt) + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(&self.encrypt) } } impl BlockCipherDecrypt for $name { - fn decrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut &self.decrypt) + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(&self.decrypt) } } @@ -185,8 +183,6 @@ macro_rules! define_aes_impl { } } - impl BlockCipher for $name_enc {} - impl KeySizeUser for $name_enc { type KeySize = $key_size; } @@ -204,8 +200,8 @@ macro_rules! define_aes_impl { } impl BlockCipherEncrypt for $name_enc { - fn encrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut &self.backend) + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(&self.backend) } } @@ -248,8 +244,6 @@ macro_rules! define_aes_impl { } } - impl BlockCipher for $name_dec {} - impl KeySizeUser for $name_dec { type KeySize = $key_size; } @@ -258,7 +252,7 @@ macro_rules! define_aes_impl { #[inline] fn new(key: &Key) -> Self { let encrypt = $name_back_enc::new(key); - let backend = (&encrypt).into(); + let backend = encrypt.clone().into(); Self { backend } } } @@ -272,7 +266,7 @@ macro_rules! define_aes_impl { impl From<&$name_enc> for $name_dec { fn from(encrypt: &$name_enc) -> $name_dec { - let backend = (&encrypt.backend).into(); + let backend = encrypt.backend.clone().into(); Self { backend } } } @@ -282,8 +276,8 @@ macro_rules! define_aes_impl { } impl BlockCipherDecrypt for $name_dec { - fn decrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut &self.backend); + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(&self.backend); } } diff --git a/aes/src/autodetect.rs b/aes/src/autodetect.rs index 5605c9d4..8c0e6898 100644 --- a/aes/src/autodetect.rs +++ b/aes/src/autodetect.rs @@ -4,8 +4,8 @@ use crate::soft; use cipher::{ consts::{U16, U24, U32}, - AlgorithmName, BlockCipher, BlockCipherDecrypt, BlockCipherEncrypt, BlockClosure, - BlockSizeUser, Key, KeyInit, KeySizeUser, + AlgorithmName, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure, + BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, KeySizeUser, }; use core::fmt; use core::mem::ManuallyDrop; @@ -128,41 +128,39 @@ macro_rules! define_aes_impl { type BlockSize = U16; } - impl BlockCipher for $name {} - impl BlockCipherEncrypt for $name { - fn encrypt_with_backend(&self, f: impl BlockClosure) { + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { unsafe { if self.token.get() { #[target_feature(enable = "aes")] unsafe fn inner( state: &intrinsics::$name, - f: impl BlockClosure, + f: impl BlockCipherEncClosure, ) { - f.call(&mut state.get_enc_backend()); + f.call(state.get_enc_backend()); } inner(&self.inner.intrinsics, f); } else { - f.call(&mut self.inner.soft.get_enc_backend()); + f.call(&self.inner.soft.get_enc_backend()); } } } } impl BlockCipherDecrypt for $name { - fn decrypt_with_backend(&self, f: impl BlockClosure) { + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { unsafe { if self.token.get() { #[target_feature(enable = "aes")] unsafe fn inner( state: &intrinsics::$name, - f: impl BlockClosure, + f: impl BlockCipherDecClosure, ) { - f.call(&mut state.get_dec_backend()); + f.call(state.get_dec_backend()); } inner(&self.inner.intrinsics, f); } else { - f.call(&mut self.inner.soft.get_dec_backend()); + f.call(&self.inner.soft.get_dec_backend()); } } } @@ -247,22 +245,20 @@ macro_rules! define_aes_impl { type BlockSize = U16; } - impl BlockCipher for $name_enc {} - impl BlockCipherEncrypt for $name_enc { - fn encrypt_with_backend(&self, f: impl BlockClosure) { + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { unsafe { if self.token.get() { #[target_feature(enable = "aes")] unsafe fn inner( state: &intrinsics::$name_enc, - f: impl BlockClosure, + f: impl BlockCipherEncClosure, ) { - f.call(&mut state.get_enc_backend()); + f.call(state.get_enc_backend()); } inner(&self.inner.intrinsics, f); } else { - f.call(&mut self.inner.soft.get_enc_backend()); + f.call(&self.inner.soft.get_enc_backend()); } } } @@ -376,22 +372,20 @@ macro_rules! define_aes_impl { type BlockSize = U16; } - impl BlockCipher for $name_dec {} - impl BlockCipherDecrypt for $name_dec { - fn decrypt_with_backend(&self, f: impl BlockClosure) { + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { unsafe { if self.token.get() { #[target_feature(enable = "aes")] unsafe fn inner( state: &intrinsics::$name_dec, - f: impl BlockClosure, + f: impl BlockCipherDecClosure, ) { - f.call(&mut state.get_dec_backend()); + f.call(state.get_dec_backend()); } inner(&self.inner.intrinsics, f); } else { - f.call(&mut self.inner.soft.get_dec_backend()); + f.call(&self.inner.soft.get_dec_backend()); } } } diff --git a/aes/src/lib.rs b/aes/src/lib.rs index 8be29189..d8a2976b 100644 --- a/aes/src/lib.rs +++ b/aes/src/lib.rs @@ -51,10 +51,7 @@ //! # Examples //! ``` //! use aes::Aes128; -//! use aes::cipher::{ -//! BlockCipher, BlockCipherEncrypt, BlockCipherDecrypt, KeyInit, -//! array::Array, -//! }; +//! use aes::cipher::{Array, BlockCipherEncrypt, BlockCipherDecrypt, KeyInit}; //! //! let key = Array::from([0u8; 16]); //! let mut block = Array::from([42u8; 16]); @@ -116,11 +113,10 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] #[cfg(feature = "hazmat")] -#[cfg_attr(docsrs, doc(cfg(feature = "hazmat")))] pub mod hazmat; #[macro_use] diff --git a/aes/src/macros.rs b/aes/src/macros.rs index c0f12ba7..e688c00d 100644 --- a/aes/src/macros.rs +++ b/aes/src/macros.rs @@ -20,11 +20,11 @@ macro_rules! impl_backends { keys: $keys_ty, } - impl cipher::BlockSizeUser for &$enc_name { + impl cipher::BlockSizeUser for $enc_name { type BlockSize = cipher::consts::U16; } - impl cipher::ParBlocksSizeUser for &$enc_name { + impl cipher::ParBlocksSizeUser for $enc_name { type ParBlocksSize = $par_size; } @@ -40,15 +40,15 @@ macro_rules! impl_backends { } } - impl cipher::BlockBackend for &$enc_name { + impl cipher::BlockCipherEncBackend for $enc_name { #[inline(always)] - fn proc_block(&mut self, block: cipher::inout::InOut<'_, '_, cipher::Block>) { + fn encrypt_block(&self, block: cipher::inout::InOut<'_, '_, cipher::Block>) { unsafe { $encrypt(&self.keys, block) } } #[inline(always)] - fn proc_par_blocks( - &mut self, + fn encrypt_par_blocks( + &self, blocks: cipher::inout::InOut<'_, '_, cipher::ParBlocks>, ) { unsafe { $encrypt_par(&self.keys, blocks) } @@ -60,11 +60,11 @@ macro_rules! impl_backends { keys: $keys_ty, } - impl cipher::BlockSizeUser for &$dec_name { + impl cipher::BlockSizeUser for $dec_name { type BlockSize = cipher::consts::U16; } - impl cipher::ParBlocksSizeUser for &$dec_name { + impl cipher::ParBlocksSizeUser for $dec_name { type ParBlocksSize = $par_size; } @@ -75,27 +75,27 @@ macro_rules! impl_backends { impl cipher::KeyInit for $dec_name { #[inline] fn new(key: &cipher::Key) -> Self { - From::from(&$enc_name::new(key)) + From::from($enc_name::new(key)) } } - impl From<&$enc_name> for $dec_name { + impl From<$enc_name> for $dec_name { #[inline] - fn from(enc: &$enc_name) -> $dec_name { + fn from(enc: $enc_name) -> $dec_name { let keys = unsafe { $inv_keys(&enc.keys) }; Self { keys } } } - impl cipher::BlockBackend for &$dec_name { + impl cipher::BlockCipherDecBackend for $dec_name { #[inline(always)] - fn proc_block(&mut self, block: cipher::inout::InOut<'_, '_, cipher::Block>) { + fn decrypt_block(&self, block: cipher::inout::InOut<'_, '_, cipher::Block>) { unsafe { $decrypt(&self.keys, block) } } #[inline(always)] - fn proc_par_blocks( - &mut self, + fn decrypt_par_blocks( + &self, blocks: cipher::inout::InOut<'_, '_, cipher::ParBlocks>, ) { unsafe { $decrypt_par(&self.keys, blocks) } diff --git a/aes/src/ni.rs b/aes/src/ni.rs index 2563df6f..a39a7c0c 100644 --- a/aes/src/ni.rs +++ b/aes/src/ni.rs @@ -30,8 +30,8 @@ use core::arch::x86_64 as arch; use cipher::{ consts::{self, U16, U24, U32}, - AlgorithmName, BlockCipher, BlockCipherDecrypt, BlockCipherEncrypt, BlockClosure, - BlockSizeUser, Key, KeyInit, KeySizeUser, + AlgorithmName, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure, + BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, KeySizeUser, }; use core::fmt; @@ -107,8 +107,6 @@ macro_rules! define_aes_impl { } } - impl BlockCipher for $name {} - impl KeySizeUser for $name { type KeySize = $key_size; } @@ -144,13 +142,13 @@ macro_rules! define_aes_impl { } impl BlockCipherEncrypt for $name { - fn encrypt_with_backend(&self, f: impl BlockClosure) { + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { self.encrypt.encrypt_with_backend(f) } } impl BlockCipherDecrypt for $name { - fn decrypt_with_backend(&self, f: impl BlockClosure) { + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { self.decrypt.decrypt_with_backend(f) } } @@ -184,8 +182,6 @@ macro_rules! define_aes_impl { } } - impl BlockCipher for $name_enc {} - impl KeySizeUser for $name_enc { type KeySize = $key_size; } @@ -204,8 +200,8 @@ macro_rules! define_aes_impl { } impl BlockCipherEncrypt for $name_enc { - fn encrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut &self.backend) + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(&self.backend) } } @@ -248,8 +244,6 @@ macro_rules! define_aes_impl { } } - impl BlockCipher for $name_dec {} - impl KeySizeUser for $name_dec { type KeySize = $key_size; } @@ -272,7 +266,7 @@ macro_rules! define_aes_impl { #[inline] fn from(enc: &$name_enc) -> $name_dec { Self { - backend: (&enc.backend).into(), + backend: enc.backend.clone().into(), } } } @@ -282,8 +276,8 @@ macro_rules! define_aes_impl { } impl BlockCipherDecrypt for $name_dec { - fn decrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut self.get_dec_backend()); + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self.get_dec_backend()); } } diff --git a/aes/src/soft.rs b/aes/src/soft.rs index 50daf7df..9e5f9bef 100644 --- a/aes/src/soft.rs +++ b/aes/src/soft.rs @@ -16,8 +16,9 @@ use crate::Block; use cipher::{ consts::{U16, U24, U32}, inout::InOut, - AlgorithmName, BlockBackend, BlockCipher, BlockCipherDecrypt, BlockCipherEncrypt, BlockClosure, - BlockSizeUser, Key, KeyInit, KeySizeUser, ParBlocksSizeUser, + AlgorithmName, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, + KeySizeUser, ParBlocksSizeUser, }; use core::fmt; use fixslice::{BatchBlocks, FixsliceBlocks, FixsliceKeys128, FixsliceKeys192, FixsliceKeys256}; @@ -72,17 +73,15 @@ macro_rules! define_aes_impl { type BlockSize = U16; } - impl BlockCipher for $name {} - impl BlockCipherEncrypt for $name { - fn encrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut self.get_enc_backend()) + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(&self.get_enc_backend()) } } impl BlockCipherDecrypt for $name { - fn decrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut self.get_dec_backend()) + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(&self.get_dec_backend()) } } @@ -137,8 +136,6 @@ macro_rules! define_aes_impl { } } - impl BlockCipher for $name_enc {} - impl KeySizeUser for $name_enc { type KeySize = $key_size; } @@ -156,8 +153,8 @@ macro_rules! define_aes_impl { } impl BlockCipherEncrypt for $name_enc { - fn encrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut self.get_enc_backend()) + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(&self.get_enc_backend()) } } @@ -190,8 +187,6 @@ macro_rules! define_aes_impl { } } - impl BlockCipher for $name_dec {} - impl KeySizeUser for $name_dec { type KeySize = $key_size; } @@ -225,8 +220,8 @@ macro_rules! define_aes_impl { } impl BlockCipherDecrypt for $name_dec { - fn decrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut self.get_dec_backend()); + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(&self.get_dec_backend()); } } @@ -255,9 +250,9 @@ macro_rules! define_aes_impl { type ParBlocksSize = FixsliceBlocks; } - impl<'a> BlockBackend for $name_back_enc<'a> { + impl<'a> BlockCipherEncBackend for $name_back_enc<'a> { #[inline(always)] - fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) { + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { let mut blocks = BatchBlocks::default(); blocks[0] = block.clone_in().into(); let res = $fixslice_encrypt(&self.0.keys, &blocks); @@ -265,7 +260,7 @@ macro_rules! define_aes_impl { } #[inline(always)] - fn proc_par_blocks(&mut self, mut blocks: InOut<'_, '_, BatchBlocks>) { + fn encrypt_par_blocks(&self, mut blocks: InOut<'_, '_, BatchBlocks>) { let res = $fixslice_encrypt(&self.0.keys, blocks.get_in()); *blocks.get_out() = res; } @@ -281,9 +276,9 @@ macro_rules! define_aes_impl { type ParBlocksSize = FixsliceBlocks; } - impl<'a> BlockBackend for $name_back_dec<'a> { + impl<'a> BlockCipherDecBackend for $name_back_dec<'a> { #[inline(always)] - fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) { + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { let mut blocks = BatchBlocks::default(); blocks[0] = block.clone_in(); let res = $fixslice_decrypt(&self.0.keys, &blocks); @@ -291,7 +286,7 @@ macro_rules! define_aes_impl { } #[inline(always)] - fn proc_par_blocks(&mut self, mut blocks: InOut<'_, '_, BatchBlocks>) { + fn decrypt_par_blocks(&self, mut blocks: InOut<'_, '_, BatchBlocks>) { let res = $fixslice_decrypt(&self.0.keys, blocks.get_in()); *blocks.get_out() = res; } diff --git a/aria/Cargo.toml b/aria/Cargo.toml index 2485e7a3..60cc9c7b 100644 --- a/aria/Cargo.toml +++ b/aria/Cargo.toml @@ -13,10 +13,10 @@ keywords = ["crypto", "aria", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" [features] diff --git a/aria/LICENSE-MIT b/aria/LICENSE-MIT index e4cbf938..6ebea87d 100644 --- a/aria/LICENSE-MIT +++ b/aria/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2022 The RustCrypto Project Developers +Copyright (c) 2022-2024 The RustCrypto Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/aria/src/aria128.rs b/aria/src/aria128.rs new file mode 100644 index 00000000..a56f61c5 --- /dev/null +++ b/aria/src/aria128.rs @@ -0,0 +1,69 @@ +use crate::{ + consts::{C1, C2, C3}, + utils::{a, fe, fo}, + Aria128, +}; +use cipher::{consts::U16, AlgorithmName, Key, KeyInit, KeySizeUser}; +use core::fmt; + +impl KeySizeUser for Aria128 { + type KeySize = U16; +} + +impl KeyInit for Aria128 { + fn new(key: &Key) -> Self { + let kl = u128::from_be_bytes(key[0..16].try_into().unwrap()); + let kr = u128::default(); + + let w0 = kl; + let w1 = fo(w0 ^ C1) ^ kr; + let w2 = fe(w1 ^ C2) ^ w0; + let w3 = fo(w2 ^ C3) ^ w1; + + let ek = [ + w0 ^ w1.rotate_right(19), + w1 ^ w2.rotate_right(19), + w2 ^ w3.rotate_right(19), + w3 ^ w0.rotate_right(19), + w0 ^ w1.rotate_right(31), + w1 ^ w2.rotate_right(31), + w2 ^ w3.rotate_right(31), + w3 ^ w0.rotate_right(31), + w0 ^ w1.rotate_left(61), + w1 ^ w2.rotate_left(61), + w2 ^ w3.rotate_left(61), + w3 ^ w0.rotate_left(61), + w0 ^ w1.rotate_left(31), + ]; + + let dk = [ + ek[12], + a(ek[11]), + a(ek[10]), + a(ek[9]), + a(ek[8]), + a(ek[7]), + a(ek[6]), + a(ek[5]), + a(ek[4]), + a(ek[3]), + a(ek[2]), + a(ek[1]), + ek[0], + ]; + + Self { ek, dk } + } +} + +impl fmt::Debug for Aria128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Aria128 { ... }") + } +} + +impl AlgorithmName for Aria128 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Aria128") + } +} diff --git a/aria/src/aria192.rs b/aria/src/aria192.rs new file mode 100644 index 00000000..9e9218d4 --- /dev/null +++ b/aria/src/aria192.rs @@ -0,0 +1,74 @@ +use crate::{ + consts::{C1, C2, C3}, + utils::{a, fe, fo}, + Aria192, +}; +use cipher::{consts::U24, AlgorithmName, Key, KeyInit, KeySizeUser}; +use core::fmt; + +impl KeySizeUser for Aria192 { + type KeySize = U24; +} + +impl KeyInit for Aria192 { + fn new(key: &Key) -> Self { + let kl = u128::from_be_bytes(key[0..16].try_into().unwrap()); + let kr = u64::from_be_bytes(key[16..24].try_into().unwrap()); + let kr = (kr as u128) << 64; + + let w0 = kl; + let w1 = fo(w0 ^ C2) ^ kr; + let w2 = fe(w1 ^ C3) ^ w0; + let w3 = fo(w2 ^ C1) ^ w1; + + let ek = [ + w0 ^ w1.rotate_right(19), + w1 ^ w2.rotate_right(19), + w2 ^ w3.rotate_right(19), + w3 ^ w0.rotate_right(19), + w0 ^ w1.rotate_right(31), + w1 ^ w2.rotate_right(31), + w2 ^ w3.rotate_right(31), + w3 ^ w0.rotate_right(31), + w0 ^ w1.rotate_left(61), + w1 ^ w2.rotate_left(61), + w2 ^ w3.rotate_left(61), + w3 ^ w0.rotate_left(61), + w0 ^ w1.rotate_left(31), + w1 ^ w2.rotate_left(31), + w2 ^ w3.rotate_left(31), + ]; + + let dk = [ + ek[14], + a(ek[13]), + a(ek[12]), + a(ek[11]), + a(ek[10]), + a(ek[9]), + a(ek[8]), + a(ek[7]), + a(ek[6]), + a(ek[5]), + a(ek[4]), + a(ek[3]), + a(ek[2]), + a(ek[1]), + ek[0], + ]; + + Self { ek, dk } + } +} + +impl fmt::Debug for Aria192 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Aria192 { ... }") + } +} + +impl AlgorithmName for Aria192 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Aria192") + } +} diff --git a/aria/src/aria256.rs b/aria/src/aria256.rs new file mode 100644 index 00000000..728792e7 --- /dev/null +++ b/aria/src/aria256.rs @@ -0,0 +1,77 @@ +use crate::{ + consts::{C1, C2, C3}, + utils::{a, fe, fo}, + Aria256, +}; +use cipher::{consts::U32, AlgorithmName, Key, KeyInit, KeySizeUser}; +use core::fmt; + +impl KeySizeUser for Aria256 { + type KeySize = U32; +} + +impl KeyInit for Aria256 { + fn new(key: &Key) -> Self { + let kl = u128::from_be_bytes(key[0..16].try_into().unwrap()); + let kr = u128::from_be_bytes(key[16..32].try_into().unwrap()); + + let w0 = kl; + let w1 = fo(w0 ^ C3) ^ kr; + let w2 = fe(w1 ^ C1) ^ w0; + let w3 = fo(w2 ^ C2) ^ w1; + + let ek = [ + w0 ^ w1.rotate_right(19), + w1 ^ w2.rotate_right(19), + w2 ^ w3.rotate_right(19), + w3 ^ w0.rotate_right(19), + w0 ^ w1.rotate_right(31), + w1 ^ w2.rotate_right(31), + w2 ^ w3.rotate_right(31), + w3 ^ w0.rotate_right(31), + w0 ^ w1.rotate_left(61), + w1 ^ w2.rotate_left(61), + w2 ^ w3.rotate_left(61), + w3 ^ w0.rotate_left(61), + w0 ^ w1.rotate_left(31), + w1 ^ w2.rotate_left(31), + w2 ^ w3.rotate_left(31), + w3 ^ w0.rotate_left(31), + w0 ^ w1.rotate_left(19), + ]; + + let dk = [ + ek[16], + a(ek[15]), + a(ek[14]), + a(ek[13]), + a(ek[12]), + a(ek[11]), + a(ek[10]), + a(ek[9]), + a(ek[8]), + a(ek[7]), + a(ek[6]), + a(ek[5]), + a(ek[4]), + a(ek[3]), + a(ek[2]), + a(ek[1]), + ek[0], + ]; + + Self { ek, dk } + } +} + +impl fmt::Debug for Aria256 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Aria256 { ... }") + } +} + +impl AlgorithmName for Aria256 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Aria256") + } +} diff --git a/aria/src/lib.rs b/aria/src/lib.rs index ff2ad66a..3444f9c8 100644 --- a/aria/src/lib.rs +++ b/aria/src/lib.rs @@ -10,8 +10,7 @@ //! //! # Examples //! ``` -//! use aria::cipher::array::Array; -//! use aria::cipher::{Key, Block, BlockCipherEncrypt, BlockCipherDecrypt, KeyInit}; +//! use aria::cipher::{Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; //! use aria::Aria128; //! //! let key = Array::from([0u8; 16]); @@ -36,7 +35,7 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] mod consts; @@ -44,324 +43,108 @@ mod consts; pub use cipher; use cipher::{ - consts::{U16, U24, U32}, - AlgorithmName, BlockCipher, Key, KeyInit, KeySizeUser, + consts::{U1, U16}, + inout::InOut, + Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncBackend, + BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, ParBlocksSizeUser, }; -use core::fmt; #[cfg(feature = "zeroize")] use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; -use crate::consts::{C1, C2, C3, DIFFUSE_CONSTS, SB1, SB2, SB3, SB4}; - -#[inline(always)] -fn diffuse(x: [u8; 16]) -> u128 { - DIFFUSE_CONSTS - .iter() - .zip(x) - .map(|(a, b)| a * b as u128) - .fold(0, |a, v| a ^ v) -} - -#[inline(always)] -fn a(x128: u128) -> u128 { - diffuse(x128.to_be_bytes()) -} - -fn sl2(x128: u128) -> u128 { - let x = x128.to_be_bytes(); - let y = [ - SB3[x[0] as usize], - SB4[x[1] as usize], - SB1[x[2] as usize], - SB2[x[3] as usize], - SB3[x[4] as usize], - SB4[x[5] as usize], - SB1[x[6] as usize], - SB2[x[7] as usize], - SB3[x[8] as usize], - SB4[x[9] as usize], - SB1[x[10] as usize], - SB2[x[11] as usize], - SB3[x[12] as usize], - SB4[x[13] as usize], - SB1[x[14] as usize], - SB2[x[15] as usize], - ]; - u128::from_be_bytes(y) +mod aria128; +mod aria192; +mod aria256; +mod utils; + +use utils::{fe, fo, sl2}; + +/// Generic implementation of the ARIA block cipher. +/// +/// It can be initialized only with `RK` being equal to 13 (ARIA-128), +/// 15 (ARIA-192), or 17 (ARIA-256). +#[derive(Clone)] +pub struct Aria { + /// Encrypting subkeys. + ek: [u128; RK], + /// Encrypting subkeys. + dk: [u128; RK], } -fn fo(x128: u128) -> u128 { - let x = x128.to_be_bytes(); - diffuse([ - SB1[x[0] as usize], - SB2[x[1] as usize], - SB3[x[2] as usize], - SB4[x[3] as usize], - SB1[x[4] as usize], - SB2[x[5] as usize], - SB3[x[6] as usize], - SB4[x[7] as usize], - SB1[x[8] as usize], - SB2[x[9] as usize], - SB3[x[10] as usize], - SB4[x[11] as usize], - SB1[x[12] as usize], - SB2[x[13] as usize], - SB3[x[14] as usize], - SB4[x[15] as usize], - ]) +impl BlockSizeUser for Aria { + type BlockSize = U16; } -fn fe(x128: u128) -> u128 { - let x = x128.to_be_bytes(); - diffuse([ - SB3[x[0] as usize], - SB4[x[1] as usize], - SB1[x[2] as usize], - SB2[x[3] as usize], - SB3[x[4] as usize], - SB4[x[5] as usize], - SB1[x[6] as usize], - SB2[x[7] as usize], - SB3[x[8] as usize], - SB4[x[9] as usize], - SB1[x[10] as usize], - SB2[x[11] as usize], - SB3[x[12] as usize], - SB4[x[13] as usize], - SB1[x[14] as usize], - SB2[x[15] as usize], - ]) +impl ParBlocksSizeUser for Aria { + type ParBlocksSize = U1; } -impl KeyInit for Aria128 { - fn new(key: &Key) -> Self { - let kl = u128::from_be_bytes(key[0..16].try_into().unwrap()); - let kr = u128::default(); - - let w0 = kl; - let w1 = fo(w0 ^ C1) ^ kr; - let w2 = fe(w1 ^ C2) ^ w0; - let w3 = fo(w2 ^ C3) ^ w1; - - let ek = [ - w0 ^ w1.rotate_right(19), - w1 ^ w2.rotate_right(19), - w2 ^ w3.rotate_right(19), - w3 ^ w0.rotate_right(19), - w0 ^ w1.rotate_right(31), - w1 ^ w2.rotate_right(31), - w2 ^ w3.rotate_right(31), - w3 ^ w0.rotate_right(31), - w0 ^ w1.rotate_left(61), - w1 ^ w2.rotate_left(61), - w2 ^ w3.rotate_left(61), - w3 ^ w0.rotate_left(61), - w0 ^ w1.rotate_left(31), - ]; - - let dk = [ - ek[12], - a(ek[11]), - a(ek[10]), - a(ek[9]), - a(ek[8]), - a(ek[7]), - a(ek[6]), - a(ek[5]), - a(ek[4]), - a(ek[3]), - a(ek[2]), - a(ek[1]), - ek[0], - ]; - - Self { ek, dk } +impl BlockCipherEncrypt for Aria { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) } } -impl KeyInit for Aria192 { - fn new(key: &Key) -> Self { - let kl = u128::from_be_bytes(key[0..16].try_into().unwrap()); - let kr = u64::from_be_bytes(key[16..24].try_into().unwrap()); - let kr = (kr as u128) << 64; - - let w0 = kl; - let w1 = fo(w0 ^ C2) ^ kr; - let w2 = fe(w1 ^ C3) ^ w0; - let w3 = fo(w2 ^ C1) ^ w1; +impl BlockCipherEncBackend for Aria { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut p0 = u128::from_be_bytes((*block.get_in()).into()); + let mut p1; - let ek = [ - w0 ^ w1.rotate_right(19), - w1 ^ w2.rotate_right(19), - w2 ^ w3.rotate_right(19), - w3 ^ w0.rotate_right(19), - w0 ^ w1.rotate_right(31), - w1 ^ w2.rotate_right(31), - w2 ^ w3.rotate_right(31), - w3 ^ w0.rotate_right(31), - w0 ^ w1.rotate_left(61), - w1 ^ w2.rotate_left(61), - w2 ^ w3.rotate_left(61), - w3 ^ w0.rotate_left(61), - w0 ^ w1.rotate_left(31), - w1 ^ w2.rotate_left(31), - w2 ^ w3.rotate_left(31), - ]; + for i in (0..RK - 3).step_by(2) { + p1 = fo(p0 ^ self.ek[i]); + p0 = fe(p1 ^ self.ek[i + 1]); + } - let dk = [ - ek[14], - a(ek[13]), - a(ek[12]), - a(ek[11]), - a(ek[10]), - a(ek[9]), - a(ek[8]), - a(ek[7]), - a(ek[6]), - a(ek[5]), - a(ek[4]), - a(ek[3]), - a(ek[2]), - a(ek[1]), - ek[0], - ]; + let p1 = fo(p0 ^ self.ek[RK - 3]); + let c = sl2(p1 ^ self.ek[RK - 2]) ^ self.ek[RK - 1]; - Self { ek, dk } + block.get_out().copy_from_slice(&c.to_be_bytes()); } } -impl KeyInit for Aria256 { - fn new(key: &Key) -> Self { - let kl = u128::from_be_bytes(key[0..16].try_into().unwrap()); - let kr = u128::from_be_bytes(key[16..32].try_into().unwrap()); - - let w0 = kl; - let w1 = fo(w0 ^ C3) ^ kr; - let w2 = fe(w1 ^ C1) ^ w0; - let w3 = fo(w2 ^ C2) ^ w1; - - let ek = [ - w0 ^ w1.rotate_right(19), - w1 ^ w2.rotate_right(19), - w2 ^ w3.rotate_right(19), - w3 ^ w0.rotate_right(19), - w0 ^ w1.rotate_right(31), - w1 ^ w2.rotate_right(31), - w2 ^ w3.rotate_right(31), - w3 ^ w0.rotate_right(31), - w0 ^ w1.rotate_left(61), - w1 ^ w2.rotate_left(61), - w2 ^ w3.rotate_left(61), - w3 ^ w0.rotate_left(61), - w0 ^ w1.rotate_left(31), - w1 ^ w2.rotate_left(31), - w2 ^ w3.rotate_left(31), - w3 ^ w0.rotate_left(31), - w0 ^ w1.rotate_left(19), - ]; - - let dk = [ - ek[16], - a(ek[15]), - a(ek[14]), - a(ek[13]), - a(ek[12]), - a(ek[11]), - a(ek[10]), - a(ek[9]), - a(ek[8]), - a(ek[7]), - a(ek[6]), - a(ek[5]), - a(ek[4]), - a(ek[3]), - a(ek[2]), - a(ek[1]), - ek[0], - ]; - - Self { ek, dk } +impl BlockCipherDecrypt for Aria { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) } } -macro_rules! impl_aria { - ($name:ident, $subkey_size:literal, $key_size:ty, $doc:literal) => { - #[doc = $doc] - #[derive(Clone)] - pub struct $name { - /// Encrypting subkeys. - ek: [u128; $subkey_size], - /// Encrypting subkeys. - dk: [u128; $subkey_size], - } - impl BlockCipher for $name {} +impl BlockCipherDecBackend for Aria { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut c0 = u128::from_be_bytes((*block.get_in()).into()); + let mut c1; - impl KeySizeUser for $name { - type KeySize = $key_size; + for i in (0..RK - 3).step_by(2) { + c1 = fo(c0 ^ self.dk[i]); + c0 = fe(c1 ^ self.dk[i + 1]); } - impl fmt::Debug for $name { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(concat!(stringify!($name), " { ... }")) - } - } + let c1 = fo(c0 ^ self.dk[RK - 3]); + let p = sl2(c1 ^ self.dk[RK - 2]) ^ self.dk[RK - 1]; - impl AlgorithmName for $name { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(stringify!($name)) - } - } + block.get_out().copy_from_slice(&p.to_be_bytes()); + } +} +impl Drop for Aria { + fn drop(&mut self) { #[cfg(feature = "zeroize")] - #[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] - impl Drop for $name { - fn drop(&mut self) { - self.ek.zeroize(); - self.dk.zeroize(); - } + { + self.ek.zeroize(); + self.dk.zeroize(); } - - #[cfg(feature = "zeroize")] - #[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] - impl ZeroizeOnDrop for $name {} - - cipher::impl_simple_block_encdec!( - $name, U16, cipher, block, - encrypt: { - let mut p0 = u128::from_be_bytes((*block.get_in()).into()); - let mut p1; - - for i in (0..$subkey_size - 3).step_by(2) { - p1 = fo(p0 ^ cipher.ek[i]); - p0 = fe(p1 ^ cipher.ek[i + 1]); - } - - let p1 = fo(p0 ^ cipher.ek[$subkey_size - 3]); - let c = sl2(p1 ^ cipher.ek[$subkey_size - 2]) ^ cipher.ek[$subkey_size - 1]; - - block.get_out().copy_from_slice(&c.to_be_bytes()); - } - decrypt: { - let mut c0 = u128::from_be_bytes((*block.get_in()).into()); - let mut c1; - - for i in (0..$subkey_size - 3).step_by(2) { - c1 = fo(c0 ^ cipher.dk[i]); - c0 = fe(c1 ^ cipher.dk[i + 1]); - } - - let c1 = fo(c0 ^ cipher.dk[$subkey_size - 3]); - let p = sl2(c1 ^ cipher.dk[$subkey_size - 2]) ^ cipher.dk[$subkey_size - 1]; - - block.get_out().copy_from_slice(&p.to_be_bytes()); - } - ); - - }; + } } -impl_aria!(Aria128, 13, U16, "Aria-128 block cipher instance."); -impl_aria!(Aria192, 15, U24, "Aria-192 block cipher instance."); -impl_aria!(Aria256, 17, U32, "Aria-256 block cipher instance."); +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Aria {} + +/// ARIA-128 block cipher instance. +pub type Aria128 = Aria<13>; +/// ARIA-192 block cipher instance. +pub type Aria192 = Aria<15>; +/// ARIA-256 block cipher instance. +pub type Aria256 = Aria<17>; diff --git a/aria/src/utils.rs b/aria/src/utils.rs new file mode 100644 index 00000000..960c1d99 --- /dev/null +++ b/aria/src/utils.rs @@ -0,0 +1,82 @@ +use crate::consts::{DIFFUSE_CONSTS, SB1, SB2, SB3, SB4}; + +#[inline(always)] +fn diffuse(x: [u8; 16]) -> u128 { + DIFFUSE_CONSTS + .iter() + .zip(x) + .map(|(a, b)| a * b as u128) + .fold(0, |a, v| a ^ v) +} + +#[inline(always)] +pub(crate) fn a(x128: u128) -> u128 { + diffuse(x128.to_be_bytes()) +} + +pub(crate) fn sl2(x128: u128) -> u128 { + let x = x128.to_be_bytes(); + let y = [ + SB3[x[0] as usize], + SB4[x[1] as usize], + SB1[x[2] as usize], + SB2[x[3] as usize], + SB3[x[4] as usize], + SB4[x[5] as usize], + SB1[x[6] as usize], + SB2[x[7] as usize], + SB3[x[8] as usize], + SB4[x[9] as usize], + SB1[x[10] as usize], + SB2[x[11] as usize], + SB3[x[12] as usize], + SB4[x[13] as usize], + SB1[x[14] as usize], + SB2[x[15] as usize], + ]; + u128::from_be_bytes(y) +} + +pub(crate) fn fo(x128: u128) -> u128 { + let x = x128.to_be_bytes(); + diffuse([ + SB1[x[0] as usize], + SB2[x[1] as usize], + SB3[x[2] as usize], + SB4[x[3] as usize], + SB1[x[4] as usize], + SB2[x[5] as usize], + SB3[x[6] as usize], + SB4[x[7] as usize], + SB1[x[8] as usize], + SB2[x[9] as usize], + SB3[x[10] as usize], + SB4[x[11] as usize], + SB1[x[12] as usize], + SB2[x[13] as usize], + SB3[x[14] as usize], + SB4[x[15] as usize], + ]) +} + +pub(crate) fn fe(x128: u128) -> u128 { + let x = x128.to_be_bytes(); + diffuse([ + SB3[x[0] as usize], + SB4[x[1] as usize], + SB1[x[2] as usize], + SB2[x[3] as usize], + SB3[x[4] as usize], + SB4[x[5] as usize], + SB1[x[6] as usize], + SB2[x[7] as usize], + SB3[x[8] as usize], + SB4[x[9] as usize], + SB1[x[10] as usize], + SB2[x[11] as usize], + SB3[x[12] as usize], + SB4[x[13] as usize], + SB1[x[14] as usize], + SB2[x[15] as usize], + ]) +} diff --git a/aria/tests/mod.rs b/aria/tests/mod.rs index f9dcdb8f..e7390215 100644 --- a/aria/tests/mod.rs +++ b/aria/tests/mod.rs @@ -1,5 +1,5 @@ use aria::{Aria128, Aria192, Aria256}; -use cipher::{array::Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; +use cipher::{Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; use hex_literal::hex; /// Test vector from RFC 5794, Appendix A.1 diff --git a/belt-block/Cargo.toml b/belt-block/Cargo.toml index 6b401bdf..a8366fb1 100644 --- a/belt-block/Cargo.toml +++ b/belt-block/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "belt-block" -version = "0.2.0-pre.1" +version = "0.2.0-pre.2" description = "belt-block block cipher implementation" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -12,10 +12,10 @@ repository = "https://github.com/RustCrypto/block-ciphers" keywords = ["crypto", "belt-block", "belt", "stb"] [dependencies] -cipher = { version = "=0.5.0-pre.6", optional = true } +cipher = { version = "=0.5.0-pre.7", optional = true } [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" [features] diff --git a/belt-block/src/cipher_impl.rs b/belt-block/src/cipher_impl.rs index 4a8e5c26..4afaf770 100644 --- a/belt-block/src/cipher_impl.rs +++ b/belt-block/src/cipher_impl.rs @@ -1,6 +1,10 @@ use crate::{belt_block_raw, from_u32, g13, g21, g5, key_idx, to_u32}; -use cipher::consts::{U16, U32}; -use cipher::{inout::InOut, AlgorithmName, Block, BlockCipher, Key, KeyInit, KeySizeUser}; +use cipher::{ + consts::{U1, U16, U32}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key, + KeyInit, KeySizeUser, ParBlocksSizeUser, +}; use core::{fmt, mem::swap, num::Wrapping}; #[cfg(feature = "zeroize")] @@ -8,15 +12,39 @@ use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; /// BelT block cipher. #[derive(Clone)] -#[cfg_attr(docsrs, doc(cfg(feature = "cipher")))] pub struct BeltBlock { key: [u32; 8], } -impl BeltBlock { - /// Encryption as described in section 6.1.3 +impl KeySizeUser for BeltBlock { + type KeySize = U32; +} + +impl KeyInit for BeltBlock { + fn new(key: &Key) -> Self { + Self { key: to_u32(key) } + } +} + +impl BlockSizeUser for BeltBlock { + type BlockSize = U16; +} + +impl ParBlocksSizeUser for BeltBlock { + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for BeltBlock { #[inline] - fn encrypt(&self, mut block: InOut<'_, '_, Block>) { + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherEncBackend for BeltBlock { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + // Encryption as described in section 6.1.3 // Steps 1 and 4 let x = to_u32(block.get_in()); let y = belt_block_raw(x, &self.key); @@ -25,10 +53,18 @@ impl BeltBlock { // 6) Y ← b ‖ d ‖ a ‖ c *block_out = from_u32(&y).into(); } +} + +impl BlockCipherDecrypt for BeltBlock { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} - /// Decryption as described in section 6.1.4 +impl BlockCipherDecBackend for BeltBlock { #[inline] - fn decrypt(&self, mut block: InOut<'_, '_, Block>) { + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { let key = &self.key; let block_in: [u32; 4] = to_u32(block.get_in()); // Steps 1 and 4 @@ -72,42 +108,18 @@ impl BeltBlock { } } -impl BlockCipher for BeltBlock {} - -impl KeySizeUser for BeltBlock { - type KeySize = U32; -} - -impl KeyInit for BeltBlock { - fn new(key: &Key) -> Self { - Self { key: to_u32(key) } - } -} - impl AlgorithmName for BeltBlock { fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("BeltBlock") } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl Drop for BeltBlock { fn drop(&mut self) { + #[cfg(feature = "zeroize")] self.key.zeroize(); } } #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl ZeroizeOnDrop for BeltBlock {} - -cipher::impl_simple_block_encdec!( - BeltBlock, U16, cipher, block, - encrypt: { - cipher.encrypt(block); - } - decrypt: { - cipher.decrypt(block); - } -); diff --git a/belt-block/src/lib.rs b/belt-block/src/lib.rs index 321bfc44..cc7ae331 100644 --- a/belt-block/src/lib.rs +++ b/belt-block/src/lib.rs @@ -17,7 +17,7 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] #![forbid(unsafe_code)] diff --git a/blowfish/Cargo.toml b/blowfish/Cargo.toml index 3eb9a598..2e158df9 100644 --- a/blowfish/Cargo.toml +++ b/blowfish/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blowfish" -version = "0.10.0-pre.1" +version = "0.10.0-pre.2" description = "Blowfish block cipher" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -13,11 +13,11 @@ keywords = ["crypto", "blowfish", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" byteorder = { version = "1.1", default-features = false } [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } [features] bcrypt = [] diff --git a/blowfish/LICENSE-MIT b/blowfish/LICENSE-MIT index 1da3a5f6..fe335449 100644 --- a/blowfish/LICENSE-MIT +++ b/blowfish/LICENSE-MIT @@ -1,5 +1,4 @@ -Copyright (c) 2006-2009 Graydon Hoare -Copyright (c) 2009-2013 Mozilla Foundation +Copyright (c) 2016-2024 The RustCrypto Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/blowfish/src/lib.rs b/blowfish/src/lib.rs index ad18fbe8..c3967642 100644 --- a/blowfish/src/lib.rs +++ b/blowfish/src/lib.rs @@ -16,15 +16,17 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] pub use cipher; use byteorder::{ByteOrder, BE, LE}; use cipher::{ - consts::{U56, U8}, - AlgorithmName, BlockCipher, InvalidLength, Key, KeyInit, KeySizeUser, + consts::{U1, U56, U8}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, + InvalidLength, Key, KeyInit, KeySizeUser, ParBlocksSizeUser, }; use core::fmt; use core::marker::PhantomData; @@ -120,8 +122,6 @@ impl Blowfish { } } -impl BlockCipher for Blowfish {} - impl KeySizeUser for Blowfish { type KeySize = U56; } @@ -141,6 +141,48 @@ impl KeyInit for Blowfish { } } +impl BlockSizeUser for Blowfish { + type BlockSize = U8; +} + +impl ParBlocksSizeUser for Blowfish { + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for Blowfish { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherEncBackend for Blowfish { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut b = [0u32; 2]; + T::read_u32_into(block.get_in(), &mut b); + b = self.encrypt(b); + T::write_u32_into(&b, block.get_out()); + } +} + +impl BlockCipherDecrypt for Blowfish { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Blowfish { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut b = [0u32; 2]; + T::read_u32_into(block.get_in(), &mut b); + b = self.decrypt(b); + T::write_u32_into(&b, block.get_out()); + } +} + impl fmt::Debug for Blowfish { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("Blowfish { ... }") @@ -165,35 +207,19 @@ impl AlgorithmName for Blowfish { } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl Drop for Blowfish { fn drop(&mut self) { - self.s.zeroize(); - self.p.zeroize(); + #[cfg(feature = "zeroize")] + { + self.s.zeroize(); + self.p.zeroize(); + } } } #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl ZeroizeOnDrop for Blowfish {} -cipher::impl_simple_block_encdec!( - Blowfish, U8, cipher, block, - encrypt: { - let mut b = [0u32; 2]; - T::read_u32_into(block.get_in(), &mut b); - b = cipher.encrypt(b); - T::write_u32_into(&b, block.get_out()); - } - decrypt: { - let mut b = [0u32; 2]; - T::read_u32_into(block.get_in(), &mut b); - b = cipher.decrypt(b); - T::write_u32_into(&b, block.get_out()); - } -); - /// Bcrypt extension of blowfish #[cfg(feature = "bcrypt")] impl Blowfish { diff --git a/camellia/Cargo.toml b/camellia/Cargo.toml index 23acdedc..d56518f5 100644 --- a/camellia/Cargo.toml +++ b/camellia/Cargo.toml @@ -14,13 +14,14 @@ categories = ["cryptography", "no-std"] [dependencies] byteorder = { version = "1.1", default-features = false } -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } [features] zeroize = ["cipher/zeroize"] [package.metadata.docs.rs] +all-features = true rustdoc-args = ["--cfg", "docsrs"] diff --git a/camellia/LICENSE-MIT b/camellia/LICENSE-MIT index f8eccd8c..394b496c 100644 --- a/camellia/LICENSE-MIT +++ b/camellia/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2021-2024 The RustCrypto Project Developers Copyright (c) 2021 Shun Sakai Permission is hereby granted, free of charge, to any diff --git a/camellia/src/camellia.rs b/camellia/src/camellia.rs deleted file mode 100644 index 71bf9f56..00000000 --- a/camellia/src/camellia.rs +++ /dev/null @@ -1,352 +0,0 @@ -// -// Based on src/lib/block/camellia/camellia.cpp from https://github.com/randombit/botan -// Revision: 32bf9784bd6ee29cb3ffa173f0a734e9edce2dac -// - -/* - * Camellia - * (C) 2012,2020 Jack Lloyd - * - * Botan is released under the Simplified BSD License (see license.txt) - */ - -use core::fmt; - -use byteorder::{ByteOrder, BE}; -use cipher::{ - consts::{U16, U24, U32}, - AlgorithmName, BlockCipher, Key, KeyInit, KeySizeUser, -}; - -#[cfg(feature = "zeroize")] -use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; - -use crate::consts::{SBOXES, SIGMAS}; - -/// F-function of component of Camellia defined in RFC 3713. -fn f(input: u64, key: u64) -> u64 { - let x = (input ^ key).to_be_bytes(); - - let z1 = 0x0101_0100_0100_0001 * u64::from(SBOXES[0][usize::from(x[0])]); - let z2 = 0x0001_0101_0101_0000 * u64::from(SBOXES[1][usize::from(x[1])]); - let z3 = 0x0100_0101_0001_0100 * u64::from(SBOXES[2][usize::from(x[2])]); - let z4 = 0x0101_0001_0000_0101 * u64::from(SBOXES[3][usize::from(x[3])]); - let z5 = 0x0001_0101_0001_0101 * u64::from(SBOXES[1][usize::from(x[4])]); - let z6 = 0x0100_0101_0100_0101 * u64::from(SBOXES[2][usize::from(x[5])]); - let z7 = 0x0101_0001_0101_0001 * u64::from(SBOXES[3][usize::from(x[6])]); - let z8 = 0x0101_0100_0101_0100 * u64::from(SBOXES[0][usize::from(x[7])]); - - z1 ^ z2 ^ z3 ^ z4 ^ z5 ^ z6 ^ z7 ^ z8 -} - -/// FL-function of component of Camellia defined in RFC 3713. -fn fl(input: u64, key: u64) -> u64 { - let mut x1 = u32::try_from(input >> 32).unwrap(); - let mut x2 = u32::try_from(input & 0xffff_ffff).unwrap(); - - let k1 = u32::try_from(key >> 32).unwrap(); - let k2 = u32::try_from(key & 0xffff_ffff).unwrap(); - - x2 ^= (x1 & k1).rotate_left(1); - x1 ^= x2 | k2; - - (u64::from(x1) << 32) | u64::from(x2) -} - -/// FLINV-function of component of Camellia defined in RFC 3713. -fn flinv(input: u64, key: u64) -> u64 { - let mut y1 = u32::try_from(input >> 32).unwrap(); - let mut y2 = u32::try_from(input & 0xffff_ffff).unwrap(); - - let k1 = u32::try_from(key >> 32).unwrap(); - let k2 = u32::try_from(key & 0xffff_ffff).unwrap(); - - y1 ^= y2 | k2; - y2 ^= (y1 & k1).rotate_left(1); - - (u64::from(y1) << 32) | u64::from(y2) -} - -macro_rules! set_kl { - ($key:expr) => { - ( - u64::from_be_bytes($key[0..8].try_into().unwrap()), - u64::from_be_bytes($key[8..16].try_into().unwrap()), - ) - }; -} - -fn set_ka(kl: (u64, u64), kr: (u64, u64)) -> (u64, u64) { - let mut d1 = kl.0 ^ kr.0; - let mut d2 = kl.1 ^ kr.1; - d2 ^= f(d1, SIGMAS[0]); - d1 ^= f(d2, SIGMAS[1]); - d1 ^= kl.0; - d2 ^= kl.1; - d2 ^= f(d1, SIGMAS[2]); - d1 ^= f(d2, SIGMAS[3]); - - (d1, d2) -} - -fn set_kb(ka: (u64, u64), kr: (u64, u64)) -> (u64, u64) { - let mut d1 = ka.0 ^ kr.0; - let mut d2 = ka.1 ^ kr.1; - d2 ^= f(d1, SIGMAS[4]); - d1 ^= f(d2, SIGMAS[5]); - - (d1, d2) -} - -/// Performs rotate left and taking the higher-half of it. -fn rotate_left_high(val: (u64, u64), mut shift: u8) -> u64 { - if shift >= 64 { - shift -= 64; - } - - (val.0 << shift) | (val.1 >> (64 - shift)) -} - -/// Performs rotate left and taking the lower-half of it. -fn rotate_left_low(val: (u64, u64), mut shift: u8) -> u64 { - if shift >= 64 { - shift -= 64; - } - - (val.0 >> (64 - shift)) | (val.1 << shift) -} - -impl Camellia128 { - fn gen_subkeys(kl: (u64, u64), ka: (u64, u64)) -> Self { - let mut k = [u64::default(); 26]; - - k[0] = kl.0; - k[1] = kl.1; - - k[2] = ka.0; - k[3] = ka.1; - k[4] = rotate_left_high(kl, 15); - k[5] = rotate_left_low(kl, 15); - k[6] = rotate_left_high(ka, 15); - k[7] = rotate_left_low(ka, 15); - - k[8] = rotate_left_high(ka, 30); - k[9] = rotate_left_low(ka, 30); - - k[10] = rotate_left_high(kl, 45); - k[11] = rotate_left_low(kl, 45); - k[12] = rotate_left_high(ka, 45); - k[13] = rotate_left_low(kl, 60); - k[14] = rotate_left_high(ka, 60); - k[15] = rotate_left_low(ka, 60); - - k[16] = rotate_left_low(kl, 77); - k[17] = rotate_left_high(kl, 77); - - k[18] = rotate_left_low(kl, 94); - k[19] = rotate_left_high(kl, 94); - k[20] = rotate_left_low(ka, 94); - k[21] = rotate_left_high(ka, 94); - k[22] = rotate_left_low(kl, 111); - k[23] = rotate_left_high(kl, 111); - - k[24] = rotate_left_low(ka, 111); - k[25] = rotate_left_high(ka, 111); - - Self { k } - } -} - -macro_rules! impl_gen_subkeys { - ($name:ident) => { - impl $name { - fn gen_subkeys(kl: (u64, u64), kr: (u64, u64), ka: (u64, u64), kb: (u64, u64)) -> Self { - let mut k = [u64::default(); 34]; - - k[0] = kl.0; - k[1] = kl.1; - - k[2] = kb.0; - k[3] = kb.1; - k[4] = rotate_left_high(kr, 15); - k[5] = rotate_left_low(kr, 15); - k[6] = rotate_left_high(ka, 15); - k[7] = rotate_left_low(ka, 15); - - k[8] = rotate_left_high(kr, 30); - k[9] = rotate_left_low(kr, 30); - - k[10] = rotate_left_high(kb, 30); - k[11] = rotate_left_low(kb, 30); - k[12] = rotate_left_high(kl, 45); - k[13] = rotate_left_low(kl, 45); - k[14] = rotate_left_high(ka, 45); - k[15] = rotate_left_low(ka, 45); - - k[16] = rotate_left_high(kl, 60); - k[17] = rotate_left_low(kl, 60); - - k[18] = rotate_left_high(kr, 60); - k[19] = rotate_left_low(kr, 60); - k[20] = rotate_left_high(kb, 60); - k[21] = rotate_left_low(kb, 60); - k[22] = rotate_left_low(kl, 77); - k[23] = rotate_left_high(kl, 77); - - k[24] = rotate_left_low(ka, 77); - k[25] = rotate_left_high(ka, 77); - - k[26] = rotate_left_low(kr, 94); - k[27] = rotate_left_high(kr, 94); - k[28] = rotate_left_low(ka, 94); - k[29] = rotate_left_high(ka, 94); - k[30] = rotate_left_low(kl, 111); - k[31] = rotate_left_high(kl, 111); - - k[32] = rotate_left_low(kb, 111); - k[33] = rotate_left_high(kb, 111); - - Self { k } - } - } - }; -} - -impl_gen_subkeys!(Camellia192); -impl_gen_subkeys!(Camellia256); - -impl KeyInit for Camellia128 { - fn new(key: &Key) -> Self { - let kl = set_kl!(key); - let kr = (u64::default(), u64::default()); - - let ka = set_ka(kl, kr); - - Self::gen_subkeys(kl, ka) - } -} - -impl KeyInit for Camellia192 { - fn new(key: &Key) -> Self { - let kl = set_kl!(key); - let kr = u64::from_be_bytes(key[16..24].try_into().unwrap()); - let kr = (kr, !kr); - - let ka = set_ka(kl, kr); - let kb = set_kb(ka, kr); - - Self::gen_subkeys(kl, kr, ka, kb) - } -} - -impl KeyInit for Camellia256 { - fn new(key: &Key) -> Self { - let kl = set_kl!(key); - let kr = ( - u64::from_be_bytes(key[16..24].try_into().unwrap()), - u64::from_be_bytes(key[24..32].try_into().unwrap()), - ); - - let ka = set_ka(kl, kr); - let kb = set_kb(ka, kr); - - Self::gen_subkeys(kl, kr, ka, kb) - } -} - -macro_rules! impl_camellia { - ($name:ident, $subkey_size:literal, $key_size:ty, $doc:literal) => { - #[doc = $doc] - #[derive(Clone)] - pub struct $name { - /// Subkeys. - k: [u64; $subkey_size], - } - - impl BlockCipher for $name {} - - impl KeySizeUser for $name { - type KeySize = $key_size; - } - - impl fmt::Debug for $name { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(concat!(stringify!($name), " { ... }")) - } - } - - impl AlgorithmName for $name { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(stringify!($name)) - } - } - - #[cfg(feature = "zeroize")] - #[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] - impl Drop for $name { - fn drop(&mut self) { - self.k.zeroize(); - } - } - - #[cfg(feature = "zeroize")] - #[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] - impl ZeroizeOnDrop for $name {} - - cipher::impl_simple_block_encdec!( - $name, U16, cipher, block, - encrypt: { - let b = block.get_in(); - let mut d1 = u64::from_be_bytes(b[0..8].try_into().unwrap()); - let mut d2 = u64::from_be_bytes(b[8..16].try_into().unwrap()); - - d1 ^= cipher.k[0]; - d2 ^= cipher.k[1]; - - for i in (2..$subkey_size - 2).step_by(2) { - if i % 8 == 0 { - d1 = fl(d1, cipher.k[i]); - d2 = flinv(d2, cipher.k[i + 1]); - - continue; - } - d2 ^= f(d1, cipher.k[i]); - d1 ^= f(d2, cipher.k[i + 1]); - } - - d2 ^= cipher.k[$subkey_size - 2]; - d1 ^= cipher.k[$subkey_size - 1]; - - BE::write_u64_into(&[d2, d1], block.get_out()); - } - decrypt: { - let b = block.get_in(); - let mut d1 = u64::from_be_bytes(b[0..8].try_into().unwrap()); - let mut d2 = u64::from_be_bytes(b[8..16].try_into().unwrap()); - - d2 ^= cipher.k[$subkey_size - 1]; - d1 ^= cipher.k[$subkey_size - 2]; - - for i in (2..$subkey_size - 2).rev().step_by(2) { - if (i - 1) % 8 == 0 { - d1 = fl(d1, cipher.k[i]); - d2 = flinv(d2, cipher.k[i - 1]); - - continue; - } - d2 ^= f(d1, cipher.k[i]); - d1 ^= f(d2, cipher.k[i - 1]); - } - - d1 ^= cipher.k[1]; - d2 ^= cipher.k[0]; - - BE::write_u64_into(&[d2, d1], block.get_out()); - } - ); - }; -} - -impl_camellia!(Camellia128, 26, U16, "Camellia-128 block cipher instance."); -impl_camellia!(Camellia192, 34, U24, "Camellia-192 block cipher instance."); -impl_camellia!(Camellia256, 34, U32, "Camellia-256 block cipher instance."); diff --git a/camellia/src/camellia128.rs b/camellia/src/camellia128.rs new file mode 100644 index 00000000..23b81ca5 --- /dev/null +++ b/camellia/src/camellia128.rs @@ -0,0 +1,35 @@ +use crate::{ + utils::{gen_subkeys26, set_ka}, + Camellia128, +}; +use cipher::{AlgorithmName, Key, KeyInit}; +use core::{fmt, marker::PhantomData}; + +impl KeyInit for Camellia128 { + fn new(key: &Key) -> Self { + let kl = ( + u64::from_be_bytes(key[0..8].try_into().unwrap()), + u64::from_be_bytes(key[8..16].try_into().unwrap()), + ); + let kr = (u64::default(), u64::default()); + + let ka = set_ka(kl, kr); + + Self { + k: gen_subkeys26(kl, ka), + _pd: PhantomData, + } + } +} + +impl fmt::Debug for Camellia128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Camellia128 { ... }") + } +} + +impl AlgorithmName for Camellia128 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Camellia128") + } +} diff --git a/camellia/src/camellia192.rs b/camellia/src/camellia192.rs new file mode 100644 index 00000000..a842dfda --- /dev/null +++ b/camellia/src/camellia192.rs @@ -0,0 +1,37 @@ +use crate::{ + utils::{get_subkeys34, set_ka, set_kb}, + Camellia192, +}; +use cipher::{AlgorithmName, Key, KeyInit}; +use core::{fmt, marker::PhantomData}; + +impl KeyInit for Camellia192 { + fn new(key: &Key) -> Self { + let kl = ( + u64::from_be_bytes(key[0..8].try_into().unwrap()), + u64::from_be_bytes(key[8..16].try_into().unwrap()), + ); + let kr = u64::from_be_bytes(key[16..24].try_into().unwrap()); + let kr = (kr, !kr); + + let ka = set_ka(kl, kr); + let kb = set_kb(ka, kr); + + Self { + k: get_subkeys34(kl, kr, ka, kb), + _pd: PhantomData, + } + } +} + +impl fmt::Debug for Camellia192 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Camellia192 { ... }") + } +} + +impl AlgorithmName for Camellia192 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Camellia192") + } +} diff --git a/camellia/src/camellia256.rs b/camellia/src/camellia256.rs new file mode 100644 index 00000000..9289683e --- /dev/null +++ b/camellia/src/camellia256.rs @@ -0,0 +1,39 @@ +use crate::{ + utils::{get_subkeys34, set_ka, set_kb}, + Camellia256, +}; +use cipher::{AlgorithmName, Key, KeyInit}; +use core::{fmt, marker::PhantomData}; + +impl KeyInit for Camellia256 { + fn new(key: &Key) -> Self { + let kl = ( + u64::from_be_bytes(key[0..8].try_into().unwrap()), + u64::from_be_bytes(key[8..16].try_into().unwrap()), + ); + let kr = ( + u64::from_be_bytes(key[16..24].try_into().unwrap()), + u64::from_be_bytes(key[24..32].try_into().unwrap()), + ); + + let ka = set_ka(kl, kr); + let kb = set_kb(ka, kr); + + Self { + k: get_subkeys34(kl, kr, ka, kb), + _pd: PhantomData, + } + } +} + +impl fmt::Debug for Camellia256 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Camellia256 { ... }") + } +} + +impl AlgorithmName for Camellia256 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Camellia256") + } +} diff --git a/camellia/src/lib.rs b/camellia/src/lib.rs index 83bec0f5..da8af86a 100644 --- a/camellia/src/lib.rs +++ b/camellia/src/lib.rs @@ -10,8 +10,7 @@ //! //! # Examples //! ``` -//! use camellia::cipher::array::Array; -//! use camellia::cipher::{BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; +//! use camellia::cipher::{Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; //! use camellia::Camellia128; //! //! let key = Array::from([0_u8; 16]); @@ -39,12 +38,146 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] +use core::marker::PhantomData; + pub use cipher; -mod camellia; +use cipher::{ + array::ArraySize, + block::{ + BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncBackend, + BlockCipherEncClosure, BlockCipherEncrypt, + }, + consts::{U1, U16, U24, U32}, + inout::InOut, + Block, BlockSizeUser, KeySizeUser, ParBlocksSizeUser, +}; + +#[cfg(feature = "zeroize")] +use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; + +mod camellia128; +mod camellia192; +mod camellia256; mod consts; +mod utils; + +use utils::{f, fl, flinv}; + +/// Generic implementation of the Camellia block cipher. +/// +/// This type can be initialized only with 3 combinations of `KeySize` and `RK`: +/// - Camellia-128: U16, 26 +/// - Camellia-192: U24, 34 +/// - Camellia-256: U32, 34 +#[derive(Clone)] +pub struct Camellia { + k: [u64; RK], + _pd: PhantomData, +} + +/// Camellia-128 block cipher instance. +pub type Camellia128 = Camellia; +/// Camellia-192 block cipher instance. +pub type Camellia192 = Camellia; +/// Camellia-256 block cipher instance. +pub type Camellia256 = Camellia; + +impl KeySizeUser for Camellia { + type KeySize = KeySize; +} + +impl BlockSizeUser for Camellia { + type BlockSize = U16; +} + +impl ParBlocksSizeUser for Camellia { + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for Camellia { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherEncBackend for Camellia { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let b = block.get_in(); + let mut d1 = u64::from_be_bytes(b[0..8].try_into().unwrap()); + let mut d2 = u64::from_be_bytes(b[8..16].try_into().unwrap()); + + d1 ^= self.k[0]; + d2 ^= self.k[1]; + + for i in (2..RK - 2).step_by(2) { + if i % 8 == 0 { + d1 = fl(d1, self.k[i]); + d2 = flinv(d2, self.k[i + 1]); + + continue; + } + d2 ^= f(d1, self.k[i]); + d1 ^= f(d2, self.k[i + 1]); + } + + d2 ^= self.k[RK - 2]; + d1 ^= self.k[RK - 1]; + + let (b1, b2) = block.get_out().split_at_mut(8); + b1.copy_from_slice(&d2.to_be_bytes()); + b2.copy_from_slice(&d1.to_be_bytes()); + } +} + +impl BlockCipherDecrypt for Camellia { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Camellia { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let b = block.get_in(); + let mut d1 = u64::from_be_bytes(b[0..8].try_into().unwrap()); + let mut d2 = u64::from_be_bytes(b[8..16].try_into().unwrap()); + + d2 ^= self.k[RK - 1]; + d1 ^= self.k[RK - 2]; + + for i in (2..RK - 2).rev().step_by(2) { + if (i - 1) % 8 == 0 { + d1 = fl(d1, self.k[i]); + d2 = flinv(d2, self.k[i - 1]); + + continue; + } + d2 ^= f(d1, self.k[i]); + d1 ^= f(d2, self.k[i - 1]); + } + + d1 ^= self.k[1]; + d2 ^= self.k[0]; + + let (b1, b2) = block.get_out().split_at_mut(8); + b1.copy_from_slice(&d2.to_be_bytes()); + b2.copy_from_slice(&d1.to_be_bytes()); + } +} + +impl Drop for Camellia { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + self.k.zeroize(); + } +} -pub use crate::camellia::{Camellia128, Camellia192, Camellia256}; +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Camellia {} diff --git a/camellia/src/utils.rs b/camellia/src/utils.rs new file mode 100644 index 00000000..13eba95f --- /dev/null +++ b/camellia/src/utils.rs @@ -0,0 +1,178 @@ +use crate::consts::{SBOXES, SIGMAS}; + +/// F-function of component of Camellia defined in RFC 3713. +pub(crate) fn f(input: u64, key: u64) -> u64 { + let x = (input ^ key).to_be_bytes(); + + let z1 = 0x0101_0100_0100_0001 * u64::from(SBOXES[0][usize::from(x[0])]); + let z2 = 0x0001_0101_0101_0000 * u64::from(SBOXES[1][usize::from(x[1])]); + let z3 = 0x0100_0101_0001_0100 * u64::from(SBOXES[2][usize::from(x[2])]); + let z4 = 0x0101_0001_0000_0101 * u64::from(SBOXES[3][usize::from(x[3])]); + let z5 = 0x0001_0101_0001_0101 * u64::from(SBOXES[1][usize::from(x[4])]); + let z6 = 0x0100_0101_0100_0101 * u64::from(SBOXES[2][usize::from(x[5])]); + let z7 = 0x0101_0001_0101_0001 * u64::from(SBOXES[3][usize::from(x[6])]); + let z8 = 0x0101_0100_0101_0100 * u64::from(SBOXES[0][usize::from(x[7])]); + + z1 ^ z2 ^ z3 ^ z4 ^ z5 ^ z6 ^ z7 ^ z8 +} + +/// FL-function of component of Camellia defined in RFC 3713. +pub(crate) fn fl(input: u64, key: u64) -> u64 { + let mut x1 = u32::try_from(input >> 32).unwrap(); + let mut x2 = u32::try_from(input & 0xffff_ffff).unwrap(); + + let k1 = u32::try_from(key >> 32).unwrap(); + let k2 = u32::try_from(key & 0xffff_ffff).unwrap(); + + x2 ^= (x1 & k1).rotate_left(1); + x1 ^= x2 | k2; + + (u64::from(x1) << 32) | u64::from(x2) +} + +/// FLINV-function of component of Camellia defined in RFC 3713. +pub(crate) fn flinv(input: u64, key: u64) -> u64 { + let mut y1 = u32::try_from(input >> 32).unwrap(); + let mut y2 = u32::try_from(input & 0xffff_ffff).unwrap(); + + let k1 = u32::try_from(key >> 32).unwrap(); + let k2 = u32::try_from(key & 0xffff_ffff).unwrap(); + + y1 ^= y2 | k2; + y2 ^= (y1 & k1).rotate_left(1); + + (u64::from(y1) << 32) | u64::from(y2) +} + +pub(crate) fn set_ka(kl: (u64, u64), kr: (u64, u64)) -> (u64, u64) { + let mut d1 = kl.0 ^ kr.0; + let mut d2 = kl.1 ^ kr.1; + d2 ^= f(d1, SIGMAS[0]); + d1 ^= f(d2, SIGMAS[1]); + d1 ^= kl.0; + d2 ^= kl.1; + d2 ^= f(d1, SIGMAS[2]); + d1 ^= f(d2, SIGMAS[3]); + + (d1, d2) +} + +pub(crate) fn set_kb(ka: (u64, u64), kr: (u64, u64)) -> (u64, u64) { + let mut d1 = ka.0 ^ kr.0; + let mut d2 = ka.1 ^ kr.1; + d2 ^= f(d1, SIGMAS[4]); + d1 ^= f(d2, SIGMAS[5]); + + (d1, d2) +} + +/// Performs rotate left and taking the higher-half of it. +fn rotate_left_high(val: (u64, u64), mut shift: u8) -> u64 { + if shift >= 64 { + shift -= 64; + } + + (val.0 << shift) | (val.1 >> (64 - shift)) +} + +/// Performs rotate left and taking the lower-half of it. +fn rotate_left_low(val: (u64, u64), mut shift: u8) -> u64 { + if shift >= 64 { + shift -= 64; + } + + (val.0 >> (64 - shift)) | (val.1 << shift) +} + +pub(crate) fn gen_subkeys26(kl: (u64, u64), ka: (u64, u64)) -> [u64; 26] { + let mut k = [0; 26]; + + k[0] = kl.0; + k[1] = kl.1; + + k[2] = ka.0; + k[3] = ka.1; + k[4] = rotate_left_high(kl, 15); + k[5] = rotate_left_low(kl, 15); + k[6] = rotate_left_high(ka, 15); + k[7] = rotate_left_low(ka, 15); + + k[8] = rotate_left_high(ka, 30); + k[9] = rotate_left_low(ka, 30); + + k[10] = rotate_left_high(kl, 45); + k[11] = rotate_left_low(kl, 45); + k[12] = rotate_left_high(ka, 45); + k[13] = rotate_left_low(kl, 60); + k[14] = rotate_left_high(ka, 60); + k[15] = rotate_left_low(ka, 60); + + k[16] = rotate_left_low(kl, 77); + k[17] = rotate_left_high(kl, 77); + + k[18] = rotate_left_low(kl, 94); + k[19] = rotate_left_high(kl, 94); + k[20] = rotate_left_low(ka, 94); + k[21] = rotate_left_high(ka, 94); + k[22] = rotate_left_low(kl, 111); + k[23] = rotate_left_high(kl, 111); + + k[24] = rotate_left_low(ka, 111); + k[25] = rotate_left_high(ka, 111); + + k +} + +pub(crate) fn get_subkeys34( + kl: (u64, u64), + kr: (u64, u64), + ka: (u64, u64), + kb: (u64, u64), +) -> [u64; 34] { + let mut k = [u64::default(); 34]; + + k[0] = kl.0; + k[1] = kl.1; + + k[2] = kb.0; + k[3] = kb.1; + k[4] = rotate_left_high(kr, 15); + k[5] = rotate_left_low(kr, 15); + k[6] = rotate_left_high(ka, 15); + k[7] = rotate_left_low(ka, 15); + + k[8] = rotate_left_high(kr, 30); + k[9] = rotate_left_low(kr, 30); + + k[10] = rotate_left_high(kb, 30); + k[11] = rotate_left_low(kb, 30); + k[12] = rotate_left_high(kl, 45); + k[13] = rotate_left_low(kl, 45); + k[14] = rotate_left_high(ka, 45); + k[15] = rotate_left_low(ka, 45); + + k[16] = rotate_left_high(kl, 60); + k[17] = rotate_left_low(kl, 60); + + k[18] = rotate_left_high(kr, 60); + k[19] = rotate_left_low(kr, 60); + k[20] = rotate_left_high(kb, 60); + k[21] = rotate_left_low(kb, 60); + k[22] = rotate_left_low(kl, 77); + k[23] = rotate_left_high(kl, 77); + + k[24] = rotate_left_low(ka, 77); + k[25] = rotate_left_high(ka, 77); + + k[26] = rotate_left_low(kr, 94); + k[27] = rotate_left_high(kr, 94); + k[28] = rotate_left_low(ka, 94); + k[29] = rotate_left_high(ka, 94); + k[30] = rotate_left_low(kl, 111); + k[31] = rotate_left_high(kl, 111); + + k[32] = rotate_left_low(kb, 111); + k[33] = rotate_left_high(kb, 111); + + k +} diff --git a/cast5/Cargo.toml b/cast5/Cargo.toml index 85c83308..eab8ffa3 100644 --- a/cast5/Cargo.toml +++ b/cast5/Cargo.toml @@ -13,10 +13,10 @@ keywords = ["crypto", "cast5", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" [features] diff --git a/cast5/LICENSE-MIT b/cast5/LICENSE-MIT index 4ddf226a..3cb7f1b3 100644 --- a/cast5/LICENSE-MIT +++ b/cast5/LICENSE-MIT @@ -1,5 +1,5 @@ +Copyright (c) 2018-2024 The RustCrypto Project Developers Copyright (c) 2018-2019 Friedel Ziegelmayer -Copyright (c) 2018-2019 The RustCrypto Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/cast5/src/lib.rs b/cast5/src/lib.rs index 575f0d33..d4403ab7 100644 --- a/cast5/src/lib.rs +++ b/cast5/src/lib.rs @@ -10,8 +10,7 @@ //! //! # Examples //! ``` -//! use cast5::cipher::array::Array; -//! use cast5::cipher::{Key, Block, BlockCipherEncrypt, BlockCipherDecrypt, KeyInit}; +//! use cast5::cipher::{Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; //! use cast5::Cast5; //! //! let key = Array::from([0u8; 16]); @@ -36,7 +35,7 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] pub use cipher; @@ -45,8 +44,10 @@ mod consts; mod schedule; use cipher::{ - consts::{U16, U8}, - AlgorithmName, BlockCipher, InvalidLength, Key, KeyInit, KeySizeUser, + consts::{U1, U16, U8}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, + InvalidLength, Key, KeyInit, KeySizeUser, ParBlocksSizeUser, }; use core::fmt; @@ -129,8 +130,6 @@ macro_rules! f3 { }}; } -impl BlockCipher for Cast5 {} - impl KeySizeUser for Cast5 { type KeySize = U16; } @@ -159,37 +158,26 @@ impl KeyInit for Cast5 { } } -impl fmt::Debug for Cast5 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Cast5 { ... }") - } +impl BlockSizeUser for Cast5 { + type BlockSize = U8; } -impl AlgorithmName for Cast5 { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Cast5") - } +impl ParBlocksSizeUser for Cast5 { + type ParBlocksSize = U1; } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl Drop for Cast5 { - fn drop(&mut self) { - self.masking.zeroize(); - self.rotate.zeroize(); - self.small_key.zeroize(); +impl BlockCipherEncrypt for Cast5 { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl ZeroizeOnDrop for Cast5 {} - -cipher::impl_simple_block_encdec!( - Cast5, U8, cipher, block, - encrypt: { - let masking = cipher.masking; - let rotate = cipher.rotate; +impl BlockCipherEncBackend for Cast5 { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let masking = self.masking; + let rotate = self.rotate; // (L0,R0) <-- (m1...m64). (Split the plaintext into left and // right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) @@ -218,7 +206,7 @@ cipher::impl_simple_block_encdec!( let (l, r) = (r, l ^ f2!(r, masking[10], rotate[10])); let (l, r) = (r, l ^ f3!(r, masking[11], rotate[11])); - let (l, r) = if cipher.small_key { + let (l, r) = if self.small_key { (l, r) } else { // Rounds 13..16 are only executed for keys > 80 bits. @@ -234,15 +222,26 @@ cipher::impl_simple_block_encdec!( block[0..4].copy_from_slice(&r.to_be_bytes()); block[4..8].copy_from_slice(&l.to_be_bytes()); } - decrypt: { - let masking = cipher.masking; - let rotate = cipher.rotate; +} + +impl BlockCipherDecrypt for Cast5 { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Cast5 { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let masking = self.masking; + let rotate = self.rotate; let b = block.get_in(); let l = u32::from_be_bytes(b[0..4].try_into().unwrap()); let r = u32::from_be_bytes(b[4..8].try_into().unwrap()); - let (l, r) = if cipher.small_key { + let (l, r) = if self.small_key { (l, r) } else { let (l, r) = (r, l ^ f1!(r, masking[15], rotate[15])); @@ -268,4 +267,30 @@ cipher::impl_simple_block_encdec!( block[0..4].copy_from_slice(&r.to_be_bytes()); block[4..8].copy_from_slice(&l.to_be_bytes()); } -); +} + +impl fmt::Debug for Cast5 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Cast5 { ... }") + } +} + +impl AlgorithmName for Cast5 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Cast5") + } +} + +impl Drop for Cast5 { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + { + self.masking.zeroize(); + self.rotate.zeroize(); + self.small_key.zeroize(); + } + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Cast5 {} diff --git a/cast5/tests/mod.rs b/cast5/tests/mod.rs index 9da6622d..e545e78d 100644 --- a/cast5/tests/mod.rs +++ b/cast5/tests/mod.rs @@ -1,5 +1,5 @@ use cast5::Cast5; -use cipher::{array::Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; +use cipher::{Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; use hex_literal::hex; /// Test vectors from RFC 2144 Appendix B.1 diff --git a/cast6/Cargo.toml b/cast6/Cargo.toml index 66818705..8448b19f 100644 --- a/cast6/Cargo.toml +++ b/cast6/Cargo.toml @@ -13,10 +13,10 @@ keywords = ["crypto", "cast6", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" [features] diff --git a/cast6/LICENSE-MIT b/cast6/LICENSE-MIT index 50c61807..3b73c41c 100644 --- a/cast6/LICENSE-MIT +++ b/cast6/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2023 The RustCrypto Project Developers +Copyright (c) 2023-2024 The RustCrypto Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/cast6/src/lib.rs b/cast6/src/lib.rs index e6d2c89a..6febf9c1 100644 --- a/cast6/src/lib.rs +++ b/cast6/src/lib.rs @@ -10,8 +10,7 @@ //! //! # Examples //! ``` -//! use cast6::cipher::array::Array; -//! use cast6::cipher::{Key, Block, BlockCipherEncrypt, BlockCipherDecrypt, KeyInit}; +//! use cast6::cipher::{Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; //! use cast6::Cast6; //! //! let key = Array::from([0u8; 32]); @@ -36,7 +35,7 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] pub use cipher; @@ -44,8 +43,10 @@ pub use cipher; mod consts; use cipher::{ - consts::{U16, U32}, - AlgorithmName, BlockCipher, InvalidLength, Key, KeyInit, KeySizeUser, + consts::{U1, U16, U32}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, + InvalidLength, Key, KeyInit, KeySizeUser, ParBlocksSizeUser, }; use core::fmt; @@ -172,8 +173,6 @@ fn forward_octave(kappa: &mut [u32; 8], m: &[u32], r: &[u8]) { *h ^= f2!(*a, m[7], r[7]); } -impl BlockCipher for Cast6 {} - impl KeySizeUser for Cast6 { type KeySize = U32; } @@ -201,36 +200,26 @@ impl KeyInit for Cast6 { } } -impl fmt::Debug for Cast6 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Cast6 { ... }") - } +impl BlockSizeUser for Cast6 { + type BlockSize = U16; } -impl AlgorithmName for Cast6 { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Cast6") - } +impl ParBlocksSizeUser for Cast6 { + type ParBlocksSize = U1; } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl Drop for Cast6 { - fn drop(&mut self) { - self.masking.zeroize(); - self.rotate.zeroize(); +impl BlockCipherEncrypt for Cast6 { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl ZeroizeOnDrop for Cast6 {} - -cipher::impl_simple_block_encdec!( - Cast6, U16, cipher, block, - encrypt: { - let masking = &cipher.masking; - let rotate = &cipher.rotate; +impl BlockCipherEncBackend for Cast6 { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let masking = &self.masking; + let rotate = &self.rotate; // Let BETA = (ABCD) be a 128-bit block where A, B, C and D are each // 32 bits in length. @@ -258,9 +247,20 @@ cipher::impl_simple_block_encdec!( // 128bits of ciphertext = BETA *block.get_out() = to_u8s::<16>(&beta).into(); } - decrypt: { - let masking = &cipher.masking; - let rotate = &cipher.rotate; +} + +impl BlockCipherDecrypt for Cast6 { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Cast6 { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let masking = &self.masking; + let rotate = &self.rotate; let mut beta = to_u32s(block.get_in()); @@ -280,7 +280,32 @@ cipher::impl_simple_block_encdec!( *block.get_out() = to_u8s::<16>(&beta).into(); } -); +} + +impl fmt::Debug for Cast6 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Cast6 { ... }") + } +} + +impl AlgorithmName for Cast6 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Cast6") + } +} + +impl Drop for Cast6 { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + { + self.masking.zeroize(); + self.rotate.zeroize(); + } + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Cast6 {} fn to_u32s(src: &[u8]) -> [u32; N] { assert_eq!(src.len(), 4 * N); diff --git a/des/CHANGELOG.md b/des/CHANGELOG.md index 8586338d..0d5ecce7 100644 --- a/des/CHANGELOG.md +++ b/des/CHANGELOG.md @@ -7,7 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Changed -- Remove `html_root_url` ([#344]) - Update Clippy and fix lints ([#378]) - Bump `cipher` to v0.5.0-pre.1; MSRV 1.65 ([#394]) - Bump `cipher` dependency to v0.5.0-pre.2 ([#398]) diff --git a/des/Cargo.toml b/des/Cargo.toml index d8a327bf..f839232f 100644 --- a/des/Cargo.toml +++ b/des/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "des" -version = "0.9.0-pre.1" +version = "0.9.0-pre.2" description = "DES and Triple DES (3DES, TDES) block ciphers implementation" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -13,10 +13,10 @@ keywords = ["crypto", "des", "tdes", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } [features] zeroize = ["cipher/zeroize"] diff --git a/des/LICENSE-MIT b/des/LICENSE-MIT index a8984a22..bbfaff8d 100644 --- a/des/LICENSE-MIT +++ b/des/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2017-2024 The RustCrypto Project Developers Copyright (c) 2017 Gulshan Singh, Antoni Boucher, Artyom Pavlov Permission is hereby granted, free of charge, to any diff --git a/des/src/des.rs b/des/src/des.rs index 6a748f5d..128e4c3c 100644 --- a/des/src/des.rs +++ b/des/src/des.rs @@ -2,13 +2,18 @@ #![allow(clippy::unreadable_literal)] -use cipher::{consts::U8, AlgorithmName, BlockCipher, Key, KeyInit, KeySizeUser}; +use cipher::{ + consts::{U1, U8}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key, + KeyInit, KeySizeUser, ParBlocksSizeUser, +}; use core::fmt; #[cfg(feature = "zeroize")] use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; -use crate::consts::{SBOXES, SHIFTS}; +use crate::utils::{fp, gen_keys, ip, round}; /// Data Encryption Standard (DES) block cipher. #[derive(Clone)] @@ -16,157 +21,6 @@ pub struct Des { pub(crate) keys: [u64; 16], } -/// Swap bits in `a` using a delta swap -fn delta_swap(a: u64, delta: u64, mask: u64) -> u64 { - let b = (a ^ (a >> delta)) & mask; - a ^ b ^ (b << delta) -} - -/// Swap bits using the PC-1 table -fn pc1(mut key: u64) -> u64 { - key = delta_swap(key, 2, 0x3333000033330000); - key = delta_swap(key, 4, 0x0f0f0f0f00000000); - key = delta_swap(key, 8, 0x009a000a00a200a8); - key = delta_swap(key, 16, 0x00006c6c0000cccc); - key = delta_swap(key, 1, 0x1045500500550550); - key = delta_swap(key, 32, 0x00000000f0f0f5fa); - key = delta_swap(key, 8, 0x00550055006a00aa); - key = delta_swap(key, 2, 0x0000333330000300); - key & 0xFFFFFFFFFFFFFF00 -} - -/// Swap bits using the PC-2 table -fn pc2(key: u64) -> u64 { - let key = key.rotate_left(61); - let b1 = (key & 0x0021000002000000) >> 7; - let b2 = (key & 0x0008020010080000) << 1; - let b3 = key & 0x0002200000000000; - let b4 = (key & 0x0000000000100020) << 19; - let b5 = (key.rotate_left(54) & 0x0005312400000011).wrapping_mul(0x0000000094200201) - & 0xea40100880000000; - let b6 = (key.rotate_left(7) & 0x0022110000012001).wrapping_mul(0x0001000000610006) - & 0x1185004400000000; - let b7 = (key.rotate_left(6) & 0x0000520040200002).wrapping_mul(0x00000080000000c1) - & 0x0028811000200000; - let b8 = (key & 0x01000004c0011100).wrapping_mul(0x0000000000004284) & 0x0400082244400000; - let b9 = (key.rotate_left(60) & 0x0000000000820280).wrapping_mul(0x0000000000089001) - & 0x0000000110880000; - let b10 = (key.rotate_left(49) & 0x0000000000024084).wrapping_mul(0x0000000002040005) - & 0x000000000a030000; - b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | b10 -} - -/// Swap bits using the reverse FP table -fn fp(mut message: u64) -> u64 { - message = delta_swap(message, 24, 0x000000FF000000FF); - message = delta_swap(message, 24, 0x00000000FF00FF00); - message = delta_swap(message, 36, 0x000000000F0F0F0F); - message = delta_swap(message, 18, 0x0000333300003333); - delta_swap(message, 9, 0x0055005500550055) -} - -/// Swap bits using the IP table -fn ip(mut message: u64) -> u64 { - message = delta_swap(message, 9, 0x0055005500550055); - message = delta_swap(message, 18, 0x0000333300003333); - message = delta_swap(message, 36, 0x000000000F0F0F0F); - message = delta_swap(message, 24, 0x00000000FF00FF00); - delta_swap(message, 24, 0x000000FF000000FF) -} - -/// Swap bits using the E table -fn e(block: u64) -> u64 { - const BLOCK_LEN: usize = 32; - const RESULT_LEN: usize = 48; - - let b1 = (block << (BLOCK_LEN - 1)) & 0x8000000000000000; - let b2 = (block >> 1) & 0x7C00000000000000; - let b3 = (block >> 3) & 0x03F0000000000000; - let b4 = (block >> 5) & 0x000FC00000000000; - let b5 = (block >> 7) & 0x00003F0000000000; - let b6 = (block >> 9) & 0x000000FC00000000; - let b7 = (block >> 11) & 0x00000003F0000000; - let b8 = (block >> 13) & 0x000000000FC00000; - let b9 = (block >> 15) & 0x00000000003E0000; - let b10 = (block >> (RESULT_LEN - 1)) & 0x0000000000010000; - b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | b10 -} - -/// Swap bits using the P table -fn p(block: u64) -> u64 { - let block = block.rotate_left(44); - let b1 = (block & 0x0000000000200000) << 32; - let b2 = (block & 0x0000000000480000) << 13; - let b3 = (block & 0x0000088000000000) << 12; - let b4 = (block & 0x0000002020120000) << 25; - let b5 = (block & 0x0000000442000000) << 14; - let b6 = (block & 0x0000000001800000) << 37; - let b7 = (block & 0x0000000004000000) << 24; - let b8 = (block & 0x0000020280015000).wrapping_mul(0x0000020080800083) & 0x02000a6400000000; - let b9 = (block.rotate_left(29) & 0x01001400000000aa).wrapping_mul(0x0000210210008081) - & 0x0902c01200000000; - let b10 = (block & 0x0000000910040000).wrapping_mul(0x0000000c04000020) & 0x8410010000000000; - b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | b10 -} - -/// Generate the 16 subkeys -pub(crate) fn gen_keys(key: u64) -> [u64; 16] { - let mut keys: [u64; 16] = [0; 16]; - let key = pc1(key); - - // The most significant bit is bit zero, and there are only 56 bits in - // the key after applying PC1, so we need to remove the eight least - // significant bits from the key. - let key = key >> 8; - - let mut c = key >> 28; - let mut d = key & 0x0FFFFFFF; - for i in 0..16 { - c = rotate(c, SHIFTS[i]); - d = rotate(d, SHIFTS[i]); - - // We need the `<< 8` because the most significant bit is bit zero, - // so we need to shift our 56 bit value 8 bits to the left. - keys[i] = pc2(((c << 28) | d) << 8); - } - - keys -} - -/// Performs a left rotate on a 28 bit number -fn rotate(mut val: u64, shift: u8) -> u64 { - let top_bits = val >> (28 - shift); - val <<= shift; - - (val | top_bits) & 0x0FFFFFFF -} - -fn round(input: u64, key: u64) -> u64 { - let l = input & (0xFFFF_FFFF << 32); - let r = input << 32; - - r | ((f(r, key) ^ l) >> 32) -} - -fn f(input: u64, key: u64) -> u64 { - let mut val = e(input); - val ^= key; - val = apply_sboxes(val); - p(val) -} - -/// Applies all eight sboxes to the input -fn apply_sboxes(input: u64) -> u64 { - let mut output: u64 = 0; - - for (i, sbox) in SBOXES.iter().enumerate() { - let val = (input >> (58 - (i * 6))) & 0x3F; - output |= u64::from(sbox[val as usize]) << (60 - (i * 4)); - } - - output -} - impl Des { pub(crate) fn encrypt(&self, mut data: u64) -> u64 { data = ip(data); @@ -185,8 +39,6 @@ impl Des { } } -impl BlockCipher for Des {} - impl KeySizeUser for Des { type KeySize = U8; } @@ -194,11 +46,51 @@ impl KeySizeUser for Des { impl KeyInit for Des { #[inline] fn new(key: &Key) -> Self { - let keys = gen_keys(u64::from_be_bytes(key.clone().into())); + let keys = gen_keys(u64::from_be_bytes(key.0)); Self { keys } } } +impl BlockSizeUser for Des { + type BlockSize = U8; +} + +impl ParBlocksSizeUser for Des { + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for Des { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherEncBackend for Des { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut data = u64::from_be_bytes(block.clone_in().into()); + data = self.encrypt(data); + block.get_out().copy_from_slice(&data.to_be_bytes()); + } +} + +impl BlockCipherDecrypt for Des { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Des { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut data = u64::from_be_bytes(block.clone_in().into()); + data = self.decrypt(data); + block.get_out().copy_from_slice(&data.to_be_bytes()); + } +} + impl fmt::Debug for Des { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("Des { ... }") @@ -211,28 +103,12 @@ impl AlgorithmName for Des { } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl Drop for Des { fn drop(&mut self) { + #[cfg(feature = "zeroize")] self.keys.zeroize(); } } #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl ZeroizeOnDrop for Des {} - -cipher::impl_simple_block_encdec!( - Des, U8, cipher, block, - encrypt: { - let mut data = u64::from_be_bytes(block.clone_in().into()); - data = cipher.encrypt(data); - block.get_out().copy_from_slice(&data.to_be_bytes()); - } - decrypt: { - let mut data = u64::from_be_bytes(block.clone_in().into()); - data = cipher.decrypt(data); - block.get_out().copy_from_slice(&data.to_be_bytes()); - } -); diff --git a/des/src/lib.rs b/des/src/lib.rs index 323406e9..7dc04377 100644 --- a/des/src/lib.rs +++ b/des/src/lib.rs @@ -18,15 +18,15 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] -#![allow(clippy::clone_on_copy)] // TODO: remove on migration to const generics pub use cipher; mod consts; mod des; mod tdes; +mod utils; pub use crate::des::Des; pub use crate::tdes::{TdesEde2, TdesEde3, TdesEee2, TdesEee3}; diff --git a/des/src/tdes.rs b/des/src/tdes.rs index ad210824..c811c0b3 100644 --- a/des/src/tdes.rs +++ b/des/src/tdes.rs @@ -1,9 +1,11 @@ //! Triple DES (3DES) block ciphers. -use crate::des::{gen_keys, Des}; +use crate::{utils::gen_keys, Des}; use cipher::{ - consts::{U16, U24, U8}, - AlgorithmName, BlockCipher, Key, KeyInit, KeySizeUser, + consts::{U1, U16, U24, U8}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key, + KeyInit, KeySizeUser, ParBlocksSizeUser, }; use core::fmt; @@ -18,8 +20,6 @@ pub struct TdesEde3 { d3: Des, } -impl BlockCipher for TdesEde3 {} - impl KeySizeUser for TdesEde3 { type KeySize = U24; } @@ -37,6 +37,50 @@ impl KeyInit for TdesEde3 { } } +impl BlockSizeUser for TdesEde3 { + type BlockSize = U8; +} + +impl ParBlocksSizeUser for TdesEde3 { + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for TdesEde3 { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherEncBackend for TdesEde3 { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut data = u64::from_be_bytes(block.clone_in().into()); + data = self.d1.encrypt(data); + data = self.d2.decrypt(data); + data = self.d3.encrypt(data); + block.get_out().copy_from_slice(&data.to_be_bytes()); + } +} + +impl BlockCipherDecrypt for TdesEde3 { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for TdesEde3 { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut data = u64::from_be_bytes(block.clone_in().into()); + data = self.d3.decrypt(data); + data = self.d2.encrypt(data); + data = self.d1.decrypt(data); + block.get_out().copy_from_slice(&data.to_be_bytes()); + } +} + impl fmt::Debug for TdesEde3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("TdesEee3 { ... }") @@ -50,27 +94,8 @@ impl AlgorithmName for TdesEde3 { } #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl ZeroizeOnDrop for TdesEde3 {} -cipher::impl_simple_block_encdec!( - TdesEde3, U8, cipher, block, - encrypt: { - let mut data = u64::from_be_bytes(block.clone_in().into()); - data = cipher.d1.encrypt(data); - data = cipher.d2.decrypt(data); - data = cipher.d3.encrypt(data); - block.get_out().copy_from_slice(&data.to_be_bytes()); - } - decrypt: { - let mut data = u64::from_be_bytes(block.clone_in().into()); - data = cipher.d3.decrypt(data); - data = cipher.d2.encrypt(data); - data = cipher.d1.decrypt(data); - block.get_out().copy_from_slice(&data.to_be_bytes()); - } -); - /// Triple DES (3DES) block cipher. #[derive(Clone)] pub struct TdesEee3 { @@ -79,8 +104,6 @@ pub struct TdesEee3 { d3: Des, } -impl BlockCipher for TdesEee3 {} - impl KeySizeUser for TdesEee3 { type KeySize = U24; } @@ -98,6 +121,50 @@ impl KeyInit for TdesEee3 { } } +impl BlockSizeUser for TdesEee3 { + type BlockSize = U8; +} + +impl ParBlocksSizeUser for TdesEee3 { + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for TdesEee3 { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherEncBackend for TdesEee3 { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut data = u64::from_be_bytes(block.clone_in().into()); + data = self.d1.encrypt(data); + data = self.d2.encrypt(data); + data = self.d3.encrypt(data); + block.get_out().copy_from_slice(&data.to_be_bytes()); + } +} + +impl BlockCipherDecrypt for TdesEee3 { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for TdesEee3 { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut data = u64::from_be_bytes(block.clone_in().into()); + data = self.d3.decrypt(data); + data = self.d2.decrypt(data); + data = self.d1.decrypt(data); + block.get_out().copy_from_slice(&data.to_be_bytes()); + } +} + impl fmt::Debug for TdesEee3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("TdesEee3 { ... }") @@ -111,27 +178,8 @@ impl AlgorithmName for TdesEee3 { } #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl ZeroizeOnDrop for TdesEee3 {} -cipher::impl_simple_block_encdec!( - TdesEee3, U8, cipher, block, - encrypt: { - let mut data = u64::from_be_bytes(block.clone_in().into()); - data = cipher.d1.encrypt(data); - data = cipher.d2.encrypt(data); - data = cipher.d3.encrypt(data); - block.get_out().copy_from_slice(&data.to_be_bytes()); - } - decrypt: { - let mut data = u64::from_be_bytes(block.clone_in().into()); - data = cipher.d3.decrypt(data); - data = cipher.d2.decrypt(data); - data = cipher.d1.decrypt(data); - block.get_out().copy_from_slice(&data.to_be_bytes()); - } -); - /// Triple DES (3DES) block cipher. #[derive(Clone)] pub struct TdesEde2 { @@ -139,8 +187,6 @@ pub struct TdesEde2 { d2: Des, } -impl BlockCipher for TdesEde2 {} - impl KeySizeUser for TdesEde2 { type KeySize = U16; } @@ -156,6 +202,50 @@ impl KeyInit for TdesEde2 { } } +impl BlockSizeUser for TdesEde2 { + type BlockSize = U8; +} + +impl ParBlocksSizeUser for TdesEde2 { + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for TdesEde2 { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherEncBackend for TdesEde2 { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut data = u64::from_be_bytes(block.clone_in().into()); + data = self.d1.encrypt(data); + data = self.d2.decrypt(data); + data = self.d1.encrypt(data); + block.get_out().copy_from_slice(&data.to_be_bytes()); + } +} + +impl BlockCipherDecrypt for TdesEde2 { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for TdesEde2 { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut data = u64::from_be_bytes(block.clone_in().into()); + data = self.d1.decrypt(data); + data = self.d2.encrypt(data); + data = self.d1.decrypt(data); + block.get_out().copy_from_slice(&data.to_be_bytes()); + } +} + impl fmt::Debug for TdesEde2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("TdesEde2 { ... }") @@ -169,27 +259,8 @@ impl AlgorithmName for TdesEde2 { } #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl ZeroizeOnDrop for TdesEde2 {} -cipher::impl_simple_block_encdec!( - TdesEde2, U8, cipher, block, - encrypt: { - let mut data = u64::from_be_bytes(block.clone_in().into()); - data = cipher.d1.encrypt(data); - data = cipher.d2.decrypt(data); - data = cipher.d1.encrypt(data); - block.get_out().copy_from_slice(&data.to_be_bytes()); - } - decrypt: { - let mut data = u64::from_be_bytes(block.clone_in().into()); - data = cipher.d1.decrypt(data); - data = cipher.d2.encrypt(data); - data = cipher.d1.decrypt(data); - block.get_out().copy_from_slice(&data.to_be_bytes()); - } -); - /// Triple DES (3DES) block cipher. #[derive(Clone)] pub struct TdesEee2 { @@ -197,8 +268,6 @@ pub struct TdesEee2 { d2: Des, } -impl BlockCipher for TdesEee2 {} - impl KeySizeUser for TdesEee2 { type KeySize = U16; } @@ -214,6 +283,50 @@ impl KeyInit for TdesEee2 { } } +impl BlockSizeUser for TdesEee2 { + type BlockSize = U8; +} + +impl ParBlocksSizeUser for TdesEee2 { + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for TdesEee2 { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherEncBackend for TdesEee2 { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut data = u64::from_be_bytes(block.clone_in().into()); + data = self.d1.encrypt(data); + data = self.d2.encrypt(data); + data = self.d1.encrypt(data); + block.get_out().copy_from_slice(&data.to_be_bytes()); + } +} + +impl BlockCipherDecrypt for TdesEee2 { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for TdesEee2 { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut data = u64::from_be_bytes(block.clone_in().into()); + data = self.d1.decrypt(data); + data = self.d2.decrypt(data); + data = self.d1.decrypt(data); + block.get_out().copy_from_slice(&data.to_be_bytes()); + } +} + impl fmt::Debug for TdesEee2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("TdesEee2 { ... }") @@ -227,23 +340,4 @@ impl AlgorithmName for TdesEee2 { } #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl ZeroizeOnDrop for TdesEee2 {} - -cipher::impl_simple_block_encdec!( - TdesEee2, U8, cipher, block, - encrypt: { - let mut data = u64::from_be_bytes(block.clone_in().into()); - data = cipher.d1.encrypt(data); - data = cipher.d2.encrypt(data); - data = cipher.d1.encrypt(data); - block.get_out().copy_from_slice(&data.to_be_bytes()); - } - decrypt: { - let mut data = u64::from_be_bytes(block.clone_in().into()); - data = cipher.d1.decrypt(data); - data = cipher.d2.decrypt(data); - data = cipher.d1.decrypt(data); - block.get_out().copy_from_slice(&data.to_be_bytes()); - } -); diff --git a/des/src/utils.rs b/des/src/utils.rs new file mode 100644 index 00000000..d2782245 --- /dev/null +++ b/des/src/utils.rs @@ -0,0 +1,152 @@ +use crate::consts::{SBOXES, SHIFTS}; + +/// Swap bits in `a` using a delta swap +fn delta_swap(a: u64, delta: u64, mask: u64) -> u64 { + let b = (a ^ (a >> delta)) & mask; + a ^ b ^ (b << delta) +} + +/// Swap bits using the PC-1 table +fn pc1(mut key: u64) -> u64 { + key = delta_swap(key, 2, 0x3333000033330000); + key = delta_swap(key, 4, 0x0f0f0f0f00000000); + key = delta_swap(key, 8, 0x009a000a00a200a8); + key = delta_swap(key, 16, 0x00006c6c0000cccc); + key = delta_swap(key, 1, 0x1045500500550550); + key = delta_swap(key, 32, 0x00000000f0f0f5fa); + key = delta_swap(key, 8, 0x00550055006a00aa); + key = delta_swap(key, 2, 0x0000333330000300); + key & 0xFFFFFFFFFFFFFF00 +} + +/// Swap bits using the PC-2 table +fn pc2(key: u64) -> u64 { + let key = key.rotate_left(61); + let b1 = (key & 0x0021000002000000) >> 7; + let b2 = (key & 0x0008020010080000) << 1; + let b3 = key & 0x0002200000000000; + let b4 = (key & 0x0000000000100020) << 19; + let b5 = (key.rotate_left(54) & 0x0005312400000011).wrapping_mul(0x0000000094200201) + & 0xea40100880000000; + let b6 = (key.rotate_left(7) & 0x0022110000012001).wrapping_mul(0x0001000000610006) + & 0x1185004400000000; + let b7 = (key.rotate_left(6) & 0x0000520040200002).wrapping_mul(0x00000080000000c1) + & 0x0028811000200000; + let b8 = (key & 0x01000004c0011100).wrapping_mul(0x0000000000004284) & 0x0400082244400000; + let b9 = (key.rotate_left(60) & 0x0000000000820280).wrapping_mul(0x0000000000089001) + & 0x0000000110880000; + let b10 = (key.rotate_left(49) & 0x0000000000024084).wrapping_mul(0x0000000002040005) + & 0x000000000a030000; + b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | b10 +} + +/// Swap bits using the reverse FP table +pub(crate) fn fp(mut message: u64) -> u64 { + message = delta_swap(message, 24, 0x000000FF000000FF); + message = delta_swap(message, 24, 0x00000000FF00FF00); + message = delta_swap(message, 36, 0x000000000F0F0F0F); + message = delta_swap(message, 18, 0x0000333300003333); + delta_swap(message, 9, 0x0055005500550055) +} + +/// Swap bits using the IP table +pub(crate) fn ip(mut message: u64) -> u64 { + message = delta_swap(message, 9, 0x0055005500550055); + message = delta_swap(message, 18, 0x0000333300003333); + message = delta_swap(message, 36, 0x000000000F0F0F0F); + message = delta_swap(message, 24, 0x00000000FF00FF00); + delta_swap(message, 24, 0x000000FF000000FF) +} + +/// Swap bits using the E table +fn e(block: u64) -> u64 { + const BLOCK_LEN: usize = 32; + const RESULT_LEN: usize = 48; + + let b1 = (block << (BLOCK_LEN - 1)) & 0x8000000000000000; + let b2 = (block >> 1) & 0x7C00000000000000; + let b3 = (block >> 3) & 0x03F0000000000000; + let b4 = (block >> 5) & 0x000FC00000000000; + let b5 = (block >> 7) & 0x00003F0000000000; + let b6 = (block >> 9) & 0x000000FC00000000; + let b7 = (block >> 11) & 0x00000003F0000000; + let b8 = (block >> 13) & 0x000000000FC00000; + let b9 = (block >> 15) & 0x00000000003E0000; + let b10 = (block >> (RESULT_LEN - 1)) & 0x0000000000010000; + b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | b10 +} + +/// Swap bits using the P table +fn p(block: u64) -> u64 { + let block = block.rotate_left(44); + let b1 = (block & 0x0000000000200000) << 32; + let b2 = (block & 0x0000000000480000) << 13; + let b3 = (block & 0x0000088000000000) << 12; + let b4 = (block & 0x0000002020120000) << 25; + let b5 = (block & 0x0000000442000000) << 14; + let b6 = (block & 0x0000000001800000) << 37; + let b7 = (block & 0x0000000004000000) << 24; + let b8 = (block & 0x0000020280015000).wrapping_mul(0x0000020080800083) & 0x02000a6400000000; + let b9 = (block.rotate_left(29) & 0x01001400000000aa).wrapping_mul(0x0000210210008081) + & 0x0902c01200000000; + let b10 = (block & 0x0000000910040000).wrapping_mul(0x0000000c04000020) & 0x8410010000000000; + b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | b10 +} + +/// Generate the 16 subkeys +pub(crate) fn gen_keys(key: u64) -> [u64; 16] { + let mut keys: [u64; 16] = [0; 16]; + let key = pc1(key); + + // The most significant bit is bit zero, and there are only 56 bits in + // the key after applying PC1, so we need to remove the eight least + // significant bits from the key. + let key = key >> 8; + + let mut c = key >> 28; + let mut d = key & 0x0FFFFFFF; + for i in 0..16 { + c = rotate(c, SHIFTS[i]); + d = rotate(d, SHIFTS[i]); + + // We need the `<< 8` because the most significant bit is bit zero, + // so we need to shift our 56 bit value 8 bits to the left. + keys[i] = pc2(((c << 28) | d) << 8); + } + + keys +} + +/// Performs a left rotate on a 28 bit number +fn rotate(mut val: u64, shift: u8) -> u64 { + let top_bits = val >> (28 - shift); + val <<= shift; + + (val | top_bits) & 0x0FFFFFFF +} + +pub(crate) fn round(input: u64, key: u64) -> u64 { + let l = input & (0xFFFF_FFFF << 32); + let r = input << 32; + + r | ((f(r, key) ^ l) >> 32) +} + +fn f(input: u64, key: u64) -> u64 { + let mut val = e(input); + val ^= key; + val = apply_sboxes(val); + p(val) +} + +/// Applies all eight sboxes to the input +fn apply_sboxes(input: u64) -> u64 { + let mut output: u64 = 0; + + for (i, sbox) in SBOXES.iter().enumerate() { + let val = (input >> (58 - (i * 6))) & 0x3F; + output |= u64::from(sbox[val as usize]) << (60 - (i * 4)); + } + + output +} diff --git a/gift/Cargo.toml b/gift/Cargo.toml index 1cebbd80..ddc5c927 100644 --- a/gift/Cargo.toml +++ b/gift/Cargo.toml @@ -13,13 +13,15 @@ keywords = ["crypto", "gift", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } +hex-literal = "0.4" [features] zeroize = ["cipher/zeroize"] [package.metadata.docs.rs] +all-features = true rustdoc-args = ["--cfg", "docsrs"] diff --git a/gift/LICENSE-MIT b/gift/LICENSE-MIT index f8eccd8c..394b496c 100644 --- a/gift/LICENSE-MIT +++ b/gift/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2021-2024 The RustCrypto Project Developers Copyright (c) 2021 Shun Sakai Permission is hereby granted, free of charge, to any diff --git a/gift/src/key_schedule.rs b/gift/src/key_schedule.rs index 58801b49..e0445a57 100644 --- a/gift/src/key_schedule.rs +++ b/gift/src/key_schedule.rs @@ -1,7 +1,6 @@ -use crate::primitives::{ror, swapmovesingle}; +use crate::primitives::{ror, swapmovesingle, u32big}; -#[inline] -pub(crate) fn rearrange_rkey_0(x: &u32) -> u32 { +fn rearrange_rkey_0(x: &u32) -> u32 { let mut tmp = *x; swapmovesingle(&mut tmp, 0x00550055, 9); swapmovesingle(&mut tmp, 0x000f000f, 12); @@ -10,8 +9,7 @@ pub(crate) fn rearrange_rkey_0(x: &u32) -> u32 { tmp } -#[inline] -pub(crate) fn rearrange_rkey_1(x: &u32) -> u32 { +fn rearrange_rkey_1(x: &u32) -> u32 { let mut tmp = *x; swapmovesingle(&mut tmp, 0x11111111, 3); swapmovesingle(&mut tmp, 0x03030303, 6); @@ -20,8 +18,7 @@ pub(crate) fn rearrange_rkey_1(x: &u32) -> u32 { tmp } -#[inline] -pub(crate) fn rearrange_rkey_2(x: &u32) -> u32 { +fn rearrange_rkey_2(x: &u32) -> u32 { let mut tmp = *x; swapmovesingle(&mut tmp, 0x0000aaaa, 15); swapmovesingle(&mut tmp, 0x00003333, 18); @@ -30,8 +27,7 @@ pub(crate) fn rearrange_rkey_2(x: &u32) -> u32 { tmp } -#[inline] -pub(crate) fn rearrange_rkey_3(x: &u32) -> u32 { +fn rearrange_rkey_3(x: &u32) -> u32 { let mut tmp = *x; swapmovesingle(&mut tmp, 0x0a0a0a0a, 3); swapmovesingle(&mut tmp, 0x00cc00cc, 6); @@ -40,55 +36,47 @@ pub(crate) fn rearrange_rkey_3(x: &u32) -> u32 { tmp } -#[inline] -pub(crate) fn key_update(x: &u32) -> u32 { +fn key_update(x: &u32) -> u32 { (((*x) >> 12) & 0x0000000f) | (((*x) & 0x00000fff) << 4) | (((*x) >> 2) & 0x3fff0000) | (((*x) & 0x00030000) << 14) } -#[inline] -pub(crate) fn key_triple_update_0(x: &u32) -> u32 { +fn key_triple_update_0(x: &u32) -> u32 { ror(&(*x & 0x33333333), &24) | ror(&(*x & 0xcccccccc), &16) } -#[inline] -pub(crate) fn key_double_update_1(x: &u32) -> u32 { +fn key_double_update_1(x: &u32) -> u32 { (((x) >> 4) & 0x0f000f00) | (((x) & 0x0f000f00) << 4) | (((x) >> 6) & 0x00030003) | (((x) & 0x003f003f) << 2) } -#[inline] -pub(crate) fn key_triple_update_1(x: &u32) -> u32 { +fn key_triple_update_1(x: &u32) -> u32 { (((x) >> 6) & 0x03000300) | (((x) & 0x3f003f00) << 2) | (((x) >> 5) & 0x00070007) | (((x) & 0x001f001f) << 3) } -#[inline] -pub(crate) fn key_double_update_2(x: &u32) -> u32 { +fn key_double_update_2(x: &u32) -> u32 { ror(&(*x & 0xaaaaaaaa), &24) | ror(&(*x & 0x55555555), &16) } -#[inline] -pub(crate) fn key_triple_update_2(x: &u32) -> u32 { +fn key_triple_update_2(x: &u32) -> u32 { ror(&(*x & 0x55555555), &24) | ror(&(*x & 0xaaaaaaaa), &20) } -#[inline] -pub(crate) fn key_double_update_3(x: &u32) -> u32 { +fn key_double_update_3(x: &u32) -> u32 { (((x) >> 2) & 0x03030303) | (((x) & 0x03030303) << 2) | (((x) >> 1) & 0x70707070) | (((x) & 0x10101010) << 3) } -#[inline] -pub(crate) fn key_triple_update_3(x: &u32) -> u32 { +fn key_triple_update_3(x: &u32) -> u32 { (((x) >> 18) & 0x00003030) | (((x) & 0x01010101) << 3) | (((x) >> 14) & 0x0000c0c0) @@ -97,18 +85,58 @@ pub(crate) fn key_triple_update_3(x: &u32) -> u32 { | (((x) & 0x00001010) << 19) } -#[inline] -pub(crate) fn key_double_update_4(x: &u32) -> u32 { +fn key_double_update_4(x: &u32) -> u32 { (((x) >> 4) & 0x0fff0000) | (((x) & 0x000f0000) << 12) | (((x) >> 8) & 0x000000ff) | (((x) & 0x000000ff) << 8) } -#[inline] -pub(crate) fn key_triple_update_4(x: &u32) -> u32 { +fn key_triple_update_4(x: &u32) -> u32 { (((x) >> 6) & 0x03ff0000) | (((x) & 0x003f0000) << 10) | (((x) >> 4) & 0x00000fff) | (((x) & 0x0000000f) << 12) } + +pub fn precompute_rkeys(key: &[u8; 16]) -> [u32; 80] { + let mut rkey = [0u32; 80]; + rkey[0] = u32big(&(key[12..16])); + rkey[1] = u32big(&(key[4..8])); + rkey[2] = u32big(&(key[8..12])); + rkey[3] = u32big(&(key[0..4])); + + for i in (0..16).step_by(2) { + rkey[i + 4] = rkey[i + 1]; + rkey[i + 5] = key_update(&rkey[i]); + } + + for i in (0..20).step_by(10) { + rkey[i] = rearrange_rkey_0(&rkey[i]); + rkey[i + 1] = rearrange_rkey_0(&rkey[i + 1]); + rkey[i + 2] = rearrange_rkey_1(&rkey[i + 2]); + rkey[i + 3] = rearrange_rkey_1(&rkey[i + 3]); + rkey[i + 4] = rearrange_rkey_2(&rkey[i + 4]); + rkey[i + 5] = rearrange_rkey_2(&rkey[i + 5]); + rkey[i + 6] = rearrange_rkey_3(&rkey[i + 6]); + rkey[i + 7] = rearrange_rkey_3(&rkey[i + 7]); + } + + for i in (20..80).step_by(10) { + rkey[i] = rkey[i - 19]; + rkey[i + 1] = key_triple_update_0(&rkey[i - 20]); + rkey[i + 2] = key_double_update_1(&rkey[i - 17]); + rkey[i + 3] = key_triple_update_1(&rkey[i - 18]); + rkey[i + 4] = key_double_update_2(&rkey[i - 15]); + rkey[i + 5] = key_triple_update_2(&rkey[i - 16]); + rkey[i + 6] = key_double_update_3(&rkey[i - 13]); + rkey[i + 7] = key_triple_update_3(&rkey[i - 14]); + rkey[i + 8] = key_double_update_4(&rkey[i - 11]); + rkey[i + 9] = key_triple_update_4(&rkey[i - 12]); + swapmovesingle(&mut rkey[i], 0x00003333, 16); + swapmovesingle(&mut rkey[i], 0x55554444, 1); + swapmovesingle(&mut rkey[i + 1], 0x55551100, 1); + } + + rkey +} diff --git a/gift/src/lib.rs b/gift/src/lib.rs index 872ef2dc..cf9ffb62 100644 --- a/gift/src/lib.rs +++ b/gift/src/lib.rs @@ -1,4 +1,4 @@ -//! Pure Rust implementation of the [Gift][1] block cipher. +//! Pure Rust implementation of the [Gift] block cipher. //! //! # ⚠️ Security Warning: Hazmat! //! @@ -10,8 +10,7 @@ //! //! # Examples //! ``` -//! use gift_cipher::cipher::array::Array; -//! use gift_cipher::cipher::{BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; +//! use gift_cipher::cipher::{Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; //! use gift_cipher::Gift128; //! //! let key = Array::from([0u8; 16]); @@ -31,19 +30,23 @@ //! assert_eq!(block, block_copy); //! ``` //! -//! [1]: https://eprint.iacr.org/2017/622.pdf +//! [Gift]: https://eprint.iacr.org/2017/622.pdf #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", - html_root_url = "https://docs.rs/gift-cipher/0.0.1" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] -use cipher::{consts::U16, BlockCipher, Key, KeyInit, KeySizeUser}; +use cipher::{ + consts::{U1, U16}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key, + KeyInit, KeySizeUser, ParBlocksSizeUser, +}; use core::fmt; #[cfg(feature = "zeroize")] @@ -56,125 +59,95 @@ mod key_schedule; mod primitives; use consts::GIFT_RC; -use key_schedule::{ - key_double_update_1, key_double_update_2, key_double_update_3, key_double_update_4, - key_triple_update_0, key_triple_update_1, key_triple_update_2, key_triple_update_3, - key_triple_update_4, key_update, rearrange_rkey_0, rearrange_rkey_1, rearrange_rkey_2, - rearrange_rkey_3, -}; -use primitives::{ - inv_quintuple_round, packing, quintuple_round, swapmovesingle, u32big, unpacking, -}; +use primitives::{inv_quintuple_round, packing, quintuple_round, unpacking}; -impl Gift128 { - #[inline] - fn precompute_rkeys(key: &[u8]) -> Self { - let mut rkey = [0u32; 80]; - rkey[0] = u32big(&(key[12..16])); - rkey[1] = u32big(&(key[4..8])); - rkey[2] = u32big(&(key[8..12])); - rkey[3] = u32big(&(key[0..4])); - - for i in (0..16).step_by(2) { - rkey[i + 4] = rkey[i + 1]; - rkey[i + 5] = key_update(&rkey[i]); - } +/// Gift-128 block cipher instance. +#[derive(Clone)] +pub struct Gift128 { + k: [u32; 80], +} - for i in (0..20).step_by(10) { - rkey[i] = rearrange_rkey_0(&rkey[i]); - rkey[i + 1] = rearrange_rkey_0(&rkey[i + 1]); - rkey[i + 2] = rearrange_rkey_1(&rkey[i + 2]); - rkey[i + 3] = rearrange_rkey_1(&rkey[i + 3]); - rkey[i + 4] = rearrange_rkey_2(&rkey[i + 4]); - rkey[i + 5] = rearrange_rkey_2(&rkey[i + 5]); - rkey[i + 6] = rearrange_rkey_3(&rkey[i + 6]); - rkey[i + 7] = rearrange_rkey_3(&rkey[i + 7]); - } +impl KeySizeUser for Gift128 { + type KeySize = U16; +} - for i in (20..80).step_by(10) { - rkey[i] = rkey[i - 19]; - rkey[i + 1] = key_triple_update_0(&rkey[i - 20]); - rkey[i + 2] = key_double_update_1(&rkey[i - 17]); - rkey[i + 3] = key_triple_update_1(&rkey[i - 18]); - rkey[i + 4] = key_double_update_2(&rkey[i - 15]); - rkey[i + 5] = key_triple_update_2(&rkey[i - 16]); - rkey[i + 6] = key_double_update_3(&rkey[i - 13]); - rkey[i + 7] = key_triple_update_3(&rkey[i - 14]); - rkey[i + 8] = key_double_update_4(&rkey[i - 11]); - rkey[i + 9] = key_triple_update_4(&rkey[i - 12]); - swapmovesingle(&mut rkey[i], 0x00003333, 16); - swapmovesingle(&mut rkey[i], 0x55554444, 1); - swapmovesingle(&mut rkey[i + 1], 0x55551100, 1); +impl KeyInit for Gift128 { + fn new(key: &Key) -> Self { + Self { + k: key_schedule::precompute_rkeys(key.into()), } - - Self { k: rkey } } } -impl KeyInit for Gift128 { - fn new(key: &Key) -> Self { - Self::precompute_rkeys(key[0..16].try_into().unwrap()) +impl BlockSizeUser for Gift128 { + type BlockSize = U16; +} + +impl ParBlocksSizeUser for Gift128 { + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for Gift128 { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) } } -macro_rules! impl_gift { - ($name:ident, $subkey_size:literal, $key_size:ty, $doc:literal) => { - #[doc = $doc] - #[derive(Clone)] - pub struct $name { - /// Subkeys - k: [u32; $subkey_size], +impl BlockCipherEncBackend for Gift128 { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let b = block.get_in(); + let mut state = [0u32; 4]; + packing(&mut state, b.into()); + for i in (0..40).step_by(5) { + quintuple_round(&mut state, &self.k[i * 2..], &GIFT_RC[i..]); } + unpacking(&state, block.get_out().into()); + } +} - impl BlockCipher for $name {} +impl BlockCipherDecrypt for Gift128 { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} - impl KeySizeUser for $name { - type KeySize = $key_size; +impl BlockCipherDecBackend for Gift128 { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let b = block.get_in(); + let mut state = [0u32; 4]; + packing(&mut state, b.into()); + let mut i: usize = 35; + while i > 0 { + inv_quintuple_round(&mut state, &self.k[i * 2..], &GIFT_RC[i..]); + i -= 5; } + inv_quintuple_round(&mut state, &self.k[i * 2..], &GIFT_RC[i..]); + unpacking(&state, block.get_out().into()); + } +} - impl fmt::Debug for $name { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(concat!(stringify!($name), " { ... }")) - } - } +impl AlgorithmName for Gift128 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Gift128") + } +} - #[cfg(feature = "zeroize")] - #[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] - impl Drop for $name { - fn drop(&mut self) { - self.k.zeroize(); - } - } +impl fmt::Debug for Gift128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Gift128 { ... }") + } +} +impl Drop for Gift128 { + fn drop(&mut self) { #[cfg(feature = "zeroize")] - #[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] - impl ZeroizeOnDrop for $name {} - - cipher::impl_simple_block_encdec!( - $name, U16, cipher, block, - encrypt: { - let b = block.get_in(); - let mut state = [0u32; 4]; - packing(&mut state, b); - for i in (0..40).step_by(5) { - quintuple_round(&mut state, &cipher.k[i*2..], &GIFT_RC[i..]); - } - unpacking(&state, block.get_out()); - } - decrypt: { - let b = block.get_in(); - let mut state = [0u32; 4]; - packing(&mut state, b); - let mut i: usize = 35; - while i > 0 { - inv_quintuple_round(&mut state, &cipher.k[i*2..], &GIFT_RC[i..]); - i -= 5; - } - inv_quintuple_round(&mut state, &cipher.k[i*2..], &GIFT_RC[i..]); - unpacking(&state, block.get_out()); - } - ); - }; + self.k.zeroize(); + } } -impl_gift!(Gift128, 80, U16, "Gift-128 block cipher instance."); +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Gift128 {} diff --git a/gift/src/primitives.rs b/gift/src/primitives.rs index 1bb90d91..525f3854 100644 --- a/gift/src/primitives.rs +++ b/gift/src/primitives.rs @@ -90,7 +90,7 @@ pub(crate) fn inv_sbox(s0: &mut u32, s1: &mut u32, s2: &mut u32, s3: &mut u32) { } #[inline] -pub(crate) fn packing(state: &mut [u32], input: &[u8]) { +pub(crate) fn packing(state: &mut [u32], input: &[u8; 16]) { let mut s0 = ((input[6] as u32) << 24) | ((input[7] as u32) << 16) | ((input[14] as u32) << 8) @@ -128,7 +128,7 @@ pub(crate) fn packing(state: &mut [u32], input: &[u8]) { } #[inline] -pub(crate) fn unpacking(state: &[u32], output: &mut [u8]) { +pub(crate) fn unpacking(state: &[u32], output: &mut [u8; 16]) { let (mut s0, mut s1, mut s2, mut s3) = (state[0], state[1], state[2], state[3]); swapmove(&mut s2, &mut s3, 0x0f000f00, 4); diff --git a/gift/tests/mod.rs b/gift/tests/mod.rs new file mode 100644 index 00000000..087da0d4 --- /dev/null +++ b/gift/tests/mod.rs @@ -0,0 +1,35 @@ +use cipher::{array::Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; +use gift_cipher::Gift128; +use hex_literal::hex; + +const KEYS: [[u8; 16]; 3] = [ + hex!("00000000000000000000000000000000"), + hex!("fedcba9876543210fedcba9876543210"), + hex!("d0f5c59a7700d3e799028fa9f90ad837"), +]; + +const PTEXT: [[u8; 16]; 3] = [ + hex!("00000000000000000000000000000000"), + hex!("fedcba9876543210fedcba9876543210"), + hex!("e39c141fa57dba43f08a85b6a91f86c1"), +]; + +const CTEXT: [[u8; 16]; 3] = [ + hex!("cd0bd738388ad3f668b15a36ceb6ff92"), + hex!("8422241a6dbf5a9346af468409ee0152"), + hex!("13ede67cbdcc3dbf400a62d6977265ea"), +]; + +#[test] +fn test_vectors() { + for i in 0..3 { + let cipher = Gift128::new(&KEYS[i].into()); + let mut buf = Array::from(PTEXT[i]); + + cipher.encrypt_block(&mut buf); + assert_eq!(buf, CTEXT[i]); + + cipher.decrypt_block(&mut buf); + assert_eq!(buf, PTEXT[i]); + } +} diff --git a/gift/tests/test.rs b/gift/tests/test.rs deleted file mode 100644 index 22cb3df4..00000000 --- a/gift/tests/test.rs +++ /dev/null @@ -1,67 +0,0 @@ -use cipher::{array::Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; -use gift_cipher::Gift128; - -const KEYS: [[u8; 16]; 3] = [ - [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1st key - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - [ - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, // 2nd key - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - ], - [ - 0xd0, 0xf5, 0xc5, 0x9a, 0x77, 0x00, 0xd3, 0xe7, // 3rd key - 0x99, 0x02, 0x8f, 0xa9, 0xf9, 0x0a, 0xd8, 0x37, - ], -]; - -const PTEXT: [[u8; 16]; 3] = [ - [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1st key - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - [ - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, // 2nd plaintext - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - ], - [ - 0xe3, 0x9c, 0x14, 0x1f, 0xa5, 0x7d, 0xba, 0x43, // 3rd plaintext - 0xf0, 0x8a, 0x85, 0xb6, 0xa9, 0x1f, 0x86, 0xc1, - ], -]; - -const CTEXT: [[u8; 16]; 3] = [ - [ - 0xcd, 0x0b, 0xd7, 0x38, 0x38, 0x8a, 0xd3, 0xf6, // 1st ciphertext - 0x68, 0xb1, 0x5a, 0x36, 0xce, 0xb6, 0xff, 0x92, - ], - [ - 0x84, 0x22, 0x24, 0x1a, 0x6d, 0xbf, 0x5a, 0x93, // 2nd ciphertext - 0x46, 0xaf, 0x46, 0x84, 0x09, 0xee, 0x01, 0x52, - ], - [ - 0x13, 0xed, 0xe6, 0x7c, 0xbd, 0xcc, 0x3d, 0xbf, // 3rd ciphertext - 0x40, 0x0a, 0x62, 0xd6, 0x97, 0x72, 0x65, 0xea, - ], -]; - -#[test] -fn test_vectors() { - for i in 0..3 { - let cipher = Gift128::new(&KEYS[i].into()); - let mut pt = Array::from(PTEXT[i]); - - cipher.encrypt_block(&mut pt); - - //println!("Ciphertext: {:#02x}", pt.as_slice()); - - assert_eq!(pt, Array::from(CTEXT[i])); - - cipher.decrypt_block(&mut pt); - - //println!("Plaintext: {:#02x}", pt.as_slice()); - - assert_eq!(pt, Array::from(PTEXT[i])); - } -} diff --git a/idea/Cargo.toml b/idea/Cargo.toml index a05af49a..9b955228 100644 --- a/idea/Cargo.toml +++ b/idea/Cargo.toml @@ -13,10 +13,10 @@ keywords = ["crypto", "idea", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } [features] zeroize = ["cipher/zeroize"] diff --git a/idea/LICENSE-MIT b/idea/LICENSE-MIT index 069bb21e..3b0382bf 100644 --- a/idea/LICENSE-MIT +++ b/idea/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2017-2024 The RustCrypto Project Developers Copyright (c) 2017 Damian Czaja Permission is hereby granted, free of charge, to any diff --git a/idea/src/lib.rs b/idea/src/lib.rs index 2878f2a4..aac7d999 100644 --- a/idea/src/lib.rs +++ b/idea/src/lib.rs @@ -16,16 +16,17 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] #![allow(clippy::many_single_char_names)] pub use cipher; use cipher::{ - consts::{U16, U8}, - inout::InOut, - AlgorithmName, Block, BlockCipher, Key, KeyInit, KeySizeUser, + consts::{U1, U16, U8}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key, + KeyInit, KeySizeUser, ParBlocksSizeUser, }; use core::fmt; @@ -183,8 +184,6 @@ impl Idea { } } -impl BlockCipher for Idea {} - impl KeySizeUser for Idea { type KeySize = U16; } @@ -201,6 +200,42 @@ impl KeyInit for Idea { } } +impl BlockSizeUser for Idea { + type BlockSize = U8; +} + +impl ParBlocksSizeUser for Idea { + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for Idea { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherEncBackend for Idea { + #[inline] + fn encrypt_block(&self, block: InOut<'_, '_, Block>) { + self.crypt(block, &self.enc_keys); + } +} + +impl BlockCipherDecrypt for Idea { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Idea { + #[inline] + fn decrypt_block(&self, block: InOut<'_, '_, Block>) { + self.crypt(block, &self.dec_keys); + } +} + impl fmt::Debug for Idea { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("Idea { ... }") @@ -213,25 +248,15 @@ impl AlgorithmName for Idea { } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl Drop for Idea { fn drop(&mut self) { - self.enc_keys.zeroize(); - self.dec_keys.zeroize(); + #[cfg(feature = "zeroize")] + { + self.enc_keys.zeroize(); + self.dec_keys.zeroize(); + } } } #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl ZeroizeOnDrop for Idea {} - -cipher::impl_simple_block_encdec!( - Idea, U8, cipher, block, - encrypt: { - cipher.crypt(block, &cipher.enc_keys); - } - decrypt: { - cipher.crypt(block, &cipher.dec_keys); - } -); diff --git a/kuznyechik/Cargo.toml b/kuznyechik/Cargo.toml index 11cbaacc..17c2fbe6 100644 --- a/kuznyechik/Cargo.toml +++ b/kuznyechik/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kuznyechik" -version = "0.9.0-pre.1" +version = "0.9.0-pre.2" description = "Kuznyechik (GOST R 34.12-2015) block cipher" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -13,11 +13,11 @@ keywords = ["crypto", "kuznyechik", "gost", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" cfg-if = "1" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" [features] diff --git a/kuznyechik/LICENSE-MIT b/kuznyechik/LICENSE-MIT index 8dcb85b3..44bf0bde 100644 --- a/kuznyechik/LICENSE-MIT +++ b/kuznyechik/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2017-2024 The RustCrypto Project Developers Copyright (c) 2017 Artyom Pavlov Permission is hereby granted, free of charge, to any diff --git a/kuznyechik/src/big_soft/backends.rs b/kuznyechik/src/big_soft/backends.rs index 2611123b..d4d8a46c 100644 --- a/kuznyechik/src/big_soft/backends.rs +++ b/kuznyechik/src/big_soft/backends.rs @@ -4,7 +4,8 @@ use crate::{ Block, Key, }; use cipher::{ - array::Array, consts, inout::InOut, BlockBackend, BlockSizeUser, ParBlocks, ParBlocksSizeUser, + consts, Array, BlockCipherDecBackend, BlockCipherEncBackend, BlockSizeUser, InOut, ParBlocks, + ParBlocksSizeUser, }; pub(super) type RoundKeys = [u128; 10]; @@ -100,9 +101,9 @@ impl<'a> ParBlocksSizeUser for EncBackend<'a> { type ParBlocksSize = ParBlocksSize; } -impl<'a> BlockBackend for EncBackend<'a> { +impl<'a> BlockCipherEncBackend for EncBackend<'a> { #[inline] - fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) { + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { let k = self.0; let mut b: u128 = u128::from_le_bytes(block.get_in().0); @@ -117,7 +118,7 @@ impl<'a> BlockBackend for EncBackend<'a> { } #[inline] - fn proc_par_blocks(&mut self, mut blocks: InOut<'_, '_, ParBlocks>) { + fn encrypt_par_blocks(&self, mut blocks: InOut<'_, '_, ParBlocks>) { let k = self.0; let mut bs = blocks.get_in().0.map(|b| u128::from_le_bytes(b.0)); @@ -147,9 +148,9 @@ impl<'a> ParBlocksSizeUser for DecBackend<'a> { type ParBlocksSize = consts::U1; } -impl<'a> BlockBackend for DecBackend<'a> { +impl<'a> BlockCipherDecBackend for DecBackend<'a> { #[inline] - fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) { + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { let k = self.0; let mut b: u128 = u128::from_le_bytes(block.get_in().0); diff --git a/kuznyechik/src/big_soft/mod.rs b/kuznyechik/src/big_soft/mod.rs index b96f7f5d..51f45036 100644 --- a/kuznyechik/src/big_soft/mod.rs +++ b/kuznyechik/src/big_soft/mod.rs @@ -1,5 +1,7 @@ use crate::{BlockSize, Key}; -use cipher::{BlockCipherDecrypt, BlockCipherEncrypt, BlockClosure}; +use cipher::{ + BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure, BlockCipherEncrypt, +}; mod backends; #[path = "../fused_tables/consts.rs"] @@ -39,25 +41,25 @@ impl From for DecKeys { } impl BlockCipherEncrypt for crate::Kuznyechik { - fn encrypt_with_backend(&self, f: impl BlockClosure) { + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { f.call(&mut EncBackend(&self.keys.enc)); } } impl BlockCipherDecrypt for crate::Kuznyechik { - fn decrypt_with_backend(&self, f: impl BlockClosure) { + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { f.call(&mut DecBackend(&self.keys.dec)); } } impl BlockCipherEncrypt for crate::KuznyechikEnc { - fn encrypt_with_backend(&self, f: impl BlockClosure) { + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { f.call(&mut EncBackend(&self.keys.0)); } } impl BlockCipherDecrypt for crate::KuznyechikDec { - fn decrypt_with_backend(&self, f: impl BlockClosure) { + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { f.call(&mut DecBackend(&self.keys.0)); } } diff --git a/kuznyechik/src/compact_soft/backends.rs b/kuznyechik/src/compact_soft/backends.rs index 076f4963..4f97499d 100644 --- a/kuznyechik/src/compact_soft/backends.rs +++ b/kuznyechik/src/compact_soft/backends.rs @@ -2,9 +2,7 @@ use super::consts::GF; use crate::consts::{P, P_INV}; use crate::{Block, Key}; use cipher::{ - consts::{U1, U16}, - inout::InOut, - BlockBackend, BlockSizeUser, ParBlocks, ParBlocksSizeUser, + consts, BlockCipherDecBackend, BlockCipherEncBackend, BlockSizeUser, InOut, ParBlocksSizeUser, }; pub(super) type RoundKeys = [Block; 10]; @@ -115,16 +113,16 @@ pub(super) fn expand(key: &Key) -> RoundKeys { pub(crate) struct EncBackend<'a>(pub(crate) &'a RoundKeys); impl<'a> BlockSizeUser for EncBackend<'a> { - type BlockSize = U16; + type BlockSize = consts::U16; } impl<'a> ParBlocksSizeUser for EncBackend<'a> { - type ParBlocksSize = U1; + type ParBlocksSize = consts::U1; } -impl<'a> BlockBackend for EncBackend<'a> { +impl<'a> BlockCipherEncBackend for EncBackend<'a> { #[inline] - fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) { + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { let mut b = *block.get_in(); for i in 0..9 { lsx(&mut b, &self.0[i]); @@ -132,26 +130,21 @@ impl<'a> BlockBackend for EncBackend<'a> { x(&mut b, &self.0[9]); *block.get_out() = b; } - - #[inline(always)] - fn proc_par_blocks(&mut self, mut blocks: InOut<'_, '_, ParBlocks>) { - self.proc_block(blocks.get(0)); - } } pub(crate) struct DecBackend<'a>(pub(crate) &'a RoundKeys); impl<'a> BlockSizeUser for DecBackend<'a> { - type BlockSize = U16; + type BlockSize = consts::U16; } impl<'a> ParBlocksSizeUser for DecBackend<'a> { - type ParBlocksSize = U1; + type ParBlocksSize = consts::U1; } -impl<'a> BlockBackend for DecBackend<'a> { +impl<'a> BlockCipherDecBackend for DecBackend<'a> { #[inline] - fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) { + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { let mut b = *block.get_in(); for i in 0..9 { lsx_inv(&mut b, &self.0[9 - i]); @@ -159,9 +152,4 @@ impl<'a> BlockBackend for DecBackend<'a> { x(&mut b, &self.0[0]); *block.get_out() = b; } - - #[inline(always)] - fn proc_par_blocks(&mut self, mut blocks: InOut<'_, '_, ParBlocks>) { - self.proc_block(blocks.get(0)); - } } diff --git a/kuznyechik/src/compact_soft/mod.rs b/kuznyechik/src/compact_soft/mod.rs index e68c1b78..0561c265 100644 --- a/kuznyechik/src/compact_soft/mod.rs +++ b/kuznyechik/src/compact_soft/mod.rs @@ -1,5 +1,7 @@ use crate::{BlockSize, Key}; -use cipher::{BlockCipherDecrypt, BlockCipherEncrypt, BlockClosure}; +use cipher::{ + BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure, BlockCipherEncrypt, +}; mod backends; mod consts; @@ -32,25 +34,25 @@ impl EncKeys { } impl BlockCipherEncrypt for crate::Kuznyechik { - fn encrypt_with_backend(&self, f: impl BlockClosure) { + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { f.call(&mut EncBackend(&self.keys.0)); } } impl BlockCipherDecrypt for crate::Kuznyechik { - fn decrypt_with_backend(&self, f: impl BlockClosure) { + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { f.call(&mut DecBackend(&self.keys.0)); } } impl BlockCipherEncrypt for crate::KuznyechikEnc { - fn encrypt_with_backend(&self, f: impl BlockClosure) { + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { f.call(&mut EncBackend(&self.keys.0)); } } impl BlockCipherDecrypt for crate::KuznyechikDec { - fn decrypt_with_backend(&self, f: impl BlockClosure) { + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { f.call(&mut DecBackend(&self.keys.0)); } } diff --git a/kuznyechik/src/lib.rs b/kuznyechik/src/lib.rs index b1b1b941..7b9b7fe2 100644 --- a/kuznyechik/src/lib.rs +++ b/kuznyechik/src/lib.rs @@ -34,12 +34,12 @@ pub use cipher; use cipher::{ array::Array, consts::{U16, U32}, - AlgorithmName, BlockCipher, BlockSizeUser, KeyInit, KeySizeUser, + AlgorithmName, BlockSizeUser, KeyInit, KeySizeUser, }; use core::fmt; #[cfg(feature = "zeroize")] -use cipher::zeroize::ZeroizeOnDrop; +use cipher::zeroize::{zeroize_flat_type, ZeroizeOnDrop}; mod consts; @@ -83,8 +83,6 @@ pub struct Kuznyechik { keys: EncDecKeys, } -impl BlockCipher for Kuznyechik {} - impl KeySizeUser for Kuznyechik { type KeySize = KeySize; } @@ -147,8 +145,6 @@ pub struct KuznyechikEnc { keys: EncKeys, } -impl BlockCipher for KuznyechikEnc {} - impl KeySizeUser for KuznyechikEnc { type KeySize = KeySize; } @@ -194,8 +190,6 @@ pub struct KuznyechikDec { keys: DecKeys, } -impl BlockCipher for KuznyechikDec {} - impl KeySizeUser for KuznyechikDec { type KeySize = KeySize; } @@ -244,7 +238,7 @@ impl Drop for KuznyechikDec { fn drop(&mut self) { #[cfg(feature = "zeroize")] unsafe { - cipher::zeroize::zeroize_flat_type(self) + zeroize_flat_type(self) } } } diff --git a/kuznyechik/src/neon/backends.rs b/kuznyechik/src/neon/backends.rs index 9c437352..30fd2c0f 100644 --- a/kuznyechik/src/neon/backends.rs +++ b/kuznyechik/src/neon/backends.rs @@ -4,17 +4,15 @@ use crate::{ Block, Key, }; use cipher::{ - consts::{U16, U8}, - inout::InOut, - typenum::Unsigned, - BlockBackend, BlockSizeUser, ParBlocks, ParBlocksSizeUser, + consts, typenum::Unsigned, BlockCipherDecBackend, BlockCipherEncBackend, BlockSizeUser, InOut, + ParBlocks, ParBlocksSizeUser, }; use core::arch::aarch64::*; pub(super) type RoundKeys = [uint8x16_t; 10]; -type ParBlocksSize = U8; +type ParBlocksSize = consts::U8; #[rustfmt::skip] macro_rules! unroll_par { @@ -189,16 +187,16 @@ pub fn inv_enc_keys(enc_keys: &RoundKeys) -> RoundKeys { pub(crate) struct EncBackend<'a>(pub(crate) &'a RoundKeys); impl<'a> BlockSizeUser for EncBackend<'a> { - type BlockSize = U16; + type BlockSize = consts::U16; } impl<'a> ParBlocksSizeUser for EncBackend<'a> { type ParBlocksSize = ParBlocksSize; } -impl<'a> BlockBackend for EncBackend<'a> { +impl<'a> BlockCipherEncBackend for EncBackend<'a> { #[inline] - fn proc_block(&mut self, block: InOut<'_, '_, Block>) { + fn encrypt_block(&self, block: InOut<'_, '_, Block>) { let k = self.0; unsafe { let (in_ptr, out_ptr) = block.into_raw(); @@ -214,7 +212,7 @@ impl<'a> BlockBackend for EncBackend<'a> { } #[inline] - fn proc_par_blocks(&mut self, blocks: InOut<'_, '_, ParBlocks>) { + fn encrypt_par_blocks(&self, blocks: InOut<'_, '_, ParBlocks>) { let k = self.0; unsafe { let (in_ptr, out_ptr) = blocks.into_raw(); @@ -248,16 +246,16 @@ impl<'a> BlockBackend for EncBackend<'a> { pub(crate) struct DecBackend<'a>(pub(crate) &'a RoundKeys); impl<'a> BlockSizeUser for DecBackend<'a> { - type BlockSize = U16; + type BlockSize = consts::U16; } impl<'a> ParBlocksSizeUser for DecBackend<'a> { type ParBlocksSize = ParBlocksSize; } -impl<'a> BlockBackend for DecBackend<'a> { +impl<'a> BlockCipherDecBackend for DecBackend<'a> { #[inline] - fn proc_block(&mut self, block: InOut<'_, '_, Block>) { + fn decrypt_block(&self, block: InOut<'_, '_, Block>) { let k = self.0; unsafe { let (in_ptr, out_ptr) = block.into_raw(); @@ -279,7 +277,7 @@ impl<'a> BlockBackend for DecBackend<'a> { } } #[inline] - fn proc_par_blocks(&mut self, blocks: InOut<'_, '_, ParBlocks>) { + fn decrypt_par_blocks(&self, blocks: InOut<'_, '_, ParBlocks>) { let k = self.0; unsafe { let (in_ptr, out_ptr) = blocks.into_raw(); diff --git a/kuznyechik/src/neon/mod.rs b/kuznyechik/src/neon/mod.rs index b96f7f5d..0742ad82 100644 --- a/kuznyechik/src/neon/mod.rs +++ b/kuznyechik/src/neon/mod.rs @@ -1,5 +1,7 @@ use crate::{BlockSize, Key}; -use cipher::{BlockCipherDecrypt, BlockCipherEncrypt, BlockClosure}; +use cipher::{ + BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure, BlockCipherEncrypt, +}; mod backends; #[path = "../fused_tables/consts.rs"] @@ -39,25 +41,25 @@ impl From for DecKeys { } impl BlockCipherEncrypt for crate::Kuznyechik { - fn encrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut EncBackend(&self.keys.enc)); + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(&EncBackend(&self.keys.enc)); } } impl BlockCipherDecrypt for crate::Kuznyechik { - fn decrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut DecBackend(&self.keys.dec)); + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(&DecBackend(&self.keys.dec)); } } impl BlockCipherEncrypt for crate::KuznyechikEnc { - fn encrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut EncBackend(&self.keys.0)); + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(&EncBackend(&self.keys.0)); } } impl BlockCipherDecrypt for crate::KuznyechikDec { - fn decrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut DecBackend(&self.keys.0)); + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(&DecBackend(&self.keys.0)); } } diff --git a/kuznyechik/src/sse2/backends.rs b/kuznyechik/src/sse2/backends.rs index 091c3691..b9bc4840 100644 --- a/kuznyechik/src/sse2/backends.rs +++ b/kuznyechik/src/sse2/backends.rs @@ -7,7 +7,7 @@ use cipher::{ consts::{U16, U4}, inout::InOut, typenum::Unsigned, - BlockBackend, BlockSizeUser, ParBlocks, ParBlocksSizeUser, + BlockCipherDecBackend, BlockCipherEncBackend, BlockSizeUser, ParBlocks, ParBlocksSizeUser, }; #[cfg(target_arch = "x86")] @@ -173,9 +173,9 @@ impl<'a> ParBlocksSizeUser for EncBackend<'a> { type ParBlocksSize = ParBlocksSize; } -impl<'a> BlockBackend for EncBackend<'a> { +impl<'a> BlockCipherEncBackend for EncBackend<'a> { #[inline] - fn proc_block(&mut self, block: InOut<'_, '_, Block>) { + fn encrypt_block(&self, block: InOut<'_, '_, Block>) { let k = self.0; unsafe { let (in_ptr, out_ptr) = block.into_raw(); @@ -191,7 +191,7 @@ impl<'a> BlockBackend for EncBackend<'a> { } #[inline] - fn proc_par_blocks(&mut self, blocks: InOut<'_, '_, ParBlocks>) { + fn encrypt_par_blocks(&self, blocks: InOut<'_, '_, ParBlocks>) { let k = self.0; unsafe { let (in_ptr, out_ptr) = blocks.into_raw(); @@ -232,9 +232,9 @@ impl<'a> ParBlocksSizeUser for DecBackend<'a> { type ParBlocksSize = ParBlocksSize; } -impl<'a> BlockBackend for DecBackend<'a> { +impl<'a> BlockCipherDecBackend for DecBackend<'a> { #[inline] - fn proc_block(&mut self, block: InOut<'_, '_, Block>) { + fn decrypt_block(&self, block: InOut<'_, '_, Block>) { let k = self.0; unsafe { let (in_ptr, out_ptr) = block.into_raw(); @@ -257,7 +257,7 @@ impl<'a> BlockBackend for DecBackend<'a> { } #[inline] - fn proc_par_blocks(&mut self, blocks: InOut<'_, '_, ParBlocks>) { + fn decrypt_par_blocks(&self, blocks: InOut<'_, '_, ParBlocks>) { let k = self.0; unsafe { let (in_ptr, out_ptr) = blocks.into_raw(); diff --git a/kuznyechik/src/sse2/mod.rs b/kuznyechik/src/sse2/mod.rs index 26f27004..61fc0c45 100644 --- a/kuznyechik/src/sse2/mod.rs +++ b/kuznyechik/src/sse2/mod.rs @@ -1,7 +1,9 @@ //! SSE2-based implementation based on use crate::{BlockSize, Key}; -use cipher::{BlockCipherDecrypt, BlockCipherEncrypt, BlockClosure}; +use cipher::{ + BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure, BlockCipherEncrypt, +}; mod backends; #[path = "../fused_tables/consts.rs"] @@ -41,25 +43,25 @@ impl From for DecKeys { } impl BlockCipherEncrypt for crate::Kuznyechik { - fn encrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut EncBackend(&self.keys.enc)); + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(&EncBackend(&self.keys.enc)); } } impl BlockCipherDecrypt for crate::Kuznyechik { - fn decrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut DecBackend(&self.keys.dec)); + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(&DecBackend(&self.keys.dec)); } } impl BlockCipherEncrypt for crate::KuznyechikEnc { - fn encrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut EncBackend(&self.keys.0)); + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(&EncBackend(&self.keys.0)); } } impl BlockCipherDecrypt for crate::KuznyechikDec { - fn decrypt_with_backend(&self, f: impl BlockClosure) { - f.call(&mut DecBackend(&self.keys.0)); + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(&DecBackend(&self.keys.0)); } } diff --git a/magma/Cargo.toml b/magma/Cargo.toml index b63d4e0e..cac7c2ff 100644 --- a/magma/Cargo.toml +++ b/magma/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "magma" -version = "0.10.0-pre.1" +version = "0.10.0-pre.2" description = "Magma (GOST R 34.12-2015) block cipher" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -13,10 +13,10 @@ keywords = ["crypto", "magma", "gost", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" [features] diff --git a/magma/LICENSE-MIT b/magma/LICENSE-MIT index 8dcb85b3..44bf0bde 100644 --- a/magma/LICENSE-MIT +++ b/magma/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2017-2024 The RustCrypto Project Developers Copyright (c) 2017 Artyom Pavlov Permission is hereby granted, free of charge, to any diff --git a/magma/src/lib.rs b/magma/src/lib.rs index e0bccc1a..15a337ba 100644 --- a/magma/src/lib.rs +++ b/magma/src/lib.rs @@ -12,10 +12,7 @@ //! # Examples //! ``` //! use magma::Magma; -//! use magma::cipher::{ -//! array::Array, -//! BlockCipherEncrypt, BlockCipherDecrypt, KeyInit, -//! }; +//! use magma::cipher::{Array, BlockCipherEncrypt, BlockCipherDecrypt, KeyInit}; //! use hex_literal::hex; //! //! // Example vector from GOST 34.12-2018 @@ -44,14 +41,16 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] pub use cipher; use cipher::{ - consts::{U32, U8}, - AlgorithmName, BlockCipher, Key, KeyInit, KeySizeUser, + consts::{U1, U32, U8}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key, + KeyInit, KeySizeUser, ParBlocksSizeUser, }; use core::{fmt, marker::PhantomData}; @@ -70,13 +69,12 @@ pub struct Gost89 { _p: PhantomData, } -impl BlockCipher for Gost89 {} - impl KeySizeUser for Gost89 { type KeySize = U32; } impl KeyInit for Gost89 { + #[inline] fn new(key: &Key) -> Self { let mut key_u32 = [0u32; 8]; key.chunks_exact(4) @@ -89,6 +87,68 @@ impl KeyInit for Gost89 { } } +impl BlockSizeUser for Gost89 { + type BlockSize = U8; +} + +impl ParBlocksSizeUser for Gost89 { + type ParBlocksSize = U1; +} + +impl BlockCipherEncBackend for Gost89 { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let b = block.get_in(); + let mut v = (to_u32(&b[0..4]), to_u32(&b[4..8])); + for _ in 0..3 { + for i in 0..8 { + v = (v.1, v.0 ^ S::g(v.1, self.key[i])); + } + } + for i in (0..8).rev() { + v = (v.1, v.0 ^ S::g(v.1, self.key[i])); + } + let block = block.get_out(); + block[0..4].copy_from_slice(&v.1.to_be_bytes()); + block[4..8].copy_from_slice(&v.0.to_be_bytes()); + } +} + +impl BlockCipherEncrypt for Gost89 { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Gost89 { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let b = block.get_in(); + let mut v = (to_u32(&b[0..4]), to_u32(&b[4..8])); + + for i in 0..8 { + v = (v.1, v.0 ^ S::g(v.1, self.key[i])); + } + + for _ in 0..3 { + for i in (0..8).rev() { + v = (v.1, v.0 ^ S::g(v.1, self.key[i])); + } + } + let block = block.get_out(); + block[0..4].copy_from_slice(&v.1.to_be_bytes()); + block[4..8].copy_from_slice(&v.0.to_be_bytes()); + } +} + +impl BlockCipherDecrypt for Gost89 { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + impl Clone for Gost89 { fn clone(&self) -> Self { Self { @@ -113,63 +173,25 @@ impl fmt::Debug for Gost89 { impl AlgorithmName for Gost89 { fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { if S::NAME == "Tc26" { - f.write_str("Magma { ... }") + f.write_str("Magma") } else { f.write_str("Gost89<")?; f.write_str(S::NAME)?; - f.write_str("> { ... }") + f.write_str(">") } } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl Drop for Gost89 { fn drop(&mut self) { + #[cfg(feature = "zeroize")] self.key.zeroize(); } } #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl ZeroizeOnDrop for Gost89 {} -cipher::impl_simple_block_encdec!( - Gost89, U8, cipher, block, - encrypt: { - let b = block.get_in(); - let mut v = (to_u32(&b[0..4]), to_u32(&b[4..8])); - for _ in 0..3 { - for i in 0..8 { - v = (v.1, v.0 ^ S::g(v.1, cipher.key[i])); - } - } - for i in (0..8).rev() { - v = (v.1, v.0 ^ S::g(v.1, cipher.key[i])); - } - let block = block.get_out(); - block[0..4].copy_from_slice(&v.1.to_be_bytes()); - block[4..8].copy_from_slice(&v.0.to_be_bytes()); - } - decrypt: { - let b = block.get_in(); - let mut v = (to_u32(&b[0..4]), to_u32(&b[4..8])); - - for i in 0..8 { - v = (v.1, v.0 ^ S::g(v.1, cipher.key[i])); - } - - for _ in 0..3 { - for i in (0..8).rev() { - v = (v.1, v.0 ^ S::g(v.1, cipher.key[i])); - } - } - let block = block.get_out(); - block[0..4].copy_from_slice(&v.1.to_be_bytes()); - block[4..8].copy_from_slice(&v.0.to_be_bytes()); - } -); - /// 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 diff --git a/rc2/Cargo.toml b/rc2/Cargo.toml index c126af72..ba494f7c 100644 --- a/rc2/Cargo.toml +++ b/rc2/Cargo.toml @@ -13,10 +13,10 @@ keywords = ["crypto", "rc2", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } [features] zeroize = ["cipher/zeroize"] diff --git a/rc2/LICENSE-MIT b/rc2/LICENSE-MIT index 069bb21e..3b0382bf 100644 --- a/rc2/LICENSE-MIT +++ b/rc2/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2017-2024 The RustCrypto Project Developers Copyright (c) 2017 Damian Czaja Permission is hereby granted, free of charge, to any diff --git a/rc2/src/lib.rs b/rc2/src/lib.rs index e41884d9..01bd2c93 100644 --- a/rc2/src/lib.rs +++ b/rc2/src/lib.rs @@ -16,14 +16,16 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] pub use cipher; use cipher::{ - consts::{U32, U8}, - AlgorithmName, BlockCipher, InvalidLength, Key, KeyInit, KeySizeUser, + consts::{U1, U32, U8}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, + InvalidLength, Key, KeyInit, KeySizeUser, ParBlocksSizeUser, }; use core::fmt; @@ -152,8 +154,6 @@ impl Rc2 { } } -impl BlockCipher for Rc2 {} - impl KeySizeUser for Rc2 { type KeySize = U32; } @@ -172,33 +172,24 @@ impl KeyInit for Rc2 { } } -impl fmt::Debug for Rc2 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Rc2 { ... }") - } +impl BlockSizeUser for Rc2 { + type BlockSize = U8; } -impl AlgorithmName for Rc2 { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Rc2") - } +impl ParBlocksSizeUser for Rc2 { + type ParBlocksSize = U1; } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl Drop for Rc2 { - fn drop(&mut self) { - self.keys.zeroize(); +impl BlockCipherEncrypt for Rc2 { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl ZeroizeOnDrop for Rc2 {} - -cipher::impl_simple_block_encdec!( - Rc2, U8, cipher, block, - encrypt: { +impl BlockCipherEncBackend for Rc2 { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { let b = block.get_in(); let mut b = [ u16::from_le_bytes(b[0..2].try_into().unwrap()), @@ -210,9 +201,9 @@ cipher::impl_simple_block_encdec!( let mut j = 0; for i in 0..16 { - cipher.mix(&mut b, &mut j); + self.mix(&mut b, &mut j); if i == 4 || i == 10 { - cipher.mash(&mut b); + self.mash(&mut b); } } @@ -222,7 +213,18 @@ cipher::impl_simple_block_encdec!( block[4..6].copy_from_slice(&b[2].to_le_bytes()); block[6..8].copy_from_slice(&b[3].to_le_bytes()); } - decrypt: { +} + +impl BlockCipherDecrypt for Rc2 { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Rc2 { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { let b = block.get_in(); let mut b = [ u16::from_le_bytes(b[0..2].try_into().unwrap()), @@ -234,9 +236,9 @@ cipher::impl_simple_block_encdec!( let mut j = 63; for i in 0..16 { - cipher.reverse_mix(&mut b, &mut j); + self.reverse_mix(&mut b, &mut j); if i == 4 || i == 10 { - cipher.reverse_mash(&mut b); + self.reverse_mash(&mut b); } } @@ -246,4 +248,26 @@ cipher::impl_simple_block_encdec!( block[4..6].copy_from_slice(&b[2].to_le_bytes()); block[6..8].copy_from_slice(&b[3].to_le_bytes()); } -); +} + +impl fmt::Debug for Rc2 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Rc2 { ... }") + } +} + +impl AlgorithmName for Rc2 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Rc2") + } +} + +impl Drop for Rc2 { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + self.keys.zeroize(); + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Rc2 {} diff --git a/rc5/Cargo.toml b/rc5/Cargo.toml index bb863b89..f63160b0 100644 --- a/rc5/Cargo.toml +++ b/rc5/Cargo.toml @@ -12,10 +12,15 @@ keywords = ["crypto", "rc5", "block-cipher"] categories = ["cryptography"] [dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["zeroize"] } +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } +hex-literal = "0.4" [features] -zeroize = [] +zeroize = ["cipher/zeroize"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/rc5/LICENSE-MIT b/rc5/LICENSE-MIT index 8dd9c4e4..4ba0c921 100644 --- a/rc5/LICENSE-MIT +++ b/rc5/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2022-2024 The RustCrypto Project Developers Copyright (c) 2022 Antonio Dropulic Permission is hereby granted, free of charge, to any diff --git a/rc5/src/block_cipher.rs b/rc5/src/block_cipher.rs deleted file mode 100644 index 56c6b88a..00000000 --- a/rc5/src/block_cipher.rs +++ /dev/null @@ -1,361 +0,0 @@ -use core::ops::{Add, Div, Mul, Sub}; - -use cipher::{ - array::ArraySize, - consts::*, - crypto_common::BlockSizes, - inout::InOut, - typenum::{Diff, IsLess, Le, NonZero, Sum, Unsigned, U1, U2, U256}, - AlgorithmName, Block, BlockBackend, BlockCipher, BlockCipherDecrypt, BlockCipherEncrypt, - BlockSizeUser, KeyInit, KeySizeUser, ParBlocksSizeUser, -}; - -use crate::core::{BlockSize, ExpandedKeyTableSize, KeyAsWordsSize, Word, RC5}; - -impl KeyInit for RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, - // Key range - B: ArraySize, - B: IsLess, - Le: NonZero, - // KeyAsWordsSize - B: Add, - Sum: Sub, - Diff, U1>: Div, - KeyAsWordsSize: ArraySize, -{ - fn new(key: &cipher::Key) -> Self { - Self::new(key) - } -} - -impl KeySizeUser for RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, - B: ArraySize, -{ - type KeySize = B; -} - -impl BlockCipher for RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ -} - -impl BlockSizeUser for RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - type BlockSize = BlockSize; -} - -impl BlockCipherEncrypt for RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, - // Key range - B: ArraySize, - B: IsLess, - Le: NonZero, - // KeyAsWordsSize - B: Add, - Sum: Sub, - Diff, U1>: Div, - KeyAsWordsSize: ArraySize, -{ - fn encrypt_with_backend(&self, f: impl cipher::BlockClosure) { - f.call(&mut RC5EncryptBackend { enc_dec: self }) - } -} - -struct RC5EncryptBackend<'a, W, R, B> -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - enc_dec: &'a RC5, -} -impl<'a, W, R, B> BlockSizeUser for RC5EncryptBackend<'a, W, R, B> -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - type BlockSize = BlockSize; -} - -impl<'a, W, R, B> ParBlocksSizeUser for RC5EncryptBackend<'a, W, R, B> -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - type ParBlocksSize = U1; -} - -impl<'a, W, R, B> BlockBackend for RC5EncryptBackend<'a, W, R, B> -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, - // Key range - B: ArraySize, - B: IsLess, - Le: NonZero, - // KeyAsWordsSize - B: Add, - Sum: Sub, - Diff, U1>: Div, - KeyAsWordsSize: ArraySize, -{ - #[inline(always)] - fn proc_block(&mut self, block: InOut<'_, '_, Block>) { - let backend = self.enc_dec; - backend.encrypt(block) - } -} - -impl BlockCipherDecrypt for RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, - // Key range - B: ArraySize, - B: IsLess, - Le: NonZero, - // KeyAsWordsSize - B: Add, - Sum: Sub, - Diff, U1>: Div, - KeyAsWordsSize: ArraySize, -{ - fn decrypt_with_backend(&self, f: impl cipher::BlockClosure) { - f.call(&mut RC5DecryptBackend { enc_dec: self }) - } -} - -struct RC5DecryptBackend<'a, W, R, B> -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - enc_dec: &'a RC5, -} -impl<'a, W, R, B> BlockSizeUser for RC5DecryptBackend<'a, W, R, B> -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - type BlockSize = BlockSize; -} - -impl<'a, W, R, B> ParBlocksSizeUser for RC5DecryptBackend<'a, W, R, B> -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - type ParBlocksSize = U1; -} - -impl<'a, W, R, B> BlockBackend for RC5DecryptBackend<'a, W, R, B> -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, - // Key range - B: ArraySize, - B: IsLess, - Le: NonZero, - // KeyAsWordsSize - B: Add, - Sum: Sub, - Diff, U1>: Div, - KeyAsWordsSize: ArraySize, -{ - #[inline(always)] - fn proc_block(&mut self, block: InOut<'_, '_, Block>) { - let backend = self.enc_dec; - backend.decrypt(block) - } -} - -impl AlgorithmName for RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!( - f, - "RC5 - {}/{}/{}", - core::any::type_name::(), - ::to_u8(), - ::to_u8(), - ) - } -} - -#[allow(dead_code)] -#[deprecated(since = "0.1.0", note = "use RC5 instead.")] -pub type RC5_16_16_8 = RC5; -#[allow(dead_code)] -#[deprecated(since = "0.1.0", note = "use RC5 instead.")] -pub type RC5_32_12_16 = RC5; -#[allow(dead_code)] -#[deprecated(since = "0.1.0", note = "use RC5 instead.")] -pub type RC5_32_16_16 = RC5; -#[allow(dead_code)] -#[deprecated(since = "0.1.0", note = "use RC5 instead.")] -pub type RC5_64_24_24 = RC5; diff --git a/rc5/src/core/backend.rs b/rc5/src/core/backend.rs deleted file mode 100644 index 86130226..00000000 --- a/rc5/src/core/backend.rs +++ /dev/null @@ -1,229 +0,0 @@ -use core::{ - cmp::max, - marker::PhantomData, - ops::{Add, Div, Mul, Sub}, -}; - -use cipher::{ - array::{Array, ArraySize}, - crypto_common::BlockSizes, - inout::InOut, - typenum::{Diff, IsLess, Le, NonZero, Sum, U1, U2}, - typenum::{Unsigned, U256}, -}; - -use super::{ - Block, BlockSize, ExpandedKeyTable, ExpandedKeyTableSize, Key, KeyAsWords, KeyAsWordsSize, Word, -}; - -pub struct RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - key_table: ExpandedKeyTable, - _key_size: PhantomData, -} - -impl RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, - // Key range - B: ArraySize, - B: IsLess, - Le: NonZero, - // KeyAsWordsSize - B: Add, - Sum: Sub, - Diff, U1>: Div, - KeyAsWordsSize: ArraySize, -{ - pub fn new(key: &Key) -> RC5 { - Self { - key_table: Self::substitute_key(key), - _key_size: PhantomData, - } - } - - fn substitute_key(key: &Key) -> ExpandedKeyTable { - let key_as_words = Self::key_into_words(key); - let expanded_key_table = Self::initialize_expanded_key_table(); - - Self::mix_in(expanded_key_table, key_as_words) - } - - fn key_into_words(key: &Key) -> KeyAsWords { - // can be uninitialized - let mut key_as_words: Array> = Array::default(); - - for i in (0..B::USIZE).rev() { - key_as_words[i / W::Bytes::USIZE] = - key_as_words[i / W::Bytes::USIZE].rotate_left(W::EIGHT) + key[i].into(); - // no need for wrapping addition since we are adding a byte sized uint onto an uint with its lsb byte zeroed - } - - key_as_words - } - - fn initialize_expanded_key_table() -> ExpandedKeyTable { - // must be zero initialized - let mut expanded_key_table: Array> = Array::from_fn(|_| W::ZERO); - - expanded_key_table[0] = W::P; - for i in 1..expanded_key_table.len() { - expanded_key_table[i] = expanded_key_table[i - 1].wrapping_add(W::Q); - } - - expanded_key_table - } - - fn mix_in( - mut key_table: ExpandedKeyTable, - mut key_as_words: KeyAsWords, - ) -> ExpandedKeyTable { - let (mut expanded_key_index, mut key_as_words_index) = (0, 0); - let (mut a, mut b) = (W::ZERO, W::ZERO); - - for _ in 0..3 * max(key_as_words.len(), key_table.len()) { - key_table[expanded_key_index] = key_table[expanded_key_index] - .wrapping_add(a) - .wrapping_add(b) - .rotate_left(W::THREE); - - a = key_table[expanded_key_index]; - - key_as_words[key_as_words_index] = key_as_words[key_as_words_index] - .wrapping_add(a) - .wrapping_add(b) - .rotate_left(a.wrapping_add(b)); - - b = key_as_words[key_as_words_index]; - - expanded_key_index = (expanded_key_index + 1) % key_table.len(); - key_as_words_index = (key_as_words_index + 1) % key_as_words.len(); - } - - key_table - } -} - -impl RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - pub fn encrypt(&self, mut block: InOut<'_, '_, Block>) { - let (mut a, mut b) = Self::words_from_block(block.get_in()); - let key = &self.key_table; - - a = a.wrapping_add(key[0]); - b = b.wrapping_add(key[1]); - - for i in 1..=R::USIZE { - a = a.bitxor(b).rotate_left(b).wrapping_add(key[2 * i]); - b = b.bitxor(a).rotate_left(a).wrapping_add(key[2 * i + 1]); - } - - Self::block_from_words(a, b, block.get_out()) - } - - pub fn decrypt(&self, mut block: InOut<'_, '_, Block>) { - let (mut a, mut b) = Self::words_from_block(block.get_in()); - let key = &self.key_table; - - for i in (1..=R::USIZE).rev() { - b = b.wrapping_sub(key[2 * i + 1]).rotate_right(a).bitxor(a); - a = a.wrapping_sub(key[2 * i]).rotate_right(b).bitxor(b); - } - - b = b.wrapping_sub(key[1]); - a = a.wrapping_sub(key[0]); - - Self::block_from_words(a, b, block.get_out()) - } - - fn words_from_block(block: &Block) -> (W, W) { - // Block size is 2 * word::BYTES so the unwrap is safe - let a = W::from_le_bytes(block[..W::Bytes::USIZE].try_into().unwrap()); - let b = W::from_le_bytes(block[W::Bytes::USIZE..].try_into().unwrap()); - - (a, b) - } - - fn block_from_words(a: W, b: W, out_block: &mut Block) { - let (left, right) = out_block.split_at_mut(W::Bytes::USIZE); - - left.copy_from_slice(&a.to_le_bytes()); - right.copy_from_slice(&b.to_le_bytes()); - } -} - -#[cfg(feature = "zeroize")] -impl cipher::zeroize::ZeroizeOnDrop for RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ -} - -#[cfg(feature = "zeroize")] -impl Drop for RC5 -where - W: Word, - // Block size - W::Bytes: Mul, - BlockSize: BlockSizes, - // Rounds range - R: Unsigned, - R: IsLess, - Le: NonZero, - // ExpandedKeyTableSize - R: Add, - Sum: Mul, - ExpandedKeyTableSize: ArraySize, -{ - fn drop(&mut self) { - cipher::zeroize::Zeroize::zeroize(&mut *self.key_table) - } -} diff --git a/rc5/src/core/mod.rs b/rc5/src/core/mod.rs deleted file mode 100644 index 770a1033..00000000 --- a/rc5/src/core/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! Implementation according to the [RC5 paper] -//! [RC5 paper]: https://www.grc.com/r&d/rc5.pdf - -mod backend; -mod primitives; - -pub use backend::RC5; -pub use primitives::*; diff --git a/rc5/src/lib.rs b/rc5/src/lib.rs index 6ddf5f99..1a84520f 100644 --- a/rc5/src/lib.rs +++ b/rc5/src/lib.rs @@ -1,7 +1,501 @@ +//! Pure Rust implementation of the [RC5] block cipher. +//! +//! # ⚠️ Security Warning: Hazmat! +//! +//! This crate implements only the low-level block cipher function, and is intended +//! for use for implementing higher-level constructions *only*. It is NOT +//! intended for direct use in applications. +//! +//! USE AT YOUR OWN RISK! +//! +//! [RC5]: https://en.wikipedia.org/wiki/RC5 #![no_std] +#![doc( + 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_auto_cfg))] +#![warn(missing_docs, rust_2018_idioms)] -mod block_cipher; -mod core; +use cipher::{ + array::ArraySize, + consts::{U1, U2, U256}, + crypto_common::BlockSizes, + inout::InOut, + typenum::{Diff, IsLess, Le, NonZero, Sum, Unsigned}, + AlgorithmName, Array, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, KeyInit, + KeySizeUser, ParBlocksSizeUser, +}; +use core::{ + cmp::max, + fmt, + marker::PhantomData, + ops::{Add, Div, Mul, Sub}, +}; -pub use crate::core::RC5; -pub use block_cipher::*; +#[cfg(feature = "zeroize")] +use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; + +mod primitives; + +use primitives::{ + Block, BlockSize, ExpandedKeyTable, ExpandedKeyTableSize, Key, KeyAsWords, KeyAsWordsSize, Word, +}; + +/// RC5 block cipher instance. +#[derive(Clone)] +pub struct RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, +{ + key_table: ExpandedKeyTable, + _key_size: PhantomData, +} + +impl RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, + // Key range + B: ArraySize, + B: IsLess, + Le: NonZero, + // KeyAsWordsSize + B: Add, + Sum: Sub, + Diff, U1>: Div, + KeyAsWordsSize: ArraySize, +{ + pub(crate) fn substitute_key(key: &Key) -> ExpandedKeyTable { + let key_as_words = Self::key_into_words(key); + let expanded_key_table = Self::initialize_expanded_key_table(); + + Self::mix_in(expanded_key_table, key_as_words) + } + + fn key_into_words(key: &Key) -> KeyAsWords { + // can be uninitialized + let mut key_as_words: Array> = Array::default(); + + for i in (0..B::USIZE).rev() { + key_as_words[i / W::Bytes::USIZE] = + key_as_words[i / W::Bytes::USIZE].rotate_left(W::EIGHT) + key[i].into(); + // no need for wrapping addition since we are adding a byte sized uint onto an uint with its lsb byte zeroed + } + + key_as_words + } + + fn initialize_expanded_key_table() -> ExpandedKeyTable { + // must be zero initialized + let mut expanded_key_table: Array> = Array::from_fn(|_| W::ZERO); + + expanded_key_table[0] = W::P; + for i in 1..expanded_key_table.len() { + expanded_key_table[i] = expanded_key_table[i - 1].wrapping_add(W::Q); + } + + expanded_key_table + } + + fn mix_in( + mut key_table: ExpandedKeyTable, + mut key_as_words: KeyAsWords, + ) -> ExpandedKeyTable { + let (mut expanded_key_index, mut key_as_words_index) = (0, 0); + let (mut a, mut b) = (W::ZERO, W::ZERO); + + for _ in 0..3 * max(key_as_words.len(), key_table.len()) { + key_table[expanded_key_index] = key_table[expanded_key_index] + .wrapping_add(a) + .wrapping_add(b) + .rotate_left(W::THREE); + + a = key_table[expanded_key_index]; + + key_as_words[key_as_words_index] = key_as_words[key_as_words_index] + .wrapping_add(a) + .wrapping_add(b) + .rotate_left(a.wrapping_add(b)); + + b = key_as_words[key_as_words_index]; + + expanded_key_index = (expanded_key_index + 1) % key_table.len(); + key_as_words_index = (key_as_words_index + 1) % key_as_words.len(); + } + + key_table + } +} + +impl RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, +{ + pub(crate) fn words_from_block(block: &Block) -> (W, W) { + // Block size is 2 * word::BYTES so the unwrap is safe + let a = W::from_le_bytes(block[..W::Bytes::USIZE].try_into().unwrap()); + let b = W::from_le_bytes(block[W::Bytes::USIZE..].try_into().unwrap()); + + (a, b) + } + + pub(crate) fn block_from_words(a: W, b: W, out_block: &mut Block) { + let (left, right) = out_block.split_at_mut(W::Bytes::USIZE); + + left.copy_from_slice(&a.to_le_bytes()); + right.copy_from_slice(&b.to_le_bytes()); + } +} + +impl KeyInit for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, + // Key range + B: ArraySize, + B: IsLess, + Le: NonZero, + // KeyAsWordsSize + B: Add, + Sum: Sub, + Diff, U1>: Div, + KeyAsWordsSize: ArraySize, +{ + fn new(key: &cipher::Key) -> Self { + Self { + key_table: Self::substitute_key(key), + _key_size: PhantomData, + } + } +} + +impl KeySizeUser for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, + B: ArraySize, +{ + type KeySize = B; +} + +impl BlockSizeUser for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, +{ + type BlockSize = BlockSize; +} + +impl ParBlocksSizeUser for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, +{ + type ParBlocksSize = U1; +} + +impl BlockCipherEncrypt for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, + // Key range + B: ArraySize, + B: IsLess, + Le: NonZero, + // KeyAsWordsSize + B: Add, + Sum: Sub, + Diff, U1>: Div, + KeyAsWordsSize: ArraySize, +{ + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) + } +} + +impl BlockCipherEncBackend for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, + // Key range + B: ArraySize, + B: IsLess, + Le: NonZero, + // KeyAsWordsSize + B: Add, + Sum: Sub, + Diff, U1>: Div, + KeyAsWordsSize: ArraySize, +{ + #[inline(always)] + fn encrypt_block(&self, mut block: InOut<'_, '_, cipher::Block>) { + let (mut a, mut b) = Self::words_from_block(block.get_in()); + let key = &self.key_table; + + a = a.wrapping_add(key[0]); + b = b.wrapping_add(key[1]); + + for i in 1..=R::USIZE { + a = a.bitxor(b).rotate_left(b).wrapping_add(key[2 * i]); + b = b.bitxor(a).rotate_left(a).wrapping_add(key[2 * i + 1]); + } + + Self::block_from_words(a, b, block.get_out()) + } +} + +impl BlockCipherDecrypt for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, + // Key range + B: ArraySize, + B: IsLess, + Le: NonZero, + // KeyAsWordsSize + B: Add, + Sum: Sub, + Diff, U1>: Div, + KeyAsWordsSize: ArraySize, +{ + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, + // Key range + B: ArraySize, + B: IsLess, + Le: NonZero, + // KeyAsWordsSize + B: Add, + Sum: Sub, + Diff, U1>: Div, + KeyAsWordsSize: ArraySize, +{ + #[inline(always)] + fn decrypt_block(&self, mut block: InOut<'_, '_, cipher::Block>) { + let (mut a, mut b) = Self::words_from_block(block.get_in()); + let key = &self.key_table; + + for i in (1..=R::USIZE).rev() { + b = b.wrapping_sub(key[2 * i + 1]).rotate_right(a).bitxor(a); + a = a.wrapping_sub(key[2 * i]).rotate_right(b).bitxor(b); + } + + b = b.wrapping_sub(key[1]); + a = a.wrapping_sub(key[0]); + + Self::block_from_words(a, b, block.get_out()) + } +} + +impl AlgorithmName for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, +{ + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "RC5 - {}/{}/{}", + core::any::type_name::(), + ::to_u8(), + ::to_u8(), + ) + } +} + +impl fmt::Debug for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "RC5 - {}/{}/{} {{ ... }}", + core::any::type_name::(), + ::to_u8(), + ::to_u8(), + ) + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, +{ +} + +impl Drop for RC5 +where + W: Word, + // Block size + W::Bytes: Mul, + BlockSize: BlockSizes, + // Rounds range + R: Unsigned, + R: IsLess, + Le: NonZero, + // ExpandedKeyTableSize + R: Add, + Sum: Mul, + ExpandedKeyTableSize: ArraySize, +{ + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + self.key_table.zeroize() + } +} diff --git a/rc5/src/core/primitives.rs b/rc5/src/primitives.rs similarity index 94% rename from rc5/src/core/primitives.rs rename to rc5/src/primitives.rs index f240d26e..bd09b0f2 100644 --- a/rc5/src/core/primitives.rs +++ b/rc5/src/primitives.rs @@ -1,9 +1,9 @@ -use core::ops::{Add, BitXor}; +use core::ops::{Add, BitXor, Mul}; use cipher::{ array::{Array, ArraySize}, + crypto_common::BlockSizes, typenum::{Diff, Prod, Quot, Sum, U1, U16, U2, U4, U8}, - zeroize::DefaultIsZeroes, }; pub type BlockSize = Prod<::Bytes, U2>; @@ -17,10 +17,12 @@ pub type ExpandedKeyTableSize = Prod, U2>; pub type KeyAsWords = Array>; pub type KeyAsWordsSize = Quot::Bytes>, U1>, ::Bytes>; -pub trait Word: - Default + Copy + From + Add + DefaultIsZeroes + Default + private::Sealed +pub trait Word +where + Self: Default + Copy + From + Add + Default + private::Sealed, + BlockSize: BlockSizes, { - type Bytes: ArraySize; + type Bytes: ArraySize + Mul; const ZERO: Self; const THREE: Self; @@ -42,7 +44,11 @@ pub trait Word: } mod private { + #[cfg(feature = "zeroize")] + pub trait Sealed: cipher::zeroize::DefaultIsZeroes {} + #[cfg(not(feature = "zeroize"))] pub trait Sealed {} + impl Sealed for u8 {} impl Sealed for u16 {} impl Sealed for u32 {} diff --git a/rc5/tests/mod.rs b/rc5/tests/mod.rs index f17416ed..a5bc0ca1 100644 --- a/rc5/tests/mod.rs +++ b/rc5/tests/mod.rs @@ -1,143 +1,107 @@ -/// generated using the code in: https://www.ietf.org/archive/id/draft-krovetz-rc6-rc5-vectors-00.txt -#[cfg(test)] -#[allow(deprecated)] // uses `clone_from_slice` -mod tests { - use cipher::consts::*; - use cipher::{array::Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; - use rc5::RC5; +//! Test vectors from: https://www.ietf.org/archive/id/draft-krovetz-rc6-rc5-vectors-00.txt +use cipher::consts::*; +use cipher::{Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; +use hex_literal::hex; +use rc5::RC5; - #[test] - fn enc_dec_8_12_4() { - let key = [0x00, 0x01, 0x02, 0x03]; +#[test] +fn rc5_8_12_4() { + let key = hex!("00010203"); + let pt = hex!("0001"); + let ct = hex!("212A"); - let pt = [0x00, 0x01]; - let ct = [0x21, 0x2A]; + let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); - let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); + let mut block = Array::from(pt); + rc5.encrypt_block(&mut block); - let mut block = Array::clone_from_slice(&pt); - rc5.encrypt_block(&mut block); + assert_eq!(ct, block[..]); - assert_eq!(ct, block[..]); - - rc5.decrypt_block(&mut block); - assert_eq!(pt, block[..]); - } - - #[test] - fn enc_dec_16_16_8() { - let key = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]; - - let pt = [0x00, 0x01, 0x02, 0x03]; - let ct = [0x23, 0xA8, 0xD7, 0x2E]; - - let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); - - let mut block = Array::clone_from_slice(&pt); - rc5.encrypt_block(&mut block); + rc5.decrypt_block(&mut block); + assert_eq!(pt, block[..]); +} - assert_eq!(ct, block[..]); +#[test] +fn rc5_16_16_8() { + let key = hex!("0001020304050607"); + let pt = hex!("00010203"); + let ct = hex!("23A8D72E"); - rc5.decrypt_block(&mut block); - assert_eq!(pt, block[..]); - } + let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); - #[test] - fn enc_dec_32_12_16() { - let key = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x0E, 0x0F, - ]; + let mut block = Array::from(pt); + rc5.encrypt_block(&mut block); - let pt = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]; - let ct = [0xC8, 0xD3, 0xB3, 0xC4, 0x86, 0x70, 0x0C, 0xFA]; + assert_eq!(ct, block[..]); - let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); + rc5.decrypt_block(&mut block); + assert_eq!(pt, block[..]); +} - let mut block = Array::clone_from_slice(&pt); - rc5.encrypt_block(&mut block); +#[test] +fn rc5_32_12_16() { + let key = hex!("000102030405060708090A0B0C0D0E0F"); + let pt = hex!("0001020304050607"); + let ct = hex!("C8D3B3C486700CFA"); - assert_eq!(ct, block[..]); + let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); - rc5.decrypt_block(&mut block); - assert_eq!(pt, block[..]); - } + let mut block = Array::from(pt); + rc5.encrypt_block(&mut block); - #[test] - fn enc_dec_32_16_16() { - let key = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x0E, 0x0F, - ]; + assert_eq!(ct, block[..]); - let pt = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]; - let ct = [0x3E, 0x2E, 0x95, 0x35, 0x70, 0x27, 0xD8, 0x96]; + rc5.decrypt_block(&mut block); + assert_eq!(pt, block[..]); +} - let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); +#[test] +fn rc5_32_16_16() { + let key = hex!("000102030405060708090A0B0C0D0E0F"); + let pt = hex!("0001020304050607"); + let ct = hex!("3E2E95357027D896"); - let mut block = Array::clone_from_slice(&pt); - rc5.encrypt_block(&mut block); + let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); - assert_eq!(ct, block[..]); + let mut block = Array::from(pt); + rc5.encrypt_block(&mut block); - rc5.decrypt_block(&mut block); - assert_eq!(pt, block[..]); - } + assert_eq!(ct, block[..]); - #[test] - fn enc_dec_64_24_24() { - let key = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - ]; + rc5.decrypt_block(&mut block); + assert_eq!(pt, block[..]); +} - let pt = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x0E, 0x0F, - ]; - let ct = [ - 0xA4, 0x67, 0x72, 0x82, 0x0E, 0xDB, 0xCE, 0x02, 0x35, 0xAB, 0xEA, 0x32, 0xAE, 0x71, - 0x78, 0xDA, - ]; +#[test] +fn rc5_64_24_24() { + let key = hex!("000102030405060708090A0B0C0D0E0F1011121314151617"); + let pt = hex!("000102030405060708090A0B0C0D0E0F"); + let ct = hex!("A46772820EDBCE0235ABEA32AE7178DA"); - let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); + let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); - let mut block = Array::clone_from_slice(&pt); - rc5.encrypt_block(&mut block); + let mut block = Array::from(pt); + rc5.encrypt_block(&mut block); - assert_eq!(ct, block[..]); + assert_eq!(ct, block[..]); - rc5.decrypt_block(&mut block); - assert_eq!(pt, block[..]); - } + rc5.decrypt_block(&mut block); + assert_eq!(pt, block[..]); +} - #[test] - fn enc_dec_128_28_32() { - let key = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1E, 0x1F, - ]; +#[test] +fn rc5_128_28_32() { + let key = hex!("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + let pt = hex!("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + let ct = hex!("ECA5910921A4F4CFDD7AD7AD20A1FCBA068EC7A7CD752D68FE914B7FE180B440"); - let pt = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1E, 0x1F, - ]; - let ct = [ - 0xEC, 0xA5, 0x91, 0x09, 0x21, 0xA4, 0xF4, 0xCF, 0xDD, 0x7A, 0xD7, 0xAD, 0x20, 0xA1, - 0xFC, 0xBA, 0x06, 0x8E, 0xC7, 0xA7, 0xCD, 0x75, 0x2D, 0x68, 0xFE, 0x91, 0x4B, 0x7F, - 0xE1, 0x80, 0xB4, 0x40, - ]; + let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); - let rc5 = as KeyInit>::new_from_slice(&key).unwrap(); + let mut block = Array::from(pt); + rc5.encrypt_block(&mut block); - let mut block = Array::clone_from_slice(&pt); - rc5.encrypt_block(&mut block); + assert_eq!(ct, block[..]); - assert_eq!(ct, block[..]); - - rc5.decrypt_block(&mut block); - assert_eq!(pt, block[..]); - } + rc5.decrypt_block(&mut block); + assert_eq!(pt, block[..]); } diff --git a/serpent/Cargo.toml b/serpent/Cargo.toml index 8536fa98..d51a6217 100644 --- a/serpent/Cargo.toml +++ b/serpent/Cargo.toml @@ -13,11 +13,10 @@ keywords = ["crypto", "serpent", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -byteorder = { version = "1.1", default-features = false } -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } [features] zeroize = ["cipher/zeroize"] diff --git a/serpent/LICENSE-MIT b/serpent/LICENSE-MIT index 6e0aa2fe..ba8a0d39 100644 --- a/serpent/LICENSE-MIT +++ b/serpent/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2019-2024 The RustCrypto Project Developers Copyright (c) 2019 Jonathan Serra Permission is hereby granted, free of charge, to any diff --git a/serpent/src/lib.rs b/serpent/src/lib.rs index e806f632..90f2ab21 100644 --- a/serpent/src/lib.rs +++ b/serpent/src/lib.rs @@ -16,15 +16,18 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] #![allow(clippy::needless_range_loop)] pub use cipher; -// TODO: remove dependency on byteorder -use byteorder::{ByteOrder, LE}; -use cipher::{consts::U16, AlgorithmName, BlockCipher, InvalidLength, KeyInit, KeySizeUser}; +use cipher::{ + consts::{U1, U16}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, + InvalidLength, KeyInit, KeySizeUser, ParBlocksSizeUser, +}; use core::fmt; #[cfg(feature = "zeroize")] @@ -33,25 +36,20 @@ use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; mod consts; use consts::{PHI, ROUNDS, S, S_INVERSE}; -type Key = [u8; 16]; -type Subkeys = [Key; ROUNDS + 1]; -type Block128 = [u8; 16]; -type Word = [u8; 16]; +type Words = [u32; 4]; +type RoundKeys = [Words; ROUNDS + 1]; /// Serpent block cipher. #[derive(Clone)] pub struct Serpent { - k: Subkeys, + round_keys: RoundKeys, } fn get_bit(x: usize, i: usize) -> u8 { (x >> i) as u8 & 0x01 } -fn linear_transform_bitslice(input: Block128, output: &mut Block128) { - let mut words = [0u32; 4]; - LE::read_u32_into(&input, &mut words); - +fn linear_transform_bitslice(mut words: Words) -> Words { words[0] = words[0].rotate_left(13); words[2] = words[2].rotate_left(3); words[1] ^= words[0] ^ words[2]; @@ -62,14 +60,10 @@ fn linear_transform_bitslice(input: Block128, output: &mut Block128) { words[2] = words[2] ^ words[3] ^ (words[1] << 7); words[0] = words[0].rotate_left(5); words[2] = words[2].rotate_left(22); - - LE::write_u32_into(&words, output); + words } -fn linear_transform_inverse_bitslice(input: Block128, output: &mut Block128) { - let mut words = [0u32; 4]; - LE::read_u32_into(&input, &mut words); - +fn linear_transform_inverse_bitslice(mut words: Words) -> Words { words[2] = words[2].rotate_right(22); words[0] = words[0].rotate_right(5); words[2] = words[2] ^ words[3] ^ (words[1] << 7); @@ -80,35 +74,7 @@ fn linear_transform_inverse_bitslice(input: Block128, output: &mut Block128) { words[1] ^= words[0] ^ words[2]; words[2] = words[2].rotate_right(3); words[0] = words[0].rotate_right(13); - - LE::write_u32_into(&words, output); -} - -fn round_bitslice(i: usize, b_i: Block128, k: Subkeys, b_output: &mut Block128) { - let xored_block = xor_block(b_i, k[i]); - - let s_i = apply_s_bitslice(i, xored_block); - - if i == ROUNDS - 1 { - *b_output = xor_block(s_i, k[ROUNDS]); - } else { - linear_transform_bitslice(s_i, b_output); - } -} - -#[allow(clippy::useless_let_if_seq)] -fn round_inverse_bitslice(i: usize, b_i_next: Block128, k: Subkeys, b_output: &mut Block128) { - let mut s_i = [0u8; 16]; - - if i == ROUNDS - 1 { - s_i = xor_block(b_i_next, k[ROUNDS]); - } else { - linear_transform_inverse_bitslice(b_i_next, &mut s_i); - } - - let xored = apply_s_inverse_bitslice(i, s_i); - - *b_output = xor_block(xored, k[i]); + words } fn apply_s(index: usize, nibble: u8) -> u8 { @@ -119,14 +85,7 @@ fn apply_s_inverse(index: usize, nibble: u8) -> u8 { S_INVERSE[index % 8][nibble as usize] } -fn apply_s_bitslice(index: usize, word: Word) -> Word { - let mut output = [0u8; 16]; - - let w1 = LE::read_u32(&word[0..4]); - let w2 = LE::read_u32(&word[4..8]); - let w3 = LE::read_u32(&word[8..12]); - let w4 = LE::read_u32(&word[12..16]); - +fn apply_s_bitslice(index: usize, [w1, w2, w3, w4]: Words) -> Words { let mut words = [0u32; 4]; for i in 0..32 { @@ -143,17 +102,10 @@ fn apply_s_bitslice(index: usize, word: Word) -> Word { } } - LE::write_u32_into(&words, &mut output); - - output + words } -fn apply_s_inverse_bitslice(index: usize, word: Word) -> Word { - let mut output = [0u8; 16]; - let w1 = LE::read_u32(&word[0..4]); - let w2 = LE::read_u32(&word[4..8]); - let w3 = LE::read_u32(&word[8..12]); - let w4 = LE::read_u32(&word[12..16]); +fn apply_s_inverse_bitslice(index: usize, [w1, w2, w3, w4]: Words) -> Words { let mut words = [0u32; 4]; for i in 0..32 { let quad = apply_s_inverse( @@ -167,33 +119,49 @@ fn apply_s_inverse_bitslice(index: usize, word: Word) -> Word { words[l] |= u32::from(get_bit(quad as usize, l)) << i; } } - LE::write_u32_into(&words, &mut output); - output + words } -fn xor_block(b1: Block128, k: Key) -> Block128 { - let mut xored: Block128 = [0u8; 16]; +#[inline(always)] +fn xor(b1: Words, k: Words) -> Words { + let mut res = [0u32; 4]; for (i, _) in b1.iter().enumerate() { - xored[i] = b1[i] ^ k[i]; + res[i] = b1[i] ^ k[i]; } - xored + res } -fn expand_key(source: &[u8], len_bits: usize, key: &mut [u8; 32]) { +fn expand_key(source: &[u8], len_bits: usize) -> [u8; 32] { + let mut key = [0u8; 32]; key[..source.len()].copy_from_slice(source); if len_bits < 256 { let byte_i = len_bits / 8; let bit_i = len_bits % 8; key[byte_i] |= 1 << bit_i; } + key +} + +impl KeySizeUser for Serpent { + type KeySize = U16; } -impl Serpent { - #[allow(clippy::many_single_char_names)] - fn key_schedule(key: [u8; 32]) -> Subkeys { +impl KeyInit for Serpent { + fn new(key: &cipher::Key) -> Self { + Self::new_from_slice(key).unwrap() + } + + fn new_from_slice(key: &[u8]) -> Result { + if key.len() < 16 || key.len() > 32 { + return Err(InvalidLength); + } + let key = expand_key(key, key.len() * 8); + let mut words = [0u32; 140]; - LE::read_u32_into(&key, &mut words[..8]); + for (src, dst) in key.chunks_exact(4).zip(words[..8].iter_mut()) { + *dst = u32::from_le_bytes(src.try_into().unwrap()); + } for i in 0..132 { let slot = i + 8; @@ -225,38 +193,72 @@ impl Serpent { } } - let mut sub_keys: Subkeys = [[0u8; 16]; ROUNDS + 1]; - for i in 0..r { - LE::write_u32(&mut sub_keys[i][..4], k[4 * i]); - LE::write_u32(&mut sub_keys[i][4..8], k[4 * i + 1]); - LE::write_u32(&mut sub_keys[i][8..12], k[4 * i + 2]); - LE::write_u32(&mut sub_keys[i][12..], k[4 * i + 3]); + let mut round_keys: RoundKeys = [[0; 4]; ROUNDS + 1]; + for (src, dst) in k.chunks_exact(4).zip(round_keys.iter_mut()) { + dst.copy_from_slice(src); } - sub_keys + Ok(Serpent { round_keys }) } } -impl BlockCipher for Serpent {} +impl BlockSizeUser for Serpent { + type BlockSize = U16; +} -impl KeySizeUser for Serpent { - type KeySize = U16; +impl ParBlocksSizeUser for Serpent { + type ParBlocksSize = U1; } -impl KeyInit for Serpent { - fn new(key: &cipher::Key) -> Self { - Self::new_from_slice(key).unwrap() +impl BlockCipherEncrypt for Serpent { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) } +} - fn new_from_slice(key: &[u8]) -> Result { - if key.len() < 16 || key.len() > 32 { - return Err(InvalidLength); +impl BlockCipherEncBackend for Serpent { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut b: [u32; 4] = read_words(block.get_in().into()); + + for i in 0..ROUNDS - 1 { + let xb = xor(b, self.round_keys[i]); + let s = apply_s_bitslice(i, xb); + b = linear_transform_bitslice(s); + } + + let xb = xor(b, self.round_keys[ROUNDS - 1]); + let s = apply_s_bitslice(ROUNDS - 1, xb); + b = xor(s, self.round_keys[ROUNDS]); + + write_words(&b, block.get_out().into()); + } +} + +impl BlockCipherDecrypt for Serpent { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Serpent { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + let mut b: [u32; 4] = read_words(block.get_in().into()); + + let s = xor(b, self.round_keys[ROUNDS]); + let xb = apply_s_inverse_bitslice(ROUNDS - 1, s); + b = xor(xb, self.round_keys[ROUNDS - 1]); + + for i in (0..ROUNDS - 1).rev() { + let s = linear_transform_inverse_bitslice(b); + let xb = apply_s_inverse_bitslice(i, s); + b = xor(xb, self.round_keys[i]); } - let mut k = [0u8; 32]; - expand_key(key, key.len() * 8, &mut k); - Ok(Serpent { - k: Serpent::key_schedule(k), - }) + + write_words(&b, block.get_out().into()); } } @@ -272,32 +274,26 @@ impl AlgorithmName for Serpent { } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl Drop for Serpent { fn drop(&mut self) { - self.k.zeroize(); + #[cfg(feature = "zeroize")] + self.round_keys.zeroize(); } } #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] impl ZeroizeOnDrop for Serpent {} -cipher::impl_simple_block_encdec!( - Serpent, U16, cipher, block, - encrypt: { - let mut b = block.clone_in().into(); - for i in 0..ROUNDS { - round_bitslice(i, b, cipher.k, &mut b); - } - *block.get_out() = b.into(); +fn read_words(src: &[u8; 16]) -> Words { + let mut res = [0; 4]; + for (src, dst) in src.chunks_exact(4).zip(res.iter_mut()) { + *dst = u32::from_le_bytes(src.try_into().unwrap()); } - decrypt: { - let mut b = block.clone_in().into(); - for i in (0..ROUNDS).rev() { - round_inverse_bitslice(i, b, cipher.k, &mut b); - } - *block.get_out() = b.into(); + res +} + +fn write_words(src: &Words, dst: &mut [u8; 16]) { + for (src, dst) in src.iter().zip(dst.chunks_exact_mut(4)) { + dst.copy_from_slice(&src.to_le_bytes()); } -); +} diff --git a/sm4/Cargo.toml b/sm4/Cargo.toml index 136ecc9e..f07cea32 100644 --- a/sm4/Cargo.toml +++ b/sm4/Cargo.toml @@ -13,10 +13,10 @@ keywords = ["crypto", "sm4", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" [features] diff --git a/sm4/LICENSE-MIT b/sm4/LICENSE-MIT index 66cf7556..05ad2e61 100644 --- a/sm4/LICENSE-MIT +++ b/sm4/LICENSE-MIT @@ -1,6 +1,4 @@ -Copyright (c) 2006-2009 Graydon Hoare -Copyright (c) 2009-2013 Mozilla Foundation -Copyright (c) 2016 Artyom Pavlov +Copyright (c) 2020-2024 The RustCrypto Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/sm4/src/lib.rs b/sm4/src/lib.rs index 2596cf27..c6cd2f8b 100644 --- a/sm4/src/lib.rs +++ b/sm4/src/lib.rs @@ -16,12 +16,17 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] pub use cipher; -use cipher::{consts::U16, AlgorithmName, BlockCipher, Key, KeyInit, KeySizeUser}; +use cipher::{ + consts::{U1, U16}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key, + KeyInit, KeySizeUser, ParBlocksSizeUser, +}; use core::fmt; #[cfg(feature = "zeroize")] @@ -67,8 +72,6 @@ pub struct Sm4 { rk: [u32; 32], } -impl BlockCipher for Sm4 {} - impl KeySizeUser for Sm4 { type KeySize = U16; } @@ -100,33 +103,24 @@ impl KeyInit for Sm4 { } } -impl fmt::Debug for Sm4 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Sm4 { ... }") - } +impl BlockSizeUser for Sm4 { + type BlockSize = U16; } -impl AlgorithmName for Sm4 { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Sm4") - } +impl ParBlocksSizeUser for Sm4 { + type ParBlocksSize = U1; } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl Drop for Sm4 { - fn drop(&mut self) { - self.rk.zeroize(); +impl BlockCipherEncrypt for Sm4 { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl ZeroizeOnDrop for Sm4 {} - -cipher::impl_simple_block_encdec!( - Sm4, U16, cipher, block, - encrypt: { +impl BlockCipherEncBackend for Sm4 { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { let b = block.get_in(); let mut x = [ u32::from_be_bytes(b[0..4].try_into().unwrap()), @@ -135,7 +129,7 @@ cipher::impl_simple_block_encdec!( u32::from_be_bytes(b[12..16].try_into().unwrap()), ]; - let rk = &cipher.rk; + let rk = &self.rk; for i in 0..8 { x[0] ^= t(x[1] ^ x[2] ^ x[3] ^ rk[i * 4]); x[1] ^= t(x[2] ^ x[3] ^ x[0] ^ rk[i * 4 + 1]); @@ -149,7 +143,18 @@ cipher::impl_simple_block_encdec!( block[8..12].copy_from_slice(&x[1].to_be_bytes()); block[12..16].copy_from_slice(&x[0].to_be_bytes()); } - decrypt: { +} + +impl BlockCipherDecrypt for Sm4 { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Sm4 { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { let b = block.get_in(); let mut x = [ u32::from_be_bytes(b[0..4].try_into().unwrap()), @@ -158,7 +163,7 @@ cipher::impl_simple_block_encdec!( u32::from_be_bytes(b[12..16].try_into().unwrap()), ]; - let rk = &cipher.rk; + let rk = &self.rk; for i in 0..8 { x[0] ^= t(x[1] ^ x[2] ^ x[3] ^ rk[31 - i * 4]); x[1] ^= t(x[2] ^ x[3] ^ x[0] ^ rk[31 - (i * 4 + 1)]); @@ -172,4 +177,26 @@ cipher::impl_simple_block_encdec!( block[8..12].copy_from_slice(&x[1].to_be_bytes()); block[12..16].copy_from_slice(&x[0].to_be_bytes()); } -); +} + +impl fmt::Debug for Sm4 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Sm4 { ... }") + } +} + +impl AlgorithmName for Sm4 { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Sm4") + } +} + +impl Drop for Sm4 { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + self.rk.zeroize(); + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Sm4 {} diff --git a/speck/Cargo.toml b/speck/Cargo.toml index 90229a6f..81a29ef6 100644 --- a/speck/Cargo.toml +++ b/speck/Cargo.toml @@ -13,8 +13,15 @@ keywords = ["crypto", "speck", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" + +[features] +zeroize = ["cipher/zeroize"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/speck/LICENSE-MIT b/speck/LICENSE-MIT index 66cf7556..3b73c41c 100644 --- a/speck/LICENSE-MIT +++ b/speck/LICENSE-MIT @@ -1,6 +1,4 @@ -Copyright (c) 2006-2009 Graydon Hoare -Copyright (c) 2009-2013 Mozilla Foundation -Copyright (c) 2016 Artyom Pavlov +Copyright (c) 2023-2024 The RustCrypto Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/speck/src/lib.rs b/speck/src/lib.rs index 7951fef0..b59e63a1 100644 --- a/speck/src/lib.rs +++ b/speck/src/lib.rs @@ -5,20 +5,23 @@ #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", - html_root_url = "https://docs.rs/speck/0.0.1" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] -#![forbid(unsafe_code)] +#![deny(unsafe_code)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] pub use cipher; use cipher::{ - consts::{U12, U16, U18, U24, U32, U4, U6, U8, U9}, - AlgorithmName, BlockCipher, Key, KeyInit, KeySizeUser, + consts::*, AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, + BlockCipherDecrypt, BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, + BlockSizeUser, InOut, Key, KeyInit, KeySizeUser, ParBlocksSizeUser, }; -use core::fmt; -use core::mem::size_of; +use core::{fmt, mem::size_of}; + +#[cfg(feature = "zeroize")] +use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; macro_rules! define_speck_impl { ( @@ -99,8 +102,6 @@ macro_rules! define_speck_impl { } } - impl BlockCipher for $name {} - impl KeySizeUser for $name { type KeySize = $key_size; } @@ -113,7 +114,7 @@ macro_rules! define_speck_impl { for i in 0..$m - 1 { l[i] = $name::from_be_bytes( - &key[($m - 2 - i) * ($n / 8)..($m - 1 - i) * ($n / 8)] + &key[($m - 2 - i) * ($n / 8)..($m - 1 - i) * ($n / 8)], ); } @@ -127,25 +128,32 @@ macro_rules! define_speck_impl { } } - impl fmt::Debug for $name { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(concat!(stringify!($name), " { .. }")) - } + impl BlockSizeUser for $name { + type BlockSize = $block_size; } - impl AlgorithmName for $name { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(stringify!($name)) + impl ParBlocksSizeUser for $name { + type ParBlocksSize = U1; + } + + impl BlockCipherEncrypt for $name { + #[inline] + fn encrypt_with_backend( + &self, + f: impl BlockCipherEncClosure, + ) { + f.call(self) } } - cipher::impl_simple_block_encdec!($name, $block_size, cipher, block, - encrypt: { + impl BlockCipherEncBackend for $name { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { let b = block.get_in(); let mut x = $name::from_be_bytes(&b[0..($n / 8)]); let mut y = $name::from_be_bytes(&b[($n / 8)..2 * ($n / 8)]); for i in 0..$rounds { - let res = $name::round_function(cipher.k[i], x, y); + let res = $name::round_function(self.k[i], x, y); x = res.0; y = res.1; } @@ -154,12 +162,26 @@ macro_rules! define_speck_impl { b[0..($n / 8)].copy_from_slice(&$name::to_be_bytes(x)); b[($n / 8)..2 * ($n / 8)].copy_from_slice(&$name::to_be_bytes(y)); } - decrypt: { + } + + impl BlockCipherDecrypt for $name { + #[inline] + fn decrypt_with_backend( + &self, + f: impl BlockCipherDecClosure, + ) { + f.call(self) + } + } + + impl BlockCipherDecBackend for $name { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { let b = block.get_in(); let mut x = $name::from_be_bytes(&b[0..($n / 8)]); let mut y = $name::from_be_bytes(&b[($n / 8)..2 * ($n / 8)]); for i in (0..$rounds).rev() { - let res = $name::inverse_round_function(cipher.k[i], x, y); + let res = $name::inverse_round_function(self.k[i], x, y); x = res.0; y = res.1; } @@ -168,7 +190,29 @@ macro_rules! define_speck_impl { b[0..($n / 8)].copy_from_slice(&$name::to_be_bytes(x)); b[($n / 8)..2 * ($n / 8)].copy_from_slice(&$name::to_be_bytes(y)); } - ); + } + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(concat!(stringify!($name), " { .. }")) + } + } + + impl AlgorithmName for $name { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($name)) + } + } + + impl Drop for $name { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + self.k.zeroize(); + } + } + + #[cfg(feature = "zeroize")] + impl ZeroizeOnDrop for $name {} }; } diff --git a/threefish/Cargo.toml b/threefish/Cargo.toml index 653ea214..f643d457 100644 --- a/threefish/Cargo.toml +++ b/threefish/Cargo.toml @@ -13,11 +13,11 @@ keywords = ["crypto", "threefish", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = { version = "=0.5.0-pre.6", optional = true } +cipher = { version = "=0.5.0-pre.7", optional = true } zeroize = { version = "1.6", optional = true, default-features = false } [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"]} +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" [features] diff --git a/threefish/LICENSE-MIT b/threefish/LICENSE-MIT index fdc21b08..9c1bd72c 100644 --- a/threefish/LICENSE-MIT +++ b/threefish/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2016-2024 The RustCrypto Project Developers Copyright (c) 2016-2017 Christian Barcenas, Artyom Pavlov Permission is hereby granted, free of charge, to any diff --git a/threefish/src/lib.rs b/threefish/src/lib.rs index 14e8ee85..97ff9dc1 100644 --- a/threefish/src/lib.rs +++ b/threefish/src/lib.rs @@ -16,7 +16,7 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] #[cfg(feature = "cipher")] @@ -26,8 +26,10 @@ use core::fmt; #[cfg(feature = "cipher")] use cipher::{ - consts::{U128, U32, U64}, - AlgorithmName, BlockCipher, Key, KeyInit, KeySizeUser, + consts::{U1, U128, U32, U64}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key, + KeyInit, KeySizeUser, ParBlocksSizeUser, }; mod consts; @@ -158,17 +160,11 @@ macro_rules! impl_threefish( } #[cfg(feature = "cipher")] - #[cfg_attr(docsrs, doc(cfg(feature = "cipher")))] - impl BlockCipher for $name {} - - #[cfg(feature = "cipher")] - #[cfg_attr(docsrs, doc(cfg(feature = "cipher")))] impl KeySizeUser for $name { type KeySize = $block_size; } #[cfg(feature = "cipher")] - #[cfg_attr(docsrs, doc(cfg(feature = "cipher")))] impl KeyInit for $name { fn new(key: &Key) -> Self { let mut tmp_key = [0u8; $n_w*8]; @@ -177,64 +173,92 @@ macro_rules! impl_threefish( } } - impl fmt::Debug for $name { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(concat!(stringify!($name), " { ... }")) - } + #[cfg(feature = "cipher")] + impl BlockSizeUser for $name { + type BlockSize = $block_size; } #[cfg(feature = "cipher")] - #[cfg_attr(docsrs, doc(cfg(feature = "cipher")))] - impl AlgorithmName for $name { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(stringify!($name)) - } + impl ParBlocksSizeUser for $name { + type ParBlocksSize = U1; } - #[cfg(all(feature = "zeroize"))] - #[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] - impl Drop for $name { - fn drop(&mut self) { - self.sk.zeroize(); + #[cfg(feature = "cipher")] + impl BlockCipherEncrypt for $name { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) } } - #[cfg(all(feature = "zeroize"))] - #[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] - impl ZeroizeOnDrop for $name {} - #[cfg(feature = "cipher")] - cipher::impl_simple_block_encdec!( - $name, $block_size, cipher, block, - encrypt: { + impl BlockCipherEncBackend for $name { + #[inline] + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { let mut v = [0u64; $n_w]; let b = block.get_in(); for (vv, chunk) in v.iter_mut().zip(b.chunks_exact(8)) { *vv = u64::from_le_bytes(chunk.try_into().unwrap()); } - cipher.encrypt_block_u64(&mut v); + self.encrypt_block_u64(&mut v); let block = block.get_out(); for (chunk, vv) in block.chunks_exact_mut(8).zip(v.iter()) { chunk.copy_from_slice(&vv.to_le_bytes()); } } - decrypt: { + } + + #[cfg(feature = "cipher")] + impl BlockCipherDecrypt for $name { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } + } + + #[cfg(feature = "cipher")] + impl BlockCipherDecBackend for $name { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { let mut v = [0u64; $n_w]; let b = block.get_in(); for (vv, chunk) in v.iter_mut().zip(b.chunks_exact(8)) { *vv = u64::from_le_bytes(chunk.try_into().unwrap()); } - cipher.decrypt_block_u64(&mut v); + self.decrypt_block_u64(&mut v); let block = block.get_out(); for (chunk, vv) in block.chunks_exact_mut(8).zip(v.iter()) { chunk.copy_from_slice(&vv.to_le_bytes()); } } - ); + } + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(concat!(stringify!($name), " { ... }")) + } + } + + #[cfg(feature = "cipher")] + impl AlgorithmName for $name { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($name)) + } + } + + impl Drop for $name { + fn drop(&mut self) { + #[cfg(all(feature = "zeroize"))] + self.sk.zeroize(); + } + } + + #[cfg(all(feature = "zeroize"))] + impl ZeroizeOnDrop for $name {} ) ); diff --git a/twofish/Cargo.toml b/twofish/Cargo.toml index 885c69cb..5eef4f35 100644 --- a/twofish/Cargo.toml +++ b/twofish/Cargo.toml @@ -13,10 +13,10 @@ keywords = ["crypto", "twofish", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } hex-literal = "0.4" [features] diff --git a/twofish/LICENSE-MIT b/twofish/LICENSE-MIT index 6b640d0b..f05fcc6f 100644 --- a/twofish/LICENSE-MIT +++ b/twofish/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2017-2024 The RustCrypto Project Developers Copyright (c) 2017 Alexander Krotov Permission is hereby granted, free of charge, to any diff --git a/twofish/src/lib.rs b/twofish/src/lib.rs index e5e95f88..84db5a6c 100644 --- a/twofish/src/lib.rs +++ b/twofish/src/lib.rs @@ -16,15 +16,17 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] #![allow(clippy::needless_range_loop, clippy::unreadable_literal)] pub use cipher; use cipher::{ - consts::{U16, U32}, - AlgorithmName, BlockCipher, InvalidLength, Key, KeyInit, KeySizeUser, + consts::{U1, U16, U32}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, + InvalidLength, Key, KeyInit, KeySizeUser, ParBlocksSizeUser, }; use core::fmt; @@ -171,8 +173,6 @@ impl Twofish { } } -impl BlockCipher for Twofish {} - impl KeySizeUser for Twofish { type KeySize = U32; } @@ -199,35 +199,24 @@ impl KeyInit for Twofish { } } -impl fmt::Debug for Twofish { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Twofish { ... }") - } +impl BlockSizeUser for Twofish { + type BlockSize = U16; } -impl AlgorithmName for Twofish { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Twofish") - } +impl ParBlocksSizeUser for Twofish { + type ParBlocksSize = U1; } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl Drop for Twofish { - fn drop(&mut self) { - self.s.zeroize(); - self.k.zeroize(); - self.start.zeroize(); +impl BlockCipherEncrypt for Twofish { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl ZeroizeOnDrop for Twofish {} - -cipher::impl_simple_block_encdec!( - Twofish, U16, cipher, block, - encrypt: { +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()), @@ -238,30 +227,30 @@ cipher::impl_simple_block_encdec!( // Input whitening for i in 0..4 { - p[i] ^= cipher.k[i]; + p[i] ^= self.k[i]; } for r in 0..8 { let k = 4 * r + 8; - let t1 = cipher.g_func(p[1].rotate_left(8)); - let t0 = cipher.g_func(p[0]).wrapping_add(t1); - p[2] = (p[2] ^ (t0.wrapping_add(cipher.k[k]))).rotate_right(1); - let t2 = t1.wrapping_add(t0).wrapping_add(cipher.k[k + 1]); + let t1 = self.g_func(p[1].rotate_left(8)); + let t0 = self.g_func(p[0]).wrapping_add(t1); + p[2] = (p[2] ^ (t0.wrapping_add(self.k[k]))).rotate_right(1); + let t2 = t1.wrapping_add(t0).wrapping_add(self.k[k + 1]); p[3] = p[3].rotate_left(1) ^ t2; - let t1 = cipher.g_func(p[3].rotate_left(8)); - let t0 = cipher.g_func(p[2]).wrapping_add(t1); - p[0] = (p[0] ^ (t0.wrapping_add(cipher.k[k + 2]))).rotate_right(1); - let t2 = t1.wrapping_add(t0).wrapping_add(cipher.k[k + 3]); + let t1 = self.g_func(p[3].rotate_left(8)); + let t0 = self.g_func(p[2]).wrapping_add(t1); + p[0] = (p[0] ^ (t0.wrapping_add(self.k[k + 2]))).rotate_right(1); + let t2 = t1.wrapping_add(t0).wrapping_add(self.k[k + 3]); p[1] = (p[1].rotate_left(1)) ^ t2; } // Undo last swap and output whitening - p[2] ^= cipher.k[4]; - p[3] ^= cipher.k[5]; - p[0] ^= cipher.k[6]; - p[1] ^= cipher.k[7]; + p[2] ^= self.k[4]; + p[3] ^= self.k[5]; + p[0] ^= self.k[6]; + p[1] ^= self.k[7]; let block = block.get_out(); block[0..4].copy_from_slice(&p[2].to_le_bytes()); @@ -269,33 +258,44 @@ cipher::impl_simple_block_encdec!( block[8..12].copy_from_slice(&p[0].to_le_bytes()); block[12..16].copy_from_slice(&p[1].to_le_bytes()); } - decrypt: { +} + +impl BlockCipherDecrypt for Twofish { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} + +impl BlockCipherDecBackend for Twofish { + #[inline] + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { let b = block.get_in(); let mut c = [ - u32::from_le_bytes(b[8..12].try_into().unwrap()) ^ cipher.k[6], - u32::from_le_bytes(b[12..16].try_into().unwrap()) ^ cipher.k[7], - u32::from_le_bytes(b[0..4].try_into().unwrap()) ^ cipher.k[4], - u32::from_le_bytes(b[4..8].try_into().unwrap()) ^ cipher.k[5], + 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], ]; for r in (0..8).rev() { let k = 4 * r + 8; - let t1 = cipher.g_func(c[3].rotate_left(8)); - let t0 = cipher.g_func(c[2]).wrapping_add(t1); - c[0] = c[0].rotate_left(1) ^ (t0.wrapping_add(cipher.k[k + 2])); - let t2 = t1.wrapping_add(t0).wrapping_add(cipher.k[k + 3]); + let t1 = self.g_func(c[3].rotate_left(8)); + let t0 = self.g_func(c[2]).wrapping_add(t1); + c[0] = c[0].rotate_left(1) ^ (t0.wrapping_add(self.k[k + 2])); + let t2 = t1.wrapping_add(t0).wrapping_add(self.k[k + 3]); c[1] = (c[1] ^ t2).rotate_right(1); - let t1 = cipher.g_func(c[1].rotate_left(8)); - let t0 = cipher.g_func(c[0]).wrapping_add(t1); - c[2] = c[2].rotate_left(1) ^ (t0.wrapping_add(cipher.k[k])); - let t2 = t1.wrapping_add(t0).wrapping_add(cipher.k[k + 1]); + let t1 = self.g_func(c[1].rotate_left(8)); + let t0 = self.g_func(c[0]).wrapping_add(t1); + c[2] = c[2].rotate_left(1) ^ (t0.wrapping_add(self.k[k])); + let t2 = t1.wrapping_add(t0).wrapping_add(self.k[k + 1]); c[3] = (c[3] ^ t2).rotate_right(1); } for i in 0..4 { - c[i] ^= cipher.k[i]; + c[i] ^= self.k[i]; } let block = block.get_out(); @@ -304,7 +304,33 @@ cipher::impl_simple_block_encdec!( block[8..12].copy_from_slice(&c[2].to_le_bytes()); block[12..16].copy_from_slice(&c[3].to_le_bytes()); } -); +} + +impl fmt::Debug for Twofish { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Twofish { ... }") + } +} + +impl AlgorithmName for Twofish { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Twofish") + } +} + +impl Drop for Twofish { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + { + self.s.zeroize(); + self.k.zeroize(); + self.start.zeroize(); + } + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Twofish {} #[cfg(test)] mod tests; diff --git a/xtea/Cargo.toml b/xtea/Cargo.toml index 9d403426..dc451c5f 100644 --- a/xtea/Cargo.toml +++ b/xtea/Cargo.toml @@ -13,10 +13,10 @@ keywords = ["crypto", "xtea", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] -cipher = "=0.5.0-pre.6" +cipher = "=0.5.0-pre.7" [dev-dependencies] -cipher = { version = "=0.5.0-pre.6", features = ["dev"] } +cipher = { version = "=0.5.0-pre.7", features = ["dev"] } [features] zeroize = ["cipher/zeroize"] diff --git a/xtea/LICENSE-MIT b/xtea/LICENSE-MIT index 95e7d3c6..327d4ec3 100644 --- a/xtea/LICENSE-MIT +++ b/xtea/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2024 The RustCrypto Project Developers Copyright (c) 2024 Kevin Ludwig Permission is hereby granted, free of charge, to any diff --git a/xtea/src/lib.rs b/xtea/src/lib.rs index 1e83dc39..cfadc981 100644 --- a/xtea/src/lib.rs +++ b/xtea/src/lib.rs @@ -16,14 +16,16 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg" )] #![deny(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn(missing_docs, rust_2018_idioms)] pub use cipher; use cipher::{ - consts::{U16, U8}, - AlgorithmName, BlockCipher, InvalidLength, Key, KeyInit, KeySizeUser, + consts::{U1, U16, U8}, + AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, + BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, + InvalidLength, Key, KeyInit, KeySizeUser, ParBlocksSizeUser, }; use core::fmt; @@ -33,13 +35,11 @@ use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; mod consts; use consts::{DELTA, ROUNDS}; -/// XTEA block cipher. +/// XTEA block self. pub struct Xtea { k: [u32; 4], } -impl BlockCipher for Xtea {} - impl KeySizeUser for Xtea { type KeySize = U16; } @@ -63,33 +63,24 @@ impl KeyInit for Xtea { } } -impl fmt::Debug for Xtea { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("XTEA { ... }") - } +impl BlockSizeUser for Xtea { + type BlockSize = U8; } -impl AlgorithmName for Xtea { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("XTEA") - } +impl ParBlocksSizeUser for Xtea { + type ParBlocksSize = U1; } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl Drop for Xtea { - fn drop(&mut self) { - self.k.zeroize(); +impl BlockCipherEncrypt for Xtea { + #[inline] + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self) } } -#[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] -impl ZeroizeOnDrop for Xtea {} - -cipher::impl_simple_block_encdec!( - Xtea, U8, cipher, block, - encrypt: { +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()); @@ -97,31 +88,66 @@ cipher::impl_simple_block_encdec!( // 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(cipher.k[(sum & 3) as usize])); + v0 = v0.wrapping_add( + (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) + ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ); sum = sum.wrapping_add(DELTA); - v1 = v1.wrapping_add((((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) ^ sum.wrapping_add(cipher.k[((sum >> 11) & 3) as usize])); + v1 = v1.wrapping_add( + (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) + ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ); } for _ in 0..8 { - v0 = v0.wrapping_add((((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) ^ sum.wrapping_add(cipher.k[(sum & 3) as usize])); + v0 = v0.wrapping_add( + (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) + ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ); sum = sum.wrapping_add(DELTA); - v1 = v1.wrapping_add((((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) ^ sum.wrapping_add(cipher.k[((sum >> 11) & 3) as usize])); + v1 = v1.wrapping_add( + (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) + ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ); } for _ in 0..8 { - v0 = v0.wrapping_add((((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) ^ sum.wrapping_add(cipher.k[(sum & 3) as usize])); + v0 = v0.wrapping_add( + (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) + ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ); sum = sum.wrapping_add(DELTA); - v1 = v1.wrapping_add((((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) ^ sum.wrapping_add(cipher.k[((sum >> 11) & 3) as usize])); + v1 = v1.wrapping_add( + (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) + ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ); } for _ in 0..8 { - v0 = v0.wrapping_add((((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) ^ sum.wrapping_add(cipher.k[(sum & 3) as usize])); + v0 = v0.wrapping_add( + (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) + ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ); sum = sum.wrapping_add(DELTA); - v1 = v1.wrapping_add((((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) ^ sum.wrapping_add(cipher.k[((sum >> 11) & 3) as usize])); + v1 = v1.wrapping_add( + (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) + ^ sum.wrapping_add(self.k[((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()); } - decrypt: { +} + +impl BlockCipherDecrypt for Xtea { + #[inline] + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + 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()); @@ -129,28 +155,74 @@ cipher::impl_simple_block_encdec!( // Same as encrypt, just in reverse for _ in 0..8 { - v1 = v1.wrapping_sub((((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) ^ sum.wrapping_add(cipher.k[((sum >> 11) & 3) as usize])); + v1 = v1.wrapping_sub( + (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) + ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ); sum = sum.wrapping_sub(DELTA); - v0 = v0.wrapping_sub((((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) ^ sum.wrapping_add(cipher.k[(sum & 3) as usize])); + v0 = v0.wrapping_sub( + (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) + ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ); } for _ in 0..8 { - v1 = v1.wrapping_sub((((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) ^ sum.wrapping_add(cipher.k[((sum >> 11) & 3) as usize])); + v1 = v1.wrapping_sub( + (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) + ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ); sum = sum.wrapping_sub(DELTA); - v0 = v0.wrapping_sub((((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) ^ sum.wrapping_add(cipher.k[(sum & 3) as usize])); + v0 = v0.wrapping_sub( + (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) + ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ); } for _ in 0..8 { - v1 = v1.wrapping_sub((((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) ^ sum.wrapping_add(cipher.k[((sum >> 11) & 3) as usize])); + v1 = v1.wrapping_sub( + (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) + ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ); sum = sum.wrapping_sub(DELTA); - v0 = v0.wrapping_sub((((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) ^ sum.wrapping_add(cipher.k[(sum & 3) as usize])); + v0 = v0.wrapping_sub( + (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) + ^ sum.wrapping_add(self.k[(sum & 3) as usize]), + ); } for _ in 0..8 { - v1 = v1.wrapping_sub((((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) ^ sum.wrapping_add(cipher.k[((sum >> 11) & 3) as usize])); + v1 = v1.wrapping_sub( + (((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) + ^ sum.wrapping_add(self.k[((sum >> 11) & 3) as usize]), + ); sum = sum.wrapping_sub(DELTA); - v0 = v0.wrapping_sub((((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) ^ sum.wrapping_add(cipher.k[(sum & 3) as usize])); + v0 = v0.wrapping_sub( + (((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) + ^ sum.wrapping_add(self.k[(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()); } -); +} + +impl fmt::Debug for Xtea { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("XTEA { ... }") + } +} + +impl AlgorithmName for Xtea { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("XTEA") + } +} + +impl Drop for Xtea { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + self.k.zeroize(); + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Xtea {}