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 };
19
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 const HEX_CHARS: &[u8; 16] = b"0123456789abcdef";
283
284 let mut s0 = unsafe { setzero() };
285 let mut s1 = unsafe { setzero() };
286 let mut s2 = unsafe { setzero() };
287 let mut s3 = unsafe { setzero() };
288 let mut s4 = unsafe { setzero() };
289 let mut s5 = unsafe { setzero() };
290 let mut s6 = unsafe { setzero() };
291 let mut s7 = unsafe { setzero() };
292 let mut s8 = unsafe { setzero() };
293 let mut s9 = unsafe { setzero() };
294 let mut s10 = unsafe { setzero() };
295 let mut s11 = unsafe { setzero() };
296
297 let mut chunks = input.chunks_exact(128);
298
299 for chunk in chunks.by_ref() {
300
301 unsafe {
302
303 let bl_a = &chunk[..64];
304 let bl_b = &chunk[64..];
305
306 let ymm_a1 = loadu(bl_a.as_ptr() as *const __m256i);
307 let ymm_a2 = xor(loadu(bl_a.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
308
309 teq_direct!(s0, s1, 7, 25, ymm_a1);
310 teq_direct!(s1, s2, 31, 28, ymm_a2);
311 teq_direct!(s2, s3, 25, 7, ymm_a1);
312 teq_direct!(s3, s4, 23, 9, ymm_a2);
313 teq_direct!(s4, s5, 13, 19, ymm_a1);
314 teq_direct!(s5, s6, 29, 3, ymm_a2);
315 teq_direct!(s6, s7, 19, 13, ymm_a1);
316 teq_direct!(s7, s8, 17, 15, ymm_a2);
317 teq_direct!(s8, s9, 11, 21, ymm_a1);
318 teq_direct!(s9, s10, 5, 27, ymm_a2);
319 teq_direct!(s10, s11, 3, 29, ymm_a1);
320 teq_direct!(s11, s0, 2, 30, ymm_a2);
321
322 let ymm_b1 = loadu(bl_b.as_ptr() as *const __m256i);
323 let ymm_b2 = xor(loadu(bl_b.as_ptr().add(32) as *const __m256i), setone_i32(0x517CC1B7));
324
325 teq_direct!(s0, s1, 7, 25, ymm_b1);
326 teq_direct!(s1, s2, 31, 28, ymm_b2);
327 teq_direct!(s2, s3, 25, 7, ymm_b1);
328 teq_direct!(s3, s4, 23, 9, ymm_b2);
329 teq_direct!(s4, s5, 13, 19, ymm_b1);
330 teq_direct!(s5, s6, 29, 3, ymm_b2);
331 teq_direct!(s6, s7, 19, 13, ymm_b1);
332 teq_direct!(s7, s8, 17, 15, ymm_b2);
333 teq_direct!(s8, s9, 11, 21, ymm_b1);
334 teq_direct!(s9, s10, 5, 27, ymm_b2);
335 teq_direct!(s10, s11, 3, 29, ymm_b1);
336 teq_direct!(s11, s0, 2, 30, ymm_b2);
337
338 s0 = xor(s0, s11);
339
340 }
341
342 }
343
344
345 unsafe {
346 self.states[0] = self.states[0] .wrapping_add(horiz_add_avx2(s0));
347 self.states[1] = self.states[1] .wrapping_add(horiz_add_avx2(s1));
348 self.states[2] = self.states[2] .wrapping_add(horiz_add_avx2(s2));
349 self.states[3] = self.states[3] .wrapping_add(horiz_add_avx2(s3));
350 self.states[4] = self.states[4] .wrapping_add(horiz_add_avx2(s4));
351 self.states[5] = self.states[5] .wrapping_add(horiz_add_avx2(s5));
352 self.states[6] = self.states[6] .wrapping_add(horiz_add_avx2(s6));
353 self.states[7] = self.states[7] .wrapping_add(horiz_add_avx2(s7));
354 self.states[8] = self.states[8] .wrapping_add(horiz_add_avx2(s8));
355 self.states[9] = self.states[9] .wrapping_add(horiz_add_avx2(s9));
356 self.states[10] = self.states[10].wrapping_add(horiz_add_avx2(s10));
357 self.states[11] = self.states[11].wrapping_add(horiz_add_avx2(s11));
358 }
359
360
361 let remainder = chunks.remainder();
362
363 for (idx, &byte) in remainder.iter().enumerate() {
364 let pos = idx % 12;
365 self.states[pos] = self.states[pos].wrapping_add((byte as u32) ^ 0x9E3779B1);
366 }
367
368 self.apply_final_mixer_64();
369
370 let mut bytes = [0u8; 48];
371
372 for (i, &val) in self.states.iter().enumerate() {
373 let b = val.to_be_bytes();
374 bytes[i*4 .. i*4+4].copy_from_slice(&b);
375 }
376
377 bytes
378 }
379
380
381
382 pub fn isv_tqlhash(&mut self, hash: &String, input: &[u8]) -> bool {
414
415 let mut prop_tequel = TequelHash::new()
416 .with_salt(&self.salt)
417 .with_iteration(self.iterations);
418
419 let new_hash = prop_tequel.tqlhash(input);
420
421 let a = new_hash.as_bytes();
422 let b = hash.as_bytes();
423
424 if a.len() != b.len() {
425 return false;
426 }
427
428 let mut result = 0u8;
429 for i in 0..a.len() {
430 result |= a[i] ^ b[i];
431 }
432
433 result == 0
434
435 }
436
437
438
439 pub fn derive_key(&mut self, password: &str, iterations: u32) -> [u8; 32] {
471
472 self.iterations = if iterations > 0 { iterations } else { 30 };
473
474 let mut derived = format!("{}{}{}", self.salt, password, self.salt);
475
476 for i in 0..self.iterations {
477 let hash_hex = self.tqlhash(derived.as_bytes());
478 derived = format!("{}{}{}", i, hash_hex, self.salt);
479 }
480
481 let final_hash = self.tqlhash(derived.as_bytes());
482 let bytes = hex::decode(&final_hash).expect("Error in key closing");
483
484 let mut key = [0u8; 32];
485 key.copy_from_slice(&bytes[0..32]);
486 key
487 }
488
489
490
491 fn apply_final_mixer_64(&mut self) {
492 for r in 0..64 {
493 for i in 0..12 {
494 let prev = if i == 0 { 11 } else { i - 1 };
495 let next = (i + 1) % 12;
496
497 self.states[i] = self.states[i]
498 .wrapping_add(self.states[prev])
499 .rotate_left(((r % 31) as u32) + 1);
500 self.states[next] ^= self.states[i].wrapping_mul(0xAD35744D);
501 }
502 }
503 }
504
505}