//! Public/private key processing.
//!
//! Asymmetric public key algorithms solve the problem of establishing and sharing
//! secret keys to securely send and receive messages.
//! This system uses a pair of keys: a public key, which can be freely
//! distributed, and a private key, which is kept to oneself. An entity may
//! encrypt information using a user's public key. The encrypted information can
//! only be deciphered using that user's private key.
//!
//! This module offers support for five popular algorithms:
//!
//! * RSA
//!
//! * DSA
//!
//! * Diffie-Hellman
//!
//! * Elliptic Curves
//!
//! * HMAC
//!
//! These algorithms rely on hard mathematical problems - namely integer factorization,
//! discrete logarithms, and elliptic curve relationships - that currently do not
//! yield efficient solutions. This property ensures the security of these
//! cryptographic algorithms.
//!
//! # Example
//!
//! Generate a 2048-bit RSA public/private key pair and print the public key.
//!
//! ```rust
//! use openssl::rsa::Rsa;
//! use openssl::pkey::PKey;
//! use std::str;
//!
//! let rsa = Rsa::generate(2048).unwrap();
//! let pkey = PKey::from_rsa(rsa).unwrap();
//!
//! let pub_key: Vec<u8> = pkey.public_key_to_pem().unwrap();
//! println!("{:?}", str::from_utf8(pub_key.as_slice()).unwrap());
//! ```
#![allow(clippy::missing_safety_doc)]
use crate::bio::{MemBio, MemBioSlice};
#[cfg(ossl110)]
use crate::cipher::CipherRef;
use crate::dh::Dh;
use crate::dsa::Dsa;
use crate::ec::EcKey;
use crate::error::ErrorStack;
#[cfg(any(ossl110, boringssl, libressl370))]
use crate::pkey_ctx::PkeyCtx;
use crate::rsa::Rsa;
use crate::symm::Cipher;
use crate::util::{invoke_passwd_cb, CallbackState};
use crate::{cvt, cvt_p};
use cfg_if::cfg_if;
use foreign_types::{ForeignType, ForeignTypeRef};
use libc::{c_int, c_long};
use openssl_macros::corresponds;
use std::convert::{TryFrom, TryInto};
use std::ffi::CString;
use std::fmt;
use std::mem;
use std::ptr;

/// A tag type indicating that a key only has parameters.
pub enum Params {}

/// A tag type indicating that a key only has public components.
pub enum Public {}

/// A tag type indicating that a key has private components.
pub enum Private {}

/// An identifier of a kind of key.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Id(c_int);

impl Id {
    pub const RSA: Id = Id(ffi::EVP_PKEY_RSA);
    #[cfg(not(boringssl))]
    pub const HMAC: Id = Id(ffi::EVP_PKEY_HMAC);
    #[cfg(not(boringssl))]
    pub const CMAC: Id = Id(ffi::EVP_PKEY_CMAC);
    pub const DSA: Id = Id(ffi::EVP_PKEY_DSA);
    pub const DH: Id = Id(ffi::EVP_PKEY_DH);
    pub const EC: Id = Id(ffi::EVP_PKEY_EC);
    #[cfg(ossl111)]
    pub const SM2: Id = Id(ffi::EVP_PKEY_SM2);

    #[cfg(any(ossl110, boringssl))]
    pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF);

    #[cfg(any(ossl111, boringssl, libressl370))]
    pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519);
    #[cfg(ossl111)]
    pub const ED448: Id = Id(ffi::EVP_PKEY_ED448);
    #[cfg(any(ossl111, boringssl, libressl370))]
    pub const X25519: Id = Id(ffi::EVP_PKEY_X25519);
    #[cfg(ossl111)]
    pub const X448: Id = Id(ffi::EVP_PKEY_X448);
    #[cfg(ossl111)]
    pub const POLY1305: Id = Id(ffi::EVP_PKEY_POLY1305);

    /// Creates a `Id` from an integer representation.
    pub fn from_raw(value: c_int) -> Id {
        Id(value)
    }

    /// Returns the integer representation of the `Id`.
    #[allow(clippy::trivially_copy_pass_by_ref)]
    pub fn as_raw(&self) -> c_int {
        self.0
    }
}

/// A trait indicating that a key has parameters.
pub unsafe trait HasParams {}

unsafe impl HasParams for Params {}

unsafe impl<T> HasParams for T where T: HasPublic {}

/// A trait indicating that a key has public components.
pub unsafe trait HasPublic {}

unsafe impl HasPublic for Public {}

unsafe impl<T> HasPublic for T where T: HasPrivate {}

/// A trait indicating that a key has private components.
pub unsafe trait HasPrivate {}

unsafe impl HasPrivate for Private {}

