]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/modes/cts128.c
Remove outdated DEBUG flags.
[thirdparty/openssl.git] / crypto / modes / cts128.c
CommitLineData
fe150ac2
AP
1/* ====================================================================
2 * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
3 *
4 * Rights for redistribution and usage in source and binary
5 * forms are granted according to the OpenSSL license.
6 */
7
a3654f05 8#include <openssl/crypto.h>
f472ec8c 9#include "modes_lcl.h"
fe150ac2
AP
10#include <string.h>
11
fe150ac2
AP
12/*
13 * Trouble with Ciphertext Stealing, CTS, mode is that there is no
14 * common official specification, but couple of cipher/application
15 * specific ones: RFC2040 and RFC3962. Then there is 'Proposal to
16 * Extend CBC Mode By "Ciphertext Stealing"' at NIST site, which
17 * deviates from mentioned RFCs. Most notably it allows input to be
18 * of block length and it doesn't flip the order of the last two
19 * blocks. CTS is being discussed even in ECB context, but it's not
67a315b6
AP
20 * adopted for any known application. This implementation provides
21 * two interfaces: one compliant with above mentioned RFCs and one
22 * compliant with the NIST proposal, both extending CBC mode.
fe150ac2
AP
23 */
24
0f113f3e
MC
25size_t CRYPTO_cts128_encrypt_block(const unsigned char *in,
26 unsigned char *out, size_t len,
27 const void *key, unsigned char ivec[16],
28 block128_f block)
29{
30 size_t residue, n;
fe150ac2 31
0f113f3e
MC
32 if (len <= 16)
33 return 0;
fe150ac2 34
0f113f3e
MC
35 if ((residue = len % 16) == 0)
36 residue = 16;
fe150ac2 37
0f113f3e 38 len -= residue;
fe150ac2 39
0f113f3e 40 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
fe150ac2 41
0f113f3e
MC
42 in += len;
43 out += len;
fe150ac2 44
0f113f3e
MC
45 for (n = 0; n < residue; ++n)
46 ivec[n] ^= in[n];
47 (*block) (ivec, ivec, key);
48 memcpy(out, out - 16, residue);
49 memcpy(out - 16, ivec, 16);
fe150ac2 50
0f113f3e 51 return len + residue;
fe150ac2
AP
52}
53
0f113f3e
MC
54size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in,
55 unsigned char *out, size_t len,
56 const void *key,
57 unsigned char ivec[16],
58 block128_f block)
59{
60 size_t residue, n;
67a315b6 61
0f113f3e
MC
62 if (len < 16)
63 return 0;
67a315b6 64
0f113f3e 65 residue = len % 16;
67a315b6 66
0f113f3e 67 len -= residue;
67a315b6 68
0f113f3e 69 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
67a315b6 70
0f113f3e
MC
71 if (residue == 0)
72 return len;
67a315b6 73
0f113f3e
MC
74 in += len;
75 out += len;
67a315b6 76
0f113f3e
MC
77 for (n = 0; n < residue; ++n)
78 ivec[n] ^= in[n];
79 (*block) (ivec, ivec, key);
80 memcpy(out - 16 + residue, ivec, 16);
67a315b6 81
0f113f3e 82 return len + residue;
67a315b6
AP
83}
84
fe150ac2 85size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out,
0f113f3e
MC
86 size_t len, const void *key,
87 unsigned char ivec[16], cbc128_f cbc)
88{
89 size_t residue;
90 union {
91 size_t align;
92 unsigned char c[16];
93 } tmp;
fe150ac2 94
0f113f3e
MC
95 if (len <= 16)
96 return 0;
fe150ac2 97
0f113f3e
MC
98 if ((residue = len % 16) == 0)
99 residue = 16;
fe150ac2 100
0f113f3e 101 len -= residue;
fe150ac2 102
0f113f3e 103 (*cbc) (in, out, len, key, ivec, 1);
fe150ac2 104
0f113f3e
MC
105 in += len;
106 out += len;
fe150ac2
AP
107
108#if defined(CBC_HANDLES_TRUNCATED_IO)
0f113f3e
MC
109 memcpy(tmp.c, out - 16, 16);
110 (*cbc) (in, out - 16, residue, key, ivec, 1);
111 memcpy(out, tmp.c, residue);
fe150ac2 112#else
0f113f3e
MC
113 memset(tmp.c, 0, sizeof(tmp));
114 memcpy(tmp.c, in, residue);
115 memcpy(out, out - 16, residue);
116 (*cbc) (tmp.c, out - 16, 16, key, ivec, 1);
fe150ac2 117#endif
0f113f3e 118 return len + residue;
fe150ac2
AP
119}
120
67a315b6 121size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out,
0f113f3e
MC
122 size_t len, const void *key,
123 unsigned char ivec[16], cbc128_f cbc)
124{
125 size_t residue;
126 union {
127 size_t align;
128 unsigned char c[16];
129 } tmp;
67a315b6 130
0f113f3e
MC
131 if (len < 16)
132 return 0;
67a315b6 133
0f113f3e 134 residue = len % 16;
67a315b6 135
0f113f3e 136 len -= residue;
67a315b6 137
0f113f3e 138 (*cbc) (in, out, len, key, ivec, 1);
67a315b6 139
0f113f3e
MC
140 if (residue == 0)
141 return len;
67a315b6 142
0f113f3e
MC
143 in += len;
144 out += len;
67a315b6
AP
145
146#if defined(CBC_HANDLES_TRUNCATED_IO)
0f113f3e 147 (*cbc) (in, out - 16 + residue, residue, key, ivec, 1);
67a315b6 148#else
0f113f3e
MC
149 memset(tmp.c, 0, sizeof(tmp));
150 memcpy(tmp.c, in, residue);
151 (*cbc) (tmp.c, out - 16 + residue, 16, key, ivec, 1);
67a315b6 152#endif
0f113f3e 153 return len + residue;
67a315b6
AP
154}
155
0f113f3e
MC
156size_t CRYPTO_cts128_decrypt_block(const unsigned char *in,
157 unsigned char *out, size_t len,
158 const void *key, unsigned char ivec[16],
159 block128_f block)
160{
161 size_t residue, n;
162 union {
163 size_t align;
164 unsigned char c[32];
165 } tmp;
fe150ac2 166
0f113f3e
MC
167 if (len <= 16)
168 return 0;
fe150ac2 169
0f113f3e
MC
170 if ((residue = len % 16) == 0)
171 residue = 16;
fe150ac2 172
0f113f3e 173 len -= 16 + residue;
fe150ac2 174
0f113f3e
MC
175 if (len) {
176 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
177 in += len;
178 out += len;
179 }
fe150ac2 180
0f113f3e 181 (*block) (in, tmp.c + 16, key);
fe150ac2 182
0f113f3e
MC
183 memcpy(tmp.c, tmp.c + 16, 16);
184 memcpy(tmp.c, in + 16, residue);
185 (*block) (tmp.c, tmp.c, key);
fe150ac2 186
0f113f3e
MC
187 for (n = 0; n < 16; ++n) {
188 unsigned char c = in[n];
189 out[n] = tmp.c[n] ^ ivec[n];
190 ivec[n] = c;
191 }
192 for (residue += 16; n < residue; ++n)
193 out[n] = tmp.c[n] ^ in[n];
fe150ac2 194
0f113f3e 195 return 16 + len + residue;
67a315b6
AP
196}
197
0f113f3e
MC
198size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in,
199 unsigned char *out, size_t len,
200 const void *key,
201 unsigned char ivec[16],
202 block128_f block)
203{
204 size_t residue, n;
205 union {
206 size_t align;
207 unsigned char c[32];
208 } tmp;
67a315b6 209
0f113f3e
MC
210 if (len < 16)
211 return 0;
67a315b6 212
0f113f3e 213 residue = len % 16;
67a315b6 214
0f113f3e
MC
215 if (residue == 0) {
216 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
217 return len;
218 }
67a315b6 219
0f113f3e 220 len -= 16 + residue;
67a315b6 221
0f113f3e
MC
222 if (len) {
223 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
224 in += len;
225 out += len;
226 }
67a315b6 227
0f113f3e 228 (*block) (in + residue, tmp.c + 16, key);
67a315b6 229
0f113f3e
MC
230 memcpy(tmp.c, tmp.c + 16, 16);
231 memcpy(tmp.c, in, residue);
232 (*block) (tmp.c, tmp.c, key);
67a315b6 233
0f113f3e
MC
234 for (n = 0; n < 16; ++n) {
235 unsigned char c = in[n];
236 out[n] = tmp.c[n] ^ ivec[n];
237 ivec[n] = in[n + residue];
238 tmp.c[n] = c;
239 }
240 for (residue += 16; n < residue; ++n)
241 out[n] = tmp.c[n] ^ tmp.c[n - 16];
67a315b6 242
0f113f3e 243 return 16 + len + residue;
fe150ac2
AP
244}
245
246size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out,
0f113f3e
MC
247 size_t len, const void *key,
248 unsigned char ivec[16], cbc128_f cbc)
249{
250 size_t residue;
251 union {
252 size_t align;
253 unsigned char c[32];
254 } tmp;
fe150ac2 255
0f113f3e
MC
256 if (len <= 16)
257 return 0;
fe150ac2 258
0f113f3e
MC
259 if ((residue = len % 16) == 0)
260 residue = 16;
fe150ac2 261
0f113f3e 262 len -= 16 + residue;
fe150ac2 263
0f113f3e
MC
264 if (len) {
265 (*cbc) (in, out, len, key, ivec, 0);
266 in += len;
267 out += len;
268 }
fe150ac2 269
0f113f3e
MC
270 memset(tmp.c, 0, sizeof(tmp));
271 /*
272 * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
273 */
274 (*cbc) (in, tmp.c, 16, key, tmp.c + 16, 0);
fe150ac2 275
0f113f3e 276 memcpy(tmp.c, in + 16, residue);
fe150ac2 277#if defined(CBC_HANDLES_TRUNCATED_IO)
0f113f3e 278 (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
fe150ac2 279#else
0f113f3e
MC
280 (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
281 memcpy(out, tmp.c, 16 + residue);
fe150ac2 282#endif
0f113f3e 283 return 16 + len + residue;
67a315b6
AP
284}
285
286size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out,
0f113f3e
MC
287 size_t len, const void *key,
288 unsigned char ivec[16], cbc128_f cbc)
289{
290 size_t residue;
291 union {
292 size_t align;
293 unsigned char c[32];
294 } tmp;
67a315b6 295
0f113f3e
MC
296 if (len < 16)
297 return 0;
67a315b6 298
0f113f3e 299 residue = len % 16;
67a315b6 300
0f113f3e
MC
301 if (residue == 0) {
302 (*cbc) (in, out, len, key, ivec, 0);
303 return len;
304 }
67a315b6 305
0f113f3e 306 len -= 16 + residue;
67a315b6 307
0f113f3e
MC
308 if (len) {
309 (*cbc) (in, out, len, key, ivec, 0);
310 in += len;
311 out += len;
312 }
67a315b6 313
0f113f3e
MC
314 memset(tmp.c, 0, sizeof(tmp));
315 /*
316 * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
317 */
318 (*cbc) (in + residue, tmp.c, 16, key, tmp.c + 16, 0);
67a315b6 319
0f113f3e 320 memcpy(tmp.c, in, residue);
67a315b6 321#if defined(CBC_HANDLES_TRUNCATED_IO)
0f113f3e 322 (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
67a315b6 323#else
0f113f3e
MC
324 (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
325 memcpy(out, tmp.c, 16 + residue);
67a315b6 326#endif
0f113f3e 327 return 16 + len + residue;
fe150ac2
AP
328}
329
330#if defined(SELFTEST)
0f113f3e
MC
331# include <stdio.h>
332# include <openssl/aes.h>
fe150ac2
AP
333
334/* test vectors from RFC 3962 */
335static const unsigned char test_key[16] = "chicken teriyaki";
336static const unsigned char test_input[64] =
0f113f3e
MC
337 "I would like the" " General Gau's C"
338 "hicken, please, " "and wonton soup.";
339static const unsigned char test_iv[16] =
340 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
fe150ac2 341
6ea3d183 342static const unsigned char vector_17[17] = {
0f113f3e
MC
343 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4,
344 0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f,
345 0x97
346};
347
6ea3d183 348static const unsigned char vector_31[31] = {
0f113f3e
MC
349 0xfc, 0x00, 0x78, 0x3e, 0x0e, 0xfd, 0xb2, 0xc1,
350 0xd4, 0x45, 0xd4, 0xc8, 0xef, 0xf7, 0xed, 0x22,
351 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
352 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5
353};
354
6ea3d183 355static const unsigned char vector_32[32] = {
0f113f3e
MC
356 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
357 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8,
358 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
359 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84
360};
361
6ea3d183 362static const unsigned char vector_47[47] = {
0f113f3e
MC
363 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
364 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
365 0xb3, 0xff, 0xfd, 0x94, 0x0c, 0x16, 0xa1, 0x8c,
366 0x1b, 0x55, 0x49, 0xd2, 0xf8, 0x38, 0x02, 0x9e,
367 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
368 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5
369};
370
6ea3d183 371static const unsigned char vector_48[48] = {
0f113f3e
MC
372 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
373 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
374 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
375 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8,
376 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
377 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8
378};
379
6ea3d183 380static const unsigned char vector_64[64] = {
0f113f3e
MC
381 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
382 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
383 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
384 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8,
385 0x48, 0x07, 0xef, 0xe8, 0x36, 0xee, 0x89, 0xa5,
386 0x26, 0x73, 0x0d, 0xbc, 0x2f, 0x7b, 0xc8, 0x40,
387 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
388 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8
389};
fe150ac2
AP
390
391static AES_KEY encks, decks;
392
0f113f3e
MC
393void test_vector(const unsigned char *vector, size_t len)
394{
395 unsigned char iv[sizeof(test_iv)];
396 unsigned char cleartext[64], ciphertext[64];
397 size_t tail;
398
399 printf("vector_%d\n", len);
400 fflush(stdout);
401
402 if ((tail = len % 16) == 0)
403 tail = 16;
404 tail += 16;
405
406 /* test block-based encryption */
407 memcpy(iv, test_iv, sizeof(test_iv));
408 CRYPTO_cts128_encrypt_block(test_input, ciphertext, len, &encks, iv,
409 (block128_f) AES_encrypt);
410 if (memcmp(ciphertext, vector, len))
411 fprintf(stderr, "output_%d mismatch\n", len), exit(1);
412 if (memcmp(iv, vector + len - tail, sizeof(iv)))
413 fprintf(stderr, "iv_%d mismatch\n", len), exit(1);
414
415 /* test block-based decryption */
416 memcpy(iv, test_iv, sizeof(test_iv));
417 CRYPTO_cts128_decrypt_block(ciphertext, cleartext, len, &decks, iv,
418 (block128_f) AES_decrypt);
419 if (memcmp(cleartext, test_input, len))
420 fprintf(stderr, "input_%d mismatch\n", len), exit(2);
421 if (memcmp(iv, vector + len - tail, sizeof(iv)))
422 fprintf(stderr, "iv_%d mismatch\n", len), exit(2);
423
424 /* test streamed encryption */
425 memcpy(iv, test_iv, sizeof(test_iv));
426 CRYPTO_cts128_encrypt(test_input, ciphertext, len, &encks, iv,
427 (cbc128_f) AES_cbc_encrypt);
428 if (memcmp(ciphertext, vector, len))
429 fprintf(stderr, "output_%d mismatch\n", len), exit(3);
430 if (memcmp(iv, vector + len - tail, sizeof(iv)))
431 fprintf(stderr, "iv_%d mismatch\n", len), exit(3);
432
433 /* test streamed decryption */
434 memcpy(iv, test_iv, sizeof(test_iv));
435 CRYPTO_cts128_decrypt(ciphertext, cleartext, len, &decks, iv,
436 (cbc128_f) AES_cbc_encrypt);
437 if (memcmp(cleartext, test_input, len))
438 fprintf(stderr, "input_%d mismatch\n", len), exit(4);
439 if (memcmp(iv, vector + len - tail, sizeof(iv)))
440 fprintf(stderr, "iv_%d mismatch\n", len), exit(4);
fe150ac2
AP
441}
442
0f113f3e
MC
443void test_nistvector(const unsigned char *vector, size_t len)
444{
445 unsigned char iv[sizeof(test_iv)];
446 unsigned char cleartext[64], ciphertext[64], nistvector[64];
447 size_t tail;
448
449 printf("nistvector_%d\n", len);
450 fflush(stdout);
451
452 if ((tail = len % 16) == 0)
453 tail = 16;
454
455 len -= 16 + tail;
456 memcpy(nistvector, vector, len);
457 /* flip two last blocks */
458 memcpy(nistvector + len, vector + len + 16, tail);
459 memcpy(nistvector + len + tail, vector + len, 16);
460 len += 16 + tail;
461 tail = 16;
462
463 /* test block-based encryption */
464 memcpy(iv, test_iv, sizeof(test_iv));
465 CRYPTO_nistcts128_encrypt_block(test_input, ciphertext, len, &encks, iv,
466 (block128_f) AES_encrypt);
467 if (memcmp(ciphertext, nistvector, len))
468 fprintf(stderr, "output_%d mismatch\n", len), exit(1);
469 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
470 fprintf(stderr, "iv_%d mismatch\n", len), exit(1);
471
472 /* test block-based decryption */
473 memcpy(iv, test_iv, sizeof(test_iv));
474 CRYPTO_nistcts128_decrypt_block(ciphertext, cleartext, len, &decks, iv,
475 (block128_f) AES_decrypt);
476 if (memcmp(cleartext, test_input, len))
477 fprintf(stderr, "input_%d mismatch\n", len), exit(2);
478 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
479 fprintf(stderr, "iv_%d mismatch\n", len), exit(2);
480
481 /* test streamed encryption */
482 memcpy(iv, test_iv, sizeof(test_iv));
483 CRYPTO_nistcts128_encrypt(test_input, ciphertext, len, &encks, iv,
484 (cbc128_f) AES_cbc_encrypt);
485 if (memcmp(ciphertext, nistvector, len))
486 fprintf(stderr, "output_%d mismatch\n", len), exit(3);
487 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
488 fprintf(stderr, "iv_%d mismatch\n", len), exit(3);
489
490 /* test streamed decryption */
491 memcpy(iv, test_iv, sizeof(test_iv));
492 CRYPTO_nistcts128_decrypt(ciphertext, cleartext, len, &decks, iv,
493 (cbc128_f) AES_cbc_encrypt);
494 if (memcmp(cleartext, test_input, len))
495 fprintf(stderr, "input_%d mismatch\n", len), exit(4);
496 if (memcmp(iv, nistvector + len - tail, sizeof(iv)))
497 fprintf(stderr, "iv_%d mismatch\n", len), exit(4);
67a315b6
AP
498}
499
500int main()
fe150ac2 501{
0f113f3e
MC
502 AES_set_encrypt_key(test_key, 128, &encks);
503 AES_set_decrypt_key(test_key, 128, &decks);
504
505 test_vector(vector_17, sizeof(vector_17));
506 test_vector(vector_31, sizeof(vector_31));
507 test_vector(vector_32, sizeof(vector_32));
508 test_vector(vector_47, sizeof(vector_47));
509 test_vector(vector_48, sizeof(vector_48));
510 test_vector(vector_64, sizeof(vector_64));
511
512 test_nistvector(vector_17, sizeof(vector_17));
513 test_nistvector(vector_31, sizeof(vector_31));
514 test_nistvector(vector_32, sizeof(vector_32));
515 test_nistvector(vector_47, sizeof(vector_47));
516 test_nistvector(vector_48, sizeof(vector_48));
517 test_nistvector(vector_64, sizeof(vector_64));
518
519 return 0;
fe150ac2
AP
520}
521#endif