Skip to content

Commit cc87515

Browse files
committed
AES-GCM internals: Make the Block type an alias for [u8; BLOCK_LEN].
After this change, there are some uses of `[u8; BLOCK_LEN]` that could now be replaced with `Block`. Now the code is a bit inconsistent regarding this, but we expect to address this soon. Keeping these instances this way reduces the size of this diff.
1 parent b3250f2 commit cc87515

File tree

7 files changed

+50
-147
lines changed

7 files changed

+50
-147
lines changed

src/aead.rs

-1
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ pub const MAX_TAG_LEN: usize = TAG_LEN;
242242

243243
mod aes;
244244
mod aes_gcm;
245-
mod block;
246245
mod chacha;
247246
mod chacha20_poly1305;
248247
pub mod chacha20_poly1305_openssh;

src/aead/aes.rs

+13-16
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,13 @@
1212
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1313
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

15-
use super::{
16-
block::{Block, BLOCK_LEN},
17-
nonce::Nonce,
18-
quic::Sample,
19-
};
15+
use super::{nonce::Nonce, quic::Sample};
2016
use crate::{
2117
bits::{BitLength, FromByteLen as _},
22-
c, cpu,
18+
c, constant_time, cpu,
2319
endian::BigEndian,
2420
error,
25-
polyfill::{self, ArraySplitMap},
21+
polyfill::{self, ArrayFlatten as _, ArraySplitMap as _},
2622
};
2723
use core::ops::RangeFrom;
2824

