summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-05-27 16:17:58 +0200
committerJustus Winter <justus@sequoia-pgp.org>2020-05-28 11:37:05 +0200
commitadcbb3fd088d3cdfc29cbc5f77755736e30b8130 (patch)
tree9cab01e71dba2f0230457d4985f01fcb2ab022d0
parent44f677ce10e2af6dbab532f996cf685e8c55afe5 (diff)
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.
-rw-r--r--openpgp/src/crypto/aead.rs9
-rw-r--r--openpgp/src/packet/aed.rs12
-rw-r--r--openpgp/src/parse.rs15
-rw-r--r--openpgp/src/serialize/stream.rs5
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<usize> {
+ 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<usize> {
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<Self> {
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<usize> {
- Ok(self.chunk_size + self.aead.digest_size()?)
+ pub fn chunk_digest_size(&self) -> Result<u64> {
+ 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,
)