6 * You may not use this file except in compliance with the License.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #ifndef _KERNEL
29 #include <strings.h>
30 #include <limits.h>
31 #include <assert.h>
32 #include <security/cryptoki.h>
33 #endif
34
35 #include <sys/types.h>
36 #include <modes/modes.h>
37 #include <sys/crypto/common.h>
38 #include <sys/crypto/impl.h>
39
40 /*
41 * Encrypt and decrypt multiple blocks of data in counter mode.
42 */
43 int
44 ctr_mode_contiguous_blocks(ctr_ctx_t *ctx, char *data, size_t length,
45 crypto_data_t *out, size_t block_size,
46 int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct),
47 void (*xor_block)(uint8_t *, uint8_t *))
48 {
49 size_t remainder = length;
50 size_t need;
51 uint8_t *datap = (uint8_t *)data;
52 uint8_t *blockp;
53 uint8_t *lastp;
54 void *iov_or_mp;
55 offset_t offset;
56 uint8_t *out_data_1;
57 uint8_t *out_data_2;
58 size_t out_data_1_len;
59 uint64_t counter;
84 return (CRYPTO_DATA_LEN_RANGE);
85
86 bcopy(datap, &((uint8_t *)ctx->ctr_remainder)
87 [ctx->ctr_remainder_len], need);
88
89 blockp = (uint8_t *)ctx->ctr_remainder;
90 } else {
91 blockp = datap;
92 }
93
94 /* ctr_cb is the counter block */
95 cipher(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb,
96 (uint8_t *)ctx->ctr_tmp);
97
98 lastp = (uint8_t *)ctx->ctr_tmp;
99
100 /*
101 * Increment counter. Counter bits are confined
102 * to the bottom 64 bits of the counter block.
103 */
104 counter = ctx->ctr_cb[1] & ctx->ctr_counter_mask;
105 #ifdef _LITTLE_ENDIAN
106 p = (uint8_t *)&counter;
107 counter = (((uint64_t)p[0] << 56) |
108 ((uint64_t)p[1] << 48) |
109 ((uint64_t)p[2] << 40) |
110 ((uint64_t)p[3] << 32) |
111 ((uint64_t)p[4] << 24) |
112 ((uint64_t)p[5] << 16) |
113 ((uint64_t)p[6] << 8) |
114 (uint64_t)p[7]);
115 #endif
116 counter++;
117 #ifdef _LITTLE_ENDIAN
118 counter = (((uint64_t)p[0] << 56) |
119 ((uint64_t)p[1] << 48) |
120 ((uint64_t)p[2] << 40) |
121 ((uint64_t)p[3] << 32) |
122 ((uint64_t)p[4] << 24) |
123 ((uint64_t)p[5] << 16) |
124 ((uint64_t)p[6] << 8) |
125 (uint64_t)p[7]);
126 #endif
127 counter &= ctx->ctr_counter_mask;
128 ctx->ctr_cb[1] =
129 (ctx->ctr_cb[1] & ~(ctx->ctr_counter_mask)) | counter;
130
131 /*
132 * XOR the previous cipher block or IV with the
133 * current clear block.
134 */
135 xor_block(blockp, lastp);
136
137 if (out == NULL) {
138 if (ctx->ctr_remainder_len > 0) {
139 bcopy(lastp, ctx->ctr_copy_to,
140 ctx->ctr_remainder_len);
141 bcopy(lastp + ctx->ctr_remainder_len, datap,
142 need);
143 }
144 } else {
145 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
146 &out_data_1_len, &out_data_2, block_size);
207
208 crypto_init_ptrs(out, &iov_or_mp, &offset);
209 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
210 &out_data_1_len, &out_data_2, ctx->ctr_remainder_len);
211
212 bcopy(p, out_data_1, out_data_1_len);
213 if (out_data_2 != NULL) {
214 bcopy((uint8_t *)p + out_data_1_len,
215 out_data_2, ctx->ctr_remainder_len - out_data_1_len);
216 }
217 out->cd_offset += ctx->ctr_remainder_len;
218 ctx->ctr_remainder_len = 0;
219 return (CRYPTO_SUCCESS);
220 }
221
222 int
223 ctr_init_ctx(ctr_ctx_t *ctr_ctx, ulong_t count, uint8_t *cb,
224 void (*copy_block)(uint8_t *, uint8_t *))
225 {
226 uint64_t mask = 0;
227 #ifdef _LITTLE_ENDIAN
228 uint8_t *p8;
229 #endif
230
231 if (count == 0 || count > 64) {
232 return (CRYPTO_MECHANISM_PARAM_INVALID);
233 }
234 while (count-- > 0)
235 mask |= (1ULL << count);
236 #ifdef _LITTLE_ENDIAN
237 p8 = (uint8_t *)&mask;
238 mask = (((uint64_t)p8[0] << 56) |
239 ((uint64_t)p8[1] << 48) |
240 ((uint64_t)p8[2] << 40) |
241 ((uint64_t)p8[3] << 32) |
242 ((uint64_t)p8[4] << 24) |
243 ((uint64_t)p8[5] << 16) |
244 ((uint64_t)p8[6] << 8) |
245 (uint64_t)p8[7]);
246 #endif
247 ctr_ctx->ctr_counter_mask = mask;
248 copy_block(cb, (uchar_t *)ctr_ctx->ctr_cb);
249 ctr_ctx->ctr_lastp = (uint8_t *)&ctr_ctx->ctr_cb[0];
250 ctr_ctx->ctr_flags |= CTR_MODE;
251 return (CRYPTO_SUCCESS);
252 }
253
254 /* ARGSUSED */
255 void *
256 ctr_alloc_ctx(int kmflag)
257 {
258 ctr_ctx_t *ctr_ctx;
259
260 #ifdef _KERNEL
261 if ((ctr_ctx = kmem_zalloc(sizeof (ctr_ctx_t), kmflag)) == NULL)
262 #else
263 if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
264 #endif
265 return (NULL);
|
6 * You may not use this file except in compliance with the License.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #ifndef _KERNEL
27 #include <strings.h>
28 #include <limits.h>
29 #include <assert.h>
30 #include <security/cryptoki.h>
31 #endif
32
33 #include <sys/types.h>
34 #include <modes/modes.h>
35 #include <sys/crypto/common.h>
36 #include <sys/crypto/impl.h>
37
38 #ifdef _LITTLE_ENDIAN
39 #include <sys/byteorder.h>
40 #endif
41
42 /*
43 * Encrypt and decrypt multiple blocks of data in counter mode.
44 */
45 int
46 ctr_mode_contiguous_blocks(ctr_ctx_t *ctx, char *data, size_t length,
47 crypto_data_t *out, size_t block_size,
48 int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct),
49 void (*xor_block)(uint8_t *, uint8_t *))
50 {
51 size_t remainder = length;
52 size_t need;
53 uint8_t *datap = (uint8_t *)data;
54 uint8_t *blockp;
55 uint8_t *lastp;
56 void *iov_or_mp;
57 offset_t offset;
58 uint8_t *out_data_1;
59 uint8_t *out_data_2;
60 size_t out_data_1_len;
61 uint64_t counter;
86 return (CRYPTO_DATA_LEN_RANGE);
87
88 bcopy(datap, &((uint8_t *)ctx->ctr_remainder)
89 [ctx->ctr_remainder_len], need);
90
91 blockp = (uint8_t *)ctx->ctr_remainder;
92 } else {
93 blockp = datap;
94 }
95
96 /* ctr_cb is the counter block */
97 cipher(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb,
98 (uint8_t *)ctx->ctr_tmp);
99
100 lastp = (uint8_t *)ctx->ctr_tmp;
101
102 /*
103 * Increment counter. Counter bits are confined
104 * to the bottom 64 bits of the counter block.
105 */
106 #ifdef _LITTLE_ENDIAN
107 counter = ntohll(ctx->ctr_cb[1] & ctx->ctr_counter_mask);
108 counter = htonll(counter + 1);
109 #else
110 counter = ctx->ctr_cb[1] & ctx->ctr_counter_mask;
111 counter++;
112 #endif /* _LITTLE_ENDIAN */
113 counter &= ctx->ctr_counter_mask;
114 ctx->ctr_cb[1] =
115 (ctx->ctr_cb[1] & ~(ctx->ctr_counter_mask)) | counter;
116
117 /*
118 * XOR the previous cipher block or IV with the
119 * current clear block.
120 */
121 xor_block(blockp, lastp);
122
123 if (out == NULL) {
124 if (ctx->ctr_remainder_len > 0) {
125 bcopy(lastp, ctx->ctr_copy_to,
126 ctx->ctr_remainder_len);
127 bcopy(lastp + ctx->ctr_remainder_len, datap,
128 need);
129 }
130 } else {
131 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
132 &out_data_1_len, &out_data_2, block_size);
193
194 crypto_init_ptrs(out, &iov_or_mp, &offset);
195 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
196 &out_data_1_len, &out_data_2, ctx->ctr_remainder_len);
197
198 bcopy(p, out_data_1, out_data_1_len);
199 if (out_data_2 != NULL) {
200 bcopy((uint8_t *)p + out_data_1_len,
201 out_data_2, ctx->ctr_remainder_len - out_data_1_len);
202 }
203 out->cd_offset += ctx->ctr_remainder_len;
204 ctx->ctr_remainder_len = 0;
205 return (CRYPTO_SUCCESS);
206 }
207
208 int
209 ctr_init_ctx(ctr_ctx_t *ctr_ctx, ulong_t count, uint8_t *cb,
210 void (*copy_block)(uint8_t *, uint8_t *))
211 {
212 uint64_t mask = 0;
213
214 if (count == 0 || count > 64) {
215 return (CRYPTO_MECHANISM_PARAM_INVALID);
216 }
217 while (count-- > 0)
218 mask |= (1ULL << count);
219
220 #ifdef _LITTLE_ENDIAN
221 mask = htonll(mask);
222 #endif
223 ctr_ctx->ctr_counter_mask = mask;
224 copy_block(cb, (uchar_t *)ctr_ctx->ctr_cb);
225 ctr_ctx->ctr_lastp = (uint8_t *)&ctr_ctx->ctr_cb[0];
226 ctr_ctx->ctr_flags |= CTR_MODE;
227 return (CRYPTO_SUCCESS);
228 }
229
230 /* ARGSUSED */
231 void *
232 ctr_alloc_ctx(int kmflag)
233 {
234 ctr_ctx_t *ctr_ctx;
235
236 #ifdef _KERNEL
237 if ((ctr_ctx = kmem_zalloc(sizeof (ctr_ctx_t), kmflag)) == NULL)
238 #else
239 if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
240 #endif
241 return (NULL);
|