Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
305
third-party/vendor/digest/src/mac.rs
vendored
Normal file
305
third-party/vendor/digest/src/mac.rs
vendored
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
use crate::{FixedOutput, FixedOutputReset, Update};
|
||||
use crypto_common::{InvalidLength, Key, KeyInit, Output, OutputSizeUser, Reset};
|
||||
|
||||
#[cfg(feature = "rand_core")]
|
||||
use crate::rand_core::{CryptoRng, RngCore};
|
||||
use core::fmt;
|
||||
use crypto_common::typenum::Unsigned;
|
||||
use subtle::{Choice, ConstantTimeEq};
|
||||
|
||||
/// Marker trait for Message Authentication algorithms.
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "mac")))]
|
||||
pub trait MacMarker {}
|
||||
|
||||
/// Convenience wrapper trait covering functionality of Message Authentication algorithms.
|
||||
///
|
||||
/// This trait wraps [`KeyInit`], [`Update`], [`FixedOutput`], and [`MacMarker`]
|
||||
/// traits and provides additional convenience methods.
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "mac")))]
|
||||
pub trait Mac: OutputSizeUser + Sized {
|
||||
/// Create new value from fixed size key.
|
||||
fn new(key: &Key<Self>) -> Self
|
||||
where
|
||||
Self: KeyInit;
|
||||
|
||||
/// Generate random key using the provided [`CryptoRng`].
|
||||
#[cfg(feature = "rand_core")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
|
||||
fn generate_key(rng: impl CryptoRng + RngCore) -> Key<Self>
|
||||
where
|
||||
Self: KeyInit;
|
||||
|
||||
/// Create new value from variable size key.
|
||||
fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength>
|
||||
where
|
||||
Self: KeyInit;
|
||||
|
||||
/// Update state using the provided data.
|
||||
fn update(&mut self, data: &[u8]);
|
||||
|
||||
/// Process input data in a chained manner.
|
||||
#[must_use]
|
||||
fn chain_update(self, data: impl AsRef<[u8]>) -> Self;
|
||||
|
||||
/// Obtain the result of a [`Mac`] computation as a [`CtOutput`] and consume
|
||||
/// [`Mac`] instance.
|
||||
fn finalize(self) -> CtOutput<Self>;
|
||||
|
||||
/// Obtain the result of a [`Mac`] computation as a [`CtOutput`] and reset
|
||||
/// [`Mac`] instance.
|
||||
fn finalize_reset(&mut self) -> CtOutput<Self>
|
||||
where
|
||||
Self: FixedOutputReset;
|
||||
|
||||
/// Reset MAC instance to its initial state.
|
||||
fn reset(&mut self)
|
||||
where
|
||||
Self: Reset;
|
||||
|
||||
/// Check if tag/code value is correct for the processed input.
|
||||
fn verify(self, tag: &Output<Self>) -> Result<(), MacError>;
|
||||
|
||||
/// Check if tag/code value is correct for the processed input and reset
|
||||
/// [`Mac`] instance.
|
||||
fn verify_reset(&mut self, tag: &Output<Self>) -> Result<(), MacError>
|
||||
where
|
||||
Self: FixedOutputReset;
|
||||
|
||||
/// Check truncated tag correctness using all bytes
|
||||
/// of calculated tag.
|
||||
///
|
||||
/// Returns `Error` if `tag` is not valid or not equal in length
|
||||
/// to MAC's output.
|
||||
fn verify_slice(self, tag: &[u8]) -> Result<(), MacError>;
|
||||
|
||||
/// Check truncated tag correctness using all bytes
|
||||
/// of calculated tag and reset [`Mac`] instance.
|
||||
///
|
||||
/// Returns `Error` if `tag` is not valid or not equal in length
|
||||
/// to MAC's output.
|
||||
fn verify_slice_reset(&mut self, tag: &[u8]) -> Result<(), MacError>
|
||||
where
|
||||
Self: FixedOutputReset;
|
||||
|
||||
/// Check truncated tag correctness using left side bytes
|
||||
/// (i.e. `tag[..n]`) of calculated tag.
|
||||
///
|
||||
/// Returns `Error` if `tag` is not valid or empty.
|
||||
fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError>;
|
||||
|
||||
/// Check truncated tag correctness using right side bytes
|
||||
/// (i.e. `tag[n..]`) of calculated tag.
|
||||
///
|
||||
/// Returns `Error` if `tag` is not valid or empty.
|
||||
fn verify_truncated_right(self, tag: &[u8]) -> Result<(), MacError>;
|
||||
}
|
||||
|
||||
impl<T: Update + FixedOutput + MacMarker> Mac for T {
|
||||
#[inline(always)]
|
||||
fn new(key: &Key<Self>) -> Self
|
||||
where
|
||||
Self: KeyInit,
|
||||
{
|
||||
KeyInit::new(key)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength>
|
||||
where
|
||||
Self: KeyInit,
|
||||
{
|
||||
KeyInit::new_from_slice(key)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn update(&mut self, data: &[u8]) {
|
||||
Update::update(self, data);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn chain_update(mut self, data: impl AsRef<[u8]>) -> Self {
|
||||
Update::update(&mut self, data.as_ref());
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn finalize(self) -> CtOutput<Self> {
|
||||
CtOutput::new(self.finalize_fixed())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn finalize_reset(&mut self) -> CtOutput<Self>
|
||||
where
|
||||
Self: FixedOutputReset,
|
||||
{
|
||||
CtOutput::new(self.finalize_fixed_reset())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reset(&mut self)
|
||||
where
|
||||
Self: Reset,
|
||||
{
|
||||
Reset::reset(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn verify(self, tag: &Output<Self>) -> Result<(), MacError> {
|
||||
if self.finalize() == tag.into() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(MacError)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn verify_reset(&mut self, tag: &Output<Self>) -> Result<(), MacError>
|
||||
where
|
||||
Self: FixedOutputReset,
|
||||
{
|
||||
if self.finalize_reset() == tag.into() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(MacError)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
|
||||
let n = tag.len();
|
||||
if n != Self::OutputSize::USIZE {
|
||||
return Err(MacError);
|
||||
}
|
||||
let choice = self.finalize_fixed().ct_eq(tag);
|
||||
if choice.into() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(MacError)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn verify_slice_reset(&mut self, tag: &[u8]) -> Result<(), MacError>
|
||||
where
|
||||
Self: FixedOutputReset,
|
||||
{
|
||||
let n = tag.len();
|
||||
if n != Self::OutputSize::USIZE {
|
||||
return Err(MacError);
|
||||
}
|
||||
let choice = self.finalize_fixed_reset().ct_eq(tag);
|
||||
if choice.into() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(MacError)
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
|
||||
let n = tag.len();
|
||||
if n == 0 || n > Self::OutputSize::USIZE {
|
||||
return Err(MacError);
|
||||
}
|
||||
let choice = self.finalize_fixed()[..n].ct_eq(tag);
|
||||
|
||||
if choice.into() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(MacError)
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_truncated_right(self, tag: &[u8]) -> Result<(), MacError> {
|
||||
let n = tag.len();
|
||||
if n == 0 || n > Self::OutputSize::USIZE {
|
||||
return Err(MacError);
|
||||
}
|
||||
let m = Self::OutputSize::USIZE - n;
|
||||
let choice = self.finalize_fixed()[m..].ct_eq(tag);
|
||||
|
||||
if choice.into() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(MacError)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "rand_core")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
|
||||
#[inline]
|
||||
fn generate_key(rng: impl CryptoRng + RngCore) -> Key<Self>
|
||||
where
|
||||
Self: KeyInit,
|
||||
{
|
||||
<T as KeyInit>::generate_key(rng)
|
||||
}
|
||||
}
|
||||
|
||||
/// Fixed size output value which provides a safe [`Eq`] implementation that
|
||||
/// runs in constant time.
|
||||
///
|
||||
/// It is useful for implementing Message Authentication Codes (MACs).
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "mac")))]
|
||||
pub struct CtOutput<T: OutputSizeUser> {
|
||||
bytes: Output<T>,
|
||||
}
|
||||
|
||||
impl<T: OutputSizeUser> CtOutput<T> {
|
||||
/// Create a new [`CtOutput`] value.
|
||||
#[inline(always)]
|
||||
pub fn new(bytes: Output<T>) -> Self {
|
||||
Self { bytes }
|
||||
}
|
||||
|
||||
/// Get the inner [`Output`] array this type wraps.
|
||||
#[inline(always)]
|
||||
pub fn into_bytes(self) -> Output<T> {
|
||||
self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: OutputSizeUser> From<Output<T>> for CtOutput<T> {
|
||||
#[inline(always)]
|
||||
fn from(bytes: Output<T>) -> Self {
|
||||
Self { bytes }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: OutputSizeUser> From<&'a Output<T>> for CtOutput<T> {
|
||||
#[inline(always)]
|
||||
fn from(bytes: &'a Output<T>) -> Self {
|
||||
bytes.clone().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: OutputSizeUser> ConstantTimeEq for CtOutput<T> {
|
||||
#[inline(always)]
|
||||
fn ct_eq(&self, other: &Self) -> Choice {
|
||||
self.bytes.ct_eq(&other.bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: OutputSizeUser> PartialEq for CtOutput<T> {
|
||||
#[inline(always)]
|
||||
fn eq(&self, x: &CtOutput<T>) -> bool {
|
||||
self.ct_eq(x).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: OutputSizeUser> Eq for CtOutput<T> {}
|
||||
|
||||
/// Error type for when the [`Output`] of a [`Mac`]
|
||||
/// is not equal to the expected value.
|
||||
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "mac")))]
|
||||
pub struct MacError;
|
||||
|
||||
impl fmt::Display for MacError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("MAC tag mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for MacError {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue