1#![no_std]
8#![allow(
9 non_snake_case,
10 clippy::cast_lossless,
11 clippy::eq_op,
12 clippy::identity_op,
13 clippy::many_single_char_names,
14 clippy::unreadable_literal
15)]
16
17pub const BLOCKBYTES: usize = 128;
18pub const BYTES: usize = 64;
19
20#[inline(always)]
21fn load_be(base: &[u8], offset: usize) -> u64 {
22 let addr = &base[offset..];
23 (addr[7] as u64)
24 | (addr[6] as u64) << 8
25 | (addr[5] as u64) << 16
26 | (addr[4] as u64) << 24
27 | (addr[3] as u64) << 32
28 | (addr[2] as u64) << 40
29 | (addr[1] as u64) << 48
30 | (addr[0] as u64) << 56
31}
32
33#[inline(always)]
34fn store_be(base: &mut [u8], offset: usize, x: u64) {
35 let addr = &mut base[offset..];
36 addr[7] = x as u8;
37 addr[6] = (x >> 8) as u8;
38 addr[5] = (x >> 16) as u8;
39 addr[4] = (x >> 24) as u8;
40 addr[3] = (x >> 32) as u8;
41 addr[2] = (x >> 40) as u8;
42 addr[1] = (x >> 48) as u8;
43 addr[0] = (x >> 56) as u8;
44}
45
46fn verify(x: &[u8], y: &[u8]) -> bool {
47 if x.len() != y.len() {
48 return false;
49 }
50 let mut v: u32 = 0;
51
52 #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
53 {
54 let (mut h1, mut h2) = (0u32, 0u32);
55 for (b1, b2) in x.iter().zip(y.iter()) {
56 h1 ^= (h1 << 5).wrapping_add((h1 >> 2) ^ *b1 as u32);
57 h2 ^= (h2 << 5).wrapping_add((h2 >> 2) ^ *b2 as u32);
58 }
59 v |= h1 ^ h2;
60 }
61 for (a, b) in x.iter().zip(y.iter()) {
62 v |= (a ^ b) as u32;
63 }
64 let v = unsafe { core::ptr::read_volatile(&v) };
65 v == 0
66}
67
68struct W([u64; 16]);
69
70#[derive(Copy, Clone)]
71struct State([u64; 8]);
72
73impl W {
74 fn new(input: &[u8]) -> Self {
75 let mut w = [0u64; 16];
76 for (i, e) in w.iter_mut().enumerate() {
77 *e = load_be(input, i * 8)
78 }
79 W(w)
80 }
81
82 #[inline(always)]
83 fn Ch(x: u64, y: u64, z: u64) -> u64 {
84 (x & y) ^ (!x & z)
85 }
86
87 #[inline(always)]
88 fn Maj(x: u64, y: u64, z: u64) -> u64 {
89 (x & y) ^ (x & z) ^ (y & z)
90 }
91
92 #[inline(always)]
93 fn Sigma0(x: u64) -> u64 {
94 x.rotate_right(28) ^ x.rotate_right(34) ^ x.rotate_right(39)
95 }
96
97 #[inline(always)]
98 fn Sigma1(x: u64) -> u64 {
99 x.rotate_right(14) ^ x.rotate_right(18) ^ x.rotate_right(41)
100 }
101
102 #[inline(always)]
103 fn sigma0(x: u64) -> u64 {
104 x.rotate_right(1) ^ x.rotate_right(8) ^ (x >> 7)
105 }
106
107 #[inline(always)]
108 fn sigma1(x: u64) -> u64 {
109 x.rotate_right(19) ^ x.rotate_right(61) ^ (x >> 6)
110 }
111
112 #[cfg_attr(feature = "opt_size", inline(never))]
113 #[cfg_attr(not(feature = "opt_size"), inline(always))]
114 fn M(&mut self, a: usize, b: usize, c: usize, d: usize) {
115 let w = &mut self.0;
116 w[a] = w[a]
117 .wrapping_add(Self::sigma1(w[b]))
118 .wrapping_add(w[c])
119 .wrapping_add(Self::sigma0(w[d]));
120 }
121
122 #[inline]
123 fn expand(&mut self) {
124 self.M(0, (0 + 14) & 15, (0 + 9) & 15, (0 + 1) & 15);
125 self.M(1, (1 + 14) & 15, (1 + 9) & 15, (1 + 1) & 15);
126 self.M(2, (2 + 14) & 15, (2 + 9) & 15, (2 + 1) & 15);
127 self.M(3, (3 + 14) & 15, (3 + 9) & 15, (3 + 1) & 15);
128 self.M(4, (4 + 14) & 15, (4 + 9) & 15, (4 + 1) & 15);
129 self.M(5, (5 + 14) & 15, (5 + 9) & 15, (5 + 1) & 15);
130 self.M(6, (6 + 14) & 15, (6 + 9) & 15, (6 + 1) & 15);
131 self.M(7, (7 + 14) & 15, (7 + 9) & 15, (7 + 1) & 15);
132 self.M(8, (8 + 14) & 15, (8 + 9) & 15, (8 + 1) & 15);
133 self.M(9, (9 + 14) & 15, (9 + 9) & 15, (9 + 1) & 15);
134 self.M(10, (10 + 14) & 15, (10 + 9) & 15, (10 + 1) & 15);
135 self.M(11, (11 + 14) & 15, (11 + 9) & 15, (11 + 1) & 15);
136 self.M(12, (12 + 14) & 15, (12 + 9) & 15, (12 + 1) & 15);
137 self.M(13, (13 + 14) & 15, (13 + 9) & 15, (13 + 1) & 15);
138 self.M(14, (14 + 14) & 15, (14 + 9) & 15, (14 + 1) & 15);
139 self.M(15, (15 + 14) & 15, (15 + 9) & 15, (15 + 1) & 15);
140 }
141
142 #[cfg_attr(feature = "opt_size", inline(never))]
143 #[cfg_attr(not(feature = "opt_size"), inline(always))]
144 fn F(&mut self, state: &mut State, i: usize, k: u64) {
145 let t = &mut state.0;
146 t[(16 - i + 7) & 7] = t[(16 - i + 7) & 7]
147 .wrapping_add(Self::Sigma1(t[(16 - i + 4) & 7]))
148 .wrapping_add(Self::Ch(
149 t[(16 - i + 4) & 7],
150 t[(16 - i + 5) & 7],
151 t[(16 - i + 6) & 7],
152 ))
153 .wrapping_add(k)
154 .wrapping_add(self.0[i]);
155 t[(16 - i + 3) & 7] = t[(16 - i + 3) & 7].wrapping_add(t[(16 - i + 7) & 7]);
156 t[(16 - i + 7) & 7] = t[(16 - i + 7) & 7]
157 .wrapping_add(Self::Sigma0(t[(16 - i + 0) & 7]))
158 .wrapping_add(Self::Maj(
159 t[(16 - i + 0) & 7],
160 t[(16 - i + 1) & 7],
161 t[(16 - i + 2) & 7],
162 ));
163 }
164
165 fn G(&mut self, state: &mut State, s: usize) {
166 const ROUND_CONSTANTS: [u64; 80] = [
167 0x428a2f98d728ae22,
168 0x7137449123ef65cd,
169 0xb5c0fbcfec4d3b2f,
170 0xe9b5dba58189dbbc,
171 0x3956c25bf348b538,
172 0x59f111f1b605d019,
173 0x923f82a4af194f9b,
174 0xab1c5ed5da6d8118,
175 0xd807aa98a3030242,
176 0x12835b0145706fbe,
177 0x243185be4ee4b28c,
178 0x550c7dc3d5ffb4e2,
179 0x72be5d74f27b896f,
180 0x80deb1fe3b1696b1,
181 0x9bdc06a725c71235,
182 0xc19bf174cf692694,
183 0xe49b69c19ef14ad2,
184 0xefbe4786384f25e3,
185 0x0fc19dc68b8cd5b5,
186 0x240ca1cc77ac9c65,
187 0x2de92c6f592b0275,
188 0x4a7484aa6ea6e483,
189 0x5cb0a9dcbd41fbd4,
190 0x76f988da831153b5,
191 0x983e5152ee66dfab,
192 0xa831c66d2db43210,
193 0xb00327c898fb213f,
194 0xbf597fc7beef0ee4,
195 0xc6e00bf33da88fc2,
196 0xd5a79147930aa725,
197 0x06ca6351e003826f,
198 0x142929670a0e6e70,
199 0x27b70a8546d22ffc,
200 0x2e1b21385c26c926,
201 0x4d2c6dfc5ac42aed,
202 0x53380d139d95b3df,
203 0x650a73548baf63de,
204 0x766a0abb3c77b2a8,
205 0x81c2c92e47edaee6,
206 0x92722c851482353b,
207 0xa2bfe8a14cf10364,
208 0xa81a664bbc423001,
209 0xc24b8b70d0f89791,
210 0xc76c51a30654be30,
211 0xd192e819d6ef5218,
212 0xd69906245565a910,
213 0xf40e35855771202a,
214 0x106aa07032bbd1b8,
215 0x19a4c116b8d2d0c8,
216 0x1e376c085141ab53,
217 0x2748774cdf8eeb99,
218 0x34b0bcb5e19b48a8,
219 0x391c0cb3c5c95a63,
220 0x4ed8aa4ae3418acb,
221 0x5b9cca4f7763e373,
222 0x682e6ff3d6b2b8a3,
223 0x748f82ee5defb2fc,
224 0x78a5636f43172f60,
225 0x84c87814a1f0ab72,
226 0x8cc702081a6439ec,
227 0x90befffa23631e28,
228 0xa4506cebde82bde9,
229 0xbef9a3f7b2c67915,
230 0xc67178f2e372532b,
231 0xca273eceea26619c,
232 0xd186b8c721c0c207,
233 0xeada7dd6cde0eb1e,
234 0xf57d4f7fee6ed178,
235 0x06f067aa72176fba,
236 0x0a637dc5a2c898a6,
237 0x113f9804bef90dae,
238 0x1b710b35131c471b,
239 0x28db77f523047d84,
240 0x32caab7b40c72493,
241 0x3c9ebe0a15c9bebc,
242 0x431d67c49c100d4c,
243 0x4cc5d4becb3e42b6,
244 0x597f299cfc657e2a,
245 0x5fcb6fab3ad6faec,
246 0x6c44198c4a475817,
247 ];
248 let rc = &ROUND_CONSTANTS[s * 16..];
249 self.F(state, 0, rc[0]);
250 self.F(state, 1, rc[1]);
251 self.F(state, 2, rc[2]);
252 self.F(state, 3, rc[3]);
253 self.F(state, 4, rc[4]);
254 self.F(state, 5, rc[5]);
255 self.F(state, 6, rc[6]);
256 self.F(state, 7, rc[7]);
257 self.F(state, 8, rc[8]);
258 self.F(state, 9, rc[9]);
259 self.F(state, 10, rc[10]);
260 self.F(state, 11, rc[11]);
261 self.F(state, 12, rc[12]);
262 self.F(state, 13, rc[13]);
263 self.F(state, 14, rc[14]);
264 self.F(state, 15, rc[15]);
265 }
266}
267
268impl State {
269 fn new() -> Self {
270 const IV: [u8; 64] = [
271 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb, 0x67, 0xae, 0x85, 0x84, 0xca,
272 0xa7, 0x3b, 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, 0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a,
273 0x5f, 0x1d, 0x36, 0xf1, 0x51, 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05,
274 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f, 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b,
275 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79,
276 ];
277 let mut t = [0u64; 8];
278 for (i, e) in t.iter_mut().enumerate() {
279 *e = load_be(&IV, i * 8)
280 }
281 State(t)
282 }
283
284 #[inline(always)]
285 fn add(&mut self, x: &State) {
286 let sx = &mut self.0;
287 let ex = &x.0;
288 sx[0] = sx[0].wrapping_add(ex[0]);
289 sx[1] = sx[1].wrapping_add(ex[1]);
290 sx[2] = sx[2].wrapping_add(ex[2]);
291 sx[3] = sx[3].wrapping_add(ex[3]);
292 sx[4] = sx[4].wrapping_add(ex[4]);
293 sx[5] = sx[5].wrapping_add(ex[5]);
294 sx[6] = sx[6].wrapping_add(ex[6]);
295 sx[7] = sx[7].wrapping_add(ex[7]);
296 }
297
298 fn store(&self, out: &mut [u8]) {
299 for (i, &e) in self.0.iter().enumerate() {
300 store_be(out, i * 8, e);
301 }
302 }
303
304 fn blocks(&mut self, mut input: &[u8]) -> usize {
305 let mut t = *self;
306 let mut inlen = input.len();
307 while inlen >= 128 {
308 let mut w = W::new(input);
309 w.G(&mut t, 0);
310 w.expand();
311 w.G(&mut t, 1);
312 w.expand();
313 w.G(&mut t, 2);
314 w.expand();
315 w.G(&mut t, 3);
316 w.expand();
317 w.G(&mut t, 4);
318 t.add(self);
319 self.0 = t.0;
320 input = &input[128..];
321 inlen -= 128;
322 }
323 inlen
324 }
325}
326
327#[derive(Copy, Clone)]
328pub struct Hash {
329 state: State,
330 w: [u8; 128],
331 r: usize,
332 len: usize,
333}
334
335impl Hash {
336 pub fn new() -> Hash {
337 Hash {
338 state: State::new(),
339 r: 0,
340 w: [0u8; 128],
341 len: 0,
342 }
343 }
344
345 fn _update<T: AsRef<[u8]>>(&mut self, input: T) {
346 let input = input.as_ref();
347 let mut n = input.len();
348 self.len += n;
349 let av = 128 - self.r;
350 let tc = ::core::cmp::min(n, av);
351 self.w[self.r..self.r + tc].copy_from_slice(&input[0..tc]);
352 self.r += tc;
353 n -= tc;
354 let pos = tc;
355 if self.r == 128 {
356 self.state.blocks(&self.w);
357 self.r = 0;
358 }
359 if self.r == 0 && n > 0 {
360 let rb = self.state.blocks(&input[pos..]);
361 if rb > 0 {
362 self.w[..rb].copy_from_slice(&input[pos + n - rb..]);
363 self.r = rb;
364 }
365 }
366 }
367
368 pub fn update<T: AsRef<[u8]>>(&mut self, input: T) {
370 self._update(input)
371 }
372
373 pub fn finalize(mut self) -> [u8; 64] {
375 let mut padded = [0u8; 256];
376 padded[..self.r].copy_from_slice(&self.w[..self.r]);
377 padded[self.r] = 0x80;
378 let r = if self.r < 112 { 128 } else { 256 };
379 let bits = self.len * 8;
380 for i in 0..8 {
381 padded[r - 8 + i] = (bits as u64 >> (56 - i * 8)) as u8;
382 }
383 self.state.blocks(&padded[..r]);
384 let mut out = [0u8; 64];
385 self.state.store(&mut out);
386 out
387 }
388
389 pub fn hash<T: AsRef<[u8]>>(input: T) -> [u8; 64] {
391 let mut h = Hash::new();
392 h.update(input);
393 h.finalize()
394 }
395
396 pub fn verify(self, expected: &[u8; 64]) -> bool {
398 let out = self.finalize();
399 verify(&out, expected)
400 }
401}
402
403impl Default for Hash {
404 fn default() -> Self {
405 Self::new()
406 }
407}
408
409#[cfg(feature = "traits09")]
410mod digest_trait {
411 use digest09::consts::{U128, U64};
412 use digest09::{BlockInput, FixedOutputDirty, Output, Reset, Update};
413
414 use super::Hash;
415
416 impl BlockInput for Hash {
417 type BlockSize = U128;
418 }
419
420 impl Update for Hash {
421 fn update(&mut self, input: impl AsRef<[u8]>) {
422 self._update(input);
423 }
424 }
425
426 impl FixedOutputDirty for Hash {
427 type OutputSize = U64;
428
429 fn finalize_into_dirty(&mut self, out: &mut Output<Self>) {
430 let h = self.finalize();
431 out.copy_from_slice(&h);
432 }
433 }
434
435 impl Reset for Hash {
436 fn reset(&mut self) {
437 *self = Self::new();
438 }
439 }
440}
441
442#[cfg(feature = "traits010")]
444pub type WrappedHash = digest010::core_api::CoreWrapper<Hash>;
445
446#[cfg(feature = "traits010")]
447mod digest_trait010 {
448 use core::fmt;
449
450 use digest010::{
451 block_buffer::Eager,
452 const_oid::{AssociatedOid, ObjectIdentifier},
453 consts::{U128, U64},
454 core_api::{
455 AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, FixedOutputCore,
456 OutputSizeUser, Reset, UpdateCore,
457 },
458 FixedOutput, FixedOutputReset, HashMarker, Output, Update,
459 };
460
461 use super::Hash;
462
463 impl AssociatedOid for Hash {
464 const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.3");
465 }
466
467 impl AlgorithmName for Hash {
468 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
469 f.write_str("Sha512")
470 }
471 }
472
473 impl HashMarker for Hash {}
474
475 impl BufferKindUser for Hash {
476 type BufferKind = Eager;
477 }
478
479 impl BlockSizeUser for Hash {
480 type BlockSize = U128;
481 }
482
483 impl OutputSizeUser for Hash {
484 type OutputSize = U64;
485 }
486
487 impl UpdateCore for Hash {
488 #[inline]
489 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
490 for block in blocks {
491 self._update(block);
492 }
493 }
494 }
495
496 impl Update for Hash {
497 #[inline]
498 fn update(&mut self, data: &[u8]) {
499 self._update(data);
500 }
501 }
502
503 impl FixedOutputCore for Hash {
504 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
505 self._update(buffer.get_data());
506 let h = self.finalize();
507 out.copy_from_slice(&h);
508 }
509 }
510
511 impl FixedOutput for Hash {
512 fn finalize_into(self, out: &mut Output<Self>) {
513 let h = self.finalize();
514 out.copy_from_slice(&h);
515 }
516 }
517
518 impl Reset for Hash {
519 fn reset(&mut self) {
520 *self = Self::new()
521 }
522 }
523
524 impl FixedOutputReset for Hash {
525 fn finalize_into_reset(&mut self, out: &mut Output<Self>) {
526 self.finalize_into(out);
527 self.reset();
528 }
529 }
530}
531
532#[cfg(feature = "traits011")]
533mod digest_trait011 {
534 use digest011::{
535 const_oid::{AssociatedOid, ObjectIdentifier},
536 consts::U64,
537 FixedOutput, FixedOutputReset, HashMarker, Output, OutputSizeUser, Reset, Update,
538 };
539
540 use super::Hash;
541
542 impl AssociatedOid for Hash {
543 const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.3");
544 }
545
546 impl HashMarker for Hash {}
547
548 impl OutputSizeUser for Hash {
549 type OutputSize = U64;
550 }
551
552 impl Update for Hash {
553 #[inline]
554 fn update(&mut self, data: &[u8]) {
555 self._update(data);
556 }
557 }
558
559 impl FixedOutput for Hash {
560 fn finalize_into(self, out: &mut Output<Self>) {
561 let h = self.finalize();
562 out.copy_from_slice(&h);
563 }
564 }
565
566 impl Reset for Hash {
567 fn reset(&mut self) {
568 *self = Self::new()
569 }
570 }
571
572 impl FixedOutputReset for Hash {
573 fn finalize_into_reset(&mut self, out: &mut Output<Self>) {
574 let h = self.finalize();
575 out.copy_from_slice(&h);
576 self.reset();
577 }
578 }
579}
580
581pub struct HMAC {
582 ih: Hash,
583 padded: [u8; 128],
584}
585
586impl HMAC {
587 pub fn mac<T: AsRef<[u8]>, U: AsRef<[u8]>>(input: T, k: U) -> [u8; 64] {
589 let input = input.as_ref();
590 let k = k.as_ref();
591 let mut hk = [0u8; 64];
592 let k2 = if k.len() > 128 {
593 hk.copy_from_slice(&Hash::hash(k));
594 &hk
595 } else {
596 k
597 };
598 let mut ih = Hash::new();
599 let mut padded = [0x36; 128];
600 for (p, &k) in padded.iter_mut().zip(k2.iter()) {
601 *p ^= k;
602 }
603 ih.update(&padded[..]);
604 ih.update(input);
605
606 let mut oh = Hash::new();
607 padded = [0x5c; 128];
608 for (p, &k) in padded.iter_mut().zip(k2.iter()) {
609 *p ^= k;
610 }
611 oh.update(&padded[..]);
612 oh.update(&ih.finalize()[..]);
613 oh.finalize()
614 }
615
616 pub fn new(k: impl AsRef<[u8]>) -> HMAC {
618 let k = k.as_ref();
619 let mut hk = [0u8; 64];
620 let k2 = if k.len() > 128 {
621 hk.copy_from_slice(&Hash::hash(k));
622 &hk
623 } else {
624 k
625 };
626 let mut padded = [0x36; 128];
627 for (p, &k) in padded.iter_mut().zip(k2.iter()) {
628 *p ^= k;
629 }
630 let mut ih = Hash::new();
631 ih.update(&padded[..]);
632 HMAC { ih, padded }
633 }
634
635 pub fn update(&mut self, input: impl AsRef<[u8]>) {
637 self.ih.update(input);
638 }
639
640 pub fn finalize(mut self) -> [u8; 64] {
642 for p in self.padded.iter_mut() {
643 *p ^= 0x6a;
644 }
645 let mut oh = Hash::new();
646 oh.update(&self.padded[..]);
647 oh.update(self.ih.finalize());
648 oh.finalize()
649 }
650
651 pub fn finalize_verify(self, expected: &[u8; 64]) -> bool {
653 let out = self.finalize();
654 verify(&out, expected)
655 }
656
657 pub fn verify<T: AsRef<[u8]>, U: AsRef<[u8]>>(input: T, k: U, expected: &[u8; 64]) -> bool {
659 let mac = Self::mac(input, k);
660 verify(&mac, expected)
661 }
662}
663
664pub struct HKDF;
682
683impl HKDF {
684 pub fn extract(salt: impl AsRef<[u8]>, ikm: impl AsRef<[u8]>) -> [u8; 64] {
697 HMAC::mac(ikm, salt)
698 }
699
700 pub fn expand(out: &mut [u8], prk: impl AsRef<[u8]>, info: impl AsRef<[u8]>) {
714 let info = info.as_ref();
715 let mut counter: u8 = 1;
716 assert!(out.len() < 0xff * 64);
717 let mut i: usize = 0;
718 while i < out.len() {
719 let mut hmac = HMAC::new(&prk);
720 if i != 0 {
721 hmac.update(&out[i - 64..][..64]);
722 }
723 hmac.update(info);
724 hmac.update([counter]);
725 let left = core::cmp::min(64, out.len() - i);
726 out[i..][..left].copy_from_slice(&hmac.finalize()[..left]);
727 counter += 1;
728 i += 64;
729 }
730 }
731}
732
733#[cfg(feature = "sha384")]
734pub mod sha384 {
735 use super::load_be;
736
737 fn new_state() -> super::State {
738 const IV: [u8; 64] = [
739 0xcb, 0xbb, 0x9d, 0x5d, 0xc1, 0x05, 0x9e, 0xd8, 0x62, 0x9a, 0x29, 0x2a, 0x36, 0x7c,
740 0xd5, 0x07, 0x91, 0x59, 0x01, 0x5a, 0x30, 0x70, 0xdd, 0x17, 0x15, 0x2f, 0xec, 0xd8,
741 0xf7, 0x0e, 0x59, 0x39, 0x67, 0x33, 0x26, 0x67, 0xff, 0xc0, 0x0b, 0x31, 0x8e, 0xb4,
742 0x4a, 0x87, 0x68, 0x58, 0x15, 0x11, 0xdb, 0x0c, 0x2e, 0x0d, 0x64, 0xf9, 0x8f, 0xa7,
743 0x47, 0xb5, 0x48, 0x1d, 0xbe, 0xfa, 0x4f, 0xa4,
744 ];
745 let mut t = [0u64; 8];
746 for (i, e) in t.iter_mut().enumerate() {
747 *e = load_be(&IV, i * 8)
748 }
749 super::State(t)
750 }
751
752 #[derive(Copy, Clone)]
753 pub struct Hash(super::Hash);
754
755 impl Hash {
756 pub fn new() -> Hash {
757 Hash(super::Hash {
758 state: new_state(),
759 r: 0,
760 w: [0u8; 128],
761 len: 0,
762 })
763 }
764
765 fn _update<T: AsRef<[u8]>>(&mut self, input: T) {
766 self.0.update(input)
767 }
768
769 pub fn update<T: AsRef<[u8]>>(&mut self, input: T) {
771 self._update(input)
772 }
773
774 pub fn finalize(self) -> [u8; 48] {
776 let mut h = [0u8; 48];
777 h.copy_from_slice(&self.0.finalize()[..48]);
778 h
779 }
780
781 pub fn hash<T: AsRef<[u8]>>(input: T) -> [u8; 48] {
783 let mut h = Hash::new();
784 h.update(input);
785 h.finalize()
786 }
787 }
788
789 impl Default for Hash {
790 fn default() -> Self {
791 Self::new()
792 }
793 }
794
795 pub struct HMAC {
796 ih: Hash,
797 padded: [u8; 128],
798 }
799
800 impl HMAC {
801 pub fn mac<T: AsRef<[u8]>, U: AsRef<[u8]>>(input: T, k: U) -> [u8; 48] {
803 let mut hmac = Self::new(k);
804 hmac.update(input);
805 hmac.finalize()
806 }
807
808 pub fn new(k: impl AsRef<[u8]>) -> HMAC {
810 let k = k.as_ref();
811 let mut hk = [0u8; 48];
812 let k2 = if k.len() > 128 {
813 hk.copy_from_slice(&Hash::hash(k));
814 &hk[..]
815 } else {
816 k
817 };
818 let mut padded = [0x36; 128];
819 for (p, &k) in padded.iter_mut().zip(k2.iter()) {
820 *p ^= k;
821 }
822 let mut ih = Hash::new();
823 ih.update(&padded[..]);
824 HMAC { ih, padded }
825 }
826
827 pub fn update(&mut self, input: impl AsRef<[u8]>) {
829 self.ih.update(input);
830 }
831
832 pub fn finalize(mut self) -> [u8; 48] {
834 for p in self.padded.iter_mut() {
835 *p ^= 0x6a;
836 }
837 let mut oh = Hash::new();
838 oh.update(&self.padded[..]);
839 oh.update(&self.ih.finalize()[..]);
840 oh.finalize()
841 }
842
843 pub fn finalize_verify(self, expected: &[u8; 48]) -> bool {
845 let out = self.finalize();
846 super::verify(&out, expected)
847 }
848
849 pub fn verify<T: AsRef<[u8]>, U: AsRef<[u8]>>(input: T, k: U, expected: &[u8; 48]) -> bool {
851 let mac = Self::mac(input, k);
852 super::verify(&mac, expected)
853 }
854 }
855
856 pub struct HKDF;
874
875 impl HKDF {
876 pub fn extract(salt: impl AsRef<[u8]>, ikm: impl AsRef<[u8]>) -> [u8; 48] {
889 HMAC::mac(ikm, salt)
890 }
891
892 pub fn expand(out: &mut [u8], prk: impl AsRef<[u8]>, info: impl AsRef<[u8]>) {
906 let info = info.as_ref();
907 let mut counter: u8 = 1;
908 assert!(out.len() < 0xff * 48);
909 let mut i: usize = 0;
910 while i < out.len() {
911 let mut hmac = HMAC::new(&prk);
912 if i != 0 {
913 hmac.update(&out[i - 48..][..48]);
914 }
915 hmac.update(info);
916 hmac.update([counter]);
917 let left = core::cmp::min(48, out.len() - i);
918 out[i..][..left].copy_from_slice(&hmac.finalize()[..left]);
919 counter += 1;
920 i += 48;
921 }
922 }
923 }
924
925 #[cfg(feature = "traits09")]
926 mod digest_trait09 {
927 use digest09::consts::{U128, U48};
928 use digest09::{BlockInput, FixedOutputDirty, Output, Reset, Update};
929
930 use super::Hash;
931
932 impl BlockInput for Hash {
933 type BlockSize = U128;
934 }
935
936 impl Update for Hash {
937 fn update(&mut self, input: impl AsRef<[u8]>) {
938 self._update(input);
939 }
940 }
941
942 impl FixedOutputDirty for Hash {
943 type OutputSize = U48;
944
945 fn finalize_into_dirty(&mut self, out: &mut Output<Self>) {
946 let h = self.finalize();
947 out.copy_from_slice(&h);
948 }
949 }
950
951 impl Reset for Hash {
952 fn reset(&mut self) {
953 *self = Self::new();
954 }
955 }
956 }
957
958 #[cfg(feature = "traits010")]
960 pub type WrappedHash = digest010::core_api::CoreWrapper<Hash>;
961
962 #[cfg(feature = "traits010")]
963 mod digest_trait010 {
964 use core::fmt;
965
966 use digest010::{
967 block_buffer::Eager,
968 const_oid::{AssociatedOid, ObjectIdentifier},
969 consts::{U128, U48},
970 core_api::{
971 AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, FixedOutputCore,
972 OutputSizeUser, Reset, UpdateCore,
973 },
974 FixedOutput, FixedOutputReset, HashMarker, Output, Update,
975 };
976
977 use super::Hash;
978
979 impl AssociatedOid for Hash {
980 const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.2");
981 }
982
983 impl AlgorithmName for Hash {
984 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
985 f.write_str("Sha384")
986 }
987 }
988
989 impl HashMarker for Hash {}
990
991 impl BufferKindUser for Hash {
992 type BufferKind = Eager;
993 }
994
995 impl BlockSizeUser for Hash {
996 type BlockSize = U128;
997 }
998
999 impl OutputSizeUser for Hash {
1000 type OutputSize = U48;
1001 }
1002
1003 impl UpdateCore for Hash {
1004 #[inline]
1005 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
1006 for block in blocks {
1007 self._update(block);
1008 }
1009 }
1010 }
1011
1012 impl Update for Hash {
1013 #[inline]
1014 fn update(&mut self, data: &[u8]) {
1015 self._update(data);
1016 }
1017 }
1018
1019 impl FixedOutputCore for Hash {
1020 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
1021 self._update(buffer.get_data());
1022 let h = self.finalize();
1023 out.copy_from_slice(&h);
1024 }
1025 }
1026
1027 impl FixedOutput for Hash {
1028 fn finalize_into(self, out: &mut Output<Self>) {
1029 let h = self.finalize();
1030 out.copy_from_slice(&h);
1031 }
1032 }
1033
1034 impl Reset for Hash {
1035 fn reset(&mut self) {
1036 *self = Self::new()
1037 }
1038 }
1039
1040 impl FixedOutputReset for Hash {
1041 fn finalize_into_reset(&mut self, out: &mut Output<Self>) {
1042 self.finalize_into(out);
1043 self.reset();
1044 }
1045 }
1046 }
1047
1048 #[cfg(feature = "traits011")]
1049 mod digest_trait011 {
1050 use digest011::{
1051 const_oid::{AssociatedOid, ObjectIdentifier},
1052 consts::U48,
1053 FixedOutput, FixedOutputReset, HashMarker, Output, OutputSizeUser, Reset, Update,
1054 };
1055
1056 use super::Hash;
1057
1058 impl AssociatedOid for Hash {
1059 const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.2");
1060 }
1061
1062 impl HashMarker for Hash {}
1063
1064 impl OutputSizeUser for Hash {
1065 type OutputSize = U48;
1066 }
1067
1068 impl Update for Hash {
1069 #[inline]
1070 fn update(&mut self, data: &[u8]) {
1071 self._update(data);
1072 }
1073 }
1074
1075 impl FixedOutput for Hash {
1076 fn finalize_into(self, out: &mut Output<Self>) {
1077 let h = self.finalize();
1078 out.copy_from_slice(&h);
1079 }
1080 }
1081
1082 impl Reset for Hash {
1083 fn reset(&mut self) {
1084 *self = Self::new()
1085 }
1086 }
1087
1088 impl FixedOutputReset for Hash {
1089 fn finalize_into_reset(&mut self, out: &mut Output<Self>) {
1090 let h = self.finalize();
1091 out.copy_from_slice(&h);
1092 self.reset();
1093 }
1094 }
1095 }
1096}
1097
1098#[test]
1099fn main() {
1100 let h = HMAC::mac([], [0u8; 32]);
1101 let expected: [u8; 64] = [
1102 185, 54, 206, 232, 108, 159, 135, 170, 93, 60, 111, 46, 132, 203, 90, 66, 57, 165, 254, 80,
1103 72, 10, 110, 198, 107, 112, 171, 91, 31, 74, 198, 115, 12, 108, 81, 84, 33, 179, 39, 236,
1104 29, 105, 64, 46, 83, 223, 180, 154, 215, 56, 30, 176, 103, 179, 56, 253, 123, 12, 178, 34,
1105 71, 34, 93, 71,
1106 ];
1107 assert_eq!(h.to_vec(), expected.to_vec());
1108 assert!(HMAC::verify([], [0u8; 32], &expected));
1109
1110 let h = HMAC::mac([42u8; 69], []);
1111 let expected: [u8; 64] = [
1112 56, 224, 189, 205, 65, 104, 107, 85, 241, 188, 253, 35, 238, 174, 69, 191, 206, 183, 205,
1113 71, 196, 180, 56, 122, 106, 55, 136, 7, 208, 183, 99, 67, 229, 213, 255, 154, 107, 136, 11,
1114 154, 11, 187, 75, 214, 172, 117, 14, 248, 189, 48, 193, 62, 37, 208, 159, 227, 115, 59, 54,
1115 91, 143, 143, 254, 220,
1116 ];
1117 assert_eq!(h.to_vec(), expected.to_vec());
1118 assert!(HMAC::verify([42u8; 69], [], &expected));
1119
1120 let h = HMAC::mac([69u8; 250], [42u8; 50]);
1121 let expected: [u8; 64] = [
1122 122, 111, 187, 241, 74, 194, 22, 106, 95, 206, 80, 215, 75, 207, 11, 78, 37, 94, 125, 110,
1123 125, 42, 254, 103, 224, 21, 112, 247, 233, 229, 36, 200, 58, 238, 211, 156, 121, 231, 15,
1124 202, 128, 90, 126, 179, 188, 37, 194, 106, 223, 218, 45, 211, 149, 91, 131, 226, 117, 184,
1125 175, 85, 224, 197, 82, 175,
1126 ];
1127 assert_eq!(h.to_vec(), expected.to_vec());
1128 assert!(HMAC::verify([69u8; 250], [42u8; 50], &expected));
1129
1130 let h = HMAC::mac(b"Hi There", [0x0b; 20]);
1131 let expected: [u8; 64] = [
1132 135, 170, 124, 222, 165, 239, 97, 157, 79, 240, 180, 36, 26, 29, 108, 176, 35, 121, 244,
1133 226, 206, 78, 194, 120, 122, 208, 179, 5, 69, 225, 124, 222, 218, 168, 51, 183, 214, 184,
1134 167, 2, 3, 139, 39, 78, 174, 163, 244, 228, 190, 157, 145, 78, 235, 97, 241, 112, 46, 105,
1135 108, 32, 58, 18, 104, 84,
1136 ];
1137 assert_eq!(h.to_vec(), expected.to_vec());
1138 assert!(HMAC::verify(b"Hi There", [0x0b; 20], &expected));
1139
1140 let incorrect: [u8; 64] = [0u8; 64];
1142 assert!(!HMAC::verify(b"Hi There", [0x0b; 20], &incorrect));
1143}
1144
1145#[cfg(feature = "sha384")]
1146#[test]
1147fn sha384() {
1148 let h = sha384::HMAC::mac(b"Hi There", [0x0b; 20]);
1149 let expected: [u8; 48] = [
1150 175, 208, 57, 68, 216, 72, 149, 98, 107, 8, 37, 244, 171, 70, 144, 127, 21, 249, 218, 219,
1151 228, 16, 30, 198, 130, 170, 3, 76, 124, 235, 197, 156, 250, 234, 158, 169, 7, 110, 222,
1152 127, 74, 241, 82, 232, 178, 250, 156, 182,
1153 ];
1154 assert_eq!(h.to_vec(), expected.to_vec());
1155 assert!(sha384::HMAC::verify(b"Hi There", [0x0b; 20], &expected));
1156
1157 let incorrect: [u8; 48] = [0u8; 48];
1159 assert!(!sha384::HMAC::verify(b"Hi There", [0x0b; 20], &incorrect));
1160}
1161
1162#[cfg(feature = "sha384")]
1163#[test]
1164fn hkdf_sha384() {
1165 let ikm = [0x0bu8; 22];
1167 let salt: [u8; 13] = [
1168 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1169 ];
1170 let info: [u8; 10] = [0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9];
1171
1172 let prk = sha384::HKDF::extract(&salt, &ikm);
1173 let mut okm = [0u8; 42];
1174 sha384::HKDF::expand(&mut okm, &prk, &info);
1175
1176 let expected_okm: [u8; 42] = [
1178 0x9b, 0x50, 0x97, 0xa8, 0x60, 0x38, 0xb8, 0x05, 0x30, 0x90, 0x76, 0xa4, 0x4b, 0x3a, 0x9f,
1179 0x38, 0x06, 0x3e, 0x25, 0xb5, 0x16, 0xdc, 0xbf, 0x36, 0x9f, 0x39, 0x4c, 0xfa, 0xb4, 0x36,
1180 0x85, 0xf7, 0x48, 0xb6, 0x45, 0x77, 0x63, 0xe4, 0xf0, 0x20, 0x4f, 0xc5,
1181 ];
1182 assert_eq!(okm, expected_okm);
1183
1184 let ikm = [0x0bu8; 22];
1186 let prk = sha384::HKDF::extract([], &ikm);
1187 let mut okm = [0u8; 42];
1188 sha384::HKDF::expand(&mut okm, &prk, []);
1189
1190 let expected_okm: [u8; 42] = [
1191 0xc8, 0xc9, 0x6e, 0x71, 0x0f, 0x89, 0xb0, 0xd7, 0x99, 0x0b, 0xca, 0x68, 0xbc, 0xde, 0xc8,
1192 0xcf, 0x85, 0x40, 0x62, 0xe5, 0x4c, 0x73, 0xa7, 0xab, 0xc7, 0x43, 0xfa, 0xde, 0x9b, 0x24,
1193 0x2d, 0xaa, 0xcc, 0x1c, 0xea, 0x56, 0x70, 0x41, 0x5b, 0x52, 0x84, 0x9c,
1194 ];
1195 assert_eq!(okm, expected_okm);
1196}
1197
1198#[cfg(feature = "traits011")]
1199#[test]
1200fn digest011_sha512() {
1201 use digest011::Digest;
1202
1203 let mut hasher = Hash::new();
1204 hasher.update(b"hello");
1205 hasher.update(b" world");
1206 let result = hasher.finalize();
1207
1208 let expected = Hash::digest(b"hello world");
1209 assert_eq!(result.as_slice(), expected.as_slice());
1210}
1211
1212#[cfg(all(feature = "traits011", feature = "sha384"))]
1213#[test]
1214fn digest011_sha384() {
1215 use digest011::Digest;
1216
1217 let mut hasher = sha384::Hash::new();
1218 hasher.update(b"hello");
1219 hasher.update(b" world");
1220 let result = hasher.finalize();
1221
1222 let expected = sha384::Hash::digest(b"hello world");
1223 assert_eq!(result.as_slice(), expected.as_slice());
1224}
1225
1226#[test]
1227fn hkdf() {
1228 let ikm = [0x0bu8; 22];
1230 let salt: [u8; 13] = [
1231 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
1232 ];
1233 let info: [u8; 10] = [0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9];
1234 let expected_okm: [u8; 42] = [
1235 0x83, 0x23, 0x90, 0x08, 0x6c, 0xda, 0x71, 0xfb, 0x47, 0x62, 0x5b, 0xb5, 0xce, 0xb1, 0x68,
1236 0xe4, 0xc8, 0xe2, 0x6a, 0x1a, 0x16, 0xed, 0x34, 0xd9, 0xfc, 0x7f, 0xe9, 0x2c, 0x14, 0x81,
1237 0x57, 0x93, 0x38, 0xda, 0x36, 0x2c, 0xb8, 0xd9, 0xf9, 0x25, 0xd7, 0xcb,
1238 ];
1239
1240 let prk = HKDF::extract(&salt, &ikm);
1241 let mut okm = [0u8; 42];
1242 HKDF::expand(&mut okm, &prk, &info);
1243 assert_eq!(okm, expected_okm);
1244
1245 let ikm = [0x0bu8; 22];
1247 let expected_okm: [u8; 42] = [
1248 0xf5, 0xfa, 0x02, 0xb1, 0x82, 0x98, 0xa7, 0x2a, 0x8c, 0x23, 0x89, 0x8a, 0x87, 0x03, 0x47,
1249 0x2c, 0x6e, 0xb1, 0x79, 0xdc, 0x20, 0x4c, 0x03, 0x42, 0x5c, 0x97, 0x0e, 0x3b, 0x16, 0x4b,
1250 0xf9, 0x0f, 0xff, 0x22, 0xd0, 0x48, 0x36, 0xd0, 0xe2, 0x34, 0x3b, 0xac,
1251 ];
1252
1253 let prk = HKDF::extract([], &ikm);
1254 let mut okm = [0u8; 42];
1255 HKDF::expand(&mut okm, &prk, []);
1256 assert_eq!(okm, expected_okm);
1257}
1258
1259#[test]
1260fn hmac_streaming() {
1261 let key = b"secret key";
1263 let message = b"Hello, World!";
1264
1265 let oneshot = HMAC::mac(message, key);
1266
1267 let mut streaming = HMAC::new(key);
1268 streaming.update(b"Hello, ");
1269 streaming.update(b"World!");
1270 let result = streaming.finalize();
1271
1272 assert_eq!(oneshot, result);
1273
1274 let mut streaming = HMAC::new(key);
1276 streaming.update(message);
1277 assert!(streaming.finalize_verify(&oneshot));
1278}
1279
1280#[cfg(feature = "sha384")]
1281#[test]
1282fn hmac_sha384_streaming() {
1283 let key = b"secret key";
1284 let message = b"Hello, World!";
1285
1286 let oneshot = sha384::HMAC::mac(message, key);
1287
1288 let mut streaming = sha384::HMAC::new(key);
1289 streaming.update(b"Hello, ");
1290 streaming.update(b"World!");
1291 let result = streaming.finalize();
1292
1293 assert_eq!(oneshot, result);
1294
1295 let mut streaming = sha384::HMAC::new(key);
1297 streaming.update(message);
1298 assert!(streaming.finalize_verify(&oneshot));
1299}