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 64void 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