~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/net/80211/sec80211.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License as
 
6
 * published by the Free Software Foundation; either version 2 of the
 
7
 * License, or any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but
 
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
17
 * 02110-1301, USA.
 
18
 */
 
19
 
 
20
FILE_LICENCE ( GPL2_OR_LATER );
 
21
 
 
22
#include <stdlib.h>
 
23
#include <string.h>
 
24
#include <errno.h>
 
25
#include <ipxe/ieee80211.h>
 
26
#include <ipxe/net80211.h>
 
27
#include <ipxe/sec80211.h>
 
28
 
 
29
/** @file
 
30
 *
 
31
 * General secured-network routines required whenever any secure
 
32
 * network support at all is compiled in. This involves things like
 
33
 * installing keys, determining the type of security used by a probed
 
34
 * network, and some small helper functions that take advantage of
 
35
 * static data in this file.
 
36
 */
 
37
 
 
38
/* Unsupported cryptosystem error numbers */
 
39
#define ENOTSUP_WEP __einfo_error ( EINFO_ENOTSUP_WEP )
 
40
#define EINFO_ENOTSUP_WEP __einfo_uniqify ( EINFO_ENOTSUP, \
 
41
        ( 0x10 | NET80211_CRYPT_WEP ), "WEP not supported" )
 
42
#define ENOTSUP_TKIP __einfo_error ( EINFO_ENOTSUP_TKIP )
 
43
#define EINFO_ENOTSUP_TKIP __einfo_uniqify ( EINFO_ENOTSUP, \
 
44
        ( 0x10 | NET80211_CRYPT_TKIP ), "TKIP not supported" )
 
45
#define ENOTSUP_CCMP __einfo_error ( EINFO_ENOTSUP_CCMP )
 
46
#define EINFO_ENOTSUP_CCMP __einfo_uniqify ( EINFO_ENOTSUP, \
 
47
        ( 0x10 | NET80211_CRYPT_CCMP ), "CCMP not supported" )
 
48
#define ENOTSUP_CRYPT( crypt )                     \
 
49
        EUNIQ ( EINFO_ENOTSUP, ( 0x10 | (crypt) ), \
 
50
                ENOTSUP_WEP, ENOTSUP_TKIP, ENOTSUP_CCMP )
 
51
 
 
52
/** Mapping from net80211 crypto/secprot types to RSN OUI descriptors */
 
53
struct descriptor_map {
 
54
        /** Value of net80211_crypto_alg or net80211_security_proto */
 
55
        u32 net80211_type;
 
56
 
 
57
        /** OUI+type in appropriate byte order, masked to exclude vendor */
 
58
        u32 oui_type;
 
59
};
 
60
 
 
61
/** Magic number in @a oui_type showing end of list */
 
62
#define END_MAGIC       0xFFFFFFFF
 
63
 
 
64
/** Mapping between net80211 cryptosystems and 802.11i cipher IDs */
 
65
static struct descriptor_map rsn_cipher_map[] = {
 
66
        { .net80211_type = NET80211_CRYPT_WEP,
 
67
          .oui_type = IEEE80211_RSN_CTYPE_WEP40 },
 
68
 
 
69
        { .net80211_type = NET80211_CRYPT_WEP,
 
70
          .oui_type = IEEE80211_RSN_CTYPE_WEP104 },
 
71
 
 
72
        { .net80211_type = NET80211_CRYPT_TKIP,
 
73
          .oui_type = IEEE80211_RSN_CTYPE_TKIP },
 
74
 
 
75
        { .net80211_type = NET80211_CRYPT_CCMP,
 
76
          .oui_type = IEEE80211_RSN_CTYPE_CCMP },
 
77
 
 
78
        { .net80211_type = NET80211_CRYPT_UNKNOWN,
 
79
          .oui_type = END_MAGIC },
 
80
};
 
81
 
 
82
/** Mapping between net80211 handshakers and 802.11i AKM IDs */
 
