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