diff --git a/boring/src/pkey.rs b/boring/src/pkey.rs index 07d3b548..9245f5b6 100644 --- a/boring/src/pkey.rs +++ b/boring/src/pkey.rs @@ -56,7 +56,7 @@ use crate::ec::EcKey; use crate::error::ErrorStack; use crate::rsa::Rsa; use crate::util::{invoke_passwd_cb, CallbackState}; -use crate::{cvt, cvt_p}; +use crate::{cvt, cvt_0i, cvt_p}; /// A tag type indicating that a key only has parameters. pub enum Params {} @@ -228,6 +228,36 @@ where { unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 } } + + /// Returns the length of the "raw" form of the public key. Only supported for certain key types. + #[corresponds(EVP_PKEY_get_raw_public_key)] + pub fn raw_public_key_len(&self) -> Result { + unsafe { + let mut size = 0; + _ = cvt_0i(ffi::EVP_PKEY_get_raw_public_key( + self.as_ptr(), + std::ptr::null_mut(), + &mut size, + ))?; + Ok(size) + } + } + + /// Outputs a copy of the "raw" form of the public key. Only supported for certain key types. + /// + /// Returns the used portion of `out`. + #[corresponds(EVP_PKEY_get_raw_public_key)] + pub fn raw_public_key<'a>(&self, out: &'a mut [u8]) -> Result<&'a [u8], ErrorStack> { + unsafe { + let mut size = out.len(); + _ = cvt_0i(ffi::EVP_PKEY_get_raw_public_key( + self.as_ptr(), + out.as_mut_ptr(), + &mut size, + ))?; + Ok(&out[..size]) + } + } } impl PKeyRef @@ -266,6 +296,36 @@ where private_key_to_der_pkcs8_passphrase, ffi::i2d_PKCS8PrivateKey_bio } + + /// Returns the length of the "raw" form of the private key. Only supported for certain key types. + #[corresponds(EVP_PKEY_get_raw_private_key)] + pub fn raw_private_key_len(&self) -> Result { + unsafe { + let mut size = 0; + _ = cvt_0i(ffi::EVP_PKEY_get_raw_private_key( + self.as_ptr(), + std::ptr::null_mut(), + &mut size, + ))?; + Ok(size) + } + } + + /// Outputs a copy of the "raw" form of the private key. Only supported for certain key types. + /// + /// Returns the used portion of `out`. + #[corresponds(EVP_PKEY_get_raw_private_key)] + pub fn raw_private_key<'a>(&self, out: &'a mut [u8]) -> Result<&'a [u8], ErrorStack> { + unsafe { + let mut size = out.len(); + _ = cvt_0i(ffi::EVP_PKEY_get_raw_private_key( + self.as_ptr(), + out.as_mut_ptr(), + &mut size, + ))?; + Ok(&out[..size]) + } + } } impl fmt::Debug for PKey { @@ -451,6 +511,8 @@ use crate::ffi::EVP_PKEY_up_ref; #[cfg(test)] mod tests { + use hex::FromHex as _; + use crate::ec::EcKey; use crate::nid::Nid; use crate::rsa::Rsa; @@ -561,4 +623,34 @@ mod tests { assert_eq!(pkey.id(), Id::EC); assert!(pkey.rsa().is_err()); } + + #[test] + fn test_raw_accessors() { + const ED25519_PRIVATE_KEY_DER: &str = concat!( + "302e020100300506032b6570042204207c8c6497f9960d5595d7815f550569e5", + "f77764ac97e63e339aaa68cc1512b683" + ); + let pkey = + PKey::private_key_from_der(&Vec::from_hex(ED25519_PRIVATE_KEY_DER).unwrap()).unwrap(); + assert_eq!(pkey.id(), Id::ED25519); + + let priv_len = pkey.raw_private_key_len().unwrap(); + assert_eq!(priv_len, 32); + let mut raw_private_key_buf = [0; 40]; + let raw_private_key = pkey.raw_private_key(&mut raw_private_key_buf).unwrap(); + assert_eq!(raw_private_key.len(), 32); + assert_ne!(raw_private_key, [0; 32]); + pkey.raw_private_key(&mut [0; 5]) + .expect_err("buffer too small"); + + let pub_len = pkey.raw_public_key_len().unwrap(); + assert_eq!(pub_len, 32); + let mut raw_public_key_buf = [0; 40]; + let raw_public_key = pkey.raw_public_key(&mut raw_public_key_buf).unwrap(); + assert_eq!(raw_public_key.len(), 32); + assert_ne!(raw_public_key, [0; 32]); + assert_ne!(raw_public_key, raw_private_key); + pkey.raw_public_key(&mut [0; 5]) + .expect_err("buffer too small"); + } }