83
static struct descriptor_map rsn_akm_map[] = {
 
84
        { .net80211_type = NET80211_SECPROT_EAP,
 
85
          .oui_type = IEEE80211_RSN_ATYPE_8021X },
 
86
 
 
87
        { .net80211_type = NET80211_SECPROT_PSK,
 
88
          .oui_type = IEEE80211_RSN_ATYPE_PSK },
 
89
 
 
90
        { .net80211_type = NET80211_SECPROT_UNKNOWN,
 
91
          .oui_type = END_MAGIC },
 
92
};
 
93
 
 
94
 
 
95
/**
 
96
 * Install 802.11 cryptosystem
 
97
 *
 
98
 * @v which     Pointer to the cryptosystem structure to install in
 
99
 * @v crypt     Cryptosystem ID number
 
100
 * @v key       Encryption key to use
 
101
 * @v len       Length of encryption key
 
102
 * @v rsc       Initial receive sequence counter, if applicable
 
103
 * @ret rc      Return status code
 
104
 *
 
105
 * The encryption key will not be accessed via the provided pointer
 
106
 * after this function returns, so you may keep it on the stack.
 
107
 *
 
108
 * @a which must point to either @c dev->crypto (for the normal case
 
109
 * of installing a unicast cryptosystem) or @c dev->gcrypto (to
 
110
 * install a cryptosystem that will be used only for decrypting
 
111
 * group-source frames).
 
112
 */
 
113
int sec80211_install ( struct net80211_crypto **which,
 
114
                       enum net80211_crypto_alg crypt,
 
115
                       const void *key, int len, const void *rsc )
 
116
{
 
117
        struct net80211_crypto *crypto = *which;
 
118
        struct net80211_crypto *tbl_crypto;
 
119
 
 
120
        /* Remove old crypto if it exists */
 
121
        free ( *which );
 
122
        *which = NULL;
 
123
 
 
124
        if ( crypt == NET80211_CRYPT_NONE ) {
 
125
                DBG ( "802.11-Sec not installing null cryptography\n" );
 
126
                return 0;
 
127
        }
 
128
 
 
129
        /* Find cryptosystem to use */
 
130
        for_each_table_entry ( tbl_crypto, NET80211_CRYPTOS ) {
 
131
                if ( tbl_crypto->algorithm == crypt ) {
 
132
                        crypto = zalloc ( sizeof ( *crypto ) +
 
133
                                          tbl_crypto->priv_len );
 
134
                        if ( ! crypto ) {
 
135
                                DBG ( "802.11-Sec out of memory\n" );
 
136
                                return -ENOMEM;
 
137
                        }
 
138
 
 
139
                        memcpy ( crypto, tbl_crypto, sizeof ( *crypto ) );
 
140
                        crypto->priv = ( ( void * ) crypto +
 
141
                                         sizeof ( *crypto ) );
 
142
                        break;
 
143
                }
 
144
        }
 
145
 
 
146
        if ( ! crypto ) {
 
147
                DBG ( "802.11-Sec no support for cryptosystem %d\n", crypt );
 
148
                return -ENOTSUP_CRYPT ( crypt );
 
149
        }
 
150
 
 
151
        *which = crypto;
 
152
 
 
153
        DBG ( "802.11-Sec installing cryptosystem %d as %p with key of "
 
154
              "length %d\n", crypt, crypto, len );
 
155
 
 
156
        return crypto->init ( crypto, key, len, rsc );
 
157
}
 
