sequoia_openpgp/crypto/
mod.rs

1//! Cryptographic primitives.
2//!
3//! This module contains cryptographic primitives as defined and used
4//! by OpenPGP.  It abstracts over the cryptographic library chosen at
5//! compile time.  Most of the time, it will not be necessary to
6//! explicitly use types from this module directly, but they are used
7//! in the API (e.g. [`Password`]).  Advanced users may use these
8//! primitives to provide custom extensions to OpenPGP.
9//!
10//!
11//! # Common Operations
12//!
13//!  - *Converting a string to a [`Password`]*: Use [`Password::from`].
14//!  - *Create a session key*: Use [`SessionKey::new`].
15//!  - *Use secret keys*: See the [`KeyPair` example].
16//!
17//!   [`Password::from`]: std::convert::From
18//!   [`SessionKey::new`]: SessionKey::new()
19//!   [`KeyPair` example]: KeyPair#examples
20
21use std::cmp::Ordering;
22use std::ops::{Deref, DerefMut};
23use std::fmt;
24use std::borrow::Cow;
25
26use crate::{
27    Error,
28    Result,
29};
30
31pub mod aead;
32mod asymmetric;
33pub use self::asymmetric::{Signer, Decryptor, KeyPair};
34pub(crate) mod backend;
35pub mod ecdh;
36pub mod hash;
37mod key;
38pub mod mem;
39pub mod mpi;
40mod s2k;
41pub use s2k::S2K;
42pub mod symmetric;
43mod types;
44pub use types::{
45    AEADAlgorithm,
46    Curve,
47    HashAlgorithm,
48    PublicKeyAlgorithm,
49    SymmetricAlgorithm,
50};
51#[cfg(test)]
52mod tests;
53
54/// Returns a short, human-readable description of the backend.
55///
56/// This starts with the name of the backend, possibly a version, and
57/// any optional features that are available.  This is meant for
58/// inclusion in version strings to improve bug reports.
59pub fn backend() -> String {
60    use backend::interface::Backend;
61    backend::Backend::backend()
62}
63
64/// Fills the given buffer with random data.
65///
66/// Fills the given buffer with random data produced by a
67/// cryptographically secure pseudorandom number generator (CSPRNG).
68/// The output may be used as session keys or to derive long-term
69/// cryptographic keys from.  However, to create session keys,
70/// consider using [`SessionKey::new`].
71///
72///   [`SessionKey::new`]: crate::crypto::SessionKey::new()
73pub fn random<B: AsMut<[u8]>>(mut buf: B) -> Result<()> {
74    use backend::interface::Backend;
75    backend::Backend::random(buf.as_mut())
76}
77
78/// Holds a session key.
79///
80/// The session key is cleared when dropped.  Sequoia uses this type
81/// to ensure that session keys are not left in memory returned to the
82/// allocator.
83///
84/// Session keys can be generated using [`SessionKey::new`], or
85/// converted from various types using [`From`].
86///
87///   [`SessionKey::new`]: SessionKey::new()
88///   [`From`]: std::convert::From
89#[derive(Clone, PartialEq, Eq)]
90pub struct SessionKey(mem::Protected);
91assert_send_and_sync!(SessionKey);
92
93impl SessionKey {
94    /// Creates a new session key.
95    ///
96    /// Creates a new session key `size` bytes in length initialized
97    /// using a strong cryptographic number generator.
98    ///
99    /// # Examples
100    ///
101    /// This creates a session key and encrypts it for a given
102    /// recipient key producing a [`PKESK`] packet.
103    ///
104    ///   [`PKESK`]: crate::packet::PKESK
105    ///
106    /// ```
107    /// # fn main() -> sequoia_openpgp::Result<()> {
108    /// use sequoia_openpgp as openpgp;
109    /// use openpgp::types::{Curve, SymmetricAlgorithm};
110    /// use openpgp::crypto::SessionKey;
111    /// use openpgp::packet::prelude::*;
112    ///
113    /// let cipher = SymmetricAlgorithm::AES256;
114    /// let sk = SessionKey::new(cipher.key_size()?)?;
115    ///
116    /// let key: Key<key::SecretParts, key::UnspecifiedRole> =
117    ///     Key6::generate_ecc(false, Curve::Cv25519)?.into();
118    ///
119    /// let pkesk: PKESK =
120    ///     PKESK3::for_recipient(cipher, &sk, &key)?.into();
121    /// # Ok(()) }
122    /// ```
123    pub fn new(size: usize) -> Result<Self> {
124        let mut sk: mem::Protected = vec![0; size].into();
125        random(&mut sk)?;
126        Ok(Self(sk))
127    }
128
129    /// Returns a reference to the inner [`mem::Protected`].
130    pub fn as_protected(&self) -> &mem::Protected {
131        &self.0
132    }
133}
134
135impl Deref for SessionKey {
136    type Target = [u8];
137
138    fn deref(&self) -> &Self::Target {
139        &self.0
140    }
141}
142
143impl AsRef<[u8]> for SessionKey {
144    fn as_ref(&self) -> &[u8] {
145        &self.0
146    }
147}
148
149impl DerefMut for SessionKey {
150    fn deref_mut(&mut self) -> &mut [u8] {
151        &mut self.0
152    }
153}
154
155impl AsMut<[u8]> for SessionKey {
156    fn as_mut(&mut self) -> &mut [u8] {
157        &mut self.0
158    }
159}
160
161impl From<mem::Protected> for SessionKey {
162    fn from(v: mem::Protected) -> Self {
163        SessionKey(v)
164    }
165}
166
167impl From<Vec<u8>> for SessionKey {
168    fn from(v: Vec<u8>) -> Self {
169        SessionKey(v.into())
170    }
171}
172
173impl From<Box<[u8]>> for SessionKey {
174    fn from(v: Box<[u8]>) -> Self {
175        SessionKey(v.into())
176    }
177}
178
179impl From<&[u8]> for SessionKey {
180    fn from(v: &[u8]) -> Self {
181        Vec::from(v).into()
182    }
183}
184
185impl fmt::Debug for SessionKey {
186    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187        write!(f, "SessionKey ({:?})", self.0)
188    }
189}
190
191/// Holds a password.
192///
193/// `Password`s can be converted from various types using [`From`].
194/// The password is encrypted in memory and only decrypted on demand.
195/// See [`mem::Encrypted`] for details.
196///
197///   [`From`]: std::convert::From
198///
199/// # Examples
200///
201/// ```
202/// use sequoia_openpgp as openpgp;
203/// use openpgp::crypto::Password;
204///
205/// // Convert from a &str.
206/// let p: Password = "hunter2".into();
207///
208/// // Convert from a &[u8].
209/// let p: Password = b"hunter2"[..].into();
210///
211/// // Convert from a String.
212/// let p: Password = String::from("hunter2").into();
213///
214/// // ...
215/// ```
216#[derive(Clone, PartialEq, Eq)]
217pub struct Password(mem::Encrypted);
218assert_send_and_sync!(Password);
219
220impl From<Vec<u8>> for Password {
221    fn from(v: Vec<u8>) -> Self {
222        Password(mem::Encrypted::new(v.into())
223                 .expect("encrypting memory failed"))
224    }
225}
226
227impl From<Box<[u8]>> for Password {
228    fn from(v: Box<[u8]>) -> Self {
229        Password(mem::Encrypted::new(v.into())
230                 .expect("encrypting memory failed"))
231    }
232}
233
234impl From<String> for Password {
235    fn from(v: String) -> Self {
236        v.into_bytes().into()
237    }
238}
239
240impl<'a> From<&'a str> for Password {
241    fn from(v: &'a str) -> Self {
242        v.to_owned().into()
243    }
244}
245
246impl From<&[u8]> for Password {
247    fn from(v: &[u8]) -> Self {
248        Vec::from(v).into()
249    }
250}
251
252impl fmt::Debug for Password {
253    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
254        if cfg!(debug_assertions) {
255            self.map(|p| write!(f, "Password({:?})", p))
256        } else {
257            f.write_str("Password(<Encrypted>)")
258        }
259    }
260}
261
262impl Password {
263    /// Maps the given function over the password.
264    ///
265    /// The password is stored encrypted in memory.  This function
266    /// temporarily decrypts it for the given function to use.
267    ///
268    /// # Examples
269    ///
270    /// ```
271    /// use sequoia_openpgp as openpgp;
272    /// use openpgp::crypto::Password;
273    ///
274    /// let p: Password = "hunter2".into();
275    /// p.map(|p| assert_eq!(p.as_ref(), &b"hunter2"[..]));
276    /// ```
277    pub fn map<F, T>(&self, fun: F) -> T
278        where F: FnMut(&mem::Protected) -> T
279    {
280        self.0.map(fun)
281    }
282}
283
284/// Returns the value zero-padded to the given length.
285///
286/// Some encodings strip leading zero-bytes.  This function adds them
287/// back, if necessary.  If the size exceeds `to`, an error is
288/// returned.
289pub(crate) fn pad(value: &[u8], to: usize) -> Result<Cow<'_, [u8]>>
290{
291    match value.len().cmp(&to) {
292        Ordering::Equal => Ok(Cow::Borrowed(value)),
293        Ordering::Less => {
294            let missing = to - value.len();
295            let mut v = vec![0; to];
296            v[missing..].copy_from_slice(value);
297            Ok(Cow::Owned(v))
298        }
299        Ordering::Greater => {
300            Err(Error::InvalidOperation(
301                format!("Input value is longer than expected: {} > {}",
302                        value.len(), to)).into())
303        }
304    }
305}
306
307/// Returns the value zero-padded to the given length.
308///
309/// Some encodings strip leading zero-bytes.  This function adds them
310/// back, if necessary.  If the size exceeds `to`, the value is
311/// returned as-is.
312#[allow(dead_code)]
313pub(crate) fn pad_at_least(value: &[u8], to: usize) -> Cow<'_, [u8]>
314{
315    pad(value, to).unwrap_or(Cow::Borrowed(value))
316}
317
318/// Returns the value zero-padded or truncated to the given length.
319///
320/// Some encodings strip leading zero-bytes.  This function adds them
321/// back, if necessary.  If the size exceeds `to`, the value is
322/// silently truncated.
323#[allow(dead_code)]
324pub(crate) fn pad_truncating(value: &[u8], to: usize) -> Cow<'_, [u8]>
325{
326    if value.len() == to {
327        Cow::Borrowed(value)
328    } else {
329        let missing = to.saturating_sub(value.len());
330        let limit = value.len().min(to);
331        let mut v = vec![0; to];
332        v[missing..].copy_from_slice(&value[..limit]);
333        Cow::Owned(v)
334    }
335}
336
337/// Compares two arbitrary-sized big-endian integers.
338///
339/// Note that the tempting `a < b` doesn't work: it computes the
340/// lexicographical order, so that `[2] > [1, 2]`, whereas we want
341/// `[2] < [1, 2]`.
342pub(crate) fn raw_bigint_cmp(mut a: &[u8], mut b: &[u8]) -> Ordering {
343    // First, trim leading zeros.
344    while a.get(0) == Some(&0) {
345        a = &a[1..];
346    }
347
348    while b.get(0) == Some(&0) {
349        b = &b[1..];
350    }
351
352    // Then, compare their length.  Shorter integers are also smaller.
353    a.len().cmp(&b.len())
354        // Finally, if their length is equal, do a lexicographical
355        // comparison.
356        .then_with(|| a.cmp(b))
357}
358
359/// Given the secret prime values `p` and `q`, returns the pair of
360/// primes so that the smaller one comes first.
361///
362/// Section 5.5.3 of RFC4880 demands that `p < q`.  This function can
363/// be used to order `p` and `q` accordingly.
364#[allow(dead_code)]
365pub(crate) fn rsa_sort_raw_pq<'a>(p: &'a [u8], q: &'a [u8])
366                                  -> (&'a [u8], &'a [u8])
367{
368    match raw_bigint_cmp(p, q) {
369        Ordering::Less => (p, q),
370        Ordering::Equal => (p, q),
371        Ordering::Greater => (q, p),
372    }
373}