]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/modes/cts128.c
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>
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.
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],
35 if ((residue
= len
% 16) == 0)
40 CRYPTO_cbc128_encrypt(in
, out
, len
, key
, ivec
, block
);
45 for (n
= 0; n
< residue
; ++n
)
47 (*block
) (ivec
, ivec
, key
);
48 memcpy(out
, out
- 16, residue
);
49 memcpy(out
- 16, ivec
, 16);
54 size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in
,
55 unsigned char *out
, size_t len
,
57 unsigned char ivec
[16],
69 CRYPTO_cbc128_encrypt(in
, out
, len
, key
, ivec
, block
);
77 for (n
= 0; n
< residue
; ++n
)
79 (*block
) (ivec
, ivec
, key
);
80 memcpy(out
- 16 + residue
, ivec
, 16);
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
)
98 if ((residue
= len
% 16) == 0)
103 (*cbc
) (in
, out
, len
, key
, ivec
, 1);
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
);
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);
118 return len
+ residue
;
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
)
138 (*cbc
) (in
, out
, len
, key
, ivec
, 1);
146 #if defined(CBC_HANDLES_TRUNCATED_IO)
147 (*cbc
) (in
, out
- 16 + residue
, residue
, key
, ivec
, 1);
149 memset(tmp
.c
, 0, sizeof(tmp
));
150 memcpy(tmp
.c
, in
, residue
);
151 (*cbc
) (tmp
.c
, out
- 16 + residue
, 16, key
, ivec
, 1);
153 return len
+ residue
;
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],
170 if ((residue
= len
% 16) == 0)
176 CRYPTO_cbc128_decrypt(in
, out
, len
, key
, ivec
, block
);
181 (*block
) (in
, tmp
.c
+ 16, key
);
183 memcpy(tmp
.c
, tmp
.c
+ 16, 16);
184 memcpy(tmp
.c
, in
+ 16, residue
);
185 (*block
) (tmp
.c
, tmp
.c
, key
);
187 for (n
= 0; n
< 16; ++n
) {
188 unsigned char c
= in
[n
];
189 out
[n
] = tmp
.c
[n
] ^ ivec
[n
];
192 for (residue
+= 16; n
< residue
; ++n
)
193 out
[n
] = tmp
.c
[n
] ^ in
[n
];
195 return 16 + len
+ residue
;
198 size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in
,
199 unsigned char *out
, size_t len
,
201 unsigned char ivec
[16],
216 CRYPTO_cbc128_decrypt(in
, out
, len
, key
, ivec
, block
);
223 CRYPTO_cbc128_decrypt(in
, out
, len
, key
, ivec
, block
);
228 (*block
) (in
+ residue
, tmp
.c
+ 16, key
);
230 memcpy(tmp
.c
, tmp
.c
+ 16, 16);
231 memcpy(tmp
.c
, in
, residue
);
232 (*block
) (tmp
.c
, tmp
.c
, key
);
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
];
240 for (residue
+= 16; n
< residue
; ++n
)
241 out
[n
] = tmp
.c
[n
] ^ tmp
.c
[n
- 16];
243 return 16 + len
+ residue
;
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
)
259 if ((residue
= len
% 16) == 0)
265 (*cbc
) (in
, out
, len
, key
, ivec
, 0);
270 memset(tmp
.c
, 0, sizeof(tmp
));
272 * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
274 (*cbc
) (in
, tmp
.c
, 16, key
, tmp
.c
+ 16, 0);
276 memcpy(tmp
.c
, in
+ 16, residue
);
277 #if defined(CBC_HANDLES_TRUNCATED_IO)
278 (*cbc
) (tmp
.c
, out
, 16 + residue
, key
, ivec
, 0);
280 (*cbc
) (tmp
.c
, tmp
.c
, 32, key
, ivec
, 0);
281 memcpy(out
, tmp
.c
, 16 + residue
);
283 return 16 + len
+ residue
;
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
)
302 (*cbc
) (in
, out
, len
, key
, ivec
, 0);
309 (*cbc
) (in
, out
, len
, key
, ivec
, 0);
314 memset(tmp
.c
, 0, sizeof(tmp
));
316 * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
318 (*cbc
) (in
+ residue
, tmp
.c
, 16, key
, tmp
.c
+ 16, 0);
320 memcpy(tmp
.c
, in
, residue
);
321 #if defined(CBC_HANDLES_TRUNCATED_IO)
322 (*cbc
) (tmp
.c
, out
, 16 + residue
, key
, ivec
, 0);
324 (*cbc
) (tmp
.c
, tmp
.c
, 32, key
, ivec
, 0);
325 memcpy(out
, tmp
.c
, 16 + residue
);
327 return 16 + len
+ residue
;
330 #if defined(SELFTEST)
332 # include <openssl/aes.h>
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 };
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,
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
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
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
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
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
391 static AES_KEY encks
, decks
;
393 void test_vector(const unsigned char *vector
, size_t len
)
395 unsigned char iv
[sizeof(test_iv
)];
396 unsigned char cleartext
[64], ciphertext
[64];
399 printf("vector_%d\n", len
);
402 if ((tail
= len
% 16) == 0)
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);
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);
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);
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);
443 void test_nistvector(const unsigned char *vector
, size_t len
)
445 unsigned char iv
[sizeof(test_iv
)];
446 unsigned char cleartext
[64], ciphertext
[64], nistvector
[64];
449 printf("nistvector_%d\n", len
);
452 if ((tail
= len
% 16) == 0)
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);
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);
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);
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);
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);
502 AES_set_encrypt_key(test_key
, 128, &encks
);
503 AES_set_decrypt_key(test_key
, 128, &decks
);
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
));
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
));