Changeset a931b7b in mainline for uspace/lib/ieee80211/src/ieee80211.c
- Timestamp:
- 2015-04-13T20:48:33Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- cc575ef9
- Parents:
- 053fc2b
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ieee80211/src/ieee80211.c
r053fc2b ra931b7b 504 504 while(true) { 505 505 ieee80211_dev->ops->scan(ieee80211_dev); 506 async_usleep( 35000000);506 async_usleep(SCAN_PERIOD_USEC); 507 507 } 508 508 … … 577 577 memset(add_data, 0, 8); 578 578 579 // TODO: Distinguish used key (pair/group) by dest address ? 579 580 if(ieee80211_query_using_key(ieee80211_dev)) { 580 581 int sec_suite = auth_data->security.pair_alg; 581 582 switch(sec_suite) { 583 case IEEE80211_SECURITY_SUITE_TKIP: 584 add_size = IEEE80211_TKIP_HEADER_LENGTH; 585 // TODO: Add data? 586 break; 582 587 case IEEE80211_SECURITY_SUITE_CCMP: 583 588 add_size = IEEE80211_CCMP_HEADER_LENGTH; … … 978 983 payload_size; 979 984 980 if(auth_data->security.type == IEEE80211_SECURITY_WPA2) { 981 buffer_size += auth_link->rsn_copy_len; 985 if(auth_data->security.type == IEEE80211_SECURITY_WPA || 986 auth_data->security.type == IEEE80211_SECURITY_WPA2) { 987 buffer_size += auth_link->auth_ie_len; 982 988 } 983 989 … … 1017 1023 } 1018 1024 1019 if(auth_data->security.type == IEEE80211_SECURITY_WPA2) { 1020 memcpy(it, auth_link->rsn_copy, auth_link->rsn_copy_len); 1025 if(auth_data->security.type == IEEE80211_SECURITY_WPA || 1026 auth_data->security.type == IEEE80211_SECURITY_WPA2) { 1027 memcpy(it, auth_link->auth_ie, auth_link->auth_ie_len); 1021 1028 } 1022 1029 … … 1037 1044 /** 1038 1045 * IEEE 802.11 deauthentication implementation. 1046 * 1047 * Note: Expecting locked results_mutex or scan_mutex. 1039 1048 * 1040 1049 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. … … 1147 1156 { 1148 1157 return (*seq << 24) + (*(seq+1) << 16) + (*(seq+2) << 8) + *(seq+3); 1158 } 1159 1160 static void copy_auth_ie(ieee80211_ie_header_t *ie_header, 1161 ieee80211_scan_result_link_t *ap_data, void *it) 1162 { 1163 ap_data->auth_ie_len = ie_header->length + 1164 sizeof(ieee80211_ie_header_t); 1165 1166 memcpy(ap_data->auth_ie, it, ap_data->auth_ie_len); 1149 1167 } 1150 1168 … … 1170 1188 ieee80211_process_auth_info(ap_data, 1171 1189 it + sizeof(ieee80211_ie_header_t)); 1172 ap_data->rsn_copy_len = ie_header->length + 1173 sizeof(ieee80211_ie_header_t); 1174 memcpy(ap_data->rsn_copy, 1175 it, 1176 ap_data->rsn_copy_len); 1190 copy_auth_ie(ie_header, ap_data, it); 1177 1191 break; 1178 1192 case IEEE80211_VENDOR_IE: … … 1180 1194 sizeof(ieee80211_ie_header_t)) == 1181 1195 WPA_OUI) { 1196 /* Prefering WPA2. */ 1182 1197 if(ap_data->scan_result.security.type == 1183 1198 IEEE80211_SECURITY_WPA2) { … … 1190 1205 sizeof(ieee80211_ie_header_t) + 1191 1206 sizeof(uint32_t)); 1207 copy_auth_ie(ie_header, ap_data, it); 1192 1208 } else if(uint32_from_uint8_seq(it + 1193 1209 sizeof(ieee80211_ie_header_t)) == … … 1356 1372 (ieee80211_eapol_key_frame_t *) buffer; 1357 1373 1358 bool handshake_done = false; 1359 1360 ieee80211_scan_result_link_t *auth_link = 1374 ieee80211_scan_result_link_t *auth_link = 1361 1375 ieee80211_dev->bssid_info.res_link; 1362 1376 1363 1377 ieee80211_scan_result_t *auth_data = &auth_link->scan_result; 1378 1379 /* We don't support 802.1X authentication yet. */ 1380 if(auth_data->security.auth == IEEE80211_AUTH_AKM_8021X) { 1381 return ENOTSUP; 1382 } 1383 1364 1384 uint8_t *ptk = ieee80211_dev->bssid_info.ptk; 1365 1385 uint8_t *gtk = ieee80211_dev->bssid_info.gtk; 1366 1386 1387 bool handshake_done = false; 1388 1389 bool old_wpa = 1390 auth_data->security.type == IEEE80211_SECURITY_WPA; 1391 1392 bool key_phase = 1393 uint16_t_be2host(key_frame->key_info) & 1394 IEEE80211_EAPOL_KEY_KEYINFO_MIC; 1395 1396 bool final_phase = 1397 uint16_t_be2host(key_frame->key_info) & 1398 IEEE80211_EAPOL_KEY_KEYINFO_SECURE; 1399 1400 bool ccmp_used = 1401 auth_data->security.pair_alg == IEEE80211_SECURITY_SUITE_CCMP || 1402 auth_data->security.group_alg == IEEE80211_SECURITY_SUITE_CCMP; 1403 1367 1404 size_t ptk_key_length, gtk_key_length; 1368 hash_func_t hash_sel; 1369 switch(auth_data->security.pair_alg) { 1370 case IEEE80211_SECURITY_SUITE_CCMP: 1371 ptk_key_length = IEEE80211_PTK_CCMP_LENGTH; 1372 hash_sel = HASH_SHA1; 1373 break; 1374 default: 1375 return ENOTSUP; 1376 } 1377 1378 switch(auth_data->security.group_alg) { 1379 case IEEE80211_SECURITY_SUITE_CCMP: 1380 gtk_key_length = IEEE80211_GTK_CCMP_LENGTH; 1381 break; 1382 default: 1383 return ENOTSUP; 1384 } 1385 1405 hash_func_t mic_hash; 1406 if(ccmp_used) { 1407 mic_hash = HASH_SHA1; 1408 } else { 1409 mic_hash = HASH_MD5; 1410 } 1411 1412 if(auth_data->security.pair_alg == IEEE80211_SECURITY_SUITE_CCMP) { 1413 ptk_key_length = IEEE80211_PTK_CCMP_LENGTH; 1414 } else { 1415 ptk_key_length = IEEE80211_PTK_TKIP_LENGTH; 1416 } 1417 1418 if(auth_data->security.group_alg == IEEE80211_SECURITY_SUITE_CCMP) { 1419 gtk_key_length = IEEE80211_GTK_CCMP_LENGTH; 1420 } else { 1421 gtk_key_length = IEEE80211_GTK_TKIP_LENGTH; 1422 } 1423 1386 1424 size_t output_size = 1387 1425 sizeof(eth_header_t) + … … 1389 1427 1390 1428 if(!(uint16_t_be2host(key_frame->key_info) & 1391 IEEE80211_EAPOL_KEY_KEYINFO_ SECURE)) {1392 output_size += auth_link-> rsn_copy_len;1429 IEEE80211_EAPOL_KEY_KEYINFO_MIC)) { 1430 output_size += auth_link->auth_ie_len; 1393 1431 } 1394 1432 … … 1415 1453 1416 1454 output_key_frame->proto_version = 0x1; 1417 output_key_frame->key_length = 0;1418 1455 output_key_frame->body_length = 1419 host2uint16_t_be(output_size - sizeof(eth_header_t) -4);1456 host2uint16_t_be(output_size - sizeof(eth_header_t) - 4); 1420 1457 output_key_frame->key_info &= 1421 1458 ~host2uint16_t_be( … … 1423 1460 ); 1424 1461 1425 /* 1426 * Check if it is last or first incoming message in 4-way 1427 * handshake. 1428 */ 1429 if(uint16_t_be2host(key_frame->key_info) & 1430 IEEE80211_EAPOL_KEY_KEYINFO_SECURE) { 1462 if(key_phase) { 1431 1463 output_key_frame->key_info &= 1432 1464 ~host2uint16_t_be( … … 1438 1470 ); 1439 1471 output_key_frame->key_data_length = 0; 1440 output_key_frame->key_length = 0;1441 1472 memset(output_key_frame->key_nonce, 0, 32); 1442 1473 memset(output_key_frame->key_mic, 0, 16); … … 1445 1476 1446 1477 /* Derive GTK and save it. */ 1447 uint16_t key_data_length = 1448 uint16_t_be2host(key_frame->key_data_length); 1449 uint16_t decrypt_len = key_data_length - 8; 1450 uint8_t key_data[decrypt_len]; 1451 uint8_t *data_ptr = (uint8_t *) (buffer + 1452 sizeof(ieee80211_eapol_key_frame_t)); 1453 if(ieee80211_aes_key_unwrap(ptk + KEK_OFFSET, data_ptr, 1454 key_data_length, key_data) == EOK) { 1478 if(final_phase) { 1479 uint16_t key_data_length = 1480 uint16_t_be2host(key_frame->key_data_length); 1481 uint8_t key_data[key_data_length]; 1482 uint8_t *data_ptr = (uint8_t *) (buffer + 1483 sizeof(ieee80211_eapol_key_frame_t)); 1484 1485 int rc; 1486 uint8_t work_key[32]; 1487 1488 if(ccmp_used) { 1489 rc = ieee80211_aes_key_unwrap(ptk + KEK_OFFSET, 1490 data_ptr, key_data_length, key_data); 1491 } else { 1492 memcpy(work_key, key_frame->eapol_key_iv, 16); 1493 memcpy(work_key + 16, ptk + KEK_OFFSET, 16); 1494 rc = ieee80211_rc4_key_unwrap(work_key, 1495 data_ptr, key_data_length, key_data); 1496 } 1455 1497 1456 uint8_t *key_ptr = ieee80211_process_ies(ieee80211_dev, 1457 NULL, key_data, decrypt_len); 1458 1459 if(key_ptr) { 1460 memcpy(gtk, key_ptr, gtk_key_length); 1461 handshake_done = true; 1498 if(rc == EOK) { 1499 uint8_t *key_ptr = old_wpa ? key_data : 1500 ieee80211_process_ies(ieee80211_dev, 1501 NULL, key_data, key_data_length); 1502 1503 if(key_ptr) { 1504 memcpy(gtk, key_ptr, gtk_key_length); 1505 handshake_done = true; 1506 } 1462 1507 } 1463 1508 } … … 1468 1513 ); 1469 1514 output_key_frame->key_data_length = 1470 host2uint16_t_be(auth_link-> rsn_copy_len);1515 host2uint16_t_be(auth_link->auth_ie_len); 1471 1516 memcpy((void *)output_key_frame + 1472 1517 sizeof(ieee80211_eapol_key_frame_t), 1473 auth_link-> rsn_copy,1474 auth_link-> rsn_copy_len);1518 auth_link->auth_ie, 1519 auth_link->auth_ie_len); 1475 1520 1476 1521 /* Compute PMK. */ … … 1479 1524 str_size(ieee80211_dev->bssid_info.password), 1480 1525 (uint8_t *) auth_data->ssid, 1481 str_size(auth_data->ssid), pmk , hash_sel);1526 str_size(auth_data->ssid), pmk); 1482 1527 1483 1528 uint8_t *anonce = key_frame->key_nonce; … … 1493 1538 1494 1539 /* Derive PTK and save it. */ 1495 uint8_t prf_result[ptk_key_length];1496 1540 uint8_t crypt_data[PRF_CRYPT_DATA_LENGTH]; 1497 1541 memcpy(crypt_data, … … 1507 1551 max_sequence(anonce, snonce, 32), 1508 1552 32); 1509 ieee80211_prf(pmk, crypt_data, prf_result, hash_sel); 1510 memcpy(ptk, prf_result, ptk_key_length); 1553 ieee80211_prf(pmk, crypt_data, ptk, ptk_key_length); 1511 1554 } 1512 1555 1513 1556 /* Compute MIC of key frame data from KCK part of PTK. */ 1514 uint8_t mic[ hash_sel];1557 uint8_t mic[mic_hash]; 1515 1558 hmac(ptk, 16, (uint8_t *) output_key_frame, 1516 output_size - sizeof(eth_header_t), mic, hash_sel);1559 output_size - sizeof(eth_header_t), mic, mic_hash); 1517 1560 1518 1561 memcpy(output_key_frame->key_mic, mic, 16); … … 1522 1565 free(output_buffer); 1523 1566 1524 if(handshake_done) { 1525 /* Insert Pairwise key. */ 1526 ieee80211_key_config_t key_config; 1567 ieee80211_key_config_t key_config; 1568 1569 /* Insert Pairwise key. */ 1570 if((key_phase && old_wpa) || (final_phase && !old_wpa)) { 1527 1571 key_config.suite = auth_data->security.pair_alg; 1528 1572 key_config.flags = … … 1534 1578 ieee80211_dev->ops->key_config(ieee80211_dev, 1535 1579 &key_config, true); 1536 1537 /* Insert Group key. */ 1580 } 1581 1582 /* Insert Group key. */ 1583 if(final_phase) { 1538 1584 key_config.suite = auth_data->security.group_alg; 1539 1585 key_config.flags = … … 1543 1589 ieee80211_dev->ops->key_config(ieee80211_dev, 1544 1590 &key_config, true); 1545 1546 /* Signal successful handshake completion. */ 1591 } 1592 1593 /* Signal successful handshake completion. */ 1594 if(handshake_done) { 1547 1595 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 1548 1596 fibril_condvar_signal(&ieee80211_dev->gen_cond); … … 1586 1634 ARRAY_SIZE(rfc1042_header); 1587 1635 1588 /* TODO: Probably different by used security alg. */ 1636 /* TODO: Different by used security alg. */ 1637 /* TODO: Trim frame by used security alg. */ 1638 // TODO: Distinguish used key (pair/group) by dest address ? 1589 1639 if(ieee80211_is_encrypted_frame(data_header->frame_ctrl)) { 1590 1640 strip_length += 8;
Note:
See TracChangeset
for help on using the changeset viewer.