iPXE
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...

Macros

#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)
 FILE_SECBOOT (FORBIDDEN)
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.

Macro Definition Documentation

◆ WEP_IV_LEN

#define WEP_IV_LEN   3

Length of WEP initialisation vector.

Definition at line 49 of file wep.c.

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

◆ WEP_KID_LEN

#define WEP_KID_LEN   1

Length of WEP key ID byte.

Definition at line 52 of file wep.c.

◆ WEP_ICV_LEN

#define WEP_ICV_LEN   4

Length of WEP ICV checksum.

Definition at line 55 of file wep.c.

Referenced by wep_decrypt(), and wep_encrypt().

◆ WEP_MAX_KEY

#define WEP_MAX_KEY   16

Maximum length of WEP key.

Definition at line 58 of file wep.c.

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

◆ WEP_HEADER_LEN

#define WEP_HEADER_LEN   4

Amount of data placed before the encrypted bytes.

Definition at line 61 of file wep.c.

Referenced by wep_decrypt(), and wep_encrypt().

◆ WEP_TRAILER_LEN

#define WEP_TRAILER_LEN   4

Amount of data placed after the encrypted bytes.

Definition at line 64 of file wep.c.

◆ WEP_OVERHEAD

#define WEP_OVERHEAD   8

Total WEP overhead bytes.

Definition at line 67 of file wep.c.

Referenced by wep_decrypt(), and wep_encrypt().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER )

◆ FILE_SECBOOT()

FILE_SECBOOT ( FORBIDDEN )

◆ wep_init()

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

101{
102 struct wep_ctx *ctx = crypto->priv;
103
104 ctx->keylen = ( keylen > WEP_MAX_KEY ? WEP_MAX_KEY : keylen );
105 memcpy ( ctx->key + WEP_IV_LEN, key, ctx->keylen );
106
107 return 0;
108}
union @162305117151260234136356364136041353210355154177 key
Sense key.
Definition scsi.h:3
struct golan_eq_context ctx
Definition CIB_PRM.h:0
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * priv
Private data for the algorithm to store key and state info.
Definition net80211.h:766
Context for WEP encryption and decryption.
Definition wep.c:71
int keylen
Length of WEP key (not including IV bytes)
Definition wep.c:81
#define WEP_IV_LEN
Length of WEP initialisation vector.
Definition wep.c:49
#define WEP_MAX_KEY
Maximum length of WEP key.
Definition wep.c:58

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

Referenced by trivial_change_key().

◆ wep_encrypt()

struct io_buffer * wep_encrypt ( struct net80211_crypto * crypto,
struct io_buffer * iob )
static

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

121{
122 struct wep_ctx *ctx = crypto->priv;
123 struct io_buffer *eiob;
124 struct ieee80211_frame *hdr;
125 const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
126 int datalen = iob_len ( iob ) - hdrlen;
127 int newlen = hdrlen + datalen + WEP_OVERHEAD;
128 u32 iv, icv;
129
130 eiob = alloc_iob ( newlen );
131 if ( ! eiob )
132 return NULL;
133
134 memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
135 hdr = eiob->data;
137
138 /* Calculate IV, put it in the header (with key ID byte = 0), and
139 set it up at the start of the encryption key. */
140 iv = random() & 0xffffff; /* IV in bottom 3 bytes, top byte = KID = 0 */
142 memcpy ( ctx->key, &iv, WEP_IV_LEN );
143
144 /* Encrypt the data using RC4 */
145 cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key,
146 ctx->keylen + WEP_IV_LEN );
147 cipher_encrypt ( &arc4_algorithm, &ctx->arc4, iob->data + hdrlen,
148 iob_put ( eiob, datalen ), datalen );
149
150 /* Add ICV */
151 icv = ~crc32_le ( ~0, iob->data + hdrlen, datalen );
152 cipher_encrypt ( &arc4_algorithm, &ctx->arc4, &icv,
153 iob_put ( eiob, WEP_ICV_LEN ), WEP_ICV_LEN );
154
155 return eiob;
156}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct golan_inbox_hdr hdr
Message header.
Definition CIB_PRM.h:0
struct cipher_algorithm arc4_algorithm
Definition arc4.c:118
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition crc32.c:40
#define IEEE80211_FC_PROTECTED
802.11 Frame Control field: Protected flag
Definition ieee80211.h:264
#define IEEE80211_TYP_FRAME_HEADER_LEN
Frame header length for frames we might work with.
Definition ieee80211.h:60
static int cipher_setkey(struct cipher_algorithm *cipher, void *ctx, const void *key, size_t keylen)
Definition crypto.h:235
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition crypto.h:251
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
#define iob_put(iobuf, len)
Definition iobuf.h:125
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
An 802.11 data or management frame without QoS or WDS header fields.
Definition ieee80211.h:301
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
#define u32
Definition vga.h:21
#define WEP_HEADER_LEN
Amount of data placed before the encrypted bytes.
Definition wep.c:61
#define WEP_ICV_LEN
Length of WEP ICV checksum.
Definition wep.c:55
#define WEP_OVERHEAD
Total WEP overhead bytes.
Definition wep.c:67
u16 datalen
Length of the data field in bytes, network byte order.
Definition wpa.h:57
u8 iv[16]
Initialization vector.
Definition wpa.h:33

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

