00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <errno.h>
00024 #include <gpxe/ieee80211.h>
00025 #include <gpxe/net80211.h>
00026 #include <gpxe/sec80211.h>
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 struct descriptor_map {
00039
00040 u32 net80211_type;
00041
00042
00043 u32 oui_type;
00044 };
00045
00046
00047 #define END_MAGIC 0xFFFFFFFF
00048
00049
00050 static struct descriptor_map rsn_cipher_map[] = {
00051 { .net80211_type = NET80211_CRYPT_WEP,
00052 .oui_type = IEEE80211_RSN_CTYPE_WEP40 },
00053
00054 { .net80211_type = NET80211_CRYPT_WEP,
00055 .oui_type = IEEE80211_RSN_CTYPE_WEP104 },
00056
00057 { .net80211_type = NET80211_CRYPT_TKIP,
00058 .oui_type = IEEE80211_RSN_CTYPE_TKIP },
00059
00060 { .net80211_type = NET80211_CRYPT_CCMP,
00061 .oui_type = IEEE80211_RSN_CTYPE_CCMP },
00062
00063 { .net80211_type = NET80211_CRYPT_UNKNOWN,
00064 .oui_type = END_MAGIC },
00065 };
00066
00067
00068 static struct descriptor_map rsn_akm_map[] = {
00069 { .net80211_type = NET80211_SECPROT_EAP,
00070 .oui_type = IEEE80211_RSN_ATYPE_8021X },
00071
00072 { .net80211_type = NET80211_SECPROT_PSK,
00073 .oui_type = IEEE80211_RSN_ATYPE_PSK },
00074
00075 { .net80211_type = NET80211_SECPROT_UNKNOWN,
00076 .oui_type = END_MAGIC },
00077 };
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 int sec80211_install ( struct net80211_crypto **which,
00099 enum net80211_crypto_alg crypt,
00100 const void *key, int len, const void *rsc )
00101 {
00102 struct net80211_crypto *crypto = *which;
00103 struct net80211_crypto *tbl_crypto;
00104
00105
00106 free ( *which );
00107 *which = NULL;
00108
00109 if ( crypt == NET80211_CRYPT_NONE ) {
00110 DBG ( "802.11-Sec not installing null cryptography\n" );
00111 return 0;
00112 }
00113
00114
00115 for_each_table_entry ( tbl_crypto, NET80211_CRYPTOS ) {
00116 if ( tbl_crypto->algorithm == crypt ) {
00117 crypto = zalloc ( sizeof ( *crypto ) +
00118 tbl_crypto->priv_len );
00119 if ( ! crypto ) {
00120 DBG ( "802.11-Sec out of memory\n" );
00121 return -ENOMEM;
00122 }
00123
00124 memcpy ( crypto, tbl_crypto, sizeof ( *crypto ) );
00125 crypto->priv = ( ( void * ) crypto +
00126 sizeof ( *crypto ) );
00127 break;
00128 }
00129 }
00130
00131 if ( ! crypto ) {
00132 DBG ( "802.11-Sec no support for cryptosystem %d\n", crypt );
00133 return -( ENOTSUP | EUNIQ_10 | ( crypt << 8 ) );
00134 }
00135
00136 *which = crypto;
00137
00138 DBG ( "802.11-Sec installing cryptosystem %d as %p with key of "
00139 "length %d\n", crypt, crypto, len );
00140
00141 return crypto->init ( crypto, key, len, rsc );
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 static struct descriptor_map * rsn_pick_desc ( u8 **rsnp, u8 *rsn_end,
00172 struct descriptor_map *map,
00173 void *tbl_start, void *tbl_end )
00174 {
00175 int ndesc;
00176 int ok = 0;
00177 struct descriptor_map *map_ent, *map_ret = NULL;
00178 u8 *rsn = *rsnp;
00179 void *tblp;
00180 size_t tbl_stride = ( map == rsn_cipher_map ?
00181 sizeof ( struct net80211_crypto ) :
00182 sizeof ( struct net80211_handshaker ) );
00183
00184 if ( map != rsn_cipher_map && map != rsn_akm_map )
00185 return NULL;
00186
00187
00188 for ( tblp = tbl_start; tblp < tbl_end; tblp += tbl_stride ) {
00189 struct net80211_crypto *crypto = tblp;
00190 struct net80211_handshaker *hs = tblp;
00191
00192 if ( map == rsn_cipher_map )
00193 ok |= ( 1 << crypto->algorithm );
00194 else
00195 ok |= ( 1 << hs->protocol );
00196 }
00197
00198
00199 if ( rsn + 2 > rsn_end ) {
00200 DBG ( "RSN detect: malformed descriptor count\n" );
00201 return NULL;
00202 }
00203
00204 ndesc = *( u16 * ) rsn;
00205 rsn += 2;
00206
00207 if ( ! ndesc ) {
00208 DBG ( "RSN detect: no descriptors\n" );
00209 return NULL;
00210 }
00211
00212
00213 while ( ndesc-- ) {
00214 u32 desc;
00215
00216 if ( rsn + 4 > rsn_end ) {
00217 DBG ( "RSN detect: malformed descriptor (%d left)\n",
00218 ndesc );
00219 return NULL;
00220 }
00221
00222 desc = *( u32 * ) rsn;
00223 rsn += 4;
00224
00225 for ( map_ent = map; map_ent->oui_type != END_MAGIC; map_ent++ )
00226 if ( map_ent->oui_type == ( desc & OUI_TYPE_MASK ) )
00227 break;
00228
00229
00230 if ( ! map_ret )
00231 map_ret = map_ent;
00232
00233
00234 if ( ok & ( 1 << map_ent->net80211_type ) ) {
00235 map_ret = map_ent;
00236 break;
00237 }
00238 }
00239
00240 if ( ndesc > 0 )
00241 rsn += 4 * ndesc;
00242
00243 *rsnp = rsn;
00244 return map_ret;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 u8 * sec80211_find_rsn ( union ieee80211_ie *ie, void *ie_end,
00269 int *is_rsn, u8 **end )
00270 {
00271 u8 *rsn = NULL;
00272
00273 if ( ! ieee80211_ie_bound ( ie, ie_end ) )
00274 return NULL;
00275
00276 while ( ie ) {
00277 if ( ie->id == IEEE80211_IE_VENDOR &&
00278 ie->vendor.oui == IEEE80211_WPA_OUI_VEN ) {
00279 DBG ( "RSN detect: old-style WPA IE found\n" );
00280 rsn = &ie->vendor.data[0];
00281 *end = rsn + ie->len - 4;
00282 *is_rsn = 0;
00283 } else if ( ie->id == IEEE80211_IE_RSN ) {
00284 DBG ( "RSN detect: 802.11i RSN IE found\n" );
00285 rsn = ( u8 * ) &ie->rsn.version;
00286 *end = rsn + ie->len;
00287 *is_rsn = 1;
00288 }
00289
00290 if ( rsn && ( *end > ( u8 * ) ie_end || rsn >= *end ||
00291 *( u16 * ) rsn != IEEE80211_RSN_VERSION ) ) {
00292 DBG ( "RSN detect: malformed RSN IE or unknown "
00293 "version, keep trying\n" );
00294 rsn = NULL;
00295 }
00296
00297 if ( rsn )
00298 break;
00299
00300 ie = ieee80211_next_ie ( ie, ie_end );
00301 }
00302
00303 if ( ! ie ) {
00304 DBG ( "RSN detect: no RSN IE found\n" );
00305 return NULL;
00306 }
00307
00308 return rsn;
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 int sec80211_detect_ie ( int is_rsn, u8 *start, u8 *end,
00326 enum net80211_security_proto *secprot,
00327 enum net80211_crypto_alg *crypt )
00328 {
00329 enum net80211_security_proto sp;
00330 enum net80211_crypto_alg cr;
00331 struct descriptor_map *map;
00332 u8 *rsn = start;
00333
00334
00335 cr = ( is_rsn ? NET80211_CRYPT_CCMP : NET80211_CRYPT_TKIP );
00336 sp = NET80211_SECPROT_EAP;
00337
00338 rsn += 2;
00339 rsn += 4;
00340
00341 if ( rsn >= end )
00342 goto done;
00343
00344
00345 map = rsn_pick_desc ( &rsn, end, rsn_cipher_map,
00346 table_start ( NET80211_CRYPTOS ),
00347 table_end ( NET80211_CRYPTOS ) );
00348 if ( ! map )
00349 goto invalid_rsn;
00350
00351 cr = map->net80211_type;
00352
00353 if ( rsn >= end )
00354 goto done;
00355
00356
00357 map = rsn_pick_desc ( &rsn, end, rsn_akm_map,
00358 table_start ( NET80211_HANDSHAKERS ),
00359 table_end ( NET80211_HANDSHAKERS ) );
00360 if ( ! map )
00361 goto invalid_rsn;
00362
00363 sp = map->net80211_type;
00364
00365 done:
00366 DBG ( "RSN detect: OK, crypto type %d, secprot type %d\n", cr, sp );
00367 *secprot = sp;
00368 *crypt = cr;
00369 return 0;
00370
00371 invalid_rsn:
00372 DBG ( "RSN detect: invalid RSN IE\n" );
00373 return -EINVAL;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 int _sec80211_detect ( struct io_buffer *iob,
00392 enum net80211_security_proto *secprot,
00393 enum net80211_crypto_alg *crypt )
00394 {
00395 struct ieee80211_frame *hdr = iob->data;
00396 struct ieee80211_beacon *beacon =
00397 ( struct ieee80211_beacon * ) hdr->data;
00398 u8 *rsn, *rsn_end;
00399 int is_rsn, rc;
00400
00401 *crypt = NET80211_CRYPT_UNKNOWN;
00402 *secprot = NET80211_SECPROT_UNKNOWN;
00403
00404
00405 if ( ! ( rsn = sec80211_find_rsn ( beacon->info_element, iob->tail,
00406 &is_rsn, &rsn_end ) ) ) {
00407
00408 *secprot = NET80211_SECPROT_NONE;
00409
00410 if ( beacon->capability & IEEE80211_CAPAB_PRIVACY )
00411 *crypt = NET80211_CRYPT_WEP;
00412 else
00413 *crypt = NET80211_CRYPT_NONE;
00414
00415 return 0;
00416 }
00417
00418
00419 if ( ( rc = sec80211_detect_ie ( is_rsn, rsn, rsn_end, secprot,
00420 crypt ) ) == 0 )
00421 return 0;
00422
00423
00424
00425 *crypt = NET80211_CRYPT_UNKNOWN;
00426 *secprot = NET80211_SECPROT_UNKNOWN;
00427 DBG ( "Failed to handle RSN IE:\n" );
00428 DBG_HD ( rsn, rsn_end - rsn );
00429 return rc;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444 static u32 rsn_get_desc ( unsigned id, int rsnie, struct descriptor_map *map )
00445 {
00446 u32 vendor = ( rsnie ? IEEE80211_RSN_OUI : IEEE80211_WPA_OUI );
00447
00448 for ( ; map->oui_type != END_MAGIC; map++ ) {
00449 if ( map->net80211_type == id )
00450 return map->oui_type | vendor;
00451 }
00452
00453 return 0;
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 u32 sec80211_rsn_get_crypto_desc ( enum net80211_crypto_alg crypt, int rsnie )
00467 {
00468 return rsn_get_desc ( crypt, rsnie, rsn_cipher_map );
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 u32 sec80211_rsn_get_akm_desc ( enum net80211_security_proto secprot,
00482 int rsnie )
00483 {
00484 return rsn_get_desc ( secprot, rsnie, rsn_akm_map );
00485 }
00486
00487
00488
00489
00490
00491
00492
00493 enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt ( u32 desc )
00494 {
00495 struct descriptor_map *map = rsn_cipher_map;
00496
00497 for ( ; map->oui_type != END_MAGIC; map++ ) {
00498 if ( map->oui_type == ( desc & OUI_TYPE_MASK ) )
00499 break;
00500 }
00501
00502 return map->net80211_type;
00503 }