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