CI: Stick with ubuntu-22.04 for CodeQL analysis
[zfs.git] / module / icp / algs / modes / ccm.c
blob1371676d6e68155fbb92a48d84eb0c539ab6d7d1
1 /*
2 * CDDL HEADER START
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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/zfs_context.h>
27 #include <modes/modes.h>
28 #include <sys/crypto/common.h>
29 #include <sys/crypto/impl.h>
31 #ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
32 #include <sys/byteorder.h>
33 #define UNALIGNED_POINTERS_PERMITTED
34 #endif
37 * Encrypt multiple blocks of data in CCM mode. Decrypt for CCM mode
38 * is done in another function.
40 int
41 ccm_mode_encrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length,
42 crypto_data_t *out, size_t block_size,
43 int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
44 void (*copy_block)(uint8_t *, uint8_t *),
45 void (*xor_block)(uint8_t *, uint8_t *))
47 size_t remainder = length;
48 size_t need = 0;
49 uint8_t *datap = (uint8_t *)data;
50 uint8_t *blockp;
51 uint8_t *lastp;
52 void *iov_or_mp;
53 offset_t offset;
54 uint8_t *out_data_1;
55 uint8_t *out_data_2;
56 size_t out_data_1_len;
57 uint64_t counter;
58 uint8_t *mac_buf;
60 if (length + ctx->ccm_remainder_len < block_size) {
61 /* accumulate bytes here and return */
62 memcpy((uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len,
63 datap,
64 length);
65 ctx->ccm_remainder_len += length;
66 ctx->ccm_copy_to = datap;
67 return (CRYPTO_SUCCESS);
70 crypto_init_ptrs(out, &iov_or_mp, &offset);
72 mac_buf = (uint8_t *)ctx->ccm_mac_buf;
74 do {
75 /* Unprocessed data from last call. */
76 if (ctx->ccm_remainder_len > 0) {
77 need = block_size - ctx->ccm_remainder_len;
79 if (need > remainder)
80 return (CRYPTO_DATA_LEN_RANGE);
82 memcpy(&((uint8_t *)ctx->ccm_remainder)
83 [ctx->ccm_remainder_len], datap, need);
85 blockp = (uint8_t *)ctx->ccm_remainder;
86 } else {
87 blockp = datap;
91 * do CBC MAC
93 * XOR the previous cipher block current clear block.
94 * mac_buf always contain previous cipher block.
96 xor_block(blockp, mac_buf);
97 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
99 /* ccm_cb is the counter block */
100 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb,
101 (uint8_t *)ctx->ccm_tmp);
103 lastp = (uint8_t *)ctx->ccm_tmp;
106 * Increment counter. Counter bits are confined
107 * to the bottom 64 bits of the counter block.
109 #ifdef _ZFS_LITTLE_ENDIAN
110 counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask);
111 counter = htonll(counter + 1);
112 #else
113 counter = ctx->ccm_cb[1] & ctx->ccm_counter_mask;
114 counter++;
115 #endif /* _ZFS_LITTLE_ENDIAN */
116 counter &= ctx->ccm_counter_mask;
117 ctx->ccm_cb[1] =
118 (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter;
121 * XOR encrypted counter block with the current clear block.
123 xor_block(blockp, lastp);
125 ctx->ccm_processed_data_len += block_size;
127 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
128 &out_data_1_len, &out_data_2, block_size);
130 /* copy block to where it belongs */
131 if (out_data_1_len == block_size) {
132 copy_block(lastp, out_data_1);
133 } else {
134 memcpy(out_data_1, lastp, out_data_1_len);
135 if (out_data_2 != NULL) {
136 memcpy(out_data_2,
137 lastp + out_data_1_len,
138 block_size - out_data_1_len);
141 /* update offset */
142 out->cd_offset += block_size;
144 /* Update pointer to next block of data to be processed. */
145 if (ctx->ccm_remainder_len != 0) {
146 datap += need;
147 ctx->ccm_remainder_len = 0;
148 } else {
149 datap += block_size;
152 remainder = (size_t)&data[length] - (size_t)datap;
154 /* Incomplete last block. */
155 if (remainder > 0 && remainder < block_size) {
156 memcpy(ctx->ccm_remainder, datap, remainder);
157 ctx->ccm_remainder_len = remainder;
158 ctx->ccm_copy_to = datap;
159 goto out;
161 ctx->ccm_copy_to = NULL;
163 } while (remainder > 0);
165 out:
166 return (CRYPTO_SUCCESS);
169 void
170 calculate_ccm_mac(ccm_ctx_t *ctx, uint8_t *ccm_mac,
171 int (*encrypt_block)(const void *, const uint8_t *, uint8_t *))
173 uint64_t counter;
174 uint8_t *counterp, *mac_buf;
175 int i;
177 mac_buf = (uint8_t *)ctx->ccm_mac_buf;
179 /* first counter block start with index 0 */
180 counter = 0;
181 ctx->ccm_cb[1] = (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter;
183 counterp = (uint8_t *)ctx->ccm_tmp;
184 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp);
186 /* calculate XOR of MAC with first counter block */
187 for (i = 0; i < ctx->ccm_mac_len; i++) {
188 ccm_mac[i] = mac_buf[i] ^ counterp[i];
193 ccm_encrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size,
194 int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
195 void (*xor_block)(uint8_t *, uint8_t *))
197 uint8_t *lastp, *mac_buf, *ccm_mac_p, *macp = NULL;
198 void *iov_or_mp;
199 offset_t offset;
200 uint8_t *out_data_1;
201 uint8_t *out_data_2;
202 size_t out_data_1_len;
203 int i;
205 if (out->cd_length < (ctx->ccm_remainder_len + ctx->ccm_mac_len)) {
206 return (CRYPTO_DATA_LEN_RANGE);
210 * When we get here, the number of bytes of payload processed
211 * plus whatever data remains, if any,
212 * should be the same as the number of bytes that's being
213 * passed in the argument during init time.
215 if ((ctx->ccm_processed_data_len + ctx->ccm_remainder_len)
216 != (ctx->ccm_data_len)) {
217 return (CRYPTO_DATA_LEN_RANGE);
220 mac_buf = (uint8_t *)ctx->ccm_mac_buf;
222 if (ctx->ccm_remainder_len > 0) {
224 /* ccm_mac_input_buf is not used for encryption */
225 macp = (uint8_t *)ctx->ccm_mac_input_buf;
226 memset(macp, 0, block_size);
228 /* copy remainder to temporary buffer */
229 memcpy(macp, ctx->ccm_remainder, ctx->ccm_remainder_len);
231 /* calculate the CBC MAC */
232 xor_block(macp, mac_buf);
233 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
235 /* calculate the counter mode */
236 lastp = (uint8_t *)ctx->ccm_tmp;
237 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, lastp);
239 /* XOR with counter block */
240 for (i = 0; i < ctx->ccm_remainder_len; i++) {
241 macp[i] ^= lastp[i];
243 ctx->ccm_processed_data_len += ctx->ccm_remainder_len;
246 /* Calculate the CCM MAC */
247 ccm_mac_p = (uint8_t *)ctx->ccm_tmp;
248 calculate_ccm_mac(ctx, ccm_mac_p, encrypt_block);
250 crypto_init_ptrs(out, &iov_or_mp, &offset);
251 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
252 &out_data_1_len, &out_data_2,
253 ctx->ccm_remainder_len + ctx->ccm_mac_len);
255 if (ctx->ccm_remainder_len > 0) {
256 /* copy temporary block to where it belongs */
257 if (out_data_2 == NULL) {
258 /* everything will fit in out_data_1 */
259 memcpy(out_data_1, macp, ctx->ccm_remainder_len);
260 memcpy(out_data_1 + ctx->ccm_remainder_len, ccm_mac_p,
261 ctx->ccm_mac_len);
262 } else {
263 if (out_data_1_len < ctx->ccm_remainder_len) {
264 size_t data_2_len_used;
266 memcpy(out_data_1, macp, out_data_1_len);
268 data_2_len_used = ctx->ccm_remainder_len
269 - out_data_1_len;
271 memcpy(out_data_2,
272 (uint8_t *)macp + out_data_1_len,
273 data_2_len_used);
274 memcpy(out_data_2 + data_2_len_used,
275 ccm_mac_p,
276 ctx->ccm_mac_len);
277 } else {
278 memcpy(out_data_1, macp, out_data_1_len);
279 if (out_data_1_len == ctx->ccm_remainder_len) {
280 /* mac will be in out_data_2 */
281 memcpy(out_data_2, ccm_mac_p,
282 ctx->ccm_mac_len);
283 } else {
284 size_t len_not_used = out_data_1_len -
285 ctx->ccm_remainder_len;
287 * part of mac in will be in
288 * out_data_1, part of the mac will be
289 * in out_data_2
291 memcpy(out_data_1 +
292 ctx->ccm_remainder_len,
293 ccm_mac_p, len_not_used);
294 memcpy(out_data_2,
295 ccm_mac_p + len_not_used,
296 ctx->ccm_mac_len - len_not_used);
301 } else {
302 /* copy block to where it belongs */
303 memcpy(out_data_1, ccm_mac_p, out_data_1_len);
304 if (out_data_2 != NULL) {
305 memcpy(out_data_2, ccm_mac_p + out_data_1_len,
306 block_size - out_data_1_len);
309 out->cd_offset += ctx->ccm_remainder_len + ctx->ccm_mac_len;
310 ctx->ccm_remainder_len = 0;
311 return (CRYPTO_SUCCESS);
315 * This will only deal with decrypting the last block of the input that
316 * might not be a multiple of block length.
318 static void
319 ccm_decrypt_incomplete_block(ccm_ctx_t *ctx,
320 int (*encrypt_block)(const void *, const uint8_t *, uint8_t *))
322 uint8_t *datap, *outp, *counterp;
323 int i;
325 datap = (uint8_t *)ctx->ccm_remainder;
326 outp = &((ctx->ccm_pt_buf)[ctx->ccm_processed_data_len]);
328 counterp = (uint8_t *)ctx->ccm_tmp;
329 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp);
331 /* XOR with counter block */
332 for (i = 0; i < ctx->ccm_remainder_len; i++) {
333 outp[i] = datap[i] ^ counterp[i];
338 * This will decrypt the cipher text. However, the plaintext won't be
339 * returned to the caller. It will be returned when decrypt_final() is
340 * called if the MAC matches
343 ccm_mode_decrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length,
344 crypto_data_t *out, size_t block_size,
345 int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
346 void (*copy_block)(uint8_t *, uint8_t *),
347 void (*xor_block)(uint8_t *, uint8_t *))
349 (void) out;
350 size_t remainder = length;
351 size_t need = 0;
352 uint8_t *datap = (uint8_t *)data;
353 uint8_t *blockp;
354 uint8_t *cbp;
355 uint64_t counter;
356 size_t pt_len, total_decrypted_len, mac_len, pm_len, pd_len;
357 uint8_t *resultp;
360 pm_len = ctx->ccm_processed_mac_len;
362 if (pm_len > 0) {
363 uint8_t *tmp;
365 * all ciphertext has been processed, just waiting for
366 * part of the value of the mac
368 if ((pm_len + length) > ctx->ccm_mac_len) {
369 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
371 tmp = (uint8_t *)ctx->ccm_mac_input_buf;
373 memcpy(tmp + pm_len, datap, length);
375 ctx->ccm_processed_mac_len += length;
376 return (CRYPTO_SUCCESS);
380 * If we decrypt the given data, what total amount of data would
381 * have been decrypted?
383 pd_len = ctx->ccm_processed_data_len;
384 total_decrypted_len = pd_len + length + ctx->ccm_remainder_len;
386 if (total_decrypted_len >
387 (ctx->ccm_data_len + ctx->ccm_mac_len)) {
388 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
391 pt_len = ctx->ccm_data_len;
393 if (total_decrypted_len > pt_len) {
395 * part of the input will be the MAC, need to isolate that
396 * to be dealt with later. The left-over data in
397 * ccm_remainder_len from last time will not be part of the
398 * MAC. Otherwise, it would have already been taken out
399 * when this call is made last time.
401 size_t pt_part = pt_len - pd_len - ctx->ccm_remainder_len;
403 mac_len = length - pt_part;
405 ctx->ccm_processed_mac_len = mac_len;
406 memcpy(ctx->ccm_mac_input_buf, data + pt_part, mac_len);
408 if (pt_part + ctx->ccm_remainder_len < block_size) {
410 * since this is last of the ciphertext, will
411 * just decrypt with it here
413 memcpy(&((uint8_t *)ctx->ccm_remainder)
414 [ctx->ccm_remainder_len], datap, pt_part);
415 ctx->ccm_remainder_len += pt_part;
416 ccm_decrypt_incomplete_block(ctx, encrypt_block);
417 ctx->ccm_processed_data_len += ctx->ccm_remainder_len;
418 ctx->ccm_remainder_len = 0;
419 return (CRYPTO_SUCCESS);
420 } else {
421 /* let rest of the code handle this */
422 length = pt_part;
424 } else if (length + ctx->ccm_remainder_len < block_size) {
425 /* accumulate bytes here and return */
426 memcpy((uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len,
427 datap,
428 length);
429 ctx->ccm_remainder_len += length;
430 ctx->ccm_copy_to = datap;
431 return (CRYPTO_SUCCESS);
434 do {
435 /* Unprocessed data from last call. */
436 if (ctx->ccm_remainder_len > 0) {
437 need = block_size - ctx->ccm_remainder_len;
439 if (need > remainder)
440 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
442 memcpy(&((uint8_t *)ctx->ccm_remainder)
443 [ctx->ccm_remainder_len], datap, need);
445 blockp = (uint8_t *)ctx->ccm_remainder;
446 } else {
447 blockp = datap;
450 /* Calculate the counter mode, ccm_cb is the counter block */
451 cbp = (uint8_t *)ctx->ccm_tmp;
452 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, cbp);
455 * Increment counter.
456 * Counter bits are confined to the bottom 64 bits
458 #ifdef _ZFS_LITTLE_ENDIAN
459 counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask);
460 counter = htonll(counter + 1);
461 #else
462 counter = ctx->ccm_cb[1] & ctx->ccm_counter_mask;
463 counter++;
464 #endif /* _ZFS_LITTLE_ENDIAN */
465 counter &= ctx->ccm_counter_mask;
466 ctx->ccm_cb[1] =
467 (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter;
469 /* XOR with the ciphertext */
470 xor_block(blockp, cbp);
472 /* Copy the plaintext to the "holding buffer" */
473 resultp = (uint8_t *)ctx->ccm_pt_buf +
474 ctx->ccm_processed_data_len;
475 copy_block(cbp, resultp);
477 ctx->ccm_processed_data_len += block_size;
479 ctx->ccm_lastp = blockp;
481 /* Update pointer to next block of data to be processed. */
482 if (ctx->ccm_remainder_len != 0) {
483 datap += need;
484 ctx->ccm_remainder_len = 0;
485 } else {
486 datap += block_size;
489 remainder = (size_t)&data[length] - (size_t)datap;
491 /* Incomplete last block */
492 if (remainder > 0 && remainder < block_size) {
493 memcpy(ctx->ccm_remainder, datap, remainder);
494 ctx->ccm_remainder_len = remainder;
495 ctx->ccm_copy_to = datap;
496 if (ctx->ccm_processed_mac_len > 0) {
498 * not expecting anymore ciphertext, just
499 * compute plaintext for the remaining input
501 ccm_decrypt_incomplete_block(ctx,
502 encrypt_block);
503 ctx->ccm_processed_data_len += remainder;
504 ctx->ccm_remainder_len = 0;
506 goto out;
508 ctx->ccm_copy_to = NULL;
510 } while (remainder > 0);
512 out:
513 return (CRYPTO_SUCCESS);
517 ccm_decrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size,
518 int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
519 void (*copy_block)(uint8_t *, uint8_t *),
520 void (*xor_block)(uint8_t *, uint8_t *))
522 size_t mac_remain, pt_len;
523 uint8_t *pt, *mac_buf, *macp, *ccm_mac_p;
524 int rv;
526 pt_len = ctx->ccm_data_len;
528 /* Make sure output buffer can fit all of the plaintext */
529 if (out->cd_length < pt_len) {
530 return (CRYPTO_DATA_LEN_RANGE);
533 pt = ctx->ccm_pt_buf;
534 mac_remain = ctx->ccm_processed_data_len;
535 mac_buf = (uint8_t *)ctx->ccm_mac_buf;
537 macp = (uint8_t *)ctx->ccm_tmp;
539 while (mac_remain > 0) {
540 if (mac_remain < block_size) {
541 memset(macp, 0, block_size);
542 memcpy(macp, pt, mac_remain);
543 mac_remain = 0;
544 } else {
545 copy_block(pt, macp);
546 mac_remain -= block_size;
547 pt += block_size;
550 /* calculate the CBC MAC */
551 xor_block(macp, mac_buf);
552 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
555 /* Calculate the CCM MAC */
556 ccm_mac_p = (uint8_t *)ctx->ccm_tmp;
557 calculate_ccm_mac((ccm_ctx_t *)ctx, ccm_mac_p, encrypt_block);
559 /* compare the input CCM MAC value with what we calculated */
560 if (memcmp(ctx->ccm_mac_input_buf, ccm_mac_p, ctx->ccm_mac_len)) {
561 /* They don't match */
562 return (CRYPTO_INVALID_MAC);
563 } else {
564 rv = crypto_put_output_data(ctx->ccm_pt_buf, out, pt_len);
565 if (rv != CRYPTO_SUCCESS)
566 return (rv);
567 out->cd_offset += pt_len;
569 return (CRYPTO_SUCCESS);
572 static int
573 ccm_validate_args(CK_AES_CCM_PARAMS *ccm_param, boolean_t is_encrypt_init)
575 size_t macSize, nonceSize;
576 uint8_t q;
577 uint64_t maxValue;
580 * Check the length of the MAC. The only valid
581 * lengths for the MAC are: 4, 6, 8, 10, 12, 14, 16
583 macSize = ccm_param->ulMACSize;
584 if ((macSize < 4) || (macSize > 16) || ((macSize % 2) != 0)) {
585 return (CRYPTO_MECHANISM_PARAM_INVALID);
588 /* Check the nonce length. Valid values are 7, 8, 9, 10, 11, 12, 13 */
589 nonceSize = ccm_param->ulNonceSize;
590 if ((nonceSize < 7) || (nonceSize > 13)) {
591 return (CRYPTO_MECHANISM_PARAM_INVALID);
594 /* q is the length of the field storing the length, in bytes */
595 q = (uint8_t)((15 - nonceSize) & 0xFF);
599 * If it is decrypt, need to make sure size of ciphertext is at least
600 * bigger than MAC len
602 if ((!is_encrypt_init) && (ccm_param->ulDataSize < macSize)) {
603 return (CRYPTO_MECHANISM_PARAM_INVALID);
607 * Check to make sure the length of the payload is within the
608 * range of values allowed by q
610 if (q < 8) {
611 maxValue = (1ULL << (q * 8)) - 1;
612 } else {
613 maxValue = ULONG_MAX;
616 if (ccm_param->ulDataSize > maxValue) {
617 return (CRYPTO_MECHANISM_PARAM_INVALID);
619 return (CRYPTO_SUCCESS);
623 * Format the first block used in CBC-MAC (B0) and the initial counter
624 * block based on formatting functions and counter generation functions
625 * specified in RFC 3610 and NIST publication 800-38C, appendix A
627 * b0 is the first block used in CBC-MAC
628 * cb0 is the first counter block
630 * It's assumed that the arguments b0 and cb0 are preallocated AES blocks
633 static void
634 ccm_format_initial_blocks(uchar_t *nonce, ulong_t nonceSize,
635 ulong_t authDataSize, uint8_t *b0, ccm_ctx_t *aes_ctx)
637 uint64_t payloadSize;
638 uint8_t t, q, have_adata = 0;
639 size_t limit;
640 int i, j, k;
641 uint64_t mask = 0;
642 uint8_t *cb;
644 q = (uint8_t)((15 - nonceSize) & 0xFF);
645 t = (uint8_t)((aes_ctx->ccm_mac_len) & 0xFF);
647 /* Construct the first octet of b0 */
648 if (authDataSize > 0) {
649 have_adata = 1;
651 b0[0] = (have_adata << 6) | (((t - 2) / 2) << 3) | (q - 1);
653 /* copy the nonce value into b0 */
654 memcpy(&(b0[1]), nonce, nonceSize);
656 /* store the length of the payload into b0 */
657 memset(&(b0[1+nonceSize]), 0, q);
659 payloadSize = aes_ctx->ccm_data_len;
660 limit = MIN(8, q);
662 for (i = 0, j = 0, k = 15; i < limit; i++, j += 8, k--) {
663 b0[k] = (uint8_t)((payloadSize >> j) & 0xFF);
666 /* format the counter block */
668 cb = (uint8_t *)aes_ctx->ccm_cb;
670 cb[0] = 0x07 & (q-1); /* first byte */
672 /* copy the nonce value into the counter block */
673 memcpy(&(cb[1]), nonce, nonceSize);
675 memset(&(cb[1+nonceSize]), 0, q);
677 /* Create the mask for the counter field based on the size of nonce */
678 q <<= 3;
679 while (q-- > 0) {
680 mask |= (1ULL << q);
683 #ifdef _ZFS_LITTLE_ENDIAN
684 mask = htonll(mask);
685 #endif
686 aes_ctx->ccm_counter_mask = mask;
689 * During calculation, we start using counter block 1, we will
690 * set it up right here.
691 * We can just set the last byte to have the value 1, because
692 * even with the biggest nonce of 13, the last byte of the
693 * counter block will be used for the counter value.
695 cb[15] = 0x01;
699 * Encode the length of the associated data as
700 * specified in RFC 3610 and NIST publication 800-38C, appendix A
702 static void
703 encode_adata_len(ulong_t auth_data_len, uint8_t *encoded, size_t *encoded_len)
705 #ifdef UNALIGNED_POINTERS_PERMITTED
706 uint32_t *lencoded_ptr;
707 #ifdef _LP64
708 uint64_t *llencoded_ptr;
709 #endif
710 #endif /* UNALIGNED_POINTERS_PERMITTED */
712 if (auth_data_len < ((1ULL<<16) - (1ULL<<8))) {
713 /* 0 < a < (2^16-2^8) */
714 *encoded_len = 2;
715 encoded[0] = (auth_data_len & 0xff00) >> 8;
716 encoded[1] = auth_data_len & 0xff;
718 } else if ((auth_data_len >= ((1ULL<<16) - (1ULL<<8))) &&
719 (auth_data_len < (1ULL << 31))) {
720 /* (2^16-2^8) <= a < 2^32 */
721 *encoded_len = 6;
722 encoded[0] = 0xff;
723 encoded[1] = 0xfe;
724 #ifdef UNALIGNED_POINTERS_PERMITTED
725 lencoded_ptr = (uint32_t *)&encoded[2];
726 *lencoded_ptr = htonl(auth_data_len);
727 #else
728 encoded[2] = (auth_data_len & 0xff000000) >> 24;
729 encoded[3] = (auth_data_len & 0xff0000) >> 16;
730 encoded[4] = (auth_data_len & 0xff00) >> 8;
731 encoded[5] = auth_data_len & 0xff;
732 #endif /* UNALIGNED_POINTERS_PERMITTED */
734 #ifdef _LP64
735 } else {
736 /* 2^32 <= a < 2^64 */
737 *encoded_len = 10;
738 encoded[0] = 0xff;
739 encoded[1] = 0xff;
740 #ifdef UNALIGNED_POINTERS_PERMITTED
741 llencoded_ptr = (uint64_t *)&encoded[2];
742 *llencoded_ptr = htonl(auth_data_len);
743 #else
744 encoded[2] = (auth_data_len & 0xff00000000000000) >> 56;
745 encoded[3] = (auth_data_len & 0xff000000000000) >> 48;
746 encoded[4] = (auth_data_len & 0xff0000000000) >> 40;
747 encoded[5] = (auth_data_len & 0xff00000000) >> 32;
748 encoded[6] = (auth_data_len & 0xff000000) >> 24;
749 encoded[7] = (auth_data_len & 0xff0000) >> 16;
750 encoded[8] = (auth_data_len & 0xff00) >> 8;
751 encoded[9] = auth_data_len & 0xff;
752 #endif /* UNALIGNED_POINTERS_PERMITTED */
753 #endif /* _LP64 */
757 static int
758 ccm_init(ccm_ctx_t *ctx, unsigned char *nonce, size_t nonce_len,
759 unsigned char *auth_data, size_t auth_data_len, size_t block_size,
760 int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
761 void (*xor_block)(uint8_t *, uint8_t *))
763 uint8_t *mac_buf, *datap, *ivp, *authp;
764 size_t remainder, processed;
765 uint8_t encoded_a[10]; /* max encoded auth data length is 10 octets */
766 size_t encoded_a_len = 0;
768 mac_buf = (uint8_t *)&(ctx->ccm_mac_buf);
771 * Format the 1st block for CBC-MAC and construct the
772 * 1st counter block.
774 * aes_ctx->ccm_iv is used for storing the counter block
775 * mac_buf will store b0 at this time.
777 ccm_format_initial_blocks(nonce, nonce_len,
778 auth_data_len, mac_buf, ctx);
780 /* The IV for CBC MAC for AES CCM mode is always zero */
781 ivp = (uint8_t *)ctx->ccm_tmp;
782 memset(ivp, 0, block_size);
784 xor_block(ivp, mac_buf);
786 /* encrypt the nonce */
787 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
789 /* take care of the associated data, if any */
790 if (auth_data_len == 0) {
791 return (CRYPTO_SUCCESS);
794 encode_adata_len(auth_data_len, encoded_a, &encoded_a_len);
796 remainder = auth_data_len;
798 /* 1st block: it contains encoded associated data, and some data */
799 authp = (uint8_t *)ctx->ccm_tmp;
800 memset(authp, 0, block_size);
801 memcpy(authp, encoded_a, encoded_a_len);
802 processed = block_size - encoded_a_len;
803 if (processed > auth_data_len) {
804 /* in case auth_data is very small */
805 processed = auth_data_len;
807 memcpy(authp+encoded_a_len, auth_data, processed);
808 /* xor with previous buffer */
809 xor_block(authp, mac_buf);
810 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
811 remainder -= processed;
812 if (remainder == 0) {
813 /* a small amount of associated data, it's all done now */
814 return (CRYPTO_SUCCESS);
817 do {
818 if (remainder < block_size) {
820 * There's not a block full of data, pad rest of
821 * buffer with zero
823 memset(authp, 0, block_size);
824 memcpy(authp, &(auth_data[processed]), remainder);
825 datap = (uint8_t *)authp;
826 remainder = 0;
827 } else {
828 datap = (uint8_t *)(&(auth_data[processed]));
829 processed += block_size;
830 remainder -= block_size;
833 xor_block(datap, mac_buf);
834 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
836 } while (remainder > 0);
838 return (CRYPTO_SUCCESS);
842 * The following function should be call at encrypt or decrypt init time
843 * for AES CCM mode.
846 ccm_init_ctx(ccm_ctx_t *ccm_ctx, char *param, int kmflag,
847 boolean_t is_encrypt_init, size_t block_size,
848 int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
849 void (*xor_block)(uint8_t *, uint8_t *))
851 int rv;
852 CK_AES_CCM_PARAMS *ccm_param;
854 if (param != NULL) {
855 ccm_param = (CK_AES_CCM_PARAMS *)param;
857 if ((rv = ccm_validate_args(ccm_param,
858 is_encrypt_init)) != 0) {
859 return (rv);
862 ccm_ctx->ccm_mac_len = ccm_param->ulMACSize;
863 if (is_encrypt_init) {
864 ccm_ctx->ccm_data_len = ccm_param->ulDataSize;
865 } else {
866 ccm_ctx->ccm_data_len =
867 ccm_param->ulDataSize - ccm_ctx->ccm_mac_len;
868 ccm_ctx->ccm_processed_mac_len = 0;
870 ccm_ctx->ccm_processed_data_len = 0;
872 ccm_ctx->ccm_flags |= CCM_MODE;
873 } else {
874 return (CRYPTO_MECHANISM_PARAM_INVALID);
877 if (ccm_init(ccm_ctx, ccm_param->nonce, ccm_param->ulNonceSize,
878 ccm_param->authData, ccm_param->ulAuthDataSize, block_size,
879 encrypt_block, xor_block) != 0) {
880 return (CRYPTO_MECHANISM_PARAM_INVALID);
882 if (!is_encrypt_init) {
883 /* allocate buffer for storing decrypted plaintext */
884 ccm_ctx->ccm_pt_buf = vmem_alloc(ccm_ctx->ccm_data_len,
885 kmflag);
886 if (ccm_ctx->ccm_pt_buf == NULL) {
887 rv = CRYPTO_HOST_MEMORY;
890 return (rv);
893 void *
894 ccm_alloc_ctx(int kmflag)
896 ccm_ctx_t *ccm_ctx;
898 if ((ccm_ctx = kmem_zalloc(sizeof (ccm_ctx_t), kmflag)) == NULL)
899 return (NULL);
901 ccm_ctx->ccm_flags = CCM_MODE;
902 return (ccm_ctx);