1 /* ====================================================================
2 * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
4 * Rights for redistribution and usage in source and binary
5 * forms are granted according to the OpenSSL license.
8 #include <openssl/crypto.h>
20 * Trouble with Ciphertext Stealing, CTS, mode is that there is no
21 * common official specification, but couple of cipher/application
22 * specific ones: RFC2040 and RFC3962. Then there is 'Proposal to
23 * Extend CBC Mode By "Ciphertext Stealing"' at NIST site, which
24 * deviates from mentioned RFCs. Most notably it allows input to be
25 * of block length and it doesn't flip the order of the last two
26 * blocks. CTS is being discussed even in ECB context, but it's not
27 * adopted for any known application. This implementation provides
28 * two interfaces: one compliant with above mentioned RFCs and one
29 * compliant with the NIST proposal, both extending CBC mode.
32 size_t CRYPTO_cts128_encrypt_block(const unsigned char *in,
33 unsigned char *out, size_t len,
34 const void *key, unsigned char ivec[16],
39 assert(in && out && key && ivec);
44 if ((residue = len % 16) == 0)
49 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
54 for (n = 0; n < residue; ++n)
56 (*block) (ivec, ivec, key);
57 memcpy(out, out - 16, residue);
58 memcpy(out - 16, ivec, 16);
63 size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in,
64 unsigned char *out, size_t len,
66 unsigned char ivec[16],
71 assert(in && out && key && ivec);
80 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
88 for (n = 0; n < residue; ++n)
90 (*block) (ivec, ivec, key);
91 memcpy(out - 16 + residue, ivec, 16);
96 size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out,
97 size_t len, const void *key,
98 unsigned char ivec[16], cbc128_f cbc)
106 assert(in && out && key && ivec);
111 if ((residue = len % 16) == 0)
116 (*cbc) (in, out, len, key, ivec, 1);
121 #if defined(CBC_HANDLES_TRUNCATED_IO)
122 memcpy(tmp.c, out - 16, 16);
123 (*cbc) (in, out - 16, residue, key, ivec, 1);
124 memcpy(out, tmp.c, residue);
126 memset(tmp.c, 0, sizeof(tmp));
127 memcpy(tmp.c, in, residue);
128 memcpy(out, out - 16, residue);
129 (*cbc) (tmp.c, out - 16, 16, key, ivec, 1);
131 return len + residue;
134 size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out,
135 size_t len, const void *key,
136 unsigned char ivec[16], cbc128_f cbc)
144 assert(in && out && key && ivec);
153 (*cbc) (in, out, len, key, ivec, 1);
161 #if defined(CBC_HANDLES_TRUNCATED_IO)
162 (*cbc) (in, out - 16 + residue, residue, key, ivec, 1);
164 memset(tmp.c, 0, sizeof(tmp));
165 memcpy(tmp.c, in, residue);
166 (*cbc) (tmp.c, out - 16 + residue, 16, key, ivec, 1);
168 return len + residue;
171 size_t CRYPTO_cts128_decrypt_block(const unsigned char *in,
172 unsigned char *out, size_t len,
173 const void *key, unsigned char ivec[16],
182 assert(in && out && key && ivec);
187 if ((residue = len % 16) == 0)
193 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
198 (*block) (in, tmp.c + 16, key);
200 memcpy(tmp.c, tmp.c + 16, 16);
201 memcpy(tmp.c, in + 16, residue);
202 (*block) (tmp.c, tmp.c, key);
204 for (n = 0; n < 16; ++n) {
205 unsigned char c = in[n];
206 out[n] = tmp.c[n] ^ ivec[n];
209 for (residue += 16; n < residue; ++n)
210 out[n] = tmp.c[n] ^ in[n];
212 return 16 + len + residue;
215 size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in,
216 unsigned char *out, size_t len,
218 unsigned char ivec[16],
227 assert(in && out && key && ivec);
235 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
242 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
247 (*block) (in + residue, tmp.c + 16, key);
249 memcpy(tmp.c, tmp.c + 16, 16);
250 memcpy(tmp.c, in, residue);
251 (*block) (tmp.c, tmp.c, key);
253 for (n = 0; n < 16; ++n) {
254 unsigned char c = in[n];
255 out[n] = tmp.c[n] ^ ivec[n];
256 ivec[n] = in[n + residue];
259 for (residue += 16; n < residue; ++n)
260 out[n] = tmp.c[n] ^ tmp.c[n - 16];
262 return 16 + len + residue;
265 size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out,
266 size_t len, const void *key,
267 unsigned char ivec[16], cbc128_f cbc)
275 assert(in && out && key && ivec);
280 if ((residue = len % 16) == 0)
286 (*cbc) (in, out, len, key, ivec, 0);
291 memset(tmp.c, 0, sizeof(tmp));
293 * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
295 (*cbc) (in, tmp.c, 16, key, tmp.c + 16, 0);
297 memcpy(tmp.c, in + 16, residue);
298 #if defined(CBC_HANDLES_TRUNCATED_IO)
299 (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
301 (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
302 memcpy(out, tmp.c, 16 + residue);
304 return 16 + len + residue;
307 size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out,
308 size_t len, const void *key,
309 unsigned char ivec[16], cbc128_f cbc)
317 assert(in && out && key && ivec);
325 (*cbc) (in, out, len, key, ivec, 0);
332 (*cbc) (in, out, len, key, ivec, 0);
337 memset(tmp.c, 0, sizeof(tmp));
339 * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
341 (*cbc) (in + residue, tmp.c, 16, key, tmp.c + 16, 0);
343 memcpy(tmp.c, in, residue);
344 #if defined(CBC_HANDLES_TRUNCATED_IO)
345 (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
347 (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
348 memcpy(out, tmp.c, 16 + residue);
350 return 16 + len + residue;
353 #if defined(SELFTEST)
355 # include <openssl/aes.h>
357 /* test vectors from RFC 3962 */
358 static const unsigned char test_key[16] = "chicken teriyaki";
359 static const unsigned char test_input[64] =
360 "I would like the" " General Gau's C"
361 "hicken, please, " "and wonton soup.";
362 static const unsigned char test_iv[16] =
363 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
365 static const unsigned char vector_17[17] = {
366 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4,
367 0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f,
371 static const unsigned char vector_31[31] = {
372 0xfc, 0x00, 0x78, 0x3e, 0x0e, 0xfd, 0xb2, 0xc1,
373 0xd4, 0x45, 0xd4, 0xc8, 0xef, 0xf7, 0xed, 0x22,
374 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
375 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5
378 static const unsigned char vector_32[32] = {
379 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
380 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8,
381 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
382 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84
385 static const unsigned char vector_47[47] = {
386 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
387 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
388 0xb3, 0xff, 0xfd, 0x94, 0x0c, 0x16, 0xa1, 0x8c,
389 0x1b, 0x55, 0x49, 0xd2, 0xf8, 0x38, 0x02, 0x9e,
390 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
391 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5
394 static const unsigned char vector_48[48] = {
395 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
396 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
397 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
398 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8,
399 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
400 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8
403 static const unsigned char vector_64[64] = {
404 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
405 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
406 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
407 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8,
408 0x48, 0x07, 0xef, 0xe8, 0x36, 0xee, 0x89, 0xa5,
409 0x26, 0x73, 0x0d, 0xbc, 0x2f, 0x7b, 0xc8, 0x40,
410 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
411 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8
414 static AES_KEY encks, decks;
416 void test_vector(const unsigned char *vector, size_t len)
418 unsigned char iv[sizeof(test_iv)];
419 unsigned char cleartext[64], ciphertext[64];
422 printf("vector_%d\n", len);
425 if ((tail = len % 16) == 0)
429 /* test block-based encryption */
430 memcpy(iv, test_iv, sizeof(test_iv));
431 CRYPTO_cts128_encrypt_block(test_input, ciphertext, len, &encks, iv,
432 (block128_f) AES_encrypt);
433 if (memcmp(ciphertext, vector, len))
434 fprintf(stderr, "output_%d mismatch\n", len), exit(1);
435 if (memcmp(iv, vector + len - tail, sizeof(iv)))
436 fprintf(stderr, "iv_%d mismatch\n", len), exit(1);
438 /* test block-based decryption */
439 memcpy(iv, test_iv, sizeof(test_iv));
440 CRYPTO_cts128_decrypt_block(ciphertext, cleartext, len, &decks, iv,
441 (block128_f) AES_decrypt);
442 if (memcmp(cleartext, test_input, len))
443 fprintf(stderr, "input_%d mismatch\n", len), exit(2);
444 if (memcmp(iv, vector + len - tail, sizeof(iv)))
445 fprintf(stderr, "iv_%d mismatch\n", len), exit(2);
447 /* test streamed encryption */
448 memcpy(iv, test_iv, sizeof(test_iv));
449 CRYPTO_cts128_encrypt(test_input, ciphertext, len, &encks, iv,
450 (cbc128_f) AES_cbc_encrypt);
451 if (memcmp(ciphertext, vector, len))
452 fprintf(stderr, "output_%d mismatch\n", len), exit(3);
453 if (memcmp(iv, vector + len - tail, sizeof(iv)))
454 fprintf(stderr, "iv_%d mismatch\n", len), exit(3);
456 /* test streamed decryption */
457 memcpy(iv, test_iv, sizeof(test_iv));
458 CRYPTO_cts128_decrypt(ciphertext, cleartext, len, &decks, iv,
459 (cbc128_f) AES_cbc_encrypt);
460 if (memcmp(cleartext, test_input, len))
461 fprintf(stderr, "input_%d mismatch\n", len), exit(4);
462 if (memcmp(iv, vector + len - tail, sizeof(iv)))
463 fprintf(stderr, "iv_%d mismatch\n", len), exit(4);
466 void test_nistvector(const unsigned char *vector, size_t len)
468 unsigned char iv[sizeof(test_iv)];
469 unsigned char cleartext[64], ciphertext[64], nistvector[64];
472 printf("nistvector_%d\n", len);
475 if ((tail = len % 16) == 0)
479 memcpy(nistvector, vector, len);
480 /* flip two last blocks */
481 memcpy(nistvector + len, vector + len + 16, tail);
482 memcpy(nistvector + len + tail, vector + len, 16);
486 /* test block-based encryption */
487 memcpy(iv, test_iv, sizeof(test_iv));
488 CRYPTO_nistcts128_encrypt_block(test_input, ciphertext, len, &encks, iv,
489 (block128_f) AES_encrypt);
490 if (memcmp(ciphertext, nistvector, len))
491 fprintf(stderr, "output_%d mismatch\n", len), exit(1);
492 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
493 fprintf(stderr, "iv_%d mismatch\n", len), exit(1);
495 /* test block-based decryption */
496 memcpy(iv, test_iv, sizeof(test_iv));
497 CRYPTO_nistcts128_decrypt_block(ciphertext, cleartext, len, &decks, iv,
498 (block128_f) AES_decrypt);
499 if (memcmp(cleartext, test_input, len))
500 fprintf(stderr, "input_%d mismatch\n", len), exit(2);
501 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
502 fprintf(stderr, "iv_%d mismatch\n", len), exit(2);
504 /* test streamed encryption */
505 memcpy(iv, test_iv, sizeof(test_iv));
506 CRYPTO_nistcts128_encrypt(test_input, ciphertext, len, &encks, iv,
507 (cbc128_f) AES_cbc_encrypt);
508 if (memcmp(ciphertext, nistvector, len))
509 fprintf(stderr, "output_%d mismatch\n", len), exit(3);
510 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
511 fprintf(stderr, "iv_%d mismatch\n", len), exit(3);
513 /* test streamed decryption */
514 memcpy(iv, test_iv, sizeof(test_iv));
515 CRYPTO_nistcts128_decrypt(ciphertext, cleartext, len, &decks, iv,
516 (cbc128_f) AES_cbc_encrypt);
517 if (memcmp(cleartext, test_input, len))
518 fprintf(stderr, "input_%d mismatch\n", len), exit(4);
519 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
520 fprintf(stderr, "iv_%d mismatch\n", len), exit(4);
525 AES_set_encrypt_key(test_key, 128, &encks);
526 AES_set_decrypt_key(test_key, 128, &decks);
528 test_vector(vector_17, sizeof(vector_17));
529 test_vector(vector_31, sizeof(vector_31));
530 test_vector(vector_32, sizeof(vector_32));
531 test_vector(vector_47, sizeof(vector_47));
532 test_vector(vector_48, sizeof(vector_48));
533 test_vector(vector_64, sizeof(vector_64));
535 test_nistvector(vector_17, sizeof(vector_17));
536 test_nistvector(vector_31, sizeof(vector_31));
537 test_nistvector(vector_32, sizeof(vector_32));
538 test_nistvector(vector_47, sizeof(vector_47));
539 test_nistvector(vector_48, sizeof(vector_48));
540 test_nistvector(vector_64, sizeof(vector_64));