GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/modes/cts128.c Lines: 133 133 100.0 %
Date: 2017-11-13 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
36
	if (len <= 16) return 0;
38
39
18
	if ((residue=len%16) == 0) residue = 16;
40
41
18
	len -= residue;
42
43
18
	CRYPTO_cbc128_encrypt(in,out,len,key,ivec,block);
44
45
18
	in  += len;
46
18
	out += len;
47
48
510
	for (n=0; n<residue; ++n)
49
237
		ivec[n] ^= in[n];
50
18
	(*block)(ivec,ivec,key);
51
18
	memcpy(out,out-16,residue);
52
18
	memcpy(out-16,ivec,16);
53
54
18
	return len+residue;
55
18
}
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
36
	if (len < 16) return 0;
63
64
18
	residue=len%16;
65
66
18
	len -= residue;
67
68
18
	CRYPTO_cbc128_encrypt(in,out,len,key,ivec,block);
69
70
27
	if (residue==0)	return len;
71
72
9
	in  += len;
73
9
	out += len;
74
75
204
	for (n=0; n<residue; ++n)
76
93
		ivec[n] ^= in[n];
77
9
	(*block)(ivec,ivec,key);
78
9
	memcpy(out-16+residue,ivec,16);
79
80
9
	return len+residue;
81
18
}
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
36
	union { size_t align; unsigned char c[16]; } tmp;
88
89
18
	if (len <= 16) return 0;
90
91
18
	if ((residue=len%16) == 0) residue = 16;
92
93
18
	len -= residue;
94
95
18
	(*cbc)(in,out,len,key,ivec,1);
96
97
18
	in  += len;
98
18
	out += len;
99
100
18
	memset(tmp.c,0,sizeof(tmp));
101
18
	memcpy(tmp.c,in,residue);
102
18
	memcpy(out,out-16,residue);
103
18
	(*cbc)(tmp.c,out-16,16,key,ivec,1);
104
18
	return len+residue;
105
18
}
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
36
	union { size_t align; unsigned char c[16]; } tmp;
112
113
18
	if (len < 16) return 0;
114
115
18
	residue=len%16;
116
117
18
	len -= residue;
118
119
18
	(*cbc)(in,out,len,key,ivec,1);
120
121
27
	if (residue==0) return len;
122
123
9
	in  += len;
124
9
	out += len;
125
126
9
	memset(tmp.c,0,sizeof(tmp));
127
9
	memcpy(tmp.c,in,residue);
128
9
	(*cbc)(tmp.c,out-16+residue,16,key,ivec,1);
129
9
	return len+residue;
130
18
}
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
36
	union { size_t align; unsigned char c[32]; } tmp;
137
138
18
	if (len<=16) return 0;
139
140
18
	if ((residue=len%16) == 0) residue = 16;
141
142
18
	len -= 16+residue;
143
144
18
	if (len) {
145
9
		CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
146
9
		in  += len;
147
9
		out += len;
148
9
	}
149
150
18
	(*block)(in,tmp.c+16,key);
151
152
18
	memcpy(tmp.c,tmp.c+16,16);
153
18
	memcpy(tmp.c,in+16,residue);
154
18
	(*block)(tmp.c,tmp.c,key);
155
156
612
	for(n=0; n<16; ++n) {
157
288
		unsigned char c = in[n];
158
288
		out[n] = tmp.c[n] ^ ivec[n];
159
288
		ivec[n] = c;
160
	}
161
510
	for(residue+=16; n<residue; ++n)
162
237
		out[n] = tmp.c[n] ^ in[n];
163
164
18
	return 16+len+residue;
165
18
}
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
36
	union { size_t align; unsigned char c[32]; } tmp;
172
173
18
	if (len<16) return 0;
174
175
18
	residue=len%16;
176
177
18
	if (residue==0) {
178
9
		CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
179
9
		return len;
180
	}
181
182
9
	len -= 16+residue;
183
184
9
	if (len) {
185
3
		CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
186
3
		in  += len;
187
3
		out += len;
188
3
	}
189
190
9
	(*block)(in+residue,tmp.c+16,key);
191
192
9
	memcpy(tmp.c,tmp.c+16,16);
193
9
	memcpy(tmp.c,in,residue);
194
9
	(*block)(tmp.c,tmp.c,key);
195
196
306
	for(n=0; n<16; ++n) {
197
144
		unsigned char c = in[n];
198
144
		out[n] = tmp.c[n] ^ ivec[n];
199
144
		ivec[n] = in[n+residue];
200
144
		tmp.c[n] = c;
201
	}
202
204
	for(residue+=16; n<residue; ++n)
203
93
		out[n] = tmp.c[n] ^ tmp.c[n-16];
204
205
9
	return 16+len+residue;
206
18
}
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
36
	union { size_t align; unsigned char c[32]; } tmp;
213
214
18
	if (len<=16) return 0;
215
216
18
	if ((residue=len%16) == 0) residue = 16;
217
218
18
	len -= 16+residue;
219
220
18
	if (len) {
221
9
		(*cbc)(in,out,len,key,ivec,0);
222
9
		in  += len;
223
9
		out += len;
224
9
	}
225
226
18
	memset(tmp.c,0,sizeof(tmp));
227
	/* this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] */
228
18
	(*cbc)(in,tmp.c,16,key,tmp.c+16,0);
229
230
18
	memcpy(tmp.c,in+16,residue);
231
18
	(*cbc)(tmp.c,tmp.c,32,key,ivec,0);
232
18
	memcpy(out,tmp.c,16+residue);
233
18
	return 16+len+residue;
234
18
}
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
36
	union { size_t align; unsigned char c[32]; } tmp;
241
242
18
	if (len<16) return 0;
243
244
18
	residue=len%16;
245
246
18
	if (residue==0) {
247
9
		(*cbc)(in,out,len,key,ivec,0);
248
9
		return len;
249
	}
250
251
9
	len -= 16+residue;
252
253
9
	if (len) {
254
3
		(*cbc)(in,out,len,key,ivec,0);
255
3
		in  += len;
256
3
		out += len;
257
3
	}
258
259
9
	memset(tmp.c,0,sizeof(tmp));
260
	/* this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] */
261
9
	(*cbc)(in+residue,tmp.c,16,key,tmp.c+16,0);
262
263
9
	memcpy(tmp.c,in,residue);
264
9
	(*cbc)(tmp.c,tmp.c,32,key,ivec,0);
265
9
	memcpy(out,tmp.c,16+residue);
266
9
	return 16+len+residue;
267
18
}