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]
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
37 * Encrypt multiple blocks of data in CCM mode. Decrypt for CCM mode
38 * is done in another function.
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
;
49 uint8_t *datap
= (uint8_t *)data
;
56 size_t out_data_1_len
;
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
,
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
;
75 /* Unprocessed data from last call. */
76 if (ctx
->ccm_remainder_len
> 0) {
77 need
= block_size
- ctx
->ccm_remainder_len
;
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
;
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);
113 counter
= ctx
->ccm_cb
[1] & ctx
->ccm_counter_mask
;
115 #endif /* _ZFS_LITTLE_ENDIAN */
116 counter
&= ctx
->ccm_counter_mask
;
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
);
134 memcpy(out_data_1
, lastp
, out_data_1_len
);
135 if (out_data_2
!= NULL
) {
137 lastp
+ out_data_1_len
,
138 block_size
- out_data_1_len
);
142 out
->cd_offset
+= block_size
;
144 /* Update pointer to next block of data to be processed. */
145 if (ctx
->ccm_remainder_len
!= 0) {
147 ctx
->ccm_remainder_len
= 0;
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
;
161 ctx
->ccm_copy_to
= NULL
;
163 } while (remainder
> 0);
166 return (CRYPTO_SUCCESS
);
170 calculate_ccm_mac(ccm_ctx_t
*ctx
, uint8_t *ccm_mac
,
171 int (*encrypt_block
)(const void *, const uint8_t *, uint8_t *))
174 uint8_t *counterp
, *mac_buf
;
177 mac_buf
= (uint8_t *)ctx
->ccm_mac_buf
;
179 /* first counter block start with index 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
;
202 size_t out_data_1_len
;
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
++) {
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
,
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
272 (uint8_t *)macp
+ out_data_1_len
,
274 memcpy(out_data_2
+ data_2_len_used
,
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
,
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
292 ctx
->ccm_remainder_len
,
293 ccm_mac_p
, len_not_used
);
295 ccm_mac_p
+ len_not_used
,
296 ctx
->ccm_mac_len
- len_not_used
);
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.
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
;
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 *))
350 size_t remainder
= length
;
352 uint8_t *datap
= (uint8_t *)data
;
356 size_t pt_len
, total_decrypted_len
, mac_len
, pm_len
, pd_len
;
360 pm_len
= ctx
->ccm_processed_mac_len
;
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
);
421 /* let rest of the code handle this */
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
,
429 ctx
->ccm_remainder_len
+= length
;
430 ctx
->ccm_copy_to
= datap
;
431 return (CRYPTO_SUCCESS
);
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
;
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
);
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);
462 counter
= ctx
->ccm_cb
[1] & ctx
->ccm_counter_mask
;
464 #endif /* _ZFS_LITTLE_ENDIAN */
465 counter
&= ctx
->ccm_counter_mask
;
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) {
484 ctx
->ccm_remainder_len
= 0;
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
,
503 ctx
->ccm_processed_data_len
+= remainder
;
504 ctx
->ccm_remainder_len
= 0;
508 ctx
->ccm_copy_to
= NULL
;
510 } while (remainder
> 0);
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
;
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
);
545 copy_block(pt
, macp
);
546 mac_remain
-= 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
);
564 rv
= crypto_put_output_data(ctx
->ccm_pt_buf
, out
, pt_len
);
565 if (rv
!= CRYPTO_SUCCESS
)
567 out
->cd_offset
+= pt_len
;
569 return (CRYPTO_SUCCESS
);
573 ccm_validate_args(CK_AES_CCM_PARAMS
*ccm_param
, boolean_t is_encrypt_init
)
575 size_t macSize
, nonceSize
;
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
611 maxValue
= (1ULL << (q
* 8)) - 1;
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
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;
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) {
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
;
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 */
683 #ifdef _ZFS_LITTLE_ENDIAN
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.
699 * Encode the length of the associated data as
700 * specified in RFC 3610 and NIST publication 800-38C, appendix A
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
;
708 uint64_t *llencoded_ptr
;
710 #endif /* UNALIGNED_POINTERS_PERMITTED */
712 if (auth_data_len
< ((1ULL<<16) - (1ULL<<8))) {
713 /* 0 < a < (2^16-2^8) */
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 */
724 #ifdef UNALIGNED_POINTERS_PERMITTED
725 lencoded_ptr
= (uint32_t *)&encoded
[2];
726 *lencoded_ptr
= htonl(auth_data_len
);
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 */
736 /* 2^32 <= a < 2^64 */
740 #ifdef UNALIGNED_POINTERS_PERMITTED
741 llencoded_ptr
= (uint64_t *)&encoded
[2];
742 *llencoded_ptr
= htonl(auth_data_len
);
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 */
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
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
);
818 if (remainder
< block_size
) {
820 * There's not a block full of data, pad rest of
823 memset(authp
, 0, block_size
);
824 memcpy(authp
, &(auth_data
[processed
]), remainder
);
825 datap
= (uint8_t *)authp
;
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
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 *))
852 CK_AES_CCM_PARAMS
*ccm_param
;
855 ccm_param
= (CK_AES_CCM_PARAMS
*)param
;
857 if ((rv
= ccm_validate_args(ccm_param
,
858 is_encrypt_init
)) != 0) {
862 ccm_ctx
->ccm_mac_len
= ccm_param
->ulMACSize
;
863 if (is_encrypt_init
) {
864 ccm_ctx
->ccm_data_len
= ccm_param
->ulDataSize
;
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
;
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
,
886 if (ccm_ctx
->ccm_pt_buf
== NULL
) {
887 rv
= CRYPTO_HOST_MEMORY
;
894 ccm_alloc_ctx(int kmflag
)
898 if ((ccm_ctx
= kmem_zalloc(sizeof (ccm_ctx_t
), kmflag
)) == NULL
)
901 ccm_ctx
->ccm_flags
= CCM_MODE
;