1#[cfg(target_arch = "x86_64")]
17use std::arch::x86_64::*;
18use crate::avx2_inline::{ add, loadu, or, rota_lf, rota_rg, setone_i32, setzero, xor, horiz_add_avx2 };
19use std::hint::black_box;
20
21macro_rules! teq_direct {
22 ($ss:ident, $ss1:expr, $lv:expr, $lr:expr, $ymm_a1:ident) => {
23 $ss = add($ss, $ymm_a1);
24 $ss = or(rota_lf::<$lv>($ss), rota_rg::<$lr>($ss));
25 $ss = xor($ss1, $ss);
26 };
27}
28
29use zeroize::{Zeroize, ZeroizeOnDrop};
30
31#[cfg(feature = "serde")]
32use serde::{Serialize, Deserialize};
33
34
35#[derive(Debug, Zeroize, ZeroizeOnDrop, Clone, PartialEq, Eq)]
37#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
38pub struct TequelHash {
39 pub states: [u32; 12],
40 pub salt: String,
41 pub iterations: u32
42}
43
44impl TequelHash {
45
46 pub fn new() -> Self {
47 Self {
48 states: [
49 0x1A2B3C4D, 0x5E6F7A8B, 0x9C0D1E2F, 0x31415926,
50 0x27182818, 0xDEADBEEF, 0xCAFEBABE, 0x80808080,
51 0xABCDEF01, 0x456789AB, 0xFEDCBA98, 0x01234567
52 ],
53 salt: "".to_string(),
54 iterations: 30
55 }
56 }
57
58
59
60 pub fn with_salt(mut self, salt: &str) -> Self {
61 self.salt = salt.to_string();
62 self
63 }
64
65 pub fn with_iteration(mut self, value: u32) -> Self{
66 self.iterations = value;
67 self
68 }
69
70 pub fn tqlhash(&mut self, input: &[u8]) -> String {
104
105 self.states = [
106 0x107912FA, 0x220952EA, 0x3320212A, 0x4324312F,
107 0x5320212A, 0x9E3779B1, 0x85EBCA6B, 0xAD35744D,
108 0xCC2912FA, 0xEE0952EA, 0x1120212A, 0x2224312F,
109 ];
110
111 const HEX_CHARS: &[u8; 16] = b"0123456789abcdef";
112
113 let mut s0 = unsafe { setzero() };
114 let mut s1 = unsafe { setzero() };
115 let mut s2 = unsafe { setzero() };
116 let mut s3 = unsafe { setzero() };
117 let mut s4 = unsafe { setzero() };
118 let mut s5 = unsafe { setzero() };
119 let mut s6 = unsafe { setzero() };
120 let mut s7 = unsafe { setzero() };
121 let mut s8 = unsafe { setzero() };
122 let mut s9 = unsafe { setzero() };
123 let mut s10 = unsafe { setzero() };
124 let mut s11 = unsafe { setzero() };
125
126 let mut chunks = input.chunks_exact(128);
127
128 for chunk in chunks.by_ref() {
129
130 unsafe {
131
132 let bl_a = &chunk[..64];
133 let bl_b = &chunk[64..];
134
135 let ymm_a1 = loadu(bl_a.as_ptr() as *const __m256i);
136 let ymm_a2 = xor(loadu(bl_a.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
137
138 teq_direct!(s0, s1, 7, 25, ymm_a1);
139 teq_direct!(s1, s2, 31, 28, ymm_a2);
140 teq_direct!(s2, s3, 25, 7, ymm_a1);
141 teq_direct!(s3, s4, 23, 9, ymm_a2);
142 teq_direct!(s4, s5, 13, 19, ymm_a1);
143 teq_direct!(s5, s6, 29, 3, ymm_a2);
144 teq_direct!(s6, s7, 19, 13, ymm_a1);
145 teq_direct!(s7, s8, 17, 15, ymm_a2);
146 teq_direct!(s8, s9, 11, 21, ymm_a1);
147 teq_direct!(s9, s10, 5, 27, ymm_a2);
148 teq_direct!(s10, s11, 3, 29, ymm_a1);
149 teq_direct!(s11, s0, 2, 30, ymm_a2);
150
151 let ymm_b1 = loadu(bl_b.as_ptr() as *const __m256i);
152 let ymm_b2 = xor(loadu(bl_b.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
153
154 teq_direct!(s0, s1, 7, 25, ymm_b1);
155 teq_direct!(s1, s2, 31, 28, ymm_b2);
156 teq_direct!(s2, s3, 25, 7, ymm_b1);
157 teq_direct!(s3, s4, 23, 9, ymm_b2);
158 teq_direct!(s4, s5, 13, 19, ymm_b1);
159 teq_direct!(s5, s6, 29, 3, ymm_b2);
160 teq_direct!(s6, s7, 19, 13, ymm_b1);
161 teq_direct!(s7, s8, 17, 15, ymm_b2);
162 teq_direct!(s8, s9, 11, 21, ymm_b1);
163 teq_direct!(s9, s10, 5, 27, ymm_b2);
164 teq_direct!(s10, s11, 3, 29, ymm_b1);
165 teq_direct!(s11, s0, 2, 30, ymm_b2);
166
167 s0 = xor(s0, s11);
168
169 }
170
171 }
172
173
174 unsafe {
175 self.states[0] = self.states[0] .wrapping_add(horiz_add_avx2(s0));
176 self.states[1] = self.states[1] .wrapping_add(horiz_add_avx2(s1));
177 self.states[2] = self.states[2] .wrapping_add(horiz_add_avx2(s2));
178 self.states[3] = self.states[3] .wrapping_add(horiz_add_avx2(s3));
179 self.states[4] = self.states[4] .wrapping_add(horiz_add_avx2(s4));
180 self.states[5] = self.states[5] .wrapping_add(horiz_add_avx2(s5));
181 self.states[6] = self.states[6] .wrapping_add(horiz_add_avx2(s6));
182 self.states[7] = self.states[7] .wrapping_add(horiz_add_avx2(s7));
183 self.states[8] = self.states[8] .wrapping_add(horiz_add_avx2(s8));
184 self.states[9] = self.states[9] .wrapping_add(horiz_add_avx2(s9));
185 self.states[10] = self.states[10].wrapping_add(horiz_add_avx2(s10));
186 self.states[11] = self.states[11].wrapping_add(horiz_add_avx2(s11));
187 }
188
189
190 let remainder_128 = chunks.remainder();
191 let mut chunks_64 = remainder_128.chunks_exact(64);
192
193 for chunk in chunks_64.by_ref() {
194 unsafe {
195
196 let ymm_a1 = loadu(chunk.as_ptr() as *const __m256i);
197 let ymm_a2 = xor(loadu(chunk.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
198
199 teq_direct!(s0, s1, 7, 25, ymm_a1);
200 teq_direct!(s1, s2, 31, 28, ymm_a2);
201 teq_direct!(s2, s3, 25, 7, ymm_a1);
202 teq_direct!(s3, s4, 23, 9, ymm_a2);
203 teq_direct!(s4, s5, 13, 19, ymm_a1);
204 teq_direct!(s5, s6, 29, 3, ymm_a2);
205 teq_direct!(s6, s7, 19, 13, ymm_a1);
206 teq_direct!(s7, s8, 17, 15, ymm_a2);
207 teq_direct!(s8, s9, 11, 21, ymm_a1);
208 teq_direct!(s9, s10, 5, 27, ymm_a2);
209 teq_direct!(s10, s11, 3, 29, ymm_a1);
210 teq_direct!(s11, s0, 2, 30, ymm_a2);
211
212 }
213 }
214
215
216 let final_remainder = chunks_64.remainder();
217
218 for (idx, &byte) in final_remainder.iter().enumerate() {
219 let pos = idx % 12;
220 self.states[pos] = self.states[pos].wrapping_add((byte as u32) ^ 0x9E3779B1);
221 }
222
223 self.apply_final_mixer_64();
224
225 let mut hex_buffer = vec![0u8; 96];
226
227 for (i, &s) in self.states.iter().enumerate() {
228 let bytes = s.to_be_bytes();
229 for (j, &byte) in bytes.iter().enumerate() {
230 let offset = (i * 8) + (j * 2);
231 hex_buffer[offset] = HEX_CHARS[(byte >> 4) as usize];
232 hex_buffer[offset + 1] = HEX_CHARS[(byte & 0x0f) as usize];
233 }
234 }
235
236 unsafe { String::from_utf8_unchecked(hex_buffer) }
237
238 }
239
240
241 pub fn tqlhash_raw(&mut self, input: &[u8]) -> [u8; 48] {
275
276 self.states = [
277 0x107912FA, 0x220952EA, 0x3320212A, 0x4324312F,
278 0x5320212A, 0x9E3779B1, 0x85EBCA6B, 0xAD35744D,
279 0xCC2912FA, 0xEE0952EA, 0x1120212A, 0x2224312F,
280 ];
281
282 let mut s0 = unsafe { setzero() };
283 let mut s1 = unsafe { setzero() };
284 let mut s2 = unsafe { setzero() };
285 let mut s3 = unsafe { setzero() };
286 let mut s4 = unsafe { setzero() };
287 let mut s5 = unsafe { setzero() };
288 let mut s6 = unsafe { setzero() };
289 let mut s7 = unsafe { setzero() };
290 let mut s8 = unsafe { setzero() };
291 let mut s9 = unsafe { setzero() };
292 let mut s10 = unsafe { setzero() };
293 let mut s11 = unsafe { setzero() };
294
295 let mut chunks = input.chunks_exact(128);
296
297 for chunk in chunks.by_ref() {
298
299 unsafe {
300
301 let bl_a = &chunk[..64];
302 let bl_b = &chunk[64..];
303
304 let ymm_a1 = loadu(bl_a.as_ptr() as *const __m256i);
305 let ymm_a2 = xor(loadu(bl_a.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
306
307 teq_direct!(s0, s1, 7, 25, ymm_a1);
308 teq_direct!(s1, s2, 31, 28, ymm_a2);
309 teq_direct!(s2, s3, 25, 7, ymm_a1);
310 teq_direct!(s3, s4, 23, 9, ymm_a2);
311 teq_direct!(s4, s5, 13, 19, ymm_a1);
312 teq_direct!(s5, s6, 29, 3, ymm_a2);
313 teq_direct!(s6, s7, 19, 13, ymm_a1);
314 teq_direct!(s7, s8, 17, 15, ymm_a2);
315 teq_direct!(s8, s9, 11, 21, ymm_a1);
316 teq_direct!(s9, s10, 5, 27, ymm_a2);
317 teq_direct!(s10, s11, 3, 29, ymm_a1);
318 teq_direct!(s11, s0, 2, 30, ymm_a2);
319
320 let ymm_b1 = loadu(bl_b.as_ptr() as *const __m256i);
321 let ymm_b2 = xor(loadu(bl_b.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
322
323 teq_direct!(s0, s1, 7, 25, ymm_b1);
324 teq_direct!(s1, s2, 31, 28, ymm_b2);
325 teq_direct!(s2, s3, 25, 7, ymm_b1);
326 teq_direct!(s3, s4, 23, 9, ymm_b2);
327 teq_direct!(s4, s5, 13, 19, ymm_b1);
328 teq_direct!(s5, s6, 29, 3, ymm_b2);
329 teq_direct!(s6, s7, 19, 13, ymm_b1);
330 teq_direct!(s7, s8, 17, 15, ymm_b2);
331 teq_direct!(s8, s9, 11, 21, ymm_b1);
332 teq_direct!(s9, s10, 5, 27, ymm_b2);
333 teq_direct!(s10, s11, 3, 29, ymm_b1);
334 teq_direct!(s11, s0, 2, 30, ymm_b2);
335
336 s0 = xor(s0, s11);
337
338 }
339
340 }
341
342
343 unsafe {
344 self.states[0] = self.states[0] .wrapping_add(horiz_add_avx2(s0));
345 self.states[1] = self.states[1] .wrapping_add(horiz_add_avx2(s1));
346 self.states[2] = self.states[2] .wrapping_add(horiz_add_avx2(s2));
347 self.states[3] = self.states[3] .wrapping_add(horiz_add_avx2(s3));
348 self.states[4] = self.states[4] .wrapping_add(horiz_add_avx2(s4));
349 self.states[5] = self.states[5] .wrapping_add(horiz_add_avx2(s5));
350 self.states[6] = self.states[6] .wrapping_add(horiz_add_avx2(s6));
351 self.states[7] = self.states[7] .wrapping_add(horiz_add_avx2(s7));
352 self.states[8] = self.states[8] .wrapping_add(horiz_add_avx2(s8));
353 self.states[9] = self.states[9] .wrapping_add(horiz_add_avx2(s9));
354 self.states[10] = self.states[10].wrapping_add(horiz_add_avx2(s10));
355 self.states[11] = self.states[11].wrapping_add(horiz_add_avx2(s11));
356 }
357
358
359 let remainder = chunks.remainder();
360
361 for (idx, &byte) in remainder.iter().enumerate() {
362 let pos = idx % 12;
363 self.states[pos] = self.states[pos].wrapping_add((byte as u32) ^ 0x9E3779B1);
364 }
365
366 self.apply_final_mixer_64();
367
368 let mut bytes = [0u8; 48];
369
370 for (i, &val) in self.states.iter().enumerate() {
371 let b = val.to_be_bytes();
372 bytes[i*4 .. i*4+4].copy_from_slice(&b);
373 }
374
375 bytes
376 }
377
378
379
380 pub fn isv_tqlhash(&mut self, hash: &String, input: &[u8]) -> bool {
412
413 let new_hash = self.tqlhash(input);
414
415 let a = new_hash.as_bytes();
416 let b = hash.as_bytes();
417
418 if a.len() != b.len() {
419 return false;
420 }
421
422 let mut result = 0u8;
423 for i in 0..a.len() {
424 result |= black_box(a[i] ^ b[i]);
425 }
426
427 result == 0
428
429 }
430
431
432 pub fn isv_tqlhash_raw(&mut self, hash: &[u8; 48], input: &[u8]) -> bool {
433
434 let a_bh = self.tqlhash_raw(input);
435
436 let mut result = 0u8;
437
438 for i in 0..48 {
439 result |= black_box(a_bh[i] ^ hash[i]);
440 }
441
442 result == 0
443
444 }
445
446
447
448 pub fn derive_key(&mut self, password: &str, iterations: u32) -> [u8; 32] {
480
481 self.iterations = if iterations > 0 { iterations } else { 30 };
482
483 let mut derived = format!("{}{}{}", self.salt, password, self.salt);
484
485 for i in 0..self.iterations {
486 let hash_hex = self.tqlhash(derived.as_bytes());
487 derived = format!("{}{}{}", i, hash_hex, self.salt);
488 }
489
490 let final_hash = self.tqlhash(derived.as_bytes());
491 let bytes = hex::decode(&final_hash).expect("Error in key closing");
492
493 let mut key = [0u8; 32];
494 key.copy_from_slice(&bytes[0..32]);
495 key
496 }
497
498
499
500 fn apply_final_mixer_64(&mut self) {
501 for r in 0..64 {
502 for i in 0..12 {
503 let prev = if i == 0 { 11 } else { i - 1 };
504 let next = (i + 1) % 12;
505
506 self.states[i] = self.states[i]
507 .wrapping_add(self.states[prev])
508 .rotate_left(((r % 31) as u32) + 1);
509 self.states[next] ^= self.states[i].wrapping_mul(0xAD35744D);
510 }
511 }
512 }
513
514}