1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "@(#)aes_cbc_crypt.c 1.9 08/05/09 SMI"
27
28
29 #include <sys/sysmacros.h>
30 #include <sys/systm.h>
31 #include <sys/crypto/common.h>
32 #include <sys/strsun.h>
33 #include "aes_cbc_crypt.h"
34 #include "aes_impl.h"
35 #ifndef _KERNEL
36 #include <limits.h>
37 #include <strings.h>
38 #endif /* !_KERNEL */
39
40 static int aes_ctr_ccm_mode_contiguous_blocks(aes_ctx_t *, char *, size_t,
41 crypto_data_t *);
42 static void
43 encode_adata_len(ulong_t auth_data_len, uint8_t *encoded, size_t *encoded_len);
44 static void
45 aes_ccm_format_initial_blocks(uchar_t *nonce, ulong_t nonceSize,
46 ulong_t authDataSize, uint8_t *b0, aes_ctx_t *aes_ctx);
47 static int
48 aes_ccm_decrypt_contiguous_blocks(aes_ctx_t *ctx, char *data, size_t length,
49 crypto_data_t *out);
50
51 /*
52 * Initialize by setting iov_or_mp to point to the current iovec or mp,
53 * and by setting current_offset to an offset within the current iovec or mp .
54 */
55 static void
56 aes_init_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset)
57 {
58 offset_t offset;
59
60 switch (out->cd_format) {
61 case CRYPTO_DATA_RAW:
62 *current_offset = out->cd_offset;
63 break;
64
65 case CRYPTO_DATA_UIO: {
66 uio_t *uiop = out->cd_uio;
67 uintptr_t vec_idx;
68
69 offset = out->cd_offset;
70 for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
71 offset >= uiop->uio_iov[vec_idx].iov_len;
72 offset -= uiop->uio_iov[vec_idx++].iov_len)
73 ;
74
75 *current_offset = offset;
76 *iov_or_mp = (void *)vec_idx;
77 break;
78 }
79
80 case CRYPTO_DATA_MBLK: {
81 mblk_t *mp;
82
83 offset = out->cd_offset;
84 for (mp = out->cd_mp; mp != NULL && offset >= MBLKL(mp);
85 offset -= MBLKL(mp), mp = mp->b_cont)
86 ;
87
88 *current_offset = offset;
89 *iov_or_mp = mp;
90 break;
91
92 }
93 } /* end switch */
94 }
95
96 /*
97 * Get pointers for where in the output to copy a block of encrypted or
98 * decrypted data. The iov_or_mp argument stores a pointer to the current
99 * iovec or mp, and offset stores an offset into the current iovec or mp.
100 */
101 static void
102 aes_get_ptrs(crypto_data_t *out, void **iov_or_mp, offset_t *current_offset,
103 uint8_t **out_data_1, size_t *out_data_1_len, uint8_t **out_data_2,
104 size_t amt)
105 {
106 offset_t offset;
107
108 switch (out->cd_format) {
109 case CRYPTO_DATA_RAW: {
110 iovec_t *iov;
111
112 offset = *current_offset;
113 iov = &out->cd_raw;
114 if ((offset + amt) <= iov->iov_len) {
115 /* one AES block fits */
116 *out_data_1 = (uint8_t *)iov->iov_base + offset;
117 *out_data_1_len = amt;
118 *out_data_2 = NULL;
119 *current_offset = offset + amt;
120 }
121 break;
122 }
123
124 case CRYPTO_DATA_UIO: {
125 uio_t *uio = out->cd_uio;
126 iovec_t *iov;
127 offset_t offset;
128 uintptr_t vec_idx;
129 uint8_t *p;
130
131 offset = *current_offset;
132 vec_idx = (uintptr_t)(*iov_or_mp);
133 iov = &uio->uio_iov[vec_idx];
134 p = (uint8_t *)iov->iov_base + offset;
135 *out_data_1 = p;
136
137 if (offset + amt <= iov->iov_len) {
138 /* can fit one AES block into this iov */
139 *out_data_1_len = amt;
140 *out_data_2 = NULL;
141 *current_offset = offset + amt;
142 } else {
143 /* one AES block spans two iovecs */
144 *out_data_1_len = iov->iov_len - offset;
145 if (vec_idx == uio->uio_iovcnt)
146 return;
147 vec_idx++;
148 iov = &uio->uio_iov[vec_idx];
149 *out_data_2 = (uint8_t *)iov->iov_base;
150 *current_offset = amt - *out_data_1_len;
151 }
152 *iov_or_mp = (void *)vec_idx;
153 break;
154 }
155
156 case CRYPTO_DATA_MBLK: {
157 mblk_t *mp;
158 uint8_t *p;
159
160 offset = *current_offset;
161 mp = (mblk_t *)*iov_or_mp;
162 p = mp->b_rptr + offset;
163 *out_data_1 = p;
164 if ((p + amt) <= mp->b_wptr) {
165 /* can fit one AES block into this mblk */
166 *out_data_1_len = amt;
167 *out_data_2 = NULL;
168 *current_offset = offset + amt;
169 } else {
170 /* one AES block spans two mblks */
171 *out_data_1_len = mp->b_wptr - p;
172 if ((mp = mp->b_cont) == NULL)
173 return;
174 *out_data_2 = mp->b_rptr;
175 *current_offset = (amt - *out_data_1_len);
176 }
177 *iov_or_mp = mp;
178 break;
179 }
180 } /* end switch */
181 }
182
183 static int
184 aes_cbc_encrypt_contiguous_blocks(aes_ctx_t *ctx, char *data, size_t length,
185 crypto_data_t *out)
186 {
187
188 /* EXPORT DELETE START */
189
190 size_t remainder = length;
191 size_t need;
192 uint8_t *datap = (uint8_t *)data;
193 uint8_t *blockp;
194 uint8_t *lastp;
195 uint32_t tmp[4];
196 void *iov_or_mp;
197 offset_t offset;
198 uint8_t *out_data_1;
199 uint8_t *out_data_2;
200 size_t out_data_1_len;
201
202 if (length + ctx->ac_remainder_len < AES_BLOCK_LEN) {
203 /* accumulate bytes here and return */
204 bcopy(datap,
205 (uint8_t *)ctx->ac_remainder + ctx->ac_remainder_len,
206 length);
207 ctx->ac_remainder_len += length;
208 ctx->ac_copy_to = datap;
209 return (0);
210 }
211
212 lastp = (uint8_t *)ctx->ac_iv;
213 if (out != NULL)
214 aes_init_ptrs(out, &iov_or_mp, &offset);
215
216 do {
217 /* Unprocessed data from last call. */
218 if (ctx->ac_remainder_len > 0) {
219 need = AES_BLOCK_LEN - ctx->ac_remainder_len;
220
221 if (need > remainder)
222 return (1);
223
224 bcopy(datap, &((uint8_t *)ctx->ac_remainder)
225 [ctx->ac_remainder_len], need);
226
227 blockp = (uint8_t *)ctx->ac_remainder;
228 } else {
229 blockp = datap;
230 }
231
232 /* don't write on the plaintext */
233 if (out != NULL) {
234 if (IS_P2ALIGNED(blockp, sizeof (uint32_t))) {
235 /* LINTED: pointer alignment */
236 tmp[0] = *(uint32_t *)blockp;
237 /* LINTED: pointer alignment */
238 tmp[1] = *(uint32_t *)&blockp[4];
239 /* LINTED: pointer alignment */
240 tmp[2] = *(uint32_t *)&blockp[8];
241 /* LINTED: pointer alignment */
242 tmp[3] = *(uint32_t *)&blockp[12];
243 } else {
244 uint8_t *tmp8 = (uint8_t *)tmp;
245
246 AES_COPY_BLOCK(blockp, tmp8);
247 }
248 blockp = (uint8_t *)tmp;
249 }
250
251 if (ctx->ac_flags & AES_CBC_MODE) {
252 /*
253 * XOR the previous cipher block or IV with the
254 * current clear block. Check for alignment.
255 */
256 if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
257 IS_P2ALIGNED(lastp, sizeof (uint32_t))) {
258 /* LINTED: pointer alignment */
259 *(uint32_t *)&blockp[0] ^=
260 /* LINTED: pointer alignment */
261 *(uint32_t *)&lastp[0];
262 /* LINTED: pointer alignment */
263 *(uint32_t *)&blockp[4] ^=
264 /* LINTED: pointer alignment */
265 *(uint32_t *)&lastp[4];
266 /* LINTED: pointer alignment */
267 *(uint32_t *)&blockp[8] ^=
268 /* LINTED: pointer alignment */
269 *(uint32_t *)&lastp[8];
270 /* LINTED: pointer alignment */
271 *(uint32_t *)&blockp[12] ^=
272 /* LINTED: pointer alignment */
273 *(uint32_t *)&lastp[12];
274 } else {
275 AES_XOR_BLOCK(lastp, blockp);
276 }
277 }
278
279 if (out == NULL) {
280 aes_encrypt_block(ctx->ac_keysched, blockp, blockp);
281
282 ctx->ac_lastp = blockp;
283 lastp = blockp;
284
285 if (ctx->ac_remainder_len > 0) {
286 bcopy(blockp, ctx->ac_copy_to,
287 ctx->ac_remainder_len);
288 bcopy(blockp + ctx->ac_remainder_len, datap,
289 need);
290 }
291 } else {
292 aes_encrypt_block(ctx->ac_keysched, blockp, lastp);
293 aes_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
294 &out_data_1_len, &out_data_2, AES_BLOCK_LEN);
295
296 /* copy block to where it belongs */
297 bcopy(lastp, out_data_1, out_data_1_len);
298 if (out_data_2 != NULL) {
299 bcopy(lastp + out_data_1_len, out_data_2,
300 AES_BLOCK_LEN - out_data_1_len);
301 }
302 /* update offset */
303 out->cd_offset += AES_BLOCK_LEN;
304 }
305
306 /* Update pointer to next block of data to be processed. */
307 if (ctx->ac_remainder_len != 0) {
308 datap += need;
309 ctx->ac_remainder_len = 0;
310 } else {
311 datap += AES_BLOCK_LEN;
312 }
313
314 remainder = (size_t)&data[length] - (size_t)datap;
315
316 /* Incomplete last block. */
317 if (remainder > 0 && remainder < AES_BLOCK_LEN) {
318 bcopy(datap, ctx->ac_remainder, remainder);
319 ctx->ac_remainder_len = remainder;
320 ctx->ac_copy_to = datap;
321 goto out;
322 }
323 ctx->ac_copy_to = NULL;
324
325 } while (remainder > 0);
326
327 out:
328 /*
329 * Save the last encrypted block in the context - but only for
330 * the CBC mode of operation.
331 */
332 if ((ctx->ac_flags & AES_CBC_MODE) && (ctx->ac_lastp != NULL)) {
333 uint8_t *iv8 = (uint8_t *)ctx->ac_iv;
334 uint8_t *last8 = (uint8_t *)ctx->ac_lastp;
335
336 if (IS_P2ALIGNED(ctx->ac_lastp, sizeof (uint32_t))) {
337 /* LINTED: pointer alignment */
338 *(uint32_t *)iv8 = *(uint32_t *)last8;
339 /* LINTED: pointer alignment */
340 *(uint32_t *)&iv8[4] = *(uint32_t *)&last8[4];
341 /* LINTED: pointer alignment */
342 *(uint32_t *)&iv8[8] = *(uint32_t *)&last8[8];
343 /* LINTED: pointer alignment */
344 *(uint32_t *)&iv8[12] = *(uint32_t *)&last8[12];
345 } else {
346 AES_COPY_BLOCK(last8, iv8);
347 }
348 ctx->ac_lastp = (uint8_t *)ctx->ac_iv;
349 }
350
351 /* EXPORT DELETE END */
352
353 return (0);
354 }
355
356 #define OTHER(a, ctx) \
357 (((a) == (ctx)->ac_lastblock) ? (ctx)->ac_iv : (ctx)->ac_lastblock)
358
359 /*
360 * Encrypt multiple blocks of data.
361 */
362 /* ARGSUSED */
363 int
364 aes_encrypt_contiguous_blocks(aes_ctx_t *ctx, char *data, size_t length,
365 crypto_data_t *out)
366 {
367 if (ctx->ac_flags & AES_CTR_MODE)
368 return (aes_ctr_ccm_mode_contiguous_blocks(ctx, data, length,
369 out));
370 else if (ctx->ac_flags & AES_CCM_MODE)
371 return (aes_ctr_ccm_mode_contiguous_blocks(ctx, data, length,
372 out));
373 return (aes_cbc_encrypt_contiguous_blocks(ctx, data, length, out));
374 }
375
376 /* ARGSUSED */
377 static int
378 aes_cbc_decrypt_contiguous_blocks(aes_ctx_t *ctx, char *data, size_t length,
379 crypto_data_t *out)
380 {
381
382 /* EXPORT DELETE START */
383
384 size_t remainder = length;
385 size_t need;
386 uint8_t *datap = (uint8_t *)data;
387 uint8_t *blockp;
388 uint8_t *lastp;
389 uint32_t tmp[4];
390 void *iov_or_mp;
391 offset_t offset;
392 uint8_t *out_data_1;
393 uint8_t *out_data_2;
394 size_t out_data_1_len;
395
396 if (length + ctx->ac_remainder_len < AES_BLOCK_LEN) {
397 /* accumulate bytes here and return */
398 bcopy(datap,
399 (uint8_t *)ctx->ac_remainder + ctx->ac_remainder_len,
400 length);
401 ctx->ac_remainder_len += length;
402 ctx->ac_copy_to = datap;
403 return (0);
404 }
405
406 lastp = ctx->ac_lastp;
407 if (out != NULL)
408 aes_init_ptrs(out, &iov_or_mp, &offset);
409
410 do {
411 /* Unprocessed data from last call. */
412 if (ctx->ac_remainder_len > 0) {
413 need = AES_BLOCK_LEN - ctx->ac_remainder_len;
414
415 if (need > remainder)
416 return (1);
417
418 bcopy(datap, &((uint8_t *)ctx->ac_remainder)
419 [ctx->ac_remainder_len], need);
420
421 blockp = (uint8_t *)ctx->ac_remainder;
422 } else {
423 blockp = datap;
424 }
425
426 if (ctx->ac_flags & AES_CBC_MODE) {
427
428 /* Save current ciphertext block */
429 if (IS_P2ALIGNED(blockp, sizeof (uint32_t))) {
430 uint32_t *tmp32;
431
432 /* LINTED: pointer alignment */
433 tmp32 = (uint32_t *)OTHER((uint64_t *)lastp,
434 ctx);
435
436 /* LINTED: pointer alignment */
437 *tmp32++ = *(uint32_t *)blockp;
438 /* LINTED: pointer alignment */
439 *tmp32++ = *(uint32_t *)&blockp[4];
440 /* LINTED: pointer alignment */
441 *tmp32++ = *(uint32_t *)&blockp[8];
442 /* LINTED: pointer alignment */
443 *tmp32++ = *(uint32_t *)&blockp[12];
444 } else {
445 uint8_t *tmp8;
446 /* LINTED: pointer alignment */
447 tmp8 = (uint8_t *)OTHER((uint64_t *)lastp, ctx);
448
449 AES_COPY_BLOCK(blockp, tmp8);
450 }
451 }
452
453 if (out != NULL) {
454 aes_decrypt_block(ctx->ac_keysched, blockp,
455 (uint8_t *)tmp);
456 blockp = (uint8_t *)tmp;
457 } else {
458 aes_decrypt_block(ctx->ac_keysched, blockp, blockp);
459 }
460
461 if (ctx->ac_flags & AES_CBC_MODE) {
462 /*
463 * XOR the previous cipher block or IV with the
464 * currently decrypted block. Check for alignment.
465 */
466 if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
467 IS_P2ALIGNED(lastp, sizeof (uint32_t))) {
468 /* LINTED: pointer alignment */
469 *(uint32_t *)blockp ^= *(uint32_t *)lastp;
470 /* LINTED: pointer alignment */
471 *(uint32_t *)&blockp[4] ^=
472 /* LINTED: pointer alignment */
473 *(uint32_t *)&lastp[4];
474 /* LINTED: pointer alignment */
475 *(uint32_t *)&blockp[8] ^=
476 /* LINTED: pointer alignment */
477 *(uint32_t *)&lastp[8];
478 /* LINTED: pointer alignment */
479 *(uint32_t *)&blockp[12] ^=
480 /* LINTED: pointer alignment */
481 *(uint32_t *)&lastp[12];
482 } else {
483 AES_XOR_BLOCK(lastp, blockp);
484 }
485
486 /* LINTED: pointer alignment */
487 lastp = (uint8_t *)OTHER((uint64_t *)lastp, ctx);
488 }
489
490 if (out != NULL) {
491 aes_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
492 &out_data_1_len, &out_data_2, AES_BLOCK_LEN);
493
494 /* copy temporary block to where it belongs */
495 bcopy(&tmp, out_data_1, out_data_1_len);
496 if (out_data_2 != NULL) {
497 bcopy((uint8_t *)&tmp + out_data_1_len,
498 out_data_2, AES_BLOCK_LEN - out_data_1_len);
499 }
500
501 /* update offset */
502 out->cd_offset += AES_BLOCK_LEN;
503
504 } else if (ctx->ac_remainder_len > 0) {
505 /* copy temporary block to where it belongs */
506 bcopy(blockp, ctx->ac_copy_to, ctx->ac_remainder_len);
507 bcopy(blockp + ctx->ac_remainder_len, datap, need);
508 }
509
510 /* Update pointer to next block of data to be processed. */
511 if (ctx->ac_remainder_len != 0) {
512 datap += need;
513 ctx->ac_remainder_len = 0;
514 } else {
515 datap += AES_BLOCK_LEN;
516 }
517
518 remainder = (size_t)&data[length] - (size_t)datap;
519
520 /* Incomplete last block. */
521 if (remainder > 0 && remainder < AES_BLOCK_LEN) {
522 bcopy(datap, ctx->ac_remainder, remainder);
523 ctx->ac_remainder_len = remainder;
524 ctx->ac_lastp = lastp;
525 ctx->ac_copy_to = datap;
526 return (0);
527 }
528 ctx->ac_copy_to = NULL;
529
530 } while (remainder > 0);
531
532 ctx->ac_lastp = lastp;
533
534 /* EXPORT DELETE END */
535
536 return (0);
537 }
538
539 /*
540 * Decrypt multiple blocks of data.
541 */
542 int
543 aes_decrypt_contiguous_blocks(aes_ctx_t *ctx, char *data, size_t length,
544 crypto_data_t *out)
545 {
546 if (ctx->ac_flags & AES_CTR_MODE)
547 return (aes_ctr_ccm_mode_contiguous_blocks(ctx, data, length,
548 out));
549 else if (ctx->ac_flags & AES_CCM_MODE)
550 return (aes_ccm_decrypt_contiguous_blocks(ctx, data, length,
551 out));
552 return (aes_cbc_decrypt_contiguous_blocks(ctx, data, length, out));
553 }
554
555 /* ARGSUSED */
556 int
557 aes_counter_final(aes_ctx_t *ctx, crypto_data_t *out)
558 {
559 /* EXPORT DELETE START */
560
561 uint8_t *lastp;
562 uint32_t counter_block[4];
563 uint8_t tmp[AES_BLOCK_LEN];
564 int i;
565 void *iov_or_mp;
566 offset_t offset;
567 uint8_t *out_data_1;
568 uint8_t *out_data_2;
569 size_t out_data_1_len;
570
571 if (out->cd_length < ctx->ac_remainder_len)
572 return (CRYPTO_ARGUMENTS_BAD);
573
574 /* ac_iv is the counter block */
575 aes_encrypt_block(ctx->ac_keysched, (uint8_t *)ctx->ac_iv,
576 (uint8_t *)counter_block);
577
578 lastp = (uint8_t *)counter_block;
579
580 /* copy remainder to temporary buffer */
581 bcopy(ctx->ac_remainder, tmp, ctx->ac_remainder_len);
582
583 /* XOR with counter block */
584 for (i = 0; i < ctx->ac_remainder_len; i++) {
585 tmp[i] ^= lastp[i];
586 }
587
588 aes_init_ptrs(out, &iov_or_mp, &offset);
589 aes_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
590 &out_data_1_len, &out_data_2, ctx->ac_remainder_len);
591
592 /* copy temporary block to where it belongs */
593 bcopy(tmp, out_data_1, out_data_1_len);
594 if (out_data_2 != NULL) {
595 bcopy((uint8_t *)tmp + out_data_1_len,
596 out_data_2, ctx->ac_remainder_len - out_data_1_len);
597 }
598 out->cd_offset += ctx->ac_remainder_len;
599 ctx->ac_remainder_len = 0;
600
601 /* EXPORT DELETE END */
602
603 return (0);
604 }
605
606 /*
607 * Encrypt and decrypt multiple blocks of data in counter mode.
608 * Encrypt multiple blocks of data in CCM mode. Decrypt for CCM mode
609 * is done in another function.
610 */
611 /* ARGSUSED */
612 int
613 aes_ctr_ccm_mode_contiguous_blocks(aes_ctx_t *ctx, char *data, size_t length,
614 crypto_data_t *out)
615 {
616
617 /* EXPORT DELETE START */
618
619 size_t remainder = length;
620 size_t need;
621 uint8_t *datap = (uint8_t *)data;
622 uint8_t *blockp;
623 uint8_t *lastp;
624 uint32_t tmp[4];
625 uint32_t counter_block[4];
626 void *iov_or_mp;
627 offset_t offset;
628 uint8_t *out_data_1;
629 uint8_t *out_data_2;
630 size_t out_data_1_len;
631 uint64_t counter;
632 uint8_t *mac_buf;
633 #ifdef _LITTLE_ENDIAN
634 uint8_t *p;
635 #endif
636
637 if (length + ctx->ac_remainder_len < AES_BLOCK_LEN) {
638 /* accumulate bytes here and return */
639 bcopy(datap,
640 (uint8_t *)ctx->ac_remainder + ctx->ac_remainder_len,
641 length);
642 ctx->ac_remainder_len += length;
643 ctx->ac_copy_to = datap;
644 return (0);
645 }
646
647 lastp = (uint8_t *)ctx->ac_cb;
648 if (out != NULL)
649 aes_init_ptrs(out, &iov_or_mp, &offset);
650
651 if (ctx->ac_flags & AES_CCM_MODE) {
652 mac_buf = (uint8_t *)ctx->ac_ccm_mac_buf;
653 }
654
655 do {
656 /* Unprocessed data from last call. */
657 if (ctx->ac_remainder_len > 0) {
658 need = AES_BLOCK_LEN - ctx->ac_remainder_len;
659
660 if (need > remainder)
661 return (1);
662
663 bcopy(datap, &((uint8_t *)ctx->ac_remainder)
664 [ctx->ac_remainder_len], need);
665
666 blockp = (uint8_t *)ctx->ac_remainder;
667 } else {
668 blockp = datap;
669 }
670
671 /* don't write on the plaintext */
672 if (out != NULL) {
673 if (IS_P2ALIGNED(blockp, sizeof (uint32_t))) {
674 /* LINTED: pointer alignment */
675 tmp[0] = *(uint32_t *)blockp;
676 /* LINTED: pointer alignment */
677 tmp[1] = *(uint32_t *)&blockp[4];
678 /* LINTED: pointer alignment */
679 tmp[2] = *(uint32_t *)&blockp[8];
680 /* LINTED: pointer alignment */
681 tmp[3] = *(uint32_t *)&blockp[12];
682 } else {
683 uint8_t *tmp8 = (uint8_t *)tmp;
684
685 AES_COPY_BLOCK(blockp, tmp8);
686 }
687 blockp = (uint8_t *)tmp;
688 }
689
690 if (ctx->ac_flags & AES_CCM_MODE) {
691 /*
692 * do CBC MAC
693 *
694 * XOR the previous cipher block current clear block.
695 * mac_buf always contain previous cipher block.
696 */
697 if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
698 IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
699 /* LINTED: pointer alignment */
700 *(uint32_t *)&mac_buf[0] ^=
701 /* LINTED: pointer alignment */
702 *(uint32_t *)&blockp[0];
703 /* LINTED: pointer alignment */
704 *(uint32_t *)&mac_buf[4] ^=
705 /* LINTED: pointer alignment */
706 *(uint32_t *)&blockp[4];
707 /* LINTED: pointer alignment */
708 *(uint32_t *)&mac_buf[8] ^=
709 /* LINTED: pointer alignment */
710 *(uint32_t *)&blockp[8];
711 /* LINTED: pointer alignment */
712 *(uint32_t *)&mac_buf[12] ^=
713 /* LINTED: pointer alignment */
714 *(uint32_t *)&blockp[12];
715 } else {
716 AES_XOR_BLOCK(blockp, mac_buf);
717 }
718 aes_encrypt_block(ctx->ac_keysched, mac_buf, mac_buf);
719 }
720
721
722 /* ac_cb is the counter block */
723 aes_encrypt_block(ctx->ac_keysched, (uint8_t *)ctx->ac_cb,
724 (uint8_t *)counter_block);
725
726 lastp = (uint8_t *)counter_block;
727
728 /*
729 * Increment counter. Counter bits are confined
730 * to the bottom 64 bits of the counter block.
731 */
732 counter = ctx->ac_cb[1] & ctx->ac_counter_mask;
733 #ifdef _LITTLE_ENDIAN
734 p = (uint8_t *)&counter;
735 counter = (((uint64_t)p[0] << 56) |
736 ((uint64_t)p[1] << 48) |
737 ((uint64_t)p[2] << 40) |
738 ((uint64_t)p[3] << 32) |
739 ((uint64_t)p[4] << 24) |
740 ((uint64_t)p[5] << 16) |
741 ((uint64_t)p[6] << 8) |
742 (uint64_t)p[7]);
743 #endif
744 counter++;
745 #ifdef _LITTLE_ENDIAN
746 counter = (((uint64_t)p[0] << 56) |
747 ((uint64_t)p[1] << 48) |
748 ((uint64_t)p[2] << 40) |
749 ((uint64_t)p[3] << 32) |
750 ((uint64_t)p[4] << 24) |
751 ((uint64_t)p[5] << 16) |
752 ((uint64_t)p[6] << 8) |
753 (uint64_t)p[7]);
754 #endif
755 counter &= ctx->ac_counter_mask;
756 ctx->ac_cb[1] =
757 (ctx->ac_cb[1] & ~(ctx->ac_counter_mask)) | counter;
758
759 /*
760 * XOR the previous cipher block or IV with the
761 * current clear block. Check for alignment.
762 */
763 if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
764 IS_P2ALIGNED(lastp, sizeof (uint32_t))) {
765 /* LINTED: pointer alignment */
766 *(uint32_t *)&blockp[0] ^=
767 /* LINTED: pointer alignment */
768 *(uint32_t *)&lastp[0];
769 /* LINTED: pointer alignment */
770 *(uint32_t *)&blockp[4] ^=
771 /* LINTED: pointer alignment */
772 *(uint32_t *)&lastp[4];
773 /* LINTED: pointer alignment */
774 *(uint32_t *)&blockp[8] ^=
775 /* LINTED: pointer alignment */
776 *(uint32_t *)&lastp[8];
777 /* LINTED: pointer alignment */
778 *(uint32_t *)&blockp[12] ^=
779 /* LINTED: pointer alignment */
780 *(uint32_t *)&lastp[12];
781 } else {
782 AES_XOR_BLOCK(lastp, blockp);
783 }
784
785 ctx->ac_lastp = blockp;
786 lastp = blockp;
787 if (ctx->ac_flags & AES_CCM_MODE) {
788 ctx->ac_ccm_processed_data_len += AES_BLOCK_LEN;
789 }
790
791 if (out == NULL) {
792 if (ctx->ac_remainder_len > 0) {
793 bcopy(blockp, ctx->ac_copy_to,
794 ctx->ac_remainder_len);
795 bcopy(blockp + ctx->ac_remainder_len, datap,
796 need);
797 }
798 } else {
799 aes_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
800 &out_data_1_len, &out_data_2, AES_BLOCK_LEN);
801
802 /* copy block to where it belongs */
803 bcopy(lastp, out_data_1, out_data_1_len);
804 if (out_data_2 != NULL) {
805 bcopy(lastp + out_data_1_len, out_data_2,
806 AES_BLOCK_LEN - out_data_1_len);
807 }
808 /* update offset */
809 out->cd_offset += AES_BLOCK_LEN;
810 }
811
812 /* Update pointer to next block of data to be processed. */
813 if (ctx->ac_remainder_len != 0) {
814 datap += need;
815 ctx->ac_remainder_len = 0;
816 } else {
817 datap += AES_BLOCK_LEN;
818 }
819
820 remainder = (size_t)&data[length] - (size_t)datap;
821
822 /* Incomplete last block. */
823 if (remainder > 0 && remainder < AES_BLOCK_LEN) {
824 bcopy(datap, ctx->ac_remainder, remainder);
825 ctx->ac_remainder_len = remainder;
826 ctx->ac_copy_to = datap;
827 goto out;
828 }
829 ctx->ac_copy_to = NULL;
830
831 } while (remainder > 0);
832
833 out:
834
835 /* EXPORT DELETE END */
836
837 return (0);
838 }
839
840 /*
841 * The following function should be call at encrypt or decrypt init time
842 * for AES CCM mode.
843 */
844 int
845 aes_ccm_init(aes_ctx_t *ctx, unsigned char *nonce, size_t nonce_len,
846 unsigned char *auth_data, size_t auth_data_len)
847 {
848 /* EXPORT DELETE START */
849 uint8_t *mac_buf, *datap, *ivp, *authp;
850 uint32_t iv[4], tmp[4];
851 size_t remainder, processed;
852 uint8_t encoded_a[10]; /* max encoded auth data length is 10 octets */
853 size_t encoded_a_len = 0;
854
855 mac_buf = (uint8_t *)&(ctx->ac_ccm_mac_buf);
856
857 /*
858 * Format the 1st block for CBC-MAC and construct the
859 * 1st counter block.
860 *
861 * aes_ctx->ac_iv is used for storing the counter block
862 * mac_buf will store b0 at this time.
863 */
864 aes_ccm_format_initial_blocks(nonce, nonce_len,
865 auth_data_len, mac_buf, ctx);
866
867 /* The IV for CBC MAC for AES CCM mode is always zero */
868 bzero(iv, AES_BLOCK_LEN);
869 ivp = (uint8_t *)iv;
870
871 if (IS_P2ALIGNED(ivp, sizeof (uint32_t)) &&
872 IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
873 /* LINTED: pointer alignment */
874 *(uint32_t *)&mac_buf[0] ^= *(uint32_t *)&ivp[0];
875 /* LINTED: pointer alignment */
876 *(uint32_t *)&mac_buf[4] ^= *(uint32_t *)&ivp[4];
877 /* LINTED: pointer alignment */
878 *(uint32_t *)&mac_buf[8] ^= *(uint32_t *)&ivp[8];
879 /* LINTED: pointer alignment */
880 *(uint32_t *)&mac_buf[12] ^= *(uint32_t *)&ivp[12];
881 } else {
882 AES_XOR_BLOCK(ivp, mac_buf);
883 }
884
885 /* encrypt the nonce */
886 aes_encrypt_block(ctx->ac_keysched, mac_buf, mac_buf);
887
888 /* take care of the associated data, if any */
889 if (auth_data_len == 0) {
890 return (0);
891 }
892
893 encode_adata_len(auth_data_len, encoded_a, &encoded_a_len);
894
895 remainder = auth_data_len;
896
897 /* 1st block: it contains encoded associated data, and some data */
898 authp = (uint8_t *)tmp;
899 bzero(authp, AES_BLOCK_LEN);
900 bcopy(encoded_a, authp, encoded_a_len);
901 processed = AES_BLOCK_LEN - encoded_a_len;
902 if (processed > auth_data_len) {
903 /* in case auth_data is very small */
904 processed = auth_data_len;
905 }
906 bcopy(auth_data, authp+encoded_a_len, processed);
907 /* xor with previous buffer */
908 if (IS_P2ALIGNED(authp, sizeof (uint32_t)) &&
909 IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
910 /* LINTED: pointer alignment */
911 *(uint32_t *)&mac_buf[0] ^= *(uint32_t *)&authp[0];
912 /* LINTED: pointer alignment */
913 *(uint32_t *)&mac_buf[4] ^= *(uint32_t *)&authp[4];
914 /* LINTED: pointer alignment */
915 *(uint32_t *)&mac_buf[8] ^= *(uint32_t *)&authp[8];
916 /* LINTED: pointer alignment */
917 *(uint32_t *)&mac_buf[12] ^= *(uint32_t *)&authp[12];
918 } else {
919 AES_XOR_BLOCK(authp, mac_buf);
920 }
921 aes_encrypt_block(ctx->ac_keysched, mac_buf, mac_buf);
922 remainder -= processed;
923 if (remainder == 0) {
924 /* a small amount of associated data, it's all done now */
925 return (0);
926 }
927
928 do {
929 if (remainder < AES_BLOCK_LEN) {
930 /*
931 * There's not a block full of data, pad rest of
932 * buffer with zero
933 */
934 bzero(authp, AES_BLOCK_LEN);
935 bcopy(&(auth_data[processed]), authp, remainder);
936 datap = (uint8_t *)authp;
937 remainder = 0;
938 } else {
939 datap = (uint8_t *)(&(auth_data[processed]));
940 processed += AES_BLOCK_LEN;
941 remainder -= AES_BLOCK_LEN;
942 }
943
944 /* xor with previous buffer */
945 if (IS_P2ALIGNED(datap, sizeof (uint32_t)) &&
946 IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
947 /* LINTED: pointer alignment */
948 *(uint32_t *)&mac_buf[0] ^= *(uint32_t *)&datap[0];
949 /* LINTED: pointer alignment */
950 *(uint32_t *)&mac_buf[4] ^= *(uint32_t *)&datap[4];
951 /* LINTED: pointer alignment */
952 *(uint32_t *)&mac_buf[8] ^= *(uint32_t *)&datap[8];
953 /* LINTED: pointer alignment */
954 *(uint32_t *)&mac_buf[12] ^= *(uint32_t *)&datap[12];
955 } else {
956 AES_XOR_BLOCK(datap, mac_buf);
957 }
958
959 aes_encrypt_block(ctx->ac_keysched, mac_buf, mac_buf);
960
961 } while (remainder > 0);
962
963 /* EXPORT DELETE END */
964 return (0);
965 }
966
967 void
968 calculate_ccm_mac(aes_ctx_t *ctx, uint8_t **ccm_mac)
969 {
970 /* EXPORT DELETE START */
971 uint64_t counter;
972 uint32_t counter_block[4];
973 uint8_t *counterp, *mac_buf;
974 int i;
975
976 mac_buf = (uint8_t *)ctx->ac_ccm_mac_buf;
977
978 /* first counter block start with index 0 */
979 counter = 0;
980 ctx->ac_cb[1] = (ctx->ac_cb[1] & ~(ctx->ac_counter_mask)) | counter;
981
982 aes_encrypt_block(ctx->ac_keysched, (uint8_t *)ctx->ac_cb,
983 (uint8_t *)counter_block);
984
985 counterp = (uint8_t *)counter_block;
986
987 /* calculate XOR of MAC with first counter block */
988 for (i = 0; i < ctx->ac_ccm_mac_len; i++) {
989 (*ccm_mac)[i] = mac_buf[i] ^ counterp[i];
990 }
991 /* EXPORT DELETE END */
992 }
993
994 /* ARGSUSED */
995 int
996 aes_ccm_encrypt_final(aes_ctx_t *ctx, crypto_data_t *out)
997 {
998 /* EXPORT DELETE START */
999
1000 uint8_t *lastp, *mac_buf, *ccm_mac_p, *macp;
1001 uint32_t counter_block[4];
1002 uint32_t tmp[4];
1003 uint8_t ccm_mac[AES_BLOCK_LEN];
1004 void *iov_or_mp;
1005 offset_t offset;
1006 uint8_t *out_data_1;
1007 uint8_t *out_data_2;
1008 size_t out_data_1_len;
1009 int i;
1010
1011 if (out->cd_length < (ctx->ac_remainder_len + ctx->ac_ccm_mac_len)) {
1012 return (CRYPTO_ARGUMENTS_BAD);
1013 }
1014
1015 /*
1016 * When we get here, the number of bytes of payload processed
1017 * plus whatever data remains, if any,
1018 * should be the same as the number of bytes that's being
1019 * passed in the argument during init time.
1020 */
1021 if ((ctx->ac_ccm_processed_data_len + ctx->ac_remainder_len)
1022 != (ctx->ac_ccm_data_len)) {
1023 return (CRYPTO_DATA_LEN_RANGE);
1024 }
1025
1026 mac_buf = (uint8_t *)ctx->ac_ccm_mac_buf;
1027
1028 if (ctx->ac_remainder_len > 0) {
1029
1030 macp = (uint8_t *)tmp;
1031 bzero(macp, AES_BLOCK_LEN);
1032
1033 /* copy remainder to temporary buffer */
1034 bcopy(ctx->ac_remainder, macp, ctx->ac_remainder_len);
1035
1036 /* calculate the CBC MAC */
1037 if (IS_P2ALIGNED(macp, sizeof (uint32_t)) &&
1038 IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
1039 /* LINTED: pointer alignment */
1040 *(uint32_t *)&mac_buf[0] ^= *(uint32_t *)&macp[0];
1041 /* LINTED: pointer alignment */
1042 *(uint32_t *)&mac_buf[4] ^= *(uint32_t *)&macp[4];
1043 /* LINTED: pointer alignment */
1044 *(uint32_t *)&mac_buf[8] ^= *(uint32_t *)&macp[8];
1045 /* LINTED: pointer alignment */
1046 *(uint32_t *)&mac_buf[12] ^= *(uint32_t *)&macp[12];
1047 } else {
1048 AES_XOR_BLOCK(macp, mac_buf);
1049 }
1050 aes_encrypt_block(ctx->ac_keysched, mac_buf, mac_buf);
1051
1052 /* calculate the counter mode */
1053 aes_encrypt_block(ctx->ac_keysched, (uint8_t *)ctx->ac_cb,
1054 (uint8_t *)counter_block);
1055
1056 lastp = (uint8_t *)counter_block;
1057
1058 /* copy remainder to temporary buffer */
1059 bcopy(ctx->ac_remainder, macp, ctx->ac_remainder_len);
1060
1061 /* XOR with counter block */
1062 for (i = 0; i < ctx->ac_remainder_len; i++) {
1063 macp[i] ^= lastp[i];
1064 }
1065 ctx->ac_ccm_processed_data_len += ctx->ac_remainder_len;
1066 }
1067
1068 /* Calculate the CCM MAC */
1069 ccm_mac_p = ccm_mac;
1070 calculate_ccm_mac(ctx, &ccm_mac_p);
1071
1072 aes_init_ptrs(out, &iov_or_mp, &offset);
1073 aes_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
1074 &out_data_1_len, &out_data_2,
1075 ctx->ac_remainder_len + ctx->ac_ccm_mac_len);
1076
1077 if (ctx->ac_remainder_len > 0) {
1078
1079 /* copy temporary block to where it belongs */
1080 if (out_data_2 == NULL) {
1081 /* everything will fit in out_data_1 */
1082 bcopy(macp, out_data_1, ctx->ac_remainder_len);
1083 bcopy(ccm_mac, out_data_1 + ctx->ac_remainder_len,
1084 ctx->ac_ccm_mac_len);
1085 } else {
1086
1087 if (out_data_1_len < ctx->ac_remainder_len) {
1088
1089 size_t data_2_len_used;
1090
1091 bcopy(macp, out_data_1, out_data_1_len);
1092
1093 data_2_len_used = ctx->ac_remainder_len
1094 - out_data_1_len;
1095
1096 bcopy((uint8_t *)macp + out_data_1_len,
1097 out_data_2, data_2_len_used);
1098 bcopy(ccm_mac, out_data_2 + data_2_len_used,
1099 ctx->ac_ccm_mac_len);
1100 } else {
1101 bcopy(macp, out_data_1, out_data_1_len);
1102 if (out_data_1_len == ctx->ac_remainder_len) {
1103 /* mac will be in out_data_2 */
1104 bcopy(ccm_mac, out_data_2,
1105 ctx->ac_ccm_mac_len);
1106 } else {
1107 size_t len_not_used
1108 = out_data_1_len -
1109 ctx->ac_remainder_len;
1110 /*
1111 * part of mac in will be in
1112 * out_data_1, part of the mac will be
1113 * in out_data_2
1114 */
1115 bcopy(ccm_mac,
1116 out_data_1 + ctx->ac_remainder_len,
1117 len_not_used);
1118 bcopy(ccm_mac+len_not_used, out_data_2,
1119 ctx->ac_ccm_mac_len - len_not_used);
1120
1121 }
1122 }
1123 }
1124 } else {
1125 /* copy block to where it belongs */
1126 bcopy(ccm_mac, out_data_1, out_data_1_len);
1127 if (out_data_2 != NULL) {
1128 bcopy(ccm_mac + out_data_1_len, out_data_2,
1129 AES_BLOCK_LEN - out_data_1_len);
1130 }
1131 }
1132 out->cd_offset += ctx->ac_remainder_len + ctx->ac_ccm_mac_len;
1133 ctx->ac_remainder_len = 0;
1134
1135 /* EXPORT DELETE END */
1136
1137 return (0);
1138 }
1139
1140 int
1141 aes_ccm_validate_args(CK_AES_CCM_PARAMS *ccm_param, boolean_t is_encrypt_init)
1142 {
1143
1144 /* EXPORT DELETE START */
1145 size_t macSize, nonceSize;
1146 uint8_t q;
1147 uint64_t maxValue;
1148
1149 /*
1150 * Check the length of the MAC. Only valid length
1151 * lengths for the MAC are: 4, 6, 8, 10, 12, 14, 16
1152 */
1153 macSize = ccm_param->ulMACSize;
1154 if ((macSize < 4) || (macSize > 16) || ((macSize % 2) != 0)) {
1155 return (CRYPTO_MECHANISM_PARAM_INVALID);
1156 }
1157
1158 /* Check the nonce value. Valid values are 7, 8, 9, 10, 11, 12, 13 */
1159 nonceSize = ccm_param->ulNonceSize;
1160 if ((nonceSize < 7) || (nonceSize > 13)) {
1161 return (CRYPTO_MECHANISM_PARAM_INVALID);
1162 }
1163
1164 q = (uint8_t)((15 - nonceSize) & 0xFF);
1165
1166
1167 /*
1168 * If it is decrypt, need to make sure size of ciphertext is at least
1169 * bigger than MAC len
1170 */
1171 if ((!is_encrypt_init) && (ccm_param->ulDataSize < macSize)) {
1172 return (CRYPTO_MECHANISM_PARAM_INVALID);
1173 }
1174
1175 /*
1176 * Check to make sure the length of the payload is within the
1177 * range of values allowed by q
1178 */
1179 if (q < 8) {
1180 maxValue = 1ULL << (q * 8);
1181 } else {
1182 maxValue = ULONG_MAX;
1183 }
1184
1185 if (ccm_param->ulDataSize > maxValue) {
1186 return (CRYPTO_MECHANISM_PARAM_INVALID);
1187 }
1188
1189 /* EXPORT DELETE END */
1190 return (0);
1191 }
1192
1193 /*
1194 * Format the first block used in CBC-MAC (B0) and the initial counter
1195 * block based on formating functions and counter generation functions
1196 * specified in RFC 3610 and NIST publication 800-38C, appendix A
1197 *
1198 * b0 is the first block used in CBC-MAC
1199 * cb0 is the first counter block
1200 *
1201 * It's assumed that the arguments b0 and cb0 are preallocated AES blocks
1202 *
1203 */
1204 static void
1205 aes_ccm_format_initial_blocks(uchar_t *nonce, ulong_t nonceSize,
1206 ulong_t authDataSize, uint8_t *b0, aes_ctx_t *aes_ctx)
1207 {
1208 /* EXPORT DELETE START */
1209 uint64_t payloadSize;
1210 uint8_t t, q, have_adata = 0;
1211 size_t limit;
1212 int i, j, k;
1213 uint64_t mask = 0;
1214 uint8_t *cb;
1215 #ifdef _LITTLE_ENDIAN
1216 uint8_t *p8;
1217 #endif /* _LITTLE_ENDIAN */
1218
1219 q = (uint8_t)((15 - nonceSize) & 0xFF);
1220 t = (uint8_t)((aes_ctx->ac_ccm_mac_len) & 0xFF);
1221
1222 /* Construct the first octect of b0 */
1223 if (authDataSize > 0) {
1224 have_adata = 1;
1225 }
1226 b0[0] = (have_adata << 6) | (((t - 2) / 2) << 3) | (q - 1);
1227
1228 /* copy the nonce value into b0 */
1229 bcopy(nonce, &(b0[1]), nonceSize);
1230
1231 /* store the length of the payload into b0 */
1232 bzero(&(b0[1+nonceSize]), q);
1233
1234 payloadSize = aes_ctx->ac_ccm_data_len;
1235 limit = 8 < q ? 8 : q;
1236
1237 for (i = 0, j = 0, k = 15; i < limit; i++, j += 8, k--) {
1238 b0[k] = (uint8_t)((payloadSize >> j) & 0xFF);
1239 }
1240
1241 /* format the counter block */
1242
1243 cb = (uint8_t *)aes_ctx->ac_cb;
1244
1245 cb[0] = 0x07 & (q-1); /* first byte */
1246
1247 /* copy the nonce value into the counter block */
1248 bcopy(nonce, &(cb[1]), nonceSize);
1249
1250 bzero(&(cb[1+nonceSize]), q);
1251
1252 /* Create the mask for the counter field based on the size of nonce */
1253 q <<= 3;
1254 while (q-- > 0) {
1255 mask |= (1ULL << q);
1256 }
1257
1258 #ifdef _LITTLE_ENDIAN
1259 p8 = (uint8_t *)&mask;
1260 mask = (((uint64_t)p8[0] << 56) |
1261 ((uint64_t)p8[1] << 48) |
1262 ((uint64_t)p8[2] << 40) |
1263 ((uint64_t)p8[3] << 32) |
1264 ((uint64_t)p8[4] << 24) |
1265 ((uint64_t)p8[5] << 16) |
1266 ((uint64_t)p8[6] << 8) |
1267 (uint64_t)p8[7]);
1268 #endif
1269 aes_ctx->ac_counter_mask = mask;
1270
1271 /*
1272 * During calculation, we start using counter block 1, we will
1273 * set it up right here.
1274 * We can just set the last byte to have the value 1, because
1275 * even with the bigest nonce of 13, the last byte of the
1276 * counter block will be used for the counter value.
1277 */
1278 cb[15] = 0x01;
1279
1280 /* EXPORT DELETE END */
1281
1282 }
1283
1284 /*
1285 * Encode the length of the associated data as
1286 * specified in RFC 3610 and NIST publication 800-38C, appendix A
1287 */
1288 static void
1289 encode_adata_len(ulong_t auth_data_len, uint8_t *encoded, size_t *encoded_len)
1290 {
1291
1292 /* EXPORT DELETE START */
1293
1294 if (auth_data_len < ((1ULL<<16) - (1ULL<<8))) {
1295 /* 0 < a < (2^16-2^8) */
1296 *encoded_len = 2;
1297 encoded[0] = (auth_data_len & 0xff00) >> 8;
1298 encoded[1] = auth_data_len & 0xff;
1299
1300 } else if ((auth_data_len >= ((1ULL<<16) - (1ULL<<8))) &&
1301 (auth_data_len < (1ULL << 31))) {
1302 /* (2^16-2^8) <= a < 2^32 */
1303 *encoded_len = 6;
1304 encoded[0] = 0xff;
1305 encoded[1] = 0xfe;
1306 encoded[2] = (auth_data_len & 0xff000000) >> 24;
1307 encoded[3] = (auth_data_len & 0xff0000) >> 16;
1308 encoded[4] = (auth_data_len & 0xff00) >> 8;
1309 encoded[5] = auth_data_len & 0xff;
1310 #ifdef _LP64
1311 } else {
1312 /* 2^32 <= a < 2^64 */
1313 *encoded_len = 10;
1314 encoded[0] = 0xff;
1315 encoded[1] = 0xff;
1316 encoded[2] = (auth_data_len & 0xff00000000000000) >> 56;
1317 encoded[3] = (auth_data_len & 0xff000000000000) >> 48;
1318 encoded[4] = (auth_data_len & 0xff0000000000) >> 40;
1319 encoded[5] = (auth_data_len & 0xff00000000) >> 32;
1320 encoded[6] = (auth_data_len & 0xff000000) >> 24;
1321 encoded[7] = (auth_data_len & 0xff0000) >> 16;
1322 encoded[8] = (auth_data_len & 0xff00) >> 8;
1323 encoded[9] = auth_data_len & 0xff;
1324 #endif /* _LP64 */
1325 }
1326 /* EXPORT DELETE END */
1327 }
1328
1329 /*
1330 * This will only deal with decrypting the last block of the input that
1331 * might not be multiples of AES_BLOCK_LEN
1332 */
1333 static void
1334 aes_ccm_decrypt_incomplete_block(aes_ctx_t *ctx)
1335 {
1336
1337 /* EXPORT DELETE START */
1338 uint8_t *datap, counter_block[AES_BLOCK_LEN], *outp, *counterp;
1339 int i;
1340
1341 datap = (uint8_t *)ctx->ac_remainder;
1342 outp = &((ctx->ac_ccm_pt_buf)[ctx->ac_ccm_processed_data_len]);
1343
1344 aes_encrypt_block(ctx->ac_keysched, (uint8_t *)ctx->ac_cb,
1345 counter_block);
1346
1347 counterp = (uint8_t *)counter_block;
1348
1349 /* XOR with counter block */
1350 for (i = 0; i < ctx->ac_remainder_len; i++) {
1351 outp[i] = datap[i] ^ counterp[i];
1352 }
1353 /* EXPORT DELETE END */
1354 }
1355
1356 /*
1357 * This will decrypt the cipher text. However, the plaintext won't be
1358 * returned to the caller. It will be returned when decrypt_final() is
1359 * called if the MAC matches
1360 */
1361 /* ARGSUSED */
1362 static int
1363 aes_ccm_decrypt_contiguous_blocks(aes_ctx_t *ctx, char *data, size_t length,
1364 crypto_data_t *out)
1365 {
1366
1367 /* EXPORT DELETE START */
1368
1369 size_t remainder = length;
1370 size_t need;
1371 uint8_t *datap = (uint8_t *)data;
1372 uint8_t *blockp;
1373 uint32_t counter_block[4];
1374 uint8_t *cbp;
1375 uint64_t counter;
1376 size_t pt_len, total_decrypted_len, mac_len, pm_len, pd_len;
1377 uint32_t tmp[4];
1378 uint8_t *resultp;
1379 #ifdef _LITTLE_ENDIAN
1380 uint8_t *p;
1381 #endif /* _LITTLE_ENDIAN */
1382
1383
1384 pm_len = ctx->ac_ccm_processed_mac_len;
1385
1386 if (pm_len > 0) {
1387 uint8_t *tmp;
1388 /*
1389 * all ciphertext has been processed, just waiting for
1390 * part of the value of the mac
1391 */
1392 if ((pm_len + length) > ctx->ac_ccm_mac_len) {
1393 return (CRYPTO_DATA_LEN_RANGE);
1394 }
1395 tmp = (uint8_t *)ctx->ac_ccm_mac_input_buf;
1396
1397 bcopy(datap, tmp + pm_len, length);
1398
1399 ctx->ac_ccm_processed_mac_len += length;
1400 return (0);
1401 }
1402
1403 /*
1404 * If we decrypt the given data, what total amount of data would
1405 * have been decrypted?
1406 */
1407 pd_len = ctx->ac_ccm_processed_data_len;
1408 total_decrypted_len = pd_len + length + ctx->ac_remainder_len;
1409
1410 if (total_decrypted_len >
1411 (ctx->ac_ccm_data_len + ctx->ac_ccm_mac_len)) {
1412 return (CRYPTO_DATA_LEN_RANGE);
1413 }
1414
1415 pt_len = ctx->ac_ccm_data_len;
1416
1417 if (total_decrypted_len > pt_len) {
1418 /*
1419 * part of the input will be the MAC, need to isolate that
1420 * to be dealt with later. The left-over data in
1421 * ac_remainder_len from last time will not be part of the
1422 * MAC. Otherwise, it would have already been taken out
1423 * when this call is made last time.
1424 */
1425 size_t pt_part = pt_len - pd_len - ctx->ac_remainder_len;
1426
1427 mac_len = length - pt_part;
1428
1429 ctx->ac_ccm_processed_mac_len = mac_len;
1430 bcopy(data + pt_part, ctx->ac_ccm_mac_input_buf, mac_len);
1431
1432 if (pt_part + ctx->ac_remainder_len < AES_BLOCK_LEN) {
1433 /*
1434 * since this is last of the ciphertext, will
1435 * just decrypt with it here
1436 */
1437 bcopy(datap, &((uint8_t *)ctx->ac_remainder)
1438 [ctx->ac_remainder_len], pt_part);
1439 ctx->ac_remainder_len += pt_part;
1440 aes_ccm_decrypt_incomplete_block(ctx);
1441 ctx->ac_remainder_len = 0;
1442 ctx->ac_ccm_processed_data_len += pt_part;
1443 return (0);
1444 } else {
1445 /* let rest of the code handle this */
1446 length = pt_part;
1447 }
1448 } else if (length + ctx->ac_remainder_len < AES_BLOCK_LEN) {
1449 /* accumulate bytes here and return */
1450 bcopy(datap,
1451 (uint8_t *)ctx->ac_remainder + ctx->ac_remainder_len,
1452 length);
1453 ctx->ac_remainder_len += length;
1454 ctx->ac_copy_to = datap;
1455 return (0);
1456 }
1457
1458 do {
1459 /* Unprocessed data from last call. */
1460 if (ctx->ac_remainder_len > 0) {
1461 need = AES_BLOCK_LEN - ctx->ac_remainder_len;
1462
1463 if (need > remainder)
1464 return (1);
1465
1466 bcopy(datap, &((uint8_t *)ctx->ac_remainder)
1467 [ctx->ac_remainder_len], need);
1468
1469 blockp = (uint8_t *)ctx->ac_remainder;
1470 } else {
1471 blockp = datap;
1472 }
1473
1474 /* don't write on the plaintext */
1475 if (IS_P2ALIGNED(blockp, sizeof (uint32_t))) {
1476 /* LINTED: pointer alignment */
1477 tmp[0] = *(uint32_t *)blockp;
1478 /* LINTED: pointer alignment */
1479 tmp[1] = *(uint32_t *)&blockp[4];
1480 /* LINTED: pointer alignment */
1481 tmp[2] = *(uint32_t *)&blockp[8];
1482 /* LINTED: pointer alignment */
1483 tmp[3] = *(uint32_t *)&blockp[12];
1484 } else {
1485 uint8_t *tmp8 = (uint8_t *)tmp;
1486
1487 AES_COPY_BLOCK(blockp, tmp8);
1488 }
1489 blockp = (uint8_t *)tmp;
1490
1491 /* Calculate the counter mode, ac_cb is the counter block */
1492 aes_encrypt_block(ctx->ac_keysched, (uint8_t *)ctx->ac_cb,
1493 (uint8_t *)counter_block);
1494 cbp = (uint8_t *)counter_block;
1495
1496 /*
1497 * Increment counter.
1498 * Counter bits are confined to the bottom 64 bits
1499 */
1500 counter = ctx->ac_cb[1] & ctx->ac_counter_mask;
1501 #ifdef _LITTLE_ENDIAN
1502 p = (uint8_t *)&counter;
1503 counter = (((uint64_t)p[0] << 56) |
1504 ((uint64_t)p[1] << 48) |
1505 ((uint64_t)p[2] << 40) |
1506 ((uint64_t)p[3] << 32) |
1507 ((uint64_t)p[4] << 24) |
1508 ((uint64_t)p[5] << 16) |
1509 ((uint64_t)p[6] << 8) |
1510 (uint64_t)p[7]);
1511 #endif
1512 counter++;
1513 #ifdef _LITTLE_ENDIAN
1514 counter = (((uint64_t)p[0] << 56) |
1515 ((uint64_t)p[1] << 48) |
1516 ((uint64_t)p[2] << 40) |
1517 ((uint64_t)p[3] << 32) |
1518 ((uint64_t)p[4] << 24) |
1519 ((uint64_t)p[5] << 16) |
1520 ((uint64_t)p[6] << 8) |
1521 (uint64_t)p[7]);
1522 #endif
1523 counter &= ctx->ac_counter_mask;
1524 ctx->ac_cb[1] =
1525 (ctx->ac_cb[1] & ~(ctx->ac_counter_mask)) | counter;
1526
1527 /* XOR with the ciphertext */
1528 if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
1529 IS_P2ALIGNED(cbp, sizeof (uint32_t))) {
1530 /* LINTED: pointer alignment */
1531 *(uint32_t *)&blockp[0] ^= *(uint32_t *)&cbp[0];
1532 /* LINTED: pointer alignment */
1533 *(uint32_t *)&blockp[4] ^= *(uint32_t *)&cbp[4];
1534 /* LINTED: pointer alignment */
1535 *(uint32_t *)&blockp[8] ^= *(uint32_t *)&cbp[8];
1536 /* LINTED: pointer alignment */
1537 *(uint32_t *)&blockp[12] ^= *(uint32_t *)&cbp[12];
1538 } else {
1539 AES_XOR_BLOCK(cbp, blockp);
1540 }
1541
1542 /* Copy the plaintext to the "holding buffer" */
1543 resultp = (uint8_t *)ctx->ac_ccm_pt_buf +
1544 ctx->ac_ccm_processed_data_len;
1545 if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
1546 IS_P2ALIGNED(resultp, sizeof (uint32_t))) {
1547 /* LINTED: pointer alignment */
1548 *(uint32_t *)&resultp[0] = *(uint32_t *)blockp;
1549 /* LINTED: pointer alignment */
1550 *(uint32_t *)&resultp[4] = *(uint32_t *)&blockp[4];
1551 /* LINTED: pointer alignment */
1552 *(uint32_t *)&resultp[8] = *(uint32_t *)&blockp[8];
1553 /* LINTED: pointer alignment */
1554 *(uint32_t *)&resultp[12] = *(uint32_t *)&blockp[12];
1555 } else {
1556 AES_COPY_BLOCK(blockp, resultp);
1557 }
1558
1559 ctx->ac_ccm_processed_data_len += AES_BLOCK_LEN;
1560
1561 ctx->ac_lastp = blockp;
1562
1563 /* Update pointer to next block of data to be processed. */
1564 if (ctx->ac_remainder_len != 0) {
1565 datap += need;
1566 ctx->ac_remainder_len = 0;
1567 } else {
1568 datap += AES_BLOCK_LEN;
1569 }
1570
1571 remainder = (size_t)&data[length] - (size_t)datap;
1572
1573 /* Incomplete last block */
1574 if (remainder > 0 && remainder < AES_BLOCK_LEN) {
1575 bcopy(datap, ctx->ac_remainder, remainder);
1576 ctx->ac_remainder_len = remainder;
1577 ctx->ac_copy_to = datap;
1578 if (ctx->ac_ccm_processed_mac_len > 0) {
1579 /*
1580 * not expecting anymore ciphertext, just
1581 * compute plaintext for the remaining input
1582 */
1583 aes_ccm_decrypt_incomplete_block(ctx);
1584 ctx->ac_ccm_processed_data_len += remainder;
1585 ctx->ac_remainder_len = 0;
1586 }
1587 goto out;
1588 }
1589 ctx->ac_copy_to = NULL;
1590
1591 } while (remainder > 0);
1592
1593 out:
1594 /* EXPORT DELETE END */
1595
1596 return (0);
1597 }
1598
1599 int
1600 aes_ccm_decrypt_final(aes_ctx_t *ctx, crypto_data_t *out)
1601 {
1602 /* EXPORT DELETE START */
1603 size_t mac_remain, pt_len;
1604 uint8_t *pt, *mac_buf, *macp, *ccm_mac_p;
1605 uint8_t ccm_mac[AES_BLOCK_LEN];
1606 void *iov_or_mp;
1607 offset_t offset;
1608 uint8_t *out_data_1, *out_data_2;
1609 size_t out_data_1_len;
1610 uint32_t tmp[4];
1611
1612 pt_len = ctx->ac_ccm_data_len;
1613
1614 /* Make sure output buffer can fit all of the plaintext */
1615 if (out->cd_length < pt_len) {
1616 return (CRYPTO_ARGUMENTS_BAD);
1617 }
1618
1619 pt = ctx->ac_ccm_pt_buf;
1620 mac_remain = ctx->ac_ccm_processed_data_len;
1621 mac_buf = (uint8_t *)ctx->ac_ccm_mac_buf;
1622
1623 macp = (uint8_t *)tmp;
1624
1625 while (mac_remain > 0) {
1626
1627 if (mac_remain < AES_BLOCK_LEN) {
1628 bzero(tmp, AES_BLOCK_LEN);
1629 bcopy(pt, tmp, mac_remain);
1630 mac_remain = 0;
1631 } else {
1632 if (IS_P2ALIGNED(pt, sizeof (uint32_t)) &&
1633 IS_P2ALIGNED(macp, sizeof (uint32_t))) {
1634 /* LINTED: pointer alignment */
1635 *(uint32_t *)&macp[0] = *(uint32_t *)pt;
1636 /* LINTED: pointer alignment */
1637 *(uint32_t *)&macp[4] = *(uint32_t *)&pt[4];
1638 /* LINTED: pointer alignment */
1639 *(uint32_t *)&macp[8] = *(uint32_t *)&pt[8];
1640 /* LINTED: pointer alignment */
1641 *(uint32_t *)&macp[12] = *(uint32_t *)&pt[12];
1642 } else {
1643 AES_COPY_BLOCK(pt, macp);
1644 }
1645 mac_remain -= AES_BLOCK_LEN;
1646 pt += AES_BLOCK_LEN;
1647 }
1648
1649 /* calculate the CBC MAC */
1650 if (IS_P2ALIGNED(macp, sizeof (uint32_t)) &&
1651 IS_P2ALIGNED(mac_buf, sizeof (uint32_t))) {
1652 /* LINTED: pointer alignment */
1653 *(uint32_t *)&mac_buf[0] ^= *(uint32_t *)&macp[0];
1654 /* LINTED: pointer alignment */
1655 *(uint32_t *)&mac_buf[4] ^= *(uint32_t *)&macp[4];
1656 /* LINTED: pointer alignment */
1657 *(uint32_t *)&mac_buf[8] ^= *(uint32_t *)&macp[8];
1658 /* LINTED: pointer alignment */
1659 *(uint32_t *)&mac_buf[12] ^= *(uint32_t *)&macp[12];
1660 } else {
1661 AES_XOR_BLOCK(macp, mac_buf);
1662 }
1663 aes_encrypt_block(ctx->ac_keysched, mac_buf, mac_buf);
1664 }
1665
1666 /* Calculate the CCM MAC */
1667 ccm_mac_p = ccm_mac;
1668 calculate_ccm_mac(ctx, &ccm_mac_p);
1669
1670 /* compare the input CCM MAC value with what we calculated */
1671 if (bcmp(ctx->ac_ccm_mac_input_buf, ccm_mac, ctx->ac_ccm_mac_len)) {
1672 /* They don't match */
1673 return (CRYPTO_DATA_LEN_RANGE);
1674 } else {
1675 aes_init_ptrs(out, &iov_or_mp, &offset);
1676 aes_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
1677 &out_data_1_len, &out_data_2, pt_len);
1678 bcopy(ctx->ac_ccm_pt_buf, out_data_1, out_data_1_len);
1679 if (out_data_2 != NULL) {
1680 bcopy((ctx->ac_ccm_pt_buf) + out_data_1_len,
1681 out_data_2, pt_len - out_data_1_len);
1682 }
1683 out->cd_offset += pt_len;
1684 }
1685
1686 /* EXPORT DELETE END */
1687 return (0);
1688 }