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 4317791 : _krb5_evp_schedule(krb5_context context,
38 : struct _krb5_key_type *kt,
39 : struct _krb5_key_data *kd)
40 : {
41 4317791 : struct _krb5_evp_schedule *key = kd->schedule->data;
42 4317791 : const EVP_CIPHER *c = (*kt->evp)();
43 :
44 4317791 : EVP_CIPHER_CTX_init(&key->ectx);
45 4317791 : EVP_CIPHER_CTX_init(&key->dctx);
46 :
47 4317791 : EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
48 4317791 : EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
49 4317791 : }
50 :
51 : void
52 4317791 : _krb5_evp_cleanup(krb5_context context, struct _krb5_key_data *kd)
53 : {
54 4317791 : struct _krb5_evp_schedule *key = kd->schedule->data;
55 4317791 : EVP_CIPHER_CTX_cleanup(&key->ectx);
56 4317791 : EVP_CIPHER_CTX_cleanup(&key->dctx);
57 4317791 : }
58 :
59 : int
60 2437596 : _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 2437596 : krb5_data current = {0,0};
71 :
72 2437596 : if (crypto != NULL) {
73 1102143 : if (crypto->mdctx == NULL)
74 271622 : crypto->mdctx = EVP_MD_CTX_create();
75 1102143 : if (crypto->mdctx == NULL)
76 0 : return 0;
77 1102143 : ctx = crypto->mdctx;
78 : } else
79 1335453 : ctx = EVP_MD_CTX_create();
80 :
81 2437596 : ret = EVP_DigestInit_ex(ctx, md, engine);
82 2437596 : if (ret != 1)
83 0 : goto out;
84 :
85 5834186 : for (i = 0; i < niov; i++) {
86 3396590 : if (_krb5_crypto_iov_should_sign(&iov[i])) {
87 3396590 : if ((char *)current.data + current.length == iov[i].data.data) {
88 32 : current.length += iov[i].data.length;
89 : } else {
90 3396558 : if (current.data) {
91 958994 : ret = EVP_DigestUpdate(ctx, current.data, current.length);
92 958994 : if (ret != 1)
93 0 : goto out;
94 : }
95 3396558 : current = iov[i].data;
96 : }
97 : }
98 : }
99 :
100 2437596 : if (current.data) {
101 2437564 : ret = EVP_DigestUpdate(ctx, current.data, current.length);
102 2437564 : if (ret != 1)
103 0 : goto out;
104 : }
105 :
106 2437596 : ret = EVP_DigestFinal_ex(ctx, hash, hsize);
107 :
108 2437596 : out:
109 2437596 : if (crypto == NULL)
110 1335453 : EVP_MD_CTX_destroy(ctx);
111 :
112 2437596 : return ret;
113 : }
114 :
115 : krb5_error_code
116 3874642 : _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 3874642 : krb5_data current = {0, 0};
128 : int i;
129 :
130 3874642 : if (crypto != NULL) {
131 3874642 : if (crypto->hmacctx == NULL)
132 874579 : crypto->hmacctx = HMAC_CTX_new();
133 3874642 : ctx = crypto->hmacctx;
134 : } else {
135 0 : ctx = HMAC_CTX_new();
136 : }
137 3874642 : if (ctx == NULL)
138 0 : return krb5_enomem(context);
139 :
140 3874642 : 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 16120142 : for (i = 0; i < niov; i++) {
147 12245500 : if (_krb5_crypto_iov_should_sign(&iov[i])) {
148 9408358 : if ((char *)current.data + current.length == iov[i].data.data) {
149 2743531 : current.length += iov[i].data.length;
150 : } else {
151 6664827 : if (current.data)
152 2790286 : HMAC_Update(ctx, current.data, current.length);
153 6664827 : current = iov[i].data;
154 : }
155 : }
156 : }
157 :
158 3874642 : if (current.data)
159 3874541 : HMAC_Update(ctx, current.data, current.length);
160 :
161 3874642 : HMAC_Final(ctx, hmac, hmaclen);
162 :
163 3874642 : if (crypto == NULL)
164 0 : HMAC_CTX_free(ctx);
165 :
166 3874642 : 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 26123025 : _krb5_evp_iov_should_encrypt(struct krb5_crypto_iov *iov)
208 : {
209 26123025 : return (iov->flags == KRB5_CRYPTO_TYPE_DATA
210 20205584 : || iov->flags == KRB5_CRYPTO_TYPE_HEADER
211 43538323 : || 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 4522106 : _krb5_evp_iov_cursor_expand(struct _krb5_evp_iov_cursor *cursor)
221 : {
222 4522106 : if (cursor->nextidx == cursor->niov)
223 0 : return;
224 :
225 9044212 : 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 4522106 : return;
236 : }
237 :
238 : /* Move the cursor along to the start of the next block to be
239 : * encrypted */
240 : static inline void
241 7312392 : _krb5_evp_iov_cursor_nextcrypt(struct _krb5_evp_iov_cursor *cursor)
242 : {
243 14625204 : for (; cursor->nextidx < cursor->niov; cursor->nextidx++) {
244 11834918 : if (_krb5_evp_iov_should_encrypt(&cursor->iov[cursor->nextidx])
245 4522298 : && cursor->iov[cursor->nextidx].data.length != 0) {
246 4522106 : cursor->current = cursor->iov[cursor->nextidx].data;
247 4522106 : cursor->nextidx++;
248 4522106 : _krb5_evp_iov_cursor_expand(cursor);
249 4522106 : return;
250 : }
251 : }
252 :
253 2790286 : cursor->current.length = 0; /* No matches, so we're done here */
254 : }
255 :
256 : static inline void
257 1395143 : _krb5_evp_iov_cursor_init(struct _krb5_evp_iov_cursor *cursor,
258 : struct krb5_crypto_iov *iov, int niov)
259 : {
260 1395143 : memset(cursor, 0, sizeof(struct _krb5_evp_iov_cursor));
261 :
262 1395143 : cursor->iov = iov;
263 1395143 : cursor->niov = niov;
264 1395143 : cursor->nextidx = 0;
265 :
266 : /* Move along to the first block we're going to be encrypting */
267 1395143 : _krb5_evp_iov_cursor_nextcrypt(cursor);
268 1395143 : }
269 :
270 : static inline void
271 6630203 : _krb5_evp_iov_cursor_advance(struct _krb5_evp_iov_cursor *cursor,
272 : size_t amount)
273 : {
274 15713703 : while (amount > 0) {
275 5571893 : if (cursor->current.length > amount) {
276 3118596 : cursor->current.data = (char *)cursor->current.data + amount;
277 3118596 : cursor->current.length -= amount;
278 3118596 : return;
279 : }
280 2453297 : amount -= cursor->current.length;
281 2453297 : _krb5_evp_iov_cursor_nextcrypt(cursor);
282 : }
283 : }
284 :
285 : static inline int
286 5195928 : _krb5_evp_iov_cursor_done(struct _krb5_evp_iov_cursor *cursor)
287 : {
288 5195928 : 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 2068809 : _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 2068809 : cursorint = *cursor;
303 :
304 6206427 : while (length > 0 && !_krb5_evp_iov_cursor_done(&cursorint)) {
305 2068809 : if (cursorint.current.length > length) {
306 336833 : memcpy(buf, cursorint.current.data, length);
307 336833 : _krb5_evp_iov_cursor_advance(&cursorint, length);
308 336833 : length = 0;
309 : } else {
310 1731976 : memcpy(buf, cursorint.current.data, cursorint.current.length);
311 1731976 : length -= cursorint.current.length;
312 1731976 : buf += cursorint.current.length;
313 1731976 : _krb5_evp_iov_cursor_nextcrypt(&cursorint);
314 : }
315 : }
316 :
317 2068809 : if (outcursor != NULL)
318 336833 : *outcursor = cursorint;
319 2068809 : }
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 3127119 : _krb5_evp_iov_cursor_fillvec(struct _krb5_evp_iov_cursor *cursor,
326 : unsigned char *buf, size_t length)
327 : {
328 9381357 : while (length > 0 && !_krb5_evp_iov_cursor_done(cursor)) {
329 3127119 : if (cursor->current.length > length) {
330 1395143 : memcpy(cursor->current.data, buf, length);
331 1395143 : _krb5_evp_iov_cursor_advance(cursor, length);
332 1395143 : length = 0;
333 : } else {
334 1731976 : memcpy(cursor->current.data, buf, cursor->current.length);
335 1731976 : length -= cursor->current.length;
336 1731976 : buf += cursor->current.length;
337 1731976 : _krb5_evp_iov_cursor_nextcrypt(cursor);
338 : }
339 : }
340 3127119 : }
341 :
342 : static size_t
343 1395143 : _krb5_evp_iov_cryptlength(struct krb5_crypto_iov *iov, int niov)
344 : {
345 : int i;
346 1395143 : size_t length = 0;
347 :
348 11161144 : for (i = 0; i < niov; i++) {
349 9766001 : if (_krb5_evp_iov_should_encrypt(&iov[i]))
350 4185429 : length += iov[i].data.length;
351 : }
352 :
353 1395143 : 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 1395143 : _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 1395143 : 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 1395143 : c = encryptp ? &ctx->ectx : &ctx->dctx;
432 :
433 1395143 : blocksize = EVP_CIPHER_CTX_block_size(c);
434 1395143 : blockmask = ~(blocksize - 1);
435 :
436 1395143 : length = _krb5_evp_iov_cryptlength(iov, niov);
437 :
438 1395143 : if (length < blocksize) {
439 0 : krb5_set_error_message(context, EINVAL,
440 : "message block too short");
441 0 : return EINVAL;
442 : }
443 :
444 1395143 : if (length == blocksize)
445 0 : return _krb5_evp_encrypt_iov(context, key, iov, niov,
446 : encryptp, usage, ivec);
447 :
448 1395143 : if (ivec)
449 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
450 : else
451 1395143 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
452 :
453 1395143 : if (encryptp) {
454 : /* On our first pass, we want to process everything but the
455 : * final partial block */
456 1058310 : remaining = ((length - 1) & blockmask);
457 1058310 : partiallen = length - remaining;
458 :
459 1058310 : 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 336833 : if (length > 2 * blocksize) {
464 336833 : remaining = (((length - 1) / blocksize) * blocksize) - (blocksize*2);
465 336833 : partiallen = length - remaining - (blocksize * 2);
466 : } else {
467 0 : remaining = 0;
468 0 : partiallen = length - blocksize;
469 : }
470 : }
471 :
472 1395143 : _krb5_evp_iov_cursor_init(&cursor, iov, niov);
473 6630203 : while (remaining > 0) {
474 : /* If the iovec has more data than we need, just use it */
475 3839917 : if (cursor.current.length >= remaining) {
476 1395107 : EVP_Cipher(c, cursor.current.data, cursor.current.data, remaining);
477 :
478 1395107 : 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 1058310 : lastpos = cursor;
482 1058310 : _krb5_evp_iov_cursor_advance(&lastpos, remaining - blocksize);
483 1058310 : memcpy(ivec2, lastpos.current.data, blocksize);
484 : }
485 :
486 1395107 : _krb5_evp_iov_cursor_advance(&cursor, remaining);
487 1395107 : remaining = 0;
488 : } else {
489 : /* Use as much as we can, firstly all of the whole blocks */
490 2444810 : wholeblocks = cursor.current.length & blockmask;
491 :
492 2444810 : if (wholeblocks > 0) {
493 2444810 : EVP_Cipher(c, cursor.current.data, cursor.current.data,
494 : wholeblocks);
495 2444810 : _krb5_evp_iov_cursor_advance(&cursor, wholeblocks);
496 2444810 : remaining -= wholeblocks;
497 : }
498 :
499 : /* Then, if we have partial data left, steal enough from subsequent
500 : * iovecs to make a whole block */
501 2444810 : 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 1395143 : if (encryptp) {
516 : /* Copy the partial block into tmp */
517 1058310 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp, partiallen, NULL);
518 :
519 : /* XOR the final partial block with ivec2 */
520 17991270 : for (i = 0; i < partiallen; i++)
521 16932960 : tmp[i] = tmp[i] ^ ivec2[i];
522 1058310 : for (; i < blocksize; i++)
523 0 : tmp[i] = 0 ^ ivec2[i]; /* XOR 0s if partial block exhausted */
524 :
525 1058310 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
526 1058310 : EVP_Cipher(c, tmp, tmp, blocksize);
527 :
528 1058310 : _krb5_evp_iov_cursor_fillvec(&lastpos, tmp, blocksize);
529 1058310 : _krb5_evp_iov_cursor_fillvec(&cursor, ivec2, partiallen);
530 :
531 1058310 : if (ivec)
532 0 : memcpy(ivec, tmp, blocksize);
533 :
534 1058310 : 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 336833 : 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 336833 : _krb5_evp_iov_cursor_fillbuf(&cursor, ivec2, blocksize, NULL);
548 336833 : EVP_Cipher(c, tmp, ivec2, blocksize);
549 336833 : _krb5_evp_iov_cursor_fillvec(&cursor, tmp, blocksize);
550 : }
551 :
552 336833 : lastpos = cursor; /* Remember where the last block is */
553 336833 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp, blocksize, &cursor);
554 336833 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
555 336833 : EVP_Cipher(c, tmp2, tmp, blocksize); /* tmp eventually becomes output ivec */
556 :
557 336833 : _krb5_evp_iov_cursor_fillbuf(&cursor, tmp3, partiallen, NULL);
558 :
559 336833 : memcpy(tmp3 + partiallen, tmp2 + partiallen, blocksize - partiallen); /* xor 0 */
560 5726161 : for (i = 0; i < partiallen; i++)
561 5389328 : tmp2[i] = tmp2[i] ^ tmp3[i];
562 :
563 336833 : _krb5_evp_iov_cursor_fillvec(&cursor, tmp2, partiallen);
564 :
565 336833 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
566 336833 : EVP_Cipher(c, tmp3, tmp3, blocksize);
567 :
568 5726161 : for (i = 0; i < blocksize; i++)
569 5389328 : tmp3[i] ^= ivec2[i];
570 :
571 336833 : _krb5_evp_iov_cursor_fillvec(&lastpos, tmp3, blocksize);
572 :
573 336833 : if (ivec)
574 0 : memcpy(ivec, tmp, blocksize);
575 :
576 336833 : return 0;
577 : }
578 :
579 : krb5_error_code
580 6454517 : _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 6454517 : 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 6454517 : c = encryptp ? &ctx->ectx : &ctx->dctx;
595 :
596 6454517 : blocksize = EVP_CIPHER_CTX_block_size(c);
597 :
598 6454517 : if (len < blocksize) {
599 0 : krb5_set_error_message(context, EINVAL,
600 : "message block too short");
601 0 : return EINVAL;
602 6454517 : } else if (len == blocksize) {
603 4733111 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
604 4733111 : EVP_Cipher(c, data, data, len);
605 4733111 : return 0;
606 : }
607 :
608 1721406 : if (ivec)
609 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
610 : else
611 1721406 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
612 :
613 1721406 : if (encryptp) {
614 :
615 836902 : p = data;
616 836902 : i = ((len - 1) / blocksize) * blocksize;
617 836902 : EVP_Cipher(c, p, p, i);
618 836902 : p += i - blocksize;
619 836902 : len -= i;
620 836902 : memcpy(ivec2, p, blocksize);
621 :
622 8303259 : for (i = 0; i < len; i++)
623 7466357 : tmp[i] = p[i + blocksize] ^ ivec2[i];
624 6760977 : for (; i < blocksize; i++)
625 5924075 : tmp[i] = 0 ^ ivec2[i];
626 :
627 836902 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
628 836902 : EVP_Cipher(c, p, tmp, blocksize);
629 :
630 836902 : memcpy(p + blocksize, ivec2, len);
631 836902 : 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 884504 : p = data;
637 884504 : if (len > blocksize * 2) {
638 : /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
639 884504 : i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize);
640 884504 : memcpy(ivec2, p + i - blocksize, blocksize);
641 884504 : EVP_Cipher(c, p, p, i);
642 884504 : p += i;
643 884504 : 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 884504 : memcpy(tmp, p, blocksize);
653 884504 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
654 884504 : EVP_Cipher(c, tmp2, p, blocksize);
655 :
656 884504 : memcpy(tmp3, p + blocksize, len);
657 884504 : memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */
658 :
659 8707863 : for (i = 0; i < len; i++)
660 7823359 : p[i + blocksize] = tmp2[i] ^ tmp3[i];
661 :
662 884504 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
663 884504 : EVP_Cipher(c, p, tmp3, blocksize);
664 :
665 15036568 : for (i = 0; i < blocksize; i++)
666 14152064 : p[i] ^= ivec2[i];
667 884504 : if (ivec)
668 0 : memcpy(ivec, tmp, blocksize);
669 : }
670 1721406 : return 0;
671 : }
|