[BACK]Return to camellia.c CVS log [TXT][DIR] Up to [local] / OpenXM / src / ox_ntl / crypt / camellia

File: [local] / OpenXM / src / ox_ntl / crypt / camellia / camellia.c (download)

Revision 1.1, Sun May 29 11:50:40 2005 UTC (19 years ago) by iwane
Branch: MAIN
CVS Tags: R_1_3_1-2, RELEASE_1_3_1_13b, RELEASE_1_2_3_12, KNOPPIX_2006, HEAD, DEB_REL_1_2_3-9

Camellia: a 128-bit block cipher

/* $OpenXM: OpenXM/src/ox_ntl/crypt/camellia/camellia.c,v 1.1 2005/05/29 11:50:40 iwane Exp $ */
/*
 * Camellia
 * http://info.isl.ntt.co.jp/crypt/camellia/index.html
 */

#include "camellia.h"


#if HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */


#define leftrot32(x, n)      ((((uint32_t)x) << n) | ((uint32_t)x) >> (32 - n))


#define DPRINTF(str, x, n)	/* DPRINTF__(str, (x), (n)) */
#define DPRINTF__(str, x, n)	{                        \
	int _i;                                  \
	printf("%s: ", str);                      \
	for (_i = 0; _i < n; _i++) {             \
		printf("%02x", ARY(x, _i) & 0xff);    \
		if (_i % 8 == 7)                 \
			printf(" ");             \
	}                                        \
	printf("\n");                            \
	fflush(stdout);                          \
}

#ifdef WORDS_BIGENDIAN
#define ARY(x, i)  (((uint8_t *)(x))[i])
#else
#define ARY(x, i)  (((uint8_t *)(x))[(int)("\x03\x02\x01\x00\x07\x06\x05\x04\x0b\x0a\x09\x08\x0f\x0e\x0d\x0c\x13\x12\x11\x10\x17\x16\x15\x14\x1b\x1a\x19\x18\x1f\x1e\x1d\x1c"[i])])
#endif


static const uint32_t G_camellia_sigma[] = {
	0xa09e667f, 0x3bcc908b,
	0xb67ae858, 0x4caa73b2,
	0xc6ef372f, 0xe94f82be,
	0x54ff53a5, 0xf1d36f1c,
	0x10e527fa, 0xde682d1d,
	0xb05688c2, 0xb3e6c1fd,
};

#define SIGMA(i)   (G_camellia_sigma + (2 * ((i) - 1)))


static const uint8_t G_camellia_sbox[256] = {
	112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65,
	 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189,
	134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26,
	166,225, 57,202,213, 71, 93, 61,217,  1, 90,214, 81, 86,108, 77,
	139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153,
	223, 76,203,194, 52,126,118,  5,109,183,169, 49,209, 23,  4,215,
	 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34,
	254, 68,207,178,195,181,122,145, 36,  8,232,168, 96,252,105, 80,
	170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210,
	 16,196,  0, 72,163,247,117,219,138,  3,230,218,  9, 63,221,148,
	135, 92,131,  2,205, 74,144, 51,115,103,246,243,157,127,191,226,
	 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46,
	233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89,
	120,152,  6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250,
	114,  7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164,
	 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158,
};

#define SBOX1(n)	G_camellia_sbox[n]
#define SBOX2(n)	(uint8_t)((SBOX1(n) >> 7 ^ SBOX1(n) << 1) & 0xff)
#define SBOX3(n)	(uint8_t)((SBOX1(n) >> 1 ^ SBOX1(n) << 7) & 0xff)
#define SBOX4(n)	SBOX1(((n) << 1 ^ (n) >> 7) & 0xff)


#if 0
static void
camellia_binprt(const uint32_t *t, int n)
{
	int i;
	int q, r;
	for (i = 0; i < n; i++) {
		q = i / 32;
		r = i % 32;

		printf("%d", (t[q] >> r) & 1);
		if (i % 32 == 31)
			printf(" ");
	}
	printf("\n");
}
#endif

/**
 * return (a ^ b)
 *  a - 128 bit
 *  b - 128 bit
 */
static void
camellia_xor128(uint32_t *t, const uint32_t *a, const uint32_t *b)
{
	int i;
	for (i = 0; i < 4; i++) {
		t[i] = a[i] ^ b[i];
	}
}
static void
camellia_xor64(uint32_t *t, const uint32_t *a, const uint32_t *b)
{
	int i;
	for (i = 0; i < 2; i++) {
		t[i] = a[i] ^ b[i];
	}
}

static void
camellia_rot128(uint32_t *t, const uint32_t *a, int n)
{
	const int N = 128 / 32;
	int i;
	int r = n % 32;
	int r2 = 32 - r;
	int q = (n / 32) % N;

	if (r) {
		for (i = 0; i < N; i++) {
			t[i] = (a[(i + q) % N] << r) | (a[(i + q + N + 1) % N] >> r2);
		}
	} else {
		for (i = 0; i < N; i++) {
			t[i] = a[(i + q) % N];
		}
	}
}




