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