1 /*
2 * common module tests
3 * Copyright (c) 2014-2019, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "utils/includes.h"
10
11 #include "utils/common.h"
12 #include "utils/module_tests.h"
13 #include "crypto/crypto.h"
14 #include "crypto/dh_groups.h"
15 #include "ieee802_11_common.h"
16 #include "ieee802_11_defs.h"
17 #include "gas.h"
18 #include "wpa_common.h"
19 #include "sae.h"
20
21
22 struct ieee802_11_parse_test_data {
23 u8 *data;
24 size_t len;
25 ParseRes result;
26 int count;
27 };
28
29 static const struct ieee802_11_parse_test_data parse_tests[] = {
30 { (u8 *) "", 0, ParseOK, 0 },
31 { (u8 *) " ", 1, ParseFailed, 0 },
32 { (u8 *) "\xff\x00", 2, ParseUnknown, 1 },
33 { (u8 *) "\xff\x01", 2, ParseFailed, 0 },
34 { (u8 *) "\xdd\x03\x01\x02\x03", 5, ParseUnknown, 1 },
35 { (u8 *) "\xdd\x04\x01\x02\x03\x04", 6, ParseUnknown, 1 },
36 { (u8 *) "\xdd\x04\x00\x50\xf2\x02", 6, ParseUnknown, 1 },
37 { (u8 *) "\xdd\x05\x00\x50\xf2\x02\x02", 7, ParseOK, 1 },
38 { (u8 *) "\xdd\x05\x00\x50\xf2\x02\xff", 7, ParseUnknown, 1 },
39 { (u8 *) "\xdd\x04\x00\x50\xf2\xff", 6, ParseUnknown, 1 },
40 { (u8 *) "\xdd\x04\x50\x6f\x9a\xff", 6, ParseUnknown, 1 },
41 { (u8 *) "\xdd\x04\x00\x90\x4c\x33", 6, ParseOK, 1 },
42 { (u8 *) "\xdd\x04\x00\x90\x4c\xff\xdd\x04\x00\x90\x4c\x33", 12,
43 ParseUnknown, 2 },
44 { (u8 *) "\x10\x01\x00\x21\x00", 5, ParseOK, 2 },
45 { (u8 *) "\x24\x00", 2, ParseOK, 1 },
46 { (u8 *) "\x38\x00", 2, ParseOK, 1 },
47 { (u8 *) "\x54\x00", 2, ParseOK, 1 },
48 { (u8 *) "\x5a\x00", 2, ParseOK, 1 },
49 { (u8 *) "\x65\x00", 2, ParseOK, 1 },
50 { (u8 *) "\x65\x12\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11",
51 20, ParseOK, 1 },
52 { (u8 *) "\x6e\x00", 2, ParseOK, 1 },
53 { (u8 *) "\xc7\x00", 2, ParseOK, 1 },
54 { (u8 *) "\xc7\x01\x00", 3, ParseOK, 1 },
55 { (u8 *) "\x03\x00\x2a\x00\x36\x00\x37\x00\x38\x00\x2d\x00\x3d\x00\xbf\x00\xc0\x00",
56 18, ParseOK, 9 },
57 { (u8 *) "\x8b\x00", 2, ParseOK, 1 },
58 { (u8 *) "\xdd\x04\x00\x90\x4c\x04", 6, ParseUnknown, 1 },
59 { (u8 *) "\xed\x00", 2, ParseOK, 1 },
60 { (u8 *) "\xef\x00", 2, ParseOK, 1 },
61 { (u8 *) "\xef\x01\x11", 3, ParseOK, 1 },
62 { (u8 *) "\xf0\x00", 2, ParseOK, 1 },
63 { (u8 *) "\xf1\x00", 2, ParseOK, 1 },
64 { (u8 *) "\xf1\x02\x11\x22", 4, ParseOK, 1 },
65 { (u8 *) "\xf2\x00", 2, ParseOK, 1 },
66 { (u8 *) "\xff\x00", 2, ParseUnknown, 1 },
67 { (u8 *) "\xff\x01\x00", 3, ParseUnknown, 1 },
68 { (u8 *) "\xff\x01\x01", 3, ParseOK, 1 },
69 { (u8 *) "\xff\x02\x01\x00", 4, ParseOK, 1 },
70 { (u8 *) "\xff\x01\x02", 3, ParseOK, 1 },
71 { (u8 *) "\xff\x04\x02\x11\x22\x33", 6, ParseOK, 1 },
72 { (u8 *) "\xff\x01\x04", 3, ParseOK, 1 },
73 { (u8 *) "\xff\x01\x05", 3, ParseOK, 1 },
74 { (u8 *) "\xff\x0d\x05\x11\x22\x33\x44\x55\x55\x11\x22\x33\x44\x55\x55",
75 15, ParseOK, 1 },
76 { (u8 *) "\xff\x01\x06", 3, ParseOK, 1 },
77 { (u8 *) "\xff\x02\x06\x00", 4, ParseOK, 1 },
78 { (u8 *) "\xff\x01\x07", 3, ParseOK, 1 },
79 { (u8 *) "\xff\x09\x07\x11\x22\x33\x44\x55\x66\x77\x88", 11,
80 ParseOK, 1 },
81 { (u8 *) "\xff\x01\x0c", 3, ParseOK, 1 },
82 { (u8 *) "\xff\x02\x0c\x00", 4, ParseOK, 1 },
83 { (u8 *) "\xff\x01\x0d", 3, ParseOK, 1 },
84 { NULL, 0, ParseOK, 0 }
85 };
86
ieee802_11_parse_tests(void)87 static int ieee802_11_parse_tests(void)
88 {
89 int i, ret = 0;
90 struct wpabuf *buf;
91
92 wpa_printf(MSG_INFO, "ieee802_11_parse tests");
93
94 for (i = 0; parse_tests[i].data; i++) {
95 const struct ieee802_11_parse_test_data *test;
96 struct ieee802_11_elems elems;
97 ParseRes res;
98
99 test = &parse_tests[i];
100 res = ieee802_11_parse_elems(test->data, test->len, &elems, 1);
101 if (res != test->result ||
102 ieee802_11_ie_count(test->data, test->len) != test->count) {
103 wpa_printf(MSG_ERROR, "ieee802_11_parse test %d failed",
104 i);
105 ret = -1;
106 }
107 }
108
109 if (ieee802_11_vendor_ie_concat((const u8 *) "\x00\x01", 2, 0) != NULL)
110 {
111 wpa_printf(MSG_ERROR,
112 "ieee802_11_vendor_ie_concat test failed");
113 ret = -1;
114 }
115
116 buf = ieee802_11_vendor_ie_concat((const u8 *) "\xdd\x05\x11\x22\x33\x44\x01\xdd\x05\x11\x22\x33\x44\x02\x00\x01",
117 16, 0x11223344);
118 do {
119 const u8 *pos;
120
121 if (!buf) {
122 wpa_printf(MSG_ERROR,
123 "ieee802_11_vendor_ie_concat test 2 failed");
124 ret = -1;
125 break;
126 }
127
128 if (wpabuf_len(buf) != 2) {
129 wpa_printf(MSG_ERROR,
130 "ieee802_11_vendor_ie_concat test 3 failed");
131 ret = -1;
132 break;
133 }
134
135 pos = wpabuf_head(buf);
136 if (pos[0] != 0x01 || pos[1] != 0x02) {
137 wpa_printf(MSG_ERROR,
138 "ieee802_11_vendor_ie_concat test 3 failed");
139 ret = -1;
140 break;
141 }
142 } while (0);
143 wpabuf_free(buf);
144
145 return ret;
146 }
147
148
149 struct rsn_ie_parse_test_data {
150 u8 *data;
151 size_t len;
152 int result;
153 };
154
155 static const struct rsn_ie_parse_test_data rsn_parse_tests[] = {
156 { (u8 *) "", 0, -1 },
157 { (u8 *) "\x30\x00", 2, -1 },
158 { (u8 *) "\x30\x02\x01\x00", 4, 0 },
159 { (u8 *) "\x30\x02\x00\x00", 4, -2 },
160 { (u8 *) "\x30\x02\x02\x00", 4, -2 },
161 { (u8 *) "\x30\x02\x00\x01", 4, -2 },
162 { (u8 *) "\x30\x02\x00\x00\x00", 5, -2 },
163 { (u8 *) "\x30\x03\x01\x00\x00", 5, -3 },
164 { (u8 *) "\x30\x06\x01\x00\x00\x00\x00\x00", 8, -1 },
165 { (u8 *) "\x30\x06\x01\x00\x00\x0f\xac\x04", 8, 0 },
166 { (u8 *) "\x30\x07\x01\x00\x00\x0f\xac\x04\x00", 9, -5 },
167 { (u8 *) "\x30\x08\x01\x00\x00\x0f\xac\x04\x00\x00", 10, -4 },
168 { (u8 *) "\x30\x08\x01\x00\x00\x0f\xac\x04\x00\x01", 10, -4 },
169 { (u8 *) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04",
170 14, 0 },
171 { (u8 *) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x00\x01\x00\x0f\xac\x04",
172 14, -4 },
173 { (u8 *) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x06",
174 14, -1 },
175 { (u8 *) "\x30\x10\x01\x00\x00\x0f\xac\x04\x02\x00\x00\x0f\xac\x04\x00\x0f\xac\x08",
176 18, 0 },
177 { (u8 *) "\x30\x0d\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00",
178 15, -7 },
179 { (u8 *) "\x30\x0e\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00\x00",
180 16, -6 },
181 { (u8 *) "\x30\x0e\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00\x01",
182 16, -6 },
183 { (u8 *) "\x30\x12\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01",
184 20, 0 },
185 { (u8 *) "\x30\x16\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x02\x00\x00\x0f\xac\x01\x00\x0f\xac\x02",
186 24, 0 },
187 { (u8 *) "\x30\x13\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00",
188 21, 0 },
189 { (u8 *) "\x30\x14\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00\x00",
190 22, 0 },
191 { (u8 *) "\x30\x16\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00\x00\x00\x00",
192 24, 0 },
193 { (u8 *) "\x30\x16\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00\x00\x00\x01",
194 24, -9 },
195 { (u8 *) "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00\x00\x00\x00\x00\x00\x00\x00",
196 28, -10 },
197 { (u8 *) "\x30\x1a\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00\x00\x00\x00\x00\x0f\xac\x06",
198 28, 0 },
199 { (u8 *) "\x30\x1c\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00\x00\x00\x00\x00\x0f\xac\x06\x01\x02",
200 30, 0 },
201 { NULL, 0, 0 }
202 };
203
rsn_ie_parse_tests(void)204 static int rsn_ie_parse_tests(void)
205 {
206 int i, ret = 0;
207
208 wpa_printf(MSG_INFO, "rsn_ie_parse tests");
209
210 for (i = 0; rsn_parse_tests[i].data; i++) {
211 const struct rsn_ie_parse_test_data *test;
212 struct wpa_ie_data data;
213
214 test = &rsn_parse_tests[i];
215 if (wpa_parse_wpa_ie_rsn(test->data, test->len, &data) !=
216 test->result) {
217 wpa_printf(MSG_ERROR, "rsn_ie_parse test %d failed", i);
218 ret = -1;
219 }
220 }
221
222 return ret;
223 }
224
225
gas_tests(void)226 static int gas_tests(void)
227 {
228 struct wpabuf *buf;
229
230 wpa_printf(MSG_INFO, "gas tests");
231 gas_anqp_set_len(NULL);
232
233 buf = wpabuf_alloc(1);
234 if (buf == NULL)
235 return -1;
236 gas_anqp_set_len(buf);
237 wpabuf_free(buf);
238
239 buf = wpabuf_alloc(20);
240 if (buf == NULL)
241 return -1;
242 wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
243 wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_REQ);
244 wpabuf_put_u8(buf, 0);
245 wpabuf_put_be32(buf, 0);
246 wpabuf_put_u8(buf, 0);
247 gas_anqp_set_len(buf);
248 wpabuf_free(buf);
249
250 return 0;
251 }
252
253
sae_tests(void)254 static int sae_tests(void)
255 {
256 #ifdef CONFIG_SAE
257 struct sae_data sae;
258 int ret = -1;
259 /* IEEE Std 802.11-2020, Annex J.10 */
260 const u8 addr1[ETH_ALEN] = { 0x4d, 0x3f, 0x2f, 0xff, 0xe3, 0x87 };
261 const u8 addr2[ETH_ALEN] = { 0xa5, 0xd8, 0xaa, 0x95, 0x8e, 0x3c };
262 const char *ssid = "byteme";
263 const char *pw = "mekmitasdigoat";
264 const char *pwid = "psk4internet";
265 const u8 local_rand[] = {
266 0x99, 0x24, 0x65, 0xfd, 0x3d, 0xaa, 0x3c, 0x60,
267 0xaa, 0x65, 0x65, 0xb7, 0xf6, 0x2a, 0x2a, 0x7f,
268 0x2e, 0x12, 0xdd, 0x12, 0xf1, 0x98, 0xfa, 0xf4,
269 0xfb, 0xed, 0x89, 0xd7, 0xff, 0x1a, 0xce, 0x94
270 };
271 const u8 local_mask[] = {
272 0x95, 0x07, 0xa9, 0x0f, 0x77, 0x7a, 0x04, 0x4d,
273 0x6a, 0x08, 0x30, 0xb9, 0x1e, 0xa3, 0xd5, 0xdd,
274 0x70, 0xbe, 0xce, 0x44, 0xe1, 0xac, 0xff, 0xb8,
275 0x69, 0x83, 0xb5, 0xe1, 0xbf, 0x9f, 0xb3, 0x22
276 };
277 const u8 local_commit[] = {
278 0x13, 0x00, 0x2e, 0x2c, 0x0f, 0x0d, 0xb5, 0x24,
279 0x40, 0xad, 0x14, 0x6d, 0x96, 0x71, 0x14, 0xce,
280 0x00, 0x5c, 0xe1, 0xea, 0xb0, 0xaa, 0x2c, 0x2e,
281 0x5c, 0x28, 0x71, 0xb7, 0x74, 0xf6, 0xc2, 0x57,
282 0x5c, 0x65, 0xd5, 0xad, 0x9e, 0x00, 0x82, 0x97,
283 0x07, 0xaa, 0x36, 0xba, 0x8b, 0x85, 0x97, 0x38,
284 0xfc, 0x96, 0x1d, 0x08, 0x24, 0x35, 0x05, 0xf4,
285 0x7c, 0x03, 0x53, 0x76, 0xd7, 0xac, 0x4b, 0xc8,
286 0xd7, 0xb9, 0x50, 0x83, 0xbf, 0x43, 0x82, 0x7d,
287 0x0f, 0xc3, 0x1e, 0xd7, 0x78, 0xdd, 0x36, 0x71,
288 0xfd, 0x21, 0xa4, 0x6d, 0x10, 0x91, 0xd6, 0x4b,
289 0x6f, 0x9a, 0x1e, 0x12, 0x72, 0x62, 0x13, 0x25,
290 0xdb, 0xe1
291 };
292 const u8 peer_commit[] = {
293 0x13, 0x00, 0x59, 0x1b, 0x96, 0xf3, 0x39, 0x7f,
294 0xb9, 0x45, 0x10, 0x08, 0x48, 0xe7, 0xb5, 0x50,
295 0x54, 0x3b, 0x67, 0x20, 0xd8, 0x83, 0x37, 0xee,
296 0x93, 0xfc, 0x49, 0xfd, 0x6d, 0xf7, 0xe0, 0x8b,
297 0x52, 0x23, 0xe7, 0x1b, 0x9b, 0xb0, 0x48, 0xd3,
298 0x87, 0x3f, 0x20, 0x55, 0x69, 0x53, 0xa9, 0x6c,
299 0x91, 0x53, 0x6f, 0xd8, 0xee, 0x6c, 0xa9, 0xb4,
300 0xa6, 0x8a, 0x14, 0x8b, 0x05, 0x6a, 0x90, 0x9b,
301 0xe0, 0x3e, 0x83, 0xae, 0x20, 0x8f, 0x60, 0xf8,
302 0xef, 0x55, 0x37, 0x85, 0x80, 0x74, 0xdb, 0x06,
303 0x68, 0x70, 0x32, 0x39, 0x98, 0x62, 0x99, 0x9b,
304 0x51, 0x1e, 0x0a, 0x15, 0x52, 0xa5, 0xfe, 0xa3,
305 0x17, 0xc2
306 };
307 const u8 kck[] = {
308 0x1e, 0x73, 0x3f, 0x6d, 0x9b, 0xd5, 0x32, 0x56,
309 0x28, 0x73, 0x04, 0x33, 0x88, 0x31, 0xb0, 0x9a,
310 0x39, 0x40, 0x6d, 0x12, 0x10, 0x17, 0x07, 0x3a,
311 0x5c, 0x30, 0xdb, 0x36, 0xf3, 0x6c, 0xb8, 0x1a
312 };
313 const u8 pmk[] = {
314 0x4e, 0x4d, 0xfa, 0xb1, 0xa2, 0xdd, 0x8a, 0xc1,
315 0xa9, 0x17, 0x90, 0xf9, 0x53, 0xfa, 0xaa, 0x45,
316 0x2a, 0xe5, 0xc6, 0x87, 0x3a, 0xb7, 0x5b, 0x63,
317 0x60, 0x5b, 0xa6, 0x63, 0xf8, 0xa7, 0xfe, 0x59
318 };
319 const u8 pmkid[] = {
320 0x87, 0x47, 0xa6, 0x00, 0xee, 0xa3, 0xf9, 0xf2,
321 0x24, 0x75, 0xdf, 0x58, 0xca, 0x1e, 0x54, 0x98
322 };
323 struct wpabuf *buf = NULL;
324 struct crypto_bignum *mask = NULL;
325 const u8 pwe_19_x[32] = {
326 0xc9, 0x30, 0x49, 0xb9, 0xe6, 0x40, 0x00, 0xf8,
327 0x48, 0x20, 0x16, 0x49, 0xe9, 0x99, 0xf2, 0xb5,
328 0xc2, 0x2d, 0xea, 0x69, 0xb5, 0x63, 0x2c, 0x9d,
329 0xf4, 0xd6, 0x33, 0xb8, 0xaa, 0x1f, 0x6c, 0x1e
330 };
331 const u8 pwe_19_y[32] = {
332 0x73, 0x63, 0x4e, 0x94, 0xb5, 0x3d, 0x82, 0xe7,
333 0x38, 0x3a, 0x8d, 0x25, 0x81, 0x99, 0xd9, 0xdc,
334 0x1a, 0x5e, 0xe8, 0x26, 0x9d, 0x06, 0x03, 0x82,
335 0xcc, 0xbf, 0x33, 0xe6, 0x14, 0xff, 0x59, 0xa0
336 };
337 const u8 pwe_15[384] = {
338 0x69, 0x68, 0x73, 0x65, 0x8f, 0x65, 0x31, 0x42,
339 0x9f, 0x97, 0x39, 0x6f, 0xb8, 0x5f, 0x89, 0xe1,
340 0xfc, 0xd2, 0xf6, 0x92, 0x19, 0xa9, 0x0e, 0x82,
341 0x2f, 0xf7, 0xf4, 0xbc, 0x0b, 0xd8, 0xa7, 0x9f,
342 0xf0, 0x80, 0x35, 0x31, 0x6f, 0xca, 0xe1, 0xa5,
343 0x39, 0x77, 0xdc, 0x11, 0x2b, 0x0b, 0xfe, 0x2e,
344 0x6f, 0x65, 0x6d, 0xc7, 0xd4, 0xa4, 0x5b, 0x08,
345 0x1f, 0xd9, 0xbb, 0xe2, 0x22, 0x85, 0x31, 0x81,
346 0x79, 0x70, 0xbe, 0xa1, 0x66, 0x58, 0x4a, 0x09,
347 0x3c, 0x57, 0x34, 0x3c, 0x9d, 0x57, 0x8f, 0x42,
348 0x58, 0xd0, 0x39, 0x81, 0xdb, 0x8f, 0x79, 0xa2,
349 0x1b, 0x01, 0xcd, 0x27, 0xc9, 0xae, 0xcf, 0xcb,
350 0x9c, 0xdb, 0x1f, 0x84, 0xb8, 0x88, 0x4e, 0x8f,
351 0x50, 0x66, 0xb4, 0x29, 0x83, 0x1e, 0xb9, 0x89,
352 0x0c, 0xa5, 0x47, 0x21, 0xba, 0x10, 0xd5, 0xaa,
353 0x1a, 0x80, 0xce, 0xf1, 0x4c, 0xad, 0x16, 0xda,
354 0x57, 0xb2, 0x41, 0x8a, 0xbe, 0x4b, 0x8c, 0xb0,
355 0xb2, 0xeb, 0xf7, 0xa8, 0x0e, 0x3e, 0xcf, 0x22,
356 0x8f, 0xd8, 0xb6, 0xdb, 0x79, 0x9c, 0x9b, 0x80,
357 0xaf, 0xd7, 0x14, 0xad, 0x51, 0x82, 0xf4, 0x64,
358 0xb6, 0x3f, 0x4c, 0x6c, 0xe5, 0x3f, 0xaa, 0x6f,
359 0xbf, 0x3d, 0xc2, 0x3f, 0x77, 0xfd, 0xcb, 0xe1,
360 0x9c, 0xe3, 0x1e, 0x8a, 0x0e, 0x97, 0xe2, 0x2b,
361 0xe2, 0xdd, 0x37, 0x39, 0x88, 0xc2, 0x8e, 0xbe,
362 0xfa, 0xac, 0x3d, 0x5b, 0x62, 0x2e, 0x1e, 0x74,
363 0xa0, 0x9a, 0xf8, 0xed, 0xfa, 0xe1, 0xce, 0x9c,
364 0xab, 0xbb, 0xdc, 0x36, 0xb1, 0x28, 0x46, 0x3c,
365 0x7e, 0xa8, 0xbd, 0xb9, 0x36, 0x4c, 0x26, 0x75,
366 0xe0, 0x17, 0x73, 0x1f, 0xe0, 0xfe, 0xf6, 0x49,
367 0xfa, 0xa0, 0x45, 0xf4, 0x44, 0x05, 0x20, 0x27,
368 0x25, 0xc2, 0x99, 0xde, 0x27, 0x8b, 0x70, 0xdc,
369 0x54, 0x60, 0x90, 0x02, 0x1e, 0x29, 0x97, 0x9a,
370 0xc4, 0xe7, 0xb6, 0xf5, 0x8b, 0xae, 0x7c, 0x34,
371 0xaa, 0xef, 0x9b, 0xc6, 0x30, 0xf2, 0x80, 0x8d,
372 0x80, 0x78, 0xc2, 0x55, 0x63, 0xa0, 0xa1, 0x38,
373 0x70, 0xfb, 0xf4, 0x74, 0x8d, 0xcd, 0x87, 0x90,
374 0xb4, 0x54, 0xc3, 0x75, 0xdf, 0x10, 0xc5, 0xb6,
375 0xb2, 0x08, 0x59, 0x61, 0xe6, 0x68, 0xa5, 0x82,
376 0xf8, 0x8f, 0x47, 0x30, 0x43, 0xb4, 0xdc, 0x31,
377 0xfc, 0xbc, 0x69, 0xe7, 0xb4, 0x94, 0xb0, 0x6a,
378 0x60, 0x59, 0x80, 0x2e, 0xd3, 0xa4, 0xe8, 0x97,
379 0xa2, 0xa3, 0xc9, 0x08, 0x4b, 0x27, 0x6c, 0xc1,
380 0x37, 0xe8, 0xfc, 0x5c, 0xe2, 0x54, 0x30, 0x3e,
381 0xf8, 0xfe, 0xa2, 0xfc, 0xbb, 0xbd, 0x88, 0x6c,
382 0x92, 0xa3, 0x2a, 0x40, 0x7a, 0x2c, 0x22, 0x38,
383 0x8c, 0x86, 0x86, 0xfe, 0xb9, 0xd4, 0x6b, 0xd6,
384 0x47, 0x88, 0xa7, 0xf6, 0x8e, 0x0f, 0x14, 0xad,
385 0x1e, 0xac, 0xcf, 0x33, 0x01, 0x99, 0xc1, 0x62
386 };
387 int pt_groups[] = { 19, 20, 21, 25, 26, 28, 29, 30, 15, 0 };
388 struct sae_pt *pt_info, *pt;
389 const u8 addr1b[ETH_ALEN] = { 0x00, 0x09, 0x5b, 0x66, 0xec, 0x1e };
390 const u8 addr2b[ETH_ALEN] = { 0x00, 0x0b, 0x6b, 0xd9, 0x02, 0x46 };
391
392 os_memset(&sae, 0, sizeof(sae));
393 buf = wpabuf_alloc(1000);
394 if (!buf ||
395 sae_set_group(&sae, 19) < 0 ||
396 sae_prepare_commit(addr1, addr2, (const u8 *) pw, os_strlen(pw),
397 &sae) < 0)
398 goto fail;
399
400 /* Override local values based on SAE test vector */
401 crypto_bignum_deinit(sae.tmp->sae_rand, 1);
402 sae.tmp->sae_rand = crypto_bignum_init_set(local_rand,
403 sizeof(local_rand));
404 mask = crypto_bignum_init_set(local_mask, sizeof(local_mask));
405 if (!sae.tmp->sae_rand || !mask)
406 goto fail;
407
408 if (crypto_bignum_add(sae.tmp->sae_rand, mask,
409 sae.tmp->own_commit_scalar) < 0 ||
410 crypto_bignum_mod(sae.tmp->own_commit_scalar, sae.tmp->order,
411 sae.tmp->own_commit_scalar) < 0 ||
412 crypto_ec_point_mul(sae.tmp->ec, sae.tmp->pwe_ecc, mask,
413 sae.tmp->own_commit_element_ecc) < 0 ||
414 crypto_ec_point_invert(sae.tmp->ec,
415 sae.tmp->own_commit_element_ecc) < 0)
416 goto fail;
417
418 /* Check that output matches the test vector */
419 if (sae_write_commit(&sae, buf, NULL, NULL, 0) < 0)
420 goto fail;
421 wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
422
423 if (wpabuf_len(buf) != sizeof(local_commit) ||
424 os_memcmp(wpabuf_head(buf), local_commit,
425 sizeof(local_commit)) != 0) {
426 wpa_printf(MSG_ERROR, "SAE: Mismatch in local commit");
427 goto fail;
428 }
429
430 if (sae_parse_commit(&sae, peer_commit, sizeof(peer_commit), NULL, NULL,
431 NULL, 0, NULL) != 0 ||
432 sae_process_commit(&sae) < 0)
433 goto fail;
434
435 if (os_memcmp(kck, sae.tmp->kck, SAE_KCK_LEN) != 0) {
436 wpa_printf(MSG_ERROR, "SAE: Mismatch in KCK");
437 goto fail;
438 }
439
440 if (os_memcmp(pmk, sae.pmk, SAE_PMK_LEN) != 0) {
441 wpa_printf(MSG_ERROR, "SAE: Mismatch in PMK");
442 goto fail;
443 }
444
445 if (os_memcmp(pmkid, sae.pmkid, SAE_PMKID_LEN) != 0) {
446 wpa_printf(MSG_ERROR, "SAE: Mismatch in PMKID");
447 goto fail;
448 }
449
450 pt_info = sae_derive_pt(pt_groups,
451 (const u8 *) ssid, os_strlen(ssid),
452 (const u8 *) pw, os_strlen(pw),
453 (const u8 *) pwid,
454 os_strlen(pwid));
455 if (!pt_info)
456 goto fail;
457
458 for (pt = pt_info; pt; pt = pt->next) {
459 if (pt->group == 19) {
460 struct crypto_ec_point *pwe;
461 u8 bin[SAE_MAX_ECC_PRIME_LEN * 2];
462 size_t prime_len = sizeof(pwe_19_x);
463
464 pwe = sae_derive_pwe_from_pt_ecc(pt, addr1b, addr2b);
465 if (!pwe) {
466 sae_deinit_pt(pt);
467 goto fail;
468 }
469 if (crypto_ec_point_to_bin(pt->ec, pwe, bin,
470 bin + prime_len) < 0 ||
471 os_memcmp(pwe_19_x, bin, prime_len) != 0 ||
472 os_memcmp(pwe_19_y, bin + prime_len,
473 prime_len) != 0) {
474 wpa_printf(MSG_ERROR,
475 "SAE: PT/PWE test vector mismatch");
476 crypto_ec_point_deinit(pwe, 1);
477 sae_deinit_pt(pt);
478 goto fail;
479 }
480 crypto_ec_point_deinit(pwe, 1);
481 }
482
483 if (pt->group == 15) {
484 struct crypto_bignum *pwe;
485 u8 bin[SAE_MAX_PRIME_LEN];
486 size_t prime_len = sizeof(pwe_15);
487
488 pwe = sae_derive_pwe_from_pt_ffc(pt, addr1b, addr2b);
489 if (!pwe) {
490 sae_deinit_pt(pt);
491 goto fail;
492 }
493 if (crypto_bignum_to_bin(pwe, bin, sizeof(bin),
494 prime_len) < 0 ||
495 os_memcmp(pwe_15, bin, prime_len) != 0) {
496 wpa_printf(MSG_ERROR,
497 "SAE: PT/PWE test vector mismatch");
498 crypto_bignum_deinit(pwe, 1);
499 sae_deinit_pt(pt);
500 goto fail;
501 }
502 crypto_bignum_deinit(pwe, 1);
503 }
504 }
505
506 sae_deinit_pt(pt_info);
507
508 ret = 0;
509 fail:
510 sae_clear_data(&sae);
511 wpabuf_free(buf);
512 crypto_bignum_deinit(mask, 1);
513 return ret;
514 #else /* CONFIG_SAE */
515 return 0;
516 #endif /* CONFIG_SAE */
517 }
518
519
sae_pk_tests(void)520 static int sae_pk_tests(void)
521 {
522 #ifdef CONFIG_SAE_PK
523 const char *invalid[] = { "a2bc-de3f-ghim-", "a2bcde3fghim", "", NULL };
524 struct {
525 const char *pw;
526 const u8 *val;
527 } valid[] = {
528 { "a2bc-de3f-ghim", (u8 *) "\x06\x82\x21\x93\x65\x31\xd0\xc0" },
529 { "aaaa-aaaa-aaaj", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x90" },
530 { "7777-7777-777f", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe\x50" },
531 { NULL, NULL }
532 };
533 int i;
534 bool failed;
535
536 for (i = 0; invalid[i]; i++) {
537 if (sae_pk_valid_password(invalid[i])) {
538 wpa_printf(MSG_ERROR,
539 "SAE-PK: Invalid password '%s' not recognized",
540 invalid[i]);
541 return -1;
542 }
543 }
544
545 failed = false;
546 for (i = 0; valid[i].pw; i++) {
547 u8 *res;
548 size_t res_len;
549 char *b32;
550 const char *pw = valid[i].pw;
551 const u8 *val = valid[i].val;
552 size_t pw_len = os_strlen(pw);
553 size_t bits = (pw_len - pw_len / 5) * 5;
554 size_t bytes = (bits + 7) / 8;
555
556 if (!sae_pk_valid_password(pw)) {
557 wpa_printf(MSG_ERROR,
558 "SAE-PK: Valid password '%s' not recognized",
559 pw);
560 failed = true;
561 continue;
562 }
563
564 res = sae_pk_base32_decode(pw, pw_len, &res_len);
565 if (!res) {
566 wpa_printf(MSG_ERROR,
567 "SAE-PK: Failed to decode password '%s'",
568 valid[i].pw);
569 failed = true;
570 continue;
571 }
572 if (res_len != bytes || os_memcmp(val, res, res_len) != 0) {
573 wpa_printf(MSG_ERROR,
574 "SAE-PK: Mismatch for decoded password '%s'",
575 valid[i].pw);
576 wpa_hexdump(MSG_INFO, "SAE-PK: Decoded value",
577 res, res_len);
578 wpa_hexdump(MSG_INFO, "SAE-PK: Expected value",
579 val, bytes);
580 failed = true;
581 }
582 os_free(res);
583
584 b32 = sae_pk_base32_encode(val, bits - 5);
585 if (!b32) {
586 wpa_printf(MSG_ERROR,
587 "SAE-PK: Failed to encode password '%s'",
588 pw);
589 failed = true;
590 continue;
591 }
592 if (os_strcmp(b32, pw) != 0) {
593 wpa_printf(MSG_ERROR,
594 "SAE-PK: Mismatch for password '%s'", pw);
595 wpa_printf(MSG_INFO, "SAE-PK: Encoded value: '%s'",
596 b32);
597 failed = true;
598 }
599 os_free(b32);
600 }
601
602 return failed ? -1 : 0;
603 #else /* CONFIG_SAE_PK */
604 return 0;
605 #endif /* CONFIG_SAE_PK */
606 }
607
608
609 #ifdef CONFIG_PASN
610
pasn_test_pasn_auth(void)611 static int pasn_test_pasn_auth(void)
612 {
613 /* Test vector taken from IEEE Std 802.11-2024,
614 * J.12 (PASN Test Vectors) */
615 const u8 pmk[] = {
616 0xde, 0xf4, 0x3e, 0x55, 0x67, 0xe0, 0x1c, 0xa6,
617 0x64, 0x92, 0x65, 0xf1, 0x9a, 0x29, 0x0e, 0xef,
618 0xf8, 0xbd, 0x88, 0x8f, 0x6c, 0x1d, 0x9c, 0xc9,
619 0xd1, 0x0f, 0x04, 0xbd, 0x37, 0x8f, 0x3c, 0xad
620 };
621
622 const u8 spa_addr[] = {
623 0x00, 0x90, 0x4c, 0x01, 0xc1, 0x07
624 };
625 const u8 bssid[] = {
626 0xc0, 0xff, 0xd4, 0xa8, 0xdb, 0xc1
627 };
628 const u8 dhss[] = {
629 0xf8, 0x7b, 0x20, 0x8e, 0x7e, 0xd2, 0xb7, 0x37,
630 0xaf, 0xdb, 0xc2, 0xe1, 0x3e, 0xae, 0x78, 0xda,
631 0x30, 0x01, 0x23, 0xd4, 0xd8, 0x4b, 0xa8, 0xb0,
632 0xea, 0xfe, 0x90, 0xc4, 0x8c, 0xdf, 0x1f, 0x93
633 };
634 const u8 kck[] = {
635 0x7b, 0xb8, 0x21, 0xac, 0x0a, 0xa5, 0x90, 0x9d,
636 0xd6, 0x54, 0xa5, 0x60, 0x65, 0xad, 0x7c, 0x77,
637 0xeb, 0x88, 0x9c, 0xbe, 0x29, 0x05, 0xbb, 0xf0,
638 0x5a, 0xbb, 0x1e, 0xea, 0xc8, 0x8b, 0xa3, 0x06
639 };
640 const u8 tk[] = {
641 0x67, 0x3e, 0xab, 0x46, 0xb8, 0x32, 0xd5, 0xa8,
642 0x0c, 0xbc, 0x02, 0x43, 0x01, 0x6e, 0x20, 0x7e
643 };
644 const u8 kdk[] = {
645 0x2d, 0x0f, 0x0e, 0x82, 0xc7, 0x0d, 0xd2, 0x6b,
646 0x79, 0x06, 0x1a, 0x46, 0x81, 0xe8, 0xdb, 0xb2,
647 0xea, 0x83, 0xbe, 0xa3, 0x99, 0x84, 0x4b, 0xd5,
648 0x89, 0x4e, 0xb3, 0x20, 0xf6, 0x9d, 0x7d, 0xd6
649 };
650 struct wpa_ptk ptk;
651 int ret;
652 enum rsn_hash_alg hash_alg;
653
654 ret = pasn_pmk_to_ptk(pmk, sizeof(pmk),
655 spa_addr, bssid,
656 dhss, sizeof(dhss),
657 &ptk, WPA_KEY_MGMT_PASN, WPA_CIPHER_CCMP,
658 WPA_KDK_MAX_LEN, 0, &hash_alg, false);
659
660 if (ret)
661 return ret;
662
663 if (ptk.kck_len != sizeof(kck) ||
664 os_memcmp(kck, ptk.kck, sizeof(kck)) != 0) {
665 wpa_printf(MSG_ERROR, "PASN: Mismatched KCK");
666 return -1;
667 }
668
669 if (ptk.tk_len != sizeof(tk) ||
670 os_memcmp(tk, ptk.tk, sizeof(tk)) != 0) {
671 wpa_printf(MSG_ERROR, "PASN: Mismatched TK");
672 return -1;
673 }
674
675 if (ptk.kdk_len != sizeof(kdk) ||
676 os_memcmp(kdk, ptk.kdk, sizeof(kdk)) != 0) {
677 wpa_printf(MSG_ERROR, "PASN: Mismatched KDK");
678 return -1;
679 }
680
681 return 0;
682 }
683
684
pasn_test_no_pasn_auth(void)685 static int pasn_test_no_pasn_auth(void)
686 {
687 /* Test vector taken from IEEE Std 802.11-2024,
688 * J.13 (KDK Test Vectors when PASN authentication is not used) */
689 const u8 pmk[] = {
690 0xde, 0xf4, 0x3e, 0x55, 0x67, 0xe0, 0x1c, 0xa6,
691 0x64, 0x92, 0x65, 0xf1, 0x9a, 0x29, 0x0e, 0xef,
692 0xf8, 0xbd, 0x88, 0x8f, 0x6c, 0x1d, 0x9c, 0xc9,
693 0xd1, 0x0f, 0x04, 0xbd, 0x37, 0x8f, 0x3c, 0xad
694 };
695 const u8 aa[] = {
696 0xc0, 0xff, 0xd4, 0xa8, 0xdb, 0xc1
697 };
698 const u8 spa[] = {
699 0x00, 0x90, 0x4c, 0x01, 0xc1, 0x07
700 };
701 const u8 anonce[] = {
702 0xbe, 0x7a, 0x1c, 0xa2, 0x84, 0x34, 0x7b, 0x5b,
703 0xd6, 0x7d, 0xbd, 0x2d, 0xfd, 0xb4, 0xd9, 0x9f,
704 0x1a, 0xfa, 0xe0, 0xb8, 0x8b, 0xa1, 0x8e, 0x00,
705 0x87, 0x18, 0x41, 0x7e, 0x4b, 0x27, 0xef, 0x5f
706 };
707 const u8 snonce[] = {
708 0x40, 0x4b, 0x01, 0x2f, 0xfb, 0x43, 0xed, 0x0f,
709 0xb4, 0x3e, 0xa1, 0xf2, 0x87, 0xc9, 0x1f, 0x25,
710 0x06, 0xd2, 0x1b, 0x4a, 0x92, 0xd7, 0x4b, 0x5e,
711 0xa5, 0x0c, 0x94, 0x33, 0x50, 0xce, 0x86, 0x71
712 };
713 const u8 kck[] = {
714 0xcd, 0x7b, 0x9e, 0x75, 0x55, 0x36, 0x2d, 0xf0,
715 0xb6, 0x35, 0x68, 0x48, 0x4a, 0x81, 0x12, 0xf5
716 };
717 const u8 kek[] = {
718 0x99, 0xca, 0xd3, 0x58, 0x8d, 0xa0, 0xf1, 0xe6,
719 0x3f, 0xd1, 0x90, 0x19, 0x10, 0x39, 0xbb, 0x4b
720 };
721 const u8 tk[] = {
722 0x9e, 0x2e, 0x93, 0x77, 0xe7, 0x53, 0x2e, 0x73,
723 0x7a, 0x1b, 0xc2, 0x50, 0xfe, 0x19, 0x4a, 0x03
724 };
725 const u8 kdk[] = {
726 0x6c, 0x7f, 0xb9, 0x7c, 0xeb, 0x55, 0xb0, 0x1a,
727 0xcf, 0xf0, 0x0f, 0x07, 0x09, 0x42, 0xbd, 0xf5,
728 0x29, 0x1f, 0xeb, 0x4b, 0xee, 0x38, 0xe0, 0x36,
729 0x5b, 0x25, 0xa2, 0x50, 0xbb, 0x2a, 0xc9, 0xff
730 };
731 struct wpa_ptk ptk;
732 int ret;
733
734 ret = wpa_pmk_to_ptk(pmk, sizeof(pmk),
735 "Pairwise key expansion",
736 spa, aa, snonce, anonce,
737 &ptk, WPA_KEY_MGMT_SAE, WPA_CIPHER_CCMP,
738 NULL, 0, WPA_KDK_MAX_LEN);
739
740 if (ret)
741 return ret;
742
743 if (ptk.kck_len != sizeof(kck) ||
744 os_memcmp(kck, ptk.kck, sizeof(kck)) != 0) {
745 wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched KCK");
746 return -1;
747 }
748
749 if (ptk.kek_len != sizeof(kek) ||
750 os_memcmp(kek, ptk.kek, sizeof(kek)) != 0) {
751 wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched KEK");
752 return -1;
753 }
754
755 if (ptk.tk_len != sizeof(tk) ||
756 os_memcmp(tk, ptk.tk, sizeof(tk)) != 0) {
757 wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched TK");
758 return -1;
759 }
760
761 if (ptk.kdk_len != sizeof(kdk) ||
762 os_memcmp(kdk, ptk.kdk, sizeof(kdk)) != 0) {
763 wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched KDK");
764 return -1;
765 }
766
767 return 0;
768 }
769
770 #endif /* CONFIG_PASN */
771
772
pasn_tests(void)773 static int pasn_tests(void)
774 {
775 #ifdef CONFIG_PASN
776 if (pasn_test_pasn_auth() ||
777 pasn_test_no_pasn_auth())
778 return -1;
779 #endif /* CONFIG_PASN */
780 return 0;
781 }
782
783
common_module_tests(void)784 int common_module_tests(void)
785 {
786 int ret = 0;
787
788 wpa_printf(MSG_INFO, "common module tests");
789
790 if (ieee802_11_parse_tests() < 0 ||
791 gas_tests() < 0 ||
792 sae_tests() < 0 ||
793 sae_pk_tests() < 0 ||
794 pasn_tests() < 0 ||
795 rsn_ie_parse_tests() < 0)
796 ret = -1;
797
798 return ret;
799 }
800