1 | //! Message digest algorithms. |
2 | |
3 | #[cfg (ossl300)] |
4 | use crate::cvt_p; |
5 | #[cfg (ossl300)] |
6 | use crate::error::ErrorStack; |
7 | #[cfg (ossl300)] |
8 | use crate::lib_ctx::LibCtxRef; |
9 | use crate::nid::Nid; |
10 | use cfg_if::cfg_if; |
11 | use foreign_types::{ForeignTypeRef, Opaque}; |
12 | use openssl_macros::corresponds; |
13 | #[cfg (ossl300)] |
14 | use std::ffi::CString; |
15 | #[cfg (ossl300)] |
16 | use std::ptr; |
17 | |
18 | cfg_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 | |
73 | /// A message digest algorithm. |
74 | pub struct Md(Inner); |
75 | |
76 | unsafe impl Sync for Md {} |
77 | unsafe impl Send for Md {} |
78 | |
79 | impl Md { |
80 | /// Returns the `Md` corresponding to an [`Nid`]. |
81 | #[corresponds (EVP_get_digestbynid)] |
82 | pub fn from_nid(type_: Nid) -> Option<&'static MdRef> { |
83 | unsafe { |
84 | let ptr = ffi::EVP_get_digestbynid(type_.as_raw()); |
85 | if ptr.is_null() { |
86 | None |
87 | } else { |
88 | Some(MdRef::from_ptr(ptr as *mut _)) |
89 | } |
90 | } |
91 | } |
92 | |
93 | /// Fetches an `Md` object corresponding to the specified algorithm name and properties. |
94 | /// |
95 | /// Requires OpenSSL 3.0.0 or newer. |
96 | #[corresponds (EVP_MD_fetch)] |
97 | #[cfg (ossl300)] |
98 | pub fn fetch( |
99 | ctx: Option<&LibCtxRef>, |
100 | algorithm: &str, |
101 | properties: Option<&str>, |
102 | ) -> Result<Self, ErrorStack> { |
103 | let algorithm = CString::new(algorithm).unwrap(); |
104 | let properties = properties.map(|s| CString::new(s).unwrap()); |
105 | |
106 | unsafe { |
107 | let ptr = cvt_p(ffi::EVP_MD_fetch( |
108 | ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr), |
109 | algorithm.as_ptr(), |
110 | properties.map_or(ptr::null_mut(), |s| s.as_ptr()), |
111 | ))?; |
112 | |
113 | Ok(Md::from_ptr(ptr)) |
114 | } |
115 | } |
116 | |
117 | #[inline ] |
118 | #[cfg (not(boringssl))] |
119 | pub fn null() -> &'static MdRef { |
120 | unsafe { MdRef::from_ptr(ffi::EVP_md_null() as *mut _) } |
121 | } |
122 | |
123 | #[inline ] |
124 | pub fn md5() -> &'static MdRef { |
125 | unsafe { MdRef::from_ptr(ffi::EVP_md5() as *mut _) } |
126 | } |
127 | |
128 | #[inline ] |
129 | pub fn sha1() -> &'static MdRef { |
130 | unsafe { MdRef::from_ptr(ffi::EVP_sha1() as *mut _) } |
131 | } |
132 | |
133 | #[inline ] |
134 | pub fn sha224() -> &'static MdRef { |
135 | unsafe { MdRef::from_ptr(ffi::EVP_sha224() as *mut _) } |
136 | } |
137 | |
138 | #[inline ] |
139 | pub fn sha256() -> &'static MdRef { |
140 | unsafe { MdRef::from_ptr(ffi::EVP_sha256() as *mut _) } |
141 | } |
142 | |
143 | #[inline ] |
144 | pub fn sha384() -> &'static MdRef { |
145 | unsafe { MdRef::from_ptr(ffi::EVP_sha384() as *mut _) } |
146 | } |
147 | |
148 | #[inline ] |
149 | pub fn sha512() -> &'static MdRef { |
150 | unsafe { MdRef::from_ptr(ffi::EVP_sha512() as *mut _) } |
151 | } |
152 | |
153 | #[cfg (any(ossl111, libressl380))] |
154 | #[inline ] |
155 | pub fn sha3_224() -> &'static MdRef { |
156 | unsafe { MdRef::from_ptr(ffi::EVP_sha3_224() as *mut _) } |
157 | } |
158 | |
159 | #[cfg (any(ossl111, libressl380))] |
160 | #[inline ] |
161 | pub fn sha3_256() -> &'static MdRef { |
162 | unsafe { MdRef::from_ptr(ffi::EVP_sha3_256() as *mut _) } |
163 | } |
164 | |
165 | #[cfg (any(ossl111, libressl380))] |
166 | #[inline ] |
167 | pub fn sha3_384() -> &'static MdRef { |
168 | unsafe { MdRef::from_ptr(ffi::EVP_sha3_384() as *mut _) } |
169 | } |
170 | |
171 | #[cfg (any(ossl111, libressl380))] |
172 | #[inline ] |
173 | pub fn sha3_512() -> &'static MdRef { |
174 | unsafe { MdRef::from_ptr(ffi::EVP_sha3_512() as *mut _) } |
175 | } |
176 | |
177 | #[cfg (ossl111)] |
178 | #[inline ] |
179 | pub fn shake128() -> &'static MdRef { |
180 | unsafe { MdRef::from_ptr(ffi::EVP_shake128() as *mut _) } |
181 | } |
182 | |
183 | #[cfg (ossl111)] |
184 | #[inline ] |
185 | pub fn shake256() -> &'static MdRef { |
186 | unsafe { MdRef::from_ptr(ffi::EVP_shake256() as *mut _) } |
187 | } |
188 | |
189 | #[cfg (not(osslconf = "OPENSSL_NO_RMD160" ))] |
190 | #[inline ] |
191 | pub fn ripemd160() -> &'static MdRef { |
192 | unsafe { MdRef::from_ptr(ffi::EVP_ripemd160() as *mut _) } |
193 | } |
194 | |
195 | #[cfg (all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3" )))] |
196 | #[inline ] |
197 | pub fn sm3() -> &'static MdRef { |
198 | unsafe { MdRef::from_ptr(ffi::EVP_sm3() as *mut _) } |
199 | } |
200 | } |
201 | |
202 | /// A reference to an [`Md`]. |
203 | pub struct MdRef(Opaque); |
204 | |
205 | impl ForeignTypeRef for MdRef { |
206 | type CType = ffi::EVP_MD; |
207 | } |
208 | |
209 | unsafe impl Sync for MdRef {} |
210 | unsafe impl Send for MdRef {} |
211 | |
212 | impl MdRef { |
213 | /// Returns the block size of the digest in bytes. |
214 | #[corresponds (EVP_MD_block_size)] |
215 | #[inline ] |
216 | pub fn block_size(&self) -> usize { |
217 | unsafe { ffi::EVP_MD_block_size(self.as_ptr()) as usize } |
218 | } |
219 | |
220 | /// Returns the size of the digest in bytes. |
221 | #[corresponds (EVP_MD_size)] |
222 | #[inline ] |
223 | pub fn size(&self) -> usize { |
224 | unsafe { ffi::EVP_MD_size(self.as_ptr()) as usize } |
225 | } |
226 | |
227 | /// Returns the [`Nid`] of the digest. |
228 | #[corresponds (EVP_MD_type)] |
229 | #[inline ] |
230 | pub fn type_(&self) -> Nid { |
231 | unsafe { Nid::from_raw(ffi::EVP_MD_type(self.as_ptr())) } |
232 | } |
233 | } |
234 | |