1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2001 Atsushi Onoe 8 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * Alternatively, this software may be distributed under the terms of the 23 * GNU General Public License ("GPL") version 2 as published by the Free 24 * Software Foundation. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 /* 41 * IEEE 802.11 WEP crypto support. 42 */ 43 #include <sys/byteorder.h> 44 #include <sys/crypto/common.h> 45 #include <sys/crypto/api.h> 46 #include <sys/crc32.h> 47 #include <sys/random.h> 48 #include "net80211_impl.h" 49 50 static void *wep_attach(struct ieee80211com *, struct ieee80211_key *); 51 static void wep_detach(struct ieee80211_key *); 52 static int wep_setkey(struct ieee80211_key *); 53 static int wep_encap(struct ieee80211_key *, mblk_t *, uint8_t keyid); 54 static int wep_decap(struct ieee80211_key *, mblk_t *, int); 55 static int wep_enmic(struct ieee80211_key *, mblk_t *, int); 56 static int wep_demic(struct ieee80211_key *, mblk_t *, int); 57 58 const struct ieee80211_cipher wep = { 59 "WEP", 60 IEEE80211_CIPHER_WEP, 61 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN, 62 IEEE80211_WEP_CRCLEN, 63 0, 64 wep_attach, 65 wep_detach, 66 wep_setkey, 67 wep_encap, 68 wep_decap, 69 wep_enmic, 70 wep_demic, 71 }; 72 73 int rc4_init(crypto_context_t *, const uint8_t *, int); 74 int rc4_crypt(crypto_context_t, const uint8_t *, uint8_t *, int); 75 int rc4_final(crypto_context_t, uint8_t *, int); 76 77 static int wep_encrypt(struct ieee80211_key *, mblk_t *, int); 78 static int wep_decrypt(struct ieee80211_key *, mblk_t *, int); 79 80 struct wep_ctx { 81 ieee80211com_t *wc_ic; /* for diagnostics */ 82 uint32_t wc_iv; /* initial vector for crypto */ 83 }; 84 85 /* Table of CRCs of all 8-bit messages */ 86 static uint32_t crc_table[] = { CRC32_TABLE }; 87 88 /* ARGSUSED */ 89 static void * 90 wep_attach(struct ieee80211com *ic, struct ieee80211_key *k) 91 { 92 struct wep_ctx *ctx; 93 94 ctx = kmem_zalloc(sizeof (struct wep_ctx), KM_NOSLEEP); 95 if (ctx == NULL) 96 return (NULL); 97 98 ctx->wc_ic = ic; 99 (void) random_get_pseudo_bytes((unsigned char *)&ctx->wc_iv, 100 sizeof (uint32_t)); 101 return (ctx); 102 } 103 104 static void 105 wep_detach(struct ieee80211_key *k) 106 { 107 struct wep_ctx *ctx = k->wk_private; 108 109 if (ctx != NULL) 110 kmem_free(ctx, sizeof (struct wep_ctx)); 111 } 112 113 static int 114 wep_setkey(struct ieee80211_key *k) 115 { 116 /* 117 * WEP key length is standardized to 40-bit. Many 118 * implementations support 104-bit WEP kwys. 119 */ 120 return (k->wk_keylen == 40/NBBY || k->wk_keylen == 104/NBBY); 121 } 122 123 /* 124 * Add privacy headers appropriate for the specified key. 125 */ 126 static int 127 wep_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid) 128 { 129 struct wep_ctx *ctx = k->wk_private; 130 struct ieee80211_frame *wh = (struct ieee80211_frame *)mp->b_rptr; 131 uint32_t iv; 132 uint8_t *ivp; 133 int hdrlen; 134 135 if (mp == NULL) 136 return (0); 137 hdrlen = ieee80211_hdrspace(wh); 138 139 ivp = (uint8_t *)wh; 140 ivp += hdrlen; 141 142 /* 143 * IV must not duplicate during the lifetime of the key. 144 * But no mechanism to renew keys is defined in IEEE 802.11 145 * WEP. And IV may be duplicated between other stations 146 * because of the session key itself is shared. 147 * So we use pseudo random IV for now, though it is not the 148 * right way. 149 */ 150 iv = ctx->wc_iv; 151 /* 152 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir: 153 * (B, 255, N) with 3 <= B < 8 154 */ 155 if ((iv & 0xff00) == 0xff00) { 156 int B = (iv & 0xff0000) >> 16; 157 if (3 <= B && B < 16) 158 iv = (B+1) << 16; 159 } 160 ctx->wc_iv = iv + 1; 161 162 ivp[2] = (uint8_t)(iv >> 0); 163 ivp[1] = (uint8_t)(iv >> 8); 164 ivp[0] = (uint8_t)(iv >> 16); 165 166 /* Key ID and pad */ 167 ivp[IEEE80211_WEP_IVLEN] = keyid; 168 169 if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) && 170 (wep_encrypt(k, mp, hdrlen) == 0)) 171 return (0); 172 173 return (1); 174 } 175 176 /* 177 * Validate and strip privacy headers (and trailer) for a 178 * received frame. If necessary, decrypt the frame using 179 * the specified key. 180 */ 181 static int 182 wep_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen) 183 { 184 struct ieee80211_frame *wh, whbuf; 185 186 wh = (struct ieee80211_frame *)mp->b_rptr; 187 188 /* 189 * Check if the device handled the decrypt in hardware. 190 * If so we just strip the header; otherwise we need to 191 * handle the decrypt in software. 192 */ 193 if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) && 194 (wep_decrypt(k, mp, hdrlen) == 0)) { 195 ieee80211_err("WEP ICV mismatch on decrypt\n"); 196 return (0); 197 } 198 199 /* 200 * Copy up 802.11 header and strip crypto bits. 201 */ 202 bcopy(wh, &whbuf, sizeof (whbuf)); 203 mp->b_rptr += wep.ic_header; 204 bcopy(&whbuf, mp->b_rptr, hdrlen); 205 mp->b_wptr -= wep.ic_trailer; 206 207 return (1); 208 } 209 210 /* 211 * Add MIC to the frame as needed. 212 */ 213 /* ARGSUSED */ 214 static int 215 wep_enmic(struct ieee80211_key *k, mblk_t *mp, int force) 216 { 217 return (1); 218 } 219 220 /* 221 * Verify and strip MIC from the frame. 222 */ 223 /* ARGSUSED */ 224 static int 225 wep_demic(struct ieee80211_key *k, mblk_t *mp, int force) 226 { 227 return (1); 228 } 229 230 static int 231 wep_encrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen) 232 { 233 uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE]; 234 uint8_t crcbuf[IEEE80211_WEP_CRCLEN]; 235 uint8_t *icv; 236 uint32_t crc; 237 crypto_context_t ctx; 238 int rv; 239 240 ASSERT(key->wk_flags & IEEE80211_KEY_SWCRYPT); 241 242 /* ctx->wc_ic->isc_stats.is_crypto_wep++; */ 243 244 (void) memcpy(rc4key, mp->b_rptr + hdrlen, IEEE80211_WEP_IVLEN); 245 (void) memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, 246 key->wk_keylen); 247 248 ctx = NULL; 249 rv = rc4_init(&ctx, (const uint8_t *)rc4key, 250 IEEE80211_WEP_IVLEN + key->wk_keylen); 251 252 if (rv != CRYPTO_SUCCESS) 253 return (0); 254 255 /* calculate CRC over unencrypted data */ 256 CRC32(crc, mp->b_rptr + hdrlen + wep.ic_header, 257 mp->b_wptr - mp->b_rptr - (hdrlen + wep.ic_header), 258 -1U, crc_table); 259 260 /* encrypt data */ 261 (void) rc4_crypt(ctx, 262 mp->b_rptr + hdrlen + wep.ic_header, 263 mp->b_rptr + hdrlen + wep.ic_header, 264 mp->b_wptr - mp->b_rptr - (hdrlen + wep.ic_header)); 265 266 /* tack on ICV */ 267 *(uint32_t *)crcbuf = LE_32(~crc); 268 icv = mp->b_wptr; 269 mp->b_wptr += IEEE80211_WEP_CRCLEN; 270 (void) rc4_crypt(ctx, crcbuf, icv, IEEE80211_WEP_CRCLEN); 271 272 (void) rc4_final(ctx, icv, IEEE80211_WEP_CRCLEN); 273 274 return (1); 275 } 276 277 static int 278 wep_decrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen) 279 { 280 uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE]; 281 uint8_t crcbuf[IEEE80211_WEP_CRCLEN]; 282 uint8_t *icv; 283 uint32_t crc; 284 crypto_context_t ctx; 285 int rv; 286 287 ASSERT(key->wk_flags & IEEE80211_KEY_SWCRYPT); 288 289 /* ctx->wc_ic->isc_stats.is_crypto_wep++; */ 290 291 (void) memcpy(rc4key, mp->b_rptr + hdrlen, IEEE80211_WEP_IVLEN); 292 (void) memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, 293 key->wk_keylen); 294 295 ctx = NULL; 296 rv = rc4_init(&ctx, (const uint8_t *)rc4key, 297 IEEE80211_WEP_IVLEN + key->wk_keylen); 298 299 if (rv != CRYPTO_SUCCESS) 300 return (0); 301 302 /* decrypt data */ 303 (void) rc4_crypt(ctx, 304 mp->b_rptr + hdrlen + wep.ic_header, 305 mp->b_rptr + hdrlen + wep.ic_header, 306 mp->b_wptr - mp->b_rptr - 307 (hdrlen + wep.ic_header + wep.ic_trailer)); 308 309 /* calculate CRC over unencrypted data */ 310 CRC32(crc, mp->b_rptr + hdrlen + wep.ic_header, 311 mp->b_wptr - mp->b_rptr - 312 (hdrlen + wep.ic_header + wep.ic_trailer), 313 -1U, crc_table); 314 315 /* decrypt ICV and compare to CRC */ 316 icv = mp->b_wptr - IEEE80211_WEP_CRCLEN; 317 (void) rc4_crypt(ctx, icv, crcbuf, IEEE80211_WEP_CRCLEN); 318 319 (void) rc4_final(ctx, crcbuf, IEEE80211_WEP_CRCLEN); 320 321 return (crc == ~LE_32(*(uint32_t *)crcbuf)); 322 } 323 324 /* 325 * rc_init() - To init the key, for multiply encryption/decryption 326 * Using the Kernel encryption framework 327 */ 328 int 329 rc4_init(crypto_context_t *ctx, const uint8_t *key, int keylen) 330 { 331 crypto_mechanism_t mech; 332 crypto_key_t crkey; 333 int rv; 334 335 bzero(&crkey, sizeof (crkey)); 336 337 crkey.ck_format = CRYPTO_KEY_RAW; 338 crkey.ck_data = (char *)key; 339 /* keys are measured in bits, not bytes, so multiply by 8 */ 340 crkey.ck_length = keylen * 8; 341 342 mech.cm_type = crypto_mech2id(SUN_CKM_RC4); 343 mech.cm_param = NULL; 344 mech.cm_param_len = 0; 345 346 rv = crypto_encrypt_init(&mech, &crkey, NULL, ctx, NULL); 347 if (rv != CRYPTO_SUCCESS) 348 cmn_err(CE_WARN, "rc4_init failed (%x)", rv); 349 350 return (rv); 351 } 352 353 /* 354 * rc4_crypt 355 * 356 * Use the Kernel encryption framework to provide the 357 * crypto operations for the indicated data. 358 */ 359 int 360 rc4_crypt(crypto_context_t ctx, const uint8_t *inbuf, 361 uint8_t *outbuf, int buflen) 362 { 363 int rv = CRYPTO_FAILED; 364 365 crypto_data_t d1, d2; 366 367 ASSERT(inbuf != NULL); 368 ASSERT(outbuf != NULL); 369 370 bzero(&d1, sizeof (d1)); 371 bzero(&d2, sizeof (d2)); 372 373 d1.cd_format = CRYPTO_DATA_RAW; 374 d1.cd_offset = 0; 375 d1.cd_length = buflen; 376 d1.cd_raw.iov_base = (char *)inbuf; 377 d1.cd_raw.iov_len = buflen; 378 379 d2.cd_format = CRYPTO_DATA_RAW; 380 d2.cd_offset = 0; 381 d2.cd_length = buflen; 382 d2.cd_raw.iov_base = (char *)outbuf; 383 d2.cd_raw.iov_len = buflen; 384 385 rv = crypto_encrypt_update(ctx, &d1, &d2, NULL); 386 387 if (rv != CRYPTO_SUCCESS) 388 cmn_err(CE_WARN, "rc4_crypt failed (%x)", rv); 389 return (rv); 390 } 391 392 /* 393 * rc4_final 394 * 395 * Use the Kernel encryption framework to provide the 396 * crypto operations for the indicated data. 397 */ 398 int 399 rc4_final(crypto_context_t ctx, uint8_t *outbuf, int buflen) 400 { 401 int rv = CRYPTO_FAILED; 402 403 crypto_data_t d2; 404 405 ASSERT(outbuf != NULL); 406 407 bzero(&d2, sizeof (d2)); 408 409 d2.cd_format = CRYPTO_DATA_RAW; 410 d2.cd_offset = 0; 411 d2.cd_length = buflen; 412 d2.cd_raw.iov_base = (char *)outbuf; 413 d2.cd_raw.iov_len = buflen; 414 415 rv = crypto_encrypt_final(ctx, &d2, NULL); 416 417 if (rv != CRYPTO_SUCCESS) 418 cmn_err(CE_WARN, "rc4_final failed (%x)", rv); 419 return (rv); 420 } 421