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