logo
Expand description

Packet parsing infrastructure.

OpenPGP defines a binary representation suitable for storing and communicating OpenPGP data structures (see Section 3 ff. of RFC 4880). Parsing is the process of interpreting the binary representation.

An OpenPGP stream represents a sequence of packets. Some of the packets contain other packets. These so called containers include encrypted data packets (the SED and SEIP packets), and compressed data packets. This structure results in a tree, which is laid out in depth-first order.

OpenPGP defines objects consisting of several packets with a specific structure. These objects are Messages, Certs and sequences of Certs (“keyrings”). Verifying the structure of these objects is also an act of parsing.

This crate provides several interfaces to parse OpenPGP data. They fall in roughly three categories:

  • First, most data structures in this crate implement the Parse trait. It provides a uniform interface to parse data from an io::Reader, a file identified by its Path, or simply a byte slice.

  • Second, there is a convenient interface to decrypt and/or verify OpenPGP messages in a streaming fashion. Encrypted and/or signed data is read using the Parse interface, and decrypted and/or verified data can be read using io::Read.

  • Finally, we expose the low-level PacketParser, allowing fine-grained control over the parsing.

The choice of interface depends on the specific use case. In many circumstances, OpenPGP data can not be trusted until it has been authenticated. Therefore, it has to be treated as attacker controlled data, and it has to be treated with great care. See the section Security Considerations below.

Common Operations

Data Structures and Interfaces

This crate provides several interfaces for parsing OpenPGP streams, ordered from the most convenient but least flexible to the least convenient but most flexible:

  • The streaming Verifier, DetachedVerifier, and Decryptor are the most convenient way to parse OpenPGP messages.

  • The PacketPile::from_file (and related methods) is the most convenient, but least flexible way to parse an arbitrary sequence of OpenPGP packets. Whereas a PacketPileParser allows the caller to determine how to handle individual packets, the PacketPile::from_file parses the whole stream at once and returns a PacketPile.

  • The PacketPileParser abstraction builds on the PacketParser abstraction and provides a similar interface. However, after each iteration, the PacketPileParser adds the packet to a PacketPile, which is returned once the packets are completely processed.

    This interface should only be used if the caller actually wants a PacketPile; if the OpenPGP stream is parsed in place, then using a PacketParser is better.

    This interface should only be used if the caller is certain that the parsed stream will fit in memory.

  • The PacketParser abstraction produces one packet at a time. What is done with those packets is completely up to the caller.

The behavior of the PacketParser can be configured using a PacketParserBuilder.

ASCII armored data

The PacketParser will by default automatically detect and remove any ASCII armor encoding (see Section 6 of RFC 4880). This automatism can be disabled and fine-tuned using PacketParserBuilder::dearmor.

Security Considerations

In general, OpenPGP data must be considered attacker controlled and thus treated with great care. Even though we use a memory-safe language, there are several aspects to be aware of:

  • OpenPGP messages may be compressed. Therefore, one cannot predict the uncompressed size of a message by looking at the compressed representation. Operations that parse OpenPGP streams and buffer the packet data (like using the PacketPile’s Parse interface) are inherently unsafe and must only be used on trusted data.

  • The authenticity of an OpenPGP message can only be checked once it has been fully processed. Therefore, the plaintext must be buffered and not be trusted until the whole message is processed and signatures and/or ciphertext integrity are verified. On the other hand, buffering an unbounded amount of data is problematic and can lead to out-of-memory situations resulting in denial of service. The streaming message processing interfaces address this problem by buffering an configurable amount of data before releasing any data to the caller, and only revert to streaming unverified data if the message exceeds the buffer. See DEFAULT_BUFFER_SIZE for more information.

  • Not all parts of signed-then-encrypted OpenPGP messages are authenticated. Notably, all packets outside the encryption container (any PKESK and SKESK packets, as well as the encryption container itself), the Literal packet’s headers, as well as parts of the Signature are not covered by the signatures.

  • Ciphertext integrity is provided by the SEIP packet’s MDC mechanism, but the integrity can only be checked after decrypting the whole container. Proper authenticated encryption is provided by the AED container, but as of this writing it is not standardized.

Re-exports

Modules

Packet maps.

Streaming decryption and verification.

Structs

Private state used by the PacketParser.

A low-level OpenPGP message parser.

A builder for configuring a PacketParser.

Information about the stream of packets parsed by the PacketParser.

Parses an OpenPGP stream with the convenience of PacketPile::from_file and the flexibility of a PacketParser.

Enums

Controls transparent stripping of ASCII armor when parsing.

The result of parsing a packet.

Constants

The default maximum size of non-container packets.

The default amount of acceptable nesting.

Traits

Parsing of packets and related structures.