◆ wep_decrypt()

struct io_buffer * wep_decrypt ( struct net80211_crypto * crypto,
struct io_buffer * eiob )
static

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

170{
171 struct wep_ctx *ctx = crypto->priv;
172 struct io_buffer *iob;
173 struct ieee80211_frame *hdr;
174 const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
175 int datalen = iob_len ( eiob ) - hdrlen - WEP_OVERHEAD;
176 int newlen = hdrlen + datalen;
177 u32 iv, icv, crc;
178
179 iob = alloc_iob ( newlen );
180 if ( ! iob )
181 return NULL;
182
183 memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
184 hdr = iob->data;
186
187 /* Strip off IV and use it to initialize cryptosystem */
188 memcpy ( &iv, eiob->data + hdrlen, 4 );
189 iv &= 0xffffff; /* ignore key ID byte */
190 memcpy ( ctx->key, &iv, WEP_IV_LEN );
191
192 /* Decrypt the data using RC4 */
193 cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key,
194 ctx->keylen + WEP_IV_LEN );
195 cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen +
197
198 /* Strip off ICV and verify it */
199 cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen +
201 crc = ~crc32_le ( ~0, iob->data + hdrlen, datalen );
202 if ( crc != icv ) {
203 DBGC ( crypto, "WEP %p CRC mismatch: expect %08x, get %08x\n",
204 crypto, icv, crc );
205 free_iob ( iob );
206 return NULL;
207 }
208 return iob;
209}
#define DBGC(...)
Definition compiler.h:505
#define cipher_decrypt(cipher, ctx, src, dst, len)
Definition crypto.h:261
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153

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

◆ trivial_init()

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

231{
232 u8 key[WEP_MAX_KEY]; /* support up to 128-bit keys */
233 int len;
234 int rc;
235
236 if ( dev->associating &&
238 return 0; /* no crypto? OK. */
239
241 &net80211_key_setting, key, WEP_MAX_KEY );
242
243 if ( len <= 0 ) {
244 DBGC ( dev, "802.11 %p cannot do WEP without a key\n", dev );
245 return -EACCES;
246 }
247
248 /* Full 128-bit keys are a nonstandard extension, but they're
249 utterly trivial to support, so we do. */
250 if ( len != 5 && len != 13 && len != 16 ) {
251 DBGC ( dev, "802.11 %p invalid WEP key length %d\n",
252 dev, len );
253 return -EINVAL;
254 }
255
256 DBGC ( dev, "802.11 %p installing %d-bit WEP\n", dev, len * 8 );
257
259 NULL );
260 if ( rc < 0 )
261 return rc;
262
263 return 0;
264}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
ring len
Length.
Definition dwmac.h:226
#define EINVAL
Invalid argument.
Definition errno.h:429
#define EACCES
Permission denied.
Definition errno.h:299
#define u8
Definition igbvf_osdep.h:40
@ NET80211_CRYPT_NONE
No security, an "Open" network.
Definition net80211.h:131
@ NET80211_CRYPT_WEP
Network protected with WEP (awful RC4-based system)
Definition net80211.h:145
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition netdevice.h:587
int sec80211_install(struct net80211_crypto **which, enum net80211_crypto_alg crypt, const void *key, int len, const void *rsc)
Install 802.11 cryptosystem.
Definition sec80211.c:114
int fetch_raw_setting(struct settings *settings, const struct setting *setting, void *data, size_t len)
Fetch value of setting.
Definition settings.c:804
struct net_device * netdev
The net_device that wraps us.
Definition net80211.h:789
struct net80211_crypto * crypto
802.11 cryptosystem for our current network
Definition net80211.h:940
struct net80211_wlan * associating
Network with which we are associating.
Definition net80211.h:866
enum net80211_crypto_alg crypto
Cryptographic algorithm used on the network.
Definition net80211.h:1087

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(), u8, and WEP_MAX_KEY.

