iPXE
Data Structures | Defines | Functions | Variables
wep.c File Reference

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

#include <ipxe/net80211.h>
#include <ipxe/sec80211.h>
#include <ipxe/crypto.h>
#include <ipxe/arc4.h>
#include <ipxe/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 48 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 51 of file wep.c.

#define WEP_ICV_LEN   4

Length of WEP ICV checksum.

Definition at line 54 of file wep.c.

Referenced by wep_decrypt(), and wep_encrypt().

#define WEP_MAX_KEY   16

Maximum length of WEP key.

Definition at line 57 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 60 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 63 of file wep.c.

#define WEP_OVERHEAD   8

Total WEP overhead bytes.

Definition at line 66 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:
crypto802.11 cryptographic algorithm
keyWEP key to use
keylenLength of WEP key
rscInitial receive sequence counter (unused)
Return values:
rcReturn 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 98 of file wep.c.

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

Referenced by trivial_change_key().

{
        struct wep_ctx *ctx = crypto->priv;

        ctx->keylen = ( keylen > WEP_MAX_KEY ? WEP_MAX_KEY : keylen );
        memcpy ( ctx->key + WEP_IV_LEN, key, ctx->keylen );

        return 0;
}
static struct io_buffer* wep_encrypt ( struct net80211_crypto crypto,
struct io_buffer iob 
) [static, read]

Encrypt packet using WEP.

Parameters:
crypto802.11 cryptographic algorithm
iobI/O buffer of plaintext packet
Return values:
eiobNewly allocated I/O buffer for encrypted packet, or NULL

If memory allocation fails, NULL is returned.

Definition at line 118 of file wep.c.

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

{
        struct wep_ctx *ctx = crypto->priv;
        struct io_buffer *eiob;
        struct ieee80211_frame *hdr;
        const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
        int datalen = iob_len ( iob ) - hdrlen;
        int newlen = hdrlen + datalen + WEP_OVERHEAD;
        u32 iv, icv;

        eiob = alloc_iob ( newlen );
        if ( ! eiob )
                return NULL;

        memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
        hdr = eiob->data;
        hdr->fc |= IEEE80211_FC_PROTECTED;

        /* Calculate IV, put it in the header (with key ID byte = 0), and
           set it up at the start of the encryption key. */
        iv = random() & 0xffffff; /* IV in bottom 3 bytes, top byte = KID = 0 */
        memcpy ( iob_put ( eiob, WEP_HEADER_LEN ), &iv, WEP_HEADER_LEN );
        memcpy ( ctx->key, &iv, WEP_IV_LEN );

        /* Encrypt the data using RC4 */
        cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key,
                        ctx->keylen + WEP_IV_LEN );
        cipher_encrypt ( &arc4_algorithm, &ctx->arc4, iob->data + hdrlen,
                         iob_put ( eiob, datalen ), datalen );

        /* Add ICV */
        icv = ~crc32_le ( ~0, iob->data + hdrlen, datalen );
        cipher_encrypt ( &arc4_algorithm, &ctx->arc4, &icv,
                         iob_put ( eiob, WEP_ICV_LEN ), WEP_ICV_LEN );

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

Decrypt packet using WEP.

Parameters:
crypto802.11 cryptographic algorithm
eiobI/O buffer of encrypted packet
Return values:
iobNewly 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 167 of file wep.c.

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

