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>
30 #include <sys/byteorder.h>
33 * Encrypt and decrypt multiple blocks of data in counter mode.
36 ctr_mode_contiguous_blocks(ctr_ctx_t
*ctx
, char *data
, size_t length
,
37 crypto_data_t
*out
, size_t block_size
,
38 int (*cipher
)(const void *ks
, const uint8_t *pt
, uint8_t *ct
),
39 void (*xor_block
)(uint8_t *, uint8_t *))
41 size_t remainder
= length
;
43 uint8_t *datap
= (uint8_t *)data
;
50 size_t out_data_1_len
;
51 uint64_t lower_counter
, upper_counter
;
53 if (length
+ ctx
->ctr_remainder_len
< block_size
) {
54 /* accumulate bytes here and return */
56 (uint8_t *)ctx
->ctr_remainder
+ ctx
->ctr_remainder_len
,
58 ctx
->ctr_remainder_len
+= length
;
59 ctx
->ctr_copy_to
= datap
;
60 return (CRYPTO_SUCCESS
);
63 lastp
= (uint8_t *)ctx
->ctr_cb
;
65 crypto_init_ptrs(out
, &iov_or_mp
, &offset
);
68 /* Unprocessed data from last call. */
69 if (ctx
->ctr_remainder_len
> 0) {
70 need
= block_size
- ctx
->ctr_remainder_len
;
73 return (CRYPTO_DATA_LEN_RANGE
);
75 bcopy(datap
, &((uint8_t *)ctx
->ctr_remainder
)
76 [ctx
->ctr_remainder_len
], need
);
78 blockp
= (uint8_t *)ctx
->ctr_remainder
;
83 /* ctr_cb is the counter block */
84 cipher(ctx
->ctr_keysched
, (uint8_t *)ctx
->ctr_cb
,
85 (uint8_t *)ctx
->ctr_tmp
);
87 lastp
= (uint8_t *)ctx
->ctr_tmp
;
92 lower_counter
= ntohll(ctx
->ctr_cb
[1] & ctx
->ctr_lower_mask
);
93 lower_counter
= htonll(lower_counter
+ 1);
94 lower_counter
&= ctx
->ctr_lower_mask
;
95 ctx
->ctr_cb
[1] = (ctx
->ctr_cb
[1] & ~(ctx
->ctr_lower_mask
)) |
99 if (lower_counter
== 0) {
101 ntohll(ctx
->ctr_cb
[0] & ctx
->ctr_upper_mask
);
102 upper_counter
= htonll(upper_counter
+ 1);
103 upper_counter
&= ctx
->ctr_upper_mask
;
105 (ctx
->ctr_cb
[0] & ~(ctx
->ctr_upper_mask
)) |
110 * XOR encrypted counter block with the current clear block.
112 xor_block(blockp
, lastp
);
115 if (ctx
->ctr_remainder_len
> 0) {
116 bcopy(lastp
, ctx
->ctr_copy_to
,
117 ctx
->ctr_remainder_len
);
118 bcopy(lastp
+ ctx
->ctr_remainder_len
, datap
,
122 crypto_get_ptrs(out
, &iov_or_mp
, &offset
, &out_data_1
,
123 &out_data_1_len
, &out_data_2
, block_size
);
125 /* copy block to where it belongs */
126 bcopy(lastp
, out_data_1
, out_data_1_len
);
127 if (out_data_2
!= NULL
) {
128 bcopy(lastp
+ out_data_1_len
, out_data_2
,
129 block_size
- out_data_1_len
);
132 out
->cd_offset
+= block_size
;
135 /* Update pointer to next block of data to be processed. */
136 if (ctx
->ctr_remainder_len
!= 0) {
138 ctx
->ctr_remainder_len
= 0;
143 remainder
= (size_t)&data
[length
] - (size_t)datap
;
145 /* Incomplete last block. */
146 if (remainder
> 0 && remainder
< block_size
) {
147 bcopy(datap
, ctx
->ctr_remainder
, remainder
);
148 ctx
->ctr_remainder_len
= remainder
;
149 ctx
->ctr_copy_to
= datap
;
152 ctx
->ctr_copy_to
= NULL
;
154 } while (remainder
> 0);
157 return (CRYPTO_SUCCESS
);
161 ctr_mode_final(ctr_ctx_t
*ctx
, crypto_data_t
*out
,
162 int (*encrypt_block
)(const void *, const uint8_t *, uint8_t *))
169 size_t out_data_1_len
;
173 if (out
->cd_length
< ctx
->ctr_remainder_len
)
174 return (CRYPTO_DATA_LEN_RANGE
);
176 encrypt_block(ctx
->ctr_keysched
, (uint8_t *)ctx
->ctr_cb
,
177 (uint8_t *)ctx
->ctr_tmp
);
179 lastp
= (uint8_t *)ctx
->ctr_tmp
;
180 p
= (uint8_t *)ctx
->ctr_remainder
;
181 for (i
= 0; i
< ctx
->ctr_remainder_len
; i
++) {
185 crypto_init_ptrs(out
, &iov_or_mp
, &offset
);
186 crypto_get_ptrs(out
, &iov_or_mp
, &offset
, &out_data_1
,
187 &out_data_1_len
, &out_data_2
, ctx
->ctr_remainder_len
);
189 bcopy(p
, out_data_1
, out_data_1_len
);
190 if (out_data_2
!= NULL
) {
191 bcopy((uint8_t *)p
+ out_data_1_len
,
192 out_data_2
, ctx
->ctr_remainder_len
- out_data_1_len
);
194 out
->cd_offset
+= ctx
->ctr_remainder_len
;
195 ctx
->ctr_remainder_len
= 0;
196 return (CRYPTO_SUCCESS
);
200 ctr_init_ctx(ctr_ctx_t
*ctr_ctx
, ulong_t count
, uint8_t *cb
,
201 void (*copy_block
)(uint8_t *, uint8_t *))
203 uint64_t upper_mask
= 0;
204 uint64_t lower_mask
= 0;
206 if (count
== 0 || count
> 128) {
207 return (CRYPTO_MECHANISM_PARAM_INVALID
);
209 /* upper 64 bits of the mask */
212 upper_mask
= (count
== 64) ? UINT64_MAX
: (1ULL << count
) - 1;
213 lower_mask
= UINT64_MAX
;
215 /* now the lower 63 bits */
216 lower_mask
= (1ULL << count
) - 1;
218 ctr_ctx
->ctr_lower_mask
= htonll(lower_mask
);
219 ctr_ctx
->ctr_upper_mask
= htonll(upper_mask
);
221 copy_block(cb
, (uchar_t
*)ctr_ctx
->ctr_cb
);
222 ctr_ctx
->ctr_lastp
= (uint8_t *)&ctr_ctx
->ctr_cb
[0];
223 ctr_ctx
->ctr_flags
|= CTR_MODE
;
224 return (CRYPTO_SUCCESS
);
229 ctr_alloc_ctx(int kmflag
)
233 if ((ctr_ctx
= kmem_zalloc(sizeof (ctr_ctx_t
), kmflag
)) == NULL
)
236 ctr_ctx
->ctr_flags
= CTR_MODE
;