openssl/
pkey.rs

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