/**
 * return s(l)
 *  t - 64 bit
 *  l - 64 bit
 */
static inline void
camellia_s(uint32_t *t, const uint32_t *l)
{
	ARY(t, 0) = SBOX1(ARY(l, 0));
	ARY(t, 1) = SBOX2(ARY(l, 1));
	ARY(t, 2) = SBOX3(ARY(l, 2));
	ARY(t, 3) = SBOX4(ARY(l, 3));
	ARY(t, 4) = SBOX2(ARY(l, 4));
	ARY(t, 5) = SBOX3(ARY(l, 5));
	ARY(t, 6) = SBOX4(ARY(l, 6));
	ARY(t, 7) = SBOX1(ARY(l, 7));
}


/**
 * return p(l)
 *  t - 64 bit
 *  l - 64 bit
 */
static inline void
camellia_p(uint32_t *t, const uint32_t *l)
{
#define L(i) (ARY(l, (i) - 1))
	ARY(t, 0) = L(1) ^ L(3) ^ L(4) ^ L(6) ^ L(7) ^ L(8);
	ARY(t, 1) = L(1) ^ L(2) ^ L(4) ^ L(5) ^ L(7) ^ L(8); 
	ARY(t, 2) = L(1) ^ L(2) ^ L(3) ^ L(5) ^ L(6) ^ L(8);
	ARY(t, 3) = L(2) ^ L(3) ^ L(4) ^ L(5) ^ L(6) ^ L(7);
	ARY(t, 4) = L(1) ^ L(2) ^ L(6) ^ L(7) ^ L(8);
	ARY(t, 5) = L(2) ^ L(3) ^ L(5) ^ L(7) ^ L(8);
	ARY(t, 6) = L(3) ^ L(4) ^ L(5) ^ L(6) ^ L(8);
	ARY(t, 7) = L(1) ^ L(4) ^ L(5) ^ L(6) ^ L(7);
#undef L
}


/**
 * return p(s(x^k))
 *  t - 64 bit
 *  l - 64 bit
 */
static inline void
camellia_f(uint32_t *y, const uint32_t *x, const uint32_t *k)
{
	uint32_t xor[4];
	uint32_t s[4];

	camellia_xor64(xor, x, k);
	camellia_s(s, xor);
	camellia_p(y, s);
}


/**
 * kl :  64 bit
 * kr :  64 bit
 * smg:  64 bit
 */
static inline void
camellia_feistel(uint32_t *w, const uint32_t *kl, const uint32_t *kr, const uint32_t *sgm)
{
	camellia_f(w, kl, sgm);
	camellia_xor64(w, w, kr);
}

static inline void
camellia_fl(uint32_t *y, const uint32_t *x, const uint32_t *k)
{
	uint32_t t;

	t = x[0] & k[0];
	y[1] = leftrot32(t, 1) ^ x[1];
	y[0] = (y[1] | k[1]) ^ x[0];
}

static inline void
camellia_fl_(uint32_t *x, const uint32_t *y, const uint32_t *k)
{
	uint32_t t;

	x[0] = (y[1] | k[1]) ^ y[0];
	t = x[0] & k[0];
	x[1] = leftrot32(t, 1) ^ y[1];
}



/*
 * len =  16 or  24 or  32
 * bit = 128 or 192 or 256
 */
