From 9221c3066c9772fe9d41abeb9f0040a141c944be Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 22 Jan 2025 10:53:17 -0800 Subject: [PATCH] poly1305 internals: Remove the I-U-F logic in poly1305.c. Only pass whole blocks to update, except for the last batch. --- crypto/poly1305/poly1305.c | 39 +------------------------------ src/aead/chacha20_poly1305/mod.rs | 20 +++++++--------- src/aead/poly1305.rs | 26 ++++++++++++++------- src/aead/poly1305/ffi_arm_neon.rs | 2 +- src/aead/poly1305/ffi_fallback.rs | 4 +++- 5 files changed, 31 insertions(+), 60 deletions(-) diff --git a/crypto/poly1305/poly1305.c b/crypto/poly1305/poly1305.c index 31da6cf1e0..e69a80c542 100644 --- a/crypto/poly1305/poly1305.c +++ b/crypto/poly1305/poly1305.c @@ -32,8 +32,6 @@ struct poly1305_state_st { uint32_t r0, r1, r2, r3, r4; uint32_t s1, s2, s3, s4; uint32_t h0, h1, h2, h3, h4; - uint8_t buf[16]; - size_t buf_used; uint8_t key[16]; }; @@ -179,7 +177,6 @@ void CRYPTO_poly1305_init(poly1305_state *statep, const uint8_t key[32]) { state->h3 = 0; state->h4 = 0; - state->buf_used = 0; OPENSSL_memcpy(state->key, key + 16, sizeof(state->key)); } @@ -192,37 +189,7 @@ void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in, return; } - if (state->buf_used) { - size_t todo = 16 - state->buf_used; - if (todo > in_len) { - todo = in_len; - } - for (size_t i = 0; i < todo; i++) { - state->buf[state->buf_used + i] = in[i]; - } - state->buf_used += todo; - in_len -= todo; - in += todo; - - if (state->buf_used == 16) { - poly1305_update(state, state->buf, 16); - state->buf_used = 0; - } - } - - if (in_len >= 16) { - size_t todo = in_len & ~0xf; - poly1305_update(state, in, todo); - in += todo; - in_len &= 0xf; - } - - if (in_len) { - for (size_t i = 0; i < in_len; i++) { - state->buf[i] = in[i]; - } - state->buf_used = in_len; - } + poly1305_update(state, in, in_len); } void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) { @@ -230,10 +197,6 @@ void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) { uint32_t g0, g1, g2, g3, g4; uint32_t b, nb; - if (state->buf_used) { - poly1305_update(state, state->buf, state->buf_used); - } - b = state->h0 >> 26; state->h0 = state->h0 & 0x3ffffff; state->h1 += b; diff --git a/src/aead/chacha20_poly1305/mod.rs b/src/aead/chacha20_poly1305/mod.rs index c054178272..cdcd9b3b2e 100644 --- a/src/aead/chacha20_poly1305/mod.rs +++ b/src/aead/chacha20_poly1305/mod.rs @@ -19,7 +19,7 @@ use super::{ use crate::{ cpu, error::InputTooLongError, - polyfill::{u64_from_usize, usize_from_u64_saturated}, + polyfill::{slice, sliceutil, u64_from_usize, usize_from_u64_saturated}, }; use cfg_if::cfg_if; @@ -147,23 +147,21 @@ pub(super) fn begin( Ok((counter, poly1305_key)) } -fn finish(mut auth: poly1305::Context, aad_len: usize, in_out_len: usize) -> Tag { +fn finish(auth: poly1305::Context, aad_len: usize, in_out_len: usize) -> Tag { let mut block = [0u8; poly1305::BLOCK_LEN]; let (alen, clen) = block.split_at_mut(poly1305::BLOCK_LEN / 2); alen.copy_from_slice(&u64::to_le_bytes(u64_from_usize(aad_len))); clen.copy_from_slice(&u64::to_le_bytes(u64_from_usize(in_out_len))); - auth.update(&block); - auth.finish() + auth.finish(&block) } #[inline] fn poly1305_update_padded_16(ctx: &mut poly1305::Context, input: &[u8]) { - if !input.is_empty() { - ctx.update(input); - let remainder_len = input.len() % poly1305::BLOCK_LEN; - if remainder_len != 0 { - const ZEROES: [u8; poly1305::BLOCK_LEN] = [0; poly1305::BLOCK_LEN]; - ctx.update(&ZEROES[..(poly1305::BLOCK_LEN - remainder_len)]) - } + let (whole, remainder) = slice::as_chunks(input); + ctx.update(whole); + if !remainder.is_empty() { + let mut block = [0u8; poly1305::BLOCK_LEN]; + sliceutil::overwrite_at_start(&mut block, remainder); + ctx.update_block(block); } } diff --git a/src/aead/poly1305.rs b/src/aead/poly1305.rs index 454e601b15..45229d560f 100644 --- a/src/aead/poly1305.rs +++ b/src/aead/poly1305.rs @@ -15,9 +15,10 @@ // TODO: enforce maximum input length. use super::{Tag, TAG_LEN}; -use crate::cpu; #[cfg(all(target_arch = "arm", target_endian = "little"))] use crate::cpu::GetFeature as _; +use crate::{cpu, polyfill::slice}; +use core::array; mod ffi_arm_neon; mod ffi_fallback; @@ -62,16 +63,24 @@ impl Context { ffi_fallback::State::new_context(key) } - #[inline(always)] - pub fn update(&mut self, input: &[u8]) { + pub fn update_block(&mut self, input: [u8; BLOCK_LEN]) { + self.update(array::from_ref(&input)) + } + + pub fn update(&mut self, input: &[[u8; BLOCK_LEN]]) { + self.update_internal(slice::flatten(input)); + } + + fn update_internal(&mut self, input: &[u8]) { match self { #[cfg(all(target_arch = "arm", target_endian = "little"))] - Self::ArmNeon(state) => state.update(input), - Self::Fallback(state) => state.update(input), + Self::ArmNeon(state) => state.update_internal(input), + Self::Fallback(state) => state.update_internal(input), } } - pub(super) fn finish(self) -> Tag { + pub(super) fn finish(mut self, input: &[u8]) -> Tag { + self.update_internal(input); match self { #[cfg(all(target_arch = "arm", target_endian = "little"))] Self::ArmNeon(state) => state.finish(), @@ -85,9 +94,8 @@ impl Context { /// This is used by chacha20_poly1305_openssh and the standalone /// poly1305 test vectors. pub(super) fn sign(key: Key, input: &[u8], cpu_features: cpu::Features) -> Tag { - let mut ctx = Context::from_key(key, cpu_features); - ctx.update(input); - ctx.finish() + let ctx = Context::from_key(key, cpu_features); + ctx.finish(input) } #[cfg(test)] diff --git a/src/aead/poly1305/ffi_arm_neon.rs b/src/aead/poly1305/ffi_arm_neon.rs index 05d8606f22..dbfd9e0961 100644 --- a/src/aead/poly1305/ffi_arm_neon.rs +++ b/src/aead/poly1305/ffi_arm_neon.rs @@ -38,7 +38,7 @@ impl State { super::Context::ArmNeon(r) } - pub(super) fn update(&mut self, input: &[u8]) { + pub(super) fn update_internal(&mut self, input: &[u8]) { prefixed_extern! { fn CRYPTO_poly1305_update_neon( state: &mut poly1305_state, diff --git a/src/aead/poly1305/ffi_fallback.rs b/src/aead/poly1305/ffi_fallback.rs index 9e1e073966..ad4d519549 100644 --- a/src/aead/poly1305/ffi_fallback.rs +++ b/src/aead/poly1305/ffi_fallback.rs @@ -34,7 +34,9 @@ impl State { super::Context::Fallback(r) } - pub(super) fn update(&mut self, input: &[u8]) { + // `input.len % BLOCK_LEN == 0` must be true for every call except the + // final one. + pub(super) fn update_internal(&mut self, input: &[u8]) { prefixed_extern! { fn CRYPTO_poly1305_update( state: &mut poly1305_state,