1 | pub const fn sha1(data: &ConstBuffer) -> Digest { |
2 | let state: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; |
3 | let len: u64 = 0; |
4 | let blocks: Blocks = Blocks { |
5 | len: 0, |
6 | data: [0; 64], |
7 | }; |
8 | let (blocks: Blocks, len: u64, state: [u32; 5]) = process_blocks(blocks, data, len, state); |
9 | digest(state, len, blocks) |
10 | } |
11 | |
12 | const BUFFER_SIZE: usize = 1024; |
13 | |
14 | pub struct ConstBuffer { |
15 | data: [u8; BUFFER_SIZE], |
16 | head: usize, |
17 | } |
18 | |
19 | impl ConstBuffer { |
20 | pub const fn for_class<C: crate::RuntimeName, I: crate::RuntimeType>() -> Self { |
21 | Self::new() |
22 | .push_slice(b"rc(" ) |
23 | .push_slice(C::NAME.as_bytes()) |
24 | .push(b';' ) |
25 | .push_other(I::SIGNATURE) |
26 | .push(b')' ) |
27 | } |
28 | |
29 | pub const fn for_interface<T: crate::Interface>() -> Self { |
30 | Self::new().push_guid(&T::IID) |
31 | } |
32 | |
33 | pub const fn from_slice(slice: &[u8]) -> Self { |
34 | let s = Self::new(); |
35 | s.push_slice(slice) |
36 | } |
37 | |
38 | pub const fn new() -> Self { |
39 | Self { |
40 | data: [0; BUFFER_SIZE], |
41 | head: 0, |
42 | } |
43 | } |
44 | |
45 | pub const fn push_slice(self, slice: &[u8]) -> Self { |
46 | self.push_amount(slice, slice.len()) |
47 | } |
48 | |
49 | const fn get(&self, index: usize) -> u8 { |
50 | self.data[index] |
51 | } |
52 | |
53 | const fn len(&self) -> usize { |
54 | self.head |
55 | } |
56 | |
57 | pub fn as_slice(&self) -> &[u8] { |
58 | &self.data[..self.head] |
59 | } |
60 | |
61 | pub const fn push_other(self, other: Self) -> Self { |
62 | self.push_amount(&other.data, other.len()) |
63 | } |
64 | |
65 | const fn push(mut self, value: u8) -> Self { |
66 | self.data[self.head] = value; |
67 | self.head += 1; |
68 | self |
69 | } |
70 | |
71 | const fn push_hex_u8(self, value: u8) -> Self { |
72 | const fn digit(mut value: u8) -> u8 { |
73 | value &= 0xF; |
74 | |
75 | if value < 10 { |
76 | b'0' + value |
77 | } else { |
78 | b'a' + (value - 10) |
79 | } |
80 | } |
81 | |
82 | self.push(digit(value >> 4)).push(digit(value)) |
83 | } |
84 | |
85 | const fn push_hex_u16(self, value: u16) -> Self { |
86 | self.push_hex_u8((value >> 8) as u8) |
87 | .push_hex_u8((value & 0xFF) as u8) |
88 | } |
89 | |
90 | const fn push_hex_u32(self, value: u32) -> Self { |
91 | self.push_hex_u16((value >> 16) as u16) |
92 | .push_hex_u16((value & 0xFFFF) as u16) |
93 | } |
94 | |
95 | const fn push_amount(mut self, slice: &[u8], amount: usize) -> Self { |
96 | let mut i = 0; |
97 | while i < amount { |
98 | self.data[self.head + i] = slice[i]; |
99 | i += 1; |
100 | } |
101 | self.head += i; |
102 | self |
103 | } |
104 | |
105 | const fn push_guid(self, guid: &crate::GUID) -> Self { |
106 | self.push(b'{' ) |
107 | .push_hex_u32(guid.data1) |
108 | .push(b'-' ) |
109 | .push_hex_u16(guid.data2) |
110 | .push(b'-' ) |
111 | .push_hex_u16(guid.data3) |
112 | .push(b'-' ) |
113 | .push_hex_u16(((guid.data4[0] as u16) << 8) | guid.data4[1] as u16) |
114 | .push(b'-' ) |
115 | .push_hex_u16(((guid.data4[2] as u16) << 8) | guid.data4[3] as u16) |
116 | .push_hex_u16(((guid.data4[4] as u16) << 8) | guid.data4[5] as u16) |
117 | .push_hex_u16(((guid.data4[6] as u16) << 8) | guid.data4[7] as u16) |
118 | .push(b'}' ) |
119 | } |
120 | } |
121 | |
122 | struct Blocks { |
123 | len: u32, |
124 | data: [u8; 64], |
125 | } |
126 | |
127 | const fn process_blocks( |
128 | mut blocks: Blocks, |
129 | data: &ConstBuffer, |
130 | mut len: u64, |
131 | mut state: [u32; 5], |
132 | ) -> (Blocks, u64, [u32; 5]) { |
133 | const fn as_block(input: &ConstBuffer, offset: usize) -> [u32; 16] { |
134 | let mut result = [0u32; 16]; |
135 | |
136 | let mut i = 0; |
137 | while i != 16 { |
138 | let off = offset + (i * 4); |
139 | result[i] = (input.get(off + 3) as u32) |
140 | | ((input.get(off + 2) as u32) << 8) |
141 | | ((input.get(off + 1) as u32) << 16) |
142 | | ((input.get(off) as u32) << 24); |
143 | i += 1; |
144 | } |
145 | result |
146 | } |
147 | |
148 | const fn clone_from_slice_64( |
149 | mut data: [u8; 64], |
150 | slice: &[u8], |
151 | offset: usize, |
152 | num_elems: usize, |
153 | ) -> [u8; 64] { |
154 | let mut i = 0; |
155 | while i < num_elems { |
156 | data[i] = slice[offset + i]; |
157 | i += 1; |
158 | } |
159 | data |
160 | } |
161 | |
162 | let mut i = 0; |
163 | while i < data.len() { |
164 | if data.len() - i >= 64 { |
165 | let chunk_block = as_block(data, i); |
166 | len += 64; |
167 | state = process_state(state, chunk_block); |
168 | i += 64; |
169 | } else { |
170 | let num_elems = data.len() - i; |
171 | blocks.data = clone_from_slice_64(blocks.data, &data.data, i, num_elems); |
172 | blocks.len = num_elems as u32; |
173 | break; |
174 | } |
175 | } |
176 | (blocks, len, state) |
177 | } |
178 | |
179 | const fn process_state(mut state: [u32; 5], block: [u32; 16]) -> [u32; 5] { |
180 | let a = state[0]; |
181 | let b = state[1]; |
182 | let c = state[2]; |
183 | let d = state[3]; |
184 | let e = state[4]; |
185 | let (block, b, e) = r0(block, a, b, c, d, e, 0); |
186 | let (block, a, d) = r0(block, e, a, b, c, d, 1); |
187 | let (block, e, c) = r0(block, d, e, a, b, c, 2); |
188 | let (block, d, b) = r0(block, c, d, e, a, b, 3); |
189 | let (block, c, a) = r0(block, b, c, d, e, a, 4); |
190 | let (block, b, e) = r0(block, a, b, c, d, e, 5); |
191 | let (block, a, d) = r0(block, e, a, b, c, d, 6); |
192 | let (block, e, c) = r0(block, d, e, a, b, c, 7); |
193 | let (block, d, b) = r0(block, c, d, e, a, b, 8); |
194 | let (block, c, a) = r0(block, b, c, d, e, a, 9); |
195 | let (block, b, e) = r0(block, a, b, c, d, e, 10); |
196 | let (block, a, d) = r0(block, e, a, b, c, d, 11); |
197 | let (block, e, c) = r0(block, d, e, a, b, c, 12); |
198 | let (block, d, b) = r0(block, c, d, e, a, b, 13); |
199 | let (block, c, a) = r0(block, b, c, d, e, a, 14); |
200 | let (block, b, e) = r0(block, a, b, c, d, e, 15); |
201 | let (block, a, d) = r1(block, e, a, b, c, d, 0); |
202 | let (block, e, c) = r1(block, d, e, a, b, c, 1); |
203 | let (block, d, b) = r1(block, c, d, e, a, b, 2); |
204 | let (block, c, a) = r1(block, b, c, d, e, a, 3); |
205 | let (block, b, e) = r2(block, a, b, c, d, e, 4); |
206 | let (block, a, d) = r2(block, e, a, b, c, d, 5); |
207 | let (block, e, c) = r2(block, d, e, a, b, c, 6); |
208 | let (block, d, b) = r2(block, c, d, e, a, b, 7); |
209 | let (block, c, a) = r2(block, b, c, d, e, a, 8); |
210 | let (block, b, e) = r2(block, a, b, c, d, e, 9); |
211 | let (block, a, d) = r2(block, e, a, b, c, d, 10); |
212 | let (block, e, c) = r2(block, d, e, a, b, c, 11); |
213 | let (block, d, b) = r2(block, c, d, e, a, b, 12); |
214 | let (block, c, a) = r2(block, b, c, d, e, a, 13); |
215 | let (block, b, e) = r2(block, a, b, c, d, e, 14); |
216 | let (block, a, d) = r2(block, e, a, b, c, d, 15); |
217 | let (block, e, c) = r2(block, d, e, a, b, c, 0); |
218 | let (block, d, b) = r2(block, c, d, e, a, b, 1); |
219 | let (block, c, a) = r2(block, b, c, d, e, a, 2); |
220 | let (block, b, e) = r2(block, a, b, c, d, e, 3); |
221 | let (block, a, d) = r2(block, e, a, b, c, d, 4); |
222 | let (block, e, c) = r2(block, d, e, a, b, c, 5); |
223 | let (block, d, b) = r2(block, c, d, e, a, b, 6); |
224 | let (block, c, a) = r2(block, b, c, d, e, a, 7); |
225 | let (block, b, e) = r3(block, a, b, c, d, e, 8); |
226 | let (block, a, d) = r3(block, e, a, b, c, d, 9); |
227 | let (block, e, c) = r3(block, d, e, a, b, c, 10); |
228 | let (block, d, b) = r3(block, c, d, e, a, b, 11); |
229 | let (block, c, a) = r3(block, b, c, d, e, a, 12); |
230 | let (block, b, e) = r3(block, a, b, c, d, e, 13); |
231 | let (block, a, d) = r3(block, e, a, b, c, d, 14); |
232 | let (block, e, c) = r3(block, d, e, a, b, c, 15); |
233 | let (block, d, b) = r3(block, c, d, e, a, b, 0); |
234 | let (block, c, a) = r3(block, b, c, d, e, a, 1); |
235 | let (block, b, e) = r3(block, a, b, c, d, e, 2); |
236 | let (block, a, d) = r3(block, e, a, b, c, d, 3); |
237 | let (block, e, c) = r3(block, d, e, a, b, c, 4); |
238 | let (block, d, b) = r3(block, c, d, e, a, b, 5); |
239 | let (block, c, a) = r3(block, b, c, d, e, a, 6); |
240 | let (block, b, e) = r3(block, a, b, c, d, e, 7); |
241 | let (block, a, d) = r3(block, e, a, b, c, d, 8); |
242 | let (block, e, c) = r3(block, d, e, a, b, c, 9); |
243 | let (block, d, b) = r3(block, c, d, e, a, b, 10); |
244 | let (block, c, a) = r3(block, b, c, d, e, a, 11); |
245 | let (block, b, e) = r4(block, a, b, c, d, e, 12); |
246 | let (block, a, d) = r4(block, e, a, b, c, d, 13); |
247 | let (block, e, c) = r4(block, d, e, a, b, c, 14); |
248 | let (block, d, b) = r4(block, c, d, e, a, b, 15); |
249 | let (block, c, a) = r4(block, b, c, d, e, a, 0); |
250 | let (block, b, e) = r4(block, a, b, c, d, e, 1); |
251 | let (block, a, d) = r4(block, e, a, b, c, d, 2); |
252 | let (block, e, c) = r4(block, d, e, a, b, c, 3); |
253 | let (block, d, b) = r4(block, c, d, e, a, b, 4); |
254 | let (block, c, a) = r4(block, b, c, d, e, a, 5); |
255 | let (block, b, e) = r4(block, a, b, c, d, e, 6); |
256 | let (block, a, d) = r4(block, e, a, b, c, d, 7); |
257 | let (block, e, c) = r4(block, d, e, a, b, c, 8); |
258 | let (block, d, b) = r4(block, c, d, e, a, b, 9); |
259 | let (block, c, a) = r4(block, b, c, d, e, a, 10); |
260 | let (block, b, e) = r4(block, a, b, c, d, e, 11); |
261 | let (block, a, d) = r4(block, e, a, b, c, d, 12); |
262 | let (block, e, c) = r4(block, d, e, a, b, c, 13); |
263 | let (block, d, b) = r4(block, c, d, e, a, b, 14); |
264 | let (_, c, a) = r4(block, b, c, d, e, a, 15); |
265 | |
266 | state[0] = state[0].wrapping_add(a); |
267 | state[1] = state[1].wrapping_add(b); |
268 | state[2] = state[2].wrapping_add(c); |
269 | state[3] = state[3].wrapping_add(d); |
270 | state[4] = state[4].wrapping_add(e); |
271 | state |
272 | } |
273 | |
274 | const fn digest(mut state: [u32; 5], len: u64, blocks: Blocks) -> Digest { |
275 | const fn clone_from_slice_128( |
276 | mut data: [u8; 128], |
277 | slice: &[u8], |
278 | offset: usize, |
279 | num_elems: usize, |
280 | ) -> [u8; 128] { |
281 | let mut i = 0; |
282 | while i < num_elems { |
283 | data[i] = slice[offset + i]; |
284 | i += 1; |
285 | } |
286 | data |
287 | } |
288 | |
289 | const fn clone_slice_128(mut data: [u8; 128], slice: &[u8], _offset: usize) -> [u8; 128] { |
290 | let mut i = 0; |
291 | while i < slice.len() { |
292 | data[_offset + i] = slice[i]; |
293 | i += 1; |
294 | } |
295 | data |
296 | } |
297 | |
298 | const fn as_block(input: &[u8], offset: usize) -> [u32; 16] { |
299 | let mut result = [0u32; 16]; |
300 | |
301 | let mut i = 0; |
302 | while i != 16 { |
303 | let off = offset + (i * 4); |
304 | result[i] = (input[off + 3] as u32) |
305 | | ((input[off + 2] as u32) << 8) |
306 | | ((input[off + 1] as u32) << 16) |
307 | | ((input[off] as u32) << 24); |
308 | i += 1; |
309 | } |
310 | result |
311 | } |
312 | |
313 | let bits = (len + (blocks.len as u64)) * 8; |
314 | let extra = [ |
315 | (bits >> 56) as u8, |
316 | (bits >> 48) as u8, |
317 | (bits >> 40) as u8, |
318 | (bits >> 32) as u8, |
319 | (bits >> 24) as u8, |
320 | (bits >> 16) as u8, |
321 | (bits >> 8) as u8, |
322 | bits as u8, |
323 | ]; |
324 | let mut last = [0; 128]; |
325 | let blocklen = blocks.len as usize; |
326 | last = clone_from_slice_128(last, &blocks.data, 0, blocklen); |
327 | last[blocklen] = 0x80; |
328 | |
329 | if blocklen < 56 { |
330 | last = clone_slice_128(last, &extra, 56); |
331 | state = process_state(state, as_block(&last, 0)); |
332 | } else { |
333 | last = clone_slice_128(last, &extra, 120); |
334 | state = process_state(state, as_block(&last, 0)); |
335 | state = process_state(state, as_block(&last, 64)); |
336 | } |
337 | Digest { data: state } |
338 | } |
339 | |
340 | const fn rol(value: u32, bits: usize) -> u32 { |
341 | (value << bits) | (value >> (32 - bits)) |
342 | } |
343 | |
344 | const fn blk(block: &[u32], i: usize) -> u32 { |
345 | let value: u32 = block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^ block[i]; |
346 | rol(value, bits:1) |
347 | } |
348 | |
349 | const fn r0( |
350 | block: [u32; 16], |
351 | v: u32, |
352 | mut w: u32, |
353 | x: u32, |
354 | y: u32, |
355 | mut z: u32, |
356 | i: usize, |
357 | ) -> ([u32; 16], u32, u32) { |
358 | let n: u32 = ((w & (x ^ y)) ^ y) |
359 | .wrapping_add(block[i]) |
360 | .wrapping_add(0x5a82_7999) |
361 | .wrapping_add(rol(value:v, bits:5)); |
362 | z = z.wrapping_add(n); |
363 | w = rol(value:w, bits:30); |
364 | (block, w, z) |
365 | } |
366 | |
367 | const fn r1( |
368 | mut block: [u32; 16], |
369 | v: u32, |
370 | mut w: u32, |
371 | x: u32, |
372 | y: u32, |
373 | mut z: u32, |
374 | i: usize, |
375 | ) -> ([u32; 16], u32, u32) { |
376 | block[i] = blk(&block, i); |
377 | let n: u32 = ((w & (x ^ y)) ^ y) |
378 | .wrapping_add(block[i]) |
379 | .wrapping_add(0x5a82_7999) |
380 | .wrapping_add(rol(value:v, bits:5)); |
381 | z = z.wrapping_add(n); |
382 | w = rol(value:w, bits:30); |
383 | (block, w, z) |
384 | } |
385 | |
386 | const fn r2( |
387 | mut block: [u32; 16], |
388 | v: u32, |
389 | mut w: u32, |
390 | x: u32, |
391 | y: u32, |
392 | mut z: u32, |
393 | i: usize, |
394 | ) -> ([u32; 16], u32, u32) { |
395 | block[i] = blk(&block, i); |
396 | let n: u32 = (w ^ x ^ y) |
397 | .wrapping_add(block[i]) |
398 | .wrapping_add(0x6ed9_eba1) |
399 | .wrapping_add(rol(value:v, bits:5)); |
400 | z = z.wrapping_add(n); |
401 | w = rol(value:w, bits:30); |
402 | (block, w, z) |
403 | } |
404 | |
405 | const fn r3( |
406 | mut block: [u32; 16], |
407 | v: u32, |
408 | mut w: u32, |
409 | x: u32, |
410 | y: u32, |
411 | mut z: u32, |
412 | i: usize, |
413 | ) -> ([u32; 16], u32, u32) { |
414 | block[i] = blk(&block, i); |
415 | let n: u32 = (((w | x) & y) | (w & x)) |
416 | .wrapping_add(block[i]) |
417 | .wrapping_add(0x8f1b_bcdc) |
418 | .wrapping_add(rol(value:v, bits:5)); |
419 | z = z.wrapping_add(n); |
420 | w = rol(value:w, bits:30); |
421 | (block, w, z) |
422 | } |
423 | |
424 | const fn r4( |
425 | mut block: [u32; 16], |
426 | v: u32, |
427 | mut w: u32, |
428 | x: u32, |
429 | y: u32, |
430 | mut z: u32, |
431 | i: usize, |
432 | ) -> ([u32; 16], u32, u32) { |
433 | block[i] = blk(&block, i); |
434 | let n: u32 = (w ^ x ^ y) |
435 | .wrapping_add(block[i]) |
436 | .wrapping_add(0xca62_c1d6) |
437 | .wrapping_add(rol(value:v, bits:5)); |
438 | z = z.wrapping_add(n); |
439 | w = rol(value:w, bits:30); |
440 | (block, w, z) |
441 | } |
442 | |
443 | pub struct Digest { |
444 | data: [u32; 5], |
445 | } |
446 | |
447 | impl Digest { |
448 | pub const fn bytes(&self) -> [u8; 20] { |
449 | [ |
450 | (self.data[0] >> 24) as u8, |
451 | (self.data[0] >> 16) as u8, |
452 | (self.data[0] >> 8) as u8, |
453 | self.data[0] as u8, |
454 | (self.data[1] >> 24) as u8, |
455 | (self.data[1] >> 16) as u8, |
456 | (self.data[1] >> 8) as u8, |
457 | self.data[1] as u8, |
458 | (self.data[2] >> 24) as u8, |
459 | (self.data[2] >> 16) as u8, |
460 | (self.data[2] >> 8) as u8, |
461 | self.data[2] as u8, |
462 | (self.data[3] >> 24) as u8, |
463 | (self.data[3] >> 16) as u8, |
464 | (self.data[3] >> 8) as u8, |
465 | self.data[3] as u8, |
466 | (self.data[4] >> 24) as u8, |
467 | (self.data[4] >> 16) as u8, |
468 | (self.data[4] >> 8) as u8, |
469 | self.data[4] as u8, |
470 | ] |
471 | } |
472 | } |
473 | |
474 | impl core::fmt::Display for Digest { |
475 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
476 | for i: &u32 in self.data.iter() { |
477 | write!(f, " {:08x}" , i)?; |
478 | } |
479 | Ok(()) |
480 | } |
481 | } |
482 | |