GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/crypto/../../libssl/src/crypto/modes/cts128.c Lines: 123 123 100.0 %
Date: 2016-12-06 Branches: 44 52 84.6 %

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