crypto.c revision 1.1.1.10 1 1.1.1.9 christos /* $NetBSD: crypto.c,v 1.1.1.10 2024/08/18 20:37:47 christos Exp $ */
2 1.1.1.9 christos
3 1.1 christos #include "config.h"
4 1.1 christos #include "unity.h"
5 1.1 christos #include "ntp_types.h"
6 1.1 christos
7 1.1 christos #include "sntptest.h"
8 1.1 christos #include "crypto.h"
9 1.1 christos
10 1.1.1.7 christos #define CMAC "AES128CMAC"
11 1.1.1.7 christos
12 1.1 christos #define SHA1_LENGTH 20
13 1.1.1.7 christos #define CMAC_LENGTH 16
14 1.1 christos
15 1.1.1.3 christos
16 1.1.1.10 christos void test_MakeSHAKE128Mac(void);
17 1.1.1.3 christos void test_MakeSHA1Mac(void);
18 1.1.1.7 christos void test_MakeCMac(void);
19 1.1.1.10 christos void test_VerifySHAKE128(void);
20 1.1.1.3 christos void test_VerifySHA1(void);
21 1.1.1.7 christos void test_VerifyCMAC(void);
22 1.1.1.3 christos void test_VerifyFailure(void);
23 1.1.1.3 christos void test_PacketSizeNotMultipleOfFourBytes(void);
24 1.1.1.3 christos
25 1.1.1.7 christos void VerifyLocalCMAC(struct key *cmac);
26 1.1.1.7 christos void VerifyOpenSSLCMAC(struct key *cmac);
27 1.1.1.7 christos
28 1.1.1.3 christos
29 1.1.1.3 christos void
30 1.1.1.10 christos test_MakeSHAKE128Mac(void)
31 1.1.1.6 christos {
32 1.1.1.10 christos #ifdef OPENSSL
33 1.1 christos
34 1.1.1.10 christos const char KEY[] = "SHAKE128 unit test key";
35 1.1.1.10 christos const u_char PAYLOAD[] = "packettestdata16";
36 1.1.1.10 christos const size_t PAYLOAD_LEN = sizeof(PAYLOAD) - 1;
37 1.1.1.10 christos const u_char EXPECTED_DIGEST[] =
38 1.1.1.10 christos "\x62\x5A\x8F\xE4\x66\xCB\xF3\xA6"
39 1.1.1.10 christos "\x73\x62\x68\x8D\x11\xB8\x42\xBB";
40 1.1.1.10 christos u_char actual[sizeof(EXPECTED_DIGEST) - 1];
41 1.1.1.10 christos struct key sk;
42 1.1.1.10 christos
43 1.1.1.10 christos sk.next = NULL;
44 1.1.1.10 christos sk.key_id = 10;
45 1.1.1.10 christos sk.key_len = sizeof(KEY) - 1;
46 1.1.1.10 christos memcpy(&sk.key_seq, KEY, min(sizeof(sk.key_seq), sk.key_len));
47 1.1.1.10 christos strlcpy(sk.typen, "SHAKE128", sizeof(sk.typen));
48 1.1.1.10 christos sk.typei = keytype_from_text(sk.typen, NULL);
49 1.1.1.10 christos
50 1.1.1.10 christos TEST_ASSERT_EQUAL(sizeof(actual),
51 1.1.1.10 christos make_mac(PAYLOAD, PAYLOAD_LEN, &sk, actual,
52 1.1.1.10 christos sizeof(actual)));
53 1.1 christos
54 1.1.1.10 christos TEST_ASSERT_EQUAL_HEX8_ARRAY(EXPECTED_DIGEST, actual, sizeof(actual));
55 1.1.1.10 christos #else
56 1.1.1.10 christos
57 1.1.1.10 christos TEST_IGNORE_MESSAGE("OpenSSL not found, skipping...");
58 1.1.1.10 christos
59 1.1.1.10 christos #endif /* OPENSSL */
60 1.1 christos }
61 1.1 christos
62 1.1 christos
63 1.1.1.3 christos void
64 1.1.1.6 christos test_MakeSHA1Mac(void)
65 1.1.1.6 christos {
66 1.1 christos #ifdef OPENSSL
67 1.1.1.6 christos
68 1.1 christos const char* PKT_DATA = "abcdefgh0123";
69 1.1 christos const int PKT_LEN = strlen(PKT_DATA);
70 1.1 christos const char* EXPECTED_DIGEST =
71 1.1 christos "\x17\xaa\x82\x97\xc7\x17\x13\x6a\x9b\xa9"
72 1.1 christos "\x63\x85\xb4\xce\xbe\x94\xa0\x97\x16\x1d";
73 1.1 christos char actual[SHA1_LENGTH];
74 1.1 christos
75 1.1 christos struct key sha1;
76 1.1 christos sha1.next = NULL;
77 1.1 christos sha1.key_id = 20;
78 1.1 christos sha1.key_len = 7;
79 1.1 christos memcpy(&sha1.key_seq, "sha1seq", sha1.key_len);
80 1.1.1.7 christos strlcpy(sha1.typen, "SHA1", sizeof(sha1.typen));
81 1.1.1.7 christos sha1.typei = keytype_from_text(sha1.typen, NULL);
82 1.1 christos
83 1.1 christos TEST_ASSERT_EQUAL(SHA1_LENGTH,
84 1.1.1.10 christos make_mac(PKT_DATA, PKT_LEN, &sha1, actual,
85 1.1.1.10 christos SHA1_LENGTH));
86 1.1 christos
87 1.1.1.3 christos TEST_ASSERT_EQUAL_MEMORY(EXPECTED_DIGEST, actual, SHA1_LENGTH);
88 1.1.1.10 christos
89 1.1 christos #else
90 1.1.1.10 christos
91 1.1 christos TEST_IGNORE_MESSAGE("OpenSSL not found, skipping...");
92 1.1.1.10 christos
93 1.1 christos #endif /* OPENSSL */
94 1.1 christos }
95 1.1 christos
96 1.1 christos
97 1.1.1.3 christos void
98 1.1.1.7 christos test_MakeCMac(void)
99 1.1.1.7 christos {
100 1.1.1.8 christos #if defined(OPENSSL) && defined(ENABLE_CMAC)
101 1.1.1.7 christos
102 1.1.1.7 christos const char* PKT_DATA = "abcdefgh0123";
103 1.1.1.7 christos const int PKT_LEN = strlen(PKT_DATA);
104 1.1.1.7 christos const char* EXPECTED_DIGEST =
105 1.1.1.7 christos "\xdd\x35\xd5\xf5\x14\x23\xd9\xd6"
106 1.1.1.7 christos "\x38\x5d\x29\x80\xfe\x51\xb9\x6b";
107 1.1.1.7 christos char actual[CMAC_LENGTH];
108 1.1.1.7 christos struct key cmac;
109 1.1.1.10 christos
110 1.1.1.7 christos cmac.next = NULL;
111 1.1.1.7 christos cmac.key_id = 30;
112 1.1.1.7 christos cmac.key_len = CMAC_LENGTH;
113 1.1.1.7 christos memcpy(&cmac.key_seq, "aes-128-cmac-seq", cmac.key_len);
114 1.1.1.7 christos memcpy(&cmac.typen, CMAC, strlen(CMAC) + 1);
115 1.1.1.7 christos
116 1.1.1.7 christos TEST_ASSERT_EQUAL(CMAC_LENGTH,
117 1.1.1.10 christos make_mac(PKT_DATA, PKT_LEN, &cmac, actual, CMAC_LENGTH));
118 1.1.1.7 christos
119 1.1.1.7 christos TEST_ASSERT_EQUAL_MEMORY(EXPECTED_DIGEST, actual, CMAC_LENGTH);
120 1.1.1.10 christos
121 1.1.1.7 christos #else
122 1.1.1.10 christos
123 1.1.1.10 christos TEST_IGNORE_MESSAGE("CMAC not enabled, skipping...");
124 1.1.1.10 christos
125 1.1.1.7 christos #endif /* OPENSSL */
126 1.1.1.7 christos }
127 1.1.1.7 christos
128 1.1.1.7 christos
129 1.1.1.7 christos void
130 1.1.1.10 christos test_VerifySHAKE128(void)
131 1.1.1.6 christos {
132 1.1.1.10 christos #ifdef OPENSSL
133 1.1.1.10 christos const char KEY[] = "SHAKE128 unit test key";
134 1.1.1.10 christos const u_char PAYLOAD[] = "packettestdata16";
135 1.1.1.10 christos const size_t PAYLOAD_LEN = sizeof(PAYLOAD) - 1;
136 1.1.1.10 christos const u_char EXPECTED_DIGEST[] =
137 1.1.1.10 christos "\x62\x5A\x8F\xE4\x66\xCB\xF3\xA6"
138 1.1.1.10 christos "\x73\x62\x68\x8D\x11\xB8\x42\xBB";
139 1.1.1.10 christos const size_t DIGEST_LEN = sizeof(EXPECTED_DIGEST) - 1;
140 1.1.1.10 christos struct key sk;
141 1.1.1.10 christos u_char PKT_DATA[ PAYLOAD_LEN + sizeof(sk.key_id)
142 1.1.1.10 christos + DIGEST_LEN];
143 1.1.1.10 christos u_char *p;
144 1.1.1.10 christos
145 1.1.1.10 christos sk.next = NULL;
146 1.1.1.10 christos sk.key_id = 0;
147 1.1.1.10 christos sk.key_len = sizeof(KEY) - 1;
148 1.1.1.10 christos memcpy(&sk.key_seq, KEY, min(sizeof(sk.key_seq), sk.key_len));
149 1.1.1.10 christos strlcpy(sk.typen, "SHAKE128", sizeof(sk.typen));
150 1.1.1.10 christos sk.typei = keytype_from_text(sk.typen, NULL);
151 1.1.1.10 christos
152 1.1.1.10 christos p = PKT_DATA;
153 1.1.1.10 christos memcpy(p, PAYLOAD, PAYLOAD_LEN); p += PAYLOAD_LEN;
154 1.1.1.10 christos memcpy(p, &sk.key_id, sizeof(sk.key_id)); p += sizeof(sk.key_id);
155 1.1.1.10 christos memcpy(p, EXPECTED_DIGEST, DIGEST_LEN); p += DIGEST_LEN;
156 1.1.1.10 christos TEST_ASSERT_TRUE(sizeof(PKT_DATA) == p - PKT_DATA);
157 1.1.1.10 christos
158 1.1.1.10 christos TEST_ASSERT_TRUE(auth_md5(PKT_DATA, PAYLOAD_LEN, DIGEST_LEN, &sk));
159 1.1.1.10 christos #else
160 1.1 christos
161 1.1.1.10 christos TEST_IGNORE_MESSAGE("OpenSSL not found, skipping...");
162 1.1 christos
163 1.1.1.10 christos #endif /* OPENSSL */
164 1.1 christos }
165 1.1 christos
166 1.1 christos
167 1.1.1.3 christos void
168 1.1.1.6 christos test_VerifySHA1(void)
169 1.1.1.6 christos {
170 1.1 christos #ifdef OPENSSL
171 1.1.1.6 christos
172 1.1 christos const char* PKT_DATA =
173 1.1.1.6 christos "sometestdata" /* Data */
174 1.1.1.6 christos "\0\0\0\0" /* Key-ID (unused) */
175 1.1.1.6 christos "\xad\x07\xde\x36\x39\xa6\x77\xfa\x5b\xce" /* MAC */
176 1.1.1.6 christos "\x2d\x8a\x7d\x06\x96\xe6\x0c\xbc\xed\xe1";
177 1.1 christos const int PKT_LEN = 12;
178 1.1 christos struct key sha1;
179 1.1.1.10 christos
180 1.1 christos sha1.next = NULL;
181 1.1 christos sha1.key_id = 0;
182 1.1 christos sha1.key_len = 7;
183 1.1 christos memcpy(&sha1.key_seq, "sha1key", sha1.key_len);
184 1.1.1.10 christos strlcpy(sha1.typen, "SHA1", sizeof(sha1.typen));
185 1.1.1.7 christos sha1.typei = keytype_from_text(sha1.typen, NULL);
186 1.1 christos
187 1.1.1.6 christos TEST_ASSERT_TRUE(auth_md5(PKT_DATA, PKT_LEN, SHA1_LENGTH, &sha1));
188 1.1.1.10 christos
189 1.1 christos #else
190 1.1.1.10 christos
191 1.1 christos TEST_IGNORE_MESSAGE("OpenSSL not found, skipping...");
192 1.1.1.10 christos
193 1.1 christos #endif /* OPENSSL */
194 1.1 christos }
195 1.1 christos
196 1.1.1.7 christos
197 1.1.1.7 christos void
198 1.1.1.7 christos test_VerifyCMAC(void)
199 1.1.1.7 christos {
200 1.1.1.7 christos struct key cmac;
201 1.1.1.7 christos
202 1.1.1.7 christos cmac.next = NULL;
203 1.1.1.7 christos cmac.key_id = 0;
204 1.1.1.7 christos cmac.key_len = CMAC_LENGTH;
205 1.1.1.7 christos memcpy(&cmac.key_seq, "aes-128-cmac-key", cmac.key_len);
206 1.1.1.7 christos memcpy(&cmac.typen, CMAC, strlen(CMAC) + 1);
207 1.1.1.7 christos
208 1.1.1.7 christos VerifyOpenSSLCMAC(&cmac);
209 1.1.1.7 christos VerifyLocalCMAC(&cmac);
210 1.1.1.7 christos }
211 1.1.1.7 christos
212 1.1.1.7 christos
213 1.1.1.7 christos void
214 1.1.1.7 christos VerifyOpenSSLCMAC(struct key *cmac)
215 1.1.1.7 christos {
216 1.1.1.8 christos #if defined(OPENSSL) && defined(ENABLE_CMAC)
217 1.1.1.7 christos
218 1.1.1.7 christos /* XXX: HMS: auth_md5 must be renamed/incorrect. */
219 1.1.1.7 christos // TEST_ASSERT_TRUE(auth_md5(PKT_DATA, PKT_LEN, CMAC_LENGTH, cmac));
220 1.1.1.7 christos TEST_IGNORE_MESSAGE("VerifyOpenSSLCMAC needs to be implemented, skipping...");
221 1.1.1.7 christos
222 1.1.1.7 christos #else
223 1.1.1.10 christos
224 1.1.1.10 christos TEST_IGNORE_MESSAGE("CMAC not enabled, skipping...");
225 1.1.1.10 christos
226 1.1.1.7 christos #endif /* OPENSSL */
227 1.1.1.7 christos return;
228 1.1.1.7 christos }
229 1.1.1.7 christos
230 1.1.1.7 christos
231 1.1.1.7 christos void
232 1.1.1.7 christos VerifyLocalCMAC(struct key *cmac)
233 1.1.1.7 christos {
234 1.1.1.7 christos
235 1.1.1.7 christos /* XXX: HMS: auth_md5 must be renamed/incorrect. */
236 1.1.1.7 christos // TEST_ASSERT_TRUE(auth_md5(PKT_DATA, PKT_LEN, CMAC_LENGTH, cmac));
237 1.1.1.7 christos
238 1.1.1.7 christos TEST_IGNORE_MESSAGE("Hook in the local AES-128-CMAC check!");
239 1.1.1.7 christos
240 1.1.1.7 christos return;
241 1.1.1.7 christos }
242 1.1.1.7 christos
243 1.1.1.7 christos
244 1.1.1.3 christos void
245 1.1.1.6 christos test_VerifyFailure(void)
246 1.1.1.6 christos {
247 1.1.1.10 christos /*
248 1.1.1.10 christos * We use a copy of test_VerifySHAKE128(), but modify the
249 1.1.1.10 christos * last packet octet to make sure verification fails.
250 1.1.1.6 christos */
251 1.1.1.10 christos #ifdef OPENSSL
252 1.1.1.10 christos const char KEY[] = "SHAKE128 unit test key";
253 1.1.1.10 christos const u_char PAYLOAD[] = "packettestdata1_";
254 1.1.1.10 christos /* last packet byte different */
255 1.1.1.10 christos const size_t PAYLOAD_LEN = sizeof(PAYLOAD) - 1;
256 1.1.1.10 christos const u_char EXPECTED_DIGEST[] =
257 1.1.1.10 christos "\x62\x5A\x8F\xE4\x66\xCB\xF3\xA6"
258 1.1.1.10 christos "\x73\x62\x68\x8D\x11\xB8\x42\xBB";
259 1.1.1.10 christos const size_t DIGEST_LEN = sizeof(EXPECTED_DIGEST) - 1;
260 1.1.1.10 christos struct key sk;
261 1.1.1.10 christos u_char PKT_DATA[ PAYLOAD_LEN + sizeof(sk.key_id)
262 1.1.1.10 christos + DIGEST_LEN];
263 1.1.1.10 christos u_char *p;
264 1.1.1.10 christos
265 1.1.1.10 christos sk.next = NULL;
266 1.1.1.10 christos sk.key_id = 0;
267 1.1.1.10 christos sk.key_len = sizeof(KEY) - 1;
268 1.1.1.10 christos memcpy(&sk.key_seq, KEY, min(sizeof(sk.key_seq), sk.key_len));
269 1.1.1.10 christos strlcpy(sk.typen, "SHAKE128", sizeof(sk.typen));
270 1.1.1.10 christos sk.typei = keytype_from_text(sk.typen, NULL);
271 1.1.1.10 christos
272 1.1.1.10 christos p = PKT_DATA;
273 1.1.1.10 christos memcpy(p, PAYLOAD, PAYLOAD_LEN); p += PAYLOAD_LEN;
274 1.1.1.10 christos memcpy(p, &sk.key_id, sizeof(sk.key_id)); p += sizeof(sk.key_id);
275 1.1.1.10 christos memcpy(p, EXPECTED_DIGEST, DIGEST_LEN); p += DIGEST_LEN;
276 1.1.1.10 christos TEST_ASSERT_TRUE(sizeof(PKT_DATA) == p - PKT_DATA);
277 1.1 christos
278 1.1.1.10 christos TEST_ASSERT_FALSE(auth_md5(PKT_DATA, PAYLOAD_LEN, DIGEST_LEN, &sk));
279 1.1.1.10 christos #else
280 1.1 christos
281 1.1.1.10 christos TEST_IGNORE_MESSAGE("OpenSSL not found, skipping...");
282 1.1.1.10 christos
283 1.1.1.10 christos #endif /* OPENSSL */
284 1.1 christos }
285 1.1 christos
286 1.1.1.3 christos
287 1.1.1.3 christos void
288 1.1.1.6 christos test_PacketSizeNotMultipleOfFourBytes(void)
289 1.1.1.6 christos {
290 1.1.1.10 christos /*
291 1.1.1.10 christos * We use a copy of test_MakeSHAKE128Mac(), but modify
292 1.1.1.10 christos * the packet length to 17.
293 1.1.1.10 christos */
294 1.1.1.10 christos #ifdef OPENSSL
295 1.1.1.10 christos
296 1.1.1.10 christos const char KEY[] = "SHAKE128 unit test key";
297 1.1.1.10 christos const u_char PAYLOAD[] = "packettestdata_17";
298 1.1.1.10 christos const size_t PAYLOAD_LEN = sizeof(PAYLOAD) - 1;
299 1.1.1.10 christos const u_char EXPECTED_DIGEST[] =
300 1.1.1.10 christos "\x62\x5A\x8F\xE4\x66\xCB\xF3\xA6"
301 1.1.1.10 christos "\x73\x62\x68\x8D\x11\xB8\x42\xBB";
302 1.1.1.10 christos u_char actual[sizeof(EXPECTED_DIGEST) - 1];
303 1.1.1.10 christos struct key sk;
304 1.1.1.10 christos
305 1.1.1.10 christos sk.next = NULL;
306 1.1.1.10 christos sk.key_id = 10;
307 1.1.1.10 christos sk.key_len = sizeof(KEY) - 1;
308 1.1.1.10 christos memcpy(&sk.key_seq, KEY, min(sizeof(sk.key_seq), sk.key_len));
309 1.1.1.10 christos strlcpy(sk.typen, "SHAKE128", sizeof(sk.typen));
310 1.1.1.10 christos sk.typei = keytype_from_text(sk.typen, NULL);
311 1.1.1.10 christos
312 1.1.1.10 christos TEST_ASSERT_EQUAL(0,
313 1.1.1.10 christos make_mac(PAYLOAD, PAYLOAD_LEN, &sk, actual,
314 1.1.1.10 christos sizeof(actual)));
315 1.1.1.10 christos #else
316 1.1 christos
317 1.1.1.10 christos TEST_IGNORE_MESSAGE("OpenSSL not found, skipping...");
318 1.1.1.10 christos
319 1.1.1.10 christos #endif /* OPENSSL */
320 1.1 christos }
321