1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]
#![forbid(unsafe_code)]
#![warn(missing_docs, rust_2018_idioms)]
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "cipher")]
pub use cipher;
#[cfg(feature = "cipher")]
use cipher::{BlockCipher, NewBlockCipher};
#[cfg(feature = "dev")]
#[cfg_attr(docsrs, doc(cfg(feature = "dev")))]
pub mod dev;
#[cfg(feature = "core-api")]
#[cfg_attr(docsrs, doc(cfg(feature = "core-api")))]
pub mod core_api;
pub use cipher::{errors::InvalidLength, FromKey};
pub use crypto_common::{FixedOutput, FixedOutputReset, Reset, Update};
pub use generic_array::{self, typenum::consts};
use core::fmt;
use generic_array::GenericArray;
use subtle::{Choice, ConstantTimeEq};
pub type Key<M> = GenericArray<u8, <M as FromKey>::KeySize>;
pub trait Mac: FromKey + Update + FixedOutput {
fn finalize(self) -> Output<Self> {
Output::new(self.finalize_fixed())
}
fn finalize_reset(&mut self) -> Output<Self>
where
Self: FixedOutputReset,
{
Output::new(self.finalize_fixed_reset())
}
fn verify(self, tag: &[u8]) -> Result<(), MacError> {
let choice = self.finalize().bytes.ct_eq(tag);
if choice.unwrap_u8() == 1 {
Ok(())
} else {
Err(MacError)
}
}
}
impl<T: FromKey + Update + FixedOutput> Mac for T {}
#[derive(Clone)]
pub struct Output<M: Mac> {
bytes: GenericArray<u8, M::OutputSize>,
}
impl<M: Mac> Output<M> {
pub fn new(bytes: GenericArray<u8, M::OutputSize>) -> Output<M> {
Output { bytes }
}
pub fn into_bytes(self) -> GenericArray<u8, M::OutputSize> {
self.bytes
}
}
impl<M: Mac> ConstantTimeEq for Output<M> {
fn ct_eq(&self, other: &Self) -> Choice {
self.bytes.ct_eq(&other.bytes)
}
}
impl<M: Mac> PartialEq for Output<M> {
fn eq(&self, x: &Output<M>) -> bool {
self.ct_eq(x).unwrap_u8() == 1
}
}
impl<M: Mac> Eq for Output<M> {}
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct MacError;
impl fmt::Display for MacError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("failed MAC verification")
}
}
#[cfg(feature = "std")]
impl std::error::Error for MacError {}