GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/modes/cts128.c Lines: 133 133 100.0 %
Date: 2017-11-07 Branches: 36 44 81.8 %

Line Branch Exec Source
1
/* $OpenBSD: cts128.c,v 1.5 2015/07/19 18:27:26 miod Exp $ */
2
/* ====================================================================
3
 * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
4
 *
5
 * Rights for redistribution and usage in source and binary
6
 * forms are granted according to the OpenSSL license.
7
 */
8
9
#include <openssl/crypto.h>
10
#include "modes_lcl.h"
11
#include <string.h>
12
13
#ifndef MODES_DEBUG
14
# ifndef NDEBUG
15
#  define NDEBUG
16
# endif
17
#endif
18
19
/*
20
 * Trouble with Ciphertext Stealing, CTS, mode is that there is no
21
 * common official specification, but couple of cipher/application
22
 * specific ones: RFC2040 and RFC3962. Then there is 'Proposal to
23
 * Extend CBC Mode By "Ciphertext Stealing"' at NIST site, which
24
 * deviates from mentioned RFCs. Most notably it allows input to be
25
 * of block length and it doesn't flip the order of the last two
26
 * blocks. CTS is being discussed even in ECB context, but it's not
27
 * adopted for any known application. This implementation provides
28
 * two interfaces: one compliant with above mentioned RFCs and one
29
 * compliant with the NIST proposal, both extending CBC mode.
30
 */
31
32
size_t CRYPTO_cts128_encrypt_block(const unsigned char *in, unsigned char *out,
33
			size_t len, const void *key,
34
			unsigned char ivec[16], block128_f block)
35
{	size_t residue, n;
36
37
72
	if (len <= 16) return 0;
38
39
36
	if ((residue=len%16) == 0) residue = 16;
40
41
36
	len -= residue;
42
43
36
	CRYPTO_cbc128_encrypt(in,out,len,key,ivec,block);
44
45
36
	in  += len;
46
36
	out += len;
47
48
1020
	for (n=0; n<residue; ++n)
49
474
		ivec[n] ^= in[n];
50
36
	(*block)(ivec,ivec,key);
51
36
	memcpy(out,out-16,residue);
52
36
	memcpy(out-16,ivec,16);
53
54
36
	return len+residue;
55
36
}
56
57
size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in, unsigned char *out,
58
			size_t len, const void *key,
59
			unsigned char ivec[16], block128_f block)
60
{	size_t residue, n;
61
62
72
	if (len < 16) return 0;
63
64
36
	residue=len%16;
65
66
36
	len -= residue;
67
68
36
	CRYPTO_cbc128_encrypt(in,out,len,key,ivec,block);
69
70
54
	if (residue==0)	return len;
71
72
18
	in  += len;
73
18
	out += len;
74
75
408
	for (n=0; n<residue; ++n)
76
186
		ivec[n] ^= in[n];
77
18
	(*block)(ivec,ivec,key);
78
18
	memcpy(out-16+residue,ivec,16);
79
80
18
	return len+residue;
81
36
}
82
83
size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out,
84
			size_t len, const void *key,
85
			unsigned char ivec[16], cbc128_f cbc)
86
{	size_t residue;
87
72
	union { size_t align; unsigned char c[16]; } tmp;
88
89
36
	if (len <= 16) return 0;
90
91
36
	if ((residue=len%16) == 0) residue = 16;
92
93
36
	len -= residue;
94
95
36
	(*cbc)(in,out,len,key,ivec,1);
96
97
36
	in  += len;
98
36
	out += len;
99
100
36
	memset(tmp.c,0,sizeof(tmp));
101
36
	memcpy(tmp.c,in,residue);
102
36
	memcpy(out,out-16,residue);
103
36
	(*cbc)(tmp.c,out-16,16,key,ivec,1);
104
36
	return len+residue;
105
36
}
106
107
size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out,
108
			size_t len, const void *key,
109
			unsigned char ivec[16], cbc128_f cbc)
110
{	size_t residue;
111
72
	union { size_t align; unsigned char c[16]; } tmp;
112
113
36
	if (len < 16) return 0;
114
115
36
	residue=len%16;
116
117
36
	len -= residue;
118
119
36
	(*cbc)(in,out,len,key,ivec,1);
120
121
54
	if (residue==0) return len;
122
123
18
	in  += len;
124
18
	out += len;
125
126
18
	memset(tmp.c,0,sizeof(tmp));
127
18
	memcpy(tmp.c,in,residue);
128
18
	(*cbc)(tmp.c,out-16+residue,16,key,ivec,1);
129
18
	return len+residue;
130
36
}
131
132
size_t CRYPTO_cts128_decrypt_block(const unsigned char *in, unsigned char *out,
133
			size_t len, const void *key,
134
			unsigned char ivec[16], block128_f block)
