rc5_block/types.rs
1use rand::Rng;
2
3/// # RC5 version identifier
4///
5/// It represents RC5 control block parameters. These parameters are
6/// defined as follows:
7///
8/// 1. Algorithm version (1 for RC5)
9/// 2. Word-size in bits
10/// 3. Number of rounds.
11/// 4. Key length in bytes.
12///
13/// This is how these parameters are arranged in version string:
14///
15/// RC5-v<`Algorithm version`>/<`Word-size`>/<`Rounds`>/<`Key-length`>
16///
17/// This can be useful when asserting what parametric version of RC5 to
18/// use for certain applications.
19pub struct Version(Vec<u8>);
20
21impl Version {
22 /// Construct a new `Version` from a 4‑element parameter vector.
23 ///
24 /// Expects the vector to be exactly four bytes:
25 /// `[algorithm, word_bits, rounds, key_bytes]`.
26 pub fn from_parametric_vector(params: Vec<u8>) -> Self {
27 Self(params)
28 }
29
30 /// Render the RC5 version string in the form: `RC5-vA/B/C/D`.
31 ///
32 /// Where A,B,C,D correspond to the four parameters passed to `new`.
33 pub fn version(&self) -> String {
34 let params = &self.0;
35 format!(
36 "RC5-v{}/{}/{}/{}",
37 params[0], params[1], params[2], params[3]
38 )
39 }
40}
41
42/// A core trait to define a word in `N-sized` blocks of a block cipher. This
43/// word must support arithmatic and binary operations required for cryptographic
44/// functions.
45pub trait Word: Clone + Copy + std::ops::BitXor<Output = Self> {
46 /// A constant zero value for a `Word` type.
47 const ZERO: Self;
48
49 /// Number of bytes in this word
50 const BYTES: usize;
51
52 /// Magic constant `P` represented by this word to
53 /// be used in RC5 key expansion.
54 const P: Self;
55
56 /// Magic constant `Q` represented by this word to
57 /// be used in RC5 key expansion.
58 const Q: Self;
59
60 /// Cast a 8-bit value to this word type.
61 fn from_u8(val: u8) -> Self;
62
63 /// Parse this word from a little‐endian byte slice of length `BYTES`.
64 ///
65 /// Returns `None` if the slice length is not equal to `Word::BYTES`
66 fn from_bytes_slice(slice: &[u8]) -> Option<Self>;
67
68 /// Serialize this word to a little‐endian bytes list.
69 fn to_bytes_slice(&self) -> Vec<u8>;
70
71 /// Generate a random word using the given RNG.
72 fn random<R: Rng + ?Sized>(rng: &mut R) -> Self;
73
74 /// Wrapped addition
75 fn wrapping_add(self, val: Self) -> Self;
76
77 /// Wrapped subtraction
78 fn wrapping_sub(self, val: Self) -> Self;
79
80 /// Left bitwise rotation
81 fn rotate_left(self, bits: Self) -> Self;
82
83 /// Right bitwise rotation
84 fn rotate_right(self, bits: Self) -> Self;
85}
86
87macro_rules! magic_consts {
88 (u16) => {
89 const P: u16 = 0xb7e1;
90 const Q: u16 = 0x9e37;
91 };
92 (u32) => {
93 const P: u32 = 0xb7e15163;
94 const Q: u32 = 0x9e3779b9;
95 };
96 (u64) => {
97 const P: u64 = 0xb7e151628aed2a6b;
98 const Q: u64 = 0x9e3779b97f4a7c15;
99 };
100 (u128) => {
101 const P: u128 = 0x9E3779B97F4A7C15F39CC0605CEDC835;
102 const Q: u128 = 0xB7E151628AED2A6ABF7158809CF4F3C7;
103 };
104}
105
106macro_rules! impl_word_for_prim {
107 ($($t:ident),*) => {
108 $(
109 impl Word for $t {
110 const ZERO: $t = 0;
111 const BYTES: usize = (<$t>::BITS / 8) as usize;
112
113 magic_consts!($t);
114
115 #[inline]
116 fn from_u8(val: u8) -> Self {
117 val as $t
118 }
119
120 #[inline]
121 fn from_bytes_slice(slice: &[u8]) -> Option<Self> {
122 slice.try_into().ok().map(|b| <$t>::from_le_bytes(b))
123 }
124
125 fn to_bytes_slice(& self) -> Vec<u8> {
126 self.to_le_bytes().to_vec()
127 }
128
129 #[inline]
130 fn random<R: Rng + ?Sized>(rng: &mut R) -> Self {
131 rng.r#gen()
132 }
133
134 #[inline]
135 fn wrapping_add(self, other: Self) -> Self {
136 <$t>::wrapping_add(self, other)
137 }
138
139 #[inline]
140 fn wrapping_sub(self, other: Self) -> Self {
141 <$t>::wrapping_sub(self, other)
142 }
143
144 #[inline]
145 fn rotate_left(self, bits: Self) -> Self {
146 self.rotate_left(bits as u32)
147 }
148
149 #[inline]
150 fn rotate_right(self, bits: Self) -> Self {
151 self.rotate_right(bits as u32)
152 }
153 }
154 )*
155 }
156}
157
158impl_word_for_prim!(u16, u32, u64, u128);