Loading openssl/src/pkey_ctx.rs +132 −158 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ //! ``` use crate::error::ErrorStack; use crate::md::MdRef; use crate::pkey::{HasPublic, PKeyRef}; use crate::pkey::{HasPrivate, HasPublic, PKeyRef}; use crate::rsa::Padding; #[cfg(any(ossl102, libressl310))] use crate::util; Loading @@ -33,18 +33,19 @@ use libc::c_int; use std::convert::TryFrom; use std::ptr; foreign_type_and_impl_send_sync! { generic_foreign_type_and_impl_send_sync! { type CType = ffi::EVP_PKEY_CTX; fn drop = ffi::EVP_PKEY_CTX_free; pub struct PkeyCtx; /// A context object which can perform asymmetric cryptography operations. pub struct PkeyCtx<T>; /// A reference to a [`PkeyCtx`]. pub struct PkeyCtxRef; pub struct PkeyCtxRef<T>; } impl PkeyCtx { impl<T> PkeyCtx<T> { #[inline] pub fn new<T>(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> { pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> { unsafe { let ptr = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?; Ok(PkeyCtx::from_ptr(ptr)) Loading @@ -52,7 +53,10 @@ impl PkeyCtx { } } impl PkeyCtxRef { impl<T> PkeyCtxRef<T> where T: HasPublic, { /// Prepares the context for encryption using the public key. /// /// This corresponds to [`EVP_PKEY_encrypt_init`]. Loading @@ -67,6 +71,45 @@ impl PkeyCtxRef { Ok(()) } /// Encrypts data using the public key. /// /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be /// returned. /// /// This corresponds to [`EVP_PKEY_encrypt`]. /// /// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html #[inline] pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut written = to.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_encrypt( self.as_ptr(), to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut written, from.as_ptr(), from.len(), ))?; } Ok(written) } /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`]. pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = out.len(); let len = self.encrypt(from, None)?; out.resize(base + len, 0); let len = self.encrypt(from, Some(&mut out[base..]))?; out.truncate(base + len); Ok(len) } } impl<T> PkeyCtxRef<T> where T: HasPrivate, { /// Prepares the context for encryption using the private key. /// /// This corresponds to [`EVP_PKEY_decrypt_init`]. Loading Loading @@ -95,6 +138,88 @@ impl PkeyCtxRef { Ok(()) } /// Sets the peer key used for secret derivation. /// /// This corresponds to [`EVP_PKEY_derive_set_peer`]. /// /// [`EVP_PKEY_derive_set_peer`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_derive_set_peer.html pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> where U: HasPublic, { unsafe { cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?; } Ok(()) } /// Decrypts data using the private key. /// /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be /// returned. /// /// This corresponds to [`EVP_PKEY_decrypt`]. /// /// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html #[inline] pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut written = to.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_decrypt( self.as_ptr(), to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut written, from.as_ptr(), from.len(), ))?; } Ok(written) } /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`]. pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = out.len(); let len = self.decrypt(from, None)?; out.resize(base + len, 0); let len = self.decrypt(from, Some(&mut out[base..]))?; out.truncate(base + len); Ok(len) } /// Derives a shared secrete between two keys. /// /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned. /// /// This corresponds to [`EVP_PKEY_derive`]. /// /// [`EVP_PKEY_derive`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_derive_init.html pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut len = buf.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_derive( self.as_ptr(), buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut len, ))?; } Ok(len) } /// Like [`Self::derive`] but appends the secret to a [`Vec`]. pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = buf.len(); let len = self.derive(None)?; buf.resize(base + len, 0); let len = self.derive(Some(&mut buf[base..]))?; buf.truncate(base + len); Ok(len) } } impl<T> PkeyCtxRef<T> { /// Returns the RSA padding mode in use. /// /// This is only useful for RSA keys. Loading Loading @@ -194,150 +319,17 @@ impl PkeyCtxRef { Ok(()) } /// Sets the peer key used for secret derivation. /// /// This corresponds to [`EVP_PKEY_derive_set_peer`]. /// /// [`EVP_PKEY_derive_set_peer`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_derive_set_peer.html pub fn derive_set_peer<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> where T: HasPublic, { unsafe { cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?; } Ok(()) } /// Encrypts data using the public key. /// /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be /// returned. /// /// This corresponds to [`EVP_PKEY_encrypt`]. /// /// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html #[inline] pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut written = to.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_encrypt( self.as_ptr(), to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut written, from.as_ptr(), from.len(), ))?; } Ok(written) } /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`]. pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = out.len(); let len = self.encrypt(from, None)?; out.resize(base + len, 0); let len = self.encrypt(from, Some(&mut out[base..]))?; out.truncate(base + len); Ok(len) } /// Decrypts data using the private key. /// /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be /// returned. /// /// This corresponds to [`EVP_PKEY_decrypt`]. /// /// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html #[inline] pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut written = to.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_decrypt( self.as_ptr(), to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut written, from.as_ptr(), from.len(), ))?; } Ok(written) } /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`]. pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = out.len(); let len = self.decrypt(from, None)?; out.resize(base + len, 0); let len = self.decrypt(from, Some(&mut out[base..]))?; out.truncate(base + len); Ok(len) } /// Derives a shared secrete between two keys. /// /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned. /// /// This corresponds to [`EVP_PKEY_derive`]. /// /// [`EVP_PKEY_derive`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_derive_init.html pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut len = buf.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_derive( self.as_ptr(), buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut len, ))?; } Ok(len) } /// Like [`Self::derive`] but appends the secret to a [`Vec`]. pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = buf.len(); let len = self.derive(None)?; buf.resize(base + len, 0); let len = self.derive(Some(&mut buf[base..]))?; buf.truncate(base + len); Ok(len) } } #[cfg(test)] mod test { use super::*; use crate::dh::Dh; use crate::ec::{EcGroup, EcKey}; use crate::md::Md; use crate::nid::Nid; use crate::pkey::PKey; use crate::rsa::Rsa; #[test] fn decrypt_without_private_key() { let key = Rsa::public_key_from_pem(include_bytes!("../test/rsa.pem.pub")).unwrap(); let key = PKey::from_rsa(key).unwrap(); let mut ctx = PkeyCtx::new(&key).unwrap(); let pt = "hello".as_bytes(); ctx.encrypt_init().unwrap(); let mut ct = vec![]; ctx.encrypt_to_vec(pt, &mut ct).unwrap(); ctx.decrypt_init().unwrap(); let mut out = vec![]; ctx.decrypt_to_vec(&ct, &mut out).unwrap_err(); } #[test] fn rsa() { let key = include_bytes!("../test/rsa.pem"); Loading Loading @@ -389,24 +381,6 @@ mod test { assert_eq!(pt, out); } #[test] fn dh_derive_without_components() { let key1 = Dh::params_from_pem(include_bytes!("../test/dhparams.pem")).unwrap(); let key1 = PKey::from_dh(key1).unwrap(); let key2 = Dh::params_from_pem(include_bytes!("../test/dhparams.pem")) .unwrap() .generate_key() .unwrap(); let key2 = PKey::from_dh(key2).unwrap(); let mut ctx = PkeyCtx::new(&key1).unwrap(); ctx.derive_init().unwrap(); ctx.derive_set_peer(&key2).unwrap(); let mut buf = vec![]; ctx.derive_to_vec(&mut buf).unwrap_err(); } #[test] fn derive() { let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); Loading Loading
openssl/src/pkey_ctx.rs +132 −158 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ //! ``` use crate::error::ErrorStack; use crate::md::MdRef; use crate::pkey::{HasPublic, PKeyRef}; use crate::pkey::{HasPrivate, HasPublic, PKeyRef}; use crate::rsa::Padding; #[cfg(any(ossl102, libressl310))] use crate::util; Loading @@ -33,18 +33,19 @@ use libc::c_int; use std::convert::TryFrom; use std::ptr; foreign_type_and_impl_send_sync! { generic_foreign_type_and_impl_send_sync! { type CType = ffi::EVP_PKEY_CTX; fn drop = ffi::EVP_PKEY_CTX_free; pub struct PkeyCtx; /// A context object which can perform asymmetric cryptography operations. pub struct PkeyCtx<T>; /// A reference to a [`PkeyCtx`]. pub struct PkeyCtxRef; pub struct PkeyCtxRef<T>; } impl PkeyCtx { impl<T> PkeyCtx<T> { #[inline] pub fn new<T>(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> { pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> { unsafe { let ptr = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?; Ok(PkeyCtx::from_ptr(ptr)) Loading @@ -52,7 +53,10 @@ impl PkeyCtx { } } impl PkeyCtxRef { impl<T> PkeyCtxRef<T> where T: HasPublic, { /// Prepares the context for encryption using the public key. /// /// This corresponds to [`EVP_PKEY_encrypt_init`]. Loading @@ -67,6 +71,45 @@ impl PkeyCtxRef { Ok(()) } /// Encrypts data using the public key. /// /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be /// returned. /// /// This corresponds to [`EVP_PKEY_encrypt`]. /// /// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html #[inline] pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut written = to.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_encrypt( self.as_ptr(), to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut written, from.as_ptr(), from.len(), ))?; } Ok(written) } /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`]. pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = out.len(); let len = self.encrypt(from, None)?; out.resize(base + len, 0); let len = self.encrypt(from, Some(&mut out[base..]))?; out.truncate(base + len); Ok(len) } } impl<T> PkeyCtxRef<T> where T: HasPrivate, { /// Prepares the context for encryption using the private key. /// /// This corresponds to [`EVP_PKEY_decrypt_init`]. Loading Loading @@ -95,6 +138,88 @@ impl PkeyCtxRef { Ok(()) } /// Sets the peer key used for secret derivation. /// /// This corresponds to [`EVP_PKEY_derive_set_peer`]. /// /// [`EVP_PKEY_derive_set_peer`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_derive_set_peer.html pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> where U: HasPublic, { unsafe { cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?; } Ok(()) } /// Decrypts data using the private key. /// /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be /// returned. /// /// This corresponds to [`EVP_PKEY_decrypt`]. /// /// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html #[inline] pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut written = to.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_decrypt( self.as_ptr(), to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut written, from.as_ptr(), from.len(), ))?; } Ok(written) } /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`]. pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = out.len(); let len = self.decrypt(from, None)?; out.resize(base + len, 0); let len = self.decrypt(from, Some(&mut out[base..]))?; out.truncate(base + len); Ok(len) } /// Derives a shared secrete between two keys. /// /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned. /// /// This corresponds to [`EVP_PKEY_derive`]. /// /// [`EVP_PKEY_derive`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_derive_init.html pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut len = buf.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_derive( self.as_ptr(), buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut len, ))?; } Ok(len) } /// Like [`Self::derive`] but appends the secret to a [`Vec`]. pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = buf.len(); let len = self.derive(None)?; buf.resize(base + len, 0); let len = self.derive(Some(&mut buf[base..]))?; buf.truncate(base + len); Ok(len) } } impl<T> PkeyCtxRef<T> { /// Returns the RSA padding mode in use. /// /// This is only useful for RSA keys. Loading Loading @@ -194,150 +319,17 @@ impl PkeyCtxRef { Ok(()) } /// Sets the peer key used for secret derivation. /// /// This corresponds to [`EVP_PKEY_derive_set_peer`]. /// /// [`EVP_PKEY_derive_set_peer`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_derive_set_peer.html pub fn derive_set_peer<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> where T: HasPublic, { unsafe { cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?; } Ok(()) } /// Encrypts data using the public key. /// /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be /// returned. /// /// This corresponds to [`EVP_PKEY_encrypt`]. /// /// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html #[inline] pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut written = to.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_encrypt( self.as_ptr(), to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut written, from.as_ptr(), from.len(), ))?; } Ok(written) } /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`]. pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = out.len(); let len = self.encrypt(from, None)?; out.resize(base + len, 0); let len = self.encrypt(from, Some(&mut out[base..]))?; out.truncate(base + len); Ok(len) } /// Decrypts data using the private key. /// /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be /// returned. /// /// This corresponds to [`EVP_PKEY_decrypt`]. /// /// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html #[inline] pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut written = to.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_decrypt( self.as_ptr(), to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut written, from.as_ptr(), from.len(), ))?; } Ok(written) } /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`]. pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = out.len(); let len = self.decrypt(from, None)?; out.resize(base + len, 0); let len = self.decrypt(from, Some(&mut out[base..]))?; out.truncate(base + len); Ok(len) } /// Derives a shared secrete between two keys. /// /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned. /// /// This corresponds to [`EVP_PKEY_derive`]. /// /// [`EVP_PKEY_derive`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_derive_init.html pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut len = buf.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_derive( self.as_ptr(), buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut len, ))?; } Ok(len) } /// Like [`Self::derive`] but appends the secret to a [`Vec`]. pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = buf.len(); let len = self.derive(None)?; buf.resize(base + len, 0); let len = self.derive(Some(&mut buf[base..]))?; buf.truncate(base + len); Ok(len) } } #[cfg(test)] mod test { use super::*; use crate::dh::Dh; use crate::ec::{EcGroup, EcKey}; use crate::md::Md; use crate::nid::Nid; use crate::pkey::PKey; use crate::rsa::Rsa; #[test] fn decrypt_without_private_key() { let key = Rsa::public_key_from_pem(include_bytes!("../test/rsa.pem.pub")).unwrap(); let key = PKey::from_rsa(key).unwrap(); let mut ctx = PkeyCtx::new(&key).unwrap(); let pt = "hello".as_bytes(); ctx.encrypt_init().unwrap(); let mut ct = vec![]; ctx.encrypt_to_vec(pt, &mut ct).unwrap(); ctx.decrypt_init().unwrap(); let mut out = vec![]; ctx.decrypt_to_vec(&ct, &mut out).unwrap_err(); } #[test] fn rsa() { let key = include_bytes!("../test/rsa.pem"); Loading Loading @@ -389,24 +381,6 @@ mod test { assert_eq!(pt, out); } #[test] fn dh_derive_without_components() { let key1 = Dh::params_from_pem(include_bytes!("../test/dhparams.pem")).unwrap(); let key1 = PKey::from_dh(key1).unwrap(); let key2 = Dh::params_from_pem(include_bytes!("../test/dhparams.pem")) .unwrap() .generate_key() .unwrap(); let key2 = PKey::from_dh(key2).unwrap(); let mut ctx = PkeyCtx::new(&key1).unwrap(); ctx.derive_init().unwrap(); ctx.derive_set_peer(&key2).unwrap(); let mut buf = vec![]; ctx.derive_to_vec(&mut buf).unwrap_err(); } #[test] fn derive() { let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); Loading