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