3 * Copyright (c) 2014-2019, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
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"
17 #include "wpa_common.h"
21 struct ieee802_11_parse_test_data
{
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,
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",
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",
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",
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,
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 }
86 static int ieee802_11_parse_tests(void)
91 wpa_printf(MSG_INFO
, "ieee802_11_parse tests");
93 for (i
= 0; parse_tests
[i
].data
; i
++) {
94 const struct ieee802_11_parse_test_data
*test
;
95 struct ieee802_11_elems elems
;
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",
108 if (ieee802_11_vendor_ie_concat((const u8
*) "\x00\x01", 2, 0) != NULL
)
110 wpa_printf(MSG_ERROR
,
111 "ieee802_11_vendor_ie_concat test failed");
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",
121 wpa_printf(MSG_ERROR
,
122 "ieee802_11_vendor_ie_concat test 2 failed");
127 if (wpabuf_len(buf
) != 2) {
128 wpa_printf(MSG_ERROR
,
129 "ieee802_11_vendor_ie_concat test 3 failed");
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");
148 struct rsn_ie_parse_test_data
{
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",
170 { (u8
*) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x00\x01\x00\x0f\xac\x04",
172 { (u8
*) "\x30\x0c\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x06",
174 { (u8
*) "\x30\x10\x01\x00\x00\x0f\xac\x04\x02\x00\x00\x0f\xac\x04\x00\x0f\xac\x08",
176 { (u8
*) "\x30\x0d\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00",
178 { (u8
*) "\x30\x0e\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00\x00",
180 { (u8
*) "\x30\x0e\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x00\x01",
182 { (u8
*) "\x30\x12\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01",
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",
186 { (u8
*) "\x30\x13\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00",
188 { (u8
*) "\x30\x14\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x00\x00",
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",
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",
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",
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",
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",
203 static int rsn_ie_parse_tests(void)
207 wpa_printf(MSG_INFO
, "rsn_ie_parse tests");
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
;
213 test
= &rsn_parse_tests
[i
];
214 if (wpa_parse_wpa_ie_rsn(test
->data
, test
->len
, &data
) !=
216 wpa_printf(MSG_ERROR
, "rsn_ie_parse test %d failed", i
);
225 static int gas_tests(void)
229 wpa_printf(MSG_INFO
, "gas tests");
230 gas_anqp_set_len(NULL
);
232 buf
= wpabuf_alloc(1);
235 gas_anqp_set_len(buf
);
238 buf
= wpabuf_alloc(20);
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
);
253 static int sae_tests(void)
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
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
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,
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,
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
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
322 0x40, 0xa0, 0x9b, 0x60, 0x17, 0xce, 0xbf, 0x00,
323 0x72, 0x84, 0x3b, 0x53, 0x52, 0xaa, 0x2b, 0x4f
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,
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,
339 struct wpabuf
*buf
= NULL
;
340 struct crypto_bignum
*mask
= NULL
;
342 os_memset(&sae
, 0, sizeof(sae
));
343 buf
= wpabuf_alloc(1000);
345 sae_set_group(&sae
, 19) < 0 ||
346 sae_prepare_commit(addr1
, addr2
, (const u8
*) pw
, os_strlen(pw
),
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
,
354 mask
= crypto_bignum_init_set(local_mask
, sizeof(local_mask
));
355 if (!sae
.tmp
->sae_rand
|| !mask
)
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)
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
);
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");
379 if (sae_parse_commit(&sae
, peer_commit
, sizeof(peer_commit
), NULL
, NULL
,
381 sae_process_commit(&sae
) < 0)
384 if (os_memcmp(kck
, sae
.tmp
->kck
, SAE_KCK_LEN
) != 0) {
385 wpa_printf(MSG_ERROR
, "SAE: Mismatch in KCK");
389 if (os_memcmp(pmk
, sae
.pmk
, SAE_PMK_LEN
) != 0) {
390 wpa_printf(MSG_ERROR
, "SAE: Mismatch in PMK");
394 if (os_memcmp(pmkid
, sae
.pmkid
, SAE_PMKID_LEN
) != 0) {
395 wpa_printf(MSG_ERROR
, "SAE: Mismatch in PMKID");
400 sae
.send_confirm
= 1;
401 sae_write_confirm(&sae
, buf
);
402 wpa_hexdump_buf(MSG_DEBUG
, "SAE: Confirm message", buf
);
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");
411 if (sae_check_confirm(&sae
, peer_confirm
, sizeof(peer_confirm
)) < 0)
416 sae_clear_data(&sae
);
418 crypto_bignum_deinit(mask
, 1);
420 #else /* CONFIG_SAE */
422 #endif /* CONFIG_SAE */
426 int common_module_tests(void)
430 wpa_printf(MSG_INFO
, "common module tests");
432 if (ieee802_11_parse_tests() < 0 ||
435 rsn_ie_parse_tests() < 0)