]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/modes/cts128.c
Remove outdated DEBUG flags.
[thirdparty/openssl.git] / crypto / modes / cts128.c
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
8 #include <openssl/crypto.h>
9 #include "modes_lcl.h"
10 #include <string.h>
11
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
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.
23 */
24
25 size_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;
31
32 if (len <= 16)
33 return 0;
34
35 if ((residue = len % 16) == 0)
36 residue = 16;
37
38 len -= residue;
39
40 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
41
42 in += len;
43 out += len;
44
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);
50
51 return len + residue;
52 }
53
54 size_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;
61
62 if (len < 16)
63 return 0;
64
65 residue = len % 16;
66
67 len -= residue;
68
69 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
70
71 if (residue == 0)
72 return len;
73
74 in += len;
75 out += len;
76
77 for (n = 0; n < residue; ++n)
78 ivec[n] ^= in[n];
79 (*block) (ivec, ivec, key);
80 memcpy(out - 16 + residue, ivec, 16);
81
82 return len + residue;
83 }
84
85 size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out,
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;
94
95 if (len <= 16)
96 return 0;
97
98 if ((residue = len % 16) == 0)
99 residue = 16;
100
101 len -= residue;
102
103 (*cbc) (in, out, len, key, ivec, 1);
104
105 in += len;
106 out += len;
107
108 #if defined(CBC_HANDLES_TRUNCATED_IO)
109 memcpy(tmp.c, out - 16, 16);
110 (*cbc) (in, out - 16, residue, key, ivec, 1);
111 memcpy(out, tmp.c, residue);
112 #else
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);
117 #endif
118 return len + residue;
119 }
120
121 size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out,
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;
130
131 if (len < 16)
132 return 0;
133
134 residue = len % 16;
135
136 len -= residue;
137
138 (*cbc) (in, out, len, key, ivec, 1);
139
140 if (residue == 0)
141 return len;
142
143 in += len;
144 out += len;
145
146 #if defined(CBC_HANDLES_TRUNCATED_IO)
147 (*cbc) (in, out - 16 + residue, residue, key, ivec, 1);
148 #else
149 memset(tmp.c, 0, sizeof(tmp));
150 memcpy(tmp.c, in, residue);
151 (*cbc) (tmp.c, out - 16 + residue, 16, key, ivec, 1);
152 #endif
153 return len + residue;
154 }
155
156 size_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;
166
167 if (len <= 16)
168 return 0;
169
170 if ((residue = len % 16) == 0)
171 residue = 16;
172
173 len -= 16 + residue;
174
175 if (len) {
176 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
177 in += len;
178 out += len;
179 }
180
181 (*block) (in, tmp.c + 16, key);
182
183 memcpy(tmp.c, tmp.c + 16, 16);
184 memcpy(tmp.c, in + 16, residue);
185 (*block) (tmp.c, tmp.c, key);
186
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];
194
195 return 16 + len + residue;
196 }
197
198 size_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;
209
210 if (len < 16)
211 return 0;
212
213 residue = len % 16;
214
215 if (residue == 0) {
216 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
217 return len;
218 }
219
220 len -= 16 + residue;
221
222 if (len) {
223 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
224 in += len;
225 out += len;
226 }
227
228 (*block) (in + residue, tmp.c + 16, key);
229
230 memcpy(tmp.c, tmp.c + 16, 16);
231 memcpy(tmp.c, in, residue);
232 (*block) (tmp.c, tmp.c, key);
233
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];
242
243 return 16 + len + residue;
244 }
245
246 size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out,
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;
255
256 if (len <= 16)
257 return 0;
258
259 if ((residue = len % 16) == 0)
260 residue = 16;
261
262 len -= 16 + residue;
263
264 if (len) {
265 (*cbc) (in, out, len, key, ivec, 0);
266 in += len;
267 out += len;
268 }
269
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);
275
276 memcpy(tmp.c, in + 16, residue);
277 #if defined(CBC_HANDLES_TRUNCATED_IO)
278 (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
279 #else
280 (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
281 memcpy(out, tmp.c, 16 + residue);
282 #endif
283 return 16 + len + residue;
284 }
285
286 size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out,
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;
295
296 if (len < 16)
297 return 0;
298
299 residue = len % 16;
300
301 if (residue == 0) {
302 (*cbc) (in, out, len, key, ivec, 0);
303 return len;
304 }
305
306 len -= 16 + residue;
307
308 if (len) {
309 (*cbc) (in, out, len, key, ivec, 0);
310 in += len;
311 out += len;
312 }
313
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);
319
320 memcpy(tmp.c, in, residue);
321 #if defined(CBC_HANDLES_TRUNCATED_IO)
322 (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
323 #else
324 (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
325 memcpy(out, tmp.c, 16 + residue);
326 #endif
327 return 16 + len + residue;
328 }
329
330 #if defined(SELFTEST)
331 # include <stdio.h>
332 # include <openssl/aes.h>
333
334 /* test vectors from RFC 3962 */
335 static const unsigned char test_key[16] = "chicken teriyaki";
336 static const unsigned char test_input[64] =
337 "I would like the" " General Gau's C"
338 "hicken, please, " "and wonton soup.";
339 static const unsigned char test_iv[16] =
340 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
341
342 static const unsigned char vector_17[17] = {
343 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4,
344 0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f,
345 0x97
346 };
347
348 static const unsigned char vector_31[31] = {
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
355 static const unsigned char vector_32[32] = {
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
362 static const unsigned char vector_47[47] = {
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
371 static const unsigned char vector_48[48] = {
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
380 static const unsigned char vector_64[64] = {
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 };
390
391 static AES_KEY encks, decks;
392
393 void 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);
441 }
442
443 void 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);
498 }
499
500 int main()
501 {
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;
520 }
521 #endif