Changeset 1dcc0b9 in mainline for uspace/lib/ieee80211/src/ieee80211.c


Ignore:
Timestamp:
2015-04-06T10:47:51Z (10 years ago)
Author:
Jan Kolarik <kolarik@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d7dadcb4
Parents:
59fa7ab
Message:

Scanning whole 2.4GHz spectrum, created supplicant for managing connection between device STA and AP, finished association process between STA and AP, handling 4way handshake protocol used for key management, written needed cryptographic algorithms (AES, SHA1, HMAC, PBKDF2) for CCMP protocol, data communication on OPEN/CCMP networks.

File:
1 edited

Legend:

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

    r59fa7ab r1dcc0b9  
    3636 */
    3737
     38#include <stdio.h>
     39#include <crypto.h>
     40#include <str.h>
    3841#include <macros.h>
    3942#include <errno.h>
     
    4548#include <ops/ieee80211.h>
    4649
     50#define IEEE80211_DATA_RATES_SIZE 8
     51#define IEEE80211_EXT_DATA_RATES_SIZE 4
     52
     53/** Frame encapsulation used in IEEE 802.11. */
     54static const uint8_t rfc1042_header[] = {
     55        0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00
     56};
     57
    4758/** Broadcast MAC address used to spread probe request through channel. */
    4859static const uint8_t ieee80211_broadcast_mac_addr[] = {
     
    5061};
    5162
    52 /** IEEE 802.11 b/g supported data rates in units of 500 kb/s. */
    53 static const uint8_t ieee80211bg_data_rates[] = {
    54         2, 4, 11, 12, 18, 22, 24, 36
    55 };
    56 
    57 /** IEEE 802.11 b/g extended supported data rates in units of 500 kb/s.
    58  *
    59  *  These are defined separately, because probe request message can
    60  *  only handle up to 8 data rates in supported rates IE.
    61  */
    62 static const uint8_t ieee80211bg_ext_data_rates[] = {
    63         48, 72, 96, 108
    64 };
    65 
     63/**
     64 * Check data frame.
     65 *
     66 * @param frame_ctrl Frame control field in little endian (!).
     67 *
     68 * @return True if it is data frame, otherwise false.
     69 */
    6670inline bool ieee80211_is_data_frame(uint16_t frame_ctrl)
    6771{
     
    7276}
    7377
     78/**
     79 * Check management frame.
     80 *
     81 * @param frame_ctrl Frame control field in little endian (!).
     82 *
     83 * @return True if it is management frame, otherwise false.
     84 */
    7485inline bool ieee80211_is_mgmt_frame(uint16_t frame_ctrl)
    7586{
     
    8091}
    8192
     93/**
     94 * Check management beacon frame.
     95 *
     96 * @param frame_ctrl Frame control field in little endian (!).
     97 *
     98 * @return True if it is beacon frame, otherwise false.
     99 */
    82100inline bool ieee80211_is_beacon_frame(uint16_t frame_ctrl)
    83101{
     
    88106}
    89107
     108/**
     109 * Check management probe response frame.
     110 *
     111 * @param frame_ctrl Frame control field in little endian (!).
     112 *
     113 * @return True if it is probe resp frame, otherwise false.
     114 */
    90115inline bool ieee80211_is_probe_response_frame(uint16_t frame_ctrl)
    91116{
     
    97122
    98123/**
     124 * Check management authentication frame.
     125 *
     126 * @param frame_ctrl Frame control field in little endian (!).
     127 *
     128 * @return True if it is auth frame, otherwise false.
     129 */
     130inline bool ieee80211_is_auth_frame(uint16_t frame_ctrl)
     131{
     132        frame_ctrl = uint16_t_le2host(frame_ctrl);
     133       
     134        return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE)
     135                == IEEE80211_MGMT_AUTH_FRAME;
     136}
     137
     138/**
     139 * Check management association response frame.
     140 *
     141 * @param frame_ctrl Frame control field in little endian (!).
     142 *
     143 * @return True if it is assoc resp frame, otherwise false.
     144 */
     145inline bool ieee80211_is_assoc_response_frame(uint16_t frame_ctrl)
     146{
     147        frame_ctrl = uint16_t_le2host(frame_ctrl);
     148       
     149        return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE)
     150                == IEEE80211_MGMT_ASSOC_RESP_FRAME;
     151}
     152
     153/**
     154 * Check data frame "to distribution system" direction.
     155 *
     156 * @param frame_ctrl Frame control field in little endian (!).
     157 *
     158 * @return True if it is TODS frame, otherwise false.
     159 */
     160static inline bool ieee80211_is_tods_frame(uint16_t frame_ctrl)
     161{
     162        frame_ctrl = uint16_t_le2host(frame_ctrl);
     163       
     164        return (frame_ctrl & IEEE80211_FRAME_CTRL_TODS);
     165}
     166
     167/**
     168 * Check data frame "from distribution system" direction.
     169 *
     170 * @param frame_ctrl Frame control field in little endian (!).
     171 *
     172 * @return True if it is FROMDS frame, otherwise false.
     173 */
     174static inline bool ieee80211_is_fromds_frame(uint16_t frame_ctrl)
     175{
     176        frame_ctrl = uint16_t_le2host(frame_ctrl);
     177       
     178        return (frame_ctrl & IEEE80211_FRAME_CTRL_FROMDS);
     179}
     180
     181/**
     182 * Check if it is data frame containing payload data.
     183 *
     184 * @param frame_ctrl Frame control field in little endian (!).
     185 *
     186 * @return True if it has payload data, otherwise false.
     187 */
     188static inline bool ieee80211_has_data_frame(uint16_t frame_ctrl)
     189{
     190        frame_ctrl = uint16_t_le2host(frame_ctrl);
     191       
     192        return (frame_ctrl & (IEEE80211_FRAME_CTRL_FRAME_TYPE | 0x40))
     193                == IEEE80211_DATA_FRAME;
     194}
     195
     196/**
     197 * Check if it is encrypted frame.
     198 *
     199 * @param frame_ctrl Frame control field in little endian (!).
     200 *
     201 * @return True if the frame is encrypted, otherwise false.
     202 */
     203static inline bool ieee80211_is_encrypted_frame(uint16_t frame_ctrl)
     204{
     205        frame_ctrl = uint16_t_le2host(frame_ctrl);
     206       
     207        return (frame_ctrl & IEEE80211_FRAME_CTRL_PROTECTED) != 0;
     208}
     209
     210/**
     211 * Check if PAE packet is EAPOL-Key frame.
     212 *
     213 * @param key_frame Pointer to start of EAPOL frame.
     214 *
     215 * @return True if it is EAPOL-Key frame, otherwise false.
     216 */
     217static inline bool ieee80211_is_eapol_key_frame(ieee80211_eapol_key_frame_t
     218        *key_frame)
     219{
     220        return (key_frame->packet_type == IEEE80211_EAPOL_KEY);
     221}
     222
     223
     224/**
     225 * Generate packet sequence number.
     226 *
     227 * @param ieee80211_dev IEEE 802.11 device.
     228 *
     229 * @return True if it has payload data, otherwise false.
     230 */
     231static uint16_t ieee80211_get_sequence_number(ieee80211_dev_t *ieee80211_dev)
     232{
     233        uint16_t ret_val = ieee80211_dev->sequence_number;
     234        ieee80211_dev->sequence_number += (1 << 4);
     235        return ret_val;
     236}
     237
     238/**
    99239 * Get driver-specific structure for IEEE 802.11 device.
    100240 *
     
    139279 * @return Current IEEE 802.11 operating mode.
    140280 */
    141 ieee80211_operating_mode_t ieee80211_query_current_op_mode(ieee80211_dev_t* ieee80211_dev)
     281ieee80211_operating_mode_t ieee80211_query_current_op_mode(ieee80211_dev_t*
     282        ieee80211_dev)
    142283{
    143284        return ieee80211_dev->current_op_mode;
     
    154295{
    155296        return ieee80211_dev->current_freq;
     297}
     298
     299/**
     300 * Query BSSID the device is connected to.
     301 *
     302 * @param ieee80211_dev IEEE 802.11 device.
     303 * @param bssid Pointer to structure where should be stored BSSID.
     304 */
     305void ieee80211_query_bssid(ieee80211_dev_t* ieee80211_dev,
     306        nic_address_t *bssid)
     307{
     308        if(bssid) {
     309                ieee80211_scan_result_t *auth_data =
     310                        &ieee80211_dev->bssid_info.res_link->scan_result;
     311               
     312                memcpy(bssid, (void *)&auth_data->bssid, sizeof(nic_address_t));
     313        }
     314}
     315
     316/**
     317 * Get AID of network we are connected to.
     318 *
     319 * @param ieee80211_dev IEEE 802.11 device.
     320 *
     321 * @return AID.
     322 */
     323uint16_t ieee80211_get_aid(ieee80211_dev_t* ieee80211_dev)
     324{
     325        return ieee80211_dev->bssid_info.aid;
     326}
     327
     328/**
     329 * Get security suite used for HW encryption.
     330 *
     331 * @param ieee80211_dev IEEE 802.11 device.
     332 *
     333 * @return Security suite indicator.
     334 */
     335int ieee80211_get_security_suite(ieee80211_dev_t* ieee80211_dev)
     336{
     337        ieee80211_scan_result_link_t *auth_link =
     338                ieee80211_dev->bssid_info.res_link;
     339       
     340        return auth_link->scan_result.security.pair_alg;
     341}
     342
     343/**
     344 * Check if IEEE 802.11 device is connected to network.
     345 *
     346 * @param ieee80211_dev IEEE 802.11 device.
     347 *
     348 * @return True if device is connected to network, otherwise false.
     349 */
     350bool ieee80211_is_connected(ieee80211_dev_t* ieee80211_dev)
     351{
     352        return ieee80211_dev->current_auth_phase == IEEE80211_AUTH_ASSOCIATED;
    156353}
    157354
     
    178375{
    179376        ieee80211_dev->current_freq = freq;
     377}
     378
     379/**
     380 * Check if IEEE 802.11 device is ready (fully initialized).
     381 *
     382 * @param ieee80211_dev IEEE 802.11 device.
     383 *
     384 * @return True if device is ready to work, otherwise false.
     385 */
     386bool ieee80211_is_ready(ieee80211_dev_t* ieee80211_dev)
     387{
     388        fibril_mutex_lock(&ieee80211_dev->gen_mutex);
     389        bool ready_state = ieee80211_dev->ready;
     390        fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
     391       
     392        return ready_state;
     393}
     394
     395/**
     396 * Set IEEE 802.11 device to ready state.
     397 *
     398 * @param ieee80211_dev IEEE 802.11 device.
     399 * @param ready Ready state to be set.
     400 */
     401void ieee80211_set_ready(ieee80211_dev_t* ieee80211_dev, bool ready)
     402{
     403        fibril_mutex_lock(&ieee80211_dev->gen_mutex);
     404        ieee80211_dev->ready = ready;
     405        fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
     406}
     407
     408extern bool ieee80211_query_using_key(ieee80211_dev_t* ieee80211_dev)
     409{
     410        return ieee80211_dev->using_hw_key;
     411}
     412
     413void ieee80211_setup_key_confirm(ieee80211_dev_t* ieee80211_dev,
     414        bool using_key)
     415{
     416        ieee80211_dev->using_hw_key = using_key;
    180417}
    181418
     
    209446}
    210447
    211 /** 
     448/**
    212449 * Send frame handler.
     450 *
     451 * @param nic Pointer to NIC device.
     452 * @param data Data buffer.
     453 * @param size Data buffer size.
    213454 */
    214455static void ieee80211_send_frame(nic_t *nic, void *data, size_t size)
     
    217458                nic_get_specific(nic);
    218459       
    219         ieee80211_dev->ops->tx_handler(ieee80211_dev, data, size);
     460        if(!ieee80211_is_connected(ieee80211_dev)) {
     461                return;
     462        }
     463       
     464        ieee80211_scan_result_t *auth_data =
     465                        &ieee80211_dev->bssid_info.res_link->scan_result;
     466       
     467        /* We drop part of IEEE 802.3 ethernet header. */
     468        size_t drop_bytes = sizeof(eth_header_t) - 2;
     469       
     470        size_t complete_size = (size - drop_bytes) +
     471                sizeof(ieee80211_data_header_t) +
     472                ARRAY_SIZE(rfc1042_header);
     473       
     474        /* Init crypto data. */
     475        size_t add_size = 0;
     476        uint16_t crypto = 0;
     477        uint8_t add_data[8];
     478        memset(add_data, 0, 8);
     479       
     480        if(ieee80211_dev->using_hw_key) {
     481                int sec_suite = auth_data->security.pair_alg;
     482                switch(sec_suite) {
     483                        case IEEE80211_SECURITY_SUITE_CCMP:
     484                                add_size = IEEE80211_CCMP_HEADER_LENGTH;
     485                                add_data[3] = 0x20;
     486                                break;
     487                        default:
     488                                break;
     489                }
     490
     491                crypto = uint16_t_le2host(IEEE80211_FRAME_CTRL_PROTECTED);
     492        }
     493       
     494        complete_size += add_size;
     495       
     496        void *complete_buffer = malloc(complete_size);
     497        memset(complete_buffer, 0, complete_size);
     498       
     499        if(add_size) {
     500                memcpy(complete_buffer + sizeof(ieee80211_data_header_t),
     501                        add_data, add_size);
     502        }
     503       
     504        memcpy(complete_buffer + sizeof(ieee80211_data_header_t) + add_size,
     505                rfc1042_header,
     506                ARRAY_SIZE(rfc1042_header));
     507       
     508        memcpy(complete_buffer +
     509                sizeof(ieee80211_data_header_t) +
     510                ARRAY_SIZE(rfc1042_header) + add_size,
     511                data + drop_bytes, size - drop_bytes);
     512       
     513        ieee80211_data_header_t *data_header =
     514                (ieee80211_data_header_t *) complete_buffer;
     515        data_header->frame_ctrl =
     516                uint16_t_le2host(IEEE80211_DATA_FRAME) |
     517                uint16_t_le2host(IEEE80211_DATA_DATA_FRAME) |
     518                uint16_t_le2host(IEEE80211_FRAME_CTRL_TODS) |
     519                crypto;
     520        data_header->seq_ctrl = ieee80211_get_sequence_number(ieee80211_dev);
     521       
     522        /* BSSID, SA, DA. */
     523        memcpy(data_header->address1, auth_data->bssid.address, ETH_ADDR);
     524        memcpy(data_header->address2, data + ETH_ADDR, ETH_ADDR);
     525        memcpy(data_header->address3, data, ETH_ADDR);
     526       
     527        ieee80211_dev->ops->tx_handler(ieee80211_dev,
     528                complete_buffer,
     529                complete_size);
     530       
     531        free(complete_buffer);
    220532}
    221533
     
    246558                        ieee80211_ops->set_freq = ieee80211_set_freq_impl;
    247559               
     560                if(!ieee80211_ops->bssid_change)
     561                        ieee80211_ops->bssid_change =
     562                                ieee80211_bssid_change_impl;
     563               
     564                if(!ieee80211_ops->key_config)
     565                        ieee80211_ops->key_config = ieee80211_key_config_impl;
     566               
    248567                if(!ieee80211_ops->scan)
    249568                        ieee80211_ops->scan = ieee80211_scan_impl;
     
    257576                if(nic_dev_ops)
    258577                        if (!nic_dev_ops->interfaces[IEEE80211_DEV_IFACE])
    259                                 nic_dev_ops->interfaces[IEEE80211_DEV_IFACE] = ieee80211_iface;
     578                                nic_dev_ops->interfaces[IEEE80211_DEV_IFACE] =
     579                                        ieee80211_iface;
    260580               
    261581                if(!ieee80211_iface->get_scan_results)
    262                         ieee80211_iface->get_scan_results = ieee80211_get_scan_results_impl;
     582                        ieee80211_iface->get_scan_results =
     583                                ieee80211_get_scan_results_impl;
    263584               
    264585                if(!ieee80211_iface->connect)
    265586                        ieee80211_iface->connect = ieee80211_connect_impl;
     587               
     588                if(!ieee80211_iface->disconnect)
     589                        ieee80211_iface->disconnect = ieee80211_disconnect_impl;
    266590        } else {
    267591                return EINVAL;
     
    304628        ieee80211_dev->ddf_dev = ddf_dev;
    305629        ieee80211_dev->started = false;
     630        ieee80211_dev->ready = false;
     631        ieee80211_dev->using_hw_key = false;
    306632        ieee80211_dev->current_op_mode = IEEE80211_OPMODE_STATION;
     633        ieee80211_dev->current_auth_phase = IEEE80211_AUTH_DISCONNECTED;
    307634        memcpy(ieee80211_dev->bssid_mask.address, ieee80211_broadcast_mac_addr,
    308635                ETH_ADDR);
     636       
     637        ieee80211_scan_result_list_init(&ieee80211_dev->ap_list);
     638       
     639        fibril_mutex_initialize(&ieee80211_dev->gen_mutex);
     640        fibril_condvar_initialize(&ieee80211_dev->gen_cond);
    309641       
    310642        /* Bind NIC to device */
     
    373705}
    374706
     707/**
     708 * Convert frequency value to channel number.
     709 *
     710 * @param freq IEEE 802.11 operating frequency.
     711 *
     712 * @return Operating channel number.
     713 */
    375714static uint8_t ieee80211_freq_to_channel(uint16_t freq)
    376715{
     
    378717}
    379718
     719static void ieee80211_prepare_ie_header(void **ie_header,
     720        uint8_t id, uint8_t length, void *data)
     721{
     722        ieee80211_ie_header_t *header =
     723                (ieee80211_ie_header_t *) *ie_header;
     724       
     725        header->element_id = id;
     726        header->length = length;
     727       
     728        memcpy(*ie_header + sizeof(ieee80211_ie_header_t), data, length);
     729       
     730        *ie_header = (void *) ((void *) header +
     731                sizeof(ieee80211_ie_header_t) + length);
     732}
     733
    380734/**
    381735 * Probe request implementation.
    382736 *
    383737 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
     738 * @param ssid Probing SSID or NULL if broadcast.
    384739 *
    385740 * @return EOK if succeed, negative error code otherwise.
    386741 */
    387 int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev)
     742int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev, char *ssid)
    388743{
    389744        nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev);
     
    391746        nic_query_address(nic, &nic_address);
    392747       
    393         size_t data_rates_size = ARRAY_SIZE(ieee80211bg_data_rates);
    394         size_t ext_data_rates_size = ARRAY_SIZE(ieee80211bg_ext_data_rates);
    395        
    396         /* 3 headers - (rates, ext rates, current channel) and their data
    397          * lengths + pad.
     748        size_t ssid_data_size = (ssid != NULL) ? str_size(ssid) : 0;
     749        size_t channel_data_size = 1;
     750       
     751        uint8_t channel =
     752                ieee80211_freq_to_channel(ieee80211_dev->current_freq);
     753       
     754        /* 4 headers - (ssid, rates, ext rates, current channel) and their data
     755         * lengths.
    398756         */
    399757        size_t payload_size =
    400                 sizeof(ieee80211_ie_header_t) * 3 +
    401                 data_rates_size + ext_data_rates_size + sizeof(uint8_t) + 2;
     758                sizeof(ieee80211_ie_header_t) * 4 +
     759                ssid_data_size +
     760                IEEE80211_DATA_RATES_SIZE + IEEE80211_EXT_DATA_RATES_SIZE +
     761                channel_data_size;
    402762       
    403763        size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + payload_size;
     
    415775        memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR);
    416776        memcpy(mgmt_header->bssid, ieee80211_broadcast_mac_addr, ETH_ADDR);
    417        
    418         /* Jump to payload -> header + padding. */
    419         ieee80211_ie_header_t *rates_ie_header = (ieee80211_ie_header_t *)
    420                 ((void *)buffer + sizeof(ieee80211_mgmt_header_t) + 2);
    421         rates_ie_header->element_id = IEEE80211_RATES_IE;
    422         rates_ie_header->length = data_rates_size;
    423         memcpy(rates_ie_header + sizeof(ieee80211_ie_header_t),
    424                 ieee80211bg_data_rates,
    425                 data_rates_size);
    426        
    427         ieee80211_ie_header_t *ext_rates_ie_header = (ieee80211_ie_header_t *)
    428                 ((void *)rates_ie_header + sizeof(ieee80211_ie_header_t) +
    429                 data_rates_size);
    430         ext_rates_ie_header->element_id = IEEE80211_EXT_RATES_IE;
    431         ext_rates_ie_header->length = ext_data_rates_size;
    432         memcpy(ext_rates_ie_header + sizeof(ieee80211_ie_header_t),
    433                 ieee80211bg_ext_data_rates,
    434                 ext_data_rates_size);
    435        
    436         ieee80211_ie_header_t *chan_ie_header = (ieee80211_ie_header_t *)
    437                 ((void *)ext_rates_ie_header + sizeof(ieee80211_ie_header_t) +
    438                 ext_data_rates_size);
    439         chan_ie_header->element_id = IEEE80211_CHANNEL_IE;
    440         chan_ie_header->length = 1;
    441         uint8_t *it = (uint8_t *) ((void *)chan_ie_header +
    442                 sizeof(ieee80211_ie_header_t));
    443         *it = ieee80211_freq_to_channel(ieee80211_dev->current_freq);
     777        mgmt_header->seq_ctrl =
     778                host2uint16_t_le(ieee80211_get_sequence_number(ieee80211_dev));
     779       
     780        /* Jump to payload. */
     781        void *it = (void *) buffer + sizeof(ieee80211_mgmt_header_t);
     782        ieee80211_prepare_ie_header(&it, IEEE80211_SSID_IE, ssid_data_size,
     783                (void *) ssid);
     784        ieee80211_prepare_ie_header(&it, IEEE80211_RATES_IE,
     785                IEEE80211_DATA_RATES_SIZE,
     786                (void *) &ieee80211bg_data_rates);
     787        ieee80211_prepare_ie_header(&it, IEEE80211_EXT_RATES_IE,
     788                IEEE80211_EXT_DATA_RATES_SIZE,
     789                (void *) &ieee80211bg_data_rates[IEEE80211_DATA_RATES_SIZE]);
     790        ieee80211_prepare_ie_header(&it, IEEE80211_CHANNEL_IE,
     791                channel_data_size, (void *) &channel);
    444792       
    445793        ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size);
     
    451799
    452800/**
    453  * Probe authentication implementation.
     801 * IEEE 802.11 authentication implementation.
    454802 *
    455803 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
     
    457805 * @return EOK if succeed, negative error code otherwise.
    458806 */
    459 int ieee80211_probe_auth(ieee80211_dev_t *ieee80211_dev)
    460 {
    461         uint8_t test_bssid[] = {0x14, 0xF6, 0x5A, 0xAF, 0x5E, 0xB7};
    462        
     807int ieee80211_authenticate(ieee80211_dev_t *ieee80211_dev)
     808{
    463809        nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev);
    464810        nic_address_t nic_address;
    465811        nic_query_address(nic, &nic_address);
    466812       
     813        ieee80211_scan_result_t *auth_data =
     814                &ieee80211_dev->bssid_info.res_link->scan_result;
     815       
    467816        size_t buffer_size = sizeof(ieee80211_mgmt_header_t) +
    468817                sizeof(ieee80211_auth_body_t);
     818       
    469819        void *buffer = malloc(buffer_size);
    470820        memset(buffer, 0, buffer_size);
     
    477827                IEEE80211_MGMT_AUTH_FRAME
    478828                );
    479         memcpy(mgmt_header->dest_addr, test_bssid, ETH_ADDR);
     829        memcpy(mgmt_header->dest_addr, auth_data->bssid.address, ETH_ADDR);
    480830        memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR);
    481         memcpy(mgmt_header->bssid, test_bssid, ETH_ADDR);
     831        memcpy(mgmt_header->bssid, auth_data->bssid.address, ETH_ADDR);
    482832       
    483833        ieee80211_auth_body_t *auth_body =
     
    485835                (buffer + sizeof(ieee80211_mgmt_header_t));
    486836        auth_body->auth_alg = host2uint16_t_le(0);
    487         auth_body->auth_trans_no = host2uint16_t_le(0);
     837        auth_body->auth_trans_no = host2uint16_t_le(1);
    488838       
    489839        ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size);
     
    494844}
    495845
     846/**
     847 * IEEE 802.11 association implementation.
     848 *
     849 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
     850 * @param password Passphrase to be used in encrypted communication or NULL
     851 * for open networks.
     852 *
     853 * @return EOK if succeed, negative error code otherwise.
     854 */
     855int ieee80211_associate(ieee80211_dev_t *ieee80211_dev, char *password)
     856{
     857        nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev);
     858        nic_address_t nic_address;
     859        nic_query_address(nic, &nic_address);
     860       
     861        ieee80211_scan_result_link_t *auth_link =
     862                ieee80211_dev->bssid_info.res_link;
     863       
     864        ieee80211_scan_result_t *auth_data = &auth_link->scan_result;
     865       
     866        size_t ssid_data_size = str_size(auth_data->ssid);
     867       
     868        size_t payload_size =
     869                sizeof(ieee80211_ie_header_t) * 3 +
     870                ssid_data_size +
     871                IEEE80211_DATA_RATES_SIZE +
     872                IEEE80211_EXT_DATA_RATES_SIZE;
     873       
     874        size_t buffer_size =
     875                sizeof(ieee80211_mgmt_header_t) +
     876                sizeof(ieee80211_assoc_req_body_t) +
     877                payload_size;
     878       
     879        if(auth_data->security.type == IEEE80211_SECURITY_WPA2) {
     880                buffer_size += auth_link->rsn_copy_len;
     881        }
     882       
     883        void *buffer = malloc(buffer_size);
     884        memset(buffer, 0, buffer_size);
     885       
     886        ieee80211_mgmt_header_t *mgmt_header =
     887                (ieee80211_mgmt_header_t *) buffer;
     888       
     889        mgmt_header->frame_ctrl = host2uint16_t_le(
     890                IEEE80211_MGMT_FRAME |
     891                IEEE80211_MGMT_ASSOC_REQ_FRAME
     892                );
     893        memcpy(mgmt_header->dest_addr, auth_data->bssid.address, ETH_ADDR);
     894        memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR);
     895        memcpy(mgmt_header->bssid, auth_data->bssid.address, ETH_ADDR);
     896       
     897        ieee80211_assoc_req_body_t *assoc_body =
     898                (ieee80211_assoc_req_body_t *)
     899                (buffer + sizeof(ieee80211_mgmt_header_t));
     900        assoc_body->listen_interval = host2uint16_t_le(1);
     901       
     902        /* Jump to payload. */
     903        void *it = buffer + sizeof(ieee80211_mgmt_header_t) +
     904                sizeof(ieee80211_assoc_req_body_t);
     905        ieee80211_prepare_ie_header(&it, IEEE80211_SSID_IE,
     906                ssid_data_size, (void *) auth_data->ssid);
     907        ieee80211_prepare_ie_header(&it, IEEE80211_RATES_IE,
     908                IEEE80211_DATA_RATES_SIZE,
     909                (void *) &ieee80211bg_data_rates);
     910        ieee80211_prepare_ie_header(&it, IEEE80211_EXT_RATES_IE,
     911                IEEE80211_EXT_DATA_RATES_SIZE,
     912                (void *) &ieee80211bg_data_rates[IEEE80211_DATA_RATES_SIZE]);
     913       
     914        if(auth_data->security.type != IEEE80211_SECURITY_OPEN) {
     915                assoc_body->capability |= host2uint16_t_le(CAP_SECURITY);
     916        }
     917       
     918        if(auth_data->security.type == IEEE80211_SECURITY_WPA2) {
     919                memcpy(it, auth_link->rsn_copy, auth_link->rsn_copy_len);
     920        }
     921       
     922        ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size);
     923       
     924        /*
     925         * Save password and SSID to be used in eventual authentication
     926         * handshake.
     927         */
     928        memcpy(ieee80211_dev->bssid_info.password, password,
     929                str_size(password));
     930       
     931        free(buffer);
     932       
     933        return EOK;
     934}
     935
     936/**
     937 * IEEE 802.11 deauthentication implementation.
     938 *
     939 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
     940 *
     941 * @return EOK if succeed, negative error code otherwise.
     942 */
     943int ieee80211_deauthenticate(ieee80211_dev_t *ieee80211_dev)
     944{
     945        ieee80211_scan_result_t *auth_data =
     946                &ieee80211_dev->bssid_info.res_link->scan_result;
     947       
     948        ieee80211_dev->current_auth_phase = IEEE80211_AUTH_DISCONNECTED;
     949        ieee80211_dev->bssid_info.aid = (uint16_t) -1;
     950        memcpy(auth_data->bssid.address, ieee80211_broadcast_mac_addr,
     951                ETH_ADDR);
     952       
     953        nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev);
     954        nic_address_t nic_address;
     955        nic_query_address(nic, &nic_address);
     956       
     957        size_t buffer_size = sizeof(ieee80211_mgmt_header_t) +
     958                sizeof(ieee80211_deauth_body_t);
     959        void *buffer = malloc(buffer_size);
     960        memset(buffer, 0, buffer_size);
     961       
     962        ieee80211_mgmt_header_t *mgmt_header =
     963                (ieee80211_mgmt_header_t *) buffer;
     964       
     965        mgmt_header->frame_ctrl = host2uint16_t_le(
     966                IEEE80211_MGMT_FRAME |
     967                IEEE80211_MGMT_DEAUTH_FRAME
     968                );
     969        memcpy(mgmt_header->dest_addr, auth_data->bssid.address, ETH_ADDR);
     970        memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR);
     971        memcpy(mgmt_header->bssid, auth_data->bssid.address, ETH_ADDR);
     972       
     973        ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size);
     974       
     975        free(buffer);
     976       
     977        ieee80211_dev->ops->bssid_change(ieee80211_dev);
     978       
     979        return EOK;
     980}
     981
     982static void ieee80211_process_auth_info(ieee80211_scan_result_link_t *ap_data,
     983        void *buffer)
     984{
     985        uint8_t *it = (uint8_t *) buffer;
     986       
     987        uint16_t *version = (uint16_t *) it;
     988        if(uint16_t_le2host(*version) != 0x1) {
     989                ap_data->scan_result.security.type = -1;
     990                return;
     991        }
     992       
     993        it += sizeof(uint16_t);
     994       
     995        uint32_t group_cipher = *(it+3);
     996        switch(group_cipher) {
     997                case IEEE80211_AUTH_CIPHER_TKIP:
     998                        ap_data->scan_result.security.group_alg =
     999                                IEEE80211_SECURITY_SUITE_TKIP;
     1000                        break;
     1001                case IEEE80211_AUTH_CIPHER_CCMP:
     1002                        ap_data->scan_result.security.group_alg =
     1003                                IEEE80211_SECURITY_SUITE_CCMP;
     1004                        break;
     1005                default:
     1006                        ap_data->scan_result.security.group_alg = -1;
     1007        }
     1008       
     1009        it += 4*sizeof(uint8_t);
     1010       
     1011        uint16_t *pairwise_count = (uint16_t *) it;
     1012        uint32_t pairwise_cipher = *(it+sizeof(uint16_t)+3);
     1013        switch(pairwise_cipher) {
     1014                case IEEE80211_AUTH_CIPHER_TKIP:
     1015                        ap_data->scan_result.security.pair_alg =
     1016                                IEEE80211_SECURITY_SUITE_TKIP;
     1017                        break;
     1018                case IEEE80211_AUTH_CIPHER_CCMP:
     1019                        ap_data->scan_result.security.pair_alg =
     1020                                IEEE80211_SECURITY_SUITE_CCMP;
     1021                        break;
     1022                default:
     1023                        ap_data->scan_result.security.pair_alg = -1;
     1024        }
     1025       
     1026        it += 2*sizeof(uint16_t) +
     1027                uint16_t_le2host(*pairwise_count)*sizeof(uint32_t);
     1028       
     1029        uint32_t auth_suite = *(it+3);
     1030        switch(auth_suite) {
     1031                case IEEE80211_AUTH_AKM_PSK:
     1032                        ap_data->scan_result.security.auth =
     1033                                IEEE80211_SECURITY_AUTH_PSK;
     1034                        break;
     1035                case IEEE80211_AUTH_AKM_8021X:
     1036                        ap_data->scan_result.security.auth =
     1037                                IEEE80211_SECURITY_AUTH_8021X;
     1038                        break;
     1039                default:
     1040                        ap_data->scan_result.security.auth = -1;
     1041        }
     1042}
     1043
     1044static uint32_t uint32_from_uint8_seq(uint8_t *seq)
     1045{
     1046        return (*seq << 24) + (*(seq+1) << 16) + (*(seq+2) << 8) + *(seq+3);
     1047}
     1048
     1049static uint8_t *ieee80211_process_ies(ieee80211_dev_t *ieee80211_dev,
     1050        ieee80211_scan_result_link_t *ap_data, void *buffer, size_t buffer_size)
     1051{
     1052        void *it = buffer;
     1053        while((it + sizeof(ieee80211_ie_header_t)) < buffer + buffer_size) {
     1054                ieee80211_ie_header_t *ie_header =
     1055                        (ieee80211_ie_header_t *) it;
     1056                uint8_t *channel;
     1057                switch(ie_header->element_id) {
     1058                        case IEEE80211_CHANNEL_IE:
     1059                                channel = (uint8_t *)
     1060                                        (it + sizeof(ieee80211_ie_header_t));
     1061                                ap_data->scan_result.channel = *channel;
     1062                                break;
     1063                        case IEEE80211_RSN_IE:
     1064                                if(!ap_data)
     1065                                        break;
     1066                                ap_data->scan_result.security.type =
     1067                                        IEEE80211_SECURITY_WPA2;
     1068                                ieee80211_process_auth_info(ap_data,
     1069                                        it + sizeof(ieee80211_ie_header_t));
     1070                                ap_data->rsn_copy_len = ie_header->length +
     1071                                        sizeof(ieee80211_ie_header_t);
     1072                                memcpy(ap_data->rsn_copy,
     1073                                        it,
     1074                                        ap_data->rsn_copy_len);
     1075                                break;
     1076                        case IEEE80211_VENDOR_IE:
     1077                                if(uint32_from_uint8_seq(it +
     1078                                        sizeof(ieee80211_ie_header_t)) ==
     1079                                        WPA_OUI) {
     1080                                        if(ap_data->scan_result.security.type ==
     1081                                                IEEE80211_SECURITY_WPA2) {
     1082                                                break;
     1083                                        }
     1084                                        ap_data->scan_result.security.type =
     1085                                                IEEE80211_SECURITY_WPA;
     1086                                        ieee80211_process_auth_info(ap_data,
     1087                                                it +
     1088                                                sizeof(ieee80211_ie_header_t) +
     1089                                                sizeof(uint32_t));
     1090                                } else if(uint32_from_uint8_seq(it +
     1091                                        sizeof(ieee80211_ie_header_t)) ==
     1092                                        GTK_OUI) {
     1093                                        return it +
     1094                                                sizeof(ieee80211_ie_header_t) +
     1095                                                sizeof(uint32_t) + 2;
     1096                                }
     1097                }
     1098                it += sizeof(ieee80211_ie_header_t) + ie_header->length;
     1099        }
     1100       
     1101        return NULL;
     1102}
     1103
    4961104/**
    4971105 * Process probe response and store results.
    4981106 *
    4991107 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
     1108 * @param mgmt_header Pointer to start of management frame header.
    5001109 *
    5011110 * @return EOK if succeed, negative error code otherwise.
    5021111 */
    5031112static int ieee80211_process_probe_response(ieee80211_dev_t *ieee80211_dev,
     1113        ieee80211_mgmt_header_t *mgmt_header, size_t buffer_size)
     1114{
     1115        ieee80211_beacon_start_t *beacon_body = (ieee80211_beacon_start_t *)
     1116                ((void *)mgmt_header + sizeof(ieee80211_mgmt_header_t));
     1117       
     1118        ieee80211_ie_header_t *ssid_ie_header = (ieee80211_ie_header_t *)
     1119                ((void *)beacon_body + sizeof(ieee80211_beacon_start_t));
     1120       
     1121        /* Not empty SSID. */
     1122        if(ssid_ie_header->length > 0) {
     1123                fibril_mutex_t *scan_mutex = &ieee80211_dev->ap_list.scan_mutex;
     1124               
     1125                fibril_mutex_lock(scan_mutex);
     1126               
     1127                ieee80211_scan_result_list_t *result_list =
     1128                        &ieee80211_dev->ap_list;
     1129               
     1130                uint8_t *ssid_start = (uint8_t *) ((void *)ssid_ie_header +
     1131                        sizeof(ieee80211_ie_header_t));
     1132                char ssid[IEEE80211_MAX_SSID_LENGTH];
     1133                memcpy(ssid, ssid_start, ssid_ie_header->length);
     1134                ssid[ssid_ie_header->length] = '\0';
     1135               
     1136                /* Check whether SSID is already in results. */
     1137                ieee80211_scan_result_list_foreach(*result_list, result) {
     1138                        if(!str_cmp(ssid, result->scan_result.ssid)) {
     1139                                result->last_beacon = time(NULL);
     1140                                fibril_mutex_unlock(scan_mutex);
     1141                                return EOK;
     1142                        }
     1143                }
     1144               
     1145                /* Results are full. */
     1146                if(result_list->size == IEEE80211_MAX_RESULTS_LENGTH - 1) {
     1147                        fibril_mutex_unlock(scan_mutex);
     1148                        return EOK;
     1149                }
     1150               
     1151                ieee80211_scan_result_link_t *ap_data =
     1152                        malloc(sizeof(ieee80211_scan_result_link_t));
     1153                memset(ap_data, 0, sizeof(ieee80211_scan_result_link_t));
     1154                link_initialize(&ap_data->link);
     1155               
     1156                memcpy(ap_data->scan_result.bssid.address,
     1157                        mgmt_header->bssid, ETH_ADDR);
     1158                memcpy(ap_data->scan_result.ssid, ssid,
     1159                        ssid_ie_header->length + 1);
     1160               
     1161                if(uint16_t_le2host(beacon_body->capability) & CAP_SECURITY) {
     1162                        ap_data->scan_result.security.type =
     1163                                IEEE80211_SECURITY_WEP;
     1164                } else {
     1165                        ap_data->scan_result.security.type =
     1166                                IEEE80211_SECURITY_OPEN;
     1167                        ap_data->scan_result.security.auth = -1;
     1168                        ap_data->scan_result.security.pair_alg = -1;
     1169                        ap_data->scan_result.security.group_alg = -1;
     1170                }
     1171               
     1172                void *rest_ies_start = ssid_start + ssid_ie_header->length;
     1173                size_t rest_buffer_size =
     1174                        buffer_size -
     1175                        sizeof(ieee80211_mgmt_header_t) -
     1176                        sizeof(ieee80211_beacon_start_t) -
     1177                        sizeof(ieee80211_ie_header_t) -
     1178                        ssid_ie_header->length;
     1179               
     1180                ieee80211_process_ies(ieee80211_dev, ap_data, rest_ies_start,
     1181                        rest_buffer_size);
     1182               
     1183                ap_data->last_beacon = time(NULL);
     1184               
     1185                ieee80211_scan_result_list_append(result_list, ap_data);
     1186               
     1187                fibril_mutex_unlock(scan_mutex);
     1188        }
     1189       
     1190        return EOK;
     1191}
     1192
     1193/**
     1194 * Process authentication response.
     1195 *
     1196 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
     1197 * @param mgmt_header Pointer to start of management frame header.
     1198 *
     1199 * @return EOK if succeed, negative error code otherwise.
     1200 */
     1201static int ieee80211_process_auth_response(ieee80211_dev_t *ieee80211_dev,
    5041202        ieee80211_mgmt_header_t *mgmt_header)
    5051203{
    506         ieee80211_ie_header_t *ssid_ie_header = (ieee80211_ie_header_t *)
    507                 ((void *)mgmt_header + sizeof(ieee80211_mgmt_header_t) +
    508                 sizeof(ieee80211_beacon_start_t));
    509        
    510         if(ssid_ie_header->length > 0) {
    511                 uint8_t *results_length = &ieee80211_dev->ap_list.length;
    512                
    513                 ieee80211_scan_result_t *ap_data =
    514                         &ieee80211_dev->ap_list.results[(*results_length)++];
    515                
    516                 memset(ap_data, 0, sizeof(ieee80211_scan_result_t));
    517                
    518                 uint8_t *ssid_start = (uint8_t *)
    519                         ((void *)ssid_ie_header +
    520                         sizeof(ieee80211_ie_header_t));
    521 
    522                 memcpy(ap_data->bssid.address, mgmt_header->bssid, ETH_ADDR);
    523                 memcpy(ap_data->ssid, ssid_start, ssid_ie_header->length);
    524                 ap_data->ssid[ssid_ie_header->length] = '\0';
     1204        fibril_mutex_lock(&ieee80211_dev->gen_mutex);
     1205       
     1206        ieee80211_dev->current_auth_phase = IEEE80211_AUTH_AUTHENTICATED;
     1207       
     1208        fibril_condvar_signal(&ieee80211_dev->gen_cond);
     1209        fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
     1210       
     1211        return EOK;
     1212}
     1213
     1214/**
     1215 * Process association response.
     1216 *
     1217 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
     1218 * @param mgmt_header Pointer to start of management frame header.
     1219 *
     1220 * @return EOK if succeed, negative error code otherwise.
     1221 */
     1222static int ieee80211_process_assoc_response(ieee80211_dev_t *ieee80211_dev,
     1223        ieee80211_mgmt_header_t *mgmt_header)
     1224{
     1225        ieee80211_scan_result_t *auth_data =
     1226                &ieee80211_dev->bssid_info.res_link->scan_result;
     1227       
     1228        fibril_mutex_lock(&ieee80211_dev->gen_mutex);
     1229       
     1230        ieee80211_assoc_resp_body_t *assoc_resp =
     1231                (ieee80211_assoc_resp_body_t *) ((void *)mgmt_header +
     1232                sizeof(ieee80211_mgmt_header_t));
     1233       
     1234        ieee80211_dev->bssid_info.aid = uint16_t_le2host(assoc_resp->aid);
     1235        memcpy(auth_data->bssid.address, mgmt_header->bssid, ETH_ADDR);
     1236       
     1237        ieee80211_dev->current_auth_phase = IEEE80211_AUTH_ASSOCIATED;
     1238       
     1239        ieee80211_dev->ops->bssid_change(ieee80211_dev);
     1240       
     1241        fibril_condvar_signal(&ieee80211_dev->gen_cond);
     1242        fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
     1243       
     1244        return EOK;
     1245}
     1246
     1247static int ieee80211_process_4way_handshake(ieee80211_dev_t *ieee80211_dev,
     1248        void *buffer, size_t buffer_size)
     1249{
     1250        ieee80211_eapol_key_frame_t *key_frame =
     1251                (ieee80211_eapol_key_frame_t *) buffer;
     1252       
     1253        bool handshake_done = false;
     1254               
     1255        ieee80211_scan_result_link_t *auth_link =
     1256                ieee80211_dev->bssid_info.res_link;
     1257
     1258        ieee80211_scan_result_t *auth_data = &auth_link->scan_result;
     1259        uint8_t *ptk = ieee80211_dev->bssid_info.ptk;
     1260        uint8_t *gtk = ieee80211_dev->bssid_info.gtk;
     1261
     1262        size_t ptk_key_length, gtk_key_length;
     1263        hash_func_t hash_sel;
     1264        switch(auth_data->security.pair_alg) {
     1265                case IEEE80211_SECURITY_SUITE_CCMP:
     1266                        ptk_key_length = IEEE80211_PTK_CCMP_LENGTH;
     1267                        hash_sel = HASH_SHA1;
     1268                        break;
     1269                default:
     1270                        return ENOTSUP;
     1271        }
     1272
     1273        switch(auth_data->security.group_alg) {
     1274                case IEEE80211_SECURITY_SUITE_CCMP:
     1275                        gtk_key_length = IEEE80211_GTK_CCMP_LENGTH;
     1276                        break;
     1277                default:
     1278                        return ENOTSUP;
     1279        }
     1280
     1281        size_t output_size =
     1282                sizeof(eth_header_t) +
     1283                sizeof(ieee80211_eapol_key_frame_t);
     1284
     1285        if(!(uint16_t_be2host(key_frame->key_info) &
     1286                IEEE80211_EAPOL_KEY_KEYINFO_SECURE)) {
     1287                output_size += auth_link->rsn_copy_len;
     1288        }
     1289
     1290        nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev);
     1291        nic_address_t nic_address;
     1292        nic_query_address(nic, &nic_address);
     1293
     1294        void *output_buffer = malloc(output_size);
     1295        memset(output_buffer, 0, output_size);
     1296
     1297        /* Setup ethernet header. */
     1298        eth_header_t *eth_header = (eth_header_t *) output_buffer;
     1299        memcpy(eth_header->dest_addr, auth_data->bssid.address, ETH_ADDR);
     1300        memcpy(eth_header->src_addr, nic_address.address, ETH_ADDR);
     1301        eth_header->proto = host2uint16_t_be(ETH_TYPE_PAE);
     1302
     1303        ieee80211_eapol_key_frame_t *output_key_frame =
     1304                (ieee80211_eapol_key_frame_t *)
     1305                (output_buffer + sizeof(eth_header_t));
     1306
     1307        /* Copy content of incoming EAPOL-Key frame. */
     1308        memcpy((void *) output_key_frame, buffer,
     1309                sizeof(ieee80211_eapol_key_frame_t));
     1310
     1311        output_key_frame->proto_version = 0x1;
     1312        output_key_frame->key_length = 0;
     1313        output_key_frame->body_length =
     1314                host2uint16_t_be(output_size - sizeof(eth_header_t)-4);
     1315        output_key_frame->key_info &=
     1316                ~host2uint16_t_be(
     1317                        IEEE80211_EAPOL_KEY_KEYINFO_ACK
     1318                );
     1319
     1320        /*
     1321         * Check if it is last or first incoming message in 4-way
     1322         * handshake.
     1323         */
     1324        if(uint16_t_be2host(key_frame->key_info) &
     1325                IEEE80211_EAPOL_KEY_KEYINFO_SECURE) {
     1326                output_key_frame->key_info &=
     1327                        ~host2uint16_t_be(
     1328                                IEEE80211_EAPOL_KEY_KEYINFO_ENCDATA
     1329                        );
     1330                output_key_frame->key_info &=
     1331                        ~host2uint16_t_be(
     1332                                IEEE80211_EAPOL_KEY_KEYINFO_INSTALL
     1333                        );
     1334                output_key_frame->key_data_length = 0;
     1335                output_key_frame->key_length = 0;
     1336                memset(output_key_frame->key_nonce, 0, 32);
     1337                memset(output_key_frame->key_mic, 0, 16);
     1338                memset(output_key_frame->key_rsc, 0, 8);
     1339                memset(output_key_frame->eapol_key_iv, 0, 16);
     1340
     1341                /* Derive GTK and save it. */
     1342                uint16_t key_data_length =
     1343                        uint16_t_be2host(key_frame->key_data_length);
     1344                uint16_t decrypt_len = key_data_length - 8;
     1345                uint8_t key_data[decrypt_len];
     1346                uint8_t *data_ptr = (uint8_t *) (buffer +
     1347                        sizeof(ieee80211_eapol_key_frame_t));
     1348                if(ieee80211_aes_key_unwrap(ptk + KEK_OFFSET, data_ptr,
     1349                        key_data_length, key_data) == EOK) {
     1350                       
     1351                        uint8_t *key_ptr = ieee80211_process_ies(ieee80211_dev,
     1352                                NULL, key_data, decrypt_len);
     1353
     1354                        if(key_ptr) {
     1355                                memcpy(gtk, key_ptr, gtk_key_length);
     1356                                handshake_done = true;
     1357                        }
     1358                }
     1359        } else {
     1360                output_key_frame->key_info |=
     1361                        host2uint16_t_be(
     1362                                IEEE80211_EAPOL_KEY_KEYINFO_MIC
     1363                        );
     1364                output_key_frame->key_data_length =
     1365                        host2uint16_t_be(auth_link->rsn_copy_len);
     1366                memcpy((void *)output_key_frame +
     1367                        sizeof(ieee80211_eapol_key_frame_t),
     1368                        auth_link->rsn_copy,
     1369                        auth_link->rsn_copy_len);
     1370
     1371                /* Compute PMK. */
     1372                uint8_t pmk[PBKDF2_KEY_LENGTH];
     1373                pbkdf2((uint8_t *) ieee80211_dev->bssid_info.password,
     1374                        str_size(ieee80211_dev->bssid_info.password),
     1375                        (uint8_t *) auth_data->ssid,
     1376                        str_size(auth_data->ssid), pmk, hash_sel);
     1377
     1378                uint8_t *anonce = key_frame->key_nonce;
     1379
     1380                /* Generate SNONCE. */
     1381                uint8_t snonce[32];
     1382                rnd_sequence(snonce, 32);
     1383
     1384                memcpy(output_key_frame->key_nonce, snonce, 32);
     1385
     1386                uint8_t *dest_addr = eth_header->dest_addr;
     1387                uint8_t *src_addr = eth_header->src_addr;
     1388
     1389                /* Derive PTK and save it. */
     1390                uint8_t prf_result[ptk_key_length];
     1391                uint8_t crypt_data[PRF_CRYPT_DATA_LENGTH];
     1392                memcpy(crypt_data,
     1393                        min_sequence(dest_addr, src_addr, ETH_ADDR),
     1394                        ETH_ADDR);
     1395                memcpy(crypt_data + ETH_ADDR,
     1396                        max_sequence(dest_addr, src_addr, ETH_ADDR),
     1397                        ETH_ADDR);
     1398                memcpy(crypt_data + 2*ETH_ADDR,
     1399                        min_sequence(anonce, snonce, 32),
     1400                        32);
     1401                memcpy(crypt_data + 2*ETH_ADDR + 32,
     1402                        max_sequence(anonce, snonce, 32),
     1403                        32);
     1404                ieee80211_prf(pmk, crypt_data, prf_result, hash_sel);
     1405                memcpy(ptk, prf_result, ptk_key_length);
     1406        }
     1407
     1408        /* Compute MIC of key frame data from KCK part of PTK. */
     1409        uint8_t mic[SHA1_HASH_LENGTH];
     1410        hmac(ptk, 16, (uint8_t *) output_key_frame,
     1411                output_size - sizeof(eth_header_t), mic, hash_sel);
     1412
     1413        memcpy(output_key_frame->key_mic, mic, 16);
     1414
     1415        ieee80211_send_frame(nic, output_buffer, output_size);
     1416
     1417        free(output_buffer);
     1418
     1419        if(handshake_done) {
     1420                /* Insert keys into device. */
     1421               
     1422                /* Pairwise key. */
     1423                ieee80211_key_config_t key_config;
     1424                key_config.suite = auth_data->security.pair_alg;
     1425                key_config.flags =
     1426                        IEEE80211_KEY_FLAG_TYPE_PAIRWISE;
     1427                memcpy(key_config.data,
     1428                        ptk + TK_OFFSET,
     1429                        ptk_key_length - TK_OFFSET);
     1430
     1431                ieee80211_dev->ops->key_config(ieee80211_dev,
     1432                        &key_config, true);
     1433               
     1434                /* Group key. */
     1435                key_config.suite = auth_data->security.group_alg;
     1436                key_config.flags =
     1437                        IEEE80211_KEY_FLAG_TYPE_GROUP;
     1438                memcpy(key_config.data, gtk, gtk_key_length);
     1439
     1440                ieee80211_dev->ops->key_config(ieee80211_dev,
     1441                        &key_config, true);
     1442
     1443                /* Signal successful handshake completion. */
     1444                fibril_mutex_lock(&ieee80211_dev->gen_mutex);
     1445                fibril_condvar_signal(&ieee80211_dev->gen_cond);
     1446                fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
     1447        }
     1448       
     1449        return EOK;
     1450}
     1451
     1452static int ieee80211_process_eapol_frame(ieee80211_dev_t *ieee80211_dev,
     1453        void *buffer, size_t buffer_size)
     1454{
     1455        ieee80211_eapol_key_frame_t *key_frame =
     1456                (ieee80211_eapol_key_frame_t *) buffer;
     1457        if(ieee80211_is_eapol_key_frame(key_frame)) {
     1458                return ieee80211_process_4way_handshake(ieee80211_dev, buffer,
     1459                        buffer_size);
     1460        }
     1461       
     1462        return EOK;
     1463}
     1464
     1465/**
     1466 * Process data frame.
     1467 *
     1468 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
     1469 * @param buffer Data buffer starting with IEEE 802.11 data header.
     1470 * @param buffer_size Size of buffer.
     1471 *
     1472 * @return EOK if succeed, negative error code otherwise.
     1473 */
     1474static int ieee80211_process_data(ieee80211_dev_t *ieee80211_dev,
     1475        void *buffer, size_t buffer_size)
     1476{
     1477        ieee80211_data_header_t *data_header =
     1478                (ieee80211_data_header_t *) buffer;
     1479       
     1480        if(ieee80211_has_data_frame(data_header->frame_ctrl)) {
     1481                nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev);
     1482                size_t strip_length = sizeof(ieee80211_data_header_t) +
     1483                        ARRAY_SIZE(rfc1042_header);
     1484               
     1485                /* TODO: Probably different by used security alg. */
     1486                if(ieee80211_is_encrypted_frame(data_header->frame_ctrl)) {
     1487                        strip_length += 8;
     1488                }
     1489               
     1490                /* Process 4-way authentication handshake. */
     1491                uint16_t *proto = (uint16_t *) (buffer + strip_length);
     1492                if(uint16_t_be2host(*proto) == ETH_TYPE_PAE) {
     1493                        return ieee80211_process_eapol_frame(ieee80211_dev,
     1494                                buffer + strip_length + sizeof(uint16_t),
     1495                                buffer_size - strip_length - sizeof(uint16_t));
     1496                }
     1497               
     1498                /* Note: ETH protocol ID is already there, so we don't create
     1499                 * whole ETH header. */
     1500                size_t frame_size =
     1501                        buffer_size - strip_length + sizeof(eth_header_t)-2;
     1502                nic_frame_t *frame = nic_alloc_frame(nic, frame_size);
     1503
     1504                if(frame == NULL) {
     1505                        return ENOMEM;
     1506                }
     1507
     1508                uint8_t *src_addr =
     1509                        ieee80211_is_fromds_frame(data_header->frame_ctrl) ?
     1510                                data_header->address3 : data_header->address2;
     1511                uint8_t *dest_addr =
     1512                        ieee80211_is_tods_frame(data_header->frame_ctrl) ?
     1513                                data_header->address3 : data_header->address1;
     1514
     1515                eth_header_t *eth_header =
     1516                        (eth_header_t *) frame->data;
     1517                memcpy(eth_header->src_addr, src_addr, ETH_ADDR);
     1518                memcpy(eth_header->dest_addr, dest_addr, ETH_ADDR);
     1519
     1520                memcpy(frame->data + sizeof(eth_header_t)-2,
     1521                        buffer + strip_length,
     1522                        buffer_size - strip_length);
     1523
     1524                nic_received_frame(nic, frame);
    5251525        }
    5261526       
     
    5481548                        ieee80211_is_beacon_frame(mgmt_header->frame_ctrl)) {
    5491549                        return ieee80211_process_probe_response(ieee80211_dev,
     1550                                mgmt_header, buffer_size);
     1551                }
     1552               
     1553                if(ieee80211_is_auth_frame(mgmt_header->frame_ctrl)) {
     1554                        return ieee80211_process_auth_response(ieee80211_dev,
    5501555                                mgmt_header);
    5511556                }
    552                 // TODO
     1557               
     1558                if(ieee80211_is_assoc_response_frame(mgmt_header->frame_ctrl)) {
     1559                        return ieee80211_process_assoc_response(ieee80211_dev,
     1560                                mgmt_header);
     1561                }
    5531562        } else if(ieee80211_is_data_frame(frame_ctrl)) {
    554                 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev);
    555                 size_t frame_size = buffer_size - sizeof(ieee80211_data_header_t);
    556                 nic_frame_t *frame = nic_alloc_frame(nic, frame_size);
    557                 if (frame != NULL) {
    558                         memcpy(frame->data,
    559                                 buffer + sizeof(ieee80211_data_header_t),
    560                                 frame_size);
    561                         nic_received_frame(nic, frame);
    562                 }
    563         } else {
    564                 // TODO
     1563                return ieee80211_process_data(ieee80211_dev, buffer,
     1564                        buffer_size);
    5651565        }
    5661566       
Note: See TracChangeset for help on using the changeset viewer.