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 4313902 : _krb5_evp_schedule(krb5_context context,
38 : struct _krb5_key_type *kt,
39 : struct _krb5_key_data *kd)
40 : {
41 4313902 : struct _krb5_evp_schedule *key = kd->schedule->data;
42 4313902 : const EVP_CIPHER *c = (*kt->evp)();
43 :
44 4313902 : EVP_CIPHER_CTX_init(&key->ectx);
45 4313902 : EVP_CIPHER_CTX_init(&key->dctx);
46 :
47 4313902 : EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
48 4313902 : EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
49 4313902 : }
50 :
51 : void
52 4313902 : _krb5_evp_cleanup(krb5_context context, struct _krb5_key_data *kd)
53 : {
54 4313902 : struct _krb5_evp_schedule *key = kd->schedule->data;
55 4313902 : EVP_CIPHER_CTX_cleanup(&key->ectx);
56 4313902 : EVP_CIPHER_CTX_cleanup(&key->dctx);
57 4313902 : }
58 :
59 : int
60 2437526 : _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 : EVP_MD_CTX *ctx;
69 : int ret, i;
70 2437526 : krb5_data current = {0,0};
71 :
72 2437526 : if (crypto != NULL) {
73 1102295 : if (crypto->mdctx == NULL)
74 271761 : crypto->mdctx = EVP_MD_CTX_create();
75 1102295 : if (crypto->mdctx == NULL)
76 0 : return 0;
77 1102295 : ctx = crypto->mdctx;
78 : } else
79 1335231 : ctx = EVP_MD_CTX_create();
80 :
81 2437526 : ret = EVP_DigestInit_ex(ctx, md, engine);
82 2437526 : if (ret != 1)
83 0 : goto out;
84 :
85 5833875 : for (i = 0; i < niov; i++) {
86 3396349 : if (_krb5_crypto_iov_should_sign(&iov[i])) {
87 3396349 : if ((char *)current.data + current.length == iov[i].data.data) {
88 32 : current.length += iov[i].data.length;
89 : } else {
90 3396317 : if (current.data) {
91 958823 : ret = EVP_DigestUpdate(ctx, current.data, current.length);
92 958823 : if (ret != 1)
93 0 : goto out;
94 : }
95 3396317 : current = iov[i].data;
96 : }
97 : }
98 : }
99 :
100 2437526 : if (current.data) {
101 2437494 : ret = EVP_DigestUpdate(ctx, current.data, current.length);
102 2437494 : if (ret != 1)
103 0 : goto out;
104 : }
105 :
106 2437526 : ret = EVP_DigestFinal_ex(ctx, hash, hsize);
107 :
108 2437526 : out:
109 2437526 : if (crypto == NULL)
110 1335231 : EVP_MD_CTX_destroy(ctx);
111 :
112 2437526 : return ret;
113 : }
114 :
115 : krb5_error_code
116 3850680 : _krb5_evp_hmac_iov(krb5_context context,
117 : krb5_crypto crypto,
118 : struct _krb5_key_data *key,
119 : const struct krb5_crypto_iov *iov,
120 : int niov,
121 : void *hmac,
122 : unsigned int *hmaclen,
123 : const EVP_MD *md,
124 : ENGINE *engine)
125 : {
126 : HMAC_CTX *ctx;
127 3850680 : krb5_data current = {0, 0};
128 : int i;
129 :
130 3850680 : if (crypto != NULL) {
131 3850680 : if (crypto->hmacctx == NULL)
132 873795 : crypto->hmacctx = HMAC_CTX_new();
133 3850680 : ctx = crypto->hmacctx;
134 : } else {
135 0 : ctx = HMAC_CTX_new();
136 : }
137 3850680 : if (ctx == NULL)
138 0 : return krb5_enomem(context);
139 :
140 3850680 : if (HMAC_Init_ex(ctx, key->key->keyvalue.data, key->key->keyvalue.length,
141 : md, engine) == 0) {
142 0 : HMAC_CTX_free(ctx);
143 0 : return krb5_enomem(context);
144 : }
145 :
146 15948198 : for (i = 0; i < niov; i++) {
147 12097518 : if (_krb5_crypto_iov_should_sign(&iov[i])) {
148 9301842 : if ((char *)current.data + current.length == iov[i].data.data) {
149 2702317 : current.length += iov[i].data.length;
150 : } else {
151 6599525 : if (current.data)
152 2748946 : HMAC_Update(ctx, current.data, current.length);
153 6599525 : current = iov[i].data;
154 : }
155 : }
156 : }
157 :
158 3850680 : if (current.data)
159 3850579 : HMAC_Update(ctx, current.data, current.length);
160 :
161 3850680 : HMAC_Final(ctx, hmac, hmaclen);
162 :
163 3850680 : if (crypto == NULL)
164 0 : HMAC_CTX_free(ctx);
165 :
166 3850680 : return 0;
167 : }
168 :
169 : krb5_error_code
170 0 : _krb5_evp_encrypt(krb5_context context,
171 : struct _krb5_key_data *key,
172 : void *data,
173 : size_t len,
174 : krb5_boolean encryptp,
175 : int usage,
176 : void *ivec)
177 : {
178 0 : struct _krb5_evp_schedule *ctx = key->schedule->data;
179 : EVP_CIPHER_CTX *c;
180 0 : c = encryptp ? &ctx->ectx : &ctx->dctx;
181 0 : if (ivec == NULL) {
182 : /* alloca ? */
183 0 : size_t len2 = EVP_CIPHER_CTX_iv_length(c);
184 0 : void *loiv = malloc(len2);
185 0 : if (loiv == NULL)
186 0 : return krb5_enomem(context);
187 0 : memset(loiv, 0, len2);
188 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
189 0 : free(loiv);
190 : } else
191 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
192 0 : EVP_Cipher(c, data, data, len);
193 0 : return 0;
194 : }
195 :
196 : struct _krb5_evp_iov_cursor
197 : {
198 : struct krb5_crypto_iov *iov;
199 : int niov;
200 : krb5_data current;
201 : int nextidx;
202 : };
203 :
204 : static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
205 :
206 : static inline int
207 25747734 : _krb5_evp_iov_should_encrypt(struct krb5_crypto_iov *iov)
208 : {
209 25747734 : return (iov->flags == KRB5_CRYPTO_TYPE_DATA
210 19914050 : || iov->flags == KRB5_CRYPTO_TYPE_HEADER
211 42912838 : || iov->flags == KRB5_CRYPTO_TYPE_PADDING);
212 : }
213 : /*
214 : * If we have a group of iovecs which have been split up from
215 : * a single common buffer, expand the 'current' iovec out to
216 : * be as large as possible.
217 : */
218 :
219 : static inline void
220 4459019 : _krb5_evp_iov_cursor_expand(struct _krb5_evp_iov_cursor *cursor)
221 : {
222 4459019 : if (cursor->nextidx == cursor->niov)
223 0 : return;
224 :
225 8918038 : while (_krb5_evp_iov_should_encrypt(&cursor->iov[cursor->nextidx])) {
226 0 : if (cursor->iov[cursor->nextidx].data.length != 0 &&
227 0 : ((char *)cursor->current.data + cursor->current.length
228 0 : != cursor->iov[cursor->nextidx].data.data)) {
229 0 : return;
230 : }
231 0 : cursor->current.length += cursor->iov[cursor->nextidx].data.length;
232 0 : cursor->nextidx++;
233 : }
234 :
235 4459019 : return;
236 : }
237 :
238 : /* Move the cursor along to the start of the next block to be
239 : * encrypted */
240 : static inline void
241 7207965 : _krb5_evp_iov_cursor_nextcrypt(struct _krb5_evp_iov_cursor *cursor)
242 : {
243 14416350 : for (; cursor->nextidx < cursor->niov; cursor->nextidx++) {
244 11667404 : if (_krb5_evp_iov_should_encrypt(&cursor->iov[cursor->nextidx])
245 4459211 : && cursor->iov[cursor->nextidx].data.length != 0) {
246 4459019 : cursor->current = cursor->iov[cursor->nextidx].data;
247 4459019 : cursor->nextidx++;
248 4459019 : _krb5_evp_iov_cursor_expand(cursor);
249 4459019 : return;
250 : }
251 : }
252 :
253 2748946 : cursor->current.length = 0; /* No matches, so we're done here */
254 : }
255 :
256 : static inline void
257 1374473 : _krb5_evp_iov_cursor_init(struct _krb5_evp_iov_cursor *cursor,
258 : struct krb5_crypto_iov *iov, int niov)
259 : {
260 1374473 : memset(cursor, 0, sizeof(struct _krb5_evp_iov_cursor));
261 :
262 1374473 : cursor->iov = iov;
263 1374473 : cursor->niov = niov;
264 1374473 : cursor->nextidx = 0;
265 :
266 : /* Move along to the first block we're going to be encrypting */
267 1374473 : _krb5_evp_iov_cursor_nextcrypt(cursor);
268 1374473 : }
269 :
270 : static inline void
271 6527993 : _krb5_evp_iov_cursor_advance(struct _krb5_evp_iov_cursor *cursor,
272 : size_t amount)
273 : {
274 15469020 : while (amount > 0) {
275 5489276 : if (cursor->current.length > amount) {
276 3076242 : cursor->current.data = (char *)cursor->current.data + amount;
277 3076242 : cursor->current.length -= amount;
278 3076242 : return;
279 : }
280 2413034 : amount -= cursor->current.length;
281 2413034 : _krb5_evp_iov_cursor_nextcrypt(cursor);
282 : }
283 : }
284 :
285 : static inline int
286 5130687 : _krb5_evp_iov_cursor_done(struct _krb5_evp_iov_cursor *cursor)
287 : {
288 5130687 : return (cursor->nextidx == cursor->niov && cursor->current.length == 0);
289 : }
290 :
291 : /* Fill a memory buffer with data from one or more iovecs. Doesn't
292 : * advance the passed in cursor - use outcursor for the position
293 : * at the end
294 : */
295 : static inline void
296 2045985 : _krb5_evp_iov_cursor_fillbuf(struct _krb5_evp_iov_cursor *cursor,
297 : unsigned char *buf, size_t length,
298 : struct _krb5_evp_iov_cursor *outcursor)
299 : {
300 : struct _krb5_evp_iov_cursor cursorint;
301 :
302 2045985 : cursorint = *cursor;
303 :
304 6137955 : while (length > 0 && !_krb5_evp_iov_cursor_done(&cursorint)) {
305 2045985 : if (cursorint.current.length > length) {
306 335756 : memcpy(buf, cursorint.current.data, length);
307 335756 : _krb5_evp_iov_cursor_advance(&cursorint, length);
308 335756 : length = 0;
309 : } else {
310 1710229 : memcpy(buf, cursorint.current.data, cursorint.current.length);
311 1710229 : length -= cursorint.current.length;
312 1710229 : buf += cursorint.current.length;
313 1710229 : _krb5_evp_iov_cursor_nextcrypt(&cursorint);
314 : }
315 : }
316 :
317 2045985 : if (outcursor != NULL)
318 335756 : *outcursor = cursorint;
319 2045985 : }
320 :
321 : /* Fill an iovec from a memory buffer. Always advances the cursor to
322 : * the end of the filled region
323 : */
324 : static inline void
325 3084702 : _krb5_evp_iov_cursor_fillvec(struct _krb5_evp_iov_cursor *cursor,
326 : unsigned char *buf, size_t length)
327 : {
328 9254106 : while (length > 0 && !_krb5_evp_iov_cursor_done(cursor)) {
329 3084702 : if (cursor->current.length > length) {
330 1374473 : memcpy(cursor->current.data, buf, length);
331 1374473 : _krb5_evp_iov_cursor_advance(cursor, length);
332 1374473 : length = 0;
333 : } else {
334 1710229 : memcpy(cursor->current.data, buf, cursor->current.length);
335 1710229 : length -= cursor->current.length;
336 1710229 : buf += cursor->current.length;
337 1710229 : _krb5_evp_iov_cursor_nextcrypt(cursor);
338 : }
339 : }
340 3084702 : }
341 :
342 : static size_t
343 1374473 : _krb5_evp_iov_cryptlength(struct krb5_crypto_iov *iov, int niov)
344 : {
345 : int i;
346 1374473 : size_t length = 0;
347 :
348 10995784 : for (i = 0; i < niov; i++) {
349 9621311 : if (_krb5_evp_iov_should_encrypt(&iov[i]))
350 4123419 : length += iov[i].data.length;
351 : }
352 :
353 1374473 : return length;
354 : }
355 :
356 : int
357 0 : _krb5_evp_encrypt_iov(krb5_context context,
358 : struct _krb5_key_data *key,
359 : struct krb5_crypto_iov *iov,
360 : int niov,
361 : krb5_boolean encryptp,
362 : int usage,
363 : void *ivec)
364 : {
365 : size_t blocksize, blockmask, wholeblocks;
366 0 : struct _krb5_evp_schedule *ctx = key->schedule->data;
367 : unsigned char tmp[EVP_MAX_BLOCK_LENGTH];
368 : EVP_CIPHER_CTX *c;
369 : struct _krb5_evp_iov_cursor cursor;
370 :
371 0 : c = encryptp ? &ctx->ectx : &ctx->dctx;
372 :
373 0 : blocksize = EVP_CIPHER_CTX_block_size(c);
374 :
375 0 : blockmask = ~(blocksize - 1);
376 :
377 0 : if (ivec)
378 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
379 : else
380 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
381 :
382 0 : _krb5_evp_iov_cursor_init(&cursor, iov, niov);
383 :
384 0 : while (!_krb5_evp_iov_cursor_done(&cursor)) {
385 :
386 : /* Number of bytes of data in this iovec that are in whole blocks */
387 0 : wholeblocks = cursor.current.length & ~blockmask;
388 :
389 0 : if (wholeblocks != 0) {
390 0 : EVP_Cipher(c, cursor.current.data,
391 0 : cursor.current.data, wholeblocks);
392 0 : _krb5_evp_iov_cursor_advance(&cursor, wholeblocks);
393 : }
394 :
395 : /* If there's a partial block of data remaining in the current
396 : * iovec, steal enough from subsequent iovecs to form a whole block */
397 0 : if (cursor.current.length > 0 && cursor.current.length < blocksize) {
398 : /* Build up a block's worth of data in tmp, leaving the cursor
399 : * pointing at where we started */
400 0 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp, blocksize, NULL);
401 :
402 0 : EVP_Cipher(c, tmp, tmp, blocksize);
403 :
404 : /* Copy the data in tmp back into the iovecs that it came from,
405 : * advancing the cursor */
406 0 : _krb5_evp_iov_cursor_fillvec(&cursor, tmp, blocksize);
407 : }
408 : }
409 :
410 0 : return 0;
411 : }
412 :
413 : int
414 1374473 : _krb5_evp_encrypt_iov_cts(krb5_context context,
415 : struct _krb5_key_data *key,
416 : struct krb5_crypto_iov *iov,
417 : int niov,
418 : krb5_boolean encryptp,
419 : int usage,
420 : void *ivec)
421 : {
422 : size_t blocksize, blockmask, wholeblocks, length;
423 : size_t remaining, partiallen;
424 : struct _krb5_evp_iov_cursor cursor, lastpos;
425 1374473 : struct _krb5_evp_schedule *ctx = key->schedule->data;
426 : unsigned char tmp[EVP_MAX_BLOCK_LENGTH], tmp2[EVP_MAX_BLOCK_LENGTH];
427 : unsigned char tmp3[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH];
428 : EVP_CIPHER_CTX *c;
429 : int i;
430 :
431 1374473 : c = encryptp ? &ctx->ectx : &ctx->dctx;
432 :
433 1374473 : blocksize = EVP_CIPHER_CTX_block_size(c);
434 1374473 : blockmask = ~(blocksize - 1);
435 :
436 1374473 : length = _krb5_evp_iov_cryptlength(iov, niov);
437 :
438 1374473 : if (length < blocksize) {
439 0 : krb5_set_error_message(context, EINVAL,
440 : "message block too short");
441 0 : return EINVAL;
442 : }
443 :
444 1374473 : if (length == blocksize)
445 0 : return _krb5_evp_encrypt_iov(context, key, iov, niov,
446 : encryptp, usage, ivec);
447 :
448 1374473 : if (ivec)
449 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
450 : else
451 1374473 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
452 :
453 1374473 : if (encryptp) {
454 : /* On our first pass, we want to process everything but the
455 : * final partial block */
456 1038717 : remaining = ((length - 1) & blockmask);
457 1038717 : partiallen = length - remaining;
458 :
459 1038717 : memset(&lastpos, 0, sizeof(lastpos)); /* Keep the compiler happy */
460 : } else {
461 : /* Decryption needs to leave 2 whole blocks and a partial for
462 : * further processing */
463 335756 : if (length > 2 * blocksize) {
464 335756 : remaining = (((length - 1) / blocksize) * blocksize) - (blocksize*2);
465 335756 : partiallen = length - remaining - (blocksize * 2);
466 : } else {
467 0 : remaining = 0;
468 0 : partiallen = length - blocksize;
469 : }
470 : }
471 :
472 1374473 : _krb5_evp_iov_cursor_init(&cursor, iov, niov);
473 6527993 : while (remaining > 0) {
474 : /* If the iovec has more data than we need, just use it */
475 3779047 : if (cursor.current.length >= remaining) {
476 1374437 : EVP_Cipher(c, cursor.current.data, cursor.current.data, remaining);
477 :
478 1374437 : if (encryptp) {
479 : /* We've just encrypted the last block of data. Make a copy
480 : * of it (and its location) for the CTS dance, below */
481 1038717 : lastpos = cursor;
482 1038717 : _krb5_evp_iov_cursor_advance(&lastpos, remaining - blocksize);
483 1038717 : memcpy(ivec2, lastpos.current.data, blocksize);
484 : }
485 :
486 1374437 : _krb5_evp_iov_cursor_advance(&cursor, remaining);
487 1374437 : remaining = 0;
488 : } else {
489 : /* Use as much as we can, firstly all of the whole blocks */
490 2404610 : wholeblocks = cursor.current.length & blockmask;
491 :
492 2404610 : if (wholeblocks > 0) {
493 2404610 : EVP_Cipher(c, cursor.current.data, cursor.current.data,
494 : wholeblocks);
495 2404610 : _krb5_evp_iov_cursor_advance(&cursor, wholeblocks);
496 2404610 : remaining -= wholeblocks;
497 : }
498 :
499 : /* Then, if we have partial data left, steal enough from subsequent
500 : * iovecs to make a whole block */
501 2404610 : if (cursor.current.length > 0 && cursor.current.length < blocksize) {
502 0 : if (encryptp && remaining == blocksize)
503 0 : lastpos = cursor;
504 :
505 0 : _krb5_evp_iov_cursor_fillbuf(&cursor, ivec2, blocksize, NULL);
506 0 : EVP_Cipher(c, ivec2, ivec2, blocksize);
507 0 : _krb5_evp_iov_cursor_fillvec(&cursor, ivec2, blocksize);
508 :
509 0 : remaining -= blocksize;
510 : }
511 : }
512 : }
513 :
514 : /* Encryption */
515 1374473 : if (encryptp) {
516 : /* Copy the partial block into tmp */
517 1038717 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp, partiallen, NULL);
518 :
519 : /* XOR the final partial block with ivec2 */
520 17658189 : for (i = 0; i < partiallen; i++)
521 16619472 : tmp[i] = tmp[i] ^ ivec2[i];
522 1038717 : for (; i < blocksize; i++)
523 0 : tmp[i] = 0 ^ ivec2[i]; /* XOR 0s if partial block exhausted */
524 :
525 1038717 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
526 1038717 : EVP_Cipher(c, tmp, tmp, blocksize);
527 :
528 1038717 : _krb5_evp_iov_cursor_fillvec(&lastpos, tmp, blocksize);
529 1038717 : _krb5_evp_iov_cursor_fillvec(&cursor, ivec2, partiallen);
530 :
531 1038717 : if (ivec)
532 0 : memcpy(ivec, tmp, blocksize);
533 :
534 1038717 : return 0;
535 : }
536 :
537 : /* Decryption */
538 :
539 : /* Make a copy of the 2nd last full ciphertext block in ivec2 before
540 : * decrypting it. If no such block exists, use ivec or zero_ivec */
541 335756 : if (length <= blocksize * 2) {
542 0 : if (ivec)
543 0 : memcpy(ivec2, ivec, blocksize);
544 : else
545 0 : memcpy(ivec2, zero_ivec, blocksize);
546 : } else {
547 335756 : _krb5_evp_iov_cursor_fillbuf(&cursor, ivec2, blocksize, NULL);
548 335756 : EVP_Cipher(c, tmp, ivec2, blocksize);
549 335756 : _krb5_evp_iov_cursor_fillvec(&cursor, tmp, blocksize);
550 : }
551 :
552 335756 : lastpos = cursor; /* Remember where the last block is */
553 335756 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp, blocksize, &cursor);
554 335756 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
555 335756 : EVP_Cipher(c, tmp2, tmp, blocksize); /* tmp eventually becomes output ivec */
556 :
557 335756 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp3, partiallen, NULL);
558 :
559 335756 : memcpy(tmp3 + partiallen, tmp2 + partiallen, blocksize - partiallen); /* xor 0 */
560 5707852 : for (i = 0; i < partiallen; i++)
561 5372096 : tmp2[i] = tmp2[i] ^ tmp3[i];
562 :
563 335756 : _krb5_evp_iov_cursor_fillvec(&cursor, tmp2, partiallen);
564 :
565 335756 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
566 335756 : EVP_Cipher(c, tmp3, tmp3, blocksize);
567 :
568 5707852 : for (i = 0; i < blocksize; i++)
569 5372096 : tmp3[i] ^= ivec2[i];
570 :
571 335756 : _krb5_evp_iov_cursor_fillvec(&lastpos, tmp3, blocksize);
572 :
573 335756 : if (ivec)
574 0 : memcpy(ivec, tmp, blocksize);
575 :
576 335756 : return 0;
577 : }
578 :
579 : krb5_error_code
580 6450427 : _krb5_evp_encrypt_cts(krb5_context context,
581 : struct _krb5_key_data *key,
582 : void *data,
583 : size_t len,
584 : krb5_boolean encryptp,
585 : int usage,
586 : void *ivec)
587 : {
588 : size_t i, blocksize;
589 6450427 : struct _krb5_evp_schedule *ctx = key->schedule->data;
590 : unsigned char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH];
591 : EVP_CIPHER_CTX *c;
592 : unsigned char *p;
593 :
594 6450427 : c = encryptp ? &ctx->ectx : &ctx->dctx;
595 :
596 6450427 : blocksize = EVP_CIPHER_CTX_block_size(c);
597 :
598 6450427 : if (len < blocksize) {
599 0 : krb5_set_error_message(context, EINVAL,
600 : "message block too short");
601 0 : return EINVAL;
602 6450427 : } else if (len == blocksize) {
603 4729218 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
604 4729218 : EVP_Cipher(c, data, data, len);
605 4729218 : return 0;
606 : }
607 :
608 1721209 : if (ivec)
609 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
610 : else
611 1721209 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
612 :
613 1721209 : if (encryptp) {
614 :
615 837008 : p = data;
616 837008 : i = ((len - 1) / blocksize) * blocksize;
617 837008 : EVP_Cipher(c, p, p, i);
618 837008 : p += i - blocksize;
619 837008 : len -= i;
620 837008 : memcpy(ivec2, p, blocksize);
621 :
622 8291257 : for (i = 0; i < len; i++)
623 7454249 : tmp[i] = p[i + blocksize] ^ ivec2[i];
624 6774887 : for (; i < blocksize; i++)
625 5937879 : tmp[i] = 0 ^ ivec2[i];
626 :
627 837008 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
628 837008 : EVP_Cipher(c, p, tmp, blocksize);
629 :
630 837008 : memcpy(p + blocksize, ivec2, len);
631 837008 : if (ivec)
632 0 : memcpy(ivec, p, blocksize);
633 : } else {
634 : unsigned char tmp2[EVP_MAX_BLOCK_LENGTH], tmp3[EVP_MAX_BLOCK_LENGTH];
635 :
636 884201 : p = data;
637 884201 : if (len > blocksize * 2) {
638 : /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
639 884201 : i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize);
640 884201 : memcpy(ivec2, p + i - blocksize, blocksize);
641 884201 : EVP_Cipher(c, p, p, i);
642 884201 : p += i;
643 884201 : len -= i + blocksize;
644 : } else {
645 0 : if (ivec)
646 0 : memcpy(ivec2, ivec, blocksize);
647 : else
648 0 : memcpy(ivec2, zero_ivec, blocksize);
649 0 : len -= blocksize;
650 : }
651 :
652 884201 : memcpy(tmp, p, blocksize);
653 884201 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
654 884201 : EVP_Cipher(c, tmp2, p, blocksize);
655 :
656 884201 : memcpy(tmp3, p + blocksize, len);
657 884201 : memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */
658 :
659 8691527 : for (i = 0; i < len; i++)
660 7807326 : p[i + blocksize] = tmp2[i] ^ tmp3[i];
661 :
662 884201 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
663 884201 : EVP_Cipher(c, p, tmp3, blocksize);
664 :
665 15031417 : for (i = 0; i < blocksize; i++)
666 14147216 : p[i] ^= ivec2[i];
667 884201 : if (ivec)
668 0 : memcpy(ivec, tmp, blocksize);
669 : }
670 1721209 : return 0;
671 : }
|