1 /* crypto/camellia/camellia_cbc.c -*- mode:C; c-file-style: "eay" -*- */
2 /* ====================================================================
3  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    openssl-core@openssl.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  */
51 
52 #ifndef CAMELLIA_DEBUG
53 # ifndef NDEBUG
54 #  define NDEBUG
55 # endif
56 #endif
57 #include <assert.h>
58 #include <stdio.h>
59 #include <string.h>
60 
61 #include <openssl/camellia.h>
62 #include "cmll_locl.h"
63 
Camellia_cbc_encrypt(const unsigned char * in,unsigned char * out,const unsigned long length,const CAMELLIA_KEY * key,unsigned char * ivec,const int enc)64 void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out,
65 		     const unsigned long length, const CAMELLIA_KEY *key,
66 		     unsigned char *ivec, const int enc) {
67 
68 	unsigned long n;
69 	unsigned long len = length;
70 	const unsigned char *iv = ivec;
71 	union {	u32 t32[CAMELLIA_BLOCK_SIZE/sizeof(u32)];
72 		u8  t8 [CAMELLIA_BLOCK_SIZE]; } tmp;
73 	const union { long one; char little; } camellia_endian = {1};
74 
75 
76 	assert(in && out && key && ivec);
77 	assert((CAMELLIA_ENCRYPT == enc)||(CAMELLIA_DECRYPT == enc));
78 
79 	if(((size_t)in|(size_t)out|(size_t)ivec) % sizeof(u32) == 0)
80 		{
81 		if (CAMELLIA_ENCRYPT == enc)
82 			{
83 			while (len >= CAMELLIA_BLOCK_SIZE)
84 				{
85 				XOR4WORD2((u32 *)out,
86 					(u32 *)in, (u32 *)iv);
87 				if (camellia_endian.little)
88 					SWAP4WORD((u32 *)out);
89 				key->enc(key->rd_key, (u32 *)out);
90 				if (camellia_endian.little)
91 					SWAP4WORD((u32 *)out);
92 				iv = out;
93 				len -= CAMELLIA_BLOCK_SIZE;
94 				in += CAMELLIA_BLOCK_SIZE;
95 				out += CAMELLIA_BLOCK_SIZE;
96 				}
97 			if (len)
98 				{
99 				for(n=0; n < len; ++n)
100 					out[n] = in[n] ^ iv[n];
101 				for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
102 					out[n] = iv[n];
103 				if (camellia_endian.little)
104 					SWAP4WORD((u32 *)out);
105 				key->enc(key->rd_key, (u32 *)out);
106 				if (camellia_endian.little)
107 					SWAP4WORD((u32 *)out);
108 				iv = out;
109 				}
110 			memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
111 			}
112 		else if (in != out)
113 			{
114 			while (len >= CAMELLIA_BLOCK_SIZE)
115 				{
116 				memcpy(out,in,CAMELLIA_BLOCK_SIZE);
117 				if (camellia_endian.little)
118 					SWAP4WORD((u32 *)out);
119 				key->dec(key->rd_key,(u32 *)out);
120 				if (camellia_endian.little)
121 					SWAP4WORD((u32 *)out);
122 				XOR4WORD((u32 *)out, (u32 *)iv);
123 				iv = in;
124 				len -= CAMELLIA_BLOCK_SIZE;
125 				in  += CAMELLIA_BLOCK_SIZE;
126 				out += CAMELLIA_BLOCK_SIZE;
127 				}
128 			if (len)
129 				{
130 				memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
131 				if (camellia_endian.little)
132 					SWAP4WORD(tmp.t32);
133 				key->dec(key->rd_key, tmp.t32);
134 				if (camellia_endian.little)
135 					SWAP4WORD(tmp.t32);
136 				for(n=0; n < len; ++n)
137 					out[n] = tmp.t8[n] ^ iv[n];
138 				iv = in;
139 				}
140 			memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
141 			}
142 		else /* in == out */
143 			{
144 			while (len >= CAMELLIA_BLOCK_SIZE)
145 				{
146 				memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
147 				if (camellia_endian.little)
148 					SWAP4WORD((u32 *)out);
149 				key->dec(key->rd_key, (u32 *)out);
150 				if (camellia_endian.little)
151 					SWAP4WORD((u32 *)out);
152 				XOR4WORD((u32 *)out, (u32 *)ivec);
153 				memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE);
154 				len -= CAMELLIA_BLOCK_SIZE;
155 				in += CAMELLIA_BLOCK_SIZE;
156 				out += CAMELLIA_BLOCK_SIZE;
157 				}
158 			if (len)
159 				{
160 				memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
161 				if (camellia_endian.little)
162 					SWAP4WORD((u32 *)out);
163 				key->dec(key->rd_key,(u32 *)out);
164 				if (camellia_endian.little)
165 					SWAP4WORD((u32 *)out);
166 				for(n=0; n < len; ++n)
167 					out[n] ^= ivec[n];
168 				for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
169 					out[n] = tmp.t8[n];
170 				memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE);
171 				}
172 			}
173 		}
174 	else /* no aligned */
175 		{
176 		if (CAMELLIA_ENCRYPT == enc)
177 			{
178 			while (len >= CAMELLIA_BLOCK_SIZE)
179 				{
180 				for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
181 					tmp.t8[n] = in[n] ^ iv[n];
182 				if (camellia_endian.little)
183 					SWAP4WORD(tmp.t32);
184 				key->enc(key->rd_key, tmp.t32);
185 				if (camellia_endian.little)
186 					SWAP4WORD(tmp.t32);
187 				memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
188 				iv = out;
189 				len -= CAMELLIA_BLOCK_SIZE;
190 				in += CAMELLIA_BLOCK_SIZE;
191 				out += CAMELLIA_BLOCK_SIZE;
192 				}
193 			if (len)
194 				{
195 				for(n=0; n < len; ++n)
196 					tmp.t8[n] = in[n] ^ iv[n];
197 				for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
198 					tmp.t8[n] = iv[n];
199 				if (camellia_endian.little)
200 					SWAP4WORD(tmp.t32);
201 				key->enc(key->rd_key, tmp.t32);
202 				if (camellia_endian.little)
203 					SWAP4WORD(tmp.t32);
204 				memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
205 				iv = out;
206 				}
207 			memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
208 			}
209 		else if (in != out)
210 			{
211 			while (len >= CAMELLIA_BLOCK_SIZE)
212 				{
213 				memcpy(tmp.t8,in,CAMELLIA_BLOCK_SIZE);
214 				if (camellia_endian.little)
215 					SWAP4WORD(tmp.t32);
216 				key->dec(key->rd_key,tmp.t32);
217 				if (camellia_endian.little)
218 					SWAP4WORD(tmp.t32);
219 				for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
220 					out[n] = tmp.t8[n] ^ iv[n];
221 				iv = in;
222 				len -= CAMELLIA_BLOCK_SIZE;
223 				in  += CAMELLIA_BLOCK_SIZE;
224 				out += CAMELLIA_BLOCK_SIZE;
225 				}
226 			if (len)
227 				{
228 				memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
229 				if (camellia_endian.little)
230 					SWAP4WORD(tmp.t32);
231 				key->dec(key->rd_key, tmp.t32);
232 				if (camellia_endian.little)
233 					SWAP4WORD(tmp.t32);
234 				for(n=0; n < len; ++n)
235 					out[n] = tmp.t8[n] ^ iv[n];
236 				iv = in;
237 				}
238 			memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
239 			}
240 		else
241 			{
242 			while (len >= CAMELLIA_BLOCK_SIZE)
243 				{
244 				memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
245 				if (camellia_endian.little)
246 					SWAP4WORD(tmp.t32);
247 				key->dec(key->rd_key, tmp.t32);
248 				if (camellia_endian.little)
249 					SWAP4WORD(tmp.t32);
250 				for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
251 					tmp.t8[n] ^= ivec[n];
252 				memcpy(ivec, in, CAMELLIA_BLOCK_SIZE);
253 				memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
254 				len -= CAMELLIA_BLOCK_SIZE;
255 				in += CAMELLIA_BLOCK_SIZE;
256 				out += CAMELLIA_BLOCK_SIZE;
257 				}
258 			if (len)
259 				{
260 				memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
261 				if (camellia_endian.little)
262 					SWAP4WORD(tmp.t32);
263 				key->dec(key->rd_key,tmp.t32);
264 				if (camellia_endian.little)
265 					SWAP4WORD(tmp.t32);
266 				for(n=0; n < len; ++n)
267 					tmp.t8[n] ^= ivec[n];
268 				memcpy(ivec, in, CAMELLIA_BLOCK_SIZE);
269 				memcpy(out,tmp.t8,len);
270 				}
271 			}
272 		}
273 }
274