generic_foreign_type_and_impl_send_sync! {
    type CType = ffi::EVP_PKEY;
    fn drop = ffi::EVP_PKEY_free;

    /// A public or private key.
    pub struct PKey<T>;
    /// Reference to `PKey`.
    pub struct PKeyRef<T>;
}

impl<T> ToOwned for PKeyRef<T> {
    type Owned = PKey<T>;

    fn to_owned(&self) -> PKey<T> {
        unsafe {
            EVP_PKEY_up_ref(self.as_ptr());
            PKey::from_ptr(self.as_ptr())
        }
    }
}

impl<T> PKeyRef<T> {
    /// Returns a copy of the internal RSA key.
    #[corresponds(EVP_PKEY_get1_RSA)]
    pub fn rsa(&self) -> Result<Rsa<T>, ErrorStack> {
        unsafe {
            let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?;
            Ok(Rsa::from_ptr(rsa))
        }
    }

    /// Returns a copy of the internal DSA key.
    #[corresponds(EVP_PKEY_get1_DSA)]
    pub fn dsa(&self) -> Result<Dsa<T>, ErrorStack> {
        unsafe {
            let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?;
            Ok(Dsa::from_ptr(dsa))
        }
    }

    /// Returns a copy of the internal DH key.
    #[corresponds(EVP_PKEY_get1_DH)]
    pub fn dh(&self) -> Result<Dh<T>, ErrorStack> {
        unsafe {
            let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?;
            Ok(Dh::from_ptr(dh))
        }
    }

    /// Returns a copy of the internal elliptic curve key.
    #[corresponds(EVP_PKEY_get1_EC_KEY)]
    pub fn ec_key(&self) -> Result<EcKey<T>, ErrorStack> {
        unsafe {
            let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?;
            Ok(EcKey::from_ptr(ec_key))
        }
    }

    /// Returns the `Id` that represents the type of this key.
    #[corresponds(EVP_PKEY_id)]
    pub fn id(&self) -> Id {
        unsafe { Id::from_raw(ffi::EVP_PKEY_id(self.as_ptr())) }
    }

    /// Returns the maximum size of a signature in bytes.
    #[corresponds(EVP_PKEY_size)]
    pub fn size(&self) -> usize {
        unsafe { ffi::EVP_PKEY_size(self.as_ptr()) as usize }
    }
}

impl<T> PKeyRef<T>
where
    T: HasPublic,
{
    to_pem! {
        /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
        ///
        /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
        #[corresponds(PEM_write_bio_PUBKEY)]
        public_key_to_pem,
        ffi::PEM_write_bio_PUBKEY
    }

    to_der! {
        /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
        #[corresponds(i2d_PUBKEY)]
        public_key_to_der,
        ffi::i2d_PUBKEY
    }

    /// Returns the size of the key.
    ///
    /// This corresponds to the bit length of the modulus of an RSA key, and the bit length of the
    /// group order for an elliptic curve key, for example.
    #[corresponds(EVP_PKEY_bits)]
    pub fn bits(&self) -> u32 {
        unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 }
    }

    ///Returns the number of security bits.
    ///
    ///Bits of security is defined in NIST SP800-57.
    #[corresponds(EVP_PKEY_security_bits)]
    #[cfg(any(ossl110, libressl360))]
    pub fn security_bits(&self) -> u32 {
        unsafe { ffi::EVP_PKEY_security_bits(self.as_ptr()) as u32 }
    }

    /// Compares the public component of this key with another.
    #[corresponds(EVP_PKEY_cmp)]
    pub fn public_eq<U>(&self, other: &PKeyRef<U>) -> bool
    where
        U: HasPublic,
    {
        let res = unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 };
        // Clear the stack. OpenSSL will put an error on the stack when the
        // keys are different types in some situations.
        let _ = ErrorStack::get();
        res
    }

    /// Raw byte representation of a public key.
    ///
    /// This function only works for algorithms that support raw public keys.
    /// Currently this is: [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`].
    #[corresponds(EVP_PKEY_get_raw_public_key)]
    #[cfg(any(ossl111, boringssl, libressl370))]
    pub fn raw_public_key(&self) -> Result<Vec<u8>, ErrorStack> {
        unsafe {
            let mut len = 0;
            cvt(ffi::EVP_PKEY_get_raw_public_key(
                self.as_ptr(),
                ptr::null_mut(),
                &mut len,
            ))?;
            let mut buf = vec![0u8; len];
            cvt(ffi::EVP_PKEY_get_raw_public_key(
                self.as_ptr(),
                buf.as_mut_ptr(),
                &mut len,
            ))?;
            buf.truncate(len);
            Ok(buf)
        }
    }
}

