Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rc5: unlock parameter size, add u128 and u8 word size support. #382

Merged
merged 3 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion rc5/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
- Added u8 and u128 word size support.
- Enabled custom word size, key size, and round count values.
- Deprecated old predefined RC5 cipher types.

## 0.0.1 (2023-02-10)
- Initial release
- Initial release
2 changes: 1 addition & 1 deletion rc5/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rc5"
version = "0.0.1"
version = "0.1.0-pre"
description = "RC5 block cipher"
authors = ["RustCrypto Developers"]
edition = "2021"
Expand Down
11 changes: 6 additions & 5 deletions rc5/benches/mod.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
#![feature(test)]
extern crate test;

use cipher::consts::*;
use cipher::{block_decryptor_bench, block_encryptor_bench};
use rc5::{RC5_32_12_16, RC5_32_16_16};
use rc5::RC5;

block_encryptor_bench!(
Key: RC5_32_12_16,
Key: RC5<u32, U12, U16>,
rc5_32_12_16_encrypt_block,
rc5_32_12_16_encrypt_blocks,
);
block_decryptor_bench!(
Key: RC5_32_12_16,
Key: RC5<u32, U12, U16>,
rc5_32_12_16_decrypt_block,
rc5_32_12_16_decrypt_blocks,
);

block_encryptor_bench!(
Key: RC5_32_16_16,
Key: RC5<u32, U16, U16>,
rc5_32_16_16_encrypt_block,
rc5_32_16_16_encrypt_blocks,
);
block_decryptor_bench!(
Key: RC5_32_16_16,
Key: RC5<u32, U16, U16>,
rc5_32_16_16_decrypt_block,
rc5_32_16_16_decrypt_blocks,
);
13 changes: 11 additions & 2 deletions rc5/src/block_cipher.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use core::ops::{Add, Div, Mul, Sub};

use cipher::{
consts::*,
generic_array::ArrayLength,
inout::InOut,
typenum::{Diff, IsLess, Le, NonZero, Sum, Unsigned, U1, U12, U16, U2, U24, U256, U8},
typenum::{Diff, IsLess, Le, NonZero, Sum, Unsigned, U1, U2, U256},
AlgorithmName, Block, BlockBackend, BlockCipher, BlockDecrypt, BlockEncrypt, BlockSizeUser,
KeyInit, KeySizeUser, ParBlocksSizeUser,
};
Expand Down Expand Up @@ -345,7 +346,15 @@ where
}
}

#[allow(dead_code)]
#[deprecated(since = "0.1.0", note = "use RC5<u16, U16, U8> instead.")]
pub type RC5_16_16_8 = RC5<u16, U16, U8>;
#[allow(dead_code)]
#[deprecated(since = "0.1.0", note = "use RC5<u32, U12, U16> instead.")]
pub type RC5_32_12_16 = RC5<u32, U12, U16>;
#[allow(dead_code)]
#[deprecated(since = "0.1.0", note = "use RC5<u32, U16, U16> instead.")]
pub type RC5_32_16_16 = RC5<u32, U16, U16>;
pub type RC5_16_16_8 = RC5<u16, U16, U8>;
#[allow(dead_code)]
#[deprecated(since = "0.1.0", note = "use RC5<u64, U24, U24> instead.")]
pub type RC5_64_24_24 = RC5<u64, U24, U24>;
121 changes: 107 additions & 14 deletions rc5/src/core/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use core::ops::{Add, BitXor};

use cipher::{
generic_array::{ArrayLength, GenericArray},
typenum::{Diff, Prod, Quot, Sum, U1, U2, U4, U8},
typenum::{Diff, Prod, Quot, Sum, U1, U16, U2, U4, U8},
zeroize::DefaultIsZeroes,
};

Expand Down Expand Up @@ -43,54 +43,55 @@ pub trait Word:

mod private {
pub trait Sealed {}

impl Sealed for u32 {}
impl Sealed for u8 {}
impl Sealed for u16 {}
impl Sealed for u32 {}
impl Sealed for u64 {}
impl Sealed for u128 {}
}

