From adcbb3fd088d3cdfc29cbc5f77755736e30b8130 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Wed, 27 May 2020 16:17:58 +0200 Subject: openpgp: Use u64 for AEAD chunk sizes. - Use u64 in packet::aed::AED1 and the API. - Add explicit overflow checks when using chunk sizes as offsets. --- openpgp/src/crypto/aead.rs | 9 +++++++++ openpgp/src/packet/aed.rs | 12 ++++++------ openpgp/src/parse.rs | 15 ++++++++++----- openpgp/src/serialize/stream.rs | 5 +++-- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/openpgp/src/crypto/aead.rs b/openpgp/src/crypto/aead.rs index 713b320e..61cfd7f7 100644 --- a/openpgp/src/crypto/aead.rs +++ b/openpgp/src/crypto/aead.rs @@ -1,4 +1,5 @@ use std::cmp; +use std::convert::TryInto; use std::fmt; use std::io; @@ -24,6 +25,14 @@ use crate::parse::Cookie; /// malformed AEAD-encrypted messages. const DANGER_DISABLE_AUTHENTICATION: bool = false; +/// Converts a chunk size to a usize. +pub(crate) fn chunk_size_usize(chunk_size: u64) -> Result { + chunk_size.try_into() + .map_err(|_| Error::InvalidOperation( + format!("AEAD chunk size exceeds size of \ + virtual memory: {}", chunk_size)).into()) +} + impl AEADAlgorithm { /// Returns the digest size of the AEAD algorithm. pub fn digest_size(&self) -> Result { diff --git a/openpgp/src/packet/aed.rs b/openpgp/src/packet/aed.rs index 7f9980bb..b7f6e58c 100644 --- a/openpgp/src/packet/aed.rs +++ b/openpgp/src/packet/aed.rs @@ -117,7 +117,7 @@ pub struct AED1 { /// AEAD algorithm. aead: AEADAlgorithm, /// Chunk size. - chunk_size: usize, + chunk_size: u64, /// Initialization vector for the AEAD algorithm. iv: Box<[u8]>, @@ -142,7 +142,7 @@ impl AED1 { /// Creates a new AED1 object. pub fn new(sym_algo: SymmetricAlgorithm, aead: AEADAlgorithm, - chunk_size: usize, + chunk_size: u64, iv: Box<[u8]>) -> Result { if chunk_size.count_ones() != 1 { return Err(Error::InvalidArgument( @@ -188,12 +188,12 @@ impl AED1 { } /// Gets the chunk size. - pub fn chunk_size(&self) -> usize { + pub fn chunk_size(&self) -> u64 { self.chunk_size } /// Sets the chunk size. - pub fn set_chunk_size(&mut self, chunk_size: usize) -> Result<()> { + pub fn set_chunk_size(&mut self, chunk_size: u64) -> Result<()> { if chunk_size.count_ones() != 1 { return Err(Error::InvalidArgument( format!("chunk size is not a power of two: {}", chunk_size)) @@ -211,8 +211,8 @@ impl AED1 { } /// Gets the size of a chunk with a digest. - pub fn chunk_digest_size(&self) -> Result { - Ok(self.chunk_size + self.aead.digest_size()?) + pub fn chunk_digest_size(&self) -> Result { + Ok(self.chunk_size + self.aead.digest_size()? as u64) } /// Gets the initialization vector for the AEAD algorithm. diff --git a/openpgp/src/parse.rs b/openpgp/src/parse.rs index ad00a9f0..cbb789cf 100644 --- a/openpgp/src/parse.rs +++ b/openpgp/src/parse.rs @@ -2626,7 +2626,7 @@ impl AED1 { php_try!(php.parse_u8("sym_algo")).into(); let aead: AEADAlgorithm = php_try!(php.parse_u8("aead_algo")).into(); - let chunk_size: usize = + let chunk_size: u64 = 1 << (php_try!(php.parse_u8("chunk_size")) as usize + 6); let iv_size = php_try!(aead.iv_size()); @@ -4851,6 +4851,9 @@ impl<'a> PacketParser<'a> { }, Packet::AED(AED::V1(aed)) => { + let chunk_size = + aead::chunk_size_usize(aed.chunk_size())?; + // Read the first chunk and check whether we can // decrypt it using the provided key. Don't actually // consume them in case we can't. @@ -4859,11 +4862,13 @@ impl<'a> PacketParser<'a> { // `aead::Decryptor` won't see EOF and think that // it has a partial block and it needs to verify // the final chunk. - let amount - = aed.chunk_digest_size()? + aed.aead().digest_size()?; + let amount = aead::chunk_size_usize( + aed.chunk_digest_size()? + + aed.aead().digest_size()? as u64)?; + let data = self.data(amount)?; let dec = aead::Decryptor::new( - 1, aed.symmetric_algo(), aed.aead(), aed.chunk_size(), + 1, aed.symmetric_algo(), aed.aead(), chunk_size, aed.iv(), key, &data[..cmp::min(data.len(), amount)])?; let mut chunk = Vec::new(); @@ -4877,7 +4882,7 @@ impl<'a> PacketParser<'a> { // above with the same parameters. let reader = self.take_reader(); let mut reader = aead::BufferedReaderDecryptor::with_cookie( - 1, aed.symmetric_algo(), aed.aead(), aed.chunk_size(), + 1, aed.symmetric_algo(), aed.aead(), chunk_size, aed.iv(), key, reader, Cookie::default()).unwrap(); reader.cookie_mut().level = Some(self.recursion_depth()); diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs index e7e8e412..357fa871 100644 --- a/openpgp/src/serialize/stream.rs +++ b/openpgp/src/serialize/stream.rs @@ -2534,7 +2534,8 @@ impl<'a> Encryptor<'a> { CTB::new(Tag::AED).serialize(&mut inner)?; let mut inner = PartialBodyFilter::new(Message::from(inner), Cookie::new(level)); - let aed = AED1::new(self.sym_algo, aead.algo, aead.chunk_size, aead.nonce)?; + let aed = AED1::new(self.sym_algo, aead.algo, + aead.chunk_size as u64, aead.nonce)?; aed.serialize_headers(&mut inner)?; writer::AEADEncryptor::new( @@ -2542,7 +2543,7 @@ impl<'a> Encryptor<'a> { Cookie::new(level), aed.symmetric_algo(), aed.aead(), - aed.chunk_size(), + aead.chunk_size, aed.iv(), &sk, ) -- cgit v1.2.3