◆ trivial_change_key()

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

273{
275 int len;
276 int change = 0;
277
278 /* If going from WEP to clear, or something else to WEP, reassociate. */
279 if ( ! dev->crypto || ( dev->crypto->init != wep_init ) )
280 change ^= 1;
281
283 &net80211_key_setting, key, WEP_MAX_KEY );
284 if ( len <= 0 )
285 change ^= 1;
286
287 /* Changing crypto type => return nonzero to reassociate. */
288 if ( change )
289 return -EINVAL;
290
291 /* Going from no crypto to still no crypto => nothing to do. */
292 if ( len <= 0 )
293 return 0;
294
295 /* Otherwise, reinitialise WEP with new key. */
296 return wep_init ( dev->crypto, key, len, NULL );
297}
int(* init)(struct net80211_crypto *crypto, const void *key, int keylen, const void *rsc)
Initialize cryptosystem using a given key.
Definition net80211.h:707
static int wep_init(struct net80211_crypto *crypto, const void *key, int keylen, const void *rsc __unused)
Initialize WEP algorithm.
Definition wep.c:99

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

Variable Documentation

◆ __net80211_crypto

struct net80211_crypto wep_crypto __net80211_crypto
Initial value:
= {
.algorithm = NET80211_CRYPT_WEP,
.init = wep_init,
.encrypt = wep_encrypt,
.decrypt = wep_decrypt,
.priv_len = sizeof ( struct wep_ctx ),
}
static struct io_buffer * wep_encrypt(struct net80211_crypto *crypto, struct io_buffer *iob)
Encrypt packet using WEP.
Definition wep.c:119
static struct io_buffer * wep_decrypt(struct net80211_crypto *crypto, struct io_buffer *eiob)
Decrypt packet using WEP.
Definition wep.c:168

WEP cryptosystem for 802.11.

Definition at line 212 of file wep.c.

212 {
213 .algorithm = NET80211_CRYPT_WEP,
214 .init = wep_init,
215 .encrypt = wep_encrypt,
216 .decrypt = wep_decrypt,
217 .priv_len = sizeof ( struct wep_ctx ),
218};

◆ __net80211_handshaker

struct net80211_handshaker trivial_handshaker __net80211_handshaker
Initial value:
= {
.protocol = NET80211_SECPROT_NONE,
.init = trivial_init,
.change_key = trivial_change_key,
.priv_len = 0,
}
@ NET80211_SECPROT_NONE
No security handshaking.
Definition net80211.h:102
static int trivial_init(struct net80211_device *dev)
Initialize trivial 802.11 security handshaker.
Definition wep.c:230
static int trivial_change_key(struct net80211_device *dev)
Check for key change on trivial 802.11 security handshaker.
Definition wep.c:272

Trivial 802.11 security handshaker.

Definition at line 300 of file wep.c.

300 {
301 .protocol = NET80211_SECPROT_NONE,
302 .init = trivial_init,
303 .change_key = trivial_change_key,
304 .priv_len = 0,
305};