@@ -199,7 +195,7 @@ impl Key {
199195
#[inline]
200196
pub fn encrypt_iv_xor_block(&self, iv: Iv, input: Block, cpu_features: cpu::Features) -> Block {
201197
let encrypted_iv = self.encrypt_block(iv.into_block_less_safe(), cpu_features);
202-
encrypted_iv ^ input
198+
constant_time::xor(encrypted_iv, input)
203199
}
204200

205201
#[inline]
@@ -266,7 +262,7 @@ impl Key {
266262
#[cfg(target_arch = "x86")]
267263
Implementation::VPAES_BSAES => {
268264
super::shift::shift_full_blocks(in_out, src, |input| {
269-
self.encrypt_iv_xor_block(ctr.increment(), Block::from(input), cpu_features)
265+
self.encrypt_iv_xor_block(ctr.increment(), *input, cpu_features)
270266
});
271267
}
272268

@@ -277,9 +273,7 @@ impl Key {
277273
}
278274

279275
pub fn new_mask(&self, sample: Sample) -> [u8; 5] {
280-
let &[b0, b1, b2, b3, b4, ..] = self
281-
.encrypt_block(Block::from(&sample), cpu::features())
282-
.as_ref();
276+
let [b0, b1, b2, b3, b4, ..] = self.encrypt_block(sample, cpu::features());
283277
[b0, b1, b2, b3, b4]
284278
}
285279

@@ -324,7 +318,7 @@ impl Counter {
324318

325319
pub fn increment(&mut self) -> Iv {
326320
let iv: [[u8; 4]; 4] = self.0.map(Into::into);
327-
let iv = Iv(Block::from(iv));
321+
let iv = Iv(iv.array_flatten());
328322
self.increment_by_less_safe(1);
329323
iv
330324
}
@@ -343,7 +337,7 @@ pub struct Iv(Block);
343337
impl From<Counter> for Iv {
344338
fn from(counter: Counter) -> Self {
345339
let iv: [[u8; 4]; 4] = counter.0.map(Into::into);
346-
Self(Block::from(iv))
340+
Self(iv.array_flatten())
347341
}
348342
}
349343

@@ -355,6 +349,10 @@ impl Iv {
355349
}
356350
}
357351

352+
pub(super) type Block = [u8; BLOCK_LEN];
353+
pub(super) const BLOCK_LEN: usize = 16;
354+
pub(super) const ZERO_BLOCK: Block = [0u8; BLOCK_LEN];
355+
358356
#[repr(C)] // Only so `Key` can be `#[repr(C)]`
359357
#[derive(Clone, Copy)]
360358
#[allow(clippy::upper_case_acronyms)]
@@ -434,10 +432,9 @@ mod tests {
434432
assert_eq!(section, "");
435433
let key = consume_key(test_case, "Key");
436434
let input = test_case.consume_bytes("Input");
437-
let input: &[u8; BLOCK_LEN] = input.as_slice().try_into()?;
435+
let block: Block = input.as_slice().try_into()?;
438436
let expected_output = test_case.consume_bytes("Output");
439437

440-
let block = Block::from(input);
441438
let output = key.encrypt_block(block, cpu_features);
442439
assert_eq!(output.as_ref(), &expected_output[..]);
443440

src/aead/aes_gcm.rs

+10-12
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@
1313
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

1515
use super::{
16-
aes::{self, Counter},
17-
block::{Block, BLOCK_LEN},
16+
aes::{self, Counter, BLOCK_LEN, ZERO_BLOCK},
1817
gcm, shift, Aad, Nonce, Tag,
1918
};
2019
use crate::{
21-
aead, cpu, error,
20+
aead, constant_time, cpu, error,
2221
polyfill::{sliceutil::overwrite_at_start, usize_from_u64_saturated},
2322
};
2423
use core::ops::RangeFrom;
@@ -62,7 +61,7 @@ fn init(
6261
) -> Result<aead::KeyInner, error::Unspecified> {
6362
let aes_key = aes::Key::new(key, variant, cpu_features)?;
6463
let gcm_key = gcm::Key::new(
65-
aes_key.encrypt_block(Block::zero(), cpu_features),
64+
aes_key.encrypt_block(ZERO_BLOCK, cpu_features),
6665
cpu_features,
6766
);
6867
Ok(aead::KeyInner::AesGcm(Key { gcm_key, aes_key }))
@@ -170,12 +169,12 @@ fn aes_gcm_seal(
170169
}
171170

172171
if !remainder.is_empty() {
173-
let mut input = Block::zero();
174-
input.overwrite_part_at(0, remainder);
172+
let mut input = ZERO_BLOCK;
173+
overwrite_at_start(&mut input, remainder);
175174
let mut output = aes_key.encrypt_iv_xor_block(ctr.into(), input, cpu_features);
176-
output.zero_from(remainder.len());
175+
output[remainder.len()..].fill(0);
177176
auth.update_block(output);
178-
overwrite_at_start(remainder, output.as_ref());
177+
overwrite_at_start(remainder, &output);
179178
}
180179

181180
Ok(finish(aes_key, auth, tag_iv))
@@ -309,8 +308,8 @@ fn aes_gcm_open(
309308

310309
let remainder = &mut in_out[whole_len..];
311310
shift::shift_partial((in_prefix_len, remainder), |remainder| {
312-
let mut input = Block::zero();
313-
input.overwrite_part_at(0, remainder);
311+
let mut input = ZERO_BLOCK;
312+
overwrite_at_start(&mut input, remainder);
314313
auth.update_block(input);
315314
aes_key.encrypt_iv_xor_block(ctr.into(), input, cpu_features)
316315
});
@@ -322,8 +321,7 @@ fn finish(aes_key: &aes::Key, gcm_ctx: gcm::Context, tag_iv: aes::Iv) -> Tag {
322321
// Finalize the tag and return it.
323322
gcm_ctx.pre_finish(|pre_tag, cpu_features| {
324323
let encrypted_iv = aes_key.encrypt_block(tag_iv.into_block_less_safe(), cpu_features);
325-
let tag = pre_tag ^ encrypted_iv;
326-
Tag(*tag.as_ref())
324+
Tag(constant_time::xor(pre_tag, encrypted_iv))
327325
})
328326
}
329327

src/aead/block.rs

-85
This file was deleted.

src/aead/gcm.rs

+17-22
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,18 @@
1212
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1313
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

15-
use super::{
16-
aes_gcm,
17-
block::{Block, BLOCK_LEN},
18-
Aad,
19-
};
15+
use super::{aes_gcm, Aad};
16+
2017
use crate::{
2118
bits::{BitLength, FromByteLen as _},
22-
cpu, error,
23-
polyfill::ArraySplitMap,
19+
constant_time, cpu, error,
20+
polyfill::{sliceutil::overwrite_at_start, ArrayFlatten as _, ArraySplitMap as _},
2421
};
2522
use core::ops::BitXorAssign;
2623

24+
// GCM uses the same block type as AES.
25+
use super::aes::{Block, BLOCK_LEN, ZERO_BLOCK};
26+
2727
mod gcm_nohw;
2828

2929
#[derive(Clone)]
@@ -33,7 +33,7 @@ pub struct Key {
3333

3434
impl Key {
3535
pub(super) fn new(h_be: Block, cpu_features: cpu::Features) -> Self {
36-
let h: [u64; 2] = h_be.as_ref().array_split_map(u64::from_be_bytes);
36+
let h: [u64; 2] = h_be.array_split_map(u64::from_be_bytes);
3737

3838
let mut key = Self {
3939
h_table: HTable {
@@ -111,7 +111,7 @@ impl Context {
111111

112112
let mut ctx = Self {
113113
inner: ContextInner {
114-
Xi: Xi(Block::zero()),
114+
Xi: Xi(ZERO_BLOCK),
115115
Htable: key.h_table.clone(),
116116
},
117117
aad_len: BitLength::from_byte_len(aad.as_ref().len())?,
@@ -120,8 +120,8 @@ impl Context {
120120
};
121121

122122
for ad in aad.0.chunks(BLOCK_LEN) {
123-
let mut block = Block::zero();
124-
block.overwrite_part_at(0, ad);
123+
let mut block = ZERO_BLOCK;
124+
overwrite_at_start(&mut block, ad);
125125
ctx.update_block(block);
126126
}
127127

@@ -268,9 +268,11 @@ impl Context {
268268
where
269269
F: FnOnce(Block, cpu::Features) -> super::Tag,
270270
{
271-
self.update_block(Block::from(
272-
[self.aad_len, self.in_out_len].map(BitLength::to_be_bytes),
273-
));
271+
self.update_block(
272+
[self.aad_len, self.in_out_len]
273+
.map(BitLength::to_be_bytes)
274+
.array_flatten(),
275+
);
274276

275277
f(self.inner.Xi.0, self.cpu_features)
276278
}
@@ -314,14 +316,7 @@ pub struct Xi(Block);
314316
impl BitXorAssign<Block> for Xi {
315317
#[inline]
316318
fn bitxor_assign(&mut self, a: Block) {
317-
self.0 ^= a;
318-
}
319-
}
320-
321-
impl From<Xi> for Block {
322-
#[inline]
323-
fn from(Xi(block): Xi) -> Self {
324-
block
319+
self.0 = constant_time::xor(self.0, a)
325320
}
326321
}
327322

src/aead/gcm/gcm_nohw.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
//
2323
// Unlike the BearSSL notes, we use u128 in the 64-bit implementation.
2424

25-
use super::{Block, Xi, BLOCK_LEN};
26-
use crate::polyfill::ArraySplitMap;
25+
use super::{Xi, BLOCK_LEN};
26+
use crate::polyfill::{ArrayFlatten as _, ArraySplitMap as _};
2727

2828
#[cfg(target_pointer_width = "64")]
2929
fn gcm_mul64_nohw(a: u64, b: u64) -> (u64, u64) {
@@ -236,9 +236,9 @@ pub(super) fn ghash(xi: &mut Xi, h: super::u128, input: &[[u8; BLOCK_LEN]]) {
236236

237237
#[inline]
238238
fn with_swapped_xi(Xi(xi): &mut Xi, f: impl FnOnce(&mut [u64; 2])) {
239-
let unswapped: [u64; 2] = xi.as_ref().array_split_map(u64::from_be_bytes);
239+
let unswapped: [u64; 2] = xi.array_split_map(u64::from_be_bytes);
240240
let mut swapped: [u64; 2] = [unswapped[1], unswapped[0]];
241241
f(&mut swapped);
242242
let reswapped = [swapped[1], swapped[0]];
243-
*xi = Block::from(reswapped.map(u64::to_be_bytes))
243+
*xi = reswapped.map(u64::to_be_bytes).array_flatten()
244244
}

src/aead/shift.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@
1212
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1313
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

15-
use super::block::{Block, BLOCK_LEN};
1615
use crate::polyfill::sliceutil::overwrite_at_start;
1716

1817
#[cfg(target_arch = "x86")]
19-
pub fn shift_full_blocks(
18+
pub fn shift_full_blocks<const BLOCK_LEN: usize>(
2019
in_out: &mut [u8],
2120
src: core::ops::RangeFrom<usize>,
22-
mut transform: impl FnMut(&[u8; BLOCK_LEN]) -> Block,
21+
mut transform: impl FnMut(&[u8; BLOCK_LEN]) -> [u8; BLOCK_LEN],
2322
) {
2423
let in_out_len = in_out[src.clone()].len();
2524

@@ -30,13 +29,13 @@ pub fn shift_full_blocks(
3029
transform(input)
3130
};
3231
let output = <&mut [u8; BLOCK_LEN]>::try_from(&mut in_out[i..][..BLOCK_LEN]).unwrap();
33-
*output = *block.as_ref();
32+
*output = block;
3433
}
3534
}
3635

37-
pub fn shift_partial(
36+
pub fn shift_partial<const BLOCK_LEN: usize>(
3837
(in_prefix_len, in_out): (usize, &mut [u8]),
39-
transform: impl FnOnce(&[u8]) -> Block,
38+
transform: impl FnOnce(&[u8]) -> [u8; BLOCK_LEN],
4039
) {
4140
let (block, in_out_len) = {
4241
let input = &in_out[in_prefix_len..];
@@ -47,5 +46,5 @@ pub fn shift_partial(
4746
debug_assert!(in_out_len < BLOCK_LEN);
4847
(transform(input), in_out_len)
4948
};
50-
overwrite_at_start(&mut in_out[..in_out_len], block.as_ref());
49+
overwrite_at_start(&mut in_out[..in_out_len], &block);
5150
}

0 commit comments

Comments
 (0)