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 "ieee802_11_common.h"
15 #include "ieee802_11_defs.h"
16 #include "gas.h"
17 #include "wpa_common.h"
18 #include "sae.h"
19 
20 
21 struct ieee802_11_parse_test_data {
22 	u8 *data;
23 	size_t len;
24 	ParseRes result;
25 	int count;
26 };
27 
28 static const struct ieee802_11_parse_test_data parse_tests[] = {
29 	{ (u8 *) "", 0, ParseOK, 0 },
30 	{ (u8 *) " ", 1, ParseFailed, 0 },
31 	{ (u8 *) "\xff\x00", 2, ParseUnknown, 1 },
32 	{ (u8 *) "\xff\x01", 2, ParseFailed, 0 },
33 	{ (u8 *) "\xdd\x03\x01\x02\x03", 5, ParseUnknown, 1 },
34 	{ (u8 *) "\xdd\x04\x01\x02\x03\x04", 6, ParseUnknown, 1 },
35 	{ (u8 *) "\xdd\x04\x00\x50\xf2\x02", 6, ParseUnknown, 1 },
36 	{ (u8 *) "\xdd\x05\x00\x50\xf2\x02\x02", 7, ParseOK, 1 },
37 	{ (u8 *) "\xdd\x05\x00\x50\xf2\x02\xff", 7, ParseUnknown, 1 },
38 	{ (u8 *) "\xdd\x04\x00\x50\xf2\xff", 6, ParseUnknown, 1 },
39 	{ (u8 *) "\xdd\x04\x50\x6f\x9a\xff", 6, ParseUnknown, 1 },
40 	{ (u8 *) "\xdd\x04\x00\x90\x4c\x33", 6, ParseOK, 1 },
41 	{ (u8 *) "\xdd\x04\x00\x90\x4c\xff\xdd\x04\x00\x90\x4c\x33", 12,
42 	  ParseUnknown, 2 },
43 	{ (u8 *) "\x10\x01\x00\x21\x00", 5, ParseOK, 2 },
44 	{ (u8 *) "\x24\x00", 2, ParseOK, 1 },
45 	{ (u8 *) "\x38\x00", 2, ParseOK, 1 },
46 	{ (u8 *) "\x54\x00", 2, ParseOK, 1 },
47 	{ (u8 *) "\x5a\x00", 2, ParseOK, 1 },
48 	{ (u8 *) "\x65\x00", 2, ParseOK, 1 },
49 	{ (u8 *) "\x65\x12\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11",
50 	  20, ParseOK, 1 },
51 	{ (u8 *) "\x6e\x00", 2, ParseOK, 1 },
52 	{ (u8 *) "\xc7\x00", 2, ParseOK, 1 },
53 	{ (u8 *) "\xc7\x01\x00", 3, ParseOK, 1 },
54 	{ (u8 *) "\x03\x00\x2a\x00\x36\x00\x37\x00\x38\x00\x2d\x00\x3d\x00\xbf\x00\xc0\x00",
55 	  18, ParseOK, 9 },
56 	{ (u8 *) "\x8b\x00", 2, ParseOK, 1 },
57 	{ (u8 *) "\xdd\x04\x00\x90\x4c\x04", 6, ParseUnknown, 1 },
58 	{ (u8 *) "\xed\x00", 2, ParseOK, 1 },
59 	{ (u8 *) "\xef\x00", 2, ParseOK, 1 },
60 	{ (u8 *) "\xef\x01\x11", 3, ParseOK, 1 },
61 	{ (u8 *) "\xf0\x00", 2, ParseOK, 1 },
62 	{ (u8 *) "\xf1\x00", 2, ParseOK, 1 },
63 	{ (u8 *) "\xf1\x02\x11\x22", 4, ParseOK, 1 },
64 	{ (u8 *) "\xf2\x00", 2, ParseOK, 1 },
65 	{ (u8 *) "\xff\x00", 2, ParseUnknown, 1 },
66 	{ (u8 *) "\xff\x01\x00", 3, ParseUnknown, 1 },
67 	{ (u8 *) "\xff\x01\x01", 3, ParseOK, 1 },
68 	{ (u8 *) "\xff\x02\x01\x00", 4, ParseOK, 1 },
69 	{ (u8 *) "\xff\x01\x02", 3, ParseOK, 1 },
70 	{ (u8 *) "\xff\x04\x02\x11\x22\x33", 6, ParseOK, 1 },
71 	{ (u8 *) "\xff\x01\x04", 3, ParseOK, 1 },
72 	{ (u8 *) "\xff\x01\x05", 3, ParseOK, 1 },
73 	{ (u8 *) "\xff\x0d\x05\x11\x22\x33\x44\x55\x55\x11\x22\x33\x44\x55\x55",
74 	  15, ParseOK, 1 },
75 	{ (u8 *) "\xff\x01\x06", 3, ParseOK, 1 },
76 	{ (u8 *) "\xff\x02\x06\x00", 4, ParseOK, 1 },
77 	{ (u8 *) "\xff\x01\x07", 3, ParseOK, 1 },
78 	{ (u8 *) "\xff\x09\x07\x11\x22\x33\x44\x55\x66\x77\x88", 11,
79 	  ParseOK, 1 },
80 	{ (u8 *) "\xff\x01\x0c", 3, ParseOK, 1 },
81 	{ (u8 *) "\xff\x02\x0c\x00", 4, ParseOK, 1 },
82 	{ (u8 *) "\xff\x01\x0d", 3, ParseOK, 1 },
83 	{ NULL, 0, ParseOK, 0 }
84 };
85 
86 static int ieee802_11_parse_tests(void)
87 {
88 	int i, ret = 0;
89 	struct wpabuf *buf;
90 
91 	wpa_printf(MSG_INFO, "ieee802_11_parse tests");
92 
93 	for (i = 0; parse_tests[i].data; i++) {
94 		const struct ieee802_11_parse_test_data *test;
95 		struct ieee802_11_elems elems;
96 		ParseRes res;
97 
98 		test = &parse_tests[i];
99 		res = ieee802_11_parse_elems(test->data, test->len, &elems, 1);
100 		if (res != test->result ||
101 		    ieee802_11_ie_count(test->data, test->len) != test->count) {
102 			wpa_printf(MSG_ERROR, "ieee802_11_parse test %d failed",
103 				   i);
104 			ret = -1;
105 		}
106 	}
107 
108 	if (ieee802_11_vendor_ie_concat((const u8 *) "\x00\x01", 2, 0) != NULL)
109 	{
110 		wpa_printf(MSG_ERROR,
111 			   "ieee802_11_vendor_ie_concat test failed");
112 		ret = -1;
113 	}
114 
115 	buf = ieee802_11_vendor_ie_concat((const u8 *) "\xdd\x05\x11\x22\x33\x44\x01\xdd\x05\x11\x22\x33\x44\x02\x00\x01",
116 					  16, 0x11223344);
117 	do {
118 		const u8 *pos;
119 
120 		if (!buf) {
121 			wpa_printf(MSG_ERROR,
122 				   "ieee802_11_vendor_ie_concat test 2 failed");
123 			ret = -1;
124 			break;
125 		}
126 
127 		if (wpabuf_len(buf) != 2) {
128 			wpa_printf(MSG_ERROR,
129 				   "ieee802_11_vendor_ie_concat test 3 failed");
130 			ret = -1;
131 			break;
132 		}
133 
134 		pos = wpabuf_head(buf);
135 		if (pos[0] != 0x01 || pos[1] != 0x02) {
136 			wpa_printf(MSG_ERROR,
137 				   "ieee802_11_vendor_ie_concat test 3 failed");
138 			ret = -1;
139 			break;
140 		}
141 	} while (0);
142 	wpabuf_free(buf);
143 
144 	return ret;
145 }
146 
147 
148 struct rsn_ie_parse_test_data {
149 	u8 *data;
150 	size_t len;
151 	int result;
152 };
153 
154 static const struct rsn_ie_parse_test_data rsn_parse_tests[] = {
155 	{ (u8 *) "", 0, -1 },
156 	{ (u8 *) "\x30\x00", 2, -1 },
157 	{ (u8 *) "\x30\x02\x01\x00", 4, 0 },
158 	{ (u8 *) "\x30\x02\x00\x00", 4, -2 },
159 	{ (u8 *) "\x30\x02\x02\x00", 4, -2 },
160 	{ (u8 *) "\x30\x02\x00\x01", 4, -2 },
161 	{ (u8 *) "\x30\x02\x00\x00\x00", 5, -2 },
162 	{ (u8 *) "\x30\x03\x01\x00\x00", 5, -3 },
163 	{ (u8 *) "\x30\x06\x01\x00\x00\x00\x00\x00", 8, -1 },
164 	{ (u8 *) "\x30\x06\x01\x00\x00\x0f\xac\x04", 8, 0 },
165 	{ (u8 *) "\x30\x07\x01\x00\x00\x0f\xac\x04\x00", 9, -5 },
166 	{ (u8 *) "\x30\x08\x01\x00\x00\x0f\xac\x04\x00\x00", 10, -4 },
167 	{ (u8 *) "\x30\x08\x01\x00\x00\x0f\xac\x04\x00\x01", 10, -4 },
168 	{ (u8 *) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04",
169 	  14, 0 },
170 	{ (u8 *) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x00\x01\x00\x0f\xac\x04",
171 	  14, -4 },
172 	{ (u8 *) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x06",
173 	  14, -1 },
174 	{ (u8 *) "\x30\x10\x01\x00\x00\x0f\xac\x04\x02\x00\x00\x0f\xac\x04\x00\x0f\xac\x08",
175 	  18, 0 },
176 	{ (u8 *) "\x30\x0d\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00",
177 	  15, -7 },
178 	{ (u8 *) "\x30\x0e\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00\x00",
179 	  16, -6 },
180 	{ (u8 *) "\x30\x0e\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00\x01",
181 	  16, -6 },
182 	{ (u8 *) "\x30\x12\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01",
183 	  20, 0 },
184 	{ (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",
185 	  24, 0 },
186 	{ (u8 *) "\x30\x13\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00",
187 	  21, 0 },
188 	{ (u8 *) "\x30\x14\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00\x00",
189 	  22, 0 },
190 	{ (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",
191 	  24, 0 },
192 	{ (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",
193 	  24, -9 },
194 	{ (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",
195 	  28, -10 },
196 	{ (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",
197 	  28, 0 },
198 	{ (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",
199 	  30, 0 },
200 	{ NULL, 0, 0 }
201 };
202 
203 static int rsn_ie_parse_tests(void)
204 {
205 	int i, ret = 0;
206 
207 	wpa_printf(MSG_INFO, "rsn_ie_parse tests");
208 
209 	for (i = 0; rsn_parse_tests[i].data; i++) {
210 		const struct rsn_ie_parse_test_data *test;
211 		struct wpa_ie_data data;
212 
213 		test = &rsn_parse_tests[i];
214 		if (wpa_parse_wpa_ie_rsn(test->data, test->len, &data) !=
215 		    test->result) {
216 			wpa_printf(MSG_ERROR, "rsn_ie_parse test %d failed", i);
217 			ret = -1;
218 		}
219 	}
220 
221 	return ret;
222 }
223 
224 
225 static int gas_tests(void)
226 {
227 	struct wpabuf *buf;
228 
229 	wpa_printf(MSG_INFO, "gas tests");
230 	gas_anqp_set_len(NULL);
231 
232 	buf = wpabuf_alloc(1);
233 	if (buf == NULL)
234 		return -1;
235 	gas_anqp_set_len(buf);
236 	wpabuf_free(buf);
237 
238 	buf = wpabuf_alloc(20);
239 	if (buf == NULL)
240 		return -1;
241 	wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
242 	wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_REQ);
243 	wpabuf_put_u8(buf, 0);
244 	wpabuf_put_be32(buf, 0);
245 	wpabuf_put_u8(buf, 0);
246 	gas_anqp_set_len(buf);
247 	wpabuf_free(buf);
248 
249 	return 0;
250 }
251 
252 
253 static int sae_tests(void)
254 {
255 #ifdef CONFIG_SAE
256 	struct sae_data sae;
257 	int ret = -1;
258 	/* IEEE P802.11-REVmd/D2.1, Annex J.10 */
259 	const u8 addr1[ETH_ALEN] = { 0x82, 0x7b, 0x91, 0x9d, 0xd4, 0xb9 };
260 	const u8 addr2[ETH_ALEN] = { 0x1e, 0xec, 0x49, 0xea, 0x64, 0x88 };
261 	const char *pw = "mekmitasdigoat";
262 	const char *pwid = "psk4internet";
263 	const u8 local_rand[] = {
264 		0xa9, 0x06, 0xf6, 0x1e, 0x4d, 0x3a, 0x5d, 0x4e,
265 		0xb2, 0x96, 0x5f, 0xf3, 0x4c, 0xf9, 0x17, 0xdd,
266 		0x04, 0x44, 0x45, 0xc8, 0x78, 0xc1, 0x7c, 0xa5,
267 		0xd5, 0xb9, 0x37, 0x86, 0xda, 0x9f, 0x83, 0xcf
268 	};
269 	const u8 local_mask[] = {
270 		0x42, 0x34, 0xb4, 0xfb, 0x17, 0xaa, 0x43, 0x5c,
271 		0x52, 0xfb, 0xfd, 0xeb, 0xe6, 0x40, 0x39, 0xb4,
272 		0x34, 0x78, 0x20, 0x0e, 0x54, 0xff, 0x7b, 0x6e,
273 		0x07, 0xb6, 0x9c, 0xad, 0x74, 0x15, 0x3c, 0x15
274 	};
275 	const u8 local_commit[] = {
276 		0x13, 0x00, 0xeb, 0x3b, 0xab, 0x19, 0x64, 0xe4,
277 		0xa0, 0xab, 0x05, 0x92, 0x5d, 0xdf, 0x33, 0x39,
278 		0x51, 0x91, 0x38, 0xbc, 0x65, 0xd6, 0xcd, 0xc0,
279 		0xf8, 0x13, 0xdd, 0x6f, 0xd4, 0x34, 0x4e, 0xb4,
280 		0xbf, 0xe4, 0x4b, 0x5c, 0x21, 0x59, 0x76, 0x58,
281 		0xf4, 0xe3, 0xed, 0xdf, 0xb4, 0xb9, 0x9f, 0x25,
282 		0xb4, 0xd6, 0x54, 0x0f, 0x32, 0xff, 0x1f, 0xd5,
283 		0xc5, 0x30, 0xc6, 0x0a, 0x79, 0x44, 0x48, 0x61,
284 		0x0b, 0xc6, 0xde, 0x3d, 0x92, 0xbd, 0xbb, 0xd4,
285 		0x7d, 0x93, 0x59, 0x80, 0xca, 0x6c, 0xf8, 0x98,
286 		0x8a, 0xb6, 0x63, 0x0b, 0xe6, 0x76, 0x4c, 0x88,
287 		0x5c, 0xeb, 0x97, 0x93, 0x97, 0x0f, 0x69, 0x52,
288 		0x17, 0xee, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b,
289 		0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
290 		0x74
291 	};
292 	const u8 peer_commit[] = {
293 		0x13, 0x00, 0x55, 0x64, 0xf0, 0x45, 0xb2, 0xea,
294 		0x1e, 0x56, 0x6c, 0xf1, 0xdd, 0x74, 0x1f, 0x70,
295 		0xd9, 0xbe, 0x35, 0xd2, 0xdf, 0x5b, 0x9a, 0x55,
296 		0x02, 0x94, 0x6e, 0xe0, 0x3c, 0xf8, 0xda, 0xe2,
297 		0x7e, 0x1e, 0x05, 0xb8, 0x43, 0x0e, 0xb7, 0xa9,
298 		0x9e, 0x24, 0x87, 0x7c, 0xe6, 0x9b, 0xaf, 0x3d,
299 		0xc5, 0x80, 0xe3, 0x09, 0x63, 0x3d, 0x6b, 0x38,
300 		0x5f, 0x83, 0xee, 0x1c, 0x3e, 0xc3, 0x59, 0x1f,
301 		0x1a, 0x53, 0x93, 0xc0, 0x6e, 0x80, 0x5d, 0xdc,
302 		0xeb, 0x2f, 0xde, 0x50, 0x93, 0x0d, 0xd7, 0xcf,
303 		0xeb, 0xb9, 0x87, 0xc6, 0xff, 0x96, 0x66, 0xaf,
304 		0x16, 0x4e, 0xb5, 0x18, 0x4d, 0x8e, 0x66, 0x62,
305 		0xed, 0x6a, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b,
306 		0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
307 		0x74
308 	};
309 	const u8 kck[] = {
310 		0x59, 0x9d, 0x6f, 0x1e, 0x27, 0x54, 0x8b, 0xe8,
311 		0x49, 0x9d, 0xce, 0xed, 0x2f, 0xec, 0xcf, 0x94,
312 		0x81, 0x8c, 0xe1, 0xc7, 0x9f, 0x1b, 0x4e, 0xb3,
313 		0xd6, 0xa5, 0x32, 0x28, 0xa0, 0x9b, 0xf3, 0xed
314 	};
315 	const u8 pmk[] = {
316 		0x7a, 0xea, 0xd8, 0x6f, 0xba, 0x4c, 0x32, 0x21,
317 		0xfc, 0x43, 0x7f, 0x5f, 0x14, 0xd7, 0x0d, 0x85,
318 		0x4e, 0xa5, 0xd5, 0xaa, 0xc1, 0x69, 0x01, 0x16,
319 		0x79, 0x30, 0x81, 0xed, 0xa4, 0xd5, 0x57, 0xc5
320 	};
321 	const u8 pmkid[] = {
322 		0x40, 0xa0, 0x9b, 0x60, 0x17, 0xce, 0xbf, 0x00,
323 		0x72, 0x84, 0x3b, 0x53, 0x52, 0xaa, 0x2b, 0x4f
324 	};
325 	const u8 local_confirm[] = {
326 		0x01, 0x00, 0x12, 0xd9, 0xd5, 0xc7, 0x8c, 0x50,
327 		0x05, 0x26, 0xd3, 0x6c, 0x41, 0xdb, 0xc5, 0x6a,
328 		0xed, 0xf2, 0x91, 0x4c, 0xed, 0xdd, 0xd7, 0xca,
329 		0xd4, 0xa5, 0x8c, 0x48, 0xf8, 0x3d, 0xbd, 0xe9,
330 		0xfc, 0x77
331 	};
332 	const u8 peer_confirm[] = {
333 		0x01, 0x00, 0x02, 0x87, 0x1c, 0xf9, 0x06, 0x89,
334 		0x8b, 0x80, 0x60, 0xec, 0x18, 0x41, 0x43, 0xbe,
335 		0x77, 0xb8, 0xc0, 0x8a, 0x80, 0x19, 0xb1, 0x3e,
336 		0xb6, 0xd0, 0xae, 0xf0, 0xd8, 0x38, 0x3d, 0xfa,
337 		0xc2, 0xfd
338 	};
339 	struct wpabuf *buf = NULL;
340 	struct crypto_bignum *mask = NULL;
341 
342 	os_memset(&sae, 0, sizeof(sae));
343 	buf = wpabuf_alloc(1000);
344 	if (!buf ||
345 	    sae_set_group(&sae, 19) < 0 ||
346 	    sae_prepare_commit(addr1, addr2, (const u8 *) pw, os_strlen(pw),
347 			       pwid, &sae) < 0)
348 		goto fail;
349 
350 	/* Override local values based on SAE test vector */
351 	crypto_bignum_deinit(sae.tmp->sae_rand, 1);
352 	sae.tmp->sae_rand = crypto_bignum_init_set(local_rand,
353 						   sizeof(local_rand));
354 	mask = crypto_bignum_init_set(local_mask, sizeof(local_mask));
355 	if (!sae.tmp->sae_rand || !mask)
356 		goto fail;
357 
358 	if (crypto_bignum_add(sae.tmp->sae_rand, mask,
359 			      sae.tmp->own_commit_scalar) < 0 ||
360 	    crypto_bignum_mod(sae.tmp->own_commit_scalar, sae.tmp->order,
361 			      sae.tmp->own_commit_scalar) < 0 ||
362 	    crypto_ec_point_mul(sae.tmp->ec, sae.tmp->pwe_ecc, mask,
363 				sae.tmp->own_commit_element_ecc) < 0 ||
364 	    crypto_ec_point_invert(sae.tmp->ec,
365 				   sae.tmp->own_commit_element_ecc) < 0)
366 		goto fail;
367 
368 	/* Check that output matches the test vector */
369 	sae_write_commit(&sae, buf, NULL, pwid);
370 	wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
371 
372 	if (wpabuf_len(buf) != sizeof(local_commit) ||
373 	    os_memcmp(wpabuf_head(buf), local_commit,
374 		      sizeof(local_commit)) != 0) {
375 		wpa_printf(MSG_ERROR, "SAE: Mismatch in local commit");
376 		goto fail;
377 	}
378 
379 	if (sae_parse_commit(&sae, peer_commit, sizeof(peer_commit), NULL, NULL,
380 		    NULL) != 0 ||
381 	    sae_process_commit(&sae) < 0)
382 		goto fail;
383 
384 	if (os_memcmp(kck, sae.tmp->kck, SAE_KCK_LEN) != 0) {
385 		wpa_printf(MSG_ERROR, "SAE: Mismatch in KCK");
386 		goto fail;
387 	}
388 
389 	if (os_memcmp(pmk, sae.pmk, SAE_PMK_LEN) != 0) {
390 		wpa_printf(MSG_ERROR, "SAE: Mismatch in PMK");
391 		goto fail;
392 	}
393 
394 	if (os_memcmp(pmkid, sae.pmkid, SAE_PMKID_LEN) != 0) {
395 		wpa_printf(MSG_ERROR, "SAE: Mismatch in PMKID");
396 		goto fail;
397 	}
398 
399 	buf->used = 0;
400 	sae.send_confirm = 1;
401 	sae_write_confirm(&sae, buf);
402 	wpa_hexdump_buf(MSG_DEBUG, "SAE: Confirm message", buf);
403 
404 	if (wpabuf_len(buf) != sizeof(local_confirm) ||
405 	    os_memcmp(wpabuf_head(buf), local_confirm,
406 		      sizeof(local_confirm)) != 0) {
407 		wpa_printf(MSG_ERROR, "SAE: Mismatch in local confirm");
408 		goto fail;
409 	}
410 
411 	if (sae_check_confirm(&sae, peer_confirm, sizeof(peer_confirm)) < 0)
412 		goto fail;
413 
414 	ret = 0;
415 fail:
416 	sae_clear_data(&sae);
417 	wpabuf_free(buf);
418 	crypto_bignum_deinit(mask, 1);
419 	return ret;
420 #else /* CONFIG_SAE */
421 	return 0;
422 #endif /* CONFIG_SAE */
423 }
424 
425 
426 int common_module_tests(void)
427 {
428 	int ret = 0;
429 
430 	wpa_printf(MSG_INFO, "common module tests");
431 
432 	if (ieee802_11_parse_tests() < 0 ||
433 	    gas_tests() < 0 ||
434 	    sae_tests() < 0 ||
435 	    rsn_ie_parse_tests() < 0)
436 		ret = -1;
437 
438 	return ret;
439 }
440