xref: /freebsd/contrib/wpa/src/common/common_module_tests.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
15b9c547cSRui Paulo /*
25b9c547cSRui Paulo  * common module tests
34bc52338SCy Schubert  * Copyright (c) 2014-2019, Jouni Malinen <j@w1.fi>
45b9c547cSRui Paulo  *
55b9c547cSRui Paulo  * This software may be distributed under the terms of the BSD license.
65b9c547cSRui Paulo  * See README for more details.
75b9c547cSRui Paulo  */
85b9c547cSRui Paulo 
95b9c547cSRui Paulo #include "utils/includes.h"
105b9c547cSRui Paulo 
115b9c547cSRui Paulo #include "utils/common.h"
12780fb4a2SCy Schubert #include "utils/module_tests.h"
134bc52338SCy Schubert #include "crypto/crypto.h"
14c1d255d3SCy Schubert #include "crypto/dh_groups.h"
155b9c547cSRui Paulo #include "ieee802_11_common.h"
16325151a3SRui Paulo #include "ieee802_11_defs.h"
17325151a3SRui Paulo #include "gas.h"
185b9c547cSRui Paulo #include "wpa_common.h"
194bc52338SCy Schubert #include "sae.h"
205b9c547cSRui Paulo 
215b9c547cSRui Paulo 
225b9c547cSRui Paulo struct ieee802_11_parse_test_data {
235b9c547cSRui Paulo 	u8 *data;
245b9c547cSRui Paulo 	size_t len;
255b9c547cSRui Paulo 	ParseRes result;
265b9c547cSRui Paulo 	int count;
275b9c547cSRui Paulo };
285b9c547cSRui Paulo 
295b9c547cSRui Paulo static const struct ieee802_11_parse_test_data parse_tests[] = {
305b9c547cSRui Paulo 	{ (u8 *) "", 0, ParseOK, 0 },
315b9c547cSRui Paulo 	{ (u8 *) " ", 1, ParseFailed, 0 },
325b9c547cSRui Paulo 	{ (u8 *) "\xff\x00", 2, ParseUnknown, 1 },
335b9c547cSRui Paulo 	{ (u8 *) "\xff\x01", 2, ParseFailed, 0 },
345b9c547cSRui Paulo 	{ (u8 *) "\xdd\x03\x01\x02\x03", 5, ParseUnknown, 1 },
355b9c547cSRui Paulo 	{ (u8 *) "\xdd\x04\x01\x02\x03\x04", 6, ParseUnknown, 1 },
365b9c547cSRui Paulo 	{ (u8 *) "\xdd\x04\x00\x50\xf2\x02", 6, ParseUnknown, 1 },
375b9c547cSRui Paulo 	{ (u8 *) "\xdd\x05\x00\x50\xf2\x02\x02", 7, ParseOK, 1 },
385b9c547cSRui Paulo 	{ (u8 *) "\xdd\x05\x00\x50\xf2\x02\xff", 7, ParseUnknown, 1 },
395b9c547cSRui Paulo 	{ (u8 *) "\xdd\x04\x00\x50\xf2\xff", 6, ParseUnknown, 1 },
405b9c547cSRui Paulo 	{ (u8 *) "\xdd\x04\x50\x6f\x9a\xff", 6, ParseUnknown, 1 },
415b9c547cSRui Paulo 	{ (u8 *) "\xdd\x04\x00\x90\x4c\x33", 6, ParseOK, 1 },
425b9c547cSRui Paulo 	{ (u8 *) "\xdd\x04\x00\x90\x4c\xff\xdd\x04\x00\x90\x4c\x33", 12,
435b9c547cSRui Paulo 	  ParseUnknown, 2 },
445b9c547cSRui Paulo 	{ (u8 *) "\x10\x01\x00\x21\x00", 5, ParseOK, 2 },
455b9c547cSRui Paulo 	{ (u8 *) "\x24\x00", 2, ParseOK, 1 },
465b9c547cSRui Paulo 	{ (u8 *) "\x38\x00", 2, ParseOK, 1 },
475b9c547cSRui Paulo 	{ (u8 *) "\x54\x00", 2, ParseOK, 1 },
485b9c547cSRui Paulo 	{ (u8 *) "\x5a\x00", 2, ParseOK, 1 },
495b9c547cSRui Paulo 	{ (u8 *) "\x65\x00", 2, ParseOK, 1 },
505b9c547cSRui Paulo 	{ (u8 *) "\x65\x12\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11",
515b9c547cSRui Paulo 	  20, ParseOK, 1 },
525b9c547cSRui Paulo 	{ (u8 *) "\x6e\x00", 2, ParseOK, 1 },
535b9c547cSRui Paulo 	{ (u8 *) "\xc7\x00", 2, ParseOK, 1 },
545b9c547cSRui Paulo 	{ (u8 *) "\xc7\x01\x00", 3, ParseOK, 1 },
55325151a3SRui Paulo 	{ (u8 *) "\x03\x00\x2a\x00\x36\x00\x37\x00\x38\x00\x2d\x00\x3d\x00\xbf\x00\xc0\x00",
56325151a3SRui Paulo 	  18, ParseOK, 9 },
57325151a3SRui Paulo 	{ (u8 *) "\x8b\x00", 2, ParseOK, 1 },
58325151a3SRui Paulo 	{ (u8 *) "\xdd\x04\x00\x90\x4c\x04", 6, ParseUnknown, 1 },
5985732ac8SCy Schubert 	{ (u8 *) "\xed\x00", 2, ParseOK, 1 },
6085732ac8SCy Schubert 	{ (u8 *) "\xef\x00", 2, ParseOK, 1 },
6185732ac8SCy Schubert 	{ (u8 *) "\xef\x01\x11", 3, ParseOK, 1 },
6285732ac8SCy Schubert 	{ (u8 *) "\xf0\x00", 2, ParseOK, 1 },
6385732ac8SCy Schubert 	{ (u8 *) "\xf1\x00", 2, ParseOK, 1 },
6485732ac8SCy Schubert 	{ (u8 *) "\xf1\x02\x11\x22", 4, ParseOK, 1 },
6585732ac8SCy Schubert 	{ (u8 *) "\xf2\x00", 2, ParseOK, 1 },
6685732ac8SCy Schubert 	{ (u8 *) "\xff\x00", 2, ParseUnknown, 1 },
6785732ac8SCy Schubert 	{ (u8 *) "\xff\x01\x00", 3, ParseUnknown, 1 },
6885732ac8SCy Schubert 	{ (u8 *) "\xff\x01\x01", 3, ParseOK, 1 },
6985732ac8SCy Schubert 	{ (u8 *) "\xff\x02\x01\x00", 4, ParseOK, 1 },
7085732ac8SCy Schubert 	{ (u8 *) "\xff\x01\x02", 3, ParseOK, 1 },
7185732ac8SCy Schubert 	{ (u8 *) "\xff\x04\x02\x11\x22\x33", 6, ParseOK, 1 },
7285732ac8SCy Schubert 	{ (u8 *) "\xff\x01\x04", 3, ParseOK, 1 },
7385732ac8SCy Schubert 	{ (u8 *) "\xff\x01\x05", 3, ParseOK, 1 },
7485732ac8SCy Schubert 	{ (u8 *) "\xff\x0d\x05\x11\x22\x33\x44\x55\x55\x11\x22\x33\x44\x55\x55",
7585732ac8SCy Schubert 	  15, ParseOK, 1 },
7685732ac8SCy Schubert 	{ (u8 *) "\xff\x01\x06", 3, ParseOK, 1 },
7785732ac8SCy Schubert 	{ (u8 *) "\xff\x02\x06\x00", 4, ParseOK, 1 },
7885732ac8SCy Schubert 	{ (u8 *) "\xff\x01\x07", 3, ParseOK, 1 },
7985732ac8SCy Schubert 	{ (u8 *) "\xff\x09\x07\x11\x22\x33\x44\x55\x66\x77\x88", 11,
8085732ac8SCy Schubert 	  ParseOK, 1 },
8185732ac8SCy Schubert 	{ (u8 *) "\xff\x01\x0c", 3, ParseOK, 1 },
8285732ac8SCy Schubert 	{ (u8 *) "\xff\x02\x0c\x00", 4, ParseOK, 1 },
8385732ac8SCy Schubert 	{ (u8 *) "\xff\x01\x0d", 3, ParseOK, 1 },
845b9c547cSRui Paulo 	{ NULL, 0, ParseOK, 0 }
855b9c547cSRui Paulo };
865b9c547cSRui Paulo 
ieee802_11_parse_tests(void)875b9c547cSRui Paulo static int ieee802_11_parse_tests(void)
885b9c547cSRui Paulo {
895b9c547cSRui Paulo 	int i, ret = 0;
9085732ac8SCy Schubert 	struct wpabuf *buf;
915b9c547cSRui Paulo 
925b9c547cSRui Paulo 	wpa_printf(MSG_INFO, "ieee802_11_parse tests");
935b9c547cSRui Paulo 
945b9c547cSRui Paulo 	for (i = 0; parse_tests[i].data; i++) {
955b9c547cSRui Paulo 		const struct ieee802_11_parse_test_data *test;
965b9c547cSRui Paulo 		struct ieee802_11_elems elems;
975b9c547cSRui Paulo 		ParseRes res;
985b9c547cSRui Paulo 
995b9c547cSRui Paulo 		test = &parse_tests[i];
1005b9c547cSRui Paulo 		res = ieee802_11_parse_elems(test->data, test->len, &elems, 1);
1015b9c547cSRui Paulo 		if (res != test->result ||
1025b9c547cSRui Paulo 		    ieee802_11_ie_count(test->data, test->len) != test->count) {
1035b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "ieee802_11_parse test %d failed",
1045b9c547cSRui Paulo 				   i);
1055b9c547cSRui Paulo 			ret = -1;
1065b9c547cSRui Paulo 		}
1075b9c547cSRui Paulo 	}
1085b9c547cSRui Paulo 
1095b9c547cSRui Paulo 	if (ieee802_11_vendor_ie_concat((const u8 *) "\x00\x01", 2, 0) != NULL)
1105b9c547cSRui Paulo 	{
1115b9c547cSRui Paulo 		wpa_printf(MSG_ERROR,
1125b9c547cSRui Paulo 			   "ieee802_11_vendor_ie_concat test failed");
1135b9c547cSRui Paulo 		ret = -1;
1145b9c547cSRui Paulo 	}
1155b9c547cSRui Paulo 
11685732ac8SCy Schubert 	buf = ieee802_11_vendor_ie_concat((const u8 *) "\xdd\x05\x11\x22\x33\x44\x01\xdd\x05\x11\x22\x33\x44\x02\x00\x01",
11785732ac8SCy Schubert 					  16, 0x11223344);
11885732ac8SCy Schubert 	do {
11985732ac8SCy Schubert 		const u8 *pos;
12085732ac8SCy Schubert 
12185732ac8SCy Schubert 		if (!buf) {
12285732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
12385732ac8SCy Schubert 				   "ieee802_11_vendor_ie_concat test 2 failed");
12485732ac8SCy Schubert 			ret = -1;
12585732ac8SCy Schubert 			break;
12685732ac8SCy Schubert 		}
12785732ac8SCy Schubert 
12885732ac8SCy Schubert 		if (wpabuf_len(buf) != 2) {
12985732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
13085732ac8SCy Schubert 				   "ieee802_11_vendor_ie_concat test 3 failed");
13185732ac8SCy Schubert 			ret = -1;
13285732ac8SCy Schubert 			break;
13385732ac8SCy Schubert 		}
13485732ac8SCy Schubert 
13585732ac8SCy Schubert 		pos = wpabuf_head(buf);
13685732ac8SCy Schubert 		if (pos[0] != 0x01 || pos[1] != 0x02) {
13785732ac8SCy Schubert 			wpa_printf(MSG_ERROR,
13885732ac8SCy Schubert 				   "ieee802_11_vendor_ie_concat test 3 failed");
13985732ac8SCy Schubert 			ret = -1;
14085732ac8SCy Schubert 			break;
14185732ac8SCy Schubert 		}
14285732ac8SCy Schubert 	} while (0);
14385732ac8SCy Schubert 	wpabuf_free(buf);
14485732ac8SCy Schubert 
1455b9c547cSRui Paulo 	return ret;
1465b9c547cSRui Paulo }
1475b9c547cSRui Paulo 
1485b9c547cSRui Paulo 
1495b9c547cSRui Paulo struct rsn_ie_parse_test_data {
1505b9c547cSRui Paulo 	u8 *data;
1515b9c547cSRui Paulo 	size_t len;
1525b9c547cSRui Paulo 	int result;
1535b9c547cSRui Paulo };
1545b9c547cSRui Paulo 
1555b9c547cSRui Paulo static const struct rsn_ie_parse_test_data rsn_parse_tests[] = {
1565b9c547cSRui Paulo 	{ (u8 *) "", 0, -1 },
1575b9c547cSRui Paulo 	{ (u8 *) "\x30\x00", 2, -1 },
1585b9c547cSRui Paulo 	{ (u8 *) "\x30\x02\x01\x00", 4, 0 },
1595b9c547cSRui Paulo 	{ (u8 *) "\x30\x02\x00\x00", 4, -2 },
1605b9c547cSRui Paulo 	{ (u8 *) "\x30\x02\x02\x00", 4, -2 },
1615b9c547cSRui Paulo 	{ (u8 *) "\x30\x02\x00\x01", 4, -2 },
1625b9c547cSRui Paulo 	{ (u8 *) "\x30\x02\x00\x00\x00", 5, -2 },
1635b9c547cSRui Paulo 	{ (u8 *) "\x30\x03\x01\x00\x00", 5, -3 },
1645b9c547cSRui Paulo 	{ (u8 *) "\x30\x06\x01\x00\x00\x00\x00\x00", 8, -1 },
1655b9c547cSRui Paulo 	{ (u8 *) "\x30\x06\x01\x00\x00\x0f\xac\x04", 8, 0 },
1665b9c547cSRui Paulo 	{ (u8 *) "\x30\x07\x01\x00\x00\x0f\xac\x04\x00", 9, -5 },
1675b9c547cSRui Paulo 	{ (u8 *) "\x30\x08\x01\x00\x00\x0f\xac\x04\x00\x00", 10, -4 },
1685b9c547cSRui Paulo 	{ (u8 *) "\x30\x08\x01\x00\x00\x0f\xac\x04\x00\x01", 10, -4 },
1695b9c547cSRui Paulo 	{ (u8 *) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04",
1705b9c547cSRui Paulo 	  14, 0 },
1715b9c547cSRui Paulo 	{ (u8 *) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x00\x01\x00\x0f\xac\x04",
1725b9c547cSRui Paulo 	  14, -4 },
1735b9c547cSRui Paulo 	{ (u8 *) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x06",
1745b9c547cSRui Paulo 	  14, -1 },
1755b9c547cSRui Paulo 	{ (u8 *) "\x30\x10\x01\x00\x00\x0f\xac\x04\x02\x00\x00\x0f\xac\x04\x00\x0f\xac\x08",
1765b9c547cSRui Paulo 	  18, 0 },
1775b9c547cSRui Paulo 	{ (u8 *) "\x30\x0d\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00",
1785b9c547cSRui Paulo 	  15, -7 },
1795b9c547cSRui Paulo 	{ (u8 *) "\x30\x0e\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00\x00",
1805b9c547cSRui Paulo 	  16, -6 },
1815b9c547cSRui Paulo 	{ (u8 *) "\x30\x0e\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00\x01",
1825b9c547cSRui Paulo 	  16, -6 },
1835b9c547cSRui Paulo 	{ (u8 *) "\x30\x12\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01",
1845b9c547cSRui Paulo 	  20, 0 },
1855b9c547cSRui Paulo 	{ (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",
1865b9c547cSRui Paulo 	  24, 0 },
1875b9c547cSRui Paulo 	{ (u8 *) "\x30\x13\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00",
1885b9c547cSRui Paulo 	  21, 0 },
1895b9c547cSRui Paulo 	{ (u8 *) "\x30\x14\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00\x00",
1905b9c547cSRui Paulo 	  22, 0 },
1915b9c547cSRui Paulo 	{ (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",
1925b9c547cSRui Paulo 	  24, 0 },
1935b9c547cSRui Paulo 	{ (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",
1945b9c547cSRui Paulo 	  24, -9 },
1955b9c547cSRui Paulo 	{ (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",
1965b9c547cSRui Paulo 	  28, -10 },
1975b9c547cSRui Paulo 	{ (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",
1985b9c547cSRui Paulo 	  28, 0 },
1995b9c547cSRui Paulo 	{ (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",
2005b9c547cSRui Paulo 	  30, 0 },
2015b9c547cSRui Paulo 	{ NULL, 0, 0 }
2025b9c547cSRui Paulo };
2035b9c547cSRui Paulo 
rsn_ie_parse_tests(void)2045b9c547cSRui Paulo static int rsn_ie_parse_tests(void)
2055b9c547cSRui Paulo {
2065b9c547cSRui Paulo 	int i, ret = 0;
2075b9c547cSRui Paulo 
2085b9c547cSRui Paulo 	wpa_printf(MSG_INFO, "rsn_ie_parse tests");
2095b9c547cSRui Paulo 
2105b9c547cSRui Paulo 	for (i = 0; rsn_parse_tests[i].data; i++) {
2115b9c547cSRui Paulo 		const struct rsn_ie_parse_test_data *test;
2125b9c547cSRui Paulo 		struct wpa_ie_data data;
2135b9c547cSRui Paulo 
2145b9c547cSRui Paulo 		test = &rsn_parse_tests[i];
2155b9c547cSRui Paulo 		if (wpa_parse_wpa_ie_rsn(test->data, test->len, &data) !=
2165b9c547cSRui Paulo 		    test->result) {
2175b9c547cSRui Paulo 			wpa_printf(MSG_ERROR, "rsn_ie_parse test %d failed", i);
2185b9c547cSRui Paulo 			ret = -1;
2195b9c547cSRui Paulo 		}
2205b9c547cSRui Paulo 	}
2215b9c547cSRui Paulo 
2225b9c547cSRui Paulo 	return ret;
2235b9c547cSRui Paulo }
2245b9c547cSRui Paulo 
2255b9c547cSRui Paulo 
gas_tests(void)226325151a3SRui Paulo static int gas_tests(void)
227325151a3SRui Paulo {
228325151a3SRui Paulo 	struct wpabuf *buf;
229325151a3SRui Paulo 
230325151a3SRui Paulo 	wpa_printf(MSG_INFO, "gas tests");
231325151a3SRui Paulo 	gas_anqp_set_len(NULL);
232325151a3SRui Paulo 
233325151a3SRui Paulo 	buf = wpabuf_alloc(1);
234325151a3SRui Paulo 	if (buf == NULL)
235325151a3SRui Paulo 		return -1;
236325151a3SRui Paulo 	gas_anqp_set_len(buf);
237325151a3SRui Paulo 	wpabuf_free(buf);
238325151a3SRui Paulo 
239325151a3SRui Paulo 	buf = wpabuf_alloc(20);
240325151a3SRui Paulo 	if (buf == NULL)
241325151a3SRui Paulo 		return -1;
242325151a3SRui Paulo 	wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
243325151a3SRui Paulo 	wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_REQ);
244325151a3SRui Paulo 	wpabuf_put_u8(buf, 0);
245325151a3SRui Paulo 	wpabuf_put_be32(buf, 0);
246325151a3SRui Paulo 	wpabuf_put_u8(buf, 0);
247325151a3SRui Paulo 	gas_anqp_set_len(buf);
248325151a3SRui Paulo 	wpabuf_free(buf);
249325151a3SRui Paulo 
250325151a3SRui Paulo 	return 0;
251325151a3SRui Paulo }
252325151a3SRui Paulo 
253325151a3SRui Paulo 
sae_tests(void)2544bc52338SCy Schubert static int sae_tests(void)
2554bc52338SCy Schubert {
2564bc52338SCy Schubert #ifdef CONFIG_SAE
2574bc52338SCy Schubert 	struct sae_data sae;
2584bc52338SCy Schubert 	int ret = -1;
259c1d255d3SCy Schubert 	/* IEEE Std 802.11-2020, Annex J.10 */
260c1d255d3SCy Schubert 	const u8 addr1[ETH_ALEN] = { 0x4d, 0x3f, 0x2f, 0xff, 0xe3, 0x87 };
261c1d255d3SCy Schubert 	const u8 addr2[ETH_ALEN] = { 0xa5, 0xd8, 0xaa, 0x95, 0x8e, 0x3c };
262c1d255d3SCy Schubert 	const char *ssid = "byteme";
2634bc52338SCy Schubert 	const char *pw = "mekmitasdigoat";
2644bc52338SCy Schubert 	const char *pwid = "psk4internet";
2654bc52338SCy Schubert 	const u8 local_rand[] = {
266c1d255d3SCy Schubert 		0x99, 0x24, 0x65, 0xfd, 0x3d, 0xaa, 0x3c, 0x60,
267c1d255d3SCy Schubert 		0xaa, 0x65, 0x65, 0xb7, 0xf6, 0x2a, 0x2a, 0x7f,
268c1d255d3SCy Schubert 		0x2e, 0x12, 0xdd, 0x12, 0xf1, 0x98, 0xfa, 0xf4,
269c1d255d3SCy Schubert 		0xfb, 0xed, 0x89, 0xd7, 0xff, 0x1a, 0xce, 0x94
2704bc52338SCy Schubert 	};
2714bc52338SCy Schubert 	const u8 local_mask[] = {
272c1d255d3SCy Schubert 		0x95, 0x07, 0xa9, 0x0f, 0x77, 0x7a, 0x04, 0x4d,
273c1d255d3SCy Schubert 		0x6a, 0x08, 0x30, 0xb9, 0x1e, 0xa3, 0xd5, 0xdd,
274c1d255d3SCy Schubert 		0x70, 0xbe, 0xce, 0x44, 0xe1, 0xac, 0xff, 0xb8,
275c1d255d3SCy Schubert 		0x69, 0x83, 0xb5, 0xe1, 0xbf, 0x9f, 0xb3, 0x22
2764bc52338SCy Schubert 	};
2774bc52338SCy Schubert 	const u8 local_commit[] = {
278c1d255d3SCy Schubert 		0x13, 0x00, 0x2e, 0x2c, 0x0f, 0x0d, 0xb5, 0x24,
279c1d255d3SCy Schubert 		0x40, 0xad, 0x14, 0x6d, 0x96, 0x71, 0x14, 0xce,
280c1d255d3SCy Schubert 		0x00, 0x5c, 0xe1, 0xea, 0xb0, 0xaa, 0x2c, 0x2e,
281c1d255d3SCy Schubert 		0x5c, 0x28, 0x71, 0xb7, 0x74, 0xf6, 0xc2, 0x57,
282c1d255d3SCy Schubert 		0x5c, 0x65, 0xd5, 0xad, 0x9e, 0x00, 0x82, 0x97,
283c1d255d3SCy Schubert 		0x07, 0xaa, 0x36, 0xba, 0x8b, 0x85, 0x97, 0x38,
284c1d255d3SCy Schubert 		0xfc, 0x96, 0x1d, 0x08, 0x24, 0x35, 0x05, 0xf4,
285c1d255d3SCy Schubert 		0x7c, 0x03, 0x53, 0x76, 0xd7, 0xac, 0x4b, 0xc8,
286c1d255d3SCy Schubert 		0xd7, 0xb9, 0x50, 0x83, 0xbf, 0x43, 0x82, 0x7d,
287c1d255d3SCy Schubert 		0x0f, 0xc3, 0x1e, 0xd7, 0x78, 0xdd, 0x36, 0x71,
288c1d255d3SCy Schubert 		0xfd, 0x21, 0xa4, 0x6d, 0x10, 0x91, 0xd6, 0x4b,
289c1d255d3SCy Schubert 		0x6f, 0x9a, 0x1e, 0x12, 0x72, 0x62, 0x13, 0x25,
290c1d255d3SCy Schubert 		0xdb, 0xe1
2914bc52338SCy Schubert 	};
2924bc52338SCy Schubert 	const u8 peer_commit[] = {
293c1d255d3SCy Schubert 		0x13, 0x00, 0x59, 0x1b, 0x96, 0xf3, 0x39, 0x7f,
294c1d255d3SCy Schubert 		0xb9, 0x45, 0x10, 0x08, 0x48, 0xe7, 0xb5, 0x50,
295c1d255d3SCy Schubert 		0x54, 0x3b, 0x67, 0x20, 0xd8, 0x83, 0x37, 0xee,
296c1d255d3SCy Schubert 		0x93, 0xfc, 0x49, 0xfd, 0x6d, 0xf7, 0xe0, 0x8b,
297c1d255d3SCy Schubert 		0x52, 0x23, 0xe7, 0x1b, 0x9b, 0xb0, 0x48, 0xd3,
298c1d255d3SCy Schubert 		0x87, 0x3f, 0x20, 0x55, 0x69, 0x53, 0xa9, 0x6c,
299c1d255d3SCy Schubert 		0x91, 0x53, 0x6f, 0xd8, 0xee, 0x6c, 0xa9, 0xb4,
300c1d255d3SCy Schubert 		0xa6, 0x8a, 0x14, 0x8b, 0x05, 0x6a, 0x90, 0x9b,
301c1d255d3SCy Schubert 		0xe0, 0x3e, 0x83, 0xae, 0x20, 0x8f, 0x60, 0xf8,
302c1d255d3SCy Schubert 		0xef, 0x55, 0x37, 0x85, 0x80, 0x74, 0xdb, 0x06,
303c1d255d3SCy Schubert 		0x68, 0x70, 0x32, 0x39, 0x98, 0x62, 0x99, 0x9b,
304c1d255d3SCy Schubert 		0x51, 0x1e, 0x0a, 0x15, 0x52, 0xa5, 0xfe, 0xa3,
305c1d255d3SCy Schubert 		0x17, 0xc2
3064bc52338SCy Schubert 	};
3074bc52338SCy Schubert 	const u8 kck[] = {
308c1d255d3SCy Schubert 		0x1e, 0x73, 0x3f, 0x6d, 0x9b, 0xd5, 0x32, 0x56,
309c1d255d3SCy Schubert 		0x28, 0x73, 0x04, 0x33, 0x88, 0x31, 0xb0, 0x9a,
310c1d255d3SCy Schubert 		0x39, 0x40, 0x6d, 0x12, 0x10, 0x17, 0x07, 0x3a,
311c1d255d3SCy Schubert 		0x5c, 0x30, 0xdb, 0x36, 0xf3, 0x6c, 0xb8, 0x1a
3124bc52338SCy Schubert 	};
3134bc52338SCy Schubert 	const u8 pmk[] = {
314c1d255d3SCy Schubert 		0x4e, 0x4d, 0xfa, 0xb1, 0xa2, 0xdd, 0x8a, 0xc1,
315c1d255d3SCy Schubert 		0xa9, 0x17, 0x90, 0xf9, 0x53, 0xfa, 0xaa, 0x45,
316c1d255d3SCy Schubert 		0x2a, 0xe5, 0xc6, 0x87, 0x3a, 0xb7, 0x5b, 0x63,
317c1d255d3SCy Schubert 		0x60, 0x5b, 0xa6, 0x63, 0xf8, 0xa7, 0xfe, 0x59
3184bc52338SCy Schubert 	};
3194bc52338SCy Schubert 	const u8 pmkid[] = {
320c1d255d3SCy Schubert 		0x87, 0x47, 0xa6, 0x00, 0xee, 0xa3, 0xf9, 0xf2,
321c1d255d3SCy Schubert 		0x24, 0x75, 0xdf, 0x58, 0xca, 0x1e, 0x54, 0x98
3224bc52338SCy Schubert 	};
3234bc52338SCy Schubert 	struct wpabuf *buf = NULL;
3244bc52338SCy Schubert 	struct crypto_bignum *mask = NULL;
325c1d255d3SCy Schubert 	const u8 pwe_19_x[32] = {
326c1d255d3SCy Schubert 		0xc9, 0x30, 0x49, 0xb9, 0xe6, 0x40, 0x00, 0xf8,
327c1d255d3SCy Schubert 		0x48, 0x20, 0x16, 0x49, 0xe9, 0x99, 0xf2, 0xb5,
328c1d255d3SCy Schubert 		0xc2, 0x2d, 0xea, 0x69, 0xb5, 0x63, 0x2c, 0x9d,
329c1d255d3SCy Schubert 		0xf4, 0xd6, 0x33, 0xb8, 0xaa, 0x1f, 0x6c, 0x1e
330c1d255d3SCy Schubert 	};
331c1d255d3SCy Schubert 	const u8 pwe_19_y[32] = {
332c1d255d3SCy Schubert 		0x73, 0x63, 0x4e, 0x94, 0xb5, 0x3d, 0x82, 0xe7,
333c1d255d3SCy Schubert 		0x38, 0x3a, 0x8d, 0x25, 0x81, 0x99, 0xd9, 0xdc,
334c1d255d3SCy Schubert 		0x1a, 0x5e, 0xe8, 0x26, 0x9d, 0x06, 0x03, 0x82,
335c1d255d3SCy Schubert 		0xcc, 0xbf, 0x33, 0xe6, 0x14, 0xff, 0x59, 0xa0
336c1d255d3SCy Schubert 	};
337c1d255d3SCy Schubert 	const u8 pwe_15[384] = {
338c1d255d3SCy Schubert 		0x69, 0x68, 0x73, 0x65, 0x8f, 0x65, 0x31, 0x42,
339c1d255d3SCy Schubert 		0x9f, 0x97, 0x39, 0x6f, 0xb8, 0x5f, 0x89, 0xe1,
340c1d255d3SCy Schubert 		0xfc, 0xd2, 0xf6, 0x92, 0x19, 0xa9, 0x0e, 0x82,
341c1d255d3SCy Schubert 		0x2f, 0xf7, 0xf4, 0xbc, 0x0b, 0xd8, 0xa7, 0x9f,
342c1d255d3SCy Schubert 		0xf0, 0x80, 0x35, 0x31, 0x6f, 0xca, 0xe1, 0xa5,
343c1d255d3SCy Schubert 		0x39, 0x77, 0xdc, 0x11, 0x2b, 0x0b, 0xfe, 0x2e,
344c1d255d3SCy Schubert 		0x6f, 0x65, 0x6d, 0xc7, 0xd4, 0xa4, 0x5b, 0x08,
345c1d255d3SCy Schubert 		0x1f, 0xd9, 0xbb, 0xe2, 0x22, 0x85, 0x31, 0x81,
346c1d255d3SCy Schubert 		0x79, 0x70, 0xbe, 0xa1, 0x66, 0x58, 0x4a, 0x09,
347c1d255d3SCy Schubert 		0x3c, 0x57, 0x34, 0x3c, 0x9d, 0x57, 0x8f, 0x42,
348c1d255d3SCy Schubert 		0x58, 0xd0, 0x39, 0x81, 0xdb, 0x8f, 0x79, 0xa2,
349c1d255d3SCy Schubert 		0x1b, 0x01, 0xcd, 0x27, 0xc9, 0xae, 0xcf, 0xcb,
350c1d255d3SCy Schubert 		0x9c, 0xdb, 0x1f, 0x84, 0xb8, 0x88, 0x4e, 0x8f,
351c1d255d3SCy Schubert 		0x50, 0x66, 0xb4, 0x29, 0x83, 0x1e, 0xb9, 0x89,
352c1d255d3SCy Schubert 		0x0c, 0xa5, 0x47, 0x21, 0xba, 0x10, 0xd5, 0xaa,
353c1d255d3SCy Schubert 		0x1a, 0x80, 0xce, 0xf1, 0x4c, 0xad, 0x16, 0xda,
354c1d255d3SCy Schubert 		0x57, 0xb2, 0x41, 0x8a, 0xbe, 0x4b, 0x8c, 0xb0,
355c1d255d3SCy Schubert 		0xb2, 0xeb, 0xf7, 0xa8, 0x0e, 0x3e, 0xcf, 0x22,
356c1d255d3SCy Schubert 		0x8f, 0xd8, 0xb6, 0xdb, 0x79, 0x9c, 0x9b, 0x80,
357c1d255d3SCy Schubert 		0xaf, 0xd7, 0x14, 0xad, 0x51, 0x82, 0xf4, 0x64,
358c1d255d3SCy Schubert 		0xb6, 0x3f, 0x4c, 0x6c, 0xe5, 0x3f, 0xaa, 0x6f,
359c1d255d3SCy Schubert 		0xbf, 0x3d, 0xc2, 0x3f, 0x77, 0xfd, 0xcb, 0xe1,
360c1d255d3SCy Schubert 		0x9c, 0xe3, 0x1e, 0x8a, 0x0e, 0x97, 0xe2, 0x2b,
361c1d255d3SCy Schubert 		0xe2, 0xdd, 0x37, 0x39, 0x88, 0xc2, 0x8e, 0xbe,
362c1d255d3SCy Schubert 		0xfa, 0xac, 0x3d, 0x5b, 0x62, 0x2e, 0x1e, 0x74,
363c1d255d3SCy Schubert 		0xa0, 0x9a, 0xf8, 0xed, 0xfa, 0xe1, 0xce, 0x9c,
364c1d255d3SCy Schubert 		0xab, 0xbb, 0xdc, 0x36, 0xb1, 0x28, 0x46, 0x3c,
365c1d255d3SCy Schubert 		0x7e, 0xa8, 0xbd, 0xb9, 0x36, 0x4c, 0x26, 0x75,
366c1d255d3SCy Schubert 		0xe0, 0x17, 0x73, 0x1f, 0xe0, 0xfe, 0xf6, 0x49,
367c1d255d3SCy Schubert 		0xfa, 0xa0, 0x45, 0xf4, 0x44, 0x05, 0x20, 0x27,
368c1d255d3SCy Schubert 		0x25, 0xc2, 0x99, 0xde, 0x27, 0x8b, 0x70, 0xdc,
369c1d255d3SCy Schubert 		0x54, 0x60, 0x90, 0x02, 0x1e, 0x29, 0x97, 0x9a,
370c1d255d3SCy Schubert 		0xc4, 0xe7, 0xb6, 0xf5, 0x8b, 0xae, 0x7c, 0x34,
371c1d255d3SCy Schubert 		0xaa, 0xef, 0x9b, 0xc6, 0x30, 0xf2, 0x80, 0x8d,
372c1d255d3SCy Schubert 		0x80, 0x78, 0xc2, 0x55, 0x63, 0xa0, 0xa1, 0x38,
373c1d255d3SCy Schubert 		0x70, 0xfb, 0xf4, 0x74, 0x8d, 0xcd, 0x87, 0x90,
374c1d255d3SCy Schubert 		0xb4, 0x54, 0xc3, 0x75, 0xdf, 0x10, 0xc5, 0xb6,
375c1d255d3SCy Schubert 		0xb2, 0x08, 0x59, 0x61, 0xe6, 0x68, 0xa5, 0x82,
376c1d255d3SCy Schubert 		0xf8, 0x8f, 0x47, 0x30, 0x43, 0xb4, 0xdc, 0x31,
377c1d255d3SCy Schubert 		0xfc, 0xbc, 0x69, 0xe7, 0xb4, 0x94, 0xb0, 0x6a,
378c1d255d3SCy Schubert 		0x60, 0x59, 0x80, 0x2e, 0xd3, 0xa4, 0xe8, 0x97,
379c1d255d3SCy Schubert 		0xa2, 0xa3, 0xc9, 0x08, 0x4b, 0x27, 0x6c, 0xc1,
380c1d255d3SCy Schubert 		0x37, 0xe8, 0xfc, 0x5c, 0xe2, 0x54, 0x30, 0x3e,
381c1d255d3SCy Schubert 		0xf8, 0xfe, 0xa2, 0xfc, 0xbb, 0xbd, 0x88, 0x6c,
382c1d255d3SCy Schubert 		0x92, 0xa3, 0x2a, 0x40, 0x7a, 0x2c, 0x22, 0x38,
383c1d255d3SCy Schubert 		0x8c, 0x86, 0x86, 0xfe, 0xb9, 0xd4, 0x6b, 0xd6,
384c1d255d3SCy Schubert 		0x47, 0x88, 0xa7, 0xf6, 0x8e, 0x0f, 0x14, 0xad,
385c1d255d3SCy Schubert 		0x1e, 0xac, 0xcf, 0x33, 0x01, 0x99, 0xc1, 0x62
386c1d255d3SCy Schubert 	};
387c1d255d3SCy Schubert 	int pt_groups[] = { 19, 20, 21, 25, 26, 28, 29, 30, 15, 0 };
388c1d255d3SCy Schubert 	struct sae_pt *pt_info, *pt;
389c1d255d3SCy Schubert 	const u8 addr1b[ETH_ALEN] = { 0x00, 0x09, 0x5b, 0x66, 0xec, 0x1e };
390c1d255d3SCy Schubert 	const u8 addr2b[ETH_ALEN] = { 0x00, 0x0b, 0x6b, 0xd9, 0x02, 0x46 };
3914bc52338SCy Schubert 
3924bc52338SCy Schubert 	os_memset(&sae, 0, sizeof(sae));
3934bc52338SCy Schubert 	buf = wpabuf_alloc(1000);
3944bc52338SCy Schubert 	if (!buf ||
3954bc52338SCy Schubert 	    sae_set_group(&sae, 19) < 0 ||
3964bc52338SCy Schubert 	    sae_prepare_commit(addr1, addr2, (const u8 *) pw, os_strlen(pw),
397c1d255d3SCy Schubert 			       &sae) < 0)
3984bc52338SCy Schubert 		goto fail;
3994bc52338SCy Schubert 
4004bc52338SCy Schubert 	/* Override local values based on SAE test vector */
4014bc52338SCy Schubert 	crypto_bignum_deinit(sae.tmp->sae_rand, 1);
4024bc52338SCy Schubert 	sae.tmp->sae_rand = crypto_bignum_init_set(local_rand,
4034bc52338SCy Schubert 						   sizeof(local_rand));
4044bc52338SCy Schubert 	mask = crypto_bignum_init_set(local_mask, sizeof(local_mask));
4054bc52338SCy Schubert 	if (!sae.tmp->sae_rand || !mask)
4064bc52338SCy Schubert 		goto fail;
4074bc52338SCy Schubert 
4084bc52338SCy Schubert 	if (crypto_bignum_add(sae.tmp->sae_rand, mask,
4094bc52338SCy Schubert 			      sae.tmp->own_commit_scalar) < 0 ||
4104bc52338SCy Schubert 	    crypto_bignum_mod(sae.tmp->own_commit_scalar, sae.tmp->order,
4114bc52338SCy Schubert 			      sae.tmp->own_commit_scalar) < 0 ||
4124bc52338SCy Schubert 	    crypto_ec_point_mul(sae.tmp->ec, sae.tmp->pwe_ecc, mask,
4134bc52338SCy Schubert 				sae.tmp->own_commit_element_ecc) < 0 ||
4144bc52338SCy Schubert 	    crypto_ec_point_invert(sae.tmp->ec,
4154bc52338SCy Schubert 				   sae.tmp->own_commit_element_ecc) < 0)
4164bc52338SCy Schubert 		goto fail;
4174bc52338SCy Schubert 
4184bc52338SCy Schubert 	/* Check that output matches the test vector */
419c1d255d3SCy Schubert 	if (sae_write_commit(&sae, buf, NULL, NULL) < 0)
420c1d255d3SCy Schubert 		goto fail;
4214bc52338SCy Schubert 	wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
4224bc52338SCy Schubert 
4234bc52338SCy Schubert 	if (wpabuf_len(buf) != sizeof(local_commit) ||
4244bc52338SCy Schubert 	    os_memcmp(wpabuf_head(buf), local_commit,
4254bc52338SCy Schubert 		      sizeof(local_commit)) != 0) {
4264bc52338SCy Schubert 		wpa_printf(MSG_ERROR, "SAE: Mismatch in local commit");
4274bc52338SCy Schubert 		goto fail;
4284bc52338SCy Schubert 	}
4294bc52338SCy Schubert 
4304bc52338SCy Schubert 	if (sae_parse_commit(&sae, peer_commit, sizeof(peer_commit), NULL, NULL,
431*a90b9d01SCy Schubert 			     NULL, 0, NULL) != 0 ||
4324bc52338SCy Schubert 	    sae_process_commit(&sae) < 0)
4334bc52338SCy Schubert 		goto fail;
4344bc52338SCy Schubert 
4354bc52338SCy Schubert 	if (os_memcmp(kck, sae.tmp->kck, SAE_KCK_LEN) != 0) {
4364bc52338SCy Schubert 		wpa_printf(MSG_ERROR, "SAE: Mismatch in KCK");
4374bc52338SCy Schubert 		goto fail;
4384bc52338SCy Schubert 	}
4394bc52338SCy Schubert 
4404bc52338SCy Schubert 	if (os_memcmp(pmk, sae.pmk, SAE_PMK_LEN) != 0) {
4414bc52338SCy Schubert 		wpa_printf(MSG_ERROR, "SAE: Mismatch in PMK");
4424bc52338SCy Schubert 		goto fail;
4434bc52338SCy Schubert 	}
4444bc52338SCy Schubert 
4454bc52338SCy Schubert 	if (os_memcmp(pmkid, sae.pmkid, SAE_PMKID_LEN) != 0) {
4464bc52338SCy Schubert 		wpa_printf(MSG_ERROR, "SAE: Mismatch in PMKID");
4474bc52338SCy Schubert 		goto fail;
4484bc52338SCy Schubert 	}
4494bc52338SCy Schubert 
450c1d255d3SCy Schubert 	pt_info = sae_derive_pt(pt_groups,
451c1d255d3SCy Schubert 				(const u8 *) ssid, os_strlen(ssid),
452c1d255d3SCy Schubert 				(const u8 *) pw, os_strlen(pw), pwid);
453c1d255d3SCy Schubert 	if (!pt_info)
454c1d255d3SCy Schubert 		goto fail;
4554bc52338SCy Schubert 
456c1d255d3SCy Schubert 	for (pt = pt_info; pt; pt = pt->next) {
457c1d255d3SCy Schubert 		if (pt->group == 19) {
458c1d255d3SCy Schubert 			struct crypto_ec_point *pwe;
459c1d255d3SCy Schubert 			u8 bin[SAE_MAX_ECC_PRIME_LEN * 2];
460c1d255d3SCy Schubert 			size_t prime_len = sizeof(pwe_19_x);
461c1d255d3SCy Schubert 
462c1d255d3SCy Schubert 			pwe = sae_derive_pwe_from_pt_ecc(pt, addr1b, addr2b);
463c1d255d3SCy Schubert 			if (!pwe) {
464c1d255d3SCy Schubert 				sae_deinit_pt(pt);
4654bc52338SCy Schubert 				goto fail;
4664bc52338SCy Schubert 			}
467c1d255d3SCy Schubert 			if (crypto_ec_point_to_bin(pt->ec, pwe, bin,
468c1d255d3SCy Schubert 						   bin + prime_len) < 0 ||
469c1d255d3SCy Schubert 			    os_memcmp(pwe_19_x, bin, prime_len) != 0 ||
470c1d255d3SCy Schubert 			    os_memcmp(pwe_19_y, bin + prime_len,
471c1d255d3SCy Schubert 				      prime_len) != 0) {
472c1d255d3SCy Schubert 				wpa_printf(MSG_ERROR,
473c1d255d3SCy Schubert 					   "SAE: PT/PWE test vector mismatch");
474c1d255d3SCy Schubert 				crypto_ec_point_deinit(pwe, 1);
475c1d255d3SCy Schubert 				sae_deinit_pt(pt);
4764bc52338SCy Schubert 				goto fail;
477c1d255d3SCy Schubert 			}
478c1d255d3SCy Schubert 			crypto_ec_point_deinit(pwe, 1);
479c1d255d3SCy Schubert 		}
480c1d255d3SCy Schubert 
481c1d255d3SCy Schubert 		if (pt->group == 15) {
482c1d255d3SCy Schubert 			struct crypto_bignum *pwe;
483c1d255d3SCy Schubert 			u8 bin[SAE_MAX_PRIME_LEN];
484c1d255d3SCy Schubert 			size_t prime_len = sizeof(pwe_15);
485c1d255d3SCy Schubert 
486c1d255d3SCy Schubert 			pwe = sae_derive_pwe_from_pt_ffc(pt, addr1b, addr2b);
487c1d255d3SCy Schubert 			if (!pwe) {
488c1d255d3SCy Schubert 				sae_deinit_pt(pt);
489c1d255d3SCy Schubert 				goto fail;
490c1d255d3SCy Schubert 			}
491c1d255d3SCy Schubert 			if (crypto_bignum_to_bin(pwe, bin, sizeof(bin),
492c1d255d3SCy Schubert 						 prime_len) < 0 ||
493c1d255d3SCy Schubert 			    os_memcmp(pwe_15, bin, prime_len) != 0) {
494c1d255d3SCy Schubert 				wpa_printf(MSG_ERROR,
495c1d255d3SCy Schubert 					   "SAE: PT/PWE test vector mismatch");
496c1d255d3SCy Schubert 				crypto_bignum_deinit(pwe, 1);
497c1d255d3SCy Schubert 				sae_deinit_pt(pt);
498c1d255d3SCy Schubert 				goto fail;
499c1d255d3SCy Schubert 			}
500c1d255d3SCy Schubert 			crypto_bignum_deinit(pwe, 1);
501c1d255d3SCy Schubert 		}
502c1d255d3SCy Schubert 	}
503c1d255d3SCy Schubert 
504c1d255d3SCy Schubert 	sae_deinit_pt(pt_info);
5054bc52338SCy Schubert 
5064bc52338SCy Schubert 	ret = 0;
5074bc52338SCy Schubert fail:
5084bc52338SCy Schubert 	sae_clear_data(&sae);
5094bc52338SCy Schubert 	wpabuf_free(buf);
5104bc52338SCy Schubert 	crypto_bignum_deinit(mask, 1);
5114bc52338SCy Schubert 	return ret;
5124bc52338SCy Schubert #else /* CONFIG_SAE */
5134bc52338SCy Schubert 	return 0;
5144bc52338SCy Schubert #endif /* CONFIG_SAE */
5154bc52338SCy Schubert }
5164bc52338SCy Schubert 
5174bc52338SCy Schubert 
sae_pk_tests(void)518c1d255d3SCy Schubert static int sae_pk_tests(void)
519c1d255d3SCy Schubert {
520c1d255d3SCy Schubert #ifdef CONFIG_SAE_PK
521c1d255d3SCy Schubert 	const char *invalid[] = { "a2bc-de3f-ghim-", "a2bcde3fghim", "", NULL };
522c1d255d3SCy Schubert 	struct {
523c1d255d3SCy Schubert 		const char *pw;
524c1d255d3SCy Schubert 		const u8 *val;
525c1d255d3SCy Schubert 	} valid[] = {
526c1d255d3SCy Schubert 		{ "a2bc-de3f-ghim", (u8 *) "\x06\x82\x21\x93\x65\x31\xd0\xc0" },
527c1d255d3SCy Schubert 		{ "aaaa-aaaa-aaaj", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x90" },
528c1d255d3SCy Schubert 		{ "7777-7777-777f", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe\x50" },
529c1d255d3SCy Schubert 		{ NULL, NULL }
530c1d255d3SCy Schubert 	};
531c1d255d3SCy Schubert 	int i;
532c1d255d3SCy Schubert 	bool failed;
533c1d255d3SCy Schubert 
534c1d255d3SCy Schubert 	for (i = 0; invalid[i]; i++) {
535c1d255d3SCy Schubert 		if (sae_pk_valid_password(invalid[i])) {
536c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
537c1d255d3SCy Schubert 				   "SAE-PK: Invalid password '%s' not recognized",
538c1d255d3SCy Schubert 				   invalid[i]);
539c1d255d3SCy Schubert 			return -1;
540c1d255d3SCy Schubert 		}
541c1d255d3SCy Schubert 	}
542c1d255d3SCy Schubert 
543c1d255d3SCy Schubert 	failed = false;
544c1d255d3SCy Schubert 	for (i = 0; valid[i].pw; i++) {
545c1d255d3SCy Schubert 		u8 *res;
546c1d255d3SCy Schubert 		size_t res_len;
547c1d255d3SCy Schubert 		char *b32;
548c1d255d3SCy Schubert 		const char *pw = valid[i].pw;
549c1d255d3SCy Schubert 		const u8 *val = valid[i].val;
550c1d255d3SCy Schubert 		size_t pw_len = os_strlen(pw);
551c1d255d3SCy Schubert 		size_t bits = (pw_len - pw_len / 5) * 5;
552c1d255d3SCy Schubert 		size_t bytes = (bits + 7) / 8;
553c1d255d3SCy Schubert 
554c1d255d3SCy Schubert 		if (!sae_pk_valid_password(pw)) {
555c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
556c1d255d3SCy Schubert 				   "SAE-PK: Valid password '%s' not recognized",
557c1d255d3SCy Schubert 				   pw);
558c1d255d3SCy Schubert 			failed = true;
559c1d255d3SCy Schubert 			continue;
560c1d255d3SCy Schubert 		}
561c1d255d3SCy Schubert 
562c1d255d3SCy Schubert 		res = sae_pk_base32_decode(pw, pw_len, &res_len);
563c1d255d3SCy Schubert 		if (!res) {
564c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
565c1d255d3SCy Schubert 				   "SAE-PK: Failed to decode password '%s'",
566c1d255d3SCy Schubert 				   valid[i].pw);
567c1d255d3SCy Schubert 			failed = true;
568c1d255d3SCy Schubert 			continue;
569c1d255d3SCy Schubert 		}
570c1d255d3SCy Schubert 		if (res_len != bytes || os_memcmp(val, res, res_len) != 0) {
571c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
572c1d255d3SCy Schubert 				   "SAE-PK: Mismatch for decoded password '%s'",
573c1d255d3SCy Schubert 				   valid[i].pw);
574c1d255d3SCy Schubert 			wpa_hexdump(MSG_INFO, "SAE-PK: Decoded value",
575c1d255d3SCy Schubert 				    res, res_len);
576c1d255d3SCy Schubert 			wpa_hexdump(MSG_INFO, "SAE-PK: Expected value",
577c1d255d3SCy Schubert 				    val, bytes);
578c1d255d3SCy Schubert 			failed = true;
579c1d255d3SCy Schubert 		}
580c1d255d3SCy Schubert 		os_free(res);
581c1d255d3SCy Schubert 
582c1d255d3SCy Schubert 		b32 = sae_pk_base32_encode(val, bits - 5);
583c1d255d3SCy Schubert 		if (!b32) {
584c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
585c1d255d3SCy Schubert 				   "SAE-PK: Failed to encode password '%s'",
586c1d255d3SCy Schubert 				   pw);
587c1d255d3SCy Schubert 			failed = true;
588c1d255d3SCy Schubert 			continue;
589c1d255d3SCy Schubert 		}
590c1d255d3SCy Schubert 		if (os_strcmp(b32, pw) != 0) {
591c1d255d3SCy Schubert 			wpa_printf(MSG_ERROR,
592c1d255d3SCy Schubert 				   "SAE-PK: Mismatch for password '%s'", pw);
593c1d255d3SCy Schubert 			wpa_printf(MSG_INFO, "SAE-PK: Encoded value: '%s'",
594c1d255d3SCy Schubert 				   b32);
595c1d255d3SCy Schubert 			failed = true;
596c1d255d3SCy Schubert 		}
597c1d255d3SCy Schubert 		os_free(b32);
598c1d255d3SCy Schubert 	}
599c1d255d3SCy Schubert 
600c1d255d3SCy Schubert 	return failed ? -1 : 0;
601c1d255d3SCy Schubert #else /* CONFIG_SAE_PK */
602c1d255d3SCy Schubert 	return 0;
603c1d255d3SCy Schubert #endif /* CONFIG_SAE_PK */
604c1d255d3SCy Schubert }
605c1d255d3SCy Schubert 
606c1d255d3SCy Schubert 
607c1d255d3SCy Schubert #ifdef CONFIG_PASN
608c1d255d3SCy Schubert 
pasn_test_pasn_auth(void)609c1d255d3SCy Schubert static int pasn_test_pasn_auth(void)
610c1d255d3SCy Schubert {
611c1d255d3SCy Schubert 	/* Test vector taken from IEEE P802.11az/D2.6, J.12 */
612c1d255d3SCy Schubert 	const u8 pmk[] = {
613c1d255d3SCy Schubert 		0xde, 0xf4, 0x3e, 0x55, 0x67, 0xe0, 0x1c, 0xa6,
614c1d255d3SCy Schubert 		0x64, 0x92, 0x65, 0xf1, 0x9a, 0x29, 0x0e, 0xef,
615c1d255d3SCy Schubert 		0xf8, 0xbd, 0x88, 0x8f, 0x6c, 0x1d, 0x9c, 0xc9,
616c1d255d3SCy Schubert 		0xd1, 0x0f, 0x04, 0xbd, 0x37, 0x8f, 0x3c, 0xad
617c1d255d3SCy Schubert 	};
618c1d255d3SCy Schubert 
619c1d255d3SCy Schubert 	const u8 spa_addr[] = {
620c1d255d3SCy Schubert 		0x00, 0x90, 0x4c, 0x01, 0xc1, 0x07
621c1d255d3SCy Schubert 	};
622c1d255d3SCy Schubert 	const u8 bssid[] = {
623c1d255d3SCy Schubert 		0xc0, 0xff, 0xd4, 0xa8, 0xdb, 0xc1
624c1d255d3SCy Schubert 	};
625c1d255d3SCy Schubert 	const u8 dhss[] = {
626c1d255d3SCy Schubert 		0xf8, 0x7b, 0x20, 0x8e, 0x7e, 0xd2, 0xb7, 0x37,
627c1d255d3SCy Schubert 		0xaf, 0xdb, 0xc2, 0xe1, 0x3e, 0xae, 0x78, 0xda,
628c1d255d3SCy Schubert 		0x30, 0x01, 0x23, 0xd4, 0xd8, 0x4b, 0xa8, 0xb0,
629c1d255d3SCy Schubert 		0xea, 0xfe, 0x90, 0xc4, 0x8c, 0xdf, 0x1f, 0x93
630c1d255d3SCy Schubert 	};
631c1d255d3SCy Schubert 	const u8 kck[] = {
632c1d255d3SCy Schubert 		0x7b, 0xb8, 0x21, 0xac, 0x0a, 0xa5, 0x90, 0x9d,
633c1d255d3SCy Schubert 		0xd6, 0x54, 0xa5, 0x60, 0x65, 0xad, 0x7c, 0x77,
634c1d255d3SCy Schubert 		0xeb, 0x88, 0x9c, 0xbe, 0x29, 0x05, 0xbb, 0xf0,
635c1d255d3SCy Schubert 		0x5a, 0xbb, 0x1e, 0xea, 0xc8, 0x8b, 0xa3, 0x06
636c1d255d3SCy Schubert 	};
637c1d255d3SCy Schubert 	const u8 tk[] = {
638c1d255d3SCy Schubert 		0x67, 0x3e, 0xab, 0x46, 0xb8, 0x32, 0xd5, 0xa8,
639c1d255d3SCy Schubert 		0x0c, 0xbc, 0x02, 0x43, 0x01, 0x6e, 0x20, 0x7e
640c1d255d3SCy Schubert 	};
641c1d255d3SCy Schubert 	const u8 kdk[] = {
642c1d255d3SCy Schubert 		0x2d, 0x0f, 0x0e, 0x82, 0xc7, 0x0d, 0xd2, 0x6b,
643c1d255d3SCy Schubert 		0x79, 0x06, 0x1a, 0x46, 0x81, 0xe8, 0xdb, 0xb2,
644c1d255d3SCy Schubert 		0xea, 0x83, 0xbe, 0xa3, 0x99, 0x84, 0x4b, 0xd5,
645c1d255d3SCy Schubert 		0x89, 0x4e, 0xb3, 0x20, 0xf6, 0x9d, 0x7d, 0xd6
646c1d255d3SCy Schubert 	};
647c1d255d3SCy Schubert 	struct wpa_ptk ptk;
648c1d255d3SCy Schubert 	int ret;
649c1d255d3SCy Schubert 
650c1d255d3SCy Schubert 	ret = pasn_pmk_to_ptk(pmk, sizeof(pmk),
651c1d255d3SCy Schubert 			      spa_addr, bssid,
652c1d255d3SCy Schubert 			      dhss, sizeof(dhss),
653c1d255d3SCy Schubert 			      &ptk, WPA_KEY_MGMT_PASN, WPA_CIPHER_CCMP,
654c1d255d3SCy Schubert 			      WPA_KDK_MAX_LEN);
655c1d255d3SCy Schubert 
656c1d255d3SCy Schubert 	if (ret)
657c1d255d3SCy Schubert 		return ret;
658c1d255d3SCy Schubert 
659c1d255d3SCy Schubert 	if (ptk.kck_len != sizeof(kck) ||
660c1d255d3SCy Schubert 	    os_memcmp(kck, ptk.kck, sizeof(kck)) != 0) {
661c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "PASN: Mismatched KCK");
662c1d255d3SCy Schubert 		return -1;
663c1d255d3SCy Schubert 	}
664c1d255d3SCy Schubert 
665c1d255d3SCy Schubert 	if (ptk.tk_len != sizeof(tk) ||
666c1d255d3SCy Schubert 	    os_memcmp(tk, ptk.tk, sizeof(tk)) != 0) {
667c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "PASN: Mismatched TK");
668c1d255d3SCy Schubert 		return -1;
669c1d255d3SCy Schubert 	}
670c1d255d3SCy Schubert 
671c1d255d3SCy Schubert 	if (ptk.kdk_len != sizeof(kdk) ||
672c1d255d3SCy Schubert 	    os_memcmp(kdk, ptk.kdk, sizeof(kdk)) != 0) {
673c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "PASN: Mismatched KDK");
674c1d255d3SCy Schubert 		return -1;
675c1d255d3SCy Schubert 	}
676c1d255d3SCy Schubert 
677c1d255d3SCy Schubert 	return 0;
678c1d255d3SCy Schubert }
679c1d255d3SCy Schubert 
680c1d255d3SCy Schubert 
pasn_test_no_pasn_auth(void)681c1d255d3SCy Schubert static int pasn_test_no_pasn_auth(void)
682c1d255d3SCy Schubert {
683c1d255d3SCy Schubert 	/* Test vector taken from IEEE P802.11az/D2.6, J.13 */
684c1d255d3SCy Schubert 	const u8 pmk[] = {
685c1d255d3SCy Schubert 		0xde, 0xf4, 0x3e, 0x55, 0x67, 0xe0, 0x1c, 0xa6,
686c1d255d3SCy Schubert 		0x64, 0x92, 0x65, 0xf1, 0x9a, 0x29, 0x0e, 0xef,
687c1d255d3SCy Schubert 		0xf8, 0xbd, 0x88, 0x8f, 0x6c, 0x1d, 0x9c, 0xc9,
688c1d255d3SCy Schubert 		0xd1, 0x0f, 0x04, 0xbd, 0x37, 0x8f, 0x3c, 0xad
689c1d255d3SCy Schubert 	};
690c1d255d3SCy Schubert 	const u8 aa[] = {
691c1d255d3SCy Schubert 		0xc0, 0xff, 0xd4, 0xa8, 0xdb, 0xc1
692c1d255d3SCy Schubert 	};
693c1d255d3SCy Schubert 	const u8 spa[] = {
694c1d255d3SCy Schubert 		0x00, 0x90, 0x4c, 0x01, 0xc1, 0x07
695c1d255d3SCy Schubert 	};
696c1d255d3SCy Schubert 	const u8 anonce[] = {
697c1d255d3SCy Schubert 		0xbe, 0x7a, 0x1c, 0xa2, 0x84, 0x34, 0x7b, 0x5b,
698c1d255d3SCy Schubert 		0xd6, 0x7d, 0xbd, 0x2d, 0xfd, 0xb4, 0xd9, 0x9f,
699c1d255d3SCy Schubert 		0x1a, 0xfa, 0xe0, 0xb8, 0x8b, 0xa1, 0x8e, 0x00,
700c1d255d3SCy Schubert 		0x87, 0x18, 0x41, 0x7e, 0x4b, 0x27, 0xef, 0x5f
701c1d255d3SCy Schubert 	};
702c1d255d3SCy Schubert 	const u8 snonce[] = {
703c1d255d3SCy Schubert 		0x40, 0x4b, 0x01, 0x2f, 0xfb, 0x43, 0xed, 0x0f,
704c1d255d3SCy Schubert 		0xb4, 0x3e, 0xa1, 0xf2, 0x87, 0xc9, 0x1f, 0x25,
705c1d255d3SCy Schubert 		0x06, 0xd2, 0x1b, 0x4a, 0x92, 0xd7, 0x4b, 0x5e,
706c1d255d3SCy Schubert 		0xa5, 0x0c, 0x94, 0x33, 0x50, 0xce, 0x86, 0x71
707c1d255d3SCy Schubert 	};
708c1d255d3SCy Schubert 	const u8 kck[] = {
709c1d255d3SCy Schubert 		0xcd, 0x7b, 0x9e, 0x75, 0x55, 0x36, 0x2d, 0xf0,
710c1d255d3SCy Schubert 		0xb6, 0x35, 0x68, 0x48, 0x4a, 0x81, 0x12, 0xf5
711c1d255d3SCy Schubert 	};
712c1d255d3SCy Schubert 	const u8 kek[] = {
713c1d255d3SCy Schubert 		0x99, 0xca, 0xd3, 0x58, 0x8d, 0xa0, 0xf1, 0xe6,
714c1d255d3SCy Schubert 		0x3f, 0xd1, 0x90, 0x19, 0x10, 0x39, 0xbb, 0x4b
715c1d255d3SCy Schubert 	};
716c1d255d3SCy Schubert 	const u8 tk[] = {
717c1d255d3SCy Schubert 		0x9e, 0x2e, 0x93, 0x77, 0xe7, 0x53, 0x2e, 0x73,
718c1d255d3SCy Schubert 		0x7a, 0x1b, 0xc2, 0x50, 0xfe, 0x19, 0x4a, 0x03
719c1d255d3SCy Schubert 	};
720c1d255d3SCy Schubert 	const u8 kdk[] = {
721c1d255d3SCy Schubert 		0x6c, 0x7f, 0xb9, 0x7c, 0xeb, 0x55, 0xb0, 0x1a,
722c1d255d3SCy Schubert 		0xcf, 0xf0, 0x0f, 0x07, 0x09, 0x42, 0xbd, 0xf5,
723c1d255d3SCy Schubert 		0x29, 0x1f, 0xeb, 0x4b, 0xee, 0x38, 0xe0, 0x36,
724c1d255d3SCy Schubert 		0x5b, 0x25, 0xa2, 0x50, 0xbb, 0x2a, 0xc9, 0xff
725c1d255d3SCy Schubert 	};
726c1d255d3SCy Schubert 	struct wpa_ptk ptk;
727c1d255d3SCy Schubert 	int ret;
728c1d255d3SCy Schubert 
729c1d255d3SCy Schubert 	ret = wpa_pmk_to_ptk(pmk, sizeof(pmk),
730c1d255d3SCy Schubert 			     "Pairwise key expansion",
731c1d255d3SCy Schubert 			     spa, aa, snonce, anonce,
732c1d255d3SCy Schubert 			     &ptk, WPA_KEY_MGMT_SAE, WPA_CIPHER_CCMP,
733c1d255d3SCy Schubert 			     NULL, 0, WPA_KDK_MAX_LEN);
734c1d255d3SCy Schubert 
735c1d255d3SCy Schubert 	if (ret)
736c1d255d3SCy Schubert 		return ret;
737c1d255d3SCy Schubert 
738c1d255d3SCy Schubert 	if (ptk.kck_len != sizeof(kck) ||
739c1d255d3SCy Schubert 	    os_memcmp(kck, ptk.kck, sizeof(kck)) != 0) {
740c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched KCK");
741c1d255d3SCy Schubert 		return -1;
742c1d255d3SCy Schubert 	}
743c1d255d3SCy Schubert 
744c1d255d3SCy Schubert 	if (ptk.kek_len != sizeof(kek) ||
745c1d255d3SCy Schubert 	    os_memcmp(kek, ptk.kek, sizeof(kek)) != 0) {
746c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched KEK");
747c1d255d3SCy Schubert 		return -1;
748c1d255d3SCy Schubert 	}
749c1d255d3SCy Schubert 
750c1d255d3SCy Schubert 	if (ptk.tk_len != sizeof(tk) ||
751c1d255d3SCy Schubert 	    os_memcmp(tk, ptk.tk, sizeof(tk)) != 0) {
752c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched TK");
753c1d255d3SCy Schubert 		return -1;
754c1d255d3SCy Schubert 	}
755c1d255d3SCy Schubert 
756c1d255d3SCy Schubert 	if (ptk.kdk_len != sizeof(kdk) ||
757c1d255d3SCy Schubert 	    os_memcmp(kdk, ptk.kdk, sizeof(kdk)) != 0) {
758c1d255d3SCy Schubert 		wpa_printf(MSG_ERROR, "KDK no PASN auth: Mismatched KDK");
759c1d255d3SCy Schubert 		return -1;
760c1d255d3SCy Schubert 	}
761c1d255d3SCy Schubert 
762c1d255d3SCy Schubert 	return 0;
763c1d255d3SCy Schubert }
764c1d255d3SCy Schubert 
765c1d255d3SCy Schubert #endif /* CONFIG_PASN */
766c1d255d3SCy Schubert 
767c1d255d3SCy Schubert 
pasn_tests(void)768c1d255d3SCy Schubert static int pasn_tests(void)
769c1d255d3SCy Schubert {
770c1d255d3SCy Schubert #ifdef CONFIG_PASN
771c1d255d3SCy Schubert 	if (pasn_test_pasn_auth() ||
772c1d255d3SCy Schubert 	    pasn_test_no_pasn_auth())
773c1d255d3SCy Schubert 		return -1;
774c1d255d3SCy Schubert #endif /* CONFIG_PASN */
775c1d255d3SCy Schubert 	return 0;
776c1d255d3SCy Schubert }
777c1d255d3SCy Schubert 
778c1d255d3SCy Schubert 
common_module_tests(void)7795b9c547cSRui Paulo int common_module_tests(void)
7805b9c547cSRui Paulo {
7815b9c547cSRui Paulo 	int ret = 0;
7825b9c547cSRui Paulo 
7835b9c547cSRui Paulo 	wpa_printf(MSG_INFO, "common module tests");
7845b9c547cSRui Paulo 
7855b9c547cSRui Paulo 	if (ieee802_11_parse_tests() < 0 ||
786325151a3SRui Paulo 	    gas_tests() < 0 ||
7874bc52338SCy Schubert 	    sae_tests() < 0 ||
788c1d255d3SCy Schubert 	    sae_pk_tests() < 0 ||
789c1d255d3SCy Schubert 	    pasn_tests() < 0 ||
7905b9c547cSRui Paulo 	    rsn_ie_parse_tests() < 0)
7915b9c547cSRui Paulo 		ret = -1;
7925b9c547cSRui Paulo 
7935b9c547cSRui Paulo 	return ret;
7945b9c547cSRui Paulo }
795