cmll_cbc.c revision 296465
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 69 unsigned long n; 70 unsigned long len = length; 71 const unsigned char *iv = ivec; 72 union { 73 u32 t32[CAMELLIA_BLOCK_SIZE / sizeof(u32)]; 74 u8 t8[CAMELLIA_BLOCK_SIZE]; 75 } tmp; 76 const union { 77 long one; 78 char little; 79 } camellia_endian = { 80 1 81 }; 82 83 assert(in && out && key && ivec); 84 assert((CAMELLIA_ENCRYPT == enc) || (CAMELLIA_DECRYPT == enc)); 85 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); 95 iv = out; 96 len -= CAMELLIA_BLOCK_SIZE; 97 in += CAMELLIA_BLOCK_SIZE; 98 out += CAMELLIA_BLOCK_SIZE; 99 } 100 if (len) { 101 for (n = 0; n < len; ++n) 102 out[n] = in[n] ^ iv[n]; 103 for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n) 104 out[n] = iv[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); 110 iv = out; 111 } 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); 122 iv = in; 123 len -= CAMELLIA_BLOCK_SIZE; 124 in += CAMELLIA_BLOCK_SIZE; 125 out += CAMELLIA_BLOCK_SIZE; 126 } 127 if (len) { 128 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE); 129 if (camellia_endian.little) 130 SWAP4WORD(tmp.t32); 131 key->dec(key->rd_key, tmp.t32); 132 if (camellia_endian.little) 133 SWAP4WORD(tmp.t32); 134 for (n = 0; n < len; ++n) 135 out[n] = tmp.t8[n] ^ iv[n]; 136 iv = in; 137 } 138 memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE); 139 } else { /* in == out */ 140 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; 153 } 154 if (len) { 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) 162 out[n] ^= ivec[n]; 163 for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n) 164 out[n] = tmp.t8[n]; 165 memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE); 166 } 167 } 168 } else { /* no aligned */ 169 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) 175 SWAP4WORD(tmp.t32); 176 key->enc(key->rd_key, tmp.t32); 177 if (camellia_endian.little) 178 SWAP4WORD(tmp.t32); 179 memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE); 180 iv = out; 181 len -= CAMELLIA_BLOCK_SIZE; 182 in += CAMELLIA_BLOCK_SIZE; 183 out += CAMELLIA_BLOCK_SIZE; 184 } 185 if (len) { 186 for (n = 0; n < len; ++n) 187 tmp.t8[n] = in[n] ^ iv[n]; 188 for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n) 189 tmp.t8[n] = iv[n]; 190 if (camellia_endian.little) 191 SWAP4WORD(tmp.t32); 192 key->enc(key->rd_key, tmp.t32); 193 if (camellia_endian.little) 194 SWAP4WORD(tmp.t32); 195 memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE); 196 iv = out; 197 } 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) 203 SWAP4WORD(tmp.t32); 204 key->dec(key->rd_key, tmp.t32); 205 if (camellia_endian.little) 206 SWAP4WORD(tmp.t32); 207 for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n) 208 out[n] = tmp.t8[n] ^ iv[n]; 209 iv = in; 210 len -= CAMELLIA_BLOCK_SIZE; 211 in += CAMELLIA_BLOCK_SIZE; 212 out += CAMELLIA_BLOCK_SIZE; 213 } 214 if (len) { 215 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE); 216 if (camellia_endian.little) 217 SWAP4WORD(tmp.t32); 218 key->dec(key->rd_key, tmp.t32); 219 if (camellia_endian.little) 220 SWAP4WORD(tmp.t32); 221 for (n = 0; n < len; ++n) 222 out[n] = tmp.t8[n] ^ iv[n]; 223 iv = in; 224 } 225 memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE); 226 } else { 227 while (len >= CAMELLIA_BLOCK_SIZE) { 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 < 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; 241 } 242 if (len) { 243 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE); 244 if (camellia_endian.little) 245 SWAP4WORD(tmp.t32); 246 key->dec(key->rd_key, tmp.t32); 247 if (camellia_endian.little) 248 SWAP4WORD(tmp.t32); 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); 253 } 254 } 255 } 256} 257