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