source: mainline/uspace/lib/ieee80211/src/ieee80211_impl.c@ 1dcc0b9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1dcc0b9 was 1dcc0b9, checked in by Jan Kolarik <kolarik@…>, 10 years ago

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.

  • Property mode set to 100644
File size: 7.7 KB
Line 
1/*
2 * Copyright (c) 2015 Jan Kolarik
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libieee80211
30 * @{
31 */
32
33/** @file ieee80211_impl.c
34 *
35 * IEEE 802.11 default device functions implementation.
36 */
37
38#include <stdio.h>
39#include <crypto.h>
40#include <stdlib.h>
41#include <errno.h>
42
43#include <ieee80211_impl.h>
44
45/**
46 * Default implementation of IEEE802.11 start function.
47 *
48 * @param ieee80211_dev Structure of IEEE802.11 device.
49 *
50 * @return EOK.
51 */
52int ieee80211_start_impl(ieee80211_dev_t *ieee80211_dev)
53{
54 return EOK;
55}
56
57/**
58 * Default implementation of IEEE802.11 TX handler function.
59 *
60 * @param ieee80211_dev Structure of IEEE802.11 device.
61 * @param buffer Buffer with data to send.
62 * @param buffer_size Size of buffer.
63 *
64 * @return EOK.
65 */
66int ieee80211_tx_handler_impl(ieee80211_dev_t *ieee80211_dev, void *buffer,
67 size_t buffer_size)
68{
69 return EOK;
70}
71
72/**
73 * Default implementation of IEEE802.11 set frequency function.
74 *
75 * @param ieee80211_dev Structure of IEEE802.11 device.
76 * @param freq Value of frequency to be switched on.
77 *
78 * @return EOK.
79 */
80int ieee80211_set_freq_impl(ieee80211_dev_t *ieee80211_dev, uint16_t freq)
81{
82 return EOK;
83}
84
85/**
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/**
111 * Default implementation of IEEE802.11 scan function.
112 *
113 * @param ieee80211_dev Structure of IEEE802.11 device.
114 * @param clear Whether to clear current scan results.
115 *
116 * @return EOK if succeed, negative error code otherwise.
117 */
118int ieee80211_scan_impl(ieee80211_dev_t *ieee80211_dev)
119{
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
142 uint16_t orig_freq = ieee80211_dev->current_freq;
143
144 for(uint16_t freq = IEEE80211_FIRST_FREQ;
145 freq <= IEEE80211_MAX_FREQ;
146 freq += IEEE80211_CHANNEL_GAP) {
147 ieee80211_dev->ops->set_freq(ieee80211_dev, freq);
148 ieee80211_probe_request(ieee80211_dev, NULL);
149
150 /* Wait for probe responses. */
151 usleep(100000);
152 }
153
154 ieee80211_dev->ops->set_freq(ieee80211_dev, orig_freq);
155
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 }
308}
309
310/** @}
311 */
Note: See TracBrowser for help on using the repository browser.