158
 
 
159
 
 
160
/**
 
161
 * Determine net80211 crypto or handshaking type value to return for RSN info
 
162
 *
 
163
 * @v rsnp              Pointer to next descriptor count field in RSN IE
 
164
 * @v rsn_end           Pointer to end of RSN IE
 
165
 * @v map               Descriptor map to use
 
166
 * @v tbl_start         Start of linker table to examine for iPXE support
 
167
 * @v tbl_end           End of linker table to examine for iPXE support
 
168
 * @ret rsnp            Updated to point to first byte after descriptors
 
169
 * @ret map_ent         Descriptor map entry of translation to use
 
170
 *
 
171
 * The entries in the linker table must be either net80211_crypto or
 
172
 * net80211_handshaker structures, and @a tbl_stride must be set to
 
173
 * sizeof() the appropriate one.
 
174
 *
 
175
 * This function expects @a rsnp to point at a two-byte descriptor
 
176
 * count followed by a list of four-byte cipher or AKM descriptors; it
 
177
 * will return @c NULL if the input packet is malformed, and otherwise
 
178
 * set @a rsnp to the first byte it has not looked at. It will return
 
179
 * the first cipher in the list that is supported by the current build
 
180
 * of iPXE, or the first of all if none are supported.
 
181
 *
 
182
 * We play rather fast and loose with type checking, because this
 
183
 * function is only called from two well-defined places in the
 
184
 * RSN-checking code. Don't try to use it for anything else.
 
185
 */
 
186
static struct descriptor_map * rsn_pick_desc ( u8 **rsnp, u8 *rsn_end,
 
187
                                               struct descriptor_map *map,
 
188
                                               void *tbl_start, void *tbl_end )
 
189
{
 
190
        int ndesc;
 
191
        int ok = 0;
 
192
        struct descriptor_map *map_ent, *map_ret = NULL;
 
193
        u8 *rsn = *rsnp;
 
194
        void *tblp;
 
195
        size_t tbl_stride = ( map == rsn_cipher_map ?
 
196
                              sizeof ( struct net80211_crypto ) :
 
197
                              sizeof ( struct net80211_handshaker ) );
 
198
 
 
199
        if ( map != rsn_cipher_map && map != rsn_akm_map )
 
200
                return NULL;
 
201
 
 
202
        /* Determine which types we support */
 
203
        for ( tblp = tbl_start; tblp < tbl_end; tblp += tbl_stride ) {
 
204
                struct net80211_crypto *crypto = tblp;
 
205
                struct net80211_handshaker *hs = tblp;
 
206
 
 
207
                if ( map == rsn_cipher_map )
 
208
                        ok |= ( 1 << crypto->algorithm );
 
209
                else
 
210
                        ok |= ( 1 << hs->protocol );
 
211
        }
 
212
 
 
213
        /* RSN sanity checks */
 
214
        if ( rsn + 2 > rsn_end ) {
 
215
                DBG ( "RSN detect: malformed descriptor count\n" );
 
216
                return NULL;
 
217
        }
 
218
 
 
219
        ndesc = *( u16 * ) rsn;
 
220
        rsn += 2;
 
221
 
 
222
        if ( ! ndesc ) {
 
223
                DBG ( "RSN detect: no descriptors\n" );
 
224
                return NULL;
 
225
        }
 
226
 
 
227
        /* Determine which net80211 crypto types are listed */
 
228
        while ( ndesc-- ) {
 
229
                u32 desc;
 
230
 
 
231
                if ( rsn + 4 > rsn_end ) {
 
232
                        DBG ( "RSN detect: malformed descriptor (%d left)\n",
 
233
                              ndesc );
 
234
                        return NULL;
 
235
                }
 
236
 
 
237
                desc = *( u32 * ) rsn;
 
238
                rsn += 4;
 
239
 
 
240
                for ( map_ent = map; map_ent->oui_type != END_MAGIC; map_ent++ )
 
241
                        if ( map_ent->oui_type == ( desc & OUI_TYPE_MASK ) )
 
242
                                break;
 
243
 
 
244
                /* Use first cipher as a fallback */
 
245
                if ( ! map_ret )
 
246
                        map_ret = map_ent;
 
247
 
 
248
                /* Once we find one we support, use it */
 
249
                if ( ok & ( 1 << map_ent->net80211_type ) ) {
 
250
                        map_ret = map_ent;
 
251
                        break;
 
252
                }
 
253
        }
 
254
 
 
255
        if ( ndesc > 0 )
 
256
                rsn += 4 * ndesc;
 
257
 
 
258
        *rsnp = rsn;
 
259
        return map_ret;
 
260
}
 
