summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2021-11-03 11:02:44 +0100
committerJustus Winter <justus@sequoia-pgp.org>2021-11-03 11:08:13 +0100
commitb78690261254350fc1a4e3475a913c5c998a3248 (patch)
tree919dd9389b003e2ab589e019b5ec23b7dee1d7da
parentc9626a20eb28428d291ae8b078830bf71633c12c (diff)
openpgp: Reuse crypto::symmetric::Decryptor's ciphertext buffer.
-rw-r--r--openpgp/src/crypto/symmetric.rs30
-rw-r--r--openpgp/src/lib.rs9
2 files changed, 24 insertions, 15 deletions
diff --git a/openpgp/src/crypto/symmetric.rs b/openpgp/src/crypto/symmetric.rs
index 64fe368c..9d165814 100644
--- a/openpgp/src/crypto/symmetric.rs
+++ b/openpgp/src/crypto/symmetric.rs
@@ -6,7 +6,7 @@ use std::fmt;
use crate::Result;
use crate::SymmetricAlgorithm;
-use crate::vec_truncate;
+use crate::{vec_resize, vec_truncate};
use buffered_reader::BufferedReader;
@@ -45,6 +45,8 @@ pub struct Decryptor<R: io::Read> {
block_size: usize,
// Up to a block of unread data.
buffer: Vec<u8>,
+ // Ciphertext buffer.
+ ciphertext: Vec<u8>,
}
assert_send_and_sync!(Decryptor<R> where R: io::Read);
@@ -61,6 +63,7 @@ impl<R: io::Read> Decryptor<R> {
dec,
block_size,
buffer: Vec::with_capacity(block_size),
+ ciphertext: Vec::with_capacity(8 * 1024),
})
}
}
@@ -121,14 +124,14 @@ impl<R: io::Read> io::Read for Decryptor<R> {
// 2. Decrypt as many whole blocks as `plaintext` can hold.
let mut to_copy
= ((plaintext.len() - pos) / self.block_size) * self.block_size;
- let mut ciphertext = vec![0u8; to_copy];
- let result = read_exact(&mut self.source, &mut ciphertext[..]);
+ vec_resize(&mut self.ciphertext, to_copy);
+ let result = read_exact(&mut self.source, &mut self.ciphertext[..]);
let short_read;
match result {
Ok(amount) => {
short_read = amount < to_copy;
to_copy = amount;
- vec_truncate(&mut ciphertext, to_copy);
+ vec_truncate(&mut self.ciphertext, to_copy);
},
// We encountered an error, but we did read some.
Err(_) if pos > 0 => return Ok(pos),
@@ -136,7 +139,7 @@ impl<R: io::Read> io::Read for Decryptor<R> {
}
self.dec.decrypt(&mut plaintext[pos..pos + to_copy],
- &ciphertext[..])
+ &self.ciphertext[..])
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput,
format!("{}", e)))?;
@@ -151,29 +154,26 @@ impl<R: io::Read> io::Read for Decryptor<R> {
assert!(0 < to_copy);
assert!(to_copy < self.block_size);
- let mut ciphertext = vec![0u8; self.block_size];
- let result = read_exact(&mut self.source, &mut ciphertext[..]);
+ vec_resize(&mut self.ciphertext, self.block_size);
+ let result = read_exact(&mut self.source, &mut self.ciphertext[..]);
match result {
Ok(amount) => {
// Make sure `ciphertext` is not larger than the
// amount of data that was actually read.
- vec_truncate(&mut ciphertext, amount);
+ vec_truncate(&mut self.ciphertext, amount);
// Make sure we don't read more than is available.
- to_copy = cmp::min(to_copy, ciphertext.len());
+ to_copy = cmp::min(to_copy, self.ciphertext.len());
},
// We encountered an error, but we did read some.
Err(_) if pos > 0 => return Ok(pos),
Err(e) => return Err(e),
}
- assert!(ciphertext.len() <= self.block_size);
+ assert!(self.ciphertext.len() <= self.block_size);
- while self.buffer.len() < ciphertext.len() {
- self.buffer.push(0u8);
- }
- vec_truncate(&mut self.buffer, ciphertext.len());
+ vec_resize(&mut self.buffer, self.ciphertext.len());
- self.dec.decrypt(&mut self.buffer, &ciphertext[..])
+ self.dec.decrypt(&mut self.buffer, &self.ciphertext[..])
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput,
format!("{}", e)))?;
diff --git a/openpgp/src/lib.rs b/openpgp/src/lib.rs
index 5f303583..f7af0123 100644
--- a/openpgp/src/lib.rs
+++ b/openpgp/src/lib.rs
@@ -76,6 +76,15 @@ fn vec_truncate(v: &mut Vec<u8>, len: usize) {
}
}
+/// Like `Vec<u8>::resize`, but fast in debug builds.
+fn vec_resize(v: &mut Vec<u8>, new_size: usize) {
+ if v.len() < new_size {
+ v.resize(new_size, 0);
+ } else {
+ vec_truncate(v, new_size);
+ }
+}
+
/// Like `drop(Vec<u8>::drain(..prefix_len))`, but fast in debug
/// builds.
fn vec_drain_prefix(v: &mut Vec<u8>, prefix_len: usize) {