1const H0: [u32; 8] = [
17 0x6a09_e667,
18 0xbb67_ae85,
19 0x3c6e_f372,
20 0xa54f_f53a,
21 0x510e_527f,
22 0x9b05_688c,
23 0x1f83_d9ab,
24 0x5be0_cd19,
25];
26
27const K: [u32; 64] = [
28 0x428a_2f98,
29 0x7137_4491,
30 0xb5c0_fbcf,
31 0xe9b5_dba5,
32 0x3956_c25b,
33 0x59f1_11f1,
34 0x923f_82a4,
35 0xab1c_5ed5,
36 0xd807_aa98,
37 0x1283_5b01,
38 0x2431_85be,
39 0x550c_7dc3,
40 0x72be_5d74,
41 0x80de_b1fe,
42 0x9bdc_06a7,
43 0xc19b_f174,
44 0xe49b_69c1,
45 0xefbe_4786,
46 0x0fc1_9dc6,
47 0x240c_a1cc,
48 0x2de9_2c6f,
49 0x4a74_84aa,
50 0x5cb0_a9dc,
51 0x76f9_88da,
52 0x983e_5152,
53 0xa831_c66d,
54 0xb003_27c8,
55 0xbf59_7fc7,
56 0xc6e0_0bf3,
57 0xd5a7_9147,
58 0x06ca_6351,
59 0x1429_2967,
60 0x27b7_0a85,
61 0x2e1b_2138,
62 0x4d2c_6dfc,
63 0x5338_0d13,
64 0x650a_7354,
65 0x766a_0abb,
66 0x81c2_c92e,
67 0x9272_2c85,
68 0xa2bf_e8a1,
69 0xa81a_664b,
70 0xc24b_8b70,
71 0xc76c_51a3,
72 0xd192_e819,
73 0xd699_0624,
74 0xf40e_3585,
75 0x106a_a070,
76 0x19a4_c116,
77 0x1e37_6c08,
78 0x2748_774c,
79 0x34b0_bcb5,
80 0x391c_0cb3,
81 0x4ed8_aa4a,
82 0x5b9c_ca4f,
83 0x682e_6ff3,
84 0x748f_82ee,
85 0x78a5_636f,
86 0x84c8_7814,
87 0x8cc7_0208,
88 0x90be_fffa,
89 0xa450_6ceb,
90 0xbef9_a3f7,
91 0xc671_78f2,
92];
93
94fn compress(h: &mut [u32; 8], block: &[u8; 64]) {
95 let mut w = [0u32; 64];
96 for i in 0..16 {
97 w[i] = u32::from_be_bytes([
98 block[i * 4],
99 block[i * 4 + 1],
100 block[i * 4 + 2],
101 block[i * 4 + 3],
102 ]);
103 }
104 for i in 16..64 {
105 let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
106 let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
107 w[i] = w[i - 16]
108 .wrapping_add(s0)
109 .wrapping_add(w[i - 7])
110 .wrapping_add(s1);
111 }
112 let (mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh) =
113 (h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]);
114 for i in 0..64 {
115 let big_s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
116 let ch = (e & f) ^ ((!e) & g);
117 let t1 = hh
118 .wrapping_add(big_s1)
119 .wrapping_add(ch)
120 .wrapping_add(K[i])
121 .wrapping_add(w[i]);
122 let big_s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
123 let maj = (a & b) ^ (a & c) ^ (b & c);
124 let t2 = big_s0.wrapping_add(maj);
125 hh = g;
126 g = f;
127 f = e;
128 e = d.wrapping_add(t1);
129 d = c;
130 c = b;
131 b = a;
132 a = t1.wrapping_add(t2);
133 }
134 h[0] = h[0].wrapping_add(a);
135 h[1] = h[1].wrapping_add(b);
136 h[2] = h[2].wrapping_add(c);
137 h[3] = h[3].wrapping_add(d);
138 h[4] = h[4].wrapping_add(e);
139 h[5] = h[5].wrapping_add(f);
140 h[6] = h[6].wrapping_add(g);
141 h[7] = h[7].wrapping_add(hh);
142}
143
144pub fn sha256(msg: &[u8]) -> [u8; 32] {
146 let mut h = H0;
147 let mut block = [0u8; 64];
148 let mut chunks = msg.chunks_exact(64);
149 for chunk in chunks.by_ref() {
150 block.copy_from_slice(chunk);
151 compress(&mut h, &block);
152 }
153 let rem = chunks.remainder();
155 let mut tail = [0u8; 128];
156 tail[..rem.len()].copy_from_slice(rem);
157 tail[rem.len()] = 0x80;
158 let bit_len = (msg.len() as u64) * 8;
159 let pad_len = if rem.len() < 56 { 64 } else { 128 };
160 tail[pad_len - 8..pad_len].copy_from_slice(&bit_len.to_be_bytes());
161 block.copy_from_slice(&tail[..64]);
162 compress(&mut h, &block);
163 if pad_len == 128 {
164 block.copy_from_slice(&tail[64..128]);
165 compress(&mut h, &block);
166 }
167 let mut out = [0u8; 32];
168 for (i, word) in h.iter().enumerate() {
169 out[i * 4..i * 4 + 4].copy_from_slice(&word.to_be_bytes());
170 }
171 out
172}
173
174pub fn hmac_sha256(key: &[u8], msg: &[u8]) -> [u8; 32] {
176 let mut k = [0u8; 64];
177 if key.len() > 64 {
178 k[..32].copy_from_slice(&sha256(key));
179 } else {
180 k[..key.len()].copy_from_slice(key);
181 }
182 let mut inner = Vec::with_capacity(64 + msg.len());
183 inner.extend(k.iter().map(|b| b ^ 0x36));
184 inner.extend_from_slice(msg);
185 let inner_hash = sha256(&inner);
186 let mut outer = Vec::with_capacity(64 + 32);
187 outer.extend(k.iter().map(|b| b ^ 0x5c));
188 outer.extend_from_slice(&inner_hash);
189 sha256(&outer)
190}
191
192pub fn pbkdf2_sha256(password: &[u8], salt: &[u8], iters: u32) -> [u8; 32] {
200 let mut k = [0u8; 64];
202 if password.len() > 64 {
203 k[..32].copy_from_slice(&sha256(password));
204 } else {
205 k[..password.len()].copy_from_slice(password);
206 }
207 let mut ipad = [0u8; 64];
208 let mut opad = [0u8; 64];
209 for i in 0..64 {
210 ipad[i] = k[i] ^ 0x36;
211 opad[i] = k[i] ^ 0x5c;
212 }
213 let mut inner_state = H0;
214 compress(&mut inner_state, &ipad);
215 let mut outer_state = H0;
216 compress(&mut outer_state, &opad);
217
218 let mut first_msg = Vec::with_capacity(salt.len() + 4);
222 first_msg.extend_from_slice(salt);
223 first_msg.extend_from_slice(&1u32.to_be_bytes());
224 let mut u = hmac_with_states(&inner_state, &outer_state, &first_msg);
225 let mut t = u;
226 for _ in 1..iters {
227 u = hmac_with_states(&inner_state, &outer_state, &u);
228 for j in 0..32 {
229 t[j] ^= u[j];
230 }
231 }
232 t
233}
234
235fn hmac_with_states(inner_state: &[u32; 8], outer_state: &[u32; 8], msg: &[u8]) -> [u8; 32] {
238 let inner_hash = finalize_from(inner_state, msg, 64);
239 finalize_from(outer_state, &inner_hash, 64)
240}
241
242fn finalize_from(state: &[u32; 8], tail: &[u8], prefix_len: u64) -> [u8; 32] {
246 let mut h = *state;
247 let total_bits = (prefix_len + tail.len() as u64) * 8;
248 let mut block = [0u8; 64];
249 let mut chunks = tail.chunks_exact(64);
250 for chunk in chunks.by_ref() {
251 block.copy_from_slice(chunk);
252 compress(&mut h, &block);
253 }
254 let rem = chunks.remainder();
255 let mut pad = [0u8; 128];
256 pad[..rem.len()].copy_from_slice(rem);
257 pad[rem.len()] = 0x80;
258 let pad_len = if rem.len() < 56 { 64 } else { 128 };
259 pad[pad_len - 8..pad_len].copy_from_slice(&total_bits.to_be_bytes());
260 block.copy_from_slice(&pad[..64]);
261 compress(&mut h, &block);
262 if pad_len == 128 {
263 block.copy_from_slice(&pad[64..128]);
264 compress(&mut h, &block);
265 }
266 let mut out = [0u8; 32];
267 for (i, word) in h.iter().enumerate() {
268 out[i * 4..i * 4 + 4].copy_from_slice(&word.to_be_bytes());
269 }
270 out
271}
272
273#[cfg(test)]
274#[path = "../../logicaffeine_tests/unit/logicaffeine_compile/crypto_accel/tests.rs"]
275mod tests;