From c08e5924d6a42758aabe0f9d9b447deb440df5b3 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Sun, 14 Jan 2024 10:01:11 +0100 Subject: [PATCH] add u32 secret integers --- .github/workflows/ci.yml | 3 ++ src/tls13cert.rs | 6 ++-- src/tls13formats.rs | 6 ++-- src/tls13utils.rs | 65 +++++++++++++++++++++++++++++++++------- 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4534e01..c197cf02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,6 +35,9 @@ jobs: - name: Test code run: cargo test --workspace + - name: Test code w/ secret-integers + run: cargo test --workspace --features secret_integers + - name: BoGo if: matrix.os != 'windows-latest' run: BORINGSSL_ROOT=./boringssl ./bogo_shim/run.sh diff --git a/src/tls13cert.rs b/src/tls13cert.rs index 7c682368..ed43bdc3 100644 --- a/src/tls13cert.rs +++ b/src/tls13cert.rs @@ -21,7 +21,7 @@ use crate::tls13utils::Declassify; use crate::{ tls13crypto::{PublicVerificationKey, RsaVerificationKey, SignatureScheme, VerificationKey}, - tls13utils::{Bytes, U32}, + tls13utils::{u32_from_be_bytes, Bytes, U8}, }; /// Certificate key start and length within the certificate DER. @@ -48,9 +48,9 @@ fn long_length(b: &Bytes, offset: usize, len: usize) -> Result if len > 4 { asn1_error(ASN1_SEQUENCE_TOO_LONG) } else { - let mut u32word: Bytes = Bytes::zeroes(4); + let mut u32word = [U8(0); 4]; u32word[0..len].copy_from_slice(&b[offset..offset + len]); - Ok(U32::from_be_bytes(&u32word)?.declassify() as usize >> ((4 - len) * 8)) + Ok(u32_from_be_bytes(u32word).declassify() as usize >> ((4 - len) * 8)) } } diff --git a/src/tls13formats.rs b/src/tls13formats.rs index a7ed9fe8..9c073340 100644 --- a/src/tls13formats.rs +++ b/src/tls13formats.rs @@ -12,8 +12,8 @@ use crate::{ check_length_encoding_u16_slice, check_length_encoding_u24, check_length_encoding_u8, check_length_encoding_u8_slice, check_mem, encode_length_u16, encode_length_u24, encode_length_u8, eq_slice, length_u16_encoded, length_u16_encoded_slice, - length_u24_encoded, length_u8_encoded, parse_failed, tlserr, Bytes, TLSError, - APPLICATION_DATA_INSTEAD_OF_HANDSHAKE, DECODE_ERROR, INVALID_COMPRESSION_LIST, + length_u24_encoded, length_u8_encoded, parse_failed, tlserr, u32_as_be_bytes, Bytes, + TLSError, APPLICATION_DATA_INSTEAD_OF_HANDSHAKE, DECODE_ERROR, INVALID_COMPRESSION_LIST, INVALID_SIGNATURE, MISSING_KEY_SHARE, PROTOCOL_VERSION_ALERT, PSK_MODE_MISMATCH, U32, U8, UNSUPPORTED_ALGORITHM, }, @@ -169,7 +169,7 @@ fn check_server_key_share(algs: &Algorithms, b: &Bytes) -> Result Result<(Bytes, usize), TLSError> { let identities = encode_length_u16( - encode_length_u16(session_ticket.clone())?.concat(U32::from(0xffffffff).as_be_bytes()), + encode_length_u16(session_ticket.clone())?.concat_array(u32_as_be_bytes(U32(0xffffffff))), )?; let binders = encode_length_u16(encode_length_u8(zero_key(&algs.hash()).as_raw())?)?; let binders_len = binders.len(); diff --git a/src/tls13utils.rs b/src/tls13utils.rs index 6b0cdf8d..0d7e4822 100644 --- a/src/tls13utils.rs +++ b/src/tls13utils.rs @@ -78,12 +78,12 @@ impl U8 { } } -pub(crate) trait Declassify { - fn declassify(self) -> u8; +pub(crate) trait Declassify { + fn declassify(self) -> T; } #[cfg(not(feature = "secret_integers"))] -impl Declassify for u8 { +impl Declassify for u8 { fn declassify(self) -> u8 { self } @@ -125,15 +125,18 @@ impl From for U16 { } } +#[cfg(feature = "secret_integers")] #[derive(Clone, Copy, PartialEq, Debug)] -pub struct U32(u32); +pub struct U32(pub(crate) u32); +#[cfg(feature = "secret_integers")] impl From for U32 { fn from(x: u32) -> U32 { U32(x) } } +#[cfg(feature = "secret_integers")] impl core::ops::Add for U32 { type Output = U32; fn add(self, y: U32) -> U32 { @@ -141,6 +144,23 @@ impl core::ops::Add for U32 { } } +#[cfg(not(feature = "secret_integers"))] +pub(crate) type U32 = u32; + +#[cfg(not(feature = "secret_integers"))] +#[allow(non_snake_case)] +pub(crate) const fn U32(x: u32) -> U32 { + x +} + +#[cfg(not(feature = "secret_integers"))] +impl Declassify for U32 { + #[inline(always)] + fn declassify(self) -> u32 { + self + } +} + /// Bytes used in Bertie. #[derive(Clone, PartialEq, Debug, Default)] pub struct Bytes(Vec); @@ -228,13 +248,8 @@ impl From<&[u8; C]> for Bytes { } } +#[cfg(feature = "secret_integers")] impl U32 { - pub(crate) fn from_be_bytes(x: &Bytes) -> Result { - Ok(U32(u32::from_be_bytes(x.declassify_array()?))) - } - pub(crate) fn as_be_bytes(&self) -> Bytes { - (self.0.to_be_bytes().to_vec()).into() - } pub(crate) fn declassify(&self) -> u32 { self.0 } @@ -248,6 +263,28 @@ pub(crate) fn u16_as_be_bytes(val: U16) -> [U8; 2] { [U8(val[0]), U8(val[1])] } +pub(crate) fn u32_as_be_bytes(val: U32) -> [U8; 4] { + #[cfg(not(feature = "secret_integers"))] + let val = val.to_be_bytes(); + #[cfg(feature = "secret_integers")] + let val = val.0.to_be_bytes(); + [U8(val[0]), U8(val[1]), U8(val[2]), U8(val[3])] +} + +pub(crate) fn u32_from_be_bytes(val: [U8; 4]) -> U32 { + #[cfg(not(feature = "secret_integers"))] + let val = u32::from_be_bytes(val); + #[cfg(feature = "secret_integers")] + let val = u32::from_be_bytes([ + val[0].declassify(), + val[1].declassify(), + val[2].declassify(), + val[3].declassify(), + ]); + + U32(val) +} + pub(crate) fn bytes(x: &[u8]) -> Bytes { x.into() } @@ -369,6 +406,12 @@ impl Bytes { self } + /// Concatenate `other` with these bytes and return a copy as [`Bytes`]. + pub fn concat_array(mut self, other: [U8; N]) -> Bytes { + self.0.extend_from_slice(&other); + self + } + /// Update the slice `self[start..start+len] = other[beg..beg+len]` and return /// a copy as [`Bytes`]. pub(crate) fn update_slice( @@ -554,7 +597,7 @@ pub(crate) fn encode_length_u24(bytes: &Bytes) -> Result { if len >= 16777216 { Err(PAYLOAD_TOO_LONG) } else { - let len = U32(len as u32).as_be_bytes(); + let len = u32_as_be_bytes(U32(len as u32)); let mut lenb = Bytes::new_alloc(3 + bytes.len()); lenb.push(len[1]); lenb.push(len[2]);