sec80211.h File Reference

Definitions for general secured-network routines. More...

#include <gpxe/net80211.h>
#include <errno.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
int _sec80211_detect (struct io_buffer *iob, enum net80211_security_proto *secprot, enum net80211_crypto_alg *crypt)
 Detect the cryptosystem and handshaking protocol used by an 802.11 network.
static int sec80211_detect (struct io_buffer *iob, enum net80211_security_proto *secprot, enum net80211_crypto_alg *crypt)
 Inline safety wrapper for _sec80211_detect().
int sec80211_detect_ie (int is_rsn, u8 *start, u8 *end, enum net80211_security_proto *secprot, enum net80211_crypto_alg *crypt)
 Detect crypto and AKM types from RSN information element.
u8sec80211_find_rsn (union ieee80211_ie *ie, void *ie_end, int *is_rsn, u8 **end)
 Find the RSN or WPA information element in the provided beacon frame.
int sec80211_install (struct net80211_crypto **which, enum net80211_crypto_alg crypt, const void *key, int len, const void *rsc)
 Install 802.11 cryptosystem.
u32 sec80211_rsn_get_crypto_desc (enum net80211_crypto_alg crypt, int rsnie)
 Determine RSN descriptor for specified net80211 cryptosystem number.
u32 sec80211_rsn_get_akm_desc (enum net80211_security_proto secprot, int rsnie)
 Determine RSN descriptor for specified net80211 handshaker number.
enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt (u32 desc)
 Determine net80211 cryptosystem number from RSN descriptor.


Detailed Description

Definitions for general secured-network routines.

