wep.c File Reference

The WEP wireless encryption method (insecure!). More...

#include <gpxe/net80211.h>
#include <gpxe/sec80211.h>
#include <gpxe/crypto.h>
#include <gpxe/arc4.h>
#include <gpxe/crc32.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

Go to the source code of this file.

Data Structures

struct  wep_ctx
 Context for WEP encryption and decryption. More...

Defines

#define WEP_IV_LEN   3
 Length of WEP initialisation vector.
#define WEP_KID_LEN   1
 Length of WEP key ID byte.
#define WEP_ICV_LEN   4
 Length of WEP ICV checksum.
#define WEP_MAX_KEY   16
 Maximum length of WEP key.
#define WEP_HEADER_LEN   4
 Amount of data placed before the encrypted bytes.
#define WEP_TRAILER_LEN   4
 Amount of data placed after the encrypted bytes.
#define WEP_OVERHEAD   8
 Total WEP overhead bytes.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static int wep_init (struct net80211_crypto *crypto, const void *key, int keylen, const void *rsc __unused)
 Initialize WEP algorithm.
static struct io_bufferwep_encrypt (struct net80211_crypto *crypto, struct io_buffer *iob)
 Encrypt packet using WEP.
static struct io_bufferwep_decrypt (struct net80211_crypto *crypto, struct io_buffer *eiob)
 Decrypt packet using WEP.
static int trivial_init (struct net80211_device *dev)
 Initialize trivial 802.11 security handshaker.
static int trivial_change_key (struct net80211_device *dev)
 Check for key change on trivial 802.11 security handshaker.

Variables

struct net80211_crypto wep_crypto __net80211_crypto
 WEP cryptosystem for 802.11.
struct net80211_handshaker
trivial_handshaker 
__net80211_handshaker
 Trivial 802.11 security handshaker.


Detailed Description

The WEP wireless encryption method (insecure!).

The data field in a WEP-encrypted packet contains a 3-byte initialisation vector, one-byte Key ID field (only the bottom two bits are ever used), encrypted data, and a 4-byte encrypted CRC of the plaintext data, called the ICV. To decrypt it, the IV is prepended to the shared key and the data stream (including ICV) is run through the ARC4 stream cipher; if the ICV matches a CRC32 calculated on the plaintext, the packet is valid.

For efficiency and code-size reasons, this file assumes it is running on a little-endian machine.

Definition in file wep.c.


Define Documentation

#define WEP_IV_LEN   3

Length of WEP initialisation vector.

Definition at line 47 of file wep.c.

Referenced by wep_decrypt(), wep_encrypt(), and wep_init().

#define WEP_KID_LEN   1

Length of WEP key ID byte.

Definition at line 50 of file wep.c.

#define WEP_ICV_LEN   4

Length of WEP ICV checksum.

Definition at line 53 of file wep.c.

Referenced by wep_decrypt(), and wep_encrypt().

#define WEP_MAX_KEY   16

Maximum length of WEP key.

Definition at line 56 of file wep.c.

Referenced by trivial_change_key(), trivial_init(), and wep_init().

#define WEP_HEADER_LEN   4

Amount of data placed before the encrypted bytes.

Definition at line 59 of file wep.c.

Referenced by wep_decrypt(), and wep_encrypt().

#define WEP_TRAILER_LEN   4

Amount of data placed after the encrypted bytes.

Definition at line 62 of file wep.c.

#define WEP_OVERHEAD   8

Total WEP overhead bytes.

Definition at line 65 of file wep.c.

Referenced by wep_decrypt(), and wep_encrypt().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static int wep_init ( struct net80211_crypto crypto,
const void *  key,
int  keylen,
const void *rsc  __unused 
) [static]

Initialize WEP algorithm.

Parameters:
crypto 802.11 cryptographic algorithm
key WEP key to use
keylen Length of WEP key
rsc Initial receive sequence counter (unused)
Return values:
rc Return status code
Standard key lengths are 5 and 13 bytes; 16-byte keys are occasionally supported as an extension to the standard.

Definition at line 97 of file wep.c.

References wep_ctx::key, wep_ctx::keylen, memcpy, net80211_crypto::priv, WEP_IV_LEN, and WEP_MAX_KEY.

Referenced by trivial_change_key().

00099 {
00100         struct wep_ctx *ctx = crypto->priv;
00101 
00102         ctx->keylen = ( keylen > WEP_MAX_KEY ? WEP_MAX_KEY : keylen );
00103         memcpy ( ctx->key + WEP_IV_LEN, key, ctx->keylen );
00104 
00105         return 0;
00106 }

static struct io_buffer* wep_encrypt ( struct net80211_crypto crypto,
struct io_buffer iob 
) [static, read]

Encrypt packet using WEP.

