1/* 2 * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19FILE_LICENCE ( GPL2_OR_LATER ); 20 21#include <gpxe/net80211.h> 22#include <gpxe/sec80211.h> 23#include <gpxe/crypto.h> 24#include <gpxe/arc4.h> 25#include <gpxe/crc32.h> 26#include <stdlib.h> 27#include <string.h> 28#include <errno.h> 29 30/** @file 31 * 32 * The WEP wireless encryption method (insecure!) 33 * 34 * The data field in a WEP-encrypted packet contains a 3-byte 35 * initialisation vector, one-byte Key ID field (only the bottom two 36 * bits are ever used), encrypted data, and a 4-byte encrypted CRC of 37 * the plaintext data, called the ICV. To decrypt it, the IV is 38 * prepended to the shared key and the data stream (including ICV) is 39 * run through the ARC4 stream cipher; if the ICV matches a CRC32 40 * calculated on the plaintext, the packet is valid. 41 * 42 * For efficiency and code-size reasons, this file assumes it is 43 * running on a little-endian machine. 44 */ 45 46/** Length of WEP initialisation vector */ 47#define WEP_IV_LEN 3 48 49/** Length of WEP key ID byte */ 50#define WEP_KID_LEN 1 51 52/** Length of WEP ICV checksum */ 53#define WEP_ICV_LEN 4 54 55/** Maximum length of WEP key */ 56#define WEP_MAX_KEY 16 57 58/** Amount of data placed before the encrypted bytes */ 59#define WEP_HEADER_LEN 4 60 61/** Amount of data placed after the encrypted bytes */ 62#define WEP_TRAILER_LEN 4 63 64/** Total WEP overhead bytes */ 65#define WEP_OVERHEAD 8 66 67/** Context for WEP encryption and decryption */ 68struct wep_ctx 69{ 70 /** Encoded WEP key 71 * 72 * The actual key bytes are stored beginning at offset 3, to 73 * leave room for easily inserting the IV before a particular 74 * operation. 75 */ 76 u8 key[WEP_IV_LEN + WEP_MAX_KEY]; 77 78 /** Length of WEP key (not including IV bytes) */ 79 int keylen; 80 81 /** ARC4 context */ 82 struct arc4_ctx arc4; 83}; 84 85/** 86 * Initialize WEP algorithm 87 * 88 * @v crypto 802.11 cryptographic algorithm 89 * @v key WEP key to use 90 * @v keylen Length of WEP key 91 * @v rsc Initial receive sequence counter (unused) 92 * @ret rc Return status code 93 * 94 * Standard key lengths are 5 and 13 bytes; 16-byte keys are 95 * occasionally supported as an extension to the standard. 96 */ 97static int wep_init ( struct net80211_crypto *crypto, const void *key, 98 int keylen, const void *rsc __unused ) 99{ 100 struct wep_ctx *ctx = crypto->priv; 101 102 ctx->keylen = ( keylen > WEP_MAX_KEY ? WEP_MAX_KEY : keylen ); 103 memcpy ( ctx->key + WEP_IV_LEN, key, ctx->keylen ); 104 105 return 0; 106} 107 108/** 109 * Encrypt packet using WEP 110 * 111 * @v crypto 802.11 cryptographic algorithm 112 * @v iob I/O buffer of plaintext packet 113 * @ret eiob Newly allocated I/O buffer for encrypted packet, or NULL 114 * 115 * If memory allocation fails, @c NULL is returned. 116 */ 117static struct io_buffer * wep_encrypt ( struct net80211_crypto *crypto, 118 struct io_buffer *iob ) 119{ 120 struct wep_ctx *ctx = crypto->priv; 121 struct io_buffer *eiob; 122 struct ieee80211_frame *hdr; 123 const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN; 124 int datalen = iob_len ( iob ) - hdrlen; 125 int newlen = hdrlen + datalen + WEP_OVERHEAD; 126 u32 iv, icv; 127 128 eiob = alloc_iob ( newlen ); 129 if ( ! eiob ) 130 return NULL; 131 132 memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen ); 133 hdr = eiob->data; 134 hdr->fc |= IEEE80211_FC_PROTECTED; 135 136 /* Calculate IV, put it in the header (with key ID byte = 0), and 137 set it up at the start of the encryption key. */ 138 iv = random() & 0xffffff; /* IV in bottom 3 bytes, top byte = KID = 0 */ 139 memcpy ( iob_put ( eiob, WEP_HEADER_LEN ), &iv, WEP_HEADER_LEN ); 140 memcpy ( ctx->key, &iv, WEP_IV_LEN ); 141 142 /* Encrypt the data using RC4 */ 143 cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key, 144 ctx->keylen + WEP_IV_LEN ); 145 cipher_encrypt ( &arc4_algorithm, &ctx->arc4, iob->data + hdrlen, 146 iob_put ( eiob, datalen ), datalen ); 147 148 /* Add ICV */ 149 icv = ~crc32_le ( ~0, iob->data + hdrlen, datalen ); 150 cipher_encrypt ( &arc4_algorithm, &ctx->arc4, &icv, 151 iob_put ( eiob, WEP_ICV_LEN ), WEP_ICV_LEN ); 152 153 return eiob; 154} 155 156/** 157 * Decrypt packet using WEP 158 * 159 * @v crypto 802.11 cryptographic algorithm 160 * @v eiob I/O buffer of encrypted packet 161 * @ret iob Newly allocated I/O buffer for plaintext packet, or NULL 162 * 163 * If a consistency check for the decryption fails (usually indicating 164 * an invalid key), @c NULL is returned. 165 */ 166static struct io_buffer * wep_decrypt ( struct net80211_crypto *crypto, 167 struct io_buffer *eiob ) 168{ 169 struct wep_ctx *ctx = crypto->priv; 170 struct io_buffer *iob; 171 struct ieee80211_frame *hdr; 172 const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN; 173 int datalen = iob_len ( eiob ) - hdrlen - WEP_OVERHEAD; 174 int newlen = hdrlen + datalen; 175 u32 iv, icv, crc; 176 177 iob = alloc_iob ( newlen ); 178 if ( ! iob ) 179 return NULL; 180 181 memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen ); 182 hdr = iob->data; 183 hdr->fc &= ~IEEE80211_FC_PROTECTED; 184 185 /* Strip off IV and use it to initialize cryptosystem */ 186 memcpy ( &iv, eiob->data + hdrlen, 4 ); 187 iv &= 0xffffff; /* ignore key ID byte */ 188 memcpy ( ctx->key, &iv, WEP_IV_LEN ); 189 190 /* Decrypt the data using RC4 */ 191 cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key, 192 ctx->keylen + WEP_IV_LEN ); 193 cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen + 194 WEP_HEADER_LEN, iob_put ( iob, datalen ), datalen ); 195 196 /* Strip off ICV and verify it */ 197 cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen + 198 WEP_HEADER_LEN + datalen, &icv, WEP_ICV_LEN ); 199 crc = ~crc32_le ( ~0, iob->data + hdrlen, datalen ); 200 if ( crc != icv ) { 201 DBGC ( crypto, "WEP %p CRC mismatch: expect %08x, get %08x\n", 202 crypto, icv, crc ); 203 free_iob ( iob ); 204 return NULL; 205 } 206 return iob; 207} 208 209/** WEP cryptosystem for 802.11 */ 210struct net80211_crypto wep_crypto __net80211_crypto = { 211 .algorithm = NET80211_CRYPT_WEP, 212 .init = wep_init, 213 .encrypt = wep_encrypt, 214 .decrypt = wep_decrypt, 215 .priv_len = sizeof ( struct wep_ctx ), 216}; 217 218/** 219 * Initialize trivial 802.11 security handshaker 220 * 221 * @v dev 802.11 device 222 * @v ctx Security handshaker 223 * 224 * This simply fetches a WEP key from netX/key, and if it exists, 225 * installs WEP cryptography on the 802.11 device. No real handshaking 226 * is performed. 227 */ 228static int trivial_init ( struct net80211_device *dev ) 229{ 230 u8 key[WEP_MAX_KEY]; /* support up to 128-bit keys */ 231 int len; 232 int rc; 233 234 if ( dev->associating && 235 dev->associating->crypto == NET80211_CRYPT_NONE ) 236 return 0; /* no crypto? OK. */ 237 238 len = fetch_setting ( netdev_settings ( dev->netdev ), 239 &net80211_key_setting, key, WEP_MAX_KEY ); 240 241 if ( len <= 0 ) { 242 DBGC ( dev, "802.11 %p cannot do WEP without a key\n", dev ); 243 return -EACCES; 244 } 245 246 /* Full 128-bit keys are a nonstandard extension, but they're 247 utterly trivial to support, so we do. */ 248 if ( len != 5 && len != 13 && len != 16 ) { 249 DBGC ( dev, "802.11 %p invalid WEP key length %d\n", 250 dev, len ); 251 return -EINVAL; 252 } 253 254 DBGC ( dev, "802.11 %p installing %d-bit WEP\n", dev, len * 8 ); 255 256 rc = sec80211_install ( &dev->crypto, NET80211_CRYPT_WEP, key, len, 257 NULL ); 258 if ( rc < 0 ) 259 return rc; 260 261 return 0; 262} 263 264/** 265 * Check for key change on trivial 802.11 security handshaker 266 * 267 * @v dev 802.11 device 268 * @v ctx Security handshaker 269 */ 270static int trivial_change_key ( struct net80211_device *dev ) 271{ 272 u8 key[WEP_MAX_KEY]; 273 int len; 274 int change = 0; 275 276 /* If going from WEP to clear, or something else to WEP, reassociate. */ 277 if ( ! dev->crypto || ( dev->crypto->init != wep_init ) ) 278 change ^= 1; 279 280 len = fetch_setting ( netdev_settings ( dev->netdev ), 281 &net80211_key_setting, key, WEP_MAX_KEY ); 282 if ( len <= 0 ) 283 change ^= 1; 284 285 /* Changing crypto type => return nonzero to reassociate. */ 286 if ( change ) 287 return -EINVAL; 288 289 /* Going from no crypto to still no crypto => nothing to do. */ 290 if ( len <= 0 ) 291 return 0; 292 293 /* Otherwise, reinitialise WEP with new key. */ 294 return wep_init ( dev->crypto, key, len, NULL ); 295} 296 297/** Trivial 802.11 security handshaker */ 298struct net80211_handshaker trivial_handshaker __net80211_handshaker = { 299 .protocol = NET80211_SECPROT_NONE, 300 .init = trivial_init, 301 .change_key = trivial_change_key, 302 .priv_len = 0, 303}; 304