Skip to content

Commit 0ac3e86

Browse files
committed
bring ocb3 and deoxys
3 parents fc4fcff + 3eddf5a + 9be4164 commit 0ac3e86

File tree

8 files changed

+405
-198
lines changed

8 files changed

+405
-198
lines changed

Cargo.lock

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

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

deoxys/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ edition = "2024"
1818
rust-version = "1.85"
1919

2020
[dependencies]
21-
aead = { version = "0.6.0-rc.0", default-features = false }
21+
aead = { version = "0.6.0-rc.0", default-features = false, features = ["inout"] }
2222
aes = { version = "=0.9.0-pre.3", features = ["hazmat"], default-features = false }
23+
inout = { version = "0.2.0-rc.4", default-features = false }
2324
subtle = { version = "2", default-features = false }
2425
zeroize = { version = "1", optional = true, default-features = false }
2526

deoxys/src/lib.rs

Lines changed: 128 additions & 21 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

@@ -157,19 +157,19 @@ where
157157

158158
/// Encrypts the data in place with the specified parameters
159159
/// Returns the tag
160-
fn encrypt_in_place(
160+
fn encrypt_inout(
161161
nonce: &Array<u8, Self::NonceSize>,
162162
associated_data: &[u8],
163-
buffer: &mut [u8],
163+
buffer: InOutBuf<'_, '_, u8>,
164164
subkeys: &Array<DeoxysKey, B::SubkeysSize>,
165165
) -> Tag;
166166

167167
/// Decrypts the data in place with the specified parameters
168168
/// Returns an error if the tag verification fails
169-
fn decrypt_in_place(
169+
fn decrypt_inout(
170170
nonce: &Array<u8, Self::NonceSize>,
171171
associated_data: &[u8],
172-
buffer: &mut [u8],
172+
buffer: InOutBuf<'_, '_, u8>,
173173
tag: &Tag,
174174
subkeys: &Array<DeoxysKey, B::SubkeysSize>,
175175
) -> Result<(), aead::Error>;
@@ -185,44 +185,40 @@ pub trait DeoxysBcType: deoxys_bc::DeoxysBcInternal {
185185
fn precompute_subkeys(key: &Array<u8, Self::KeySize>) -> Array<DeoxysKey, Self::SubkeysSize>;
186186

187187
/// Encrypts a block of data in place.
188-
fn encrypt_in_place(
189-
block: &mut Block,
188+
fn encrypt_inout(
189+
mut block: InOut<'_, '_, Block>,
190190
tweak: &Tweak,
191191
subkeys: &Array<DeoxysKey, Self::SubkeysSize>,
192192
) {
193193
let keys = Self::key_schedule(tweak, subkeys);
194194

195-
for (b, k) in block.iter_mut().zip(keys[0].iter()) {
196-
*b ^= k;
197-
}
195+
block.xor_in2out(&keys[0]);
198196

199197
for k in &keys[1..] {
200-
aes::hazmat::cipher_round(block, k);
198+
aes::hazmat::cipher_round(block.get_out(), k);
201199
}
202200
}
203201

204202
/// Decrypts a block of data in place.
205-
fn decrypt_in_place(
206-
block: &mut Block,
203+
fn decrypt_inout(
204+
mut block: InOut<'_, '_, Block>,
207205
tweak: &Tweak,
208206
subkeys: &Array<DeoxysKey, Self::SubkeysSize>,
209207
) {
210208
let mut keys = Self::key_schedule(tweak, subkeys);
211209

212210
let r = keys.len();
213211

214-
for (b, k) in block.iter_mut().zip(keys[r - 1].iter()) {
215-
*b ^= k;
216-
}
212+
block.xor_in2out(&keys[r - 1]);
217213

218-
aes::hazmat::inv_mix_columns(block);
214+
aes::hazmat::inv_mix_columns(block.get_out());
219215

220216
for k in keys[..r - 1].iter_mut().rev() {
221217
aes::hazmat::inv_mix_columns(k);
222-
aes::hazmat::equiv_inv_cipher_round(block, k);
218+
aes::hazmat::equiv_inv_cipher_round(block.get_out(), k);
223219
}
224220

225-
aes::hazmat::mix_columns(block);
221+
aes::hazmat::mix_columns(block.get_out());
226222
}
227223
}
228224

@@ -286,7 +282,7 @@ where
286282
associated_data: &[u8],
287283
buffer: InOutBuf<'_, '_, u8>,
288284
) -> Result<Tag, Error> {
289-
Ok(Tag::from(M::encrypt_in_place(
285+
Ok(Tag::from(M::encrypt_inout(
290286
nonce,
291287
associated_data,
292288
buffer,
@@ -301,7 +297,7 @@ where
301297
buffer: InOutBuf<'_, '_, u8>,
302298
tag: &Tag,
303299
) -> Result<(), Error> {
304-
M::decrypt_in_place(nonce, associated_data, buffer, tag, &self.subkeys)
300+
M::decrypt_inout(nonce, associated_data, buffer, tag, &self.subkeys)
305301
}
306302
}
307303

@@ -328,3 +324,114 @@ where
328324
B: DeoxysBcType,
329325
{
330326
}
327+
328+
#[cfg(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+
use hex_literal::hex;
339+
340+
use super::*;
341+
342+
struct MockBuffer {
343+
in_buf: [u8; 33],
344+
out_buf: [u8; 33],
345+
}
346+
347+
impl From<&[u8]> for MockBuffer {
348+
fn from(buf: &[u8]) -> Self {
349+
let mut in_buf = [0u8; 33];
350+
in_buf.copy_from_slice(buf);
351+
Self {
352+
in_buf,
353+
out_buf: [0u8; 33],
354+
}
355+
}
356+
}
357+
358+
impl MockBuffer {
359+
/// Get an [`InOutBuf`] from a [`MockBuffer`]
360+
pub fn to_in_out_buf(&mut self) -> InOutBuf<'_, '_, u8> {
361+
InOutBuf::new(self.in_buf.as_slice(), self.out_buf.as_mut_slice())
362+
.expect("Invariant violation")
363+
}
364+
}
365+
366+
impl AsRef<[u8]> for MockBuffer {
367+
fn as_ref(&self) -> &[u8] {
368+
&self.out_buf
369+
}
370+
}
371+
372+
#[test]
373+
fn test_deoxys_i_128_5() {
374+
let plaintext = hex!("5a4c652cb880808707230679224b11799b5883431292973215e9bd03cf3bc32fe4");
375+
let mut buffer = MockBuffer::from(&plaintext[..]);
376+
377+
let aad = [];
378+
379+
let key = hex!("101112131415161718191a1b1c1d1e1f");
380+
let key = Array(key);
381+
382+
let nonce = hex!("202122232425262728292a2b2c2d2e2f");
383+
let nonce = Array::try_from(&nonce[..8]).unwrap();
384+
385+
let ciphertext_expected =
386+
hex!("cded5a43d3c76e942277c2a1517530ad66037897c985305ede345903ed7585a626");
387+
388+
let tag_expected: [u8; 16] = hex!("cbf5faa6b8398c47f4278d2019161776");
389+
390+
type M = modes::DeoxysI<deoxys_bc::DeoxysBc256>;
391+
let cipher = DeoxysI128::new(&key);
392+
let tag: Tag = M::encrypt_inout(&nonce, &aad, buffer.to_in_out_buf(), &cipher.subkeys);
393+
394+
let ciphertext = buffer.as_ref();
395+
assert_eq!(ciphertext, ciphertext_expected);
396+
assert_eq!(tag, tag_expected);
397+
398+
let mut buffer = MockBuffer::from(buffer.as_ref());
399+
M::decrypt_inout(&nonce, &aad, buffer.to_in_out_buf(), &tag, &cipher.subkeys)
400+
.expect("decryption failed");
401+
402+
assert_eq!(&plaintext[..], buffer.as_ref());
403+
}
404+
405+
#[test]
406+
fn test_deoxys_ii_128_5() {
407+
let plaintext = hex!("06ac1756eccece62bd743fa80c299f7baa3872b556130f52265919494bdc136db3");
408+
let mut buffer = MockBuffer::from(&plaintext[..]);
409+
410+
let aad = [];
411+
412+
let key = hex!("101112131415161718191a1b1c1d1e1f");
413+
let key = Array(key);
414+
415+
let nonce = hex!("202122232425262728292a2b2c2d2e2f");
416+
let nonce = Array::try_from(&nonce[..15]).unwrap();
417+
418+
let ciphertext_expected =
419+
hex!("82bf241958b324ed053555d23315d3cc20935527fc970ff34a9f521a95e302136d");
420+
421+
let tag_expected: [u8; 16] = hex!("0eadc8612d5208c491e93005195e9769");
422+
423+
type M = modes::DeoxysII<deoxys_bc::DeoxysBc256>;
424+
let cipher = DeoxysII128::new(&key);
425+
let tag: Tag = M::encrypt_inout(&nonce, &aad, buffer.to_in_out_buf(), &cipher.subkeys);
426+
427+
let ciphertext = buffer.as_ref();
428+
assert_eq!(ciphertext, ciphertext_expected);
429+
assert_eq!(tag, tag_expected);
430+
431+
let mut buffer = MockBuffer::from(buffer.as_ref());
432+
M::decrypt_inout(&nonce, &aad, buffer.to_in_out_buf(), &tag, &cipher.subkeys)
433+
.expect("decryption failed");
434+
435+
assert_eq!(&plaintext[..], buffer.as_ref());
436+
}
437+
}

0 commit comments

Comments
 (0)