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