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