impl<T> PKeyRef<T>
where
    T: HasPrivate,
{
    private_key_to_pem! {
        /// Serializes the private key to a PEM-encoded PKCS#8 PrivateKeyInfo structure.
        ///
        /// The output will have a header of `-----BEGIN PRIVATE KEY-----`.
        #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
        private_key_to_pem_pkcs8,
        /// Serializes the private key to a PEM-encoded PKCS#8 EncryptedPrivateKeyInfo structure.
        ///
        /// The output will have a header of `-----BEGIN ENCRYPTED PRIVATE KEY-----`.
        #[corresponds(PEM_write_bio_PKCS8PrivateKey)]
        private_key_to_pem_pkcs8_passphrase,
        ffi::PEM_write_bio_PKCS8PrivateKey
    }

    to_der! {
        /// Serializes the private key to a DER-encoded key type specific format.
        #[corresponds(i2d_PrivateKey)]
        private_key_to_der,
        ffi::i2d_PrivateKey
    }

    /// Raw byte representation of a private key.
    ///
    /// This function only works for algorithms that support raw private keys.
    /// Currently this is: [`Id::HMAC`], [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`].
    #[corresponds(EVP_PKEY_get_raw_private_key)]
    #[cfg(any(ossl111, boringssl, libressl370))]
    pub fn raw_private_key(&self) -> Result<Vec<u8>, ErrorStack> {
        unsafe {
            let mut len = 0;
            cvt(ffi::EVP_PKEY_get_raw_private_key(
                self.as_ptr(),
                ptr::null_mut(),
                &mut len,
            ))?;
            let mut buf = vec![0u8; len];
            cvt(ffi::EVP_PKEY_get_raw_private_key(
                self.as_ptr(),
                buf.as_mut_ptr(),
                &mut len,
            ))?;
            buf.truncate(len);
            Ok(buf)
        }
    }

    /// Serializes a private key into an unencrypted DER-formatted PKCS#8
    #[corresponds(i2d_PKCS8PrivateKey_bio)]
    pub fn private_key_to_pkcs8(&self) -> Result<Vec<u8>, ErrorStack> {
        unsafe {
            let bio = MemBio::new()?;
            cvt(ffi::i2d_PKCS8PrivateKey_bio(
                bio.as_ptr(),
                self.as_ptr(),
                ptr::null(),
                ptr::null_mut(),
                0,
                None,
                ptr::null_mut(),
            ))?;

            Ok(bio.get_buf().to_owned())
        }
    }

    /// Serializes a private key into a DER-formatted PKCS#8, using the supplied password to
    /// encrypt the key.
    #[corresponds(i2d_PKCS8PrivateKey_bio)]
    pub fn private_key_to_pkcs8_passphrase(
        &self,
        cipher: Cipher,
        passphrase: &[u8],
    ) -> Result<Vec<u8>, ErrorStack> {
        unsafe {
            let bio = MemBio::new()?;
            cvt(ffi::i2d_PKCS8PrivateKey_bio(
                bio.as_ptr(),
                self.as_ptr(),
                cipher.as_ptr(),
                passphrase.as_ptr() as *const _ as *mut _,
                passphrase.len().try_into().unwrap(),
                None,
                ptr::null_mut(),
            ))?;

            Ok(bio.get_buf().to_owned())
        }
    }
}

impl<T> fmt::Debug for PKey<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let alg = match self.id() {
            Id::RSA => "RSA",
            #[cfg(not(boringssl))]
            Id::HMAC => "HMAC",
            Id::DSA => "DSA",
            Id::DH => "DH",
            Id::EC => "EC",
            #[cfg(ossl111)]
            Id::ED25519 => "Ed25519",
            #[cfg(ossl111)]
            Id::ED448 => "Ed448",
            _ => "unknown",
        };
        fmt.debug_struct("PKey").field("algorithm", &alg).finish()
        // TODO: Print details for each specific type of key
    }
}

impl<T> Clone for PKey<T> {
    fn clone(&self) -> PKey<T> {
        PKeyRef::to_owned(self)
    }
}

