1 /* 2 * Copyright 2008 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 <sys/strsun.h> 49 #include "net80211_impl.h" 50 51 static void *wep_attach(struct ieee80211com *, struct ieee80211_key *); 52 static void wep_detach(struct ieee80211_key *); 53 static int wep_setkey(struct ieee80211_key *); 54 static int wep_encap(struct ieee80211_key *, mblk_t *, uint8_t keyid); 55 static int wep_decap(struct ieee80211_key *, mblk_t *, int); 56 static int wep_enmic(struct ieee80211_key *, mblk_t *, int); 57 static int wep_demic(struct ieee80211_key *, mblk_t *, int); 58 59 const struct ieee80211_cipher wep = { 60 "WEP", 61 IEEE80211_CIPHER_WEP, 62 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN, 63 IEEE80211_WEP_CRCLEN, 64 0, 65 wep_attach, 66 wep_detach, 67 wep_setkey, 68 wep_encap, 69 wep_decap, 70 wep_enmic, 71 wep_demic, 72 }; 73 74 int rc4_init(crypto_context_t *, const uint8_t *, int); 75 int rc4_crypt(crypto_context_t, const uint8_t *, uint8_t *, int); 76 int rc4_final(crypto_context_t, uint8_t *, int); 77 78 static int wep_encrypt(struct ieee80211_key *, mblk_t *, int); 79 static int wep_decrypt(struct ieee80211_key *, mblk_t *, int); 80 81 struct wep_ctx { 82 ieee80211com_t *wc_ic; /* for diagnostics */ 83 uint32_t wc_iv; /* initial vector for crypto */ 84 }; 85 86 /* Table of CRCs of all 8-bit messages */ 87 static uint32_t crc_table[] = { CRC32_TABLE }; 88 89 /* ARGSUSED */ 90 static void * 91 wep_attach(struct ieee80211com *ic, struct ieee80211_key *k) 92 { 93 struct wep_ctx *ctx; 94 95 ctx = kmem_zalloc(sizeof (struct wep_ctx), KM_NOSLEEP); 96 if (ctx == NULL) 97 return (NULL); 98 99 ctx->wc_ic = ic; 100 (void) random_get_pseudo_bytes((unsigned char *)&ctx->wc_iv, 101 sizeof (uint32_t)); 102 return (ctx); 103 } 104 105 static void 106 wep_detach(struct ieee80211_key *k) 107 { 108 struct wep_ctx *ctx = k->wk_private; 109 110 if (ctx != NULL) 111 kmem_free(ctx, sizeof (struct wep_ctx)); 112 } 113 114 static int 115 wep_setkey(struct ieee80211_key *k) 116 { 117 /* 118 * WEP key length is standardized to 40-bit. Many 119 * implementations support 104-bit WEP kwys. 120 */ 121 return (k->wk_keylen == 40/NBBY || k->wk_keylen == 104/NBBY); 122 } 123 124 /* 125 * Add privacy headers appropriate for the specified key. 126 */ 127 static int 128 wep_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid) 129 { 130 struct wep_ctx *ctx = k->wk_private; 131 struct ieee80211_frame *wh = (struct ieee80211_frame *)mp->b_rptr; 132 uint32_t iv; 133 uint8_t *ivp; 134 int hdrlen; 135 136 if (mp == NULL) 137 return (0); 138 hdrlen = ieee80211_hdrspace(wh); 139 140 ivp = (uint8_t *)wh; 141 ivp += hdrlen; 142 143 /* 144 * IV must not duplicate during the lifetime of the key. 145 * But no mechanism to renew keys is defined in IEEE 802.11 146 * WEP. And IV may be duplicated between other stations 147 * because of the session key itself is shared. 148 * So we use pseudo random IV for now, though it is not the 149 * right way. 150 */ 151 iv = ctx->wc_iv; 152 /* 153 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir: 154 * (B, 255, N) with 3 <= B < 8 155 */ 156 if ((iv & 0xff00) == 0xff00) { 157 int B = (iv & 0xff0000) >> 16; 158 if (3 <= B && B < 16) 159 iv = (B+1) << 16; 160 } 161 ctx->wc_iv = iv + 1; 162 163 ivp[2] = (uint8_t)(iv >> 0); 164 ivp[1] = (uint8_t)(iv >> 8); 165 ivp[0] = (uint8_t)(iv >> 16); 166 167 /* Key ID and pad */ 168 ivp[IEEE80211_WEP_IVLEN] = keyid; 169 170 if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) && 171 (wep_encrypt(k, mp, hdrlen) == 0)) 172 return (0); 173 174 return (1); 175 } 176 177 /* 178 * Validate and strip privacy headers (and trailer) for a 179 * received frame. If necessary, decrypt the frame using 180 * the specified key. 181 */ 182 static int 183 wep_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen) 184 { 185 struct ieee80211_frame *wh, whbuf; 186 187 wh = (struct ieee80211_frame *)mp->b_rptr; 188 189 /* 190 * Check if the device handled the decrypt in hardware. 191 * If so we just strip the header; otherwise we need to 192 * handle the decrypt in software. 193 */ 194 if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) && 195 (wep_decrypt(k, mp, hdrlen) == 0)) { 196 ieee80211_err("WEP ICV mismatch on decrypt\n"); 197 return (0); 198 } 199 200 /* 201 * Copy up 802.11 header and strip crypto bits. 202 */ 203 bcopy(wh, &whbuf, sizeof (whbuf)); 204 mp->b_rptr += wep.ic_header; 205 bcopy(&whbuf, mp->b_rptr, hdrlen); 206 mp->b_wptr -= wep.ic_trailer; 207 208 return (1); 209 } 210 211 /* 212 * Add MIC to the frame as needed. 213 */ 214 /* ARGSUSED */ 215 static int 216 wep_enmic(struct ieee80211_key *k, mblk_t *mp, int force) 217 { 218 return (1); 219 } 220 221 /* 222 * Verify and strip MIC from the frame. 223 */ 224 /* ARGSUSED */ 225 static int 226 wep_demic(struct ieee80211_key *k, mblk_t *mp, int force) 227 { 228 return (1); 229 } 230 231 static int 232 wep_encrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen) 233 { 234 uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE]; 235 uint8_t crcbuf[IEEE80211_WEP_CRCLEN]; 236 uint8_t *icv; 237 uint32_t crc; 238 crypto_context_t ctx; 239 int rv; 240 241 ASSERT(key->wk_flags & IEEE80211_KEY_SWCRYPT); 242 243 /* ctx->wc_ic->isc_stats.is_crypto_wep++; */ 244 245 (void) memcpy(rc4key, mp->b_rptr + hdrlen, IEEE80211_WEP_IVLEN); 246 (void) memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, 247 key->wk_keylen); 248 249 ctx = NULL; 250 rv = rc4_init(&ctx, (const uint8_t *)rc4key, 251 IEEE80211_WEP_IVLEN + key->wk_keylen); 252 253 if (rv != CRYPTO_SUCCESS) 254 return (0); 255 256 /* calculate CRC over unencrypted data */ 257 CRC32(crc, mp->b_rptr + hdrlen + wep.ic_header, 258 MBLKL(mp) - (hdrlen + wep.ic_header), 259 -1U, crc_table); 260 261 /* encrypt data */ 262 (void) rc4_crypt(ctx, 263 mp->b_rptr + hdrlen + wep.ic_header, 264 mp->b_rptr + hdrlen + wep.ic_header, 265 MBLKL(mp) - (hdrlen + wep.ic_header)); 266 267 /* tack on ICV */ 268 *(uint32_t *)crcbuf = LE_32(~crc); 269 icv = mp->b_wptr; 270 mp->b_wptr += IEEE80211_WEP_CRCLEN; 271 (void) rc4_crypt(ctx, crcbuf, icv, IEEE80211_WEP_CRCLEN); 272 273 (void) rc4_final(ctx, icv, IEEE80211_WEP_CRCLEN); 274 275 return (1); 276 } 277 278 static int 279 wep_decrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen) 280 { 281 uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE]; 282 uint8_t crcbuf[IEEE80211_WEP_CRCLEN]; 283 uint8_t *icv; 284 uint32_t crc; 285 crypto_context_t ctx; 286 int rv; 287 288 ASSERT(key->wk_flags & IEEE80211_KEY_SWCRYPT); 289 290 /* ctx->wc_ic->isc_stats.is_crypto_wep++; */ 291 292 (void) memcpy(rc4key, mp->b_rptr + hdrlen, IEEE80211_WEP_IVLEN); 293 (void) memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, 294 key->wk_keylen); 295 296 ctx = NULL; 297 rv = rc4_init(&ctx, (const uint8_t *)rc4key, 298 IEEE80211_WEP_IVLEN + key->wk_keylen); 299 300 if (rv != CRYPTO_SUCCESS) 301 return (0); 302 303 /* decrypt data */ 304 (void) rc4_crypt(ctx, 305 mp->b_rptr + hdrlen + wep.ic_header, 306 mp->b_rptr + hdrlen + wep.ic_header, 307 MBLKL(mp) - 308 (hdrlen + wep.ic_header + wep.ic_trailer)); 309 310 /* calculate CRC over unencrypted data */ 311 CRC32(crc, mp->b_rptr + hdrlen + wep.ic_header, 312 MBLKL(mp) - 313 (hdrlen + wep.ic_header + wep.ic_trailer), 314 -1U, crc_table); 315 316 /* decrypt ICV and compare to CRC */ 317 icv = mp->b_wptr - IEEE80211_WEP_CRCLEN; 318 (void) rc4_crypt(ctx, icv, crcbuf, IEEE80211_WEP_CRCLEN); 319 320 (void) rc4_final(ctx, crcbuf, IEEE80211_WEP_CRCLEN); 321 322 return (crc == ~LE_32(*(uint32_t *)crcbuf)); 323 } 324 325 /* 326 * rc_init() - To init the key, for multiply encryption/decryption 327 * Using the Kernel encryption framework 328 */ 329 int 330 rc4_init(crypto_context_t *ctx, const uint8_t *key, int keylen) 331 { 332 crypto_mechanism_t mech; 333 crypto_key_t crkey; 334 int rv; 335 336 bzero(&crkey, sizeof (crkey)); 337 338 crkey.ck_format = CRYPTO_KEY_RAW; 339 crkey.ck_data = (char *)key; 340 /* keys are measured in bits, not bytes, so multiply by 8 */ 341 crkey.ck_length = keylen * 8; 342 343 mech.cm_type = crypto_mech2id(SUN_CKM_RC4); 344 mech.cm_param = NULL; 345 mech.cm_param_len = 0; 346 347 rv = crypto_encrypt_init(&mech, &crkey, NULL, ctx, NULL); 348 if (rv != CRYPTO_SUCCESS) 349 cmn_err(CE_WARN, "rc4_init failed (%x)", rv); 350 351 return (rv); 352 } 353 354 /* 355 * rc4_crypt 356 * 357 * Use the Kernel encryption framework to provide the 358 * crypto operations for the indicated data. 359 */ 360 int 361 rc4_crypt(crypto_context_t ctx, const uint8_t *inbuf, 362 uint8_t *outbuf, int buflen) 363 { 364 int rv = CRYPTO_FAILED; 365 366 crypto_data_t d1, d2; 367 368 ASSERT(inbuf != NULL); 369 ASSERT(outbuf != NULL); 370 371 bzero(&d1, sizeof (d1)); 372 bzero(&d2, sizeof (d2)); 373 374 d1.cd_format = CRYPTO_DATA_RAW; 375 d1.cd_offset = 0; 376 d1.cd_length = buflen; 377 d1.cd_raw.iov_base = (char *)inbuf; 378 d1.cd_raw.iov_len = buflen; 379 380 d2.cd_format = CRYPTO_DATA_RAW; 381 d2.cd_offset = 0; 382 d2.cd_length = buflen; 383 d2.cd_raw.iov_base = (char *)outbuf; 384 d2.cd_raw.iov_len = buflen; 385 386 rv = crypto_encrypt_update(ctx, &d1, &d2, NULL); 387 388 if (rv != CRYPTO_SUCCESS) 389 cmn_err(CE_WARN, "rc4_crypt failed (%x)", rv); 390 return (rv); 391 } 392 393 /* 394 * rc4_final 395 * 396 * Use the Kernel encryption framework to provide the 397 * crypto operations for the indicated data. 398 */ 399 int 400 rc4_final(crypto_context_t ctx, uint8_t *outbuf, int buflen) 401 { 402 int rv = CRYPTO_FAILED; 403 404 crypto_data_t d2; 405 406 ASSERT(outbuf != NULL); 407 408 bzero(&d2, sizeof (d2)); 409 410 d2.cd_format = CRYPTO_DATA_RAW; 411 d2.cd_offset = 0; 412 d2.cd_length = buflen; 413 d2.cd_raw.iov_base = (char *)outbuf; 414 d2.cd_raw.iov_len = buflen; 415 416 rv = crypto_encrypt_final(ctx, &d2, NULL); 417 418 if (rv != CRYPTO_SUCCESS) 419 cmn_err(CE_WARN, "rc4_final failed (%x)", rv); 420 return (rv); 421 } 422