1#[cfg(ossl300)]
4use crate::cvt_p;
5#[cfg(ossl300)]
6use crate::error::ErrorStack;
7#[cfg(ossl300)]
8use crate::lib_ctx::LibCtxRef;
9use crate::nid::Nid;
10use cfg_if::cfg_if;
11use foreign_types::{ForeignTypeRef, Opaque};
12use openssl_macros::corresponds;
13#[cfg(ossl300)]
14use std::ffi::CString;
15#[cfg(ossl300)]
16use std::ptr;
17
18cfg_if! {
19 if #[cfg(ossl300)] {
20 use foreign_types::ForeignType;
21 use std::ops::{Deref, DerefMut};
22
23 type Inner = *mut ffi::EVP_MD;
24
25 impl Drop for Md {
26 #[inline]
27 fn drop(&mut self) {
28 unsafe {
29 ffi::EVP_MD_free(self.as_ptr());
30 }
31 }
32 }
33
34 impl ForeignType for Md {
35 type CType = ffi::EVP_MD;
36 type Ref = MdRef;
37
38 #[inline]
39 unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
40 Md(ptr)
41 }
42
43 #[inline]
44 fn as_ptr(&self) -> *mut Self::CType {
45 self.0
46 }
47 }
48
49 impl Deref for Md {
50 type Target = MdRef;
51
52 #[inline]
53 fn deref(&self) -> &Self::Target {
54 unsafe {
55 MdRef::from_ptr(self.as_ptr())
56 }
57 }
58 }
59
60 impl DerefMut for Md {
61 #[inline]
62 fn deref_mut(&mut self) -> &mut Self::Target {
63 unsafe {
64 MdRef::from_ptr_mut(self.as_ptr())
65 }
66 }
67 }
68 } else {
69 enum Inner {}
70 }
71}
72
73pub struct Md(Inner);
75
76unsafe impl Sync for Md {}
77unsafe impl Send for Md {}
78
79impl Md {
80 #[corresponds(EVP_get_digestbynid)]
82 pub fn from_nid(type_: Nid) -> Option<&'static MdRef> {
83 ffi::init();
84 unsafe {
85 let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
86 if ptr.is_null() {
87 None
88 } else {
89 Some(MdRef::from_ptr(ptr as *mut _))
90 }
91 }
92 }
93
94 #[corresponds(EVP_MD_fetch)]
98 #[cfg(ossl300)]
99 pub fn fetch(
100 ctx: Option<&LibCtxRef>,
101 algorithm: &str,
102 properties: Option<&str>,
103 ) -> Result<Self, ErrorStack> {
104 ffi::init();
105 let algorithm = CString::new(algorithm).unwrap();
106 let properties = properties.map(|s| CString::new(s).unwrap());
107
108 unsafe {
109 let ptr = cvt_p(ffi::EVP_MD_fetch(
110 ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
111 algorithm.as_ptr(),
112 properties.as_ref().map_or(ptr::null_mut(), |s| s.as_ptr()),
113 ))?;
114
115 Ok(Md::from_ptr(ptr))
116 }
117 }
118
119 #[inline]
120 #[cfg(not(boringssl))]
121 pub fn null() -> &'static MdRef {
122 unsafe { MdRef::from_ptr(ffi::EVP_md_null() as *mut _) }
123 }
124
125 #[inline]
126 pub fn md5() -> &'static MdRef {
127 unsafe { MdRef::from_ptr(ffi::EVP_md5() as *mut _) }
128 }
129
130 #[inline]
131 pub fn sha1() -> &'static MdRef {
132 unsafe { MdRef::from_ptr(ffi::EVP_sha1() as *mut _) }
133 }
134
135 #[inline]
136 pub fn sha224() -> &'static MdRef {
137 unsafe { MdRef::from_ptr(ffi::EVP_sha224() as *mut _) }
138 }
139
140 #[inline]
141 pub fn sha256() -> &'static MdRef {
142 unsafe { MdRef::from_ptr(ffi::EVP_sha256() as *mut _) }
143 }
144
145 #[inline]
146 pub fn sha384() -> &'static MdRef {
147 unsafe { MdRef::from_ptr(ffi::EVP_sha384() as *mut _) }
148 }
149
150 #[inline]
151 pub fn sha512() -> &'static MdRef {
152 unsafe { MdRef::from_ptr(ffi::EVP_sha512() as *mut _) }
153 }
154
155 #[cfg(any(ossl111, libressl380))]
156 #[inline]
157 pub fn sha3_224() -> &'static MdRef {
158 unsafe { MdRef::from_ptr(ffi::EVP_sha3_224() as *mut _) }
159 }
160
161 #[cfg(any(ossl111, libressl380))]
162 #[inline]
163 pub fn sha3_256() -> &'static MdRef {
164 unsafe { MdRef::from_ptr(ffi::EVP_sha3_256() as *mut _) }
165 }
166
167 #[cfg(any(ossl111, libressl380))]
168 #[inline]
169 pub fn sha3_384() -> &'static MdRef {
170 unsafe { MdRef::from_ptr(ffi::EVP_sha3_384() as *mut _) }
171 }
172
173 #[cfg(any(ossl111, libressl380))]
174 #[inline]
175 pub fn sha3_512() -> &'static MdRef {
176 unsafe { MdRef::from_ptr(ffi::EVP_sha3_512() as *mut _) }
177 }
178
179 #[cfg(ossl111)]
180 #[inline]
181 pub fn shake128() -> &'static MdRef {
182 unsafe { MdRef::from_ptr(ffi::EVP_shake128() as *mut _) }
183 }
184
185 #[cfg(ossl111)]
186 #[inline]
187 pub fn shake256() -> &'static MdRef {
188 unsafe { MdRef::from_ptr(ffi::EVP_shake256() as *mut _) }
189 }
190
191 #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
192 #[inline]
193 pub fn ripemd160() -> &'static MdRef {
194 unsafe { MdRef::from_ptr(ffi::EVP_ripemd160() as *mut _) }
195 }
196
197 #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
198 #[inline]
199 pub fn sm3() -> &'static MdRef {
200 unsafe { MdRef::from_ptr(ffi::EVP_sm3() as *mut _) }
201 }
202}
203
204pub struct MdRef(Opaque);
206
207impl ForeignTypeRef for MdRef {
208 type CType = ffi::EVP_MD;
209}
210
211unsafe impl Sync for MdRef {}
212unsafe impl Send for MdRef {}
213
214impl MdRef {
215 #[corresponds(EVP_MD_block_size)]
217 #[inline]
218 pub fn block_size(&self) -> usize {
219 unsafe { ffi::EVP_MD_block_size(self.as_ptr()) as usize }
220 }
221
222 #[corresponds(EVP_MD_size)]
224 #[inline]
225 pub fn size(&self) -> usize {
226 unsafe { ffi::EVP_MD_size(self.as_ptr()) as usize }
227 }
228
229 #[corresponds(EVP_MD_type)]
231 #[inline]
232 pub fn type_(&self) -> Nid {
233 unsafe { Nid::from_raw(ffi::EVP_MD_type(self.as_ptr())) }
234 }
235}
236
237#[cfg(test)]
238mod test {
239 #[cfg(ossl300)]
240 use super::Md;
241
242 #[test]
243 #[cfg(ossl300)]
244 fn test_md_fetch_properties() {
245 assert!(Md::fetch(None, "SHA-256", Some("provider=gibberish")).is_err());
246 }
247}