261
 
 
262
 
 
263
/**
 
264
 * Find the RSN or WPA information element in the provided beacon frame
 
265
 *
 
266
 * @v ie        Pointer to first information element to check
 
267
 * @v ie_end    Pointer to end of information element space
 
268
 * @ret is_rsn  TRUE if returned IE is RSN, FALSE if it's WPA
 
269
 * @ret end     Pointer to byte immediately after last byte of data
 
270
 * @ret data    Pointer to first byte of data (the `version' field)
 
271
 *
 
272
 * If both an RSN and a WPA information element are found, this
 
273
 * function will return the first one seen, which by ordering rules
 
274
 * should always prefer the newer RSN IE.
 
275
 *
 
276
 * If no RSN or WPA infomration element is found, returns @c NULL and
 
277
 * leaves @a is_rsn and @a end in an undefined state.
 
278
 *
 
279
 * This function will not return a pointer to an information element
 
280
 * that states it extends past the tail of the io_buffer, or whose @a
 
281
 * version field is incorrect.
 
282
 */
 
283
u8 * sec80211_find_rsn ( union ieee80211_ie *ie, void *ie_end,
 
284
                         int *is_rsn, u8 **end )
 
285
{
 
286
        u8 *rsn = NULL;
 
287
 
 
288
        if ( ! ieee80211_ie_bound ( ie, ie_end ) )
 
289
                return NULL;
 
290
 
 
291
        while ( ie ) {
 
292
                if ( ie->id == IEEE80211_IE_VENDOR &&
 
293
                     ie->vendor.oui == IEEE80211_WPA_OUI_VEN ) {
 
294
                        DBG ( "RSN detect: old-style WPA IE found\n" );
 
295
                        rsn = &ie->vendor.data[0];
 
296
                        *end = rsn + ie->len - 4;
 
297
                        *is_rsn = 0;
 
298
                } else if ( ie->id == IEEE80211_IE_RSN ) {
 
299
                        DBG ( "RSN detect: 802.11i RSN IE found\n" );
 
300
                        rsn = ( u8 * ) &ie->rsn.version;
 
301
                        *end = rsn + ie->len;
 
302
                        *is_rsn = 1;
 
303
                }
 
304
 
 
305
                if ( rsn && ( *end > ( u8 * ) ie_end || rsn >= *end ||
 
306
                              *( u16 * ) rsn != IEEE80211_RSN_VERSION ) ) {
 
307
                        DBG ( "RSN detect: malformed RSN IE or unknown "
 
308
                              "version, keep trying\n" );
 
309
                        rsn = NULL;
 
310
                }
 
311
 
 
312
                if ( rsn )
 
313
                        break;
 
314
 
 
315
                ie = ieee80211_next_ie ( ie, ie_end );
 
316
        }
 
317
 
 
318
        if ( ! ie ) {
 
319
                DBG ( "RSN detect: no RSN IE found\n" );
 
320
                return NULL;
 
321
        }
 
322
 
 
323
        return rsn;
 
324
}
 
325
 
 
326
 
 
327
/**
 
328
 * Detect crypto and AKM types from RSN information element
 
329
 *
 
330
 * @v is_rsn    If TRUE, IE is a new-style RSN information element
 
331
 * @v start     Pointer to first byte of @a version field
 
332
 * @v end       Pointer to first byte not in the RSN IE
 
333
 * @ret secprot Security handshaking protocol used by network
 
334
 * @ret crypt   Cryptosystem used by network
 
335
 * @ret rc      Return status code
 
336
 *
 
337
 * If the IE cannot be parsed, returns an error indication and leaves
 
338
 * @a secprot and @a crypt unchanged.
 
339
 */
 
340
int sec80211_detect_ie ( int is_rsn, u8 *start, u8 *end,
 
341
                         enum net80211_security_proto *secprot,
 
342
                         enum net80211_crypto_alg *crypt )
 