Parameters:
crypto 802.11 cryptographic algorithm
iob I/O buffer of plaintext packet
Return values:
eiob Newly allocated I/O buffer for encrypted packet, or NULL
If memory allocation fails, NULL is returned.

Definition at line 117 of file wep.c.

References alloc_iob(), wep_ctx::arc4, arc4_algorithm, cipher_encrypt, cipher_setkey(), crc32_le(), io_buffer::data, ieee80211_frame::fc, IEEE80211_FC_PROTECTED, IEEE80211_TYP_FRAME_HEADER_LEN, iob_len(), iob_put, wep_ctx::key, wep_ctx::keylen, memcpy, NULL, net80211_crypto::priv, random(), u32, WEP_HEADER_LEN, WEP_ICV_LEN, WEP_IV_LEN, and WEP_OVERHEAD.

00119 {
00120         struct wep_ctx *ctx = crypto->priv;
00121         struct io_buffer *eiob;
00122         struct ieee80211_frame *hdr;
00123         const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
00124         int datalen = iob_len ( iob ) - hdrlen;
00125         int newlen = hdrlen + datalen + WEP_OVERHEAD;
00126         u32 iv, icv;
00127 
00128         eiob = alloc_iob ( newlen );
00129         if ( ! eiob )
00130                 return NULL;
00131 
00132         memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
00133         hdr = eiob->data;
00134         hdr->fc |= IEEE80211_FC_PROTECTED;
00135 
00136         /* Calculate IV, put it in the header (with key ID byte = 0), and
00137            set it up at the start of the encryption key. */
00138         iv = random() & 0xffffff; /* IV in bottom 3 bytes, top byte = KID = 0 */
00139         memcpy ( iob_put ( eiob, WEP_HEADER_LEN ), &iv, WEP_HEADER_LEN );
00140         memcpy ( ctx->key, &iv, WEP_IV_LEN );
00141 
00142         /* Encrypt the data using RC4 */
00143         cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key,
00144                         ctx->keylen + WEP_IV_LEN );
00145         cipher_encrypt ( &arc4_algorithm, &ctx->arc4, iob->data + hdrlen,
00146                          iob_put ( eiob, datalen ), datalen );
00147 
00148         /* Add ICV */
00149         icv = ~crc32_le ( ~0, iob->data + hdrlen, datalen );
00150         cipher_encrypt ( &arc4_algorithm, &ctx->arc4, &icv,
00151                          iob_put ( eiob, WEP_ICV_LEN ), WEP_ICV_LEN );
00152 
00153         return eiob;
00154 }

static struct io_buffer* wep_decrypt ( struct net80211_crypto crypto,
struct io_buffer eiob 
) [static, read]

Decrypt packet using WEP.

Parameters:
crypto 802.11 cryptographic algorithm
eiob I/O buffer of encrypted packet
Return values:
iob Newly allocated I/O buffer for plaintext packet, or NULL
If a consistency check for the decryption fails (usually indicating an invalid key), NULL is returned.

Definition at line 166 of file wep.c.

References alloc_iob(), wep_ctx::arc4, arc4_algorithm, cipher_decrypt, cipher_setkey(), crc32_le(), io_buffer::data, DBGC, ieee80211_frame::fc, free_iob(), IEEE80211_FC_PROTECTED, IEEE80211_TYP_FRAME_HEADER_LEN, iob_len(), iob_put, wep_ctx::key, wep_ctx::keylen, memcpy, NULL, net80211_crypto::priv, u32, WEP_HEADER_LEN, WEP_ICV_LEN, WEP_IV_LEN, and WEP_OVERHEAD.

00168 {
00169         struct wep_ctx *ctx = crypto->priv;
00170         struct io_buffer *iob;
00171         struct ieee80211_frame *hdr;
00172         const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
00173         int datalen = iob_len ( eiob ) - hdrlen - WEP_OVERHEAD;
00174         int newlen = hdrlen + datalen;
00175         u32 iv, icv, crc;
00176 
00177         iob = alloc_iob ( newlen );
00178         if ( ! iob )
00179                 return NULL;
00180 
00181         memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
00182         hdr = iob->data;
00183         hdr->fc &= ~IEEE80211_FC_PROTECTED;
00184 
00185         /* Strip off IV and use it to initialize cryptosystem */
00186         memcpy ( &iv, eiob->data + hdrlen, 4 );
00187         iv &= 0xffffff;         /* ignore key ID byte */
00188         memcpy ( ctx->key, &iv, WEP_IV_LEN );
00189 
00190         /* Decrypt the data using RC4 */
00191         cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key,
00192                         ctx->keylen + WEP_IV_LEN );
00193         cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen +
00194                          WEP_HEADER_LEN, iob_put ( iob, datalen ), datalen );
00195 
00196         /* Strip off ICV and verify it */
00197         cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen +
00198                          WEP_HEADER_LEN + datalen, &icv, WEP_ICV_LEN );
00199         crc = ~crc32_le ( ~0, iob->data + hdrlen, datalen );
00200         if ( crc != icv ) {
00201                 DBGC ( crypto, "WEP %p CRC mismatch: expect %08x, get %08x\n",
00202                        crypto, icv, crc );
00203                 free_iob ( iob );
00204                 return NULL;
00205         }
00206         return iob;
00207 }

