cmll_cbc.c revision 162911
1319780Sdim/* crypto/camellia/camellia_cbc.c -*- mode:C; c-file-style: "eay" -*- */
2319780Sdim/* ====================================================================
3353358Sdim * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
4353358Sdim *
5353358Sdim * Redistribution and use in source and binary forms, with or without
6319780Sdim * modification, are permitted provided that the following conditions
7319780Sdim * are met:
8319780Sdim *
9319780Sdim * 1. Redistributions of source code must retain the above copyright
10319780Sdim *    notice, this list of conditions and the following disclaimer.
11319780Sdim *
12319780Sdim * 2. Redistributions in binary form must reproduce the above copyright
13319780Sdim *    notice, this list of conditions and the following disclaimer in
14319780Sdim *    the documentation and/or other materials provided with the
15320397Sdim *    distribution.
16320397Sdim *
17341825Sdim * 3. All advertising materials mentioning features or use of this
18327952Sdim *    software must display the following acknowledgment:
19319780Sdim *    "This product includes software developed by the OpenSSL Project
20319780Sdim *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21341825Sdim *
22319780Sdim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23341825Sdim *    endorse or promote products derived from this software without
24319780Sdim *    prior written permission. For written permission, please contact
25319780Sdim *    openssl-core@openssl.org.
26319780Sdim *
27341825Sdim * 5. Products derived from this software may not be called "OpenSSL"
28319780Sdim *    nor may "OpenSSL" appear in their names without prior written
29319780Sdim *    permission of the OpenSSL Project.
30319780Sdim *
31319780Sdim * 6. Redistributions of any form whatsoever must retain the following
32319780Sdim *    acknowledgment:
33319780Sdim *    "This product includes software developed by the OpenSSL Project
34319780Sdim *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35319780Sdim *
36327952Sdim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37319780Sdim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38327952Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39319780Sdim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40319780Sdim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41319780Sdim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42319780Sdim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43327952Sdim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44320041Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45319780Sdim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46319780Sdim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47319780Sdim * OF THE POSSIBILITY OF SUCH DAMAGE.
48341825Sdim * ====================================================================
49319780Sdim *
50319780Sdim */
51319780Sdim
52319780Sdim#ifndef CAMELLIA_DEBUG
53341825Sdim# ifndef NDEBUG
54319780Sdim#  define NDEBUG
55319780Sdim# endif
56319780Sdim#endif
57319780Sdim#include <assert.h>
58319780Sdim#include <stdio.h>
59319780Sdim#include <string.h>
60319780Sdim
61319780Sdim#include <openssl/camellia.h>
62319780Sdim#include "cmll_locl.h"
63319780Sdim
64319780Sdimvoid Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out,
65319780Sdim		     const unsigned long length, const CAMELLIA_KEY *key,
66319780Sdim		     unsigned char *ivec, const int enc) {
67319780Sdim
68341825Sdim	unsigned long n;
69319780Sdim	unsigned long len = length;
70341825Sdim	unsigned char tmp[CAMELLIA_BLOCK_SIZE];
71344779Sdim	const unsigned char *iv = ivec;
72344779Sdim	uint32_t t32[UNITSIZE];
73341825Sdim
74341825Sdim
75319780Sdim	assert(in && out && key && ivec);
76319780Sdim	assert((CAMELLIA_ENCRYPT == enc)||(CAMELLIA_DECRYPT == enc));
77319780Sdim
78319780Sdim	if(((size_t)in) % ALIGN == 0
79319780Sdim		&& ((size_t)out) % ALIGN == 0
80319780Sdim		&& ((size_t)ivec) % ALIGN == 0)
81319780Sdim		{
82341825Sdim		if (CAMELLIA_ENCRYPT == enc)
83327952Sdim			{
84319780Sdim			while (len >= CAMELLIA_BLOCK_SIZE)
85319780Sdim				{
86319780Sdim				XOR4WORD2((uint32_t *)out,
87319780Sdim					(uint32_t *)in, (uint32_t *)iv);
88319780Sdim				key->enc(key->rd_key, (uint32_t *)out);
89319780Sdim				iv = out;
90319780Sdim				len -= CAMELLIA_BLOCK_SIZE;
91319780Sdim				in += CAMELLIA_BLOCK_SIZE;
92319780Sdim				out += CAMELLIA_BLOCK_SIZE;
93319780Sdim				}
94319780Sdim			if (len)
95319780Sdim				{
96319780Sdim				for(n=0; n < len; ++n)
97319780Sdim					out[n] = in[n] ^ iv[n];
98319780Sdim				for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
99319780Sdim					out[n] = iv[n];
100319780Sdim				key->enc(key->rd_key, (uint32_t *)out);
101320397Sdim				iv = out;
102320397Sdim				}
103320397Sdim			memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
104344779Sdim			}
105344779Sdim		else if (in != out)
106344779Sdim			{
107319780Sdim			while (len >= CAMELLIA_BLOCK_SIZE)
108319780Sdim				{
109319780Sdim				memcpy(out,in,CAMELLIA_BLOCK_SIZE);
110319780Sdim				key->dec(key->rd_key,(uint32_t *)out);
111319780Sdim				XOR4WORD((uint32_t *)out, (uint32_t *)iv);
112319780Sdim				iv = in;
113319780Sdim				len -= CAMELLIA_BLOCK_SIZE;
114319780Sdim				in  += CAMELLIA_BLOCK_SIZE;
115319780Sdim				out += CAMELLIA_BLOCK_SIZE;
116319780Sdim				}
117319780Sdim			if (len)
118319780Sdim				{
119319780Sdim				memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
120319780Sdim				key->dec(key->rd_key, (uint32_t *)tmp);
121341825Sdim				for(n=0; n < len; ++n)
122341825Sdim					out[n] = tmp[n] ^ iv[n];
123341825Sdim				iv = in;
124341825Sdim				}
125341825Sdim			memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
126341825Sdim			}
127319780Sdim		else /* in == out */
128319780Sdim			{
129319780Sdim			while (len >= CAMELLIA_BLOCK_SIZE)
130319780Sdim				{
131320397Sdim				memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
132320397Sdim				key->dec(key->rd_key, (uint32_t *)out);
133320397Sdim				XOR4WORD((uint32_t *)out, (uint32_t *)ivec);
134320397Sdim				memcpy(ivec, tmp, CAMELLIA_BLOCK_SIZE);
135320397Sdim				len -= CAMELLIA_BLOCK_SIZE;
136320397Sdim				in += CAMELLIA_BLOCK_SIZE;
137320397Sdim				out += CAMELLIA_BLOCK_SIZE;
138320397Sdim				}
139320397Sdim			if (len)
140320397Sdim				{
141320397Sdim				memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
142320397Sdim				key->dec(key->rd_key,(uint32_t *)out);
143320397Sdim				for(n=0; n < len; ++n)
144320397Sdim					out[n] ^= ivec[n];
145320397Sdim				for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
146320397Sdim					out[n] = tmp[n];
147320397Sdim				memcpy(ivec, tmp, CAMELLIA_BLOCK_SIZE);
148320397Sdim				}
149320397Sdim			}
150320397Sdim		}
151320397Sdim	else /* no aligned */
152320397Sdim		{
153320397Sdim		if (CAMELLIA_ENCRYPT == enc)
154320397Sdim			{
155320397Sdim			while (len >= CAMELLIA_BLOCK_SIZE)
156344779Sdim				{
157344779Sdim				for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
158344779Sdim					out[n] = in[n] ^ iv[n];
159344779Sdim				memcpy(t32, out, CAMELLIA_BLOCK_SIZE);
160344779Sdim				key->enc(key->rd_key, t32);
161344779Sdim				memcpy(out, t32, CAMELLIA_BLOCK_SIZE);
162344779Sdim				iv = out;
163344779Sdim				len -= CAMELLIA_BLOCK_SIZE;
164344779Sdim				in += CAMELLIA_BLOCK_SIZE;
165344779Sdim				out += CAMELLIA_BLOCK_SIZE;
166344779Sdim				}
167344779Sdim			if (len)
168344779Sdim				{
169344779Sdim				for(n=0; n < len; ++n)
170344779Sdim					out[n] = in[n] ^ iv[n];
171344779Sdim				for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
172344779Sdim					out[n] = iv[n];
173344779Sdim				key->enc(key->rd_key, (uint32_t *)out);
174344779Sdim				iv = out;
175344779Sdim				}
176344779Sdim			memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
177344779Sdim			}
178344779Sdim		else if (in != out)
179344779Sdim			{
180344779Sdim			while (len >= CAMELLIA_BLOCK_SIZE)
181344779Sdim				{
182344779Sdim				memcpy(t32,in,CAMELLIA_BLOCK_SIZE);
183344779Sdim				key->dec(key->rd_key,t32);
184344779Sdim				memcpy(out,t32,CAMELLIA_BLOCK_SIZE);
185344779Sdim				for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
186344779Sdim					out[n] ^= iv[n];
187344779Sdim				iv = in;
188344779Sdim				len -= CAMELLIA_BLOCK_SIZE;
189344779Sdim				in  += CAMELLIA_BLOCK_SIZE;
190344779Sdim				out += CAMELLIA_BLOCK_SIZE;
191344779Sdim				}
192344779Sdim			if (len)
193344779Sdim				{
194344779Sdim				memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
195344779Sdim				memcpy(t32, in, CAMELLIA_BLOCK_SIZE);
196344779Sdim				key->dec(key->rd_key, t32);
197344779Sdim				memcpy(out, t32, CAMELLIA_BLOCK_SIZE);
198319780Sdim				for(n=0; n < len; ++n)
199319780Sdim					out[n] = tmp[n] ^ iv[n];
200319780Sdim				iv = in;
201319780Sdim				}
202319780Sdim			memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
203341825Sdim			}
204341825Sdim		else
205341825Sdim			{
206341825Sdim			while (len >= CAMELLIA_BLOCK_SIZE)
207341825Sdim				{
208341825Sdim				memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
209341825Sdim				memcpy(t32, in, CAMELLIA_BLOCK_SIZE);
210341825Sdim				key->dec(key->rd_key, t32);
211341825Sdim				memcpy(out, t32, CAMELLIA_BLOCK_SIZE);
212341825Sdim				for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
213341825Sdim					out[n] ^= ivec[n];
214341825Sdim				memcpy(ivec, tmp, CAMELLIA_BLOCK_SIZE);
215341825Sdim				len -= CAMELLIA_BLOCK_SIZE;
216319780Sdim				in += CAMELLIA_BLOCK_SIZE;
217319780Sdim				out += CAMELLIA_BLOCK_SIZE;
218319780Sdim				}
219319780Sdim			if (len)
220319780Sdim				{
221319780Sdim				memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
222319780Sdim				memcpy(t32, in, CAMELLIA_BLOCK_SIZE);
223319780Sdim				key->dec(key->rd_key,t32);
224319780Sdim				memcpy(out, t32, CAMELLIA_BLOCK_SIZE);
225319780Sdim				for(n=0; n < len; ++n)
226319780Sdim					out[n] ^= ivec[n];
227319780Sdim				for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
228319780Sdim					out[n] = tmp[n];
229319780Sdim				memcpy(ivec, tmp, CAMELLIA_BLOCK_SIZE);
230319780Sdim				}
231319780Sdim			}
232319780Sdim		}
233319780Sdim}
234319780Sdim
235319780Sdim