1 use core::hint::assert_unchecked;
2
3 use super::{large::INITIAL_ACCUMULATORS, *};
4
5 /// A buffer containing the secret bytes.
6 ///
7 /// # Safety
8 ///
9 /// Must always return a slice with the same number of elements.
10 pub unsafe trait FixedBuffer: AsRef<[u8]> {}
11
12 /// A mutable buffer to contain the secret bytes.
13 ///
14 /// # Safety
15 ///
16 /// Must always return a slice with the same number of elements. The
17 /// slice must always be the same as that returned from
18 /// [`AsRef::as_ref`][].
19 pub unsafe trait FixedMutBuffer: FixedBuffer + AsMut<[u8]> {}
20
21 // Safety: An array will never change size.
22 unsafe impl<const N: usize> FixedBuffer for [u8; N] {}
23
24 // Safety: An array will never change size.
25 unsafe impl<const N: usize> FixedMutBuffer for [u8; N] {}
26
27 // Safety: An array will never change size.
28 unsafe impl<const N: usize> FixedBuffer for &[u8; N] {}
29
30 // Safety: An array will never change size.
31 unsafe impl<const N: usize> FixedBuffer for &mut [u8; N] {}
32
33 // Safety: An array will never change size.
34 unsafe impl<const N: usize> FixedMutBuffer for &mut [u8; N] {}
35
36 const STRIPE_BYTES: usize = 64;
37 const BUFFERED_STRIPES: usize = 4;
38 const BUFFERED_BYTES: usize = STRIPE_BYTES * BUFFERED_STRIPES;
39 type Buffer = [u8; BUFFERED_BYTES];
40
41 // Ensure that a full buffer always implies we are in the 241+ byte case.
42 const _: () = assert!(BUFFERED_BYTES > CUTOFF);
43
44 /// Holds secret and temporary buffers that are ensured to be
45 /// appropriately sized.
46 #[derive(Clone)]
47 pub struct SecretBuffer<S> {
48 seed: u64,
49 secret: S,
50 buffer: Buffer,
51 }
52
53 impl<S> SecretBuffer<S> {
54 /// Returns the secret.
into_secret(self) -> S55 pub fn into_secret(self) -> S {
56 self.secret
57 }
58 }
59
60 impl<S> SecretBuffer<S>
61 where
62 S: FixedBuffer,
63 {
64 /// Takes the seed, secret, and buffer and performs no
65 /// modifications to them, only validating that the sizes are
66 /// appropriate.
new(seed: u64, secret: S) -> Result<Self, SecretTooShortError<S>>67 pub fn new(seed: u64, secret: S) -> Result<Self, SecretTooShortError<S>> {
68 match Secret::new(secret.as_ref()) {
69 Ok(_) => Ok(Self {
70 seed,
71 secret,
72 buffer: [0; BUFFERED_BYTES],
73 }),
74 Err(e) => Err(SecretTooShortError(e, secret)),
75 }
76 }
77
78 #[inline(always)]
79 #[cfg(test)]
is_valid(&self) -> bool80 fn is_valid(&self) -> bool {
81 let secret = self.secret.as_ref();
82
83 secret.len() >= SECRET_MINIMUM_LENGTH
84 }
85
86 #[inline]
n_stripes(&self) -> usize87 fn n_stripes(&self) -> usize {
88 Self::secret(&self.secret).n_stripes()
89 }
90
91 #[inline]
parts(&self) -> (u64, &Secret, &Buffer)92 fn parts(&self) -> (u64, &Secret, &Buffer) {
93 (self.seed, Self::secret(&self.secret), &self.buffer)
94 }
95
96 #[inline]
parts_mut(&mut self) -> (u64, &Secret, &mut Buffer)97 fn parts_mut(&mut self) -> (u64, &Secret, &mut Buffer) {
98 (self.seed, Self::secret(&self.secret), &mut self.buffer)
99 }
100
secret(secret: &S) -> &Secret101 fn secret(secret: &S) -> &Secret {
102 let secret = secret.as_ref();
103 // Safety: We established the length at construction and the
104 // length is not allowed to change.
105 unsafe { Secret::new_unchecked(secret) }
106 }
107 }
108
109 impl<S> SecretBuffer<S>
110 where
111 S: FixedMutBuffer,
112 {
113 /// Fills the secret buffer with a secret derived from the seed
114 /// and the default secret. The secret must be exactly
115 /// [`DEFAULT_SECRET_LENGTH`][] bytes long.
with_seed(seed: u64, mut secret: S) -> Result<Self, SecretWithSeedError<S>>116 pub fn with_seed(seed: u64, mut secret: S) -> Result<Self, SecretWithSeedError<S>> {
117 match <&mut DefaultSecret>::try_from(secret.as_mut()) {
118 Ok(secret_slice) => {
119 *secret_slice = DEFAULT_SECRET_RAW;
120 derive_secret(seed, secret_slice);
121
122 Ok(Self {
123 seed,
124 secret,
125 buffer: [0; BUFFERED_BYTES],
126 })
127 }
128 Err(_) => Err(SecretWithSeedError(secret)),
129 }
130 }
131 }
132
133 impl SecretBuffer<&'static [u8; DEFAULT_SECRET_LENGTH]> {
134 /// Use the default seed and secret values while allocating nothing.
135 #[inline]
default() -> Self136 pub const fn default() -> Self {
137 SecretBuffer {
138 seed: DEFAULT_SEED,
139 secret: &DEFAULT_SECRET_RAW,
140 buffer: [0; BUFFERED_BYTES],
141 }
142 }
143 }
144
145 #[derive(Clone)]
146 pub struct RawHasherCore<S> {
147 secret_buffer: SecretBuffer<S>,
148 buffer_usage: usize,
149 stripe_accumulator: StripeAccumulator,
150 total_bytes: usize,
151 }
152
153 impl<S> RawHasherCore<S> {
new(secret_buffer: SecretBuffer<S>) -> Self154 pub fn new(secret_buffer: SecretBuffer<S>) -> Self {
155 Self {
156 secret_buffer,
157 buffer_usage: 0,
158 stripe_accumulator: StripeAccumulator::new(),
159 total_bytes: 0,
160 }
161 }
162
into_secret(self) -> S163 pub fn into_secret(self) -> S {
164 self.secret_buffer.into_secret()
165 }
166 }
167
168 impl<S> RawHasherCore<S>
169 where
170 S: FixedBuffer,
171 {
172 #[inline]
write(&mut self, input: &[u8])173 pub fn write(&mut self, input: &[u8]) {
174 let this = self;
175 dispatch! {
176 fn write_impl<S>(this: &mut RawHasherCore<S>, input: &[u8])
177 [S: FixedBuffer]
178 }
179 }
180
181 #[inline]
finish<F>(&self, finalize: F) -> F::Output where F: Finalize,182 pub fn finish<F>(&self, finalize: F) -> F::Output
183 where
184 F: Finalize,
185 {
186 let this = self;
187 dispatch! {
188 fn finish_impl<S, F>(this: &RawHasherCore<S>, finalize: F) -> F::Output
189 [S: FixedBuffer, F: Finalize]
190 }
191 }
192 }
193
194 #[inline(always)]
write_impl<S>(vector: impl Vector, this: &mut RawHasherCore<S>, mut input: &[u8]) where S: FixedBuffer,195 fn write_impl<S>(vector: impl Vector, this: &mut RawHasherCore<S>, mut input: &[u8])
196 where
197 S: FixedBuffer,
198 {
199 if input.is_empty() {
200 return;
201 }
202
203 let RawHasherCore {
204 secret_buffer,
205 buffer_usage,
206 stripe_accumulator,
207 total_bytes,
208 ..
209 } = this;
210
211 let n_stripes = secret_buffer.n_stripes();
212 let (_, secret, buffer) = secret_buffer.parts_mut();
213
214 *total_bytes += input.len();
215
216 // Safety: This is an invariant of the buffer.
217 unsafe {
218 debug_assert!(*buffer_usage <= buffer.len());
219 assert_unchecked(*buffer_usage <= buffer.len())
220 };
221
222 // We have some previous data saved; try to fill it up and process it first
223 if !buffer.is_empty() {
224 let remaining = &mut buffer[*buffer_usage..];
225 let n_to_copy = usize::min(remaining.len(), input.len());
226
227 let (remaining_head, remaining_tail) = remaining.split_at_mut(n_to_copy);
228 let (input_head, input_tail) = input.split_at(n_to_copy);
229
230 remaining_head.copy_from_slice(input_head);
231 *buffer_usage += n_to_copy;
232
233 input = input_tail;
234
235 // We did not fill up the buffer
236 if !remaining_tail.is_empty() {
237 return;
238 }
239
240 // We don't know this isn't the last of the data
241 if input.is_empty() {
242 return;
243 }
244
245 let (stripes, _) = buffer.bp_as_chunks();
246 for stripe in stripes {
247 stripe_accumulator.process_stripe(vector, stripe, n_stripes, secret);
248 }
249 *buffer_usage = 0;
250 }
251
252 debug_assert!(*buffer_usage == 0);
253
254 // Process as much of the input data in-place as possible,
255 // while leaving at least one full stripe for the
256 // finalization.
257 if let Some(len) = input.len().checked_sub(STRIPE_BYTES) {
258 let full_block_point = (len / STRIPE_BYTES) * STRIPE_BYTES;
259 // Safety: We know that `full_block_point` must be less than
260 // `input.len()` as we subtracted and then integer-divided
261 // (which rounds down) and then multiplied back. That's not
262 // evident to the compiler and `split_at` results in a
263 // potential panic.
264 //
265 // https://github.com/llvm/llvm-project/issues/104827
266 let (stripes, remainder) = unsafe { input.split_at_unchecked(full_block_point) };
267 let (stripes, _) = stripes.bp_as_chunks();
268
269 for stripe in stripes {
270 stripe_accumulator.process_stripe(vector, stripe, n_stripes, secret)
271 }
272 input = remainder;
273 }
274
275 // Any remaining data has to be less than the buffer, and the
276 // buffer is empty so just fill up the buffer.
277 debug_assert!(*buffer_usage == 0);
278 debug_assert!(!input.is_empty());
279
280 // Safety: We have parsed all the full blocks of input except one
281 // and potentially a full block minus one byte. That amount of
282 // data must be less than the buffer.
283 let buffer_head = unsafe {
284 debug_assert!(input.len() < 2 * STRIPE_BYTES);
285 debug_assert!(2 * STRIPE_BYTES < buffer.len());
286 buffer.get_unchecked_mut(..input.len())
287 };
288
289 buffer_head.copy_from_slice(input);
290 *buffer_usage = input.len();
291 }
292
293 #[inline(always)]
finish_impl<S, F>(vector: impl Vector, this: &RawHasherCore<S>, finalize: F) -> F::Output where S: FixedBuffer, F: Finalize,294 fn finish_impl<S, F>(vector: impl Vector, this: &RawHasherCore<S>, finalize: F) -> F::Output
295 where
296 S: FixedBuffer,
297 F: Finalize,
298 {
299 let RawHasherCore {
300 ref secret_buffer,
301 buffer_usage,
302 mut stripe_accumulator,
303 total_bytes,
304 } = *this;
305
306 let n_stripes = secret_buffer.n_stripes();
307 let (seed, secret, buffer) = secret_buffer.parts();
308
309 // Safety: This is an invariant of the buffer.
310 unsafe {
311 debug_assert!(buffer_usage <= buffer.len());
312 assert_unchecked(buffer_usage <= buffer.len())
313 };
314
315 if total_bytes > CUTOFF {
316 let input = &buffer[..buffer_usage];
317
318 // Ingest final stripes
319 let (stripes, remainder) = stripes_with_tail(input);
320 for stripe in stripes {
321 stripe_accumulator.process_stripe(vector, stripe, n_stripes, secret);
322 }
323
324 let mut temp = [0; 64];
325
326 let last_stripe = match input.last_chunk() {
327 Some(chunk) => chunk,
328 None => {
329 let n_to_reuse = 64 - input.len();
330 let to_reuse = buffer.len() - n_to_reuse;
331
332 let (temp_head, temp_tail) = temp.split_at_mut(n_to_reuse);
333 temp_head.copy_from_slice(&buffer[to_reuse..]);
334 temp_tail.copy_from_slice(input);
335
336 &temp
337 }
338 };
339
340 finalize.large(
341 vector,
342 stripe_accumulator.accumulator,
343 remainder,
344 last_stripe,
345 secret,
346 total_bytes,
347 )
348 } else {
349 finalize.small(DEFAULT_SECRET, seed, &buffer[..total_bytes])
350 }
351 }
352
353 pub trait Finalize {
354 type Output;
355
small(&self, secret: &Secret, seed: u64, input: &[u8]) -> Self::Output356 fn small(&self, secret: &Secret, seed: u64, input: &[u8]) -> Self::Output;
357
large( &self, vector: impl Vector, acc: [u64; 8], last_block: &[u8], last_stripe: &[u8; 64], secret: &Secret, len: usize, ) -> Self::Output358 fn large(
359 &self,
360 vector: impl Vector,
361 acc: [u64; 8],
362 last_block: &[u8],
363 last_stripe: &[u8; 64],
364 secret: &Secret,
365 len: usize,
366 ) -> Self::Output;
367 }
368
369 #[cfg(feature = "alloc")]
370 #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
371 pub mod with_alloc {
372 use ::alloc::boxed::Box;
373
374 use super::*;
375
376 // Safety: A plain slice will never change size.
377 unsafe impl FixedBuffer for Box<[u8]> {}
378
379 // Safety: A plain slice will never change size.
380 unsafe impl FixedMutBuffer for Box<[u8]> {}
381
382 type AllocSecretBuffer = SecretBuffer<Box<[u8]>>;
383
384 impl AllocSecretBuffer {
385 /// Allocates the secret and temporary buffers and fills them
386 /// with the default seed and secret values.
allocate_default() -> Self387 pub fn allocate_default() -> Self {
388 Self {
389 seed: DEFAULT_SEED,
390 secret: DEFAULT_SECRET_RAW.to_vec().into(),
391 buffer: [0; BUFFERED_BYTES],
392 }
393 }
394
395 /// Allocates the secret and temporary buffers and uses the
396 /// provided seed to construct the secret value.
allocate_with_seed(seed: u64) -> Self397 pub fn allocate_with_seed(seed: u64) -> Self {
398 let mut secret = DEFAULT_SECRET_RAW;
399 derive_secret(seed, &mut secret);
400
401 Self {
402 seed,
403 secret: secret.to_vec().into(),
404 buffer: [0; BUFFERED_BYTES],
405 }
406 }
407
408 /// Allocates the temporary buffer and uses the provided seed
409 /// and secret buffer.
allocate_with_seed_and_secret( seed: u64, secret: impl Into<Box<[u8]>>, ) -> Result<Self, SecretTooShortError<Box<[u8]>>>410 pub fn allocate_with_seed_and_secret(
411 seed: u64,
412 secret: impl Into<Box<[u8]>>,
413 ) -> Result<Self, SecretTooShortError<Box<[u8]>>> {
414 Self::new(seed, secret.into())
415 }
416 }
417
418 pub type AllocRawHasher = RawHasherCore<Box<[u8]>>;
419
420 impl AllocRawHasher {
allocate_default() -> Self421 pub fn allocate_default() -> Self {
422 Self::new(SecretBuffer::allocate_default())
423 }
424
allocate_with_seed(seed: u64) -> Self425 pub fn allocate_with_seed(seed: u64) -> Self {
426 Self::new(SecretBuffer::allocate_with_seed(seed))
427 }
428
allocate_with_seed_and_secret( seed: u64, secret: impl Into<Box<[u8]>>, ) -> Result<Self, SecretTooShortError<Box<[u8]>>>429 pub fn allocate_with_seed_and_secret(
430 seed: u64,
431 secret: impl Into<Box<[u8]>>,
432 ) -> Result<Self, SecretTooShortError<Box<[u8]>>> {
433 SecretBuffer::allocate_with_seed_and_secret(seed, secret).map(Self::new)
434 }
435 }
436 }
437
438 #[cfg(feature = "alloc")]
439 pub use with_alloc::AllocRawHasher;
440
441 /// Tracks which stripe we are currently on to know which part of the
442 /// secret we should be using.
443 #[derive(Copy, Clone)]
444 pub struct StripeAccumulator {
445 pub accumulator: [u64; 8],
446 current_stripe: usize,
447 }
448
449 impl StripeAccumulator {
new() -> Self450 pub fn new() -> Self {
451 Self {
452 accumulator: INITIAL_ACCUMULATORS,
453 current_stripe: 0,
454 }
455 }
456
457 #[inline]
process_stripe( &mut self, vector: impl Vector, stripe: &[u8; 64], n_stripes: usize, secret: &Secret, )458 pub fn process_stripe(
459 &mut self,
460 vector: impl Vector,
461 stripe: &[u8; 64],
462 n_stripes: usize,
463 secret: &Secret,
464 ) {
465 let Self {
466 accumulator,
467 current_stripe,
468 ..
469 } = self;
470
471 // For each stripe
472
473 // Safety: The number of stripes is determined by the
474 // block size, which is determined by the secret size.
475 let secret_stripe = unsafe { secret.stripe(*current_stripe) };
476 vector.accumulate(accumulator, stripe, secret_stripe);
477
478 *current_stripe += 1;
479
480 // After a full block's worth
481 if *current_stripe == n_stripes {
482 let secret_end = secret.last_stripe();
483 vector.round_scramble(accumulator, secret_end);
484
485 *current_stripe = 0;
486 }
487 }
488 }
489
490 /// The provided secret was not exactly [`DEFAULT_SECRET_LENGTH`][]
491 /// bytes.
492 pub struct SecretWithSeedError<S>(S);
493
494 impl<S> SecretWithSeedError<S> {
495 /// Returns the secret.
into_secret(self) -> S496 pub fn into_secret(self) -> S {
497 self.0
498 }
499 }
500
501 impl<S> core::error::Error for SecretWithSeedError<S> {}
502
503 impl<S> core::fmt::Debug for SecretWithSeedError<S> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result504 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
505 f.debug_tuple("SecretWithSeedError").finish()
506 }
507 }
508
509 impl<S> core::fmt::Display for SecretWithSeedError<S> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result510 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
511 write!(
512 f,
513 "The secret must be exactly {DEFAULT_SECRET_LENGTH} bytes"
514 )
515 }
516 }
517
518 /// The provided secret was not at least [`SECRET_MINIMUM_LENGTH`][]
519 /// bytes.
520 pub struct SecretTooShortError<S>(secret::Error, S);
521
522 impl<S> SecretTooShortError<S> {
523 /// Returns the secret.
into_secret(self) -> S524 pub fn into_secret(self) -> S {
525 self.1
526 }
527 }
528
529 impl<S> core::error::Error for SecretTooShortError<S> {}
530
531 impl<S> core::fmt::Debug for SecretTooShortError<S> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result532 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
533 f.debug_tuple("SecretTooShortError").finish()
534 }
535 }
536
537 impl<S> core::fmt::Display for SecretTooShortError<S> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result538 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
539 self.0.fmt(f)
540 }
541 }
542
543 #[cfg(test)]
544 mod test {
545 use super::*;
546
547 #[test]
secret_buffer_default_is_valid()548 fn secret_buffer_default_is_valid() {
549 assert!(SecretBuffer::default().is_valid());
550 }
551
552 #[test]
secret_buffer_allocate_default_is_valid()553 fn secret_buffer_allocate_default_is_valid() {
554 assert!(SecretBuffer::allocate_default().is_valid())
555 }
556
557 #[test]
secret_buffer_allocate_with_seed_is_valid()558 fn secret_buffer_allocate_with_seed_is_valid() {
559 assert!(SecretBuffer::allocate_with_seed(0xdead_beef).is_valid())
560 }
561 }
562