192f3ab15Sopenharmony_ci//! Public/private key processing.
292f3ab15Sopenharmony_ci//!
392f3ab15Sopenharmony_ci//! Asymmetric public key algorithms solve the problem of establishing and sharing
492f3ab15Sopenharmony_ci//! secret keys to securely send and receive messages.
592f3ab15Sopenharmony_ci//! This system uses a pair of keys: a public key, which can be freely
692f3ab15Sopenharmony_ci//! distributed, and a private key, which is kept to oneself. An entity may
792f3ab15Sopenharmony_ci//! encrypt information using a user's public key. The encrypted information can
892f3ab15Sopenharmony_ci//! only be deciphered using that user's private key.
992f3ab15Sopenharmony_ci//!
1092f3ab15Sopenharmony_ci//! This module offers support for five popular algorithms:
1192f3ab15Sopenharmony_ci//!
1292f3ab15Sopenharmony_ci//! * RSA
1392f3ab15Sopenharmony_ci//!
1492f3ab15Sopenharmony_ci//! * DSA
1592f3ab15Sopenharmony_ci//!
1692f3ab15Sopenharmony_ci//! * Diffie-Hellman
1792f3ab15Sopenharmony_ci//!
1892f3ab15Sopenharmony_ci//! * Elliptic Curves
1992f3ab15Sopenharmony_ci//!
2092f3ab15Sopenharmony_ci//! * HMAC
2192f3ab15Sopenharmony_ci//!
2292f3ab15Sopenharmony_ci//! These algorithms rely on hard mathematical problems - namely integer factorization,
2392f3ab15Sopenharmony_ci//! discrete logarithms, and elliptic curve relationships - that currently do not
2492f3ab15Sopenharmony_ci//! yield efficient solutions. This property ensures the security of these
2592f3ab15Sopenharmony_ci//! cryptographic algorithms.
2692f3ab15Sopenharmony_ci//!
2792f3ab15Sopenharmony_ci//! # Example
2892f3ab15Sopenharmony_ci//!
2992f3ab15Sopenharmony_ci//! Generate a 2048-bit RSA public/private key pair and print the public key.
3092f3ab15Sopenharmony_ci//!
3192f3ab15Sopenharmony_ci//! ```rust
3292f3ab15Sopenharmony_ci//! use openssl::rsa::Rsa;
3392f3ab15Sopenharmony_ci//! use openssl::pkey::PKey;
3492f3ab15Sopenharmony_ci//! use std::str;
3592f3ab15Sopenharmony_ci//!
3692f3ab15Sopenharmony_ci//! let rsa = Rsa::generate(2048).unwrap();
3792f3ab15Sopenharmony_ci//! let pkey = PKey::from_rsa(rsa).unwrap();
3892f3ab15Sopenharmony_ci//!
3992f3ab15Sopenharmony_ci//! let pub_key: Vec<u8> = pkey.public_key_to_pem().unwrap();
4092f3ab15Sopenharmony_ci//! println!("{:?}", str::from_utf8(pub_key.as_slice()).unwrap());
4192f3ab15Sopenharmony_ci//! ```
4292f3ab15Sopenharmony_ci#![allow(clippy::missing_safety_doc)]
4392f3ab15Sopenharmony_ciuse crate::bio::{MemBio, MemBioSlice};
4492f3ab15Sopenharmony_ci#[cfg(ossl110)]
4592f3ab15Sopenharmony_ciuse crate::cipher::CipherRef;
4692f3ab15Sopenharmony_ciuse crate::dh::Dh;
4792f3ab15Sopenharmony_ciuse crate::dsa::Dsa;
4892f3ab15Sopenharmony_ciuse crate::ec::EcKey;
4992f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
5092f3ab15Sopenharmony_ci#[cfg(any(ossl110, boringssl, libressl370))]
5192f3ab15Sopenharmony_ciuse crate::pkey_ctx::PkeyCtx;
5292f3ab15Sopenharmony_ciuse crate::rsa::Rsa;
5392f3ab15Sopenharmony_ciuse crate::symm::Cipher;
5492f3ab15Sopenharmony_ciuse crate::util::{invoke_passwd_cb, CallbackState};
5592f3ab15Sopenharmony_ciuse crate::{cvt, cvt_p};
5692f3ab15Sopenharmony_ciuse cfg_if::cfg_if;
5792f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef};
5892f3ab15Sopenharmony_ciuse libc::{c_int, c_long};
5992f3ab15Sopenharmony_ciuse openssl_macros::corresponds;
6092f3ab15Sopenharmony_ciuse std::convert::{TryFrom, TryInto};
6192f3ab15Sopenharmony_ciuse std::ffi::CString;
6292f3ab15Sopenharmony_ciuse std::fmt;
6392f3ab15Sopenharmony_ciuse std::mem;
6492f3ab15Sopenharmony_ciuse std::ptr;
6592f3ab15Sopenharmony_ci
6692f3ab15Sopenharmony_ci/// A tag type indicating that a key only has parameters.
6792f3ab15Sopenharmony_cipub enum Params {}
6892f3ab15Sopenharmony_ci
6992f3ab15Sopenharmony_ci/// A tag type indicating that a key only has public components.
7092f3ab15Sopenharmony_cipub enum Public {}
7192f3ab15Sopenharmony_ci
7292f3ab15Sopenharmony_ci/// A tag type indicating that a key has private components.
7392f3ab15Sopenharmony_cipub enum Private {}
7492f3ab15Sopenharmony_ci
7592f3ab15Sopenharmony_ci/// An identifier of a kind of key.
7692f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7792f3ab15Sopenharmony_cipub struct Id(c_int);
7892f3ab15Sopenharmony_ci
7992f3ab15Sopenharmony_ciimpl Id {
8092f3ab15Sopenharmony_ci    pub const RSA: Id = Id(ffi::EVP_PKEY_RSA);
8192f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
8292f3ab15Sopenharmony_ci    pub const HMAC: Id = Id(ffi::EVP_PKEY_HMAC);
8392f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
8492f3ab15Sopenharmony_ci    pub const CMAC: Id = Id(ffi::EVP_PKEY_CMAC);
8592f3ab15Sopenharmony_ci    pub const DSA: Id = Id(ffi::EVP_PKEY_DSA);
8692f3ab15Sopenharmony_ci    pub const DH: Id = Id(ffi::EVP_PKEY_DH);
8792f3ab15Sopenharmony_ci    pub const EC: Id = Id(ffi::EVP_PKEY_EC);
8892f3ab15Sopenharmony_ci    #[cfg(ossl111)]
8992f3ab15Sopenharmony_ci    pub const SM2: Id = Id(ffi::EVP_PKEY_SM2);
9092f3ab15Sopenharmony_ci
9192f3ab15Sopenharmony_ci    #[cfg(any(ossl110, boringssl))]
9292f3ab15Sopenharmony_ci    pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF);
9392f3ab15Sopenharmony_ci
9492f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
9592f3ab15Sopenharmony_ci    pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519);
9692f3ab15Sopenharmony_ci    #[cfg(ossl111)]
9792f3ab15Sopenharmony_ci    pub const ED448: Id = Id(ffi::EVP_PKEY_ED448);
9892f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
9992f3ab15Sopenharmony_ci    pub const X25519: Id = Id(ffi::EVP_PKEY_X25519);
10092f3ab15Sopenharmony_ci    #[cfg(ossl111)]
10192f3ab15Sopenharmony_ci    pub const X448: Id = Id(ffi::EVP_PKEY_X448);
10292f3ab15Sopenharmony_ci    #[cfg(ossl111)]
10392f3ab15Sopenharmony_ci    pub const POLY1305: Id = Id(ffi::EVP_PKEY_POLY1305);
10492f3ab15Sopenharmony_ci
10592f3ab15Sopenharmony_ci    /// Creates a `Id` from an integer representation.
10692f3ab15Sopenharmony_ci    pub fn from_raw(value: c_int) -> Id {
10792f3ab15Sopenharmony_ci        Id(value)
10892f3ab15Sopenharmony_ci    }
10992f3ab15Sopenharmony_ci
11092f3ab15Sopenharmony_ci    /// Returns the integer representation of the `Id`.
11192f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
11292f3ab15Sopenharmony_ci    pub fn as_raw(&self) -> c_int {
11392f3ab15Sopenharmony_ci        self.0
11492f3ab15Sopenharmony_ci    }
11592f3ab15Sopenharmony_ci}
11692f3ab15Sopenharmony_ci
11792f3ab15Sopenharmony_ci/// A trait indicating that a key has parameters.
11892f3ab15Sopenharmony_cipub unsafe trait HasParams {}
11992f3ab15Sopenharmony_ci
12092f3ab15Sopenharmony_ciunsafe impl HasParams for Params {}
12192f3ab15Sopenharmony_ci
12292f3ab15Sopenharmony_ciunsafe impl<T> HasParams for T where T: HasPublic {}
12392f3ab15Sopenharmony_ci
12492f3ab15Sopenharmony_ci/// A trait indicating that a key has public components.
12592f3ab15Sopenharmony_cipub unsafe trait HasPublic {}
12692f3ab15Sopenharmony_ci
12792f3ab15Sopenharmony_ciunsafe impl HasPublic for Public {}
12892f3ab15Sopenharmony_ci
12992f3ab15Sopenharmony_ciunsafe impl<T> HasPublic for T where T: HasPrivate {}
13092f3ab15Sopenharmony_ci
13192f3ab15Sopenharmony_ci/// A trait indicating that a key has private components.
13292f3ab15Sopenharmony_cipub unsafe trait HasPrivate {}
13392f3ab15Sopenharmony_ci
13492f3ab15Sopenharmony_ciunsafe impl HasPrivate for Private {}
13592f3ab15Sopenharmony_ci
13692f3ab15Sopenharmony_cigeneric_foreign_type_and_impl_send_sync! {
13792f3ab15Sopenharmony_ci    type CType = ffi::EVP_PKEY;
13892f3ab15Sopenharmony_ci    fn drop = ffi::EVP_PKEY_free;
13992f3ab15Sopenharmony_ci
14092f3ab15Sopenharmony_ci    /// A public or private key.
14192f3ab15Sopenharmony_ci    pub struct PKey<T>;
14292f3ab15Sopenharmony_ci    /// Reference to `PKey`.
14392f3ab15Sopenharmony_ci    pub struct PKeyRef<T>;
14492f3ab15Sopenharmony_ci}
14592f3ab15Sopenharmony_ci
14692f3ab15Sopenharmony_ciimpl<T> ToOwned for PKeyRef<T> {
14792f3ab15Sopenharmony_ci    type Owned = PKey<T>;
14892f3ab15Sopenharmony_ci
14992f3ab15Sopenharmony_ci    fn to_owned(&self) -> PKey<T> {
15092f3ab15Sopenharmony_ci        unsafe {
15192f3ab15Sopenharmony_ci            EVP_PKEY_up_ref(self.as_ptr());
15292f3ab15Sopenharmony_ci            PKey::from_ptr(self.as_ptr())
15392f3ab15Sopenharmony_ci        }
15492f3ab15Sopenharmony_ci    }
15592f3ab15Sopenharmony_ci}
15692f3ab15Sopenharmony_ci
15792f3ab15Sopenharmony_ciimpl<T> PKeyRef<T> {
15892f3ab15Sopenharmony_ci    /// Returns a copy of the internal RSA key.
15992f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_get1_RSA)]
16092f3ab15Sopenharmony_ci    pub fn rsa(&self) -> Result<Rsa<T>, ErrorStack> {
16192f3ab15Sopenharmony_ci        unsafe {
16292f3ab15Sopenharmony_ci            let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?;
16392f3ab15Sopenharmony_ci            Ok(Rsa::from_ptr(rsa))
16492f3ab15Sopenharmony_ci        }
16592f3ab15Sopenharmony_ci    }
16692f3ab15Sopenharmony_ci
16792f3ab15Sopenharmony_ci    /// Returns a copy of the internal DSA key.
16892f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_get1_DSA)]
16992f3ab15Sopenharmony_ci    pub fn dsa(&self) -> Result<Dsa<T>, ErrorStack> {
17092f3ab15Sopenharmony_ci        unsafe {
17192f3ab15Sopenharmony_ci            let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?;
17292f3ab15Sopenharmony_ci            Ok(Dsa::from_ptr(dsa))
17392f3ab15Sopenharmony_ci        }
17492f3ab15Sopenharmony_ci    }
17592f3ab15Sopenharmony_ci
17692f3ab15Sopenharmony_ci    /// Returns a copy of the internal DH key.
17792f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_get1_DH)]
17892f3ab15Sopenharmony_ci    pub fn dh(&self) -> Result<Dh<T>, ErrorStack> {
17992f3ab15Sopenharmony_ci        unsafe {
18092f3ab15Sopenharmony_ci            let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?;
18192f3ab15Sopenharmony_ci            Ok(Dh::from_ptr(dh))
18292f3ab15Sopenharmony_ci        }
18392f3ab15Sopenharmony_ci    }
18492f3ab15Sopenharmony_ci
18592f3ab15Sopenharmony_ci    /// Returns a copy of the internal elliptic curve key.
18692f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_get1_EC_KEY)]
18792f3ab15Sopenharmony_ci    pub fn ec_key(&self) -> Result<EcKey<T>, ErrorStack> {
18892f3ab15Sopenharmony_ci        unsafe {
18992f3ab15Sopenharmony_ci            let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?;
19092f3ab15Sopenharmony_ci            Ok(EcKey::from_ptr(ec_key))
19192f3ab15Sopenharmony_ci        }
19292f3ab15Sopenharmony_ci    }
19392f3ab15Sopenharmony_ci
19492f3ab15Sopenharmony_ci    /// Returns the `Id` that represents the type of this key.
19592f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_id)]
19692f3ab15Sopenharmony_ci    pub fn id(&self) -> Id {
19792f3ab15Sopenharmony_ci        unsafe { Id::from_raw(ffi::EVP_PKEY_id(self.as_ptr())) }
19892f3ab15Sopenharmony_ci    }
19992f3ab15Sopenharmony_ci
20092f3ab15Sopenharmony_ci    /// Returns the maximum size of a signature in bytes.
20192f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_size)]
20292f3ab15Sopenharmony_ci    pub fn size(&self) -> usize {
20392f3ab15Sopenharmony_ci        unsafe { ffi::EVP_PKEY_size(self.as_ptr()) as usize }
20492f3ab15Sopenharmony_ci    }
20592f3ab15Sopenharmony_ci}
20692f3ab15Sopenharmony_ci
20792f3ab15Sopenharmony_ciimpl<T> PKeyRef<T>
20892f3ab15Sopenharmony_ciwhere
20992f3ab15Sopenharmony_ci    T: HasPublic,
21092f3ab15Sopenharmony_ci{
21192f3ab15Sopenharmony_ci    to_pem! {
21292f3ab15Sopenharmony_ci        /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
21392f3ab15Sopenharmony_ci        ///
21492f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
21592f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_PUBKEY)]
21692f3ab15Sopenharmony_ci        public_key_to_pem,
21792f3ab15Sopenharmony_ci        ffi::PEM_write_bio_PUBKEY
21892f3ab15Sopenharmony_ci    }
21992f3ab15Sopenharmony_ci
22092f3ab15Sopenharmony_ci    to_der! {
22192f3ab15Sopenharmony_ci        /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
22292f3ab15Sopenharmony_ci        #[corresponds(i2d_PUBKEY)]
22392f3ab15Sopenharmony_ci        public_key_to_der,
22492f3ab15Sopenharmony_ci        ffi::i2d_PUBKEY
22592f3ab15Sopenharmony_ci    }
22692f3ab15Sopenharmony_ci
22792f3ab15Sopenharmony_ci    /// Returns the size of the key.
22892f3ab15Sopenharmony_ci    ///
22992f3ab15Sopenharmony_ci    /// This corresponds to the bit length of the modulus of an RSA key, and the bit length of the
23092f3ab15Sopenharmony_ci    /// group order for an elliptic curve key, for example.
23192f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_bits)]
23292f3ab15Sopenharmony_ci    pub fn bits(&self) -> u32 {
23392f3ab15Sopenharmony_ci        unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 }
23492f3ab15Sopenharmony_ci    }
23592f3ab15Sopenharmony_ci
23692f3ab15Sopenharmony_ci    ///Returns the number of security bits.
23792f3ab15Sopenharmony_ci    ///
23892f3ab15Sopenharmony_ci    ///Bits of security is defined in NIST SP800-57.
23992f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_security_bits)]
24092f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl360))]
24192f3ab15Sopenharmony_ci    pub fn security_bits(&self) -> u32 {
24292f3ab15Sopenharmony_ci        unsafe { ffi::EVP_PKEY_security_bits(self.as_ptr()) as u32 }
24392f3ab15Sopenharmony_ci    }
24492f3ab15Sopenharmony_ci
24592f3ab15Sopenharmony_ci    /// Compares the public component of this key with another.
24692f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_cmp)]
24792f3ab15Sopenharmony_ci    pub fn public_eq<U>(&self, other: &PKeyRef<U>) -> bool
24892f3ab15Sopenharmony_ci    where
24992f3ab15Sopenharmony_ci        U: HasPublic,
25092f3ab15Sopenharmony_ci    {
25192f3ab15Sopenharmony_ci        let res = unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 };
25292f3ab15Sopenharmony_ci        // Clear the stack. OpenSSL will put an error on the stack when the
25392f3ab15Sopenharmony_ci        // keys are different types in some situations.
25492f3ab15Sopenharmony_ci        let _ = ErrorStack::get();
25592f3ab15Sopenharmony_ci        res
25692f3ab15Sopenharmony_ci    }
25792f3ab15Sopenharmony_ci
25892f3ab15Sopenharmony_ci    /// Raw byte representation of a public key.
25992f3ab15Sopenharmony_ci    ///
26092f3ab15Sopenharmony_ci    /// This function only works for algorithms that support raw public keys.
26192f3ab15Sopenharmony_ci    /// Currently this is: [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`].
26292f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_get_raw_public_key)]
26392f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
26492f3ab15Sopenharmony_ci    pub fn raw_public_key(&self) -> Result<Vec<u8>, ErrorStack> {
26592f3ab15Sopenharmony_ci        unsafe {
26692f3ab15Sopenharmony_ci            let mut len = 0;
26792f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_get_raw_public_key(
26892f3ab15Sopenharmony_ci                self.as_ptr(),
26992f3ab15Sopenharmony_ci                ptr::null_mut(),
27092f3ab15Sopenharmony_ci                &mut len,
27192f3ab15Sopenharmony_ci            ))?;
27292f3ab15Sopenharmony_ci            let mut buf = vec![0u8; len];
27392f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_get_raw_public_key(
27492f3ab15Sopenharmony_ci                self.as_ptr(),
27592f3ab15Sopenharmony_ci                buf.as_mut_ptr(),
27692f3ab15Sopenharmony_ci                &mut len,
27792f3ab15Sopenharmony_ci            ))?;
27892f3ab15Sopenharmony_ci            buf.truncate(len);
27992f3ab15Sopenharmony_ci            Ok(buf)
28092f3ab15Sopenharmony_ci        }
28192f3ab15Sopenharmony_ci    }
28292f3ab15Sopenharmony_ci}
28392f3ab15Sopenharmony_ci
28492f3ab15Sopenharmony_ciimpl<T> PKeyRef<T>
28592f3ab15Sopenharmony_ciwhere
28692f3ab15Sopenharmony_ci    T: HasPrivate,
28792f3ab15Sopenharmony_ci{
28892f3ab15Sopenharmony_ci    private_key_to_pem! {
28992f3ab15Sopenharmony_ci        /// Serializes the private key to a PEM-encoded PKCS#8 PrivateKeyInfo structure.
29092f3ab15Sopenharmony_ci        ///
29192f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN PRIVATE KEY-----`.
29292f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
29392f3ab15Sopenharmony_ci        private_key_to_pem_pkcs8,
29492f3ab15Sopenharmony_ci        /// Serializes the private key to a PEM-encoded PKCS#8 EncryptedPrivateKeyInfo structure.
29592f3ab15Sopenharmony_ci        ///
29692f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN ENCRYPTED PRIVATE KEY-----`.
29792f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
29892f3ab15Sopenharmony_ci        private_key_to_pem_pkcs8_passphrase,
29992f3ab15Sopenharmony_ci        ffi::PEM_write_bio_PKCS8PrivateKey
30092f3ab15Sopenharmony_ci    }
30192f3ab15Sopenharmony_ci
30292f3ab15Sopenharmony_ci    to_der! {
30392f3ab15Sopenharmony_ci        /// Serializes the private key to a DER-encoded key type specific format.
30492f3ab15Sopenharmony_ci        #[corresponds(i2d_PrivateKey)]
30592f3ab15Sopenharmony_ci        private_key_to_der,
30692f3ab15Sopenharmony_ci        ffi::i2d_PrivateKey
30792f3ab15Sopenharmony_ci    }
30892f3ab15Sopenharmony_ci
30992f3ab15Sopenharmony_ci    /// Raw byte representation of a private key.
31092f3ab15Sopenharmony_ci    ///
31192f3ab15Sopenharmony_ci    /// This function only works for algorithms that support raw private keys.
31292f3ab15Sopenharmony_ci    /// Currently this is: [`Id::HMAC`], [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`].
31392f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_get_raw_private_key)]
31492f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
31592f3ab15Sopenharmony_ci    pub fn raw_private_key(&self) -> Result<Vec<u8>, ErrorStack> {
31692f3ab15Sopenharmony_ci        unsafe {
31792f3ab15Sopenharmony_ci            let mut len = 0;
31892f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_get_raw_private_key(
31992f3ab15Sopenharmony_ci                self.as_ptr(),
32092f3ab15Sopenharmony_ci                ptr::null_mut(),
32192f3ab15Sopenharmony_ci                &mut len,
32292f3ab15Sopenharmony_ci            ))?;
32392f3ab15Sopenharmony_ci            let mut buf = vec![0u8; len];
32492f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_get_raw_private_key(
32592f3ab15Sopenharmony_ci                self.as_ptr(),
32692f3ab15Sopenharmony_ci                buf.as_mut_ptr(),
32792f3ab15Sopenharmony_ci                &mut len,
32892f3ab15Sopenharmony_ci            ))?;
32992f3ab15Sopenharmony_ci            buf.truncate(len);
33092f3ab15Sopenharmony_ci            Ok(buf)
33192f3ab15Sopenharmony_ci        }
33292f3ab15Sopenharmony_ci    }
33392f3ab15Sopenharmony_ci
33492f3ab15Sopenharmony_ci    /// Serializes a private key into an unencrypted DER-formatted PKCS#8
33592f3ab15Sopenharmony_ci    #[corresponds(i2d_PKCS8PrivateKey_bio)]
33692f3ab15Sopenharmony_ci    pub fn private_key_to_pkcs8(&self) -> Result<Vec<u8>, ErrorStack> {
33792f3ab15Sopenharmony_ci        unsafe {
33892f3ab15Sopenharmony_ci            let bio = MemBio::new()?;
33992f3ab15Sopenharmony_ci            cvt(ffi::i2d_PKCS8PrivateKey_bio(
34092f3ab15Sopenharmony_ci                bio.as_ptr(),
34192f3ab15Sopenharmony_ci                self.as_ptr(),
34292f3ab15Sopenharmony_ci                ptr::null(),
34392f3ab15Sopenharmony_ci                ptr::null_mut(),
34492f3ab15Sopenharmony_ci                0,
34592f3ab15Sopenharmony_ci                None,
34692f3ab15Sopenharmony_ci                ptr::null_mut(),
34792f3ab15Sopenharmony_ci            ))?;
34892f3ab15Sopenharmony_ci
34992f3ab15Sopenharmony_ci            Ok(bio.get_buf().to_owned())
35092f3ab15Sopenharmony_ci        }
35192f3ab15Sopenharmony_ci    }
35292f3ab15Sopenharmony_ci
35392f3ab15Sopenharmony_ci    /// Serializes a private key into a DER-formatted PKCS#8, using the supplied password to
35492f3ab15Sopenharmony_ci    /// encrypt the key.
35592f3ab15Sopenharmony_ci    #[corresponds(i2d_PKCS8PrivateKey_bio)]
35692f3ab15Sopenharmony_ci    pub fn private_key_to_pkcs8_passphrase(
35792f3ab15Sopenharmony_ci        &self,
35892f3ab15Sopenharmony_ci        cipher: Cipher,
35992f3ab15Sopenharmony_ci        passphrase: &[u8],
36092f3ab15Sopenharmony_ci    ) -> Result<Vec<u8>, ErrorStack> {
36192f3ab15Sopenharmony_ci        unsafe {
36292f3ab15Sopenharmony_ci            let bio = MemBio::new()?;
36392f3ab15Sopenharmony_ci            cvt(ffi::i2d_PKCS8PrivateKey_bio(
36492f3ab15Sopenharmony_ci                bio.as_ptr(),
36592f3ab15Sopenharmony_ci                self.as_ptr(),
36692f3ab15Sopenharmony_ci                cipher.as_ptr(),
36792f3ab15Sopenharmony_ci                passphrase.as_ptr() as *const _ as *mut _,
36892f3ab15Sopenharmony_ci                passphrase.len().try_into().unwrap(),
36992f3ab15Sopenharmony_ci                None,
37092f3ab15Sopenharmony_ci                ptr::null_mut(),
37192f3ab15Sopenharmony_ci            ))?;
37292f3ab15Sopenharmony_ci
37392f3ab15Sopenharmony_ci            Ok(bio.get_buf().to_owned())
37492f3ab15Sopenharmony_ci        }
37592f3ab15Sopenharmony_ci    }
37692f3ab15Sopenharmony_ci}
37792f3ab15Sopenharmony_ci
37892f3ab15Sopenharmony_ciimpl<T> fmt::Debug for PKey<T> {
37992f3ab15Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
38092f3ab15Sopenharmony_ci        let alg = match self.id() {
38192f3ab15Sopenharmony_ci            Id::RSA => "RSA",
38292f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
38392f3ab15Sopenharmony_ci            Id::HMAC => "HMAC",
38492f3ab15Sopenharmony_ci            Id::DSA => "DSA",
38592f3ab15Sopenharmony_ci            Id::DH => "DH",
38692f3ab15Sopenharmony_ci            Id::EC => "EC",
38792f3ab15Sopenharmony_ci            #[cfg(ossl111)]
38892f3ab15Sopenharmony_ci            Id::ED25519 => "Ed25519",
38992f3ab15Sopenharmony_ci            #[cfg(ossl111)]
39092f3ab15Sopenharmony_ci            Id::ED448 => "Ed448",
39192f3ab15Sopenharmony_ci            _ => "unknown",
39292f3ab15Sopenharmony_ci        };
39392f3ab15Sopenharmony_ci        fmt.debug_struct("PKey").field("algorithm", &alg).finish()
39492f3ab15Sopenharmony_ci        // TODO: Print details for each specific type of key
39592f3ab15Sopenharmony_ci    }
39692f3ab15Sopenharmony_ci}
39792f3ab15Sopenharmony_ci
39892f3ab15Sopenharmony_ciimpl<T> Clone for PKey<T> {
39992f3ab15Sopenharmony_ci    fn clone(&self) -> PKey<T> {
40092f3ab15Sopenharmony_ci        PKeyRef::to_owned(self)
40192f3ab15Sopenharmony_ci    }
40292f3ab15Sopenharmony_ci}
40392f3ab15Sopenharmony_ci
40492f3ab15Sopenharmony_ciimpl<T> PKey<T> {
40592f3ab15Sopenharmony_ci    /// Creates a new `PKey` containing an RSA key.
40692f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_assign_RSA)]
40792f3ab15Sopenharmony_ci    pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
40892f3ab15Sopenharmony_ci        unsafe {
40992f3ab15Sopenharmony_ci            let evp = cvt_p(ffi::EVP_PKEY_new())?;
41092f3ab15Sopenharmony_ci            let pkey = PKey::from_ptr(evp);
41192f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_assign_RSA(pkey.0, rsa.as_ptr()))?;
41292f3ab15Sopenharmony_ci            mem::forget(rsa);
41392f3ab15Sopenharmony_ci            Ok(pkey)
41492f3ab15Sopenharmony_ci        }
41592f3ab15Sopenharmony_ci    }
41692f3ab15Sopenharmony_ci
41792f3ab15Sopenharmony_ci    /// Creates a new `PKey` containing a DSA key.
41892f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_assign_DSA)]
41992f3ab15Sopenharmony_ci    pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
42092f3ab15Sopenharmony_ci        unsafe {
42192f3ab15Sopenharmony_ci            let evp = cvt_p(ffi::EVP_PKEY_new())?;
42292f3ab15Sopenharmony_ci            let pkey = PKey::from_ptr(evp);
42392f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_assign_DSA(pkey.0, dsa.as_ptr()))?;
42492f3ab15Sopenharmony_ci            mem::forget(dsa);
42592f3ab15Sopenharmony_ci            Ok(pkey)
42692f3ab15Sopenharmony_ci        }
42792f3ab15Sopenharmony_ci    }
42892f3ab15Sopenharmony_ci
42992f3ab15Sopenharmony_ci    /// Creates a new `PKey` containing a Diffie-Hellman key.
43092f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_assign_DH)]
43192f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
43292f3ab15Sopenharmony_ci    pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
43392f3ab15Sopenharmony_ci        unsafe {
43492f3ab15Sopenharmony_ci            let evp = cvt_p(ffi::EVP_PKEY_new())?;
43592f3ab15Sopenharmony_ci            let pkey = PKey::from_ptr(evp);
43692f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_assign_DH(pkey.0, dh.as_ptr()))?;
43792f3ab15Sopenharmony_ci            mem::forget(dh);
43892f3ab15Sopenharmony_ci            Ok(pkey)
43992f3ab15Sopenharmony_ci        }
44092f3ab15Sopenharmony_ci    }
44192f3ab15Sopenharmony_ci
44292f3ab15Sopenharmony_ci    /// Creates a new `PKey` containing an elliptic curve key.
44392f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_assign_EC_KEY)]
44492f3ab15Sopenharmony_ci    pub fn from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
44592f3ab15Sopenharmony_ci        unsafe {
44692f3ab15Sopenharmony_ci            let evp = cvt_p(ffi::EVP_PKEY_new())?;
44792f3ab15Sopenharmony_ci            let pkey = PKey::from_ptr(evp);
44892f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_assign_EC_KEY(pkey.0, ec_key.as_ptr()))?;
44992f3ab15Sopenharmony_ci            mem::forget(ec_key);
45092f3ab15Sopenharmony_ci            Ok(pkey)
45192f3ab15Sopenharmony_ci        }
45292f3ab15Sopenharmony_ci    }
45392f3ab15Sopenharmony_ci}
45492f3ab15Sopenharmony_ci
45592f3ab15Sopenharmony_ciimpl PKey<Private> {
45692f3ab15Sopenharmony_ci    /// Creates a new `PKey` containing an HMAC key.
45792f3ab15Sopenharmony_ci    ///
45892f3ab15Sopenharmony_ci    /// # Note
45992f3ab15Sopenharmony_ci    ///
46092f3ab15Sopenharmony_ci    /// To compute HMAC values, use the `sign` module.
46192f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_new_mac_key)]
46292f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
46392f3ab15Sopenharmony_ci    pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
46492f3ab15Sopenharmony_ci        unsafe {
46592f3ab15Sopenharmony_ci            assert!(key.len() <= c_int::max_value() as usize);
46692f3ab15Sopenharmony_ci            let key = cvt_p(ffi::EVP_PKEY_new_mac_key(
46792f3ab15Sopenharmony_ci                ffi::EVP_PKEY_HMAC,
46892f3ab15Sopenharmony_ci                ptr::null_mut(),
46992f3ab15Sopenharmony_ci                key.as_ptr() as *const _,
47092f3ab15Sopenharmony_ci                key.len() as c_int,
47192f3ab15Sopenharmony_ci            ))?;
47292f3ab15Sopenharmony_ci            Ok(PKey::from_ptr(key))
47392f3ab15Sopenharmony_ci        }
47492f3ab15Sopenharmony_ci    }
47592f3ab15Sopenharmony_ci
47692f3ab15Sopenharmony_ci    /// Creates a new `PKey` containing a CMAC key.
47792f3ab15Sopenharmony_ci    ///
47892f3ab15Sopenharmony_ci    /// Requires OpenSSL 1.1.0 or newer.
47992f3ab15Sopenharmony_ci    ///
48092f3ab15Sopenharmony_ci    /// # Note
48192f3ab15Sopenharmony_ci    ///
48292f3ab15Sopenharmony_ci    /// To compute CMAC values, use the `sign` module.
48392f3ab15Sopenharmony_ci    #[cfg(all(not(boringssl), ossl110))]
48492f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
48592f3ab15Sopenharmony_ci    pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
48692f3ab15Sopenharmony_ci        let mut ctx = PkeyCtx::new_id(Id::CMAC)?;
48792f3ab15Sopenharmony_ci        ctx.keygen_init()?;
48892f3ab15Sopenharmony_ci        ctx.set_keygen_cipher(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) })?;
48992f3ab15Sopenharmony_ci        ctx.set_keygen_mac_key(key)?;
49092f3ab15Sopenharmony_ci        ctx.keygen()
49192f3ab15Sopenharmony_ci    }
49292f3ab15Sopenharmony_ci
49392f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
49492f3ab15Sopenharmony_ci    fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> {
49592f3ab15Sopenharmony_ci        let mut ctx = PkeyCtx::new_id(id)?;
49692f3ab15Sopenharmony_ci        ctx.keygen_init()?;
49792f3ab15Sopenharmony_ci        ctx.keygen()
49892f3ab15Sopenharmony_ci    }
49992f3ab15Sopenharmony_ci
50092f3ab15Sopenharmony_ci    /// Generates a new private X25519 key.
50192f3ab15Sopenharmony_ci    ///
50292f3ab15Sopenharmony_ci    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
50392f3ab15Sopenharmony_ci    ///
50492f3ab15Sopenharmony_ci    /// # Examples
50592f3ab15Sopenharmony_ci    ///
50692f3ab15Sopenharmony_ci    /// ```
50792f3ab15Sopenharmony_ci    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
50892f3ab15Sopenharmony_ci    /// use openssl::pkey::{PKey, Id};
50992f3ab15Sopenharmony_ci    /// use openssl::derive::Deriver;
51092f3ab15Sopenharmony_ci    ///
51192f3ab15Sopenharmony_ci    /// let public = // ...
51292f3ab15Sopenharmony_ci    /// # &PKey::generate_x25519()?.raw_public_key()?;
51392f3ab15Sopenharmony_ci    /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X25519)?;
51492f3ab15Sopenharmony_ci    ///
51592f3ab15Sopenharmony_ci    /// let key = PKey::generate_x25519()?;
51692f3ab15Sopenharmony_ci    /// let mut deriver = Deriver::new(&key)?;
51792f3ab15Sopenharmony_ci    /// deriver.set_peer(&public_key)?;
51892f3ab15Sopenharmony_ci    ///
51992f3ab15Sopenharmony_ci    /// let secret = deriver.derive_to_vec()?;
52092f3ab15Sopenharmony_ci    /// assert_eq!(secret.len(), 32);
52192f3ab15Sopenharmony_ci    /// # Ok(()) }
52292f3ab15Sopenharmony_ci    /// ```
52392f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
52492f3ab15Sopenharmony_ci    pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> {
52592f3ab15Sopenharmony_ci        PKey::generate_eddsa(Id::X25519)
52692f3ab15Sopenharmony_ci    }
52792f3ab15Sopenharmony_ci
52892f3ab15Sopenharmony_ci    /// Generates a new private X448 key.
52992f3ab15Sopenharmony_ci    ///
53092f3ab15Sopenharmony_ci    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
53192f3ab15Sopenharmony_ci    ///
53292f3ab15Sopenharmony_ci    /// # Examples
53392f3ab15Sopenharmony_ci    ///
53492f3ab15Sopenharmony_ci    /// ```
53592f3ab15Sopenharmony_ci    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
53692f3ab15Sopenharmony_ci    /// use openssl::pkey::{PKey, Id};
53792f3ab15Sopenharmony_ci    /// use openssl::derive::Deriver;
53892f3ab15Sopenharmony_ci    ///
53992f3ab15Sopenharmony_ci    /// let public = // ...
54092f3ab15Sopenharmony_ci    /// # &PKey::generate_x448()?.raw_public_key()?;
54192f3ab15Sopenharmony_ci    /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X448)?;
54292f3ab15Sopenharmony_ci    ///
54392f3ab15Sopenharmony_ci    /// let key = PKey::generate_x448()?;
54492f3ab15Sopenharmony_ci    /// let mut deriver = Deriver::new(&key)?;
54592f3ab15Sopenharmony_ci    /// deriver.set_peer(&public_key)?;
54692f3ab15Sopenharmony_ci    ///
54792f3ab15Sopenharmony_ci    /// let secret = deriver.derive_to_vec()?;
54892f3ab15Sopenharmony_ci    /// assert_eq!(secret.len(), 56);
54992f3ab15Sopenharmony_ci    /// # Ok(()) }
55092f3ab15Sopenharmony_ci    /// ```
55192f3ab15Sopenharmony_ci    #[cfg(ossl111)]
55292f3ab15Sopenharmony_ci    pub fn generate_x448() -> Result<PKey<Private>, ErrorStack> {
55392f3ab15Sopenharmony_ci        PKey::generate_eddsa(Id::X448)
55492f3ab15Sopenharmony_ci    }
55592f3ab15Sopenharmony_ci
55692f3ab15Sopenharmony_ci    /// Generates a new private Ed25519 key.
55792f3ab15Sopenharmony_ci    ///
55892f3ab15Sopenharmony_ci    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
55992f3ab15Sopenharmony_ci    ///
56092f3ab15Sopenharmony_ci    /// # Examples
56192f3ab15Sopenharmony_ci    ///
56292f3ab15Sopenharmony_ci    /// ```
56392f3ab15Sopenharmony_ci    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
56492f3ab15Sopenharmony_ci    /// use openssl::pkey::{PKey, Id};
56592f3ab15Sopenharmony_ci    /// use openssl::sign::Signer;
56692f3ab15Sopenharmony_ci    ///
56792f3ab15Sopenharmony_ci    /// let key = PKey::generate_ed25519()?;
56892f3ab15Sopenharmony_ci    /// let public_key = key.raw_public_key()?;
56992f3ab15Sopenharmony_ci    ///
57092f3ab15Sopenharmony_ci    /// let mut signer = Signer::new_without_digest(&key)?;
57192f3ab15Sopenharmony_ci    /// let digest = // ...
57292f3ab15Sopenharmony_ci    /// # &vec![0; 32];
57392f3ab15Sopenharmony_ci    /// let signature = signer.sign_oneshot_to_vec(digest)?;
57492f3ab15Sopenharmony_ci    /// assert_eq!(signature.len(), 64);
57592f3ab15Sopenharmony_ci    /// # Ok(()) }
57692f3ab15Sopenharmony_ci    /// ```
57792f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
57892f3ab15Sopenharmony_ci    pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> {
57992f3ab15Sopenharmony_ci        PKey::generate_eddsa(Id::ED25519)
58092f3ab15Sopenharmony_ci    }
58192f3ab15Sopenharmony_ci
58292f3ab15Sopenharmony_ci    /// Generates a new private Ed448 key.
58392f3ab15Sopenharmony_ci    ///
58492f3ab15Sopenharmony_ci    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
58592f3ab15Sopenharmony_ci    ///
58692f3ab15Sopenharmony_ci    /// # Examples
58792f3ab15Sopenharmony_ci    ///
58892f3ab15Sopenharmony_ci    /// ```
58992f3ab15Sopenharmony_ci    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
59092f3ab15Sopenharmony_ci    /// use openssl::pkey::{PKey, Id};
59192f3ab15Sopenharmony_ci    /// use openssl::sign::Signer;
59292f3ab15Sopenharmony_ci    ///
59392f3ab15Sopenharmony_ci    /// let key = PKey::generate_ed448()?;
59492f3ab15Sopenharmony_ci    /// let public_key = key.raw_public_key()?;
59592f3ab15Sopenharmony_ci    ///
59692f3ab15Sopenharmony_ci    /// let mut signer = Signer::new_without_digest(&key)?;
59792f3ab15Sopenharmony_ci    /// let digest = // ...
59892f3ab15Sopenharmony_ci    /// # &vec![0; 32];
59992f3ab15Sopenharmony_ci    /// let signature = signer.sign_oneshot_to_vec(digest)?;
60092f3ab15Sopenharmony_ci    /// assert_eq!(signature.len(), 114);
60192f3ab15Sopenharmony_ci    /// # Ok(()) }
60292f3ab15Sopenharmony_ci    /// ```
60392f3ab15Sopenharmony_ci    #[cfg(ossl111)]
60492f3ab15Sopenharmony_ci    pub fn generate_ed448() -> Result<PKey<Private>, ErrorStack> {
60592f3ab15Sopenharmony_ci        PKey::generate_eddsa(Id::ED448)
60692f3ab15Sopenharmony_ci    }
60792f3ab15Sopenharmony_ci
60892f3ab15Sopenharmony_ci    /// Generates a new EC key using the provided curve.
60992f3ab15Sopenharmony_ci    ///
61092f3ab15Sopenharmony_ci    /// Requires OpenSSL 3.0.0 or newer.
61192f3ab15Sopenharmony_ci    #[corresponds(EVP_EC_gen)]
61292f3ab15Sopenharmony_ci    #[cfg(ossl300)]
61392f3ab15Sopenharmony_ci    pub fn ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack> {
61492f3ab15Sopenharmony_ci        ffi::init();
61592f3ab15Sopenharmony_ci
61692f3ab15Sopenharmony_ci        let curve = CString::new(curve).unwrap();
61792f3ab15Sopenharmony_ci        unsafe {
61892f3ab15Sopenharmony_ci            let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?;
61992f3ab15Sopenharmony_ci            Ok(PKey::from_ptr(ptr))
62092f3ab15Sopenharmony_ci        }
62192f3ab15Sopenharmony_ci    }
62292f3ab15Sopenharmony_ci
62392f3ab15Sopenharmony_ci    private_key_from_pem! {
62492f3ab15Sopenharmony_ci        /// Deserializes a private key from a PEM-encoded key type specific format.
62592f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_PrivateKey)]
62692f3ab15Sopenharmony_ci        private_key_from_pem,
62792f3ab15Sopenharmony_ci
62892f3ab15Sopenharmony_ci        /// Deserializes a private key from a PEM-encoded encrypted key type specific format.
62992f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_PrivateKey)]
63092f3ab15Sopenharmony_ci        private_key_from_pem_passphrase,
63192f3ab15Sopenharmony_ci
63292f3ab15Sopenharmony_ci        /// Deserializes a private key from a PEM-encoded encrypted key type specific format.
63392f3ab15Sopenharmony_ci        ///
63492f3ab15Sopenharmony_ci        /// The callback should fill the password into the provided buffer and return its length.
63592f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_PrivateKey)]
63692f3ab15Sopenharmony_ci        private_key_from_pem_callback,
63792f3ab15Sopenharmony_ci        PKey<Private>,
63892f3ab15Sopenharmony_ci        ffi::PEM_read_bio_PrivateKey
63992f3ab15Sopenharmony_ci    }
64092f3ab15Sopenharmony_ci
64192f3ab15Sopenharmony_ci    from_der! {
64292f3ab15Sopenharmony_ci        /// Decodes a DER-encoded private key.
64392f3ab15Sopenharmony_ci        ///
64492f3ab15Sopenharmony_ci        /// This function will attempt to automatically detect the underlying key format, and
64592f3ab15Sopenharmony_ci        /// supports the unencrypted PKCS#8 PrivateKeyInfo structures as well as key type specific
64692f3ab15Sopenharmony_ci        /// formats.
64792f3ab15Sopenharmony_ci        #[corresponds(d2i_AutoPrivateKey)]
64892f3ab15Sopenharmony_ci        private_key_from_der,
64992f3ab15Sopenharmony_ci        PKey<Private>,
65092f3ab15Sopenharmony_ci        ffi::d2i_AutoPrivateKey
65192f3ab15Sopenharmony_ci    }
65292f3ab15Sopenharmony_ci
65392f3ab15Sopenharmony_ci    /// Deserializes a DER-formatted PKCS#8 unencrypted private key.
65492f3ab15Sopenharmony_ci    ///
65592f3ab15Sopenharmony_ci    /// This method is mainly for interoperability reasons. Encrypted keyfiles should be preferred.
65692f3ab15Sopenharmony_ci    pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> {
65792f3ab15Sopenharmony_ci        unsafe {
65892f3ab15Sopenharmony_ci            ffi::init();
65992f3ab15Sopenharmony_ci            let len = der.len().min(c_long::max_value() as usize) as c_long;
66092f3ab15Sopenharmony_ci            let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO(
66192f3ab15Sopenharmony_ci                ptr::null_mut(),
66292f3ab15Sopenharmony_ci                &mut der.as_ptr(),
66392f3ab15Sopenharmony_ci                len,
66492f3ab15Sopenharmony_ci            ))?;
66592f3ab15Sopenharmony_ci            let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p));
66692f3ab15Sopenharmony_ci            ffi::PKCS8_PRIV_KEY_INFO_free(p8inf);
66792f3ab15Sopenharmony_ci            res
66892f3ab15Sopenharmony_ci        }
66992f3ab15Sopenharmony_ci    }
67092f3ab15Sopenharmony_ci
67192f3ab15Sopenharmony_ci    /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password
67292f3ab15Sopenharmony_ci    /// if the key is encrypted.
67392f3ab15Sopenharmony_ci    ///
67492f3ab15Sopenharmony_ci    /// The callback should copy the password into the provided buffer and return the number of
67592f3ab15Sopenharmony_ci    /// bytes written.
67692f3ab15Sopenharmony_ci    #[corresponds(d2i_PKCS8PrivateKey_bio)]
67792f3ab15Sopenharmony_ci    pub fn private_key_from_pkcs8_callback<F>(
67892f3ab15Sopenharmony_ci        der: &[u8],
67992f3ab15Sopenharmony_ci        callback: F,
68092f3ab15Sopenharmony_ci    ) -> Result<PKey<Private>, ErrorStack>
68192f3ab15Sopenharmony_ci    where
68292f3ab15Sopenharmony_ci        F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
68392f3ab15Sopenharmony_ci    {
68492f3ab15Sopenharmony_ci        unsafe {
68592f3ab15Sopenharmony_ci            ffi::init();
68692f3ab15Sopenharmony_ci            let mut cb = CallbackState::new(callback);
68792f3ab15Sopenharmony_ci            let bio = MemBioSlice::new(der)?;
68892f3ab15Sopenharmony_ci            cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
68992f3ab15Sopenharmony_ci                bio.as_ptr(),
69092f3ab15Sopenharmony_ci                ptr::null_mut(),
69192f3ab15Sopenharmony_ci                Some(invoke_passwd_cb::<F>),
69292f3ab15Sopenharmony_ci                &mut cb as *mut _ as *mut _,
69392f3ab15Sopenharmony_ci            ))
69492f3ab15Sopenharmony_ci            .map(|p| PKey::from_ptr(p))
69592f3ab15Sopenharmony_ci        }
69692f3ab15Sopenharmony_ci    }
69792f3ab15Sopenharmony_ci
69892f3ab15Sopenharmony_ci    /// Deserializes a DER-formatted PKCS#8 private key, using the supplied password if the key is
69992f3ab15Sopenharmony_ci    /// encrypted.
70092f3ab15Sopenharmony_ci    ///
70192f3ab15Sopenharmony_ci    /// # Panics
70292f3ab15Sopenharmony_ci    ///
70392f3ab15Sopenharmony_ci    /// Panics if `passphrase` contains an embedded null.
70492f3ab15Sopenharmony_ci    #[corresponds(d2i_PKCS8PrivateKey_bio)]
70592f3ab15Sopenharmony_ci    pub fn private_key_from_pkcs8_passphrase(
70692f3ab15Sopenharmony_ci        der: &[u8],
70792f3ab15Sopenharmony_ci        passphrase: &[u8],
70892f3ab15Sopenharmony_ci    ) -> Result<PKey<Private>, ErrorStack> {
70992f3ab15Sopenharmony_ci        unsafe {
71092f3ab15Sopenharmony_ci            ffi::init();
71192f3ab15Sopenharmony_ci            let bio = MemBioSlice::new(der)?;
71292f3ab15Sopenharmony_ci            let passphrase = CString::new(passphrase).unwrap();
71392f3ab15Sopenharmony_ci            cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
71492f3ab15Sopenharmony_ci                bio.as_ptr(),
71592f3ab15Sopenharmony_ci                ptr::null_mut(),
71692f3ab15Sopenharmony_ci                None,
71792f3ab15Sopenharmony_ci                passphrase.as_ptr() as *const _ as *mut _,
71892f3ab15Sopenharmony_ci            ))
71992f3ab15Sopenharmony_ci            .map(|p| PKey::from_ptr(p))
72092f3ab15Sopenharmony_ci        }
72192f3ab15Sopenharmony_ci    }
72292f3ab15Sopenharmony_ci
72392f3ab15Sopenharmony_ci    /// Creates a private key from its raw byte representation
72492f3ab15Sopenharmony_ci    ///
72592f3ab15Sopenharmony_ci    /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448
72692f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_new_raw_private_key)]
72792f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
72892f3ab15Sopenharmony_ci    pub fn private_key_from_raw_bytes(
72992f3ab15Sopenharmony_ci        bytes: &[u8],
73092f3ab15Sopenharmony_ci        key_type: Id,
73192f3ab15Sopenharmony_ci    ) -> Result<PKey<Private>, ErrorStack> {
73292f3ab15Sopenharmony_ci        unsafe {
73392f3ab15Sopenharmony_ci            ffi::init();
73492f3ab15Sopenharmony_ci            cvt_p(ffi::EVP_PKEY_new_raw_private_key(
73592f3ab15Sopenharmony_ci                key_type.as_raw(),
73692f3ab15Sopenharmony_ci                ptr::null_mut(),
73792f3ab15Sopenharmony_ci                bytes.as_ptr(),
73892f3ab15Sopenharmony_ci                bytes.len(),
73992f3ab15Sopenharmony_ci            ))
74092f3ab15Sopenharmony_ci            .map(|p| PKey::from_ptr(p))
74192f3ab15Sopenharmony_ci        }
74292f3ab15Sopenharmony_ci    }
74392f3ab15Sopenharmony_ci}
74492f3ab15Sopenharmony_ci
74592f3ab15Sopenharmony_ciimpl PKey<Public> {
74692f3ab15Sopenharmony_ci    from_pem! {
74792f3ab15Sopenharmony_ci        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure.
74892f3ab15Sopenharmony_ci        ///
74992f3ab15Sopenharmony_ci        /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
75092f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_PUBKEY)]
75192f3ab15Sopenharmony_ci        public_key_from_pem,
75292f3ab15Sopenharmony_ci        PKey<Public>,
75392f3ab15Sopenharmony_ci        ffi::PEM_read_bio_PUBKEY
75492f3ab15Sopenharmony_ci    }
75592f3ab15Sopenharmony_ci
75692f3ab15Sopenharmony_ci    from_der! {
75792f3ab15Sopenharmony_ci        /// Decodes a DER-encoded SubjectPublicKeyInfo structure.
75892f3ab15Sopenharmony_ci        #[corresponds(d2i_PUBKEY)]
75992f3ab15Sopenharmony_ci        public_key_from_der,
76092f3ab15Sopenharmony_ci        PKey<Public>,
76192f3ab15Sopenharmony_ci        ffi::d2i_PUBKEY
76292f3ab15Sopenharmony_ci    }
76392f3ab15Sopenharmony_ci
76492f3ab15Sopenharmony_ci    /// Creates a public key from its raw byte representation
76592f3ab15Sopenharmony_ci    ///
76692f3ab15Sopenharmony_ci    /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448
76792f3ab15Sopenharmony_ci    #[corresponds(EVP_PKEY_new_raw_public_key)]
76892f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
76992f3ab15Sopenharmony_ci    pub fn public_key_from_raw_bytes(
77092f3ab15Sopenharmony_ci        bytes: &[u8],
77192f3ab15Sopenharmony_ci        key_type: Id,
77292f3ab15Sopenharmony_ci    ) -> Result<PKey<Public>, ErrorStack> {
77392f3ab15Sopenharmony_ci        unsafe {
77492f3ab15Sopenharmony_ci            ffi::init();
77592f3ab15Sopenharmony_ci            cvt_p(ffi::EVP_PKEY_new_raw_public_key(
77692f3ab15Sopenharmony_ci                key_type.as_raw(),
77792f3ab15Sopenharmony_ci                ptr::null_mut(),
77892f3ab15Sopenharmony_ci                bytes.as_ptr(),
77992f3ab15Sopenharmony_ci                bytes.len(),
78092f3ab15Sopenharmony_ci            ))
78192f3ab15Sopenharmony_ci            .map(|p| PKey::from_ptr(p))
78292f3ab15Sopenharmony_ci        }
78392f3ab15Sopenharmony_ci    }
78492f3ab15Sopenharmony_ci}
78592f3ab15Sopenharmony_ci
78692f3ab15Sopenharmony_cicfg_if! {
78792f3ab15Sopenharmony_ci    if #[cfg(any(boringssl, ossl110, libressl270))] {
78892f3ab15Sopenharmony_ci        use ffi::EVP_PKEY_up_ref;
78992f3ab15Sopenharmony_ci    } else {
79092f3ab15Sopenharmony_ci        #[allow(bad_style)]
79192f3ab15Sopenharmony_ci        unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) {
79292f3ab15Sopenharmony_ci            ffi::CRYPTO_add_lock(
79392f3ab15Sopenharmony_ci                &mut (*pkey).references,
79492f3ab15Sopenharmony_ci                1,
79592f3ab15Sopenharmony_ci                ffi::CRYPTO_LOCK_EVP_PKEY,
79692f3ab15Sopenharmony_ci                "pkey.rs\0".as_ptr() as *const _,
79792f3ab15Sopenharmony_ci                line!() as c_int,
79892f3ab15Sopenharmony_ci            );
79992f3ab15Sopenharmony_ci        }
80092f3ab15Sopenharmony_ci    }
80192f3ab15Sopenharmony_ci}
80292f3ab15Sopenharmony_ci
80392f3ab15Sopenharmony_ciimpl<T> TryFrom<EcKey<T>> for PKey<T> {
80492f3ab15Sopenharmony_ci    type Error = ErrorStack;
80592f3ab15Sopenharmony_ci
80692f3ab15Sopenharmony_ci    fn try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
80792f3ab15Sopenharmony_ci        PKey::from_ec_key(ec_key)
80892f3ab15Sopenharmony_ci    }
80992f3ab15Sopenharmony_ci}
81092f3ab15Sopenharmony_ci
81192f3ab15Sopenharmony_ciimpl<T> TryFrom<PKey<T>> for EcKey<T> {
81292f3ab15Sopenharmony_ci    type Error = ErrorStack;
81392f3ab15Sopenharmony_ci
81492f3ab15Sopenharmony_ci    fn try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack> {
81592f3ab15Sopenharmony_ci        pkey.ec_key()
81692f3ab15Sopenharmony_ci    }
81792f3ab15Sopenharmony_ci}
81892f3ab15Sopenharmony_ci
81992f3ab15Sopenharmony_ciimpl<T> TryFrom<Rsa<T>> for PKey<T> {
82092f3ab15Sopenharmony_ci    type Error = ErrorStack;
82192f3ab15Sopenharmony_ci
82292f3ab15Sopenharmony_ci    fn try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
82392f3ab15Sopenharmony_ci        PKey::from_rsa(rsa)
82492f3ab15Sopenharmony_ci    }
82592f3ab15Sopenharmony_ci}
82692f3ab15Sopenharmony_ci
82792f3ab15Sopenharmony_ciimpl<T> TryFrom<PKey<T>> for Rsa<T> {
82892f3ab15Sopenharmony_ci    type Error = ErrorStack;
82992f3ab15Sopenharmony_ci
83092f3ab15Sopenharmony_ci    fn try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack> {
83192f3ab15Sopenharmony_ci        pkey.rsa()
83292f3ab15Sopenharmony_ci    }
83392f3ab15Sopenharmony_ci}
83492f3ab15Sopenharmony_ci
83592f3ab15Sopenharmony_ciimpl<T> TryFrom<Dsa<T>> for PKey<T> {
83692f3ab15Sopenharmony_ci    type Error = ErrorStack;
83792f3ab15Sopenharmony_ci
83892f3ab15Sopenharmony_ci    fn try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
83992f3ab15Sopenharmony_ci        PKey::from_dsa(dsa)
84092f3ab15Sopenharmony_ci    }
84192f3ab15Sopenharmony_ci}
84292f3ab15Sopenharmony_ci
84392f3ab15Sopenharmony_ciimpl<T> TryFrom<PKey<T>> for Dsa<T> {
84492f3ab15Sopenharmony_ci    type Error = ErrorStack;
84592f3ab15Sopenharmony_ci
84692f3ab15Sopenharmony_ci    fn try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack> {
84792f3ab15Sopenharmony_ci        pkey.dsa()
84892f3ab15Sopenharmony_ci    }
84992f3ab15Sopenharmony_ci}
85092f3ab15Sopenharmony_ci
85192f3ab15Sopenharmony_ci#[cfg(not(boringssl))]
85292f3ab15Sopenharmony_ciimpl<T> TryFrom<Dh<T>> for PKey<T> {
85392f3ab15Sopenharmony_ci    type Error = ErrorStack;
85492f3ab15Sopenharmony_ci
85592f3ab15Sopenharmony_ci    fn try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
85692f3ab15Sopenharmony_ci        PKey::from_dh(dh)
85792f3ab15Sopenharmony_ci    }
85892f3ab15Sopenharmony_ci}
85992f3ab15Sopenharmony_ci
86092f3ab15Sopenharmony_ciimpl<T> TryFrom<PKey<T>> for Dh<T> {
86192f3ab15Sopenharmony_ci    type Error = ErrorStack;
86292f3ab15Sopenharmony_ci
86392f3ab15Sopenharmony_ci    fn try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack> {
86492f3ab15Sopenharmony_ci        pkey.dh()
86592f3ab15Sopenharmony_ci    }
86692f3ab15Sopenharmony_ci}
86792f3ab15Sopenharmony_ci
86892f3ab15Sopenharmony_ci#[cfg(test)]
86992f3ab15Sopenharmony_cimod tests {
87092f3ab15Sopenharmony_ci    use std::convert::TryInto;
87192f3ab15Sopenharmony_ci
87292f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
87392f3ab15Sopenharmony_ci    use crate::dh::Dh;
87492f3ab15Sopenharmony_ci    use crate::dsa::Dsa;
87592f3ab15Sopenharmony_ci    use crate::ec::EcKey;
87692f3ab15Sopenharmony_ci    use crate::error::Error;
87792f3ab15Sopenharmony_ci    use crate::nid::Nid;
87892f3ab15Sopenharmony_ci    use crate::rsa::Rsa;
87992f3ab15Sopenharmony_ci    use crate::symm::Cipher;
88092f3ab15Sopenharmony_ci
88192f3ab15Sopenharmony_ci    use super::*;
88292f3ab15Sopenharmony_ci
88392f3ab15Sopenharmony_ci    #[cfg(ossl111)]
88492f3ab15Sopenharmony_ci    use crate::rand::rand_bytes;
88592f3ab15Sopenharmony_ci
88692f3ab15Sopenharmony_ci    #[test]
88792f3ab15Sopenharmony_ci    fn test_to_password() {
88892f3ab15Sopenharmony_ci        let rsa = Rsa::generate(2048).unwrap();
88992f3ab15Sopenharmony_ci        let pkey = PKey::from_rsa(rsa).unwrap();
89092f3ab15Sopenharmony_ci        let pem = pkey
89192f3ab15Sopenharmony_ci            .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar")
89292f3ab15Sopenharmony_ci            .unwrap();
89392f3ab15Sopenharmony_ci        PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
89492f3ab15Sopenharmony_ci        assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
89592f3ab15Sopenharmony_ci    }
89692f3ab15Sopenharmony_ci
89792f3ab15Sopenharmony_ci    #[test]
89892f3ab15Sopenharmony_ci    fn test_unencrypted_pkcs8() {
89992f3ab15Sopenharmony_ci        let key = include_bytes!("../test/pkcs8-nocrypt.der");
90092f3ab15Sopenharmony_ci        let pkey = PKey::private_key_from_pkcs8(key).unwrap();
90192f3ab15Sopenharmony_ci        let serialized = pkey.private_key_to_pkcs8().unwrap();
90292f3ab15Sopenharmony_ci        let pkey2 = PKey::private_key_from_pkcs8(&serialized).unwrap();
90392f3ab15Sopenharmony_ci
90492f3ab15Sopenharmony_ci        assert_eq!(
90592f3ab15Sopenharmony_ci            pkey2.private_key_to_der().unwrap(),
90692f3ab15Sopenharmony_ci            pkey.private_key_to_der().unwrap()
90792f3ab15Sopenharmony_ci        );
90892f3ab15Sopenharmony_ci    }
90992f3ab15Sopenharmony_ci
91092f3ab15Sopenharmony_ci    #[test]
91192f3ab15Sopenharmony_ci    fn test_encrypted_pkcs8_passphrase() {
91292f3ab15Sopenharmony_ci        let key = include_bytes!("../test/pkcs8.der");
91392f3ab15Sopenharmony_ci        PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap();
91492f3ab15Sopenharmony_ci
91592f3ab15Sopenharmony_ci        let rsa = Rsa::generate(2048).unwrap();
91692f3ab15Sopenharmony_ci        let pkey = PKey::from_rsa(rsa).unwrap();
91792f3ab15Sopenharmony_ci        let der = pkey
91892f3ab15Sopenharmony_ci            .private_key_to_pkcs8_passphrase(Cipher::aes_128_cbc(), b"mypass")
91992f3ab15Sopenharmony_ci            .unwrap();
92092f3ab15Sopenharmony_ci        let pkey2 = PKey::private_key_from_pkcs8_passphrase(&der, b"mypass").unwrap();
92192f3ab15Sopenharmony_ci        assert_eq!(
92292f3ab15Sopenharmony_ci            pkey.private_key_to_der().unwrap(),
92392f3ab15Sopenharmony_ci            pkey2.private_key_to_der().unwrap()
92492f3ab15Sopenharmony_ci        );
92592f3ab15Sopenharmony_ci    }
92692f3ab15Sopenharmony_ci
92792f3ab15Sopenharmony_ci    #[test]
92892f3ab15Sopenharmony_ci    fn test_encrypted_pkcs8_callback() {
92992f3ab15Sopenharmony_ci        let mut password_queried = false;
93092f3ab15Sopenharmony_ci        let key = include_bytes!("../test/pkcs8.der");
93192f3ab15Sopenharmony_ci        PKey::private_key_from_pkcs8_callback(key, |password| {
93292f3ab15Sopenharmony_ci            password_queried = true;
93392f3ab15Sopenharmony_ci            password[..6].copy_from_slice(b"mypass");
93492f3ab15Sopenharmony_ci            Ok(6)
93592f3ab15Sopenharmony_ci        })
93692f3ab15Sopenharmony_ci        .unwrap();
93792f3ab15Sopenharmony_ci        assert!(password_queried);
93892f3ab15Sopenharmony_ci    }
93992f3ab15Sopenharmony_ci
94092f3ab15Sopenharmony_ci    #[test]
94192f3ab15Sopenharmony_ci    fn test_private_key_from_pem() {
94292f3ab15Sopenharmony_ci        let key = include_bytes!("../test/key.pem");
94392f3ab15Sopenharmony_ci        PKey::private_key_from_pem(key).unwrap();
94492f3ab15Sopenharmony_ci    }
94592f3ab15Sopenharmony_ci
94692f3ab15Sopenharmony_ci    #[test]
94792f3ab15Sopenharmony_ci    fn test_public_key_from_pem() {
94892f3ab15Sopenharmony_ci        let key = include_bytes!("../test/key.pem.pub");
94992f3ab15Sopenharmony_ci        PKey::public_key_from_pem(key).unwrap();
95092f3ab15Sopenharmony_ci    }
95192f3ab15Sopenharmony_ci
95292f3ab15Sopenharmony_ci    #[test]
95392f3ab15Sopenharmony_ci    fn test_public_key_from_der() {
95492f3ab15Sopenharmony_ci        let key = include_bytes!("../test/key.der.pub");
95592f3ab15Sopenharmony_ci        PKey::public_key_from_der(key).unwrap();
95692f3ab15Sopenharmony_ci    }
95792f3ab15Sopenharmony_ci
95892f3ab15Sopenharmony_ci    #[test]
95992f3ab15Sopenharmony_ci    fn test_private_key_from_der() {
96092f3ab15Sopenharmony_ci        let key = include_bytes!("../test/key.der");
96192f3ab15Sopenharmony_ci        PKey::private_key_from_der(key).unwrap();
96292f3ab15Sopenharmony_ci    }
96392f3ab15Sopenharmony_ci
96492f3ab15Sopenharmony_ci    #[test]
96592f3ab15Sopenharmony_ci    fn test_pem() {
96692f3ab15Sopenharmony_ci        let key = include_bytes!("../test/key.pem");
96792f3ab15Sopenharmony_ci        let key = PKey::private_key_from_pem(key).unwrap();
96892f3ab15Sopenharmony_ci
96992f3ab15Sopenharmony_ci        let priv_key = key.private_key_to_pem_pkcs8().unwrap();
97092f3ab15Sopenharmony_ci        let pub_key = key.public_key_to_pem().unwrap();
97192f3ab15Sopenharmony_ci
97292f3ab15Sopenharmony_ci        // As a super-simple verification, just check that the buffers contain
97392f3ab15Sopenharmony_ci        // the `PRIVATE KEY` or `PUBLIC KEY` strings.
97492f3ab15Sopenharmony_ci        assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY"));
97592f3ab15Sopenharmony_ci        assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY"));
97692f3ab15Sopenharmony_ci    }
97792f3ab15Sopenharmony_ci
97892f3ab15Sopenharmony_ci    #[test]
97992f3ab15Sopenharmony_ci    fn test_rsa_accessor() {
98092f3ab15Sopenharmony_ci        let rsa = Rsa::generate(2048).unwrap();
98192f3ab15Sopenharmony_ci        let pkey = PKey::from_rsa(rsa).unwrap();
98292f3ab15Sopenharmony_ci        pkey.rsa().unwrap();
98392f3ab15Sopenharmony_ci        assert_eq!(pkey.id(), Id::RSA);
98492f3ab15Sopenharmony_ci        assert!(pkey.dsa().is_err());
98592f3ab15Sopenharmony_ci    }
98692f3ab15Sopenharmony_ci
98792f3ab15Sopenharmony_ci    #[test]
98892f3ab15Sopenharmony_ci    fn test_dsa_accessor() {
98992f3ab15Sopenharmony_ci        let dsa = Dsa::generate(2048).unwrap();
99092f3ab15Sopenharmony_ci        let pkey = PKey::from_dsa(dsa).unwrap();
99192f3ab15Sopenharmony_ci        pkey.dsa().unwrap();
99292f3ab15Sopenharmony_ci        assert_eq!(pkey.id(), Id::DSA);
99392f3ab15Sopenharmony_ci        assert!(pkey.rsa().is_err());
99492f3ab15Sopenharmony_ci    }
99592f3ab15Sopenharmony_ci
99692f3ab15Sopenharmony_ci    #[test]
99792f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
99892f3ab15Sopenharmony_ci    fn test_dh_accessor() {
99992f3ab15Sopenharmony_ci        let dh = include_bytes!("../test/dhparams.pem");
100092f3ab15Sopenharmony_ci        let dh = Dh::params_from_pem(dh).unwrap();
100192f3ab15Sopenharmony_ci        let pkey = PKey::from_dh(dh).unwrap();
100292f3ab15Sopenharmony_ci        pkey.dh().unwrap();
100392f3ab15Sopenharmony_ci        assert_eq!(pkey.id(), Id::DH);
100492f3ab15Sopenharmony_ci        assert!(pkey.rsa().is_err());
100592f3ab15Sopenharmony_ci    }
100692f3ab15Sopenharmony_ci
100792f3ab15Sopenharmony_ci    #[test]
100892f3ab15Sopenharmony_ci    fn test_ec_key_accessor() {
100992f3ab15Sopenharmony_ci        let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
101092f3ab15Sopenharmony_ci        let pkey = PKey::from_ec_key(ec_key).unwrap();
101192f3ab15Sopenharmony_ci        pkey.ec_key().unwrap();
101292f3ab15Sopenharmony_ci        assert_eq!(pkey.id(), Id::EC);
101392f3ab15Sopenharmony_ci        assert!(pkey.rsa().is_err());
101492f3ab15Sopenharmony_ci    }
101592f3ab15Sopenharmony_ci
101692f3ab15Sopenharmony_ci    #[test]
101792f3ab15Sopenharmony_ci    fn test_rsa_conversion() {
101892f3ab15Sopenharmony_ci        let rsa = Rsa::generate(2048).unwrap();
101992f3ab15Sopenharmony_ci        let pkey: PKey<Private> = rsa.clone().try_into().unwrap();
102092f3ab15Sopenharmony_ci        let rsa_: Rsa<Private> = pkey.try_into().unwrap();
102192f3ab15Sopenharmony_ci        // Eq is missing
102292f3ab15Sopenharmony_ci        assert_eq!(rsa.p(), rsa_.p());
102392f3ab15Sopenharmony_ci        assert_eq!(rsa.q(), rsa_.q());
102492f3ab15Sopenharmony_ci    }
102592f3ab15Sopenharmony_ci
102692f3ab15Sopenharmony_ci    #[test]
102792f3ab15Sopenharmony_ci    fn test_dsa_conversion() {
102892f3ab15Sopenharmony_ci        let dsa = Dsa::generate(2048).unwrap();
102992f3ab15Sopenharmony_ci        let pkey: PKey<Private> = dsa.clone().try_into().unwrap();
103092f3ab15Sopenharmony_ci        let dsa_: Dsa<Private> = pkey.try_into().unwrap();
103192f3ab15Sopenharmony_ci        // Eq is missing
103292f3ab15Sopenharmony_ci        assert_eq!(dsa.priv_key(), dsa_.priv_key());
103392f3ab15Sopenharmony_ci    }
103492f3ab15Sopenharmony_ci
103592f3ab15Sopenharmony_ci    #[test]
103692f3ab15Sopenharmony_ci    fn test_ec_key_conversion() {
103792f3ab15Sopenharmony_ci        let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap();
103892f3ab15Sopenharmony_ci        let ec_key = EcKey::generate(&group).unwrap();
103992f3ab15Sopenharmony_ci        let pkey: PKey<Private> = ec_key.clone().try_into().unwrap();
104092f3ab15Sopenharmony_ci        let ec_key_: EcKey<Private> = pkey.try_into().unwrap();
104192f3ab15Sopenharmony_ci        // Eq is missing
104292f3ab15Sopenharmony_ci        assert_eq!(ec_key.private_key(), ec_key_.private_key());
104392f3ab15Sopenharmony_ci    }
104492f3ab15Sopenharmony_ci
104592f3ab15Sopenharmony_ci    #[test]
104692f3ab15Sopenharmony_ci    #[cfg(any(ossl110, libressl360))]
104792f3ab15Sopenharmony_ci    fn test_security_bits() {
104892f3ab15Sopenharmony_ci        let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::SECP521R1).unwrap();
104992f3ab15Sopenharmony_ci        let ec_key = EcKey::generate(&group).unwrap();
105092f3ab15Sopenharmony_ci        let pkey: PKey<Private> = ec_key.try_into().unwrap();
105192f3ab15Sopenharmony_ci
105292f3ab15Sopenharmony_ci        assert_eq!(pkey.security_bits(), 256);
105392f3ab15Sopenharmony_ci    }
105492f3ab15Sopenharmony_ci
105592f3ab15Sopenharmony_ci    #[test]
105692f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
105792f3ab15Sopenharmony_ci    fn test_dh_conversion() {
105892f3ab15Sopenharmony_ci        let dh_params = include_bytes!("../test/dhparams.pem");
105992f3ab15Sopenharmony_ci        let dh_params = Dh::params_from_pem(dh_params).unwrap();
106092f3ab15Sopenharmony_ci        let dh = dh_params.generate_key().unwrap();
106192f3ab15Sopenharmony_ci
106292f3ab15Sopenharmony_ci        // Clone is missing for Dh, save the parameters
106392f3ab15Sopenharmony_ci        let p = dh.prime_p().to_owned().unwrap();
106492f3ab15Sopenharmony_ci        let q = dh.prime_q().map(|q| q.to_owned().unwrap());
106592f3ab15Sopenharmony_ci        let g = dh.generator().to_owned().unwrap();
106692f3ab15Sopenharmony_ci
106792f3ab15Sopenharmony_ci        let pkey: PKey<Private> = dh.try_into().unwrap();
106892f3ab15Sopenharmony_ci        let dh_: Dh<Private> = pkey.try_into().unwrap();
106992f3ab15Sopenharmony_ci
107092f3ab15Sopenharmony_ci        // Eq is missing
107192f3ab15Sopenharmony_ci        assert_eq!(&p, dh_.prime_p());
107292f3ab15Sopenharmony_ci        assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap()));
107392f3ab15Sopenharmony_ci        assert_eq!(&g, dh_.generator());
107492f3ab15Sopenharmony_ci    }
107592f3ab15Sopenharmony_ci
107692f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
107792f3ab15Sopenharmony_ci    fn test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
107892f3ab15Sopenharmony_ci        // Generate a new key
107992f3ab15Sopenharmony_ci        let key = gen().unwrap();
108092f3ab15Sopenharmony_ci
108192f3ab15Sopenharmony_ci        // Get the raw bytes, and create a new key from the raw bytes
108292f3ab15Sopenharmony_ci        let raw = key.raw_public_key().unwrap();
108392f3ab15Sopenharmony_ci        let from_raw = PKey::public_key_from_raw_bytes(&raw, key_type).unwrap();
108492f3ab15Sopenharmony_ci
108592f3ab15Sopenharmony_ci        // Compare the der encoding of the original and raw / restored public key
108692f3ab15Sopenharmony_ci        assert_eq!(
108792f3ab15Sopenharmony_ci            key.public_key_to_der().unwrap(),
108892f3ab15Sopenharmony_ci            from_raw.public_key_to_der().unwrap()
108992f3ab15Sopenharmony_ci        );
109092f3ab15Sopenharmony_ci    }
109192f3ab15Sopenharmony_ci
109292f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
109392f3ab15Sopenharmony_ci    fn test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
109492f3ab15Sopenharmony_ci        // Generate a new key
109592f3ab15Sopenharmony_ci        let key = gen().unwrap();
109692f3ab15Sopenharmony_ci
109792f3ab15Sopenharmony_ci        // Get the raw bytes, and create a new key from the raw bytes
109892f3ab15Sopenharmony_ci        let raw = key.raw_private_key().unwrap();
109992f3ab15Sopenharmony_ci        let from_raw = PKey::private_key_from_raw_bytes(&raw, key_type).unwrap();
110092f3ab15Sopenharmony_ci
110192f3ab15Sopenharmony_ci        // Compare the der encoding of the original and raw / restored public key
110292f3ab15Sopenharmony_ci        assert_eq!(
110392f3ab15Sopenharmony_ci            key.private_key_to_pkcs8().unwrap(),
110492f3ab15Sopenharmony_ci            from_raw.private_key_to_pkcs8().unwrap()
110592f3ab15Sopenharmony_ci        );
110692f3ab15Sopenharmony_ci    }
110792f3ab15Sopenharmony_ci
110892f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
110992f3ab15Sopenharmony_ci    #[test]
111092f3ab15Sopenharmony_ci    fn test_raw_public_key_bytes() {
111192f3ab15Sopenharmony_ci        test_raw_public_key(PKey::generate_x25519, Id::X25519);
111292f3ab15Sopenharmony_ci        test_raw_public_key(PKey::generate_ed25519, Id::ED25519);
111392f3ab15Sopenharmony_ci        #[cfg(all(not(boringssl), not(libressl370)))]
111492f3ab15Sopenharmony_ci        test_raw_public_key(PKey::generate_x448, Id::X448);
111592f3ab15Sopenharmony_ci        #[cfg(all(not(boringssl), not(libressl370)))]
111692f3ab15Sopenharmony_ci        test_raw_public_key(PKey::generate_ed448, Id::ED448);
111792f3ab15Sopenharmony_ci    }
111892f3ab15Sopenharmony_ci
111992f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl370))]
112092f3ab15Sopenharmony_ci    #[test]
112192f3ab15Sopenharmony_ci    fn test_raw_private_key_bytes() {
112292f3ab15Sopenharmony_ci        test_raw_private_key(PKey::generate_x25519, Id::X25519);
112392f3ab15Sopenharmony_ci        test_raw_private_key(PKey::generate_ed25519, Id::ED25519);
112492f3ab15Sopenharmony_ci        #[cfg(all(not(boringssl), not(libressl370)))]
112592f3ab15Sopenharmony_ci        test_raw_private_key(PKey::generate_x448, Id::X448);
112692f3ab15Sopenharmony_ci        #[cfg(all(not(boringssl), not(libressl370)))]
112792f3ab15Sopenharmony_ci        test_raw_private_key(PKey::generate_ed448, Id::ED448);
112892f3ab15Sopenharmony_ci    }
112992f3ab15Sopenharmony_ci
113092f3ab15Sopenharmony_ci    #[cfg(ossl111)]
113192f3ab15Sopenharmony_ci    #[test]
113292f3ab15Sopenharmony_ci    fn test_raw_hmac() {
113392f3ab15Sopenharmony_ci        let mut test_bytes = vec![0u8; 32];
113492f3ab15Sopenharmony_ci        rand_bytes(&mut test_bytes).unwrap();
113592f3ab15Sopenharmony_ci
113692f3ab15Sopenharmony_ci        let hmac_key = PKey::hmac(&test_bytes).unwrap();
113792f3ab15Sopenharmony_ci        assert!(hmac_key.raw_public_key().is_err());
113892f3ab15Sopenharmony_ci
113992f3ab15Sopenharmony_ci        let key_bytes = hmac_key.raw_private_key().unwrap();
114092f3ab15Sopenharmony_ci        assert_eq!(key_bytes, test_bytes);
114192f3ab15Sopenharmony_ci    }
114292f3ab15Sopenharmony_ci
114392f3ab15Sopenharmony_ci    #[cfg(ossl111)]
114492f3ab15Sopenharmony_ci    #[test]
114592f3ab15Sopenharmony_ci    fn test_raw_key_fail() {
114692f3ab15Sopenharmony_ci        // Getting a raw byte representation will not work with Nist curves
114792f3ab15Sopenharmony_ci        let group = crate::ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
114892f3ab15Sopenharmony_ci        let ec_key = EcKey::generate(&group).unwrap();
114992f3ab15Sopenharmony_ci        let pkey = PKey::from_ec_key(ec_key).unwrap();
115092f3ab15Sopenharmony_ci        assert!(pkey.raw_private_key().is_err());
115192f3ab15Sopenharmony_ci        assert!(pkey.raw_public_key().is_err());
115292f3ab15Sopenharmony_ci    }
115392f3ab15Sopenharmony_ci
115492f3ab15Sopenharmony_ci    #[cfg(ossl300)]
115592f3ab15Sopenharmony_ci    #[test]
115692f3ab15Sopenharmony_ci    fn test_ec_gen() {
115792f3ab15Sopenharmony_ci        let key = PKey::ec_gen("prime256v1").unwrap();
115892f3ab15Sopenharmony_ci        assert!(key.ec_key().is_ok());
115992f3ab15Sopenharmony_ci    }
116092f3ab15Sopenharmony_ci
116192f3ab15Sopenharmony_ci    #[test]
116292f3ab15Sopenharmony_ci    fn test_public_eq() {
116392f3ab15Sopenharmony_ci        let rsa = Rsa::generate(2048).unwrap();
116492f3ab15Sopenharmony_ci        let pkey1 = PKey::from_rsa(rsa).unwrap();
116592f3ab15Sopenharmony_ci
116692f3ab15Sopenharmony_ci        let group = crate::ec::EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
116792f3ab15Sopenharmony_ci        let ec_key = EcKey::generate(&group).unwrap();
116892f3ab15Sopenharmony_ci        let pkey2 = PKey::from_ec_key(ec_key).unwrap();
116992f3ab15Sopenharmony_ci
117092f3ab15Sopenharmony_ci        assert!(!pkey1.public_eq(&pkey2));
117192f3ab15Sopenharmony_ci        assert!(Error::get().is_none());
117292f3ab15Sopenharmony_ci    }
117392f3ab15Sopenharmony_ci}
1174