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