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 http://www.opensolaris.org/os/licensing.
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 lastp
= (uint8_t *)ctx
->ccm_cb
;
71 crypto_init_ptrs(out
, &iov_or_mp
, &offset
);
73 mac_buf
= (uint8_t *)ctx
->ccm_mac_buf
;
76 /* Unprocessed data from last call. */
77 if (ctx
->ccm_remainder_len
> 0) {
78 need
= block_size
- ctx
->ccm_remainder_len
;
81 return (CRYPTO_DATA_LEN_RANGE
);
83 memcpy(&((uint8_t *)ctx
->ccm_remainder
)
84 [ctx
->ccm_remainder_len
], datap
, need
);
86 blockp
= (uint8_t *)ctx
->ccm_remainder
;
94 * XOR the previous cipher block current clear block.
95 * mac_buf always contain previous cipher block.
97 xor_block(blockp
, mac_buf
);
98 encrypt_block(ctx
->ccm_keysched
, mac_buf
, mac_buf
);
100 /* ccm_cb is the counter block */
101 encrypt_block(ctx
->ccm_keysched
, (uint8_t *)ctx
->ccm_cb
,
102 (uint8_t *)ctx
->ccm_tmp
);
104 lastp
= (uint8_t *)ctx
->ccm_tmp
;
107 * Increment counter. Counter bits are confined
108 * to the bottom 64 bits of the counter block.
110 #ifdef _ZFS_LITTLE_ENDIAN
111 counter
= ntohll(ctx
->ccm_cb
[1] & ctx
->ccm_counter_mask
);
112 counter
= htonll(counter
+ 1);
114 counter
= ctx
->ccm_cb
[1] & ctx
->ccm_counter_mask
;
116 #endif /* _ZFS_LITTLE_ENDIAN */
117 counter
&= ctx
->ccm_counter_mask
;
119 (ctx
->ccm_cb
[1] & ~(ctx
->ccm_counter_mask
)) | counter
;
122 * XOR encrypted counter block with the current clear block.
124 xor_block(blockp
, lastp
);
126 ctx
->ccm_processed_data_len
+= block_size
;
128 crypto_get_ptrs(out
, &iov_or_mp
, &offset
, &out_data_1
,
129 &out_data_1_len
, &out_data_2
, block_size
);
131 /* copy block to where it belongs */
132 if (out_data_1_len
== block_size
) {
133 copy_block(lastp
, out_data_1
);
135 memcpy(out_data_1
, lastp
, out_data_1_len
);
136 if (out_data_2
!= NULL
) {
138 lastp
+ out_data_1_len
,
139 block_size
- out_data_1_len
);
143 out
->cd_offset
+= block_size
;
145 /* Update pointer to next block of data to be processed. */
146 if (ctx
->ccm_remainder_len
!= 0) {
148 ctx
->ccm_remainder_len
= 0;
153 remainder
= (size_t)&data
[length
] - (size_t)datap
;
155 /* Incomplete last block. */
156 if (remainder
> 0 && remainder
< block_size
) {
157 memcpy(ctx
->ccm_remainder
, datap
, remainder
);
158 ctx
->ccm_remainder_len
= remainder
;
159 ctx
->ccm_copy_to
= datap
;
162 ctx
->ccm_copy_to
= NULL
;
164 } while (remainder
> 0);
167 return (CRYPTO_SUCCESS
);
171 calculate_ccm_mac(ccm_ctx_t
*ctx
, uint8_t *ccm_mac
,
172 int (*encrypt_block
)(const void *, const uint8_t *, uint8_t *))
175 uint8_t *counterp
, *mac_buf
;
178 mac_buf
= (uint8_t *)ctx
->ccm_mac_buf
;
180 /* first counter block start with index 0 */
182 ctx
->ccm_cb
[1] = (ctx
->ccm_cb
[1] & ~(ctx
->ccm_counter_mask
)) | counter
;
184 counterp
= (uint8_t *)ctx
->ccm_tmp
;
185 encrypt_block(ctx
->ccm_keysched
, (uint8_t *)ctx
->ccm_cb
, counterp
);
187 /* calculate XOR of MAC with first counter block */
188 for (i
= 0; i
< ctx
->ccm_mac_len
; i
++) {
189 ccm_mac
[i
] = mac_buf
[i
] ^ counterp
[i
];
194 ccm_encrypt_final(ccm_ctx_t
*ctx
, crypto_data_t
*out
, size_t block_size
,
195 int (*encrypt_block
)(const void *, const uint8_t *, uint8_t *),
196 void (*xor_block
)(uint8_t *, uint8_t *))
198 uint8_t *lastp
, *mac_buf
, *ccm_mac_p
, *macp
= NULL
;
203 size_t out_data_1_len
;
206 if (out
->cd_length
< (ctx
->ccm_remainder_len
+ ctx
->ccm_mac_len
)) {
207 return (CRYPTO_DATA_LEN_RANGE
);
211 * When we get here, the number of bytes of payload processed
212 * plus whatever data remains, if any,
213 * should be the same as the number of bytes that's being
214 * passed in the argument during init time.
216 if ((ctx
->ccm_processed_data_len
+ ctx
->ccm_remainder_len
)
217 != (ctx
->ccm_data_len
)) {
218 return (CRYPTO_DATA_LEN_RANGE
);
221 mac_buf
= (uint8_t *)ctx
->ccm_mac_buf
;
223 if (ctx
->ccm_remainder_len
> 0) {
225 /* ccm_mac_input_buf is not used for encryption */
226 macp
= (uint8_t *)ctx
->ccm_mac_input_buf
;
227 memset(macp
, 0, block_size
);
229 /* copy remainder to temporary buffer */
230 memcpy(macp
, ctx
->ccm_remainder
, ctx
->ccm_remainder_len
);
232 /* calculate the CBC MAC */
233 xor_block(macp
, mac_buf
);
234 encrypt_block(ctx
->ccm_keysched
, mac_buf
, mac_buf
);
236 /* calculate the counter mode */
237 lastp
= (uint8_t *)ctx
->ccm_tmp
;
238 encrypt_block(ctx
->ccm_keysched
, (uint8_t *)ctx
->ccm_cb
, lastp
);
240 /* XOR with counter block */
241 for (i
= 0; i
< ctx
->ccm_remainder_len
; i
++) {
244 ctx
->ccm_processed_data_len
+= ctx
->ccm_remainder_len
;
247 /* Calculate the CCM MAC */
248 ccm_mac_p
= (uint8_t *)ctx
->ccm_tmp
;
249 calculate_ccm_mac(ctx
, ccm_mac_p
, encrypt_block
);
251 crypto_init_ptrs(out
, &iov_or_mp
, &offset
);
252 crypto_get_ptrs(out
, &iov_or_mp
, &offset
, &out_data_1
,
253 &out_data_1_len
, &out_data_2
,
254 ctx
->ccm_remainder_len
+ ctx
->ccm_mac_len
);
256 if (ctx
->ccm_remainder_len
> 0) {
257 /* copy temporary block to where it belongs */
258 if (out_data_2
== NULL
) {
259 /* everything will fit in out_data_1 */
260 memcpy(out_data_1
, macp
, ctx
->ccm_remainder_len
);
261 memcpy(out_data_1
+ ctx
->ccm_remainder_len
, ccm_mac_p
,
264 if (out_data_1_len
< ctx
->ccm_remainder_len
) {
265 size_t data_2_len_used
;
267 memcpy(out_data_1
, macp
, out_data_1_len
);
269 data_2_len_used
= ctx
->ccm_remainder_len
273 (uint8_t *)macp
+ out_data_1_len
,
275 memcpy(out_data_2
+ data_2_len_used
,
279 memcpy(out_data_1
, macp
, out_data_1_len
);
280 if (out_data_1_len
== ctx
->ccm_remainder_len
) {
281 /* mac will be in out_data_2 */
282 memcpy(out_data_2
, ccm_mac_p
,
285 size_t len_not_used
= out_data_1_len
-
286 ctx
->ccm_remainder_len
;
288 * part of mac in will be in
289 * out_data_1, part of the mac will be
293 ctx
->ccm_remainder_len
,
294 ccm_mac_p
, len_not_used
);
296 ccm_mac_p
+ len_not_used
,
297 ctx
->ccm_mac_len
- len_not_used
);
303 /* copy block to where it belongs */
304 memcpy(out_data_1
, ccm_mac_p
, out_data_1_len
);
305 if (out_data_2
!= NULL
) {
306 memcpy(out_data_2
, ccm_mac_p
+ out_data_1_len
,
307 block_size
- out_data_1_len
);
310 out
->cd_offset
+= ctx
->ccm_remainder_len
+ ctx
->ccm_mac_len
;
311 ctx
->ccm_remainder_len
= 0;
312 return (CRYPTO_SUCCESS
);
316 * This will only deal with decrypting the last block of the input that
317 * might not be a multiple of block length.
320 ccm_decrypt_incomplete_block(ccm_ctx_t
*ctx
,
321 int (*encrypt_block
)(const void *, const uint8_t *, uint8_t *))
323 uint8_t *datap
, *outp
, *counterp
;
326 datap
= (uint8_t *)ctx
->ccm_remainder
;
327 outp
= &((ctx
->ccm_pt_buf
)[ctx
->ccm_processed_data_len
]);
329 counterp
= (uint8_t *)ctx
->ccm_tmp
;
330 encrypt_block(ctx
->ccm_keysched
, (uint8_t *)ctx
->ccm_cb
, counterp
);
332 /* XOR with counter block */
333 for (i
= 0; i
< ctx
->ccm_remainder_len
; i
++) {
334 outp
[i
] = datap
[i
] ^ counterp
[i
];
339 * This will decrypt the cipher text. However, the plaintext won't be
340 * returned to the caller. It will be returned when decrypt_final() is
341 * called if the MAC matches
344 ccm_mode_decrypt_contiguous_blocks(ccm_ctx_t
*ctx
, char *data
, size_t length
,
345 crypto_data_t
*out
, size_t block_size
,
346 int (*encrypt_block
)(const void *, const uint8_t *, uint8_t *),
347 void (*copy_block
)(uint8_t *, uint8_t *),
348 void (*xor_block
)(uint8_t *, uint8_t *))
351 size_t remainder
= length
;
353 uint8_t *datap
= (uint8_t *)data
;
357 size_t pt_len
, total_decrypted_len
, mac_len
, pm_len
, pd_len
;
361 pm_len
= ctx
->ccm_processed_mac_len
;
366 * all ciphertext has been processed, just waiting for
367 * part of the value of the mac
369 if ((pm_len
+ length
) > ctx
->ccm_mac_len
) {
370 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE
);
372 tmp
= (uint8_t *)ctx
->ccm_mac_input_buf
;
374 memcpy(tmp
+ pm_len
, datap
, length
);
376 ctx
->ccm_processed_mac_len
+= length
;
377 return (CRYPTO_SUCCESS
);
381 * If we decrypt the given data, what total amount of data would
382 * have been decrypted?
384 pd_len
= ctx
->ccm_processed_data_len
;
385 total_decrypted_len
= pd_len
+ length
+ ctx
->ccm_remainder_len
;
387 if (total_decrypted_len
>
388 (ctx
->ccm_data_len
+ ctx
->ccm_mac_len
)) {
389 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE
);
392 pt_len
= ctx
->ccm_data_len
;
394 if (total_decrypted_len
> pt_len
) {
396 * part of the input will be the MAC, need to isolate that
397 * to be dealt with later. The left-over data in
398 * ccm_remainder_len from last time will not be part of the
399 * MAC. Otherwise, it would have already been taken out
400 * when this call is made last time.
402 size_t pt_part
= pt_len
- pd_len
- ctx
->ccm_remainder_len
;
404 mac_len
= length
- pt_part
;
406 ctx
->ccm_processed_mac_len
= mac_len
;
407 memcpy(ctx
->ccm_mac_input_buf
, data
+ pt_part
, mac_len
);
409 if (pt_part
+ ctx
->ccm_remainder_len
< block_size
) {
411 * since this is last of the ciphertext, will
412 * just decrypt with it here
414 memcpy(&((uint8_t *)ctx
->ccm_remainder
)
415 [ctx
->ccm_remainder_len
], datap
, pt_part
);
416 ctx
->ccm_remainder_len
+= pt_part
;
417 ccm_decrypt_incomplete_block(ctx
, encrypt_block
);
418 ctx
->ccm_processed_data_len
+= ctx
->ccm_remainder_len
;
419 ctx
->ccm_remainder_len
= 0;
420 return (CRYPTO_SUCCESS
);
422 /* let rest of the code handle this */
425 } else if (length
+ ctx
->ccm_remainder_len
< block_size
) {
426 /* accumulate bytes here and return */
427 memcpy((uint8_t *)ctx
->ccm_remainder
+ ctx
->ccm_remainder_len
,
430 ctx
->ccm_remainder_len
+= length
;
431 ctx
->ccm_copy_to
= datap
;
432 return (CRYPTO_SUCCESS
);
436 /* Unprocessed data from last call. */
437 if (ctx
->ccm_remainder_len
> 0) {
438 need
= block_size
- ctx
->ccm_remainder_len
;
440 if (need
> remainder
)
441 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE
);
443 memcpy(&((uint8_t *)ctx
->ccm_remainder
)
444 [ctx
->ccm_remainder_len
], datap
, need
);
446 blockp
= (uint8_t *)ctx
->ccm_remainder
;
451 /* Calculate the counter mode, ccm_cb is the counter block */
452 cbp
= (uint8_t *)ctx
->ccm_tmp
;
453 encrypt_block(ctx
->ccm_keysched
, (uint8_t *)ctx
->ccm_cb
, cbp
);
457 * Counter bits are confined to the bottom 64 bits
459 #ifdef _ZFS_LITTLE_ENDIAN
460 counter
= ntohll(ctx
->ccm_cb
[1] & ctx
->ccm_counter_mask
);
461 counter
= htonll(counter
+ 1);
463 counter
= ctx
->ccm_cb
[1] & ctx
->ccm_counter_mask
;
465 #endif /* _ZFS_LITTLE_ENDIAN */
466 counter
&= ctx
->ccm_counter_mask
;
468 (ctx
->ccm_cb
[1] & ~(ctx
->ccm_counter_mask
)) | counter
;
470 /* XOR with the ciphertext */
471 xor_block(blockp
, cbp
);
473 /* Copy the plaintext to the "holding buffer" */
474 resultp
= (uint8_t *)ctx
->ccm_pt_buf
+
475 ctx
->ccm_processed_data_len
;
476 copy_block(cbp
, resultp
);
478 ctx
->ccm_processed_data_len
+= block_size
;
480 ctx
->ccm_lastp
= blockp
;
482 /* Update pointer to next block of data to be processed. */
483 if (ctx
->ccm_remainder_len
!= 0) {
485 ctx
->ccm_remainder_len
= 0;
490 remainder
= (size_t)&data
[length
] - (size_t)datap
;
492 /* Incomplete last block */
493 if (remainder
> 0 && remainder
< block_size
) {
494 memcpy(ctx
->ccm_remainder
, datap
, remainder
);
495 ctx
->ccm_remainder_len
= remainder
;
496 ctx
->ccm_copy_to
= datap
;
497 if (ctx
->ccm_processed_mac_len
> 0) {
499 * not expecting anymore ciphertext, just
500 * compute plaintext for the remaining input
502 ccm_decrypt_incomplete_block(ctx
,
504 ctx
->ccm_processed_data_len
+= remainder
;
505 ctx
->ccm_remainder_len
= 0;
509 ctx
->ccm_copy_to
= NULL
;
511 } while (remainder
> 0);
514 return (CRYPTO_SUCCESS
);
518 ccm_decrypt_final(ccm_ctx_t
*ctx
, crypto_data_t
*out
, size_t block_size
,
519 int (*encrypt_block
)(const void *, const uint8_t *, uint8_t *),
520 void (*copy_block
)(uint8_t *, uint8_t *),
521 void (*xor_block
)(uint8_t *, uint8_t *))
523 size_t mac_remain
, pt_len
;
524 uint8_t *pt
, *mac_buf
, *macp
, *ccm_mac_p
;
527 pt_len
= ctx
->ccm_data_len
;
529 /* Make sure output buffer can fit all of the plaintext */
530 if (out
->cd_length
< pt_len
) {
531 return (CRYPTO_DATA_LEN_RANGE
);
534 pt
= ctx
->ccm_pt_buf
;
535 mac_remain
= ctx
->ccm_processed_data_len
;
536 mac_buf
= (uint8_t *)ctx
->ccm_mac_buf
;
538 macp
= (uint8_t *)ctx
->ccm_tmp
;
540 while (mac_remain
> 0) {
541 if (mac_remain
< block_size
) {
542 memset(macp
, 0, block_size
);
543 memcpy(macp
, pt
, mac_remain
);
546 copy_block(pt
, macp
);
547 mac_remain
-= block_size
;
551 /* calculate the CBC MAC */
552 xor_block(macp
, mac_buf
);
553 encrypt_block(ctx
->ccm_keysched
, mac_buf
, mac_buf
);
556 /* Calculate the CCM MAC */
557 ccm_mac_p
= (uint8_t *)ctx
->ccm_tmp
;
558 calculate_ccm_mac((ccm_ctx_t
*)ctx
, ccm_mac_p
, encrypt_block
);
560 /* compare the input CCM MAC value with what we calculated */
561 if (memcmp(ctx
->ccm_mac_input_buf
, ccm_mac_p
, ctx
->ccm_mac_len
)) {
562 /* They don't match */
563 return (CRYPTO_INVALID_MAC
);
565 rv
= crypto_put_output_data(ctx
->ccm_pt_buf
, out
, pt_len
);
566 if (rv
!= CRYPTO_SUCCESS
)
568 out
->cd_offset
+= pt_len
;
570 return (CRYPTO_SUCCESS
);
574 ccm_validate_args(CK_AES_CCM_PARAMS
*ccm_param
, boolean_t is_encrypt_init
)
576 size_t macSize
, nonceSize
;
581 * Check the length of the MAC. The only valid
582 * lengths for the MAC are: 4, 6, 8, 10, 12, 14, 16
584 macSize
= ccm_param
->ulMACSize
;
585 if ((macSize
< 4) || (macSize
> 16) || ((macSize
% 2) != 0)) {
586 return (CRYPTO_MECHANISM_PARAM_INVALID
);
589 /* Check the nonce length. Valid values are 7, 8, 9, 10, 11, 12, 13 */
590 nonceSize
= ccm_param
->ulNonceSize
;
591 if ((nonceSize
< 7) || (nonceSize
> 13)) {
592 return (CRYPTO_MECHANISM_PARAM_INVALID
);
595 /* q is the length of the field storing the length, in bytes */
596 q
= (uint8_t)((15 - nonceSize
) & 0xFF);
600 * If it is decrypt, need to make sure size of ciphertext is at least
601 * bigger than MAC len
603 if ((!is_encrypt_init
) && (ccm_param
->ulDataSize
< macSize
)) {
604 return (CRYPTO_MECHANISM_PARAM_INVALID
);
608 * Check to make sure the length of the payload is within the
609 * range of values allowed by q
612 maxValue
= (1ULL << (q
* 8)) - 1;
614 maxValue
= ULONG_MAX
;
617 if (ccm_param
->ulDataSize
> maxValue
) {
618 return (CRYPTO_MECHANISM_PARAM_INVALID
);
620 return (CRYPTO_SUCCESS
);
624 * Format the first block used in CBC-MAC (B0) and the initial counter
625 * block based on formatting functions and counter generation functions
626 * specified in RFC 3610 and NIST publication 800-38C, appendix A
628 * b0 is the first block used in CBC-MAC
629 * cb0 is the first counter block
631 * It's assumed that the arguments b0 and cb0 are preallocated AES blocks
635 ccm_format_initial_blocks(uchar_t
*nonce
, ulong_t nonceSize
,
636 ulong_t authDataSize
, uint8_t *b0
, ccm_ctx_t
*aes_ctx
)
638 uint64_t payloadSize
;
639 uint8_t t
, q
, have_adata
= 0;
645 q
= (uint8_t)((15 - nonceSize
) & 0xFF);
646 t
= (uint8_t)((aes_ctx
->ccm_mac_len
) & 0xFF);
648 /* Construct the first octet of b0 */
649 if (authDataSize
> 0) {
652 b0
[0] = (have_adata
<< 6) | (((t
- 2) / 2) << 3) | (q
- 1);
654 /* copy the nonce value into b0 */
655 memcpy(&(b0
[1]), nonce
, nonceSize
);
657 /* store the length of the payload into b0 */
658 memset(&(b0
[1+nonceSize
]), 0, q
);
660 payloadSize
= aes_ctx
->ccm_data_len
;
661 limit
= 8 < q
? 8 : q
;
663 for (i
= 0, j
= 0, k
= 15; i
< limit
; i
++, j
+= 8, k
--) {
664 b0
[k
] = (uint8_t)((payloadSize
>> j
) & 0xFF);
667 /* format the counter block */
669 cb
= (uint8_t *)aes_ctx
->ccm_cb
;
671 cb
[0] = 0x07 & (q
-1); /* first byte */
673 /* copy the nonce value into the counter block */
674 memcpy(&(cb
[1]), nonce
, nonceSize
);
676 memset(&(cb
[1+nonceSize
]), 0, q
);
678 /* Create the mask for the counter field based on the size of nonce */
684 #ifdef _ZFS_LITTLE_ENDIAN
687 aes_ctx
->ccm_counter_mask
= mask
;
690 * During calculation, we start using counter block 1, we will
691 * set it up right here.
692 * We can just set the last byte to have the value 1, because
693 * even with the biggest nonce of 13, the last byte of the
694 * counter block will be used for the counter value.
700 * Encode the length of the associated data as
701 * specified in RFC 3610 and NIST publication 800-38C, appendix A
704 encode_adata_len(ulong_t auth_data_len
, uint8_t *encoded
, size_t *encoded_len
)
706 #ifdef UNALIGNED_POINTERS_PERMITTED
707 uint32_t *lencoded_ptr
;
709 uint64_t *llencoded_ptr
;
711 #endif /* UNALIGNED_POINTERS_PERMITTED */
713 if (auth_data_len
< ((1ULL<<16) - (1ULL<<8))) {
714 /* 0 < a < (2^16-2^8) */
716 encoded
[0] = (auth_data_len
& 0xff00) >> 8;
717 encoded
[1] = auth_data_len
& 0xff;
719 } else if ((auth_data_len
>= ((1ULL<<16) - (1ULL<<8))) &&
720 (auth_data_len
< (1ULL << 31))) {
721 /* (2^16-2^8) <= a < 2^32 */
725 #ifdef UNALIGNED_POINTERS_PERMITTED
726 lencoded_ptr
= (uint32_t *)&encoded
[2];
727 *lencoded_ptr
= htonl(auth_data_len
);
729 encoded
[2] = (auth_data_len
& 0xff000000) >> 24;
730 encoded
[3] = (auth_data_len
& 0xff0000) >> 16;
731 encoded
[4] = (auth_data_len
& 0xff00) >> 8;
732 encoded
[5] = auth_data_len
& 0xff;
733 #endif /* UNALIGNED_POINTERS_PERMITTED */
737 /* 2^32 <= a < 2^64 */
741 #ifdef UNALIGNED_POINTERS_PERMITTED
742 llencoded_ptr
= (uint64_t *)&encoded
[2];
743 *llencoded_ptr
= htonl(auth_data_len
);
745 encoded
[2] = (auth_data_len
& 0xff00000000000000) >> 56;
746 encoded
[3] = (auth_data_len
& 0xff000000000000) >> 48;
747 encoded
[4] = (auth_data_len
& 0xff0000000000) >> 40;
748 encoded
[5] = (auth_data_len
& 0xff00000000) >> 32;
749 encoded
[6] = (auth_data_len
& 0xff000000) >> 24;
750 encoded
[7] = (auth_data_len
& 0xff0000) >> 16;
751 encoded
[8] = (auth_data_len
& 0xff00) >> 8;
752 encoded
[9] = auth_data_len
& 0xff;
753 #endif /* UNALIGNED_POINTERS_PERMITTED */
759 ccm_init(ccm_ctx_t
*ctx
, unsigned char *nonce
, size_t nonce_len
,
760 unsigned char *auth_data
, size_t auth_data_len
, size_t block_size
,
761 int (*encrypt_block
)(const void *, const uint8_t *, uint8_t *),
762 void (*xor_block
)(uint8_t *, uint8_t *))
764 uint8_t *mac_buf
, *datap
, *ivp
, *authp
;
765 size_t remainder
, processed
;
766 uint8_t encoded_a
[10]; /* max encoded auth data length is 10 octets */
767 size_t encoded_a_len
= 0;
769 mac_buf
= (uint8_t *)&(ctx
->ccm_mac_buf
);
772 * Format the 1st block for CBC-MAC and construct the
775 * aes_ctx->ccm_iv is used for storing the counter block
776 * mac_buf will store b0 at this time.
778 ccm_format_initial_blocks(nonce
, nonce_len
,
779 auth_data_len
, mac_buf
, ctx
);
781 /* The IV for CBC MAC for AES CCM mode is always zero */
782 ivp
= (uint8_t *)ctx
->ccm_tmp
;
783 memset(ivp
, 0, block_size
);
785 xor_block(ivp
, mac_buf
);
787 /* encrypt the nonce */
788 encrypt_block(ctx
->ccm_keysched
, mac_buf
, mac_buf
);
790 /* take care of the associated data, if any */
791 if (auth_data_len
== 0) {
792 return (CRYPTO_SUCCESS
);
795 encode_adata_len(auth_data_len
, encoded_a
, &encoded_a_len
);
797 remainder
= auth_data_len
;
799 /* 1st block: it contains encoded associated data, and some data */
800 authp
= (uint8_t *)ctx
->ccm_tmp
;
801 memset(authp
, 0, block_size
);
802 memcpy(authp
, encoded_a
, encoded_a_len
);
803 processed
= block_size
- encoded_a_len
;
804 if (processed
> auth_data_len
) {
805 /* in case auth_data is very small */
806 processed
= auth_data_len
;
808 memcpy(authp
+encoded_a_len
, auth_data
, processed
);
809 /* xor with previous buffer */
810 xor_block(authp
, mac_buf
);
811 encrypt_block(ctx
->ccm_keysched
, mac_buf
, mac_buf
);
812 remainder
-= processed
;
813 if (remainder
== 0) {
814 /* a small amount of associated data, it's all done now */
815 return (CRYPTO_SUCCESS
);
819 if (remainder
< block_size
) {
821 * There's not a block full of data, pad rest of
824 memset(authp
, 0, block_size
);
825 memcpy(authp
, &(auth_data
[processed
]), remainder
);
826 datap
= (uint8_t *)authp
;
829 datap
= (uint8_t *)(&(auth_data
[processed
]));
830 processed
+= block_size
;
831 remainder
-= block_size
;
834 xor_block(datap
, mac_buf
);
835 encrypt_block(ctx
->ccm_keysched
, mac_buf
, mac_buf
);
837 } while (remainder
> 0);
839 return (CRYPTO_SUCCESS
);
843 * The following function should be call at encrypt or decrypt init time
847 ccm_init_ctx(ccm_ctx_t
*ccm_ctx
, char *param
, int kmflag
,
848 boolean_t is_encrypt_init
, size_t block_size
,
849 int (*encrypt_block
)(const void *, const uint8_t *, uint8_t *),
850 void (*xor_block
)(uint8_t *, uint8_t *))
853 CK_AES_CCM_PARAMS
*ccm_param
;
856 ccm_param
= (CK_AES_CCM_PARAMS
*)param
;
858 if ((rv
= ccm_validate_args(ccm_param
,
859 is_encrypt_init
)) != 0) {
863 ccm_ctx
->ccm_mac_len
= ccm_param
->ulMACSize
;
864 if (is_encrypt_init
) {
865 ccm_ctx
->ccm_data_len
= ccm_param
->ulDataSize
;
867 ccm_ctx
->ccm_data_len
=
868 ccm_param
->ulDataSize
- ccm_ctx
->ccm_mac_len
;
869 ccm_ctx
->ccm_processed_mac_len
= 0;
871 ccm_ctx
->ccm_processed_data_len
= 0;
873 ccm_ctx
->ccm_flags
|= CCM_MODE
;
875 return (CRYPTO_MECHANISM_PARAM_INVALID
);
878 if (ccm_init(ccm_ctx
, ccm_param
->nonce
, ccm_param
->ulNonceSize
,
879 ccm_param
->authData
, ccm_param
->ulAuthDataSize
, block_size
,
880 encrypt_block
, xor_block
) != 0) {
881 return (CRYPTO_MECHANISM_PARAM_INVALID
);
883 if (!is_encrypt_init
) {
884 /* allocate buffer for storing decrypted plaintext */
885 ccm_ctx
->ccm_pt_buf
= vmem_alloc(ccm_ctx
->ccm_data_len
,
887 if (ccm_ctx
->ccm_pt_buf
== NULL
) {
888 rv
= CRYPTO_HOST_MEMORY
;
895 ccm_alloc_ctx(int kmflag
)
899 if ((ccm_ctx
= kmem_zalloc(sizeof (ccm_ctx_t
), kmflag
)) == NULL
)
902 ccm_ctx
->ccm_flags
= CCM_MODE
;