New Camellia implementation (replacing previous version)

Submitted by: NTT
This commit is contained in:
Bodo Möller 2006-07-19 13:38:27 +00:00
parent d045e1d77e
commit d9c06b56ca
5 changed files with 1874 additions and 597 deletions

File diff suppressed because it is too large Load diff

View file

@ -74,13 +74,17 @@ extern "C" {
#define CAMELLIA_TABLE_BYTE_LEN 272
#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; /* to match with WORD */
/* to match with WORD */
typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN];
struct camellia_key_st
{
KEY_TABLE_TYPE rd_key;
int bitLength;
void (*enc)(const unsigned int *subkey, unsigned int *io);
void (*dec)(const unsigned int *subkey, unsigned int *io);
};
typedef struct camellia_key_st CAMELLIA_KEY;
int Camellia_set_key(const unsigned char *userKey, const int bits,
@ -122,3 +126,4 @@ void Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out,
#endif
#endif /* !HEADER_Camellia_H */

View file

@ -55,89 +55,180 @@
# endif
#endif
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <openssl/camellia.h>
#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;
unsigned char tmp[CAMELLIA_BLOCK_SIZE];
const unsigned char *iv = ivec;
uint32_t t32[UNITSIZE];
assert(in && out && key && ivec);
assert((CAMELLIA_ENCRYPT == enc)||(CAMELLIA_DECRYPT == enc));
if (CAMELLIA_ENCRYPT == enc)
if(((size_t)in) % ALIGN == 0
&& ((size_t)out) % ALIGN == 0
&& ((size_t)ivec) % ALIGN == 0)
{
while (len >= CAMELLIA_BLOCK_SIZE)
if (CAMELLIA_ENCRYPT == enc)
{
for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] = in[n] ^ iv[n];
Camellia_encrypt(out, out, key);
iv = out;
len -= CAMELLIA_BLOCK_SIZE;
in += CAMELLIA_BLOCK_SIZE;
out += CAMELLIA_BLOCK_SIZE;
while (len >= CAMELLIA_BLOCK_SIZE)
{
XOR4WORD2((uint32_t *)out,
(uint32_t *)in, (uint32_t *)iv);
key->enc(key->rd_key, (uint32_t *)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];
key->enc(key->rd_key, (uint32_t *)out);
iv = out;
}
memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
}
if (len)
else if (in != out)
{
for(n=0; n < len; ++n)
out[n] = in[n] ^ iv[n];
for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] = iv[n];
Camellia_encrypt(out, out, key);
iv = out;
while (len >= CAMELLIA_BLOCK_SIZE)
{
memcpy(out,in,CAMELLIA_BLOCK_SIZE);
key->dec(key->rd_key,(uint32_t *)out);
XOR4WORD((uint32_t *)out, (uint32_t *)iv);
iv = in;
len -= CAMELLIA_BLOCK_SIZE;
in += CAMELLIA_BLOCK_SIZE;
out += CAMELLIA_BLOCK_SIZE;
}
if (len)
{
memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
key->dec(key->rd_key, (uint32_t *)tmp);
for(n=0; n < len; ++n)
out[n] = tmp[n] ^ iv[n];
iv = in;
}
memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
}
memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
}
else if (in != out)
{
while (len >= CAMELLIA_BLOCK_SIZE)
else /* in == out */
{
Camellia_decrypt(in, out, key);
for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] ^= iv[n];
iv = in;
len -= CAMELLIA_BLOCK_SIZE;
in += CAMELLIA_BLOCK_SIZE;
out += CAMELLIA_BLOCK_SIZE;
}
if (len)
{
Camellia_decrypt(in,tmp,key);
for(n=0; n < len; ++n)
out[n] = tmp[n] ^ iv[n];
iv = in;
}
memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
}
else
{
while (len >= CAMELLIA_BLOCK_SIZE)
{
memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
Camellia_decrypt(in, out, key);
for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] ^= ivec[n];
memcpy(ivec, tmp, CAMELLIA_BLOCK_SIZE);
len -= CAMELLIA_BLOCK_SIZE;
in += CAMELLIA_BLOCK_SIZE;
out += CAMELLIA_BLOCK_SIZE;
}
if (len)
{
memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
Camellia_decrypt(tmp, out, key);
for(n=0; n < len; ++n)
out[n] ^= ivec[n];
for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] = tmp[n];
memcpy(ivec, tmp, CAMELLIA_BLOCK_SIZE);
while (len >= CAMELLIA_BLOCK_SIZE)
{
memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
key->dec(key->rd_key, (uint32_t *)out);
XOR4WORD((uint32_t *)out, (uint32_t *)ivec);
memcpy(ivec, tmp, CAMELLIA_BLOCK_SIZE);
len -= CAMELLIA_BLOCK_SIZE;
in += CAMELLIA_BLOCK_SIZE;
out += CAMELLIA_BLOCK_SIZE;
}
if (len)
{
memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
key->dec(key->rd_key,(uint32_t *)out);
for(n=0; n < len; ++n)
out[n] ^= ivec[n];
for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] = tmp[n];
memcpy(ivec, tmp, CAMELLIA_BLOCK_SIZE);
}
}
}
}
else /* no aligned */
{
if (CAMELLIA_ENCRYPT == enc)
{
while (len >= CAMELLIA_BLOCK_SIZE)
{
for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] = in[n] ^ iv[n];
memcpy(t32, out, CAMELLIA_BLOCK_SIZE);
key->enc(key->rd_key, t32);
memcpy(out, t32, 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)
out[n] = in[n] ^ iv[n];
for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] = iv[n];
key->enc(key->rd_key, (uint32_t *)out);
iv = out;
}
memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
}
else if (in != out)
{
while (len >= CAMELLIA_BLOCK_SIZE)
{
memcpy(t32,in,CAMELLIA_BLOCK_SIZE);
key->dec(key->rd_key,t32);
memcpy(out,t32,CAMELLIA_BLOCK_SIZE);
for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] ^= iv[n];
iv = in;
len -= CAMELLIA_BLOCK_SIZE;
in += CAMELLIA_BLOCK_SIZE;
out += CAMELLIA_BLOCK_SIZE;
}
if (len)
{
memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
memcpy(t32, in, CAMELLIA_BLOCK_SIZE);
key->dec(key->rd_key, t32);
memcpy(out, t32, CAMELLIA_BLOCK_SIZE);
for(n=0; n < len; ++n)
out[n] = tmp[n] ^ iv[n];
iv = in;
}
memcpy(ivec,iv,CAMELLIA_BLOCK_SIZE);
}
else
{
while (len >= CAMELLIA_BLOCK_SIZE)
{
memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
memcpy(t32, in, CAMELLIA_BLOCK_SIZE);
key->dec(key->rd_key, t32);
memcpy(out, t32, CAMELLIA_BLOCK_SIZE);
for(n=0; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] ^= ivec[n];
memcpy(ivec, tmp, CAMELLIA_BLOCK_SIZE);
len -= CAMELLIA_BLOCK_SIZE;
in += CAMELLIA_BLOCK_SIZE;
out += CAMELLIA_BLOCK_SIZE;
}
if (len)
{
memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
memcpy(t32, in, CAMELLIA_BLOCK_SIZE);
key->dec(key->rd_key,t32);
memcpy(out, t32, CAMELLIA_BLOCK_SIZE);
for(n=0; n < len; ++n)
out[n] ^= ivec[n];
for(n=len; n < CAMELLIA_BLOCK_SIZE; ++n)
out[n] = tmp[n];
memcpy(ivec, tmp, CAMELLIA_BLOCK_SIZE);
}
}
}
}

