#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_buffer * | wep_encrypt (struct net80211_crypto *crypto, struct io_buffer *iob) |
| Encrypt packet using WEP. | |
| static struct io_buffer * | wep_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. | |
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 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_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 |
| #define WEP_OVERHEAD 8 |
Total WEP overhead bytes.
Definition at line 65 of file wep.c.
Referenced by wep_decrypt(), and wep_encrypt().
| 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.
| crypto | 802.11 cryptographic algorithm | |
| key | WEP key to use | |
| keylen | Length of WEP key | |
| rsc | Initial receive sequence counter (unused) |
| rc | Return status code |
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.
| crypto | 802.11 cryptographic algorithm | |
| iob | I/O buffer of plaintext packet |
| eiob | Newly allocated I/O buffer for encrypted packet, or NULL |
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.
| crypto | 802.11 cryptographic algorithm | |
| eiob | I/O buffer of encrypted packet |
| iob | Newly allocated I/O buffer for plaintext packet, or NULL |
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.
| dev | 802.11 device | |
| ctx | Security handshaker |
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.
| 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 }
| 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 ),
}
| struct net80211_handshaker trivial_handshaker __net80211_handshaker |
Initial value:
{
.protocol = NET80211_SECPROT_NONE,
.init = trivial_init,
.change_key = trivial_change_key,
.priv_len = 0,
}
1.5.7.1