summaryrefslogtreecommitdiffstats
path: root/openpgp/src/parse.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/parse.rs')
-rw-r--r--openpgp/src/parse.rs109
1 files changed, 104 insertions, 5 deletions
diff --git a/openpgp/src/parse.rs b/openpgp/src/parse.rs
index bd33bc8c..9d4b6afc 100644
--- a/openpgp/src/parse.rs
+++ b/openpgp/src/parse.rs
@@ -2801,16 +2801,54 @@ impl SEIP {
fn parse<'a, T: 'a + BufferedReader<Cookie>>(mut php: PacketHeaderParser<T>) -> Result<PacketParser<'a>> {
make_php_try!(php);
let version = php_try!(php.parse_u8("version"));
- if version != 1 {
- return php.fail("unknown version");
+ match version {
+ 1 => SEIP1::parse(php),
+ 2 => SEIP2::parse(php),
+ _ => php.fail("unknown version"),
}
+ }
+}
+impl_parse_generic_packet!(SEIP);
+
+impl SEIP1 {
+ /// Parses the body of a SEIP1 packet.
+ fn parse<'a, T: 'a + BufferedReader<Cookie>>(php: PacketHeaderParser<T>)
+ -> Result<PacketParser<'a>>
+ {
php.ok(SEIP1::new().into())
.map(|pp| pp.set_processed(false))
}
}
-impl_parse_generic_packet!(SEIP);
+impl SEIP2 {
+ /// Parses the body of a SEIP1 packet.
+ fn parse<'a, T: 'a + BufferedReader<Cookie>>(mut php: PacketHeaderParser<T>)
+ -> Result<PacketParser<'a>>
+ {
+ make_php_try!(php);
+ let cipher: SymmetricAlgorithm =
+ php_try!(php.parse_u8("sym_algo")).into();
+ let aead: AEADAlgorithm =
+ php_try!(php.parse_u8("aead_algo")).into();
+ let chunk_size = php_try!(php.parse_u8("chunk_size"));
+
+ // DRAFT 4880bis-08, section 5.16: "An implementation MUST
+ // support chunk size octets with values from 0 to 56. Chunk
+ // size octets with other values are reserved for future
+ // extensions."
+ if chunk_size > 56 {
+ return php.fail("unsupported chunk size");
+ }
+ let chunk_size: u64 = 1 << (chunk_size + 6);
+ let salt_v = php_try!(php.parse_bytes("salt", 32));
+ let mut salt = [0u8; 32];
+ salt.copy_from_slice(&salt_v);
+
+ let seip2 = php_try!(Self::new(cipher, aead, chunk_size, salt));
+ php.ok(seip2.into()).map(|pp| pp.set_processed(false))
+ }
+}
impl MDC {
/// Parses the body of an MDC packet.
@@ -4855,7 +4893,9 @@ impl <'a> PacketParser<'a> {
Packet::Unknown(p) => set_or_extend(rest, p.container_mut(), false),
Packet::CompressedData(p) =>
set_or_extend(rest, p.deref_mut(), self.processed),
- Packet::SEIP(p) =>
+ Packet::SEIP(SEIP::V1(p)) =>
+ set_or_extend(rest, p.deref_mut(), self.processed),
+ Packet::SEIP(SEIP::V2(p)) =>
set_or_extend(rest, p.deref_mut(), self.processed),
Packet::AED(p) =>
set_or_extend(rest, p.deref_mut(), self.processed),
@@ -5319,7 +5359,7 @@ impl<'a> PacketParser<'a> {
}
match self.packet.clone() {
- Packet::SEIP(_) => {
+ Packet::SEIP(SEIP::V1(_)) => {
// Get the first blocksize plus two bytes and check
// whether we can decrypt them using the provided key.
// Don't actually consume them in case we can't.
@@ -5391,6 +5431,65 @@ impl<'a> PacketParser<'a> {
Ok(())
},
+ Packet::SEIP(SEIP::V2(seip)) => {
+ let chunk_size =
+ aead::chunk_size_usize(seip.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.
+ {
+ // We need a bit more than one chunk so that
+ // `aead::Decryptor` won't see EOF and think that
+ // it has a partial block and it needs to verify
+ // the final chunk.
+ let amount = aead::chunk_size_usize(
+ seip.chunk_digest_size()?
+ + seip.aead().digest_size()? as u64)?;
+
+ let data = self.data(amount)?;
+ let (message_key, schedule) = aead::SEIPv2Schedule::new(
+ &key,
+ seip.symmetric_algo(),
+ seip.aead(),
+ chunk_size,
+ seip.salt())?;
+
+ let dec = aead::Decryptor::new(
+ seip.symmetric_algo(), seip.aead(), chunk_size,
+ schedule, message_key,
+ &data[..cmp::min(data.len(), amount)])?;
+ let mut chunk = Vec::new();
+ dec.take(seip.chunk_size() as u64).read_to_end(&mut chunk)?;
+ }
+
+ // Ok, we can decrypt the data. Push a Decryptor and
+ // a HashedReader on the `BufferedReader` stack.
+
+ // This can't fail, because we create a decryptor
+ // above with the same parameters.
+ let (message_key, schedule) = aead::SEIPv2Schedule::new(
+ &key,
+ seip.symmetric_algo(),
+ seip.aead(),
+ chunk_size,
+ seip.salt())?;
+
+ let reader = self.take_reader();
+ let mut reader = aead::BufferedReaderDecryptor::with_cookie(
+ seip.symmetric_algo(), seip.aead(), chunk_size,
+ schedule, message_key, reader, Cookie::default()).unwrap();
+ reader.cookie_mut().level = Some(self.recursion_depth());
+
+ t!("Pushing aead::Decryptor, level {:?}.",
+ reader.cookie_ref().level);
+
+ self.reader = Box::new(reader);
+ self.processed = true;
+
+ Ok(())
+ },
+
Packet::AED(AED::V1(aed)) => {
let chunk_size =
aead::chunk_size_usize(aed.chunk_size())?;