343
{
 
344
        enum net80211_security_proto sp;
 
345
        enum net80211_crypto_alg cr;
 
346
        struct descriptor_map *map;
 
347
        u8 *rsn = start;
 
348
 
 
349
        /* Set some defaults */
 
350
        cr = ( is_rsn ? NET80211_CRYPT_CCMP : NET80211_CRYPT_TKIP );
 
351
        sp = NET80211_SECPROT_EAP;
 
352
 
 
353
        rsn += 2;               /* version - already checked */
 
354
        rsn += 4;               /* group cipher - we don't use it here */
 
355
 
 
356
        if ( rsn >= end )
 
357
                goto done;
 
358
 
 
359
        /* Pick crypto algorithm */
 
360
        map = rsn_pick_desc ( &rsn, end, rsn_cipher_map,
 
361
                              table_start ( NET80211_CRYPTOS ),
 
362
                              table_end ( NET80211_CRYPTOS ) );
 
363
        if ( ! map )
 
364
                goto invalid_rsn;
 
365
 
 
366
        cr = map->net80211_type;
 
367
 
 
368
        if ( rsn >= end )
 
369
                goto done;
 
370
 
 
371
        /* Pick handshaking algorithm */
 
372
        map = rsn_pick_desc ( &rsn, end, rsn_akm_map,
 
373
                              table_start ( NET80211_HANDSHAKERS ),
 
374
                              table_end ( NET80211_HANDSHAKERS ) );
 
375
        if ( ! map )
 
376
                goto invalid_rsn;
 
377
 
 
378
        sp = map->net80211_type;
 
379
 
 
380
 done:
 
381
        DBG ( "RSN detect: OK, crypto type %d, secprot type %d\n", cr, sp );
 
382
        *secprot = sp;
 
383
        *crypt = cr;
 
384
        return 0;
 
385
 
 
386
 invalid_rsn:
 
387
        DBG ( "RSN detect: invalid RSN IE\n" );
 
388
        return -EINVAL;
 
389
}
 
390
 
 
391
 
 
392
/**
 
393
 * Detect the cryptosystem and handshaking protocol used by an 802.11 network
 
394
 *
 
395
 * @v iob       I/O buffer containing beacon frame
 
396
 * @ret secprot Security handshaking protocol used by network
 
397
 * @ret crypt   Cryptosystem used by network
 
398
 * @ret rc      Return status code
 
399
 *
 
400
 * This function uses weak linkage, as it must be called from generic
 
401
 * contexts but should only be linked in if some encryption is
 
402
 * supported; you must test its address against @c NULL before calling
 
403
 * it. If it does not exist, any network with the PRIVACY bit set in
 
404
 * beacon->capab should be considered unknown.
 
405
 */
 
406
int sec80211_detect ( struct io_buffer *iob,
 
407
                      enum net80211_security_proto *secprot,
 
408
                      enum net80211_crypto_alg *crypt )
 
409
{
 
410
        struct ieee80211_frame *hdr = iob->data;
 
411
        struct ieee80211_beacon *beacon =
 
412
                ( struct ieee80211_beacon * ) hdr->data;
 
413
        u8 *rsn, *rsn_end;
 
414
        int is_rsn, rc;
 
415
 
 
416
        *crypt = NET80211_CRYPT_UNKNOWN;
 
417
        *secprot = NET80211_SECPROT_UNKNOWN;
 
418
 
 
419
        /* Find RSN or WPA IE */
 
420
        if ( ! ( rsn = sec80211_find_rsn ( beacon->info_element, iob->tail,
 
421
                                           &is_rsn, &rsn_end ) ) ) {
 
422
                /* No security IE at all; either WEP or no security. */
 
423
                *secprot = NET80211_SECPROT_NONE;
 
424
 
 
425
                if ( beacon->capability & IEEE80211_CAPAB_PRIVACY )
 
426
                        *crypt = NET80211_CRYPT_WEP;
 
427
                else
 
428
                        *crypt = NET80211_CRYPT_NONE;
 
429
 
 
430
                return 0;
 
431
        }
 
432
 
 
433
        /* Determine type of security */
 
434
        if ( ( rc = sec80211_detect_ie ( is_rsn, rsn, rsn_end, secprot,
 
435
                                         crypt ) ) == 0 )
 
436
                return 0;
 
437
 
 
438
        /* If we get here, the RSN IE was invalid */
 
439
 
 
440
        *crypt = NET80211_CRYPT_UNKNOWN;
 
441
        *secprot = NET80211_SECPROT_UNKNOWN;
 
442
        DBG ( "Failed to handle RSN IE:\n" );
 
443
        DBG_HD ( rsn, rsn_end - rsn );
 
444
        return rc;
 
445
}
 
