* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
#include "cmll_locl.h"
void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out,
- const unsigned long length, const CAMELLIA_KEY *key,
- unsigned char *ivec, const int enc) {
+ const unsigned long length, const CAMELLIA_KEY *key,
+ unsigned char *ivec, const int enc)
+{
- unsigned long n;
- unsigned long len = length;
- const unsigned char *iv = ivec;
- union { u32 t32[CAMELLIA_BLOCK_SIZE/sizeof(u32)];
- u8 t8 [CAMELLIA_BLOCK_SIZE]; } tmp;
- const union { long one; char little; } camellia_endian = {1};
+ unsigned long n;
+ unsigned long len = length;
+ const unsigned char *iv = ivec;
+ union {
+ u32 t32[CAMELLIA_BLOCK_SIZE / sizeof(u32)];
+ u8 t8[CAMELLIA_BLOCK_SIZE];
+ } tmp;
+ const union {
+ long one;
+ char little;
+ } camellia_endian = {
+ 1
+ };
+ assert(in && out && key && ivec);
+ assert((CAMELLIA_ENCRYPT == enc) || (CAMELLIA_DECRYPT == enc));
- assert(in && out && key && ivec);
- assert((CAMELLIA_ENCRYPT == enc)||(CAMELLIA_DECRYPT == enc));
+ if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(u32) == 0) {
+ if (CAMELLIA_ENCRYPT == enc) {
+ while (len >= CAMELLIA_BLOCK_SIZE) {
+ XOR4WORD2((u32 *)out, (u32 *)in, (u32 *)iv);
+ if (camellia_endian.little)
+ SWAP4WORD((u32 *)out);
+ key->enc(key->rd_key, (u32 *)out);
+ if (camellia_endian.little)
+ SWAP4WORD((u32 *)out);
+ iv = out;
+ len -= CAMELLIA_BLOCK_SIZE;
+ in += CAMELLIA_BLOCK_SIZE;
+ out += CAMELLIA_BLOCK_SIZE;
+ }
+ if (len) {
+ for (n = 0; n < len; ++n)
+ out[n] = in[n] ^ iv[n];
+ for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n)
+ out[n] = iv[n];
+ if (camellia_endian.little)
+ SWAP4WORD((u32 *)out);
+ key->enc(key->rd_key, (u32 *)out);
+ if (camellia_endian.little)
+ SWAP4WORD((u32 *)out);
+ iv = out;
+ }
+ memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
+ } else if (in != out) {
+ while (len >= CAMELLIA_BLOCK_SIZE) {
+ memcpy(out, in, CAMELLIA_BLOCK_SIZE);
+ if (camellia_endian.little)
+ SWAP4WORD((u32 *)out);
+ key->dec(key->rd_key, (u32 *)out);
+ if (camellia_endian.little)
+ SWAP4WORD((u32 *)out);
+ XOR4WORD((u32 *)out, (u32 *)iv);
+ iv = in;
+ len -= CAMELLIA_BLOCK_SIZE;
+ in += CAMELLIA_BLOCK_SIZE;
+ out += CAMELLIA_BLOCK_SIZE;
+ }
+ if (len) {
+ memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ key->dec(key->rd_key, tmp.t32);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ for (n = 0; n < len; ++n)
+ out[n] = tmp.t8[n] ^ iv[n];
+ iv = in;
+ }
+ memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
+ } else { /* in == out */
- if(((size_t)in|(size_t)out|(size_t)ivec) % sizeof(u32) == 0)
- {
- if (CAMELLIA_ENCRYPT == enc)
- {
- while (len >= CAMELLIA_BLOCK_SIZE)
- {
- XOR4WORD2((u32 *)out,
- (u32 *)in, (u32 *)iv);
- if (camellia_endian.little)
- SWAP4WORD((u32 *)out);
- key->enc(key->rd_key, (u32 *)out);
- if (camellia_endian.little)
- SWAP4WORD((u32 *)out);
- iv = out;
- len -= CAMELLIA_BLOCK_SIZE;
- in += CAMELLIA_BLOCK_SIZE;
- out += CAMELLIA_BLOCK_SIZE;
- }
- if (len)
- {
- for(n=0; n < len; ++n)
- out[n] = in[n] ^ iv[n];
- for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
- out[n] = iv[n];
- if (camellia_endian.little)
- SWAP4WORD((u32 *)out);
- key->enc(key->rd_key, (u32 *)out);
- if (camellia_endian.little)
- SWAP4WORD((u32 *)out);
- iv = out;
- }
- memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
- }
- else if (in != out)
- {
- while (len >= CAMELLIA_BLOCK_SIZE)
- {
- memcpy(out,in,CAMELLIA_BLOCK_SIZE);
- if (camellia_endian.little)
- SWAP4WORD((u32 *)out);
- key->dec(key->rd_key,(u32 *)out);
- if (camellia_endian.little)
- SWAP4WORD((u32 *)out);
- XOR4WORD((u32 *)out, (u32 *)iv);
- iv = in;
- len -= CAMELLIA_BLOCK_SIZE;
- in += CAMELLIA_BLOCK_SIZE;
- out += CAMELLIA_BLOCK_SIZE;
- }
- if (len)
- {
- memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- key->dec(key->rd_key, tmp.t32);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- for(n=0; n < len; ++n)
- out[n] = tmp.t8[n] ^ iv[n];
- iv = in;
- }
- memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
- }
- else /* in == out */
- {
- while (len >= CAMELLIA_BLOCK_SIZE)
- {
- memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
- if (camellia_endian.little)
- SWAP4WORD((u32 *)out);
- key->dec(key->rd_key, (u32 *)out);
- if (camellia_endian.little)
- SWAP4WORD((u32 *)out);
- XOR4WORD((u32 *)out, (u32 *)ivec);
- memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE);
- len -= CAMELLIA_BLOCK_SIZE;
- in += CAMELLIA_BLOCK_SIZE;
- out += CAMELLIA_BLOCK_SIZE;
- }
- if (len)
- {
- memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
- if (camellia_endian.little)
- SWAP4WORD((u32 *)out);
- key->dec(key->rd_key,(u32 *)out);
- if (camellia_endian.little)
- SWAP4WORD((u32 *)out);
- for(n=0; n < len; ++n)
- out[n] ^= ivec[n];
- for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
- out[n] = tmp.t8[n];
- memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE);
- }
- }
- }
- else /* no aligned */
- {
- if (CAMELLIA_ENCRYPT == enc)
- {
- while (len >= CAMELLIA_BLOCK_SIZE)
- {
- for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
- tmp.t8[n] = in[n] ^ iv[n];
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- key->enc(key->rd_key, tmp.t32);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
- iv = out;
- len -= CAMELLIA_BLOCK_SIZE;
- in += CAMELLIA_BLOCK_SIZE;
- out += CAMELLIA_BLOCK_SIZE;
- }
- if (len)
- {
- for(n=0; n < len; ++n)
- tmp.t8[n] = in[n] ^ iv[n];
- for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
- tmp.t8[n] = iv[n];
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- key->enc(key->rd_key, tmp.t32);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
- iv = out;
- }
- memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
- }
- else if (in != out)
- {
- while (len >= CAMELLIA_BLOCK_SIZE)
- {
- memcpy(tmp.t8,in,CAMELLIA_BLOCK_SIZE);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- key->dec(key->rd_key,tmp.t32);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
- out[n] = tmp.t8[n] ^ iv[n];
- iv = in;
- len -= CAMELLIA_BLOCK_SIZE;
- in += CAMELLIA_BLOCK_SIZE;
- out += CAMELLIA_BLOCK_SIZE;
- }
- if (len)
- {
- memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- key->dec(key->rd_key, tmp.t32);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- for(n=0; n < len; ++n)
- out[n] = tmp.t8[n] ^ iv[n];
- iv = in;
- }
- memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
- }
- else
- {
- while (len >= CAMELLIA_BLOCK_SIZE)
- {
- memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- key->dec(key->rd_key, tmp.t32);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
- tmp.t8[n] ^= ivec[n];
- memcpy(ivec, in, CAMELLIA_BLOCK_SIZE);
- memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
- len -= CAMELLIA_BLOCK_SIZE;
- in += CAMELLIA_BLOCK_SIZE;
- out += CAMELLIA_BLOCK_SIZE;
- }
- if (len)
- {
- memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- key->dec(key->rd_key,tmp.t32);
- if (camellia_endian.little)
- SWAP4WORD(tmp.t32);
- for(n=0; n < len; ++n)
- tmp.t8[n] ^= ivec[n];
- memcpy(ivec, in, CAMELLIA_BLOCK_SIZE);
- memcpy(out,tmp.t8,len);
- }
- }
- }
+ while (len >= CAMELLIA_BLOCK_SIZE) {
+ memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
+ if (camellia_endian.little)
+ SWAP4WORD((u32 *)out);
+ key->dec(key->rd_key, (u32 *)out);
+ if (camellia_endian.little)
+ SWAP4WORD((u32 *)out);
+ XOR4WORD((u32 *)out, (u32 *)ivec);
+ memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE);
+ len -= CAMELLIA_BLOCK_SIZE;
+ in += CAMELLIA_BLOCK_SIZE;
+ out += CAMELLIA_BLOCK_SIZE;
+ }
+ if (len) {
+ memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
+ if (camellia_endian.little)
+ SWAP4WORD((u32 *)out);
+ key->dec(key->rd_key, (u32 *)out);
+ if (camellia_endian.little)
+ SWAP4WORD((u32 *)out);
+ for (n = 0; n < len; ++n)
+ out[n] ^= ivec[n];
+ for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n)
+ out[n] = tmp.t8[n];
+ memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE);
+ }
+ }
+ } else { /* no aligned */
+
+ if (CAMELLIA_ENCRYPT == enc) {
+ while (len >= CAMELLIA_BLOCK_SIZE) {
+ for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n)
+ tmp.t8[n] = in[n] ^ iv[n];
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ key->enc(key->rd_key, tmp.t32);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
+ iv = out;
+ len -= CAMELLIA_BLOCK_SIZE;
+ in += CAMELLIA_BLOCK_SIZE;
+ out += CAMELLIA_BLOCK_SIZE;
+ }
+ if (len) {
+ for (n = 0; n < len; ++n)
+ tmp.t8[n] = in[n] ^ iv[n];
+ for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n)
+ tmp.t8[n] = iv[n];
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ key->enc(key->rd_key, tmp.t32);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
+ iv = out;
+ }
+ memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
+ } else if (in != out) {
+ while (len >= CAMELLIA_BLOCK_SIZE) {
+ memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ key->dec(key->rd_key, tmp.t32);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n)
+ out[n] = tmp.t8[n] ^ iv[n];
+ iv = in;
+ len -= CAMELLIA_BLOCK_SIZE;
+ in += CAMELLIA_BLOCK_SIZE;
+ out += CAMELLIA_BLOCK_SIZE;
+ }
+ if (len) {
+ memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ key->dec(key->rd_key, tmp.t32);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ for (n = 0; n < len; ++n)
+ out[n] = tmp.t8[n] ^ iv[n];
+ iv = in;
+ }
+ memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
+ } else {
+ while (len >= CAMELLIA_BLOCK_SIZE) {
+ memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ key->dec(key->rd_key, tmp.t32);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n)
+ tmp.t8[n] ^= ivec[n];
+ memcpy(ivec, in, CAMELLIA_BLOCK_SIZE);
+ memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
+ len -= CAMELLIA_BLOCK_SIZE;
+ in += CAMELLIA_BLOCK_SIZE;
+ out += CAMELLIA_BLOCK_SIZE;
+ }
+ if (len) {
+ memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ key->dec(key->rd_key, tmp.t32);
+ if (camellia_endian.little)
+ SWAP4WORD(tmp.t32);
+ for (n = 0; n < len; ++n)
+ tmp.t8[n] ^= ivec[n];
+ memcpy(ivec, in, CAMELLIA_BLOCK_SIZE);
+ memcpy(out, tmp.t8, len);
+ }
+ }
+ }
}