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
22struct ieee802_11_parse_test_data {
23	u8 *data;
24	size_t len;
25	ParseRes result;
26	int count;
27};
28
29static 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
87static 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
149struct rsn_ie_parse_test_data {
150	u8 *data;
151	size_t len;
152	int result;
153};
154
155static 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
204static 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
226static 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
254static 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)
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) != 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), pwid);
453	if (!pt_info)
454		goto fail;
455
456	for (pt = pt_info; pt; pt = pt->next) {
457		if (pt->group == 19) {
458			struct crypto_ec_point *pwe;
459			u8 bin[SAE_MAX_ECC_PRIME_LEN * 2];
460			size_t prime_len = sizeof(pwe_19_x);
461
462			pwe = sae_derive_pwe_from_pt_ecc(pt, addr1b, addr2b);
463			if (!pwe) {
464				sae_deinit_pt(pt);
465				goto fail;
466			}
467			if (crypto_ec_point_to_bin(pt->ec, pwe, bin,
468						   bin + prime_len) < 0 ||
469			    os_memcmp(pwe_19_x, bin, prime_len) != 0 ||
470			    os_memcmp(pwe_19_y, bin + prime_len,
471				      prime_len) != 0) {
472				wpa_printf(MSG_ERROR,
473					   "SAE: PT/PWE test vector mismatch");
474				crypto_ec_point_deinit(pwe, 1);
475				sae_deinit_pt(pt);
476				goto fail;
477			}
478			crypto_ec_point_deinit(pwe, 1);
479		}
480
481		if (pt->group == 15) {
482			struct crypto_bignum *pwe;
483			u8 bin[SAE_MAX_PRIME_LEN];
484			size_t prime_len = sizeof(pwe_15);
485
486			pwe = sae_derive_pwe_from_pt_ffc(pt, addr1b, addr2b);
487			if (!pwe) {
488				sae_deinit_pt(pt);
489				goto fail;
490			}
491			if (crypto_bignum_to_bin(pwe, bin, sizeof(bin),
492						 prime_len) < 0 ||
493			    os_memcmp(pwe_15, bin, prime_len) != 0) {
494				wpa_printf(MSG_ERROR,
495					   "SAE: PT/PWE test vector mismatch");
496				crypto_bignum_deinit(pwe, 1);
497				sae_deinit_pt(pt);
498				goto fail;
499			}
500			crypto_bignum_deinit(pwe, 1);
501		}
502	}
503
504	sae_deinit_pt(pt_info);
505
506	ret = 0;
507fail:
508	sae_clear_data(&sae);
509	wpabuf_free(buf);
510	crypto_bignum_deinit(mask, 1);
511	return ret;
512#else /* CONFIG_SAE */
513	return 0;
514#endif /* CONFIG_SAE */
515}
516
517
518static int sae_pk_tests(void)
519{
520#ifdef CONFIG_SAE_PK
521	const char *invalid[] = { "a2bc-de3f-ghim-", "a2bcde3fghim", "", NULL };
522	struct {
523		const char *pw;
524		const u8 *val;
525	} valid[] = {
526		{ "a2bc-de3f-ghim", (u8 *) "\x06\x82\x21\x93\x65\x31\xd0\xc0" },
527		{ "aaaa-aaaa-aaaj", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x90" },
528		{ "7777-7777-777f", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe\x50" },
529		{ NULL, NULL }
530	};
531	int i;
532	bool failed;
533
534	for (i = 0; invalid[i]; i++) {
535		if (sae_pk_valid_password(invalid[i])) {
536			wpa_printf(MSG_ERROR,
537				   "SAE-PK: Invalid password '%s' not recognized",
538				   invalid[i]);
539			return -1;
540		}
541	}
542
543	failed = false;
544	for (i = 0; valid[i].pw; i++) {
545		u8 *res;
546		size_t res_len;
547		char *b32;
548		const char *pw = valid[i].pw;
549		const u8 *val = valid[i].val;
550		size_t pw_len = os_strlen(pw);
551		size_t bits = (pw_len - pw_len / 5) * 5;
552		size_t bytes = (bits + 7) / 8;
553
554		if (!sae_pk_valid_password(pw)) {
555			wpa_printf(MSG_ERROR,
556				   "SAE-PK: Valid password '%s' not recognized",
557				   pw);
558			failed = true;
559			continue;
560		}
561
562		res = sae_pk_base32_decode(pw, pw_len, &res_len);
563		if (!res) {
564			wpa_printf(MSG_ERROR,
565				   "SAE-PK: Failed to decode password '%s'",
566				   valid[i].pw);
567			failed = true;
568			continue;
569		}
570		if (res_len != bytes || os_memcmp(val, res, res_len) != 0) {
571			wpa_printf(MSG_ERROR,
572				   "SAE-PK: Mismatch for decoded password '%s'",
573				   valid[i].pw);
574			wpa_hexdump(MSG_INFO, "SAE-PK: Decoded value",
575				    res, res_len);
576			wpa_hexdump(MSG_INFO, "SAE-PK: Expected value",
577				    val, bytes);
578			failed = true;
579		}
580		os_free(res);
581
582		b32 = sae_pk_base32_encode(val, bits - 5);
583		if (!b32) {
584			wpa_printf(MSG_ERROR,
585				   "SAE-PK: Failed to encode password '%s'",
586				   pw);
587			failed = true;
588			continue;
589		}
590		if (os_strcmp(b32, pw) != 0) {
591			wpa_printf(MSG_ERROR,
592				   "SAE-PK: Mismatch for password '%s'", pw);
593			wpa_printf(MSG_INFO, "SAE-PK: Encoded value: '%s'",
594				   b32);
595			failed = true;
596		}
597		os_free(b32);
598	}
599
600	return failed ? -1 : 0;
601#else /* CONFIG_SAE_PK */
602	return 0;
603#endif /* CONFIG_SAE_PK */
604}
605
606
607#ifdef CONFIG_PASN
608
609static int pasn_test_pasn_auth(void)
610{
611	/* Test vector taken from IEEE P802.11az/D2.6, J.12 */
612	const u8 pmk[] = {
613		0xde, 0xf4, 0x3e, 0x55, 0x67, 0xe0, 0x1c, 0xa6,
614		0x64, 0x92, 0x65, 0xf1, 0x9a, 0x29, 0x0e, 0xef,
615		0xf8, 0xbd, 0x88, 0x8f, 0x6c, 0x1d, 0x9c, 0xc9,
616		0xd1, 0x0f, 0x04, 0xbd, 0x37, 0x8f, 0x3c, 0xad
617	};
618
619	const u8 spa_addr[] = {
620		0x00, 0x90, 0x4c, 0x01, 0xc1, 0x07
621	};
622	const u8 bssid[] = {
623		0xc0, 0xff, 0xd4, 0xa8, 0xdb, 0xc1
624	};
625	const u8 dhss[] = {
626		0xf8, 0x7b, 0x20, 0x8e, 0x7e, 0xd2, 0xb7, 0x37,
627		0xaf, 0xdb, 0xc2, 0xe1, 0x3e, 0xae, 0x78, 0xda,
628		0x30, 0x01, 0x23, 0xd4, 0xd8, 0x4b, 0xa8, 0xb0,
629		0xea, 0xfe, 0x90, 0xc4, 0x8c, 0xdf, 0x1f, 0x93
630	};
631	const u8 kck[] = {
632		0x7b, 0xb8, 0x21, 0xac, 0x0a, 0xa5, 0x90, 0x9d,
633		0xd6, 0x54, 0xa5, 0x60, 0x65, 0xad, 0x7c, 0x77,
634		0xeb, 0x88, 0x9c, 0xbe, 0x29, 0x05, 0xbb, 0xf0,
635		0x5a, 0xbb, 0x1e, 0xea, 0xc8, 0x8b, 0xa3, 0x06
636	};
637	const u8 tk[] = {
638		0x67, 0x3e, 0xab, 0x46, 0xb8, 0x32, 0xd5, 0xa8,
639		0x0c, 0xbc, 0x02, 0x43, 0x01, 0x6e, 0x20, 0x7e
640	};
641	const u8 kdk[] = {
642		0x2d, 0x0f, 0x0e, 0x82, 0xc7, 0x0d, 0xd2, 0x6b,
643		0x79, 0x06, 0x1a, 0x46, 0x81, 0xe8, 0xdb, 0xb2,
644		0xea, 0x83, 0xbe, 0xa3, 0x99, 0x84, 0x4b, 0xd5,
645		0x89, 0x4e, 0xb3, 0x20, 0xf6, 0x9d, 0x7d, 0xd6
646	};
647	struct wpa_ptk ptk;
648	int ret;
649
650	ret = pasn_pmk_to_ptk(pmk, sizeof(pmk),
651			      spa_addr, bssid,
652			      dhss, sizeof(dhss),
653			      &ptk, WPA_KEY_MGMT_PASN, WPA_CIPHER_CCMP,
654			      WPA_KDK_MAX_LEN);
655
656	if (ret)
657		return ret;
658
659	if (ptk.kck_len != sizeof(kck) ||
660	    os_memcmp(kck, ptk.kck, sizeof(kck)) != 0) {
661		wpa_printf(MSG_ERROR, "PASN: Mismatched KCK");
662		return -1;
663	}
664
665	if (ptk.tk_len != sizeof(tk) ||
666	    os_memcmp(tk, ptk.tk, sizeof(tk)) != 0) {
667		wpa_printf(MSG_ERROR, "PASN: Mismatched TK");
668		return -1;
669	}
670
671	if (ptk.kdk_len != sizeof(kdk) ||
672	    os_memcmp(kdk, ptk.kdk, sizeof(kdk)) != 0) {
673		wpa_printf(MSG_ERROR, "PASN: Mismatched KDK");
674		return -1;
675	}
676
677	return 0;
678}
679
680
681static int pasn_test_no_pasn_auth(void)
682{
683	/* Test vector taken from IEEE P802.11az/D2.6, J.13 */
684	const u8 pmk[] = {
685		0xde, 0xf4, 0x3e, 0x55, 0x67, 0xe0, 0x1c, 0xa6,
686		0x64, 0x92, 0x65, 0xf1, 0x9a, 0x29, 0x0e, 0xef,
687		0xf8, 0xbd, 0x88, 0x8f, 0x6c, 0x1d, 0x9c, 0xc9,
688		0xd1, 0x0f, 0x04, 0xbd, 0x37, 0x8f, 0x3c, 0xad
689	};
690	const u8 aa[] = {
691		0xc0, 0xff, 0xd4, 0xa8, 0xdb, 0xc1
692	};
693	const u8 spa[] = {
694		0x00, 0x90, 0x4c, 0x01, 0xc1, 0x07
695	};
696	const u8 anonce[] = {
697		0xbe, 0x7a, 0x1c, 0xa2, 0x84, 0x34, 0x7b, 0x5b,
698		0xd6, 0x7d, 0xbd, 0x2d, 0xfd, 0xb4, 0xd9, 0x9f,
699		0x1a, 0xfa, 0xe0, 0xb8, 0x8b, 0xa1, 0x8e, 0x00,
700		0x87, 0x18, 0x41, 0x7e, 0x4b, 0x27, 0xef, 0x5f
701	};
702	const u8 snonce[] = {
703		0x40, 0x4b, 0x01, 0x2f, 0xfb, 0x43, 0xed, 0x0f,
704		0xb4, 0x3e, 0xa1, 0xf2, 0x87, 0xc9, 0x1f, 0x25,
705		0x06, 0xd2, 0x1b, 0x4a, 0x92, 0xd7, 0x4b, 0x5e,
706		0xa5, 0x0c, 0x94, 0x33, 0x50, 0xce, 0x86, 0x71
707	};
708	const u8 kck[] = {
709		0xcd, 0x7b, 0x9e, 0x75, 0x55, 0x36, 0x2d, 0xf0,
710		0xb6, 0x35, 0x68, 0x48, 0x4a, 0x81, 0x12, 0xf5
711	};
712	const u8 kek[] = {
713		0x99, 0xca, 0xd3, 0x58, 0x8d, 0xa0, 0xf1, 0xe6,
714		0x3f, 0xd1, 0x90, 0x19, 0x10, 0x39, 0xbb, 0x4b
715	};
716	const u8 tk[] = {
717		0x9e, 0x2e, 0x93, 0x77, 0xe7, 0x53, 0x2e, 0x73,
718		0x7a, 0x1b, 0xc2, 0x50, 0xfe, 0x19, 0x4a, 0x03
719	};
720	const u8 kdk[] = {
721		0x6c, 0x7f, 0xb9, 0x7c, 0xeb, 0x55, 0xb0, 0x1a,
722		0xcf, 0xf0, 0x0f, 0x07, 0x09, 0x42, 0xbd, 0xf5,
723		0x29, 0x1f, 0xeb, 0x4b, 0xee, 0x38, 0xe0, 0x36,
724		0x5b, 0x25, 0xa2, 0x50, 0xbb, 0x2a, 0xc9, 0xff
725	};
726	struct wpa_ptk ptk;
727	int ret;
728
729	ret = wpa_pmk_to_ptk(pmk, sizeof(pmk),
730			     "Pairwise key expansion",
731			     spa, aa, snonce, anonce,
732			     &ptk, WPA_KEY_MGMT_SAE, WPA_CIPHER_CCMP,
733			     NULL, 0, WPA_KDK_MAX_LEN);
734
735	if (ret)
736		return ret;
737
738	if (ptk.kck_len != sizeof(kck) ||
739	    os_memcmp(kck, ptk.kck, sizeof(kck)) != 0) {
740		wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched KCK");
741		return -1;
742	}
743
744	if (ptk.kek_len != sizeof(kek) ||
745	    os_memcmp(kek, ptk.kek, sizeof(kek)) != 0) {
746		wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched KEK");
747		return -1;
748	}
749
750	if (ptk.tk_len != sizeof(tk) ||
751	    os_memcmp(tk, ptk.tk, sizeof(tk)) != 0) {
752		wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched TK");
753		return -1;
754	}
755
756	if (ptk.kdk_len != sizeof(kdk) ||
757	    os_memcmp(kdk, ptk.kdk, sizeof(kdk)) != 0) {
758		wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched KDK");
759		return -1;
760	}
761
762	return 0;
763}
764
765#endif /* CONFIG_PASN */
766
767
768static int pasn_tests(void)
769{
770#ifdef CONFIG_PASN
771	if (pasn_test_pasn_auth() ||
772	    pasn_test_no_pasn_auth())
773		return -1;
774#endif /* CONFIG_PASN */
775	return 0;
776}
777
778
779int common_module_tests(void)
780{
781	int ret = 0;
782
783	wpa_printf(MSG_INFO, "common module tests");
784
785	if (ieee802_11_parse_tests() < 0 ||
786	    gas_tests() < 0 ||
787	    sae_tests() < 0 ||
788	    sae_pk_tests() < 0 ||
789	    pasn_tests() < 0 ||
790	    rsn_ie_parse_tests() < 0)
791		ret = -1;
792
793	return ret;
794}
795