1use crate::{can_cast_i32, can_cast_u32, const_can_cast_i32, const_can_cast_u32, to_u32};
4use crate::sealed::AadSealed as Sealed;
5use core::num::NonZeroU32;
6use core::convert::Infallible;
7use crate::buf::InvalidSize;
8use crate::error::InvalidIters;
9use core::fmt;
10
11non_fips! {
12 mod hmac;
13 pub use hmac::hkdf;
14 pub use hmac::hkdf_into;
15}
16
17pub mod pbkdf;
18#[doc(inline)]
19pub use pbkdf::{pbkdf2, pbkdf2_into, FipsPbkdf2};
20
21non_fips! {
22 #[doc(inline)]
23 pub use pbkdf::{pbkdf1, pbkdf1_into};
24}
25
26#[doc(inline)]
27pub use crate::mac::hmac::algo::{
28 InsecureKey,
29 KeySlice,
30 Sha224, Sha256, Sha384, Sha512,
31 Sha3_224, Sha3_256, Sha3_384, Sha3_512
32};
33
34non_fips! {
35 #[doc(inline)]
36 pub use crate::mac::hmac::algo::{
37 Sha, Md5
38 };
39}
40
41#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
55#[repr(transparent)]
56pub struct Iters { count: NonZeroU32 }
57
58impl fmt::Display for Iters {
59 #[inline]
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.write_fmt(format_args!("Iters({})", self.count))
62 }
63}
64
65impl fmt::Debug for Iters {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 <Self as fmt::Display>::fmt(self, f)
68 }
69}
70
71impl Iters {
72 pub const fn new(iters: u32) -> Option<Self> {
91 match NonZeroU32::new(iters) {
100 Some(count) => Some(Self { count }),
101 None => None
102 }
103 }
104
105 pub const unsafe fn new_unchecked(iters: u32) -> Self {
112 Self { count: NonZeroU32::new_unchecked(iters) }
113 }
114
115 pub const fn is_valid_size(&self) -> bool {
123 self.get() <= i32::MAX as u32
124 }
125
126 #[inline]
128 #[must_use]
129 pub const fn get(&self) -> u32 {
130 self.count.get()
131 }
132}
133
134impl From<NonZeroU32> for Iters {
135 #[inline]
136 fn from(value: NonZeroU32) -> Self {
137 Self { count: value }
138 }
139}
140
141impl TryFrom<u32> for Iters {
142 type Error = InvalidIters;
143
144 #[inline]
150 fn try_from(value: u32) -> Result<Self, Self::Error> {
151 Self::new(value).ok_or(InvalidIters)
152 }
153}
154
155impl TryFrom<usize> for Iters {
156 type Error = InvalidIters;
157
158 #[inline]
165 fn try_from(value: usize) -> Result<Self, Self::Error> {
166 to_u32(value).and_then(Self::new).ok_or(InvalidIters)
167 }
168}
169
170pub mod salt {
171 use super::{InvalidSize, Infallible, Salt, Sealed};
173 use core::marker::PhantomData;
174 use core::fmt;
175
176 pub trait MinSize : Sealed {
180 type CreateError;
184
185 fn min_size() -> u32;
189 }
190
191 macro_rules! def_sz {
192 ($(
193 $(#[$meta:meta])*
194 $name:ident => $sz:literal => $err:ident
195 ),* $(,)?) => {
196 $(
197 $(#[$meta])*
198 pub struct $name;
199
200 impl super::Sealed for $name {}
201 impl MinSize for $name {
202 type CreateError = $err;
203
204 #[inline]
205 fn min_size() -> u32 {
206 $sz
207 }
208 }
209 )*
210 };
211 }
212
213 def_sz! {
214 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
218 Empty => 0 => Infallible,
219 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
223 NonEmpty => 1 => InvalidSize,
224 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
228 Min16 => 16 => InvalidSize
229 }
230
231 pub trait NonEmptySize<SZ: MinSize> : Salt<SZ> {}
233 impl<S: Salt<NonEmpty>> NonEmptySize<NonEmpty> for S {}
234 impl<S: Salt<Min16>> NonEmptySize<Min16> for S {}
235
236 mark_fips! { Min16, Sealed }
237
238 #[repr(transparent)]
244 pub struct Slice<'s, SZ> {
245 raw: &'s [u8],
246 _min_size: PhantomData<SZ>
247 }
248
249 impl<'s, SZ: MinSize> Clone for Slice<'s, SZ> {
250 #[inline]
251 fn clone(&self) -> Self { Self::create(self.raw) }
252 }
253
254 impl<'s, SZ: MinSize> AsRef<[u8]> for Slice<'s, SZ> {
255 #[inline]
256 fn as_ref(&self) -> &[u8] { self.raw }
257 }
258
259 impl<'s, SZ: MinSize> fmt::Debug for Slice<'s, SZ> {
260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 f.debug_tuple("Slice").field(&self.raw).finish()
262 }
263 }
264
265 macro_rules! impl_salt_for {
266 ($sz:ty => { $item:item }) => {
267 impl<'s> Slice<'s, $sz> {
268 $item
269 }
270 };
271 }
272
273 impl_salt_for! { Empty => {
274 pub const fn new(slice: &'s [u8]) -> Result<Self, Infallible> {
286 Ok(Self::create(slice))
287 }
288 }}
289
290 impl_salt_for! { NonEmpty => {
291 pub const fn new(slice: &'s [u8]) -> Result<Self, InvalidSize> {
304 if !slice.is_empty() {
305 Ok(Self::create(slice))
306 } else {
307 Err(InvalidSize)
308 }
309 }
310 }}
311
312 impl_salt_for! { Min16 => {
313 pub const fn new(slice: &'s [u8]) -> Result<Self, InvalidSize> {
326 if slice.len() >= 16 {
327 Ok(Self::create(slice))
328 } else {
329 Err(InvalidSize)
330 }
331 }
332 }}
333
334 impl<'s, SZ: MinSize> Slice<'s, SZ> {
335 #[inline]
336 const fn create(raw: &'s [u8]) -> Self {
337 Self { raw, _min_size: PhantomData }
338 }
339 }
340
341 macro_rules! impl_salt_try_from {
342 ($ty:ty) => {
343 impl<'s> TryFrom<&'s [u8]> for Slice<'s, $ty> {
344 type Error = <$ty as MinSize>::CreateError;
345
346 #[inline]
347 fn try_from(value: &'s [u8]) -> Result<Self, Self::Error> {
348 Self::new(value)
349 }
350 }
351 };
352 }
353
354 impl_salt_try_from! { NonEmpty }
355 impl_salt_try_from! { Min16 }
356
357 impl<'s> From<&'s [u8]> for Slice<'s, Empty> {
358 #[inline]
359 fn from(value: &'s [u8]) -> Self {
360 Self::create(value)
361 }
362 }
363
364 impl<'s> From<&'s [u8; 16]> for Slice<'s, Min16> {
365 #[inline]
366 fn from(value: &'s [u8; 16]) -> Self {
367 Self::create(value)
368 }
369 }
370
371 impl<'s, SZ: MinSize> Sealed for Slice<'s, SZ> {}
372
373 macro_rules! impl_salt_slice {
374 ($for:ident allows $with:ident) => {
375 impl<'s> Salt<$for> for Slice<'s, $with> {
376 #[inline]
377 fn size(&self) -> u32 {
378 debug_assert!($crate::can_cast_u32(self.raw.len()));
379 self.raw.len() as u32
380 }
381
382 #[inline]
383 fn is_valid_size(&self) -> bool {
384 $crate::can_cast_u32(self.raw.len())
385 }
386
387 #[inline]
388 fn i_size(&self) -> i32 {
389 debug_assert!($crate::can_cast_i32(self.raw.len()));
390 self.raw.len() as i32
391 }
392
393 #[inline]
394 fn i_is_valid_size(&self) -> bool {
395 $crate::can_cast_i32(self.raw.len())
396 }
397
398 #[inline]
399 fn ptr(&self) -> *const u8 {
400 self.raw.as_ptr()
401 }
402 }
403 };
404 }
405
406 impl_salt_slice! { Empty allows Empty }
407 impl_salt_slice! { Empty allows NonEmpty }
408 impl_salt_slice! { Empty allows Min16 }
409
410 impl_salt_slice! { NonEmpty allows NonEmpty }
411
412 impl_salt_slice! { Min16 allows Min16 }
413}
414
415pub trait Salt<SZ: salt::MinSize>: Sealed {
430 #[doc(hidden)]
431 #[must_use]
432 fn size(&self) -> u32;
433
434 #[doc(hidden)]
435 #[must_use]
436 fn is_valid_size(&self) -> bool;
437
438 #[doc(hidden)]
439 #[must_use]
440 fn i_size(&self) -> i32;
441
442 #[doc(hidden)]
443 #[must_use]
444 fn i_is_valid_size(&self) -> bool;
445
446 #[doc(hidden)]
447 #[must_use]
448 fn ptr(&self) -> *const u8;
449}
450
451impl<T: Salt<salt::Min16>> Salt<salt::NonEmpty> for T {
452 #[inline]
453 fn size(&self) -> u32 {
454 <T as Salt<salt::Min16>>::size(self)
455 }
456
457 #[inline]
458 fn is_valid_size(&self) -> bool {
459 <T as Salt<salt::Min16>>::is_valid_size(self)
460 }
461
462 #[inline]
463 fn i_size(&self) -> i32 {
464 <T as Salt<salt::Min16>>::i_size(self)
465 }
466
467 #[inline]
468 fn i_is_valid_size(&self) -> bool {
469 <T as Salt<salt::Min16>>::i_is_valid_size(self)
470 }
471
472 #[inline]
473 fn ptr(&self) -> *const u8 {
474 <T as Salt<salt::Min16>>::ptr(self)
475 }
476}
477
478impl Salt<salt::Empty> for &[u8] {
479 #[inline]
480 fn size(&self) -> u32 {
481 debug_assert!(can_cast_u32(self.len()));
482 self.len() as u32
483 }
484
485 #[inline]
486 fn is_valid_size(&self) -> bool {
487 can_cast_u32(self.len())
488 }
489
490 #[inline]
491 fn i_size(&self) -> i32 {
492 debug_assert!(can_cast_i32(self.len()));
493 self.len() as i32
494 }
495
496 #[inline]
497 fn i_is_valid_size(&self) -> bool {
498 can_cast_i32(self.len())
499 }
500
501 #[inline]
502 fn ptr(&self) -> *const u8 {
503 self.as_ptr()
504 }
505}
506
507impl<const C: usize> Salt<salt::Empty> for [u8; C] {
508 #[inline]
509 fn size(&self) -> u32 {
510 debug_assert!(const_can_cast_u32::<C>());
511 self.len() as u32
512 }
513
514 #[inline]
515 fn is_valid_size(&self) -> bool {
516 const_can_cast_u32::<C>()
517 }
518
519 #[inline]
520 fn i_size(&self) -> i32 {
521 debug_assert!(const_can_cast_i32::<C>());
522 C as i32
523 }
524
525 #[inline]
526 fn i_is_valid_size(&self) -> bool {
527 const_can_cast_i32::<C>()
528 }
529
530 #[inline]
531 fn ptr(&self) -> *const u8 {
532 self.as_ptr()
533 }
534}
535
536macro_rules! impl_salt_for_sizes {
537 ($constraint:ty => [$($sz:literal),*]) => {
538 $(
539 impl Salt<$constraint> for [u8; $sz] {
540 #[inline]
541 fn size(&self) -> u32 { $sz }
542 #[inline]
543 fn is_valid_size(&self) -> bool { true }
544 #[inline]
545 fn i_size(&self) -> i32 { $sz }
546 #[inline]
547 fn i_is_valid_size(&self) -> bool { true }
548 #[inline]
549 fn ptr(&self) -> *const u8 { self.as_ptr() }
550 }
551 impl Salt<$constraint> for &[u8; $sz] {
552 #[inline]
553 fn size(&self) -> u32 { $sz }
554 #[inline]
555 fn is_valid_size(&self) -> bool { true }
556 #[inline]
557 fn i_size(&self) -> i32 { $sz }
558 #[inline]
559 fn i_is_valid_size(&self) -> bool { true }
560 #[inline]
561 fn ptr(&self) -> *const u8 { self.as_ptr() }
562 }
563 )*
564 };
565}
566
567impl_salt_for_sizes! { salt::Min16 => [
568 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 48, 64
569]}
570
571impl_salt_for_sizes! { salt::NonEmpty => [
572 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
573]}
574
575impl Salt<salt::Empty> for () {
576 #[inline]
577 fn size(&self) -> u32 {
578 0
579 }
580
581 #[inline]
582 fn is_valid_size(&self) -> bool {
583 true
584 }
585
586 #[inline]
587 fn i_size(&self) -> i32 {
588 0
589 }
590
591 #[inline]
592 fn i_is_valid_size(&self) -> bool {
593 true
594 }
595
596 #[inline]
597 fn ptr(&self) -> *const u8 {
598 core::ptr::null()
599 }
600}
601
602impl<T: Salt<salt::Empty>> Salt<salt::Empty> for &T {
603 #[inline]
604 fn size(&self) -> u32 {
605 <T as Salt<salt::Empty>>::size(self)
606 }
607
608 #[inline]
609 fn is_valid_size(&self) -> bool {
610 <T as Salt<salt::Empty>>::is_valid_size(self)
611 }
612
613 #[inline]
614 fn i_size(&self) -> i32 {
615 <T as Salt<salt::Empty>>::i_size(self)
616 }
617
618 #[inline]
619 fn i_is_valid_size(&self) -> bool {
620 <T as Salt<salt::Empty>>::i_is_valid_size(self)
621 }
622
623 #[inline]
624 fn ptr(&self) -> *const u8 {
625 <T as Salt<salt::Empty>>::ptr(self)
626 }
627}
628
629impl<T: Salt<salt::Empty>> Salt<salt::Empty> for &mut T {
630 #[inline]
631 fn size(&self) -> u32 {
632 <T as Salt<salt::Empty>>::size(self)
633 }
634
635 #[inline]
636 fn is_valid_size(&self) -> bool {
637 <T as Salt<salt::Empty>>::is_valid_size(self)
638 }
639
640 #[inline]
641 fn i_size(&self) -> i32 {
642 <T as Salt<salt::Empty>>::i_size(self)
643 }
644
645 #[inline]
646 fn i_is_valid_size(&self) -> bool {
647 <T as Salt<salt::Empty>>::i_is_valid_size(self)
648 }
649
650 #[inline]
651 fn ptr(&self) -> *const u8 {
652 <T as Salt<salt::Empty>>::ptr(self)
653 }
654}
655
656impl<T: Salt<salt::Empty>> Salt<salt::Empty> for Option<T> {
657 #[inline]
658 fn size(&self) -> u32 {
659 self.as_ref().map_or(0, <T as Salt<salt::Empty>>::size)
660 }
661
662 #[inline]
663 fn is_valid_size(&self) -> bool {
664 self.as_ref().map_or(true, <T as Salt<salt::Empty>>::is_valid_size)
665 }
666
667 #[inline]
668 fn i_size(&self) -> i32 {
669 self.as_ref().map_or(0, <T as Salt<salt::Empty>>::i_size)
670 }
671
672 #[inline]
673 fn i_is_valid_size(&self) -> bool {
674 self.as_ref().map_or(true, <T as Salt<salt::Empty>>::i_is_valid_size)
675 }
676
677 #[inline]
678 fn ptr(&self) -> *const u8 {
679 self.as_ref().map_or_else(core::ptr::null, <T as Salt<salt::Empty>>::ptr)
680 }
681}
682
683pub type FipsSaltSlice<'s> = salt::Slice<'s, salt::Min16>;
685pub type SaltSlice<'s> = salt::Slice<'s, salt::NonEmpty>;
687pub type MaybeSaltSlice<'s> = salt::Slice<'s, salt::Empty>;
689
690#[cfg(not(feature = "allow-non-fips"))]
691pub type DynSaltSlice<'s> = FipsSaltSlice<'s>;
700#[cfg(feature = "allow-non-fips")]
701pub type DynSaltSlice<'s> = SaltSlice<'s>;
710
711impl<T: Salt<salt::Min16>> crate::sealed::FipsSealed for T {}
712impl<T: Salt<salt::Min16>> crate::Fips for T {}
713
714#[cfg(test)]
715mod foolery {
716 use core::mem;
717 use super::*;
718
719 #[test]
720 fn foolery() {
721 dbg!(mem::size_of::<Option<NonZeroU32>>());
722 dbg!(mem::size_of::<Option<Iters>>());
723 dbg!(mem::align_of::<Option<Iters>>());
724 dbg!(mem::align_of::<Option<NonZeroU32>>());
725 }
726}