Print this page
5007142 Add ntohll and htonll to sys/byteorder.h
6717509 Need to use bswap/bswapq for byte swap of 64-bit integer on x32/x64
PSARC 2008/474
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/common/crypto/modes/ctr.c
+++ new/usr/src/common/crypto/modes/ctr.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 -#pragma ident "%Z%%M% %I% %E% SMI"
27 -
28 26 #ifndef _KERNEL
29 27 #include <strings.h>
30 28 #include <limits.h>
31 29 #include <assert.h>
32 30 #include <security/cryptoki.h>
33 31 #endif
34 32
35 33 #include <sys/types.h>
36 34 #include <modes/modes.h>
37 35 #include <sys/crypto/common.h>
38 36 #include <sys/crypto/impl.h>
39 37
38 +#ifdef _LITTLE_ENDIAN
39 +#include <sys/byteorder.h>
40 +#endif
41 +
40 42 /*
41 43 * Encrypt and decrypt multiple blocks of data in counter mode.
42 44 */
43 45 int
44 46 ctr_mode_contiguous_blocks(ctr_ctx_t *ctx, char *data, size_t length,
45 47 crypto_data_t *out, size_t block_size,
46 48 int (*cipher)(const void *ks, const uint8_t *pt, uint8_t *ct),
47 49 void (*xor_block)(uint8_t *, uint8_t *))
48 50 {
49 51 size_t remainder = length;
50 52 size_t need;
51 53 uint8_t *datap = (uint8_t *)data;
52 54 uint8_t *blockp;
53 55 uint8_t *lastp;
54 56 void *iov_or_mp;
55 57 offset_t offset;
56 58 uint8_t *out_data_1;
57 59 uint8_t *out_data_2;
58 60 size_t out_data_1_len;
59 61 uint64_t counter;
60 62 #ifdef _LITTLE_ENDIAN
61 63 uint8_t *p;
62 64 #endif
63 65
64 66 if (length + ctx->ctr_remainder_len < block_size) {
65 67 /* accumulate bytes here and return */
66 68 bcopy(datap,
67 69 (uint8_t *)ctx->ctr_remainder + ctx->ctr_remainder_len,
68 70 length);
69 71 ctx->ctr_remainder_len += length;
70 72 ctx->ctr_copy_to = datap;
71 73 return (CRYPTO_SUCCESS);
72 74 }
73 75
74 76 lastp = (uint8_t *)ctx->ctr_cb;
75 77 if (out != NULL)
76 78 crypto_init_ptrs(out, &iov_or_mp, &offset);
77 79
78 80 do {
79 81 /* Unprocessed data from last call. */
80 82 if (ctx->ctr_remainder_len > 0) {
81 83 need = block_size - ctx->ctr_remainder_len;
82 84
83 85 if (need > remainder)
84 86 return (CRYPTO_DATA_LEN_RANGE);
85 87
86 88 bcopy(datap, &((uint8_t *)ctx->ctr_remainder)
87 89 [ctx->ctr_remainder_len], need);
88 90
89 91 blockp = (uint8_t *)ctx->ctr_remainder;
90 92 } else {
91 93 blockp = datap;
92 94 }
93 95
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
94 96 /* ctr_cb is the counter block */
95 97 cipher(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb,
96 98 (uint8_t *)ctx->ctr_tmp);
97 99
98 100 lastp = (uint8_t *)ctx->ctr_tmp;
99 101
100 102 /*
101 103 * Increment counter. Counter bits are confined
102 104 * to the bottom 64 bits of the counter block.
103 105 */
104 - counter = ctx->ctr_cb[1] & ctx->ctr_counter_mask;
105 106 #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
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;
116 111 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
112 +#endif /* _LITTLE_ENDIAN */
127 113 counter &= ctx->ctr_counter_mask;
128 114 ctx->ctr_cb[1] =
129 115 (ctx->ctr_cb[1] & ~(ctx->ctr_counter_mask)) | counter;
130 116
131 117 /*
132 118 * XOR the previous cipher block or IV with the
133 119 * current clear block.
134 120 */
135 121 xor_block(blockp, lastp);
136 122
137 123 if (out == NULL) {
138 124 if (ctx->ctr_remainder_len > 0) {
139 125 bcopy(lastp, ctx->ctr_copy_to,
140 126 ctx->ctr_remainder_len);
141 127 bcopy(lastp + ctx->ctr_remainder_len, datap,
142 128 need);
143 129 }
144 130 } else {
145 131 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
146 132 &out_data_1_len, &out_data_2, block_size);
147 133
148 134 /* copy block to where it belongs */
149 135 bcopy(lastp, out_data_1, out_data_1_len);
150 136 if (out_data_2 != NULL) {
151 137 bcopy(lastp + out_data_1_len, out_data_2,
152 138 block_size - out_data_1_len);
153 139 }
154 140 /* update offset */
155 141 out->cd_offset += block_size;
156 142 }
157 143
158 144 /* Update pointer to next block of data to be processed. */
159 145 if (ctx->ctr_remainder_len != 0) {
160 146 datap += need;
161 147 ctx->ctr_remainder_len = 0;
162 148 } else {
163 149 datap += block_size;
164 150 }
165 151
166 152 remainder = (size_t)&data[length] - (size_t)datap;
167 153
168 154 /* Incomplete last block. */
169 155 if (remainder > 0 && remainder < block_size) {
170 156 bcopy(datap, ctx->ctr_remainder, remainder);
171 157 ctx->ctr_remainder_len = remainder;
172 158 ctx->ctr_copy_to = datap;
173 159 goto out;
174 160 }
175 161 ctx->ctr_copy_to = NULL;
176 162
177 163 } while (remainder > 0);
178 164
179 165 out:
180 166 return (CRYPTO_SUCCESS);
181 167 }
182 168
183 169 int
184 170 ctr_mode_final(ctr_ctx_t *ctx, crypto_data_t *out,
185 171 int (*encrypt_block)(const void *, const uint8_t *, uint8_t *))
186 172 {
187 173 uint8_t *lastp;
188 174 void *iov_or_mp;
189 175 offset_t offset;
190 176 uint8_t *out_data_1;
191 177 uint8_t *out_data_2;
192 178 size_t out_data_1_len;
193 179 uint8_t *p;
194 180 int i;
195 181
196 182 if (out->cd_length < ctx->ctr_remainder_len)
197 183 return (CRYPTO_DATA_LEN_RANGE);
198 184
199 185 encrypt_block(ctx->ctr_keysched, (uint8_t *)ctx->ctr_cb,
200 186 (uint8_t *)ctx->ctr_tmp);
201 187
202 188 lastp = (uint8_t *)ctx->ctr_tmp;
203 189 p = (uint8_t *)ctx->ctr_remainder;
204 190 for (i = 0; i < ctx->ctr_remainder_len; i++) {
205 191 p[i] ^= lastp[i];
206 192 }
207 193
208 194 crypto_init_ptrs(out, &iov_or_mp, &offset);
209 195 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
210 196 &out_data_1_len, &out_data_2, ctx->ctr_remainder_len);
211 197
212 198 bcopy(p, out_data_1, out_data_1_len);
213 199 if (out_data_2 != NULL) {
214 200 bcopy((uint8_t *)p + out_data_1_len,
215 201 out_data_2, ctx->ctr_remainder_len - out_data_1_len);
216 202 }
↓ open down ↓ |
80 lines elided |
↑ open up ↑ |
217 203 out->cd_offset += ctx->ctr_remainder_len;
218 204 ctx->ctr_remainder_len = 0;
219 205 return (CRYPTO_SUCCESS);
220 206 }
221 207
222 208 int
223 209 ctr_init_ctx(ctr_ctx_t *ctr_ctx, ulong_t count, uint8_t *cb,
224 210 void (*copy_block)(uint8_t *, uint8_t *))
225 211 {
226 212 uint64_t mask = 0;
227 -#ifdef _LITTLE_ENDIAN
228 - uint8_t *p8;
229 -#endif
230 213
231 214 if (count == 0 || count > 64) {
232 215 return (CRYPTO_MECHANISM_PARAM_INVALID);
233 216 }
234 217 while (count-- > 0)
235 218 mask |= (1ULL << count);
219 +
236 220 #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]);
221 + mask = htonll(mask);
246 222 #endif
247 223 ctr_ctx->ctr_counter_mask = mask;
248 224 copy_block(cb, (uchar_t *)ctr_ctx->ctr_cb);
249 225 ctr_ctx->ctr_lastp = (uint8_t *)&ctr_ctx->ctr_cb[0];
250 226 ctr_ctx->ctr_flags |= CTR_MODE;
251 227 return (CRYPTO_SUCCESS);
252 228 }
253 229
254 230 /* ARGSUSED */
255 231 void *
256 232 ctr_alloc_ctx(int kmflag)
257 233 {
258 234 ctr_ctx_t *ctr_ctx;
259 235
260 236 #ifdef _KERNEL
261 237 if ((ctr_ctx = kmem_zalloc(sizeof (ctr_ctx_t), kmflag)) == NULL)
262 238 #else
263 239 if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
264 240 #endif
265 241 return (NULL);
266 242
267 243 ctr_ctx->ctr_flags = CTR_MODE;
268 244 return (ctr_ctx);
269 245 }
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX