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