1 /*
2 * Copyright (c) 2016, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <openthread/config.h>
30
31 #include "common/array.hpp"
32 #include "common/debug.hpp"
33 #include "common/message.hpp"
34 #include "crypto/hmac_sha256.hpp"
35 #include "crypto/sha256.hpp"
36
37 #include "test_platform.h"
38 #include "test_util.h"
39
40 namespace ot {
41
TestSha256(void)42 void TestSha256(void)
43 {
44 const char kData1[] = "abc";
45
46 const otCryptoSha256Hash kHash1 = {{
47 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
48 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
49 }};
50
51 const char kData2[] = "";
52
53 const otCryptoSha256Hash kHash2 = {{
54 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
55 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
56 }};
57
58 const char kData3[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
59
60 const otCryptoSha256Hash kHash3 = {{
61 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
62 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
63 }};
64
65 const char kData4[] = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmno"
66 "pqrsmnopqrstnopqrstu";
67
68 const otCryptoSha256Hash kHash4 = {{
69 0xcf, 0x5b, 0x16, 0xa7, 0x78, 0xaf, 0x83, 0x80, 0x03, 0x6c, 0xe5, 0x9e, 0x7b, 0x04, 0x92, 0x37,
70 0x0b, 0x24, 0x9b, 0x11, 0xe8, 0xf0, 0x7a, 0x51, 0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1,
71 }};
72
73 struct TestCase
74 {
75 const char *mData; // (null-terminated string).
76 otCryptoSha256Hash mHash;
77 };
78
79 static const TestCase kTestCases[] = {
80 {kData1, kHash1},
81 {kData2, kHash2},
82 {kData3, kHash3},
83 {kData4, kHash4},
84 };
85
86 printf("TestSha256\n");
87
88 Instance *instance = testInitInstance();
89 MessagePool *messagePool;
90 Message *message;
91 uint16_t offsets[GetArrayLength(kTestCases)];
92 uint8_t index;
93
94 VerifyOrQuit(instance != nullptr);
95
96 messagePool = &instance->Get<MessagePool>();
97 VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
98
99 for (const TestCase &testCase : kTestCases)
100 {
101 Crypto::Sha256 sha256;
102 Crypto::Sha256::Hash hash;
103
104 sha256.Start();
105 sha256.Update(testCase.mData, static_cast<uint16_t>(strlen(testCase.mData)));
106 sha256.Finish(hash);
107
108 VerifyOrQuit(hash == static_cast<const Crypto::HmacSha256::Hash &>(testCase.mHash));
109 }
110
111 // Append all test case `mData` in the message.
112
113 index = 0;
114
115 for (const TestCase &testCase : kTestCases)
116 {
117 SuccessOrQuit(message->Append("Hello"));
118 offsets[index++] = message->GetLength();
119 SuccessOrQuit(message->AppendBytes(testCase.mData, static_cast<uint16_t>(strlen(testCase.mData))));
120 SuccessOrQuit(message->Append("There!"));
121 }
122
123 index = 0;
124
125 for (const TestCase &testCase : kTestCases)
126 {
127 Crypto::Sha256 sha256;
128 Crypto::Sha256::Hash hash;
129
130 sha256.Start();
131 sha256.Update(*message, offsets[index++], static_cast<uint16_t>(strlen(testCase.mData)));
132 sha256.Finish(hash);
133
134 VerifyOrQuit(hash == static_cast<const Crypto::HmacSha256::Hash &>(testCase.mHash));
135 }
136
137 testFreeInstance(instance);
138 }
139
TestHmacSha256(void)140 void TestHmacSha256(void)
141 {
142 struct TestCase
143 {
144 otCryptoKey mKey;
145 const void *mData;
146 uint16_t mDataLength;
147 otCryptoSha256Hash mHash;
148 };
149
150 // Test-cases from RFC 4231.
151
152 const uint8_t kKey1[] = {
153 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
154 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
155 };
156
157 const char kData1[] = "Hi There";
158
159 const otCryptoSha256Hash kHash1 = {{
160 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
161 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7,
162 }};
163
164 const char kKey2[] = "Jefe";
165 const char kData2[] = "what do ya want for nothing?";
166
167 const otCryptoSha256Hash kHash2 = {{
168 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
169 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43,
170 }};
171
172 const uint8_t kKey3[] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
173 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
174
175 const uint8_t kData3[] = {
176 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
177 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
178 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
179 };
180
181 const otCryptoSha256Hash kHash3 = {{
182 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
183 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe,
184 }};
185
186 const uint8_t kKey4[] = {
187 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
188 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
189 };
190
191 const uint8_t kData4[] = {
192 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
193 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
194 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
195 };
196
197 const otCryptoSha256Hash kHash4 = {{
198 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
199 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b,
200 }};
201
202 const uint8_t kKey5[] = {
203 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
204 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
205 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
206 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
207 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
208 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
209 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
210 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
211 };
212
213 const char kData5[] = "This is a test using a larger than block-size key and a larger than block-size data. The "
214 "key needs to be hashed before being used by the HMAC algorithm.";
215
216 const otCryptoSha256Hash kHash5 = {{
217 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
218 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2,
219 }};
220
221 static const TestCase kTestCases[] = {
222 {{&kKey1[0], sizeof(kKey1), 0}, kData1, sizeof(kData1) - 1, kHash1},
223 {{reinterpret_cast<const uint8_t *>(&kKey2[0]), sizeof(kKey2) - 1, 0}, kData2, sizeof(kData2) - 1, kHash2},
224 {{&kKey3[0], sizeof(kKey3), 0}, kData3, sizeof(kData3), kHash3},
225 {{&kKey4[0], sizeof(kKey4), 0}, kData4, sizeof(kData4), kHash4},
226 {{&kKey5[0], sizeof(kKey5), 0}, kData5, sizeof(kData5) - 1, kHash5},
227 };
228
229 Instance *instance = testInitInstance();
230 MessagePool *messagePool;
231 Message *message;
232 uint16_t offsets[GetArrayLength(kTestCases)];
233 uint8_t index;
234
235 printf("TestHmacSha256\n");
236
237 VerifyOrQuit(instance != nullptr);
238
239 messagePool = &instance->Get<MessagePool>();
240 VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
241
242 for (const TestCase &testCase : kTestCases)
243 {
244 Crypto::HmacSha256 hmac;
245 Crypto::HmacSha256::Hash hash;
246
247 hmac.Start(static_cast<const Crypto::Key &>(testCase.mKey));
248 hmac.Update(testCase.mData, testCase.mDataLength);
249 hmac.Finish(hash);
250
251 VerifyOrQuit(hash == static_cast<const Crypto::HmacSha256::Hash &>(testCase.mHash));
252 }
253
254 // Append all test case `mData` in the message.
255
256 index = 0;
257
258 for (const TestCase &testCase : kTestCases)
259 {
260 SuccessOrQuit(message->Append("Hello"));
261 offsets[index++] = message->GetLength();
262 SuccessOrQuit(message->AppendBytes(testCase.mData, testCase.mDataLength));
263 SuccessOrQuit(message->Append("There"));
264 }
265
266 index = 0;
267
268 for (const TestCase &testCase : kTestCases)
269 {
270 Crypto::HmacSha256 hmac;
271 Crypto::HmacSha256::Hash hash;
272
273 hmac.Start(static_cast<const Crypto::Key &>(testCase.mKey));
274 hmac.Update(*message, offsets[index++], testCase.mDataLength);
275 hmac.Finish(hash);
276
277 VerifyOrQuit(hash == static_cast<const Crypto::HmacSha256::Hash &>(testCase.mHash));
278 }
279
280 message->Free();
281
282 testFreeInstance(instance);
283 }
284
285 } // namespace ot
286
main(void)287 int main(void)
288 {
289 ot::TestSha256();
290 ot::TestHmacSha256();
291 printf("All tests passed\n");
292 return 0;
293 }
294