{
        struct wep_ctx *ctx = crypto->priv;
        struct io_buffer *iob;
        struct ieee80211_frame *hdr;
        const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
        int datalen = iob_len ( eiob ) - hdrlen - WEP_OVERHEAD;
        int newlen = hdrlen + datalen;
        u32 iv, icv, crc;

        iob = alloc_iob ( newlen );
        if ( ! iob )
                return NULL;

        memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
        hdr = iob->data;
        hdr->fc &= ~IEEE80211_FC_PROTECTED;

        /* Strip off IV and use it to initialize cryptosystem */
        memcpy ( &iv, eiob->data + hdrlen, 4 );
        iv &= 0xffffff;         /* ignore key ID byte */
        memcpy ( ctx->key, &iv, WEP_IV_LEN );

        /* Decrypt the data using RC4 */
        cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key,
                        ctx->keylen + WEP_IV_LEN );
        cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen +
                         WEP_HEADER_LEN, iob_put ( iob, datalen ), datalen );

        /* Strip off ICV and verify it */
        cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen +
                         WEP_HEADER_LEN + datalen, &icv, WEP_ICV_LEN );
        crc = ~crc32_le ( ~0, iob->data + hdrlen, datalen );
        if ( crc != icv ) {
                DBGC ( crypto, "WEP %p CRC mismatch: expect %08x, get %08x\n",
                       crypto, icv, crc );
                free_iob ( iob );
                return NULL;
        }
        return iob;
}
static int trivial_init ( struct net80211_device dev) [static]

Initialize trivial 802.11 security handshaker.

Parameters:
dev802.11 device
ctxSecurity 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 229 of file wep.c.

References net80211_device::associating, net80211_device::crypto, net80211_wlan::crypto, DBGC, EACCES, EINVAL, fetch_raw_setting(), key, len, NET80211_CRYPT_NONE, NET80211_CRYPT_WEP, net80211_device::netdev, netdev_settings(), NULL, rc, sec80211_install(), and WEP_MAX_KEY.

{
        u8 key[WEP_MAX_KEY];    /* support up to 128-bit keys */
        int len;
        int rc;

        if ( dev->associating &&
             dev->associating->crypto == NET80211_CRYPT_NONE )
                return 0;       /* no crypto? OK. */

        len = fetch_raw_setting ( netdev_settings ( dev->netdev ),
                                  &net80211_key_setting, key, WEP_MAX_KEY );

        if ( len <= 0 ) {
                DBGC ( dev, "802.11 %p cannot do WEP without a key\n", dev );
                return -EACCES;
        }

        /* Full 128-bit keys are a nonstandard extension, but they're
           utterly trivial to support, so we do. */
        if ( len != 5 && len != 13 && len != 16 ) {
                DBGC ( dev, "802.11 %p invalid WEP key length %d\n",
                       dev, len );
                return -EINVAL;
        }

        DBGC ( dev, "802.11 %p installing %d-bit WEP\n", dev, len * 8 );

        rc = sec80211_install ( &dev->crypto, NET80211_CRYPT_WEP, key, len,
                                NULL );
        if ( rc < 0 )
                return rc;

        return 0;
}
static int trivial_change_key ( struct net80211_device dev) [static]

Check for key change on trivial 802.11 security handshaker.

Parameters:
dev802.11 device
ctxSecurity handshaker

Definition at line 271 of file wep.c.

References net80211_device::crypto, EINVAL, fetch_raw_setting(), net80211_crypto::init, key, len, net80211_device::netdev, netdev_settings(), NULL, wep_init(), and WEP_MAX_KEY.

{
        u8 key[WEP_MAX_KEY];
        int len;
        int change = 0;

        /* If going from WEP to clear, or something else to WEP, reassociate. */
        if ( ! dev->crypto || ( dev->crypto->init != wep_init ) )
                change ^= 1;

        len = fetch_raw_setting ( netdev_settings ( dev->netdev ),
                                  &net80211_key_setting, key, WEP_MAX_KEY );
        if ( len <= 0 )
                change ^= 1;

        /* Changing crypto type => return nonzero to reassociate. */
        if ( change )
                return -EINVAL;

        /* Going from no crypto to still no crypto => nothing to do. */
        if ( len <= 0 )
                return 0;

        /* Otherwise, reinitialise WEP with new key. */
        return wep_init ( dev->crypto, key, len, NULL );
}

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 211 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 299 of file wep.c.