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 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 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 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 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 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 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 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 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 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