impl<T> PKey<T> {
    /// Creates a new `PKey` containing an RSA key.
    #[corresponds(EVP_PKEY_assign_RSA)]
    pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
        unsafe {
            let evp = cvt_p(ffi::EVP_PKEY_new())?;
            let pkey = PKey::from_ptr(evp);
            cvt(ffi::EVP_PKEY_assign_RSA(pkey.0, rsa.as_ptr()))?;
            mem::forget(rsa);
            Ok(pkey)
        }
    }

    /// Creates a new `PKey` containing a DSA key.
    #[corresponds(EVP_PKEY_assign_DSA)]
    pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
        unsafe {
            let evp = cvt_p(ffi::EVP_PKEY_new())?;
            let pkey = PKey::from_ptr(evp);
            cvt(ffi::EVP_PKEY_assign_DSA(pkey.0, dsa.as_ptr()))?;
            mem::forget(dsa);
            Ok(pkey)
        }
    }

    /// Creates a new `PKey` containing a Diffie-Hellman key.
    #[corresponds(EVP_PKEY_assign_DH)]
    #[cfg(not(boringssl))]
    pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
        unsafe {
            let evp = cvt_p(ffi::EVP_PKEY_new())?;
            let pkey = PKey::from_ptr(evp);
            cvt(ffi::EVP_PKEY_assign_DH(pkey.0, dh.as_ptr()))?;
            mem::forget(dh);
            Ok(pkey)
        }
    }

    /// Creates a new `PKey` containing an elliptic curve key.
    #[corresponds(EVP_PKEY_assign_EC_KEY)]
    pub fn from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
        unsafe {
            let evp = cvt_p(ffi::EVP_PKEY_new())?;
            let pkey = PKey::from_ptr(evp);
            cvt(ffi::EVP_PKEY_assign_EC_KEY(pkey.0, ec_key.as_ptr()))?;
            mem::forget(ec_key);
            Ok(pkey)
        }
    }
}

