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