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.
30 #include <security/cryptoki.h>
33 #include <sys/types.h>
34 #include <modes/modes.h>
35 #include <sys/crypto/common.h>
36 #include <sys/crypto/impl.h>
37 #include <sys/byteorder.h>
40 * Encrypt and decrypt multiple blocks of data in counter mode.
43 ctr_mode_contiguous_blocks(ctr_ctx_t
*ctx
, char *data
, size_t length
,
44 crypto_data_t
*out
, size_t block_size
,
45 int (*cipher
)(const void *ks
, const uint8_t *pt
, uint8_t *ct
),
46 void (*xor_block
)(uint8_t *, uint8_t *))
48 size_t remainder
= length
;
50 uint8_t *datap
= (uint8_t *)data
;
57 size_t out_data_1_len
;
58 uint64_t lower_counter
, upper_counter
;
60 if (length
+ ctx
->ctr_remainder_len
< block_size
) {
61 /* accumulate bytes here and return */
63 (uint8_t *)ctx
->ctr_remainder
+ ctx
->ctr_remainder_len
,
65 ctx
->ctr_remainder_len
+= length
;
66 ctx
->ctr_copy_to
= datap
;
67 return (CRYPTO_SUCCESS
);
70 lastp
= (uint8_t *)ctx
->ctr_cb
;
72 crypto_init_ptrs(out
, &iov_or_mp
, &offset
);
75 /* Unprocessed data from last call. */
76 if (ctx
->ctr_remainder_len
> 0) {
77 need
= block_size
- ctx
->ctr_remainder_len
;
80 return (CRYPTO_DATA_LEN_RANGE
);
82 bcopy(datap
, &((uint8_t *)ctx
->ctr_remainder
)
83 [ctx
->ctr_remainder_len
], need
);
85 blockp
= (uint8_t *)ctx
->ctr_remainder
;
90 /* ctr_cb is the counter block */
91 cipher(ctx
->ctr_keysched
, (uint8_t *)ctx
->ctr_cb
,
92 (uint8_t *)ctx
->ctr_tmp
);
94 lastp
= (uint8_t *)ctx
->ctr_tmp
;
99 lower_counter
= ntohll(ctx
->ctr_cb
[1] & ctx
->ctr_lower_mask
);
100 lower_counter
= htonll(lower_counter
+ 1);
101 lower_counter
&= ctx
->ctr_lower_mask
;
102 ctx
->ctr_cb
[1] = (ctx
->ctr_cb
[1] & ~(ctx
->ctr_lower_mask
)) |
106 if (lower_counter
== 0) {
108 ntohll(ctx
->ctr_cb
[0] & ctx
->ctr_upper_mask
);
109 upper_counter
= htonll(upper_counter
+ 1);
110 upper_counter
&= ctx
->ctr_upper_mask
;
112 (ctx
->ctr_cb
[0] & ~(ctx
->ctr_upper_mask
)) |
117 * XOR encrypted counter block with the current clear block.
119 xor_block(blockp
, lastp
);
122 if (ctx
->ctr_remainder_len
> 0) {
123 bcopy(lastp
, ctx
->ctr_copy_to
,
124 ctx
->ctr_remainder_len
);
125 bcopy(lastp
+ ctx
->ctr_remainder_len
, datap
,
129 crypto_get_ptrs(out
, &iov_or_mp
, &offset
, &out_data_1
,
130 &out_data_1_len
, &out_data_2
, block_size
);
132 /* copy block to where it belongs */
133 bcopy(lastp
, out_data_1
, out_data_1_len
);
134 if (out_data_2
!= NULL
) {
135 bcopy(lastp
+ out_data_1_len
, out_data_2
,
136 block_size
- out_data_1_len
);
139 out
->cd_offset
+= block_size
;
142 /* Update pointer to next block of data to be processed. */
143 if (ctx
->ctr_remainder_len
!= 0) {
145 ctx
->ctr_remainder_len
= 0;
150 remainder
= (size_t)&data
[length
] - (size_t)datap
;
152 /* Incomplete last block. */
153 if (remainder
> 0 && remainder
< block_size
) {
154 bcopy(datap
, ctx
->ctr_remainder
, remainder
);
155 ctx
->ctr_remainder_len
= remainder
;
156 ctx
->ctr_copy_to
= datap
;
159 ctx
->ctr_copy_to
= NULL
;
161 } while (remainder
> 0);
164 return (CRYPTO_SUCCESS
);
168 ctr_mode_final(ctr_ctx_t
*ctx
, crypto_data_t
*out
,
169 int (*encrypt_block
)(const void *, const uint8_t *, uint8_t *))
176 size_t out_data_1_len
;
180 if (out
->cd_length
< ctx
->ctr_remainder_len
)
181 return (CRYPTO_DATA_LEN_RANGE
);
183 encrypt_block(ctx
->ctr_keysched
, (uint8_t *)ctx
->ctr_cb
,
184 (uint8_t *)ctx
->ctr_tmp
);
186 lastp
= (uint8_t *)ctx
->ctr_tmp
;
187 p
= (uint8_t *)ctx
->ctr_remainder
;
188 for (i
= 0; i
< ctx
->ctr_remainder_len
; i
++) {
192 crypto_init_ptrs(out
, &iov_or_mp
, &offset
);
193 crypto_get_ptrs(out
, &iov_or_mp
, &offset
, &out_data_1
,
194 &out_data_1_len
, &out_data_2
, ctx
->ctr_remainder_len
);
196 bcopy(p
, out_data_1
, out_data_1_len
);
197 if (out_data_2
!= NULL
) {
198 bcopy((uint8_t *)p
+ out_data_1_len
,
199 out_data_2
, ctx
->ctr_remainder_len
- out_data_1_len
);
201 out
->cd_offset
+= ctx
->ctr_remainder_len
;
202 ctx
->ctr_remainder_len
= 0;
203 return (CRYPTO_SUCCESS
);
207 ctr_init_ctx(ctr_ctx_t
*ctr_ctx
, ulong_t count
, uint8_t *cb
,
208 void (*copy_block
)(uint8_t *, uint8_t *))
210 uint64_t upper_mask
= 0;
211 uint64_t lower_mask
= 0;
213 if (count
== 0 || count
> 128) {
214 return (CRYPTO_MECHANISM_PARAM_INVALID
);
216 /* upper 64 bits of the mask */
219 upper_mask
= (count
== 64) ? UINT64_MAX
: (1ULL << count
) - 1;
220 lower_mask
= UINT64_MAX
;
222 /* now the lower 63 bits */
223 lower_mask
= (1ULL << count
) - 1;
225 ctr_ctx
->ctr_lower_mask
= htonll(lower_mask
);
226 ctr_ctx
->ctr_upper_mask
= htonll(upper_mask
);
228 copy_block(cb
, (uchar_t
*)ctr_ctx
->ctr_cb
);
229 ctr_ctx
->ctr_lastp
= (uint8_t *)&ctr_ctx
->ctr_cb
[0];
230 ctr_ctx
->ctr_flags
|= CTR_MODE
;
231 return (CRYPTO_SUCCESS
);
236 ctr_alloc_ctx(int kmflag
)
241 if ((ctr_ctx
= kmem_zalloc(sizeof (ctr_ctx_t
), kmflag
)) == NULL
)
243 if ((ctr_ctx
= calloc(1, sizeof (ctr_ctx_t
))) == NULL
)
247 ctr_ctx
->ctr_flags
= CTR_MODE
;