1162911Ssimon/* crypto/camellia/camellia_cbc.c -*- mode:C; c-file-style: "eay" -*- */ 2162911Ssimon/* ==================================================================== 3162911Ssimon * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 4162911Ssimon * 5162911Ssimon * Redistribution and use in source and binary forms, with or without 6162911Ssimon * modification, are permitted provided that the following conditions 7162911Ssimon * are met: 8162911Ssimon * 9162911Ssimon * 1. Redistributions of source code must retain the above copyright 10296465Sdelphij * notice, this list of conditions and the following disclaimer. 11162911Ssimon * 12162911Ssimon * 2. Redistributions in binary form must reproduce the above copyright 13162911Ssimon * notice, this list of conditions and the following disclaimer in 14162911Ssimon * the documentation and/or other materials provided with the 15162911Ssimon * distribution. 16162911Ssimon * 17162911Ssimon * 3. All advertising materials mentioning features or use of this 18162911Ssimon * software must display the following acknowledgment: 19162911Ssimon * "This product includes software developed by the OpenSSL Project 20162911Ssimon * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21162911Ssimon * 22162911Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23162911Ssimon * endorse or promote products derived from this software without 24162911Ssimon * prior written permission. For written permission, please contact 25162911Ssimon * openssl-core@openssl.org. 26162911Ssimon * 27162911Ssimon * 5. Products derived from this software may not be called "OpenSSL" 28162911Ssimon * nor may "OpenSSL" appear in their names without prior written 29162911Ssimon * permission of the OpenSSL Project. 30162911Ssimon * 31162911Ssimon * 6. Redistributions of any form whatsoever must retain the following 32162911Ssimon * acknowledgment: 33162911Ssimon * "This product includes software developed by the OpenSSL Project 34162911Ssimon * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35162911Ssimon * 36162911Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37162911Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38162911Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39162911Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40162911Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41162911Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42162911Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43162911Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44162911Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45162911Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46162911Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47162911Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 48162911Ssimon * ==================================================================== 49162911Ssimon * 50162911Ssimon */ 51162911Ssimon 52162911Ssimon#ifndef CAMELLIA_DEBUG 53162911Ssimon# ifndef NDEBUG 54162911Ssimon# define NDEBUG 55162911Ssimon# endif 56162911Ssimon#endif 57162911Ssimon#include <assert.h> 58162911Ssimon#include <stdio.h> 59162911Ssimon#include <string.h> 60162911Ssimon 61162911Ssimon#include <openssl/camellia.h> 62162911Ssimon#include "cmll_locl.h" 63162911Ssimon 64162911Ssimonvoid Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out, 65296465Sdelphij const unsigned long length, const CAMELLIA_KEY *key, 66296465Sdelphij unsigned char *ivec, const int enc) 67296465Sdelphij{ 68162911Ssimon 69296465Sdelphij unsigned long n; 70296465Sdelphij unsigned long len = length; 71296465Sdelphij const unsigned char *iv = ivec; 72296465Sdelphij union { 73296465Sdelphij u32 t32[CAMELLIA_BLOCK_SIZE / sizeof(u32)]; 74296465Sdelphij u8 t8[CAMELLIA_BLOCK_SIZE]; 75296465Sdelphij } tmp; 76296465Sdelphij const union { 77296465Sdelphij long one; 78296465Sdelphij char little; 79296465Sdelphij } camellia_endian = { 80296465Sdelphij 1 81296465Sdelphij }; 82162911Ssimon 83296465Sdelphij assert(in && out && key && ivec); 84296465Sdelphij assert((CAMELLIA_ENCRYPT == enc) || (CAMELLIA_DECRYPT == enc)); 85162911Ssimon 86296465Sdelphij if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(u32) == 0) { 87296465Sdelphij if (CAMELLIA_ENCRYPT == enc) { 88296465Sdelphij while (len >= CAMELLIA_BLOCK_SIZE) { 89296465Sdelphij XOR4WORD2((u32 *)out, (u32 *)in, (u32 *)iv); 90296465Sdelphij if (camellia_endian.little) 91296465Sdelphij SWAP4WORD((u32 *)out); 92296465Sdelphij key->enc(key->rd_key, (u32 *)out); 93296465Sdelphij if (camellia_endian.little) 94296465Sdelphij SWAP4WORD((u32 *)out); 95296465Sdelphij iv = out; 96296465Sdelphij len -= CAMELLIA_BLOCK_SIZE; 97296465Sdelphij in += CAMELLIA_BLOCK_SIZE; 98296465Sdelphij out += CAMELLIA_BLOCK_SIZE; 99296465Sdelphij } 100296465Sdelphij if (len) { 101296465Sdelphij for (n = 0; n < len; ++n) 102296465Sdelphij out[n] = in[n] ^ iv[n]; 103296465Sdelphij for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n) 104296465Sdelphij out[n] = iv[n]; 105296465Sdelphij if (camellia_endian.little) 106296465Sdelphij SWAP4WORD((u32 *)out); 107296465Sdelphij key->enc(key->rd_key, (u32 *)out); 108296465Sdelphij if (camellia_endian.little) 109296465Sdelphij SWAP4WORD((u32 *)out); 110296465Sdelphij iv = out; 111296465Sdelphij } 112296465Sdelphij memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE); 113296465Sdelphij } else if (in != out) { 114296465Sdelphij while (len >= CAMELLIA_BLOCK_SIZE) { 115296465Sdelphij memcpy(out, in, CAMELLIA_BLOCK_SIZE); 116296465Sdelphij if (camellia_endian.little) 117296465Sdelphij SWAP4WORD((u32 *)out); 118296465Sdelphij key->dec(key->rd_key, (u32 *)out); 119296465Sdelphij if (camellia_endian.little) 120296465Sdelphij SWAP4WORD((u32 *)out); 121296465Sdelphij XOR4WORD((u32 *)out, (u32 *)iv); 122296465Sdelphij iv = in; 123296465Sdelphij len -= CAMELLIA_BLOCK_SIZE; 124296465Sdelphij in += CAMELLIA_BLOCK_SIZE; 125296465Sdelphij out += CAMELLIA_BLOCK_SIZE; 126296465Sdelphij } 127296465Sdelphij if (len) { 128296465Sdelphij memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE); 129296465Sdelphij if (camellia_endian.little) 130296465Sdelphij SWAP4WORD(tmp.t32); 131296465Sdelphij key->dec(key->rd_key, tmp.t32); 132296465Sdelphij if (camellia_endian.little) 133296465Sdelphij SWAP4WORD(tmp.t32); 134296465Sdelphij for (n = 0; n < len; ++n) 135296465Sdelphij out[n] = tmp.t8[n] ^ iv[n]; 136296465Sdelphij iv = in; 137296465Sdelphij } 138296465Sdelphij memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE); 139296465Sdelphij } else { /* in == out */ 140162911Ssimon 141296465Sdelphij while (len >= CAMELLIA_BLOCK_SIZE) { 142296465Sdelphij memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE); 143296465Sdelphij if (camellia_endian.little) 144296465Sdelphij SWAP4WORD((u32 *)out); 145296465Sdelphij key->dec(key->rd_key, (u32 *)out); 146296465Sdelphij if (camellia_endian.little) 147296465Sdelphij SWAP4WORD((u32 *)out); 148296465Sdelphij XOR4WORD((u32 *)out, (u32 *)ivec); 149296465Sdelphij memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE); 150296465Sdelphij len -= CAMELLIA_BLOCK_SIZE; 151296465Sdelphij in += CAMELLIA_BLOCK_SIZE; 152296465Sdelphij out += CAMELLIA_BLOCK_SIZE; 153296465Sdelphij } 154296465Sdelphij if (len) { 155296465Sdelphij memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE); 156296465Sdelphij if (camellia_endian.little) 157296465Sdelphij SWAP4WORD((u32 *)out); 158296465Sdelphij key->dec(key->rd_key, (u32 *)out); 159296465Sdelphij if (camellia_endian.little) 160296465Sdelphij SWAP4WORD((u32 *)out); 161296465Sdelphij for (n = 0; n < len; ++n) 162296465Sdelphij out[n] ^= ivec[n]; 163296465Sdelphij for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n) 164296465Sdelphij out[n] = tmp.t8[n]; 165296465Sdelphij memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE); 166296465Sdelphij } 167296465Sdelphij } 168296465Sdelphij } else { /* no aligned */ 169296465Sdelphij 170296465Sdelphij if (CAMELLIA_ENCRYPT == enc) { 171296465Sdelphij while (len >= CAMELLIA_BLOCK_SIZE) { 172296465Sdelphij for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n) 173296465Sdelphij tmp.t8[n] = in[n] ^ iv[n]; 174296465Sdelphij if (camellia_endian.little) 175296465Sdelphij SWAP4WORD(tmp.t32); 176296465Sdelphij key->enc(key->rd_key, tmp.t32); 177296465Sdelphij if (camellia_endian.little) 178296465Sdelphij SWAP4WORD(tmp.t32); 179296465Sdelphij memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE); 180296465Sdelphij iv = out; 181296465Sdelphij len -= CAMELLIA_BLOCK_SIZE; 182296465Sdelphij in += CAMELLIA_BLOCK_SIZE; 183296465Sdelphij out += CAMELLIA_BLOCK_SIZE; 184296465Sdelphij } 185296465Sdelphij if (len) { 186296465Sdelphij for (n = 0; n < len; ++n) 187296465Sdelphij tmp.t8[n] = in[n] ^ iv[n]; 188296465Sdelphij for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n) 189296465Sdelphij tmp.t8[n] = iv[n]; 190296465Sdelphij if (camellia_endian.little) 191296465Sdelphij SWAP4WORD(tmp.t32); 192296465Sdelphij key->enc(key->rd_key, tmp.t32); 193296465Sdelphij if (camellia_endian.little) 194296465Sdelphij SWAP4WORD(tmp.t32); 195296465Sdelphij memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE); 196296465Sdelphij iv = out; 197296465Sdelphij } 198296465Sdelphij memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE); 199296465Sdelphij } else if (in != out) { 200296465Sdelphij while (len >= CAMELLIA_BLOCK_SIZE) { 201296465Sdelphij memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE); 202296465Sdelphij if (camellia_endian.little) 203296465Sdelphij SWAP4WORD(tmp.t32); 204296465Sdelphij key->dec(key->rd_key, tmp.t32); 205296465Sdelphij if (camellia_endian.little) 206296465Sdelphij SWAP4WORD(tmp.t32); 207296465Sdelphij for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n) 208296465Sdelphij out[n] = tmp.t8[n] ^ iv[n]; 209296465Sdelphij iv = in; 210296465Sdelphij len -= CAMELLIA_BLOCK_SIZE; 211296465Sdelphij in += CAMELLIA_BLOCK_SIZE; 212296465Sdelphij out += CAMELLIA_BLOCK_SIZE; 213296465Sdelphij } 214296465Sdelphij if (len) { 215296465Sdelphij memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE); 216296465Sdelphij if (camellia_endian.little) 217296465Sdelphij SWAP4WORD(tmp.t32); 218296465Sdelphij key->dec(key->rd_key, tmp.t32); 219296465Sdelphij if (camellia_endian.little) 220296465Sdelphij SWAP4WORD(tmp.t32); 221296465Sdelphij for (n = 0; n < len; ++n) 222296465Sdelphij out[n] = tmp.t8[n] ^ iv[n]; 223296465Sdelphij iv = in; 224296465Sdelphij } 225296465Sdelphij memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE); 226296465Sdelphij } else { 227296465Sdelphij while (len >= CAMELLIA_BLOCK_SIZE) { 228296465Sdelphij memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE); 229296465Sdelphij if (camellia_endian.little) 230296465Sdelphij SWAP4WORD(tmp.t32); 231296465Sdelphij key->dec(key->rd_key, tmp.t32); 232296465Sdelphij if (camellia_endian.little) 233296465Sdelphij SWAP4WORD(tmp.t32); 234296465Sdelphij for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n) 235296465Sdelphij tmp.t8[n] ^= ivec[n]; 236296465Sdelphij memcpy(ivec, in, CAMELLIA_BLOCK_SIZE); 237296465Sdelphij memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE); 238296465Sdelphij len -= CAMELLIA_BLOCK_SIZE; 239296465Sdelphij in += CAMELLIA_BLOCK_SIZE; 240296465Sdelphij out += CAMELLIA_BLOCK_SIZE; 241296465Sdelphij } 242296465Sdelphij if (len) { 243296465Sdelphij memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE); 244296465Sdelphij if (camellia_endian.little) 245296465Sdelphij SWAP4WORD(tmp.t32); 246296465Sdelphij key->dec(key->rd_key, tmp.t32); 247296465Sdelphij if (camellia_endian.little) 248296465Sdelphij SWAP4WORD(tmp.t32); 249296465Sdelphij for (n = 0; n < len; ++n) 250296465Sdelphij tmp.t8[n] ^= ivec[n]; 251296465Sdelphij memcpy(ivec, in, CAMELLIA_BLOCK_SIZE); 252296465Sdelphij memcpy(out, tmp.t8, len); 253296465Sdelphij } 254296465Sdelphij } 255296465Sdelphij } 256162911Ssimon} 257