Coverage Report

Created: 2025-09-04 06:37

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