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
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;
    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)
    }
}