From b0d917067636c9f7dad7865ed9a5ef349c8c9b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Tue, 25 Mar 2025 01:17:36 +0300 Subject: [PATCH 1/2] deoxys: tweak `DeoxysMode::encrypt/decrypt_inout` methods --- deoxys/src/modes.rs | 180 +++++++++++++++++++++----------------------- 1 file changed, 87 insertions(+), 93 deletions(-) diff --git a/deoxys/src/modes.rs b/deoxys/src/modes.rs index 0f91ec36..aedc063d 100644 --- a/deoxys/src/modes.rs +++ b/deoxys/src/modes.rs @@ -111,75 +111,71 @@ where tweak[8] = nonce[7] << 4; // Message authentication and encryption - if !buffer.is_empty() { - tweak[0] = (tweak[0] & 0xf) | TWEAK_M; - let (data_blocks, tail) = buffer.into_chunks(); - let data_blocks_len = data_blocks.len(); + tweak[0] = (tweak[0] & 0xf) | TWEAK_M; - for (index, data) in data_blocks.into_iter().enumerate() { - // Copy block number - let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&(index as u64).to_be_bytes()); - tweak[8] = (tweak[8] & 0xf) | tmp; + let (data_blocks, mut tail) = buffer.into_chunks(); + let data_blocks_len = data_blocks.len(); - for (c, d) in checksum.iter_mut().zip(data.get_in().iter()) { - *c ^= d; - } + for (index, data) in data_blocks.into_iter().enumerate() { + // Copy block number + let tmp = tweak[8] & 0xf0; + tweak[8..].copy_from_slice(&(index as u64).to_be_bytes()); + tweak[8] = (tweak[8] & 0xf) | tmp; - B::encrypt_inout(data, &tweak, subkeys); + for (c, d) in checksum.iter_mut().zip(data.get_in().iter()) { + *c ^= d; } - let mut data = tail; - let index = data_blocks_len; - if !data.is_empty() { - // Last block, incomplete + B::encrypt_inout(data, &tweak, subkeys); + } - // Copy block number - let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&(index as u64).to_be_bytes()); - tweak[8] = (tweak[8] & 0xf) | tmp; + if tail.is_empty() { + // Tag computing without last block + tweak[0] = (tweak[0] & 0xf) | TWEAK_TAG; - // Last block checksum - tweak[0] = (tweak[0] & 0xf) | TWEAK_M_LAST; + let tmp = tweak[8] & 0xf0; + tweak[8..].copy_from_slice(&((buffer_len / 16) as u64).to_be_bytes()); + tweak[8] = (tweak[8] & 0xf) | tmp; - let mut block = Block::default(); - block[0..data.len()].copy_from_slice(data.get_in()); + B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); - block[data.len()] = 0x80; + for (t, c) in tag.iter_mut().zip(checksum.iter()) { + *t ^= c; + } + } else { + // Tag computing with incomplete last block + let index = data_blocks_len; - for (c, d) in checksum.iter_mut().zip(block.iter()) { - *c ^= d; - } + // Copy block number + let tmp = tweak[8] & 0xf0; + tweak[8..].copy_from_slice(&(index as u64).to_be_bytes()); + tweak[8] = (tweak[8] & 0xf) | tmp; - block.fill(0); + // Last block checksum + tweak[0] = (tweak[0] & 0xf) | TWEAK_M_LAST; - // Last block encryption - B::encrypt_inout((&mut block).into(), &tweak, subkeys); + let mut block = Block::default(); + block[..tail.len()].copy_from_slice(tail.get_in()); - data.xor_in2out((block[..data.len()]).into()); + block[tail.len()] = 0x80; - // Tag computing. - tweak[0] = (tweak[0] & 0xf) | TWEAK_CHKSUM; + for (c, d) in checksum.iter_mut().zip(block.iter()) { + *c ^= d; + } - let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&((index + 1) as u64).to_be_bytes()); - tweak[8] = (tweak[8] & 0xf) | tmp; + block.fill(0); - B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); + // Last block encryption + B::encrypt_inout((&mut block).into(), &tweak, subkeys); - for (t, c) in tag.iter_mut().zip(checksum.iter()) { - *t ^= c; - } - } - } + tail.xor_in2out((block[..tail.len()]).into()); - if buffer_len % 16 == 0 { - // Tag computing without last block - tweak[0] = (tweak[0] & 0xf) | TWEAK_TAG; + // Tag computing. + tweak[0] = (tweak[0] & 0xf) | TWEAK_CHKSUM; let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&((buffer_len / 16) as u64).to_be_bytes()); + tweak[8..].copy_from_slice(&((index + 1) as u64).to_be_bytes()); tweak[8] = (tweak[8] & 0xf) | tmp; B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); @@ -221,71 +217,69 @@ where tweak[8] = nonce[7] << 4; // Message authentication and encryption - if !buffer.is_empty() { - tweak[0] = (tweak[0] & 0xf) | TWEAK_M; - let (data_blocks, tail) = buffer.into_chunks(); - let data_blocks_len = data_blocks.len(); + tweak[0] = (tweak[0] & 0xf) | TWEAK_M; - for (index, mut data) in data_blocks.into_iter().enumerate() { - // Copy block number - let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&(index as u64).to_be_bytes()); - tweak[8] = (tweak[8] & 0xf) | tmp; + let (data_blocks, mut tail) = buffer.into_chunks(); + let data_blocks_len = data_blocks.len(); - B::decrypt_inout(data.reborrow(), tweak.as_ref(), subkeys); + for (index, mut data) in data_blocks.into_iter().enumerate() { + // Copy block number + let tmp = tweak[8] & 0xf0; + tweak[8..].copy_from_slice(&(index as u64).to_be_bytes()); + tweak[8] = (tweak[8] & 0xf) | tmp; - for (c, d) in checksum.iter_mut().zip(data.get_out().iter()) { - *c ^= d; - } + B::decrypt_inout(data.reborrow(), tweak.as_ref(), subkeys); + + for (c, d) in checksum.iter_mut().zip(data.get_out().iter()) { + *c ^= d; } + } - let mut data = tail; - let index = data_blocks_len; - if !data.is_empty() { - // Copy block number - let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&(index as u64).to_be_bytes()); - tweak[8] = (tweak[8] & 0xf) | tmp; + if tail.is_empty() { + // Tag computing without last block + tweak[0] = (tweak[0] & 0xf) | TWEAK_TAG; - // Last block checksum - tweak[0] = (tweak[0] & 0xf) | TWEAK_M_LAST; + let tmp = tweak[8] & 0xf0; + tweak[8..].copy_from_slice(&((buffer_len / 16) as u64).to_be_bytes()); + tweak[8] = (tweak[8] & 0xf) | tmp; - let mut block = Block::default(); - B::encrypt_inout((&mut block).into(), tweak.as_ref(), subkeys); + B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); - data.xor_in2out((block[..data.len()]).into()); + for (t, c) in computed_tag.iter_mut().zip(checksum.iter()) { + *t ^= c; + } + } else { + // Tag computing with incomplete last block + let index = data_blocks_len; - block.fill(0); + // Copy block number + let tmp = tweak[8] & 0xf0; + tweak[8..].copy_from_slice(&(index as u64).to_be_bytes()); + tweak[8] = (tweak[8] & 0xf) | tmp; - block[0..data.len()].copy_from_slice(data.get_out()); - block[data.len()] = 0x80; + // Last block checksum + tweak[0] = (tweak[0] & 0xf) | TWEAK_M_LAST; - for (c, d) in checksum.iter_mut().zip(block.iter()) { - *c ^= d; - } + let mut block = Block::default(); + B::encrypt_inout((&mut block).into(), tweak.as_ref(), subkeys); - // Tag computing. - tweak[0] = (tweak[0] & 0xf) | TWEAK_CHKSUM; + tail.xor_in2out((block[..tail.len()]).into()); - let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&((index + 1) as u64).to_be_bytes()); - tweak[8] = (tweak[8] & 0xf) | tmp; + block.fill(0); - B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); + block[..tail.len()].copy_from_slice(tail.get_out()); + block[tail.len()] = 0x80; - for (t, c) in computed_tag.iter_mut().zip(checksum.iter()) { - *t ^= c; - } + for (c, d) in checksum.iter_mut().zip(block.iter()) { + *c ^= d; } - } - if buffer_len % 16 == 0 { - // Tag computing without last block - tweak[0] = (tweak[0] & 0xf) | TWEAK_TAG; + // Tag computing. + tweak[0] = (tweak[0] & 0xf) | TWEAK_CHKSUM; let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&((buffer_len / 16) as u64).to_be_bytes()); + tweak[8..].copy_from_slice(&((index + 1) as u64).to_be_bytes()); tweak[8] = (tweak[8] & 0xf) | tmp; B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); From faa4172b541c7ccc9edb444ba61d6bd4adb4a7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Tue, 25 Mar 2025 02:20:05 +0300 Subject: [PATCH 2/2] Remove separate branch for complete blocks --- deoxys/src/modes.rs | 99 ++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 60 deletions(-) diff --git a/deoxys/src/modes.rs b/deoxys/src/modes.rs index aedc063d..a4e01bb9 100644 --- a/deoxys/src/modes.rs +++ b/deoxys/src/modes.rs @@ -92,7 +92,6 @@ where let mut tag = Tag::default(); let mut checksum = Checksum::default(); let mut tweak = Tweak::default(); - let buffer_len = buffer.len(); // Associated Data >::compute_ad_tag( @@ -115,7 +114,7 @@ where tweak[0] = (tweak[0] & 0xf) | TWEAK_M; let (data_blocks, mut tail) = buffer.into_chunks(); - let data_blocks_len = data_blocks.len(); + let mut data_blocks_len = data_blocks.len(); for (index, data) in data_blocks.into_iter().enumerate() { // Copy block number @@ -130,26 +129,11 @@ where B::encrypt_inout(data, &tweak, subkeys); } - if tail.is_empty() { - // Tag computing without last block - tweak[0] = (tweak[0] & 0xf) | TWEAK_TAG; - - let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&((buffer_len / 16) as u64).to_be_bytes()); - tweak[8] = (tweak[8] & 0xf) | tmp; - - B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); - - for (t, c) in tag.iter_mut().zip(checksum.iter()) { - *t ^= c; - } - } else { - // Tag computing with incomplete last block - let index = data_blocks_len; - + // Process incomplete last block + if !tail.is_empty() { // Copy block number let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&(index as u64).to_be_bytes()); + tweak[8..].copy_from_slice(&(data_blocks_len as u64).to_be_bytes()); tweak[8] = (tweak[8] & 0xf) | tmp; // Last block checksum @@ -171,18 +155,23 @@ where tail.xor_in2out((block[..tail.len()]).into()); - // Tag computing. - tweak[0] = (tweak[0] & 0xf) | TWEAK_CHKSUM; - - let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&((index + 1) as u64).to_be_bytes()); - tweak[8] = (tweak[8] & 0xf) | tmp; + data_blocks_len += 1; + }; - B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); - - for (t, c) in tag.iter_mut().zip(checksum.iter()) { - *t ^= c; - } + // Tag computing. + let t = if tail.is_empty() { + TWEAK_TAG + } else { + TWEAK_CHKSUM + }; + tweak[0] = (tweak[0] & 0xf) | t; + let tmp = tweak[8] & 0xf0; + tweak[8..].copy_from_slice(&(data_blocks_len as u64).to_be_bytes()); + tweak[8] = (tweak[8] & 0xf) | tmp; + + B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); + for (t, c) in tag.iter_mut().zip(checksum.iter()) { + *t ^= c; } tag @@ -198,7 +187,6 @@ where let mut computed_tag = Tag::default(); let mut checksum = Checksum::default(); let mut tweak = Tweak::default(); - let buffer_len = buffer.len(); // Associated Data >::compute_ad_tag( @@ -221,7 +209,7 @@ where tweak[0] = (tweak[0] & 0xf) | TWEAK_M; let (data_blocks, mut tail) = buffer.into_chunks(); - let data_blocks_len = data_blocks.len(); + let mut data_blocks_len = data_blocks.len(); for (index, mut data) in data_blocks.into_iter().enumerate() { // Copy block number @@ -236,26 +224,11 @@ where } } - if tail.is_empty() { - // Tag computing without last block - tweak[0] = (tweak[0] & 0xf) | TWEAK_TAG; - - let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&((buffer_len / 16) as u64).to_be_bytes()); - tweak[8] = (tweak[8] & 0xf) | tmp; - - B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); - - for (t, c) in computed_tag.iter_mut().zip(checksum.iter()) { - *t ^= c; - } - } else { - // Tag computing with incomplete last block - let index = data_blocks_len; - + // Process incomplete last block + if !tail.is_empty() { // Copy block number let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&(index as u64).to_be_bytes()); + tweak[8..].copy_from_slice(&(data_blocks_len as u64).to_be_bytes()); tweak[8] = (tweak[8] & 0xf) | tmp; // Last block checksum @@ -275,18 +248,24 @@ where *c ^= d; } - // Tag computing. - tweak[0] = (tweak[0] & 0xf) | TWEAK_CHKSUM; + data_blocks_len += 1; + } - let tmp = tweak[8] & 0xf0; - tweak[8..].copy_from_slice(&((index + 1) as u64).to_be_bytes()); - tweak[8] = (tweak[8] & 0xf) | tmp; + // Tag computing. + let t = if tail.is_empty() { + TWEAK_TAG + } else { + TWEAK_CHKSUM + }; + tweak[0] = (tweak[0] & 0xf) | t; + let tmp = tweak[8] & 0xf0; + tweak[8..].copy_from_slice(&(data_blocks_len as u64).to_be_bytes()); + tweak[8] = (tweak[8] & 0xf) | tmp; - B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); + B::encrypt_inout((&mut checksum).into(), tweak.as_ref(), subkeys); - for (t, c) in computed_tag.iter_mut().zip(checksum.iter()) { - *t ^= c; - } + for (t, c) in computed_tag.iter_mut().zip(checksum.iter()) { + *t ^= c; } if tag.ct_eq(&computed_tag).into() {