• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Public/private key processing.
2 //!
3 //! Asymmetric public key algorithms solve the problem of establishing and sharing
4 //! secret keys to securely send and receive messages.
5 //! This system uses a pair of keys: a public key, which can be freely
6 //! distributed, and a private key, which is kept to oneself. An entity may
7 //! encrypt information using a user's public key. The encrypted information can
8 //! only be deciphered using that user's private key.
9 //!
10 //! This module offers support for five popular algorithms:
11 //!
12 //! * RSA
13 //!
14 //! * DSA
15 //!
16 //! * Diffie-Hellman
17 //!
18 //! * Elliptic Curves
19 //!
20 //! * HMAC
21 //!
22 //! These algorithms rely on hard mathematical problems - namely integer factorization,
23 //! discrete logarithms, and elliptic curve relationships - that currently do not
24 //! yield efficient solutions. This property ensures the security of these
25 //! cryptographic algorithms.
26 //!
27 //! # Example
28 //!
29 //! Generate a 2048-bit RSA public/private key pair and print the public key.
30 //!
31 //! ```rust
32 //! use openssl::rsa::Rsa;
33 //! use openssl::pkey::PKey;
34 //! use std::str;
35 //!
36 //! let rsa = Rsa::generate(2048).unwrap();
37 //! let pkey = PKey::from_rsa(rsa).unwrap();
38 //!
39 //! let pub_key: Vec<u8> = pkey.public_key_to_pem().unwrap();
40 //! println!("{:?}", str::from_utf8(pub_key.as_slice()).unwrap());
41 //! ```
42 #![allow(clippy::missing_safety_doc)]
43 use crate::bio::{MemBio, MemBioSlice};
44 #[cfg(ossl110)]
45 use crate::cipher::CipherRef;
46 use crate::dh::Dh;
47 use crate::dsa::Dsa;
48 use crate::ec::EcKey;
49 use crate::error::ErrorStack;
50 #[cfg(any(boringssl, ossl110))]
51 use crate::pkey_ctx::PkeyCtx;
52 use crate::rsa::Rsa;
53 use crate::symm::Cipher;
54 use crate::util::{invoke_passwd_cb, CallbackState};
55 use crate::{cvt, cvt_p};
56 use cfg_if::cfg_if;
57 use foreign_types::{ForeignType, ForeignTypeRef};
58 use libc::{c_int, c_long};
59 use openssl_macros::corresponds;
60 use std::convert::TryFrom;
61 use std::ffi::CString;
62 use std::fmt;
63 use std::mem;
64 use std::ptr;
65 
66 /// A tag type indicating that a key only has parameters.
67 pub enum Params {}
68 
69 /// A tag type indicating that a key only has public components.
70 pub enum Public {}
71 
72 /// A tag type indicating that a key has private components.
73 pub enum Private {}
74 
75 /// An identifier of a kind of key.
76 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
77 pub struct Id(c_int);
78 
79 impl Id {
80     pub const RSA: Id = Id(ffi::EVP_PKEY_RSA);
81     #[cfg(not(boringssl))]
82     pub const HMAC: Id = Id(ffi::EVP_PKEY_HMAC);
83     #[cfg(not(boringssl))]
84     pub const CMAC: Id = Id(ffi::EVP_PKEY_CMAC);
85     pub const DSA: Id = Id(ffi::EVP_PKEY_DSA);
86     pub const DH: Id = Id(ffi::EVP_PKEY_DH);
87     pub const EC: Id = Id(ffi::EVP_PKEY_EC);
88 
89     #[cfg(ossl110)]
90     pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF);
91 
92     #[cfg(any(boringssl, ossl111))]
93     pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519);
94     #[cfg(ossl111)]
95     pub const ED448: Id = Id(ffi::EVP_PKEY_ED448);
96     #[cfg(any(boringssl, ossl111))]
97     pub const X25519: Id = Id(ffi::EVP_PKEY_X25519);
98     #[cfg(ossl111)]
99     pub const X448: Id = Id(ffi::EVP_PKEY_X448);
100 
101     /// Creates a `Id` from an integer representation.
from_raw(value: c_int) -> Id102     pub fn from_raw(value: c_int) -> Id {
103         Id(value)
104     }
105 
106     /// Returns the integer representation of the `Id`.
107     #[allow(clippy::trivially_copy_pass_by_ref)]
as_raw(&self) -> c_int108     pub fn as_raw(&self) -> c_int {
109         self.0
110     }
111 }
112 
113 /// A trait indicating that a key has parameters.
114 pub unsafe trait HasParams {}
115 
116 unsafe impl HasParams for Params {}
117 
118 unsafe impl<T> HasParams for T where T: HasPublic {}
119 
120 /// A trait indicating that a key has public components.
121 pub unsafe trait HasPublic {}
122 
123 unsafe impl HasPublic for Public {}
124 
125 unsafe impl<T> HasPublic for T where T: HasPrivate {}
126 
127 /// A trait indicating that a key has private components.
128 pub unsafe trait HasPrivate {}
129 
130 unsafe impl HasPrivate for Private {}
131 
132 generic_foreign_type_and_impl_send_sync! {
133     type CType = ffi::EVP_PKEY;
134     fn drop = ffi::EVP_PKEY_free;
135 
136     /// A public or private key.
137     pub struct PKey<T>;
138     /// Reference to `PKey`.
139     pub struct PKeyRef<T>;
140 }
141 
142 impl<T> ToOwned for PKeyRef<T> {
143     type Owned = PKey<T>;
144 
to_owned(&self) -> PKey<T>145     fn to_owned(&self) -> PKey<T> {
146         unsafe {
147             EVP_PKEY_up_ref(self.as_ptr());
148             PKey::from_ptr(self.as_ptr())
149         }
150     }
151 }
152 
153 impl<T> PKeyRef<T> {
154     /// Returns a copy of the internal RSA key.
155     #[corresponds(EVP_PKEY_get1_RSA)]
rsa(&self) -> Result<Rsa<T>, ErrorStack>156     pub fn rsa(&self) -> Result<Rsa<T>, ErrorStack> {
157         unsafe {
158             let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?;
159             Ok(Rsa::from_ptr(rsa))
160         }
161     }
162 
163     /// Returns a copy of the internal DSA key.
164     #[corresponds(EVP_PKEY_get1_DSA)]
dsa(&self) -> Result<Dsa<T>, ErrorStack>165     pub fn dsa(&self) -> Result<Dsa<T>, ErrorStack> {
166         unsafe {
167             let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?;
168             Ok(Dsa::from_ptr(dsa))
169         }
170     }
171 
172     /// Returns a copy of the internal DH key.
173     #[corresponds(EVP_PKEY_get1_DH)]
dh(&self) -> Result<Dh<T>, ErrorStack>174     pub fn dh(&self) -> Result<Dh<T>, ErrorStack> {
175         unsafe {
176             let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?;
177             Ok(Dh::from_ptr(dh))
178         }
179     }
180 
181     /// Returns a copy of the internal elliptic curve key.
182     #[corresponds(EVP_PKEY_get1_EC_KEY)]
ec_key(&self) -> Result<EcKey<T>, ErrorStack>183     pub fn ec_key(&self) -> Result<EcKey<T>, ErrorStack> {
184         unsafe {
185             let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?;
186             Ok(EcKey::from_ptr(ec_key))
187         }
188     }
189 
190     /// Returns the `Id` that represents the type of this key.
191     #[corresponds(EVP_PKEY_id)]
id(&self) -> Id192     pub fn id(&self) -> Id {
193         unsafe { Id::from_raw(ffi::EVP_PKEY_id(self.as_ptr())) }
194     }
195 
196     /// Returns the maximum size of a signature in bytes.
197     #[corresponds(EVP_PKEY_size)]
size(&self) -> usize198     pub fn size(&self) -> usize {
199         unsafe { ffi::EVP_PKEY_size(self.as_ptr()) as usize }
200     }
201 }
202 
203 impl<T> PKeyRef<T>
204 where
205     T: HasPublic,
206 {
207     to_pem! {
208         /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
209         ///
210         /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
211         #[corresponds(PEM_write_bio_PUBKEY)]
212         public_key_to_pem,
213         ffi::PEM_write_bio_PUBKEY
214     }
215 
216     to_der! {
217         /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
218         #[corresponds(i2d_PUBKEY)]
219         public_key_to_der,
220         ffi::i2d_PUBKEY
221     }
222 
223     /// Returns the size of the key.
224     ///
225     /// This corresponds to the bit length of the modulus of an RSA key, and the bit length of the
226     /// group order for an elliptic curve key, for example.
227     #[corresponds(EVP_PKEY_bits)]
bits(&self) -> u32228     pub fn bits(&self) -> u32 {
229         unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 }
230     }
231 
232     ///Returns the number of security bits.
233     ///
234     ///Bits of security is defined in NIST SP800-57.
235     #[corresponds(EVP_PKEY_security_bits)]
236     #[cfg(any(ossl110, libressl360))]
security_bits(&self) -> u32237     pub fn security_bits(&self) -> u32 {
238         unsafe { ffi::EVP_PKEY_security_bits(self.as_ptr()) as u32 }
239     }
240 
241     /// Compares the public component of this key with another.
242     #[corresponds(EVP_PKEY_cmp)]
public_eq<U>(&self, other: &PKeyRef<U>) -> bool where U: HasPublic,243     pub fn public_eq<U>(&self, other: &PKeyRef<U>) -> bool
244     where
245         U: HasPublic,
246     {
247         unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 }
248     }
249 
250     /// Raw byte representation of a public key.
251     ///
252     /// This function only works for algorithms that support raw public keys.
253     /// Currently this is: [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`].
254     #[corresponds(EVP_PKEY_get_raw_public_key)]
255     #[cfg(any(boringssl, ossl111))]
raw_public_key(&self) -> Result<Vec<u8>, ErrorStack>256     pub fn raw_public_key(&self) -> Result<Vec<u8>, ErrorStack> {
257         unsafe {
258             let mut len = 0;
259             cvt(ffi::EVP_PKEY_get_raw_public_key(
260                 self.as_ptr(),
261                 ptr::null_mut(),
262                 &mut len,
263             ))?;
264             let mut buf = vec![0u8; len];
265             cvt(ffi::EVP_PKEY_get_raw_public_key(
266                 self.as_ptr(),
267                 buf.as_mut_ptr(),
268                 &mut len,
269             ))?;
270             buf.truncate(len);
271             Ok(buf)
272         }
273     }
274 }
275 
276 impl<T> PKeyRef<T>
277 where
278     T: HasPrivate,
279 {
280     private_key_to_pem! {
281         /// Serializes the private key to a PEM-encoded PKCS#8 PrivateKeyInfo structure.
282         ///
283         /// The output will have a header of `-----BEGIN PRIVATE KEY-----`.
284         #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
285         private_key_to_pem_pkcs8,
286         /// Serializes the private key to a PEM-encoded PKCS#8 EncryptedPrivateKeyInfo structure.
287         ///
288         /// The output will have a header of `-----BEGIN ENCRYPTED PRIVATE KEY-----`.
289         #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
290         private_key_to_pem_pkcs8_passphrase,
291         ffi::PEM_write_bio_PKCS8PrivateKey
292     }
293 
294     to_der! {
295         /// Serializes the private key to a DER-encoded key type specific format.
296         #[corresponds(i2d_PrivateKey)]
297         private_key_to_der,
298         ffi::i2d_PrivateKey
299     }
300 
301     /// Raw byte representation of a private key.
302     ///
303     /// This function only works for algorithms that support raw private keys.
304     /// Currently this is: [`Id::HMAC`], [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`].
305     #[corresponds(EVP_PKEY_get_raw_private_key)]
306     #[cfg(any(boringssl, ossl111))]
raw_private_key(&self) -> Result<Vec<u8>, ErrorStack>307     pub fn raw_private_key(&self) -> Result<Vec<u8>, ErrorStack> {
308         unsafe {
309             let mut len = 0;
310             cvt(ffi::EVP_PKEY_get_raw_private_key(
311                 self.as_ptr(),
312                 ptr::null_mut(),
313                 &mut len,
314             ))?;
315             let mut buf = vec![0u8; len];
316             cvt(ffi::EVP_PKEY_get_raw_private_key(
317                 self.as_ptr(),
318                 buf.as_mut_ptr(),
319                 &mut len,
320             ))?;
321             buf.truncate(len);
322             Ok(buf)
323         }
324     }
325 
326     /// Serializes a private key into a DER-formatted PKCS#8, using the supplied password to
327     /// encrypt the key.
328     ///
329     /// # Panics
330     ///
331     /// Panics if `passphrase` contains an embedded null.
332     #[corresponds(i2d_PKCS8PrivateKey_bio)]
private_key_to_pkcs8_passphrase( &self, cipher: Cipher, passphrase: &[u8], ) -> Result<Vec<u8>, ErrorStack>333     pub fn private_key_to_pkcs8_passphrase(
334         &self,
335         cipher: Cipher,
336         passphrase: &[u8],
337     ) -> Result<Vec<u8>, ErrorStack> {
338         unsafe {
339             let bio = MemBio::new()?;
340             let len = passphrase.len();
341             let passphrase = CString::new(passphrase).unwrap();
342             cvt(ffi::i2d_PKCS8PrivateKey_bio(
343                 bio.as_ptr(),
344                 self.as_ptr(),
345                 cipher.as_ptr(),
346                 passphrase.as_ptr() as *const _ as *mut _,
347                 len as ::libc::c_int,
348                 None,
349                 ptr::null_mut(),
350             ))?;
351 
352             Ok(bio.get_buf().to_owned())
353         }
354     }
355 }
356 
357 impl<T> fmt::Debug for PKey<T> {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result358     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
359         let alg = match self.id() {
360             Id::RSA => "RSA",
361             #[cfg(not(boringssl))]
362             Id::HMAC => "HMAC",
363             Id::DSA => "DSA",
364             Id::DH => "DH",
365             Id::EC => "EC",
366             #[cfg(ossl111)]
367             Id::ED25519 => "Ed25519",
368             #[cfg(ossl111)]
369             Id::ED448 => "Ed448",
370             _ => "unknown",
371         };
372         fmt.debug_struct("PKey").field("algorithm", &alg).finish()
373         // TODO: Print details for each specific type of key
374     }
375 }
376 
377 impl<T> Clone for PKey<T> {
clone(&self) -> PKey<T>378     fn clone(&self) -> PKey<T> {
379         PKeyRef::to_owned(self)
380     }
381 }
382 
383 impl<T> PKey<T> {
384     /// Creates a new `PKey` containing an RSA key.
385     #[corresponds(EVP_PKEY_assign_RSA)]
from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack>386     pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
387         unsafe {
388             let evp = cvt_p(ffi::EVP_PKEY_new())?;
389             let pkey = PKey::from_ptr(evp);
390             cvt(ffi::EVP_PKEY_assign(
391                 pkey.0,
392                 ffi::EVP_PKEY_RSA,
393                 rsa.as_ptr() as *mut _,
394             ))?;
395             mem::forget(rsa);
396             Ok(pkey)
397         }
398     }
399 
400     /// Creates a new `PKey` containing a DSA key.
401     #[corresponds(EVP_PKEY_assign_DSA)]
from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack>402     pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
403         unsafe {
404             let evp = cvt_p(ffi::EVP_PKEY_new())?;
405             let pkey = PKey::from_ptr(evp);
406             cvt(ffi::EVP_PKEY_assign(
407                 pkey.0,
408                 ffi::EVP_PKEY_DSA,
409                 dsa.as_ptr() as *mut _,
410             ))?;
411             mem::forget(dsa);
412             Ok(pkey)
413         }
414     }
415 
416     /// Creates a new `PKey` containing a Diffie-Hellman key.
417     #[corresponds(EVP_PKEY_assign_DH)]
from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack>418     pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
419         unsafe {
420             let evp = cvt_p(ffi::EVP_PKEY_new())?;
421             let pkey = PKey::from_ptr(evp);
422             cvt(ffi::EVP_PKEY_assign(
423                 pkey.0,
424                 ffi::EVP_PKEY_DH,
425                 dh.as_ptr() as *mut _,
426             ))?;
427             mem::forget(dh);
428             Ok(pkey)
429         }
430     }
431 
432     /// Creates a new `PKey` containing an elliptic curve key.
433     #[corresponds(EVP_PKEY_assign_EC_KEY)]
from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack>434     pub fn from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
435         unsafe {
436             let evp = cvt_p(ffi::EVP_PKEY_new())?;
437             let pkey = PKey::from_ptr(evp);
438             cvt(ffi::EVP_PKEY_assign(
439                 pkey.0,
440                 ffi::EVP_PKEY_EC,
441                 ec_key.as_ptr() as *mut _,
442             ))?;
443             mem::forget(ec_key);
444             Ok(pkey)
445         }
446     }
447 }
448 
449 impl PKey<Private> {
450     /// Creates a new `PKey` containing an HMAC key.
451     ///
452     /// # Note
453     ///
454     /// To compute HMAC values, use the `sign` module.
455     #[corresponds(EVP_PKEY_new_mac_key)]
456     #[cfg(not(boringssl))]
hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack>457     pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
458         unsafe {
459             assert!(key.len() <= c_int::max_value() as usize);
460             let key = cvt_p(ffi::EVP_PKEY_new_mac_key(
461                 ffi::EVP_PKEY_HMAC,
462                 ptr::null_mut(),
463                 key.as_ptr() as *const _,
464                 key.len() as c_int,
465             ))?;
466             Ok(PKey::from_ptr(key))
467         }
468     }
469 
470     /// Creates a new `PKey` containing a CMAC key.
471     ///
472     /// Requires OpenSSL 1.1.0 or newer.
473     ///
474     /// # Note
475     ///
476     /// To compute CMAC values, use the `sign` module.
477     #[cfg(all(not(boringssl), ossl110))]
478     #[allow(clippy::trivially_copy_pass_by_ref)]
cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack>479     pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
480         let mut ctx = PkeyCtx::new_id(Id::CMAC)?;
481         ctx.keygen_init()?;
482         ctx.set_keygen_cipher(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) })?;
483         ctx.set_keygen_mac_key(key)?;
484         ctx.keygen()
485     }
486 
487     #[cfg(any(boringssl, ossl111))]
generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack>488     fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> {
489         let mut ctx = PkeyCtx::new_id(id)?;
490         ctx.keygen_init()?;
491         ctx.keygen()
492     }
493 
494     /// Generates a new private X25519 key.
495     ///
496     /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
497     ///
498     /// # Examples
499     ///
500     /// ```
501     /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
502     /// use openssl::pkey::{PKey, Id};
503     /// use openssl::derive::Deriver;
504     ///
505     /// let public = // ...
506     /// # &PKey::generate_x25519()?.raw_public_key()?;
507     /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X25519)?;
508     ///
509     /// let key = PKey::generate_x25519()?;
510     /// let mut deriver = Deriver::new(&key)?;
511     /// deriver.set_peer(&public_key)?;
512     ///
513     /// let secret = deriver.derive_to_vec()?;
514     /// assert_eq!(secret.len(), 32);
515     /// # Ok(()) }
516     /// ```
517     #[cfg(any(boringssl, ossl111))]
generate_x25519() -> Result<PKey<Private>, ErrorStack>518     pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> {
519         PKey::generate_eddsa(Id::X25519)
520     }
521 
522     /// Generates a new private X448 key.
523     ///
524     /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
525     ///
526     /// # Examples
527     ///
528     /// ```
529     /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
530     /// use openssl::pkey::{PKey, Id};
531     /// use openssl::derive::Deriver;
532     ///
533     /// let public = // ...
534     /// # &PKey::generate_x448()?.raw_public_key()?;
535     /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X448)?;
536     ///
537     /// let key = PKey::generate_x448()?;
538     /// let mut deriver = Deriver::new(&key)?;
539     /// deriver.set_peer(&public_key)?;
540     ///
541     /// let secret = deriver.derive_to_vec()?;
542     /// assert_eq!(secret.len(), 56);
543     /// # Ok(()) }
544     /// ```
545     #[cfg(ossl111)]
generate_x448() -> Result<PKey<Private>, ErrorStack>546     pub fn generate_x448() -> Result<PKey<Private>, ErrorStack> {
547         PKey::generate_eddsa(Id::X448)
548     }
549 
550     /// Generates a new private Ed25519 key.
551     ///
552     /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
553     ///
554     /// # Examples
555     ///
556     /// ```
557     /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
558     /// use openssl::pkey::{PKey, Id};
559     /// use openssl::sign::Signer;
560     ///
561     /// let key = PKey::generate_ed25519()?;
562     /// let public_key = key.raw_public_key()?;
563     ///
564     /// let mut signer = Signer::new_without_digest(&key)?;
565     /// let digest = // ...
566     /// # &vec![0; 32];
567     /// let signature = signer.sign_oneshot_to_vec(digest)?;
568     /// assert_eq!(signature.len(), 64);
569     /// # Ok(()) }
570     /// ```
571     #[cfg(any(boringssl, ossl111))]
generate_ed25519() -> Result<PKey<Private>, ErrorStack>572     pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> {
573         PKey::generate_eddsa(Id::ED25519)
574     }
575 
576     /// Generates a new private Ed448 key.
577     ///
578     /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
579     ///
580     /// # Examples
581     ///
582     /// ```
583     /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
584     /// use openssl::pkey::{PKey, Id};
585     /// use openssl::sign::Signer;
586     ///
587     /// let key = PKey::generate_ed448()?;
588     /// let public_key = key.raw_public_key()?;
589     ///
590     /// let mut signer = Signer::new_without_digest(&key)?;
591     /// let digest = // ...
592     /// # &vec![0; 32];
593     /// let signature = signer.sign_oneshot_to_vec(digest)?;
594     /// assert_eq!(signature.len(), 114);
595     /// # Ok(()) }
596     /// ```
597     #[cfg(ossl111)]
generate_ed448() -> Result<PKey<Private>, ErrorStack>598     pub fn generate_ed448() -> Result<PKey<Private>, ErrorStack> {
599         PKey::generate_eddsa(Id::ED448)
600     }
601 
602     /// Generates a new EC key using the provided curve.
603     ///
604     /// Requires OpenSSL 3.0.0 or newer.
605     #[corresponds(EVP_EC_gen)]
606     #[cfg(ossl300)]
ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack>607     pub fn ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack> {
608         ffi::init();
609 
610         let curve = CString::new(curve).unwrap();
611         unsafe {
612             let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?;
613             Ok(PKey::from_ptr(ptr))
614         }
615     }
616 
617     private_key_from_pem! {
618         /// Deserializes a private key from a PEM-encoded key type specific format.
619         #[corresponds(PEM_read_bio_PrivateKey)]
620         private_key_from_pem,
621 
622         /// Deserializes a private key from a PEM-encoded encrypted key type specific format.
623         #[corresponds(PEM_read_bio_PrivateKey)]
624         private_key_from_pem_passphrase,
625 
626         /// Deserializes a private key from a PEM-encoded encrypted key type specific format.
627         ///
628         /// The callback should fill the password into the provided buffer and return its length.
629         #[corresponds(PEM_read_bio_PrivateKey)]
630         private_key_from_pem_callback,
631         PKey<Private>,
632         ffi::PEM_read_bio_PrivateKey
633     }
634 
635     from_der! {
636         /// Decodes a DER-encoded private key.
637         ///
638         /// This function will attempt to automatically detect the underlying key format, and
639         /// supports the unencrypted PKCS#8 PrivateKeyInfo structures as well as key type specific
640         /// formats.
641         #[corresponds(d2i_AutoPrivateKey)]
642         private_key_from_der,
643         PKey<Private>,
644         ffi::d2i_AutoPrivateKey
645     }
646 
647     /// Deserializes a DER-formatted PKCS#8 unencrypted private key.
648     ///
649     /// This method is mainly for interoperability reasons. Encrypted keyfiles should be preferred.
private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack>650     pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> {
651         unsafe {
652             ffi::init();
653             let len = der.len().min(c_long::max_value() as usize) as c_long;
654             let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO(
655                 ptr::null_mut(),
656                 &mut der.as_ptr(),
657                 len,
658             ))?;
659             let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p));
660             ffi::PKCS8_PRIV_KEY_INFO_free(p8inf);
661             res
662         }
663     }
664 
665     /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password
666     /// if the key is encrypted.
667     ///
668     /// The callback should copy the password into the provided buffer and return the number of
669     /// bytes written.
670     #[corresponds(d2i_PKCS8PrivateKey_bio)]
private_key_from_pkcs8_callback<F>( der: &[u8], callback: F, ) -> Result<PKey<Private>, ErrorStack> where F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,671     pub fn private_key_from_pkcs8_callback<F>(
672         der: &[u8],
673         callback: F,
674     ) -> Result<PKey<Private>, ErrorStack>
675     where
676         F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
677     {
678         unsafe {
679             ffi::init();
680             let mut cb = CallbackState::new(callback);
681             let bio = MemBioSlice::new(der)?;
682             cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
683                 bio.as_ptr(),
684                 ptr::null_mut(),
685                 Some(invoke_passwd_cb::<F>),
686                 &mut cb as *mut _ as *mut _,
687             ))
688             .map(|p| PKey::from_ptr(p))
689         }
690     }
691 
692     /// Deserializes a DER-formatted PKCS#8 private key, using the supplied password if the key is
693     /// encrypted.
694     ///
695     /// # Panics
696     ///
697     /// Panics if `passphrase` contains an embedded null.
698     #[corresponds(d2i_PKCS8PrivateKey_bio)]
private_key_from_pkcs8_passphrase( der: &[u8], passphrase: &[u8], ) -> Result<PKey<Private>, ErrorStack>699     pub fn private_key_from_pkcs8_passphrase(
700         der: &[u8],
701         passphrase: &[u8],
702     ) -> Result<PKey<Private>, ErrorStack> {
703         unsafe {
704             ffi::init();
705             let bio = MemBioSlice::new(der)?;
706             let passphrase = CString::new(passphrase).unwrap();
707             cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
708                 bio.as_ptr(),
709                 ptr::null_mut(),
710                 None,
711                 passphrase.as_ptr() as *const _ as *mut _,
712             ))
713             .map(|p| PKey::from_ptr(p))
714         }
715     }
716 
717     /// Creates a private key from its raw byte representation
718     ///
719     /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448
720     #[corresponds(EVP_PKEY_new_raw_private_key)]
721     #[cfg(any(boringssl, ossl111))]
private_key_from_raw_bytes( bytes: &[u8], key_type: Id, ) -> Result<PKey<Private>, ErrorStack>722     pub fn private_key_from_raw_bytes(
723         bytes: &[u8],
724         key_type: Id,
725     ) -> Result<PKey<Private>, ErrorStack> {
726         unsafe {
727             ffi::init();
728             cvt_p(ffi::EVP_PKEY_new_raw_private_key(
729                 key_type.as_raw(),
730                 ptr::null_mut(),
731                 bytes.as_ptr(),
732                 bytes.len(),
733             ))
734             .map(|p| PKey::from_ptr(p))
735         }
736     }
737 }
738 
739 impl PKey<Public> {
740     from_pem! {
741         /// Decodes a PEM-encoded SubjectPublicKeyInfo structure.
742         ///
743         /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
744         #[corresponds(PEM_read_bio_PUBKEY)]
745         public_key_from_pem,
746         PKey<Public>,
747         ffi::PEM_read_bio_PUBKEY
748     }
749 
750     from_der! {
751         /// Decodes a DER-encoded SubjectPublicKeyInfo structure.
752         #[corresponds(d2i_PUBKEY)]
753         public_key_from_der,
754         PKey<Public>,
755         ffi::d2i_PUBKEY
756     }
757 
758     /// Creates a public key from its raw byte representation
759     ///
760     /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448
761     #[corresponds(EVP_PKEY_new_raw_public_key)]
762     #[cfg(any(boringssl, ossl111))]
public_key_from_raw_bytes( bytes: &[u8], key_type: Id, ) -> Result<PKey<Public>, ErrorStack>763     pub fn public_key_from_raw_bytes(
764         bytes: &[u8],
765         key_type: Id,
766     ) -> Result<PKey<Public>, ErrorStack> {
767         unsafe {
768             ffi::init();
769             cvt_p(ffi::EVP_PKEY_new_raw_public_key(
770                 key_type.as_raw(),
771                 ptr::null_mut(),
772                 bytes.as_ptr(),
773                 bytes.len(),
774             ))
775             .map(|p| PKey::from_ptr(p))
776         }
777     }
778 }
779 
780 cfg_if! {
781     if #[cfg(any(boringssl, ossl110, libressl270))] {
782         use ffi::EVP_PKEY_up_ref;
783     } else {
784         #[allow(bad_style)]
785         unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) {
786             ffi::CRYPTO_add_lock(
787                 &mut (*pkey).references,
788                 1,
789                 ffi::CRYPTO_LOCK_EVP_PKEY,
790                 "pkey.rs\0".as_ptr() as *const _,
791                 line!() as c_int,
792             );
793         }
794     }
795 }
796 
797 impl<T> TryFrom<EcKey<T>> for PKey<T> {
798     type Error = ErrorStack;
799 
try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack>800     fn try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
801         PKey::from_ec_key(ec_key)
802     }
803 }
804 
805 impl<T> TryFrom<PKey<T>> for EcKey<T> {
806     type Error = ErrorStack;
807 
try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack>808     fn try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack> {
809         pkey.ec_key()
810     }
811 }
812 
813 impl<T> TryFrom<Rsa<T>> for PKey<T> {
814     type Error = ErrorStack;
815 
try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack>816     fn try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
817         PKey::from_rsa(rsa)
818     }
819 }
820 
821 impl<T> TryFrom<PKey<T>> for Rsa<T> {
822     type Error = ErrorStack;
823 
try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack>824     fn try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack> {
825         pkey.rsa()
826     }
827 }
828 
829 impl<T> TryFrom<Dsa<T>> for PKey<T> {
830     type Error = ErrorStack;
831 
try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack>832     fn try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
833         PKey::from_dsa(dsa)
834     }
835 }
836 
837 impl<T> TryFrom<PKey<T>> for Dsa<T> {
838     type Error = ErrorStack;
839 
try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack>840     fn try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack> {
841         pkey.dsa()
842     }
843 }
844 
845 impl<T> TryFrom<Dh<T>> for PKey<T> {
846     type Error = ErrorStack;
847 
try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack>848     fn try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
849         PKey::from_dh(dh)
850     }
851 }
852 
853 impl<T> TryFrom<PKey<T>> for Dh<T> {
854     type Error = ErrorStack;
855 
try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack>856     fn try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack> {
857         pkey.dh()
858     }
859 }
860 
861 #[cfg(test)]
862 mod tests {
863     use std::convert::TryInto;
864 
865     #[cfg(not(boringssl))]
866     use crate::dh::Dh;
867     use crate::dsa::Dsa;
868     use crate::ec::EcKey;
869     use crate::nid::Nid;
870     use crate::rsa::Rsa;
871     use crate::symm::Cipher;
872 
873     use super::*;
874 
875     #[cfg(ossl111)]
876     use crate::rand::rand_bytes;
877 
878     #[test]
test_to_password()879     fn test_to_password() {
880         let rsa = Rsa::generate(2048).unwrap();
881         let pkey = PKey::from_rsa(rsa).unwrap();
882         let pem = pkey
883             .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar")
884             .unwrap();
885         PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
886         assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
887     }
888 
889     #[test]
test_unencrypted_pkcs8()890     fn test_unencrypted_pkcs8() {
891         let key = include_bytes!("../test/pkcs8-nocrypt.der");
892         PKey::private_key_from_pkcs8(key).unwrap();
893     }
894 
895     #[test]
test_encrypted_pkcs8_passphrase()896     fn test_encrypted_pkcs8_passphrase() {
897         let key = include_bytes!("../test/pkcs8.der");
898         PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap();
899 
900         let rsa = Rsa::generate(2048).unwrap();
901         let pkey = PKey::from_rsa(rsa).unwrap();
902         let der = pkey
903             .private_key_to_pkcs8_passphrase(Cipher::aes_128_cbc(), b"mypass")
904             .unwrap();
905         let pkey2 = PKey::private_key_from_pkcs8_passphrase(&der, b"mypass").unwrap();
906         assert_eq!(
907             pkey.private_key_to_der().unwrap(),
908             pkey2.private_key_to_der().unwrap()
909         );
910     }
911 
912     #[test]
test_encrypted_pkcs8_callback()913     fn test_encrypted_pkcs8_callback() {
914         let mut password_queried = false;
915         let key = include_bytes!("../test/pkcs8.der");
916         PKey::private_key_from_pkcs8_callback(key, |password| {
917             password_queried = true;
918             password[..6].copy_from_slice(b"mypass");
919             Ok(6)
920         })
921         .unwrap();
922         assert!(password_queried);
923     }
924 
925     #[test]
test_private_key_from_pem()926     fn test_private_key_from_pem() {
927         let key = include_bytes!("../test/key.pem");
928         PKey::private_key_from_pem(key).unwrap();
929     }
930 
931     #[test]
test_public_key_from_pem()932     fn test_public_key_from_pem() {
933         let key = include_bytes!("../test/key.pem.pub");
934         PKey::public_key_from_pem(key).unwrap();
935     }
936 
937     #[test]
test_public_key_from_der()938     fn test_public_key_from_der() {
939         let key = include_bytes!("../test/key.der.pub");
940         PKey::public_key_from_der(key).unwrap();
941     }
942 
943     #[test]
test_private_key_from_der()944     fn test_private_key_from_der() {
945         let key = include_bytes!("../test/key.der");
946         PKey::private_key_from_der(key).unwrap();
947     }
948 
949     #[test]
test_pem()950     fn test_pem() {
951         let key = include_bytes!("../test/key.pem");
952         let key = PKey::private_key_from_pem(key).unwrap();
953 
954         let priv_key = key.private_key_to_pem_pkcs8().unwrap();
955         let pub_key = key.public_key_to_pem().unwrap();
956 
957         // As a super-simple verification, just check that the buffers contain
958         // the `PRIVATE KEY` or `PUBLIC KEY` strings.
959         assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY"));
960         assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY"));
961     }
962 
963     #[test]
test_rsa_accessor()964     fn test_rsa_accessor() {
965         let rsa = Rsa::generate(2048).unwrap();
966         let pkey = PKey::from_rsa(rsa).unwrap();
967         pkey.rsa().unwrap();
968         assert_eq!(pkey.id(), Id::RSA);
969         assert!(pkey.dsa().is_err());
970     }
971 
972     #[test]
test_dsa_accessor()973     fn test_dsa_accessor() {
974         let dsa = Dsa::generate(2048).unwrap();
975         let pkey = PKey::from_dsa(dsa).unwrap();
976         pkey.dsa().unwrap();
977         assert_eq!(pkey.id(), Id::DSA);
978         assert!(pkey.rsa().is_err());
979     }
980 
981     #[test]
982     #[cfg(not(boringssl))]
test_dh_accessor()983     fn test_dh_accessor() {
984         let dh = include_bytes!("../test/dhparams.pem");
985         let dh = Dh::params_from_pem(dh).unwrap();
986         let pkey = PKey::from_dh(dh).unwrap();
987         pkey.dh().unwrap();
988         assert_eq!(pkey.id(), Id::DH);
989         assert!(pkey.rsa().is_err());
990     }
991 
992     #[test]
test_ec_key_accessor()993     fn test_ec_key_accessor() {
994         let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
995         let pkey = PKey::from_ec_key(ec_key).unwrap();
996         pkey.ec_key().unwrap();
997         assert_eq!(pkey.id(), Id::EC);
998         assert!(pkey.rsa().is_err());
999     }
1000 
1001     #[test]
test_rsa_conversion()1002     fn test_rsa_conversion() {
1003         let rsa = Rsa::generate(2048).unwrap();
1004         let pkey: PKey<Private> = rsa.clone().try_into().unwrap();
1005         let rsa_: Rsa<Private> = pkey.try_into().unwrap();
1006         // Eq is missing
1007         assert_eq!(rsa.p(), rsa_.p());
1008         assert_eq!(rsa.q(), rsa_.q());
1009     }
1010 
1011     #[test]
test_dsa_conversion()1012     fn test_dsa_conversion() {
1013         let dsa = Dsa::generate(2048).unwrap();
1014         let pkey: PKey<Private> = dsa.clone().try_into().unwrap();
1015         let dsa_: Dsa<Private> = pkey.try_into().unwrap();
1016         // Eq is missing
1017         assert_eq!(dsa.priv_key(), dsa_.priv_key());
1018     }
1019 
1020     #[test]
test_ec_key_conversion()1021     fn test_ec_key_conversion() {
1022         let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap();
1023         let ec_key = EcKey::generate(&group).unwrap();
1024         let pkey: PKey<Private> = ec_key.clone().try_into().unwrap();
1025         let ec_key_: EcKey<Private> = pkey.try_into().unwrap();
1026         // Eq is missing
1027         assert_eq!(ec_key.private_key(), ec_key_.private_key());
1028     }
1029 
1030     #[test]
1031     #[cfg(any(ossl110, libressl360))]
test_security_bits()1032     fn test_security_bits() {
1033         let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::SECP521R1).unwrap();
1034         let ec_key = EcKey::generate(&group).unwrap();
1035         let pkey: PKey<Private> = ec_key.try_into().unwrap();
1036 
1037         assert_eq!(pkey.security_bits(), 256);
1038     }
1039 
1040     #[test]
1041     #[cfg(not(boringssl))]
test_dh_conversion()1042     fn test_dh_conversion() {
1043         let dh_params = include_bytes!("../test/dhparams.pem");
1044         let dh_params = Dh::params_from_pem(dh_params).unwrap();
1045         let dh = dh_params.generate_key().unwrap();
1046 
1047         // Clone is missing for Dh, save the parameters
1048         let p = dh.prime_p().to_owned().unwrap();
1049         let q = dh.prime_q().map(|q| q.to_owned().unwrap());
1050         let g = dh.generator().to_owned().unwrap();
1051 
1052         let pkey: PKey<Private> = dh.try_into().unwrap();
1053         let dh_: Dh<Private> = pkey.try_into().unwrap();
1054 
1055         // Eq is missing
1056         assert_eq!(&p, dh_.prime_p());
1057         assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap()));
1058         assert_eq!(&g, dh_.generator());
1059     }
1060 
1061     #[cfg(ossl111)]
test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id)1062     fn test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
1063         // Generate a new key
1064         let key = gen().unwrap();
1065 
1066         // Get the raw bytes, and create a new key from the raw bytes
1067         let raw = key.raw_public_key().unwrap();
1068         let from_raw = PKey::public_key_from_raw_bytes(&raw, key_type).unwrap();
1069 
1070         // Compare the der encoding of the original and raw / restored public key
1071         assert_eq!(
1072             key.public_key_to_der().unwrap(),
1073             from_raw.public_key_to_der().unwrap()
1074         );
1075     }
1076 
1077     #[cfg(ossl111)]
test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id)1078     fn test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
1079         // Generate a new key
1080         let key = gen().unwrap();
1081 
1082         // Get the raw bytes, and create a new key from the raw bytes
1083         let raw = key.raw_private_key().unwrap();
1084         let from_raw = PKey::private_key_from_raw_bytes(&raw, key_type).unwrap();
1085 
1086         // Compare the der encoding of the original and raw / restored public key
1087         assert_eq!(
1088             key.private_key_to_der().unwrap(),
1089             from_raw.private_key_to_der().unwrap()
1090         );
1091     }
1092 
1093     #[cfg(ossl111)]
1094     #[test]
test_raw_public_key_bytes()1095     fn test_raw_public_key_bytes() {
1096         test_raw_public_key(PKey::generate_x25519, Id::X25519);
1097         test_raw_public_key(PKey::generate_ed25519, Id::ED25519);
1098         test_raw_public_key(PKey::generate_x448, Id::X448);
1099         test_raw_public_key(PKey::generate_ed448, Id::ED448);
1100     }
1101 
1102     #[cfg(ossl111)]
1103     #[test]
test_raw_private_key_bytes()1104     fn test_raw_private_key_bytes() {
1105         test_raw_private_key(PKey::generate_x25519, Id::X25519);
1106         test_raw_private_key(PKey::generate_ed25519, Id::ED25519);
1107         test_raw_private_key(PKey::generate_x448, Id::X448);
1108         test_raw_private_key(PKey::generate_ed448, Id::ED448);
1109     }
1110 
1111     #[cfg(ossl111)]
1112     #[test]
test_raw_hmac()1113     fn test_raw_hmac() {
1114         let mut test_bytes = vec![0u8; 32];
1115         rand_bytes(&mut test_bytes).unwrap();
1116 
1117         let hmac_key = PKey::hmac(&test_bytes).unwrap();
1118         assert!(hmac_key.raw_public_key().is_err());
1119 
1120         let key_bytes = hmac_key.raw_private_key().unwrap();
1121         assert_eq!(key_bytes, test_bytes);
1122     }
1123 
1124     #[cfg(ossl111)]
1125     #[test]
test_raw_key_fail()1126     fn test_raw_key_fail() {
1127         // Getting a raw byte representation will not work with Nist curves
1128         let group = crate::ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
1129         let ec_key = EcKey::generate(&group).unwrap();
1130         let pkey = PKey::from_ec_key(ec_key).unwrap();
1131         assert!(pkey.raw_private_key().is_err());
1132         assert!(pkey.raw_public_key().is_err());
1133     }
1134 
1135     #[cfg(ossl300)]
1136     #[test]
test_ec_gen()1137     fn test_ec_gen() {
1138         let key = PKey::ec_gen("prime256v1").unwrap();
1139         assert!(key.ec_key().is_ok());
1140     }
1141 }
1142