aws_lc_rs/digest/
digest_ctx.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0 OR ISC
3
4use crate::aws_lc::{
5    EVP_DigestInit_ex, EVP_MD_CTX_cleanup, EVP_MD_CTX_copy, EVP_MD_CTX_init, EVP_MD_CTX,
6};
7use crate::digest::{match_digest_type, Algorithm};
8use crate::error::Unspecified;
9use core::mem::MaybeUninit;
10use core::ptr::null_mut;
11
12pub(crate) struct DigestContext(EVP_MD_CTX);
13
14impl DigestContext {
15    pub fn new(algorithm: &'static Algorithm) -> Result<DigestContext, Unspecified> {
16        let evp_md_type = match_digest_type(&algorithm.id);
17        let mut dc = Self::new_uninit();
18        unsafe {
19            if 1 != EVP_DigestInit_ex(dc.as_mut_ptr(), *evp_md_type, null_mut()) {
20                return Err(Unspecified);
21            }
22            Ok(dc)
23        }
24    }
25
26    pub fn new_uninit() -> DigestContext {
27        let mut dc = MaybeUninit::<EVP_MD_CTX>::uninit();
28        unsafe {
29            EVP_MD_CTX_init(dc.as_mut_ptr());
30            Self(dc.assume_init())
31        }
32    }
33
34    pub(crate) fn as_mut_ptr(&mut self) -> *mut EVP_MD_CTX {
35        &mut self.0
36    }
37
38    pub(crate) fn as_ptr(&self) -> *const EVP_MD_CTX {
39        &self.0
40    }
41}
42
43unsafe impl Send for DigestContext {}
44unsafe impl Sync for DigestContext {}
45
46impl Clone for DigestContext {
47    fn clone(&self) -> Self {
48        self.try_clone().expect("Unable to clone DigestContext")
49    }
50}
51
52impl Drop for DigestContext {
53    fn drop(&mut self) {
54        unsafe {
55            EVP_MD_CTX_cleanup(self.as_mut_ptr());
56        }
57    }
58}
59
60impl DigestContext {
61    fn try_clone(&self) -> Result<Self, &'static str> {
62        let mut dc = MaybeUninit::<EVP_MD_CTX>::uninit();
63        unsafe {
64            // The first parameter of `EVP_MD_CTX_copy` should not be initialized.
65            // https://github.com/aws/aws-lc/blob/98ccf4a316401112943bed604562102ad52efac6/include/openssl/digest.h#L280
66            if 1 != EVP_MD_CTX_copy(dc.as_mut_ptr(), self.as_ptr()) {
67                return Err("EVP_MD_CTX_copy failed");
68            }
69            Ok(Self(dc.assume_init()))
70        }
71    }
72}