diff --git a/openssl-sys/src/handwritten/evp.rs b/openssl-sys/src/handwritten/evp.rs index 04b8aed26ab9e736af19e137e458d9f8dd4bb658..56b0066812b3b5751c140ab4981264b1233ff87c 100644 --- a/openssl-sys/src/handwritten/evp.rs +++ b/openssl-sys/src/handwritten/evp.rs @@ -261,6 +261,7 @@ extern "C" { pub fn EVP_CIPHER_CTX_new() -> *mut EVP_CIPHER_CTX; pub fn EVP_CIPHER_CTX_free(ctx: *mut EVP_CIPHER_CTX); pub fn EVP_MD_CTX_copy_ex(dst: *mut EVP_MD_CTX, src: *const EVP_MD_CTX) -> c_int; + pub fn EVP_MD_CTX_reset(ctx: *mut EVP_MD_CTX) -> c_int; pub fn EVP_CIPHER_CTX_set_key_length(ctx: *mut EVP_CIPHER_CTX, keylen: c_int) -> c_int; pub fn EVP_CIPHER_CTX_set_padding(ctx: *mut EVP_CIPHER_CTX, padding: c_int) -> c_int; pub fn EVP_CIPHER_CTX_ctrl( diff --git a/openssl/src/md_ctx.rs b/openssl/src/md_ctx.rs index 954a5921c9bb0f88c54419d408899fa7653fa516..a9a5ccab7c8731aebc8f69ca91d3c56757b5b0f4 100644 --- a/openssl/src/md_ctx.rs +++ b/openssl/src/md_ctx.rs @@ -380,6 +380,16 @@ impl MdCtxRef { pub fn size(&self) -> usize { unsafe { ffi::EVP_MD_CTX_size(self.as_ptr()) as usize } } + + /// Resets the underlying EVP_MD_CTX instance + #[corresponds(EVP_MD_CTX_init)] + #[inline] + pub fn reset(&self) -> Result<(), ErrorStack> { + unsafe { + let _ = cvt(ffi::EVP_MD_CTX_reset(self.as_ptr()))?; + Ok(()) + } + } } #[cfg(test)] @@ -484,4 +494,35 @@ mod test { assert_eq!(Md::sha512().size(), ctx.size()); assert_eq!(Md::sha512().size(), 64); } + + #[test] + fn verify_md_ctx_reset() { + let hello_expected = hex::decode("185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969").unwrap(); + let world_expected = hex::decode("78ae647dc5544d227130a0682a51e30bc7777fbb6d8a8f17007463a3ecd1d524").unwrap(); + // Calculate SHA-256 digest of "Hello" + let mut ctx = MdCtx::new().unwrap(); + ctx.digest_init(Md::sha256()).unwrap(); + ctx.digest_update(b"Hello").unwrap(); + let mut result = vec![0; 32]; + let result_len = ctx.digest_final(result.as_mut_slice()).unwrap(); + assert_eq!(result_len, result.len()); + // Validate result of "Hello" + assert_eq!(result, hello_expected); + + // Create new context + let mut ctx = MdCtx::new().unwrap(); + // Initialize and update to "Hello" + ctx.digest_init(Md::sha256()).unwrap(); + ctx.digest_update(b"Hello").unwrap(); + // Now reset, init to SHA-256 and use "World" + ctx.reset().unwrap(); + ctx.digest_init(Md::sha256()).unwrap(); + ctx.digest_update(b"World").unwrap(); + + let mut reset_result = vec![0;32]; + let result_len = ctx.digest_final(reset_result.as_mut_slice()).unwrap(); + assert_eq!(result_len, reset_result.len()); + // Validate result of digest of "World" + assert_eq!(reset_result, world_expected); + } }