int
camellia_keyset(const unsigned char *key, int len, camellia_key *ckey)
{
	int i;
	const uint32_t *kr, *kl, *kb;
	uint32_t ka[4];
	uint32_t t[4];  /* 128 bit */
	uint32_t w[4];  /* 128 bit */
	uint32_t v[4];  /* 128 bit */

#define Kl(i) (ARY(ckey->key, i))
#define Kr(i) (ARY(ckey->key, (i + 16)))
#define T(i)  (ARY(t,  i))

	if (len == 16) {
		for (i = 0; i < 16; i++) {
			Kl(i) = key[i];
			Kr(i) = 0x00;
		}
	} else if (len == 24) {
		for (i = 0; i < 16; i++) {
			Kl(i) = key[i];
		}
		for (; i < 24; i++) {
			Kr(i - 16) = key[i];
			Kr(i - 8) = ~key[i];
		}
	} else if (len == 32) {
		for (i = 0; i < 16; i++) {
			Kl(i) = key[i];
			Kr(i) = key[i + 16];
		}
	} else {
		return (-1);
	}

	kl = ckey->key;
	kr = ckey->key + 4;

	ckey->len = len;

	camellia_xor128(t, kl, kr);


	camellia_feistel(w + 2, t, t + 2, SIGMA(1));
	camellia_feistel(w, w + 2, t, SIGMA(2));

	camellia_xor128(v, w, kl);

	camellia_feistel(w + 2, v, v + 2, SIGMA(3));
	camellia_feistel(w, w + 2, v, SIGMA(4));

	if (len == 16) {
		/*
		 * KA = w
		 * KL = key
		 */
		camellia_rot128(ckey->kw, ckey->key, 0);
		camellia_rot128(ckey->kw + 4, w, 111);

		camellia_rot128(ckey->kl, w, 30);
		camellia_rot128(ckey->kl + 4, ckey->key, 77);

		camellia_rot128(ckey->k +  0, w, 0);
		camellia_rot128(ckey->k +  4, ckey->key, 15);
		camellia_rot128(ckey->k +  8, w, 15);
		camellia_rot128(ckey->k + 12, ckey->key, 45);
		camellia_rot128(ckey->k + 16, w, 45);
		camellia_rot128(ckey->k + 20, w, 60);
		camellia_rot128(ckey->k + 24, ckey->key, 94);
		camellia_rot128(ckey->k + 28, w, 94);
		camellia_rot128(ckey->k + 32, ckey->key, 111);

		camellia_rot128(v, ckey->key, 60);
		ckey->k[18] = v[2];
		ckey->k[19] = v[3];

		return (0);
	}

	memcpy(ka, w, sizeof(w));

	camellia_xor128(v, w, kr);

	camellia_feistel(w + 2, v, v + 2, SIGMA(5));
	camellia_feistel(w + 0, w + 2, v, SIGMA(6));

	kb = w;

	camellia_rot128(ckey->kw + 0, kl, 0);
	camellia_rot128(ckey->kw + 4, kb, 111);

	camellia_rot128(ckey->kl + 0, kr, 30);
	camellia_rot128(ckey->kl + 4, kl, 60);
	camellia_rot128(ckey->kl + 8, ka, 77);

	camellia_rot128(ckey->k +  0, kb, 0);
	camellia_rot128(ckey->k +  4, kr, 15);
	camellia_rot128(ckey->k +  8, ka, 15);
	camellia_rot128(ckey->k + 12, kb, 30);
	camellia_rot128(ckey->k + 16, kl, 45);
	camellia_rot128(ckey->k + 20, ka, 45);

	camellia_rot128(ckey->k + 24, kr, 60);
	camellia_rot128(ckey->k + 28, kb, 60);
	camellia_rot128(ckey->k + 32, kl, 77);
	camellia_rot128(ckey->k + 36, kr, 94);
	camellia_rot128(ckey->k + 40, ka, 94);
	camellia_rot128(ckey->k + 44, kl, 111);


	return (0);
#undef X
}


/*
 * m: message 128 bit
 * e: encrypt 128 bit
 */
void
camellia_enc(camellia_key *ckey, const uint8_t *msg, uint8_t *e)
{
	uint32_t m[4];
	uint32_t w[8] = {0, 0, 0, 0, 0, 0, 0, 0};
	int i, j, k;
	int loop;


	if (ckey->len == 16) { /* 128 bit */
		loop = 2;
	} else {               /* 192 or 256 bit */
		loop = 3;
	}

	for (i = 0; i < 16; i++) {
		ARY(m, i) = msg[i];
	}

	for (i = 0; i < 4; i++) {
		w[(i + 2) % 4] = m[i] ^ ckey->kw[i];
	}

	i = 0;
	for (j = 0;; j++) {

		for (k = 0; k < 6; k++, i++) {
			camellia_feistel(w + (4 + 2 * k) % 8, w + (2 + 2 * k) % 8, w + (0 + 2 * k) % 8, ckey->k + 2 * i);
		}

		if (j == loop)
			break;

		camellia_fl(w + 2, w + 6, ckey->kl + 4 * j);
		camellia_fl_(w + 0, w + 4, ckey->kl + 4 * j + 2);

	}


	camellia_xor128(w, w + 4, ckey->kw + 4);

	for (i = 0; i < 32; i++) {
		e[i] = ARY(w, i);
	}

}

/*
 * e: encrypt 128 bit
 * m: message 128 bit
 */
void
camellia_dec(camellia_key *ckey, const uint8_t *enc, uint8_t *m)
{
	uint32_t e[4];
	uint32_t w[8] = {0, 0, 0, 0, 0, 0, 0, 0};
	int i, j, k;
	int loop;

	if (ckey->len == 16) { /* 128 bit */
		loop = 2;
/*18*/
	} else {
		loop = 3;
/*24*/
	}

	for (i = 0; i < 16; i++) {
		ARY(e, i) = enc[i];
	}


	for (i = 0; i < 4; i++) {
		w[(i + 2) % 4] = e[i] ^ ckey->kw[(i + 0) % 4 + 4];
	}


	i = (loop + 1) * 6 - 1;
	for (j = loop - 1;; j--) {

		for (k = 0; k < 6; k++, i--) {
			camellia_feistel(w + (4 + 2 * k) % 8, w + (2 + 2 * k) % 8, w + (0 + 2 * k) % 8, ckey->k + 2 * i);
		}

		if (j < 0)
			break;


		camellia_fl(w + 2, w + 6, ckey->kl + 4 * j + 2);
		camellia_fl_(w + 0, w + 4, ckey->kl + 4 * j + 0);

	}


	camellia_xor128(w, w + 4, ckey->kw + 0);

	for (i = 0; i < 32; i++) {
		m[i] = ARY(w, i);
	}

}



/* End of File */