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