2 * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #include <openssl/crypto.h>
11 #include "modes_lcl.h"
15 * Trouble with Ciphertext Stealing, CTS, mode is that there is no
16 * common official specification, but couple of cipher/application
17 * specific ones: RFC2040 and RFC3962. Then there is 'Proposal to
18 * Extend CBC Mode By "Ciphertext Stealing"' at NIST site, which
19 * deviates from mentioned RFCs. Most notably it allows input to be
20 * of block length and it doesn't flip the order of the last two
21 * blocks. CTS is being discussed even in ECB context, but it's not
22 * adopted for any known application. This implementation provides
23 * two interfaces: one compliant with above mentioned RFCs and one
24 * compliant with the NIST proposal, both extending CBC mode.
27 size_t CRYPTO_cts128_encrypt_block(const unsigned char *in,
28 unsigned char *out, size_t len,
29 const void *key, unsigned char ivec[16],
37 if ((residue = len % 16) == 0)
42 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
47 for (n = 0; n < residue; ++n)
49 (*block) (ivec, ivec, key);
50 memcpy(out, out - 16, residue);
51 memcpy(out - 16, ivec, 16);
56 size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in,
57 unsigned char *out, size_t len,
59 unsigned char ivec[16],
71 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
79 for (n = 0; n < residue; ++n)
81 (*block) (ivec, ivec, key);
82 memcpy(out - 16 + residue, ivec, 16);
87 size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out,
88 size_t len, const void *key,
89 unsigned char ivec[16], cbc128_f cbc)
100 if ((residue = len % 16) == 0)
105 (*cbc) (in, out, len, key, ivec, 1);
110 #if defined(CBC_HANDLES_TRUNCATED_IO)
111 memcpy(tmp.c, out - 16, 16);
112 (*cbc) (in, out - 16, residue, key, ivec, 1);
113 memcpy(out, tmp.c, residue);
115 memset(tmp.c, 0, sizeof(tmp));
116 memcpy(tmp.c, in, residue);
117 memcpy(out, out - 16, residue);
118 (*cbc) (tmp.c, out - 16, 16, key, ivec, 1);
120 return len + residue;
123 size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out,
124 size_t len, const void *key,
125 unsigned char ivec[16], cbc128_f cbc)
140 (*cbc) (in, out, len, key, ivec, 1);
148 #if defined(CBC_HANDLES_TRUNCATED_IO)
149 (*cbc) (in, out - 16 + residue, residue, key, ivec, 1);
151 memset(tmp.c, 0, sizeof(tmp));
152 memcpy(tmp.c, in, residue);
153 (*cbc) (tmp.c, out - 16 + residue, 16, key, ivec, 1);
155 return len + residue;
158 size_t CRYPTO_cts128_decrypt_block(const unsigned char *in,
159 unsigned char *out, size_t len,
160 const void *key, unsigned char ivec[16],
172 if ((residue = len % 16) == 0)
178 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
183 (*block) (in, tmp.c + 16, key);
185 memcpy(tmp.c, tmp.c + 16, 16);
186 memcpy(tmp.c, in + 16, residue);
187 (*block) (tmp.c, tmp.c, key);
189 for (n = 0; n < 16; ++n) {
190 unsigned char c = in[n];
191 out[n] = tmp.c[n] ^ ivec[n];
194 for (residue += 16; n < residue; ++n)
195 out[n] = tmp.c[n] ^ in[n];
197 return 16 + len + residue;
200 size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in,
201 unsigned char *out, size_t len,
203 unsigned char ivec[16],
218 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
225 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
230 (*block) (in + residue, tmp.c + 16, key);
232 memcpy(tmp.c, tmp.c + 16, 16);
233 memcpy(tmp.c, in, residue);
234 (*block) (tmp.c, tmp.c, key);
236 for (n = 0; n < 16; ++n) {
237 unsigned char c = in[n];
238 out[n] = tmp.c[n] ^ ivec[n];
239 ivec[n] = in[n + residue];
242 for (residue += 16; n < residue; ++n)
243 out[n] = tmp.c[n] ^ tmp.c[n - 16];
245 return 16 + len + residue;
248 size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out,
249 size_t len, const void *key,
250 unsigned char ivec[16], cbc128_f cbc)
261 if ((residue = len % 16) == 0)
267 (*cbc) (in, out, len, key, ivec, 0);
272 memset(tmp.c, 0, sizeof(tmp));
274 * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
276 (*cbc) (in, tmp.c, 16, key, tmp.c + 16, 0);
278 memcpy(tmp.c, in + 16, residue);
279 #if defined(CBC_HANDLES_TRUNCATED_IO)
280 (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
282 (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
283 memcpy(out, tmp.c, 16 + residue);
285 return 16 + len + residue;
288 size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out,
289 size_t len, const void *key,
290 unsigned char ivec[16], cbc128_f cbc)
304 (*cbc) (in, out, len, key, ivec, 0);
311 (*cbc) (in, out, len, key, ivec, 0);
316 memset(tmp.c, 0, sizeof(tmp));
318 * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
320 (*cbc) (in + residue, tmp.c, 16, key, tmp.c + 16, 0);
322 memcpy(tmp.c, in, residue);
323 #if defined(CBC_HANDLES_TRUNCATED_IO)
324 (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
326 (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
327 memcpy(out, tmp.c, 16 + residue);
329 return 16 + len + residue;
332 #if defined(SELFTEST)
334 # include <openssl/aes.h>
336 /* test vectors from RFC 3962 */
337 static const unsigned char test_key[16] = "chicken teriyaki";
338 static const unsigned char test_input[64] =
339 "I would like the" " General Gau's C"
340 "hicken, please, " "and wonton soup.";
341 static const unsigned char test_iv[16] =
342 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
344 static const unsigned char vector_17[17] = {
345 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4,
346 0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f,
350 static const unsigned char vector_31[31] = {
351 0xfc, 0x00, 0x78, 0x3e, 0x0e, 0xfd, 0xb2, 0xc1,
352 0xd4, 0x45, 0xd4, 0xc8, 0xef, 0xf7, 0xed, 0x22,
353 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
354 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5
357 static const unsigned char vector_32[32] = {
358 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
359 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8,
360 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
361 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84
364 static const unsigned char vector_47[47] = {
365 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
366 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
367 0xb3, 0xff, 0xfd, 0x94, 0x0c, 0x16, 0xa1, 0x8c,
368 0x1b, 0x55, 0x49, 0xd2, 0xf8, 0x38, 0x02, 0x9e,
369 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
370 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5
373 static const unsigned char vector_48[48] = {
374 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
375 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
376 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
377 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8,
378 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
379 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8
382 static const unsigned char vector_64[64] = {
383 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
384 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
385 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
386 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8,
387 0x48, 0x07, 0xef, 0xe8, 0x36, 0xee, 0x89, 0xa5,
388 0x26, 0x73, 0x0d, 0xbc, 0x2f, 0x7b, 0xc8, 0x40,
389 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
390 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8
393 static AES_KEY encks, decks;
395 void test_vector(const unsigned char *vector, size_t len)
397 unsigned char iv[sizeof(test_iv)];
398 unsigned char cleartext[64], ciphertext[64];
401 printf("vector_%d\n", len);
404 if ((tail = len % 16) == 0)
408 /* test block-based encryption */
409 memcpy(iv, test_iv, sizeof(test_iv));
410 CRYPTO_cts128_encrypt_block(test_input, ciphertext, len, &encks, iv,
411 (block128_f) AES_encrypt);
412 if (memcmp(ciphertext, vector, len))
413 fprintf(stderr, "output_%d mismatch\n", len), exit(1);
414 if (memcmp(iv, vector + len - tail, sizeof(iv)))
415 fprintf(stderr, "iv_%d mismatch\n", len), exit(1);
417 /* test block-based decryption */
418 memcpy(iv, test_iv, sizeof(test_iv));
419 CRYPTO_cts128_decrypt_block(ciphertext, cleartext, len, &decks, iv,
420 (block128_f) AES_decrypt);
421 if (memcmp(cleartext, test_input, len))
422 fprintf(stderr, "input_%d mismatch\n", len), exit(2);
423 if (memcmp(iv, vector + len - tail, sizeof(iv)))
424 fprintf(stderr, "iv_%d mismatch\n", len), exit(2);
426 /* test streamed encryption */
427 memcpy(iv, test_iv, sizeof(test_iv));
428 CRYPTO_cts128_encrypt(test_input, ciphertext, len, &encks, iv,
429 (cbc128_f) AES_cbc_encrypt);
430 if (memcmp(ciphertext, vector, len))
431 fprintf(stderr, "output_%d mismatch\n", len), exit(3);
432 if (memcmp(iv, vector + len - tail, sizeof(iv)))
433 fprintf(stderr, "iv_%d mismatch\n", len), exit(3);
435 /* test streamed decryption */
436 memcpy(iv, test_iv, sizeof(test_iv));
437 CRYPTO_cts128_decrypt(ciphertext, cleartext, len, &decks, iv,
438 (cbc128_f) AES_cbc_encrypt);
439 if (memcmp(cleartext, test_input, len))
440 fprintf(stderr, "input_%d mismatch\n", len), exit(4);
441 if (memcmp(iv, vector + len - tail, sizeof(iv)))
442 fprintf(stderr, "iv_%d mismatch\n", len), exit(4);
445 void test_nistvector(const unsigned char *vector, size_t len)
447 unsigned char iv[sizeof(test_iv)];
448 unsigned char cleartext[64], ciphertext[64], nistvector[64];
451 printf("nistvector_%d\n", len);
454 if ((tail = len % 16) == 0)
458 memcpy(nistvector, vector, len);
459 /* flip two last blocks */
460 memcpy(nistvector + len, vector + len + 16, tail);
461 memcpy(nistvector + len + tail, vector + len, 16);
465 /* test block-based encryption */
466 memcpy(iv, test_iv, sizeof(test_iv));
467 CRYPTO_nistcts128_encrypt_block(test_input, ciphertext, len, &encks, iv,
468 (block128_f) AES_encrypt);
469 if (memcmp(ciphertext, nistvector, len))
470 fprintf(stderr, "output_%d mismatch\n", len), exit(1);
471 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
472 fprintf(stderr, "iv_%d mismatch\n", len), exit(1);
474 /* test block-based decryption */
475 memcpy(iv, test_iv, sizeof(test_iv));
476 CRYPTO_nistcts128_decrypt_block(ciphertext, cleartext, len, &decks, iv,
477 (block128_f) AES_decrypt);
478 if (memcmp(cleartext, test_input, len))
479 fprintf(stderr, "input_%d mismatch\n", len), exit(2);
480 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
481 fprintf(stderr, "iv_%d mismatch\n", len), exit(2);
483 /* test streamed encryption */
484 memcpy(iv, test_iv, sizeof(test_iv));
485 CRYPTO_nistcts128_encrypt(test_input, ciphertext, len, &encks, iv,
486 (cbc128_f) AES_cbc_encrypt);
487 if (memcmp(ciphertext, nistvector, len))
488 fprintf(stderr, "output_%d mismatch\n", len), exit(3);
489 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
490 fprintf(stderr, "iv_%d mismatch\n", len), exit(3);
492 /* test streamed decryption */
493 memcpy(iv, test_iv, sizeof(test_iv));
494 CRYPTO_nistcts128_decrypt(ciphertext, cleartext, len, &decks, iv,
495 (cbc128_f) AES_cbc_encrypt);
496 if (memcmp(cleartext, test_input, len))
497 fprintf(stderr, "input_%d mismatch\n", len), exit(4);
498 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
499 fprintf(stderr, "iv_%d mismatch\n", len), exit(4);
504 AES_set_encrypt_key(test_key, 128, &encks);
505 AES_set_decrypt_key(test_key, 128, &decks);
507 test_vector(vector_17, sizeof(vector_17));
508 test_vector(vector_31, sizeof(vector_31));
509 test_vector(vector_32, sizeof(vector_32));
510 test_vector(vector_47, sizeof(vector_47));
511 test_vector(vector_48, sizeof(vector_48));
512 test_vector(vector_64, sizeof(vector_64));
514 test_nistvector(vector_17, sizeof(vector_17));
515 test_nistvector(vector_31, sizeof(vector_31));
516 test_nistvector(vector_32, sizeof(vector_32));
517 test_nistvector(vector_47, sizeof(vector_47));
518 test_nistvector(vector_48, sizeof(vector_48));
519 test_nistvector(vector_64, sizeof(vector_64));