iPXE
sec80211.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  */
00019 
00020 FILE_LICENCE ( GPL2_OR_LATER );
00021 
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <errno.h>
00025 #include <ipxe/ieee80211.h>
00026 #include <ipxe/net80211.h>
00027 #include <ipxe/sec80211.h>
00028 
00029 /** @file
00030  *
00031  * General secured-network routines required whenever any secure
00032  * network support at all is compiled in. This involves things like
00033  * installing keys, determining the type of security used by a probed
00034  * network, and some small helper functions that take advantage of
00035  * static data in this file.
00036  */
00037 
00038 /* Unsupported cryptosystem error numbers */
00039 #define ENOTSUP_WEP __einfo_error ( EINFO_ENOTSUP_WEP )
00040 #define EINFO_ENOTSUP_WEP __einfo_uniqify ( EINFO_ENOTSUP, \
00041         ( 0x10 | NET80211_CRYPT_WEP ), "WEP not supported" )
00042 #define ENOTSUP_TKIP __einfo_error ( EINFO_ENOTSUP_TKIP )
00043 #define EINFO_ENOTSUP_TKIP __einfo_uniqify ( EINFO_ENOTSUP, \
00044         ( 0x10 | NET80211_CRYPT_TKIP ), "TKIP not supported" )
00045 #define ENOTSUP_CCMP __einfo_error ( EINFO_ENOTSUP_CCMP )
00046 #define EINFO_ENOTSUP_CCMP __einfo_uniqify ( EINFO_ENOTSUP, \
00047         ( 0x10 | NET80211_CRYPT_CCMP ), "CCMP not supported" )
00048 #define ENOTSUP_CRYPT( crypt )                     \
00049         EUNIQ ( EINFO_ENOTSUP, ( 0x10 | (crypt) ), \
00050                 ENOTSUP_WEP, ENOTSUP_TKIP, ENOTSUP_CCMP )
00051 
00052 /** Mapping from net80211 crypto/secprot types to RSN OUI descriptors */
00053 struct descriptor_map {
00054         /** Value of net80211_crypto_alg or net80211_security_proto */
00055         u32 net80211_type;
00056 
00057         /** OUI+type in appropriate byte order, masked to exclude vendor */
00058         u32 oui_type;
00059 };
00060 
00061 /** Magic number in @a oui_type showing end of list */
00062 #define END_MAGIC       0xFFFFFFFF
00063 
00064 /** Mapping between net80211 cryptosystems and 802.11i cipher IDs */
00065 static struct descriptor_map rsn_cipher_map[] = {
00066         { .net80211_type = NET80211_CRYPT_WEP,
00067           .oui_type = IEEE80211_RSN_CTYPE_WEP40 },
00068 
00069         { .net80211_type = NET80211_CRYPT_WEP,
00070           .oui_type = IEEE80211_RSN_CTYPE_WEP104 },
00071 
00072         { .net80211_type = NET80211_CRYPT_TKIP,
00073           .oui_type = IEEE80211_RSN_CTYPE_TKIP },
00074 
00075         { .net80211_type = NET80211_CRYPT_CCMP,
00076           .oui_type = IEEE80211_RSN_CTYPE_CCMP },
00077 
00078         { .net80211_type = NET80211_CRYPT_UNKNOWN,
00079           .oui_type = END_MAGIC },
00080 };
00081 
00082 /** Mapping between net80211 handshakers and 802.11i AKM IDs */
00083 static struct descriptor_map rsn_akm_map[] = {
00084         { .net80211_type = NET80211_SECPROT_EAP,
00085           .oui_type = IEEE80211_RSN_ATYPE_8021X },
00086 
00087         { .net80211_type = NET80211_SECPROT_PSK,
00088           .oui_type = IEEE80211_RSN_ATYPE_PSK },
00089 
00090         { .net80211_type = NET80211_SECPROT_UNKNOWN,
00091           .oui_type = END_MAGIC },
00092 };
00093 
00094 
00095 /**
00096  * Install 802.11 cryptosystem
00097  *
00098  * @v which     Pointer to the cryptosystem structure to install in
00099  * @v crypt     Cryptosystem ID number
00100  * @v key       Encryption key to use
00101  * @v len       Length of encryption key
00102  * @v rsc       Initial receive sequence counter, if applicable
00103  * @ret rc      Return status code
00104  *
00105  * The encryption key will not be accessed via the provided pointer
00106  * after this function returns, so you may keep it on the stack.
00107  *
00108  * @a which must point to either @c dev->crypto (for the normal case
00109  * of installing a unicast cryptosystem) or @c dev->gcrypto (to
00110  * install a cryptosystem that will be used only for decrypting
00111  * group-source frames).
00112  */
00113 int sec80211_install ( struct net80211_crypto **which,
00114                        enum net80211_crypto_alg crypt,
00115                        const void *key, int len, const void *rsc )
00116 {
00117         struct net80211_crypto *crypto = *which;
00118         struct net80211_crypto *tbl_crypto;
00119 
00120         /* Remove old crypto if it exists */
00121         free ( *which );
00122         *which = NULL;
00123 
00124         if ( crypt == NET80211_CRYPT_NONE ) {
00125                 DBG ( "802.11-Sec not installing null cryptography\n" );
00126                 return 0;
00127         }
00128 
00129         /* Find cryptosystem to use */
00130         for_each_table_entry ( tbl_crypto, NET80211_CRYPTOS ) {
00131                 if ( tbl_crypto->algorithm == crypt ) {
00132                         crypto = zalloc ( sizeof ( *crypto ) +
00133                                           tbl_crypto->priv_len );
00134                         if ( ! crypto ) {
00135                                 DBG ( "802.11-Sec out of memory\n" );
00136                                 return -ENOMEM;
00137                         }
00138 
00139                         memcpy ( crypto, tbl_crypto, sizeof ( *crypto ) );
00140                         crypto->priv = ( ( void * ) crypto +
00141                                          sizeof ( *crypto ) );
00142                         break;
00143                 }
00144         }
00145 
00146         if ( ! crypto ) {
00147                 DBG ( "802.11-Sec no support for cryptosystem %d\n", crypt );
00148                 return -ENOTSUP_CRYPT ( crypt );
00149         }
00150 
00151         *which = crypto;
00152 
00153         DBG ( "802.11-Sec installing cryptosystem %d as %p with key of "
00154               "length %d\n", crypt, crypto, len );
00155 
00156         return crypto->init ( crypto, key, len, rsc );
00157 }
00158 
00159 
00160 /**
00161  * Determine net80211 crypto or handshaking type value to return for RSN info
00162  *
00163  * @v rsnp              Pointer to next descriptor count field in RSN IE
00164  * @v rsn_end           Pointer to end of RSN IE
00165  * @v map               Descriptor map to use
00166  * @v tbl_start         Start of linker table to examine for iPXE support
00167  * @v tbl_end           End of linker table to examine for iPXE support
00168  * @ret rsnp            Updated to point to first byte after descriptors
00169  * @ret map_ent         Descriptor map entry of translation to use
00170  *
00171  * The entries in the linker table must be either net80211_crypto or
00172  * net80211_handshaker structures, and @a tbl_stride must be set to
00173  * sizeof() the appropriate one.
00174  *
00175  * This function expects @a rsnp to point at a two-byte descriptor
00176  * count followed by a list of four-byte cipher or AKM descriptors; it
00177  * will return @c NULL if the input packet is malformed, and otherwise
00178  * set @a rsnp to the first byte it has not looked at. It will return
00179  * the first cipher in the list that is supported by the current build
00180  * of iPXE, or the first of all if none are supported.
00181  *
00182  * We play rather fast and loose with type checking, because this
00183  * function is only called from two well-defined places in the
00184  * RSN-checking code. Don't try to use it for anything else.
00185  */
00186 static struct descriptor_map * rsn_pick_desc ( u8 **rsnp, u8 *rsn_end,
00187                                                struct descriptor_map *map,
00188                                                void *tbl_start, void *tbl_end )
00189 {
00190         int ndesc;
00191         int ok = 0;
00192         struct descriptor_map *map_ent, *map_ret = NULL;
00193         u8 *rsn = *rsnp;
00194         void *tblp;
00195         size_t tbl_stride = ( map == rsn_cipher_map ?
00196                               sizeof ( struct net80211_crypto ) :
00197                               sizeof ( struct net80211_handshaker ) );
00198 
00199         if ( map != rsn_cipher_map && map != rsn_akm_map )
00200                 return NULL;
00201 
00202         /* Determine which types we support */
00203         for ( tblp = tbl_start; tblp < tbl_end; tblp += tbl_stride ) {
00204                 struct net80211_crypto *crypto = tblp;
00205                 struct net80211_handshaker *hs = tblp;
00206 
00207                 if ( map == rsn_cipher_map )
00208                         ok |= ( 1 << crypto->algorithm );
00209                 else
00210                         ok |= ( 1 << hs->protocol );
00211         }
00212 
00213         /* RSN sanity checks */
00214         if ( rsn + 2 > rsn_end ) {
00215                 DBG ( "RSN detect: malformed descriptor count\n" );
00216                 return NULL;
00217         }
00218 
00219         ndesc = *( u16 * ) rsn;
00220         rsn += 2;
00221 
00222         if ( ! ndesc ) {
00223                 DBG ( "RSN detect: no descriptors\n" );
00224                 return NULL;
00225         }
00226 
00227         /* Determine which net80211 crypto types are listed */
00228         while ( ndesc-- ) {
00229                 u32 desc;
00230 
00231                 if ( rsn + 4 > rsn_end ) {
00232                         DBG ( "RSN detect: malformed descriptor (%d left)\n",
00233                               ndesc );
00234                         return NULL;
00235                 }
00236 
00237                 desc = *( u32 * ) rsn;
00238                 rsn += 4;
00239 
00240                 for ( map_ent = map; map_ent->oui_type != END_MAGIC; map_ent++ )
00241                         if ( map_ent->oui_type == ( desc & OUI_TYPE_MASK ) )
00242                                 break;
00243 
00244                 /* Use first cipher as a fallback */
00245                 if ( ! map_ret )
00246                         map_ret = map_ent;
00247 
00248                 /* Once we find one we support, use it */
00249                 if ( ok & ( 1 << map_ent->net80211_type ) ) {
00250                         map_ret = map_ent;
00251                         break;
00252                 }
00253         }
00254 
00255         if ( ndesc > 0 )
00256                 rsn += 4 * ndesc;
00257 
00258         *rsnp = rsn;
00259         return map_ret;
00260 }
00261 
00262 
00263 /**
00264  * Find the RSN or WPA information element in the provided beacon frame
00265  *
00266  * @v ie        Pointer to first information element to check
00267  * @v ie_end    Pointer to end of information element space
00268  * @ret is_rsn  TRUE if returned IE is RSN, FALSE if it's WPA
00269  * @ret end     Pointer to byte immediately after last byte of data
00270  * @ret data    Pointer to first byte of data (the `version' field)
00271  *
00272  * If both an RSN and a WPA information element are found, this
00273  * function will return the first one seen, which by ordering rules
00274  * should always prefer the newer RSN IE.
00275  *
00276  * If no RSN or WPA infomration element is found, returns @c NULL and
00277  * leaves @a is_rsn and @a end in an undefined state.
00278  *
00279  * This function will not return a pointer to an information element
00280  * that states it extends past the tail of the io_buffer, or whose @a
00281  * version field is incorrect.
00282  */
00283 u8 * sec80211_find_rsn ( union ieee80211_ie *ie, void *ie_end,
00284                          int *is_rsn, u8 **end )
00285 {
00286         u8 *rsn = NULL;
00287 
00288         if ( ! ieee80211_ie_bound ( ie, ie_end ) )
00289                 return NULL;
00290 
00291         while ( ie ) {
00292                 if ( ie->id == IEEE80211_IE_VENDOR &&
00293                      ie->vendor.oui == IEEE80211_WPA_OUI_VEN ) {
00294                         DBG ( "RSN detect: old-style WPA IE found\n" );
00295                         rsn = &ie->vendor.data[0];
00296                         *end = rsn + ie->len - 4;
00297                         *is_rsn = 0;
00298                 } else if ( ie->id == IEEE80211_IE_RSN ) {
00299                         DBG ( "RSN detect: 802.11i RSN IE found\n" );
00300                         rsn = ( u8 * ) &ie->rsn.version;
00301                         *end = rsn + ie->len;
00302                         *is_rsn = 1;
00303                 }
00304 
00305                 if ( rsn && ( *end > ( u8 * ) ie_end || rsn >= *end ||
00306                               *( u16 * ) rsn != IEEE80211_RSN_VERSION ) ) {
00307                         DBG ( "RSN detect: malformed RSN IE or unknown "
00308                               "version, keep trying\n" );
00309                         rsn = NULL;
00310                 }
00311 
00312                 if ( rsn )
00313                         break;
00314 
00315                 ie = ieee80211_next_ie ( ie, ie_end );
00316         }
00317 
00318         if ( ! ie ) {
00319                 DBG ( "RSN detect: no RSN IE found\n" );
00320                 return NULL;
00321         }
00322 
00323         return rsn;
00324 }
00325 
00326 
00327 /**
00328  * Detect crypto and AKM types from RSN information element
00329  *
00330  * @v is_rsn    If TRUE, IE is a new-style RSN information element
00331  * @v start     Pointer to first byte of @a version field
00332  * @v end       Pointer to first byte not in the RSN IE
00333  * @ret secprot Security handshaking protocol used by network
00334  * @ret crypt   Cryptosystem used by network
00335  * @ret rc      Return status code
00336  *
00337  * If the IE cannot be parsed, returns an error indication and leaves
00338  * @a secprot and @a crypt unchanged.
00339  */
00340 int sec80211_detect_ie ( int is_rsn, u8 *start, u8 *end,
00341                          enum net80211_security_proto *secprot,
00342                          enum net80211_crypto_alg *crypt )
00343 {
00344         enum net80211_security_proto sp;
00345         enum net80211_crypto_alg cr;
00346         struct descriptor_map *map;
00347         u8 *rsn = start;
00348 
00349         /* Set some defaults */
00350         cr = ( is_rsn ? NET80211_CRYPT_CCMP : NET80211_CRYPT_TKIP );
00351         sp = NET80211_SECPROT_EAP;
00352 
00353         rsn += 2;               /* version - already checked */
00354         rsn += 4;               /* group cipher - we don't use it here */
00355 
00356         if ( rsn >= end )
00357                 goto done;
00358 
00359         /* Pick crypto algorithm */
00360         map = rsn_pick_desc ( &rsn, end, rsn_cipher_map,
00361                               table_start ( NET80211_CRYPTOS ),
00362                               table_end ( NET80211_CRYPTOS ) );
00363         if ( ! map )
00364                 goto invalid_rsn;
00365 
00366         cr = map->net80211_type;
00367 
00368         if ( rsn >= end )
00369                 goto done;
00370 
00371         /* Pick handshaking algorithm */
00372         map = rsn_pick_desc ( &rsn, end, rsn_akm_map,
00373                               table_start ( NET80211_HANDSHAKERS ),
00374                               table_end ( NET80211_HANDSHAKERS ) );
00375         if ( ! map )
00376                 goto invalid_rsn;
00377 
00378         sp = map->net80211_type;
00379 
00380  done:
00381         DBG ( "RSN detect: OK, crypto type %d, secprot type %d\n", cr, sp );
00382         *secprot = sp;
00383         *crypt = cr;
00384         return 0;
00385 
00386  invalid_rsn:
00387         DBG ( "RSN detect: invalid RSN IE\n" );
00388         return -EINVAL;
00389 }
00390 
00391 
00392 /**
00393  * Detect the cryptosystem and handshaking protocol used by an 802.11 network
00394  *
00395  * @v iob       I/O buffer containing beacon frame
00396  * @ret secprot Security handshaking protocol used by network
00397  * @ret crypt   Cryptosystem used by network
00398  * @ret rc      Return status code
00399  *
00400  * This function uses weak linkage, as it must be called from generic
00401  * contexts but should only be linked in if some encryption is
00402  * supported; you must test its address against @c NULL before calling
00403  * it. If it does not exist, any network with the PRIVACY bit set in
00404  * beacon->capab should be considered unknown.
00405  */
00406 int sec80211_detect ( struct io_buffer *iob,
00407                       enum net80211_security_proto *secprot,
00408                       enum net80211_crypto_alg *crypt )
00409 {
00410         struct ieee80211_frame *hdr = iob->data;
00411         struct ieee80211_beacon *beacon =
00412                 ( struct ieee80211_beacon * ) hdr->data;
00413         u8 *rsn, *rsn_end;
00414         int is_rsn, rc;
00415 
00416         *crypt = NET80211_CRYPT_UNKNOWN;
00417         *secprot = NET80211_SECPROT_UNKNOWN;
00418 
00419         /* Find RSN or WPA IE */
00420         if ( ! ( rsn = sec80211_find_rsn ( beacon->info_element, iob->tail,
00421                                            &is_rsn, &rsn_end ) ) ) {
00422                 /* No security IE at all; either WEP or no security. */
00423                 *secprot = NET80211_SECPROT_NONE;
00424 
00425                 if ( beacon->capability & IEEE80211_CAPAB_PRIVACY )
00426                         *crypt = NET80211_CRYPT_WEP;
00427                 else
00428                         *crypt = NET80211_CRYPT_NONE;
00429 
00430                 return 0;
00431         }
00432 
00433         /* Determine type of security */
00434         if ( ( rc = sec80211_detect_ie ( is_rsn, rsn, rsn_end, secprot,
00435                                          crypt ) ) == 0 )
00436                 return 0;
00437 
00438         /* If we get here, the RSN IE was invalid */
00439 
00440         *crypt = NET80211_CRYPT_UNKNOWN;
00441         *secprot = NET80211_SECPROT_UNKNOWN;
00442         DBG ( "Failed to handle RSN IE:\n" );
00443         DBG_HD ( rsn, rsn_end - rsn );
00444         return rc;
00445 }
00446 
00447 
00448 /**
00449  * Determine RSN descriptor for specified net80211 ID
00450  *
00451  * @v id        net80211 ID value
00452  * @v rsnie     Whether to return a new-format (RSN IE) descriptor
00453  * @v map       Map to use in translation
00454  * @ret desc    RSN descriptor, or 0 on error
00455  *
00456  * If @a rsnie is false, returns an old-format (WPA vendor IE)
00457  * descriptor.
00458  */
00459 static u32 rsn_get_desc ( unsigned id, int rsnie, struct descriptor_map *map )
00460 {
00461         u32 vendor = ( rsnie ? IEEE80211_RSN_OUI : IEEE80211_WPA_OUI );
00462 
00463         for ( ; map->oui_type != END_MAGIC; map++ ) {
00464                 if ( map->net80211_type == id )
00465                         return map->oui_type | vendor;
00466         }
00467 
00468         return 0;
00469 }
00470 
00471 /**
00472  * Determine RSN descriptor for specified net80211 cryptosystem number
00473  *
00474  * @v crypt     Cryptosystem number
00475  * @v rsnie     Whether to return a new-format (RSN IE) descriptor
00476  * @ret desc    RSN descriptor
00477  *
00478  * If @a rsnie is false, returns an old-format (WPA vendor IE)
00479  * descriptor.
00480  */
00481 u32 sec80211_rsn_get_crypto_desc ( enum net80211_crypto_alg crypt, int rsnie )
00482 {
00483         return rsn_get_desc ( crypt, rsnie, rsn_cipher_map );
00484 }
00485 
00486 /**
00487  * Determine RSN descriptor for specified net80211 handshaker number
00488  *
00489  * @v secprot   Handshaker number
00490  * @v rsnie     Whether to return a new-format (RSN IE) descriptor
00491  * @ret desc    RSN descriptor
00492  *
00493  * If @a rsnie is false, returns an old-format (WPA vendor IE)
00494  * descriptor.
00495  */
00496 u32 sec80211_rsn_get_akm_desc ( enum net80211_security_proto secprot,
00497                                 int rsnie )
00498 {
00499         return rsn_get_desc ( secprot, rsnie, rsn_akm_map );
00500 }
00501 
00502 /**
00503  * Determine net80211 cryptosystem number from RSN descriptor
00504  *
00505  * @v desc      RSN descriptor
00506  * @ret crypt   net80211 cryptosystem enumeration value
00507  */
00508 enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt ( u32 desc )
00509 {
00510         struct descriptor_map *map = rsn_cipher_map;
00511 
00512         for ( ; map->oui_type != END_MAGIC; map++ ) {
00513                 if ( map->oui_type == ( desc & OUI_TYPE_MASK ) )
00514                         break;
00515         }
00516 
00517         return map->net80211_type;
00518 }