00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <gpxe/net80211.h>
00022 #include <gpxe/sec80211.h>
00023 #include <gpxe/crypto.h>
00024 #include <gpxe/arc4.h>
00025 #include <gpxe/crc32.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <errno.h>
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #define WEP_IV_LEN 3
00048
00049
00050 #define WEP_KID_LEN 1
00051
00052
00053 #define WEP_ICV_LEN 4
00054
00055
00056 #define WEP_MAX_KEY 16
00057
00058
00059 #define WEP_HEADER_LEN 4
00060
00061
00062 #define WEP_TRAILER_LEN 4
00063
00064
00065 #define WEP_OVERHEAD 8
00066
00067
00068 struct wep_ctx
00069 {
00070
00071
00072
00073
00074
00075
00076 u8 key[WEP_IV_LEN + WEP_MAX_KEY];
00077
00078
00079 int keylen;
00080
00081
00082 struct arc4_ctx arc4;
00083 };
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 static int wep_init ( struct net80211_crypto *crypto, const void *key,
00098 int keylen, const void *rsc __unused )
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 }
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 static struct io_buffer * wep_encrypt ( struct net80211_crypto *crypto,
00118 struct io_buffer *iob )
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
00137
00138 iv = random() & 0xffffff;
00139 memcpy ( iob_put ( eiob, WEP_HEADER_LEN ), &iv, WEP_HEADER_LEN );
00140 memcpy ( ctx->key, &iv, WEP_IV_LEN );
00141
00142
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
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 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 static struct io_buffer * wep_decrypt ( struct net80211_crypto *crypto,
00167 struct io_buffer *eiob )
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
00186 memcpy ( &iv, eiob->data + hdrlen, 4 );
00187 iv &= 0xffffff;
00188 memcpy ( ctx->key, &iv, WEP_IV_LEN );
00189
00190
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
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 }
00208
00209
00210 struct net80211_crypto wep_crypto __net80211_crypto = {
00211 .algorithm = NET80211_CRYPT_WEP,
00212 .init = wep_init,
00213 .encrypt = wep_encrypt,
00214 .decrypt = wep_decrypt,
00215 .priv_len = sizeof ( struct wep_ctx ),
00216 };
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 static int trivial_init ( struct net80211_device *dev )
00229 {
00230 u8 key[WEP_MAX_KEY];
00231 int len;
00232 int rc;
00233
00234 if ( dev->associating &&
00235 dev->associating->crypto == NET80211_CRYPT_NONE )
00236 return 0;
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
00247
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 }
00263
00264
00265
00266
00267
00268
00269
00270 static int trivial_change_key ( struct net80211_device *dev )
00271 {
00272 u8 key[WEP_MAX_KEY];
00273 int len;
00274 int change = 0;
00275
00276
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
00286 if ( change )
00287 return -EINVAL;
00288
00289
00290 if ( len <= 0 )
00291 return 0;
00292
00293
00294 return wep_init ( dev->crypto, key, len, NULL );
00295 }
00296
00297
00298 struct net80211_handshaker trivial_handshaker __net80211_handshaker = {
00299 .protocol = NET80211_SECPROT_NONE,
00300 .init = trivial_init,
00301 .change_key = trivial_change_key,
00302 .priv_len = 0,
00303 };