urtw: suppress set but not used warnings
[unleashed.git] / lib / libcrypto / modes / cts128.c
blob802aa77cd56139c097f273e32114ee867cd94dee
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.
5 * Rights for redistribution and usage in source and binary
6 * forms are granted according to the OpenSSL license.
7 */
9 #include <openssl/crypto.h>
10 #include "modes_lcl.h"
11 #include <string.h>
13 #ifndef MODES_DEBUG
14 # ifndef NDEBUG
15 # define NDEBUG
16 # endif
17 #endif
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.
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;
37 if (len <= 16) return 0;
39 if ((residue=len%16) == 0) residue = 16;
41 len -= residue;
43 CRYPTO_cbc128_encrypt(in,out,len,key,ivec,block);
45 in += len;
46 out += len;
48 for (n=0; n<residue; ++n)
49 ivec[n] ^= in[n];
50 (*block)(ivec,ivec,key);
51 memcpy(out,out-16,residue);
52 memcpy(out-16,ivec,16);
54 return len+residue;
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;
62 if (len < 16) return 0;
64 residue=len%16;
66 len -= residue;
68 CRYPTO_cbc128_encrypt(in,out,len,key,ivec,block);
70 if (residue==0) return len;
72 in += len;
73 out += len;
75 for (n=0; n<residue; ++n)
76 ivec[n] ^= in[n];
77 (*block)(ivec,ivec,key);
78 memcpy(out-16+residue,ivec,16);
80 return len+residue;
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 union { size_t align; unsigned char c[16]; } tmp;
89 if (len <= 16) return 0;
91 if ((residue=len%16) == 0) residue = 16;
93 len -= residue;
95 (*cbc)(in,out,len,key,ivec,1);
97 in += len;
98 out += len;
100 memset(tmp.c,0,sizeof(tmp));
101 memcpy(tmp.c,in,residue);
102 memcpy(out,out-16,residue);
103 (*cbc)(tmp.c,out-16,16,key,ivec,1);
104 return len+residue;
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 union { size_t align; unsigned char c[16]; } tmp;
113 if (len < 16) return 0;
115 residue=len%16;
117 len -= residue;
119 (*cbc)(in,out,len,key,ivec,1);
121 if (residue==0) return len;
123 in += len;
124 out += len;
126 memset(tmp.c,0,sizeof(tmp));
127 memcpy(tmp.c,in,residue);
128 (*cbc)(tmp.c,out-16+residue,16,key,ivec,1);
129 return len+residue;
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 union { size_t align; unsigned char c[32]; } tmp;
138 if (len<=16) return 0;
140 if ((residue=len%16) == 0) residue = 16;
142 len -= 16+residue;
144 if (len) {
145 CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
146 in += len;
147 out += len;
150 (*block)(in,tmp.c+16,key);
152 memcpy(tmp.c,tmp.c+16,16);
153 memcpy(tmp.c,in+16,residue);
154 (*block)(tmp.c,tmp.c,key);
156 for(n=0; n<16; ++n) {
157 unsigned char c = in[n];
158 out[n] = tmp.c[n] ^ ivec[n];
159 ivec[n] = c;
161 for(residue+=16; n<residue; ++n)
162 out[n] = tmp.c[n] ^ in[n];
164 return 16+len+residue;
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 union { size_t align; unsigned char c[32]; } tmp;
173 if (len<16) return 0;
175 residue=len%16;
177 if (residue==0) {
178 CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
179 return len;
182 len -= 16+residue;
184 if (len) {
185 CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
186 in += len;
187 out += len;
190 (*block)(in+residue,tmp.c+16,key);
192 memcpy(tmp.c,tmp.c+16,16);
193 memcpy(tmp.c,in,residue);
194 (*block)(tmp.c,tmp.c,key);
196 for(n=0; n<16; ++n) {
197 unsigned char c = in[n];
198 out[n] = tmp.c[n] ^ ivec[n];
199 ivec[n] = in[n+residue];
200 tmp.c[n] = c;
202 for(residue+=16; n<residue; ++n)
203 out[n] = tmp.c[n] ^ tmp.c[n-16];
205 return 16+len+residue;
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 union { size_t align; unsigned char c[32]; } tmp;
214 if (len<=16) return 0;
216 if ((residue=len%16) == 0) residue = 16;
218 len -= 16+residue;
220 if (len) {
221 (*cbc)(in,out,len,key,ivec,0);
222 in += len;
223 out += len;
226 memset(tmp.c,0,sizeof(tmp));
227 /* this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] */
228 (*cbc)(in,tmp.c,16,key,tmp.c+16,0);
230 memcpy(tmp.c,in+16,residue);
231 (*cbc)(tmp.c,tmp.c,32,key,ivec,0);
232 memcpy(out,tmp.c,16+residue);
233 return 16+len+residue;
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 union { size_t align; unsigned char c[32]; } tmp;
242 if (len<16) return 0;
244 residue=len%16;
246 if (residue==0) {
247 (*cbc)(in,out,len,key,ivec,0);
248 return len;
251 len -= 16+residue;
253 if (len) {
254 (*cbc)(in,out,len,key,ivec,0);
255 in += len;
256 out += len;
259 memset(tmp.c,0,sizeof(tmp));
260 /* this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] */
261 (*cbc)(in+residue,tmp.c,16,key,tmp.c+16,0);
263 memcpy(tmp.c,in,residue);
264 (*cbc)(tmp.c,tmp.c,32,key,ivec,0);
265 memcpy(out,tmp.c,16+residue);
266 return 16+len+residue;