impl Word for u32 {
type Bytes = U4;
impl Word for u8 {
type Bytes = U1;

const ZERO: Self = 0;
const THREE: Self = 3;
const EIGHT: Self = 8;

const P: Self = 0xb7e15163;
const Q: Self = 0x9e3779b9;
const P: Self = 0xb7;
const Q: Self = 0x9f;

#[inline(always)]
fn wrapping_add(self, rhs: Self) -> Self {
u32::wrapping_add(self, rhs)
u8::wrapping_add(self, rhs)
}
#[inline(always)]
fn wrapping_sub(self, rhs: Self) -> Self {
u32::wrapping_sub(self, rhs)
u8::wrapping_sub(self, rhs)
}

#[inline(always)]
fn rotate_left(self, n: Self) -> Self {
u32::rotate_left(self, n)
u8::rotate_left(self, n as u32)
}

#[inline(always)]
fn rotate_right(self, n: Self) -> Self {
u32::rotate_right(self, n)
u8::rotate_right(self, n as u32)
}

#[inline(always)]
fn from_le_bytes(bytes: &GenericArray<u8, Self::Bytes>) -> Self {
u32::from_le_bytes(bytes.as_slice().try_into().unwrap())
u8::from_le_bytes(bytes.as_slice().try_into().unwrap())
}

#[inline(always)]
fn to_le_bytes(self) -> GenericArray<u8, Self::Bytes> {
u32::to_le_bytes(self).into()
u8::to_le_bytes(self).into()
}

#[inline(always)]
fn bitxor(self, other: Self) -> Self {
<u32 as BitXor>::bitxor(self, other)
<u8 as BitXor>::bitxor(self, other)
}
}

Expand Down Expand Up @@ -139,6 +140,51 @@ impl Word for u16 {
}
}

impl Word for u32 {
type Bytes = U4;

const ZERO: Self = 0;
const THREE: Self = 3;
const EIGHT: Self = 8;

const P: Self = 0xb7e15163;
const Q: Self = 0x9e3779b9;

#[inline(always)]
fn wrapping_add(self, rhs: Self) -> Self {
u32::wrapping_add(self, rhs)
}
#[inline(always)]
fn wrapping_sub(self, rhs: Self) -> Self {
u32::wrapping_sub(self, rhs)
}

#[inline(always)]
fn rotate_left(self, n: Self) -> Self {
u32::rotate_left(self, n)
}

#[inline(always)]
fn rotate_right(self, n: Self) -> Self {
u32::rotate_right(self, n)
}

#[inline(always)]
fn from_le_bytes(bytes: &GenericArray<u8, Self::Bytes>) -> Self {
u32::from_le_bytes(bytes.as_slice().try_into().unwrap())
}

#[inline(always)]
fn to_le_bytes(self) -> GenericArray<u8, Self::Bytes> {
u32::to_le_bytes(self).into()
}

#[inline(always)]
fn bitxor(self, other: Self) -> Self {
<u32 as BitXor>::bitxor(self, other)
}
}

impl Word for u64 {
type Bytes = U8;

Expand Down Expand Up @@ -185,3 +231,50 @@ impl Word for u64 {
<u64 as BitXor>::bitxor(self, other)
}
}

impl Word for u128 {
type Bytes = U16;

const ZERO: Self = 0;
const THREE: Self = 3;
const EIGHT: Self = 8;

const P: Self = 0xb7e151628aed2a6abf7158809cf4f3c7;
const Q: Self = 0x9e3779b97f4a7c15f39cc0605cedc835;

#[inline(always)]
fn wrapping_add(self, rhs: Self) -> Self {
u128::wrapping_add(self, rhs)
}
#[inline(always)]
fn wrapping_sub(self, rhs: Self) -> Self {
u128::wrapping_sub(self, rhs)
}

#[inline(always)]
fn rotate_left(self, n: Self) -> Self {
let size = Self::BITS;
u128::rotate_left(self, (n % size as u128) as u32)
}

#[inline(always)]
fn rotate_right(self, n: Self) -> Self {
let size = Self::BITS;
u128::rotate_right(self, (n % size as u128) as u32)
}

#[inline(always)]
fn from_le_bytes(bytes: &GenericArray<u8, Self::Bytes>) -> Self {
u128::from_le_bytes(bytes.as_slice().try_into().unwrap())
}

#[inline(always)]
fn to_le_bytes(self) -> GenericArray<u8, Self::Bytes> {
u128::to_le_bytes(self).into()
}

#[inline(always)]
fn bitxor(self, other: Self) -> Self {
<u128 as BitXor>::bitxor(self, other)
}
}
1 change: 1 addition & 0 deletions rc5/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
mod block_cipher;
mod core;