135
{	size_t residue, n;
136
72
	union { size_t align; unsigned char c[32]; } tmp;
137
138
36
	if (len<=16) return 0;
139
140
36
	if ((residue=len%16) == 0) residue = 16;
141
142
36
	len -= 16+residue;
143
144
36
	if (len) {
145
18
		CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
146
18
		in  += len;
147
18
		out += len;
148
18
	}
149
150
36
	(*block)(in,tmp.c+16,key);
151
152
36
	memcpy(tmp.c,tmp.c+16,16);
153
36
	memcpy(tmp.c,in+16,residue);
154
36
	(*block)(tmp.c,tmp.c,key);
155
156
1224
	for(n=0; n<16; ++n) {
157
576
		unsigned char c = in[n];
158
576
		out[n] = tmp.c[n] ^ ivec[n];
159
576
		ivec[n] = c;
160
	}
161
1020
	for(residue+=16; n<residue; ++n)
162
474
		out[n] = tmp.c[n] ^ in[n];
163
164
36
	return 16+len+residue;
165
36
}
166
167
size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in, unsigned char *out,
168
			size_t len, const void *key,
169
			unsigned char ivec[16], block128_f block)
170
{	size_t residue, n;
171
72
	union { size_t align; unsigned char c[32]; } tmp;
172
173
36
	if (len<16) return 0;
174
175
36
	residue=len%16;
176
177
36
	if (residue==0) {
178
18
		CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
179
18
		return len;
180
	}
181
182
18
	len -= 16+residue;
183
184
18
	if (len) {
185
6
		CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
186
6
		in  += len;
187
6
		out += len;
188
6
	}
189
190
18
	(*block)(in+residue,tmp.c+16,key);
191
192
18
	memcpy(tmp.c,tmp.c+16,16);
193
18
	memcpy(tmp.c,in,residue);
194
18
	(*block)(tmp.c,tmp.c,key);
195
196
612
	for(n=0; n<16; ++n) {
197
288
		unsigned char c = in[n];
198
288
		out[n] = tmp.c[n] ^ ivec[n];
199
288
		ivec[n] = in[n+residue];
200
288
		tmp.c[n] = c;
201
	}
202
408
	for(residue+=16; n<residue; ++n)
203
186
		out[n] = tmp.c[n] ^ tmp.c[n-16];
204
205
18
	return 16+len+residue;
206
36
}
207
208
size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out,
209
			size_t len, const void *key,
210
			unsigned char ivec[16], cbc128_f cbc)
211
{	size_t residue;
212
72
	union { size_t align; unsigned char c[32]; } tmp;
213
214
36
	if (len<=16) return 0;
215
216
36
	if ((residue=len%16) == 0) residue = 16;
217
218
36
	len -= 16+residue;
219
220
36
	if (len) {
221
18
		(*cbc)(in,out,len,key,ivec,0);
222
18
		in  += len;
223
18
		out += len;
224
18
	}
225
226
36
	memset(tmp.c,0,sizeof(tmp));
227
	/* this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] */
228
36
	(*cbc)(in,tmp.c,16,key,tmp.c+16,0);
229
230
36
	memcpy(tmp.c,in+16,residue);
231
36
	(*cbc)(tmp.c,tmp.c,32,key,ivec,0);
232
36
	memcpy(out,tmp.c,16+residue);
233
36
	return 16+len+residue;
234
36
}
235
236
size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out,
237
			size_t len, const void *key,
238
			unsigned char ivec[16], cbc128_f cbc)
239
{	size_t residue;
240
72
	union { size_t align; unsigned char c[32]; } tmp;
241
242
36
	if (len<16) return 0;
243
244
36
	residue=len%16;
245
246
36
	if (residue==0) {
247
18
		(*cbc)(in,out,len,key,ivec,0);
248
18
		return len;
249
	}
250
251
18
	len -= 16+residue;
252
253
18
	if (len) {
254
6
		(*cbc)(in,out,len,key,ivec,0);
255
6
		in  += len;
256
6
		out += len;
257
6
	}
258
259
18
	memset(tmp.c,0,sizeof(tmp));
260
	/* this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] */
261
18
	(*cbc)(in+residue,tmp.c,16,key,tmp.c+16,0);
262
263
18
	memcpy(tmp.c,in,residue);
264
18
	(*cbc)(tmp.c,tmp.c,32,key,ivec,0);
265
18
	memcpy(out,tmp.c,16+residue);
266
18
	return 16+len+residue;
267
36
}