wolf_crypto/aead/tag.rs
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 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
use core::fmt;
/// Represents the authentication tag for AEADs
#[must_use = "You must use the tag, or GCM is doing nothing for you"]
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct Tag {
inner: [u8; 16],
}
impl fmt::Debug for Tag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_fmt(format_args!("Tag({:?})", &self.inner))
}
}
impl Tag {
/// The size of the authentication tag in bytes.
pub const CAPACITY: usize = 16;
#[cfg(feature = "allow-non-fips")]
pub(crate) const SIZE: u32 = 16;
/// Creates a new `Tag` instance from a 16-byte array.
///
/// # Arguments
///
/// * `inner` - A 16-byte array containing the authentication tag.
///
/// # Returns
///
/// A new `Tag` instance.
pub const fn new(inner: [u8; Self::CAPACITY]) -> Self {
Self { inner }
}
/// Creates a new `Tag` instance filled with zeros.
///
/// This is typically used to create a tag buffer that will be filled
/// by an encryption operation.
///
/// # Returns
///
/// A new `Tag` instance with all bytes set to zero.
///
/// # Example
///
/// ```
/// use wolf_crypto::aead::Tag;
///
/// let tag = Tag::new_zeroed();
/// assert_eq!(tag.as_slice(), &[0u8; 16]);
/// ```
pub const fn new_zeroed() -> Self {
Self::new([0u8; Self::CAPACITY])
}
/// Consumes the `Tag` and returns the underlying 16-byte array.
#[inline]
pub const fn take(self) -> [u8; Self::CAPACITY] {
self.inner
}
/// Returns a reference to the tag as a byte slice.
pub const fn as_slice(&self) -> &[u8] {
self.inner.as_slice()
}
#[inline]
pub(crate) fn as_mut_ptr(&mut self) -> *mut u8 {
self.inner.as_mut_ptr()
}
#[inline]
pub(crate) const fn as_ptr(&self) -> *const u8 {
self.inner.as_ptr()
}
}
impl PartialEq for Tag {
/// Constant Time Equivalence
#[inline]
fn eq(&self, other: &Self) -> bool {
// wolfcrypt (or just with my current config) does not expose the `misc` module
// utilities. This function is only ensuring both pointers are valid, and then uses the
// `misc` module's ConstantCompare on the two tags. So this will work for all tags, and
// allows us not to depend on a crate like subtle.
use wolf_crypto_sys::wc_ChaCha20Poly1305_CheckTag;
unsafe { wc_ChaCha20Poly1305_CheckTag(self.as_ptr(), other.as_ptr()) == 0 }
}
}
impl PartialEq<[u8; 16]> for Tag {
/// Constant Time Equivalence
#[inline]
fn eq(&self, other: &[u8; 16]) -> bool {
use wolf_crypto_sys::wc_ChaCha20Poly1305_CheckTag;
unsafe { wc_ChaCha20Poly1305_CheckTag(self.as_ptr(), other.as_ptr()) == 0 }
}
}
impl PartialEq<[u8]> for Tag {
/// Constant Time Equivalence (variable timing for length of `other`)
#[inline]
fn eq(&self, other: &[u8]) -> bool {
use wolf_crypto_sys::wc_ChaCha20Poly1305_CheckTag;
if other.len() != Self::CAPACITY { return false; }
unsafe { wc_ChaCha20Poly1305_CheckTag(self.as_ptr(), other.as_ptr()) == 0 }
}
}
impl PartialEq<Tag> for [u8; 16] {
/// Constant Time Equivalence
#[inline]
fn eq(&self, other: &Tag) -> bool {
other.eq(self)
}
}
impl PartialEq<Tag> for [u8] {
/// Constant Time Equivalence (variable timing for length of `self`)
#[inline]
fn eq(&self, other: &Tag) -> bool {
other.eq(self)
}
}
impl<T> PartialEq<&T> for Tag where Self: PartialEq<T>, T: ?Sized {
/// `PartialEq` for references of types which already can be compared to `Tag` in constant
/// time.
#[inline]
fn eq(&self, other: &&T) -> bool {
self.eq(*other)
}
}
impl<T> PartialEq<&mut T> for Tag where Self: PartialEq<T>, T: ?Sized {
/// `PartialEq` for references of types which already can be compared to `Tag` in constant
/// time.
#[inline]
fn eq(&self, other: &&mut T) -> bool {
self.eq(*other)
}
}