1use crate::device::Device;
6use crate::error::{check_error, Result};
7use crate::ffi;
8use crate::types::HashAlgorithm;
9
10pub struct HashContext {
14 handle: ffi::quac_hash_ctx_t,
15 algorithm: HashAlgorithm,
16}
17
18impl HashContext {
19 fn new(handle: ffi::quac_hash_ctx_t, algorithm: HashAlgorithm) -> Self {
21 Self { handle, algorithm }
22 }
23
24 pub fn update(&mut self, data: &[u8]) -> Result<()> {
26 let result = unsafe { ffi::quac_hash_update(self.handle, data.as_ptr(), data.len()) };
27 check_error(result)
28 }
29
30 pub fn finalize(self) -> Result<Vec<u8>> {
34 let size = self.algorithm.digest_size().unwrap_or(64);
35 let mut digest = vec![0u8; size];
36 let mut digest_len = size;
37
38 let result = unsafe {
39 ffi::quac_hash_final(self.handle, digest.as_mut_ptr(), &mut digest_len)
40 };
41
42 std::mem::forget(self);
44
45 check_error(result)?;
46 digest.truncate(digest_len);
47
48 Ok(digest)
49 }
50
51 pub fn algorithm(&self) -> HashAlgorithm {
53 self.algorithm
54 }
55}
56
57impl Drop for HashContext {
58 fn drop(&mut self) {
59 unsafe {
60 ffi::quac_hash_free(self.handle);
61 }
62 }
63}
64
65unsafe impl Send for HashContext {}
67
68impl std::fmt::Debug for HashContext {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 f.debug_struct("HashContext")
71 .field("algorithm", &self.algorithm)
72 .finish()
73 }
74}
75
76#[derive(Clone)]
101pub struct Hash {
102 device: Device,
103}
104
105impl Hash {
106 pub(crate) fn new(device: Device) -> Self {
108 Self { device }
109 }
110
111 pub fn hash(&self, algorithm: HashAlgorithm, data: &[u8]) -> Result<Vec<u8>> {
122 let size = algorithm.digest_size().unwrap_or(64);
123 let mut digest = vec![0u8; size];
124 let mut digest_len = size;
125
126 let result = unsafe {
127 ffi::quac_hash(
128 self.device.handle(),
129 algorithm.to_raw(),
130 data.as_ptr(),
131 data.len(),
132 digest.as_mut_ptr(),
133 &mut digest_len,
134 )
135 };
136
137 check_error(result)?;
138 digest.truncate(digest_len);
139
140 Ok(digest)
141 }
142
143 pub fn sha256(&self, data: &[u8]) -> Result<Vec<u8>> {
145 self.hash(HashAlgorithm::Sha256, data)
146 }
147
148 pub fn sha384(&self, data: &[u8]) -> Result<Vec<u8>> {
150 self.hash(HashAlgorithm::Sha384, data)
151 }
152
153 pub fn sha512(&self, data: &[u8]) -> Result<Vec<u8>> {
155 self.hash(HashAlgorithm::Sha512, data)
156 }
157
158 pub fn sha3_256(&self, data: &[u8]) -> Result<Vec<u8>> {
160 self.hash(HashAlgorithm::Sha3_256, data)
161 }
162
163 pub fn sha3_384(&self, data: &[u8]) -> Result<Vec<u8>> {
165 self.hash(HashAlgorithm::Sha3_384, data)
166 }
167
168 pub fn sha3_512(&self, data: &[u8]) -> Result<Vec<u8>> {
170 self.hash(HashAlgorithm::Sha3_512, data)
171 }
172
173 pub fn shake128(&self, data: &[u8], output_len: usize) -> Result<Vec<u8>> {
180 self.shake(HashAlgorithm::Shake128, data, output_len)
181 }
182
183 pub fn shake256(&self, data: &[u8], output_len: usize) -> Result<Vec<u8>> {
190 self.shake(HashAlgorithm::Shake256, data, output_len)
191 }
192
193 fn shake(&self, algorithm: HashAlgorithm, data: &[u8], output_len: usize) -> Result<Vec<u8>> {
195 let mut output = vec![0u8; output_len];
196 let mut len = output_len;
197
198 let result = unsafe {
199 ffi::quac_hash(
200 self.device.handle(),
201 algorithm.to_raw(),
202 data.as_ptr(),
203 data.len(),
204 output.as_mut_ptr(),
205 &mut len,
206 )
207 };
208
209 check_error(result)?;
210 output.truncate(len);
211
212 Ok(output)
213 }
214
215 pub fn create_context(&self, algorithm: HashAlgorithm) -> Result<HashContext> {
230 let mut handle = std::ptr::null_mut();
231 let result = unsafe {
232 ffi::quac_hash_init(self.device.handle(), algorithm.to_raw(), &mut handle)
233 };
234 check_error(result)?;
235 Ok(HashContext::new(handle, algorithm))
236 }
237
238 pub fn hmac(&self, algorithm: HashAlgorithm, key: &[u8], data: &[u8]) -> Result<Vec<u8>> {
250 let size = algorithm.digest_size().unwrap_or(64);
251 let mut mac = vec![0u8; size];
252 let mut mac_len = size;
253
254 let result = unsafe {
255 ffi::quac_hmac(
256 self.device.handle(),
257 algorithm.to_raw(),
258 key.as_ptr(),
259 key.len(),
260 data.as_ptr(),
261 data.len(),
262 mac.as_mut_ptr(),
263 &mut mac_len,
264 )
265 };
266
267 check_error(result)?;
268 mac.truncate(mac_len);
269
270 Ok(mac)
271 }
272
273 pub fn hmac_sha256(&self, key: &[u8], data: &[u8]) -> Result<Vec<u8>> {
275 self.hmac(HashAlgorithm::Sha256, key, data)
276 }
277
278 pub fn hmac_sha384(&self, key: &[u8], data: &[u8]) -> Result<Vec<u8>> {
280 self.hmac(HashAlgorithm::Sha384, key, data)
281 }
282
283 pub fn hmac_sha512(&self, key: &[u8], data: &[u8]) -> Result<Vec<u8>> {
285 self.hmac(HashAlgorithm::Sha512, key, data)
286 }
287
288 pub fn hkdf(
302 &self,
303 algorithm: HashAlgorithm,
304 ikm: &[u8],
305 salt: &[u8],
306 info: &[u8],
307 output_len: usize,
308 ) -> Result<Vec<u8>> {
309 let mut okm = vec![0u8; output_len];
310
311 let result = unsafe {
312 ffi::quac_hkdf(
313 self.device.handle(),
314 algorithm.to_raw(),
315 ikm.as_ptr(),
316 ikm.len(),
317 salt.as_ptr(),
318 salt.len(),
319 info.as_ptr(),
320 info.len(),
321 okm.as_mut_ptr(),
322 output_len,
323 )
324 };
325
326 check_error(result)?;
327 Ok(okm)
328 }
329
330 pub fn hkdf_sha256(
332 &self,
333 ikm: &[u8],
334 salt: &[u8],
335 info: &[u8],
336 output_len: usize,
337 ) -> Result<Vec<u8>> {
338 self.hkdf(HashAlgorithm::Sha256, ikm, salt, info, output_len)
339 }
340}
341
342impl std::fmt::Debug for Hash {
343 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
344 f.debug_struct("Hash").finish()
345 }
346}