Skip to content

Commit 96a264b

Browse files
committed
bring ocb3 and deoxys
3 parents 4eeff4a + e6191ae + 3396c54 commit 96a264b

File tree

8 files changed

+1058
-239
lines changed

8 files changed

+1058
-239
lines changed

Cargo.lock

Lines changed: 642 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ members = [
77
"ascon-aead",
88
"ccm",
99
"chacha20poly1305",
10-
#"deoxys",
10+
"deoxys",
1111
"eax",
12-
#"ocb3",
12+
"ocb3",
1313
"xaes-256-gcm",
14+
15+
"benches",
1416
]
1517
resolver = "2"
1618

benches/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ edition = "2021"
88
publish = false
99
rust-version = "1.56"
1010

11-
[workspace]
12-
1311
[dependencies]
1412
criterion = "0.4.0"
1513
rand = "0.9.0"

deoxys/src/deoxys_bc.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use aead::{
33
consts::{U15, U16, U17, U32, U48},
44
};
55

6-
use crate::DeoxysBcType;
6+
use crate::{DeoxysBcType, DeoxysKey, Tweak};
77

88
const H_PERM: [u8; 16] = [1, 6, 11, 12, 5, 10, 15, 0, 9, 14, 3, 4, 13, 2, 7, 8];
99

