]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/modes/cts128.c
Following the license change, modify the boilerplates in crypto/modes/
[thirdparty/openssl.git] / crypto / modes / cts128.c
CommitLineData
4f22f405
RS
1/*
2 * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
fe150ac2 3 *
81cae8ce 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
4f22f405
RS
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
fe150ac2
AP
8 */
9
a3654f05 10#include <openssl/crypto.h>
f472ec8c 11#include "modes_lcl.h"
fe150ac2
AP
12#include <string.h>
13
fe150ac2
AP
14/*
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
67a315b6
AP
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.
fe150ac2
AP
25 */
26
0f113f3e
MC
27size_t CRYPTO_cts128_encrypt_block(const unsigned char *in,
28 unsigned char *out, size_t len,
29 const void *key, unsigned char ivec[16],
30 block128_f block)
31{
32 size_t residue, n;
fe150ac2 33
0f113f3e
MC
34 if (len <= 16)
35 return 0;
fe150ac2 36
0f113f3e
MC
37 if ((residue = len % 16) == 0)
38 residue = 16;
fe150ac2 39
0f113f3e 40 len -= residue;
fe150ac2 41
0f113f3e 42 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
fe150ac2 43
0f113f3e
MC
44 in += len;
45 out += len;
fe150ac2 46
0f113f3e
MC
47 for (n = 0; n < residue; ++n)
48 ivec[n] ^= in[n];
49 (*block) (ivec, ivec, key);
50 memcpy(out, out - 16, residue);
51 memcpy(out - 16, ivec, 16);
fe150ac2 52
0f113f3e 53 return len + residue;
fe150ac2
AP
54}
55
0f113f3e
MC
56size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in,
57 unsigned char *out, size_t len,
58 const void *key,
59 unsigned char ivec[16],
60 block128_f block)
61{
62 size_t residue, n;
67a315b6 63
0f113f3e
MC
64 if (len < 16)
65 return 0;
67a315b6 66
0f113f3e 67 residue = len % 16;
67a315b6 68
0f113f3e 69 len -= residue;
67a315b6 70
0f113f3e 71 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
67a315b6 72
0f113f3e
MC
73 if (residue == 0)
74 return len;
67a315b6 75
0f113f3e
MC
76 in += len;
77 out += len;
67a315b6 78
0f113f3e
MC
79 for (n = 0; n < residue; ++n)
80 ivec[n] ^= in[n];
81 (*block) (ivec, ivec, key);
82 memcpy(out - 16 + residue, ivec, 16);
67a315b6 83
0f113f3e 84 return len + residue;
67a315b6
AP
85}
86
fe150ac2 87size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out,
0f113f3e
MC
88 size_t len, const void *key,
89 unsigned char ivec[16], cbc128_f cbc)
90{
91 size_t residue;
92 union {
93 size_t align;
94 unsigned char c[16];
95 } tmp;
fe150ac2 96
0f113f3e
MC
97 if (len <= 16)
98 return 0;
fe150ac2 99
0f113f3e
MC
100 if ((residue = len % 16) == 0)
101 residue = 16;
fe150ac2 102
0f113f3e 103 len -= residue;
fe150ac2 104
0f113f3e 105 (*cbc) (in, out, len, key, ivec, 1);
fe150ac2 106
0f113f3e
MC
107 in += len;
108 out += len;
fe150ac2
AP
109
110#if defined(CBC_HANDLES_TRUNCATED_IO)
0f113f3e
MC
111 memcpy(tmp.c, out - 16, 16);
112 (*cbc) (in, out - 16, residue, key, ivec, 1);
113 memcpy(out, tmp.c, residue);
fe150ac2 114#else
0f113f3e
MC
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);
fe150ac2 119#endif
0f113f3e 120 return len + residue;
fe150ac2
AP
121}
122
67a315b6 123size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out,
0f113f3e
MC
124 size_t len, const void *key,
125 unsigned char ivec[16], cbc128_f cbc)
126{
127 size_t residue;
128 union {
129 size_t align;
130 unsigned char c[16];
131 } tmp;
67a315b6 132
0f113f3e
MC
133 if (len < 16)
134 return 0;
67a315b6 135
0f113f3e 136 residue = len % 16;
67a315b6 137
0f113f3e 138 len -= residue;
67a315b6 139
0f113f3e 140 (*cbc) (in, out, len, key, ivec, 1);
67a315b6 141
0f113f3e
MC
142 if (residue == 0)
143 return len;
67a315b6 144
0f113f3e
MC
145 in += len;
146 out += len;
67a315b6
AP
147
148#if defined(CBC_HANDLES_TRUNCATED_IO)
0f113f3e 149 (*cbc) (in, out - 16 + residue, residue, key, ivec, 1);
67a315b6 150#else
0f113f3e
MC
151 memset(tmp.c, 0, sizeof(tmp));
152 memcpy(tmp.c, in, residue);
153 (*cbc) (tmp.c, out - 16 + residue, 16, key, ivec, 1);
67a315b6 154#endif
0f113f3e 155 return len + residue;
67a315b6
AP
156}
157
0f113f3e
MC
158size_t CRYPTO_cts128_decrypt_block(const unsigned char *in,
159 unsigned char *out, size_t len,
160 const void *key, unsigned char ivec[16],
161 block128_f block)
162{
163 size_t residue, n;
164 union {
165 size_t align;
166 unsigned char c[32];
167 } tmp;
fe150ac2 168
0f113f3e
MC
169 if (len <= 16)
170 return 0;
fe150ac2 171
0f113f3e
MC
172 if ((residue = len % 16) == 0)
173 residue = 16;
fe150ac2 174
0f113f3e 175 len -= 16 + residue;
fe150ac2 176
0f113f3e
MC
177 if (len) {
178 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
179 in += len;
180 out += len;
181 }
fe150ac2 182
0f113f3e 183 (*block) (in, tmp.c + 16, key);
fe150ac2 184
0f113f3e
MC
185 memcpy(tmp.c, tmp.c + 16, 16);
186 memcpy(tmp.c, in + 16, residue);
187 (*block) (tmp.c, tmp.c, key);
fe150ac2 188
0f113f3e
MC
189 for (n = 0; n < 16; ++n) {
190 unsigned char c = in[n];
191 out[n] = tmp.c[n] ^ ivec[n];
192 ivec[n] = c;
193 }
194 for (residue += 16; n < residue; ++n)
195 out[n] = tmp.c[n] ^ in[n];
fe150ac2 196
0f113f3e 197 return 16 + len + residue;
67a315b6
AP
198}
199
0f113f3e
MC
200size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in,
201 unsigned char *out, size_t len,
202 const void *key,
203 unsigned char ivec[16],
204 block128_f block)
205{
206 size_t residue, n;
207 union {
208 size_t align;
209 unsigned char c[32];
210 } tmp;
67a315b6 211
0f113f3e
MC
212 if (len < 16)
213 return 0;
67a315b6 214
0f113f3e 215 residue = len % 16;
67a315b6 216
0f113f3e
MC
217 if (residue == 0) {
218 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
219 return len;
220 }
67a315b6 221
0f113f3e 222 len -= 16 + residue;
67a315b6 223
0f113f3e
MC
224 if (len) {
225 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
226 in += len;
227 out += len;
228 }
67a315b6 229
0f113f3e 230 (*block) (in + residue, tmp.c + 16, key);
67a315b6 231
0f113f3e
MC
232 memcpy(tmp.c, tmp.c + 16, 16);
233 memcpy(tmp.c, in, residue);
234 (*block) (tmp.c, tmp.c, key);
67a315b6 235
0f113f3e
MC
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];
240 tmp.c[n] = c;
241 }
242 for (residue += 16; n < residue; ++n)
243 out[n] = tmp.c[n] ^ tmp.c[n - 16];
67a315b6 244
0f113f3e 245 return 16 + len + residue;
fe150ac2
AP
246}
247
248size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out,
0f113f3e
MC
249 size_t len, const void *key,
250 unsigned char ivec[16], cbc128_f cbc)
251{
252 size_t residue;
253 union {
254 size_t align;
255 unsigned char c[32];
256 } tmp;
fe150ac2 257
0f113f3e
MC
258 if (len <= 16)
259 return 0;
fe150ac2 260
0f113f3e
MC
261 if ((residue = len % 16) == 0)
262 residue = 16;
fe150ac2 263
0f113f3e 264 len -= 16 + residue;
fe150ac2 265
0f113f3e
MC
266 if (len) {
267 (*cbc) (in, out, len, key, ivec, 0);
268 in += len;
269 out += len;
270 }
fe150ac2 271
0f113f3e
MC
272 memset(tmp.c, 0, sizeof(tmp));
273 /*
274 * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
275 */
276 (*cbc) (in, tmp.c, 16, key, tmp.c + 16, 0);
fe150ac2 277
0f113f3e 278 memcpy(tmp.c, in + 16, residue);
fe150ac2 279#if defined(CBC_HANDLES_TRUNCATED_IO)
0f113f3e 280 (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
fe150ac2 281#else
0f113f3e
MC
282 (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
283 memcpy(out, tmp.c, 16 + residue);
fe150ac2 284#endif
0f113f3e 285 return 16 + len + residue;
67a315b6
AP
286}
287
288size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out,
0f113f3e
MC
289 size_t len, const void *key,
290 unsigned char ivec[16], cbc128_f cbc)
291{
292 size_t residue;
293 union {
294 size_t align;
295 unsigned char c[32];
296 } tmp;
67a315b6 297
0f113f3e
MC
298 if (len < 16)
299 return 0;
67a315b6 300
0f113f3e 301 residue = len % 16;
67a315b6 302
0f113f3e
MC
303 if (residue == 0) {
304 (*cbc) (in, out, len, key, ivec, 0);
305 return len;
306 }
67a315b6 307
0f113f3e 308 len -= 16 + residue;
67a315b6 309
0f113f3e
MC
310 if (len) {
311 (*cbc) (in, out, len, key, ivec, 0);
312 in += len;
313 out += len;
314 }
67a315b6 315
0f113f3e
MC
316 memset(tmp.c, 0, sizeof(tmp));
317 /*
318 * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
319 */
320 (*cbc) (in + residue, tmp.c, 16, key, tmp.c + 16, 0);
67a315b6 321
0f113f3e 322 memcpy(tmp.c, in, residue);
67a315b6 323#if defined(CBC_HANDLES_TRUNCATED_IO)
0f113f3e 324 (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
67a315b6 325#else
0f113f3e
MC
326 (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
327 memcpy(out, tmp.c, 16 + residue);
67a315b6 328#endif
0f113f3e 329 return 16 + len + residue;
fe150ac2 330}