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