Loading openssl-sys/src/evp.rs +124 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ pub const EVP_PKEY_X448: c_int = NID_X448; pub const EVP_PKEY_ED448: c_int = NID_ED448; pub const EVP_PKEY_HMAC: c_int = NID_hmac; pub const EVP_PKEY_CMAC: c_int = NID_cmac; #[cfg(ossl110)] pub const EVP_PKEY_HKDF: c_int = NID_hkdf; pub const EVP_CTRL_GCM_SET_IVLEN: c_int = 0x9; pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10; Loading Loading @@ -561,6 +563,7 @@ cfg_if! { pub const EVP_PKEY_OP_VERIFYCTX: c_int = 1 << 8; pub const EVP_PKEY_OP_ENCRYPT: c_int = 1 << 9; pub const EVP_PKEY_OP_DECRYPT: c_int = 1 << 10; pub const EVP_PKEY_OP_DERIVE: c_int = 1 << 11; } else { pub const EVP_PKEY_OP_SIGN: c_int = 1 << 3; pub const EVP_PKEY_OP_VERIFY: c_int = 1 << 4; Loading @@ -569,6 +572,7 @@ cfg_if! { pub const EVP_PKEY_OP_VERIFYCTX: c_int = 1 << 7; pub const EVP_PKEY_OP_ENCRYPT: c_int = 1 << 8; pub const EVP_PKEY_OP_DECRYPT: c_int = 1 << 9; pub const EVP_PKEY_OP_DERIVE: c_int = 1 << 10; } } Loading @@ -586,6 +590,30 @@ pub const EVP_PKEY_CTRL_CIPHER: c_int = 12; pub const EVP_PKEY_ALG_CTRL: c_int = 0x1000; #[cfg(ossl111)] pub const EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND: c_int = 0; #[cfg(ossl111)] pub const EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY: c_int = 1; #[cfg(ossl111)] pub const EVP_PKEY_HKDEF_MODE_EXPAND_ONLY: c_int = 2; #[cfg(ossl110)] pub const EVP_PKEY_CTRL_HKDF_MD: c_int = EVP_PKEY_ALG_CTRL + 3; #[cfg(ossl110)] pub const EVP_PKEY_CTRL_HKDF_SALT: c_int = EVP_PKEY_ALG_CTRL + 4; #[cfg(ossl110)] pub const EVP_PKEY_CTRL_HKDF_KEY: c_int = EVP_PKEY_ALG_CTRL + 5; #[cfg(ossl110)] pub const EVP_PKEY_CTRL_HKDF_INFO: c_int = EVP_PKEY_ALG_CTRL + 6; #[cfg(ossl111)] pub const EVP_PKEY_CTRL_HKDF_MODE: c_int = EVP_PKEY_ALG_CTRL + 7; extern "C" { pub fn EVP_PKEY_CTX_new(k: *mut EVP_PKEY, e: *mut ENGINE) -> *mut EVP_PKEY_CTX; pub fn EVP_PKEY_CTX_new_id(id: c_int, e: *mut ENGINE) -> *mut EVP_PKEY_CTX; Loading Loading @@ -639,6 +667,102 @@ extern "C" { ) -> c_int; } // HKDF Functions cfg_if! { if #[cfg(ossl300)] { extern "C" { pub fn EVP_PKEY_CTX_set_hkdf_mode(ctx: *mut EVP_PKEY_CTX, mode: c_int) -> c_int; pub fn EVP_PKEY_CTX_set_hkdf_md(ctx: *mut EVP_PKEY_CTX, md: *const EVP_MD) -> c_int; pub fn EVP_PKEY_CTX_set1_hkdf_salt( ctx: *mut EVP_PKEY_CTX, salt: *const u8, saltlen: c_int, ) -> c_int; pub fn EVP_PKEY_CTX_set1_hkdf_key( ctx: *mut EVP_PKEY_CTX, key: *const u8, keylen: c_int, ) -> c_int; pub fn EVP_PKEY_CTX_add1_hkdf_info( ctx: *mut EVP_PKEY_CTX, info: *const u8, infolen: c_int, ) -> c_int; } } else { #[cfg(ossl111)] pub unsafe fn EVP_PKEY_CTX_set_hkdf_mode(ctx: *mut EVP_PKEY_CTX, mode: c_int) -> c_int { EVP_PKEY_CTX_ctrl( ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_MODE, mode, std::ptr::null_mut(), ) } #[cfg(ossl110)] pub unsafe fn EVP_PKEY_CTX_set_hkdf_md(ctx: *mut EVP_PKEY_CTX, md: *const EVP_MD) -> c_int { EVP_PKEY_CTX_ctrl( ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_MD, 0, md as *mut c_void, ) } #[cfg(ossl110)] pub unsafe fn EVP_PKEY_CTX_set1_hkdf_salt( ctx: *mut EVP_PKEY_CTX, salt: *const u8, saltlen: c_int, ) -> c_int { EVP_PKEY_CTX_ctrl( ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_SALT, saltlen, salt as *mut c_void, ) } #[cfg(ossl110)] pub unsafe fn EVP_PKEY_CTX_set1_hkdf_key( ctx: *mut EVP_PKEY_CTX, key: *const u8, keylen: c_int, ) -> c_int { EVP_PKEY_CTX_ctrl( ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_KEY, keylen, key as *mut c_void, ) } #[cfg(ossl110)] pub unsafe fn EVP_PKEY_CTX_add1_hkdf_info( ctx: *mut EVP_PKEY_CTX, info: *const u8, infolen: c_int, ) -> c_int { EVP_PKEY_CTX_ctrl( ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_INFO, infolen, info as *mut c_void, ) } } } const_ptr_api! { extern "C" { pub fn EVP_PKCS82PKEY(p8: #[const_ptr_if(any(ossl110, libressl280))] PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY; Loading openssl-sys/src/obj_mac.rs +2 −0 Original line number Diff line number Diff line Loading @@ -916,6 +916,8 @@ pub const NID_aes_256_cbc_hmac_sha1: c_int = 918; pub const NID_X25519: c_int = 1034; #[cfg(ossl111)] pub const NID_X448: c_int = 1035; #[cfg(ossl110)] pub const NID_hkdf: c_int = 1036; #[cfg(ossl111)] pub const NID_ED25519: c_int = 1087; #[cfg(ossl111)] Loading openssl/src/pkey.rs +3 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,9 @@ impl Id { pub const DH: Id = Id(ffi::EVP_PKEY_DH); pub const EC: Id = Id(ffi::EVP_PKEY_EC); #[cfg(ossl110)] pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF); #[cfg(ossl111)] pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519); #[cfg(ossl111)] Loading openssl/src/pkey_ctx.rs +210 −36 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ //! use openssl::cipher::Cipher; //! //! let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap(); //! ctx.keygen_init(); //! ctx.keygen_init().unwrap(); //! ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap(); //! ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap(); //! let cmac_key = ctx.keygen().unwrap(); Loading @@ -45,6 +45,17 @@ use openssl_macros::corresponds; use std::convert::TryFrom; use std::ptr; /// HKDF modes of operation. #[cfg(ossl111)] pub struct HkdfMode(c_int); #[cfg(ossl111)] impl HkdfMode { pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND); pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY); pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY); } generic_foreign_type_and_impl_send_sync! { type CType = ffi::EVP_PKEY_CTX; fn drop = ffi::EVP_PKEY_CTX_free; Loading Loading @@ -141,17 +152,6 @@ where Ok(()) } /// Prepares the context for shared secret derivation. #[corresponds(EVP_PKEY_derive_init)] #[inline] pub fn derive_init(&mut self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?; } Ok(()) } /// Sets the peer key used for secret derivation. #[corresponds(EVP_PKEY_derive_set_peer)] pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> Loading Loading @@ -195,36 +195,20 @@ where 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. #[corresponds(EVP_PKEY_derive)] 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) impl<T> PkeyCtxRef<T> { /// Prepares the context for shared secret derivation. #[corresponds(EVP_PKEY_derive_init)] #[inline] pub fn derive_init(&mut self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?; } /// 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) } Ok(()) } impl<T> PkeyCtxRef<T> { /// Prepares the context for key generation. #[corresponds(EVP_PKEY_keygen_init)] pub fn keygen_init(&mut self) -> Result<(), ErrorStack> { Loading Loading @@ -322,6 +306,7 @@ impl<T> PkeyCtxRef<T> { /// Sets the cipher used during key generation. #[corresponds(EVP_PKEY_CTX_ctrl)] #[inline] pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_CTX_ctrl( Loading @@ -339,6 +324,7 @@ impl<T> PkeyCtxRef<T> { /// Sets the key MAC key used during key generation. #[corresponds(EVP_PKEY_CTX_ctrl)] #[inline] pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(key.len()).unwrap(); Loading @@ -356,8 +342,129 @@ impl<T> PkeyCtxRef<T> { Ok(()) } /// Sets the digest used for HKDF derivation. /// /// Requires OpenSSL 1.1.0 or newer. #[corresponds(EVP_PKEY_CTX_set_hkdf_md)] #[cfg(ossl110)] #[inline] pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_CTX_set_hkdf_md( self.as_ptr(), digest.as_ptr(), ))?; } Ok(()) } /// Sets the HKDF mode of operation. /// /// Defaults to [`HkdfMode::EXTRACT_THEN_EXPAND`]. /// /// Requires OpenSSL 1.1.1 or newer. #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)] #[cfg(ossl111)] #[inline] pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?; } Ok(()) } /// Sets the input keying material for HKDF generation. /// /// Requires OpenSSL 1.1.0 or newer. #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)] #[cfg(ossl110)] #[inline] pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(key.len()).unwrap(); unsafe { cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key( self.as_ptr(), key.as_ptr(), len, ))?; } Ok(()) } /// Sets the salt value for HKDF generation. /// /// Requires OpenSSL 1.1.0 or newer. #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)] #[cfg(ossl110)] #[inline] pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(salt.len()).unwrap(); unsafe { cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt( self.as_ptr(), salt.as_ptr(), len, ))?; } Ok(()) } /// Appends info bytes for HKDF generation. /// /// Requires OpenSSL 1.1.0 or newer. #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)] #[cfg(ossl110)] #[inline] pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(info.len()).unwrap(); unsafe { cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info( self.as_ptr(), info.as_ptr(), len, ))?; } Ok(()) } /// Derives a shared secret between two keys. /// /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned. #[corresponds(EVP_PKEY_derive)] 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) } /// Generates a new public/private keypair. #[corresponds(EVP_PKEY_keygen)] #[inline] pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> { unsafe { let mut key = ptr::null_mut(); Loading Loading @@ -454,4 +561,71 @@ mod test { .unwrap(); ctx.keygen().unwrap(); } #[test] #[cfg(ossl110)] fn hkdf() { let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); ctx.derive_init().unwrap(); ctx.set_hkdf_md(Md::sha256()).unwrap(); ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap()) .unwrap(); ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap()) .unwrap(); ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap()) .unwrap(); let mut out = [0; 42]; ctx.derive(Some(&mut out)).unwrap(); assert_eq!( &out[..], hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") .unwrap() ); } #[test] #[cfg(ossl111)] fn hkdf_expand() { let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); ctx.derive_init().unwrap(); ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap(); ctx.set_hkdf_md(Md::sha256()).unwrap(); ctx.set_hkdf_key( &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") .unwrap(), ) .unwrap(); ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap()) .unwrap(); let mut out = [0; 42]; ctx.derive(Some(&mut out)).unwrap(); assert_eq!( &out[..], hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") .unwrap() ); } #[test] #[cfg(ossl111)] fn hkdf_extract() { let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); ctx.derive_init().unwrap(); ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap(); ctx.set_hkdf_md(Md::sha256()).unwrap(); ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap()) .unwrap(); ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap()) .unwrap(); let mut out = vec![]; ctx.derive_to_vec(&mut out).unwrap(); assert_eq!( &out[..], hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") .unwrap() ); } } systest/build.rs +4 −1 Original line number Diff line number Diff line Loading @@ -63,8 +63,11 @@ fn main() { .header("openssl/evp.h") .header("openssl/x509_vfy.h"); if openssl_version.is_some() { if let Some(version) = openssl_version { cfg.header("openssl/cms.h"); if version >= 0x010100000 { cfg.header("openssl/kdf.h"); } } #[allow(clippy::if_same_then_else)] Loading Loading
openssl-sys/src/evp.rs +124 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ pub const EVP_PKEY_X448: c_int = NID_X448; pub const EVP_PKEY_ED448: c_int = NID_ED448; pub const EVP_PKEY_HMAC: c_int = NID_hmac; pub const EVP_PKEY_CMAC: c_int = NID_cmac; #[cfg(ossl110)] pub const EVP_PKEY_HKDF: c_int = NID_hkdf; pub const EVP_CTRL_GCM_SET_IVLEN: c_int = 0x9; pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10; Loading Loading @@ -561,6 +563,7 @@ cfg_if! { pub const EVP_PKEY_OP_VERIFYCTX: c_int = 1 << 8; pub const EVP_PKEY_OP_ENCRYPT: c_int = 1 << 9; pub const EVP_PKEY_OP_DECRYPT: c_int = 1 << 10; pub const EVP_PKEY_OP_DERIVE: c_int = 1 << 11; } else { pub const EVP_PKEY_OP_SIGN: c_int = 1 << 3; pub const EVP_PKEY_OP_VERIFY: c_int = 1 << 4; Loading @@ -569,6 +572,7 @@ cfg_if! { pub const EVP_PKEY_OP_VERIFYCTX: c_int = 1 << 7; pub const EVP_PKEY_OP_ENCRYPT: c_int = 1 << 8; pub const EVP_PKEY_OP_DECRYPT: c_int = 1 << 9; pub const EVP_PKEY_OP_DERIVE: c_int = 1 << 10; } } Loading @@ -586,6 +590,30 @@ pub const EVP_PKEY_CTRL_CIPHER: c_int = 12; pub const EVP_PKEY_ALG_CTRL: c_int = 0x1000; #[cfg(ossl111)] pub const EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND: c_int = 0; #[cfg(ossl111)] pub const EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY: c_int = 1; #[cfg(ossl111)] pub const EVP_PKEY_HKDEF_MODE_EXPAND_ONLY: c_int = 2; #[cfg(ossl110)] pub const EVP_PKEY_CTRL_HKDF_MD: c_int = EVP_PKEY_ALG_CTRL + 3; #[cfg(ossl110)] pub const EVP_PKEY_CTRL_HKDF_SALT: c_int = EVP_PKEY_ALG_CTRL + 4; #[cfg(ossl110)] pub const EVP_PKEY_CTRL_HKDF_KEY: c_int = EVP_PKEY_ALG_CTRL + 5; #[cfg(ossl110)] pub const EVP_PKEY_CTRL_HKDF_INFO: c_int = EVP_PKEY_ALG_CTRL + 6; #[cfg(ossl111)] pub const EVP_PKEY_CTRL_HKDF_MODE: c_int = EVP_PKEY_ALG_CTRL + 7; extern "C" { pub fn EVP_PKEY_CTX_new(k: *mut EVP_PKEY, e: *mut ENGINE) -> *mut EVP_PKEY_CTX; pub fn EVP_PKEY_CTX_new_id(id: c_int, e: *mut ENGINE) -> *mut EVP_PKEY_CTX; Loading Loading @@ -639,6 +667,102 @@ extern "C" { ) -> c_int; } // HKDF Functions cfg_if! { if #[cfg(ossl300)] { extern "C" { pub fn EVP_PKEY_CTX_set_hkdf_mode(ctx: *mut EVP_PKEY_CTX, mode: c_int) -> c_int; pub fn EVP_PKEY_CTX_set_hkdf_md(ctx: *mut EVP_PKEY_CTX, md: *const EVP_MD) -> c_int; pub fn EVP_PKEY_CTX_set1_hkdf_salt( ctx: *mut EVP_PKEY_CTX, salt: *const u8, saltlen: c_int, ) -> c_int; pub fn EVP_PKEY_CTX_set1_hkdf_key( ctx: *mut EVP_PKEY_CTX, key: *const u8, keylen: c_int, ) -> c_int; pub fn EVP_PKEY_CTX_add1_hkdf_info( ctx: *mut EVP_PKEY_CTX, info: *const u8, infolen: c_int, ) -> c_int; } } else { #[cfg(ossl111)] pub unsafe fn EVP_PKEY_CTX_set_hkdf_mode(ctx: *mut EVP_PKEY_CTX, mode: c_int) -> c_int { EVP_PKEY_CTX_ctrl( ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_MODE, mode, std::ptr::null_mut(), ) } #[cfg(ossl110)] pub unsafe fn EVP_PKEY_CTX_set_hkdf_md(ctx: *mut EVP_PKEY_CTX, md: *const EVP_MD) -> c_int { EVP_PKEY_CTX_ctrl( ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_MD, 0, md as *mut c_void, ) } #[cfg(ossl110)] pub unsafe fn EVP_PKEY_CTX_set1_hkdf_salt( ctx: *mut EVP_PKEY_CTX, salt: *const u8, saltlen: c_int, ) -> c_int { EVP_PKEY_CTX_ctrl( ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_SALT, saltlen, salt as *mut c_void, ) } #[cfg(ossl110)] pub unsafe fn EVP_PKEY_CTX_set1_hkdf_key( ctx: *mut EVP_PKEY_CTX, key: *const u8, keylen: c_int, ) -> c_int { EVP_PKEY_CTX_ctrl( ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_KEY, keylen, key as *mut c_void, ) } #[cfg(ossl110)] pub unsafe fn EVP_PKEY_CTX_add1_hkdf_info( ctx: *mut EVP_PKEY_CTX, info: *const u8, infolen: c_int, ) -> c_int { EVP_PKEY_CTX_ctrl( ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_INFO, infolen, info as *mut c_void, ) } } } const_ptr_api! { extern "C" { pub fn EVP_PKCS82PKEY(p8: #[const_ptr_if(any(ossl110, libressl280))] PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY; Loading
openssl-sys/src/obj_mac.rs +2 −0 Original line number Diff line number Diff line Loading @@ -916,6 +916,8 @@ pub const NID_aes_256_cbc_hmac_sha1: c_int = 918; pub const NID_X25519: c_int = 1034; #[cfg(ossl111)] pub const NID_X448: c_int = 1035; #[cfg(ossl110)] pub const NID_hkdf: c_int = 1036; #[cfg(ossl111)] pub const NID_ED25519: c_int = 1087; #[cfg(ossl111)] Loading
openssl/src/pkey.rs +3 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,9 @@ impl Id { pub const DH: Id = Id(ffi::EVP_PKEY_DH); pub const EC: Id = Id(ffi::EVP_PKEY_EC); #[cfg(ossl110)] pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF); #[cfg(ossl111)] pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519); #[cfg(ossl111)] Loading
openssl/src/pkey_ctx.rs +210 −36 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ //! use openssl::cipher::Cipher; //! //! let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap(); //! ctx.keygen_init(); //! ctx.keygen_init().unwrap(); //! ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap(); //! ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap(); //! let cmac_key = ctx.keygen().unwrap(); Loading @@ -45,6 +45,17 @@ use openssl_macros::corresponds; use std::convert::TryFrom; use std::ptr; /// HKDF modes of operation. #[cfg(ossl111)] pub struct HkdfMode(c_int); #[cfg(ossl111)] impl HkdfMode { pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND); pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY); pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY); } generic_foreign_type_and_impl_send_sync! { type CType = ffi::EVP_PKEY_CTX; fn drop = ffi::EVP_PKEY_CTX_free; Loading Loading @@ -141,17 +152,6 @@ where Ok(()) } /// Prepares the context for shared secret derivation. #[corresponds(EVP_PKEY_derive_init)] #[inline] pub fn derive_init(&mut self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?; } Ok(()) } /// Sets the peer key used for secret derivation. #[corresponds(EVP_PKEY_derive_set_peer)] pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> Loading Loading @@ -195,36 +195,20 @@ where 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. #[corresponds(EVP_PKEY_derive)] 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) impl<T> PkeyCtxRef<T> { /// Prepares the context for shared secret derivation. #[corresponds(EVP_PKEY_derive_init)] #[inline] pub fn derive_init(&mut self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?; } /// 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) } Ok(()) } impl<T> PkeyCtxRef<T> { /// Prepares the context for key generation. #[corresponds(EVP_PKEY_keygen_init)] pub fn keygen_init(&mut self) -> Result<(), ErrorStack> { Loading Loading @@ -322,6 +306,7 @@ impl<T> PkeyCtxRef<T> { /// Sets the cipher used during key generation. #[corresponds(EVP_PKEY_CTX_ctrl)] #[inline] pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_CTX_ctrl( Loading @@ -339,6 +324,7 @@ impl<T> PkeyCtxRef<T> { /// Sets the key MAC key used during key generation. #[corresponds(EVP_PKEY_CTX_ctrl)] #[inline] pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(key.len()).unwrap(); Loading @@ -356,8 +342,129 @@ impl<T> PkeyCtxRef<T> { Ok(()) } /// Sets the digest used for HKDF derivation. /// /// Requires OpenSSL 1.1.0 or newer. #[corresponds(EVP_PKEY_CTX_set_hkdf_md)] #[cfg(ossl110)] #[inline] pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_CTX_set_hkdf_md( self.as_ptr(), digest.as_ptr(), ))?; } Ok(()) } /// Sets the HKDF mode of operation. /// /// Defaults to [`HkdfMode::EXTRACT_THEN_EXPAND`]. /// /// Requires OpenSSL 1.1.1 or newer. #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)] #[cfg(ossl111)] #[inline] pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?; } Ok(()) } /// Sets the input keying material for HKDF generation. /// /// Requires OpenSSL 1.1.0 or newer. #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)] #[cfg(ossl110)] #[inline] pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(key.len()).unwrap(); unsafe { cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key( self.as_ptr(), key.as_ptr(), len, ))?; } Ok(()) } /// Sets the salt value for HKDF generation. /// /// Requires OpenSSL 1.1.0 or newer. #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)] #[cfg(ossl110)] #[inline] pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(salt.len()).unwrap(); unsafe { cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt( self.as_ptr(), salt.as_ptr(), len, ))?; } Ok(()) } /// Appends info bytes for HKDF generation. /// /// Requires OpenSSL 1.1.0 or newer. #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)] #[cfg(ossl110)] #[inline] pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(info.len()).unwrap(); unsafe { cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info( self.as_ptr(), info.as_ptr(), len, ))?; } Ok(()) } /// Derives a shared secret between two keys. /// /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned. #[corresponds(EVP_PKEY_derive)] 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) } /// Generates a new public/private keypair. #[corresponds(EVP_PKEY_keygen)] #[inline] pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> { unsafe { let mut key = ptr::null_mut(); Loading Loading @@ -454,4 +561,71 @@ mod test { .unwrap(); ctx.keygen().unwrap(); } #[test] #[cfg(ossl110)] fn hkdf() { let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); ctx.derive_init().unwrap(); ctx.set_hkdf_md(Md::sha256()).unwrap(); ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap()) .unwrap(); ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap()) .unwrap(); ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap()) .unwrap(); let mut out = [0; 42]; ctx.derive(Some(&mut out)).unwrap(); assert_eq!( &out[..], hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") .unwrap() ); } #[test] #[cfg(ossl111)] fn hkdf_expand() { let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); ctx.derive_init().unwrap(); ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap(); ctx.set_hkdf_md(Md::sha256()).unwrap(); ctx.set_hkdf_key( &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") .unwrap(), ) .unwrap(); ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap()) .unwrap(); let mut out = [0; 42]; ctx.derive(Some(&mut out)).unwrap(); assert_eq!( &out[..], hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") .unwrap() ); } #[test] #[cfg(ossl111)] fn hkdf_extract() { let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); ctx.derive_init().unwrap(); ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap(); ctx.set_hkdf_md(Md::sha256()).unwrap(); ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap()) .unwrap(); ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap()) .unwrap(); let mut out = vec![]; ctx.derive_to_vec(&mut out).unwrap(); assert_eq!( &out[..], hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") .unwrap() ); } }
systest/build.rs +4 −1 Original line number Diff line number Diff line Loading @@ -63,8 +63,11 @@ fn main() { .header("openssl/evp.h") .header("openssl/x509_vfy.h"); if openssl_version.is_some() { if let Some(version) = openssl_version { cfg.header("openssl/cms.h"); if version >= 0x010100000 { cfg.header("openssl/kdf.h"); } } #[allow(clippy::if_same_then_else)] Loading