1 //! OpenPGP data types and associated machinery.
2 //!
3 //! This crate aims to provide a complete implementation of OpenPGP as
4 //! defined by [RFC 4880] as well as some extensions (e.g., [RFC
5 //! 6637], which describes ECC cryptography for OpenPGP.  This
6 //! includes support for unbuffered message processing.
7 //!
8 //! A few features that the OpenPGP community considers to be
9 //! deprecated (e.g., version 3 compatibility) have been left out.  We
10 //! have also updated some OpenPGP defaults to avoid foot guns (e.g.,
11 //! we selected modern algorithm defaults).  If some functionality is
12 //! missing, please file a bug report.
13 //!
14 //! A non-goal of this crate is support for any sort of high-level,
15 //! bolted-on functionality.  For instance, [RFC 4880] does not define
16 //! trust models, such as the web of trust, direct trust, or TOFU.
17 //! Neither does this crate.  [RFC 4880] does provide some mechanisms
18 //! for creating trust models (specifically, UserID certifications),
19 //! and this crate does expose those mechanisms.
20 //!
21 //! We also try hard to avoid dictating how OpenPGP should be used.
22 //! This doesn't mean that we don't have opinions about how OpenPGP
23 //! should be used in a number of common scenarios (for instance,
24 //! message validation).  But, in this crate, we refrain from
25 //! expressing those opinions; we expose an opinionated, high-level
26 //! interface in the [sequoia-core] and related crates.  In our
27 //! opinion, you should generally use those crates instead of this
28 //! one.
29 //!
30 //! [RFC 4880]: https://tools.ietf.org/html/rfc4880
31 //! [RFC 6637]: https://tools.ietf.org/html/rfc6637
32 //! [sequoia-core]: ../sequoia_core
33 //!
34 //! # Experimental Features
35 //!
36 //! This crate implements functionality from [RFC 4880bis], notably
37 //! AEAD encryption containers.  As of this writing, this RFC is still
38 //! a draft and the syntax or semantic defined in it may change or go
39 //! away.  Therefore, all related functionality may change and
40 //! artifacts created using this functionality may not be usable in
41 //! the future.  Do not use it for things other than experiments.
42 //!
43 //! [RFC 4880bis]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08
44 
45 #![warn(missing_docs)]
46 
47 #[cfg(test)]
48 #[macro_use]
49 extern crate quickcheck;
50 
51 #[macro_use]
52 extern crate lazy_static;
53 
54 #[macro_use]
55 mod macros;
56 
57 // On debug builds, Vec<u8>::truncate is very, very slow.  For
58 // instance, running the decrypt_test_stream test takes 51 seconds on
59 // my (Neal's) computer using Vec<u8>::truncate and <0.1 seconds using
60 // `unsafe { v.set_len(len); }`.
61 //
62 // The issue is that the compiler calls drop on every element that is
63 // dropped, even though a u8 doesn't have a drop implementation.  The
64 // compiler optimizes this away at high optimization levels, but those
65 // levels make debugging harder.
vec_truncate(v: &mut Vec<u8>, len: usize)66 fn vec_truncate(v: &mut Vec<u8>, len: usize) {
67     if cfg!(debug_assertions) {
68         if len < v.len() {
69             unsafe { v.set_len(len); }
70         }
71     } else {
72         v.truncate(len);
73     }
74 }
75 
76 /// Like `drop(Vec<u8>::drain(..prefix_len))`, but fast in debug
77 /// builds.
vec_drain_prefix(v: &mut Vec<u8>, prefix_len: usize)78 fn vec_drain_prefix(v: &mut Vec<u8>, prefix_len: usize) {
79     if cfg!(debug_assertions) {
80         // Panic like v.drain(..prefix_len).
81         assert!(prefix_len <= v.len(), "prefix len {} > vector len {}",
82                 prefix_len, v.len());
83         let new_len = v.len() - prefix_len;
84         unsafe {
85             std::ptr::copy(v[prefix_len..].as_ptr(),
86                            v[..].as_mut_ptr(),
87                            new_len);
88         }
89         vec_truncate(v, new_len);
90     } else {
91         v.drain(..prefix_len);
92     }
93 }
94 
95 // Like assert!, but checks a pattern.
96 //
97 //   assert_match!(Some(_) = x);
98 //
99 // Note: For modules to see this macro, we need to define it before we
100 // declare the modules.
101 #[allow(unused_macros)]
102 macro_rules! assert_match {
103     ( $error: pat = $expr:expr, $fmt:expr, $($pargs:expr),* ) => {{
104         let x = $expr;
105         if let $error = x {
106             /* Pass.  */
107         } else {
108             let extra = format!($fmt, $($pargs),*);
109             panic!("Expected {}, got {:?}{}{}",
110                    stringify!($error), x,
111                    if $fmt.len() > 0 { ": " } else { "." }, extra);
112         }
113     }};
114     ( $error: pat = $expr: expr, $fmt:expr ) => {
115         assert_match!($error = $expr, $fmt, );
116     };
117     ( $error: pat = $expr: expr ) => {
118         assert_match!($error = $expr, "");
119     };
120 }
121 
122 #[macro_use]
123 pub mod armor;
124 pub mod fmt;
125 pub mod crypto;
126 
127 pub mod packet;
128 pub use packet::Packet;
129 use crate::packet::key;
130 
131 pub mod parse;
132 
133 pub mod cert;
134 pub use cert::Cert;
135 pub mod serialize;
136 
137 mod packet_pile;
138 pub use packet_pile::PacketPile;
139 pub mod message;
140 pub use message::Message;
141 
142 pub mod types;
143 use crate::types::{
144     PublicKeyAlgorithm,
145     SymmetricAlgorithm,
146     HashAlgorithm,
147     SignatureType,
148 };
149 
150 mod fingerprint;
151 pub use fingerprint::Fingerprint;
152 mod keyid;
153 pub use keyid::KeyID;
154 mod keyhandle;
155 pub use keyhandle::KeyHandle;
156 pub mod policy;
157 
158 pub(crate) mod utils;
159 
160 #[cfg(test)]
161 mod tests;
162 
163 /// Returns a timestamp for the tests.
164 ///
165 /// The time is chosen to that the subkeys in
166 /// openpgp/tests/data/keys/neal.pgp are not expired.
167 #[cfg(test)]
frozen_time() -> std::time::SystemTime168 fn frozen_time() -> std::time::SystemTime {
169     crate::types::Timestamp::from(1554542220 - 1).into()
170 }
171 
172 /// The version of this crate.
173 pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
174 
175 /// Crate result specialization.
176 pub type Result<T> = ::std::result::Result<T, anyhow::Error>;
177 
178 /// Errors used in this crate.
179 ///
180 /// Note: This enum cannot be exhaustively matched to allow future
181 /// extensions.
182 #[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
183 pub enum Error {
184     /// Invalid argument.
185     #[error("Invalid argument: {0}")]
186     InvalidArgument(String),
187 
188     /// Invalid operation.
189     #[error("Invalid operation: {0}")]
190     InvalidOperation(String),
191 
192     /// A malformed packet.
193     #[error("Malformed packet: {0}")]
194     MalformedPacket(String),
195 
196     /// Packet size exceeds the configured limit.
197     #[error("{} Packet ({} bytes) exceeds limit of {} bytes",
198            _0, _1, _2)]
199     PacketTooLarge(packet::Tag, u32, u32),
200 
201     /// Unsupported packet type.
202     #[error("Unsupported packet type.  Tag: {0}")]
203     UnsupportedPacketType(packet::Tag),
204 
205     /// Unsupported hash algorithm identifier.
206     #[error("Unsupported hash algorithm: {0}")]
207     UnsupportedHashAlgorithm(HashAlgorithm),
208 
209     /// Unsupported public key algorithm identifier.
210     #[error("Unsupported public key algorithm: {0}")]
211     UnsupportedPublicKeyAlgorithm(PublicKeyAlgorithm),
212 
213     /// Unsupported elliptic curve ASN.1 OID.
214     #[error("Unsupported elliptic curve: {0}")]
215     UnsupportedEllipticCurve(types::Curve),
216 
217     /// Unsupported symmetric key algorithm.
218     #[error("Unsupported symmetric algorithm: {0}")]
219     UnsupportedSymmetricAlgorithm(SymmetricAlgorithm),
220 
221     /// Unsupported AEAD algorithm.
222     #[error("Unsupported AEAD algorithm: {0}")]
223     UnsupportedAEADAlgorithm(types::AEADAlgorithm),
224 
225     /// Unsupported Compression algorithm.
226     #[error("Unsupported Compression algorithm: {0}")]
227     UnsupportedCompressionAlgorithm(types::CompressionAlgorithm),
228 
229     /// Unsupported signature type.
230     #[error("Unsupported signature type: {0}")]
231     UnsupportedSignatureType(SignatureType),
232 
233     /// Invalid password.
234     #[error("Invalid password")]
235     InvalidPassword,
236 
237     /// Invalid session key.
238     #[error("Invalid session key: {0}")]
239     InvalidSessionKey(String),
240 
241     /// Missing session key.
242     #[error("Missing session key: {0}")]
243     MissingSessionKey(String),
244 
245     /// Malformed MPI.
246     #[error("Malformed MPI: {0}")]
247     MalformedMPI(String),
248 
249     /// Bad signature.
250     #[error("Bad signature: {0}")]
251     BadSignature(String),
252 
253     /// Message has been manipulated.
254     #[error("Message has been manipulated")]
255     ManipulatedMessage,
256 
257     /// Malformed message.
258     #[error("Malformed Message: {0}")]
259     MalformedMessage(String),
260 
261     /// Malformed certificate.
262     #[error("Malformed Cert: {0}")]
263     MalformedCert(String),
264 
265     /// Unsupported Cert.
266     ///
267     /// This usually occurs, because the primary key is in an
268     /// unsupported format.  In particular, Sequoia does not support
269     /// version 3 keys.
270     #[error("Unsupported Cert: {0}")]
271     UnsupportedCert(String),
272 
273     /// Index out of range.
274     #[error("Index out of range")]
275     IndexOutOfRange,
276 
277     /// Expired.
278     #[error("Expired on {}", crate::fmt::time(.0))]
279     Expired(std::time::SystemTime),
280 
281     /// Not yet live.
282     #[error("Not live until {}", crate::fmt::time(.0))]
283     NotYetLive(std::time::SystemTime),
284 
285     /// No binding signature.
286     #[error("No binding signature at time {}", crate::fmt::time(.0))]
287     NoBindingSignature(std::time::SystemTime),
288 
289     /// Invalid key.
290     #[error("Invalid key: {0:?}")]
291     InvalidKey(String),
292 
293     /// The operation is not allowed, because it violates the policy.
294     ///
295     /// The optional time is the time at which the operation was
296     /// determined to no longer be secure.
297     #[error("{0} is not considered secure{}",
298             .1.as_ref().map(|t| format!(" since {}", crate::fmt::time(t)))
299             .unwrap_or("".into()))]
300     PolicyViolation(String, Option<std::time::SystemTime>),
301 
302     /// This marks this enum as non-exhaustive.  Do not use this
303     /// variant.
304     #[doc(hidden)] #[error("__Nonexhaustive")] __Nonexhaustive,
305 }
306