1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <limits.h>
6 #include <stddef.h>
7 #include <stdint.h>
8
9 #include <crypto/bytes.h>
10 #include <crypto/secret.h>
11 #include <crypto/digest.h>
12 #include <crypto/hmac.h>
13 #include <unittest/unittest.h>
14 #include <zircon/errors.h>
15 #include <zircon/types.h>
16
17 #include "utils.h"
18
19 namespace crypto {
20 namespace testing {
21 namespace {
22
TestInit(void)23 bool TestInit(void) {
24 BEGIN_TEST;
25 HMAC hmac;
26 Secret key;
27
28 size_t key_len;
29 ASSERT_OK(GetDigestLen(digest::kSHA256, &key_len));
30
31 // Bad digest
32 EXPECT_ZX(hmac.Init(digest::kUninitialized, key), ZX_ERR_INVALID_ARGS);
33
34 // Bad flags
35 EXPECT_ZX(hmac.Init(digest::kSHA256, key, 0x8000), ZX_ERR_INVALID_ARGS);
36
37 // Short key
38 ASSERT_OK(key.Generate(key_len - 1));
39 EXPECT_ZX(hmac.Init(digest::kSHA256, key), ZX_ERR_INVALID_ARGS);
40
41 // Medium key
42 ASSERT_OK(key.Generate(key_len));
43 EXPECT_OK(hmac.Init(digest::kSHA256, key));
44
45 // Long key
46 ASSERT_OK(key.Generate(PAGE_SIZE));
47 EXPECT_OK(hmac.Init(digest::kSHA256, key));
48 END_TEST;
49 }
50
TestUpdate(void)51 bool TestUpdate(void) {
52 BEGIN_TEST;
53 HMAC hmac;
54
55 size_t key_len;
56 Secret key;
57 Bytes buf;
58 ASSERT_OK(GetDigestLen(digest::kSHA256, &key_len));
59 ASSERT_OK(key.Generate(key_len));
60 ASSERT_OK(buf.Randomize(PAGE_SIZE));
61
62 // Uninitialized
63 EXPECT_ZX(hmac.Update(buf.get(), buf.len()), ZX_ERR_BAD_STATE);
64
65 // Null data
66 ASSERT_OK(hmac.Init(digest::kSHA256, key));
67 EXPECT_OK(hmac.Update(nullptr, 0));
68 EXPECT_ZX(hmac.Update(nullptr, buf.len()), ZX_ERR_INVALID_ARGS);
69
70 // Multiple calls
71 EXPECT_OK(hmac.Update(buf.get(), buf.len()));
72 EXPECT_OK(hmac.Update(buf.get(), buf.len()));
73 END_TEST;
74 }
75
TestFinal(void)76 bool TestFinal(void) {
77 BEGIN_TEST;
78 HMAC hmac;
79
80 size_t key_len;
81 Secret key;
82 Bytes buf;
83 ASSERT_OK(GetDigestLen(digest::kSHA256, &key_len));
84 ASSERT_OK(key.Generate(key_len));
85 ASSERT_OK(buf.Randomize(PAGE_SIZE));
86
87 // Uninitialized
88 Bytes out;
89 EXPECT_ZX(hmac.Final(&out), ZX_ERR_BAD_STATE);
90
91 // Bad parameter
92 ASSERT_OK(hmac.Init(digest::kSHA256, key));
93 EXPECT_ZX(hmac.Final(nullptr), ZX_ERR_INVALID_ARGS);
94
95 // No update
96 EXPECT_OK(hmac.Final(&out));
97
98 // No update after final without init
99 EXPECT_ZX(hmac.Update(buf.get(), buf.len()), ZX_ERR_BAD_STATE);
100
101 // With update
102 ASSERT_OK(hmac.Init(digest::kSHA256, key));
103 ASSERT_OK(hmac.Update(buf.get(), buf.len()));
104 EXPECT_OK(hmac.Final(&out));
105 END_TEST;
106 }
107
TestCreate(void)108 bool TestCreate(void) {
109 BEGIN_TEST;
110 Secret key;
111 Bytes digest1, digest2, block1, block2;
112
113 ASSERT_OK(block1.Randomize(PAGE_SIZE));
114
115 size_t key_len;
116 ASSERT_OK(GetDigestLen(digest::kSHA256, &key_len));
117
118 // Bad parameters
119 EXPECT_ZX(HMAC::Create(digest::kUninitialized, key, block1.get(), PAGE_SIZE, &digest1),
120 ZX_ERR_INVALID_ARGS);
121 ASSERT_OK(key.Generate(key_len - 1));
122 EXPECT_ZX(HMAC::Create(digest::kSHA256, key, block1.get(), PAGE_SIZE, &digest1),
123 ZX_ERR_INVALID_ARGS);
124 ASSERT_OK(key.Generate(key_len));
125 EXPECT_ZX(HMAC::Create(digest::kSHA256, key, nullptr, PAGE_SIZE, &digest1),
126 ZX_ERR_INVALID_ARGS);
127 EXPECT_ZX(HMAC::Create(digest::kSHA256, key, block1.get(), PAGE_SIZE, nullptr),
128 ZX_ERR_INVALID_ARGS);
129
130 // Same blocks, same HMACs
131 ASSERT_OK(block2.Copy(block1));
132 EXPECT_OK(HMAC::Create(digest::kSHA256, key, block1.get(), PAGE_SIZE, &digest1));
133 EXPECT_OK(HMAC::Create(digest::kSHA256, key, block2.get(), PAGE_SIZE, &digest2));
134 EXPECT_TRUE(digest1 == digest2);
135
136 // Different blocks, different HMACs
137 block2.get()[0] ^= 1;
138 EXPECT_OK(HMAC::Create(digest::kSHA256, key, block2.get(), PAGE_SIZE, &digest2));
139 EXPECT_TRUE(digest1 != digest2);
140 END_TEST;
141 }
142
TestVerify(void)143 bool TestVerify(void) {
144 BEGIN_TEST;
145 Secret key;
146 Bytes out, block;
147
148 ASSERT_OK(block.Randomize(PAGE_SIZE));
149
150 size_t key_len;
151 ASSERT_OK(GetDigestLen(digest::kSHA256, &key_len));
152
153 // Bad parameters
154 EXPECT_ZX(HMAC::Verify(digest::kUninitialized, key, block.get(), PAGE_SIZE, out),
155 ZX_ERR_INVALID_ARGS);
156 ASSERT_OK(key.Generate(key_len - 1));
157 EXPECT_ZX(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out), ZX_ERR_INVALID_ARGS);
158 ASSERT_OK(key.Generate(key_len));
159 EXPECT_ZX(HMAC::Verify(digest::kSHA256, key, nullptr, PAGE_SIZE, out), ZX_ERR_INVALID_ARGS);
160 ASSERT_OK(key.Generate(key_len));
161 EXPECT_ZX(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out), ZX_ERR_INVALID_ARGS);
162
163 // Verify valid
164 ASSERT_OK(key.Generate(key_len));
165 ASSERT_OK(HMAC::Create(digest::kSHA256, key, block.get(), PAGE_SIZE, &out));
166 EXPECT_OK(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out));
167
168 // Verify invalid
169 block.get()[0] ^= 1;
170 EXPECT_ZX(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out),
171 ZX_ERR_IO_DATA_INTEGRITY);
172 block.get()[0] ^= 1;
173 EXPECT_OK(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out));
174
175 ASSERT_OK(key.Generate(key_len));
176 EXPECT_ZX(HMAC::Verify(digest::kSHA256, key, block.get(), PAGE_SIZE, out),
177 ZX_ERR_IO_DATA_INTEGRITY);
178 END_TEST;
179 }
180
181 // The following tests are taken from RFC 4231 section 4. They are intentionally formatted to be as
182 // close to the RFC's representation as possible.
TestRfc4231_TC(const char * xkey,const char * xdata,const char * xhmac)183 bool TestRfc4231_TC(const char* xkey, const char* xdata, const char* xhmac) {
184 BEGIN_TEST;
185 Secret key;
186 Bytes data, hmac;
187 ASSERT_OK(HexToSecret(xkey, &key));
188 ASSERT_OK(HexToBytes(xdata, &data));
189 ASSERT_OK(HexToBytes(xhmac, &hmac));
190 EXPECT_OK(HMAC::Verify(digest::kSHA256, key, data.get(), data.len(), hmac,
191 HMAC::ALLOW_WEAK_KEY | HMAC::ALLOW_TRUNCATION));
192 END_TEST;
193 }
194
195 // clang-format off
TestRfc4231_TC1(void)196 bool TestRfc4231_TC1(void) {
197 return TestRfc4231_TC(
198 /* Key */ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
199 "0b0b0b0b", // 20 bytes
200 /* Data */ "4869205468657265", // "Hi There"
201 /* SHA256 */ "b0344c61d8db38535ca8afceaf0bf12b"
202 "881dc200c9833da726e9376c2e32cff7");
203 }
204
TestRfc4231_TC2(void)205 bool TestRfc4231_TC2(void) {
206 return TestRfc4231_TC(
207 /* Key */ "4a656665", // "Jefe"
208 /* Data */ "7768617420646f2079612077616e7420" // "what do ya want "
209 "666f72206e6f7468696e673f", // "for nothing?"
210 /* SHA256 */ "5bdcc146bf60754e6a042426089575c7"
211 "5a003f089d2739839dec58b964ec3843");
212 }
213
TestRfc4231_TC3(void)214 bool TestRfc4231_TC3(void) {
215 return TestRfc4231_TC(
216 /* Key */ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
217 "aaaaaaaa", // 20 bytes
218 /* Data */ "dddddddddddddddddddddddddddddddd"
219 "dddddddddddddddddddddddddddddddd"
220 "dddddddddddddddddddddddddddddddd"
221 "dddd", // 50 bytes
222 /* SHA256 */ "773ea91e36800e46854db8ebd09181a7"
223 "2959098b3ef8c122d9635514ced565fe");
224 }
225
TestRfc4231_TC4(void)226 bool TestRfc4231_TC4(void) {
227 return TestRfc4231_TC(
228 /* Key */ "0102030405060708090a0b0c0d0e0f10"
229 "111213141516171819", // 25 bytes
230 /* Data */ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
231 "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
232 "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
233 "cdcd", // 50 bytes
234 /* SHA256 */ "82558a389a443c0ea4cc819899f2083a"
235 "85f0faa3e578f8077a2e3ff46729665b");
236 }
237
TestRfc4231_TC5(void)238 bool TestRfc4231_TC5(void) {
239 return TestRfc4231_TC(
240 /* Key */
241 /* Key */ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"
242 "0c0c0c0c", // 20 bytes
243 /* Data */ "546573742057697468205472756e6361" // "Test With Trunca"
244 "74696f6e", // "tion"
245 /* SHA256 */ "a3b6167473100ee06e0c796c2955552b");
246 }
247
TestRfc4231_TC6(void)248 bool TestRfc4231_TC6(void) {
249 return TestRfc4231_TC(
250 /* Key */ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
251 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
252 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
253 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
254 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
255 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
256 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
257 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
258 "aaaaaa", // 131 bytes
259 /* Data */ "54657374205573696e67204c61726765" // "Test Using Large"
260 "72205468616e20426c6f636b2d53697a" // "r Than Block-Siz"
261 "65204b6579202d2048617368204b6579" // "e Key - Hash Key"
262 "204669727374", // " First"
263 /* SHA256 */ "60e431591ee0b67f0d8a26aacbf5b77f"
264 "8e0bc6213728c5140546040f0ee37f54");
265 }
266
TestRfc4231_TC7(void)267 bool TestRfc4231_TC7(void) {
268 return TestRfc4231_TC(
269 /* Key */ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
270 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
271 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
272 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
273 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
274 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
275 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
276 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
277 "aaaaaa", // 131 bytes
278 /* Data */ "54686973206973206120746573742075" // "This is a test u"
279 "73696e672061206c6172676572207468" // "sing a larger th"
280 "616e20626c6f636b2d73697a65206b65" // "an block-size ke"
281 "7920616e642061206c61726765722074" // "y and a larger t"
282 "68616e20626c6f636b2d73697a652064" // "han block-size d"
283 "6174612e20546865206b6579206e6565" // "ata. The key nee"
284 "647320746f2062652068617368656420" // "ds to be hashed "
285 "6265666f7265206265696e6720757365" // "before being use"
286 "642062792074686520484d414320616c" // "d by the HMAC al"
287 "676f726974686d2e", // "gorithm."
288 /* SHA256 */ "9b09ffa71b942fcb27635fbcd5b0e944"
289 "bfdc63644f0713938a7f51535c3a35e2");
290 } // clang-format on
291
292 BEGIN_TEST_CASE(HmacTest)
293 RUN_TEST(TestCreate)
294 RUN_TEST(TestVerify)
295 RUN_TEST(TestRfc4231_TC1)
296 RUN_TEST(TestRfc4231_TC2)
297 RUN_TEST(TestRfc4231_TC3)
298 RUN_TEST(TestRfc4231_TC4)
299 RUN_TEST(TestRfc4231_TC5)
300 RUN_TEST(TestRfc4231_TC6)
301 RUN_TEST(TestRfc4231_TC7)
302 END_TEST_CASE(HmacTest)
303
304 } // namespace
305 } // namespace testing
306 } // namespace crypto
307