use crate::digest::{match_digest_type, Algorithm};
use crate::error::Unspecified;
use crate::ptr::LcPtr;
use crate::wolfcrypt_rs::{EVP_DigestInit_ex, EVP_MD_CTX_copy, EVP_MD_CTX_new, EVP_MD_CTX};
use core::ptr::null_mut;
pub(crate) struct DigestContext(LcPtr<EVP_MD_CTX>);
impl DigestContext {
pub fn new(algorithm: &'static Algorithm) -> Result<DigestContext, Unspecified> {
let evp_md_type = match_digest_type(&algorithm.id);
let mut ctx = LcPtr::new(unsafe { EVP_MD_CTX_new() }).map_err(|_| Unspecified)?;
unsafe {
if 1 != EVP_DigestInit_ex(ctx.as_mut_ptr(), evp_md_type.as_const_ptr(), null_mut()) {
return Err(Unspecified);
}
}
Ok(DigestContext(ctx))
}
pub fn new_uninit() -> Result<DigestContext, Unspecified> {
let ctx = LcPtr::new(unsafe { EVP_MD_CTX_new() }).map_err(|_| Unspecified)?;
Ok(DigestContext(ctx))
}
pub(crate) fn as_mut_ptr(&mut self) -> *mut EVP_MD_CTX {
self.0.as_mut_ptr()
}
pub(crate) fn as_ptr(&self) -> *const EVP_MD_CTX {
self.0.as_const_ptr()
}
}
unsafe impl Send for DigestContext {}
unsafe impl Sync for DigestContext {}
impl Clone for DigestContext {
fn clone(&self) -> Self {
self.try_clone().expect("Unable to clone DigestContext")
}
}
impl DigestContext {
fn try_clone(&self) -> Result<Self, &'static str> {
let mut dc =
LcPtr::new(unsafe { EVP_MD_CTX_new() }).map_err(|_| "EVP_MD_CTX_new failed")?;
unsafe {
if 1 != EVP_MD_CTX_copy(dc.as_mut_ptr(), self.as_ptr()) {
return Err("EVP_MD_CTX_copy failed");
}
}
Ok(Self(dc))
}
}