Changeset 8a64320e in mainline for uspace/lib/ieee80211/src/ieee80211_impl.c
- Timestamp:
- 2015-04-23T23:40:14Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- dcba819
- Parents:
- 09044cb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ieee80211/src/ieee80211_impl.c
r09044cb r8a64320e 32 32 33 33 /** @file ieee80211_impl.c 34 * 34 * 35 35 * IEEE 802.11 default device functions implementation. 36 36 */ … … 40 40 #include <stdlib.h> 41 41 #include <errno.h> 42 43 42 #include <ieee80211_impl.h> 44 43 45 /** 46 * Default implementation of IEEE802.11 start function.47 * 48 * @param ieee80211_dev Structure of IEEE802.11 device.49 * 50 * @return EOK.44 /** Default implementation of IEEE802.11 start function. 45 * 46 * @param ieee80211_dev Structure of IEEE802.11 device. 47 * 48 * @return EOK. 49 * 51 50 */ 52 51 int ieee80211_start_impl(ieee80211_dev_t *ieee80211_dev) … … 55 54 } 56 55 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 */ 66 int ieee80211_tx_handler_impl(ieee80211_dev_t *ieee80211_dev, void *buffer, 67 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.56 /** Default implementation of IEEE802.11 TX handler function. 57 * 58 * @param ieee80211_dev Structure of IEEE802.11 device. 59 * @param buffer Buffer with data to send. 60 * @param buffer_size Size of buffer. 61 * 62 * @return EOK. 63 * 64 */ 65 int ieee80211_tx_handler_impl(ieee80211_dev_t *ieee80211_dev, void *buffer, 66 size_t buffer_size) 67 { 68 return EOK; 69 } 70 71 /** Default implementation of IEEE802.11 set frequency function. 72 * 73 * @param ieee80211_dev Structure of IEEE802.11 device. 74 * @param freq Value of frequency to be switched on. 75 * 76 * @return EOK. 77 * 79 78 */ 80 79 int ieee80211_set_freq_impl(ieee80211_dev_t *ieee80211_dev, uint16_t freq) … … 83 82 } 84 83 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 */ 92 int ieee80211_bssid_change_impl(ieee80211_dev_t *ieee80211_dev, 93 94 { 95 return EOK; 96 } 97 98 /** 99 * Default implementation of IEEE802.11 key config function.100 * 101 * @param ieee80211_dev Structure of IEEE802.11 device.102 * 103 * @return EOK.84 /** Default implementation of IEEE802.11 BSSID change function. 85 * 86 * @param ieee80211_dev Structure of IEEE802.11 device. 87 * 88 * @return EOK. 89 * 90 */ 91 int ieee80211_bssid_change_impl(ieee80211_dev_t *ieee80211_dev, 92 bool connected) 93 { 94 return EOK; 95 } 96 97 /** Default implementation of IEEE802.11 key config function. 98 * 99 * @param ieee80211_dev Structure of IEEE802.11 device. 100 * 101 * @return EOK. 102 * 104 103 */ 105 104 int ieee80211_key_config_impl(ieee80211_dev_t *ieee80211_dev, 106 107 { 108 return EOK; 109 } 110 111 /** 112 * Default implementation of IEEE802.11 scan function.113 * 114 * @param ieee80211_dev Structure of IEEE802.11 device.115 * @param clear Whether to clear current scan results.116 * 117 * @return EOK if succeed, negative error code otherwise.105 ieee80211_key_config_t *key_conf, bool insert) 106 { 107 return EOK; 108 } 109 110 /** Default implementation of IEEE802.11 scan function. 111 * 112 * @param ieee80211_dev Structure of IEEE802.11 device. 113 * @param clear Whether to clear current scan results. 114 * 115 * @return EOK if succeed, negative error code otherwise. 116 * 118 117 */ 119 118 int ieee80211_scan_impl(ieee80211_dev_t *ieee80211_dev) … … 121 120 fibril_mutex_lock(&ieee80211_dev->scan_mutex); 122 121 123 if (ieee80211_get_auth_phase(ieee80211_dev) ==124 122 if (ieee80211_get_auth_phase(ieee80211_dev) == 123 IEEE80211_AUTH_DISCONNECTED) { 125 124 fibril_mutex_lock(&ieee80211_dev->ap_list.results_mutex); 125 126 126 /* Remove old entries we don't receive beacons from. */ 127 ieee80211_scan_result_list_t *result_list = 128 &ieee80211_dev->ap_list; 127 ieee80211_scan_result_list_t *result_list = 128 &ieee80211_dev->ap_list; 129 129 130 list_foreach_safe(result_list->list, cur_link, next_link) { 130 ieee80211_scan_result_link_t *cur_result = 131 list_get_instance(cur_link, 132 ieee80211_scan_result_link_t, 133 link); 134 if((time(NULL) - cur_result->last_beacon) > 135 MAX_KEEP_SCAN_SPAN_SEC) { 136 ieee80211_scan_result_list_remove(result_list, 137 cur_result); 138 } 131 ieee80211_scan_result_link_t *cur_result = 132 list_get_instance(cur_link, 133 ieee80211_scan_result_link_t, link); 134 135 if ((time(NULL) - cur_result->last_beacon) > 136 MAX_KEEP_SCAN_SPAN_SEC) 137 ieee80211_scan_result_list_remove(result_list, 138 cur_result); 139 139 } 140 140 141 fibril_mutex_unlock(&ieee80211_dev->ap_list.results_mutex); 141 142 142 143 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 if(ieee80211_pending_connect_request(ieee80211_dev)) { 144 145 for (uint16_t freq = IEEE80211_FIRST_FREQ; 146 freq <= IEEE80211_MAX_FREQ; freq += IEEE80211_CHANNEL_GAP) { 147 if (ieee80211_pending_connect_request(ieee80211_dev)) 148 148 break; 149 }150 149 151 150 ieee80211_dev->ops->set_freq(ieee80211_dev, freq); 152 151 ieee80211_probe_request(ieee80211_dev, NULL); 153 152 154 153 /* Wait for probe responses. */ 155 154 async_usleep(SCAN_CHANNEL_WAIT_USEC); 156 155 } 157 156 158 157 ieee80211_dev->ops->set_freq(ieee80211_dev, orig_freq); 159 158 } … … 164 163 } 165 164 166 /** 167 * Pseudorandom function used for IEEE 802.11 pairwise key computation 168 * using SHA1 hash algorithm. 169 * 170 * @param key Key with PBKDF2 encrypted passphrase. 171 * @param data Concatenated sequence of both mac addresses and nonces. 172 * @param hash Output parameter for result hash. 165 /** Pseudorandom function used for IEEE 802.11 pairwise key computation. 166 * 167 * Using SHA1 hash algorithm. 168 * 169 * @param key Key with PBKDF2 encrypted passphrase. 170 * @param data Concatenated sequence of both MAC 171 * addresses and nonces. 172 * @param hash Output parameter for result hash. 173 173 * @param output_size Length of output sequence to be generated. 174 * 175 * @return EINVAL when key or data not specified, ENOMEM when pointer for 176 * output hash result is not allocated, otherwise EOK. 177 */ 178 int ieee80211_prf(uint8_t *key, uint8_t *data, uint8_t *hash, 179 size_t output_size) 180 { 181 if(!key || !data) 174 * 175 * @return EINVAL when key or data not specified, 176 * ENOMEM when pointer for output hash result 177 * is not allocated, otherwise EOK. 178 * 179 */ 180 int ieee80211_prf(uint8_t *key, uint8_t *data, uint8_t *hash, 181 size_t output_size) 182 { 183 if ((!key) || (!data)) 182 184 return EINVAL; 183 185 184 if (!hash)186 if (!hash) 185 187 return ENOMEM; 186 188 … … 188 190 189 191 const char *a = "Pairwise key expansion"; 190 uint8_t result[HASH_SHA1 *iters];192 uint8_t result[HASH_SHA1 * iters]; 191 193 uint8_t temp[HASH_SHA1]; 194 192 195 size_t data_size = PRF_CRYPT_DATA_LENGTH + str_size(a) + 2; 193 196 uint8_t work_arr[data_size]; … … 196 199 memcpy(work_arr, a, str_size(a)); 197 200 memcpy(work_arr + str_size(a) + 1, data, PRF_CRYPT_DATA_LENGTH); 198 199 for (uint8_t i = 0; i < iters; i++) {201 202 for (uint8_t i = 0; i < iters; i++) { 200 203 memcpy(work_arr + data_size - 1, &i, 1); 201 hmac(key, PBKDF2_KEY_LENGTH, work_arr, data_size, temp, 202 204 hmac(key, PBKDF2_KEY_LENGTH, work_arr, data_size, temp, 205 HASH_SHA1); 203 206 memcpy(result + i*HASH_SHA1, temp, HASH_SHA1); 204 207 } … … 210 213 211 214 int ieee80211_rc4_key_unwrap(uint8_t *key, uint8_t *data, size_t data_size, 212 215 uint8_t *output) 213 216 { 214 217 return rc4(key, 32, data, data_size, 256, output); … … 216 219 217 220 int ieee80211_aes_key_unwrap(uint8_t *kek, uint8_t *data, size_t data_size, 218 219 { 220 if (!kek || !data)221 uint8_t *output) 222 { 223 if ((!kek) || (!data)) 221 224 return EINVAL; 222 225 223 if (!output)226 if (!output) 224 227 return ENOMEM; 225 226 uint32_t n = data_size /8 - 1;227 uint8_t work_data[n *8];228 229 uint32_t n = data_size / 8 - 1; 230 uint8_t work_data[n * 8]; 228 231 uint8_t work_input[AES_CIPHER_LENGTH]; 229 232 uint8_t work_output[AES_CIPHER_LENGTH]; 230 233 uint8_t *work_block; 231 234 uint8_t a[8]; 235 232 236 memcpy(a, data, 8); 233 uint64_t mask = 0xFF; 237 238 uint64_t mask = 0xff; 234 239 uint8_t shift, shb; 235 240 236 memcpy(work_data, data + 8, n *8);237 for (int j = 5; j >= 0; j--) {238 for (int i = n; i > 0; i--) {239 for (size_t k = 0; k < 8; k++) {240 shift = 56 - 8 *k;241 shb = ((n *j+i) & (mask << shift)) >> shift;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; 242 247 a[k] ^= shb; 243 248 } 244 work_block = work_data + (i-1)*8; 249 250 work_block = work_data + (i - 1) * 8; 245 251 memcpy(work_input, a, 8); 246 252 memcpy(work_input + 8, work_block, 8); 247 253 aes_decrypt(kek, work_input, work_output); 248 254 memcpy(a, work_output, 8); 249 memcpy(work_data + (i -1)*8, work_output + 8, 8);255 memcpy(work_data + (i - 1) * 8, work_output + 8, 8); 250 256 } 251 257 } 252 258 253 259 size_t it; 254 for (it = 0; it < 8; it++) {255 if (a[it] != 0xA6)260 for (it = 0; it < 8; it++) { 261 if (a[it] != 0xa6) 256 262 break; 257 263 } 258 264 259 if (it == 8) {260 memcpy(output, work_data, n *8);265 if (it == 8) { 266 memcpy(output, work_data, n * 8); 261 267 return EOK; 262 } else {263 return EINVAL;264 }265 } 266 267 static void ieee80211_michael_mic_block(uint32_t *l, uint32_t *r, 268 268 } 269 270 return EINVAL; 271 } 272 273 static void ieee80211_michael_mic_block(uint32_t *l, uint32_t *r, 274 uint32_t value) 269 275 { 270 276 *l ^= value; 271 277 *r ^= rotl_uint32(*l, 17); 272 278 *l += *r; 273 *r ^= ((*l & 0x00 FF00FF) << 8) | ((*l & 0xFF00FF00) >> 8);279 *r ^= ((*l & 0x00ff00ff) << 8) | ((*l & 0xff00ff00) >> 8); 274 280 *l += *r; 275 281 *r ^= rotl_uint32(*l, 3); … … 279 285 } 280 286 281 int ieee80211_michael_mic(uint8_t *key, uint8_t *buffer, size_t size, 282 283 { 284 if (!key || !buffer)287 int ieee80211_michael_mic(uint8_t *key, uint8_t *buffer, size_t size, 288 uint8_t *mic) 289 { 290 if ((!key) || (!buffer)) 285 291 return EINVAL; 286 292 287 if (!mic)293 if (!mic) 288 294 return ENOMEM; 289 295 … … 292 298 293 299 ieee80211_data_header_t *data_header = 294 295 296 uint8_t *data = buffer + sizeof(ieee80211_data_header_t) + 297 300 (ieee80211_data_header_t *) buffer; 301 302 uint8_t *data = buffer + sizeof(ieee80211_data_header_t) + 303 IEEE80211_TKIP_HEADER_LENGTH; 298 304 size_t data_size = size - sizeof(ieee80211_data_header_t) - 299 305 IEEE80211_TKIP_HEADER_LENGTH; 300 306 301 307 /* Process header. */ 302 uint8_t *src_addr = 303 304 305 uint8_t *dest_addr = 306 307 308 uint8_t *src_addr = 309 ieee80211_is_fromds_frame(data_header->frame_ctrl) ? 310 data_header->address3 : data_header->address2; 311 uint8_t *dest_addr = 312 ieee80211_is_tods_frame(data_header->frame_ctrl) ? 313 data_header->address3 : data_header->address1; 308 314 309 315 ieee80211_michael_mic_block(&l, &r, uint32le_from_seq(dest_addr)); 310 ieee80211_michael_mic_block(&l, &r, 311 312 316 ieee80211_michael_mic_block(&l, &r, 317 uint16le_from_seq(dest_addr + 4) | 318 (uint16le_from_seq(src_addr) << 16)); 313 319 ieee80211_michael_mic_block(&l, &r, uint32le_from_seq(src_addr + 2)); 314 320 ieee80211_michael_mic_block(&l, &r, 0); … … 318 324 size_t pad = data_size % 4; 319 325 320 for (size_t k = 0; k < blocks; k++) {321 ieee80211_michael_mic_block(&l, &r, 322 uint32le_from_seq(&data[k*4]));326 for (size_t k = 0; k < blocks; k++) { 327 ieee80211_michael_mic_block(&l, &r, 328 uint32le_from_seq(&data[k * 4])); 323 329 } 324 330 325 331 /* Add padding. */ 326 uint32_t value = 0x5 A;327 for (size_t i = pad; i > 0; i--) {332 uint32_t value = 0x5a; 333 for (size_t i = pad; i > 0; i--) { 328 334 value <<= 8; 329 value |= data[blocks *4 + (i-1)];335 value |= data[blocks * 4 + (i - 1)]; 330 336 } 331 337 … … 345 351 { 346 352 uint16_t *u16 = (uint16_t *) seq; 347 return uint16_t_le2host(*u16); 353 return uint16_t_le2host(*u16); 348 354 } 349 355 … … 351 357 { 352 358 uint32_t *u32 = (uint32_t *) seq; 353 return uint32_t_le2host(*u32); 359 return uint32_t_le2host(*u32); 354 360 } 355 361 … … 357 363 { 358 364 uint16_t *u16 = (uint16_t *) seq; 359 return uint16_t_be2host(*u16); 365 return uint16_t_be2host(*u16); 360 366 } 361 367 … … 363 369 { 364 370 uint32_t *u32 = (uint32_t *) seq; 365 return uint32_t_be2host(*u32); 371 return uint32_t_be2host(*u32); 366 372 } 367 373 368 374 int rnd_sequence(uint8_t *sequence, size_t length) 369 375 { 370 if (!sequence)376 if (!sequence) 371 377 return ENOMEM; 372 378 373 for (size_t i = 0; i < length; i++) {379 for (size_t i = 0; i < length; i++) 374 380 sequence[i] = (uint8_t) rand(); 375 }376 381 377 382 return EOK; … … 380 385 uint8_t *min_sequence(uint8_t *seq1, uint8_t *seq2, size_t size) 381 386 { 382 if (!seq1 || !seq2)387 if ((!seq1) || (!seq2)) 383 388 return NULL; 384 389 385 for (size_t i = 0; i < size; i++) {386 if (seq1[i] < seq2[i]) {390 for (size_t i = 0; i < size; i++) { 391 if (seq1[i] < seq2[i]) 387 392 return seq1; 388 } else if(seq1[i] > seq2[i]) {393 else if (seq1[i] > seq2[i]) 389 394 return seq2; 390 }391 395 } 392 396 … … 397 401 { 398 402 uint8_t *min = min_sequence(seq1, seq2, size); 399 if (min == seq1) {403 if (min == seq1) 400 404 return seq2; 401 } else { 402 return seq1; 403 } 405 406 return seq1; 404 407 } 405 408
Note:
See TracChangeset
for help on using the changeset viewer.