impl PKey<Private> {
    /// Creates a new `PKey` containing an HMAC key.
    ///
    /// # Note
    ///
    /// To compute HMAC values, use the `sign` module.
    #[corresponds(EVP_PKEY_new_mac_key)]
    #[cfg(not(boringssl))]
    pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
        unsafe {
            assert!(key.len() <= c_int::max_value() as usize);
            let key = cvt_p(ffi::EVP_PKEY_new_mac_key(
                ffi::EVP_PKEY_HMAC,
                ptr::null_mut(),
                key.as_ptr() as *const _,
                key.len() as c_int,
            ))?;
            Ok(PKey::from_ptr(key))
        }
    }

    /// Creates a new `PKey` containing a CMAC key.
    ///
    /// Requires OpenSSL 1.1.0 or newer.
    ///
    /// # Note
    ///
    /// To compute CMAC values, use the `sign` module.
    #[cfg(all(not(boringssl), ossl110))]
    #[allow(clippy::trivially_copy_pass_by_ref)]
    pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> {
        let mut ctx = PkeyCtx::new_id(Id::CMAC)?;
        ctx.keygen_init()?;
        ctx.set_keygen_cipher(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) })?;
        ctx.set_keygen_mac_key(key)?;
        ctx.keygen()
    }

    #[cfg(any(ossl111, boringssl, libressl370))]
    fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> {
        let mut ctx = PkeyCtx::new_id(id)?;
        ctx.keygen_init()?;
        ctx.keygen()
    }

    /// Generates a new private X25519 key.
    ///
    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
    ///
    /// # Examples
    ///
    /// ```
    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
    /// use openssl::pkey::{PKey, Id};
    /// use openssl::derive::Deriver;
    ///
    /// let public = // ...
    /// # &PKey::generate_x25519()?.raw_public_key()?;
    /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X25519)?;
    ///
    /// let key = PKey::generate_x25519()?;
    /// let mut deriver = Deriver::new(&key)?;
    /// deriver.set_peer(&public_key)?;
    ///
    /// let secret = deriver.derive_to_vec()?;
    /// assert_eq!(secret.len(), 32);
    /// # Ok(()) }
    /// ```
    #[cfg(any(ossl111, boringssl, libressl370))]
    pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> {
        PKey::generate_eddsa(Id::X25519)
    }

    /// Generates a new private X448 key.
    ///
    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
    ///
    /// # Examples
    ///
    /// ```
    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
    /// use openssl::pkey::{PKey, Id};
    /// use openssl::derive::Deriver;
    ///
    /// let public = // ...
    /// # &PKey::generate_x448()?.raw_public_key()?;
    /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X448)?;
    ///
    /// let key = PKey::generate_x448()?;
    /// let mut deriver = Deriver::new(&key)?;
    /// deriver.set_peer(&public_key)?;
    ///
    /// let secret = deriver.derive_to_vec()?;
    /// assert_eq!(secret.len(), 56);
    /// # Ok(()) }
    /// ```
    #[cfg(ossl111)]
    pub fn generate_x448() -> Result<PKey<Private>, ErrorStack> {
        PKey::generate_eddsa(Id::X448)
    }

    /// Generates a new private Ed25519 key.
    ///
    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
    ///
    /// # Examples
    ///
    /// ```
    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
    /// use openssl::pkey::{PKey, Id};
    /// use openssl::sign::Signer;
    ///
    /// let key = PKey::generate_ed25519()?;
    /// let public_key = key.raw_public_key()?;
    ///
    /// let mut signer = Signer::new_without_digest(&key)?;
    /// let digest = // ...
    /// # &vec![0; 32];
    /// let signature = signer.sign_oneshot_to_vec(digest)?;
    /// assert_eq!(signature.len(), 64);
    /// # Ok(()) }
    /// ```
    #[cfg(any(ossl111, boringssl, libressl370))]
    pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> {
        PKey::generate_eddsa(Id::ED25519)
    }

    /// Generates a new private Ed448 key.
    ///
    /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`].
    ///
    /// # Examples
    ///
    /// ```
    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
    /// use openssl::pkey::{PKey, Id};
    /// use openssl::sign::Signer;
    ///
    /// let key = PKey::generate_ed448()?;
    /// let public_key = key.raw_public_key()?;
    ///
    /// let mut signer = Signer::new_without_digest(&key)?;
    /// let digest = // ...
    /// # &vec![0; 32];
    /// let signature = signer.sign_oneshot_to_vec(digest)?;
    /// assert_eq!(signature.len(), 114);
    /// # Ok(()) }
    /// ```
    #[cfg(ossl111)]
    pub fn generate_ed448() -> Result<PKey<Private>, ErrorStack> {
        PKey::generate_eddsa(Id::ED448)
    }

    /// Generates a new EC key using the provided curve.
    ///
    /// Requires OpenSSL 3.0.0 or newer.
    #[corresponds(EVP_EC_gen)]
    #[cfg(ossl300)]
    pub fn ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack> {
        ffi::init();

        let curve = CString::new(curve).unwrap();
        unsafe {
            let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?;
            Ok(PKey::from_ptr(ptr))
        }
    }

    private_key_from_pem! {
        /// Deserializes a private key from a PEM-encoded key type specific format.
        #[corresponds(PEM_read_bio_PrivateKey)]
        private_key_from_pem,

        /// Deserializes a private key from a PEM-encoded encrypted key type specific format.
        #[corresponds(PEM_read_bio_PrivateKey)]
        private_key_from_pem_passphrase,

        /// Deserializes a private key from a PEM-encoded encrypted key type specific format.
        ///
        /// The callback should fill the password into the provided buffer and return its length.
        #[corresponds(PEM_read_bio_PrivateKey)]
        private_key_from_pem_callback,
        PKey<Private>,
        ffi::PEM_read_bio_PrivateKey
    }

    from_der! {
        /// Decodes a DER-encoded private key.
        ///
        /// This function will attempt to automatically detect the underlying key format, and
        /// supports the unencrypted PKCS#8 PrivateKeyInfo structures as well as key type specific
        /// formats.
        #[corresponds(d2i_AutoPrivateKey)]
        private_key_from_der,
        PKey<Private>,
        ffi::d2i_AutoPrivateKey
    }

    /// Deserializes a DER-formatted PKCS#8 unencrypted private key.
    ///
    /// This method is mainly for interoperability reasons. Encrypted keyfiles should be preferred.
    pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> {
        unsafe {
            ffi::init();
            let len = der.len().min(c_long::max_value() as usize) as c_long;
            let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO(
                ptr::null_mut(),
                &mut der.as_ptr(),
                len,
            ))?;
            let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p));
            ffi::PKCS8_PRIV_KEY_INFO_free(p8inf);
            res
        }
    }

    /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password
    /// if the key is encrypted.
    ///
    /// The callback should copy the password into the provided buffer and return the number of
    /// bytes written.
    #[corresponds(d2i_PKCS8PrivateKey_bio)]
    pub fn private_key_from_pkcs8_callback<F>(
        der: &[u8],
        callback: F,
    ) -> Result<PKey<Private>, ErrorStack>
    where
        F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
    {
        unsafe {
            ffi::init();
            let mut cb = CallbackState::new(callback);
            let bio = MemBioSlice::new(der)?;
            cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
                bio.as_ptr(),
                ptr::null_mut(),
                Some(invoke_passwd_cb::<F>),
                &mut cb as *mut _ as *mut _,
            ))
            .map(|p| PKey::from_ptr(p))
        }
    }

    /// Deserializes a DER-formatted PKCS#8 private key, using the supplied password if the key is
    /// encrypted.
    ///
    /// # Panics
    ///
    /// Panics if `passphrase` contains an embedded null.
    #[corresponds(d2i_PKCS8PrivateKey_bio)]
    pub fn private_key_from_pkcs8_passphrase(
        der: &[u8],
        passphrase: &[u8],
    ) -> Result<PKey<Private>, ErrorStack> {
        unsafe {
            ffi::init();
            let bio = MemBioSlice::new(der)?;
            let passphrase = CString::new(passphrase).unwrap();
            cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
                bio.as_ptr(),
                ptr::null_mut(),
                None,
                passphrase.as_ptr() as *const _ as *mut _,
            ))
            .map(|p| PKey::from_ptr(p))
        }
    }

    /// Creates a private key from its raw byte representation
    ///
    /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448
    #[corresponds(EVP_PKEY_new_raw_private_key)]
    #[cfg(any(ossl111, boringssl, libressl370))]
    pub fn private_key_from_raw_bytes(
        bytes: &[u8],
        key_type: Id,
    ) -> Result<PKey<Private>, ErrorStack> {
        unsafe {
            ffi::init();
            cvt_p(ffi::EVP_PKEY_new_raw_private_key(
                key_type.as_raw(),
                ptr::null_mut(),
                bytes.as_ptr(),
                bytes.len(),
            ))
            .map(|p| PKey::from_ptr(p))
        }
    }
}

