1use crate::{sealed, FfiSlice, ForeignTypeRef};
47use alloc::vec::Vec;
48
49#[non_exhaustive]
50#[doc(hidden)]
51pub struct MdRef;
52
53unsafe impl ForeignTypeRef for MdRef {
54 type CType = bssl_sys::EVP_MD;
55}
56
57pub trait Algorithm {
59 const OUTPUT_LEN: usize;
61 const BLOCK_LEN: usize;
63
64 #[doc(hidden)]
66 fn get_md(_: sealed::Sealed) -> &'static MdRef;
67
68 fn hash_to_vec(input: &[u8]) -> Vec<u8>;
70
71 fn new() -> Self;
73
74 fn update(&mut self, input: &[u8]);
76
77 fn digest_to_vec(self) -> Vec<u8>;
79}
80
81#[derive(Clone)]
87pub struct InsecureSha1 {
88 ctx: bssl_sys::SHA_CTX,
89}
90
91unsafe_iuf_algo!(
92 InsecureSha1,
93 20,
94 64,
95 EVP_sha1,
96 SHA1,
97 SHA1_Init,
98 SHA1_Update,
99 SHA1_Final
100);
101
102#[derive(Clone)]
104pub struct Sha256 {
105 ctx: bssl_sys::SHA256_CTX,
106}
107
108unsafe_iuf_algo!(
109 Sha256,
110 32,
111 64,
112 EVP_sha256,
113 SHA256,
114 SHA256_Init,
115 SHA256_Update,
116 SHA256_Final
117);
118
119#[derive(Clone)]
121pub struct Sha384 {
122 ctx: bssl_sys::SHA512_CTX,
123}
124
125unsafe_iuf_algo!(
126 Sha384,
127 48,
128 128,
129 EVP_sha384,
130 SHA384,
131 SHA384_Init,
132 SHA384_Update,
133 SHA384_Final
134);
135
136#[derive(Clone)]
138pub struct Sha512 {
139 ctx: bssl_sys::SHA512_CTX,
140}
141
142unsafe_iuf_algo!(
143 Sha512,
144 64,
145 128,
146 EVP_sha512,
147 SHA512,
148 SHA512_Init,
149 SHA512_Update,
150 SHA512_Final
151);
152
153#[derive(Clone)]
155pub struct Sha512_256 {
156 ctx: bssl_sys::SHA512_CTX,
157}
158
159unsafe_iuf_algo!(
160 Sha512_256,
161 32,
162 128,
163 EVP_sha512_256,
164 SHA512_256,
165 SHA512_256_Init,
166 SHA512_256_Update,
167 SHA512_256_Final
168);
169
170#[cfg(test)]
171mod test {
172 use super::*;
173 use crate::test_helpers::decode_hex;
174
175 #[test]
176 fn sha256_c_type() {
177 unsafe {
178 assert_eq!(
179 MdRef::from_ptr(bssl_sys::EVP_sha256() as *mut _).as_ptr(),
180 bssl_sys::EVP_sha256() as *mut _
181 )
182 }
183 }
184
185 #[test]
186 fn sha512_c_type() {
187 unsafe {
188 assert_eq!(
189 MdRef::from_ptr(bssl_sys::EVP_sha512() as *mut _).as_ptr(),
190 bssl_sys::EVP_sha512() as *mut _
191 )
192 }
193 }
194
195 #[test]
196 fn sha1() {
197 assert_eq!(
198 decode_hex("a9993e364706816aba3e25717850c26c9cd0d89d"),
199 InsecureSha1::hash(b"abc")
200 );
201 }
202
203 #[test]
204 fn sha256() {
205 let msg: [u8; 4] = decode_hex("74ba2521");
206 let expected_digest: [u8; 32] =
207 decode_hex("b16aa56be3880d18cd41e68384cf1ec8c17680c45a02b1575dc1518923ae8b0e");
208
209 assert_eq!(Sha256::hash(&msg), expected_digest);
210
211 let mut ctx = Sha256::new();
212 ctx.update(&msg);
213 assert_eq!(expected_digest, ctx.digest());
214
215 let mut ctx = Sha256::new();
216 ctx.update(&msg[0..1]);
217 let mut ctx2 = ctx.clone();
218 ctx2.update(&msg[1..]);
219 assert_eq!(expected_digest, ctx2.digest());
220 }
221
222 #[test]
223 fn sha384() {
224 assert_eq!(
225 decode_hex("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"),
226 Sha384::hash(b"abc")
227 );
228 }
229
230 #[test]
231 fn sha512() {
232 let msg: [u8; 4] = decode_hex("23be86d5");
233 let expected_digest: [u8; 64] = decode_hex(concat!(
234 "76d42c8eadea35a69990c63a762f330614a4699977f058adb988f406fb0be8f2",
235 "ea3dce3a2bbd1d827b70b9b299ae6f9e5058ee97b50bd4922d6d37ddc761f8eb"
236 ));
237
238 assert_eq!(Sha512::hash(&msg), expected_digest);
239
240 let mut ctx = Sha512::new();
241 ctx.update(&msg);
242 assert_eq!(expected_digest, ctx.digest());
243 }
244
245 #[test]
246 fn sha512_256() {
247 assert_eq!(
248 decode_hex("53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"),
249 Sha512_256::hash(b"abc")
250 );
251 }
252}