sequoia_openpgp/parse.rs
1//! Packet parsing infrastructure.
2//!
3//! OpenPGP defines a binary representation suitable for storing and
4//! communicating OpenPGP data structures (see [Section 3 ff. of RFC
5//! 9580]). Parsing is the process of interpreting the binary
6//! representation.
7//!
8//! [Section 3 ff. of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3
9//!
10//! An OpenPGP stream represents a sequence of packets. Some of the
11//! packets contain other packets. These so-called containers include
12//! encrypted data packets (the SED and [SEIP] packets), and
13//! [compressed data] packets. This structure results in a tree,
14//! which is laid out in depth-first order.
15//!
16//! [SEIP]: crate::packet::SEIP
17//! [compressed data]: crate::packet::CompressedData
18//!
19//! OpenPGP defines objects consisting of several packets with a
20//! specific structure. These objects are [`Message`]s, [`Cert`]s and
21//! sequences of [`Cert`]s ("keyrings"). Verifying the structure of
22//! these objects is also an act of parsing.
23//!
24//! [`Message`]: super::Message
25//! [`Cert`]: crate::cert::Cert
26//!
27//! This crate provides several interfaces to parse OpenPGP data.
28//! They fall in roughly three categories:
29//!
30//! - First, most data structures in this crate implement the
31//! [`Parse`] trait. It provides a uniform interface to parse data
32//! from an [`io::Read`]er, a file identified by its [`Path`], or
33//! simply a byte slice.
34//!
35//! - Second, there is a convenient interface to decrypt and/or
36//! verify OpenPGP messages in a streaming fashion. Encrypted
37//! and/or signed data is read using the [`Parse`] interface, and
38//! decrypted and/or verified data can be read using [`io::Read`].
39//!
40//! - Finally, we expose the low-level [`PacketParser`], allowing
41//! fine-grained control over the parsing.
42//!
43//! [`io::Read`]: std::io::Read
44//! [`Path`]: std::path::Path
45//!
46//! The choice of interface depends on the specific use case. In many
47//! circumstances, OpenPGP data can not be trusted until it has been
48//! authenticated. Therefore, it has to be treated as attacker
49//! controlled data, and it has to be treated with great care. See
50//! the section [Security Considerations] below.
51//!
52//! [Security Considerations]: #security-considerations
53//!
54//! # Common Operations
55//!
56//! - *Decrypt a message*: Use a [streaming `Decryptor`].
57//! - *Verify a message*: Use a [streaming `Verifier`].
58//! - *Verify a detached signature*: Use a [`DetachedVerifier`].
59//! - *Parse a [`Cert`]*: Use [`Cert`]'s [`Parse`] interface.
60//! - *Parse a keyring*: Use [`CertParser`]'s [`Parse`] interface.
61//! - *Parse an unstructured sequence of small packets from a trusted
62//! source*: Use [`PacketPile`]s [`Parse`] interface (e.g.
63//! [`PacketPile::from_file`]).
64//! - *Parse an unstructured sequence of packets*: Use the
65//! [`PacketPileParser`].
66//! - *Parse an unstructured sequence of packets with full control
67//! over the parser*: Use a [`PacketParser`].
68//! - *Customize the parser behavior even more*: Use a
69//! [`PacketParserBuilder`].
70//!
71//! [`CertParser`]: crate::cert::CertParser
72//! [streaming `Decryptor`]: stream::Decryptor
73//! [streaming `Verifier`]: stream::Verifier
74//! [`DetachedVerifier`]: stream::DetachedVerifier
75//! [`PacketPile`]: crate::PacketPile
76//! [`PacketPile::from_file`]: super::PacketPile::from_file()
77//!
78//! # Data Structures and Interfaces
79//!
80//! This crate provides several interfaces for parsing OpenPGP
81//! streams, ordered from the most convenient but least flexible to
82//! the least convenient but most flexible:
83//!
84//! - The streaming [`Verifier`], [`DetachedVerifier`], and
85//! [`Decryptor`] are the most convenient way to parse OpenPGP
86//! messages.
87//!
88//! - The [`PacketPile::from_file`] (and related methods) is the
89//! most convenient, but least flexible way to parse an arbitrary
90//! sequence of OpenPGP packets. Whereas a [`PacketPileParser`]
91//! allows the caller to determine how to handle individual
92//! packets, the [`PacketPile::from_file`] parses the whole stream
93//! at once and returns a [`PacketPile`].
94//!
95//! - The [`PacketPileParser`] abstraction builds on the
96//! [`PacketParser`] abstraction and provides a similar interface.
97//! However, after each iteration, the [`PacketPileParser`] adds the
98//! packet to a [`PacketPile`], which is returned once the packets are
99//! completely processed.
100//!
101//! This interface should only be used if the caller actually
102//! wants a [`PacketPile`]; if the OpenPGP stream is parsed in place,
103//! then using a [`PacketParser`] is better.
104//!
105//! This interface should only be used if the caller is certain
106//! that the parsed stream will fit in memory.
107//!
108//! - The [`PacketParser`] abstraction produces one packet at a
109//! time. What is done with those packets is completely up to the
110//! caller.
111//!
112//! The behavior of the [`PacketParser`] can be configured using a
113//! [`PacketParserBuilder`].
114//!
115//! [`Decryptor`]: stream::Decryptor
116//! [`Verifier`]: stream::Verifier
117//!
118//! # ASCII armored data
119//!
120//! The [`PacketParser`] will by default automatically detect and
121//! remove any ASCII armor encoding (see [Section 6 of RFC 9580]).
122//! This automatism can be disabled and fine-tuned using
123//! [`PacketParserBuilder::dearmor`].
124//!
125//! [Section 6 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-6
126//! [`PacketParserBuilder::dearmor`]: PacketParserBuilder::dearmor()
127//!
128//! # Security Considerations
129//!
130//! In general, OpenPGP data must be considered attacker controlled
131//! and thus treated with great care. Even though we use a
132//! memory-safe language, there are several aspects to be aware of:
133//!
134//! - OpenPGP messages may be compressed. Therefore, one cannot
135//! predict the uncompressed size of a message by looking at the
136//! compressed representation. Operations that parse OpenPGP
137//! streams and buffer the packet data (like using the
138//! [`PacketPile`]'s [`Parse`] interface) are inherently unsafe and
139//! must only be used on trusted data.
140//!
141//! - The authenticity of an OpenPGP message can only be checked once
142//! it has been fully processed. Therefore, the plaintext must be
143//! buffered and not be trusted until the whole message is
144//! processed and signatures and/or ciphertext integrity are
145//! verified. On the other hand, buffering an unbounded amount of
146//! data is problematic and can lead to out-of-memory situations
147//! resulting in denial of service. The streaming message
148//! processing interfaces address this problem by buffering a
149//! configurable amount of data before releasing any data to the
150//! caller, and only revert to streaming unverified data if the
151//! message exceeds the buffer. See [`DEFAULT_BUFFER_SIZE`] for
152//! more information.
153//!
154//! - Not all parts of signed-then-encrypted OpenPGP messages are
155//! authenticated. Notably, all packets outside the encryption
156//! container (any [`PKESK`] and [`SKESK`] packets, as well as the
157//! encryption container itself), the [`Literal`] packet's headers,
158//! as well as parts of the [`Signature`] are not covered by the
159//! signatures.
160//!
161//! - Ciphertext integrity is provided by the [version 2 SEIP]
162//! packet's use of authenticated encryption.
163//!
164//! - In messages compatible with [RFC 4880], ciphertext integrity is
165//! provided by the [`version 1 SEIP`] packet's [`MDC`] mechanism,
166//! but the integrity can only be checked after decrypting the whole
167//! container.
168//!
169//! [`DEFAULT_BUFFER_SIZE`]: stream::DEFAULT_BUFFER_SIZE
170//! [`PKESK`]: crate::packet::PKESK
171//! [`SKESK`]: crate::packet::PKESK
172//! [`Literal`]: crate::packet::Literal
173//! [`Signature`]: crate::packet::Signature
174//! [`version 2 SEIP`]: crate::packet::seip::SEIP2
175//! [RFC 4880]: https://datatracker.ietf.org/doc/html/rfc4880
176//! [`version 1 SEIP`]: crate::packet::seip::SEIP1
177//! [`SEIP`]: crate::packet::SEIP
178//! [`MDC`]: crate::packet::MDC
179
180use std::io;
181use std::io::prelude::*;
182use std::convert::TryFrom;
183use std::cmp;
184use std::str;
185use std::mem;
186use std::fmt;
187use std::path::Path;
188use std::result::Result as StdResult;
189
190use xxhash_rust::xxh3::Xxh3;
191
192// Re-export buffered_reader.
193//
194// We use this in our API, and re-exporting it here makes it easy to
195// use the correct version of the crate in downstream code without
196// having to explicitly depend on it.
197pub use buffered_reader;
198use ::buffered_reader::*;
199
200use crate::{
201 cert::CertValidator,
202 cert::CertValidity,
203 cert::KeyringValidator,
204 cert::KeyringValidity,
205 crypto::{aead, hash::Hash},
206 Result,
207 packet::header::{
208 CTB,
209 BodyLength,
210 PacketLengthType,
211 },
212 crypto::S2K,
213 Error,
214 packet::{
215 Container,
216 Header,
217 },
218 packet::signature::Signature3,
219 packet::signature::Signature4,
220 packet::signature::Signature6,
221 packet::prelude::*,
222 Packet,
223 Fingerprint,
224 KeyID,
225 crypto::SessionKey,
226};
227use crate::types::{
228 AEADAlgorithm,
229 CompressionAlgorithm,
230 Features,
231 HashAlgorithm,
232 KeyFlags,
233 KeyServerPreferences,
234 PublicKeyAlgorithm,
235 RevocationKey,
236 SignatureType,
237 SymmetricAlgorithm,
238 Timestamp,
239};
240use crate::crypto::{self, mpi::{PublicKey, MPI, ProtectedMPI}};
241use crate::crypto::symmetric::{Decryptor, InternalDecryptor};
242use crate::message;
243use crate::message::MessageValidator;
244
245mod partial_body;
246use self::partial_body::BufferedReaderPartialBodyFilter;
247
248use crate::packet::signature::subpacket::{
249 NotationData,
250 NotationDataFlags,
251 Subpacket,
252 SubpacketArea,
253 SubpacketLength,
254 SubpacketTag,
255 SubpacketValue,
256};
257
258use crate::serialize::MarshalInto;
259
260mod packet_pile_parser;
261pub use self::packet_pile_parser::PacketPileParser;
262
263mod hashed_reader;
264pub(crate) use self::hashed_reader::{
265 HashingMode,
266 HashedReader,
267};
268
269mod packet_parser_builder;
270pub use self::packet_parser_builder::{Dearmor, PacketParserBuilder};
271use packet_parser_builder::ARMOR_READER_LEVEL;
272
273pub mod map;
274mod mpis;
275pub mod stream;
276
277// Whether to trace execution by default (on stderr).
278const TRACE : bool = false;
279
280// How much junk the packet parser is willing to skip when recovering.
281// This is an internal implementation detail and hence not exported.
282pub(crate) const RECOVERY_THRESHOLD: usize = 32 * 1024;
283
284/// Parsing of packets and related structures.
285///
286/// This is a uniform interface to parse packets, messages, keys, and
287/// related data structures.
288///
289/// # Sealed trait
290///
291/// This trait is [sealed] and cannot be implemented for types outside this crate.
292/// Therefore it can be extended in a non-breaking way.
293/// If you want to implement the trait inside the crate
294/// you also need to implement the `seal::Sealed` marker trait.
295///
296/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
297pub trait Parse<'a, T>: crate::seal::Sealed {
298 /// Reads from the given buffered reader.
299 ///
300 /// Implementations of this function should be short. Ideally,
301 /// they should hand of the reader to a private function erasing
302 /// the readers type by invoking [`BufferedReader::into_boxed`].
303 fn from_buffered_reader<R>(reader: R) -> Result<T>
304 where
305 R: BufferedReader<Cookie> + 'a;
306
307 /// Reads from the given reader.
308 ///
309 /// The default implementation just uses
310 /// [`Parse::from_buffered_reader`], but implementations can
311 /// provide their own specialized version.
312 fn from_reader<R: 'a + Read + Send + Sync>(reader: R) -> Result<T> {
313 Self::from_buffered_reader(
314 buffered_reader::Generic::with_cookie(reader,
315 None,
316 Default::default())
317 .into_boxed())
318 }
319
320 /// Reads from the given file.
321 ///
322 /// The default implementation just uses
323 /// [`Parse::from_buffered_reader`], but implementations can
324 /// provide their own specialized version.
325 fn from_file<P: AsRef<Path>>(path: P) -> Result<T>
326 {
327 Self::from_buffered_reader(
328 buffered_reader::File::with_cookie(path.as_ref(),
329 Default::default())?
330 .into_boxed())
331 }
332
333 /// Reads from the given slice.
334 ///
335 /// The default implementation just uses
336 /// [`Parse::from_buffered_reader`], but implementations can
337 /// provide their own specialized version.
338 fn from_bytes<D: AsRef<[u8]> + ?Sized + Send + Sync>(data: &'a D) -> Result<T> {
339 Self::from_buffered_reader(
340 buffered_reader::Memory::with_cookie(data.as_ref(), Default::default())
341 .into_boxed())
342 }
343}
344
345// Implement type::from_buffered_reader and the Parse trait in terms
346// of type::from_buffered_reader for a particular packet type. If the
347// generic from_buffered_reader implementation is inappropriate, then
348// it can be overridden.
349macro_rules! impl_parse_with_buffered_reader {
350 ($typ: ident) => {
351 impl_parse_with_buffered_reader!(
352 $typ,
353 |br: Box<dyn BufferedReader<Cookie>>| -> Result<$typ> {
354 let parser = PacketHeaderParser::new_naked(br);
355
356 let mut pp = Self::parse(parser)?;
357 pp.buffer_unread_content()?;
358
359 match pp.next()? {
360 #[allow(deprecated)]
361 (Packet::$typ(o), PacketParserResult::EOF(_))
362 => Ok(o),
363 (Packet::Unknown(u), PacketParserResult::EOF(_)) =>
364 Err(u.into_error()),
365 (p, PacketParserResult::EOF(_)) =>
366 Err(Error::InvalidOperation(
367 format!("Not a {} packet: {:?}", stringify!($typ),
368 p)).into()),
369 (_, PacketParserResult::Some(_)) =>
370 Err(Error::InvalidOperation(
371 "Excess data after packet".into()).into()),
372 }
373 });
374 };
375
376 // from_buffered_reader should be a closure that takes a
377 // BufferedReader and returns a Result<Self>.
378 ($typ: ident, $from_buffered_reader: expr) => {
379 impl<'a> Parse<'a, $typ> for $typ {
380 fn from_buffered_reader<R>(reader: R) -> Result<Self>
381 where
382 R: BufferedReader<Cookie> + 'a,
383 {
384 Ok($from_buffered_reader(reader.into_boxed())?)
385 }
386 }
387 }
388}
389
390/// The default amount of acceptable nesting.
391///
392/// The default is `16`.
393///
394/// Typically, we expect a message to look like:
395///
396/// ```text
397/// [ encryption container: [ compression container: [ signature: [ literal data ]]]]
398/// ```
399///
400/// So, this should be more than enough.
401///
402/// To change the maximum recursion depth, use
403/// [`PacketParserBuilder::max_recursion_depth`].
404///
405/// [`PacketParserBuilder::max_recursion_depth`]: PacketParserBuilder::max_recursion_depth()
406pub const DEFAULT_MAX_RECURSION_DEPTH : u8 = 16;
407
408/// The default maximum size of non-container packets.
409///
410/// The default is `1 MiB`.
411///
412/// Packets that exceed this limit will be returned as
413/// `Packet::Unknown`, with the error set to `Error::PacketTooLarge`.
414///
415/// This limit applies to any packet type that is *not* a container
416/// packet, i.e. any packet that is not a literal data packet, a
417/// compressed data packet, a symmetrically encrypted data packet, or
418/// an AEAD encrypted data packet.
419///
420/// To change the maximum recursion depth, use
421/// [`PacketParserBuilder::max_packet_size`].
422///
423/// [`PacketParserBuilder::max_packet_size`]: PacketParserBuilder::max_packet_size()
424pub const DEFAULT_MAX_PACKET_SIZE: u32 = 1 << 20; // 1 MiB
425
426// Used to parse an OpenPGP packet's header (note: in this case, the
427// header means a Packet's fixed data, not the OpenPGP framing
428// information, such as the CTB, and length information).
429//
430// This struct is not exposed to the user. Instead, when a header has
431// been successfully parsed, a `PacketParser` is returned.
432pub(crate) struct PacketHeaderParser<'a> {
433 // The reader stack wrapped in a buffered_reader::Dup so that if
434 // there is a parse error, we can abort and still return an
435 // Unknown packet.
436 reader: buffered_reader::Dup<Box<dyn BufferedReader<Cookie> + 'a>, Cookie>,
437
438 // The current packet's header.
439 header: Header,
440 header_bytes: Vec<u8>,
441
442 // This packet's path.
443 path: Vec<usize>,
444
445 // The `PacketParser`'s state.
446 state: PacketParserState,
447
448 /// A map of this packet.
449 map: Option<map::Map>,
450}
451
452/// Creates a local marco called php_try! that returns an Unknown
453/// packet instead of an Error like try! on parsing-related errors.
454/// (Errors like read errors are still returned as usual.)
455///
456/// If you want to fail like this in a non-try! context, use
457/// php.fail("reason").
458macro_rules! make_php_try {
459 ($parser:expr) => {
460 macro_rules! php_try {
461 ($e:expr) => {
462 match $e {
463 Ok(b) => {
464 Ok(b)
465 },
466 Err(e) => {
467 t!("parsing failed at {}:{}: {}", file!(), line!(), e);
468 let e = match e.downcast::<io::Error>() {
469 Ok(e) =>
470 if let io::ErrorKind::UnexpectedEof = e.kind() {
471 return $parser.error(e.into());
472 } else {
473 e.into()
474 },
475 Err(e) => e,
476 };
477 let e = match e.downcast::<Error>() {
478 Ok(e) => return $parser.error(e.into()),
479 Err(e) => e,
480 };
481
482 Err(e)
483 },
484 }?
485 };
486 }
487 };
488}
489
490impl std::fmt::Debug for PacketHeaderParser<'_> {
491 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
492 f.debug_struct("PacketHeaderParser")
493 .field("header", &self.header)
494 .field("path", &self.path)
495 .field("reader", &self.reader)
496 .field("state", &self.state)
497 .field("map", &self.map)
498 .finish()
499 }
500}
501
502impl<'a> PacketHeaderParser<'a> {
503 // Returns a `PacketHeaderParser` to parse an OpenPGP packet.
504 // `inner` points to the start of the OpenPGP framing information,
505 // i.e., the CTB.
506 fn new(inner: Box<dyn BufferedReader<Cookie> + 'a>,
507 state: PacketParserState,
508 path: Vec<usize>, header: Header,
509 header_bytes: Vec<u8>) -> Self
510 {
511 assert!(!path.is_empty());
512
513 let cookie = Cookie {
514 level: inner.cookie_ref().level,
515 ..Default::default()
516 };
517 let map = if state.settings.map {
518 Some(map::Map::new(header_bytes.clone()))
519 } else {
520 None
521 };
522 PacketHeaderParser {
523 reader: buffered_reader::Dup::with_cookie(inner, cookie),
524 header,
525 header_bytes,
526 path,
527 state,
528 map,
529 }
530 }
531
532 // Returns a `PacketHeaderParser` that parses a bare packet. That
533 // is, `inner` points to the start of the packet; the OpenPGP
534 // framing has already been processed, and `inner` already
535 // includes any required filters (e.g., a
536 // `BufferedReaderPartialBodyFilter`, etc.).
537 fn new_naked(inner: Box<dyn BufferedReader<Cookie> + 'a>) -> Self {
538 PacketHeaderParser::new(inner,
539 PacketParserState::new(Default::default()),
540 vec![ 0 ],
541 Header::new(CTB::new(Tag::Reserved),
542 BodyLength::Full(0)),
543 Vec::new())
544 }
545
546 // Consumes the bytes belonging to the packet's header (i.e., the
547 // number of bytes read) from the reader, and returns a
548 // `PacketParser` that can be returned to the user.
549 //
550 // Only call this function if the packet's header has been
551 // completely and correctly parsed. If a failure occurs while
552 // parsing the header, use `fail()` instead.
553 fn ok(mut self, packet: Packet) -> Result<PacketParser<'a>> {
554 tracer!(TRACE, "PacketHeaderParser::ok",
555 self.reader.cookie_ref().level.unwrap_or(0));
556 let total_out = self.reader.total_out();
557 t!("total_out = {}", total_out);
558
559 if self.state.settings.map {
560 // Steal the body for the map.
561 self.reader.rewind();
562 let body = if self.state.settings.buffer_unread_content {
563 self.reader.steal_eof()?
564 } else {
565 self.reader.steal(total_out)?
566 };
567 t!("got {} bytes of body for the map", body.len());
568 if body.len() > total_out {
569 self.field("body", body.len() - total_out);
570 }
571 self.map.as_mut().unwrap().finalize(body);
572 }
573
574 // This is a buffered_reader::Dup, so this always has an
575 // inner.
576 let mut reader = Box::new(self.reader).into_inner().unwrap();
577
578 if total_out > 0 {
579 // We know the data has been read, so this cannot fail.
580 reader.data_consume_hard(total_out).unwrap();
581 }
582
583 Ok(PacketParser {
584 header: self.header,
585 packet,
586 path: self.path,
587 last_path: vec![],
588 reader,
589 content_was_read: false,
590 processed: true,
591 finished: false,
592 map: self.map,
593 body_hash: Some(Container::make_body_hash()),
594 state: self.state,
595 })
596 }
597
598 // Something went wrong while parsing the packet's header. Aborts
599 // and returns an Unknown packet instead.
600 fn fail(self, reason: &'static str) -> Result<PacketParser<'a>> {
601 self.error(Error::MalformedPacket(reason.into()).into())
602 }
603
604 fn error(mut self, error: anyhow::Error) -> Result<PacketParser<'a>> {
605 // Rewind the dup reader, so that the caller has a chance to
606 // buffer the whole body of the unknown packet.
607 self.reader.rewind();
608 Unknown::parse(self, error)
609 }
610
611 fn field(&mut self, name: &'static str, size: usize) {
612 if let Some(ref mut map) = self.map {
613 map.add(name, size)
614 }
615 }
616
617 fn parse_u8(&mut self, name: &'static str) -> Result<u8> {
618 let r = self.reader.data_consume_hard(1)?[0];
619 self.field(name, 1);
620 Ok(r)
621 }
622
623 fn parse_u8_len(&mut self, name: &'static str) -> Result<usize> {
624 self.parse_u8(name).map(Into::into)
625 }
626
627 fn parse_be_u16(&mut self, name: &'static str) -> Result<u16> {
628 let r = self.reader.read_be_u16()?;
629 self.field(name, 2);
630 Ok(r)
631 }
632
633 fn parse_be_u32(&mut self, name: &'static str) -> Result<u32> {
634 let r = self.reader.read_be_u32()?;
635 self.field(name, 4);
636 Ok(r)
637 }
638
639 fn parse_bool(&mut self, name: &'static str) -> Result<bool> {
640 let v = self.reader.data_consume_hard(1)?[0];
641 self.field(name, 1);
642 match v {
643 0 => Ok(false),
644 1 => Ok(true),
645 n => Err(Error::MalformedPacket(
646 format!("Invalid value for bool: {}", n)).into()),
647 }
648 }
649
650 fn parse_bytes(&mut self, name: &'static str, amount: usize)
651 -> Result<Vec<u8>> {
652 let r = self.reader.steal(amount)?;
653 self.field(name, amount);
654 Ok(r)
655 }
656
657 fn parse_bytes_into(&mut self, name: &'static str, buf: &mut [u8])
658 -> Result<()> {
659 self.reader.read_exact(buf)?;
660 self.field(name, buf.len());
661 Ok(())
662 }
663
664 fn parse_bytes_eof(&mut self, name: &'static str) -> Result<Vec<u8>> {
665 let r = self.reader.steal_eof()?;
666 self.field(name, r.len());
667 Ok(r)
668 }
669
670 fn recursion_depth(&self) -> isize {
671 self.path.len() as isize - 1
672 }
673
674 /// Marks the start of a variable-sized field `name` of length
675 /// `len`.
676 ///
677 /// After parsing the variable-sized field, hand the returned
678 /// object to [`PacketHeaderParser::variable_sized_field_end`].
679 fn variable_sized_field_start<L>(&self, name: &'static str, len: L)
680 -> VariableSizedField
681 where
682 L: Into<u32>,
683 {
684 VariableSizedField {
685 name,
686 start: self.reader.total_out().try_into()
687 .expect("offsets in packet headers cannot exceed u32"),
688 length: len.into(),
689 }
690 }
691
692 /// Returns the remaining bytes in a variable-sized field.
693 fn variable_sized_field_remaining(&self, f: &VariableSizedField) -> usize {
694 let current: u32 = self.reader.total_out().try_into()
695 .expect("offsets in packet headers cannot exceed u32");
696 f.length.saturating_sub(current - f.start) as usize
697 }
698
699 /// Marks the start of a variable-sized field and checks whether
700 /// the correct amount of data has been consumed.
701 fn variable_sized_field_end(&self, f: VariableSizedField) -> Result<()>
702 {
703 let l = u32::try_from(self.reader.total_out())
704 .expect("offsets in packet headers cannot exceed u32")
705 - f.start;
706
707 use std::cmp::Ordering;
708 match l.cmp(&f.length) {
709 Ordering::Less => Err(Error::MalformedPacket(format!(
710 "{}: length {} but only consumed {} bytes",
711 f.name, f.length, l)).into()),
712 Ordering::Equal => Ok(()),
713 Ordering::Greater => Err(Error::MalformedPacket(format!(
714 "{}: length {} but consumed {} bytes",
715 f.name, f.length, l)).into()),
716 }
717 }
718}
719
720/// Represents a variable-sized field in a packet header.
721#[must_use]
722struct VariableSizedField {
723 /// Name of the field.
724 name: &'static str,
725
726 /// The amount of bytes consumed in self.reader at the start of
727 /// the field.
728 start: u32,
729
730 /// The expected length of the variable-sized field.
731 length: u32,
732}
733
734/// What the hash in the Cookie is for.
735#[derive(Copy, Clone, PartialEq, Debug)]
736pub(crate) enum HashesFor {
737 Nothing,
738 MDC,
739 Signature,
740 CleartextSignature,
741}
742
743/// Controls whether a hashed reader hashes data.
744#[derive(Copy, Clone, PartialEq, Debug)]
745enum Hashing {
746 /// Hashing is enabled.
747 Enabled,
748 /// Hashing is enabled for notarized signatures.
749 Notarized,
750 /// Hashing is disabled.
751 Disabled,
752}
753
754/// Private state used by the `PacketParser`.
755///
756/// This is not intended to be used. It is possible to explicitly
757/// create `Cookie` instances using its `Default` implementation for
758/// low-level interfacing with parsing code.
759#[derive(Debug)]
760pub struct Cookie {
761 // `BufferedReader`s managed by a `PacketParser` have
762 // `Some(level)`; an external `BufferedReader` (i.e., the
763 // underlying `BufferedReader`) has no level.
764 //
765 // Before parsing a top-level packet, we may push a
766 // `buffered_reader::Limitor` in front of the external
767 // `BufferedReader`. Such `BufferedReader`s are assigned a level
768 // of 0.
769 //
770 // When a top-level packet (i.e., a packet with a recursion depth
771 // of 0) reads from the `BufferedReader` stack, the top
772 // `BufferedReader` will have a level of at most 0.
773 //
774 // If the top-level packet is a container, say, a `CompressedData`
775 // packet, then it pushes a decompression filter with a level of 0
776 // onto the `BufferedReader` stack, and it recursively invokes the
777 // parser.
778 //
779 // When the parser encounters the `CompressedData`'s first child,
780 // say, a `Literal` packet, it pushes a `buffered_reader::Limitor` on
781 // the `BufferedReader` stack with a level of 1. Then, a
782 // `PacketParser` for the `Literal` data packet is created with a
783 // recursion depth of 1.
784 //
785 // There are several things to note:
786 //
787 // - When a `PacketParser` with a recursion depth of N reads
788 // from the `BufferedReader` stack, the top `BufferedReader`'s
789 // level is (at most) N.
790 //
791 // - Because we sometimes don't need to push a limitor
792 // (specifically, when the length is indeterminate), the
793 // `BufferedReader` at the top of the stack may have a level
794 // less than the current `PacketParser`'s recursion depth.
795 //
796 // - When a packet at depth N is a container that filters the
797 // data, it pushes a `BufferedReader` at level N onto the
798 // `BufferedReader` stack.
799 //
800 // - When we finish parsing a packet at depth N, we pop all
801 // `BufferedReader`s from the `BufferedReader` stack that are
802 // at level N. The intuition is: the `BufferedReaders` at
803 // level N are associated with the packet at depth N.
804 //
805 // - If a OnePassSig packet occurs at the top level, then we
806 // need to push a HashedReader above the current level. The
807 // top level is level 0, thus we push the HashedReader at
808 // level -1.
809 level: Option<isize>,
810
811 hashes_for: HashesFor,
812 hashing: Hashing,
813
814 /// Keeps track of whether the last one pass signature packet had
815 /// the last flag set.
816 saw_last: bool,
817 sig_groups: Vec<SignatureGroup>,
818 /// Keep track of the maximal size of sig_groups to compute
819 /// signature levels.
820 sig_groups_max_len: usize,
821
822 /// Stashed bytes that need to be hashed.
823 ///
824 /// When checking nested signatures, we need to hash the framing.
825 /// However, at the time we know that we want to hash it, it has
826 /// already been consumed. Deferring the consumption of headers
827 /// failed due to complications with the partial body decoder
828 /// eagerly consuming data. I (Justus) decided that doing the
829 /// right thing is not worth the trouble, at least for now. Also,
830 /// hash stash sounds funny.
831 hash_stash: Option<Vec<u8>>,
832
833 /// Whether this `BufferedReader` is actually an interior EOF in a
834 /// container.
835 ///
836 /// This is used by the SEIP parser to prevent a child packet from
837 /// accidentally swallowing the trailing MDC packet. This can
838 /// happen when there is a compressed data packet with an
839 /// indeterminate body length encoding. In this case, due to
840 /// buffering, the decompressor consumes data beyond the end of
841 /// the compressed data.
842 ///
843 /// When set, buffered_reader_stack_pop will return early when it
844 /// encounters a fake EOF at the level it is popping to.
845 fake_eof: bool,
846
847 /// Indicates that this is the top-level armor reader that is
848 /// doing a transformation of a message using the cleartext
849 /// signature framework into a signed message.
850 csf_transformation: bool,
851}
852assert_send_and_sync!(Cookie);
853
854/// Contains hashes for consecutive one pass signature packets ending
855/// in one with the last flag set.
856#[derive(Default)]
857pub(crate) struct SignatureGroup {
858 /// Counts the number of one pass signature packets this group is
859 /// for. Once this drops to zero, we pop the group from the
860 /// stack.
861 ops_count: usize,
862
863 /// The hash contexts.
864 ///
865 /// We store a salt and the hash context as tuples.
866 ///
867 /// In v6, the hash is salted. We store the salt here so that we
868 /// can find the right hash context again when we encounter the
869 /// signature packet.
870 ///
871 /// In v4, the hash is not salted. Hence, salt is the zero-length
872 /// vector. The fact that the hash is not salted allows for an
873 /// optimization: to verify two signatures using the same hash
874 /// algorithm, the hash must be computed just once. We implement
875 /// this optimization for v4 signatures.
876 pub(crate) hashes: Vec<HashingMode<crypto::hash::Context>>,
877}
878
879impl fmt::Debug for SignatureGroup {
880 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
881 let algos = self.hashes.iter()
882 .map(|mode| mode.map(|ctx| ctx.algo()))
883 .collect::<Vec<_>>();
884
885 f.debug_struct("Cookie")
886 .field("ops_count", &self.ops_count)
887 .field("hashes", &algos)
888 .finish()
889 }
890}
891
892impl SignatureGroup {
893 /// Clears the signature group.
894 fn clear(&mut self) {
895 self.ops_count = 0;
896 self.hashes.clear();
897 }
898}
899
900impl Default for Cookie {
901 fn default() -> Self {
902 Cookie {
903 level: None,
904 hashing: Hashing::Enabled,
905 hashes_for: HashesFor::Nothing,
906 saw_last: false,
907 sig_groups: vec![Default::default()],
908 sig_groups_max_len: 1,
909 hash_stash: None,
910 fake_eof: false,
911 csf_transformation: false,
912 }
913 }
914}
915
916impl Cookie {
917 fn new(level: isize) -> Cookie {
918 Cookie {
919 level: Some(level),
920 hashing: Hashing::Enabled,
921 hashes_for: HashesFor::Nothing,
922 saw_last: false,
923 sig_groups: vec![Default::default()],
924 sig_groups_max_len: 1,
925 hash_stash: None,
926 fake_eof: false,
927 csf_transformation: false,
928 }
929 }
930
931 /// Returns a reference to the topmost signature group.
932 pub(crate) fn sig_group(&self) -> &SignatureGroup {
933 assert!(!self.sig_groups.is_empty());
934 &self.sig_groups[self.sig_groups.len() - 1]
935 }
936
937 /// Returns a mutable reference to the topmost signature group.
938 pub(crate) fn sig_group_mut(&mut self) -> &mut SignatureGroup {
939 assert!(!self.sig_groups.is_empty());
940 let len = self.sig_groups.len();
941 &mut self.sig_groups[len - 1]
942 }
943
944 /// Returns the level of the currently parsed signature.
945 fn signature_level(&self) -> usize {
946 // The signature with the deepest "nesting" is closest to the
947 // data, and hence level 0.
948 self.sig_groups_max_len - self.sig_groups.len()
949 }
950
951 /// Tests whether the topmost signature group is no longer used.
952 fn sig_group_unused(&self) -> bool {
953 assert!(!self.sig_groups.is_empty());
954 self.sig_groups[self.sig_groups.len() - 1].ops_count == 0
955 }
956
957 /// Pushes a new signature group to the stack.
958 fn sig_group_push(&mut self) {
959 self.sig_groups.push(Default::default());
960 self.sig_groups_max_len += 1;
961 }
962
963 /// Pops a signature group from the stack.
964 fn sig_group_pop(&mut self) {
965 if self.sig_groups.len() == 1 {
966 // Don't pop the last one, just clear it.
967 self.sig_groups[0].clear();
968 self.hashes_for = HashesFor::Nothing;
969 } else {
970 self.sig_groups.pop();
971 }
972 }
973}
974
975impl Cookie {
976 // Enables or disables signature hashers (HashesFor::Signature) at
977 // level `level`.
978 //
979 // Thus to disable the hashing of a level 3 literal packet's
980 // meta-data, we disable hashing at level 2.
981 fn hashing(reader: &mut dyn BufferedReader<Cookie>,
982 how: Hashing, level: isize) {
983 let mut reader : Option<&mut dyn BufferedReader<Cookie>>
984 = Some(reader);
985 while let Some(r) = reader {
986 {
987 let cookie = r.cookie_mut();
988 if let Some(br_level) = cookie.level {
989 if br_level < level {
990 break;
991 }
992 if br_level == level
993 && (cookie.hashes_for == HashesFor::Signature
994 || cookie.hashes_for == HashesFor::CleartextSignature)
995 {
996 cookie.hashing = how;
997 }
998 } else {
999 break;
1000 }
1001 }
1002 reader = r.get_mut();
1003 }
1004 }
1005
1006 /// Signals that we are processing a message using the Cleartext
1007 /// Signature Framework.
1008 ///
1009 /// This is used by the armor reader to signal that it has
1010 /// encountered such a message and is transforming it into an
1011 /// inline signed message.
1012 pub(crate) fn set_processing_csf_message(&mut self) {
1013 tracer!(TRACE, "set_processing_csf_message", self.level.unwrap_or(0));
1014 t!("Enabling CSF Transformation mode");
1015 self.csf_transformation = true;
1016 }
1017
1018 /// Checks if we are processing a signed message using the
1019 /// Cleartext Signature Framework.
1020 fn processing_csf_message(reader: &dyn BufferedReader<Cookie>)
1021 -> bool {
1022 let mut reader: Option<&dyn BufferedReader<Cookie>>
1023 = Some(reader);
1024 while let Some(r) = reader {
1025 if r.cookie_ref().level == Some(ARMOR_READER_LEVEL) {
1026 return r.cookie_ref().csf_transformation;
1027 } else {
1028 reader = r.get_ref();
1029 }
1030 }
1031 false
1032 }
1033}
1034
1035// Pops readers from a buffered reader stack at the specified level.
1036fn buffered_reader_stack_pop<'a>(
1037 mut reader: Box<dyn BufferedReader<Cookie> + 'a>, depth: isize)
1038 -> Result<(bool, Box<dyn BufferedReader<Cookie> + 'a>)>
1039{
1040 tracer!(TRACE, "buffered_reader_stack_pop", depth);
1041 t!("(reader level: {:?}, pop through: {})",
1042 reader.cookie_ref().level, depth);
1043
1044 while let Some(level) = reader.cookie_ref().level {
1045 assert!(level <= depth // Peel off exactly one level.
1046 || depth < 0); // Except for the topmost filters.
1047
1048 if level >= depth {
1049 let fake_eof = reader.cookie_ref().fake_eof;
1050
1051 t!("top reader at level {:?} (fake eof: {}), pop through: {}",
1052 reader.cookie_ref().level, fake_eof, depth);
1053
1054 t!("popping level {:?} reader, reader: {:?}",
1055 reader.cookie_ref().level,
1056 reader);
1057
1058 if reader.eof() && ! reader.consummated() {
1059 return Err(Error::MalformedPacket("Truncated packet".into())
1060 .into());
1061 }
1062 reader.drop_eof()?;
1063 reader = reader.into_inner().unwrap();
1064
1065 if level == depth && fake_eof {
1066 t!("Popped a fake EOF reader at level {}, stopping.", depth);
1067 return Ok((true, reader));
1068 }
1069
1070 t!("now at level {:?} reader: {:?}",
1071 reader.cookie_ref().level, reader);
1072 } else {
1073 break;
1074 }
1075 }
1076
1077 Ok((false, reader))
1078}
1079
1080
1081// A `PacketParser`'s settings.
1082#[derive(Clone, Debug)]
1083struct PacketParserSettings {
1084 // The maximum allowed recursion depth.
1085 //
1086 // There is absolutely no reason that this should be more than
1087 // 255. (GnuPG defaults to 32.) Moreover, if it is too large,
1088 // then a read from the reader pipeline could blow the stack.
1089 max_recursion_depth: u8,
1090
1091 // The maximum size of non-container packets.
1092 //
1093 // Packets that exceed this limit will be returned as
1094 // `Packet::Unknown`, with the error set to
1095 // `Error::PacketTooLarge`.
1096 //
1097 // This limit applies to any packet type that is *not* a
1098 // container packet, i.e. any packet that is not a literal data
1099 // packet, a compressed data packet, a symmetrically encrypted
1100 // data packet, or an AEAD encrypted data packet.
1101 max_packet_size: u32,
1102
1103 // Whether a packet's contents should be buffered or dropped when
1104 // the next packet is retrieved.
1105 buffer_unread_content: bool,
1106
1107 // Whether to create a map.
1108 map: bool,
1109
1110 // Whether to implicitly start hashing upon parsing OnePassSig
1111 // packets.
1112 automatic_hashing: bool,
1113}
1114
1115// The default `PacketParser` settings.
1116impl Default for PacketParserSettings {
1117 fn default() -> Self {
1118 PacketParserSettings {
1119 max_recursion_depth: DEFAULT_MAX_RECURSION_DEPTH,
1120 max_packet_size: DEFAULT_MAX_PACKET_SIZE,
1121 buffer_unread_content: false,
1122 map: false,
1123 automatic_hashing: true,
1124 }
1125 }
1126}
1127
1128impl S2K {
1129 /// Reads an S2K from `php`.
1130 fn parse_v4(php: &mut PacketHeaderParser<'_>)
1131 -> Result<Self> {
1132 Self::parse_common(php, None)
1133 }
1134
1135 /// Reads an S2K from `php` with explicit S2K length.
1136 fn parse_v6(php: &mut PacketHeaderParser, s2k_len: u8) -> Result<Self> {
1137 Self::parse_common(php, Some(s2k_len))
1138 }
1139
1140 /// Reads an S2K from `php` with optional explicit S2K length.
1141 fn parse_common(php: &mut PacketHeaderParser<'_>,
1142 s2k_len: Option<u8>)
1143 -> Result<Self>
1144 {
1145 if s2k_len == Some(0) {
1146 return Err(Error::MalformedPacket(
1147 "Invalid size for S2K object: 0 octets".into()).into());
1148 }
1149
1150 let check_size = |expected| {
1151 if let Some(got) = s2k_len {
1152 if got != expected {
1153 return Err(Error::MalformedPacket(format!(
1154 "Invalid size for S2K object: {} octets, expected {}",
1155 got, expected)));
1156 }
1157 }
1158 Ok(())
1159 };
1160
1161 let s2k = php.parse_u8("s2k_type")?;
1162 #[allow(deprecated)]
1163 let ret = match s2k {
1164 0 => {
1165 check_size(2)?;
1166 S2K::Simple {
1167 hash: HashAlgorithm::from(php.parse_u8("s2k_hash_algo")?),
1168 }
1169 },
1170 1 => {
1171 check_size(10)?;
1172 S2K::Salted {
1173 hash: HashAlgorithm::from(php.parse_u8("s2k_hash_algo")?),
1174 salt: Self::read_salt(php)?,
1175 }
1176 },
1177 3 => {
1178 check_size(11)?;
1179 S2K::Iterated {
1180 hash: HashAlgorithm::from(php.parse_u8("s2k_hash_algo")?),
1181 salt: Self::read_salt(php)?,
1182 hash_bytes: S2K::decode_count(php.parse_u8("s2k_count")?),
1183 }
1184 },
1185 4 => S2K::Argon2 {
1186 salt: {
1187 let mut b = [0u8; 16];
1188 let b_len = b.len();
1189 b.copy_from_slice(
1190 &php.parse_bytes("argon2_salt", b_len)?);
1191 b
1192 },
1193 t: php.parse_u8("argon2_t")?,
1194 p: php.parse_u8("argon2_p")?,
1195 m: php.parse_u8("argon2_m")?,
1196 },
1197 100..=110 => S2K::Private {
1198 tag: s2k,
1199 parameters: if let Some(l) = s2k_len {
1200 Some(
1201 php.parse_bytes("parameters", l as usize - 1 /* Tag */)?
1202 .into())
1203 } else {
1204 None
1205 },
1206 },
1207 u => S2K::Unknown {
1208 tag: u,
1209 parameters: if let Some(l) = s2k_len {
1210 Some(
1211 php.parse_bytes("parameters", l as usize - 1 /* Tag */)?
1212 .into())
1213 } else {
1214 None
1215 },
1216 },
1217 };
1218
1219 Ok(ret)
1220 }
1221
1222 fn read_salt(php: &mut PacketHeaderParser<'_>) -> Result<[u8; 8]> {
1223 let mut b = [0u8; 8];
1224 b.copy_from_slice(&php.parse_bytes("s2k_salt", 8)?);
1225
1226 Ok(b)
1227 }
1228}
1229
1230impl_parse_with_buffered_reader!(
1231 S2K,
1232 |bio: Box<dyn BufferedReader<Cookie>>| -> Result<Self> {
1233 let mut parser = PacketHeaderParser::new_naked(bio.into_boxed());
1234 Self::parse_v4(&mut parser)
1235 });
1236
1237impl Header {
1238 pub(crate) fn parse<R: BufferedReader<C>, C: fmt::Debug + Send + Sync> (bio: &mut R)
1239 -> Result<Header>
1240 {
1241 let ctb = CTB::try_from(bio.data_consume_hard(1)?[0])?;
1242 let length = match ctb {
1243 CTB::New(_) => BodyLength::parse_new_format(bio)?,
1244 CTB::Old(ref ctb) =>
1245 BodyLength::parse_old_format(bio, ctb.length_type())?,
1246 };
1247 Ok(Header::new(ctb, length))
1248 }
1249}
1250
1251impl_parse_with_buffered_reader!(
1252 Header,
1253 |mut reader| -> Result<Self> {
1254 Header::parse(&mut reader)
1255 });
1256
1257impl BodyLength {
1258 /// Decodes a new format body length as described in [Section
1259 /// 4.2.1 of RFC 9580].
1260 ///
1261 /// [Section 4.2.1 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-4.2.1
1262 pub(crate) fn parse_new_format<T: BufferedReader<C>, C: fmt::Debug + Send + Sync> (bio: &mut T)
1263 -> io::Result<BodyLength>
1264 {
1265 let octet1 : u8 = bio.data_consume_hard(1)?[0];
1266 match octet1 {
1267 0..=191 => // One octet.
1268 Ok(BodyLength::Full(octet1 as u32)),
1269 192..=223 => { // Two octets length.
1270 let octet2 = bio.data_consume_hard(1)?[0];
1271 Ok(BodyLength::Full(((octet1 as u32 - 192) << 8)
1272 + octet2 as u32 + 192))
1273 },
1274 224..=254 => // Partial body length.
1275 Ok(BodyLength::Partial(1 << (octet1 & 0x1F))),
1276 255 => // Five octets.
1277 Ok(BodyLength::Full(bio.read_be_u32()?)),
1278 }
1279 }
1280
1281 /// Decodes an old format body length as described in [Section
1282 /// 4.2.2 of RFC 9580].
1283 ///
1284 /// [Section 4.2.2 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-4.2.2
1285 pub(crate) fn parse_old_format<T: BufferedReader<C>, C: fmt::Debug + Send + Sync>
1286 (bio: &mut T, length_type: PacketLengthType)
1287 -> Result<BodyLength>
1288 {
1289 match length_type {
1290 PacketLengthType::OneOctet =>
1291 Ok(BodyLength::Full(bio.data_consume_hard(1)?[0] as u32)),
1292 PacketLengthType::TwoOctets =>
1293 Ok(BodyLength::Full(bio.read_be_u16()? as u32)),
1294 PacketLengthType::FourOctets =>
1295 Ok(BodyLength::Full(bio.read_be_u32()? as u32)),
1296 PacketLengthType::Indeterminate =>
1297 Ok(BodyLength::Indeterminate),
1298 }
1299 }
1300}
1301
1302#[test]
1303fn body_length_new_format() {
1304 fn test(input: &[u8], expected_result: BodyLength) {
1305 assert_eq!(
1306 BodyLength::parse_new_format(
1307 &mut buffered_reader::Memory::new(input)).unwrap(),
1308 expected_result);
1309 }
1310
1311 // Examples from Section 4.2.3 of RFC4880.
1312
1313 // Example #1.
1314 test(&[0x64][..], BodyLength::Full(100));
1315
1316 // Example #2.
1317 test(&[0xC5, 0xFB][..], BodyLength::Full(1723));
1318
1319 // Example #3.
1320 test(&[0xFF, 0x00, 0x01, 0x86, 0xA0][..], BodyLength::Full(100000));
1321
1322 // Example #4.
1323 test(&[0xEF][..], BodyLength::Partial(32768));
1324 test(&[0xE1][..], BodyLength::Partial(2));
1325 test(&[0xF0][..], BodyLength::Partial(65536));
1326 test(&[0xC5, 0xDD][..], BodyLength::Full(1693));
1327}
1328
1329#[test]
1330fn body_length_old_format() {
1331 fn test(input: &[u8], plt: PacketLengthType,
1332 expected_result: BodyLength, expected_rest: &[u8]) {
1333 let mut bio = buffered_reader::Memory::new(input);
1334 assert_eq!(BodyLength::parse_old_format(&mut bio, plt).unwrap(),
1335 expected_result);
1336 let rest = bio.data_eof();
1337 assert_eq!(rest.unwrap(), expected_rest);
1338 }
1339
1340 test(&[1], PacketLengthType::OneOctet, BodyLength::Full(1), &b""[..]);
1341 test(&[1, 2], PacketLengthType::TwoOctets,
1342 BodyLength::Full((1 << 8) + 2), &b""[..]);
1343 test(&[1, 2, 3, 4], PacketLengthType::FourOctets,
1344 BodyLength::Full((1 << 24) + (2 << 16) + (3 << 8) + 4), &b""[..]);
1345 test(&[1, 2, 3, 4, 5, 6], PacketLengthType::FourOctets,
1346 BodyLength::Full((1 << 24) + (2 << 16) + (3 << 8) + 4), &[5, 6][..]);
1347 test(&[1, 2, 3, 4], PacketLengthType::Indeterminate,
1348 BodyLength::Indeterminate, &[1, 2, 3, 4][..]);
1349}
1350
1351impl Unknown {
1352 /// Parses the body of any packet and returns an Unknown.
1353 fn parse(php: PacketHeaderParser, error: anyhow::Error)
1354 -> Result<PacketParser>
1355 {
1356 let tag = php.header.ctb().tag();
1357 php.ok(Packet::Unknown(Unknown::new(tag, error)))
1358 }
1359}
1360
1361// Read the next packet as an unknown packet.
1362//
1363// The `reader` must point to the packet's header, i.e., the CTB.
1364// This buffers the packet's contents.
1365//
1366// Note: we only need this function for testing purposes in a
1367// different module.
1368#[cfg(test)]
1369pub(crate) fn to_unknown_packet<R: Read + Send + Sync>(reader: R) -> Result<Unknown>
1370{
1371 let mut reader = buffered_reader::Generic::with_cookie(
1372 reader, None, Cookie::default());
1373 let header = Header::parse(&mut reader)?;
1374
1375 let reader : Box<dyn BufferedReader<Cookie>>
1376 = match header.length() {
1377 &BodyLength::Full(len) =>
1378 Box::new(buffered_reader::Limitor::with_cookie(
1379 reader, len as u64, Cookie::default())),
1380 &BodyLength::Partial(len) =>
1381 Box::new(BufferedReaderPartialBodyFilter::with_cookie(
1382 reader, len, true, Cookie::default())),
1383 _ => Box::new(reader),
1384 };
1385
1386 let parser = PacketHeaderParser::new(
1387 reader, PacketParserState::new(Default::default()), vec![ 0 ], header, Vec::new());
1388 let mut pp =
1389 Unknown::parse(parser,
1390 anyhow::anyhow!("explicit conversion to unknown"))?;
1391 pp.buffer_unread_content()?;
1392 pp.finish()?;
1393
1394 if let Packet::Unknown(packet) = pp.packet {
1395 Ok(packet)
1396 } else {
1397 panic!("Internal inconsistency.");
1398 }
1399}
1400
1401impl Signature {
1402 // Parses a signature packet.
1403 fn parse(mut php: PacketHeaderParser)
1404 -> Result<PacketParser>
1405 {
1406 let indent = php.recursion_depth();
1407 tracer!(TRACE, "Signature::parse", indent);
1408
1409 make_php_try!(php);
1410
1411 let version = php_try!(php.parse_u8("version"));
1412
1413 match version {
1414 3 => Signature3::parse(php),
1415 4 => Signature4::parse(php),
1416 6 => Signature6::parse(php),
1417 _ => {
1418 t!("Ignoring version {} packet.", version);
1419 php.fail("unknown version")
1420 },
1421 }
1422 }
1423
1424 /// Returns whether the data appears to be a signature (no promises).
1425 fn plausible(bio: &mut dyn BufferedReader<Cookie>, header: &Header)
1426 -> Result<()>
1427 {
1428 // XXX: Support other versions.
1429 Signature4::plausible(bio, header)
1430 }
1431
1432 /// When parsing an inline-signed message, attaches the digest to
1433 /// the signature.
1434 fn parse_finish(indent: isize, mut pp: PacketParser,
1435 hash_algo: HashAlgorithm)
1436 -> Result<PacketParser>
1437 {
1438 tracer!(TRACE, "Signature::parse_finish", indent);
1439
1440 let sig: &Signature = pp.packet.downcast_ref()
1441 .ok_or_else(
1442 || Error::InvalidOperation(
1443 format!("Called Signature::parse_finish on a {:?}",
1444 pp.packet)))?;
1445
1446 // If we are not parsing an inline-signed message, we are
1447 // done.
1448 if sig.typ() != SignatureType::Binary
1449 && sig.typ() != SignatureType::Text
1450 {
1451 return Ok(pp);
1452 }
1453
1454 let need_hash = HashingMode::for_signature(hash_algo, sig);
1455 t!("Need a {:?}", need_hash);
1456 if TRACE {
1457 pp.reader.dump(&mut std::io::stderr())?;
1458 }
1459
1460 // Locate the corresponding HashedReader and extract the
1461 // computed hash.
1462 let mut computed_digest = None;
1463 {
1464 let recursion_depth = pp.recursion_depth();
1465
1466 // We know that the top reader is not a HashedReader (it's
1467 // a buffered_reader::Dup). So, start with its child.
1468 let mut r = (&mut pp.reader).get_mut();
1469 while let Some(tmp) = r {
1470 {
1471 let cookie = tmp.cookie_mut();
1472
1473 assert!(cookie.level.unwrap_or(-1)
1474 <= recursion_depth);
1475 // The HashedReader has to be at level
1476 // 'recursion_depth - 1'.
1477 if cookie.level.is_none()
1478 || cookie.level.unwrap() < recursion_depth - 1 {
1479 t!("Abandoning search for suitable \
1480 hashed reader at {:?}.", cookie.level);
1481 break
1482 }
1483
1484 if cookie.hashes_for == HashesFor::Signature {
1485 // When verifying cleartext signed messages,
1486 // we may have more signatures than
1487 // one-pass-signature packets, but are
1488 // guaranteed to only have one signature
1489 // group.
1490 //
1491 // Only decrement the count when hashing for
1492 // signatures, not when hashing for cleartext
1493 // signatures.
1494 cookie.sig_group_mut().ops_count -= 1;
1495 }
1496
1497 if cookie.hashes_for == HashesFor::Signature
1498 || cookie.hashes_for == HashesFor::CleartextSignature
1499 {
1500 t!("Have: {:?}",
1501 cookie.sig_group().hashes.iter()
1502 .map(|h| h.map(|h| h.algo()))
1503 .collect::<Vec<_>>());
1504 if let Some(hash) =
1505 cookie.sig_group().hashes.iter().find_map(
1506 |mode|
1507 if mode.map(|ctx| ctx.algo()) == need_hash
1508 {
1509 Some(mode.as_ref())
1510 } else {
1511 None
1512 })
1513 {
1514 t!("found a {:?} HashedReader", need_hash);
1515 computed_digest = Some((cookie.signature_level(),
1516 hash.clone()));
1517 }
1518
1519 if cookie.sig_group_unused() {
1520 cookie.sig_group_pop();
1521 }
1522 break;
1523 }
1524 }
1525
1526 r = tmp.get_mut();
1527 }
1528 }
1529
1530 if let Some((level, mut hash)) = computed_digest {
1531 if let Packet::Signature(ref mut sig) = pp.packet {
1532 sig.hash(&mut hash)?;
1533
1534 let mut digest = vec![0u8; hash.digest_size()];
1535 let _ = hash.digest(&mut digest);
1536
1537 sig.set_computed_digest(Some(digest));
1538 sig.set_level(level);
1539 } else {
1540 unreachable!()
1541 }
1542 }
1543
1544 Ok(pp)
1545 }
1546}
1547
1548impl Signature6 {
1549 // Parses a signature packet.
1550 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
1551 let indent = php.recursion_depth();
1552 tracer!(TRACE, "Signature6::parse", indent);
1553
1554 make_php_try!(php);
1555
1556 let typ = php_try!(php.parse_u8("type"));
1557 let pk_algo: PublicKeyAlgorithm = php_try!(php.parse_u8("pk_algo")).into();
1558 let hash_algo: HashAlgorithm =
1559 php_try!(php.parse_u8("hash_algo")).into();
1560 let hashed_area_len = php_try!(php.parse_be_u32("hashed_area_len"));
1561 let hashed_area
1562 = php_try!(SubpacketArea::parse(&mut php,
1563 hashed_area_len as usize,
1564 hash_algo));
1565 let unhashed_area_len = php_try!(php.parse_be_u32("unhashed_area_len"));
1566 let unhashed_area
1567 = php_try!(SubpacketArea::parse(&mut php,
1568 unhashed_area_len as usize,
1569 hash_algo));
1570 let digest_prefix1 = php_try!(php.parse_u8("digest_prefix1"));
1571 let digest_prefix2 = php_try!(php.parse_u8("digest_prefix2"));
1572 if ! pk_algo.for_signing() {
1573 return php.fail("not a signature algorithm");
1574 }
1575 let salt_len = php_try!(php.parse_u8("salt_len")) as usize;
1576 let salt = php_try!(php.parse_bytes("salt", salt_len));
1577 let mpis = php_try!(
1578 crypto::mpi::Signature::_parse(pk_algo, &mut php));
1579
1580 let typ = typ.into();
1581 let sig = php_try!(Signature6::new(
1582 typ, pk_algo, hash_algo,
1583 hashed_area,
1584 unhashed_area,
1585 [digest_prefix1, digest_prefix2],
1586 salt,
1587 mpis));
1588 let pp = php.ok(sig.into())?;
1589
1590 Signature::parse_finish(indent, pp, hash_algo)
1591 }
1592}
1593
1594impl Signature4 {
1595 // Parses a signature packet.
1596 fn parse(mut php: PacketHeaderParser)
1597 -> Result<PacketParser>
1598 {
1599 let indent = php.recursion_depth();
1600 tracer!(TRACE, "Signature4::parse", indent);
1601
1602 make_php_try!(php);
1603
1604 let typ = php_try!(php.parse_u8("type"));
1605 let pk_algo: PublicKeyAlgorithm = php_try!(php.parse_u8("pk_algo")).into();
1606 let hash_algo: HashAlgorithm =
1607 php_try!(php.parse_u8("hash_algo")).into();
1608 let hashed_area_len = php_try!(php.parse_be_u16("hashed_area_len"));
1609 let hashed_area
1610 = php_try!(SubpacketArea::parse(&mut php,
1611 hashed_area_len as usize,
1612 hash_algo));
1613 let unhashed_area_len = php_try!(php.parse_be_u16("unhashed_area_len"));
1614 let unhashed_area
1615 = php_try!(SubpacketArea::parse(&mut php,
1616 unhashed_area_len as usize,
1617 hash_algo));
1618 let digest_prefix1 = php_try!(php.parse_u8("digest_prefix1"));
1619 let digest_prefix2 = php_try!(php.parse_u8("digest_prefix2"));
1620 if ! pk_algo.for_signing() {
1621 return php.fail("not a signature algorithm");
1622 }
1623 let mpis = php_try!(
1624 crypto::mpi::Signature::_parse(pk_algo, &mut php));
1625
1626 let typ = typ.into();
1627 let pp = php.ok(Packet::Signature(Signature4::new(
1628 typ, pk_algo, hash_algo,
1629 hashed_area,
1630 unhashed_area,
1631 [digest_prefix1, digest_prefix2],
1632 mpis).into()))?;
1633
1634 Signature::parse_finish(indent, pp, hash_algo)
1635 }
1636
1637 /// Returns whether the data appears to be a signature (no promises).
1638 fn plausible(bio: &mut dyn BufferedReader<Cookie>, header: &Header)
1639 -> Result<()>
1640 {
1641 // The absolute minimum size for the header is 11 bytes (this
1642 // doesn't include the signature MPIs).
1643
1644 if let BodyLength::Full(len) = header.length() {
1645 if *len < 11 {
1646 // Much too short.
1647 return Err(
1648 Error::MalformedPacket("Packet too short".into()).into());
1649 }
1650 } else {
1651 return Err(
1652 Error::MalformedPacket(
1653 format!("Unexpected body length encoding: {:?}",
1654 header.length())).into());
1655 }
1656
1657 // Make sure we have a minimum header.
1658 let data = bio.data(11)?;
1659 if data.len() < 11 {
1660 return Err(
1661 Error::MalformedPacket("Short read".into()).into());
1662 }
1663
1664 // Assume unknown == bad.
1665 let version = data[0];
1666 let typ : SignatureType = data[1].into();
1667 let pk_algo : PublicKeyAlgorithm = data[2].into();
1668 let hash_algo : HashAlgorithm = data[3].into();
1669
1670 if version == 4
1671 && !matches!(typ, SignatureType::Unknown(_))
1672 && !matches!(pk_algo, PublicKeyAlgorithm::Unknown(_))
1673 && !matches!(hash_algo, HashAlgorithm::Unknown(_))
1674 {
1675 Ok(())
1676 } else {
1677 Err(Error::MalformedPacket("Invalid or unsupported data".into())
1678 .into())
1679 }
1680 }
1681}
1682
1683impl Signature3 {
1684 // Parses a v3 signature packet.
1685 fn parse(mut php: PacketHeaderParser)
1686 -> Result<PacketParser>
1687 {
1688 let indent = php.recursion_depth();
1689 tracer!(TRACE, "Signature3::parse", indent);
1690
1691 make_php_try!(php);
1692
1693 let len = php_try!(php.parse_u8("hashed length"));
1694 if len != 5 {
1695 return php.fail("invalid length \
1696 (a v3 sig has 5 bytes of hashed data)");
1697 }
1698 let typ = php_try!(php.parse_u8("type"));
1699 let creation_time: Timestamp
1700 = php_try!(php.parse_be_u32("creation_time")).into();
1701 let issuer: KeyID
1702 = KeyID::from_bytes(&php_try!(php.parse_bytes("issuer", 8))[..]);
1703 let pk_algo: PublicKeyAlgorithm
1704 = php_try!(php.parse_u8("pk_algo")).into();
1705 let hash_algo: HashAlgorithm =
1706 php_try!(php.parse_u8("hash_algo")).into();
1707 let digest_prefix1 = php_try!(php.parse_u8("digest_prefix1"));
1708 let digest_prefix2 = php_try!(php.parse_u8("digest_prefix2"));
1709 if ! pk_algo.for_signing() {
1710 return php.fail("not a signature algorithm");
1711 }
1712 let mpis = php_try!(
1713 crypto::mpi::Signature::_parse(pk_algo, &mut php));
1714
1715 let typ = typ.into();
1716 let pp = php.ok(Packet::Signature(Signature3::new(
1717 typ, creation_time, issuer, pk_algo, hash_algo,
1718 [digest_prefix1, digest_prefix2],
1719 mpis).into()))?;
1720
1721 Signature::parse_finish(indent, pp, hash_algo)
1722 }
1723}
1724
1725impl_parse_with_buffered_reader!(Signature);
1726
1727#[test]
1728fn signature_parser_test () {
1729 use crate::serialize::MarshalInto;
1730 let data = crate::tests::message("sig.pgp");
1731
1732 {
1733 let pp = PacketParser::from_bytes(data).unwrap().unwrap();
1734 assert_eq!(pp.header.length(), &BodyLength::Full(307));
1735 if let Packet::Signature(ref p) = pp.packet {
1736 assert_eq!(p.version(), 4);
1737 assert_eq!(p.typ(), SignatureType::Binary);
1738 assert_eq!(p.pk_algo(), PublicKeyAlgorithm::RSAEncryptSign);
1739 assert_eq!(p.hash_algo(), HashAlgorithm::SHA512);
1740 assert_eq!(p.hashed_area().iter().count(), 2);
1741 assert_eq!(p.unhashed_area().iter().count(), 1);
1742 assert_eq!(p.digest_prefix(), &[0x65u8, 0x74]);
1743 assert_eq!(p.mpis().serialized_len(), 258);
1744 } else {
1745 panic!("Wrong packet!");
1746 }
1747 }
1748}
1749
1750impl SubpacketArea {
1751 // Parses a subpacket area.
1752 fn parse(php: &mut PacketHeaderParser,
1753 mut limit: usize,
1754 hash_algo: HashAlgorithm)
1755 -> Result<Self>
1756 {
1757 let indent = php.recursion_depth();
1758 tracer!(TRACE, "SubpacketArea::parse", indent);
1759
1760 let mut packets = Vec::new();
1761 while limit > 0 {
1762 let r = Subpacket::parse(php, limit, hash_algo);
1763 t!("Subpacket::parse(_, {}, {:?}) => {:?}",
1764 limit, hash_algo, r);
1765 let p = r?;
1766 assert!(limit >= p.length.len() + p.length.serialized_len());
1767 limit -= p.length.len() + p.length.serialized_len();
1768 packets.push(p);
1769 }
1770 assert!(limit == 0);
1771 Self::new(packets)
1772 }
1773}
1774
1775impl Subpacket {
1776 // Parses a raw subpacket.
1777 fn parse(php: &mut PacketHeaderParser,
1778 limit: usize,
1779 hash_algo: HashAlgorithm)
1780 -> Result<Self>
1781 {
1782 let length = SubpacketLength::parse(&mut php.reader)?;
1783 php.field("subpacket length", length.serialized_len());
1784 let len = length.len() as usize;
1785
1786 if limit < length.serialized_len() + len {
1787 return Err(Error::MalformedPacket(
1788 "Subpacket extends beyond the end of the subpacket area".into())
1789 .into());
1790 }
1791
1792 if len == 0 {
1793 return Err(Error::MalformedPacket("Zero-length subpacket".into())
1794 .into());
1795 }
1796
1797 let tag = php.parse_u8("subpacket tag")?;
1798 let len = len - 1;
1799
1800 // Remember our position in the reader to check subpacket boundaries.
1801 let total_out_before = php.reader.total_out();
1802
1803 // The critical bit is the high bit. Extract it.
1804 let critical = tag & (1 << 7) != 0;
1805 // Then clear it from the type and convert it.
1806 let tag: SubpacketTag = (tag & !(1 << 7)).into();
1807
1808 #[allow(deprecated)]
1809 let value = match tag {
1810 SubpacketTag::SignatureCreationTime =>
1811 SubpacketValue::SignatureCreationTime(
1812 php.parse_be_u32("sig creation time")?.into()),
1813 SubpacketTag::SignatureExpirationTime =>
1814 SubpacketValue::SignatureExpirationTime(
1815 php.parse_be_u32("sig expiry time")?.into()),
1816 SubpacketTag::ExportableCertification =>
1817 SubpacketValue::ExportableCertification(
1818 php.parse_bool("exportable")?),
1819 SubpacketTag::TrustSignature =>
1820 SubpacketValue::TrustSignature {
1821 level: php.parse_u8("trust level")?,
1822 trust: php.parse_u8("trust value")?,
1823 },
1824 SubpacketTag::RegularExpression => {
1825 let mut v = php.parse_bytes("regular expr", len)?;
1826 if v.is_empty() || v[v.len() - 1] != 0 {
1827 return Err(Error::MalformedPacket(
1828 "Regular expression not 0-terminated".into())
1829 .into());
1830 }
1831 v.pop();
1832 SubpacketValue::RegularExpression(v)
1833 },
1834 SubpacketTag::Revocable =>
1835 SubpacketValue::Revocable(php.parse_bool("revocable")?),
1836 SubpacketTag::KeyExpirationTime =>
1837 SubpacketValue::KeyExpirationTime(
1838 php.parse_be_u32("key expiry time")?.into()),
1839 SubpacketTag::PreferredSymmetricAlgorithms =>
1840 SubpacketValue::PreferredSymmetricAlgorithms(
1841 php.parse_bytes("pref sym algos", len)?
1842 .iter().map(|o| (*o).into()).collect()),
1843 SubpacketTag::RevocationKey => {
1844 // 1 octet of class, 1 octet of pk algorithm, 20 bytes
1845 // for a v4 fingerprint and 32 bytes for a v6
1846 // fingerprint.
1847 if len < 22 {
1848 return Err(Error::MalformedPacket(
1849 "Short revocation key subpacket".into())
1850 .into());
1851 }
1852 let class = php.parse_u8("class")?;
1853 let pk_algo = php.parse_u8("pk algo")?.into();
1854 let fp = Fingerprint::from_bytes_intern(
1855 None,
1856 &php.parse_bytes("fingerprint", len - 2)?)?;
1857 SubpacketValue::RevocationKey(
1858 RevocationKey::from_bits(pk_algo, fp, class)?)
1859 },
1860 SubpacketTag::Issuer =>
1861 SubpacketValue::Issuer(
1862 KeyID::from_bytes(&php.parse_bytes("issuer", len)?)),
1863 SubpacketTag::NotationData => {
1864 let flags = php.parse_bytes("flags", 4)?;
1865 let name_len = php.parse_be_u16("name len")? as usize;
1866 let value_len = php.parse_be_u16("value len")? as usize;
1867
1868 if len != 8 + name_len + value_len {
1869 return Err(Error::MalformedPacket(
1870 format!("Malformed notation data subpacket: \
1871 expected {} bytes, got {}",
1872 8 + name_len + value_len,
1873 len)).into());
1874 }
1875 SubpacketValue::NotationData(
1876 NotationData::new(
1877 std::str::from_utf8(
1878 &php.parse_bytes("notation name", name_len)?)
1879 .map_err(|e| anyhow::Error::from(
1880 Error::MalformedPacket(
1881 format!("Malformed notation name: {}", e)))
1882 )?,
1883 &php.parse_bytes("notation value", value_len)?,
1884 Some(NotationDataFlags::new(&flags)?)))
1885 },
1886 SubpacketTag::PreferredHashAlgorithms =>
1887 SubpacketValue::PreferredHashAlgorithms(
1888 php.parse_bytes("pref hash algos", len)?
1889 .iter().map(|o| (*o).into()).collect()),
1890 SubpacketTag::PreferredCompressionAlgorithms =>
1891 SubpacketValue::PreferredCompressionAlgorithms(
1892 php.parse_bytes("pref compression algos", len)?
1893 .iter().map(|o| (*o).into()).collect()),
1894 SubpacketTag::KeyServerPreferences =>
1895 SubpacketValue::KeyServerPreferences(
1896 KeyServerPreferences::new(
1897 &php.parse_bytes("key server pref", len)?
1898 )),
1899 SubpacketTag::PreferredKeyServer =>
1900 SubpacketValue::PreferredKeyServer(
1901 php.parse_bytes("pref key server", len)?),
1902 SubpacketTag::PrimaryUserID =>
1903 SubpacketValue::PrimaryUserID(
1904 php.parse_bool("primary user id")?),
1905 SubpacketTag::PolicyURI =>
1906 SubpacketValue::PolicyURI(php.parse_bytes("policy URI", len)?),
1907 SubpacketTag::KeyFlags =>
1908 SubpacketValue::KeyFlags(KeyFlags::new(
1909 &php.parse_bytes("key flags", len)?)),
1910 SubpacketTag::SignersUserID =>
1911 SubpacketValue::SignersUserID(
1912 php.parse_bytes("signers user id", len)?),
1913 SubpacketTag::ReasonForRevocation => {
1914 if len == 0 {
1915 return Err(Error::MalformedPacket(
1916 "Short reason for revocation subpacket".into()).into());
1917 }
1918 SubpacketValue::ReasonForRevocation {
1919 code: php.parse_u8("revocation reason")?.into(),
1920 reason: php.parse_bytes("human-readable", len - 1)?,
1921 }
1922 },
1923 SubpacketTag::Features =>
1924 SubpacketValue::Features(Features::new(
1925 &php.parse_bytes("features", len)?)),
1926 SubpacketTag::SignatureTarget => {
1927 if len < 2 {
1928 return Err(Error::MalformedPacket(
1929 "Short reason for revocation subpacket".into()).into());
1930 }
1931 SubpacketValue::SignatureTarget {
1932 pk_algo: php.parse_u8("pk algo")?.into(),
1933 hash_algo: php.parse_u8("hash algo")?.into(),
1934 digest: php.parse_bytes("digest", len - 2)?,
1935 }
1936 },
1937 SubpacketTag::EmbeddedSignature =>
1938 SubpacketValue::EmbeddedSignature(
1939 Signature::from_bytes(
1940 &php.parse_bytes("embedded sig", len)?)?),
1941 SubpacketTag::IssuerFingerprint => {
1942 if len == 0 {
1943 return Err(Error::MalformedPacket(
1944 "Short issuer fingerprint subpacket".into()).into());
1945 }
1946 let version = php.parse_u8("version")?;
1947 if let Some(expect_len) = match version {
1948 4 => Some(1 + 20),
1949 6 => Some(1 + 32),
1950 _ => None,
1951 } {
1952 if len != expect_len {
1953 return Err(Error::MalformedPacket(
1954 format!("Malformed issuer fingerprint subpacket: \
1955 expected {} bytes, got {}",
1956 expect_len, len)).into());
1957 }
1958 }
1959 let bytes = php.parse_bytes("issuer fp", len - 1)?;
1960 SubpacketValue::IssuerFingerprint(
1961 Fingerprint::from_bytes(version, &bytes)?)
1962 },
1963 SubpacketTag::IntendedRecipient => {
1964 if len == 0 {
1965 return Err(Error::MalformedPacket(
1966 "Short intended recipient subpacket".into()).into());
1967 }
1968 let version = php.parse_u8("version")?;
1969 if let Some(expect_len) = match version {
1970 4 => Some(1 + 20),
1971 6 => Some(1 + 32),
1972 _ => None,
1973 } {
1974 if len != expect_len {
1975 return Err(Error::MalformedPacket(
1976 format!("Malformed intended recipient subpacket: \
1977 expected {} bytes, got {}",
1978 expect_len, len)).into());
1979 }
1980 }
1981 let bytes = php.parse_bytes("intended rcpt", len - 1)?;
1982 SubpacketValue::IntendedRecipient(
1983 Fingerprint::from_bytes(version, &bytes)?)
1984 },
1985 SubpacketTag::ApprovedCertifications => {
1986 // If we don't know the hash algorithm, put all digest
1987 // into one bucket. That way, at least it will
1988 // roundtrip. It will never verify, because we don't
1989 // know the hash.
1990 let digest_size =
1991 hash_algo.context().map(|c| c.for_digest().digest_size())
1992 .unwrap_or(len);
1993
1994 if digest_size == 0 {
1995 // Empty body with unknown hash algorithm.
1996 SubpacketValue::ApprovedCertifications(
1997 Vec::with_capacity(0))
1998 } else {
1999 if len % digest_size != 0 {
2000 return Err(Error::BadSignature(
2001 "Wrong number of bytes in certification subpacket"
2002 .into()).into());
2003 }
2004 let bytes = php.parse_bytes("attested crts", len)?;
2005 SubpacketValue::ApprovedCertifications(
2006 bytes.chunks(digest_size).map(Into::into).collect())
2007 }
2008 },
2009
2010 SubpacketTag::PreferredAEADCiphersuites => {
2011 if len % 2 != 0 {
2012 return Err(Error::BadSignature(
2013 "Wrong number of bytes in preferred AEAD \
2014 Ciphersuites subpacket"
2015 .into()).into());
2016 }
2017
2018 SubpacketValue::PreferredAEADCiphersuites(
2019 php.parse_bytes("pref aead ciphersuites", len)?
2020 .chunks(2).map(|o| (o[0].into(),
2021 o[1].into())).collect())
2022 },
2023
2024 SubpacketTag::Reserved(_)
2025 | SubpacketTag::PlaceholderForBackwardCompatibility
2026 | SubpacketTag::PreferredAEADAlgorithms
2027 | SubpacketTag::Private(_)
2028 | SubpacketTag::Unknown(_) =>
2029 SubpacketValue::Unknown {
2030 tag,
2031 body: php.parse_bytes("unknown subpacket", len)?,
2032 },
2033 };
2034
2035 let total_out = php.reader.total_out();
2036 if total_out_before + len != total_out {
2037 return Err(Error::MalformedPacket(
2038 format!("Malformed subpacket: \
2039 body length is {} bytes, but read {}",
2040 len, total_out - total_out_before)).into());
2041 }
2042
2043 Ok(Subpacket::with_length(
2044 length,
2045 value,
2046 critical,
2047 ))
2048 }
2049}
2050
2051impl SubpacketLength {
2052 /// Parses a subpacket length.
2053 fn parse<R: BufferedReader<C>, C: fmt::Debug + Send + Sync>(bio: &mut R) -> Result<Self> {
2054 let octet1 = bio.data_consume_hard(1)?[0];
2055 if octet1 < 192 {
2056 // One octet.
2057 Ok(Self::new(
2058 octet1 as u32,
2059 // Unambiguous.
2060 None))
2061 } else if (192..255).contains(&octet1) {
2062 // Two octets length.
2063 let octet2 = bio.data_consume_hard(1)?[0];
2064 let len = ((octet1 as u32 - 192) << 8) + octet2 as u32 + 192;
2065 Ok(Self::new(
2066 len,
2067 if Self::len_optimal_encoding(len) == 2 {
2068 None
2069 } else {
2070 Some(vec![octet1, octet2])
2071 }))
2072 } else {
2073 // Five octets.
2074 assert_eq!(octet1, 255);
2075 let len = bio.read_be_u32()?;
2076 Ok(Self::new(
2077 len,
2078 if Self::len_optimal_encoding(len) == 5 {
2079 None
2080 } else {
2081 let mut out = Vec::with_capacity(5);
2082 out.push(octet1);
2083 out.extend_from_slice(&len.to_be_bytes());
2084 Some(out)
2085 }))
2086 }
2087 }
2088}
2089
2090#[cfg(test)]
2091quickcheck! {
2092 fn length_roundtrip(l: u32) -> bool {
2093 use crate::serialize::Marshal;
2094
2095 let length = SubpacketLength::from(l);
2096 let mut encoded = Vec::new();
2097 length.serialize(&mut encoded).unwrap();
2098 assert_eq!(encoded.len(), length.serialized_len());
2099 let mut reader = buffered_reader::Memory::new(&encoded);
2100 SubpacketLength::parse(&mut reader).unwrap().len() == l as usize
2101 }
2102}
2103
2104impl OnePassSig {
2105 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
2106 let indent = php.recursion_depth();
2107 tracer!(TRACE, "OnePassSig", indent);
2108
2109 make_php_try!(php);
2110
2111 let version = php_try!(php.parse_u8("version"));
2112 match version {
2113 3 => OnePassSig3::parse(php),
2114 6 => OnePassSig6::parse(php),
2115 _ => {
2116 t!("Ignoring version {} packet", version);
2117
2118 // Unknown version. Return an unknown packet.
2119 php.fail("unknown version")
2120 },
2121 }
2122 }
2123}
2124
2125impl_parse_with_buffered_reader!(OnePassSig);
2126
2127impl OnePassSig3 {
2128 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
2129 let indent = php.recursion_depth();
2130 tracer!(TRACE, "OnePassSig3", indent);
2131
2132 make_php_try!(php);
2133
2134 let typ = php_try!(php.parse_u8("type"));
2135 let hash_algo = php_try!(php.parse_u8("hash_algo"));
2136 let pk_algo = php_try!(php.parse_u8("pk_algo"));
2137 let mut issuer = [0u8; 8];
2138 issuer.copy_from_slice(&php_try!(php.parse_bytes("issuer", 8)));
2139 let last = php_try!(php.parse_u8("last"));
2140
2141 let hash_algo = hash_algo.into();
2142 let typ = typ.into();
2143 let mut sig = OnePassSig3::new(typ);
2144 sig.set_hash_algo(hash_algo);
2145 sig.set_pk_algo(pk_algo.into());
2146 sig.set_issuer(KeyID::from_bytes(&issuer));
2147 sig.set_last_raw(last);
2148 let need_hash = HashingMode::for_salt_and_type(hash_algo, &[], typ);
2149
2150 let recursion_depth = php.recursion_depth();
2151
2152 // Check if we are processing a cleartext signed message.
2153 let want_hashes_for = if Cookie::processing_csf_message(&php.reader) {
2154 HashesFor::CleartextSignature
2155 } else {
2156 HashesFor::Signature
2157 };
2158
2159 // Walk up the reader chain to see if there is already a
2160 // hashed reader on level recursion_depth - 1.
2161 let done = {
2162 let mut done = false;
2163 let mut reader : Option<&mut dyn BufferedReader<Cookie>>
2164 = Some(&mut php.reader);
2165 while let Some(r) = reader {
2166 {
2167 let cookie = r.cookie_mut();
2168 if let Some(br_level) = cookie.level {
2169 if br_level < recursion_depth - 1 {
2170 break;
2171 }
2172 if br_level == recursion_depth - 1
2173 && cookie.hashes_for == want_hashes_for {
2174 // We found a suitable hashed reader.
2175 if cookie.saw_last {
2176 cookie.sig_group_push();
2177 cookie.saw_last = false;
2178 cookie.hash_stash =
2179 Some(php.header_bytes.clone());
2180 }
2181
2182 // Make sure that it uses the required
2183 // hash algorithm.
2184 if php.state.settings.automatic_hashing
2185 && ! cookie.sig_group().hashes.iter()
2186 .any(|mode| {
2187 mode.map(|ctx| ctx.algo()) == need_hash
2188 })
2189 {
2190 if let Ok(ctx) = hash_algo.context() {
2191 let ctx = ctx.for_signature(4);
2192 cookie.sig_group_mut().hashes.push(
2193 HashingMode::for_salt_and_type(
2194 ctx, &[], typ)
2195 );
2196 }
2197 }
2198
2199 // Account for this OPS packet.
2200 cookie.sig_group_mut().ops_count += 1;
2201
2202 // Keep track of the last flag.
2203 cookie.saw_last = last > 0;
2204
2205 // We're done.
2206 done = true;
2207 break;
2208 }
2209 } else {
2210 break;
2211 }
2212 }
2213 reader = r.get_mut();
2214 }
2215 done
2216 };
2217 // Commit here after potentially pushing a signature group.
2218 let mut pp = php.ok(Packet::OnePassSig(sig.into()))?;
2219 if done {
2220 return Ok(pp);
2221 }
2222
2223 // We create an empty hashed reader even if we don't support
2224 // the hash algorithm so that we have something to match
2225 // against when we get to the Signature packet. Or, automatic
2226 // hashing may be disabled, and we want to be able to enable
2227 // it explicitly.
2228 let mut algos = Vec::new();
2229 if pp.state.settings.automatic_hashing && hash_algo.is_supported() {
2230 algos.push(HashingMode::for_salt_and_type(hash_algo, &[], typ));
2231 }
2232
2233 // We can't push the HashedReader on the BufferedReader stack:
2234 // when we finish processing this OnePassSig packet, it will
2235 // be popped. Instead, we need to insert it at the next
2236 // higher level. Unfortunately, this isn't possible. But,
2237 // since we're done reading the current packet, we can pop the
2238 // readers associated with it, and then push the HashedReader.
2239 // This is a bit of a layering violation, but I (Neal) can't
2240 // think of a more elegant solution.
2241
2242 assert!(pp.reader.cookie_ref().level <= Some(recursion_depth));
2243 let (fake_eof, reader)
2244 = buffered_reader_stack_pop(Box::new(pp.take_reader()),
2245 recursion_depth)?;
2246 // We only pop the buffered readers for the OPS, and we
2247 // (currently) never use a fake eof for OPS packets.
2248 assert!(! fake_eof);
2249
2250 let mut reader = HashedReader::new(
2251 reader, want_hashes_for, algos)?;
2252 reader.cookie_mut().level = Some(recursion_depth - 1);
2253 // Account for this OPS packet.
2254 reader.cookie_mut().sig_group_mut().ops_count += 1;
2255 // Keep track of the last flag.
2256 reader.cookie_mut().saw_last = last > 0;
2257
2258 t!("Pushed a hashed reader, level {:?}", reader.cookie_mut().level);
2259
2260 // We add an empty limitor on top of the hashed reader,
2261 // because when we are done processing a packet,
2262 // PacketParser::finish discards any unread data from the top
2263 // reader. Since the top reader is the HashedReader, this
2264 // discards any following packets. To prevent this, we push a
2265 // Limitor on the reader stack.
2266 let mut reader = buffered_reader::Limitor::with_cookie(
2267 reader, 0, Cookie::default());
2268 reader.cookie_mut().level = Some(recursion_depth);
2269
2270 pp.reader = Box::new(reader);
2271
2272 Ok(pp)
2273 }
2274}
2275
2276impl PacketParser<'_> {
2277 /// Starts hashing for the current [`OnePassSig`] packet.
2278 ///
2279 /// If automatic hashing is disabled using
2280 /// [`PacketParserBuilder::automatic_hashing`], then hashing can
2281 /// be explicitly enabled while parsing a [`OnePassSig`] packet.
2282 ///
2283 /// If this function is called on a packet other than a
2284 /// [`OnePassSig`] packet, it returns [`Error::InvalidOperation`].
2285 ///
2286 /// [`Error::InvalidOperation`]: crate::Error::InvalidOperation
2287 ///
2288 /// # Examples
2289 ///
2290 /// ```rust
2291 /// # fn main() -> sequoia_openpgp::Result<()> {
2292 /// # use sequoia_openpgp as openpgp;
2293 /// # use openpgp::{Cert, Packet};
2294 /// # use openpgp::parse::{Parse, PacketParserResult, PacketParserBuilder};
2295 /// // Parse a signed message, verify using the signer's key.
2296 /// let message_data: &[u8] = // ...
2297 /// # include_bytes!("../tests/data/messages/signed-1-eddsa-ed25519.pgp");
2298 /// # let cert: Cert = // ...
2299 /// # Cert::from_bytes(include_bytes!("../tests/data/keys/emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
2300 /// let signer = // ...
2301 /// # cert.primary_key().key();
2302 /// let mut good = false;
2303 /// let mut ppr = PacketParserBuilder::from_bytes(message_data)?
2304 /// .automatic_hashing(false)
2305 /// .build()?;
2306 /// while let PacketParserResult::Some(mut pp) = ppr {
2307 /// if let Packet::OnePassSig(_) = &pp.packet {
2308 /// pp.start_hashing()?;
2309 /// }
2310 /// if let Packet::Signature(sig) = &mut pp.packet {
2311 /// good |= sig.verify_document(signer).is_ok();
2312 /// }
2313 /// // Start parsing the next packet, recursing.
2314 /// ppr = pp.recurse()?.1;
2315 /// }
2316 /// assert!(good);
2317 /// # Ok(()) }
2318 /// ```
2319 pub fn start_hashing(&mut self) -> Result<()> {
2320 let ops: &OnePassSig = self.packet.downcast_ref()
2321 .ok_or_else(|| Error::InvalidOperation(
2322 "Must only be invoked on one-pass-signature packets".into())
2323 )?;
2324
2325 let sig_version = match ops.version() {
2326 3 => 4,
2327 n => return Err(Error::InvalidOperation(
2328 format!("don't know how to hash for v{} one pass sig",
2329 n)).into()),
2330 };
2331
2332 let hash_algo = ops.hash_algo();
2333 let typ = ops.typ();
2334 let salt = ops.salt().unwrap_or(&[]);
2335 let need_hash = HashingMode::for_salt_and_type(hash_algo, salt, typ);
2336 let recursion_depth = self.recursion_depth();
2337 let want_hashes_for = if Cookie::processing_csf_message(&self.reader) {
2338 HashesFor::CleartextSignature
2339 } else {
2340 HashesFor::Signature
2341 };
2342
2343 // Walk up the reader chain to find the hashed reader on level
2344 // recursion_depth - 1.
2345 let mut reader : Option<&mut dyn BufferedReader<Cookie>>
2346 = Some(&mut self.reader);
2347 while let Some(r) = reader {
2348 {
2349 let cookie = r.cookie_mut();
2350 if let Some(br_level) = cookie.level {
2351 if br_level < recursion_depth - 1 {
2352 break;
2353 }
2354 if br_level == recursion_depth - 1
2355 && cookie.hashes_for == want_hashes_for {
2356 // We found a suitable hashed reader.
2357 // Make sure that it uses the required
2358 // hash algorithm.
2359 if ! cookie.sig_group().hashes.iter()
2360 .any(|mode| {
2361 mode.map(|ctx| ctx.algo()) == need_hash
2362 })
2363 {
2364 let mut ctx = hash_algo.context()?
2365 .for_signature(sig_version);
2366
2367 ctx.update(&salt);
2368 cookie.sig_group_mut().hashes.push(
2369 HashingMode::for_salt_and_type(
2370 ctx, salt, typ));
2371 }
2372 break;
2373 }
2374 } else {
2375 break;
2376 }
2377 }
2378 reader = r.get_mut();
2379 }
2380
2381 Ok(())
2382 }
2383}
2384
2385#[test]
2386fn one_pass_sig3_parser_test () {
2387 use crate::SignatureType;
2388 use crate::PublicKeyAlgorithm;
2389
2390 // This test assumes that the first packet is a OnePassSig packet.
2391 let data = crate::tests::message("signed-1.pgp");
2392 let mut pp = PacketParser::from_bytes(data).unwrap().unwrap();
2393 let p = pp.finish().unwrap();
2394 // eprintln!("packet: {:?}", p);
2395
2396 if let &Packet::OnePassSig(ref p) = p {
2397 assert_eq!(p.version(), 3);
2398 assert_eq!(p.typ(), SignatureType::Binary);
2399 assert_eq!(p.hash_algo(), HashAlgorithm::SHA512);
2400 assert_eq!(p.pk_algo(), PublicKeyAlgorithm::RSAEncryptSign);
2401 assert_eq!(format!("{:X}", p.issuer()), "7223B56678E02528");
2402 assert_eq!(p.last_raw(), 1);
2403 } else {
2404 panic!("Wrong packet!");
2405 }
2406}
2407
2408impl_parse_with_buffered_reader!(
2409 OnePassSig3,
2410 |reader| -> Result<Self> {
2411 OnePassSig::from_buffered_reader(reader).and_then(|p| match p {
2412 OnePassSig::V3(p) => Ok(p),
2413 p => Err(Error::InvalidOperation(
2414 format!("Not a OnePassSig::V3 packet: {:?}", p)).into()),
2415 })
2416 });
2417
2418impl OnePassSig6 {
2419 #[allow(clippy::blocks_in_conditions)]
2420 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
2421 let indent = php.recursion_depth();
2422 tracer!(TRACE, "OnePassSig6", indent);
2423
2424 make_php_try!(php);
2425
2426 let typ = php_try!(php.parse_u8("type"));
2427 let hash_algo = php_try!(php.parse_u8("hash_algo"));
2428 let pk_algo = php_try!(php.parse_u8("pk_algo"));
2429 let salt_len = php_try!(php.parse_u8("salt_len"));
2430 let salt = php_try!(php.parse_bytes("salt", salt_len.into()));
2431 let mut issuer = [0u8; 32];
2432 issuer.copy_from_slice(&php_try!(php.parse_bytes("issuer", 32)));
2433 let last = php_try!(php.parse_u8("last"));
2434
2435 let hash_algo = hash_algo.into();
2436 let typ = typ.into();
2437 let mut sig =
2438 OnePassSig6::new(typ, Fingerprint::from_bytes(6, &issuer)?);
2439 sig.set_salt(salt.clone());
2440 sig.set_hash_algo(hash_algo);
2441 sig.set_pk_algo(pk_algo.into());
2442 sig.set_last_raw(last);
2443 let need_hash = HashingMode::for_salt_and_type(hash_algo, &salt, typ);
2444
2445 let recursion_depth = php.recursion_depth();
2446
2447 // Check if we are processing a cleartext signed message.
2448 let want_hashes_for = if Cookie::processing_csf_message(&php.reader) {
2449 HashesFor::CleartextSignature
2450 } else {
2451 HashesFor::Signature
2452 };
2453
2454 // Walk up the reader chain to see if there is already a
2455 // hashed reader on level recursion_depth - 1.
2456 let done = {
2457 let mut done = false;
2458 let mut reader : Option<&mut dyn BufferedReader<Cookie>>
2459 = Some(&mut php.reader);
2460 while let Some(r) = reader {
2461 {
2462 let cookie = r.cookie_mut();
2463 if let Some(br_level) = cookie.level {
2464 if br_level < recursion_depth - 1 {
2465 break;
2466 }
2467 if br_level == recursion_depth - 1
2468 && cookie.hashes_for == want_hashes_for {
2469 // We found a suitable hashed reader.
2470 if cookie.saw_last {
2471 cookie.sig_group_push();
2472 cookie.saw_last = false;
2473 cookie.hash_stash =
2474 Some(php.header_bytes.clone());
2475 }
2476
2477 // Make sure that it uses the required
2478 // hash algorithm.
2479 if php.state.settings.automatic_hashing
2480 && ! cookie.sig_group().hashes.iter()
2481 .any(|mode| {
2482 mode.map(|ctx| ctx.algo()) == need_hash
2483 })
2484 {
2485 if let Ok(ctx) = hash_algo.context() {
2486 let mut ctx = ctx.for_signature(6);
2487 ctx.update(&salt);
2488 cookie.sig_group_mut().hashes.push(
2489 HashingMode::for_salt_and_type(
2490 ctx, &salt, typ)
2491 );
2492 }
2493 }
2494
2495 // Account for this OPS packet.
2496 cookie.sig_group_mut().ops_count += 1;
2497
2498 // Keep track of the last flag.
2499 cookie.saw_last = last > 0;
2500
2501 // We're done.
2502 done = true;
2503 break;
2504 }
2505 } else {
2506 break;
2507 }
2508 }
2509 reader = r.get_mut();
2510 }
2511 done
2512 };
2513 // Commit here after potentially pushing a signature group.
2514 let mut pp = php.ok(Packet::OnePassSig(sig.into()))?;
2515 if done {
2516 return Ok(pp);
2517 }
2518
2519 // We create an empty hashed reader even if we don't support
2520 // the hash algorithm so that we have something to match
2521 // against when we get to the Signature packet.
2522 let mut algos = Vec::new();
2523 if pp.state.settings.automatic_hashing && hash_algo.is_supported() {
2524 algos.push(HashingMode::for_salt_and_type(hash_algo, &salt, typ));
2525 }
2526
2527 // We can't push the HashedReader on the BufferedReader stack:
2528 // when we finish processing this OnePassSig packet, it will
2529 // be popped. Instead, we need to insert it at the next
2530 // higher level. Unfortunately, this isn't possible. But,
2531 // since we're done reading the current packet, we can pop the
2532 // readers associated with it, and then push the HashedReader.
2533 // This is a bit of a layering violation, but I (Neal) can't
2534 // think of a more elegant solution.
2535
2536 assert!(pp.reader.cookie_ref().level <= Some(recursion_depth));
2537 let (fake_eof, reader)
2538 = buffered_reader_stack_pop(Box::new(pp.take_reader()),
2539 recursion_depth)?;
2540 // We only pop the buffered readers for the OPS, and we
2541 // (currently) never use a fake eof for OPS packets.
2542 assert!(! fake_eof);
2543
2544 let mut reader = HashedReader::new(
2545 reader, want_hashes_for, algos)?;
2546 reader.cookie_mut().level = Some(recursion_depth - 1);
2547 // Account for this OPS packet.
2548 reader.cookie_mut().sig_group_mut().ops_count += 1;
2549 // Keep track of the last flag.
2550 reader.cookie_mut().saw_last = last > 0;
2551
2552 t!("Pushed a hashed reader, level {:?}", reader.cookie_mut().level);
2553
2554 // We add an empty limitor on top of the hashed reader,
2555 // because when we are done processing a packet,
2556 // PacketParser::finish discards any unread data from the top
2557 // reader. Since the top reader is the HashedReader, this
2558 // discards any following packets. To prevent this, we push a
2559 // Limitor on the reader stack.
2560 let mut reader = buffered_reader::Limitor::with_cookie(
2561 reader, 0, Cookie::default());
2562 reader.cookie_mut().level = Some(recursion_depth);
2563
2564 pp.reader = Box::new(reader);
2565
2566 Ok(pp)
2567 }
2568}
2569
2570impl_parse_with_buffered_reader!(
2571 OnePassSig6,
2572 |reader| -> Result<Self> {
2573 OnePassSig::from_buffered_reader(reader).and_then(|p| match p {
2574 OnePassSig::V6(p) => Ok(p),
2575 p => Err(Error::InvalidOperation(
2576 format!("Not a OnePassSig::V6 packet: {:?}", p)).into()),
2577 })
2578 });
2579
2580#[test]
2581fn one_pass_sig_test () {
2582 struct Test<'a> {
2583 filename: &'a str,
2584 digest_prefix: Vec<[u8; 2]>,
2585 }
2586
2587 let tests = [
2588 Test {
2589 filename: "signed-1.pgp",
2590 digest_prefix: vec![ [ 0x83, 0xF5 ] ],
2591 },
2592 Test {
2593 filename: "signed-2-partial-body.pgp",
2594 digest_prefix: vec![ [ 0x2F, 0xBE ] ],
2595 },
2596 Test {
2597 filename: "signed-3-partial-body-multiple-sigs.pgp",
2598 digest_prefix: vec![ [ 0x29, 0x64 ], [ 0xff, 0x7d ] ],
2599 },
2600 ];
2601
2602 for test in tests.iter() {
2603 eprintln!("Trying {}...", test.filename);
2604 let mut ppr = PacketParserBuilder::from_bytes(
2605 crate::tests::message(test.filename))
2606 .expect(&format!("Reading {}", test.filename)[..])
2607 .build().unwrap();
2608
2609 let mut one_pass_sigs = 0;
2610 let mut sigs = 0;
2611
2612 while let PacketParserResult::Some(pp) = ppr {
2613 if let Packet::OnePassSig(_) = pp.packet {
2614 one_pass_sigs += 1;
2615 } else if let Packet::Signature(ref sig) = pp.packet {
2616 eprintln!(" {}:\n prefix: expected: {}, in sig: {}",
2617 test.filename,
2618 crate::fmt::to_hex(&test.digest_prefix[sigs][..], false),
2619 crate::fmt::to_hex(sig.digest_prefix(), false));
2620 eprintln!(" computed hash: {}",
2621 crate::fmt::to_hex(sig.computed_digest().unwrap(),
2622 false));
2623
2624 assert_eq!(&test.digest_prefix[sigs], sig.digest_prefix());
2625 assert_eq!(&test.digest_prefix[sigs][..],
2626 &sig.computed_digest().unwrap()[..2]);
2627
2628 sigs += 1;
2629 } else if one_pass_sigs > 0 {
2630 assert_eq!(one_pass_sigs, test.digest_prefix.len(),
2631 "Number of OnePassSig packets does not match \
2632 number of expected OnePassSig packets.");
2633 }
2634
2635 ppr = pp.recurse().expect("Parsing message").1;
2636 }
2637 assert_eq!(one_pass_sigs, sigs,
2638 "Number of OnePassSig packets does not match \
2639 number of signature packets.");
2640
2641 eprintln!("done.");
2642 }
2643}
2644
2645// Key::parse doesn't actually use the Key type parameters. So, we
2646// can just set them to anything. This avoids the caller having to
2647// set them to something.
2648impl Key<key::UnspecifiedParts, key::UnspecifiedRole>
2649{
2650 /// Parses the body of a public key, public subkey, secret key or
2651 /// secret subkey packet.
2652 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
2653 tracer!(TRACE, "Key::parse", php.recursion_depth());
2654 make_php_try!(php);
2655 let tag = php.header.ctb().tag();
2656 assert!(tag == Tag::Reserved
2657 || tag == Tag::PublicKey
2658 || tag == Tag::PublicSubkey
2659 || tag == Tag::SecretKey
2660 || tag == Tag::SecretSubkey);
2661 let version = php_try!(php.parse_u8("version"));
2662
2663 match version {
2664 4 => Key4::parse(php),
2665 6 => Key6::parse(php),
2666 _ => php.fail("unknown version"),
2667 }
2668 }
2669
2670 /// Returns whether the data appears to be a key (no promises).
2671 fn plausible(bio: &mut dyn BufferedReader<Cookie>, header: &Header)
2672 -> Result<()>
2673 {
2674 // The packet's header is 6 bytes.
2675 if let BodyLength::Full(len) = header.length() {
2676 if *len < 6 {
2677 // Much too short.
2678 return Err(Error::MalformedPacket(
2679 format!("Packet too short ({} bytes)", len)).into());
2680 }
2681 } else {
2682 return Err(
2683 Error::MalformedPacket(
2684 format!("Unexpected body length encoding: {:?}",
2685 header.length())).into());
2686 }
2687
2688 // Make sure we have a minimum header.
2689 let data = bio.data(6)?;
2690 if data.len() < 6 {
2691 return Err(
2692 Error::MalformedPacket("Short read".into()).into());
2693 }
2694
2695 // Assume unknown == bad.
2696 let version = data[0];
2697 match version {
2698 4 => Key4::plausible(bio, header),
2699 6 => Key6::plausible(bio, header),
2700 n => Err(Error::MalformedPacket(
2701 format!("Unknown version {}", n)).into()),
2702 }
2703 }
2704}
2705
2706// Key4::parse doesn't actually use the Key4 type parameters. So, we
2707// can just set them to anything. This avoids the caller having to
2708// set them to something.
2709impl Key4<key::UnspecifiedParts, key::UnspecifiedRole>
2710{
2711 /// Parses the body of a public key, public subkey, secret key or
2712 /// secret subkey packet.
2713 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
2714 tracer!(TRACE, "Key4::parse", php.recursion_depth());
2715 make_php_try!(php);
2716 let tag = php.header.ctb().tag();
2717 assert!(tag == Tag::Reserved
2718 || tag == Tag::PublicKey
2719 || tag == Tag::PublicSubkey
2720 || tag == Tag::SecretKey
2721 || tag == Tag::SecretSubkey);
2722
2723 let creation_time = php_try!(php.parse_be_u32("creation_time"));
2724 let pk_algo: PublicKeyAlgorithm = php_try!(php.parse_u8("pk_algo")).into();
2725 let mpis = php_try!(PublicKey::_parse(pk_algo, &mut php));
2726 let secret = if let Ok(s2k_usage) = php.parse_u8("s2k_usage") {
2727 use crypto::mpi;
2728 let sec = match s2k_usage {
2729 // Unencrypted
2730 0 => {
2731 let sec = php_try!(
2732 mpi::SecretKeyMaterial::_parse(
2733 pk_algo, &mut php,
2734 Some(mpi::SecretKeyChecksum::Sum16)));
2735 sec.into()
2736 }
2737
2738 // AEAD encrypted secrets.
2739 253 => {
2740 let sym_algo: SymmetricAlgorithm =
2741 php_try!(php.parse_u8("sym_algo")).into();
2742
2743 let aead_algo: AEADAlgorithm =
2744 php_try!(php.parse_u8("aead_algo")).into();
2745
2746 let s2k = php_try!(S2K::parse_v4(&mut php));
2747
2748 let aead_iv = php_try!(php.parse_bytes(
2749 "aead_iv",
2750 // If we don't know the AEAD mode, we won't
2751 // know the nonce size, and all the IV will
2752 // end up in the ciphertext. This is an
2753 // inherent limitation of the v4 packet
2754 // format.
2755 aead_algo.nonce_size().unwrap_or(0)))
2756 .into();
2757
2758 let cipher =
2759 php_try!(php.parse_bytes_eof("encrypted_mpis"))
2760 .into_boxed_slice();
2761
2762 crate::packet::key::Encrypted::new_aead(
2763 s2k, sym_algo, aead_algo, aead_iv, cipher).into()
2764 },
2765
2766 // Encrypted, whether we support the S2K method or not.
2767 _ => {
2768 let sk: SymmetricAlgorithm = match s2k_usage {
2769 254 | 255 =>
2770 php_try!(php.parse_u8("sym_algo")).into(),
2771 _ => s2k_usage.into(),
2772 };
2773 let s2k = match s2k_usage {
2774 254 | 255 => php_try!(S2K::parse_v4(&mut php)),
2775 _ => {
2776 #[allow(deprecated)] S2K::Implicit
2777 },
2778 };
2779 let s2k_supported = s2k.is_supported();
2780 let cipher =
2781 php_try!(php.parse_bytes_eof("encrypted_mpis"))
2782 .into_boxed_slice();
2783
2784 crate::packet::key::Encrypted::new_raw(
2785 s2k, sk,
2786 match s2k_usage {
2787 254 => Some(mpi::SecretKeyChecksum::SHA1),
2788 255 => Some(mpi::SecretKeyChecksum::Sum16),
2789 _ => Some(mpi::SecretKeyChecksum::Sum16),
2790 },
2791 if s2k_supported {
2792 Ok((0, cipher))
2793 } else {
2794 Err(cipher)
2795 },
2796 ).into()
2797 }
2798 };
2799
2800 Some(sec)
2801 } else {
2802 None
2803 };
2804
2805 let have_secret = secret.is_some();
2806 if have_secret {
2807 if tag == Tag::PublicKey || tag == Tag::PublicSubkey {
2808 return php.error(Error::MalformedPacket(
2809 format!("Unexpected secret key found in {:?} packet", tag)
2810 ).into());
2811 }
2812 } else if tag == Tag::SecretKey || tag == Tag::SecretSubkey {
2813 return php.error(Error::MalformedPacket(
2814 format!("Expected secret key in {:?} packet", tag)
2815 ).into());
2816 }
2817
2818 fn k<R>(creation_time: u32,
2819 pk_algo: PublicKeyAlgorithm,
2820 mpis: PublicKey)
2821 -> Result<Key4<key::PublicParts, R>>
2822 where R: key::KeyRole
2823 {
2824 Key4::make(creation_time.into(), pk_algo, mpis, None)
2825 }
2826 fn s<R>(creation_time: u32,
2827 pk_algo: PublicKeyAlgorithm,
2828 mpis: PublicKey,
2829 secret: SecretKeyMaterial)
2830 -> Result<Key4<key::SecretParts, R>>
2831 where R: key::KeyRole
2832 {
2833 Key4::make(creation_time.into(), pk_algo, mpis, Some(secret))
2834 }
2835
2836 let tag = php.header.ctb().tag();
2837
2838 let p : Packet = match tag {
2839 // For the benefit of Key::from_bytes.
2840 Tag::Reserved => if have_secret {
2841 Packet::SecretKey(
2842 php_try!(s(creation_time, pk_algo, mpis, secret.unwrap()))
2843 .into())
2844 } else {
2845 Packet::PublicKey(
2846 php_try!(k(creation_time, pk_algo, mpis)).into())
2847 },
2848 Tag::PublicKey => Packet::PublicKey(
2849 php_try!(k(creation_time, pk_algo, mpis)).into()),
2850 Tag::PublicSubkey => Packet::PublicSubkey(
2851 php_try!(k(creation_time, pk_algo, mpis)).into()),
2852 Tag::SecretKey => Packet::SecretKey(
2853 php_try!(s(creation_time, pk_algo, mpis, secret.unwrap()))
2854 .into()),
2855 Tag::SecretSubkey => Packet::SecretSubkey(
2856 php_try!(s(creation_time, pk_algo, mpis, secret.unwrap()))
2857 .into()),
2858 _ => unreachable!(),
2859 };
2860
2861 php.ok(p)
2862 }
2863
2864 /// Returns whether the data appears to be a version 4 key (no
2865 /// promises).
2866 fn plausible<C>(bio: &mut dyn BufferedReader<C>, _: &Header)
2867 -> Result<()>
2868 where
2869 C: fmt::Debug + Send + Sync,
2870 {
2871 // Make sure we have a minimum header.
2872 let data = bio.data(6)?;
2873 if data.len() < 6 {
2874 return Err(
2875 Error::MalformedPacket("Short read".into()).into());
2876 }
2877
2878 // Assume unknown == bad.
2879 let version = data[0];
2880 let pk_algo : PublicKeyAlgorithm = data[5].into();
2881
2882 if version == 4 && !matches!(pk_algo, PublicKeyAlgorithm::Unknown(_)) {
2883 Ok(())
2884 } else {
2885 Err(Error::MalformedPacket("Invalid or unsupported data".into())
2886 .into())
2887 }
2888 }
2889}
2890
2891// Key6::parse doesn't actually use the Key6 type parameters. So, we
2892// can just set them to anything. This avoids the caller having to
2893// set them to something.
2894impl Key6<key::UnspecifiedParts, key::UnspecifiedRole>
2895{
2896 /// Parses the body of a public key, public subkey, secret key or
2897 /// secret subkey packet.
2898 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
2899 tracer!(TRACE, "Key6::parse", php.recursion_depth());
2900 make_php_try!(php);
2901 let tag = php.header.ctb().tag();
2902 assert!(tag == Tag::Reserved
2903 || tag == Tag::PublicKey
2904 || tag == Tag::PublicSubkey
2905 || tag == Tag::SecretKey
2906 || tag == Tag::SecretSubkey);
2907
2908 let creation_time = php_try!(php.parse_be_u32("creation_time"));
2909 let pk_algo: PublicKeyAlgorithm = php_try!(php.parse_u8("pk_algo")).into();
2910
2911 let public_len = php_try!(php.parse_be_u32("public_len"));
2912 let public_mpis =
2913 php.variable_sized_field_start("public_mpis", public_len);
2914 let mpis = php_try!(PublicKey::_parse(pk_algo, &mut php));
2915 php_try!(php.variable_sized_field_end(public_mpis));
2916
2917 let secret = if let Ok(s2k_usage) = php.parse_u8("s2k_usage") {
2918 use crypto::mpi;
2919 let sec = match s2k_usage {
2920 // Unencrypted secrets.
2921 0 => {
2922 let sec = php_try!(
2923 mpi::SecretKeyMaterial::_parse(
2924 pk_algo, &mut php, None));
2925 sec.into()
2926 },
2927
2928 // Encrypted & MD5 for key derivation: unsupported.
2929 //
2930 // XXX: Technically, we could/should parse them, then
2931 // fail later. But, this limitation has been with us
2932 // since the beginning, and no-one complained.
2933 1..=252 => {
2934 return php.fail("unsupported secret key encryption");
2935 },
2936
2937 // AEAD encrypted secrets.
2938 253 => {
2939 let parameters_len =
2940 php_try!(php.parse_u8("parameters_len"));
2941 let parameters =
2942 php.variable_sized_field_start("parameters",
2943 parameters_len);
2944 let sym_algo: SymmetricAlgorithm =
2945 php_try!(php.parse_u8("sym_algo")).into();
2946
2947 let aead_algo: AEADAlgorithm =
2948 php_try!(php.parse_u8("aead_algo")).into();
2949
2950 let s2k_len = php_try!(php.parse_u8("s2k_len"));
2951 let s2k_params =
2952 php.variable_sized_field_start("s2k_params", s2k_len);
2953 let s2k = php_try!(S2K::parse_v6(&mut php, s2k_len as _));
2954 php_try!(php.variable_sized_field_end(s2k_params));
2955
2956 let aead_iv = php_try!(php.parse_bytes(
2957 "aead_iv",
2958 php.variable_sized_field_remaining(¶meters)))
2959 .into();
2960 php_try!(php.variable_sized_field_end(parameters));
2961
2962 let cipher =
2963 php_try!(php.parse_bytes_eof("encrypted_mpis"))
2964 .into_boxed_slice();
2965
2966 crate::packet::key::Encrypted::new_aead(
2967 s2k, sym_algo, aead_algo, aead_iv, cipher).into()
2968 },
2969
2970 // Encrypted secrets.
2971 254 | 255 => {
2972 let parameters_len =
2973 php_try!(php.parse_u8("parameters_len"));
2974 let parameters =
2975 php.variable_sized_field_start("parameters",
2976 parameters_len);
2977 let sym_algo: SymmetricAlgorithm =
2978 php_try!(php.parse_u8("sym_algo")).into();
2979
2980 let s2k_len = php_try!(php.parse_u8("s2k_len"));
2981 let s2k_params =
2982 php.variable_sized_field_start("s2k_params", s2k_len);
2983 let s2k = php_try!(S2K::parse_v6(&mut php, s2k_len as _));
2984 php_try!(php.variable_sized_field_end(s2k_params));
2985
2986 // The "IV" is part of the sized parameter field.
2987 let cfb_iv = php_try!(php.parse_bytes(
2988 "cfb_iv",
2989 php.variable_sized_field_remaining(¶meters)));
2990 php_try!(php.variable_sized_field_end(parameters));
2991
2992 let cipher =
2993 php_try!(php.parse_bytes_eof("encrypted_mpis"));
2994
2995 // But we store "IV" and ciphertext as one.
2996 let cfb_iv_len = cfb_iv.len();
2997 let mut combined_ciphertext = cfb_iv;
2998 combined_ciphertext.extend_from_slice(&cipher);
2999
3000 crate::packet::key::Encrypted::new_raw(
3001 s2k, sym_algo,
3002 if s2k_usage == 254 {
3003 Some(mpi::SecretKeyChecksum::SHA1)
3004 } else {
3005 Some(mpi::SecretKeyChecksum::Sum16)
3006 },
3007 Ok((cfb_iv_len, combined_ciphertext.into())))
3008 .into()
3009 },
3010 };
3011
3012 Some(sec)
3013 } else {
3014 None
3015 };
3016
3017 let have_secret = secret.is_some();
3018 if have_secret {
3019 if tag == Tag::PublicKey || tag == Tag::PublicSubkey {
3020 return php.error(Error::MalformedPacket(
3021 format!("Unexpected secret key found in {:?} packet", tag)
3022 ).into());
3023 }
3024 } else if tag == Tag::SecretKey || tag == Tag::SecretSubkey {
3025 return php.error(Error::MalformedPacket(
3026 format!("Expected secret key in {:?} packet", tag)
3027 ).into());
3028 }
3029
3030 fn k<R>(creation_time: u32,
3031 pk_algo: PublicKeyAlgorithm,
3032 mpis: PublicKey)
3033 -> Result<Key6<key::PublicParts, R>>
3034 where R: key::KeyRole
3035 {
3036 Key6::make(creation_time.into(), pk_algo, mpis, None)
3037 }
3038 fn s<R>(creation_time: u32,
3039 pk_algo: PublicKeyAlgorithm,
3040 mpis: PublicKey,
3041 secret: SecretKeyMaterial)
3042 -> Result<Key6<key::SecretParts, R>>
3043 where R: key::KeyRole
3044 {
3045 Key6::make(creation_time.into(), pk_algo, mpis, Some(secret))
3046 }
3047
3048 let tag = php.header.ctb().tag();
3049
3050 let p : Packet = match tag {
3051 // For the benefit of Key::from_bytes.
3052 Tag::Reserved => if have_secret {
3053 Packet::SecretKey(
3054 php_try!(s(creation_time, pk_algo, mpis, secret.unwrap()))
3055 .into())
3056 } else {
3057 Packet::PublicKey(
3058 php_try!(k(creation_time, pk_algo, mpis)).into())
3059 },
3060 Tag::PublicKey => Packet::PublicKey(
3061 php_try!(k(creation_time, pk_algo, mpis)).into()),
3062 Tag::PublicSubkey => Packet::PublicSubkey(
3063 php_try!(k(creation_time, pk_algo, mpis)).into()),
3064 Tag::SecretKey => Packet::SecretKey(
3065 php_try!(s(creation_time, pk_algo, mpis, secret.unwrap()))
3066 .into()),
3067 Tag::SecretSubkey => Packet::SecretSubkey(
3068 php_try!(s(creation_time, pk_algo, mpis, secret.unwrap()))
3069 .into()),
3070 _ => unreachable!(),
3071 };
3072
3073 php.ok(p)
3074 }
3075
3076 /// Returns whether the data appears to be a version 6 key (no
3077 /// promises).
3078 fn plausible<C>(bio: &mut dyn BufferedReader<C>, header: &Header)
3079 -> Result<()>
3080 where
3081 C: fmt::Debug + Send + Sync,
3082 {
3083 // Make sure we have a minimum header.
3084 const MIN: usize = 10;
3085 let data = bio.data(MIN)?;
3086 if data.len() < MIN {
3087 return Err(
3088 Error::MalformedPacket("Short read".into()).into());
3089 }
3090
3091 // Assume unknown == bad.
3092 let version = data[0];
3093 let creation_time =
3094 u32::from_be_bytes(data[1..5].try_into().unwrap());
3095 let pk_algo: PublicKeyAlgorithm = data[5].into();
3096 let public_len =
3097 u32::from_be_bytes(data[6..10].try_into().unwrap());
3098
3099 /// The unix time at which RFC9580 was published, 2024-07-31.
3100 const RFC9580_PUBLICATION_TIME: u32 = 1722376800;
3101
3102 if version == 6
3103 && !matches!(pk_algo, PublicKeyAlgorithm::Unknown(_))
3104 && creation_time >= RFC9580_PUBLICATION_TIME
3105 && match header.length() {
3106 BodyLength::Full(len) => public_len < *len,
3107 _ => false,
3108 }
3109 {
3110 Ok(())
3111 } else {
3112 Err(Error::MalformedPacket("Invalid or unsupported data".into())
3113 .into())
3114 }
3115 }
3116}
3117
3118use key::UnspecifiedKey;
3119impl_parse_with_buffered_reader!(
3120 UnspecifiedKey,
3121 |br| -> Result<Self> {
3122 let parser = PacketHeaderParser::new_naked(br);
3123
3124 let mut pp = Self::parse(parser)?;
3125 pp.buffer_unread_content()?;
3126
3127 match pp.next()? {
3128 (Packet::PublicKey(o), PacketParserResult::EOF(_)) => Ok(o.into()),
3129 (Packet::PublicSubkey(o), PacketParserResult::EOF(_)) => Ok(o.into()),
3130 (Packet::SecretKey(o), PacketParserResult::EOF(_)) => Ok(o.into()),
3131 (Packet::SecretSubkey(o), PacketParserResult::EOF(_)) => Ok(o.into()),
3132 (Packet::Unknown(u), PacketParserResult::EOF(_)) =>
3133 Err(u.into_error()),
3134 (p, PacketParserResult::EOF(_)) =>
3135 Err(Error::InvalidOperation(
3136 format!("Not a Key packet: {:?}", p)).into()),
3137 (_, PacketParserResult::Some(_)) =>
3138 Err(Error::InvalidOperation(
3139 "Excess data after packet".into()).into()),
3140 }
3141 });
3142
3143impl Trust {
3144 /// Parses the body of a trust packet.
3145 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3146 tracer!(TRACE, "Trust::parse", php.recursion_depth());
3147 make_php_try!(php);
3148 let value = php_try!(php.parse_bytes_eof("value"));
3149 php.ok(Packet::Trust(Trust::from(value)))
3150 }
3151}
3152
3153impl_parse_with_buffered_reader!(Trust);
3154
3155impl UserID {
3156 /// Parses the body of a user id packet.
3157 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3158 tracer!(TRACE, "UserID::parse", php.recursion_depth());
3159 make_php_try!(php);
3160
3161 let value = php_try!(php.parse_bytes_eof("value"));
3162
3163 php.ok(Packet::UserID(UserID::from(value)))
3164 }
3165}
3166
3167impl_parse_with_buffered_reader!(UserID);
3168
3169impl UserAttribute {
3170 /// Parses the body of a user attribute packet.
3171 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3172 tracer!(TRACE, "UserAttribute::parse", php.recursion_depth());
3173 make_php_try!(php);
3174
3175 let value = php_try!(php.parse_bytes_eof("value"));
3176
3177 php.ok(Packet::UserAttribute(UserAttribute::from(value)))
3178 }
3179}
3180
3181impl_parse_with_buffered_reader!(UserAttribute);
3182
3183impl Marker {
3184 /// Parses the body of a marker packet.
3185 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser>
3186 {
3187 tracer!(TRACE, "Marker::parse", php.recursion_depth());
3188 make_php_try!(php);
3189 let marker = php_try!(php.parse_bytes("marker", Marker::BODY.len()));
3190 if &marker[..] == Marker::BODY {
3191 php.ok(Marker::default().into())
3192 } else {
3193 php.fail("invalid marker")
3194 }
3195 }
3196
3197 /// Returns whether the data is a marker packet.
3198 fn plausible(bio: &mut dyn BufferedReader<Cookie>, header: &Header)
3199 -> Result<()>
3200 {
3201 if let BodyLength::Full(len) = header.length() {
3202 let len = *len;
3203 if len as usize != Marker::BODY.len() {
3204 return Err(Error::MalformedPacket(
3205 format!("Unexpected packet length {}", len)).into());
3206 }
3207 } else {
3208 return Err(Error::MalformedPacket(
3209 format!("Unexpected body length encoding: {:?}",
3210 header.length())).into());
3211 }
3212
3213 // Check the body.
3214 let data = bio.data(Marker::BODY.len())?;
3215 if data.len() < Marker::BODY.len() {
3216 return Err(Error::MalformedPacket("Short read".into()).into());
3217 }
3218
3219 if data == Marker::BODY {
3220 Ok(())
3221 } else {
3222 Err(Error::MalformedPacket("Invalid or unsupported data".into())
3223 .into())
3224 }
3225 }
3226}
3227
3228impl_parse_with_buffered_reader!(Marker);
3229
3230impl Literal {
3231 /// Parses the body of a literal packet.
3232 ///
3233 /// Condition: Hashing has been disabled by the callee.
3234 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser>
3235 {
3236 tracer!(TRACE, "Literal::parse", php.recursion_depth());
3237 make_php_try!(php);
3238
3239 // Directly hashing a literal data packet is... strange.
3240 // Neither the packet's header, the packet's meta-data nor the
3241 // length encoding information is included in the hash.
3242
3243 let format = php_try!(php.parse_u8("format"));
3244 let filename_len = php_try!(php.parse_u8("filename_len"));
3245
3246 let filename = if filename_len > 0 {
3247 Some(php_try!(php.parse_bytes("filename", filename_len as usize)))
3248 } else {
3249 None
3250 };
3251
3252 let date = php_try!(php.parse_be_u32("date"));
3253
3254 // The header is consumed while hashing is disabled.
3255 let recursion_depth = php.recursion_depth();
3256
3257 let mut literal = Literal::new(format.into());
3258 if let Some(filename) = filename {
3259 literal.set_filename(&filename)
3260 .expect("length checked above");
3261 }
3262 literal.set_date(
3263 Some(std::time::SystemTime::from(Timestamp::from(date))))?;
3264 let mut pp = php.ok(Packet::Literal(literal))?;
3265
3266 // Enable hashing of the body.
3267 Cookie::hashing(pp.mut_reader(), Hashing::Enabled,
3268 recursion_depth - 1);
3269
3270 Ok(pp)
3271 }
3272}
3273
3274impl_parse_with_buffered_reader!(Literal);
3275
3276#[test]
3277fn literal_parser_test () {
3278 use crate::types::DataFormat;
3279 {
3280 let data = crate::tests::message("literal-mode-b.pgp");
3281 let mut pp = PacketParser::from_bytes(data).unwrap().unwrap();
3282 assert_eq!(pp.header.length(), &BodyLength::Full(18));
3283 let content = pp.steal_eof().unwrap();
3284 let p = pp.finish().unwrap();
3285 // eprintln!("{:?}", p);
3286 if let &Packet::Literal(ref p) = p {
3287 assert_eq!(p.format(), DataFormat::Binary);
3288 assert_eq!(p.filename().unwrap()[..], b"foobar"[..]);
3289 assert_eq!(p.date().unwrap(), Timestamp::from(1507458744).into());
3290 assert_eq!(content, b"FOOBAR");
3291 } else {
3292 panic!("Wrong packet!");
3293 }
3294 }
3295
3296 {
3297 let data = crate::tests::message("literal-mode-t-partial-body.pgp");
3298 let mut pp = PacketParser::from_bytes(data).unwrap().unwrap();
3299 assert_eq!(pp.header.length(), &BodyLength::Partial(4096));
3300 let content = pp.steal_eof().unwrap();
3301 let p = pp.finish().unwrap();
3302 if let &Packet::Literal(ref p) = p {
3303 #[allow(deprecated)] {
3304 assert_eq!(p.format(), DataFormat::Text);
3305 }
3306 assert_eq!(p.filename().unwrap()[..],
3307 b"manifesto.txt"[..]);
3308 assert_eq!(p.date().unwrap(), Timestamp::from(1508000649).into());
3309
3310 let expected = crate::tests::manifesto();
3311
3312 assert_eq!(&content[..], expected);
3313 } else {
3314 panic!("Wrong packet!");
3315 }
3316 }
3317}
3318
3319impl CompressedData {
3320 /// Parses the body of a compressed data packet.
3321 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3322 let recursion_depth = php.recursion_depth();
3323 tracer!(TRACE, "CompressedData::parse", recursion_depth);
3324
3325 make_php_try!(php);
3326 let algo: CompressionAlgorithm =
3327 php_try!(php.parse_u8("algo")).into();
3328
3329 let recursion_depth = php.recursion_depth();
3330 let mut pp = php.ok(Packet::CompressedData(CompressedData::new(algo)))?;
3331
3332 #[allow(unreachable_patterns)]
3333 match algo {
3334 CompressionAlgorithm::Uncompressed => (),
3335 #[cfg(feature = "compression-deflate")]
3336 CompressionAlgorithm::Zip
3337 | CompressionAlgorithm::Zlib => (),
3338 #[cfg(feature = "compression-bzip2")]
3339 CompressionAlgorithm::BZip2 => (),
3340 _ => {
3341 // We don't know or support this algorithm. Return a
3342 // CompressedData packet without pushing a filter, so
3343 // that it has an opaque body.
3344 t!("Algorithm {} unknown or unsupported.", algo);
3345 return Ok(pp.set_processed(false));
3346 },
3347 }
3348
3349 t!("Pushing a decompressor for {}, recursion depth = {:?}.",
3350 algo, recursion_depth);
3351
3352 let reader = pp.take_reader();
3353 let reader = match algo {
3354 CompressionAlgorithm::Uncompressed => {
3355 if TRACE {
3356 eprintln!("CompressedData::parse(): Actually, no need \
3357 for a compression filter: this is an \
3358 \"uncompressed compression packet\".");
3359 }
3360 let _ = recursion_depth;
3361 reader
3362 },
3363 #[cfg(feature = "compression-deflate")]
3364 CompressionAlgorithm::Zip =>
3365 Box::new(buffered_reader::Deflate::with_cookie(
3366 reader, Cookie::new(recursion_depth))),
3367 #[cfg(feature = "compression-deflate")]
3368 CompressionAlgorithm::Zlib =>
3369 Box::new(buffered_reader::Zlib::with_cookie(
3370 reader, Cookie::new(recursion_depth))),
3371 #[cfg(feature = "compression-bzip2")]
3372 CompressionAlgorithm::BZip2 =>
3373 Box::new(buffered_reader::Bzip::with_cookie(
3374 reader, Cookie::new(recursion_depth))),
3375 _ => unreachable!(), // Validated above.
3376 };
3377 pp.set_reader(reader);
3378
3379 Ok(pp)
3380 }
3381}
3382
3383impl_parse_with_buffered_reader!(CompressedData);
3384
3385#[cfg(any(feature = "compression-deflate", feature = "compression-bzip2"))]
3386#[test]
3387fn compressed_data_parser_test () {
3388 use crate::types::DataFormat;
3389
3390 let expected = crate::tests::manifesto();
3391
3392 for i in 1..4 {
3393 match CompressionAlgorithm::from(i) {
3394 #[cfg(feature = "compression-deflate")]
3395 CompressionAlgorithm::Zip | CompressionAlgorithm::Zlib => (),
3396 #[cfg(feature = "compression-bzip2")]
3397 CompressionAlgorithm::BZip2 => (),
3398 _ => continue,
3399 }
3400 let pp = PacketParser::from_bytes(crate::tests::message(
3401 &format!("compressed-data-algo-{}.pgp", i))).unwrap().unwrap();
3402
3403 // We expect a compressed packet containing a literal data
3404 // packet, and that is it.
3405 if let Packet::CompressedData(ref compressed) = pp.packet {
3406 assert_eq!(compressed.algo(), i.into());
3407 } else {
3408 panic!("Wrong packet!");
3409 }
3410
3411 let ppr = pp.recurse().unwrap().1;
3412
3413 // ppr should be the literal data packet.
3414 let mut pp = ppr.unwrap();
3415
3416 // It is a child.
3417 assert_eq!(pp.recursion_depth(), 1);
3418
3419 let content = pp.steal_eof().unwrap();
3420
3421 let (literal, ppr) = pp.recurse().unwrap();
3422
3423 if let Packet::Literal(literal) = literal {
3424 assert_eq!(literal.filename(), None);
3425 assert_eq!(literal.format(), DataFormat::Binary);
3426 assert_eq!(literal.date().unwrap(),
3427 Timestamp::from(1509219866).into());
3428 assert_eq!(content, expected.to_vec());
3429 } else {
3430 panic!("Wrong packet!");
3431 }
3432
3433 // And, we're done...
3434 assert!(ppr.is_eof());
3435 }
3436}
3437
3438impl SKESK {
3439 /// Parses the body of an SK-ESK packet.
3440 fn parse(mut php: PacketHeaderParser)
3441 -> Result<PacketParser>
3442 {
3443 tracer!(TRACE, "SKESK::parse", php.recursion_depth());
3444 make_php_try!(php);
3445 let version = php_try!(php.parse_u8("version"));
3446 match version {
3447 4 => SKESK4::parse(php),
3448 6 => SKESK6::parse(php),
3449 _ => php.fail("unknown version"),
3450 }
3451 }
3452}
3453
3454impl SKESK4 {
3455 /// Parses the body of an SK-ESK packet.
3456 fn parse(mut php: PacketHeaderParser)
3457 -> Result<PacketParser>
3458 {
3459 tracer!(TRACE, "SKESK4::parse", php.recursion_depth());
3460 make_php_try!(php);
3461 let sym_algo = php_try!(php.parse_u8("sym_algo"));
3462 let s2k = php_try!(S2K::parse_v4(&mut php));
3463 let s2k_supported = s2k.is_supported();
3464 let esk = php_try!(php.parse_bytes_eof("esk"));
3465
3466 let skesk = php_try!(SKESK4::new_raw(
3467 sym_algo.into(),
3468 s2k,
3469 if s2k_supported || esk.is_empty() {
3470 Ok(if ! esk.is_empty() {
3471 Some(esk.into())
3472 } else {
3473 None
3474 })
3475 } else {
3476 Err(esk.into())
3477 },
3478 ));
3479
3480 php.ok(skesk.into())
3481 }
3482}
3483
3484impl SKESK6 {
3485 /// Parses the body of an SK-ESK packet.
3486 fn parse(mut php: PacketHeaderParser)
3487 -> Result<PacketParser>
3488 {
3489 tracer!(TRACE, "SKESK6::parse", php.recursion_depth());
3490 make_php_try!(php);
3491
3492 // Octet count of the following 5 fields.
3493 let parameter_len = php_try!(php.parse_u8_len("parameter_len"));
3494 if parameter_len < 1 + 1 + 1 + 1 /* S2K */ + 12 /* IV */ {
3495 return php.fail("expected at least 16 parameter octets");
3496 }
3497
3498 let sym_algo: SymmetricAlgorithm =
3499 php_try!(php.parse_u8("sym_algo")).into();
3500 let aead_algo: AEADAlgorithm =
3501 php_try!(php.parse_u8("aead_algo")).into();
3502
3503 // The S2K object's length and the S2K.
3504 let s2k_len = php_try!(php.parse_u8_len("s2k_len"));
3505 if parameter_len < 1 + 1 + 1 + s2k_len + 12 /* IV */ {
3506 return php.fail("S2K overflows parameter count");
3507 }
3508
3509 let s2k = php_try!(S2K::parse_v6(&mut php, s2k_len as u8));
3510
3511 // And the IV.
3512 let iv =
3513 if let Some(iv_len) = parameter_len.checked_sub(1 + 1 + 1 + s2k_len) {
3514 php_try!(php.parse_bytes("iv", iv_len as usize)).into()
3515 } else {
3516 return php.fail("IV overflows parameter count");
3517 };
3518
3519 // Finally, the ESK including the AEAD tag.
3520 let esk = php_try!(php.parse_bytes_eof("esk")).into();
3521
3522 let skesk = php_try!(SKESK6::new(
3523 sym_algo,
3524 aead_algo,
3525 s2k,
3526 iv,
3527 esk,
3528 ));
3529
3530 php.ok(skesk.into())
3531 }
3532}
3533
3534impl_parse_with_buffered_reader!(SKESK);
3535
3536#[test]
3537fn skesk_parser_test() {
3538 use crate::crypto::Password;
3539 struct Test<'a> {
3540 filename: &'a str,
3541 s2k: S2K,
3542 cipher_algo: SymmetricAlgorithm,
3543 password: Password,
3544 key_hex: &'a str,
3545 }
3546
3547 let tests = [
3548 Test {
3549 filename: "s2k/mode-3-encrypted-key-password-bgtyhn.pgp",
3550 cipher_algo: SymmetricAlgorithm::AES128,
3551 s2k: S2K::Iterated {
3552 hash: HashAlgorithm::SHA1,
3553 salt: [0x82, 0x59, 0xa0, 0x6e, 0x98, 0xda, 0x94, 0x1c],
3554 hash_bytes: S2K::decode_count(238),
3555 },
3556 password: "bgtyhn".into(),
3557 key_hex: "474E5C373BA18AF0A499FCAFE6093F131DF636F6A3812B9A8AE707F1F0214AE9",
3558 },
3559 ];
3560
3561 for test in tests.iter() {
3562 let pp = PacketParser::from_bytes(
3563 crate::tests::message(test.filename)).unwrap().unwrap();
3564 if let Packet::SKESK(SKESK::V4(ref skesk)) = pp.packet {
3565 eprintln!("{:?}", skesk);
3566
3567 assert_eq!(skesk.symmetric_algo(), test.cipher_algo);
3568 assert_eq!(skesk.s2k(), &test.s2k);
3569
3570 match skesk.decrypt(&test.password) {
3571 Ok((_sym_algo, key)) => {
3572 let key = crate::fmt::to_hex(&key[..], false);
3573 assert_eq!(&key[..], test.key_hex);
3574 }
3575 Err(e) => {
3576 panic!("No session key, got: {:?}", e);
3577 }
3578 }
3579 } else {
3580 panic!("Wrong packet!");
3581 }
3582 }
3583}
3584
3585impl SEIP {
3586 /// Parses the body of a SEIP packet.
3587 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3588 tracer!(TRACE, "SEIP::parse", php.recursion_depth());
3589 make_php_try!(php);
3590 let version = php_try!(php.parse_u8("version"));
3591 match version {
3592 1 => SEIP1::parse(php),
3593 2 => SEIP2::parse(php),
3594 _ => php.fail("unknown version"),
3595 }
3596 }
3597}
3598
3599impl_parse_with_buffered_reader!(SEIP);
3600
3601impl SEIP1 {
3602 /// Parses the body of a SEIP1 packet.
3603 fn parse(php: PacketHeaderParser) -> Result<PacketParser> {
3604 php.ok(SEIP1::new().into())
3605 .map(|pp| pp.set_processed(false))
3606 }
3607}
3608
3609impl SEIP2 {
3610 /// Parses the body of a SEIP2 packet.
3611 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3612 tracer!(TRACE, "SEIP2::parse", php.recursion_depth());
3613 make_php_try!(php);
3614 let cipher: SymmetricAlgorithm =
3615 php_try!(php.parse_u8("sym_algo")).into();
3616 let aead: AEADAlgorithm =
3617 php_try!(php.parse_u8("aead_algo")).into();
3618 let chunk_size = php_try!(php.parse_u8("chunk_size"));
3619
3620 // An implementation MUST accept chunk size octets with values
3621 // from 0 to 16. An implementation MUST NOT create data with a
3622 // chunk size octet value larger than 16 (4 MiB chunks).
3623 if chunk_size > 16 {
3624 return php.fail("unsupported chunk size");
3625 }
3626 let chunk_size: u64 = 1 << (chunk_size + 6);
3627 let salt_v = php_try!(php.parse_bytes("salt", 32));
3628 let mut salt = [0u8; 32];
3629 salt.copy_from_slice(&salt_v);
3630
3631 let seip2 = php_try!(Self::new(cipher, aead, chunk_size, salt));
3632 php.ok(seip2.into()).map(|pp| pp.set_processed(false))
3633 }
3634}
3635
3636impl MDC {
3637 /// Parses the body of an MDC packet.
3638 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3639 tracer!(TRACE, "MDC::parse", php.recursion_depth());
3640 make_php_try!(php);
3641
3642 // Find the HashedReader pushed by the containing SEIP packet.
3643 // In a well-formed message, this will be the outermost
3644 // HashedReader on the BufferedReader stack: we pushed it
3645 // there when we started decrypting the SEIP packet, and an
3646 // MDC packet is the last packet in a SEIP container.
3647 // Nevertheless, we take some basic precautions to check
3648 // whether it is really the matching HashedReader.
3649
3650 let mut computed_digest : [u8; 20] = Default::default();
3651 {
3652 let mut r : Option<&mut dyn BufferedReader<Cookie>>
3653 = Some(&mut php.reader);
3654 while let Some(bio) = r {
3655 {
3656 let state = bio.cookie_mut();
3657 if state.hashes_for == HashesFor::MDC {
3658 if !state.sig_group().hashes.is_empty() {
3659 let h = state.sig_group_mut().hashes
3660 .iter_mut().find_map(
3661 |mode|
3662 if matches!(mode.map(|ctx| ctx.algo()),
3663 HashingMode::Binary(_, HashAlgorithm::SHA1))
3664 {
3665 Some(mode.as_mut())
3666 } else {
3667 None
3668 }).unwrap();
3669 let _ = h.digest(&mut computed_digest);
3670 }
3671
3672 // If the outermost HashedReader is not the
3673 // matching HashedReader, then the message is
3674 // malformed.
3675 break;
3676 }
3677 }
3678
3679 r = bio.get_mut();
3680 }
3681 }
3682
3683 let mut digest: [u8; 20] = Default::default();
3684 digest.copy_from_slice(&php_try!(php.parse_bytes("digest", 20)));
3685
3686 #[allow(deprecated)]
3687 php.ok(Packet::MDC(MDC::new(digest, computed_digest)))
3688 }
3689}
3690
3691impl_parse_with_buffered_reader!(MDC);
3692
3693impl Padding {
3694 /// Parses the body of a padding packet.
3695 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3696 tracer!(TRACE, "Padding::parse", php.recursion_depth());
3697 make_php_try!(php);
3698 // XXX: I don't think we should capture the body.
3699 let value = php_try!(php.parse_bytes_eof("value"));
3700 php.ok(Packet::Padding(Padding::from(value)))
3701 }
3702}
3703
3704impl_parse_with_buffered_reader!(Padding);
3705
3706impl MPI {
3707 /// Parses an OpenPGP MPI.
3708 ///
3709 /// See [Section 3.2 of RFC 9580] for details.
3710 ///
3711 /// [Section 3.2 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.2
3712 fn parse(name_len: &'static str,
3713 name: &'static str,
3714 php: &mut PacketHeaderParser<'_>) -> Result<Self> {
3715 Ok(MPI::parse_common(name_len, name, false, false, php)?.into())
3716 }
3717
3718 /// Parses an OpenPGP MPI.
3719 ///
3720 /// If `parsing_secrets` is `true`, errors are normalized as not
3721 /// to reveal parts of the plaintext to the caller.
3722 ///
3723 /// If `lenient_parsing` is `true`, this function will accept MPIs
3724 /// that are not well-formed (notably, issues related to leading
3725 /// zeros).
3726 fn parse_common(
3727 name_len: &'static str,
3728 name: &'static str,
3729 parsing_secrets: bool,
3730 lenient_parsing: bool,
3731 php: &mut PacketHeaderParser<'_>)
3732 -> Result<Vec<u8>> {
3733 // When we are parsing secrets, we don't want to leak it
3734 // accidentally by revealing it in error messages, or indeed
3735 // by the kind of error.
3736 //
3737 // All errors returned by this function that are depend on
3738 // secret data must be uniform and return the following error.
3739 // We make an exception for i/o errors, which may reveal
3740 // truncation, because swallowing i/o errors may be very
3741 // confusing when diagnosing errors, and we don't consider the
3742 // length of the value to be confidential as it can also be
3743 // inferred from the size of the ciphertext.
3744 let uniform_error_for_secrets = |e: Error| {
3745 if parsing_secrets {
3746 Err(Error::MalformedMPI("Details omitted, \
3747 parsing secret".into()).into())
3748 } else {
3749 Err(e.into())
3750 }
3751 };
3752
3753 // This function is used to parse MPIs from unknown
3754 // algorithms, which may use an encoding unknown to us.
3755 // Therefore, we need to be extra careful only to consume the
3756 // data once we found a well-formed MPI.
3757 let bits = {
3758 let buf = php.reader.data_hard(2)?;
3759 u16::from_be_bytes([buf[0], buf[1]]) as usize
3760 };
3761 if bits == 0 {
3762 // Now consume the data.
3763 php.parse_be_u16(name_len).expect("worked before");
3764 return Ok(vec![]);
3765 }
3766
3767 let bytes = (bits + 7) / 8;
3768 let value = {
3769 let buf = php.reader.data_hard(2 + bytes)?;
3770 Vec::from(&buf[2..2 + bytes])
3771 };
3772
3773 let unused_bits = bytes * 8 - bits;
3774 assert_eq!(bytes * 8 - unused_bits, bits);
3775
3776 // Make sure the unused bits are zeroed.
3777 if unused_bits > 0 {
3778 let mask = !((1 << (8 - unused_bits)) - 1);
3779 let unused_value = value[0] & mask;
3780
3781 if unused_value != 0 && ! lenient_parsing {
3782 return uniform_error_for_secrets(
3783 Error::MalformedMPI(
3784 format!("{} unused bits not zeroed: ({:x})",
3785 unused_bits, unused_value)
3786 ));
3787 }
3788 }
3789
3790 let first_used_bit = 8 - unused_bits;
3791 if value[0] & (1 << (first_used_bit - 1)) == 0 && ! lenient_parsing {
3792 return uniform_error_for_secrets(
3793 Error::MalformedMPI(
3794 format!("leading bit is not set: \
3795 expected bit {} to be set in {:8b} ({:x})",
3796 first_used_bit, value[0], value[0])
3797 ));
3798 }
3799
3800 // Now consume the data. Note: we avoid using parse_bytes
3801 // here because MPIs may contain secrets, and we don't want to
3802 // casually leak them into the heap. Also, we avoid doing a
3803 // heap allocation.
3804 php.reader.consume(2 + bytes);
3805 // Now fix the map.
3806 php.field(name_len, 2);
3807 php.field(name, bytes);
3808
3809 Ok(value)
3810 }
3811}
3812
3813impl_parse_with_buffered_reader!(
3814 MPI,
3815 |bio: Box<dyn BufferedReader<Cookie>>| -> Result<Self> {
3816 let mut parser = PacketHeaderParser::new_naked(bio.into_boxed());
3817 Self::parse("(none_len)", "(none)", &mut parser)
3818 });
3819
3820impl ProtectedMPI {
3821 /// Parses an OpenPGP MPI containing secrets.
3822 ///
3823 /// See [Section 3.2 of RFC 9580] for details.
3824 ///
3825 /// [Section 3.2 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.2
3826 fn parse(name_len: &'static str,
3827 name: &'static str,
3828 php: &mut PacketHeaderParser<'_>) -> Result<Self> {
3829 // XXX: While lenient parsing seemed like the right thing to
3830 // do, this breaks equality and round-tripping: we normalize
3831 // the non-canonical encoding, so two distinct wire
3832 // representations are folded into one in-core representation.
3833 Ok(MPI::parse_common(name_len, name, true, false, php)?.into())
3834 }
3835}
3836impl PKESK {
3837 /// Parses the body of an PK-ESK packet.
3838 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3839 tracer!(TRACE, "PKESK::parse", php.recursion_depth());
3840 make_php_try!(php);
3841 let version = php_try!(php.parse_u8("version"));
3842 match version {
3843 3 => PKESK3::parse(php),
3844 6 => PKESK6::parse(php),
3845 _ => php.fail("unknown version"),
3846 }
3847 }
3848}
3849
3850impl_parse_with_buffered_reader!(PKESK);
3851
3852impl PKESK3 {
3853 /// Parses the body of an PK-ESK packet.
3854 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3855 tracer!(TRACE, "PKESK3::parse", php.recursion_depth());
3856 make_php_try!(php);
3857
3858 let keyid = {
3859 let mut keyid = [0u8; 8];
3860 keyid.copy_from_slice(&php_try!(php.parse_bytes("keyid", 8)));
3861
3862 let keyid = KeyID::from_bytes(&keyid);
3863 if keyid.is_wildcard() {
3864 None
3865 } else {
3866 Some(keyid)
3867 }
3868 };
3869
3870 let pk_algo: PublicKeyAlgorithm = php_try!(php.parse_u8("pk_algo")).into();
3871 if ! pk_algo.for_encryption() {
3872 return php.fail("not an encryption algorithm");
3873 }
3874 let mpis = crypto::mpi::Ciphertext::_parse(pk_algo, &mut php)?;
3875
3876 let pkesk = php_try!(PKESK3::new(keyid, pk_algo, mpis));
3877 php.ok(pkesk.into())
3878 }
3879}
3880
3881impl_parse_with_buffered_reader!(
3882 PKESK3,
3883 |reader| -> Result<Self> {
3884 PKESK::from_buffered_reader(reader).and_then(|p| match p {
3885 PKESK::V3(p) => Ok(p),
3886 p => Err(Error::InvalidOperation(
3887 format!("Not a PKESKv3 packet: {:?}", p)).into()),
3888 })
3889 });
3890
3891impl PKESK6 {
3892 /// Parses the body of an PKESKv6 packet.
3893 fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
3894 tracer!(TRACE, "PKESK6::parse", php.recursion_depth());
3895 make_php_try!(php);
3896 let fp_len = php_try!(php.parse_u8("recipient_len"));
3897 let fingerprint = if fp_len == 0 {
3898 None
3899 } else {
3900 // Get the version and sanity check the length.
3901 let fp_version = php_try!(php.parse_u8("recipient_version"));
3902 if let Some(expected_length) = match fp_version {
3903 4 => Some(20),
3904 6 => Some(32),
3905 _ => None,
3906 } {
3907 if fp_len - 1 != expected_length {
3908 return php.fail("bad fingerprint length");
3909 }
3910 }
3911 Some(Fingerprint::from_bytes(
3912 fp_version,
3913 &php_try!(php.parse_bytes("recipient", (fp_len - 1).into())))?)
3914 };
3915
3916 let pk_algo: PublicKeyAlgorithm =
3917 php_try!(php.parse_u8("pk_algo")).into();
3918 if ! pk_algo.for_encryption() { // XXX
3919 return php.fail("not an encryption algorithm");
3920 }
3921 let mpis = crypto::mpi::Ciphertext::_parse(pk_algo, &mut php)?;
3922
3923 let pkesk = php_try!(PKESK6::new(fingerprint, pk_algo, mpis));
3924 php.ok(pkesk.into())
3925 }
3926}
3927
3928impl_parse_with_buffered_reader!(
3929 PKESK6,
3930 |reader| -> Result<Self> {
3931 PKESK::from_buffered_reader(reader).and_then(|p| match p {
3932 PKESK::V6(p) => Ok(p),
3933 p => Err(Error::InvalidOperation(
3934 format!("Not a PKESKv6 packet: {:?}", p)).into()),
3935 })
3936 });
3937
3938impl_parse_with_buffered_reader!(
3939 Packet,
3940 |br| -> Result<Self> {
3941 let ppr =
3942 PacketParserBuilder::from_buffered_reader(br)
3943 ?.buffer_unread_content().build()?;
3944
3945 let (p, ppr) = match ppr {
3946 PacketParserResult::Some(pp) => {
3947 pp.next()?
3948 },
3949 PacketParserResult::EOF(_) =>
3950 return Err(Error::InvalidOperation(
3951 "Unexpected EOF".into()).into()),
3952 };
3953
3954 match (p, ppr) {
3955 (p, PacketParserResult::EOF(_)) =>
3956 Ok(p),
3957 (_, PacketParserResult::Some(_)) =>
3958 Err(Error::InvalidOperation(
3959 "Excess data after packet".into()).into()),
3960 }
3961 });
3962
3963// State that lives for the life of the packet parser, not the life of
3964// an individual packet.
3965#[derive(Debug)]
3966struct PacketParserState {
3967 // The `PacketParser`'s settings
3968 settings: PacketParserSettings,
3969
3970 /// Whether the packet sequence is a valid OpenPGP Message.
3971 message_validator: MessageValidator,
3972
3973 /// Whether the packet sequence is a valid OpenPGP keyring.
3974 keyring_validator: KeyringValidator,
3975
3976 /// Whether the packet sequence is a valid OpenPGP Cert.
3977 cert_validator: CertValidator,
3978
3979 // Whether this is the first packet in the packet sequence.
3980 first_packet: bool,
3981
3982 // Whether PacketParser::parse encountered an unrecoverable error.
3983 pending_error: Option<anyhow::Error>,
3984}
3985
3986impl PacketParserState {
3987 fn new(settings: PacketParserSettings) -> Self {
3988 PacketParserState {
3989 settings,
3990 message_validator: Default::default(),
3991 keyring_validator: Default::default(),
3992 cert_validator: Default::default(),
3993 first_packet: true,
3994 pending_error: None,
3995 }
3996 }
3997}
3998
3999/// A low-level OpenPGP message parser.
4000///
4001/// A `PacketParser` provides a low-level, iterator-like interface to
4002/// parse OpenPGP messages.
4003///
4004/// For each iteration, the user is presented with a [`Packet`]
4005/// corresponding to the last packet, a `PacketParser` for the next
4006/// packet, and their positions within the message.
4007///
4008/// Using the `PacketParser`, the user is able to configure how the
4009/// new packet will be parsed. For instance, it is possible to stream
4010/// the packet's contents (a `PacketParser` implements the
4011/// [`std::io::Read`] and the [`BufferedReader`] traits), buffer them
4012/// within the [`Packet`], or drop them. The user can also decide to
4013/// recurse into the packet, if it is a container, instead of getting
4014/// the following packet.
4015///
4016/// See the [`PacketParser::next`] and [`PacketParser::recurse`]
4017/// methods for more details.
4018///
4019/// [`Packet`]: super::Packet
4020/// [`BufferedReader`]: https://docs.rs/buffered-reader/*/buffered_reader/trait.BufferedReader.html
4021/// [`PacketParser::next`]: PacketParser::next()
4022/// [`PacketParser::recurse`]: PacketParser::recurse()
4023///
4024/// # Examples
4025///
4026/// These examples demonstrate how to process packet bodies by parsing
4027/// the simplest possible OpenPGP message containing just a single
4028/// literal data packet with the body "Hello world.". There are three
4029/// options. First, the body can be dropped. Second, it can be
4030/// buffered. Lastly, the body can be streamed. In general,
4031/// streaming should be preferred, because it avoids buffering in
4032/// Sequoia.
4033///
4034/// This example demonstrates simply ignoring the packet body:
4035///
4036/// ```rust
4037/// # fn main() -> sequoia_openpgp::Result<()> {
4038/// use sequoia_openpgp as openpgp;
4039/// use openpgp::Packet;
4040/// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4041///
4042/// // By default, the `PacketParser` will drop packet bodies.
4043/// let mut ppr =
4044/// PacketParser::from_bytes(b"\xcb\x12b\x00\x00\x00\x00\x00Hello world.")?;
4045/// while let PacketParserResult::Some(pp) = ppr {
4046/// // Get the packet out of the parser and start parsing the next
4047/// // packet, recursing.
4048/// let (packet, next_ppr) = pp.recurse()?;
4049/// ppr = next_ppr;
4050///
4051/// // Process the packet.
4052/// if let Packet::Literal(literal) = packet {
4053/// // The body was dropped.
4054/// assert_eq!(literal.body(), b"");
4055/// } else {
4056/// unreachable!("We know it is a literal packet.");
4057/// }
4058/// }
4059/// # Ok(()) }
4060/// ```
4061///
4062/// This example demonstrates how the body can be buffered by
4063/// configuring the `PacketParser` to buffer all packet bodies:
4064///
4065/// ```rust
4066/// # fn main() -> sequoia_openpgp::Result<()> {
4067/// use sequoia_openpgp as openpgp;
4068/// use openpgp::Packet;
4069/// use openpgp::parse::{Parse, PacketParserResult, PacketParserBuilder};
4070///
4071/// // By default, the `PacketParser` will drop packet bodies. Use a
4072/// // `PacketParserBuilder` to change that.
4073/// let mut ppr =
4074/// PacketParserBuilder::from_bytes(
4075/// b"\xcb\x12b\x00\x00\x00\x00\x00Hello world.")?
4076/// .buffer_unread_content()
4077/// .build()?;
4078/// while let PacketParserResult::Some(pp) = ppr {
4079/// // Get the packet out of the parser and start parsing the next
4080/// // packet, recursing.
4081/// let (packet, next_ppr) = pp.recurse()?;
4082/// ppr = next_ppr;
4083///
4084/// // Process the packet.
4085/// if let Packet::Literal(literal) = packet {
4086/// // The body was buffered.
4087/// assert_eq!(literal.body(), b"Hello world.");
4088/// } else {
4089/// unreachable!("We know it is a literal packet.");
4090/// }
4091/// }
4092/// # Ok(()) }
4093/// ```
4094///
4095/// This example demonstrates how the body can be buffered by
4096/// buffering an individual packet:
4097///
4098/// ```rust
4099/// # fn main() -> sequoia_openpgp::Result<()> {
4100/// use sequoia_openpgp as openpgp;
4101/// use openpgp::Packet;
4102/// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4103///
4104/// // By default, the `PacketParser` will drop packet bodies.
4105/// let mut ppr =
4106/// PacketParser::from_bytes(b"\xcb\x12b\x00\x00\x00\x00\x00Hello world.")?;
4107/// while let PacketParserResult::Some(mut pp) = ppr {
4108/// if let Packet::Literal(_) = pp.packet {
4109/// // Buffer this packet's body.
4110/// pp.buffer_unread_content()?;
4111/// }
4112///
4113/// // Get the packet out of the parser and start parsing the next
4114/// // packet, recursing.
4115/// let (packet, next_ppr) = pp.recurse()?;
4116/// ppr = next_ppr;
4117///
4118/// // Process the packet.
4119/// if let Packet::Literal(literal) = packet {
4120/// // The body was buffered.
4121/// assert_eq!(literal.body(), b"Hello world.");
4122/// } else {
4123/// unreachable!("We know it is a literal packet.");
4124/// }
4125/// }
4126/// # Ok(()) }
4127/// ```
4128///
4129/// This example demonstrates how to stream the packet body:
4130///
4131/// ```rust
4132/// # fn main() -> sequoia_openpgp::Result<()> {
4133/// use std::io::Read;
4134///
4135/// use sequoia_openpgp as openpgp;
4136/// use openpgp::Packet;
4137/// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4138///
4139/// let mut ppr =
4140/// PacketParser::from_bytes(b"\xcb\x12b\x00\x00\x00\x00\x00Hello world.")?;
4141/// while let PacketParserResult::Some(mut pp) = ppr {
4142/// if let Packet::Literal(_) = pp.packet {
4143/// // Stream the body.
4144/// let mut buf = Vec::new();
4145/// pp.read_to_end(&mut buf)?;
4146/// assert_eq!(buf, b"Hello world.");
4147/// } else {
4148/// unreachable!("We know it is a literal packet.");
4149/// }
4150///
4151/// // Get the packet out of the parser and start parsing the next
4152/// // packet, recursing.
4153/// let (packet, next_ppr) = pp.recurse()?;
4154/// ppr = next_ppr;
4155///
4156/// // Process the packet.
4157/// if let Packet::Literal(literal) = packet {
4158/// // The body was streamed, not buffered.
4159/// assert_eq!(literal.body(), b"");
4160/// } else {
4161/// unreachable!("We know it is a literal packet.");
4162/// }
4163/// }
4164/// # Ok(()) }
4165/// ```
4166///
4167/// # Packet Parser Design
4168///
4169/// There are two major concerns that inform the design of the parsing
4170/// API.
4171///
4172/// First, when processing a container, it is possible to either
4173/// recurse into the container, and process its children, or treat the
4174/// contents of the container as an opaque byte stream, and process
4175/// the packet following the container. The low-level
4176/// [`PacketParser`] and mid-level [`PacketPileParser`] abstractions
4177/// allow the caller to choose the behavior by either calling the
4178/// [`PacketParser::recurse`] method or the [`PacketParser::next`]
4179/// method, as appropriate. OpenPGP doesn't impose any restrictions
4180/// on the amount of nesting. So, to prevent a denial-of-service
4181/// attack, the parsers don't recurse more than
4182/// [`DEFAULT_MAX_RECURSION_DEPTH`] times, by default.
4183///
4184///
4185/// Second, packets can contain an effectively unbounded amount of
4186/// data. To avoid errors due to memory exhaustion, the
4187/// `PacketParser` and [`PacketPileParser`] abstractions support
4188/// parsing packets in a streaming manner, i.e., never buffering more
4189/// than O(1) bytes of data. To do this, the parsers initially only
4190/// parse a packet's header (which is rarely more than a few kilobytes
4191/// of data), and return control to the caller. After inspecting that
4192/// data, the caller can decide how to handle the packet's contents.
4193/// If the content is deemed interesting, it can be streamed or
4194/// buffered. Otherwise, it can be dropped. Streaming is possible
4195/// not only for literal data packets, but also containers (other
4196/// packets also support the interface, but just return EOF). For
4197/// instance, encryption can be stripped by saving the decrypted
4198/// content of an encryption packet, which is just an OpenPGP message.
4199///
4200/// ## Iterator Design
4201///
4202/// We explicitly chose to not use a callback-based API, but something
4203/// that is closer to Rust's iterator API. Unfortunately, because a
4204/// `PacketParser` needs mutable access to the input stream (so that
4205/// the content can be streamed), only a single `PacketParser` item
4206/// can be live at a time (without a fair amount of unsafe nastiness).
4207/// This is incompatible with Rust's iterator concept, which allows
4208/// any number of items to be live at any time. For instance:
4209///
4210/// ```rust
4211/// let mut v = vec![1, 2, 3, 4];
4212/// let mut iter = v.iter_mut();
4213///
4214/// let x = iter.next().unwrap();
4215/// let y = iter.next().unwrap();
4216///
4217/// *x += 10; // This does not cause an error!
4218/// *y += 10;
4219/// ```
4220pub struct PacketParser<'a> {
4221 /// The current packet's header.
4222 header: Header,
4223
4224 /// The packet that is being parsed.
4225 pub packet: Packet,
4226
4227 // The path of the packet that is currently being parsed.
4228 path: Vec<usize>,
4229 // The path of the packet that was most recently returned by
4230 // `next()` or `recurse()`.
4231 last_path: Vec<usize>,
4232
4233 reader: Box<dyn BufferedReader<Cookie> + 'a>,
4234
4235 // Whether the caller read the packet's content. If so, then we
4236 // can't recurse, because we're missing some of the packet!
4237 content_was_read: bool,
4238
4239 // Whether PacketParser::finish has been called.
4240 finished: bool,
4241
4242 // Whether the content has been processed.
4243 processed: bool,
4244
4245 /// A map of this packet.
4246 map: Option<map::Map>,
4247
4248 /// We compute a hashsum over the body to implement comparison on
4249 /// containers that have been streamed.
4250 body_hash: Option<Box<Xxh3>>,
4251
4252 state: PacketParserState,
4253}
4254assert_send_and_sync!(PacketParser<'_>);
4255
4256impl<'a> std::fmt::Display for PacketParser<'a> {
4257 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4258 write!(f, "PacketParser")
4259 }
4260}
4261
4262impl<'a> std::fmt::Debug for PacketParser<'a> {
4263 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4264 f.debug_struct("PacketParser")
4265 .field("header", &self.header)
4266 .field("packet", &self.packet)
4267 .field("path", &self.path)
4268 .field("last_path", &self.last_path)
4269 .field("processed", &self.processed)
4270 .field("content_was_read", &self.content_was_read)
4271 .field("settings", &self.state.settings)
4272 .field("map", &self.map)
4273 .finish()
4274 }
4275}
4276
4277/// The return value of PacketParser::parse.
4278enum ParserResult<'a> {
4279 Success(PacketParser<'a>),
4280 EOF((Box<dyn BufferedReader<Cookie> + 'a>, PacketParserState, Vec<usize>)),
4281}
4282
4283/// Information about the stream of packets parsed by the
4284/// `PacketParser`.
4285///
4286/// Once the [`PacketParser`] reaches the end of the input stream, it
4287/// returns a [`PacketParserResult::EOF`] with a `PacketParserEOF`.
4288/// This object provides information about the parsed stream, notably
4289/// whether the packet stream was a well-formed [`Message`],
4290/// [`Cert`] or keyring.
4291///
4292/// [`Message`]: super::Message
4293/// [`Cert`]: crate::cert::Cert
4294///
4295/// # Examples
4296///
4297/// Parse some OpenPGP stream using a [`PacketParser`] and detects the
4298/// kind of data:
4299///
4300/// ```rust
4301/// # fn main() -> sequoia_openpgp::Result<()> {
4302/// use sequoia_openpgp as openpgp;
4303/// use openpgp::Packet;
4304/// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4305///
4306/// let openpgp_data: &[u8] = // ...
4307/// # include_bytes!("../tests/data/keys/public-key.pgp");
4308/// let mut ppr = PacketParser::from_bytes(openpgp_data)?;
4309/// while let PacketParserResult::Some(mut pp) = ppr {
4310/// // Start parsing the next packet, recursing.
4311/// ppr = pp.recurse()?.1;
4312/// }
4313///
4314/// if let PacketParserResult::EOF(eof) = ppr {
4315/// if eof.is_message().is_ok() {
4316/// // ...
4317/// } else if eof.is_cert().is_ok() {
4318/// // ...
4319/// } else if eof.is_keyring().is_ok() {
4320/// // ...
4321/// } else {
4322/// // ...
4323/// }
4324/// }
4325/// # Ok(()) }
4326/// ```
4327#[derive(Debug)]
4328pub struct PacketParserEOF<'a> {
4329 state: PacketParserState,
4330 reader: Box<dyn BufferedReader<Cookie> + 'a>,
4331 last_path: Vec<usize>,
4332}
4333assert_send_and_sync!(PacketParserEOF<'_>);
4334
4335impl<'a> PacketParserEOF<'a> {
4336 /// Copies the important information in `pp` into a new
4337 /// `PacketParserEOF` instance.
4338 fn new(mut state: PacketParserState,
4339 reader: Box<dyn BufferedReader<Cookie> + 'a>)
4340 -> Self {
4341 state.message_validator.finish();
4342 state.keyring_validator.finish();
4343 state.cert_validator.finish();
4344
4345 PacketParserEOF {
4346 state,
4347 reader,
4348 last_path: vec![],
4349 }
4350 }
4351
4352 /// Creates a placeholder instance for PacketParserResult::take.
4353 fn empty() -> Self {
4354 Self::new(
4355 PacketParserState::new(Default::default()),
4356 buffered_reader::Memory::with_cookie(b"", Default::default())
4357 .into_boxed())
4358 }
4359
4360 /// Returns whether the stream is an OpenPGP Message.
4361 ///
4362 /// A [`Message`] has a very specific structure. Returns `true`
4363 /// if the stream is of that form, as opposed to a [`Cert`] or
4364 /// just a bunch of packets.
4365 ///
4366 /// [`Message`]: super::Message
4367 /// [`Cert`]: crate::cert::Cert
4368 ///
4369 /// # Examples
4370 ///
4371 /// Parse some OpenPGP stream using a [`PacketParser`] and detects the
4372 /// kind of data:
4373 ///
4374 ///
4375 /// ```rust
4376 /// # fn main() -> sequoia_openpgp::Result<()> {
4377 /// use sequoia_openpgp as openpgp;
4378 /// use openpgp::Packet;
4379 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4380 ///
4381 /// let openpgp_data: &[u8] = // ...
4382 /// # include_bytes!("../tests/data/keys/public-key.pgp");
4383 /// let mut ppr = PacketParser::from_bytes(openpgp_data)?;
4384 /// while let PacketParserResult::Some(mut pp) = ppr {
4385 /// // Start parsing the next packet, recursing.
4386 /// ppr = pp.recurse()?.1;
4387 /// }
4388 ///
4389 /// if let PacketParserResult::EOF(eof) = ppr {
4390 /// if eof.is_message().is_ok() {
4391 /// // ...
4392 /// }
4393 /// }
4394 /// # Ok(()) }
4395 /// ```
4396 pub fn is_message(&self) -> Result<()> {
4397 use crate::message::MessageValidity;
4398
4399 match self.state.message_validator.check() {
4400 MessageValidity::Message => Ok(()),
4401 MessageValidity::MessagePrefix => unreachable!(),
4402 MessageValidity::Error(err) => Err(err),
4403 }
4404 }
4405
4406 /// Returns whether the message is an OpenPGP keyring.
4407 ///
4408 /// A keyring has a very specific structure. Returns `true` if
4409 /// the stream is of that form, as opposed to a [`Message`] or
4410 /// just a bunch of packets.
4411 ///
4412 /// [`Message`]: super::Message
4413 ///
4414 /// # Examples
4415 ///
4416 /// Parse some OpenPGP stream using a [`PacketParser`] and detects the
4417 /// kind of data:
4418 ///
4419 ///
4420 /// ```rust
4421 /// # fn main() -> sequoia_openpgp::Result<()> {
4422 /// use sequoia_openpgp as openpgp;
4423 /// use openpgp::Packet;
4424 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4425 ///
4426 /// let openpgp_data: &[u8] = // ...
4427 /// # include_bytes!("../tests/data/keys/public-key.pgp");
4428 /// let mut ppr = PacketParser::from_bytes(openpgp_data)?;
4429 /// while let PacketParserResult::Some(mut pp) = ppr {
4430 /// // Start parsing the next packet, recursing.
4431 /// ppr = pp.recurse()?.1;
4432 /// }
4433 ///
4434 /// if let PacketParserResult::EOF(eof) = ppr {
4435 /// if eof.is_keyring().is_ok() {
4436 /// // ...
4437 /// }
4438 /// }
4439 /// # Ok(()) }
4440 /// ```
4441 pub fn is_keyring(&self) -> Result<()> {
4442 match self.state.keyring_validator.check() {
4443 KeyringValidity::Keyring => Ok(()),
4444 KeyringValidity::KeyringPrefix => unreachable!(),
4445 KeyringValidity::Error(err) => Err(err),
4446 }
4447 }
4448
4449 /// Returns whether the message is an OpenPGP Cert.
4450 ///
4451 /// A [`Cert`] has a very specific structure. Returns `true` if
4452 /// the stream is of that form, as opposed to a [`Message`] or
4453 /// just a bunch of packets.
4454 ///
4455 /// [`Message`]: super::Message
4456 /// [`Cert`]: crate::cert::Cert
4457 ///
4458 /// # Examples
4459 ///
4460 /// Parse some OpenPGP stream using a [`PacketParser`] and detects the
4461 /// kind of data:
4462 ///
4463 ///
4464 /// ```rust
4465 /// # fn main() -> sequoia_openpgp::Result<()> {
4466 /// use sequoia_openpgp as openpgp;
4467 /// use openpgp::Packet;
4468 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4469 ///
4470 /// let openpgp_data: &[u8] = // ...
4471 /// # include_bytes!("../tests/data/keys/public-key.pgp");
4472 /// let mut ppr = PacketParser::from_bytes(openpgp_data)?;
4473 /// while let PacketParserResult::Some(mut pp) = ppr {
4474 /// // Start parsing the next packet, recursing.
4475 /// ppr = pp.recurse()?.1;
4476 /// }
4477 ///
4478 /// if let PacketParserResult::EOF(eof) = ppr {
4479 /// if eof.is_cert().is_ok() {
4480 /// // ...
4481 /// }
4482 /// }
4483 /// # Ok(()) }
4484 /// ```
4485 pub fn is_cert(&self) -> Result<()> {
4486 match self.state.cert_validator.check() {
4487 CertValidity::Cert => Ok(()),
4488 CertValidity::CertPrefix => unreachable!(),
4489 CertValidity::Error(err) => Err(err),
4490 }
4491 }
4492
4493 /// Returns the path of the last packet.
4494 ///
4495 /// # Examples
4496 ///
4497 /// Parse some OpenPGP stream using a [`PacketParser`] and returns
4498 /// the path (see [`PacketPile::path_ref`]) of the last packet:
4499 ///
4500 /// [`PacketPile::path_ref`]: super::PacketPile::path_ref()
4501 ///
4502 /// ```rust
4503 /// # fn main() -> sequoia_openpgp::Result<()> {
4504 /// use sequoia_openpgp as openpgp;
4505 /// use openpgp::Packet;
4506 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4507 ///
4508 /// let openpgp_data: &[u8] = // ...
4509 /// # include_bytes!("../tests/data/keys/public-key.pgp");
4510 /// let mut ppr = PacketParser::from_bytes(openpgp_data)?;
4511 /// while let PacketParserResult::Some(mut pp) = ppr {
4512 /// // Start parsing the next packet, recursing.
4513 /// ppr = pp.recurse()?.1;
4514 /// }
4515 ///
4516 /// if let PacketParserResult::EOF(eof) = ppr {
4517 /// let _ = eof.last_path();
4518 /// }
4519 /// # Ok(()) }
4520 /// ```
4521 pub fn last_path(&self) -> &[usize] {
4522 &self.last_path[..]
4523 }
4524
4525 /// The last packet's recursion depth.
4526 ///
4527 /// A top-level packet has a recursion depth of 0. Packets in a
4528 /// top-level container have a recursion depth of 1, etc.
4529 ///
4530 /// # Examples
4531 ///
4532 /// Parse some OpenPGP stream using a [`PacketParser`] and returns
4533 /// the recursion depth of the last packet:
4534 ///
4535 ///
4536 /// ```rust
4537 /// # fn main() -> sequoia_openpgp::Result<()> {
4538 /// use sequoia_openpgp as openpgp;
4539 /// use openpgp::Packet;
4540 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4541 ///
4542 /// let openpgp_data: &[u8] = // ...
4543 /// # include_bytes!("../tests/data/keys/public-key.pgp");
4544 /// let mut ppr = PacketParser::from_bytes(openpgp_data)?;
4545 /// while let PacketParserResult::Some(mut pp) = ppr {
4546 /// // Start parsing the next packet, recursing.
4547 /// ppr = pp.recurse()?.1;
4548 /// }
4549 ///
4550 /// if let PacketParserResult::EOF(eof) = ppr {
4551 /// let _ = eof.last_recursion_depth();
4552 /// }
4553 /// # Ok(()) }
4554 /// ```
4555 pub fn last_recursion_depth(&self) -> Option<isize> {
4556 if self.last_path.is_empty() {
4557 None
4558 } else {
4559 Some(self.last_path.len() as isize - 1)
4560 }
4561 }
4562
4563 /// Returns the exhausted reader.
4564 pub fn into_reader(self) -> Box<dyn BufferedReader<Cookie> + 'a> {
4565 self.reader
4566 }
4567}
4568
4569/// The result of parsing a packet.
4570///
4571/// This type is returned by [`PacketParser::next`],
4572/// [`PacketParser::recurse`], [`PacketParserBuilder::build`], and the
4573/// implementation of [`PacketParser`]'s [`Parse` trait]. The result
4574/// is either `Some(PacketParser)`, indicating successful parsing of a
4575/// packet, or `EOF(PacketParserEOF)` if the end of the input stream
4576/// has been reached.
4577///
4578/// [`PacketParser::next`]: PacketParser::next()
4579/// [`PacketParser::recurse`]: PacketParser::recurse()
4580/// [`PacketParserBuilder::build`]: PacketParserBuilder::build()
4581/// [`Parse` trait]: struct.PacketParser.html#impl-Parse%3C%27a%2C%20PacketParserResult%3C%27a%3E%3E
4582#[derive(Debug)]
4583pub enum PacketParserResult<'a> {
4584 /// A `PacketParser` for the next packet.
4585 Some(PacketParser<'a>),
4586 /// Information about a fully parsed packet sequence.
4587 EOF(PacketParserEOF<'a>),
4588}
4589assert_send_and_sync!(PacketParserResult<'_>);
4590
4591impl<'a> PacketParserResult<'a> {
4592 /// Returns `true` if the result is `EOF`.
4593 pub fn is_eof(&self) -> bool {
4594 matches!(self, PacketParserResult::EOF(_))
4595 }
4596
4597 /// Returns `true` if the result is `Some`.
4598 pub fn is_some(&self) -> bool {
4599 ! Self::is_eof(self)
4600 }
4601
4602 /// Unwraps a result, yielding the content of an `Some`.
4603 ///
4604 /// # Panics
4605 ///
4606 /// Panics if the value is an `EOF`, with a panic message
4607 /// including the passed message, and the information in the
4608 /// [`PacketParserEOF`] object.
4609 ///
4610 pub fn expect(self, msg: &str) -> PacketParser<'a> {
4611 if let PacketParserResult::Some(pp) = self {
4612 pp
4613 } else {
4614 panic!("{}", msg);
4615 }
4616 }
4617
4618 /// Unwraps a result, yielding the content of an `Some`.
4619 ///
4620 /// # Panics
4621 ///
4622 /// Panics if the value is an `EOF`, with a panic message
4623 /// including the information in the [`PacketParserEOF`] object.
4624 ///
4625 pub fn unwrap(self) -> PacketParser<'a> {
4626 self.expect("called `PacketParserResult::unwrap()` on a \
4627 `PacketParserResult::PacketParserEOF` value")
4628 }
4629
4630 /// Converts from `PacketParserResult` to `Result<&PacketParser,
4631 /// &PacketParserEOF>`.
4632 ///
4633 /// Produces a new `Result`, containing references into the
4634 /// original `PacketParserResult`, leaving the original in place.
4635 pub fn as_ref(&self)
4636 -> StdResult<&PacketParser<'a>, &PacketParserEOF> {
4637 match self {
4638 PacketParserResult::Some(pp) => Ok(pp),
4639 PacketParserResult::EOF(eof) => Err(eof),
4640 }
4641 }
4642
4643 /// Converts from `PacketParserResult` to `Result<&mut
4644 /// PacketParser, &mut PacketParserEOF>`.
4645 ///
4646 /// Produces a new `Result`, containing mutable references into the
4647 /// original `PacketParserResult`, leaving the original in place.
4648 pub fn as_mut(&mut self)
4649 -> StdResult<&mut PacketParser<'a>, &mut PacketParserEOF<'a>>
4650 {
4651 match self {
4652 PacketParserResult::Some(pp) => Ok(pp),
4653 PacketParserResult::EOF(eof) => Err(eof),
4654 }
4655 }
4656
4657 /// Takes the value out of the `PacketParserResult`, leaving a
4658 /// `EOF` in its place.
4659 ///
4660 /// The `EOF` left in place carries a [`PacketParserEOF`] with
4661 /// default values.
4662 ///
4663 pub fn take(&mut self) -> Self {
4664 mem::replace(
4665 self,
4666 PacketParserResult::EOF(PacketParserEOF::empty()))
4667 }
4668
4669 /// Maps a `PacketParserResult` to `Result<PacketParser,
4670 /// PacketParserEOF>` by applying a function to a contained `Some`
4671 /// value, leaving an `EOF` value untouched.
4672 pub fn map<U, F>(self, f: F) -> StdResult<U, PacketParserEOF<'a>>
4673 where F: FnOnce(PacketParser<'a>) -> U
4674 {
4675 match self {
4676 PacketParserResult::Some(x) => Ok(f(x)),
4677 PacketParserResult::EOF(e) => Err(e),
4678 }
4679 }
4680}
4681
4682impl<'a> Parse<'a, PacketParserResult<'a>> for PacketParser<'a> {
4683 /// Starts parsing an OpenPGP object stored in a `BufferedReader` object.
4684 ///
4685 /// This function returns a `PacketParser` for the first packet in
4686 /// the stream.
4687 fn from_buffered_reader<R>(reader: R) -> Result<PacketParserResult<'a>>
4688 where
4689 R: BufferedReader<Cookie> + 'a,
4690 {
4691 PacketParserBuilder::from_buffered_reader(reader.into_boxed())?.build()
4692 }
4693}
4694
4695impl<'a> crate::seal::Sealed for PacketParser<'a> {}
4696
4697impl <'a> PacketParser<'a> {
4698 /// Starts parsing an OpenPGP message stored in a `BufferedReader`
4699 /// object.
4700 ///
4701 /// This function returns a `PacketParser` for the first packet in
4702 /// the stream.
4703 pub(crate) fn from_cookie_reader(bio: Box<dyn BufferedReader<Cookie> + 'a>)
4704 -> Result<PacketParserResult<'a>> {
4705 PacketParserBuilder::from_cookie_reader(bio)?.build()
4706 }
4707
4708 /// Returns the reader stack, replacing it with a
4709 /// `buffered_reader::EOF` reader.
4710 ///
4711 /// This function may only be called when the `PacketParser` is in
4712 /// State::Body.
4713 fn take_reader(&mut self) -> Box<dyn BufferedReader<Cookie> + 'a> {
4714 self.set_reader(
4715 Box::new(buffered_reader::EOF::with_cookie(Default::default())))
4716 }
4717
4718 /// Replaces the reader stack.
4719 ///
4720 /// This function may only be called when the `PacketParser` is in
4721 /// State::Body.
4722 fn set_reader(&mut self, reader: Box<dyn BufferedReader<Cookie> + 'a>)
4723 -> Box<dyn BufferedReader<Cookie> + 'a>
4724 {
4725 mem::replace(&mut self.reader, reader)
4726 }
4727
4728 /// Returns a mutable reference to the reader stack.
4729 fn mut_reader(&mut self) -> &mut dyn BufferedReader<Cookie> {
4730 &mut self.reader
4731 }
4732
4733 /// Marks the packet's contents as processed or not.
4734 fn set_processed(mut self, v: bool) -> Self {
4735 self.processed = v;
4736 self
4737 }
4738
4739 /// Returns whether the packet's contents have been processed.
4740 ///
4741 /// This function returns `true` while processing an encryption
4742 /// container before it is decrypted using
4743 /// [`PacketParser::decrypt`]. Once successfully decrypted, it
4744 /// returns `false`.
4745 ///
4746 /// [`PacketParser::decrypt`]: PacketParser::decrypt()
4747 ///
4748 /// # Examples
4749 ///
4750 /// ```rust
4751 /// # fn main() -> sequoia_openpgp::Result<()> {
4752 /// use sequoia_openpgp as openpgp;
4753 /// use openpgp::Packet;
4754 /// use openpgp::fmt::hex;
4755 /// use openpgp::types::SymmetricAlgorithm;
4756 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4757 ///
4758 /// // Parse an encrypted message.
4759 /// let message_data: &[u8] = // ...
4760 /// # include_bytes!("../tests/data/messages/encrypted-aes256-password-123.pgp");
4761 /// let mut ppr = PacketParser::from_bytes(message_data)?;
4762 /// while let PacketParserResult::Some(mut pp) = ppr {
4763 /// if let Packet::SEIP(_) = pp.packet {
4764 /// assert!(!pp.processed());
4765 /// pp.decrypt(SymmetricAlgorithm::AES256,
4766 /// &hex::decode("7EF4F08C44F780BEA866961423306166\
4767 /// B8912C43352F3D9617F745E4E3939710")?
4768 /// .into())?;
4769 /// assert!(pp.processed());
4770 /// }
4771 ///
4772 /// // Start parsing the next packet, recursing.
4773 /// ppr = pp.recurse()?.1;
4774 /// }
4775 /// # Ok(()) }
4776 /// ```
4777 pub fn processed(&self) -> bool {
4778 self.processed
4779 }
4780
4781 /// Returns the path of the last packet.
4782 ///
4783 /// This function returns the path (see [`PacketPile::path_ref`]
4784 /// for a description of paths) of the packet last returned by a
4785 /// call to [`PacketParser::recurse`] or [`PacketParser::next`].
4786 /// If no packet has been returned (i.e. the current packet is the
4787 /// first packet), this returns the empty slice.
4788 ///
4789 /// [`PacketPile::path_ref`]: super::PacketPile::path_ref()
4790 /// [`PacketParser::recurse`]: PacketParser::recurse()
4791 /// [`PacketParser::next`]: PacketParser::next()
4792 ///
4793 /// # Examples
4794 ///
4795 /// ```rust
4796 /// # fn main() -> sequoia_openpgp::Result<()> {
4797 /// use sequoia_openpgp as openpgp;
4798 /// use openpgp::Packet;
4799 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4800 ///
4801 /// // Parse a compressed message.
4802 /// let message_data: &[u8] = // ...
4803 /// # include_bytes!("../tests/data/messages/compressed-data-algo-0.pgp");
4804 /// let mut ppr = PacketParser::from_bytes(message_data)?;
4805 /// while let PacketParserResult::Some(mut pp) = ppr {
4806 /// match pp.packet {
4807 /// Packet::CompressedData(_) => assert_eq!(pp.last_path(), &[]),
4808 /// Packet::Literal(_) => assert_eq!(pp.last_path(), &[0]),
4809 /// _ => (),
4810 /// }
4811 ///
4812 /// // Start parsing the next packet, recursing.
4813 /// ppr = pp.recurse()?.1;
4814 /// }
4815 /// # Ok(()) }
4816 /// ```
4817 pub fn last_path(&self) -> &[usize] {
4818 &self.last_path[..]
4819 }
4820
4821 /// Returns the path of the current packet.
4822 ///
4823 /// This function returns the path (see [`PacketPile::path_ref`]
4824 /// for a description of paths) of the packet currently being
4825 /// processed (see [`PacketParser::packet`]).
4826 ///
4827 /// [`PacketPile::path_ref`]: super::PacketPile::path_ref()
4828 ///
4829 /// # Examples
4830 ///
4831 /// ```rust
4832 /// # fn main() -> sequoia_openpgp::Result<()> {
4833 /// use sequoia_openpgp as openpgp;
4834 /// use openpgp::Packet;
4835 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4836 ///
4837 /// // Parse a compressed message.
4838 /// let message_data: &[u8] = // ...
4839 /// # include_bytes!("../tests/data/messages/compressed-data-algo-0.pgp");
4840 /// let mut ppr = PacketParser::from_bytes(message_data)?;
4841 /// while let PacketParserResult::Some(mut pp) = ppr {
4842 /// match pp.packet {
4843 /// Packet::CompressedData(_) => assert_eq!(pp.path(), &[0]),
4844 /// Packet::Literal(_) => assert_eq!(pp.path(), &[0, 0]),
4845 /// _ => (),
4846 /// }
4847 ///
4848 /// // Start parsing the next packet, recursing.
4849 /// ppr = pp.recurse()?.1;
4850 /// }
4851 /// # Ok(()) }
4852 /// ```
4853 pub fn path(&self) -> &[usize] {
4854 &self.path[..]
4855 }
4856
4857 /// The current packet's recursion depth.
4858 ///
4859 /// A top-level packet has a recursion depth of 0. Packets in a
4860 /// top-level container have a recursion depth of 1, etc.
4861 ///
4862 /// # Examples
4863 ///
4864 /// ```rust
4865 /// # fn main() -> sequoia_openpgp::Result<()> {
4866 /// use sequoia_openpgp as openpgp;
4867 /// use openpgp::Packet;
4868 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4869 ///
4870 /// // Parse a compressed message.
4871 /// let message_data: &[u8] = // ...
4872 /// # include_bytes!("../tests/data/messages/compressed-data-algo-0.pgp");
4873 /// let mut ppr = PacketParser::from_bytes(message_data)?;
4874 /// while let PacketParserResult::Some(mut pp) = ppr {
4875 /// match pp.packet {
4876 /// Packet::CompressedData(_) => assert_eq!(pp.recursion_depth(), 0),
4877 /// Packet::Literal(_) => assert_eq!(pp.recursion_depth(), 1),
4878 /// _ => (),
4879 /// }
4880 ///
4881 /// // Start parsing the next packet, recursing.
4882 /// ppr = pp.recurse()?.1;
4883 /// }
4884 /// # Ok(()) }
4885 /// ```
4886 pub fn recursion_depth(&self) -> isize {
4887 self.path.len() as isize - 1
4888 }
4889
4890 /// The last packet's recursion depth.
4891 ///
4892 /// A top-level packet has a recursion depth of 0. Packets in a
4893 /// top-level container have a recursion depth of 1, etc.
4894 ///
4895 /// Note: if no packet has been returned yet, this returns None.
4896 ///
4897 /// # Examples
4898 ///
4899 /// ```rust
4900 /// # fn main() -> sequoia_openpgp::Result<()> {
4901 /// use sequoia_openpgp as openpgp;
4902 /// use openpgp::Packet;
4903 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4904 ///
4905 /// // Parse a compressed message.
4906 /// let message_data: &[u8] = // ...
4907 /// # include_bytes!("../tests/data/messages/compressed-data-algo-0.pgp");
4908 /// let mut ppr = PacketParser::from_bytes(message_data)?;
4909 /// while let PacketParserResult::Some(mut pp) = ppr {
4910 /// match pp.packet {
4911 /// Packet::CompressedData(_) => assert_eq!(pp.last_recursion_depth(), None),
4912 /// Packet::Literal(_) => assert_eq!(pp.last_recursion_depth(), Some(0)),
4913 /// _ => (),
4914 /// }
4915 ///
4916 /// // Start parsing the next packet, recursing.
4917 /// ppr = pp.recurse()?.1;
4918 /// }
4919 /// # Ok(()) }
4920 /// ```
4921 pub fn last_recursion_depth(&self) -> Option<isize> {
4922 if self.last_path.is_empty() {
4923 assert_eq!(&self.path[..], &[ 0 ]);
4924 None
4925 } else {
4926 Some(self.last_path.len() as isize - 1)
4927 }
4928 }
4929
4930 /// Returns whether the message appears to be an OpenPGP Message.
4931 ///
4932 /// Only when the whole message has been processed is it possible
4933 /// to say whether the message is definitely an OpenPGP Message.
4934 /// Before that, it is only possible to say that the message is a
4935 /// valid prefix or definitely not an OpenPGP message (see
4936 /// [`PacketParserEOF::is_message`]).
4937 ///
4938 /// [`PacketParserEOF::is_message`]: PacketParserEOF::is_message()
4939 ///
4940 /// # Examples
4941 ///
4942 /// ```rust
4943 /// # fn main() -> sequoia_openpgp::Result<()> {
4944 /// use sequoia_openpgp as openpgp;
4945 /// use openpgp::Packet;
4946 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4947 ///
4948 /// // Parse a compressed message.
4949 /// let message_data: &[u8] = // ...
4950 /// # include_bytes!("../tests/data/messages/compressed-data-algo-0.pgp");
4951 /// let mut ppr = PacketParser::from_bytes(message_data)?;
4952 /// while let PacketParserResult::Some(mut pp) = ppr {
4953 /// pp.possible_message()?;
4954 ///
4955 /// // Start parsing the next packet, recursing.
4956 /// ppr = pp.recurse()?.1;
4957 /// }
4958 /// # Ok(()) }
4959 /// ```
4960 pub fn possible_message(&self) -> Result<()> {
4961 use crate::message::MessageValidity;
4962
4963 match self.state.message_validator.check() {
4964 MessageValidity::Message => unreachable!(),
4965 MessageValidity::MessagePrefix => Ok(()),
4966 MessageValidity::Error(err) => Err(err),
4967 }
4968 }
4969
4970 /// Returns whether the message appears to be an OpenPGP keyring.
4971 ///
4972 /// Only when the whole message has been processed is it possible
4973 /// to say whether the message is definitely an OpenPGP keyring.
4974 /// Before that, it is only possible to say that the message is a
4975 /// valid prefix or definitely not an OpenPGP keyring (see
4976 /// [`PacketParserEOF::is_keyring`]).
4977 ///
4978 /// [`PacketParserEOF::is_keyring`]: PacketParserEOF::is_keyring()
4979 ///
4980 /// # Examples
4981 ///
4982 /// ```rust
4983 /// # fn main() -> sequoia_openpgp::Result<()> {
4984 /// use sequoia_openpgp as openpgp;
4985 /// use openpgp::Packet;
4986 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
4987 ///
4988 /// // Parse a certificate.
4989 /// let message_data: &[u8] = // ...
4990 /// # include_bytes!("../tests/data/keys/testy.pgp");
4991 /// let mut ppr = PacketParser::from_bytes(message_data)?;
4992 /// while let PacketParserResult::Some(mut pp) = ppr {
4993 /// pp.possible_keyring()?;
4994 ///
4995 /// // Start parsing the next packet, recursing.
4996 /// ppr = pp.recurse()?.1;
4997 /// }
4998 /// # Ok(()) }
4999 /// ```
5000 pub fn possible_keyring(&self) -> Result<()> {
5001 match self.state.keyring_validator.check() {
5002 KeyringValidity::Keyring => unreachable!(),
5003 KeyringValidity::KeyringPrefix => Ok(()),
5004 KeyringValidity::Error(err) => Err(err),
5005 }
5006 }
5007
5008 /// Returns whether the message appears to be an OpenPGP Cert.
5009 ///
5010 /// Only when the whole message has been processed is it possible
5011 /// to say whether the message is definitely an OpenPGP Cert.
5012 /// Before that, it is only possible to say that the message is a
5013 /// valid prefix or definitely not an OpenPGP Cert (see
5014 /// [`PacketParserEOF::is_cert`]).
5015 ///
5016 /// [`PacketParserEOF::is_cert`]: PacketParserEOF::is_cert()
5017 ///
5018 /// # Examples
5019 ///
5020 /// ```rust
5021 /// # fn main() -> sequoia_openpgp::Result<()> {
5022 /// use sequoia_openpgp as openpgp;
5023 /// use openpgp::Packet;
5024 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
5025 ///
5026 /// // Parse a certificate.
5027 /// let message_data: &[u8] = // ...
5028 /// # include_bytes!("../tests/data/keys/testy.pgp");
5029 /// let mut ppr = PacketParser::from_bytes(message_data)?;
5030 /// while let PacketParserResult::Some(mut pp) = ppr {
5031 /// pp.possible_cert()?;
5032 ///
5033 /// // Start parsing the next packet, recursing.
5034 /// ppr = pp.recurse()?.1;
5035 /// }
5036 /// # Ok(()) }
5037 /// ```
5038 pub fn possible_cert(&self) -> Result<()> {
5039 match self.state.cert_validator.check() {
5040 CertValidity::Cert => unreachable!(),
5041 CertValidity::CertPrefix => Ok(()),
5042 CertValidity::Error(err) => Err(err),
5043 }
5044 }
5045
5046 /// Tests whether the data appears to be a legal cert packet.
5047 ///
5048 /// This is just a heuristic. It can be used for recovering from
5049 /// garbage.
5050 ///
5051 /// Successfully reading the header only means that the top bit of
5052 /// the ptag is 1. Assuming a uniform distribution, there's a 50%
5053 /// chance that that is the case.
5054 ///
5055 /// To improve our chances of a correct recovery, we make sure the
5056 /// tag is known (for new format CTBs, there are 64 possible tags,
5057 /// but only a third of them are reasonable; for old format
5058 /// packets, there are only 16 and nearly all are plausible), and
5059 /// we make sure the packet contents are reasonable.
5060 ///
5061 /// Currently, we only try to recover the most interesting
5062 /// packets.
5063 pub(crate) fn plausible_cert(bio: &mut dyn BufferedReader<Cookie>,
5064 header: &Header)
5065 -> Result<()>
5066 {
5067 let bad = Err(
5068 Error::MalformedPacket("Can't make an educated case".into()).into());
5069
5070 match header.ctb().tag() {
5071 Tag::Reserved
5072 | Tag::Unknown(_) | Tag::Private(_) =>
5073 Err(Error::MalformedPacket("Looks like garbage".into()).into()),
5074
5075 Tag::Marker => Marker::plausible(bio, header),
5076 Tag::Padding => {
5077 // Even though a padding packet may occur here, it has
5078 // so little structure, that we're likely better off
5079 // trying to find the next packet.
5080 //
5081 // XXX: We could optimize that though, by using the
5082 // potential padding packet's length to see if the
5083 // next packet is plausible.
5084 bad
5085 },
5086 Tag::Signature => Signature::plausible(bio, header),
5087
5088 Tag::SecretKey => Key::plausible(bio, header),
5089 Tag::PublicKey => Key::plausible(bio, header),
5090 Tag::SecretSubkey => Key::plausible(bio, header),
5091 Tag::PublicSubkey => Key::plausible(bio, header),
5092
5093 Tag::UserID => bad,
5094 Tag::UserAttribute => bad,
5095
5096 // It is reasonable to try and ignore garbage in Certs,
5097 // because who knows what the keyservers return, etc.
5098 // But, if we have what appears to be an OpenPGP message,
5099 // then, ignore.
5100 Tag::PKESK => bad,
5101 Tag::SKESK => bad,
5102 Tag::OnePassSig => bad,
5103 Tag::CompressedData => bad,
5104 Tag::SED => bad,
5105 Tag::Literal => bad,
5106 Tag::Trust => bad,
5107 Tag::SEIP => bad,
5108 Tag::MDC => bad,
5109 Tag::AED => bad,
5110 }
5111 }
5112
5113 /// Returns a `PacketParser` for the next OpenPGP packet in the
5114 /// stream. If there are no packets left, this function returns
5115 /// `bio`.
5116 fn parse(mut bio: Box<dyn BufferedReader<Cookie> + 'a>,
5117 mut state: PacketParserState,
5118 path: Vec<usize>)
5119 -> Result<ParserResult<'a>>
5120 {
5121 assert!(!path.is_empty());
5122
5123 let indent = path.len() as isize - 1;
5124 tracer!(TRACE, "PacketParser::parse", indent);
5125
5126 if let Some(err) = state.pending_error.take() {
5127 t!("Returning pending error: {}", err);
5128 return Err(err);
5129 }
5130 t!("Parsing packet at {:?}", path);
5131
5132 let recursion_depth = path.len() as isize - 1;
5133
5134 // When header encounters an EOF, it returns an error. But,
5135 // we want to return None. Try a one byte read.
5136 if bio.data(1)?.is_empty() {
5137 t!("No packet at {:?} (EOF).", path);
5138 return Ok(ParserResult::EOF((bio, state, path)));
5139 }
5140
5141 // When computing a hash for a signature, most of the
5142 // signature packet should not be included in the hash. That
5143 // is:
5144 //
5145 // [ one pass sig ] [ ... message ... ] [ sig ]
5146 // ^^^^^^^^^^^^^^^^^^^
5147 // hash only this
5148 //
5149 // (The special logic for the Signature packet is in
5150 // Signature::parse.)
5151 //
5152 // To avoid this, we use a Dup reader to figure out if the
5153 // next packet is a sig packet without consuming the headers,
5154 // which would cause the headers to be hashed. If so, we
5155 // extract the hash context.
5156
5157 let mut bio = buffered_reader::Dup::with_cookie(bio, Cookie::default());
5158 let header;
5159
5160 // Read the header.
5161 let mut skip = 0;
5162 let mut orig_error : Option<anyhow::Error> = None;
5163 loop {
5164 bio.rewind();
5165 if let Err(_err) = bio.data_consume_hard(skip) {
5166 // EOF. We checked for EOF above when skip was 0, so
5167 // we must have skipped something.
5168 assert!(skip > 0);
5169
5170 // Fabricate a header.
5171 header = Header::new(CTB::new(Tag::Reserved),
5172 BodyLength::Full(skip as u32));
5173
5174 break;
5175 }
5176
5177 match Header::parse(&mut bio) {
5178 Ok(header_) => {
5179 if skip == 0 {
5180 header = header_;
5181 break;
5182 }
5183
5184 match Self::plausible_cert(&mut bio, &header_) {
5185 Ok(()) => {
5186 header = Header::new(CTB::new(Tag::Reserved),
5187 BodyLength::Full(skip as u32));
5188 break;
5189 }
5190 Err(err_) => {
5191 t!("{} not plausible @ {}: {}",
5192 header_.ctb().tag(), skip, err_);
5193 },
5194 }
5195 }
5196 Err(err) => {
5197 t!("Failed to read a header after skipping {} bytes: {}",
5198 skip, err);
5199 if orig_error.is_none() {
5200 orig_error = Some(err);
5201 }
5202
5203 if state.first_packet {
5204 // We don't try to recover if we haven't seen
5205 // any packets.
5206 return Err(orig_error.unwrap());
5207 }
5208
5209 if skip > RECOVERY_THRESHOLD {
5210 // Limit the search space. This should be
5211 // enough to find a reasonable recovery point
5212 // in a Cert.
5213 state.pending_error = orig_error;
5214
5215 // Fabricate a header.
5216 header = Header::new(CTB::new(Tag::Reserved),
5217 BodyLength::Full(skip as u32));
5218 break;
5219 }
5220 }
5221 }
5222
5223 skip += 1;
5224 }
5225
5226 // Prepare to actually consume the header or garbage.
5227 let consumed = if skip == 0 {
5228 bio.total_out()
5229 } else {
5230 t!("turning {} bytes of junk into an Unknown packet", skip);
5231 bio.rewind();
5232 0
5233 };
5234
5235 let tag = header.ctb().tag();
5236 t!("Packet's tag is {}", tag);
5237
5238 // A buffered_reader::Dup always has an inner.
5239 let mut bio = Box::new(bio).into_inner().unwrap();
5240
5241 // Disable hashing for literal packets, Literal::parse will
5242 // enable it for the body. Signatures and OnePassSig packets
5243 // are only hashed by notarizing signatures.
5244 if tag == Tag::Literal {
5245 Cookie::hashing(
5246 &mut bio, Hashing::Disabled, recursion_depth - 1);
5247 } else if tag == Tag::OnePassSig || tag == Tag::Signature {
5248 if Cookie::processing_csf_message(&bio) {
5249 // When processing a CSF message, the hashing reader
5250 // is not peeled off, because the number of signature
5251 // packets cannot be known from the number of OPS
5252 // packets. Instead, we simply disable hashing.
5253 //
5254 // XXX: It would be nice to peel off the hashing
5255 // reader and drop this workaround.
5256 Cookie::hashing(
5257 &mut bio, Hashing::Disabled, recursion_depth - 1);
5258 } else {
5259 Cookie::hashing(
5260 &mut bio, Hashing::Notarized, recursion_depth - 1);
5261 }
5262 }
5263
5264 // Save header for the map or nested signatures.
5265 let header_bytes =
5266 Vec::from(&bio.data_consume_hard(consumed)?[..consumed]);
5267
5268 let bio : Box<dyn BufferedReader<Cookie>>
5269 = match header.length() {
5270 &BodyLength::Full(len) => {
5271 t!("Pushing a limitor ({} bytes), level: {}.",
5272 len, recursion_depth);
5273 Box::new(buffered_reader::Limitor::with_cookie(
5274 bio, len as u64,
5275 Cookie::new(recursion_depth)))
5276 },
5277 &BodyLength::Partial(len) => {
5278 t!("Pushing a partial body chunk decoder, level: {}.",
5279 recursion_depth);
5280 Box::new(BufferedReaderPartialBodyFilter::with_cookie(
5281 bio, len,
5282 // When hashing a literal data packet, we only
5283 // hash the packet's contents; we don't hash
5284 // the literal data packet's meta-data or the
5285 // length information, which includes the
5286 // partial body headers.
5287 tag != Tag::Literal,
5288 Cookie::new(recursion_depth)))
5289 },
5290 BodyLength::Indeterminate => {
5291 t!("Indeterminate length packet, not adding a limitor.");
5292 bio
5293 },
5294 };
5295
5296 // Our parser should not accept packets that fail our header
5297 // syntax check. Doing so breaks roundtripping, and seems
5298 // like a bad idea anyway.
5299 let mut header_syntax_error = header.valid(true).err();
5300
5301 // Check packet size.
5302 if header_syntax_error.is_none() {
5303 let max_size = state.settings.max_packet_size;
5304 match tag {
5305 // Don't check the size for container packets, those
5306 // can be safely streamed.
5307 Tag::Literal | Tag::CompressedData | Tag::SED | Tag::SEIP
5308 | Tag::AED => (),
5309 _ => match header.length() {
5310 BodyLength::Full(l) => if *l > max_size {
5311 header_syntax_error = Some(
5312 Error::PacketTooLarge(tag, *l, max_size).into());
5313 },
5314 _ => unreachable!("non-data packets have full length, \
5315 syntax check above"),
5316 }
5317 }
5318 }
5319
5320 let parser = PacketHeaderParser::new(bio, state, path,
5321 header, header_bytes);
5322
5323 let mut result = match tag {
5324 Tag::Reserved if skip > 0 => Unknown::parse(
5325 parser, Error::MalformedPacket(format!(
5326 "Skipped {} bytes of junk", skip)).into()),
5327 _ if header_syntax_error.is_some() =>
5328 Unknown::parse(parser, header_syntax_error.unwrap()),
5329 Tag::Signature => Signature::parse(parser),
5330 Tag::OnePassSig => OnePassSig::parse(parser),
5331 Tag::PublicSubkey => Key::parse(parser),
5332 Tag::PublicKey => Key::parse(parser),
5333 Tag::SecretKey => Key::parse(parser),
5334 Tag::SecretSubkey => Key::parse(parser),
5335 Tag::Trust => Trust::parse(parser),
5336 Tag::UserID => UserID::parse(parser),
5337 Tag::UserAttribute => UserAttribute::parse(parser),
5338 Tag::Marker => Marker::parse(parser),
5339 Tag::Literal => Literal::parse(parser),
5340 Tag::CompressedData => CompressedData::parse(parser),
5341 Tag::SKESK => SKESK::parse(parser),
5342 Tag::SEIP => SEIP::parse(parser),
5343 Tag::MDC => MDC::parse(parser),
5344 Tag::PKESK => PKESK::parse(parser),
5345 Tag::Padding => Padding::parse(parser),
5346 _ => Unknown::parse(parser,
5347 Error::UnsupportedPacketType(tag).into()),
5348 }?;
5349
5350 if tag == Tag::OnePassSig {
5351 Cookie::hashing(
5352 &mut result, Hashing::Enabled, recursion_depth - 1);
5353 }
5354
5355 result.state.first_packet = false;
5356
5357 t!(" -> {:?}, path: {:?}, level: {:?}.",
5358 result.packet.tag(), result.path, result.cookie_ref().level);
5359
5360 return Ok(ParserResult::Success(result));
5361 }
5362
5363 /// Finishes parsing the current packet and starts parsing the
5364 /// next one.
5365 ///
5366 /// This function finishes parsing the current packet. By
5367 /// default, any unread content is dropped. (See
5368 /// [`PacketParsererBuilder`] for how to configure this.) It then
5369 /// creates a new packet parser for the next packet. If the
5370 /// current packet is a container, this function does *not*
5371 /// recurse into the container, but skips any packets it contains.
5372 /// To recurse into the container, use the [`recurse()`] method.
5373 ///
5374 /// [`PacketParsererBuilder`]: PacketParserBuilder
5375 /// [`recurse()`]: PacketParser::recurse()
5376 ///
5377 /// The return value is a tuple containing:
5378 ///
5379 /// - A `Packet` holding the fully processed old packet;
5380 ///
5381 /// - A `PacketParser` holding the new packet;
5382 ///
5383 /// To determine the two packet's position within the parse tree,
5384 /// you can use `last_path()` and `path()`, respectively. To
5385 /// determine their depth, you can use `last_recursion_depth()`
5386 /// and `recursion_depth()`, respectively.
5387 ///
5388 /// Note: A recursion depth of 0 means that the packet is a
5389 /// top-level packet, a recursion depth of 1 means that the packet
5390 /// is an immediate child of a top-level-packet, etc.
5391 ///
5392 /// Since the packets are serialized in depth-first order and all
5393 /// interior nodes are visited, we know that if the recursion
5394 /// depth is the same, then the packets are siblings (they have a
5395 /// common parent) and not, e.g., cousins (they have a common
5396 /// grandparent). This is because, if we move up the tree, the
5397 /// only way to move back down is to first visit a new container
5398 /// (e.g., an aunt).
5399 ///
5400 /// Using the two positions, we can compute the change in depth as
5401 /// new_depth - old_depth. Thus, if the change in depth is 0, the
5402 /// two packets are siblings. If the value is 1, the old packet
5403 /// is a container, and the new packet is its first child. And,
5404 /// if the value is -1, the new packet is contained in the old
5405 /// packet's grandparent. The idea is illustrated below:
5406 ///
5407 /// ```text
5408 /// ancestor
5409 /// | \
5410 /// ... -n
5411 /// |
5412 /// grandparent
5413 /// | \
5414 /// parent -1
5415 /// | \
5416 /// packet 0
5417 /// |
5418 /// 1
5419 /// ```
5420 ///
5421 /// Note: since this function does not automatically recurse into
5422 /// a container, the change in depth will always be non-positive.
5423 /// If the current container is empty, this function DOES pop that
5424 /// container off the container stack, and returns the following
5425 /// packet in the parent container.
5426 ///
5427 /// # Examples
5428 ///
5429 /// ```rust
5430 /// # fn main() -> sequoia_openpgp::Result<()> {
5431 /// use sequoia_openpgp as openpgp;
5432 /// use openpgp::Packet;
5433 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
5434 ///
5435 /// // Parse a message.
5436 /// let message_data: &[u8] = // ...
5437 /// # include_bytes!("../tests/data/messages/compressed-data-algo-0.pgp");
5438 /// let mut ppr = PacketParser::from_bytes(message_data)?;
5439 /// while let PacketParserResult::Some(mut pp) = ppr {
5440 /// // Start parsing the next packet.
5441 /// ppr = pp.next()?.1;
5442 /// }
5443 /// # Ok(()) }
5444 /// ```
5445 pub fn next(mut self)
5446 -> Result<(Packet, PacketParserResult<'a>)>
5447 {
5448 let indent = self.recursion_depth();
5449 tracer!(TRACE, "PacketParser::next", indent);
5450 t!("({:?}, path: {:?}, level: {:?}).",
5451 self.packet.tag(), self.path, self.cookie_ref().level);
5452
5453 self.finish()?;
5454
5455 let (mut fake_eof, mut reader) = buffered_reader_stack_pop(
5456 mem::replace(&mut self.reader,
5457 Box::new(buffered_reader::EOF::with_cookie(
5458 Default::default()))),
5459 self.recursion_depth())?;
5460
5461 self.last_path.clear();
5462 self.last_path.extend_from_slice(&self.path[..]);
5463
5464 // Assume that we succeed in parsing the next packet. If not,
5465 // then we'll adjust the path.
5466 *self.path.last_mut().expect("A path is never empty") += 1;
5467
5468 // Now read the next packet.
5469 loop {
5470 // Parse the next packet.
5471 t!("Reading packet at {:?}", self.path);
5472
5473 let recursion_depth = self.recursion_depth();
5474
5475 let ppr = PacketParser::parse(reader, self.state, self.path)?;
5476 match ppr {
5477 ParserResult::EOF((reader_, state_, path_)) => {
5478 // We got EOF on the current container. The
5479 // container at recursion depth n is empty. Pop
5480 // it and any filters for it, i.e., those at level
5481 // n (e.g., the limitor that caused us to hit
5482 // EOF), and then try again.
5483
5484 t!("depth: {}, got EOF trying to read the next packet",
5485 recursion_depth);
5486
5487 self.path = path_;
5488
5489 if ! fake_eof && recursion_depth == 0 {
5490 t!("Popped top-level container, done reading message.");
5491 // Pop topmost filters (e.g. the armor::Reader).
5492 let (_, reader_) = buffered_reader_stack_pop(
5493 reader_, ARMOR_READER_LEVEL)?;
5494 let mut eof = PacketParserEOF::new(state_, reader_);
5495 eof.last_path = self.last_path;
5496 return Ok((self.packet,
5497 PacketParserResult::EOF(eof)));
5498 } else {
5499 self.state = state_;
5500 self.finish()?;
5501 let (fake_eof_, reader_) = buffered_reader_stack_pop(
5502 reader_, recursion_depth - 1)?;
5503 fake_eof = fake_eof_;
5504 if ! fake_eof {
5505 self.path.pop().unwrap();
5506 *self.path.last_mut()
5507 .expect("A path is never empty") += 1;
5508 }
5509 reader = reader_;
5510 }
5511 },
5512 ParserResult::Success(mut pp) => {
5513 let path = pp.path().to_vec();
5514 pp.state.message_validator.push(
5515 pp.packet.tag(), pp.packet.version(),
5516 &path);
5517 pp.state.keyring_validator.push(pp.packet.tag());
5518 pp.state.cert_validator.push(pp.packet.tag());
5519
5520 pp.last_path = self.last_path;
5521
5522 return Ok((self.packet, PacketParserResult::Some(pp)));
5523 }
5524 }
5525 }
5526 }
5527
5528 /// Finishes parsing the current packet and starts parsing the
5529 /// next one, recursing if possible.
5530 ///
5531 /// This method is similar to the [`next()`] method (see that
5532 /// method for more details), but if the current packet is a
5533 /// container (and we haven't reached the maximum recursion depth,
5534 /// and the user hasn't started reading the packet's contents), we
5535 /// recurse into the container, and return a `PacketParser` for
5536 /// its first child. Otherwise, we return the next packet in the
5537 /// packet stream. If this function recurses, then the new
5538 /// packet's recursion depth will be `last_recursion_depth() + 1`;
5539 /// because we always visit interior nodes, we can't recurse more
5540 /// than one level at a time.
5541 ///
5542 /// [`next()`]: PacketParser::next()
5543 ///
5544 /// # Examples
5545 ///
5546 /// ```rust
5547 /// # fn main() -> sequoia_openpgp::Result<()> {
5548 /// use sequoia_openpgp as openpgp;
5549 /// use openpgp::Packet;
5550 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
5551 ///
5552 /// // Parse a message.
5553 /// let message_data: &[u8] = // ...
5554 /// # include_bytes!("../tests/data/messages/compressed-data-algo-0.pgp");
5555 /// let mut ppr = PacketParser::from_bytes(message_data)?;
5556 /// while let PacketParserResult::Some(mut pp) = ppr {
5557 /// // Start parsing the next packet, recursing.
5558 /// ppr = pp.recurse()?.1;
5559 /// }
5560 /// # Ok(()) }
5561 /// ```
5562 pub fn recurse(self) -> Result<(Packet, PacketParserResult<'a>)> {
5563 let indent = self.recursion_depth();
5564 tracer!(TRACE, "PacketParser::recurse", indent);
5565 t!("({:?}, path: {:?}, level: {:?})",
5566 self.packet.tag(), self.path, self.cookie_ref().level);
5567
5568 match self.packet {
5569 // Packets that recurse.
5570 Packet::CompressedData(_) | Packet::SEIP(_)
5571 if self.processed =>
5572 {
5573 if self.recursion_depth() as u8
5574 >= self.state.settings.max_recursion_depth
5575 {
5576 t!("Not recursing into the {:?} packet, maximum recursion \
5577 depth ({}) reached.",
5578 self.packet.tag(),
5579 self.state.settings.max_recursion_depth);
5580
5581 // Drop through.
5582 } else if self.content_was_read {
5583 t!("Not recursing into the {:?} packet, some data was \
5584 already read.",
5585 self.packet.tag());
5586
5587 // Drop through.
5588 } else {
5589 let mut last_path = self.last_path;
5590 last_path.clear();
5591 last_path.extend_from_slice(&self.path[..]);
5592
5593 let mut path = self.path;
5594 path.push(0);
5595
5596 match PacketParser::parse(self.reader, self.state,
5597 path.clone())?
5598 {
5599 ParserResult::Success(mut pp) => {
5600 t!("Recursed into the {:?} packet, got a {:?}.",
5601 self.packet.tag(), pp.packet.tag());
5602
5603 pp.state.message_validator.push(
5604 pp.packet.tag(),
5605 pp.packet.version(),
5606 &path);
5607 pp.state.keyring_validator.push(pp.packet.tag());
5608 pp.state.cert_validator.push(pp.packet.tag());
5609
5610 pp.last_path = last_path;
5611
5612 return Ok((self.packet,
5613 PacketParserResult::Some(pp)));
5614 },
5615 ParserResult::EOF(_) => {
5616 return Err(Error::MalformedPacket(
5617 "Container is truncated".into()).into());
5618 },
5619 }
5620 }
5621 },
5622 // Packets that don't recurse.
5623 #[allow(deprecated)]
5624 Packet::Unknown(_) | Packet::Signature(_) | Packet::OnePassSig(_)
5625 | Packet::PublicKey(_) | Packet::PublicSubkey(_)
5626 | Packet::SecretKey(_) | Packet::SecretSubkey(_)
5627 | Packet::Marker(_) | Packet::Trust(_)
5628 | Packet::UserID(_) | Packet::UserAttribute(_)
5629 | Packet::Literal(_) | Packet::PKESK(_) | Packet::SKESK(_)
5630 | Packet::SEIP(_) | Packet::MDC(_)
5631 | Packet::CompressedData(_)
5632 | Packet::Padding(_) => {
5633 // Drop through.
5634 t!("A {:?} packet is not a container, not recursing.",
5635 self.packet.tag());
5636 },
5637 }
5638
5639 // No recursion.
5640 self.next()
5641 }
5642
5643 /// Causes the PacketParser to buffer the packet's contents.
5644 ///
5645 /// The packet's contents can be retrieved using
5646 /// e.g. [`Container::body`]. In general, you should avoid
5647 /// buffering a packet's content and prefer streaming its content
5648 /// unless you are certain that the content is small.
5649 ///
5650 /// [`Container::body`]: crate::packet::Container::body()
5651 ///
5652 /// ```rust
5653 /// # fn main() -> sequoia_openpgp::Result<()> {
5654 /// use sequoia_openpgp as openpgp;
5655 /// use openpgp::Packet;
5656 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
5657 ///
5658 /// // Parse a message.
5659 /// let message_data: &[u8] = // ...
5660 /// # include_bytes!("../tests/data/messages/literal-mode-t-partial-body.pgp");
5661 /// let mut ppr = PacketParser::from_bytes(message_data)?;
5662 /// while let PacketParserResult::Some(mut pp) = ppr {
5663 /// // Process the packet.
5664 ///
5665 /// if let Packet::Literal(_) = pp.packet {
5666 /// assert!(pp.buffer_unread_content()?
5667 /// .starts_with(b"A Cypherpunk's Manifesto"));
5668 /// # assert!(pp.buffer_unread_content()?
5669 /// # .starts_with(b"A Cypherpunk's Manifesto"));
5670 /// if let Packet::Literal(l) = &pp.packet {
5671 /// assert!(l.body().starts_with(b"A Cypherpunk's Manifesto"));
5672 /// assert_eq!(l.body().len(), 5158);
5673 /// } else {
5674 /// unreachable!();
5675 /// }
5676 /// }
5677 ///
5678 /// // Start parsing the next packet, recursing.
5679 /// ppr = pp.recurse()?.1;
5680 /// }
5681 /// # Ok(()) }
5682 /// ```
5683 pub fn buffer_unread_content(&mut self) -> Result<&[u8]> {
5684 let rest = self.steal_eof()?;
5685
5686 fn set_or_extend(rest: Vec<u8>, c: &mut Container, processed: bool)
5687 -> Result<&[u8]> {
5688 if !rest.is_empty() {
5689 let current = match c.body() {
5690 Body::Unprocessed(bytes) => &bytes[..],
5691 Body::Processed(bytes) => &bytes[..],
5692 Body::Structured(packets) if packets.is_empty() => &[][..],
5693 Body::Structured(_) => return Err(Error::InvalidOperation(
5694 "cannot append unread bytes to parsed packets"
5695 .into()).into()),
5696 };
5697 let rest = if !current.is_empty() {
5698 let mut new =
5699 Vec::with_capacity(current.len() + rest.len());
5700 new.extend_from_slice(current);
5701 new.extend_from_slice(&rest);
5702 new
5703 } else {
5704 rest
5705 };
5706
5707 c.set_body(if processed {
5708 Body::Processed(rest)
5709 } else {
5710 Body::Unprocessed(rest)
5711 });
5712 }
5713
5714 match c.body() {
5715 Body::Unprocessed(bytes) => Ok(bytes),
5716 Body::Processed(bytes) => Ok(bytes),
5717 Body::Structured(packets) if packets.is_empty() => Ok(&[][..]),
5718 Body::Structured(_) => Err(Error::InvalidOperation(
5719 "cannot append unread bytes to parsed packets"
5720 .into()).into()),
5721 }
5722 }
5723
5724 match &mut self.packet {
5725 Packet::Literal(p) => set_or_extend(rest, p.container_mut(), false),
5726 Packet::Unknown(p) => set_or_extend(rest, p.container_mut(), false),
5727 Packet::CompressedData(p) =>
5728 set_or_extend(rest, p.container_mut(), self.processed),
5729 Packet::SEIP(SEIP::V1(p)) =>
5730 set_or_extend(rest, p.container_mut(), self.processed),
5731 Packet::SEIP(SEIP::V2(p)) =>
5732 set_or_extend(rest, p.container_mut(), self.processed),
5733 p => {
5734 if !rest.is_empty() {
5735 Err(Error::MalformedPacket(
5736 format!("Unexpected body data for {:?}: {}",
5737 p, crate::fmt::hex::encode_pretty(rest)))
5738 .into())
5739 } else {
5740 Ok(&b""[..])
5741 }
5742 },
5743 }
5744 }
5745
5746 /// Finishes parsing the current packet.
5747 ///
5748 /// By default, this drops any unread content. Use, for instance,
5749 /// [`PacketParserBuilder`] to customize the default behavior.
5750 ///
5751 ///
5752 /// # Examples
5753 ///
5754 /// ```rust
5755 /// # fn main() -> sequoia_openpgp::Result<()> {
5756 /// use sequoia_openpgp as openpgp;
5757 /// use openpgp::Packet;
5758 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
5759 ///
5760 /// // Parse a message.
5761 /// let message_data: &[u8] = // ...
5762 /// # include_bytes!("../tests/data/messages/compressed-data-algo-0.pgp");
5763 /// let mut ppr = PacketParser::from_bytes(message_data)?;
5764 /// while let PacketParserResult::Some(mut pp) = ppr {
5765 /// let p = pp.finish()?;
5766 /// # let _ = p;
5767 ///
5768 /// // Start parsing the next packet, recursing.
5769 /// ppr = pp.recurse()?.1;
5770 /// }
5771 /// # Ok(()) }
5772 // Note: this function is public and may be called multiple times!
5773 pub fn finish(&mut self) -> Result<&Packet> {
5774 let indent = self.recursion_depth();
5775 tracer!(TRACE, "PacketParser::finish", indent);
5776
5777 if self.finished {
5778 return Ok(&self.packet);
5779 }
5780
5781 let recursion_depth = self.recursion_depth();
5782
5783 let unread_content = if self.state.settings.buffer_unread_content {
5784 t!("({:?} at depth {}): buffering {} bytes of unread content",
5785 self.packet.tag(), recursion_depth,
5786 self.data_eof().unwrap_or(&[]).len());
5787
5788 !self.buffer_unread_content()?.is_empty()
5789 } else {
5790 t!("({:?} at depth {}): dropping {} bytes of unread content",
5791 self.packet.tag(), recursion_depth,
5792 self.data_eof().unwrap_or(&[]).len());
5793
5794 self.drop_eof()?
5795 };
5796
5797 if unread_content {
5798 match self.packet.tag() {
5799 Tag::SEIP | Tag::AED | Tag::SED | Tag::CompressedData => {
5800 // We didn't (fully) process a container's content. Add
5801 // this as opaque content to the message validator.
5802 let mut path = self.path().to_vec();
5803 path.push(0);
5804 self.state.message_validator.push_token(
5805 message::Token::OpaqueContent, &path);
5806 }
5807 _ => {},
5808 }
5809 }
5810
5811 if let Some(c) = self.packet.container_mut() {
5812 let h = self.body_hash.take()
5813 .expect("body_hash is Some");
5814 c.set_body_hash(h);
5815 }
5816
5817 self.finished = true;
5818
5819 Ok(&self.packet)
5820 }
5821
5822 /// Hashes content that has been streamed.
5823 fn hash_read_content(&mut self, b: &[u8]) {
5824 if !b.is_empty() {
5825 assert!(self.body_hash.is_some());
5826 if let Some(h) = self.body_hash.as_mut() {
5827 h.update(b);
5828 }
5829 self.content_was_read = true;
5830 }
5831 }
5832
5833 /// Returns a reference to the current packet's header.
5834 ///
5835 /// # Examples
5836 ///
5837 /// ```rust
5838 /// # fn main() -> sequoia_openpgp::Result<()> {
5839 /// use sequoia_openpgp as openpgp;
5840 /// use openpgp::Packet;
5841 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
5842 ///
5843 /// // Parse a message.
5844 /// let message_data: &[u8] = // ...
5845 /// # include_bytes!("../tests/data/messages/compressed-data-algo-0.pgp");
5846 /// let mut ppr = PacketParser::from_bytes(message_data)?;
5847 /// while let PacketParserResult::Some(mut pp) = ppr {
5848 /// pp.header().valid(false)?;
5849 ///
5850 /// // Start parsing the next packet, recursing.
5851 /// ppr = pp.recurse()?.1;
5852 /// }
5853 /// # Ok(()) }
5854 /// ```
5855 pub fn header(&self) -> &Header {
5856 &self.header
5857 }
5858
5859 /// Returns a reference to the map (if any is written).
5860 ///
5861 /// # Examples
5862 ///
5863 /// ```
5864 /// # fn main() -> sequoia_openpgp::Result<()> {
5865 /// use sequoia_openpgp as openpgp;
5866 /// use openpgp::parse::{Parse, PacketParserBuilder};
5867 ///
5868 /// let message_data = b"\xcb\x12t\x00\x00\x00\x00\x00Hello world.";
5869 /// let pp = PacketParserBuilder::from_bytes(message_data)?
5870 /// .map(true) // Enable mapping.
5871 /// .build()?
5872 /// .expect("One packet, not EOF");
5873 /// let map = pp.map().expect("Mapping is enabled");
5874 ///
5875 /// assert_eq!(map.iter().nth(0).unwrap().name(), "CTB");
5876 /// assert_eq!(map.iter().nth(0).unwrap().offset(), 0);
5877 /// assert_eq!(map.iter().nth(0).unwrap().as_bytes(), &[0xcb]);
5878 /// # Ok(()) }
5879 /// ```
5880 pub fn map(&self) -> Option<&map::Map> {
5881 self.map.as_ref()
5882 }
5883
5884 /// Takes the map (if any is written).
5885 ///
5886 /// # Examples
5887 ///
5888 /// ```
5889 /// # fn main() -> sequoia_openpgp::Result<()> {
5890 /// use sequoia_openpgp as openpgp;
5891 /// use openpgp::parse::{Parse, PacketParserBuilder};
5892 ///
5893 /// let message_data = b"\xcb\x12t\x00\x00\x00\x00\x00Hello world.";
5894 /// let mut pp = PacketParserBuilder::from_bytes(message_data)?
5895 /// .map(true) // Enable mapping.
5896 /// .build()?
5897 /// .expect("One packet, not EOF");
5898 /// let map = pp.take_map().expect("Mapping is enabled");
5899 ///
5900 /// assert_eq!(map.iter().nth(0).unwrap().name(), "CTB");
5901 /// assert_eq!(map.iter().nth(0).unwrap().offset(), 0);
5902 /// assert_eq!(map.iter().nth(0).unwrap().as_bytes(), &[0xcb]);
5903 /// # Ok(()) }
5904 /// ```
5905 pub fn take_map(&mut self) -> Option<map::Map> {
5906 self.map.take()
5907 }
5908
5909 /// Checks if we are processing a signed message using the
5910 /// Cleartext Signature Framework.
5911 pub(crate) fn processing_csf_message(&self) -> bool {
5912 Cookie::processing_csf_message(&self.reader)
5913 }
5914}
5915
5916/// This interface allows a caller to read the content of a
5917/// `PacketParser` using the `Read` interface. This is essential to
5918/// supporting streaming operation.
5919///
5920/// Note: it is safe to mix the use of the `std::io::Read` and
5921/// `BufferedReader` interfaces.
5922impl<'a> io::Read for PacketParser<'a> {
5923 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
5924 // The BufferedReader interface takes care of hashing the read
5925 // values.
5926 buffered_reader_generic_read_impl(self, buf)
5927 }
5928}
5929
5930/// This interface allows a caller to read the content of a
5931/// `PacketParser` using the `BufferedReader` interface. This is
5932/// essential to supporting streaming operation.
5933///
5934/// Note: it is safe to mix the use of the `std::io::Read` and
5935/// `BufferedReader` interfaces.
5936impl<'a> BufferedReader<Cookie> for PacketParser<'a> {
5937 fn buffer(&self) -> &[u8] {
5938 self.reader.buffer()
5939 }
5940
5941 fn data(&mut self, amount: usize) -> io::Result<&[u8]> {
5942 // There is no need to set `content_was_read`, because this
5943 // doesn't actually consume any data.
5944 self.reader.data(amount)
5945 }
5946
5947 fn data_hard(&mut self, amount: usize) -> io::Result<&[u8]> {
5948 // There is no need to set `content_was_read`, because this
5949 // doesn't actually consume any data.
5950 self.reader.data_hard(amount)
5951 }
5952
5953 fn data_eof(&mut self) -> io::Result<&[u8]> {
5954 // There is no need to set `content_was_read`, because this
5955 // doesn't actually consume any data.
5956 self.reader.data_eof()
5957 }
5958
5959 fn consume(&mut self, amount: usize) -> &[u8] {
5960 // This is awkward. Juggle mutable references around.
5961 if let Some(mut body_hash) = self.body_hash.take() {
5962 let data = self.data_hard(amount)
5963 .expect("It is an error to consume more than data returns");
5964 body_hash.update(&data[..amount]);
5965 self.body_hash = Some(body_hash);
5966 self.content_was_read |= amount > 0;
5967 } else {
5968 panic!("body_hash is None");
5969 }
5970
5971 self.reader.consume(amount)
5972 }
5973
5974 fn data_consume(&mut self, mut amount: usize) -> io::Result<&[u8]> {
5975 // This is awkward. Juggle mutable references around.
5976 if let Some(mut body_hash) = self.body_hash.take() {
5977 let data = self.data(amount)?;
5978 amount = cmp::min(data.len(), amount);
5979 body_hash.update(&data[..amount]);
5980 self.body_hash = Some(body_hash);
5981 self.content_was_read |= amount > 0;
5982 } else {
5983 panic!("body_hash is None");
5984 }
5985
5986 self.reader.data_consume(amount)
5987 }
5988
5989 fn data_consume_hard(&mut self, amount: usize) -> io::Result<&[u8]> {
5990 // This is awkward. Juggle mutable references around.
5991 if let Some(mut body_hash) = self.body_hash.take() {
5992 let data = self.data_hard(amount)?;
5993 body_hash.update(&data[..amount]);
5994 self.body_hash = Some(body_hash);
5995 self.content_was_read |= amount > 0;
5996 } else {
5997 panic!("body_hash is None");
5998 }
5999
6000 self.reader.data_consume_hard(amount)
6001 }
6002
6003 fn steal(&mut self, amount: usize) -> io::Result<Vec<u8>> {
6004 let v = self.reader.steal(amount)?;
6005 self.hash_read_content(&v);
6006 Ok(v)
6007 }
6008
6009 fn steal_eof(&mut self) -> io::Result<Vec<u8>> {
6010 let v = self.reader.steal_eof()?;
6011 self.hash_read_content(&v);
6012 Ok(v)
6013 }
6014
6015 fn get_mut(&mut self) -> Option<&mut dyn BufferedReader<Cookie>> {
6016 None
6017 }
6018
6019 fn get_ref(&self) -> Option<&dyn BufferedReader<Cookie>> {
6020 None
6021 }
6022
6023 fn into_inner<'b>(self: Box<Self>)
6024 -> Option<Box<dyn BufferedReader<Cookie> + 'b>>
6025 where Self: 'b {
6026 None
6027 }
6028
6029 fn cookie_set(&mut self, cookie: Cookie)
6030 -> Cookie {
6031 self.reader.cookie_set(cookie)
6032 }
6033
6034 fn cookie_ref(&self) -> &Cookie {
6035 self.reader.cookie_ref()
6036 }
6037
6038 fn cookie_mut(&mut self) -> &mut Cookie {
6039 self.reader.cookie_mut()
6040 }
6041}
6042
6043// Check that we can use the read interface to stream the contents of
6044// a packet.
6045#[cfg(feature = "compression-deflate")]
6046#[test]
6047fn packet_parser_reader_interface() {
6048 // We need the Read trait.
6049 use std::io::Read;
6050
6051 let expected = crate::tests::manifesto();
6052
6053 // A message containing a compressed packet that contains a
6054 // literal packet.
6055 let pp = PacketParser::from_bytes(
6056 crate::tests::message("compressed-data-algo-1.pgp")).unwrap().unwrap();
6057
6058 // The message has the form:
6059 //
6060 // [ compressed data [ literal data ] ]
6061 //
6062 // packet is the compressed data packet; ppo is the literal data
6063 // packet.
6064 let packet_depth = pp.recursion_depth();
6065 let (packet, ppr) = pp.recurse().unwrap();
6066 let pp_depth = ppr.as_ref().unwrap().recursion_depth();
6067 if let Packet::CompressedData(_) = packet {
6068 } else {
6069 panic!("Expected a compressed data packet.");
6070 }
6071
6072 let relative_position = pp_depth - packet_depth;
6073 assert_eq!(relative_position, 1);
6074
6075 let mut pp = ppr.unwrap();
6076
6077 if let Packet::Literal(_) = pp.packet {
6078 } else {
6079 panic!("Expected a literal data packet.");
6080 }
6081
6082 // Check that we can read the packet's contents. We do this one
6083 // byte at a time to exercise the cursor implementation.
6084 for i in 0..expected.len() {
6085 let mut buf = [0u8; 1];
6086 let r = pp.read(&mut buf).unwrap();
6087 assert_eq!(r, 1);
6088 assert_eq!(buf[0], expected[i]);
6089 }
6090 // And, now an EOF.
6091 let mut buf = [0u8; 1];
6092 let r = pp.read(&mut buf).unwrap();
6093 assert_eq!(r, 0);
6094
6095 // Make sure we can still get the next packet (which in this case
6096 // is just EOF).
6097 let (packet, ppr) = pp.recurse().unwrap();
6098 assert!(ppr.is_eof());
6099 // Since we read all the data, we expect content to be None.
6100 assert_eq!(packet.unprocessed_body().unwrap().len(), 0);
6101}
6102
6103impl<'a> PacketParser<'a> {
6104 /// Tries to decrypt the current packet.
6105 ///
6106 /// On success, this function pushes one or more readers onto the
6107 /// `PacketParser`'s reader stack, and sets the packet parser's
6108 /// `processed` flag (see [`PacketParser::processed`]).
6109 ///
6110 /// [`PacketParser::processed`]: PacketParser::processed()
6111 ///
6112 /// If this function is called on a packet that does not contain
6113 /// encrypted data, or some of the data was already read, then it
6114 /// returns [`Error::InvalidOperation`].
6115 ///
6116 /// [`Error::InvalidOperation`]: super::Error::InvalidOperation
6117 ///
6118 /// # Examples
6119 ///
6120 /// ```rust
6121 /// # fn main() -> sequoia_openpgp::Result<()> {
6122 /// use sequoia_openpgp as openpgp;
6123 /// use openpgp::Packet;
6124 /// use openpgp::fmt::hex;
6125 /// use openpgp::types::SymmetricAlgorithm;
6126 /// use openpgp::parse::{Parse, PacketParserResult, PacketParser};
6127 ///
6128 /// // Parse an encrypted message.
6129 /// let message_data: &[u8] = // ...
6130 /// # include_bytes!("../tests/data/messages/encrypted-aes256-password-123.pgp");
6131 /// let mut ppr = PacketParser::from_bytes(message_data)?;
6132 /// while let PacketParserResult::Some(mut pp) = ppr {
6133 /// if let Packet::SEIP(_) = pp.packet {
6134 /// pp.decrypt(SymmetricAlgorithm::AES256,
6135 /// &hex::decode("7EF4F08C44F780BEA866961423306166\
6136 /// B8912C43352F3D9617F745E4E3939710")?
6137 /// .into())?;
6138 /// }
6139 ///
6140 /// // Start parsing the next packet, recursing.
6141 /// ppr = pp.recurse()?.1;
6142 /// }
6143 /// # Ok(()) }
6144 /// ```
6145 ///
6146 /// # Security Considerations
6147 ///
6148 /// This functions returns rich errors in case the decryption
6149 /// fails. In combination with certain asymmetric algorithms
6150 /// (RSA), this may lead to compromise of secret key material or
6151 /// (partial) recovery of the message's plain text. See [Section
6152 /// 13 of RFC 9580].
6153 ///
6154 /// [Section 13 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-13
6155 ///
6156 /// DO NOT relay these errors in situations where an attacker can
6157 /// request decryption of messages in an automated fashion. The
6158 /// API of the streaming [`Decryptor`] prevents leaking rich
6159 /// decryption errors.
6160 ///
6161 /// [`Decryptor`]: stream::Decryptor
6162 ///
6163 /// Nevertheless, decrypting messages that do not use an
6164 /// authenticated encryption mode in an automated fashion that
6165 /// relays or leaks information to a third party is NEVER SAFE due
6166 /// to unavoidable format oracles, see [Format Oracles on
6167 /// OpenPGP].
6168 ///
6169 /// [Format Oracles on OpenPGP]: https://www.ssi.gouv.fr/uploads/2015/05/format-Oracles-on-OpenPGP.pdf
6170 pub fn decrypt<A>(&mut self, algo: A, key: &SessionKey)
6171 -> Result<()>
6172 where
6173 A: Into<Option<SymmetricAlgorithm>>,
6174 {
6175 self.decrypt_(algo.into(), key)
6176 }
6177
6178 fn decrypt_(&mut self,
6179 algo: Option<SymmetricAlgorithm>,
6180 key: &SessionKey)
6181 -> Result<()>
6182 {
6183 let indent = self.recursion_depth();
6184 tracer!(TRACE, "PacketParser::decrypt", indent);
6185
6186 if self.content_was_read {
6187 return Err(Error::InvalidOperation(
6188 "Packet's content has already been read.".to_string()).into());
6189 }
6190 if self.processed {
6191 return Err(Error::InvalidOperation(
6192 "Packet not encrypted.".to_string()).into());
6193 }
6194
6195 match self.packet.clone() {
6196 Packet::SEIP(SEIP::V1(_)) => {
6197 use crate::crypto::symmetric::{
6198 BlockCipherMode,
6199 UnpaddingMode,
6200 };
6201
6202 let algo = if let Some(a) = algo {
6203 a
6204 } else {
6205 return Err(Error::InvalidOperation(
6206 "Trying to decrypt a SEIPDv1 packet: \
6207 no symmetric algorithm given".into()).into());
6208 };
6209
6210 if algo.key_size()? != key.len () {
6211 return Err(Error::InvalidOperation(
6212 format!("Bad key size: {} expected: {}",
6213 key.len(), algo.key_size()?)).into());
6214 }
6215
6216 // Get the first blocksize plus two bytes and check
6217 // whether we can decrypt them using the provided key.
6218 // Don't actually consume them in case we can't.
6219 let bl = algo.block_size()?;
6220
6221 {
6222 let cur = buffered_reader::Memory::with_cookie(
6223 &self.data_hard(bl + 2)?[..bl + 2],
6224 Default::default());
6225 let mut dec = InternalDecryptor::new(
6226 algo, BlockCipherMode::CFB, UnpaddingMode::None,
6227 key, None, cur)?;
6228 let mut header = vec![ 0u8; bl + 2 ];
6229 dec.read_exact(&mut header)?;
6230
6231 if !(header[bl - 2] == header[bl]
6232 && header[bl - 1] == header[bl + 1]) {
6233 return Err(Error::InvalidSessionKey(
6234 "Decryption failed".into()).into());
6235 }
6236 }
6237
6238 // Ok, we can decrypt the data. Push a Decryptor and
6239 // a HashedReader on the `BufferedReader` stack.
6240
6241 // This can't fail, because we create a decryptor
6242 // above with the same parameters.
6243 let reader = self.take_reader();
6244 let mut reader = Decryptor::with_cookie(
6245 algo, BlockCipherMode::CFB, UnpaddingMode::None,
6246 key, None, reader, Cookie::default())?;
6247 reader.cookie_mut().level = Some(self.recursion_depth());
6248
6249 t!("Pushing Decryptor, level {:?}.", reader.cookie_ref().level);
6250
6251 // And the hasher.
6252 let mut reader = HashedReader::new(
6253 reader, HashesFor::MDC,
6254 vec![HashingMode::Binary(vec![], HashAlgorithm::SHA1)])?;
6255 reader.cookie_mut().level = Some(self.recursion_depth());
6256
6257 t!("Pushing HashedReader, level {:?}.",
6258 reader.cookie_ref().level);
6259
6260 // A SEIP packet is a container that always ends with
6261 // an MDC packet. But, if the packet preceding the
6262 // MDC packet uses an indeterminate length encoding
6263 // (gpg generates these for compressed data packets,
6264 // for instance), the parser has to detect the EOF and
6265 // be careful to not read any further. Unfortunately,
6266 // our decompressor buffers the data. To stop the
6267 // decompressor from buffering the MDC packet, we use
6268 // a buffered_reader::Reserve. Note: we do this
6269 // unconditionally, since it doesn't otherwise
6270 // interfere with parsing.
6271
6272 // An MDC consists of a 1-byte CTB, a 1-byte length
6273 // encoding, and a 20-byte hash.
6274 let mut reader = buffered_reader::Reserve::with_cookie(
6275 reader, 1 + 1 + 20,
6276 Cookie::new(self.recursion_depth()));
6277 reader.cookie_mut().fake_eof = true;
6278
6279 t!("Pushing buffered_reader::Reserve, level: {}.",
6280 self.recursion_depth());
6281
6282 // Consume the header. This shouldn't fail, because
6283 // it worked when reading the header.
6284 reader.data_consume_hard(bl + 2).unwrap();
6285
6286 self.reader = Box::new(reader);
6287 self.processed = true;
6288
6289 Ok(())
6290 },
6291
6292 Packet::SEIP(SEIP::V2(seip)) => {
6293 let chunk_size =
6294 aead::chunk_size_usize(seip.chunk_size())?;
6295
6296 let schedule = aead::SEIPv2Schedule::new(
6297 key,
6298 seip.symmetric_algo(),
6299 seip.aead(),
6300 chunk_size,
6301 seip.salt())?;
6302
6303 // Read the first chunk and check whether we can
6304 // decrypt it using the provided key. Don't actually
6305 // consume them in case we can't.
6306 {
6307 // We need a bit more than one chunk so that
6308 // `aead::Decryptor` won't see EOF and think that
6309 // it has a partial block and it needs to verify
6310 // the final chunk.
6311 let amount = aead::chunk_size_usize(
6312 seip.chunk_digest_size()?
6313 + seip.aead().digest_size()? as u64)?;
6314
6315 let data = self.data(amount)?;
6316 let cur = buffered_reader::Memory::with_cookie(
6317 &data[..cmp::min(data.len(), amount)],
6318 Default::default());
6319
6320 let dec = aead::InternalDecryptor::new(
6321 seip.symmetric_algo(), seip.aead(), chunk_size,
6322 schedule.clone(),
6323 cur)?;
6324 let mut chunk = Vec::new();
6325 dec.take(seip.chunk_size() as u64).read_to_end(&mut chunk)?;
6326 }
6327
6328 // Ok, we can decrypt the data. Push a Decryptor and
6329 // a HashedReader on the `BufferedReader` stack.
6330
6331 let reader = self.take_reader();
6332 let mut reader = aead::Decryptor::with_cookie(
6333 seip.symmetric_algo(), seip.aead(), chunk_size,
6334 schedule, reader, Cookie::default()).unwrap();
6335 reader.cookie_mut().level = Some(self.recursion_depth());
6336
6337 t!("Pushing aead::Decryptor, level {:?}.",
6338 reader.cookie_ref().level);
6339
6340 self.reader = Box::new(reader);
6341 self.processed = true;
6342
6343 Ok(())
6344 },
6345
6346 _ =>
6347 Err(Error::InvalidOperation(
6348 format!("Can't decrypt {:?} packets.",
6349 self.packet.tag())).into())
6350 }
6351 }
6352}
6353
6354#[cfg(test)]
6355mod test {
6356 use super::*;
6357 use crate::serialize::Serialize;
6358
6359 enum Data<'a> {
6360 File(&'a str),
6361 String(&'a [u8]),
6362 }
6363
6364 impl<'a> Data<'a> {
6365 fn content(&self) -> Vec<u8> {
6366 match self {
6367 Data::File(filename) => crate::tests::message(filename).to_vec(),
6368 Data::String(data) => data.to_vec(),
6369 }
6370 }
6371 }
6372
6373 struct DecryptTest<'a> {
6374 filename: &'a str,
6375 algo: SymmetricAlgorithm,
6376 aead_algo: Option<AEADAlgorithm>,
6377 key_hex: &'a str,
6378 plaintext: Data<'a>,
6379 paths: &'a[ (Tag, &'a[ usize ] ) ],
6380 }
6381 const DECRYPT_TESTS: &[DecryptTest] = &[
6382 // Messages with a relatively simple structure:
6383 //
6384 // [ SKESK SEIP [ Literal MDC ] ].
6385 //
6386 // And simple length encodings (no indeterminate length
6387 // encodings).
6388 DecryptTest {
6389 filename: "encrypted-aes256-password-123.pgp",
6390 algo: SymmetricAlgorithm::AES256,
6391 aead_algo: None,
6392 key_hex: "7EF4F08C44F780BEA866961423306166B8912C43352F3D9617F745E4E3939710",
6393 plaintext: Data::File("a-cypherpunks-manifesto.txt"),
6394 paths: &[
6395 (Tag::SKESK, &[ 0 ]),
6396 (Tag::SEIP, &[ 1 ]),
6397 (Tag::Literal, &[ 1, 0 ]),
6398 (Tag::MDC, &[ 1, 1 ]),
6399 ],
6400 },
6401 DecryptTest {
6402 filename: "encrypted-aes192-password-123456.pgp",
6403 algo: SymmetricAlgorithm::AES192,
6404 aead_algo: None,
6405 key_hex: "B2F747F207EFF198A6C826F1D398DE037986218ED468DB61",
6406 plaintext: Data::File("a-cypherpunks-manifesto.txt"),
6407 paths: &[
6408 (Tag::SKESK, &[ 0 ]),
6409 (Tag::SEIP, &[ 1 ]),
6410 (Tag::Literal, &[ 1, 0 ]),
6411 (Tag::MDC, &[ 1, 1 ]),
6412 ],
6413 },
6414 DecryptTest {
6415 filename: "encrypted-aes128-password-123456789.pgp",
6416 algo: SymmetricAlgorithm::AES128,
6417 aead_algo: None,
6418 key_hex: "AC0553096429260B4A90B1CEC842D6A0",
6419 plaintext: Data::File("a-cypherpunks-manifesto.txt"),
6420 paths: &[
6421 (Tag::SKESK, &[ 0 ]),
6422 (Tag::SEIP, &[ 1 ]),
6423 (Tag::Literal, &[ 1, 0 ]),
6424 (Tag::MDC, &[ 1, 1 ]),
6425 ],
6426 },
6427
6428 // Created using:
6429 //
6430 // gpg --compression-algo none \
6431 // --s2k-digest-algo sha256 \
6432 // --cipher-algo camellia256 \
6433 // --s2k-cipher-algo camellia256 \
6434 // --encrypt --symmetric \
6435 // -o encrypted-camellia256-password-123.pgp \
6436 // a-cypherpunks-manifesto.txt
6437 DecryptTest {
6438 filename: "encrypted-camellia256-password-123.pgp",
6439 algo: SymmetricAlgorithm::Camellia256,
6440 aead_algo: None,
6441 key_hex: "FC9644B500B9D0540880CB44B40F8C89\
6442 A7D817F2EF7EF9DA0D34A574377E300A",
6443 plaintext: Data::File("a-cypherpunks-manifesto.txt"),
6444 paths: &[
6445 (Tag::SKESK, &[ 0 ]),
6446 (Tag::SEIP, &[ 1 ]),
6447 (Tag::Literal, &[ 1, 0 ]),
6448 (Tag::MDC, &[ 1, 1 ]),
6449 ],
6450 },
6451 DecryptTest {
6452 filename: "encrypted-camellia192-password-123.pgp",
6453 algo: SymmetricAlgorithm::Camellia192,
6454 aead_algo: None,
6455 key_hex: "EC941DB1C5F4D3605E3F3C10B30888DA3287256E55CC978B",
6456 plaintext: Data::File("a-cypherpunks-manifesto.txt"),
6457 paths: &[
6458 (Tag::SKESK, &[ 0 ]),
6459 (Tag::SEIP, &[ 1 ]),
6460 (Tag::Literal, &[ 1, 0 ]),
6461 (Tag::MDC, &[ 1, 1 ]),
6462 ],
6463 },
6464 DecryptTest {
6465 filename: "encrypted-camellia128-password-123.pgp",
6466 algo: SymmetricAlgorithm::Camellia128,
6467 aead_algo: None,
6468 key_hex: "E1CF87BF2E030CC89CBC0F03EC2B7DF5",
6469 plaintext: Data::File("a-cypherpunks-manifesto.txt"),
6470 paths: &[
6471 (Tag::SKESK, &[ 0 ]),
6472 (Tag::SEIP, &[ 1 ]),
6473 (Tag::Literal, &[ 1, 0 ]),
6474 (Tag::MDC, &[ 1, 1 ]),
6475 ],
6476 },
6477
6478 DecryptTest {
6479 filename: "encrypted-twofish-password-red-fish-blue-fish.pgp",
6480 algo: SymmetricAlgorithm::Twofish,
6481 aead_algo: None,
6482 key_hex: "96AFE1EDFA7C9CB7E8B23484C718015E5159CFA268594180D4DB68B2543393CB",
6483 plaintext: Data::File("a-cypherpunks-manifesto.txt"),
6484 paths: &[
6485 (Tag::SKESK, &[ 0 ]),
6486 (Tag::SEIP, &[ 1 ]),
6487 (Tag::Literal, &[ 1, 0 ]),
6488 (Tag::MDC, &[ 1, 1 ]),
6489 ],
6490 },
6491
6492 // More complex messages. In particular, some of these
6493 // messages include compressed data packets, and some are
6494 // signed. But what makes these particularly complex is the
6495 // use of an indeterminate length encoding, which checks the
6496 // buffered_reader::Reserve hack.
6497 #[cfg(feature = "compression-deflate")]
6498 DecryptTest {
6499 filename: "seip/msg-compression-not-signed-password-123.pgp",
6500 algo: SymmetricAlgorithm::AES128,
6501 aead_algo: None,
6502 key_hex: "86A8C1C7961F55A3BE181A990D0ABB2A",
6503 plaintext: Data::String(b"compression, not signed\n"),
6504 paths: &[
6505 (Tag::SKESK, &[ 0 ]),
6506 (Tag::SEIP, &[ 1 ]),
6507 (Tag::CompressedData, &[ 1, 0 ]),
6508 (Tag::Literal, &[ 1, 0, 0 ]),
6509 (Tag::MDC, &[ 1, 1 ]),
6510 ],
6511 },
6512 #[cfg(feature = "compression-deflate")]
6513 DecryptTest {
6514 filename: "seip/msg-compression-signed-password-123.pgp",
6515 algo: SymmetricAlgorithm::AES128,
6516 aead_algo: None,
6517 key_hex: "1B195CD35CAD4A99D9399B4CDA4CDA4E",
6518 plaintext: Data::String(b"compression, signed\n"),
6519 paths: &[
6520 (Tag::SKESK, &[ 0 ]),
6521 (Tag::SEIP, &[ 1 ]),
6522 (Tag::CompressedData, &[ 1, 0 ]),
6523 (Tag::OnePassSig, &[ 1, 0, 0 ]),
6524 (Tag::Literal, &[ 1, 0, 1 ]),
6525 (Tag::Signature, &[ 1, 0, 2 ]),
6526 (Tag::MDC, &[ 1, 1 ]),
6527 ],
6528 },
6529 DecryptTest {
6530 filename: "seip/msg-no-compression-not-signed-password-123.pgp",
6531 algo: SymmetricAlgorithm::AES128,
6532 aead_algo: None,
6533 key_hex: "AFB43B83A4B9D971E4B4A4C53749076A",
6534 plaintext: Data::String(b"no compression, not signed\n"),
6535 paths: &[
6536 (Tag::SKESK, &[ 0 ]),
6537 (Tag::SEIP, &[ 1 ]),
6538 (Tag::Literal, &[ 1, 0 ]),
6539 (Tag::MDC, &[ 1, 1 ]),
6540 ],
6541 },
6542 DecryptTest {
6543 filename: "seip/msg-no-compression-signed-password-123.pgp",
6544 algo: SymmetricAlgorithm::AES128,
6545 aead_algo: None,
6546 key_hex: "9D5DB92F77F0E4A356EE53813EF2C3DC",
6547 plaintext: Data::String(b"no compression, signed\n"),
6548 paths: &[
6549 (Tag::SKESK, &[ 0 ]),
6550 (Tag::SEIP, &[ 1 ]),
6551 (Tag::OnePassSig, &[ 1, 0 ]),
6552 (Tag::Literal, &[ 1, 1 ]),
6553 (Tag::Signature, &[ 1, 2 ]),
6554 (Tag::MDC, &[ 1, 3 ]),
6555 ],
6556 },
6557 ];
6558
6559 // Consume packets until we get to one in `keep`.
6560 fn consume_until<'a>(mut ppr: PacketParserResult<'a>,
6561 ignore_first: bool, keep: &[Tag], skip: &[Tag])
6562 -> PacketParserResult<'a>
6563 {
6564 if ignore_first {
6565 ppr = ppr.unwrap().recurse().unwrap().1;
6566 }
6567
6568 while let PacketParserResult::Some(pp) = ppr {
6569 let tag = pp.packet.tag();
6570 for t in keep.iter() {
6571 if *t == tag {
6572 return PacketParserResult::Some(pp);
6573 }
6574 }
6575
6576 let mut ok = false;
6577 for t in skip.iter() {
6578 if *t == tag {
6579 ok = true;
6580 }
6581 }
6582 if !ok {
6583 panic!("Packet not in keep ({:?}) or skip ({:?}) set: {:?}",
6584 keep, skip, pp.packet);
6585 }
6586
6587 ppr = pp.recurse().unwrap().1;
6588 }
6589 ppr
6590 }
6591
6592 #[test]
6593 fn decrypt_test() {
6594 decrypt_test_common(false);
6595 }
6596
6597 #[test]
6598 fn decrypt_test_stream() {
6599 decrypt_test_common(true);
6600 }
6601
6602 #[allow(deprecated)]
6603 fn decrypt_test_common(stream: bool) {
6604 for test in DECRYPT_TESTS.iter() {
6605 if !test.algo.is_supported() {
6606 eprintln!("Algorithm {} unsupported, skipping", test.algo);
6607 continue;
6608 }
6609
6610 if let Some(aead_algo) = test.aead_algo {
6611 if !aead_algo.is_supported() {
6612 eprintln!("AEAD algorithm {} unsupported by
6613 selected crypto backend, skipping", aead_algo);
6614 continue;
6615 }
6616 }
6617
6618 eprintln!("Decrypting {}, streaming content: {}",
6619 test.filename, stream);
6620
6621 let ppr = PacketParserBuilder::from_bytes(
6622 crate::tests::message(test.filename)).unwrap()
6623 .buffer_unread_content()
6624 .build()
6625 .expect(&format!("Error reading {}", test.filename)[..]);
6626
6627 let mut ppr = consume_until(
6628 ppr, false, &[ Tag::SEIP, Tag::AED ][..],
6629 &[ Tag::SKESK, Tag::PKESK ][..] );
6630 if let PacketParserResult::Some(ref mut pp) = ppr {
6631 let key = crate::fmt::from_hex(test.key_hex, false)
6632 .unwrap().into();
6633
6634 pp.decrypt(Some(test.algo), &key).unwrap();
6635 } else {
6636 panic!("Expected a SEIP packet. Got: {:?}", ppr);
6637 }
6638
6639 let mut ppr = consume_until(
6640 ppr, true, &[ Tag::Literal ][..],
6641 &[ Tag::OnePassSig, Tag::CompressedData ][..]);
6642 if let PacketParserResult::Some(ref mut pp) = ppr {
6643 if stream {
6644 let mut body = Vec::new();
6645 loop {
6646 let mut b = [0];
6647 if pp.read(&mut b).unwrap() == 0 {
6648 break;
6649 }
6650 body.push(b[0]);
6651 }
6652
6653 assert_eq!(&body[..],
6654 &test.plaintext.content()[..],
6655 "{:?}", pp.packet);
6656 } else {
6657 pp.buffer_unread_content().unwrap();
6658 if let Packet::Literal(l) = &pp.packet {
6659 assert_eq!(l.body(), &test.plaintext.content()[..],
6660 "{:?}", pp.packet);
6661 } else {
6662 panic!("Expected literal, got: {:?}", pp.packet);
6663 }
6664 }
6665 } else {
6666 panic!("Expected a Literal packet. Got: {:?}", ppr);
6667 }
6668
6669 let ppr = consume_until(
6670 ppr, true, &[ Tag::MDC ][..], &[ Tag::Signature ][..]);
6671 if let PacketParserResult::Some(
6672 PacketParser { packet: Packet::MDC(ref mdc), .. }) = ppr
6673 {
6674 assert_eq!(mdc.computed_digest(), mdc.digest(),
6675 "MDC doesn't match");
6676 }
6677
6678 if ppr.is_eof() {
6679 // AED packets don't have an MDC packet.
6680 continue;
6681 }
6682 let ppr = consume_until(
6683 ppr, true, &[][..], &[][..]);
6684 assert!(ppr.is_eof());
6685 }
6686 }
6687
6688 #[test]
6689 fn message_validator() {
6690 for marker in 0..4 {
6691 let marker_before = marker & 1 > 0;
6692 let marker_after = marker & 2 > 0;
6693
6694 for test in DECRYPT_TESTS.iter() {
6695 if !test.algo.is_supported() {
6696 eprintln!("Algorithm {} unsupported, skipping", test.algo);
6697 continue;
6698 }
6699
6700 if let Some(aead_algo) = test.aead_algo {
6701 if !aead_algo.is_supported() {
6702 eprintln!("AEAD algorithm {} unsupported by
6703 selected crypto backend, skipping", aead_algo);
6704 continue;
6705 }
6706 }
6707
6708 let mut buf = Vec::new();
6709 if marker_before {
6710 Packet::Marker(Default::default()).serialize(&mut buf).unwrap();
6711 }
6712 buf.extend_from_slice(crate::tests::message(test.filename));
6713 if marker_after {
6714 Packet::Marker(Default::default()).serialize(&mut buf).unwrap();
6715 }
6716
6717 let mut ppr = PacketParserBuilder::from_bytes(&buf)
6718 .unwrap()
6719 .build()
6720 .expect(&format!("Error reading {}", test.filename)[..]);
6721
6722 // Make sure we actually decrypted...
6723 let mut saw_literal = false;
6724 while let PacketParserResult::Some(mut pp) = ppr {
6725 pp.possible_message().unwrap();
6726
6727 match pp.packet {
6728 Packet::SEIP(_) => {
6729 let key = crate::fmt::from_hex(test.key_hex, false)
6730 .unwrap().into();
6731 pp.decrypt(Some(test.algo), &key).unwrap();
6732 },
6733 Packet::Literal(_) => {
6734 assert!(! saw_literal);
6735 saw_literal = true;
6736 },
6737 _ => {},
6738 }
6739
6740 ppr = pp.recurse().unwrap().1;
6741 }
6742 assert!(saw_literal);
6743 if let PacketParserResult::EOF(eof) = ppr {
6744 eof.is_message().unwrap();
6745 } else {
6746 unreachable!();
6747 }
6748 }
6749 }
6750 }
6751
6752 #[test]
6753 fn keyring_validator() {
6754 for marker in 0..4 {
6755 let marker_before = marker & 1 > 0;
6756 let marker_after = marker & 2 > 0;
6757
6758 for test in &["testy.pgp",
6759 "lutz.pgp",
6760 "testy-new.pgp",
6761 "neal.pgp"]
6762 {
6763 let mut buf = Vec::new();
6764 if marker_before {
6765 Packet::Marker(Default::default()).serialize(&mut buf).unwrap();
6766 }
6767 buf.extend_from_slice(crate::tests::key("testy.pgp"));
6768 buf.extend_from_slice(crate::tests::key(test));
6769 if marker_after {
6770 Packet::Marker(Default::default()).serialize(&mut buf).unwrap();
6771 }
6772
6773 let mut ppr = PacketParserBuilder::from_bytes(&buf)
6774 .unwrap()
6775 .build()
6776 .expect(&format!("Error reading {:?}", test));
6777
6778 while let PacketParserResult::Some(pp) = ppr {
6779 assert!(pp.possible_keyring().is_ok());
6780 ppr = pp.recurse().unwrap().1;
6781 }
6782 if let PacketParserResult::EOF(eof) = ppr {
6783 assert!(eof.is_keyring().is_ok());
6784 assert!(eof.is_cert().is_err());
6785 } else {
6786 unreachable!();
6787 }
6788 }
6789 }
6790 }
6791
6792 #[test]
6793 fn cert_validator() {
6794 for marker in 0..4 {
6795 let marker_before = marker & 1 > 0;
6796 let marker_after = marker & 2 > 0;
6797
6798 for test in &["testy.pgp",
6799 "lutz.pgp",
6800 "testy-new.pgp",
6801 "neal.pgp"]
6802 {
6803 let mut buf = Vec::new();
6804 if marker_before {
6805 Packet::Marker(Default::default()).serialize(&mut buf).unwrap();
6806 }
6807 buf.extend_from_slice(crate::tests::key(test));
6808 if marker_after {
6809 Packet::Marker(Default::default()).serialize(&mut buf).unwrap();
6810 }
6811
6812 let mut ppr = PacketParserBuilder::from_bytes(&buf)
6813 .unwrap()
6814 .build()
6815 .expect(&format!("Error reading {:?}", test));
6816
6817 while let PacketParserResult::Some(pp) = ppr {
6818 assert!(pp.possible_keyring().is_ok());
6819 assert!(pp.possible_cert().is_ok());
6820 ppr = pp.recurse().unwrap().1;
6821 }
6822 if let PacketParserResult::EOF(eof) = ppr {
6823 assert!(eof.is_keyring().is_ok());
6824 assert!(eof.is_cert().is_ok());
6825 } else {
6826 unreachable!();
6827 }
6828 }
6829 }
6830 }
6831
6832 // If we don't decrypt the SEIP packet, it shows up as opaque
6833 // content.
6834 #[test]
6835 fn message_validator_opaque_content() {
6836 for test in DECRYPT_TESTS.iter() {
6837 let mut ppr = PacketParserBuilder::from_bytes(
6838 crate::tests::message(test.filename)).unwrap()
6839 .build()
6840 .expect(&format!("Error reading {}", test.filename)[..]);
6841
6842 let mut saw_literal = false;
6843 while let PacketParserResult::Some(pp) = ppr {
6844 assert!(pp.possible_message().is_ok());
6845
6846 match pp.packet {
6847 Packet::Literal(_) => {
6848 assert!(! saw_literal);
6849 saw_literal = true;
6850 },
6851 _ => {},
6852 }
6853
6854 ppr = pp.recurse().unwrap().1;
6855 }
6856 assert!(! saw_literal);
6857 if let PacketParserResult::EOF(eof) = ppr {
6858 eprintln!("eof: {:?}; message: {:?}", eof, eof.is_message());
6859 assert!(eof.is_message().is_ok());
6860 } else {
6861 unreachable!();
6862 }
6863 }
6864 }
6865
6866 #[test]
6867 fn path() {
6868 for test in DECRYPT_TESTS.iter() {
6869 if !test.algo.is_supported() {
6870 eprintln!("Algorithm {} unsupported, skipping", test.algo);
6871 continue;
6872 }
6873
6874 if let Some(aead_algo) = test.aead_algo {
6875 if !aead_algo.is_supported() {
6876 eprintln!("AEAD algorithm {} unsupported, skipping", aead_algo);
6877 continue;
6878 }
6879 }
6880
6881 eprintln!("Decrypting {}", test.filename);
6882
6883 let mut ppr = PacketParserBuilder::from_bytes(
6884 crate::tests::message(test.filename)).unwrap()
6885 .build()
6886 .expect(&format!("Error reading {}", test.filename)[..]);
6887
6888 let mut last_path = vec![];
6889
6890 let mut paths = test.paths.to_vec();
6891 // We pop from the end.
6892 paths.reverse();
6893
6894 while let PacketParserResult::Some(mut pp) = ppr {
6895 let path = paths.pop().expect("Message longer than expect");
6896 assert_eq!(path.0, pp.packet.tag());
6897 assert_eq!(path.1, pp.path());
6898
6899 assert_eq!(last_path, pp.last_path());
6900 last_path = pp.path.to_vec();
6901
6902 eprintln!(" {}: {:?}", pp.packet.tag(), pp.path());
6903
6904 match pp.packet {
6905 Packet::SEIP(_) => {
6906 let key = crate::fmt::from_hex(test.key_hex, false)
6907 .unwrap().into();
6908
6909 pp.decrypt(test.algo, &key).unwrap();
6910 }
6911 _ => (),
6912 }
6913
6914 ppr = pp.recurse().unwrap().1;
6915 }
6916 paths.reverse();
6917 assert_eq!(paths.len(), 0,
6918 "Message shorter than expected (expecting: {:?})",
6919 paths);
6920
6921 if let PacketParserResult::EOF(eof) = ppr {
6922 assert_eq!(last_path, eof.last_path());
6923 } else {
6924 panic!("Expect an EOF");
6925 }
6926 }
6927 }
6928
6929 #[test]
6930 fn corrupted_cert() {
6931 use crate::armor::{Reader, ReaderMode, Kind};
6932
6933 // The following Cert is corrupted about a third the way
6934 // through. Make sure we can recover.
6935 let mut ppr = PacketParser::from_reader(
6936 Reader::from_bytes(crate::tests::key("corrupted.pgp"),
6937 ReaderMode::Tolerant(Some(Kind::PublicKey))))
6938 .unwrap();
6939
6940 let mut sigs = 0;
6941 let mut subkeys = 0;
6942 let mut userids = 0;
6943 let mut uas = 0;
6944 let mut unknown = 0;
6945 while let PacketParserResult::Some(pp) = ppr {
6946 match pp.packet {
6947 Packet::Signature(_) => sigs += 1,
6948 Packet::PublicSubkey(_) => subkeys += 1,
6949 Packet::UserID(_) => userids += 1,
6950 Packet::UserAttribute(_) => uas += 1,
6951 Packet::Unknown(ref p) => {
6952 dbg!(p);
6953 unknown += 1;
6954 },
6955 _ => (),
6956 }
6957
6958 ppr = pp.next().unwrap().1;
6959 }
6960
6961 assert_eq!(sigs, 53);
6962 assert_eq!(subkeys, 3);
6963 assert_eq!(userids, 5);
6964 assert_eq!(uas, 0);
6965 assert_eq!(unknown, 2);
6966 }
6967
6968 #[test]
6969 fn junk_prefix() {
6970 // Make sure we can read the first packet.
6971 let msg = crate::tests::message("sig.pgp");
6972
6973 let ppr = PacketParserBuilder::from_bytes(msg).unwrap()
6974 .dearmor(packet_parser_builder::Dearmor::Disabled)
6975 .build();
6976 assert_match!(Ok(PacketParserResult::Some(ref _pp)) = ppr);
6977
6978
6979 // Prepend an invalid byte and make sure we fail. Note: we
6980 // have a mechanism to skip corruption, however, that is only
6981 // activated once we've seen a good packet. This test checks
6982 // that we don't try to recover.
6983 let mut msg2 = Vec::new();
6984 msg2.push(0);
6985 msg2.extend_from_slice(msg);
6986
6987 let ppr = PacketParserBuilder::from_bytes(&msg2[..]).unwrap()
6988 .dearmor(packet_parser_builder::Dearmor::Disabled)
6989 .build();
6990 assert_match!(Err(_) = ppr);
6991 }
6992
6993 /// Issue #141.
6994 #[test]
6995 fn truncated_packet() {
6996 for msg in &[crate::tests::message("literal-mode-b.pgp"),
6997 crate::tests::message("literal-mode-t-partial-body.pgp"),
6998 ] {
6999 // Make sure we can read the first packet.
7000 let ppr = PacketParserBuilder::from_bytes(msg).unwrap()
7001 .dearmor(packet_parser_builder::Dearmor::Disabled)
7002 .build();
7003 assert_match!(Ok(PacketParserResult::Some(ref _pp)) = ppr);
7004
7005 // Now truncate the packet.
7006 let msg2 = &msg[..msg.len() - 1];
7007 let ppr = PacketParserBuilder::from_bytes(msg2).unwrap()
7008 .dearmor(packet_parser_builder::Dearmor::Disabled)
7009 .build().unwrap();
7010 if let PacketParserResult::Some(pp) = ppr {
7011 let err = pp.next().err().unwrap();
7012 assert_match!(Some(&Error::MalformedPacket(_))
7013 = err.downcast_ref());
7014 } else {
7015 panic!("No packet!?");
7016 }
7017 }
7018 }
7019
7020 #[test]
7021 fn max_packet_size() {
7022 use crate::serialize::Serialize;
7023 let uid = Packet::UserID("foobar".into());
7024 let mut buf = Vec::new();
7025 uid.serialize(&mut buf).unwrap();
7026
7027 // Make sure we can read it.
7028 let ppr = PacketParserBuilder::from_bytes(&buf).unwrap()
7029 .build().unwrap();
7030 if let PacketParserResult::Some(pp) = ppr {
7031 assert_eq!(Packet::UserID("foobar".into()), pp.packet);
7032 } else {
7033 panic!("failed to parse userid");
7034 }
7035
7036 // But if we set the maximum packet size too low, it is parsed
7037 // into an unknown packet.
7038 let ppr = PacketParserBuilder::from_bytes(&buf).unwrap()
7039 .max_packet_size(5)
7040 .build().unwrap();
7041 if let PacketParserResult::Some(pp) = ppr {
7042 if let Packet::Unknown(ref u) = pp.packet {
7043 assert_eq!(u.tag(), Tag::UserID);
7044 assert_match!(Some(&Error::PacketTooLarge(_, _, _))
7045 = u.error().downcast_ref());
7046 } else {
7047 panic!("expected an unknown packet, got {:?}", pp.packet);
7048 }
7049 } else {
7050 panic!("failed to parse userid");
7051 }
7052
7053 }
7054
7055 /// We erroneously assumed that when BufferedReader::next() is
7056 /// called, a SEIP container be opaque and hence there cannot be a
7057 /// buffered_reader::Reserve on the stack with Cookie::fake_eof
7058 /// set. But, we could simply call BufferedReader::next() after
7059 /// the SEIP packet is decrypted, or buffer a SEIP packet's body,
7060 /// then call BufferedReader::recurse(), which falls back to
7061 /// BufferedReader::next() because some data has been read.
7062 #[test]
7063 fn issue_455() -> Result<()> {
7064 let sk: SessionKey =
7065 crate::fmt::hex::decode("3E99593760EE241488462BAFAE4FA268\
7066 260B14B82D310D196DCEC82FD4F67678")?.into();
7067 let algo = SymmetricAlgorithm::AES256;
7068
7069 // Decrypt, then call BufferedReader::next().
7070 eprintln!("Decrypt, then next():\n");
7071 let mut ppr = PacketParser::from_bytes(
7072 crate::tests::message("encrypted-to-testy.pgp"))?;
7073 while let PacketParserResult::Some(mut pp) = ppr {
7074 match &pp.packet {
7075 Packet::SEIP(_) => {
7076 pp.decrypt(algo, &sk)?;
7077 },
7078 _ => (),
7079 }
7080 // Used to trigger the assertion failure on the SEIP
7081 // packet:
7082 ppr = pp.next()?.1;
7083 }
7084
7085 // Decrypt, buffer, then call BufferedReader::recurse().
7086 eprintln!("\nDecrypt, buffer, then recurse():\n");
7087 let mut ppr = PacketParser::from_bytes(
7088 crate::tests::message("encrypted-to-testy.pgp"))?;
7089 while let PacketParserResult::Some(mut pp) = ppr {
7090 match &pp.packet {
7091 Packet::SEIP(_) => {
7092 pp.decrypt(algo, &sk)?;
7093 pp.buffer_unread_content()?;
7094 },
7095 _ => (),
7096 }
7097 // Used to trigger the assertion failure on the SEIP
7098 // packet:
7099 ppr = pp.recurse()?.1;
7100 }
7101 Ok(())
7102 }
7103
7104 /// Crash in the AED parser due to missing chunk size validation.
7105 #[test]
7106 fn issue_514() -> Result<()> {
7107 let data = &[212, 43, 1, 0, 0, 125, 212, 0, 10, 10, 10];
7108 let ppr = PacketParser::from_bytes(&data)?;
7109 let packet = &ppr.unwrap().packet;
7110 if let Packet::Unknown(_) = packet {
7111 Ok(())
7112 } else {
7113 panic!("expected unknown packet, got: {:?}", packet);
7114 }
7115 }
7116
7117 /// Malformed subpackets must not cause a hard parsing error.
7118 #[test]
7119 fn malformed_embedded_signature() -> Result<()> {
7120 let ppr = PacketParser::from_bytes(
7121 crate::tests::file("edge-cases/malformed-embedded-sig.pgp"))?;
7122 let packet = &ppr.unwrap().packet;
7123 if let Packet::Unknown(_) = packet {
7124 Ok(())
7125 } else {
7126 panic!("expected unknown packet, got: {:?}", packet);
7127 }
7128 }
7129
7130 /// Malformed notation names must not cause hard parsing errors.
7131 #[test]
7132 fn malformed_notation_name() -> Result<()> {
7133 let ppr = PacketParser::from_bytes(
7134 crate::tests::file("edge-cases/malformed-notation-name.pgp"))?;
7135 let packet = &ppr.unwrap().packet;
7136 if let Packet::Unknown(_) = packet {
7137 Ok(())
7138 } else {
7139 panic!("expected unknown packet, got: {:?}", packet);
7140 }
7141 }
7142
7143 /// Checks that the content hash is correctly computed whether
7144 /// the content has been (fully) read.
7145 #[test]
7146 fn issue_537() -> Result<()> {
7147 // Buffer unread content.
7148 let ppr0 = PacketParserBuilder::from_bytes(
7149 crate::tests::message("literal-mode-b.pgp"))?
7150 .buffer_unread_content()
7151 .build()?;
7152 let pp0 = ppr0.unwrap();
7153 let (packet0, _) = pp0.recurse()?;
7154
7155 // Drop unread content.
7156 let ppr1 = PacketParser::from_bytes(
7157 crate::tests::message("literal-mode-b.pgp"))?;
7158 let pp1 = ppr1.unwrap();
7159 let (packet1, _) = pp1.recurse()?;
7160
7161 // Read content.
7162 let ppr2 = PacketParser::from_bytes(
7163 crate::tests::message("literal-mode-b.pgp"))?;
7164 let mut pp2 = ppr2.unwrap();
7165 io::copy(&mut pp2, &mut io::sink())?;
7166 let (packet2, _) = pp2.recurse()?;
7167
7168 // Partially read content.
7169 let ppr3 = PacketParser::from_bytes(
7170 crate::tests::message("literal-mode-b.pgp"))?;
7171 let mut pp3 = ppr3.unwrap();
7172 let mut buf = [0];
7173 let nread = pp3.read(&mut buf)?;
7174 assert_eq!(buf.len(), nread);
7175 let (packet3, _) = pp3.recurse()?;
7176
7177 assert_eq!(packet0, packet1);
7178 assert_eq!(packet1, packet2);
7179 assert_eq!(packet2, packet3);
7180 Ok(())
7181 }
7182
7183 /// Checks that newlines are properly normalized when verifying
7184 /// text signatures.
7185 #[test]
7186 fn issue_530_verifying() -> Result<()> {
7187 use std::io::Write;
7188 use crate::*;
7189 use crate::packet::signature;
7190 use crate::serialize::stream::{Message, Signer};
7191
7192 use crate::policy::StandardPolicy;
7193 use crate::{Result, Cert};
7194 use crate::parse::Parse;
7195 use crate::parse::stream::*;
7196
7197 let data = b"one\r\ntwo\r\nthree";
7198
7199 let p = &StandardPolicy::new();
7200 let cert: Cert =
7201 Cert::from_bytes(crate::tests::key("testy-new-private.pgp"))?;
7202 let signing_keypair = cert.keys().secret()
7203 .with_policy(p, None).alive().revoked(false).for_signing().next().unwrap()
7204 .key().clone().into_keypair()?;
7205 let mut signature = vec![];
7206 {
7207 let message = Message::new(&mut signature);
7208 let mut message = Signer::with_template(
7209 message, signing_keypair,
7210 signature::SignatureBuilder::new(SignatureType::Text)
7211 )?.detached().build()?;
7212 message.write_all(data)?;
7213 message.finalize()?;
7214 }
7215
7216 struct Helper {}
7217 impl VerificationHelper for Helper {
7218 fn get_certs(&mut self, _ids: &[KeyHandle]) -> Result<Vec<Cert>> {
7219 Ok(vec![Cert::from_bytes(crate::tests::key("testy-new.pgp"))?])
7220 }
7221 fn check(&mut self, structure: MessageStructure) -> Result<()> {
7222 for (i, layer) in structure.iter().enumerate() {
7223 assert_eq!(i, 0);
7224 if let MessageLayer::SignatureGroup { results } = layer {
7225 assert_eq!(results.len(), 1);
7226 results[0].as_ref().unwrap();
7227 assert!(results[0].is_ok());
7228 return Ok(());
7229 } else {
7230 unreachable!();
7231 }
7232 }
7233 unreachable!()
7234 }
7235 }
7236
7237 let h = Helper {};
7238 let mut v = DetachedVerifierBuilder::from_bytes(&signature)?
7239 .with_policy(p, None, h)?;
7240
7241 for data in &[
7242 &b"one\r\ntwo\r\nthree"[..], // dos
7243 b"one\ntwo\nthree", // unix
7244 b"one\ntwo\r\nthree", // mixed
7245 b"one\r\ntwo\nthree",
7246 b"one\rtwo\rthree", // classic mac
7247 ] {
7248 v.verify_bytes(data)?;
7249 }
7250
7251 Ok(())
7252 }
7253
7254 /// Tests for a panic in the SKESK parser.
7255 #[test]
7256 fn issue_588() -> Result<()> {
7257 let data = vec![0x8c, 0x34, 0x05, 0x12, 0x02, 0x00, 0xaf, 0x0d,
7258 0xff, 0xff, 0x65];
7259 let _ = PacketParser::from_bytes(&data);
7260 Ok(())
7261 }
7262
7263 /// Tests for a panic in the packet parser.
7264 #[test]
7265 fn packet_parser_on_mangled_cert() -> Result<()> {
7266 // The armored input cert is mangled. Currently, Sequoia
7267 // doesn't grok the mangled armor, but it should not panic.
7268 let mut ppr = match PacketParser::from_bytes(
7269 crate::tests::key("bobs-cert-badly-mangled.asc")) {
7270 Ok(ppr) => ppr,
7271 Err(_) => return Ok(()),
7272 };
7273 while let PacketParserResult::Some(pp) = ppr {
7274 dbg!(&pp.packet);
7275 if let Ok((_, tmp)) = pp.recurse() {
7276 ppr = tmp;
7277 } else {
7278 break;
7279 }
7280 }
7281 Ok(())
7282 }
7283
7284 // Issue 967.
7285 #[test]
7286 fn packet_before_junk_emitted() -> Result<()> {
7287 let bytes = crate::tests::key("testy-new.pgp");
7288
7289 let mut ppr = match PacketParser::from_bytes(bytes) {
7290 Ok(ppr) => ppr,
7291 Err(_) => panic!("valid"),
7292 };
7293 let mut packets_ok = Vec::new();
7294 while let PacketParserResult::Some(pp) = ppr {
7295 if let Ok((packet, tmp)) = pp.recurse() {
7296 packets_ok.push(packet);
7297 ppr = tmp;
7298 } else {
7299 break;
7300 }
7301 }
7302
7303 let mut bytes = bytes.to_vec();
7304 // Add some junk.
7305 bytes.push(0);
7306 let mut ppr = match PacketParser::from_bytes(&bytes[..]) {
7307 Ok(ppr) => ppr,
7308 Err(_) => panic!("valid"),
7309 };
7310 let mut packets_mangled = Vec::new();
7311 while let PacketParserResult::Some(pp) = ppr {
7312 if let Ok((packet, tmp)) = pp.recurse() {
7313 packets_mangled.push(packet);
7314 ppr = tmp;
7315 } else {
7316 break;
7317 }
7318 }
7319
7320 assert_eq!(packets_ok.len(), packets_mangled.len());
7321 assert_eq!(packets_ok, packets_mangled);
7322
7323 Ok(())
7324 }
7325
7326 /// Tests for a panic in the packet parser.
7327 fn parse_message(message: &str) {
7328 eprintln!("parsing {:?}", message);
7329 let mut ppr = match PacketParser::from_bytes(message) {
7330 Ok(ppr) => ppr,
7331 Err(_) => return,
7332 };
7333 while let PacketParserResult::Some(pp) = ppr {
7334 dbg!(&pp.packet);
7335 if let Ok((_, tmp)) = pp.recurse() {
7336 ppr = tmp;
7337 } else {
7338 break;
7339 }
7340 }
7341 }
7342
7343 /// Tests issue 1005.
7344 #[test]
7345 fn panic_on_short_zip() {
7346 parse_message("-----BEGIN PGP SIGNATURE-----
7347
7348owGjAA0=
7349zXvj
7350-----END PGP SIGNATURE-----
7351");
7352 }
7353
7354 /// Tests issue 957.
7355 #[test]
7356 fn panic_on_malformed_armor() {
7357 parse_message("-----BEGIN PGP MESSAGE-----
7358
7359heLBX8Pq0kUBwQz2iFAzRwOdgTBvH5KsDU9lmE
7360
7361-----END PGP MESSAGE-----
7362");
7363 }
7364
7365 /// Tests issue 1024.
7366 #[test]
7367 // XXX: While lenient parsing seemed like the right thing to do,
7368 // this breaks equality and round-tripping: we normalize the
7369 // non-canonical encoding, so two distinct wire representations
7370 // are folded into one in-core representation.
7371 #[ignore]
7372 fn parse_secret_with_leading_zeros() -> Result<()> {
7373 crate::Cert::from_bytes(
7374 crate::tests::key("leading-zeros-private.pgp"))?
7375 .primary_key().key().clone()
7376 .parts_into_secret()?
7377 .decrypt_secret(&("hunter22"[..]).into())?
7378 .into_keypair()?;
7379 Ok(())
7380 }
7381
7382 /// Tests that junk pseudo-packets have a proper map when
7383 /// buffering is turned on.
7384 #[test]
7385 #[cfg(feature = "compression-deflate")]
7386 fn parse_junk_with_mapping() -> Result<()> {
7387 let silly = "-----BEGIN PGP MESSAGE-----
7388
7389yCsBO81bKqlfklugX5yRX5qTopuXX6KbWpFZXKJXUlGSetb4dXm+gYFBCRcA
7390=IHpt
7391-----END PGP MESSAGE-----
7392";
7393 let mut ppr = PacketParserBuilder::from_bytes(silly)?
7394 .map(true).buffer_unread_content().build()?;
7395 let mut i = 0;
7396 while let PacketParserResult::Some(pp) = ppr {
7397 assert!(pp.map().unwrap().iter().count() > 0);
7398 for f in pp.map().unwrap().iter() {
7399 eprintln!("{:?}", f);
7400 }
7401 ppr = match pp.recurse() {
7402 Ok((_, ppr)) => {
7403 i += 1;
7404 ppr
7405 },
7406 Err(_) => {
7407 // The third packet is a junk pseudo-packet, and
7408 // recursing will fail.
7409 assert_eq!(i, 2);
7410 break;
7411 },
7412 }
7413 }
7414 Ok(())
7415 }
7416
7417 /// Tests for issue 1095, parsing a secret key packet with an
7418 /// unknown S2K mechanism.
7419 #[test]
7420 fn key_unknown_s2k() -> Result<()> {
7421 let mut ppr = PacketParser::from_bytes(
7422 crate::tests::key("hardware-backed-secret.pgp"))?;
7423 let mut i = 0;
7424 while let PacketParserResult::Some(pp) = ppr {
7425 if i == 0 {
7426 assert!(matches!(&pp.packet, Packet::SecretKey(_)));
7427 }
7428 if i == 3 {
7429 assert!(matches!(&pp.packet, Packet::SecretSubkey(_)));
7430 }
7431
7432 // Make sure it roundtrips.
7433 let p = &pp.packet;
7434 let v = p.to_vec()?;
7435 let q = Packet::from_bytes(&v)?;
7436 assert_eq!(p, &q);
7437
7438 ppr = pp.recurse()?.1;
7439 i += 1;
7440 }
7441 Ok(())
7442 }
7443}