impl PKey<Public> {
    from_pem! {
        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure.
        ///
        /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
        #[corresponds(PEM_read_bio_PUBKEY)]
        public_key_from_pem,
        PKey<Public>,
        ffi::PEM_read_bio_PUBKEY
    }

    from_der! {
        /// Decodes a DER-encoded SubjectPublicKeyInfo structure.
        #[corresponds(d2i_PUBKEY)]
        public_key_from_der,
        PKey<Public>,
        ffi::d2i_PUBKEY
    }

    /// Creates a public key from its raw byte representation
    ///
    /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448
    #[corresponds(EVP_PKEY_new_raw_public_key)]
    #[cfg(any(ossl111, boringssl, libressl370))]
    pub fn public_key_from_raw_bytes(
        bytes: &[u8],
        key_type: Id,
    ) -> Result<PKey<Public>, ErrorStack> {
        unsafe {
            ffi::init();
            cvt_p(ffi::EVP_PKEY_new_raw_public_key(
                key_type.as_raw(),
                ptr::null_mut(),
                bytes.as_ptr(),
                bytes.len(),
            ))
            .map(|p| PKey::from_ptr(p))
        }
    }
}

cfg_if! {
    if #[cfg(any(boringssl, ossl110, libressl270))] {
        use ffi::EVP_PKEY_up_ref;
    } else {
        #[allow(bad_style)]
        unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) {
            ffi::CRYPTO_add_lock(
                &mut (*pkey).references,
                1,
                ffi::CRYPTO_LOCK_EVP_PKEY,
                "pkey.rs\0".as_ptr() as *const _,
                line!() as c_int,
            );
        }
    }
}

impl<T> TryFrom<EcKey<T>> for PKey<T> {
    type Error = ErrorStack;

    fn try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> {
        PKey::from_ec_key(ec_key)
    }
}

impl<T> TryFrom<PKey<T>> for EcKey<T> {
    type Error = ErrorStack;

    fn try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack> {
        pkey.ec_key()
    }
}

impl<T> TryFrom<Rsa<T>> for PKey<T> {
    type Error = ErrorStack;

    fn try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> {
        PKey::from_rsa(rsa)
    }
}

impl<T> TryFrom<PKey<T>> for Rsa<T> {
    type Error = ErrorStack;

    fn try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack> {
        pkey.rsa()
    }
}

impl<T> TryFrom<Dsa<T>> for PKey<T> {
    type Error = ErrorStack;

    fn try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> {
        PKey::from_dsa(dsa)
    }
}

impl<T> TryFrom<PKey<T>> for Dsa<T> {
    type Error = ErrorStack;

    fn try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack> {
        pkey.dsa()
    }
}

#[cfg(not(boringssl))]
impl<T> TryFrom<Dh<T>> for PKey<T> {
    type Error = ErrorStack;

    fn try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
        PKey::from_dh(dh)
    }
}

impl<T> TryFrom<PKey<T>> for Dh<T> {
    type Error = ErrorStack;

    fn try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack> {
        pkey.dh()
    }
}

#[cfg(test)]
mod tests {
    use std::convert::TryInto;

    #[cfg(not(boringssl))]
    use crate::dh::Dh;
    use crate::dsa::Dsa;
    use crate::ec::EcKey;
    use crate::error::Error;
    use crate::nid::Nid;
    use crate::rsa::Rsa;
    use crate::symm::Cipher;

    use super::*;

    #[cfg(ossl111)]
    use crate::rand::rand_bytes;

    #[test]
    fn test_to_password() {
        let rsa = Rsa::generate(2048).unwrap();
        let pkey = PKey::from_rsa(rsa).unwrap();
        let pem = pkey
            .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar")
            .unwrap();
        PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
        assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
    }

    #[test]
    fn test_unencrypted_pkcs8() {
        let key = include_bytes!("../test/pkcs8-nocrypt.der");
        let pkey = PKey::private_key_from_pkcs8(key).unwrap();
        let serialized = pkey.private_key_to_pkcs8().unwrap();
        let pkey2 = PKey::private_key_from_pkcs8(&serialized).unwrap();

        assert_eq!(
            pkey2.private_key_to_der().unwrap(),
            pkey.private_key_to_der().unwrap()
        );
    }

