xref: /freebsd/contrib/wpa/src/common/common_module_tests.c (revision 71e72c9e91c4b8007a4292e09669e8b549c29e97)
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