Changeset a931b7b in mainline for uspace/lib/ieee80211/src/ieee80211.c


Ignore:
Timestamp:
2015-04-13T20:48:33Z (10 years ago)
Author:
Jan Kolarik <kolarik@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
cc575ef9
Parents:
053fc2b
Message:

Added TKIP support, handling old WPA in 4way handshake, some fixes in wifi_supplicant app

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ieee80211/src/ieee80211.c

    r053fc2b ra931b7b  
    504504        while(true) {
    505505                ieee80211_dev->ops->scan(ieee80211_dev);
    506                 async_usleep(35000000);
     506                async_usleep(SCAN_PERIOD_USEC);
    507507        }
    508508       
     
    577577        memset(add_data, 0, 8);
    578578       
     579        // TODO: Distinguish used key (pair/group) by dest address ?
    579580        if(ieee80211_query_using_key(ieee80211_dev)) {
    580581                int sec_suite = auth_data->security.pair_alg;
    581582                switch(sec_suite) {
     583                        case IEEE80211_SECURITY_SUITE_TKIP:
     584                                add_size = IEEE80211_TKIP_HEADER_LENGTH;
     585                                // TODO: Add data?
     586                                break;
    582587                        case IEEE80211_SECURITY_SUITE_CCMP:
    583588                                add_size = IEEE80211_CCMP_HEADER_LENGTH;
     
    978983                payload_size;
    979984       
    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;
    982988        }
    983989       
     
    10171023        }
    10181024       
    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);
    10211028        }
    10221029       
     
    10371044/**
    10381045 * IEEE 802.11 deauthentication implementation.
     1046 *
     1047 * Note: Expecting locked results_mutex or scan_mutex.
    10391048 *
    10401049 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
     
    11471156{
    11481157        return (*seq << 24) + (*(seq+1) << 16) + (*(seq+2) << 8) + *(seq+3);
     1158}
     1159
     1160static 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);
    11491167}
    11501168
     
    11701188                                ieee80211_process_auth_info(ap_data,
    11711189                                        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);
    11771191                                break;
    11781192                        case IEEE80211_VENDOR_IE:
     
    11801194                                        sizeof(ieee80211_ie_header_t)) ==
    11811195                                        WPA_OUI) {
     1196                                        /* Prefering WPA2. */
    11821197                                        if(ap_data->scan_result.security.type ==
    11831198                                                IEEE80211_SECURITY_WPA2) {
     
    11901205                                                sizeof(ieee80211_ie_header_t) +
    11911206                                                sizeof(uint32_t));
     1207                                        copy_auth_ie(ie_header, ap_data, it);
    11921208                                } else if(uint32_from_uint8_seq(it +
    11931209                                        sizeof(ieee80211_ie_header_t)) ==
     
    13561372                (ieee80211_eapol_key_frame_t *) buffer;
    13571373       
    1358         bool handshake_done = false;
    1359                
    1360         ieee80211_scan_result_link_t *auth_link =
     1374        ieee80211_scan_result_link_t *auth_link =
    13611375                ieee80211_dev->bssid_info.res_link;
    13621376
    13631377        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       
    13641384        uint8_t *ptk = ieee80211_dev->bssid_info.ptk;
    13651385        uint8_t *gtk = ieee80211_dev->bssid_info.gtk;
    13661386
     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       
    13671404        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       
    13861424        size_t output_size =
    13871425                sizeof(eth_header_t) +
     
    13891427
    13901428        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;
    13931431        }
    13941432
     
    14151453
    14161454        output_key_frame->proto_version = 0x1;
    1417         output_key_frame->key_length = 0;
    14181455        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);
    14201457        output_key_frame->key_info &=
    14211458                ~host2uint16_t_be(
     
    14231460                );
    14241461
    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) {
    14311463                output_key_frame->key_info &=
    14321464                        ~host2uint16_t_be(
     
    14381470                        );
    14391471                output_key_frame->key_data_length = 0;
    1440                 output_key_frame->key_length = 0;
    14411472                memset(output_key_frame->key_nonce, 0, 32);
    14421473                memset(output_key_frame->key_mic, 0, 16);
     
    14451476
    14461477                /* 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                        }
    14551497                       
    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                                }
    14621507                        }
    14631508                }
     
    14681513                        );
    14691514                output_key_frame->key_data_length =
    1470                         host2uint16_t_be(auth_link->rsn_copy_len);
     1515                        host2uint16_t_be(auth_link->auth_ie_len);
    14711516                memcpy((void *)output_key_frame +
    14721517                        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);
    14751520
    14761521                /* Compute PMK. */
     
    14791524                        str_size(ieee80211_dev->bssid_info.password),
    14801525                        (uint8_t *) auth_data->ssid,
    1481                         str_size(auth_data->ssid), pmk, hash_sel);
     1526                        str_size(auth_data->ssid), pmk);
    14821527
    14831528                uint8_t *anonce = key_frame->key_nonce;
     
    14931538
    14941539                /* Derive PTK and save it. */
    1495                 uint8_t prf_result[ptk_key_length];
    14961540                uint8_t crypt_data[PRF_CRYPT_DATA_LENGTH];
    14971541                memcpy(crypt_data,
     
    15071551                        max_sequence(anonce, snonce, 32),
    15081552                        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);
    15111554        }
    15121555
    15131556        /* Compute MIC of key frame data from KCK part of PTK. */
    1514         uint8_t mic[hash_sel];
     1557        uint8_t mic[mic_hash];
    15151558        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);
    15171560
    15181561        memcpy(output_key_frame->key_mic, mic, 16);
     
    15221565        free(output_buffer);
    15231566
    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)) {
    15271571                key_config.suite = auth_data->security.pair_alg;
    15281572                key_config.flags =
     
    15341578                ieee80211_dev->ops->key_config(ieee80211_dev,
    15351579                        &key_config, true);
    1536                
    1537                 /* Insert Group key. */
     1580        }
     1581       
     1582        /* Insert Group key. */
     1583        if(final_phase) {
    15381584                key_config.suite = auth_data->security.group_alg;
    15391585                key_config.flags =
     
    15431589                ieee80211_dev->ops->key_config(ieee80211_dev,
    15441590                        &key_config, true);
    1545 
    1546                 /* Signal successful handshake completion. */
     1591        }
     1592
     1593        /* Signal successful handshake completion. */
     1594        if(handshake_done) {
    15471595                fibril_mutex_lock(&ieee80211_dev->gen_mutex);
    15481596                fibril_condvar_signal(&ieee80211_dev->gen_cond);
     
    15861634                        ARRAY_SIZE(rfc1042_header);
    15871635               
    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 ?
    15891639                if(ieee80211_is_encrypted_frame(data_header->frame_ctrl)) {
    15901640                        strip_length += 8;
Note: See TracChangeset for help on using the changeset viewer.