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