static int trivial_init ( struct net80211_device dev  )  [static]

Initialize trivial 802.11 security handshaker.

Parameters:
dev 802.11 device
ctx Security handshaker
This simply fetches a WEP key from netX/key, and if it exists, installs WEP cryptography on the 802.11 device. No real handshaking is performed.

Definition at line 228 of file wep.c.

References net80211_device::associating, net80211_device::crypto, net80211_wlan::crypto, DBGC, EACCES, EINVAL, fetch_setting(), wep_ctx::key, NET80211_CRYPT_NONE, NET80211_CRYPT_WEP, net80211_device::netdev, netdev_settings(), NULL, sec80211_install(), u8, and WEP_MAX_KEY.

00229 {
00230         u8 key[WEP_MAX_KEY];    /* support up to 128-bit keys */
00231         int len;
00232         int rc;
00233 
00234         if ( dev->associating &&
00235              dev->associating->crypto == NET80211_CRYPT_NONE )
00236                 return 0;       /* no crypto? OK. */
00237 
00238         len = fetch_setting ( netdev_settings ( dev->netdev ),
00239                               &net80211_key_setting, key, WEP_MAX_KEY );
00240 
00241         if ( len <= 0 ) {
00242                 DBGC ( dev, "802.11 %p cannot do WEP without a key\n", dev );
00243                 return -EACCES;
00244         }
00245 
00246         /* Full 128-bit keys are a nonstandard extension, but they're
00247            utterly trivial to support, so we do. */
00248         if ( len != 5 && len != 13 && len != 16 ) {
00249                 DBGC ( dev, "802.11 %p invalid WEP key length %d\n",
00250                        dev, len );
00251                 return -EINVAL;
00252         }
00253 
00254         DBGC ( dev, "802.11 %p installing %d-bit WEP\n", dev, len * 8 );
00255 
00256         rc = sec80211_install ( &dev->crypto, NET80211_CRYPT_WEP, key, len,
00257                                 NULL );
00258         if ( rc < 0 )
00259                 return rc;
00260 
00261         return 0;
00262 }

static int trivial_change_key ( struct net80211_device dev  )  [static]

Check for key change on trivial 802.11 security handshaker.

Parameters:
dev 802.11 device
ctx Security handshaker

Definition at line 270 of file wep.c.

References net80211_device::crypto, EINVAL, fetch_setting(), net80211_crypto::init, wep_ctx::key, net80211_device::netdev, netdev_settings(), NULL, u8, wep_init(), and WEP_MAX_KEY.

00271 {
00272         u8 key[WEP_MAX_KEY];
00273         int len;
00274         int change = 0;
00275 
00276         /* If going from WEP to clear, or something else to WEP, reassociate. */
00277         if ( ! dev->crypto || ( dev->crypto->init != wep_init ) )
00278                 change ^= 1;
00279 
00280         len = fetch_setting ( netdev_settings ( dev->netdev ),
00281                               &net80211_key_setting, key, WEP_MAX_KEY );
00282         if ( len <= 0 )
00283                 change ^= 1;
00284 
00285         /* Changing crypto type => return nonzero to reassociate. */
00286         if ( change )
00287                 return -EINVAL;
00288 
00289         /* Going from no crypto to still no crypto => nothing to do. */
00290         if ( len <= 0 )
00291                 return 0;
00292 
00293         /* Otherwise, reinitialise WEP with new key. */
00294         return wep_init ( dev->crypto, key, len, NULL );
00295 }


Variable Documentation

Initial value:

 {
        .algorithm = NET80211_CRYPT_WEP,
        .init = wep_init,
        .encrypt = wep_encrypt,
        .decrypt = wep_decrypt,
        .priv_len = sizeof ( struct wep_ctx ),
}
WEP cryptosystem for 802.11.

Definition at line 210 of file wep.c.

struct net80211_handshaker trivial_handshaker __net80211_handshaker

Initial value:

 {
        .protocol = NET80211_SECPROT_NONE,
        .init = trivial_init,
        .change_key = trivial_change_key,
        .priv_len = 0,
}
Trivial 802.11 security handshaker.

Definition at line 298 of file wep.c.


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