diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2021-08-19 14:30:35 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2021-09-08 11:08:19 +0200 |
commit | 0c0621ed263657e1d1348a62d7ceb59f2823bf76 (patch) | |
tree | 89f51764e2dc8bdca6b671f716108d6fcce37a59 /openpgp | |
parent | f6abef476d180fc1f16e95641248eac230f3c10e (diff) |
openpgp: Constrain AEAD chunk sizes.
- Make sure that chunk sizes are between 64B and 4MiB.
- Fixes a DoS resulting from unconstrained, attacker-controlled heap
allocations.
- Fixes #738.
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/NEWS | 4 | ||||
-rw-r--r-- | openpgp/src/crypto/aead.rs | 20 | ||||
-rw-r--r-- | openpgp/src/parse.rs | 4 | ||||
-rw-r--r-- | openpgp/tests/data/messages/aed/msg-aes128-eax-chunk-size-4194304-password-123.pgp | bin | 0 -> 5314 bytes |
4 files changed, 26 insertions, 2 deletions
diff --git a/openpgp/NEWS b/openpgp/NEWS index 4606ac1b..9fc36a9c 100644 --- a/openpgp/NEWS +++ b/openpgp/NEWS @@ -12,6 +12,10 @@ ** Notable fixes - Filters set using CertParser::unvalidated_cert_filter are now preserved during iterations. +* Changes in 1.3.1 +** Notable fixes + - Fixed a crash resulting from unconstrained, attacker-controlled + heap allocations. * Changes in 1.3.0 ** New functionality - CertBuilder::add_subkey_with diff --git a/openpgp/src/crypto/aead.rs b/openpgp/src/crypto/aead.rs index 9418d847..8ca021cb 100644 --- a/openpgp/src/crypto/aead.rs +++ b/openpgp/src/crypto/aead.rs @@ -19,6 +19,16 @@ use crate::crypto::mem::secure_cmp; use crate::seal; use crate::parse::Cookie; +/// Minimum AEAD chunk size. +/// +/// Implementations MUST support chunk sizes down to 64B. +const MIN_CHUNK_SIZE: usize = 1 << 6; // 64B + +/// Maximum AEAD chunk size. +/// +/// Implementations MUST support chunk sizes up to 4MiB. +const MAX_CHUNK_SIZE: usize = 1 << 22; // 4MiB + /// Disables authentication checks. /// /// This is DANGEROUS, and is only useful for debugging problems with @@ -140,6 +150,11 @@ impl<'a> Decryptor<'a> { source: Box<dyn 'a + BufferedReader<Cookie>>) -> Result<Self> { + if chunk_size < MIN_CHUNK_SIZE || chunk_size > MAX_CHUNK_SIZE { + return Err(Error::InvalidArgument( + format!("Invalid AEAD chunk size: {}", chunk_size)).into()); + } + Ok(Decryptor { source, sym_algo, @@ -552,6 +567,11 @@ impl<W: io::Write> Encryptor<W> { pub fn new(version: u8, sym_algo: SymmetricAlgorithm, aead: AEADAlgorithm, chunk_size: usize, iv: &[u8], key: &SessionKey, sink: W) -> Result<Self> { + if chunk_size < MIN_CHUNK_SIZE || chunk_size > MAX_CHUNK_SIZE { + return Err(Error::InvalidArgument( + format!("Invalid AEAD chunk size: {}", chunk_size)).into()); + } + let mut scratch = Vec::with_capacity(chunk_size); unsafe { scratch.set_len(chunk_size); } diff --git a/openpgp/src/parse.rs b/openpgp/src/parse.rs index 7b747180..fbb5cfff 100644 --- a/openpgp/src/parse.rs +++ b/openpgp/src/parse.rs @@ -5482,9 +5482,9 @@ mod test { ], }, DecryptTest { - filename: "aed/msg-aes128-eax-chunk-size-134217728-password-123.pgp", + filename: "aed/msg-aes128-eax-chunk-size-4194304-password-123.pgp", algo: SymmetricAlgorithm::AES128, - key_hex: "D7EE3F3B049DE011687EC9E08D6DCBB0", + key_hex: "918E6BF5C6CE4320D014735AF27BFA76", plaintext: Data::File("a-cypherpunks-manifesto.txt"), paths: &[ (Tag::SKESK, &[ 0 ]), diff --git a/openpgp/tests/data/messages/aed/msg-aes128-eax-chunk-size-4194304-password-123.pgp b/openpgp/tests/data/messages/aed/msg-aes128-eax-chunk-size-4194304-password-123.pgp Binary files differnew file mode 100644 index 00000000..145ab4a4 --- /dev/null +++ b/openpgp/tests/data/messages/aed/msg-aes128-eax-chunk-size-4194304-password-123.pgp |