View file

@ -68,30 +68,111 @@
#ifndef HEADER_CAMELLIA_LOCL_H
#define HEADER_CAMELLIA_LOCL_H
#include "openssl/e_os2.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_MSC_VER)
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned __int64 uint64_t;
#else
#include <inttypes.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define ALIGN 4
#define UNITSIZE 4
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
# define GETU32(p) SWAP(*((u32 *)(p)))
# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
#else
# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
# define SWAP(x) ( _lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00 )
# define GETU32(p) SWAP(*((uint32_t *)(p)))
# define PUTU32(ct, st) { *((uint32_t *)(ct)) = SWAP((st)); }
# define CAMELLIA_SWAP4(x) (x = ( _lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) )
#else /* not windows */
# define GETU32(pt) (((uint32_t)(pt)[0] << 24) \
^ ((uint32_t)(pt)[1] << 16) \
^ ((uint32_t)(pt)[2] << 8) \
^ ((uint32_t)(pt)[3]))
# define PUTU32(ct, st) { (ct)[0] = (uint8_t)((st) >> 24); \
(ct)[1] = (uint8_t)((st) >> 16); \
(ct)[2] = (uint8_t)((st) >> 8); \
(ct)[3] = (uint8_t)(st); }
#ifdef L_ENDIAN
#if (defined (__GNUC__) && !defined(i386))
#define CAMELLIA_SWAP4(x) \
do{\
asm("bswap %1" : "+r" (x));\
}while(0)
#else /* not gcc */
#define CAMELLIA_SWAP4(x) \
do{\
x = ((uint32_t)x << 16) + ((uint32_t)x >> 16);\
x = (((uint32_t)x & 0xff00ff) << 8) + (((uint32_t)x >> 8) & 0xff00ff);\
} while(0)
#endif /* not gcc */
#else /* big endian */
#define CAMELLIA_SWAP4(x)
#endif /* L_ENDIAN */
#endif
/* Internal types */
typedef unsigned char Byte;
typedef unsigned int Word;
#define COPY4WORD(dst, src) \
do \
{ \
(dst)[0]=(src)[0]; \
(dst)[1]=(src)[1]; \
(dst)[2]=(src)[2]; \
(dst)[3]=(src)[3]; \
}while(0)
#ifdef CAMELLIA_LONG
typedef unsigned long u32;
#else
typedef unsigned int u32;
#define SWAP4WORD(word) \
do \
{ \
CAMELLIA_SWAP4((word)[0]); \
CAMELLIA_SWAP4((word)[1]); \
CAMELLIA_SWAP4((word)[2]); \
CAMELLIA_SWAP4((word)[3]); \
}while(0)
#define XOR4WORD(a, b)/* a = a ^ b */ \
do \
{ \
(a)[0]^=(b)[0]; \
(a)[1]^=(b)[1]; \
(a)[2]^=(b)[2]; \
(a)[3]^=(b)[3]; \
}while(0)
#define XOR4WORD2(a, b, c)/* a = b ^ c */ \
do \
{ \
(a)[0]=(b)[0]^(c)[0]; \
(a)[1]=(b)[1]^(c)[1]; \
(a)[2]=(b)[2]^(c)[2]; \
(a)[3]=(b)[3]^(c)[3]; \
}while(0)
void camellia_setup128(const unsigned char *key, uint32_t *subkey);
void camellia_setup192(const unsigned char *key, uint32_t *subkey);
void camellia_setup256(const unsigned char *key, uint32_t *subkey);
void camellia_encrypt128(const uint32_t *subkey, uint32_t *io);
void camellia_decrypt128(const uint32_t *subkey, uint32_t *io);
void camellia_encrypt256(const uint32_t *subkey, uint32_t *io);
void camellia_decrypt256(const uint32_t *subkey, uint32_t *io);
#ifdef __cplusplus
}
#endif
typedef unsigned short u16;
typedef unsigned char u8;
void Camellia_Ekeygen(const int keyBitLength, const Byte *rawKey, KEY_TABLE_TYPE keyTable);
void Camellia_EncryptBlock(const int keyBitLength, const Byte plaintext[],
const KEY_TABLE_TYPE keyTable, Byte ciphertext[]);
void Camellia_DecryptBlock(const int keyBitLength, const Byte ciphertext[],
const KEY_TABLE_TYPE keyTable, Byte plaintext[]);
#endif /* #ifndef HEADER_CAMELLIA_LOCL_H */