Any function in this file which may be referenced by code which is not exclusive to encryption-enabled builds (e.g. sec80211_detect(), which is called by net80211_probe_step() to fill the net80211_wlan structure's security fields) must be declared as a weak symbol, using an inline interface similar to that used for sec80211_detect() below. This prevents secure network support from bloating general builds by any more than a few tiny hooks to call crypto functions when crypto structures are non-NULL.

Definition in file sec80211.h.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

int _sec80211_detect ( struct io_buffer iob,
enum net80211_security_proto secprot,
enum net80211_crypto_alg crypt 
)

Detect the cryptosystem and handshaking protocol used by an 802.11 network.

Parameters:
iob I/O buffer containing beacon frame
Return values:
secprot Security handshaking protocol used by network
crypt Cryptosystem used by network
rc Return status code
This function uses weak linkage, as it must be called from generic contexts but should only be linked in if some encryption is supported; you must test its address against NULL before calling it. If it does not exist, any network with the PRIVACY bit set in beacon->capab should be considered unknown.

Definition at line 391 of file sec80211.c.

References ieee80211_frame::data, io_buffer::data, DBG, DBG_HD, ieee80211_beacon, IEEE80211_CAPAB_PRIVACY, NET80211_CRYPT_NONE, NET80211_CRYPT_UNKNOWN, NET80211_CRYPT_WEP, NET80211_SECPROT_NONE, NET80211_SECPROT_UNKNOWN, sec80211_detect_ie(), sec80211_find_rsn(), io_buffer::tail, and u8.

Referenced by sec80211_detect().

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         /* Find RSN or WPA IE */
00405         if ( ! ( rsn = sec80211_find_rsn ( beacon->info_element, iob->tail,
00406                                            &is_rsn, &rsn_end ) ) ) {
00407                 /* No security IE at all; either WEP or no security. */
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         /* Determine type of security */
00419         if ( ( rc = sec80211_detect_ie ( is_rsn, rsn, rsn_end, secprot,
00420                                          crypt ) ) == 0 )
00421                 return 0;
00422 
00423         /* If we get here, the RSN IE was invalid */
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 }

static int sec80211_detect ( struct io_buffer iob,
enum net80211_security_proto secprot,
enum net80211_crypto_alg crypt 
) [inline, static]

Inline safety wrapper for _sec80211_detect().

Parameters:
iob I/O buffer containing beacon frame
Return values:
secprot Security handshaking protocol used by network
crypt Cryptosystem used by network
rc Return status code
This function transparently calls _sec80211_detect() if the file containing it was compiled in, or returns an error indication of -ENOTSUP if not.

Definition at line 59 of file sec80211.h.

References _sec80211_detect(), and ENOTSUP.

Referenced by net80211_probe_step().

00061                                                                       {
00062         if ( _sec80211_detect )
00063                 return _sec80211_detect ( iob, secprot, crypt );
00064         return -ENOTSUP;
00065 }

int sec80211_detect_ie ( int  is_rsn,
u8 start,
u8 end,
enum net80211_security_proto secprot,
enum net80211_crypto_alg crypt 
)

Detect crypto and AKM types from RSN information element.

Parameters:
is_rsn If TRUE, IE is a new-style RSN information element
start Pointer to first byte of version field
end Pointer to first byte not in the RSN IE
Return values:
secprot Security handshaking protocol used by network
crypt Cryptosystem used by network
rc Return status code
If the IE cannot be parsed, returns an error indication and leaves secprot and crypt unchanged.

Definition at line 325 of file sec80211.c.

References cr, DBG, EINVAL, NET80211_CRYPT_CCMP, NET80211_CRYPT_TKIP, NET80211_CRYPTOS, NET80211_HANDSHAKERS, NET80211_SECPROT_EAP, descriptor_map::net80211_type, rsn_pick_desc(), table_end, table_start, and u8.

Referenced by _sec80211_detect(), and wpa_handle_3_of_4().

00328 {
00329         enum net80211_security_proto sp;
00330         enum net80211_crypto_alg cr;
00331         struct descriptor_map *map;
00332         u8 *rsn = start;
00333 
00334         /* Set some defaults */
00335         cr = ( is_rsn ? NET80211_CRYPT_CCMP : NET80211_CRYPT_TKIP );
00336         sp = NET80211_SECPROT_EAP;
00337 
00338         rsn += 2;               /* version - already checked */
00339         rsn += 4;               /* group cipher - we don't use it here */
00340 
00341         if ( rsn >= end )
00342                 goto done;
00343 
00344         /* Pick crypto algorithm */
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         /* Pick handshaking algorithm */
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 }

u8* sec80211_find_rsn ( union ieee80211_ie ie,
void *  ie_end,
int *  is_rsn,
u8 **  end 
)

Find the RSN or WPA information element in the provided beacon frame.

Parameters:
ie Pointer to first information element to check
ie_end Pointer to end of information element space
Return values:
is_rsn TRUE if returned IE is RSN, FALSE if it's WPA
end Pointer to byte immediately after last byte of data
data Pointer to first byte of data (the `version' field)
If both an RSN and a WPA information element are found, this function will return the first one seen, which by ordering rules should always prefer the newer RSN IE.

If no RSN or WPA infomration element is found, returns NULL and leaves is_rsn and end in an undefined state.

This function will not return a pointer to an information element that states it extends past the tail of the io_buffer, or whose version field is incorrect.

Definition at line 268 of file sec80211.c.

References DBG, ieee80211_ie_bound(), IEEE80211_IE_RSN, IEEE80211_IE_VENDOR, ieee80211_next_ie(), IEEE80211_RSN_VERSION, IEEE80211_WPA_OUI_VEN, NULL, u16, and u8.

Referenced by _sec80211_detect(), wpa_handle_3_of_4(), wpa_make_rsn_ie(), and wpa_start().

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 }

int sec80211_install ( struct net80211_crypto **  which,
enum net80211_crypto_alg  crypt,
const void *  key,
int  len,
const void *  rsc 
)

Install 802.11 cryptosystem.

Parameters:
which Pointer to the cryptosystem structure to install in
crypt Cryptosystem ID number
key Encryption key to use
len Length of encryption key
rsc Initial receive sequence counter, if applicable
Return values:
rc Return status code
The encryption key will not be accessed via the provided pointer after this function returns, so you may keep it on the stack.

which must point to either dev->crypto (for the normal case of installing a unicast cryptosystem) or dev->gcrypto (to install a cryptosystem that will be used only for decrypting group-source frames).

Definition at line 98 of file sec80211.c.

References net80211_crypto::algorithm, DBG, ENOMEM, ENOTSUP, EUNIQ_10, for_each_table_entry, free(), net80211_crypto::init, memcpy, NET80211_CRYPT_NONE, NET80211_CRYPTOS, NULL, net80211_crypto::priv, net80211_crypto::priv_len, and zalloc().

Referenced by trivial_init(), wpa_install_gtk(), and wpa_install_ptk().

00101 {
00102         struct net80211_crypto *crypto = *which;
00103         struct net80211_crypto *tbl_crypto;
00104 
00105         /* Remove old crypto if it exists */
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         /* Find cryptosystem to use */
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 }

u32 sec80211_rsn_get_crypto_desc ( enum net80211_crypto_alg  crypt,
int  rsnie 
)

Determine RSN descriptor for specified net80211 cryptosystem number.

Parameters:
crypt Cryptosystem number
rsnie Whether to return a new-format (RSN IE) descriptor
Return values:
desc RSN descriptor
If rsnie is false, returns an old-format (WPA vendor IE) descriptor.

Definition at line 466 of file sec80211.c.

References rsn_get_desc().

Referenced by wpa_make_rsn_ie().

00467 {
00468         return rsn_get_desc ( crypt, rsnie, rsn_cipher_map );
00469 }

u32 sec80211_rsn_get_akm_desc ( enum net80211_security_proto  secprot,
int  rsnie 
)

Determine RSN descriptor for specified net80211 handshaker number.

Parameters:
secprot Handshaker number
rsnie Whether to return a new-format (RSN IE) descriptor
Return values:
desc RSN descriptor
If rsnie is false, returns an old-format (WPA vendor IE) descriptor.

Definition at line 481 of file sec80211.c.

References rsn_get_desc().

Referenced by wpa_make_rsn_ie().

00483 {
00484         return rsn_get_desc ( secprot, rsnie, rsn_akm_map );
00485 }

enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt ( u32  desc  ) 

Determine net80211 cryptosystem number from RSN descriptor.

Parameters:
desc RSN descriptor
Return values:
crypt net80211 cryptosystem enumeration value

Definition at line 493 of file sec80211.c.

References END_MAGIC, descriptor_map::net80211_type, descriptor_map::oui_type, and OUI_TYPE_MASK.

Referenced by wpa_handle_3_of_4(), and wpa_make_rsn_ie().

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 }


Generated on Tue Apr 6 20:01:52 2010 for gPXE by  doxygen 1.5.7.1