    #[test]
    fn test_encrypted_pkcs8_passphrase() {
        let key = include_bytes!("../test/pkcs8.der");
        PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap();

        let rsa = Rsa::generate(2048).unwrap();
        let pkey = PKey::from_rsa(rsa).unwrap();
        let der = pkey
            .private_key_to_pkcs8_passphrase(Cipher::aes_128_cbc(), b"mypass")
            .unwrap();
        let pkey2 = PKey::private_key_from_pkcs8_passphrase(&der, b"mypass").unwrap();
        assert_eq!(
            pkey.private_key_to_der().unwrap(),
            pkey2.private_key_to_der().unwrap()
        );
    }

    #[test]
    fn test_encrypted_pkcs8_callback() {
        let mut password_queried = false;
        let key = include_bytes!("../test/pkcs8.der");
        PKey::private_key_from_pkcs8_callback(key, |password| {
            password_queried = true;
            password[..6].copy_from_slice(b"mypass");
            Ok(6)
        })
        .unwrap();
        assert!(password_queried);
    }

    #[test]
    fn test_private_key_from_pem() {
        let key = include_bytes!("../test/key.pem");
        PKey::private_key_from_pem(key).unwrap();
    }

    #[test]
    fn test_public_key_from_pem() {
        let key = include_bytes!("../test/key.pem.pub");
        PKey::public_key_from_pem(key).unwrap();
    }

    #[test]
    fn test_public_key_from_der() {
        let key = include_bytes!("../test/key.der.pub");
        PKey::public_key_from_der(key).unwrap();
    }

    #[test]
    fn test_private_key_from_der() {
        let key = include_bytes!("../test/key.der");
        PKey::private_key_from_der(key).unwrap();
    }

    #[test]
    fn test_pem() {
        let key = include_bytes!("../test/key.pem");
        let key = PKey::private_key_from_pem(key).unwrap();

        let priv_key = key.private_key_to_pem_pkcs8().unwrap();
        let pub_key = key.public_key_to_pem().unwrap();

        // As a super-simple verification, just check that the buffers contain
        // the `PRIVATE KEY` or `PUBLIC KEY` strings.
        assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY"));
        assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY"));
    }

    #[test]
    fn test_rsa_accessor() {
        let rsa = Rsa::generate(2048).unwrap();
        let pkey = PKey::from_rsa(rsa).unwrap();
        pkey.rsa().unwrap();
        assert_eq!(pkey.id(), Id::RSA);
        assert!(pkey.dsa().is_err());
    }

    #[test]
    fn test_dsa_accessor() {
        let dsa = Dsa::generate(2048).unwrap();
        let pkey = PKey::from_dsa(dsa).unwrap();
        pkey.dsa().unwrap();
        assert_eq!(pkey.id(), Id::DSA);
        assert!(pkey.rsa().is_err());
    }

    #[test]
    #[cfg(not(boringssl))]
    fn test_dh_accessor() {
        let dh = include_bytes!("../test/dhparams.pem");
        let dh = Dh::params_from_pem(dh).unwrap();
        let pkey = PKey::from_dh(dh).unwrap();
        pkey.dh().unwrap();
        assert_eq!(pkey.id(), Id::DH);
        assert!(pkey.rsa().is_err());
    }

    #[test]
    fn test_ec_key_accessor() {
        let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
        let pkey = PKey::from_ec_key(ec_key).unwrap();
        pkey.ec_key().unwrap();
        assert_eq!(pkey.id(), Id::EC);
        assert!(pkey.rsa().is_err());
    }

    #[test]
    fn test_rsa_conversion() {
        let rsa = Rsa::generate(2048).unwrap();
        let pkey: PKey<Private> = rsa.clone().try_into().unwrap();
        let rsa_: Rsa<Private> = pkey.try_into().unwrap();
        // Eq is missing
        assert_eq!(rsa.p(), rsa_.p());
        assert_eq!(rsa.q(), rsa_.q());
    }

    #[test]
    fn test_dsa_conversion() {
        let dsa = Dsa::generate(2048).unwrap();
        let pkey: PKey<Private> = dsa.clone().try_into().unwrap();
        let dsa_: Dsa<Private> = pkey.try_into().unwrap();
        // Eq is missing
        assert_eq!(dsa.priv_key(), dsa_.priv_key());
    }

    #[test]
    fn test_ec_key_conversion() {
        let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap();
        let ec_key = EcKey::generate(&group).unwrap();
        let pkey: PKey<Private> = ec_key.clone().try_into().unwrap();
        let ec_key_: EcKey<Private> = pkey.try_into().unwrap();
        // Eq is missing
        assert_eq!(ec_key.private_key(), ec_key_.private_key());
    }