View file

@ -53,16 +53,37 @@
#include <openssl/camellia.h>
#include "cmll_locl.h"
const char *CAMELLIA_version="CAMELLIA" OPENSSL_VERSION_PTEXT;
const char *CAMELLIA_version="CAMELLIA" OPENSSL_VERSION_PTEXT;
int Camellia_set_key(const unsigned char *userKey, const int bits,
CAMELLIA_KEY *key)
{
if(!userKey || !key)
if (!userKey || !key)
{
return -1;
if(bits != 128 && bits != 192 && bits != 256)
}
switch(bits)
{
case 128:
camellia_setup128(userKey, (unsigned int *)key->rd_key);
key->enc = camellia_encrypt128;
key->dec = camellia_decrypt128;
break;
case 192:
camellia_setup192(userKey, (unsigned int *)key->rd_key);
key->enc = camellia_encrypt256;
key->dec = camellia_decrypt256;
break;
case 256:
camellia_setup256(userKey, (unsigned int *)key->rd_key);
key->enc = camellia_encrypt256;
key->dec = camellia_decrypt256;
break;
default:
return -2;
Camellia_Ekeygen(bits , userKey, key->rd_key);
}
key->bitLength = bits;
return 0;
}
@ -70,12 +91,20 @@ int Camellia_set_key(const unsigned char *userKey, const int bits,
void Camellia_encrypt(const unsigned char *in, unsigned char *out,
const CAMELLIA_KEY *key)
{
Camellia_EncryptBlock(key->bitLength, in , key->rd_key , out);
uint32_t tmp[UNITSIZE];
memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
key->enc(key->rd_key, tmp);
memcpy(out, tmp, CAMELLIA_BLOCK_SIZE);
}
void Camellia_decrypt(const unsigned char *in, unsigned char *out,
const CAMELLIA_KEY *key)
{
Camellia_DecryptBlock(key->bitLength, in , key->rd_key , out);
uint32_t tmp[UNITSIZE];
memcpy(tmp, in, CAMELLIA_BLOCK_SIZE);
key->dec(key->rd_key, tmp);
memcpy(out, tmp, CAMELLIA_BLOCK_SIZE);
}