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