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