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, awslc))]
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(any(boringssl, awslc)), 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, awslc))]
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(any(boringssl, awslc)))]
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, awslc))]
97    pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF);
98
99    #[cfg(any(ossl111, boringssl, libressl370, awslc))]
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, awslc))]
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, awslc))]
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, awslc))]
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(any(ossl111, libressl310, boringssl, awslc))]
388            Id::RSA_PSS => "RSA-PSS",
389            #[cfg(not(boringssl))]
390            Id::HMAC => "HMAC",
391            #[cfg(not(any(boringssl, awslc)))]
392            Id::CMAC => "CMAC",
393            Id::DSA => "DSA",
394            Id::DH => "DH",
395            #[cfg(ossl110)]
396            Id::DHX => "DHX",
397            Id::EC => "EC",
398            #[cfg(ossl111)]
399            Id::SM2 => "SM2",
400            #[cfg(any(ossl110, boringssl, libressl360, awslc))]
401            Id::HKDF => "HKDF",
402            #[cfg(any(ossl111, boringssl, libressl370, awslc))]
403            Id::ED25519 => "Ed25519",
404            #[cfg(ossl111)]
405            Id::ED448 => "Ed448",
406            #[cfg(any(ossl111, boringssl, libressl370, awslc))]
407            Id::X25519 => "X25519",
408            #[cfg(ossl111)]
409            Id::X448 => "X448",
410            #[cfg(ossl111)]
411            Id::POLY1305 => "POLY1305",
412            _ => "unknown",
413        };
414        fmt.debug_struct("PKey").field("algorithm", &alg).finish()
415        // TODO: Print details for each specific type of key
416    }
417}
418
419impl<T> Clone for PKey<T> {
420    fn clone(&self) -> PKey<T> {
421        PKeyRef::to_owned(self)
422    }
423}
424
425impl<T> PKey<T> {
426    /// Creates a new `PKey` containing an RSA key.
427    #[corresponds(EVP_PKEY_set1_RSA)]
428    pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
429        // TODO: Next time we make backwards incompatible changes, this could
430        // become an `&RsaRef<T>`. Same for all the other `from_*` methods.
431        unsafe {
432            let evp = cvt_p(ffi::EVP_PKEY_new())?;
433            let pkey = PKey::from_ptr(evp);
434            cvt(ffi::EVP_PKEY_set1_RSA(pkey.0, rsa.as_ptr()))?;
435            Ok(pkey)
436        }
437    }
438
439    /// Creates a new `PKey` containing a DSA key.
440    #[corresponds(EVP_PKEY_set1_DSA)]
441    pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
442        unsafe {
443            let evp = cvt_p(ffi::EVP_PKEY_new())?;
444            let pkey = PKey::from_ptr(evp);
445            cvt(ffi::EVP_PKEY_set1_DSA(pkey.0, dsa.as_ptr()))?;
446            Ok(pkey)
447        }
448    }
449
450    /// Creates a new `PKey` containing a Diffie-Hellman key.
451    #[corresponds(EVP_PKEY_set1_DH)]
452    #[cfg(not(boringssl))]
453    pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
454        unsafe {
455            let evp = cvt_p(ffi::EVP_PKEY_new())?;
456            let pkey = PKey::from_ptr(evp);
457            cvt(ffi::EVP_PKEY_set1_DH(pkey.0, dh.as_ptr()))?;
458            Ok(pkey)
459        }
460    }
461
462    /// Creates a new `PKey` containing a Diffie-Hellman key with type DHX.
463    #[cfg(all(not(any(boringssl, awslc)), ossl110))]
464    pub fn from_dhx(dh: Dh<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_assign(
469                pkey.0,
470                ffi::EVP_PKEY_DHX,
471                dh.as_ptr().cast(),
472            ))?;
473            mem::forget(dh);
474            Ok(pkey)
475        }
476    }
477
478    /// Creates a new `PKey` containing an elliptic curve key.
479    #[corresponds(EVP_PKEY_set1_EC_KEY)]
480    pub fn from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
481        unsafe {
482            let evp = cvt_p(ffi::EVP_PKEY_new())?;
483            let pkey = PKey::from_ptr(evp);
484            cvt(ffi::EVP_PKEY_set1_EC_KEY(pkey.0, ec_key.as_ptr()))?;
485            Ok(pkey)
486        }
487    }
488}
489
490impl PKey<Private> {
491    /// Creates a new `PKey` containing an HMAC key.
492    ///
493    /// # Note
494    ///
495    /// To compute HMAC values, use the `sign` module.
496    #[corresponds(EVP_PKEY_new_mac_key)]
497    #[cfg(not(boringssl))]
498    pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
499        #[cfg(awslc)]
500        let key_len = key.len();
501        #[cfg(not(awslc))]
502        let key_len = key.len() as c_int;
503        unsafe {
504            assert!(key.len() <= c_int::MAX as usize);
505            let key = cvt_p(ffi::EVP_PKEY_new_mac_key(
506                ffi::EVP_PKEY_HMAC,
507                ptr::null_mut(),
508                key.as_ptr() as *const _,
509                key_len,
510            ))?;
511            Ok(PKey::from_ptr(key))
512        }
513    }
514
515    /// Creates a new `PKey` containing a CMAC key.
516    ///
517    /// Requires OpenSSL 1.1.0 or newer.
518    ///
519    /// # Note
520    ///
521    /// To compute CMAC values, use the `sign` module.
522    #[cfg(all(not(any(boringssl, awslc)), ossl110))]
523    #[allow(clippy::trivially_copy_pass_by_ref)]
524    pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
525        let mut ctx = PkeyCtx::new_id(Id::CMAC)?;
526        ctx.keygen_init()?;
527        ctx.set_keygen_cipher(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) })?;
528        ctx.set_keygen_mac_key(key)?;
529        ctx.keygen()
530    }
531
532    #[cfg(any(ossl111, boringssl, libressl370, awslc))]
533    fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> {
534        let mut ctx = PkeyCtx::new_id(id)?;
535        ctx.keygen_init()?;
536        ctx.keygen()
537    }
538
539    /// Generates a new private X25519 key.
540    ///
541    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
542    ///
543    /// # Examples
544    ///
545    /// ```
546    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
547    /// use openssl::pkey::{PKey, Id};
548    /// use openssl::derive::Deriver;
549    ///
550    /// let public = // ...
551    /// # &PKey::generate_x25519()?.raw_public_key()?;
552    /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X25519)?;
553    ///
554    /// let key = PKey::generate_x25519()?;
555    /// let mut deriver = Deriver::new(&key)?;
556    /// deriver.set_peer(&public_key)?;
557    ///
558    /// let secret = deriver.derive_to_vec()?;
559    /// assert_eq!(secret.len(), 32);
560    /// # Ok(()) }
561    /// ```
562    #[cfg(any(ossl111, boringssl, libressl370, awslc))]
563    pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> {
564        PKey::generate_eddsa(Id::X25519)
565    }
566
567    /// Generates a new private X448 key.
568    ///
569    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
570    ///
571    /// # Examples
572    ///
573    /// ```
574    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
575    /// use openssl::pkey::{PKey, Id};
576    /// use openssl::derive::Deriver;
577    ///
578    /// let public = // ...
579    /// # &PKey::generate_x448()?.raw_public_key()?;
580    /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X448)?;
581    ///
582    /// let key = PKey::generate_x448()?;
583    /// let mut deriver = Deriver::new(&key)?;
584    /// deriver.set_peer(&public_key)?;
585    ///
586    /// let secret = deriver.derive_to_vec()?;
587    /// assert_eq!(secret.len(), 56);
588    /// # Ok(()) }
589    /// ```
590    #[cfg(ossl111)]
591    pub fn generate_x448() -> Result<PKey<Private>, ErrorStack> {
592        PKey::generate_eddsa(Id::X448)
593    }
594
595    /// Generates a new private Ed25519 key.
596    ///
597    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
598    ///
599    /// # Examples
600    ///
601    /// ```
602    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
603    /// use openssl::pkey::{PKey, Id};
604    /// use openssl::sign::Signer;
605    ///
606    /// let key = PKey::generate_ed25519()?;
607    /// let public_key = key.raw_public_key()?;
608    ///
609    /// let mut signer = Signer::new_without_digest(&key)?;
610    /// let digest = // ...
611    /// # &vec![0; 32];
612    /// let signature = signer.sign_oneshot_to_vec(digest)?;
613    /// assert_eq!(signature.len(), 64);
614    /// # Ok(()) }
615    /// ```
616    #[cfg(any(ossl111, boringssl, libressl370, awslc))]
617    pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> {
618        PKey::generate_eddsa(Id::ED25519)
619    }
620
621    /// Generates a new private Ed448 key.
622    ///
623    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
624    ///
625    /// # Examples
626    ///
627    /// ```
628    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
629    /// use openssl::pkey::{PKey, Id};
630    /// use openssl::sign::Signer;
631    ///
632    /// let key = PKey::generate_ed448()?;
633    /// let public_key = key.raw_public_key()?;
634    ///
635    /// let mut signer = Signer::new_without_digest(&key)?;
636    /// let digest = // ...
637    /// # &vec![0; 32];
638    /// let signature = signer.sign_oneshot_to_vec(digest)?;
639    /// assert_eq!(signature.len(), 114);
640    /// # Ok(()) }
641    /// ```
642    #[cfg(ossl111)]
643    pub fn generate_ed448() -> Result<PKey<Private>, ErrorStack> {
644        PKey::generate_eddsa(Id::ED448)
645    }
646
647    /// Generates a new EC key using the provided curve.
648    ///
649    /// Requires OpenSSL 3.0.0 or newer.
650    #[corresponds(EVP_EC_gen)]
651    #[cfg(ossl300)]
652    pub fn ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack> {
653        ffi::init();
654
655        let curve = CString::new(curve).unwrap();
656        unsafe {
657            let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?;
658            Ok(PKey::from_ptr(ptr))
659        }
660    }
661
662    private_key_from_pem! {
663        /// Deserializes a private key from a PEM-encoded key type specific format.
664        #[corresponds(PEM_read_bio_PrivateKey)]
665        private_key_from_pem,
666
667        /// Deserializes a private key from a PEM-encoded encrypted key type specific format.
668        #[corresponds(PEM_read_bio_PrivateKey)]
669        private_key_from_pem_passphrase,
670
671        /// Deserializes a private key from a PEM-encoded encrypted key type specific format.
672        ///
673        /// The callback should fill the password into the provided buffer and return its length.
674        #[corresponds(PEM_read_bio_PrivateKey)]
675        private_key_from_pem_callback,
676        PKey<Private>,
677        ffi::PEM_read_bio_PrivateKey
678    }
679
680    from_der! {
681        /// Decodes a DER-encoded private key.
682        ///
683        /// This function will attempt to automatically detect the underlying key format, and
684        /// supports the unencrypted PKCS#8 PrivateKeyInfo structures as well as key type specific
685        /// formats.
686        #[corresponds(d2i_AutoPrivateKey)]
687        private_key_from_der,
688        PKey<Private>,
689        ffi::d2i_AutoPrivateKey
690    }
691
692    /// Deserializes a DER-formatted PKCS#8 unencrypted private key.
693    ///
694    /// This method is mainly for interoperability reasons. Encrypted keyfiles should be preferred.
695    pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> {
696        unsafe {
697            ffi::init();
698            let len = der.len().min(c_long::MAX as usize) as c_long;
699            let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO(
700                ptr::null_mut(),
701                &mut der.as_ptr(),
702                len,
703            ))?;
704            let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p));
705            ffi::PKCS8_PRIV_KEY_INFO_free(p8inf);
706            res
707        }
708    }
709
710    /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password
711    /// if the key is encrypted.
712    ///
713    /// The callback should copy the password into the provided buffer and return the number of
714    /// bytes written.
715    #[corresponds(d2i_PKCS8PrivateKey_bio)]
716    pub fn private_key_from_pkcs8_callback<F>(
717        der: &[u8],
718        callback: F,
719    ) -> Result<PKey<Private>, ErrorStack>
720    where
721        F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
722    {
723        unsafe {
724            ffi::init();
725            let mut cb = CallbackState::new(callback);
726            let bio = MemBioSlice::new(der)?;
727            cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
728                bio.as_ptr(),
729                ptr::null_mut(),
730                Some(invoke_passwd_cb::<F>),
731                &mut cb as *mut _ as *mut _,
732            ))
733            .map(|p| PKey::from_ptr(p))
734        }
735    }
736
737    /// Deserializes a DER-formatted PKCS#8 private key, using the supplied password if the key is
738    /// encrypted.
739    ///
740    /// # Panics
741    ///
742    /// Panics if `passphrase` contains an embedded null.
743    #[corresponds(d2i_PKCS8PrivateKey_bio)]
744    pub fn private_key_from_pkcs8_passphrase(
745        der: &[u8],
746        passphrase: &[u8],
747    ) -> Result<PKey<Private>, ErrorStack> {
748        unsafe {
749            ffi::init();
750            let bio = MemBioSlice::new(der)?;
751            let passphrase = CString::new(passphrase).unwrap();
752            cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
753                bio.as_ptr(),
754                ptr::null_mut(),
755                None,
756                passphrase.as_ptr() as *const _ as *mut _,
757            ))
758            .map(|p| PKey::from_ptr(p))
759        }
760    }
761
762    /// Creates a private key from its raw byte representation
763    ///
764    /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448
765    #[corresponds(EVP_PKEY_new_raw_private_key)]
766    #[cfg(any(ossl111, boringssl, libressl370, awslc))]
767    pub fn private_key_from_raw_bytes(
768        bytes: &[u8],
769        key_type: Id,
770    ) -> Result<PKey<Private>, ErrorStack> {
771        unsafe {
772            ffi::init();
773            cvt_p(ffi::EVP_PKEY_new_raw_private_key(
774                key_type.as_raw(),
775                ptr::null_mut(),
776                bytes.as_ptr(),
777                bytes.len(),
778            ))
779            .map(|p| PKey::from_ptr(p))
780        }
781    }
782}
783
784impl PKey<Public> {
785    private_key_from_pem! {
786        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure.
787        ///
788        /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
789        #[corresponds(PEM_read_bio_PUBKEY)]
790        public_key_from_pem,
791
792        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure.
793        #[corresponds(PEM_read_bio_PUBKEY)]
794        public_key_from_pem_passphrase,
795
796        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure.
797        ///
798        /// The callback should fill the password into the provided buffer and return its length.
799        #[corresponds(PEM_read_bio_PrivateKey)]
800        public_key_from_pem_callback,
801        PKey<Public>,
802        ffi::PEM_read_bio_PUBKEY
803    }
804
805    from_der! {
806        /// Decodes a DER-encoded SubjectPublicKeyInfo structure.
807        #[corresponds(d2i_PUBKEY)]
808        public_key_from_der,
809        PKey<Public>,
810        ffi::d2i_PUBKEY
811    }
812
813    /// Creates a public key from its raw byte representation
814    ///
815    /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448
816    #[corresponds(EVP_PKEY_new_raw_public_key)]
817    #[cfg(any(ossl111, boringssl, libressl370, awslc))]
818    pub fn public_key_from_raw_bytes(
819        bytes: &[u8],
820        key_type: Id,
821    ) -> Result<PKey<Public>, ErrorStack> {
822        unsafe {
823            ffi::init();
824            cvt_p(ffi::EVP_PKEY_new_raw_public_key(
825                key_type.as_raw(),
826                ptr::null_mut(),
827                bytes.as_ptr(),
828                bytes.len(),
829            ))
830            .map(|p| PKey::from_ptr(p))
831        }
832    }
833}
834
835cfg_if! {
836    if #[cfg(any(boringssl, ossl110, libressl270, awslc))] {
837        use ffi::EVP_PKEY_up_ref;
838    } else {
839        #[allow(bad_style)]
840        unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) {
841            ffi::CRYPTO_add_lock(
842                &mut (*pkey).references,
843                1,
844                ffi::CRYPTO_LOCK_EVP_PKEY,
845                "pkey.rs\0".as_ptr() as *const _,
846                line!() as c_int,
847            );
848        }
849    }
850}
851
852impl<T> TryFrom<EcKey<T>> for PKey<T> {
853    type Error = ErrorStack;
854
855    fn try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
856        PKey::from_ec_key(ec_key)
857    }
858}
859
860impl<T> TryFrom<PKey<T>> for EcKey<T> {
861    type Error = ErrorStack;
862
863    fn try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack> {
864        pkey.ec_key()
865    }
866}
867
868impl<T> TryFrom<Rsa<T>> for PKey<T> {
869    type Error = ErrorStack;
870
871    fn try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
872        PKey::from_rsa(rsa)
873    }
874}
875
876impl<T> TryFrom<PKey<T>> for Rsa<T> {
877    type Error = ErrorStack;
878
879    fn try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack> {
880        pkey.rsa()
881    }
882}
883
884impl<T> TryFrom<Dsa<T>> for PKey<T> {
885    type Error = ErrorStack;
886
887    fn try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
888        PKey::from_dsa(dsa)
889    }
890}
891
892impl<T> TryFrom<PKey<T>> for Dsa<T> {
893    type Error = ErrorStack;
894
895    fn try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack> {
896        pkey.dsa()
897    }
898}
899
900#[cfg(not(boringssl))]
901impl<T> TryFrom<Dh<T>> for PKey<T> {
902    type Error = ErrorStack;
903
904    fn try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
905        PKey::from_dh(dh)
906    }
907}
908
909impl<T> TryFrom<PKey<T>> for Dh<T> {
910    type Error = ErrorStack;
911
912    fn try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack> {
913        pkey.dh()
914    }
915}
916
917#[cfg(test)]
918mod tests {
919    use std::convert::TryInto;
920
921    #[cfg(not(boringssl))]
922    use crate::dh::Dh;
923    use crate::dsa::Dsa;
924    use crate::ec::EcKey;
925    use crate::error::Error;
926    use crate::nid::Nid;
927    use crate::rsa::Rsa;
928    use crate::symm::Cipher;
929
930    use super::*;
931
932    #[cfg(any(ossl111, awslc))]
933    use crate::rand::rand_bytes;
934
935    #[test]
936    fn test_to_password() {
937        let rsa = Rsa::generate(2048).unwrap();
938        let pkey = PKey::from_rsa(rsa).unwrap();
939        let pem = pkey
940            .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar")
941            .unwrap();
942        PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
943        assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
944    }
945
946    #[test]
947    fn test_unencrypted_pkcs8() {
948        let key = include_bytes!("../test/pkcs8-nocrypt.der");
949        let pkey = PKey::private_key_from_pkcs8(key).unwrap();
950        let serialized = pkey.private_key_to_pkcs8().unwrap();
951        let pkey2 = PKey::private_key_from_pkcs8(&serialized).unwrap();
952
953        assert_eq!(
954            pkey2.private_key_to_der().unwrap(),
955            pkey.private_key_to_der().unwrap()
956        );
957    }
958
959    #[test]
960    fn test_encrypted_pkcs8_passphrase() {
961        let key = include_bytes!("../test/pkcs8.der");
962        PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap();
963
964        let rsa = Rsa::generate(2048).unwrap();
965        let pkey = PKey::from_rsa(rsa).unwrap();
966        let der = pkey
967            .private_key_to_pkcs8_passphrase(Cipher::aes_128_cbc(), b"mypass")
968            .unwrap();
969        let pkey2 = PKey::private_key_from_pkcs8_passphrase(&der, b"mypass").unwrap();
970        assert_eq!(
971            pkey.private_key_to_der().unwrap(),
972            pkey2.private_key_to_der().unwrap()
973        );
974    }
975
976    #[test]
977    fn test_encrypted_pkcs8_callback() {
978        let mut password_queried = false;
979        let key = include_bytes!("../test/pkcs8.der");
980        PKey::private_key_from_pkcs8_callback(key, |password| {
981            password_queried = true;
982            password[..6].copy_from_slice(b"mypass");
983            Ok(6)
984        })
985        .unwrap();
986        assert!(password_queried);
987    }
988
989    #[test]
990    fn test_private_key_from_pem() {
991        let key = include_bytes!("../test/key.pem");
992        PKey::private_key_from_pem(key).unwrap();
993    }
994
995    #[test]
996    fn test_public_key_from_pem() {
997        let key = include_bytes!("../test/key.pem.pub");
998        PKey::public_key_from_pem(key).unwrap();
999    }
1000
1001    #[test]
1002    fn test_public_key_from_der() {
1003        let key = include_bytes!("../test/key.der.pub");
1004        PKey::public_key_from_der(key).unwrap();
1005    }
1006
1007    #[test]
1008    fn test_private_key_from_der() {
1009        let key = include_bytes!("../test/key.der");
1010        PKey::private_key_from_der(key).unwrap();
1011    }
1012
1013    #[test]
1014    fn test_pem() {
1015        let key = include_bytes!("../test/key.pem");
1016        let key = PKey::private_key_from_pem(key).unwrap();
1017
1018        let priv_key = key.private_key_to_pem_pkcs8().unwrap();
1019        let pub_key = key.public_key_to_pem().unwrap();
1020
1021        // As a super-simple verification, just check that the buffers contain
1022        // the `PRIVATE KEY` or `PUBLIC KEY` strings.
1023        assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY"));
1024        assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY"));
1025    }
1026
1027    #[test]
1028    fn test_rsa_accessor() {
1029        let rsa = Rsa::generate(2048).unwrap();
1030        let pkey = PKey::from_rsa(rsa).unwrap();
1031        pkey.rsa().unwrap();
1032        assert_eq!(pkey.id(), Id::RSA);
1033        assert!(pkey.dsa().is_err());
1034    }
1035
1036    #[test]
1037    fn test_dsa_accessor() {
1038        let dsa = Dsa::generate(2048).unwrap();
1039        let pkey = PKey::from_dsa(dsa).unwrap();
1040        pkey.dsa().unwrap();
1041        assert_eq!(pkey.id(), Id::DSA);
1042        assert!(pkey.rsa().is_err());
1043    }
1044
1045    #[test]
1046    #[cfg(not(boringssl))]
1047    fn test_dh_accessor() {
1048        let dh = include_bytes!("../test/dhparams.pem");
1049        let dh = Dh::params_from_pem(dh).unwrap();
1050        let pkey = PKey::from_dh(dh).unwrap();
1051        pkey.dh().unwrap();
1052        assert_eq!(pkey.id(), Id::DH);
1053        assert!(pkey.rsa().is_err());
1054    }
1055
1056    #[test]
1057    fn test_ec_key_accessor() {
1058        let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1059        let pkey = PKey::from_ec_key(ec_key).unwrap();
1060        pkey.ec_key().unwrap();
1061        assert_eq!(pkey.id(), Id::EC);
1062        assert!(pkey.rsa().is_err());
1063    }
1064
1065    #[test]
1066    fn test_rsa_conversion() {
1067        let rsa = Rsa::generate(2048).unwrap();
1068        let pkey: PKey<Private> = rsa.clone().try_into().unwrap();
1069        let rsa_: Rsa<Private> = pkey.try_into().unwrap();
1070        // Eq is missing
1071        assert_eq!(rsa.p(), rsa_.p());
1072        assert_eq!(rsa.q(), rsa_.q());
1073    }
1074
1075    #[test]
1076    fn test_dsa_conversion() {
1077        let dsa = Dsa::generate(2048).unwrap();
1078        let pkey: PKey<Private> = dsa.clone().try_into().unwrap();
1079        let dsa_: Dsa<Private> = pkey.try_into().unwrap();
1080        // Eq is missing
1081        assert_eq!(dsa.priv_key(), dsa_.priv_key());
1082    }
1083
1084    #[test]
1085    fn test_ec_key_conversion() {
1086        let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap();
1087        let ec_key = EcKey::generate(&group).unwrap();
1088        let pkey: PKey<Private> = ec_key.clone().try_into().unwrap();
1089        let ec_key_: EcKey<Private> = pkey.try_into().unwrap();
1090        // Eq is missing
1091        assert_eq!(ec_key.private_key(), ec_key_.private_key());
1092    }
1093
1094    #[test]
1095    #[cfg(any(ossl110, libressl360))]
1096    fn test_security_bits() {
1097        let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::SECP521R1).unwrap();
1098        let ec_key = EcKey::generate(&group).unwrap();
1099        let pkey: PKey<Private> = ec_key.try_into().unwrap();
1100
1101        assert_eq!(pkey.security_bits(), 256);
1102    }
1103
1104    #[test]
1105    #[cfg(not(boringssl))]
1106    fn test_dh_conversion() {
1107        let dh_params = include_bytes!("../test/dhparams.pem");
1108        let dh_params = Dh::params_from_pem(dh_params).unwrap();
1109        let dh = dh_params.generate_key().unwrap();
1110
1111        // Clone is missing for Dh, save the parameters
1112        let p = dh.prime_p().to_owned().unwrap();
1113        let q = dh.prime_q().map(|q| q.to_owned().unwrap());
1114        let g = dh.generator().to_owned().unwrap();
1115
1116        let pkey: PKey<Private> = dh.try_into().unwrap();
1117        let dh_: Dh<Private> = pkey.try_into().unwrap();
1118
1119        // Eq is missing
1120        assert_eq!(&p, dh_.prime_p());
1121        assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap()));
1122        assert_eq!(&g, dh_.generator());
1123    }
1124
1125    #[cfg(any(ossl111, boringssl, libressl370, awslc))]
1126    fn test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
1127        // Generate a new key
1128        let key = gen().unwrap();
1129
1130        // Get the raw bytes, and create a new key from the raw bytes
1131        let raw = key.raw_public_key().unwrap();
1132        let from_raw = PKey::public_key_from_raw_bytes(&raw, key_type).unwrap();
1133
1134        // Compare the der encoding of the original and raw / restored public key
1135        assert_eq!(
1136            key.public_key_to_der().unwrap(),
1137            from_raw.public_key_to_der().unwrap()
1138        );
1139    }
1140
1141    #[cfg(any(ossl111, boringssl, libressl370, awslc))]
1142    fn test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
1143        // Generate a new key
1144        let key = gen().unwrap();
1145
1146        // Get the raw bytes, and create a new key from the raw bytes
1147        let raw = key.raw_private_key().unwrap();
1148        let from_raw = PKey::private_key_from_raw_bytes(&raw, key_type).unwrap();
1149
1150        // Compare the der encoding of the original and raw / restored public key
1151        assert_eq!(
1152            key.private_key_to_pkcs8().unwrap(),
1153            from_raw.private_key_to_pkcs8().unwrap()
1154        );
1155    }
1156
1157    #[cfg(any(ossl111, boringssl, libressl370, awslc))]
1158    #[test]
1159    fn test_raw_public_key_bytes() {
1160        test_raw_public_key(PKey::generate_x25519, Id::X25519);
1161        test_raw_public_key(PKey::generate_ed25519, Id::ED25519);
1162        #[cfg(not(any(boringssl, libressl370, awslc)))]
1163        test_raw_public_key(PKey::generate_x448, Id::X448);
1164        #[cfg(not(any(boringssl, libressl370, awslc)))]
1165        test_raw_public_key(PKey::generate_ed448, Id::ED448);
1166    }
1167
1168    #[cfg(any(ossl111, boringssl, libressl370, awslc))]
1169    #[test]
1170    fn test_raw_private_key_bytes() {
1171        test_raw_private_key(PKey::generate_x25519, Id::X25519);
1172        test_raw_private_key(PKey::generate_ed25519, Id::ED25519);
1173        #[cfg(not(any(boringssl, libressl370, awslc)))]
1174        test_raw_private_key(PKey::generate_x448, Id::X448);
1175        #[cfg(not(any(boringssl, libressl370, awslc)))]
1176        test_raw_private_key(PKey::generate_ed448, Id::ED448);
1177    }
1178
1179    #[cfg(any(ossl111, awslc))]
1180    #[test]
1181    fn test_raw_hmac() {
1182        let mut test_bytes = vec![0u8; 32];
1183        rand_bytes(&mut test_bytes).unwrap();
1184
1185        let hmac_key = PKey::hmac(&test_bytes).unwrap();
1186        assert!(hmac_key.raw_public_key().is_err());
1187
1188        let key_bytes = hmac_key.raw_private_key().unwrap();
1189        assert_eq!(key_bytes, test_bytes);
1190    }
1191
1192    #[cfg(any(ossl111, awslc))]
1193    #[test]
1194    fn test_raw_key_fail() {
1195        // Getting a raw byte representation will not work with Nist curves
1196        let group = crate::ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
1197        let ec_key = EcKey::generate(&group).unwrap();
1198        let pkey = PKey::from_ec_key(ec_key).unwrap();
1199        assert!(pkey.raw_private_key().is_err());
1200        assert!(pkey.raw_public_key().is_err());
1201    }
1202
1203    #[cfg(ossl300)]
1204    #[test]
1205    fn test_ec_gen() {
1206        let key = PKey::ec_gen("prime256v1").unwrap();
1207        assert!(key.ec_key().is_ok());
1208    }
1209
1210    #[test]
1211    fn test_public_eq() {
1212        let rsa = Rsa::generate(2048).unwrap();
1213        let pkey1 = PKey::from_rsa(rsa).unwrap();
1214
1215        let group = crate::ec::EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1216        let ec_key = EcKey::generate(&group).unwrap();
1217        let pkey2 = PKey::from_ec_key(ec_key).unwrap();
1218
1219        assert!(!pkey1.public_eq(&pkey2));
1220        assert!(Error::get().is_none());
1221    }
1222}