Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include "krb5_locl.h"
35 :
36 : void
37 5815328 : _krb5_evp_schedule(krb5_context context,
38 : struct _krb5_key_type *kt,
39 : struct _krb5_key_data *kd)
40 : {
41 5815328 : struct _krb5_evp_schedule *key = kd->schedule->data;
42 5815328 : const EVP_CIPHER *c = (*kt->evp)();
43 :
44 5815328 : EVP_CIPHER_CTX_init(&key->ectx);
45 5815328 : EVP_CIPHER_CTX_init(&key->dctx);
46 :
47 5815328 : EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
48 5815328 : EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
49 5815328 : }
50 :
51 : void
52 5815328 : _krb5_evp_cleanup(krb5_context context, struct _krb5_key_data *kd)
53 : {
54 5815328 : struct _krb5_evp_schedule *key = kd->schedule->data;
55 5815328 : EVP_CIPHER_CTX_cleanup(&key->ectx);
56 5815328 : EVP_CIPHER_CTX_cleanup(&key->dctx);
57 5815328 : }
58 :
59 : int
60 2975456 : _krb5_evp_digest_iov(krb5_crypto crypto,
61 : const struct krb5_crypto_iov *iov,
62 : int niov,
63 : void *hash,
64 : unsigned int *hsize,
65 : const EVP_MD *md,
66 : ENGINE *engine)
67 : {
68 26920 : EVP_MD_CTX *ctx;
69 26920 : int ret, i;
70 2975456 : krb5_data current = {0,0};
71 :
72 2975456 : if (crypto != NULL) {
73 1407183 : if (crypto->mdctx == NULL)
74 369232 : crypto->mdctx = EVP_MD_CTX_create();
75 1407183 : if (crypto->mdctx == NULL)
76 0 : return 0;
77 1380479 : ctx = crypto->mdctx;
78 : } else
79 1568273 : ctx = EVP_MD_CTX_create();
80 :
81 2975456 : ret = EVP_DigestInit_ex(ctx, md, engine);
82 2975456 : if (ret != 1)
83 0 : goto out;
84 :
85 : /* Minimize EVP calls by coalescing contiguous iovec elements */
86 7081031 : for (i = 0; i < niov; i++) {
87 4105575 : if (_krb5_crypto_iov_should_sign(&iov[i])) {
88 4105575 : if (current.data &&
89 1130119 : (char *)current.data + current.length == iov[i].data.data) {
90 0 : current.length += iov[i].data.length;
91 : } else {
92 4105575 : if (current.data) {
93 1130119 : ret = EVP_DigestUpdate(ctx, current.data, current.length);
94 1130119 : if (ret != 1)
95 0 : goto out;
96 : }
97 4105575 : current = iov[i].data;
98 : }
99 : }
100 : }
101 :
102 2975456 : if (current.data) {
103 2975424 : ret = EVP_DigestUpdate(ctx, current.data, current.length);
104 2975424 : if (ret != 1)
105 0 : goto out;
106 : }
107 :
108 2975456 : ret = EVP_DigestFinal_ex(ctx, hash, hsize);
109 :
110 2975456 : out:
111 2975456 : if (crypto == NULL)
112 1568273 : EVP_MD_CTX_destroy(ctx);
113 :
114 2948536 : return ret;
115 : }
116 :
117 : krb5_error_code
118 4824286 : _krb5_evp_hmac_iov(krb5_context context,
119 : krb5_crypto crypto,
120 : struct _krb5_key_data *key,
121 : const struct krb5_crypto_iov *iov,
122 : int niov,
123 : void *hmac,
124 : unsigned int *hmaclen,
125 : const EVP_MD *md,
126 : ENGINE *engine)
127 : {
128 52223 : HMAC_CTX *ctx;
129 4824286 : krb5_data current = {0, NULL};
130 52223 : int i;
131 :
132 4824286 : if (crypto != NULL) {
133 4824286 : if (crypto->hmacctx == NULL)
134 1193564 : crypto->hmacctx = HMAC_CTX_new();
135 4824286 : ctx = crypto->hmacctx;
136 : } else {
137 0 : ctx = HMAC_CTX_new();
138 : }
139 4824286 : if (ctx == NULL)
140 0 : return krb5_enomem(context);
141 :
142 4824286 : if (HMAC_Init_ex(ctx, key->key->keyvalue.data, key->key->keyvalue.length,
143 : md, engine) == 0) {
144 0 : HMAC_CTX_free(ctx);
145 0 : return krb5_enomem(context);
146 : }
147 :
148 19056014 : for (i = 0; i < niov; i++) {
149 14231728 : if (_krb5_crypto_iov_should_sign(&iov[i])) {
150 11045406 : if (current.data &&
151 6221120 : (char *)current.data + current.length == iov[i].data.data) {
152 3085306 : current.length += iov[i].data.length;
153 : } else {
154 7960100 : if (current.data)
155 3135814 : HMAC_Update(ctx, current.data, current.length);
156 7960100 : current = iov[i].data;
157 : }
158 : }
159 : }
160 :
161 4824286 : if (current.data)
162 4824184 : HMAC_Update(ctx, current.data, current.length);
163 :
164 4824286 : HMAC_Final(ctx, hmac, hmaclen);
165 :
166 4824286 : if (crypto == NULL)
167 0 : HMAC_CTX_free(ctx);
168 :
169 4772063 : return 0;
170 : }
171 :
172 : krb5_error_code
173 0 : _krb5_evp_encrypt(krb5_context context,
174 : struct _krb5_key_data *key,
175 : void *data,
176 : size_t len,
177 : krb5_boolean encryptp,
178 : int usage,
179 : void *ivec)
180 : {
181 0 : struct _krb5_evp_schedule *ctx = key->schedule->data;
182 0 : EVP_CIPHER_CTX *c;
183 0 : c = encryptp ? &ctx->ectx : &ctx->dctx;
184 0 : if (ivec == NULL) {
185 : /* alloca ? */
186 0 : size_t len2 = EVP_CIPHER_CTX_iv_length(c);
187 0 : void *loiv = malloc(len2);
188 0 : if (loiv == NULL)
189 0 : return krb5_enomem(context);
190 0 : memset(loiv, 0, len2);
191 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
192 0 : free(loiv);
193 : } else
194 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
195 0 : EVP_Cipher(c, data, data, len);
196 0 : return 0;
197 : }
198 :
199 : struct _krb5_evp_iov_cursor
200 : {
201 : struct krb5_crypto_iov *iov;
202 : int niov;
203 : krb5_data current;
204 : int nextidx;
205 : };
206 :
207 : static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
208 :
209 : static inline int
210 29499177 : _krb5_evp_iov_should_encrypt(struct krb5_crypto_iov *iov)
211 : {
212 29499177 : return (iov->flags == KRB5_CRYPTO_TYPE_DATA
213 22762460 : || iov->flags == KRB5_CRYPTO_TYPE_HEADER
214 52261637 : || iov->flags == KRB5_CRYPTO_TYPE_PADDING);
215 : }
216 : /*
217 : * If we have a group of iovecs which have been split up from
218 : * a single common buffer, expand the 'current' iovec out to
219 : * be as large as possible.
220 : */
221 :
222 : static inline void
223 5129106 : _krb5_evp_iov_cursor_expand(struct _krb5_evp_iov_cursor *cursor)
224 : {
225 5129106 : if (cursor->nextidx == cursor->niov)
226 0 : return;
227 :
228 5129106 : while (_krb5_evp_iov_should_encrypt(&cursor->iov[cursor->nextidx])) {
229 0 : if (cursor->iov[cursor->nextidx].data.length != 0 &&
230 0 : ((char *)cursor->current.data + cursor->current.length
231 0 : != cursor->iov[cursor->nextidx].data.data)) {
232 0 : return;
233 : }
234 0 : cursor->current.length += cursor->iov[cursor->nextidx].data.length;
235 0 : cursor->nextidx++;
236 : }
237 :
238 5119919 : return;
239 : }
240 :
241 : /* Move the cursor along to the start of the next block to be
242 : * encrypted */
243 : static inline void
244 8264920 : _krb5_evp_iov_cursor_nextcrypt(struct _krb5_evp_iov_cursor *cursor)
245 : {
246 16530536 : for (; cursor->nextidx < cursor->niov; cursor->nextidx++) {
247 13394722 : if (_krb5_evp_iov_should_encrypt(&cursor->iov[cursor->nextidx])
248 5129436 : && cursor->iov[cursor->nextidx].data.length != 0) {
249 5129106 : cursor->current = cursor->iov[cursor->nextidx].data;
250 5129106 : cursor->nextidx++;
251 5129106 : _krb5_evp_iov_cursor_expand(cursor);
252 5129106 : return;
253 : }
254 : }
255 :
256 3135814 : cursor->current.length = 0; /* No matches, so we're done here */
257 : }
258 :
259 : static inline void
260 1567907 : _krb5_evp_iov_cursor_init(struct _krb5_evp_iov_cursor *cursor,
261 : struct krb5_crypto_iov *iov, int niov)
262 : {
263 1567907 : memset(cursor, 0, sizeof(struct _krb5_evp_iov_cursor));
264 :
265 1567907 : cursor->iov = iov;
266 1567907 : cursor->niov = niov;
267 1567907 : cursor->nextidx = 0;
268 :
269 : /* Move along to the first block we're going to be encrypting */
270 1567907 : _krb5_evp_iov_cursor_nextcrypt(cursor);
271 1567907 : }
272 :
273 : static inline void
274 7401039 : _krb5_evp_iov_cursor_advance(struct _krb5_evp_iov_cursor *cursor,
275 : size_t amount)
276 : {
277 10110880 : while (amount > 0) {
278 6258811 : if (cursor->current.length > amount) {
279 3548970 : cursor->current.data = (char *)cursor->current.data + amount;
280 3548970 : cursor->current.length -= amount;
281 3548970 : return;
282 : }
283 2709841 : amount -= cursor->current.length;
284 2709841 : _krb5_evp_iov_cursor_nextcrypt(cursor);
285 : }
286 : }
287 :
288 : static inline int
289 5980758 : _krb5_evp_iov_cursor_done(struct _krb5_evp_iov_cursor *cursor)
290 : {
291 5980758 : return (cursor->nextidx == cursor->niov && cursor->current.length == 0);
292 : }
293 :
294 : /* Fill a memory buffer with data from one or more iovecs. Doesn't
295 : * advance the passed in cursor - use outcursor for the position
296 : * at the end
297 : */
298 : static inline void
299 2419265 : _krb5_evp_iov_cursor_fillbuf(struct _krb5_evp_iov_cursor *cursor,
300 : unsigned char *buf, size_t length,
301 : struct _krb5_evp_iov_cursor *outcursor)
302 : {
303 5249 : struct _krb5_evp_iov_cursor cursorint;
304 :
305 2419265 : cursorint = *cursor;
306 :
307 4837218 : while (length > 0 && !_krb5_evp_iov_cursor_done(&cursorint)) {
308 2419265 : if (cursorint.current.length > length) {
309 425679 : memcpy(buf, cursorint.current.data, length);
310 425679 : _krb5_evp_iov_cursor_advance(&cursorint, length);
311 425679 : length = 0;
312 : } else {
313 1993586 : memcpy(buf, cursorint.current.data, cursorint.current.length);
314 1993586 : length -= cursorint.current.length;
315 1993586 : buf += cursorint.current.length;
316 1993586 : _krb5_evp_iov_cursor_nextcrypt(&cursorint);
317 : }
318 : }
319 :
320 2419265 : if (outcursor != NULL)
321 425679 : *outcursor = cursorint;
322 2419265 : }
323 :
324 : /* Fill an iovec from a memory buffer. Always advances the cursor to
325 : * the end of the filled region
326 : */
327 : static inline void
328 3561493 : _krb5_evp_iov_cursor_fillvec(struct _krb5_evp_iov_cursor *cursor,
329 : unsigned char *buf, size_t length)
330 : {
331 7120361 : while (length > 0 && !_krb5_evp_iov_cursor_done(cursor)) {
332 3561493 : if (cursor->current.length > length) {
333 1567907 : memcpy(cursor->current.data, buf, length);
334 1567907 : _krb5_evp_iov_cursor_advance(cursor, length);
335 1567907 : length = 0;
336 : } else {
337 1993586 : memcpy(cursor->current.data, buf, cursor->current.length);
338 1993586 : length -= cursor->current.length;
339 1993586 : buf += cursor->current.length;
340 1993586 : _krb5_evp_iov_cursor_nextcrypt(cursor);
341 : }
342 : }
343 3561493 : }
344 :
345 : static size_t
346 1567907 : _krb5_evp_iov_cryptlength(struct krb5_crypto_iov *iov, int niov)
347 : {
348 2625 : int i;
349 1567907 : size_t length = 0;
350 :
351 12543256 : for (i = 0; i < niov; i++) {
352 10975349 : if (_krb5_evp_iov_should_encrypt(&iov[i]))
353 4703721 : length += iov[i].data.length;
354 : }
355 :
356 1567907 : return length;
357 : }
358 :
359 : int
360 0 : _krb5_evp_encrypt_iov(krb5_context context,
361 : struct _krb5_key_data *key,
362 : struct krb5_crypto_iov *iov,
363 : int niov,
364 : krb5_boolean encryptp,
365 : int usage,
366 : void *ivec)
367 : {
368 0 : size_t blocksize, blockmask, wholeblocks;
369 0 : struct _krb5_evp_schedule *ctx = key->schedule->data;
370 0 : unsigned char tmp[EVP_MAX_BLOCK_LENGTH];
371 0 : EVP_CIPHER_CTX *c;
372 0 : struct _krb5_evp_iov_cursor cursor;
373 :
374 0 : c = encryptp ? &ctx->ectx : &ctx->dctx;
375 :
376 0 : blocksize = EVP_CIPHER_CTX_block_size(c);
377 :
378 0 : blockmask = ~(blocksize - 1);
379 :
380 0 : if (ivec)
381 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
382 : else
383 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
384 :
385 0 : _krb5_evp_iov_cursor_init(&cursor, iov, niov);
386 :
387 0 : while (!_krb5_evp_iov_cursor_done(&cursor)) {
388 :
389 : /* Number of bytes of data in this iovec that are in whole blocks */
390 0 : wholeblocks = cursor.current.length & ~blockmask;
391 :
392 0 : if (wholeblocks != 0) {
393 0 : EVP_Cipher(c, cursor.current.data,
394 0 : cursor.current.data, wholeblocks);
395 0 : _krb5_evp_iov_cursor_advance(&cursor, wholeblocks);
396 : }
397 :
398 : /* If there's a partial block of data remaining in the current
399 : * iovec, steal enough from subsequent iovecs to form a whole block */
400 0 : if (cursor.current.length > 0 && cursor.current.length < blocksize) {
401 : /* Build up a block's worth of data in tmp, leaving the cursor
402 : * pointing at where we started */
403 0 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp, blocksize, NULL);
404 :
405 0 : EVP_Cipher(c, tmp, tmp, blocksize);
406 :
407 : /* Copy the data in tmp back into the iovecs that it came from,
408 : * advancing the cursor */
409 0 : _krb5_evp_iov_cursor_fillvec(&cursor, tmp, blocksize);
410 : }
411 : }
412 :
413 0 : return 0;
414 : }
415 :
416 : int
417 1567907 : _krb5_evp_encrypt_iov_cts(krb5_context context,
418 : struct _krb5_key_data *key,
419 : struct krb5_crypto_iov *iov,
420 : int niov,
421 : krb5_boolean encryptp,
422 : int usage,
423 : void *ivec)
424 : {
425 2625 : size_t blocksize, blockmask, wholeblocks, length;
426 2625 : size_t remaining, partiallen;
427 2625 : struct _krb5_evp_iov_cursor cursor, lastpos;
428 1567907 : struct _krb5_evp_schedule *ctx = key->schedule->data;
429 2625 : unsigned char tmp[EVP_MAX_BLOCK_LENGTH], tmp2[EVP_MAX_BLOCK_LENGTH];
430 2625 : unsigned char tmp3[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH];
431 2625 : EVP_CIPHER_CTX *c;
432 2625 : int i;
433 :
434 1567907 : c = encryptp ? &ctx->ectx : &ctx->dctx;
435 :
436 1567907 : blocksize = EVP_CIPHER_CTX_block_size(c);
437 1567907 : blockmask = ~(blocksize - 1);
438 :
439 1567907 : length = _krb5_evp_iov_cryptlength(iov, niov);
440 :
441 1567907 : if (length < blocksize) {
442 0 : krb5_set_error_message(context, EINVAL,
443 : "message block too short");
444 0 : return EINVAL;
445 : }
446 :
447 1567907 : if (length == blocksize)
448 0 : return _krb5_evp_encrypt_iov(context, key, iov, niov,
449 : encryptp, usage, ivec);
450 :
451 1567907 : if (ivec)
452 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
453 : else
454 1567907 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
455 :
456 1567907 : if (encryptp) {
457 : /* On our first pass, we want to process everything but the
458 : * final partial block */
459 1142228 : remaining = ((length - 1) & blockmask);
460 1142228 : partiallen = length - remaining;
461 :
462 1142228 : memset(&lastpos, 0, sizeof(lastpos)); /* Keep the compiler happy */
463 : } else {
464 : /* Decryption needs to leave 2 whole blocks and a partial for
465 : * further processing */
466 425679 : if (length > 2 * blocksize) {
467 425679 : remaining = (((length - 1) / blocksize) * blocksize) - (blocksize*2);
468 425679 : partiallen = length - remaining - (blocksize * 2);
469 : } else {
470 0 : remaining = 0;
471 0 : partiallen = length - blocksize;
472 : }
473 : }
474 :
475 1567907 : _krb5_evp_iov_cursor_init(&cursor, iov, niov);
476 5830507 : while (remaining > 0) {
477 : /* If the iovec has more data than we need, just use it */
478 4265225 : if (cursor.current.length >= remaining) {
479 1567871 : EVP_Cipher(c, cursor.current.data, cursor.current.data, remaining);
480 :
481 1567871 : if (encryptp) {
482 : /* We've just encrypted the last block of data. Make a copy
483 : * of it (and its location) for the CTS dance, below */
484 1142228 : lastpos = cursor;
485 1142228 : _krb5_evp_iov_cursor_advance(&lastpos, remaining - blocksize);
486 1142228 : memcpy(ivec2, lastpos.current.data, blocksize);
487 : }
488 :
489 1567871 : _krb5_evp_iov_cursor_advance(&cursor, remaining);
490 1567871 : remaining = 0;
491 : } else {
492 : /* Use as much as we can, firstly all of the whole blocks */
493 2697354 : wholeblocks = cursor.current.length & blockmask;
494 :
495 2697354 : if (wholeblocks > 0) {
496 2697354 : EVP_Cipher(c, cursor.current.data, cursor.current.data,
497 : wholeblocks);
498 2697354 : _krb5_evp_iov_cursor_advance(&cursor, wholeblocks);
499 2697354 : remaining -= wholeblocks;
500 : }
501 :
502 : /* Then, if we have partial data left, steal enough from subsequent
503 : * iovecs to make a whole block */
504 2697354 : if (cursor.current.length > 0 && cursor.current.length < blocksize) {
505 0 : if (encryptp && remaining == blocksize)
506 0 : lastpos = cursor;
507 :
508 0 : _krb5_evp_iov_cursor_fillbuf(&cursor, ivec2, blocksize, NULL);
509 0 : EVP_Cipher(c, ivec2, ivec2, blocksize);
510 0 : _krb5_evp_iov_cursor_fillvec(&cursor, ivec2, blocksize);
511 :
512 0 : remaining -= blocksize;
513 : }
514 : }
515 : }
516 :
517 : /* Encryption */
518 1567907 : if (encryptp) {
519 : /* Copy the partial block into tmp */
520 1142228 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp, partiallen, NULL);
521 :
522 : /* XOR the final partial block with ivec2 */
523 19419189 : for (i = 0; i < partiallen; i++)
524 18275648 : tmp[i] = tmp[i] ^ ivec2[i];
525 1142228 : for (; i < blocksize; i++)
526 0 : tmp[i] = 0 ^ ivec2[i]; /* XOR 0s if partial block exhausted */
527 :
528 1142228 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
529 1142228 : EVP_Cipher(c, tmp, tmp, blocksize);
530 :
531 1142228 : _krb5_evp_iov_cursor_fillvec(&lastpos, tmp, blocksize);
532 1142228 : _krb5_evp_iov_cursor_fillvec(&cursor, ivec2, partiallen);
533 :
534 1142228 : if (ivec)
535 0 : memcpy(ivec, tmp, blocksize);
536 :
537 1142228 : return 0;
538 : }
539 :
540 : /* Decryption */
541 :
542 : /* Make a copy of the 2nd last full ciphertext block in ivec2 before
543 : * decrypting it. If no such block exists, use ivec or zero_ivec */
544 425679 : if (length <= blocksize * 2) {
545 0 : if (ivec)
546 0 : memcpy(ivec2, ivec, blocksize);
547 : else
548 0 : memcpy(ivec2, zero_ivec, blocksize);
549 : } else {
550 425679 : _krb5_evp_iov_cursor_fillbuf(&cursor, ivec2, blocksize, NULL);
551 425679 : EVP_Cipher(c, tmp, ivec2, blocksize);
552 425679 : _krb5_evp_iov_cursor_fillvec(&cursor, tmp, blocksize);
553 : }
554 :
555 425679 : lastpos = cursor; /* Remember where the last block is */
556 425679 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp, blocksize, &cursor);
557 425679 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
558 425679 : EVP_Cipher(c, tmp2, tmp, blocksize); /* tmp eventually becomes output ivec */
559 :
560 425679 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp3, partiallen, NULL);
561 :
562 425679 : memcpy(tmp3 + partiallen, tmp2 + partiallen, blocksize - partiallen); /* xor 0 */
563 7236543 : for (i = 0; i < partiallen; i++)
564 6810864 : tmp2[i] = tmp2[i] ^ tmp3[i];
565 :
566 425679 : _krb5_evp_iov_cursor_fillvec(&cursor, tmp2, partiallen);
567 :
568 425679 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
569 425679 : EVP_Cipher(c, tmp3, tmp3, blocksize);
570 :
571 7237855 : for (i = 0; i < blocksize; i++)
572 6810864 : tmp3[i] ^= ivec2[i];
573 :
574 425679 : _krb5_evp_iov_cursor_fillvec(&lastpos, tmp3, blocksize);
575 :
576 425679 : if (ivec)
577 0 : memcpy(ivec, tmp, blocksize);
578 :
579 424367 : return 0;
580 : }
581 :
582 : krb5_error_code
583 8599961 : _krb5_evp_encrypt_cts(krb5_context context,
584 : struct _krb5_key_data *key,
585 : void *data,
586 : size_t len,
587 : krb5_boolean encryptp,
588 : int usage,
589 : void *ivec)
590 : {
591 234305 : size_t i, blocksize;
592 8599961 : struct _krb5_evp_schedule *ctx = key->schedule->data;
593 234305 : unsigned char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH];
594 234305 : EVP_CIPHER_CTX *c;
595 234305 : unsigned char *p;
596 :
597 8599961 : c = encryptp ? &ctx->ectx : &ctx->dctx;
598 :
599 8599961 : blocksize = EVP_CIPHER_CTX_block_size(c);
600 :
601 8599961 : if (len < blocksize) {
602 0 : krb5_set_error_message(context, EINVAL,
603 : "message block too short");
604 0 : return EINVAL;
605 8599961 : } else if (len == blocksize) {
606 6412162 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
607 6412162 : EVP_Cipher(c, data, data, len);
608 6412162 : return 0;
609 : }
610 :
611 2187799 : if (ivec)
612 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
613 : else
614 2187799 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
615 :
616 2187799 : if (encryptp) {
617 :
618 1069009 : p = data;
619 1069009 : i = ((len - 1) / blocksize) * blocksize;
620 1069009 : EVP_Cipher(c, p, p, i);
621 1069009 : p += i - blocksize;
622 1069009 : len -= i;
623 1069009 : memcpy(ivec2, p, blocksize);
624 :
625 10617994 : for (i = 0; i < len; i++)
626 9548985 : tmp[i] = p[i + blocksize] ^ ivec2[i];
627 8624168 : for (; i < blocksize; i++)
628 7555159 : tmp[i] = 0 ^ ivec2[i];
629 :
630 1069009 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
631 1069009 : EVP_Cipher(c, p, tmp, blocksize);
632 :
633 1069009 : memcpy(p + blocksize, ivec2, len);
634 1069009 : if (ivec)
635 0 : memcpy(ivec, p, blocksize);
636 : } else {
637 13699 : unsigned char tmp2[EVP_MAX_BLOCK_LENGTH], tmp3[EVP_MAX_BLOCK_LENGTH];
638 :
639 1118790 : p = data;
640 1118790 : if (len > blocksize * 2) {
641 : /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
642 1118789 : i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize);
643 1118789 : memcpy(ivec2, p + i - blocksize, blocksize);
644 1118789 : EVP_Cipher(c, p, p, i);
645 1118789 : p += i;
646 1118789 : len -= i + blocksize;
647 : } else {
648 1 : if (ivec)
649 0 : memcpy(ivec2, ivec, blocksize);
650 : else
651 1 : memcpy(ivec2, zero_ivec, blocksize);
652 1 : len -= blocksize;
653 : }
654 :
655 1118790 : memcpy(tmp, p, blocksize);
656 1118790 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
657 1118790 : EVP_Cipher(c, tmp2, p, blocksize);
658 :
659 1118790 : memcpy(tmp3, p + blocksize, len);
660 1118790 : memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */
661 :
662 11056976 : for (i = 0; i < len; i++)
663 9938186 : p[i + blocksize] = tmp2[i] ^ tmp3[i];
664 :
665 1118790 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
666 1118790 : EVP_Cipher(c, p, tmp3, blocksize);
667 :
668 19033129 : for (i = 0; i < blocksize; i++)
669 17900640 : p[i] ^= ivec2[i];
670 1118790 : if (ivec)
671 13699 : memcpy(ivec, tmp, blocksize);
672 : }
673 2159961 : return 0;
674 : }
|