1 /* crypto/camellia/camellia_cbc.c -*- mode:C; c-file-style: "eay" -*- */
2 /* ====================================================================
3 * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
31 * 6. Redistributions of any form whatsoever must retain the following
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
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 * ====================================================================
52 #ifndef CAMELLIA_DEBUG
61 #include <openssl/camellia.h>
62 #include "cmll_locl.h"
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)
70 unsigned long len = length;
71 const unsigned char *iv = ivec;
73 u32 t32[CAMELLIA_BLOCK_SIZE / sizeof(u32)];
74 u8 t8[CAMELLIA_BLOCK_SIZE];
83 assert(in && out && key && ivec);
84 assert((CAMELLIA_ENCRYPT == enc) || (CAMELLIA_DECRYPT == enc));
86 if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(u32) == 0) {
87 if (CAMELLIA_ENCRYPT == enc) {
88 while (len >= CAMELLIA_BLOCK_SIZE) {
89 XOR4WORD2((u32 *)out, (u32 *)in, (u32 *)iv);
90 if (camellia_endian.little)
91 SWAP4WORD((u32 *)out);
92 key->enc(key->rd_key, (u32 *)out);
93 if (camellia_endian.little)
94 SWAP4WORD((u32 *)out);
96 len -= CAMELLIA_BLOCK_SIZE;
97 in += CAMELLIA_BLOCK_SIZE;
98 out += CAMELLIA_BLOCK_SIZE;
101 for (n = 0; n < len; ++n)
102 out[n] = in[n] ^ iv[n];
103 for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n)
105 if (camellia_endian.little)
106 SWAP4WORD((u32 *)out);
107 key->enc(key->rd_key, (u32 *)out);
108 if (camellia_endian.little)
109 SWAP4WORD((u32 *)out);
112 memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
113 } else if (in != out) {
114 while (len >= CAMELLIA_BLOCK_SIZE) {
115 memcpy(out, in, CAMELLIA_BLOCK_SIZE);
116 if (camellia_endian.little)
117 SWAP4WORD((u32 *)out);
118 key->dec(key->rd_key, (u32 *)out);
119 if (camellia_endian.little)
120 SWAP4WORD((u32 *)out);
121 XOR4WORD((u32 *)out, (u32 *)iv);
123 len -= CAMELLIA_BLOCK_SIZE;
124 in += CAMELLIA_BLOCK_SIZE;
125 out += CAMELLIA_BLOCK_SIZE;
128 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
129 if (camellia_endian.little)
131 key->dec(key->rd_key, tmp.t32);
132 if (camellia_endian.little)
134 for (n = 0; n < len; ++n)
135 out[n] = tmp.t8[n] ^ iv[n];
138 memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
139 } else { /* in == out */
141 while (len >= CAMELLIA_BLOCK_SIZE) {
142 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
143 if (camellia_endian.little)
144 SWAP4WORD((u32 *)out);
145 key->dec(key->rd_key, (u32 *)out);
146 if (camellia_endian.little)
147 SWAP4WORD((u32 *)out);
148 XOR4WORD((u32 *)out, (u32 *)ivec);
149 memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE);
150 len -= CAMELLIA_BLOCK_SIZE;
151 in += CAMELLIA_BLOCK_SIZE;
152 out += CAMELLIA_BLOCK_SIZE;
155 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
156 if (camellia_endian.little)
157 SWAP4WORD((u32 *)out);
158 key->dec(key->rd_key, (u32 *)out);
159 if (camellia_endian.little)
160 SWAP4WORD((u32 *)out);
161 for (n = 0; n < len; ++n)
163 for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n)
165 memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE);
168 } else { /* no aligned */
170 if (CAMELLIA_ENCRYPT == enc) {
171 while (len >= CAMELLIA_BLOCK_SIZE) {
172 for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n)
173 tmp.t8[n] = in[n] ^ iv[n];
174 if (camellia_endian.little)
176 key->enc(key->rd_key, tmp.t32);
177 if (camellia_endian.little)
179 memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
181 len -= CAMELLIA_BLOCK_SIZE;
182 in += CAMELLIA_BLOCK_SIZE;
183 out += CAMELLIA_BLOCK_SIZE;
186 for (n = 0; n < len; ++n)
187 tmp.t8[n] = in[n] ^ iv[n];
188 for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n)
190 if (camellia_endian.little)
192 key->enc(key->rd_key, tmp.t32);
193 if (camellia_endian.little)
195 memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
198 memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
199 } else if (in != out) {
200 while (len >= CAMELLIA_BLOCK_SIZE) {
201 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
202 if (camellia_endian.little)
204 key->dec(key->rd_key, tmp.t32);
205 if (camellia_endian.little)
207 for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n)
208 out[n] = tmp.t8[n] ^ iv[n];
210 len -= CAMELLIA_BLOCK_SIZE;
211 in += CAMELLIA_BLOCK_SIZE;
212 out += CAMELLIA_BLOCK_SIZE;
215 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
216 if (camellia_endian.little)
218 key->dec(key->rd_key, tmp.t32);
219 if (camellia_endian.little)
221 for (n = 0; n < len; ++n)
222 out[n] = tmp.t8[n] ^ iv[n];
225 memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
227 while (len >= CAMELLIA_BLOCK_SIZE) {
228 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
229 if (camellia_endian.little)
231 key->dec(key->rd_key, tmp.t32);
232 if (camellia_endian.little)
234 for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n)
235 tmp.t8[n] ^= ivec[n];
236 memcpy(ivec, in, CAMELLIA_BLOCK_SIZE);
237 memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
238 len -= CAMELLIA_BLOCK_SIZE;
239 in += CAMELLIA_BLOCK_SIZE;
240 out += CAMELLIA_BLOCK_SIZE;
243 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
244 if (camellia_endian.little)
246 key->dec(key->rd_key, tmp.t32);
247 if (camellia_endian.little)
249 for (n = 0; n < len; ++n)
250 tmp.t8[n] ^= ivec[n];
251 memcpy(ivec, in, CAMELLIA_BLOCK_SIZE);
252 memcpy(out, tmp.t8, len);