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.11i CCMP 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 struct ccmp_ctx { 52 struct ieee80211com *cc_ic; /* for diagnostics */ 53 }; 54 55 #define AES_BLOCK_LEN 16 56 #define AES_NONCE_LEN 13 57 58 static void *ccmp_attach(struct ieee80211com *, struct ieee80211_key *); 59 static void ccmp_detach(struct ieee80211_key *); 60 static int ccmp_setkey(struct ieee80211_key *); 61 static int ccmp_encap(struct ieee80211_key *k, mblk_t *, uint8_t); 62 static int ccmp_decap(struct ieee80211_key *, mblk_t *, int); 63 static int ccmp_enmic(struct ieee80211_key *, mblk_t *, int); 64 static int ccmp_demic(struct ieee80211_key *, mblk_t *, int); 65 66 static int ccmp_encrypt(struct ieee80211_key *, mblk_t *, int); 67 static int ccmp_decrypt(struct ieee80211_key *, uint64_t pn, mblk_t *, int); 68 69 const struct ieee80211_cipher ccmp = { 70 "AES-CCM", 71 IEEE80211_CIPHER_AES_CCM, 72 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 73 IEEE80211_WEP_EXTIVLEN, 74 IEEE80211_WEP_MICLEN, 75 0, 76 ccmp_attach, 77 ccmp_detach, 78 ccmp_setkey, 79 ccmp_encap, 80 ccmp_decap, 81 ccmp_enmic, 82 ccmp_demic, 83 }; 84 85 /* ARGSUSED */ 86 static void * 87 ccmp_attach(struct ieee80211com *ic, struct ieee80211_key *k) 88 { 89 struct ccmp_ctx *ctx; 90 91 ctx = kmem_zalloc(sizeof (struct ccmp_ctx), KM_SLEEP); 92 if (ctx == NULL) 93 return (NULL); 94 95 ctx->cc_ic = ic; 96 return (ctx); 97 } 98 99 static void 100 ccmp_detach(struct ieee80211_key *k) 101 { 102 struct ccmp_ctx *ctx = k->wk_private; 103 104 if (ctx != NULL) 105 kmem_free(ctx, sizeof (struct ccmp_ctx)); 106 } 107 108 static int 109 ccmp_setkey(struct ieee80211_key *k) 110 { 111 if (k->wk_keylen != (128/NBBY)) 112 return (0); 113 114 return (1); 115 } 116 117 /* 118 * Add privacy headers appropriate for the specified key. 119 */ 120 static int 121 ccmp_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid) 122 { 123 uint8_t *ivp; 124 int hdrlen; 125 126 hdrlen = ieee80211_hdrspace(mp->b_rptr); 127 /* 128 * Copy down 802.11 header and add the IV, KeyID, and ExtIV. 129 */ 130 ivp = mp->b_rptr; 131 ivp += hdrlen; 132 133 k->wk_keytsc++; /* wrap at 48 bits */ 134 ivp[0] = k->wk_keytsc >> 0; /* PN0 */ 135 ivp[1] = k->wk_keytsc >> 8; /* PN1 */ 136 ivp[2] = 0; /* Reserved */ 137 ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */ 138 ivp[4] = k->wk_keytsc >> 16; /* PN2 */ 139 ivp[5] = k->wk_keytsc >> 24; /* PN3 */ 140 ivp[6] = k->wk_keytsc >> 32; /* PN4 */ 141 ivp[7] = k->wk_keytsc >> 40; /* PN5 */ 142 143 /* 144 * Finally, do software encrypt if neeed. 145 */ 146 if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) && 147 !ccmp_encrypt(k, mp, hdrlen)) 148 return (0); 149 150 return (1); 151 } 152 153 /* 154 * Validate and strip privacy headers (and trailer) for a 155 * received frame. The specified key should be correct but 156 * is also verified. 157 */ 158 static int 159 ccmp_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen) 160 { 161 struct ieee80211_frame tmp; 162 uint8_t *ivp; 163 uint64_t pn; 164 165 /* 166 * Header should have extended IV and sequence number; 167 * verify the former and validate the latter. 168 */ 169 ivp = mp->b_rptr + hdrlen; 170 if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) { 171 /* 172 * No extended IV; discard frame. 173 */ 174 return (0); 175 } 176 177 pn = ieee80211_read_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]); 178 if (pn <= k->wk_keyrsc) { 179 /* 180 * Replay violation. 181 */ 182 return (0); 183 } 184 185 /* 186 * Check if the device handled the decrypt in hardware. 187 * If so we just strip the header; otherwise we need to 188 * handle the decrypt in software. Note that for the 189 * latter we leave the header in place for use in the 190 * decryption work. 191 */ 192 if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) && 193 !ccmp_decrypt(k, pn, mp, hdrlen)) 194 return (0); 195 196 /* 197 * Copy up 802.11 header and strip crypto bits. 198 */ 199 bcopy(mp->b_rptr, &tmp, hdrlen); 200 bcopy(&tmp, mp->b_rptr + ccmp.ic_header, hdrlen); 201 mp->b_rptr += ccmp.ic_header; 202 mp->b_wptr -= ccmp.ic_trailer; 203 204 /* 205 * Ok to update rsc now. 206 */ 207 k->wk_keyrsc = pn; 208 209 return (1); 210 } 211 212 /* 213 * Add MIC to the frame as needed. 214 */ 215 /* ARGSUSED */ 216 static int 217 ccmp_enmic(struct ieee80211_key *k, mblk_t *mp, int force) 218 { 219 return (1); 220 } 221 222 /* 223 * Verify and strip MIC from the frame. 224 */ 225 /* ARGSUSED */ 226 static int 227 ccmp_demic(struct ieee80211_key *k, mblk_t *mp, int force) 228 { 229 return (1); 230 } 231 232 static int 233 aes_ccm_encrypt(CK_AES_CCM_PARAMS *cmparam, const uint8_t *key, int keylen, 234 const uint8_t *plaintext, int plain_len, 235 uint8_t *ciphertext, int cipher_len) 236 { 237 crypto_mechanism_t mech; 238 crypto_key_t crkey; 239 crypto_data_t d1, d2; 240 241 int rv; 242 243 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 244 "aes_ccm_encrypt(len=%d, keylen=%d)", plain_len, keylen); 245 246 bzero(&crkey, sizeof (crkey)); 247 248 crkey.ck_format = CRYPTO_KEY_RAW; 249 crkey.ck_data = (char *)key; 250 /* keys are measured in bits, not bytes, so multiply by 8 */ 251 crkey.ck_length = keylen * 8; 252 253 mech.cm_type = crypto_mech2id(SUN_CKM_AES_CCM); 254 mech.cm_param = (caddr_t)cmparam; 255 mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS); 256 257 #if defined(__amd64) || defined(__sparc) 258 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%lx", mech.cm_type); 259 #else 260 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%llx", mech.cm_type); 261 #endif 262 263 bzero(&d1, sizeof (d1)); 264 bzero(&d2, sizeof (d2)); 265 266 d1.cd_format = CRYPTO_DATA_RAW; 267 d1.cd_offset = 0; 268 d1.cd_length = plain_len; 269 d1.cd_raw.iov_base = (char *)plaintext; 270 d1.cd_raw.iov_len = plain_len; 271 272 d2.cd_format = CRYPTO_DATA_RAW; 273 d2.cd_offset = 0; 274 d2.cd_length = cipher_len; 275 d2.cd_raw.iov_base = (char *)ciphertext; 276 d2.cd_raw.iov_len = cipher_len; 277 278 279 rv = crypto_encrypt(&mech, &d1, &crkey, NULL, &d2, NULL); 280 if (rv != CRYPTO_SUCCESS) 281 ieee80211_err("aes_ccm_encrypt failed (%x)", rv); 282 return (rv); 283 } 284 285 static int 286 aes_ccm_decrypt(CK_AES_CCM_PARAMS *cmparam, const uint8_t *key, int keylen, 287 const uint8_t *ciphertext, int cipher_len, 288 uint8_t *plaintext, int plain_len) 289 { 290 crypto_mechanism_t mech; 291 crypto_key_t crkey; 292 crypto_data_t d1, d2; 293 294 int rv; 295 296 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 297 "aes_ccm_decrypt(len=%d, keylen=%d)", cipher_len, keylen); 298 299 bzero(&crkey, sizeof (crkey)); 300 301 crkey.ck_format = CRYPTO_KEY_RAW; 302 crkey.ck_data = (char *)key; 303 /* keys are measured in bits, not bytes, so multiply by 8 */ 304 crkey.ck_length = keylen * 8; 305 306 mech.cm_type = crypto_mech2id(SUN_CKM_AES_CCM); 307 mech.cm_param = (caddr_t)cmparam; 308 mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS); 309 310 #if defined(__amd64) || defined(__sparc) 311 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%lx", mech.cm_type); 312 #else 313 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "cm_type=%llx", mech.cm_type); 314 #endif 315 316 bzero(&d1, sizeof (d1)); 317 bzero(&d2, sizeof (d2)); 318 319 d1.cd_format = CRYPTO_DATA_RAW; 320 d1.cd_offset = 0; 321 d1.cd_length = cipher_len; 322 d1.cd_raw.iov_base = (char *)ciphertext; 323 d1.cd_raw.iov_len = cipher_len; 324 325 d2.cd_format = CRYPTO_DATA_RAW; 326 d2.cd_offset = 0; 327 d2.cd_length = plain_len; 328 d2.cd_raw.iov_base = (char *)plaintext; 329 d2.cd_raw.iov_len = plain_len; 330 331 332 rv = crypto_decrypt(&mech, &d1, &crkey, NULL, &d2, NULL); 333 if (rv != CRYPTO_SUCCESS) 334 ieee80211_err("aes_ccm_decrypt failed (%x)", rv); 335 return (rv); 336 } 337 338 /* 339 * For the avoidance of doubt, except that if any license choice other 340 * than GPL or LGPL is available it will apply instead, Sun elects to 341 * use only the General Public License version 2 (GPLv2) at this time 342 * for any software where a choice of GPL license versions is made 343 * available with the language indicating that GPLv2 or any later 344 * version may be used, or where a choice of which version of the GPL 345 * is applied is otherwise unspecified. 346 */ 347 348 /* 349 * Host AP crypt: host-based CCMP encryption implementation for Host AP driver 350 * 351 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> 352 * 353 * This program is free software; you can redistribute it and/or modify 354 * it under the terms of the GNU General Public License version 2 as 355 * published by the Free Software Foundation. See README and COPYING for 356 * more details. 357 * 358 * Alternatively, this software may be distributed under the terms of BSD 359 * license. 360 */ 361 362 static void 363 ccmp_init(struct ieee80211_frame *wh, uint64_t pn, size_t dlen, 364 uint8_t b0[AES_BLOCK_LEN], uint8_t aad[2 * AES_BLOCK_LEN]) 365 { 366 /* 367 * CCM Initial Block: 368 * Flag (Include authentication header, M=3 (8-octet MIC), 369 * L=1 (2-octet Dlen)) 370 * Nonce: 0x00 | A2 | PN 371 * Dlen 372 */ 373 b0[0] = 0x59; 374 /* b0[1] set below */ 375 IEEE80211_ADDR_COPY(b0 + 2, wh->i_addr2); 376 b0[8] = pn >> 40; 377 b0[9] = pn >> 32; 378 b0[10] = pn >> 24; 379 b0[11] = pn >> 16; 380 b0[12] = pn >> 8; 381 b0[13] = (uint8_t)(pn >> 0); 382 b0[14] = (dlen >> 8) & 0xff; 383 b0[15] = dlen & 0xff; 384 385 /* 386 * AAD: 387 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one 388 * A1 | A2 | A3 389 * SC with bits 4..15 (seq#) masked to zero 390 * A4 (if present) 391 * QC (if present) 392 */ 393 aad[0] = 0; /* AAD length >> 8 */ 394 /* aad[1] set below */ 395 aad[2] = wh->i_fc[0] & 0x8f; /* magic #s */ 396 aad[3] = wh->i_fc[1] & 0xc7; /* magic #s */ 397 /* we know 3 addresses are contiguous */ 398 (void) memcpy(aad + 4, wh->i_addr1, 3 * IEEE80211_ADDR_LEN); 399 aad[22] = wh->i_seq[0] & IEEE80211_SEQ_FRAG_MASK; 400 aad[23] = 0; /* all bits masked */ 401 /* 402 * Construct variable-length portion of AAD based 403 * on whether this is a 4-address frame/QOS frame. 404 * We always zero-pad to 32 bytes before running it 405 * through the cipher. 406 * 407 * We also fill in the priority bits of the CCM 408 * initial block as we know whether or not we have 409 * a QOS frame. 410 */ 411 *(uint16_t *)&aad[24] = 0; 412 b0[1] = 0; 413 aad[1] = 22; 414 *(uint16_t *)&aad[26] = 0; 415 *(uint32_t *)&aad[28] = 0; 416 } 417 418 static int 419 ccmp_encrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen) 420 { 421 struct ieee80211_frame *wh; 422 int rv, data_len; 423 uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN]; 424 uint8_t *pos; 425 CK_AES_CCM_PARAMS cmparam; 426 uint8_t buf[IEEE80211_MAX_LEN]; 427 428 wh = (struct ieee80211_frame *)mp->b_rptr; 429 data_len = MBLKL(mp) - (hdrlen + ccmp.ic_header); 430 pos = mp->b_rptr + hdrlen + ccmp.ic_header; 431 432 ccmp_init(wh, key->wk_keytsc, data_len, b0, aad); 433 434 cmparam.ulMACSize = IEEE80211_WEP_MICLEN; 435 cmparam.ulNonceSize = AES_NONCE_LEN; /* N size */ 436 cmparam.ulAuthDataSize = aad[1]; /* A size */ 437 cmparam.ulDataSize = data_len; /* data length; */ 438 cmparam.nonce = &b0[1]; /* N */ 439 cmparam.authData = &aad[2]; /* A */ 440 441 rv = aes_ccm_encrypt(&cmparam, 442 key->wk_key, key->wk_keylen, 443 pos, data_len, buf, data_len + IEEE80211_WEP_MICLEN); 444 445 bcopy(buf, pos, data_len + IEEE80211_WEP_MICLEN); 446 mp->b_wptr += ccmp.ic_trailer; 447 448 return ((rv == CRYPTO_SUCCESS)? 1 : 0); 449 } 450 451 static int 452 ccmp_decrypt(struct ieee80211_key *key, uint64_t pn, mblk_t *mp, int hdrlen) 453 { 454 struct ieee80211_frame *wh; 455 int rv, data_len; 456 uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN]; 457 uint8_t *pos; 458 CK_AES_CCM_PARAMS cmparam; 459 uint8_t buf[IEEE80211_MAX_LEN]; 460 461 wh = (struct ieee80211_frame *)mp->b_rptr; 462 data_len = MBLKL(mp) - (hdrlen + ccmp.ic_header); 463 pos = mp->b_rptr + hdrlen + ccmp.ic_header; 464 465 ccmp_init(wh, pn, data_len, b0, aad); 466 467 cmparam.ulMACSize = IEEE80211_WEP_MICLEN; /* MIC = 8 */ 468 cmparam.ulNonceSize = AES_NONCE_LEN; /* N size */ 469 cmparam.ulAuthDataSize = aad[1]; /* A size */ 470 cmparam.ulDataSize = data_len; 471 cmparam.nonce = &b0[1]; /* N */ 472 cmparam.authData = &aad[2]; /* A */ 473 474 rv = aes_ccm_decrypt(&cmparam, 475 key->wk_key, key->wk_keylen, pos, data_len, buf, data_len); 476 bcopy(buf, pos, data_len); 477 478 return ((rv == CRYPTO_SUCCESS)? 1 : 0); 479 } 480