    #[test]
    #[cfg(any(ossl110, libressl360))]
    fn test_security_bits() {
        let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::SECP521R1).unwrap();
        let ec_key = EcKey::generate(&group).unwrap();
        let pkey: PKey<Private> = ec_key.try_into().unwrap();

        assert_eq!(pkey.security_bits(), 256);
    }

    #[test]
    #[cfg(not(boringssl))]
    fn test_dh_conversion() {
        let dh_params = include_bytes!("../test/dhparams.pem");
        let dh_params = Dh::params_from_pem(dh_params).unwrap();
        let dh = dh_params.generate_key().unwrap();

        // Clone is missing for Dh, save the parameters
        let p = dh.prime_p().to_owned().unwrap();
        let q = dh.prime_q().map(|q| q.to_owned().unwrap());
        let g = dh.generator().to_owned().unwrap();

        let pkey: PKey<Private> = dh.try_into().unwrap();
        let dh_: Dh<Private> = pkey.try_into().unwrap();

        // Eq is missing
        assert_eq!(&p, dh_.prime_p());
        assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap()));
        assert_eq!(&g, dh_.generator());
    }

    #[cfg(any(ossl111, boringssl, libressl370))]
    fn test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
        // Generate a new key
        let key = gen().unwrap();

        // Get the raw bytes, and create a new key from the raw bytes
        let raw = key.raw_public_key().unwrap();
        let from_raw = PKey::public_key_from_raw_bytes(&raw, key_type).unwrap();

        // Compare the der encoding of the original and raw / restored public key
        assert_eq!(
            key.public_key_to_der().unwrap(),
            from_raw.public_key_to_der().unwrap()
        );
    }

    #[cfg(any(ossl111, boringssl, libressl370))]
    fn test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) {
        // Generate a new key
        let key = gen().unwrap();

        // Get the raw bytes, and create a new key from the raw bytes
        let raw = key.raw_private_key().unwrap();
        let from_raw = PKey::private_key_from_raw_bytes(&raw, key_type).unwrap();

        // Compare the der encoding of the original and raw / restored public key
        assert_eq!(
            key.private_key_to_pkcs8().unwrap(),
            from_raw.private_key_to_pkcs8().unwrap()
        );
    }

    #[cfg(any(ossl111, boringssl, libressl370))]
    #[test]
    fn test_raw_public_key_bytes() {
        test_raw_public_key(PKey::generate_x25519, Id::X25519);
        test_raw_public_key(PKey::generate_ed25519, Id::ED25519);
        #[cfg(all(not(boringssl), not(libressl370)))]
        test_raw_public_key(PKey::generate_x448, Id::X448);
        #[cfg(all(not(boringssl), not(libressl370)))]
        test_raw_public_key(PKey::generate_ed448, Id::ED448);
    }

    #[cfg(any(ossl111, boringssl, libressl370))]
    #[test]
    fn test_raw_private_key_bytes() {
        test_raw_private_key(PKey::generate_x25519, Id::X25519);
        test_raw_private_key(PKey::generate_ed25519, Id::ED25519);
        #[cfg(all(not(boringssl), not(libressl370)))]
        test_raw_private_key(PKey::generate_x448, Id::X448);
        #[cfg(all(not(boringssl), not(libressl370)))]
        test_raw_private_key(PKey::generate_ed448, Id::ED448);
    }

    #[cfg(ossl111)]
    #[test]
    fn test_raw_hmac() {
        let mut test_bytes = vec![0u8; 32];
        rand_bytes(&mut test_bytes).unwrap();

        let hmac_key = PKey::hmac(&test_bytes).unwrap();
        assert!(hmac_key.raw_public_key().is_err());

        let key_bytes = hmac_key.raw_private_key().unwrap();
        assert_eq!(key_bytes, test_bytes);
    }

    #[cfg(ossl111)]
    #[test]
    fn test_raw_key_fail() {
        // Getting a raw byte representation will not work with Nist curves
        let group = crate::ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
        let ec_key = EcKey::generate(&group).unwrap();
        let pkey = PKey::from_ec_key(ec_key).unwrap();
        assert!(pkey.raw_private_key().is_err());
        assert!(pkey.raw_public_key().is_err());
    }

    #[cfg(ossl300)]
    #[test]
    fn test_ec_gen() {
        let key = PKey::ec_gen("prime256v1").unwrap();
        assert!(key.ec_key().is_ok());
    }

    #[test]
    fn test_public_eq() {
        let rsa = Rsa::generate(2048).unwrap();
        let pkey1 = PKey::from_rsa(rsa).unwrap();

        let group = crate::ec::EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
        let ec_key = EcKey::generate(&group).unwrap();
        let pkey2 = PKey::from_ec_key(ec_key).unwrap();

        assert!(!pkey1.public_eq(&pkey2));
        assert!(Error::get().is_none());
    }
}
