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_impl.c

    r59fa7ab r1dcc0b9  
    3636 */
    3737
     38#include <stdio.h>
     39#include <crypto.h>
     40#include <stdlib.h>
    3841#include <errno.h>
    3942
     
    8184
    8285/**
     86 * Default implementation of IEEE802.11 BSSID change function.
     87 *
     88 * @param ieee80211_dev Structure of IEEE802.11 device.
     89 *
     90 * @return EOK.
     91 */
     92int ieee80211_bssid_change_impl(ieee80211_dev_t *ieee80211_dev)
     93{
     94        return EOK;
     95}
     96
     97/**
     98 * Default implementation of IEEE802.11 key config function.
     99 *
     100 * @param ieee80211_dev Structure of IEEE802.11 device.
     101 *
     102 * @return EOK.
     103 */
     104int ieee80211_key_config_impl(ieee80211_dev_t *ieee80211_dev,
     105        ieee80211_key_config_t *key_conf, bool insert)
     106{
     107        return EOK;
     108}
     109
     110/**
    83111 * Default implementation of IEEE802.11 scan function.
    84112 *
    85113 * @param ieee80211_dev Structure of IEEE802.11 device.
    86  * @param results Pointer to structure where should be scan results stored.
     114 * @param clear Whether to clear current scan results.
    87115 *
    88116 * @return EOK if succeed, negative error code otherwise.
     
    90118int ieee80211_scan_impl(ieee80211_dev_t *ieee80211_dev)
    91119{
     120        if(ieee80211_is_connected(ieee80211_dev))
     121                return EOK;
     122       
     123        fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex);
     124       
     125        /* Remove old entries we don't receive beacons from. */
     126        ieee80211_scan_result_list_t *result_list =
     127                &ieee80211_dev->ap_list;
     128        list_foreach_safe(result_list->list, cur_link, next_link) {
     129                ieee80211_scan_result_link_t *cur_result =
     130                        list_get_instance(cur_link,
     131                        ieee80211_scan_result_link_t,
     132                        link);
     133                if((time(NULL) - cur_result->last_beacon) >
     134                        MAX_KEEP_SCAN_SPAN_SEC) {
     135                        ieee80211_scan_result_list_remove(result_list,
     136                                cur_result);
     137                }
     138        }
     139       
     140        fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex);
     141       
    92142        uint16_t orig_freq = ieee80211_dev->current_freq;
    93143       
     
    96146                freq += IEEE80211_CHANNEL_GAP) {
    97147                ieee80211_dev->ops->set_freq(ieee80211_dev, freq);
    98                 ieee80211_probe_request(ieee80211_dev);
     148                ieee80211_probe_request(ieee80211_dev, NULL);
    99149               
    100150                /* Wait for probe responses. */
     
    104154        ieee80211_dev->ops->set_freq(ieee80211_dev, orig_freq);
    105155       
    106         return EOK;
     156        fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex);
     157        time(&ieee80211_dev->ap_list.last_scan);
     158        fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex);
     159       
     160        return EOK;
     161}
     162
     163/**
     164 * Pseudorandom function used for IEEE 802.11 pairwise key computation.
     165 *
     166 * @param key Key with PBKDF2 encrypted passphrase.
     167 * @param data Concatenated sequence of both mac addresses and nonces.
     168 * @param hash Output parameter for result hash (48 byte value).
     169 * @param hash_sel Hash function selector.
     170 *
     171 * @return EINVAL when key or data not specified, ENOMEM when pointer for
     172 * output hash result is not allocated, otherwise EOK.
     173 */
     174int ieee80211_prf(uint8_t *key, uint8_t *data, uint8_t *hash,
     175        hash_func_t hash_sel)
     176{
     177        if(!key || !data)
     178                return EINVAL;
     179       
     180        if(!hash)
     181                return ENOMEM;
     182       
     183        size_t hash_length, result_length;
     184        switch(hash_sel) {
     185                case HASH_MD5:
     186                        hash_length = MD5_HASH_LENGTH;
     187                        result_length = IEEE80211_PTK_TKIP_LENGTH;
     188                        break;
     189                case HASH_SHA1:
     190                        hash_length = SHA1_HASH_LENGTH;
     191                        result_length = IEEE80211_PTK_CCMP_LENGTH;
     192                        break;
     193                default:
     194                        hash_length = 0;
     195                        result_length = 0;
     196        }
     197       
     198        size_t iters = ((result_length * 8) + 159) / 160;
     199       
     200        const char *a = "Pairwise key expansion";
     201        uint8_t result[hash_length*iters];
     202        uint8_t temp[hash_length];
     203        size_t data_size = PRF_CRYPT_DATA_LENGTH + str_size(a) + 2;
     204        uint8_t work_arr[data_size];
     205        memset(work_arr, 0, data_size);
     206       
     207        memcpy(work_arr, a, str_size(a));
     208        memcpy(work_arr + str_size(a) + 1, data, PRF_CRYPT_DATA_LENGTH);
     209
     210        for(uint8_t i = 0; i < iters; i++) {
     211                memcpy(work_arr + data_size - 1, &i, 1);
     212                hmac(key, PBKDF2_KEY_LENGTH, work_arr, data_size, temp,
     213                        hash_sel);
     214                memcpy(result + i*hash_length, temp, hash_length);
     215        }
     216       
     217        memcpy(hash, result, result_length);
     218       
     219        return EOK;
     220}
     221
     222int ieee80211_aes_key_unwrap(uint8_t *kek, uint8_t *data, size_t data_size,
     223        uint8_t *output)
     224{
     225        if(!kek || !data)
     226                return EINVAL;
     227       
     228        if(!output)
     229                return ENOMEM;
     230
     231        uint32_t n = data_size/8 - 1;
     232        uint8_t work_data[n*8];
     233        uint8_t work_input[AES_CIPHER_LENGTH];
     234        uint8_t work_output[AES_CIPHER_LENGTH];
     235        uint8_t *work_block;
     236        uint8_t a[8];
     237        memcpy(a, data, 8);
     238        uint64_t mask = 0xFF;
     239        uint8_t shift, shb;
     240       
     241        memcpy(work_data, data + 8, n*8);
     242        for(int j = 5; j >=0; j--) {
     243                for(int i = n; i > 0; i--) {
     244                        for(size_t k = 0; k < 8; k++) {
     245                                shift = 56 - 8*k;
     246                                shb = ((n*j+i) & (mask << shift)) >> shift;
     247                                a[k] ^= shb;
     248                        }
     249                        work_block = work_data + (i-1)*8;
     250                        memcpy(work_input, a, 8);
     251                        memcpy(work_input + 8, work_block, 8);
     252                        aes_decrypt(kek, work_input, work_output);
     253                        memcpy(a, work_output, 8);
     254                        memcpy(work_data + (i-1)*8, work_output + 8, 8);
     255                }
     256        }
     257       
     258        size_t it;
     259        for(it = 0; it < 8; it++) {
     260                if(a[it] != 0xA6)
     261                        break;
     262        }
     263       
     264        if(it == 8) {
     265                memcpy(output, work_data, n*8);
     266                return EOK;
     267        } else {
     268                return EINVAL;
     269        }
     270}
     271
     272int rnd_sequence(uint8_t *sequence, size_t length)
     273{
     274        if(!sequence)
     275                return ENOMEM;
     276       
     277        for(size_t i = 0; i < length; i++) {
     278                sequence[i] = (uint8_t) rand();
     279        }
     280       
     281        return EOK;
     282}
     283
     284uint8_t *min_sequence(uint8_t *seq1, uint8_t *seq2, size_t size)
     285{
     286        if(!seq1 || !seq2)
     287                return NULL;
     288       
     289        for(size_t i = 0; i < size; i++) {
     290                if(seq1[i] < seq2[i]) {
     291                        return seq1;
     292                } else if(seq1[i] > seq2[i]) {
     293                        return seq2;
     294                }
     295        }
     296       
     297        return seq1;
     298}
     299
     300uint8_t *max_sequence(uint8_t *seq1, uint8_t *seq2, size_t size)
     301{
     302        uint8_t *min = min_sequence(seq1, seq2, size);
     303        if(min == seq1) {
     304                return seq2;
     305        } else {
     306                return seq1;
     307        }
    107308}
    108309
Note: See TracChangeset for help on using the changeset viewer.