446
 
 
447
 
 
448
/**
 
449
 * Determine RSN descriptor for specified net80211 ID
 
450
 *
 
451
 * @v id        net80211 ID value
 
452
 * @v rsnie     Whether to return a new-format (RSN IE) descriptor
 
453
 * @v map       Map to use in translation
 
454
 * @ret desc    RSN descriptor, or 0 on error
 
455
 *
 
456
 * If @a rsnie is false, returns an old-format (WPA vendor IE)
 
457
 * descriptor.
 
458
 */
 
459
static u32 rsn_get_desc ( unsigned id, int rsnie, struct descriptor_map *map )
 
460
{
 
461
        u32 vendor = ( rsnie ? IEEE80211_RSN_OUI : IEEE80211_WPA_OUI );
 
462
 
 
463
        for ( ; map->oui_type != END_MAGIC; map++ ) {
 
464
                if ( map->net80211_type == id )
 
465
                        return map->oui_type | vendor;
 
466
        }
 
467
 
 
468
        return 0;
 
469
}
 
470
 
 
471
/**
 
472
 * Determine RSN descriptor for specified net80211 cryptosystem number
 
473
 *
 
474
 * @v crypt     Cryptosystem number
 
475
 * @v rsnie     Whether to return a new-format (RSN IE) descriptor
 
476
 * @ret desc    RSN descriptor
 
477
 *
 
478
 * If @a rsnie is false, returns an old-format (WPA vendor IE)
 
479
 * descriptor.
 
480
 */
 
481
u32 sec80211_rsn_get_crypto_desc ( enum net80211_crypto_alg crypt, int rsnie )
 
482
{
 
483
        return rsn_get_desc ( crypt, rsnie, rsn_cipher_map );
 
484
}
 
485
 
 
486
/**
 
487
 * Determine RSN descriptor for specified net80211 handshaker number
 
488
 *
 
489
 * @v secprot   Handshaker number
 
490
 * @v rsnie     Whether to return a new-format (RSN IE) descriptor
 
491
 * @ret desc    RSN descriptor
 
492
 *
 
493
 * If @a rsnie is false, returns an old-format (WPA vendor IE)
 
494
 * descriptor.
 
495
 */
 
496
u32 sec80211_rsn_get_akm_desc ( enum net80211_security_proto secprot,
 
497
                                int rsnie )
 
498
{
 
499
        return rsn_get_desc ( secprot, rsnie, rsn_akm_map );
 
500
}
 
501
 
 
502
/**
 
503
 * Determine net80211 cryptosystem number from RSN descriptor
 
504
 *
 
505
 * @v desc      RSN descriptor
 
506
 * @ret crypt   net80211 cryptosystem enumeration value
 
507
 */
 
508
enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt ( u32 desc )
 
509
{
 
510
        struct descriptor_map *map = rsn_cipher_map;
 
511
 
 
512
        for ( ; map->oui_type != END_MAGIC; map++ ) {
 
513
                if ( map->oui_type == ( desc & OUI_TYPE_MASK ) )
 
514
                        break;
 
515
        }
 
516
 
 
517
        return map->net80211_type;
 
518
}