1use std::ffi::c_void;
2
3pub struct Hash;
4
5macro_rules! implement_hash {
6 ($func:ident, $struct:ident, $ctx:ident, $one_shot:ident, $init:ident, $update:ident, $final:ident, $len:expr) => {
7 extern "C" {
8 fn $one_shot(data: *const c_void, len: i32, output: *mut u8) -> *mut u8;
9 fn $init(ctx: *mut $ctx) -> i32;
10 fn $update(ctx: *mut $ctx, data: *const c_void, len: i32) -> i32;
11 fn $final(output: *mut c_void, ctx: *mut $ctx) -> i32;
12 }
13
14 impl Hash {
15 pub fn $func(data: impl AsRef<[u8]>) -> [u8; $len] {
16 let mut output = [0u8; $len];
17
18 unsafe {
19 $one_shot(
20 data.as_ref().as_ptr() as *const c_void,
21 data.as_ref().len() as i32,
22 output.as_mut_ptr(),
23 );
24 }
25
26 output
27 }
28 }
29
30 pub struct $struct {
31 ctx: $ctx,
32 }
33
34 impl $struct {
35 pub fn new() -> Self {
36 let mut ctx = $ctx::default();
37
38 unsafe {
39 $init(&mut ctx);
40 }
41
42 Self { ctx }
43 }
44
45 pub fn update(&mut self, data: impl AsRef<[u8]>) {
46 unsafe {
47 $update(
48 &mut self.ctx,
49 data.as_ref().as_ptr() as *const c_void,
50 data.as_ref().len() as i32,
51 );
52 }
53 }
54
55 pub fn finish(mut self) -> [u8; $len] {
56 let mut output = [0u8; $len];
57 unsafe { $final(output.as_mut_ptr() as *mut c_void, &mut self.ctx) };
58 output
59 }
60 }
61 };
62}
63
64#[repr(C)]
65#[derive(Default)]
66struct SHA1Context {
67 h0: u32,
68 h1: u32,
69 h2: u32,
70 h3: u32,
71 h4: u32,
72 nl: u32,
73 nh: u32,
74 data: [u32; 16],
75 num: i32,
76}
77implement_hash!(
78 sha1,
79 SHA1,
80 SHA1Context,
81 CC_SHA1,
82 CC_SHA1_Init,
83 CC_SHA1_Update,
84 CC_SHA1_Final,
85 20
86);
87
88#[repr(C)]
89#[derive(Default)]
90struct SHA256Context {
91 count: [u32; 2],
92 hash: [u32; 8],
93 wbuf: [u32; 16],
94}
95
96implement_hash!(
97 sha224,
98 SHA224,
99 SHA256Context,
100 CC_SHA224,
101 CC_SHA224_Init,
102 CC_SHA224_Update,
103 CC_SHA224_Final,
104 28
105);
106
107implement_hash!(
108 sha256,
109 SHA256,
110 SHA256Context,
111 CC_SHA256,
112 CC_SHA256_Init,
113 CC_SHA256_Update,
114 CC_SHA256_Final,
115 32
116);
117
118#[repr(C)]
119#[derive(Default)]
120struct SHA512Context {
121 count: [u64; 2],
122 hash: [u64; 8],
123 wbuf: [u64; 16],
124}
125
126implement_hash!(
127 sha384,
128 SHA384,
129 SHA512Context,
130 CC_SHA384,
131 CC_SHA384_Init,
132 CC_SHA384_Update,
133 CC_SHA384_Final,
134 48
135);
136
137implement_hash!(
138 sha512,
139 SHA512,
140 SHA512Context,
141 CC_SHA512,
142 CC_SHA512_Init,
143 CC_SHA512_Update,
144 CC_SHA512_Final,
145 64
146);
147
148#[repr(C)]
149#[derive(Default)]
150struct MD2Context {
151 num: i32,
152 data: [u8; 16],
153 cksm: [u32; 16],
154 state: [u32; 16],
155}
156
157implement_hash!(
158 md2,
159 MD2,
160 MD2Context,
161 CC_MD2,
162 CC_MD2_Init,
163 CC_MD2_Update,
164 CC_MD2_Final,
165 16
166);
167
168#[repr(C)]
169#[derive(Default)]
170struct MD4Context {
171 a: u32,
172 b: u32,
173 c: u32,
174 d: u32,
175 nl: u32,
176 nh: u32,
177 data: [u32; 16],
178 num: i32,
179}
180
181implement_hash!(
182 md4,
183 MD4,
184 MD4Context,
185 CC_MD4,
186 CC_MD4_Init,
187 CC_MD4_Update,
188 CC_MD4_Final,
189 16
190);
191
192#[repr(C)]
193#[derive(Default)]
194struct MD5Context {
195 a: u32,
196 b: u32,
197 c: u32,
198 d: u32,
199 nl: u32,
200 nh: u32,
201 data: [u32; 16],
202 num: i32,
203}
204
205implement_hash!(
206 md5,
207 MD5,
208 MD5Context,
209 CC_MD5,
210 CC_MD5_Init,
211 CC_MD5_Update,
212 CC_MD5_Final,
213 16
214);