7
7
8
8
use crate :: log:: error;
9
9
use alloc:: boxed:: Box ;
10
- use alloc:: vec;
11
- use alloc:: vec:: Vec ;
12
10
use rustls:: crypto;
13
11
14
12
/// HMAC using SHA-256.
@@ -17,7 +15,7 @@ pub(crate) static HMAC_SHA256: Hmac = Hmac(&super::hash::MBED_SHA_256);
17
15
/// HMAC using SHA-384.
18
16
pub ( crate ) static HMAC_SHA384 : Hmac = Hmac ( & super :: hash:: MBED_SHA_384 ) ;
19
17
20
- pub ( crate ) struct Hmac ( & ' static super :: hash:: Algorithm ) ;
18
+ pub ( crate ) struct Hmac ( pub ( crate ) & ' static super :: hash:: Algorithm ) ;
21
19
22
20
impl crypto:: hmac:: Hmac for Hmac {
23
21
fn with_key ( & self , key : & [ u8 ] ) -> Box < dyn crypto:: hmac:: Key > {
@@ -29,17 +27,24 @@ impl crypto::hmac::Hmac for Hmac {
29
27
}
30
28
}
31
29
30
+ impl Hmac {
31
+ #[ inline]
32
+ pub ( crate ) fn hash_algorithm ( & self ) -> & ' static super :: hash:: Algorithm {
33
+ self . 0
34
+ }
35
+ }
36
+
32
37
struct HmacKey ( MbedHmacKey ) ;
33
38
34
39
impl crypto:: hmac:: Key for HmacKey {
35
- fn sign_concat ( & self , first : & [ u8 ] , middle : & [ & [ u8 ] ] , last : & [ u8 ] ) -> crypto:: hmac:: Tag {
40
+ fn sign_concat ( & self , first : & [ u8 ] , middle : & [ & [ u8 ] ] , last : & [ u8 ] ) -> rustls :: crypto:: hmac:: Tag {
36
41
let mut ctx = self . 0 . starts ( ) ;
37
42
ctx. update ( first) ;
38
43
for m in middle {
39
44
ctx. update ( m) ;
40
45
}
41
46
ctx. update ( last) ;
42
- crypto :: hmac :: Tag :: new ( & ctx. finish ( ) )
47
+ ctx. finish ( ) . into ( )
43
48
}
44
49
45
50
fn tag_len ( & self ) -> usize {
@@ -49,13 +54,12 @@ impl crypto::hmac::Key for HmacKey {
49
54
50
55
struct MbedHmacKey {
51
56
hmac_algo : & ' static super :: hash:: Algorithm ,
52
- /// use [`crypto::hmac::Tag`] for saving key material, since they have same max size.
53
- key : crypto:: hmac:: Tag ,
57
+ key : Tag ,
54
58
}
55
59
56
60
impl MbedHmacKey {
57
61
pub ( crate ) fn new ( hmac_algo : & ' static super :: hash:: Algorithm , key : & [ u8 ] ) -> Self {
58
- Self { hmac_algo, key : crypto :: hmac :: Tag :: new ( key) }
62
+ Self { hmac_algo, key : Tag :: new ( key) }
59
63
}
60
64
61
65
pub ( crate ) fn starts ( & self ) -> MbedHmacContext {
@@ -73,13 +77,13 @@ struct MbedHmacContext {
73
77
74
78
impl MbedHmacContext {
75
79
/// Since the trait does not provider a way to return error, empty vector is returned when getting error from `mbedtls`.
76
- pub ( crate ) fn finish ( self ) -> Vec < u8 > {
77
- let mut out = vec ! [ 0u8 ; self . hmac_algo. output_len] ;
78
- match self . ctx . finish ( & mut out) {
80
+ pub ( crate ) fn finish ( self ) -> Tag {
81
+ let mut out = Tag :: with_len ( self . hmac_algo . output_len ) ;
82
+ match self . ctx . finish ( out. as_mut ( ) ) {
79
83
Ok ( _) => out,
80
84
Err ( _err) => {
81
85
error ! ( "Failed to finish hmac, mbedtls error: {:?}" , _err) ;
82
- vec ! [ ]
86
+ Tag :: with_len ( 0 )
83
87
}
84
88
}
85
89
}
@@ -93,3 +97,97 @@ impl MbedHmacContext {
93
97
}
94
98
}
95
99
}
100
+
101
+ /// A HMAC tag, stored as a value.
102
+ #[ derive( Clone , PartialEq , Eq , Debug ) ]
103
+ pub ( crate ) struct Tag {
104
+ buf : [ u8 ; Self :: MAX_LEN ] ,
105
+ used : usize ,
106
+ }
107
+
108
+ impl Tag {
109
+ /// Build a tag by copying a byte slice.
110
+ ///
111
+ /// The slice can be up to [`Tag::MAX_LEN`] bytes in length.
112
+ pub ( crate ) fn new ( bytes : & [ u8 ] ) -> Self {
113
+ let mut tag = Self { buf : [ 0u8 ; Self :: MAX_LEN ] , used : bytes. len ( ) } ;
114
+ tag. buf [ ..tag. used ] . copy_from_slice ( bytes) ;
115
+ tag
116
+ }
117
+
118
+ /// Build a tag with given capacity.
119
+ ///
120
+ /// The slice can be up to [`Tag::MAX_LEN`] bytes in length.
121
+ pub ( crate ) fn with_len ( len : usize ) -> Self {
122
+ Self { buf : [ 0u8 ; Self :: MAX_LEN ] , used : len }
123
+ }
124
+
125
+ /// Maximum supported HMAC tag size: supports up to SHA512.
126
+ pub ( crate ) const MAX_LEN : usize = 64 ;
127
+ }
128
+
129
+ impl Drop for Tag {
130
+ fn drop ( & mut self ) {
131
+ mbedtls:: zeroize ( & mut self . buf )
132
+ }
133
+ }
134
+
135
+ impl AsRef < [ u8 ] > for Tag {
136
+ fn as_ref ( & self ) -> & [ u8 ] {
137
+ & self . buf [ ..self . used ]
138
+ }
139
+ }
140
+
141
+ impl AsMut < [ u8 ] > for Tag {
142
+ fn as_mut ( & mut self ) -> & mut [ u8 ] {
143
+ & mut self . buf [ ..self . used ]
144
+ }
145
+ }
146
+
147
+ impl From < Tag > for rustls:: crypto:: hmac:: Tag {
148
+ fn from ( val : Tag ) -> Self {
149
+ Self :: new ( & val. buf [ ..val. used ] )
150
+ }
151
+ }
152
+
153
+ #[ cfg( test) ]
154
+ mod tests {
155
+ use rustls:: crypto:: hmac:: Hmac ;
156
+
157
+ use super :: * ;
158
+
159
+ #[ test]
160
+ fn test_hmac_sha256_tag_length ( ) {
161
+ let hmac = & HMAC_SHA256 ;
162
+ let key_len = 256 / 8 ;
163
+ let key = vec ! [ 0u8 ; key_len] ;
164
+ test_hmac_tag_length_helper ( hmac, & key, key_len) ;
165
+ }
166
+
167
+ #[ test]
168
+ fn test_hmac_sha384_tag_length ( ) {
169
+ let hmac = & HMAC_SHA384 ;
170
+ let key_len = 384 / 8 ;
171
+ let key = vec ! [ 0u8 ; key_len] ;
172
+ test_hmac_tag_length_helper ( hmac, & key, key_len) ;
173
+ }
174
+
175
+ fn test_hmac_tag_length_helper ( hmac : & super :: Hmac , key : & [ u8 ] , key_len : usize ) {
176
+ let hmac_key = hmac. with_key ( key) ;
177
+ assert_eq ! ( hmac. hash_output_len( ) , hmac_key. tag_len( ) ) ;
178
+ assert_eq ! ( hmac. hash_output_len( ) , key_len) ;
179
+ }
180
+
181
+ #[ test]
182
+ fn test_mbed_hmac_context_error ( ) {
183
+ let key_len = 256 / 8 ;
184
+ let key = vec ! [ 0u8 ; key_len] ;
185
+ let mut bad_ctx = MbedHmacContext {
186
+ hmac_algo : & crate :: hash:: MBED_SHA_256 ,
187
+ ctx : mbedtls:: hash:: Hmac :: new ( crate :: hash:: MBED_SHA_384 . hash_type , & key) . unwrap ( ) ,
188
+ } ;
189
+ bad_ctx. update ( & [ ] ) ;
190
+ let tag = bad_ctx. finish ( ) ;
191
+ assert_eq ! ( tag, Tag :: with_len( 0 ) ) ;
192
+ }
193
+ }
0 commit comments