1/* crypto/evp/e_camellia.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 * This product includes cryptographic software written by Eric Young 51 * (eay@cryptsoft.com). This product includes software written by Tim 52 * Hudson (tjh@cryptsoft.com). 53 * 54 */ 55 56#include <openssl/opensslconf.h> 57#ifndef OPENSSL_NO_CAMELLIA 58# include <openssl/evp.h> 59# include <openssl/err.h> 60# include <string.h> 61# include <assert.h> 62# include <openssl/camellia.h> 63# include "evp_locl.h" 64# include "modes_lcl.h" 65 66static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 67 const unsigned char *iv, int enc); 68 69/* Camellia subkey Structure */ 70typedef struct { 71 CAMELLIA_KEY ks; 72 block128_f block; 73 union { 74 cbc128_f cbc; 75 ctr128_f ctr; 76 } stream; 77} EVP_CAMELLIA_KEY; 78 79# define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4)) 80 81/* Attribute operation for Camellia */ 82# define data(ctx) EVP_C_DATA(EVP_CAMELLIA_KEY,ctx) 83 84# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) 85/* ---------^^^ this is not a typo, just a way to detect that 86 * assembler support was in general requested... */ 87# include "sparc_arch.h" 88 89extern unsigned int OPENSSL_sparcv9cap_P[]; 90 91# define SPARC_CMLL_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_CAMELLIA) 92 93void cmll_t4_set_key(const unsigned char *key, int bits, CAMELLIA_KEY *ks); 94void cmll_t4_encrypt(const unsigned char *in, unsigned char *out, 95 const CAMELLIA_KEY *key); 96void cmll_t4_decrypt(const unsigned char *in, unsigned char *out, 97 const CAMELLIA_KEY *key); 98 99void cmll128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, 100 size_t len, const CAMELLIA_KEY *key, 101 unsigned char *ivec); 102void cmll128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, 103 size_t len, const CAMELLIA_KEY *key, 104 unsigned char *ivec); 105void cmll256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, 106 size_t len, const CAMELLIA_KEY *key, 107 unsigned char *ivec); 108void cmll256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, 109 size_t len, const CAMELLIA_KEY *key, 110 unsigned char *ivec); 111void cmll128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, 112 size_t blocks, const CAMELLIA_KEY *key, 113 unsigned char *ivec); 114void cmll256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, 115 size_t blocks, const CAMELLIA_KEY *key, 116 unsigned char *ivec); 117 118static int cmll_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 119 const unsigned char *iv, int enc) 120{ 121 int ret, mode, bits; 122 EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; 123 124 mode = ctx->cipher->flags & EVP_CIPH_MODE; 125 bits = ctx->key_len * 8; 126 127 cmll_t4_set_key(key, bits, &dat->ks); 128 129 if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) 130 && !enc) { 131 ret = 0; 132 dat->block = (block128_f) cmll_t4_decrypt; 133 switch (bits) { 134 case 128: 135 dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? 136 (cbc128_f) cmll128_t4_cbc_decrypt : NULL; 137 break; 138 case 192: 139 case 256: 140 dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? 141 (cbc128_f) cmll256_t4_cbc_decrypt : NULL; 142 break; 143 default: 144 ret = -1; 145 } 146 } else { 147 ret = 0; 148 dat->block = (block128_f) cmll_t4_encrypt; 149 switch (bits) { 150 case 128: 151 if (mode == EVP_CIPH_CBC_MODE) 152 dat->stream.cbc = (cbc128_f) cmll128_t4_cbc_encrypt; 153 else if (mode == EVP_CIPH_CTR_MODE) 154 dat->stream.ctr = (ctr128_f) cmll128_t4_ctr32_encrypt; 155 else 156 dat->stream.cbc = NULL; 157 break; 158 case 192: 159 case 256: 160 if (mode == EVP_CIPH_CBC_MODE) 161 dat->stream.cbc = (cbc128_f) cmll256_t4_cbc_encrypt; 162 else if (mode == EVP_CIPH_CTR_MODE) 163 dat->stream.ctr = (ctr128_f) cmll256_t4_ctr32_encrypt; 164 else 165 dat->stream.cbc = NULL; 166 break; 167 default: 168 ret = -1; 169 } 170 } 171 172 if (ret < 0) { 173 EVPerr(EVP_F_CMLL_T4_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED); 174 return 0; 175 } 176 177 return 1; 178} 179 180# define cmll_t4_cbc_cipher camellia_cbc_cipher 181static int cmll_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 182 const unsigned char *in, size_t len); 183 184# define cmll_t4_ecb_cipher camellia_ecb_cipher 185static int cmll_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 186 const unsigned char *in, size_t len); 187 188# define cmll_t4_ofb_cipher camellia_ofb_cipher 189static int cmll_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 190 const unsigned char *in, size_t len); 191 192# define cmll_t4_cfb_cipher camellia_cfb_cipher 193static int cmll_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 194 const unsigned char *in, size_t len); 195 196# define cmll_t4_cfb8_cipher camellia_cfb8_cipher 197static int cmll_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 198 const unsigned char *in, size_t len); 199 200# define cmll_t4_cfb1_cipher camellia_cfb1_cipher 201static int cmll_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 202 const unsigned char *in, size_t len); 203 204# define cmll_t4_ctr_cipher camellia_ctr_cipher 205static int cmll_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 206 const unsigned char *in, size_t len); 207 208# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ 209static const EVP_CIPHER cmll_t4_##keylen##_##mode = { \ 210 nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ 211 flags|EVP_CIPH_##MODE##_MODE, \ 212 cmll_t4_init_key, \ 213 cmll_t4_##mode##_cipher, \ 214 NULL, \ 215 sizeof(EVP_CAMELLIA_KEY), \ 216 NULL,NULL,NULL,NULL }; \ 217static const EVP_CIPHER camellia_##keylen##_##mode = { \ 218 nid##_##keylen##_##nmode,blocksize, \ 219 keylen/8,ivlen, \ 220 flags|EVP_CIPH_##MODE##_MODE, \ 221 camellia_init_key, \ 222 camellia_##mode##_cipher, \ 223 NULL, \ 224 sizeof(EVP_CAMELLIA_KEY), \ 225 NULL,NULL,NULL,NULL }; \ 226const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \ 227{ return SPARC_CMLL_CAPABLE?&cmll_t4_##keylen##_##mode:&camellia_##keylen##_##mode; } 228 229# else 230 231# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ 232static const EVP_CIPHER camellia_##keylen##_##mode = { \ 233 nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ 234 flags|EVP_CIPH_##MODE##_MODE, \ 235 camellia_init_key, \ 236 camellia_##mode##_cipher, \ 237 NULL, \ 238 sizeof(EVP_CAMELLIA_KEY), \ 239 NULL,NULL,NULL,NULL }; \ 240const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \ 241{ return &camellia_##keylen##_##mode; } 242 243# endif 244 245# define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \ 246 BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ 247 BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ 248 BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ 249 BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ 250 BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags) \ 251 BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags) 252# if 0 /* not yet, missing NID */ 253BLOCK_CIPHER_generic(nid, keylen, 1, 16, ctr, ctr, CTR, flags) 254# endif 255/* The subkey for Camellia is generated. */ 256static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 257 const unsigned char *iv, int enc) 258{ 259 int ret, mode; 260 EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; 261 262 ret = Camellia_set_key(key, ctx->key_len * 8, &dat->ks); 263 if (ret < 0) { 264 EVPerr(EVP_F_CAMELLIA_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED); 265 return 0; 266 } 267 268 mode = ctx->cipher->flags & EVP_CIPH_MODE; 269 if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) 270 && !enc) { 271 dat->block = (block128_f) Camellia_decrypt; 272 dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? 273 (cbc128_f) Camellia_cbc_encrypt : NULL; 274 } else { 275 dat->block = (block128_f) Camellia_encrypt; 276 dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? 277 (cbc128_f) Camellia_cbc_encrypt : NULL; 278 } 279 280 return 1; 281} 282 283static int camellia_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 284 const unsigned char *in, size_t len) 285{ 286 EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; 287 288 if (dat->stream.cbc) 289 (*dat->stream.cbc) (in, out, len, &dat->ks, ctx->iv, ctx->encrypt); 290 else if (ctx->encrypt) 291 CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block); 292 else 293 CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv, dat->block); 294 295 return 1; 296} 297 298static int camellia_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 299 const unsigned char *in, size_t len) 300{ 301 size_t bl = ctx->cipher->block_size; 302 size_t i; 303 EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; 304 305 if (len < bl) 306 return 1; 307 308 for (i = 0, len -= bl; i <= len; i += bl) 309 (*dat->block) (in + i, out + i, &dat->ks); 310 311 return 1; 312} 313 314static int camellia_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 315 const unsigned char *in, size_t len) 316{ 317 EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; 318 319 CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, 320 ctx->iv, &ctx->num, dat->block); 321 return 1; 322} 323 324static int camellia_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 325 const unsigned char *in, size_t len) 326{ 327 EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; 328 329 CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, 330 ctx->iv, &ctx->num, ctx->encrypt, dat->block); 331 return 1; 332} 333 334static int camellia_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 335 const unsigned char *in, size_t len) 336{ 337 EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; 338 339 CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, 340 ctx->iv, &ctx->num, ctx->encrypt, dat->block); 341 return 1; 342} 343 344static int camellia_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 345 const unsigned char *in, size_t len) 346{ 347 EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; 348 349 if (ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) { 350 CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, 351 ctx->iv, &ctx->num, ctx->encrypt, dat->block); 352 return 1; 353 } 354 355 while (len >= MAXBITCHUNK) { 356 CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks, 357 ctx->iv, &ctx->num, ctx->encrypt, dat->block); 358 len -= MAXBITCHUNK; 359 } 360 if (len) 361 CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks, 362 ctx->iv, &ctx->num, ctx->encrypt, dat->block); 363 364 return 1; 365} 366 367# if 0 /* not yet, missing NID */ 368static int camellia_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 369 const unsigned char *in, size_t len) 370{ 371 unsigned int num = ctx->num; 372 EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; 373 374 if (dat->stream.ctr) 375 CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, 376 ctx->iv, ctx->buf, &num, dat->stream.ctr); 377 else 378 CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, 379 ctx->iv, ctx->buf, &num, dat->block); 380 ctx->num = (size_t)num; 381 return 1; 382} 383# endif 384 385BLOCK_CIPHER_generic_pack(NID_camellia, 128, 0) 386 BLOCK_CIPHER_generic_pack(NID_camellia, 192, 0) 387 BLOCK_CIPHER_generic_pack(NID_camellia, 256, 0) 388#else 389 390# ifdef PEDANTIC 391static void *dummy = &dummy; 392# endif 393 394#endif 395