Loading openssl-sys/src/handwritten/evp.rs +19 −0 Original line number Diff line number Diff line Loading @@ -538,6 +538,12 @@ extern "C" { #[cfg(ossl300)] pub fn EVP_PKEY_CTX_set_signature_md(ctx: *mut EVP_PKEY_CTX, md: *const EVP_MD) -> c_int; #[cfg(ossl300)] pub fn EVP_PKEY_CTX_set_params(ctx: *mut EVP_PKEY_CTX, params: *const OSSL_PARAM) -> c_int; #[cfg(ossl300)] pub fn EVP_PKEY_CTX_get_params(ctx: *mut EVP_PKEY_CTX, params: *mut OSSL_PARAM) -> c_int; pub fn EVP_PKEY_new_mac_key( type_: c_int, e: *mut ENGINE, Loading Loading @@ -646,3 +652,16 @@ extern "C" { pub fn EVP_EncodeBlock(dst: *mut c_uchar, src: *const c_uchar, src_len: c_int) -> c_int; pub fn EVP_DecodeBlock(dst: *mut c_uchar, src: *const c_uchar, src_len: c_int) -> c_int; } extern "C" { #[cfg(ossl300)] pub fn OSSL_PARAM_construct_uint(key: *const c_char, buf: *mut c_uint) -> OSSL_PARAM; #[cfg(ossl300)] pub fn OSSL_PARAM_construct_utf8_string( key: *const c_char, buf: *mut c_char, bsize: size_t, ) -> OSSL_PARAM; #[cfg(ossl300)] pub fn OSSL_PARAM_construct_end() -> OSSL_PARAM; } openssl-sys/src/handwritten/types.rs +10 −0 Original line number Diff line number Diff line Loading @@ -1093,3 +1093,13 @@ pub enum OSSL_PROVIDER {} #[cfg(ossl300)] pub enum OSSL_LIB_CTX {} #[cfg(ossl300)] #[repr(C)] pub struct OSSL_PARAM { key: *const c_char, data_type: c_uchar, data: *mut c_void, data_size: size_t, return_size: size_t, } openssl/CHANGELOG.md +6 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,12 @@ ## [Unreleased] ### Added * Added `PkeyCtxRef::{digest, set_digest, nonce_type, set_nonce_type}`. * Added `OSSL_PARAM`, `OSSL_PARAM_construct_uint` , `OSSL_PARAM_construct_utf8_string`, `OSSL_PARAM_construct_end` to openssl-sys. * Added `EVP_PKEY_CTX_set_params` and `EVP_PKEY_CTX_get_params` to openssl-sys. ## [v0.10.63] - 2024-01-19 ### Added Loading openssl/src/pkey_ctx.rs +154 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,8 @@ let cmac_key = ctx.keygen().unwrap(); #[cfg(not(boringssl))] use crate::cipher::CipherRef; use crate::error::ErrorStack; #[cfg(ossl300)] use crate::hash::MessageDigest; use crate::md::MdRef; use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private}; use crate::rsa::Padding; Loading @@ -75,8 +77,12 @@ use crate::{cvt, cvt_p}; use foreign_types::{ForeignType, ForeignTypeRef}; #[cfg(not(boringssl))] use libc::c_int; #[cfg(ossl320)] use libc::c_uint; use openssl_macros::corresponds; use std::convert::TryFrom; #[cfg(ossl300)] use std::ffi::CString; use std::ptr; /// HKDF modes of operation. Loading Loading @@ -105,6 +111,21 @@ impl HkdfMode { pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY); } /// Nonce type for ECDSA and DSA. #[cfg(ossl320)] #[derive(Debug, PartialEq)] pub struct NonceType(c_uint); #[cfg(ossl320)] impl NonceType { /// This is the default mode. It uses a random value for the nonce k as defined in FIPS 186-4 Section 6.3 /// “Secret Number Generation”. pub const RANDOM_K: Self = NonceType(0); /// Uses a deterministic value for the nonce k as defined in RFC #6979 (See Section 3.2 “Generation of k”). pub const DETERMINISTIC_K: Self = NonceType(1); } generic_foreign_type_and_impl_send_sync! { type CType = ffi::EVP_PKEY_CTX; fn drop = ffi::EVP_PKEY_CTX_free; Loading Loading @@ -714,6 +735,109 @@ impl<T> PkeyCtxRef<T> { Ok(PKey::from_ptr(key)) } } /// Sets the digest algorithm for a private key context. /// /// Requires OpenSSL 3.0.0 or newer. #[cfg(ossl300)] #[corresponds(EVP_PKEY_CTX_set_params)] pub fn set_digest(&mut self, hash_algorithm: MessageDigest) -> Result<(), ErrorStack> { let digest_name = hash_algorithm.type_().short_name()?; let digest = CString::new(digest_name).unwrap().into_raw(); let digest_field_name = CString::new("digest").unwrap(); unsafe { let param_digest = ffi::OSSL_PARAM_construct_utf8_string( digest_field_name.as_ptr(), digest, digest_name.len(), ); let param_end = ffi::OSSL_PARAM_construct_end(); let params = [param_digest, param_end]; cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?; // retake pointer to free memory let _ = CString::from_raw(digest); } Ok(()) } /// Gets the digest algorithm for a private key context. /// /// Requires OpenSSL 3.0.0 or newer. #[cfg(ossl300)] #[corresponds(EVP_PKEY_CTX_get_params)] pub fn digest(&mut self) -> Result<Option<MessageDigest>, ErrorStack> { use libc::c_char; // From openssl/internal/sizes.h let ossl_max_name_size = 50usize; let digest_field_name = CString::new("digest").unwrap(); let digest: *mut c_char = CString::new(vec![1; ossl_max_name_size]) .unwrap() .into_raw(); unsafe { let param_digest = ffi::OSSL_PARAM_construct_utf8_string( digest_field_name.as_ptr(), digest, ossl_max_name_size, ); let param_end = ffi::OSSL_PARAM_construct_end(); let mut params = [param_digest, param_end]; cvt(ffi::EVP_PKEY_CTX_get_params( self.as_ptr(), params.as_mut_ptr(), ))?; let digest_str = CString::from_raw(digest); Ok(MessageDigest::from_name(digest_str.to_str().unwrap())) } } /// Sets the nonce type for a private key context. /// /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979). /// /// This is only useful for DSA and ECDSA. /// Requires OpenSSL 3.2.0 or newer. #[cfg(ossl320)] #[corresponds(EVP_PKEY_CTX_set_params)] pub fn set_nonce_type(&mut self, nonce_type: NonceType) -> Result<(), ErrorStack> { let nonce_field_name = CString::new("nonce-type").unwrap(); let mut nonce_type = nonce_type.0; unsafe { let param_nonce = ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type); let param_end = ffi::OSSL_PARAM_construct_end(); let params = [param_nonce, param_end]; cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?; } Ok(()) } /// Gets the nonce type for a private key context. /// /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979). /// /// This is only useful for DSA and ECDSA. /// Requires OpenSSL 3.2.0 or newer. #[cfg(ossl320)] #[corresponds(EVP_PKEY_CTX_get_params)] pub fn nonce_type(&mut self) -> Result<NonceType, ErrorStack> { let nonce_field_name = CString::new("nonce-type").unwrap(); let mut nonce_type: c_uint = 0; unsafe { let param_nonce = ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type); let param_end = ffi::OSSL_PARAM_construct_end(); let mut params = [param_nonce, param_end]; cvt(ffi::EVP_PKEY_CTX_get_params( self.as_ptr(), params.as_mut_ptr(), ))?; } Ok(NonceType(nonce_type)) } } #[cfg(test)] Loading Loading @@ -999,4 +1123,34 @@ mod test { // The digest is the end of the DigestInfo structure. assert_eq!(result_buf[length - digest.len()..length], digest); } #[test] #[cfg(ossl300)] fn set_digest() { let key1 = EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap(); let key1 = PKey::from_ec_key(key1).unwrap(); let mut ctx = PkeyCtx::new(&key1).unwrap(); ctx.sign_init().unwrap(); ctx.set_digest(MessageDigest::sha224()).unwrap(); let digest_name = ctx.digest().unwrap().unwrap().type_(); assert_eq!(digest_name, MessageDigest::sha224().type_()); assert!(ErrorStack::get().errors().is_empty()); } #[test] #[cfg(ossl320)] fn set_nonce_type() { let key1 = EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap(); let key1 = PKey::from_ec_key(key1).unwrap(); let mut ctx = PkeyCtx::new(&key1).unwrap(); ctx.sign_init().unwrap(); ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap(); let nonce_type = ctx.nonce_type().unwrap(); assert_eq!(nonce_type, NonceType::DETERMINISTIC_K); assert!(ErrorStack::get().errors().is_empty()); } } Loading
openssl-sys/src/handwritten/evp.rs +19 −0 Original line number Diff line number Diff line Loading @@ -538,6 +538,12 @@ extern "C" { #[cfg(ossl300)] pub fn EVP_PKEY_CTX_set_signature_md(ctx: *mut EVP_PKEY_CTX, md: *const EVP_MD) -> c_int; #[cfg(ossl300)] pub fn EVP_PKEY_CTX_set_params(ctx: *mut EVP_PKEY_CTX, params: *const OSSL_PARAM) -> c_int; #[cfg(ossl300)] pub fn EVP_PKEY_CTX_get_params(ctx: *mut EVP_PKEY_CTX, params: *mut OSSL_PARAM) -> c_int; pub fn EVP_PKEY_new_mac_key( type_: c_int, e: *mut ENGINE, Loading Loading @@ -646,3 +652,16 @@ extern "C" { pub fn EVP_EncodeBlock(dst: *mut c_uchar, src: *const c_uchar, src_len: c_int) -> c_int; pub fn EVP_DecodeBlock(dst: *mut c_uchar, src: *const c_uchar, src_len: c_int) -> c_int; } extern "C" { #[cfg(ossl300)] pub fn OSSL_PARAM_construct_uint(key: *const c_char, buf: *mut c_uint) -> OSSL_PARAM; #[cfg(ossl300)] pub fn OSSL_PARAM_construct_utf8_string( key: *const c_char, buf: *mut c_char, bsize: size_t, ) -> OSSL_PARAM; #[cfg(ossl300)] pub fn OSSL_PARAM_construct_end() -> OSSL_PARAM; }
openssl-sys/src/handwritten/types.rs +10 −0 Original line number Diff line number Diff line Loading @@ -1093,3 +1093,13 @@ pub enum OSSL_PROVIDER {} #[cfg(ossl300)] pub enum OSSL_LIB_CTX {} #[cfg(ossl300)] #[repr(C)] pub struct OSSL_PARAM { key: *const c_char, data_type: c_uchar, data: *mut c_void, data_size: size_t, return_size: size_t, }
openssl/CHANGELOG.md +6 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,12 @@ ## [Unreleased] ### Added * Added `PkeyCtxRef::{digest, set_digest, nonce_type, set_nonce_type}`. * Added `OSSL_PARAM`, `OSSL_PARAM_construct_uint` , `OSSL_PARAM_construct_utf8_string`, `OSSL_PARAM_construct_end` to openssl-sys. * Added `EVP_PKEY_CTX_set_params` and `EVP_PKEY_CTX_get_params` to openssl-sys. ## [v0.10.63] - 2024-01-19 ### Added Loading
openssl/src/pkey_ctx.rs +154 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,8 @@ let cmac_key = ctx.keygen().unwrap(); #[cfg(not(boringssl))] use crate::cipher::CipherRef; use crate::error::ErrorStack; #[cfg(ossl300)] use crate::hash::MessageDigest; use crate::md::MdRef; use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private}; use crate::rsa::Padding; Loading @@ -75,8 +77,12 @@ use crate::{cvt, cvt_p}; use foreign_types::{ForeignType, ForeignTypeRef}; #[cfg(not(boringssl))] use libc::c_int; #[cfg(ossl320)] use libc::c_uint; use openssl_macros::corresponds; use std::convert::TryFrom; #[cfg(ossl300)] use std::ffi::CString; use std::ptr; /// HKDF modes of operation. Loading Loading @@ -105,6 +111,21 @@ impl HkdfMode { pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY); } /// Nonce type for ECDSA and DSA. #[cfg(ossl320)] #[derive(Debug, PartialEq)] pub struct NonceType(c_uint); #[cfg(ossl320)] impl NonceType { /// This is the default mode. It uses a random value for the nonce k as defined in FIPS 186-4 Section 6.3 /// “Secret Number Generation”. pub const RANDOM_K: Self = NonceType(0); /// Uses a deterministic value for the nonce k as defined in RFC #6979 (See Section 3.2 “Generation of k”). pub const DETERMINISTIC_K: Self = NonceType(1); } generic_foreign_type_and_impl_send_sync! { type CType = ffi::EVP_PKEY_CTX; fn drop = ffi::EVP_PKEY_CTX_free; Loading Loading @@ -714,6 +735,109 @@ impl<T> PkeyCtxRef<T> { Ok(PKey::from_ptr(key)) } } /// Sets the digest algorithm for a private key context. /// /// Requires OpenSSL 3.0.0 or newer. #[cfg(ossl300)] #[corresponds(EVP_PKEY_CTX_set_params)] pub fn set_digest(&mut self, hash_algorithm: MessageDigest) -> Result<(), ErrorStack> { let digest_name = hash_algorithm.type_().short_name()?; let digest = CString::new(digest_name).unwrap().into_raw(); let digest_field_name = CString::new("digest").unwrap(); unsafe { let param_digest = ffi::OSSL_PARAM_construct_utf8_string( digest_field_name.as_ptr(), digest, digest_name.len(), ); let param_end = ffi::OSSL_PARAM_construct_end(); let params = [param_digest, param_end]; cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?; // retake pointer to free memory let _ = CString::from_raw(digest); } Ok(()) } /// Gets the digest algorithm for a private key context. /// /// Requires OpenSSL 3.0.0 or newer. #[cfg(ossl300)] #[corresponds(EVP_PKEY_CTX_get_params)] pub fn digest(&mut self) -> Result<Option<MessageDigest>, ErrorStack> { use libc::c_char; // From openssl/internal/sizes.h let ossl_max_name_size = 50usize; let digest_field_name = CString::new("digest").unwrap(); let digest: *mut c_char = CString::new(vec![1; ossl_max_name_size]) .unwrap() .into_raw(); unsafe { let param_digest = ffi::OSSL_PARAM_construct_utf8_string( digest_field_name.as_ptr(), digest, ossl_max_name_size, ); let param_end = ffi::OSSL_PARAM_construct_end(); let mut params = [param_digest, param_end]; cvt(ffi::EVP_PKEY_CTX_get_params( self.as_ptr(), params.as_mut_ptr(), ))?; let digest_str = CString::from_raw(digest); Ok(MessageDigest::from_name(digest_str.to_str().unwrap())) } } /// Sets the nonce type for a private key context. /// /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979). /// /// This is only useful for DSA and ECDSA. /// Requires OpenSSL 3.2.0 or newer. #[cfg(ossl320)] #[corresponds(EVP_PKEY_CTX_set_params)] pub fn set_nonce_type(&mut self, nonce_type: NonceType) -> Result<(), ErrorStack> { let nonce_field_name = CString::new("nonce-type").unwrap(); let mut nonce_type = nonce_type.0; unsafe { let param_nonce = ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type); let param_end = ffi::OSSL_PARAM_construct_end(); let params = [param_nonce, param_end]; cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?; } Ok(()) } /// Gets the nonce type for a private key context. /// /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979). /// /// This is only useful for DSA and ECDSA. /// Requires OpenSSL 3.2.0 or newer. #[cfg(ossl320)] #[corresponds(EVP_PKEY_CTX_get_params)] pub fn nonce_type(&mut self) -> Result<NonceType, ErrorStack> { let nonce_field_name = CString::new("nonce-type").unwrap(); let mut nonce_type: c_uint = 0; unsafe { let param_nonce = ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type); let param_end = ffi::OSSL_PARAM_construct_end(); let mut params = [param_nonce, param_end]; cvt(ffi::EVP_PKEY_CTX_get_params( self.as_ptr(), params.as_mut_ptr(), ))?; } Ok(NonceType(nonce_type)) } } #[cfg(test)] Loading Loading @@ -999,4 +1123,34 @@ mod test { // The digest is the end of the DigestInfo structure. assert_eq!(result_buf[length - digest.len()..length], digest); } #[test] #[cfg(ossl300)] fn set_digest() { let key1 = EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap(); let key1 = PKey::from_ec_key(key1).unwrap(); let mut ctx = PkeyCtx::new(&key1).unwrap(); ctx.sign_init().unwrap(); ctx.set_digest(MessageDigest::sha224()).unwrap(); let digest_name = ctx.digest().unwrap().unwrap().type_(); assert_eq!(digest_name, MessageDigest::sha224().type_()); assert!(ErrorStack::get().errors().is_empty()); } #[test] #[cfg(ossl320)] fn set_nonce_type() { let key1 = EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap(); let key1 = PKey::from_ec_key(key1).unwrap(); let mut ctx = PkeyCtx::new(&key1).unwrap(); ctx.sign_init().unwrap(); ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap(); let nonce_type = ctx.nonce_type().unwrap(); assert_eq!(nonce_type, NonceType::DETERMINISTIC_K); assert!(ErrorStack::get().errors().is_empty()); } }