diff --git a/.github/workflows/mgm.yml b/.github/workflows/mgm.yml index 4115bca3..2e50635e 100644 --- a/.github/workflows/mgm.yml +++ b/.github/workflows/mgm.yml @@ -56,5 +56,4 @@ jobs: - run: cargo test --release --no-default-features - run: cargo test --release - run: cargo test --release --features force-soft - - run: cargo test --release --features stream,std - run: RUSTFLAGS="-C target-cpu=native" cargo test --release --all-features diff --git a/Cargo.lock b/Cargo.lock index 2d9fe082..9ed16acb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -233,9 +233,9 @@ checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" [[package]] name = "cpufeatures" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" dependencies = [ "libc", ] @@ -359,12 +359,45 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "kuznyechik" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003764d77f5f2e2a57a4d17dc6547e0595f14a3c289283c9eeaf7170d3a4ff83" +dependencies = [ + "cfg-if", + "cipher", +] + [[package]] name = "libc" version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +[[package]] +name = "magma" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84fcdd6a71a6af65297be074d9d26cda7a2e98b86294ee0de0732b00c2063a61" +dependencies = [ + "cipher", +] + +[[package]] +name = "mgm" +version = "0.5.0-pre.1" +dependencies = [ + "aead", + "cfg-if", + "cipher", + "cpufeatures", + "ctutils", + "hex-literal", + "kuznyechik", + "magma", +] + [[package]] name = "ocb3" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index afd4bfa9..9e945dfc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ "chacha20poly1305", "deoxys", "eax", + "mgm", "ocb3", "xaes-256-gcm", ] diff --git a/mgm/CHANGELOG.md b/mgm/CHANGELOG.md index 271e2d58..02cef9b9 100644 --- a/mgm/CHANGELOG.md +++ b/mgm/CHANGELOG.md @@ -4,6 +4,15 @@ 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). +## 0.5.0 (UNRELEASED) +### Changed +- Bump `aead` to v0.6, `cipher` to v0.5 and `cpufeatures` to v0.3 +- Edition changed to 2024 and MSRV bumped to 1.85 +- Move into the workspace + +### Removed +- `std` and `stream` features + ## 0.4.6 (2021-09-01) ### Added - Target feature autodetection on x86(-64) targets ([#371]) diff --git a/mgm/Cargo.lock b/mgm/Cargo.lock deleted file mode 100644 index 8d76ca8b..00000000 --- a/mgm/Cargo.lock +++ /dev/null @@ -1,183 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "arrayvec", - "blobby", - "bytes", - "crypto-common", - "generic-array", -] - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "blobby" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "847495c209977a90e8aad588b959d0ca9f5dc228096d29a6bd3defd53f35eaec" - -[[package]] -name = "bytes" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array", -] - -[[package]] -name = "cmov" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" - -[[package]] -name = "cpufeatures" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core", - "typenum", -] - -[[package]] -name = "ctutils" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" -dependencies = [ - "cmov", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hex-literal" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" - -[[package]] -name = "kuznyechik" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a4e0a85306cf7cdcd497111b9ecd8df4da5290bacd3cc2f426ce3fb2c0a327e" -dependencies = [ - "cipher", -] - -[[package]] -name = "libc" -version = "0.2.169" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" - -[[package]] -name = "magma" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53792c7fca348c3d880c5ab2b0a2378a28edca57d080feabc4b60b4633dff91b" -dependencies = [ - "cipher", - "opaque-debug", -] - -[[package]] -name = "mgm" -version = "0.5.0-pre.1" -dependencies = [ - "aead", - "cfg-if", - "cipher", - "cpufeatures", - "ctutils", - "hex-literal", - "kuznyechik", - "magma", -] - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/mgm/Cargo.toml b/mgm/Cargo.toml index f4f607eb..ce5cae24 100644 --- a/mgm/Cargo.toml +++ b/mgm/Cargo.toml @@ -1,5 +1,3 @@ -[workspace] - [package] name = "mgm" version = "0.5.0-pre.1" @@ -16,27 +14,31 @@ keywords = ["encryption", "aead"] rust-version = "1.85" [dependencies] -aead = { version = "0.5", default-features = false } -cipher = "0.3" +aead = { version = "0.6", default-features = false } +cipher = "0.5" cfg-if = "1" ctutils = "0.4" [target.'cfg(any(target_arch = "x86_64", target_arch = "x86"))'.dependencies] -cpufeatures = "0.2" +cpufeatures = "0.3.1" [dev-dependencies] -aead = { version = "0.5", features = ["dev"], default-features = false } -kuznyechik = "0.7" -magma = "0.7" +aead = { version = "0.6", features = ["dev"], default-features = false } +kuznyechik = "0.9" +magma = "0.10" hex-literal = "1" [features] default = ["alloc", "getrandom"] -std = ["aead/std", "alloc"] alloc = ["aead/alloc"] arrayvec = ["aead/arrayvec"] bytes = ["aead/bytes"] -getrandom = ["aead/getrandom", "rand_core"] +getrandom = ["aead/getrandom"] rand_core = ["aead/rand_core"] -stream = ["aead/stream"] force-soft = [] # Disable support for hardware intrinsics + +[package.metadata.docs.rs] +all-features = true + +[lints] +workspace = true diff --git a/mgm/benches/mod.rs b/mgm/benches/mod.rs index c2447a5a..b807921e 100644 --- a/mgm/benches/mod.rs +++ b/mgm/benches/mod.rs @@ -1,32 +1,33 @@ +//! MGM benchmarks. + #![feature(test)] extern crate test; -use aead::{AeadInPlace, KeyInit, generic_array::GenericArray}; +use aead::{ + AeadInOut, KeyInit, + array::Array, + consts::{U16, U32}, +}; use hex_literal::hex; use kuznyechik::Kuznyechik; use mgm::Mgm; use test::Bencher; -#[rustfmt::skip] -const KEY: [u8; 32] = hex!(" - 8899AABBCCDDEEFF0011223344556677 - FEDCBA98765432100123456789ABCDEF -"); -#[rustfmt::skip] -const NONCE: [u8; 16] = hex!(" - 1122334455667700FFEEDDCCBBAA9988 -"); +const KEY: Array = Array(hex!( + "8899AABBCCDDEEFF0011223344556677" + "FEDCBA98765432100123456789ABCDEF" +)); +const NONCE: Array = Array(hex!("1122334455667700FFEEDDCCBBAA9988")); #[bench] fn encrypt_aad_only_16kb(b: &mut Bencher) { - let c = Mgm::::new(GenericArray::from_slice(&KEY)); - let nonce = GenericArray::from_slice(&NONCE); + let c = Mgm::::new(&KEY); let aad = vec![0; 16 * 1024]; let mut buf = []; b.iter(|| { - let (aad, buf) = test::black_box((&aad, &mut buf)); - let res = c.encrypt_in_place_detached(nonce, aad, buf).unwrap(); + let (aad, buf, nonce) = test::black_box((&aad, &mut buf[..], &NONCE)); + let res = c.encrypt_inout_detached(nonce, aad, buf.into()).unwrap(); test::black_box(res); }); @@ -35,14 +36,13 @@ fn encrypt_aad_only_16kb(b: &mut Bencher) { #[bench] fn encrypt_msg_only_16kb(b: &mut Bencher) { - let c = Mgm::::new(GenericArray::from_slice(&KEY)); - let nonce = GenericArray::from_slice(&NONCE); + let c = Mgm::::new(&KEY); let aad = []; let mut buf = vec![0; 16 * 1024]; b.iter(|| { - let (aad, buf) = test::black_box((&aad, &mut buf)); - let res = c.encrypt_in_place_detached(nonce, aad, buf).unwrap(); + let (aad, buf, nonce) = test::black_box((&aad, &mut buf[..], &NONCE)); + let res = c.encrypt_inout_detached(nonce, aad, buf.into()).unwrap(); test::black_box(res); }); @@ -51,17 +51,17 @@ fn encrypt_msg_only_16kb(b: &mut Bencher) { #[bench] fn decrypt_aad_only_16kb(b: &mut Bencher) { - let c = Mgm::::new(GenericArray::from_slice(&KEY)); - let nonce = GenericArray::from_slice(&NONCE); + let c = Mgm::::new(&KEY); let aad = vec![0; 16 * 1024]; let mut buf = []; - let tag = c.encrypt_in_place_detached(nonce, &aad, &mut []).unwrap(); + let tag = c + .encrypt_inout_detached(&NONCE, &aad, (&mut buf[..]).into()) + .unwrap(); - #[allow(unused_must_use)] b.iter(|| { - let (aad, buf, tag) = test::black_box((&aad, &mut buf, &tag)); - let res = c.decrypt_in_place_detached(nonce, aad, buf, tag); - test::black_box(res); + let (aad, buf, nonce, tag) = test::black_box((&aad, &mut buf[..], &NONCE, &tag)); + let res = c.decrypt_inout_detached(nonce, aad, buf.into(), tag); + let _ = test::black_box(res); }); b.bytes = 16 * 1024; @@ -69,18 +69,19 @@ fn decrypt_aad_only_16kb(b: &mut Bencher) { #[bench] fn decrypt_msg_only_16kb(b: &mut Bencher) { - let c = Mgm::::new(GenericArray::from_slice(&KEY)); - let nonce = GenericArray::from_slice(&NONCE); + let c = Mgm::::new(&KEY); let aad = []; - let mut buf = vec![0u8; 16 * 1024]; - let tag = c.encrypt_in_place_detached(nonce, &aad, &mut buf).unwrap(); + let mut ct_buf = vec![0u8; 16 * 1024]; + let tag = c + .encrypt_inout_detached(&NONCE, &aad, (&mut ct_buf[..]).into()) + .unwrap(); - #[allow(unused_must_use)] + let mut buf = ct_buf.clone(); b.iter(|| { - let mut buf_cpy = buf.clone(); - let (aad, buf, tag) = test::black_box((&aad, &mut buf_cpy, &tag)); - let res = c.decrypt_in_place_detached(nonce, aad, buf, tag); - test::black_box(res); + let (aad, buf, nonce, tag) = test::black_box((&aad, &mut buf[..], &NONCE, &tag)); + let res = c.decrypt_inout_detached(nonce, aad, buf.into(), tag); + let _ = test::black_box(res); + buf.copy_from_slice(&ct_buf); }); b.bytes = 16 * 1024; diff --git a/mgm/src/encdec.rs b/mgm/src/encdec.rs index 1eb39db3..3eaedaa5 100644 --- a/mgm/src/encdec.rs +++ b/mgm/src/encdec.rs @@ -1,306 +1,148 @@ use crate::{ + DecArgs, EncArgs, MgmBlockSize, gf::GfElement, sealed::{Counter, Sealed}, - DecArgs, EncArgs, MgmBlockSize, }; use aead::{ - generic_array::{ - typenum::{Unsigned, U16, U8}, - GenericArray, - }, Error, + array::{Array, typenum::Unsigned}, + consts::{U8, U16}, + inout::InOutBuf, }; -use cipher::{Block, BlockEncrypt, ParBlocks}; +use cipher::{Block, BlockCipherEncrypt}; use ctutils::CtEq; +/// Number of blocks passed to the cipher at once, so it can use its parallel backend. +const PAR_BLOCKS: usize = 8; + pub(crate) fn encrypt(args: EncArgs<'_, C>) -> Result, Error> where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, E64: GfElement, E128: GfElement, { + let (cipher, nonce, adata, mut buffer) = args; + apply_keystream(cipher, nonce, buffer.reborrow()); // ideally we would use type-level branching here match C::BlockSize::USIZE { - 8 => encrypt_inner::(args), - 16 => encrypt_inner::(args), + 8 => calc_tag::(cipher, nonce, adata, buffer.get_out()), + 16 => calc_tag::(cipher, nonce, adata, buffer.get_out()), _ => unreachable!(), } } pub(crate) fn decrypt(args: DecArgs<'_, C>) -> Result<(), Error> where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, E64: GfElement, E128: GfElement, { + let (cipher, nonce, adata, buffer, expected_tag) = args; // ideally we would use type-level branching here - match C::BlockSize::USIZE { - 8 => decrypt_inner::(args), - 16 => decrypt_inner::(args), + let tag = match C::BlockSize::USIZE { + 8 => calc_tag::(cipher, nonce, adata, buffer.get_in()), + 16 => calc_tag::(cipher, nonce, adata, buffer.get_in()), _ => unreachable!(), - } -} - -// E::N must be equal to C::BlockSize -fn encrypt_inner(args: EncArgs<'_, C>) -> Result, Error> -where - C: BlockEncrypt, - C::BlockSize: MgmBlockSize, - E: GfElement, -{ - let (cipher, nonce, mut adata, mut buffer) = args; - - let fin_block = C::BlockSize::lengths2block(adata.len(), buffer.len())?; - - let mut tag_ctr = nonce.clone(); - tag_ctr[0] |= 0b1000_0000; - cipher.encrypt_block(&mut tag_ctr); - let mut tag_ctr = C::BlockSize::block2ctr(&tag_ctr); - - let mut tag = E::new(); - - let pb = C::ParBlocks::USIZE; - let bs = C::BlockSize::USIZE; - - // process adata - if pb > 1 { - let mut iter = adata.chunks_exact(pb * bs); - for chunk in &mut iter { - update_par_tag(cipher, &mut tag, &mut tag_ctr, chunk); - } - adata = iter.remainder(); - }; + }?; - let mut iter = adata.chunks_exact(bs); - for block in (&mut iter).map(Block::::from_slice) { - update_tag(cipher, &mut tag, &mut tag_ctr, block); - } - let rem = iter.remainder(); - if !rem.is_empty() { - let mut block: Block = Default::default(); - block[..rem.len()].copy_from_slice(rem); - update_tag(cipher, &mut tag, &mut tag_ctr, &block); - } - - let mut enc_ctr = nonce.clone(); - enc_ctr[0] &= 0b0111_1111; - cipher.encrypt_block(&mut enc_ctr); - let mut enc_ctr = C::BlockSize::block2ctr(&enc_ctr); - - // process plaintext - if pb > 1 { - let mut iter = buffer.chunks_exact_mut(pb * bs); - for chunk in &mut iter { - apply_par_ks_blocks(cipher, &mut enc_ctr, chunk); - update_par_tag(cipher, &mut tag, &mut tag_ctr, chunk); - } - buffer = iter.into_remainder(); - } - - let mut iter = buffer.chunks_exact_mut(bs); - for block in (&mut iter).map(Block::::from_mut_slice) { - apply_ks_block(cipher, &mut enc_ctr, block); - update_tag(cipher, &mut tag, &mut tag_ctr, block); - } - let rem = iter.into_remainder(); - if !rem.is_empty() { - apply_ks_block(cipher, &mut enc_ctr, rem); - - let mut block = Block::::default(); - let n = rem.len(); - block[..n].copy_from_slice(rem); - update_tag(cipher, &mut tag, &mut tag_ctr, &block); + if !expected_tag.ct_eq(&tag).to_bool() { + return Err(Error); } - update_tag(cipher, &mut tag, &mut tag_ctr, &fin_block); - - let mut tag = GenericArray::clone_from_slice(&tag.into_bytes()); - cipher.encrypt_block(&mut tag); - - Ok(tag) + apply_keystream(cipher, nonce, buffer); + Ok(()) } // E::N must be equal to C::BlockSize -fn decrypt_inner(args: DecArgs<'_, C>) -> Result<(), Error> +fn calc_tag( + cipher: &C, + nonce: &Block, + adata: &[u8], + data: &[u8], +) -> Result, Error> where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, E: GfElement, { - let (cipher, nonce, mut adata, mut buffer, expected_tag) = args; - - let fin_block = C::BlockSize::lengths2block(adata.len(), buffer.len())?; + let fin_block = C::BlockSize::lengths2block(adata.len(), data.len())?; let mut tag_ctr = nonce.clone(); tag_ctr[0] |= 0b1000_0000; cipher.encrypt_block(&mut tag_ctr); - let mut tag_ctr = C::BlockSize::block2ctr(&tag_ctr); - let mut tag = E::new(); - let pb = C::ParBlocks::USIZE; + let mut tag = E::new(); let bs = C::BlockSize::USIZE; - // calculate tag - // process adata - if pb > 1 { - let mut iter = adata.chunks_exact(pb * bs); - for chunk in &mut iter { - update_par_tag(cipher, &mut tag, &mut tag_ctr, chunk); + // adata and data are padded with zeros to the block size separately + for chunk in adata + .chunks(PAR_BLOCKS * bs) + .chain(data.chunks(PAR_BLOCKS * bs)) + { + let mut par_h: [Block; PAR_BLOCKS] = Default::default(); + let par_h = &mut par_h[..chunk.len().div_ceil(bs)]; + for h in par_h.iter_mut() { + *h = C::BlockSize::ctr2block(&tag_ctr); + C::BlockSize::incr_l(&mut tag_ctr); } - adata = iter.remainder(); - }; - - let mut iter = adata.chunks_exact(bs); - for block in (&mut iter).map(Block::::from_slice) { - update_tag(cipher, &mut tag, &mut tag_ctr, block); - } - let rem = iter.remainder(); - if !rem.is_empty() { - let mut block: Block = Default::default(); - block[..rem.len()].copy_from_slice(rem); - update_tag(cipher, &mut tag, &mut tag_ctr, &block); - } + cipher.encrypt_blocks(par_h); - // process ciphertext - let buf = if pb > 1 { - let mut iter = buffer.chunks_exact(pb * bs); - for chunk in &mut iter { - update_par_tag(cipher, &mut tag, &mut tag_ctr, chunk); + for (h, block) in par_h.iter().zip(chunk.chunks(bs)) { + let mut padded = Block::::default(); + padded[..block.len()].copy_from_slice(block); + mul_sum(&mut tag, h, &padded); } - iter.remainder() - } else { - #[allow(clippy::needless_borrow)] - &buffer - }; - - let mut iter = buf.chunks_exact(bs); - for block in (&mut iter).map(Block::::from_slice) { - update_tag(cipher, &mut tag, &mut tag_ctr, block); - } - let rem = iter.remainder(); - if !rem.is_empty() { - let n = rem.len(); - - let mut block = Block::::default(); - block[..n].copy_from_slice(rem); - - update_tag(cipher, &mut tag, &mut tag_ctr, &block); } - update_tag(cipher, &mut tag, &mut tag_ctr, &fin_block); + let mut h = C::BlockSize::ctr2block(&tag_ctr); + cipher.encrypt_block(&mut h); + mul_sum(&mut tag, &h, &fin_block); - let mut tag = GenericArray::clone_from_slice(&tag.into_bytes()); + let mut tag = Block::::try_from(&tag.into_bytes()[..]).map_err(|_| Error)?; cipher.encrypt_block(&mut tag); - - if !expected_tag.ct_eq(&tag).to_bool() { - return Err(Error); - } - - // decrypt ciphertext - let mut dec_ctr = nonce.clone(); - dec_ctr[0] &= 0b0111_1111; - cipher.encrypt_block(&mut dec_ctr); - let mut dec_ctr = C::BlockSize::block2ctr(&dec_ctr); - - if pb > 1 { - let mut iter = buffer.chunks_exact_mut(pb * bs); - for chunk in &mut iter { - apply_par_ks_blocks(cipher, &mut dec_ctr, chunk); - } - buffer = iter.into_remainder(); - } - - let mut iter = buffer.chunks_exact_mut(bs); - for block in (&mut iter).map(Block::::from_mut_slice) { - apply_ks_block(cipher, &mut dec_ctr, block); - } - let rem = iter.into_remainder(); - if !rem.is_empty() { - apply_ks_block(cipher, &mut dec_ctr, rem); - } - - Ok(()) + Ok(tag) } +// panics if E::N != C::BlockSize #[inline(always)] -fn apply_ks_block(cipher: &C, ctr: &mut Counter, buf: &mut [u8]) -where - C: BlockEncrypt, - C::BlockSize: MgmBlockSize, -{ - let mut block = C::BlockSize::ctr2block(ctr); - cipher.encrypt_block(&mut block); - for i in 0..core::cmp::min(block.len(), buf.len()) { - buf[i] ^= block[i]; - } - C::BlockSize::incr_r(ctr); +fn mul_sum(tag: &mut E, h: &[u8], block: &[u8]) { + let h: &Array = h.try_into().expect("E::N == C::BlockSize"); + let block: &Array = block.try_into().expect("E::N == C::BlockSize"); + tag.mul_sum(h, block); } -#[inline(always)] -fn apply_par_ks_blocks(cipher: &C, ctr: &mut Counter, par_blocks: &mut [u8]) +fn apply_keystream(cipher: &C, nonce: &Block, mut buffer: InOutBuf<'_, '_, u8>) where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, { - let pb = C::ParBlocks::USIZE; - let bs = C::BlockSize::USIZE; - assert_eq!(par_blocks.len(), pb * bs); - - let mut par_ks = ParBlocks::::default(); - for ks in par_ks.iter_mut() { - *ks = C::BlockSize::ctr2block(ctr); - C::BlockSize::incr_r(ctr); - } - cipher.encrypt_par_blocks(&mut par_ks); + let mut ctr = nonce.clone(); + ctr[0] &= 0b0111_1111; + cipher.encrypt_block(&mut ctr); + let mut ctr: Counter = C::BlockSize::block2ctr(&ctr); - let iter = par_blocks.chunks_exact_mut(bs); - for (ks, block) in par_ks.iter().zip(iter) { - for i in 0..bs { - block[i] ^= ks[i]; + let bs = C::BlockSize::USIZE; + while !buffer.is_empty() { + let n = buffer.len().min(PAR_BLOCKS * bs); + let (mut chunk, tail) = buffer.split_at(n); + + let mut par_ks: [Block; PAR_BLOCKS] = Default::default(); + let par_ks = &mut par_ks[..n.div_ceil(bs)]; + for ks in par_ks.iter_mut() { + *ks = C::BlockSize::ctr2block(&ctr); + C::BlockSize::incr_r(&mut ctr); } - } -} + cipher.encrypt_blocks(par_ks); -#[inline(always)] -fn update_tag(cipher: &C, tag: &mut E, tag_ctr: &mut Counter, block: &Block) -where - C: BlockEncrypt, - C::BlockSize: MgmBlockSize, - E: GfElement, -{ - let mut h = C::BlockSize::ctr2block(tag_ctr); - cipher.encrypt_block(&mut h); - // panics if E::N != C::BlockSize - tag.mul_sum( - GenericArray::from_slice(&h), - GenericArray::from_slice(block), - ); - C::BlockSize::incr_l(tag_ctr); -} - -#[inline(always)] -fn update_par_tag(cipher: &C, tag: &mut E, tag_ctr: &mut Counter, par_blocks: &[u8]) -where - C: BlockEncrypt, - C::BlockSize: MgmBlockSize, - E: GfElement, -{ - let pb = C::ParBlocks::USIZE; - let bs = C::BlockSize::USIZE; - assert_eq!(par_blocks.len(), pb * bs); + let mut ks_bytes = [0u8; PAR_BLOCKS * 16]; + for (dst, ks) in ks_bytes.chunks_mut(bs).zip(par_ks.iter()) { + dst.copy_from_slice(ks); + } + chunk.xor_in2out(&ks_bytes[..n]); - let mut par_h = ParBlocks::::default(); - for h in par_h.iter_mut() { - *h = C::BlockSize::ctr2block(tag_ctr); - C::BlockSize::incr_l(tag_ctr); - } - cipher.encrypt_par_blocks(&mut par_h); - // panics if E::N != C::BlockSize - let iter = par_blocks.chunks_exact(bs).map(GenericArray::from_slice); - for (h, block) in par_h.iter().zip(iter) { - tag.mul_sum(GenericArray::from_slice(h), block); + buffer = tail; } } diff --git a/mgm/src/gf.rs b/mgm/src/gf.rs index 91c734c9..c96a3252 100644 --- a/mgm/src/gf.rs +++ b/mgm/src/gf.rs @@ -1,4 +1,4 @@ -use aead::generic_array::{ArrayLength, GenericArray}; +use aead::array::{Array, ArraySize}; mod utils; @@ -6,22 +6,46 @@ mod utils; any(target_arch = "x86_64", target_arch = "x86"), not(feature = "force-soft") ))] +#[allow( + unsafe_code, + clippy::undocumented_unsafe_blocks, + clippy::cast_possible_wrap, + clippy::unwrap_used, + reason = "CPU intrinsics" +)] pub(crate) mod gf128_pclmul; +#[allow( + clippy::cast_possible_truncation, + clippy::unwrap_used, + reason = "splitting into fixed-size words" +)] pub(crate) mod gf128_soft64; #[cfg(all( any(target_arch = "x86_64", target_arch = "x86"), not(feature = "force-soft") ))] +#[allow( + unsafe_code, + clippy::undocumented_unsafe_blocks, + clippy::cast_possible_wrap, + clippy::unwrap_used, + reason = "CPU intrinsics" +)] pub(crate) mod gf64_pclmul; +#[allow( + clippy::cast_possible_truncation, + clippy::unwrap_used, + reason = "splitting into fixed-size words" +)] pub(crate) mod gf64_soft64; pub trait GfElement { - type N: ArrayLength; + type N: ArraySize; fn new() -> Self; - fn into_bytes(self) -> GenericArray; - fn mul_sum(&mut self, a: &GenericArray, b: &GenericArray); + fn into_bytes(self) -> Array; + fn mul_sum(&mut self, a: &Array, b: &Array); } diff --git a/mgm/src/gf/gf128_pclmul.rs b/mgm/src/gf/gf128_pclmul.rs index 9d66e38d..3032d868 100644 --- a/mgm/src/gf/gf128_pclmul.rs +++ b/mgm/src/gf/gf128_pclmul.rs @@ -4,14 +4,14 @@ //! More information can be found in the Intel whitepaper: //! https://software.intel.com/sites/default/files/managed/72/cc/clmul-wp-rev-2.02-2014-04-20.pdf use super::GfElement; -use aead::{consts::U16, generic_array::GenericArray}; +use aead::{array::Array, consts::U16}; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; -type Block = GenericArray; +type Block = Array; const BS_MASK1: i64 = 0x0001_0203_0405_0607; const BS_MASK2: i64 = 0x0809_0A0B_0C0D_0E0F; @@ -40,8 +40,8 @@ impl GfElement for Element { unsafe { let bs_mask = _mm_set_epi64x(BS_MASK1, BS_MASK2); - let a = _mm_loadu_si128(a.as_ptr() as *const _); - let b = _mm_loadu_si128(b.as_ptr() as *const _); + let a = _mm_loadu_si128(a.as_ptr().cast()); + let b = _mm_loadu_si128(b.as_ptr().cast()); let a = _mm_shuffle_epi8(a, bs_mask); let b = _mm_shuffle_epi8(b, bs_mask); diff --git a/mgm/src/gf/gf128_soft64.rs b/mgm/src/gf/gf128_soft64.rs index f2569153..a71f588a 100644 --- a/mgm/src/gf/gf128_soft64.rs +++ b/mgm/src/gf/gf128_soft64.rs @@ -1,9 +1,9 @@ use super::{GfElement, utils::bmul64}; -use aead::{consts::U16, generic_array::GenericArray}; +use aead::{array::Array, consts::U16}; pub struct Element(u64, u64); -type Block = GenericArray; +type Block = Array; impl GfElement for Element { type N = U16; diff --git a/mgm/src/gf/gf64_pclmul.rs b/mgm/src/gf/gf64_pclmul.rs index eaaee291..45494467 100644 --- a/mgm/src/gf/gf64_pclmul.rs +++ b/mgm/src/gf/gf64_pclmul.rs @@ -2,14 +2,14 @@ //! on `x86` and `x86_64` target architectures. use super::GfElement; -use aead::{consts::U8, generic_array::GenericArray}; +use aead::{array::Array, consts::U8}; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; -type Block = GenericArray; +type Block = Array; pub struct Element(u64); diff --git a/mgm/src/gf/gf64_soft64.rs b/mgm/src/gf/gf64_soft64.rs index 822cdcf8..f571ad1e 100644 --- a/mgm/src/gf/gf64_soft64.rs +++ b/mgm/src/gf/gf64_soft64.rs @@ -1,9 +1,9 @@ use super::{GfElement, utils::bmul64}; -use aead::{consts::U8, generic_array::GenericArray}; +use aead::{array::Array, consts::U8}; pub struct Element(u64); -type Block = GenericArray; +type Block = Array; impl GfElement for Element { type N = U8; diff --git a/mgm/src/gf/utils.rs b/mgm/src/gf/utils.rs index 0c7b7f97..7c988140 100644 --- a/mgm/src/gf/utils.rs +++ b/mgm/src/gf/utils.rs @@ -7,14 +7,14 @@ use core::num::Wrapping; /// When carries do occur, they wind up in a "hole" and are subsequently masked /// out of the result. pub(super) fn bmul64(x: u64, y: u64) -> u128 { - let x0 = Wrapping((x & 0x1111_1111_1111_1111) as u128); - let x1 = Wrapping((x & 0x2222_2222_2222_2222) as u128); - let x2 = Wrapping((x & 0x4444_4444_4444_4444) as u128); - let x3 = Wrapping((x & 0x8888_8888_8888_8888) as u128); - let y0 = Wrapping((y & 0x1111_1111_1111_1111) as u128); - let y1 = Wrapping((y & 0x2222_2222_2222_2222) as u128); - let y2 = Wrapping((y & 0x4444_4444_4444_4444) as u128); - let y3 = Wrapping((y & 0x8888_8888_8888_8888) as u128); + let x0 = Wrapping(u128::from(x & 0x1111_1111_1111_1111)); + let x1 = Wrapping(u128::from(x & 0x2222_2222_2222_2222)); + let x2 = Wrapping(u128::from(x & 0x4444_4444_4444_4444)); + let x3 = Wrapping(u128::from(x & 0x8888_8888_8888_8888)); + let y0 = Wrapping(u128::from(y & 0x1111_1111_1111_1111)); + let y1 = Wrapping(u128::from(y & 0x2222_2222_2222_2222)); + let y2 = Wrapping(u128::from(y & 0x4444_4444_4444_4444)); + let y3 = Wrapping(u128::from(y & 0x8888_8888_8888_8888)); let mut z0 = ((x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1)).0; let mut z1 = ((x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2)).0; diff --git a/mgm/src/lib.rs b/mgm/src/lib.rs index 1e4c6f4f..03d9e8f2 100644 --- a/mgm/src/lib.rs +++ b/mgm/src/lib.rs @@ -7,22 +7,22 @@ #![warn(missing_docs, rust_2018_idioms)] //! # Usage Example -#![cfg_attr(all(feature = "getrandom", feature = "std"), doc = "```")] -#![cfg_attr(not(all(feature = "getrandom", feature = "std")), doc = "```ignore")] -//! # fn main() -> Result<(), Box> { +#![cfg_attr(feature = "alloc", doc = "```")] +#![cfg_attr(not(feature = "alloc"), doc = "```ignore")] +//! # fn main() -> Result<(), Box> { //! use kuznyechik::Kuznyechik; //! use mgm::Mgm; -//! use mgm::aead::{Aead, KeyInit, OsRng, generic_array::GenericArray}; +//! use mgm::aead::{Aead, KeyInit, array::Array}; //! -//! let key = Mgm::::generate_key(&mut OsRng); +//! let key = Array::from([42u8; 32]); //! let cipher = Mgm::::new(&key); //! //! // 127-bit nonce value, since API has to accept 128 bits, first nonce bit //! // MUST be equal to zero, otherwise encryption and decryption will fail -//! let nonce = GenericArray::from_slice(b"unique nonce val"); +//! let nonce = Array(*b"unique nonce val"); //! -//! let ciphertext = cipher.encrypt(nonce, b"plaintext message".as_ref())?; -//! let plaintext = cipher.decrypt(nonce, ciphertext.as_ref())?; +//! let ciphertext = cipher.encrypt(&nonce, b"plaintext message".as_ref())?; +//! let plaintext = cipher.decrypt(&nonce, ciphertext.as_ref())?; //! //! assert_eq!(&plaintext, b"plaintext message"); //! # Ok(()) @@ -30,11 +30,11 @@ //! ``` use aead::{ - AeadCore, AeadInPlace, Error, Key, KeyInit, KeySizeUser, consts::U0, - generic_array::GenericArray, + AeadCore, AeadInOut, Error, Key, KeyInit, KeySizeUser, TagPosition, array::Array, + inout::InOutBuf, }; use cfg_if::cfg_if; -use cipher::{BlockCipher, BlockEncrypt, NewBlockCipher}; +use cipher::{BlockCipherEncrypt, BlockSizeUser}; pub use aead; @@ -48,20 +48,26 @@ use sealed::Sealed; cpufeatures::new!(mul_intrinsics, "sse2", "ssse3", "pclmulqdq"); /// MGM nonces -pub type Nonce = GenericArray; +pub type Nonce = Array; /// MGM tags -pub type Tag = GenericArray; +pub type Tag = Array; -type Block = GenericArray::BlockSize>; +type Block = Array::BlockSize>; // cipher, nonce, aad, buffer -type EncArgs<'a, C> = (&'a C, &'a Block, &'a [u8], &'a mut [u8]); +type EncArgs<'a, C> = (&'a C, &'a Block, &'a [u8], InOutBuf<'a, 'a, u8>); // cipher, nonce, aad, buf, expected_tag -type DecArgs<'a, C> = (&'a C, &'a Block, &'a [u8], &'a mut [u8], &'a Block); +type DecArgs<'a, C> = ( + &'a C, + &'a Block, + &'a [u8], + InOutBuf<'a, 'a, u8>, + &'a Block, +); /// Trait implemented for block cipher sizes usable with MGM. // ideally we would use type level set, i.e. `U8 | U16` -pub trait MgmBlockSize: sealed::Sealed {} +pub trait MgmBlockSize: Sealed {} impl MgmBlockSize for T {} @@ -69,7 +75,7 @@ impl MgmBlockSize for T {} #[derive(Clone, Debug)] pub struct Mgm where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, { cipher: C, @@ -77,7 +83,7 @@ where impl From for Mgm where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, { fn from(cipher: C) -> Self { @@ -87,7 +93,7 @@ where impl KeySizeUser for Mgm where - C: BlockEncrypt + NewBlockCipher, + C: BlockCipherEncrypt + KeyInit, C::BlockSize: MgmBlockSize, { type KeySize = C::KeySize; @@ -95,7 +101,7 @@ where impl KeyInit for Mgm where - C: BlockEncrypt + NewBlockCipher, + C: BlockCipherEncrypt + KeyInit, C::BlockSize: MgmBlockSize, { fn new(key: &Key) -> Self { @@ -105,24 +111,24 @@ where impl AeadCore for Mgm where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, { type NonceSize = C::BlockSize; type TagSize = C::BlockSize; - type CiphertextOverhead = U0; + const TAG_POSITION: TagPosition = TagPosition::Postfix; } -impl AeadInPlace for Mgm +impl AeadInOut for Mgm where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, { - fn encrypt_in_place_detached( + fn encrypt_inout_detached( &self, nonce: &Nonce, adata: &[u8], - buffer: &mut [u8], + buffer: InOutBuf<'_, '_, u8>, ) -> Result, Error> { // first nonce bit must be equal to zero if nonce[0] >> 7 != 0 { @@ -131,11 +137,11 @@ where mgm_encrypt((&self.cipher, nonce, adata, buffer)) } - fn decrypt_in_place_detached( + fn decrypt_inout_detached( &self, nonce: &Nonce, adata: &[u8], - buffer: &mut [u8], + buffer: InOutBuf<'_, '_, u8>, expected_tag: &Tag, ) -> Result<(), Error> { // first nonce bit must be equal to zero @@ -151,15 +157,17 @@ cfg_if! { any(target_arch = "x86_64", target_arch = "x86"), not(feature = "force-soft") ))] { + #[allow(unsafe_code, reason = "CPU intrinsics")] #[target_feature(enable = "pclmulqdq")] #[target_feature(enable = "ssse3")] #[target_feature(enable = "sse2")] unsafe fn wrapper(f: impl FnOnce() -> R) -> R { f() } + #[allow(unsafe_code, reason = "CPU intrinsics")] fn mgm_encrypt(args: EncArgs<'_, C>) -> Result, Error> where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, { if mul_intrinsics::get() { @@ -179,9 +187,10 @@ cfg_if! { } } + #[allow(unsafe_code, reason = "CPU intrinsics")] fn mgm_decrypt(args: DecArgs<'_, C>) -> Result<(), Error> where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, { if mul_intrinsics::get() { @@ -203,7 +212,7 @@ cfg_if! { } else { fn mgm_encrypt(args: EncArgs<'_, C>) -> Result, Error> where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, { encdec::encrypt::(args) @@ -211,7 +220,7 @@ cfg_if! { fn mgm_decrypt(args: DecArgs<'_, C>) -> Result<(), Error> where - C: BlockEncrypt, + C: BlockCipherEncrypt, C::BlockSize: MgmBlockSize, { encdec::decrypt::(args) diff --git a/mgm/src/sealed.rs b/mgm/src/sealed.rs index dfa5573f..3700a02b 100644 --- a/mgm/src/sealed.rs +++ b/mgm/src/sealed.rs @@ -1,116 +1,71 @@ use aead::{ Error, - generic_array::{ - ArrayLength, GenericArray, - typenum::{U8, U16}, - }, + array::{Array, ArraySize}, + consts::{U8, U16}, }; -use cipher::BlockCipher; +use cipher::BlockSizeUser; -pub type Counter = [<::BlockSize as Sealed>::Counter; 2]; +pub type Counter = [<::BlockSize as Sealed>::Counter; 2]; -pub trait Sealed: ArrayLength { +pub trait Sealed: ArraySize { type Counter; - fn block2ctr(block: &GenericArray) -> [Self::Counter; 2]; - fn ctr2block(ctr: &[Self::Counter; 2]) -> GenericArray; + fn block2ctr(block: &Array) -> [Self::Counter; 2]; + fn ctr2block(ctr: &[Self::Counter; 2]) -> Array; fn incr_l(ctr: &mut [Self::Counter; 2]); fn incr_r(ctr: &mut [Self::Counter; 2]); - fn lengths2block(adata_len: usize, data_len: usize) -> Result, Error>; + fn lengths2block(adata_len: usize, data_len: usize) -> Result, Error>; } -impl Sealed for U16 { - type Counter = u64; +macro_rules! impl_sealed { + ($size:ty, $counter:ty, $half:literal) => { + impl Sealed for $size { + type Counter = $counter; - #[inline(always)] - fn block2ctr(block: &GenericArray) -> [Self::Counter; 2] { - let (a, b) = block.split_at(8); - [ - u64::from_be_bytes(a.try_into().unwrap()), - u64::from_be_bytes(b.try_into().unwrap()), - ] - } + #[inline(always)] + fn block2ctr(block: &Array) -> [Self::Counter; 2] { + let (a, b) = block.split_at($half); + [ + <$counter>::from_be_bytes(a.try_into().unwrap()), + <$counter>::from_be_bytes(b.try_into().unwrap()), + ] + } - #[inline(always)] - fn ctr2block(ctr: &[Self::Counter; 2]) -> GenericArray { - let a = ctr[0].to_be_bytes(); - let b = ctr[1].to_be_bytes(); - let mut block = GenericArray::::default(); - block[..8].copy_from_slice(&a); - block[8..].copy_from_slice(&b); - block - } + #[inline(always)] + fn ctr2block(ctr: &[Self::Counter; 2]) -> Array { + let mut block = Array::::default(); + block[..$half].copy_from_slice(&ctr[0].to_be_bytes()); + block[$half..].copy_from_slice(&ctr[1].to_be_bytes()); + block + } - #[inline(always)] - fn incr_l(ctr: &mut [Self::Counter; 2]) { - ctr[0] = ctr[0].wrapping_add(1); - } + #[inline(always)] + fn incr_l(ctr: &mut [Self::Counter; 2]) { + ctr[0] = ctr[0].wrapping_add(1); + } - #[inline(always)] - fn incr_r(ctr: &mut [Self::Counter; 2]) { - ctr[1] = ctr[1].wrapping_add(1); - } + #[inline(always)] + fn incr_r(ctr: &mut [Self::Counter; 2]) { + ctr[1] = ctr[1].wrapping_add(1); + } - #[inline(always)] - fn lengths2block(adata_len: usize, data_len: usize) -> Result, Error> { - let adata_len = adata_len - .checked_mul(8) - .ok_or(Error)? - .try_into() - .map_err(|_| Error)?; - let data_len = data_len - .checked_mul(8) - .ok_or(Error)? - .try_into() - .map_err(|_| Error)?; - Ok(Self::ctr2block(&[adata_len, data_len])) - } + #[inline(always)] + fn lengths2block(adata_len: usize, data_len: usize) -> Result, Error> { + let adata_len = adata_len + .checked_mul(8) + .ok_or(Error)? + .try_into() + .map_err(|_| Error)?; + let data_len = data_len + .checked_mul(8) + .ok_or(Error)? + .try_into() + .map_err(|_| Error)?; + Ok(Self::ctr2block(&[adata_len, data_len])) + } + } + }; } -impl Sealed for U8 { - type Counter = u32; - - #[inline(always)] - fn block2ctr(block: &GenericArray) -> [Self::Counter; 2] { - let (a, b) = block.split_at(4); - [ - u32::from_be_bytes(a.try_into().unwrap()), - u32::from_be_bytes(b.try_into().unwrap()), - ] - } - - #[inline(always)] - fn ctr2block(ctr: &[Self::Counter; 2]) -> GenericArray { - let a = ctr[0].to_be_bytes(); - let b = ctr[1].to_be_bytes(); - let mut block = GenericArray::::default(); - block[..4].copy_from_slice(&a); - block[4..].copy_from_slice(&b); - block - } - - #[inline(always)] - fn incr_l(ctr: &mut [Self::Counter; 2]) { - ctr[0] = ctr[0].wrapping_add(1); - } - - #[inline(always)] - fn incr_r(ctr: &mut [Self::Counter; 2]) { - ctr[1] = ctr[1].wrapping_add(1); - } - - #[inline(always)] - fn lengths2block(adata_len: usize, data_len: usize) -> Result, Error> { - let adata_len = adata_len - .checked_mul(8) - .ok_or(Error)? - .try_into() - .map_err(|_| Error)?; - let data_len = data_len - .checked_mul(8) - .ok_or(Error)? - .try_into() - .map_err(|_| Error)?; - Ok(Self::ctr2block(&[adata_len, data_len])) - } -} +impl_sealed!(U16, u64, 8); +impl_sealed!(U8, u32, 4); diff --git a/mgm/tests/bad_nonce.rs b/mgm/tests/bad_nonce.rs index c2618407..e5155ad7 100644 --- a/mgm/tests/bad_nonce.rs +++ b/mgm/tests/bad_nonce.rs @@ -2,14 +2,14 @@ #![cfg(feature = "alloc")] -use aead::{Aead, KeyInit, generic_array::GenericArray}; +use aead::{Aead, KeyInit, array::Array}; use mgm::Mgm; #[test] fn kuznyechik_bad_nonce() { - let key = GenericArray::from_slice(&[0u8; 32]); - let mut nonce = GenericArray::clone_from_slice(&[0u8; 16]); - let cipher = Mgm::::new(key); + let key = Array([0u8; 32]); + let mut nonce = Array([0u8; 16]); + let cipher = Mgm::::new(&key); let mut enc_data = cipher.encrypt(&nonce, &[][..]).unwrap(); let res = cipher.decrypt(&nonce, &enc_data[..]); assert!(res.is_ok()); diff --git a/mgm/tests/data/kuznyechik.blb b/mgm/tests/data/kuznyechik.blb index 36744c8e..aefc6c07 100644 Binary files a/mgm/tests/data/kuznyechik.blb and b/mgm/tests/data/kuznyechik.blb differ diff --git a/mgm/tests/data/magma.blb b/mgm/tests/data/magma.blb index 0315675f..5c71ee98 100644 Binary files a/mgm/tests/data/magma.blb and b/mgm/tests/data/magma.blb differ diff --git a/mgm/tests/rfc9058.rs b/mgm/tests/rfc9058.rs index bd2ee6e1..5242cb66 100644 --- a/mgm/tests/rfc9058.rs +++ b/mgm/tests/rfc9058.rs @@ -2,5 +2,5 @@ #![cfg(feature = "alloc")] -aead::new_test!(kuznyechik, "kuznyechik", mgm::Mgm); -aead::new_test!(magma, "magma", mgm::Mgm); +aead::new_pass_test!(kuznyechik, "kuznyechik", mgm::Mgm); +aead::new_pass_test!(magma, "magma", mgm::Mgm);