1#![no_std]
2#![doc(
3 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
4 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
5 html_root_url = "https://docs.rs/bake-kdf/0.0.0"
6)]
7#![doc = include_str!("../README.md")]
8#![cfg_attr(docsrs, feature(doc_auto_cfg))]
9#![forbid(unsafe_code)]
10#![warn(missing_docs, rust_2018_idioms)]
11
12use belt_hash::digest::FixedOutput;
13use belt_hash::{belt_compress, BeltHash, Digest};
14
15#[inline]
21pub fn belt_keyexpand<const N: usize>(k: &[u8; N]) -> [u32; 8] {
22 let mut t = [0u32; 8];
23 for (src, dst) in k.chunks_exact(4).zip(t.iter_mut()) {
26 *dst = u32::from_le_bytes(src.try_into().unwrap());
27 }
28 match N {
29 16 => {
30 t[4] = t[0];
31 t[5] = t[1];
32 t[6] = t[2];
33 t[7] = t[3];
34 }
35 24 => {
36 t[6] = t[0] ^ t[1] ^ t[2];
37 t[7] = t[3] ^ t[4] ^ t[5];
38 }
39 32 => {}
40 _ => panic!("Invalid key size n={N}. Expected 16, 24, or 32."),
41 }
42 t
43}
44
45#[inline]
52pub fn belt_keyrep<const N: usize, const M: usize>(
53 x: &[u8; N],
54 d: &[u8; 12],
55 i: &[u8; 16],
56) -> [u8; M] {
57 let r: u32 = match (N, M) {
58 (16, 16) => 0xC8BA94B1,
59 (24, 16) => 0x12D6E35B,
60 (24, 24) => 0xFFC0B05C,
61 (32, 16) => 0x1ADC2BE1,
62 (32, 24) => 0x3876ABC1,
63 (32, 32) => 0x7B653CF3,
64 _ => panic!("belt-keyrep: invalid combination of N ({N}) and M ({M})"),
65 };
66
67 let s = belt_keyexpand(x);
68
69 let d = [
70 u32::from_le_bytes(d[..4].try_into().unwrap()),
71 u32::from_le_bytes(d[4..][..4].try_into().unwrap()),
72 u32::from_le_bytes(d[8..][..4].try_into().unwrap()),
73 ];
74
75 let i = [
76 u32::from_le_bytes(i[0..][..4].try_into().unwrap()),
77 u32::from_le_bytes(i[4..][..4].try_into().unwrap()),
78 u32::from_le_bytes(i[8..][..4].try_into().unwrap()),
79 u32::from_le_bytes(i[12..][..4].try_into().unwrap()),
80 ];
81
82 let (_, s) = belt_compress([r, d[0], d[1], d[2]], i, s);
83
84 let mut y = [0u8; M];
85 for (src, dst) in s.iter().zip(y.chunks_exact_mut(4)) {
86 dst.copy_from_slice(&src.to_le_bytes());
87 }
88 y
89}
90
91#[inline]
93pub fn bake_kdf(x: &[u8], s: &[u8], c: u128) -> [u8; 32] {
94 let mut hasher = BeltHash::default();
95 hasher.update(x);
96 hasher.update(s);
97 let y = hasher.finalize_fixed().0;
98
99 belt_keyrep(&y, &[0xFF; 12], &c.to_le_bytes())
100}