@@ -46,10 +46,10 @@ pub trait DeoxysBcInternal {
4646
type TweakKeySize: ArraySize;
4747

4848
fn key_schedule(
49-
tweak: &[u8; 16],
50-
subkeys: &Array<[u8; 16], Self::SubkeysSize>,
51-
) -> Array<[u8; 16], Self::SubkeysSize> {
52-
let mut subtweakeys: Array<[u8; 16], Self::SubkeysSize> = Default::default();
49+
tweak: &Tweak,
50+
subkeys: &Array<DeoxysKey, Self::SubkeysSize>,
51+
) -> Array<DeoxysKey, Self::SubkeysSize> {
52+
let mut subtweakeys: Array<DeoxysKey, Self::SubkeysSize> = Default::default();
5353
let mut tweak = *tweak;
5454

5555
// First key
@@ -59,7 +59,7 @@ pub trait DeoxysBcInternal {
5959

6060
// Other keys
6161
for (stk, sk) in subtweakeys[1..].iter_mut().zip(subkeys[1..].iter()) {
62-
h_substitution(&mut tweak);
62+
h_substitution((&mut tweak).into());
6363

6464
for i in 0..16 {
6565
stk[i] = sk[i] ^ tweak[i];
@@ -78,8 +78,8 @@ impl DeoxysBcInternal for DeoxysBc256 {
7878
impl DeoxysBcType for DeoxysBc256 {
7979
type KeySize = U16;
8080

81-
fn precompute_subkeys(key: &Array<u8, Self::KeySize>) -> Array<[u8; 16], Self::SubkeysSize> {
82-
let mut subkeys: Array<[u8; 16], Self::SubkeysSize> = Default::default();
81+
fn precompute_subkeys(key: &Array<u8, Self::KeySize>) -> Array<DeoxysKey, Self::SubkeysSize> {
82+
let mut subkeys: Array<DeoxysKey, Self::SubkeysSize> = Default::default();
8383

8484
let mut tk2 = [0u8; 16];
8585

@@ -116,8 +116,8 @@ impl DeoxysBcInternal for DeoxysBc384 {
116116
impl DeoxysBcType for DeoxysBc384 {
117117
type KeySize = U32;
118118

119-
fn precompute_subkeys(key: &Array<u8, Self::KeySize>) -> Array<[u8; 16], Self::SubkeysSize> {
120-
let mut subkeys: Array<[u8; 16], Self::SubkeysSize> = Default::default();
119+
fn precompute_subkeys(key: &Array<u8, Self::KeySize>) -> Array<DeoxysKey, Self::SubkeysSize> {
120+
let mut subkeys: Array<DeoxysKey, Self::SubkeysSize> = Default::default();
121121

122122
let mut tk3 = [0u8; 16];
123123
let mut tk2 = [0u8; 16];

deoxys/src/lib.rs

Lines changed: 145 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ use aead::{
116116
PostfixTagged,
117117
array::{Array, ArraySize},
118118
consts::U16,
119-
inout::InOutBuf,
119+
inout::{InOut, InOutBuf},
120120
};
121121
use core::marker::PhantomData;
122122

@@ -140,6 +140,12 @@ pub type Nonce<NonceSize> = Array<u8, NonceSize>;
140140
/// Deoxys tags
141141
pub type Tag = Array<u8, U16>;
142142

143+
type Block = Array<u8, U16>;
144+
145+
type Tweak = Array<u8, U16>;
146+
147+
type DeoxysKey = Array<u8, U16>;
148+
143149
/// Deoxys encryption modes.
144150
/// This type contains the public API for a Deoxys mode, like Deoxys-I and Deoxys-II.
145151
pub trait DeoxysMode<B>: modes::DeoxysModeInternal<B>
@@ -151,21 +157,21 @@ where
151157

152158
/// Encrypts the data in place with the specified parameters
153159
/// Returns the tag
154-
fn encrypt_in_place(
160+
fn encrypt_inout(
155161
nonce: &Array<u8, Self::NonceSize>,
156162
associated_data: &[u8],
157-
buffer: &mut [u8],
158-
subkeys: &Array<[u8; 16], B::SubkeysSize>,
159-
) -> [u8; 16];
163+
buffer: InOutBuf<'_, '_, u8>,
164+
subkeys: &Array<DeoxysKey, B::SubkeysSize>,
165+
) -> Tag;
160166

161167
/// Decrypts the data in place with the specified parameters
162168
/// Returns an error if the tag verification fails
163-
fn decrypt_in_place(
169+
fn decrypt_inout(
164170
nonce: &Array<u8, Self::NonceSize>,
165171
associated_data: &[u8],
166-
buffer: &mut [u8],
172+
buffer: InOutBuf<'_, '_, u8>,
167173
tag: &Tag,
168-
subkeys: &Array<[u8; 16], B::SubkeysSize>,
174+
subkeys: &Array<DeoxysKey, B::SubkeysSize>,
169175
) -> Result<(), aead::Error>;
170176
}
171177

@@ -176,47 +182,43 @@ pub trait DeoxysBcType: deoxys_bc::DeoxysBcInternal {
176182
type KeySize: ArraySize;
177183

178184
/// Precompute the subkeys
179-
fn precompute_subkeys(key: &Array<u8, Self::KeySize>) -> Array<[u8; 16], Self::SubkeysSize>;
185+
fn precompute_subkeys(key: &Array<u8, Self::KeySize>) -> Array<DeoxysKey, Self::SubkeysSize>;
180186

181187
/// Encrypts a block of data in place.
182-
fn encrypt_in_place(
183-
block: &mut [u8; 16],
184-
tweak: &[u8; 16],
185-
subkeys: &Array<[u8; 16], Self::SubkeysSize>,
188+
fn encrypt_inout(
189+
mut block: InOut<'_, '_, Block>,
190+
tweak: &Tweak,
191+
subkeys: &Array<DeoxysKey, Self::SubkeysSize>,
186192
) {
187193
let keys = Self::key_schedule(tweak, subkeys);
188194

189-
for (b, k) in block.iter_mut().zip(keys[0].iter()) {
190-
*b ^= k;
191-
}
195+
block.xor_in2out(&keys[0]);
192196

193197
for k in &keys[1..] {
194-
aes::hazmat::cipher_round(block.into(), k.into());
198+
aes::hazmat::cipher_round(block.get_out(), k);
195199
}
196200
}
197201

198202
/// Decrypts a block of data in place.
199-
fn decrypt_in_place(
200-
block: &mut [u8; 16],
201-
tweak: &[u8; 16],
202-
subkeys: &Array<[u8; 16], Self::SubkeysSize>,
203+
fn decrypt_inout(
204+
mut block: InOut<'_, '_, Block>,
205+
tweak: &Tweak,
206+
subkeys: &Array<DeoxysKey, Self::SubkeysSize>,
203207
) {
204208
let mut keys = Self::key_schedule(tweak, subkeys);
205209

206210
let r = keys.len();
207211

208-
for (b, k) in block.iter_mut().zip(keys[r - 1].iter()) {
209-
*b ^= k;
210-
}
212+
block.xor_in2out(&keys[r - 1]);
211213

212-
aes::hazmat::inv_mix_columns(block.into());
214+
aes::hazmat::inv_mix_columns(block.get_out());
213215

214216
for k in keys[..r - 1].iter_mut().rev() {
215-
aes::hazmat::inv_mix_columns(k.into());
216-
aes::hazmat::equiv_inv_cipher_round(block.into(), (&*k).into());
217+
aes::hazmat::inv_mix_columns(k);
218+
aes::hazmat::equiv_inv_cipher_round(block.get_out(), k);
217219
}
218220

219-
aes::hazmat::mix_columns(block.into());
221+
aes::hazmat::mix_columns(block.get_out());
220222
}
221223
}
222224

@@ -228,7 +230,7 @@ where
228230
M: DeoxysMode<B>,
229231
B: DeoxysBcType,
230232
{
231-
subkeys: Array<[u8; 16], B::SubkeysSize>,
233+
subkeys: Array<DeoxysKey, B::SubkeysSize>,
232234
mode: PhantomData<M>,
233235
}
234236

@@ -280,7 +282,7 @@ where
280282
associated_data: &[u8],
281283
buffer: InOutBuf<'_, '_, u8>,
282284
) -> Result<Tag, Error> {
283-
Ok(Tag::from(M::encrypt_in_place(
285+
Ok(Tag::from(M::encrypt_inout(
284286
nonce,
285287
associated_data,
286288
buffer,
@@ -295,7 +297,7 @@ where
295297
buffer: InOutBuf<'_, '_, u8>,
296298
tag: &Tag,
297299
) -> Result<(), Error> {
298-
M::decrypt_in_place(nonce, associated_data, buffer, tag, &self.subkeys)
300+
M::decrypt_inout(nonce, associated_data, buffer, tag, &self.subkeys)
299301
}
300302
}
301303

@@ -322,3 +324,115 @@ where
322324
B: DeoxysBcType,
323325
{
324326
}
327+
328+
#[cfg(all(feature = "alloc", test))]
329+
mod tests {
330+
//! this module is here to test the inout behavior which is not currently exposed.
331+
//! it will be once we port over to the API made in RustCrypto/traits#1793.
332+
//!
333+
//! This is to drop once https://github.com/RustCrypto/traits/pull/1797 is made available.
334+
//!
335+
//! It duplicates test vectors from `tests/deoxys_i_128.rs` and provides a mock buffer backing
336+
//! for InOut.
337+
338+
extern crate alloc;
339+
340+
use alloc::{vec, vec::Vec};
341+
use hex_literal::hex;
342+
343+
use super::*;
344+
345+
struct MockBuffer {
346+
in_buf: Vec<u8>,
347+
out_buf: Vec<u8>,
348+
}
349+
350+
impl From<&[u8]> for MockBuffer {
351+
fn from(buf: &[u8]) -> Self {
352+
Self {
353+
in_buf: buf.to_vec(),
354+
out_buf: vec![0u8; buf.len()],
355+
}
356+
}
357+
}
358+
359+
impl MockBuffer {
360+
/// Get an [`InOutBuf`] from a [`MockBuffer`]
361+
pub fn to_in_out_buf(&mut self) -> InOutBuf<'_, '_, u8> {
362+
InOutBuf::new(self.in_buf.as_slice(), self.out_buf.as_mut_slice())
363+
.expect("Invariant violation")
364+
}
365+
}
366+
367+
impl AsRef<[u8]> for MockBuffer {
368+
fn as_ref(&self) -> &[u8] {
369+
&self.out_buf
370+
}
371+
}
372+
373+
#[test]
374+
fn test_deoxys_i_128_5() {
375+
let plaintext = hex!("5a4c652cb880808707230679224b11799b5883431292973215e9bd03cf3bc32fe4");
376+
let mut buffer = MockBuffer::from(&plaintext[..]);
377+
378+
let aad = Vec::new();
379+
380+
let key = hex!("101112131415161718191a1b1c1d1e1f");
381+
let key = Array(key);
382+
383+
let nonce = hex!("202122232425262728292a2b2c2d2e2f");
384+
let nonce = Array::try_from(&nonce[..8]).unwrap();
385+
386+
let ciphertext_expected =
387+
hex!("cded5a43d3c76e942277c2a1517530ad66037897c985305ede345903ed7585a626");
388+
389+
let tag_expected: [u8; 16] = hex!("cbf5faa6b8398c47f4278d2019161776");
390+
391+
type M = modes::DeoxysI<deoxys_bc::DeoxysBc256>;
392+
let cipher = DeoxysI128::new(&key);
393+
let tag: Tag = M::encrypt_inout(&nonce, &aad, buffer.to_in_out_buf(), &cipher.subkeys);
394+
395+
let ciphertext = buffer.as_ref();
396+
assert_eq!(ciphertext, ciphertext_expected);
397+
assert_eq!(tag, tag_expected);
398+
399+
let mut buffer = MockBuffer::from(buffer.as_ref());
400+
M::decrypt_inout(&nonce, &aad, buffer.to_in_out_buf(), &tag, &cipher.subkeys)
401+
.expect("decryption failed");
402+
403+
assert_eq!(&plaintext[..], buffer.as_ref());
404+
}
405+
406+
#[test]
407+
fn test_deoxys_ii_128_5() {
408+
let plaintext = hex!("06ac1756eccece62bd743fa80c299f7baa3872b556130f52265919494bdc136db3");
409+
let mut buffer = MockBuffer::from(&plaintext[..]);
410+
411+
let aad = Vec::new();
412+
413+
let key = hex!("101112131415161718191a1b1c1d1e1f");
414+
let key = Array(key);
415+
416+
let nonce = hex!("202122232425262728292a2b2c2d2e2f");
417+
let nonce = Array::try_from(&nonce[..15]).unwrap();
418+
419+
let ciphertext_expected =
420+
hex!("82bf241958b324ed053555d23315d3cc20935527fc970ff34a9f521a95e302136d");
421+
422+
let tag_expected: [u8; 16] = hex!("0eadc8612d5208c491e93005195e9769");
423+
424+
type M = modes::DeoxysII<deoxys_bc::DeoxysBc256>;
425+
let cipher = DeoxysII128::new(&key);
426+
let tag: Tag = M::encrypt_inout(&nonce, &aad, buffer.to_in_out_buf(), &cipher.subkeys);
427+
428+
let ciphertext = buffer.as_ref();
429+
assert_eq!(ciphertext, ciphertext_expected);
430+
assert_eq!(tag, tag_expected);
431+
432+
let mut buffer = MockBuffer::from(buffer.as_ref());
433+
M::decrypt_inout(&nonce, &aad, buffer.to_in_out_buf(), &tag, &cipher.subkeys)
434+
.expect("decryption failed");
435+
436+
assert_eq!(&plaintext[..], buffer.as_ref());
437+
}
438+
}

0 commit comments

Comments
 (0)