pub use crate::core::RC5;
pub use block_cipher::*;
59 changes: 54 additions & 5 deletions rc5/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
/// generated using the code in: https://www.ietf.org/archive/id/draft-krovetz-rc6-rc5-vectors-00.txt
#[cfg(test)]
mod tests {
use cipher::consts::*;
use cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit};
use rc5::{RC5_16_16_8, RC5_32_12_16, RC5_32_16_16, RC5_64_24_24};
use rc5::RC5;

#[test]
fn enc_dec_8_12_4() {
let key = [0x00, 0x01, 0x02, 0x03];

let pt = [0x00, 0x01];
let ct = [0x21, 0x2A];

let rc5 = <RC5<u8, U12, U4> as KeyInit>::new_from_slice(&key).unwrap();

let mut block = GenericArray::clone_from_slice(&pt);
rc5.encrypt_block(&mut block);

assert_eq!(ct, block[..]);

rc5.decrypt_block(&mut block);
assert_eq!(pt, block[..]);
}

#[test]
fn enc_dec_16_16_8() {
Expand All @@ -11,7 +30,7 @@ mod tests {
let pt = [0x00, 0x01, 0x02, 0x03];
let ct = [0x23, 0xA8, 0xD7, 0x2E];

let rc5 = <RC5_16_16_8 as KeyInit>::new_from_slice(&key).unwrap();
let rc5 = <RC5<u16, U16, U8> as KeyInit>::new_from_slice(&key).unwrap();

let mut block = GenericArray::clone_from_slice(&pt);
rc5.encrypt_block(&mut block);
Expand All @@ -32,7 +51,7 @@ mod tests {
let pt = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
let ct = [0xC8, 0xD3, 0xB3, 0xC4, 0x86, 0x70, 0x0C, 0xFA];

let rc5 = <RC5_32_12_16 as KeyInit>::new_from_slice(&key).unwrap();
let rc5 = <RC5<u32, U12, U16> as KeyInit>::new_from_slice(&key).unwrap();

let mut block = GenericArray::clone_from_slice(&pt);
rc5.encrypt_block(&mut block);
Expand All @@ -53,7 +72,7 @@ mod tests {
let pt = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
let ct = [0x3E, 0x2E, 0x95, 0x35, 0x70, 0x27, 0xD8, 0x96];

let rc5 = <RC5_32_16_16 as KeyInit>::new_from_slice(&key).unwrap();
let rc5 = <RC5<u32, U16, U16> as KeyInit>::new_from_slice(&key).unwrap();

let mut block = GenericArray::clone_from_slice(&pt);
rc5.encrypt_block(&mut block);
Expand All @@ -80,7 +99,37 @@ mod tests {
0x78, 0xDA,
];

let rc5 = <RC5_64_24_24 as KeyInit>::new_from_slice(&key).unwrap();
let rc5 = <RC5<u64, U24, U24> as KeyInit>::new_from_slice(&key).unwrap();

let mut block = GenericArray::clone_from_slice(&pt);
rc5.encrypt_block(&mut block);

assert_eq!(ct, 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,
];

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 = <RC5<u128, U28, U32> as KeyInit>::new_from_slice(&key).unwrap();

let mut block = GenericArray::clone_from_slice(&pt);
rc5.encrypt_block(&mut block);
Expand Down
Loading