From a4d89a90e601794c1995aa71ebb37662c068388e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se>
Date: Wed, 7 Jul 2010 21:17:56 +0200
Subject: [PATCH] * Makefile.in (nettle_SOURCES): Added camellia.c and
 camellia-meta.c. (HEADERS): Added camellia.h.

* camellia-meta.c: New file.

* camellia.h: Rewrote interface to match nettle conventions.

* camellia.c: Converted to nettle conventions.
(camellia_encrypt128, camellia_encrypt256): Unified to new
function...
(camellia_encrypt): ...New function, with a loop doing 6
regular rounds, one FL round and one FLINV round per iteration,
with iteration count depending on the key size.

Rev: nettle/ChangeLog:1.89
Rev: nettle/Makefile.in:1.25
Rev: nettle/camellia-meta.c:1.1
Rev: nettle/camellia.c:1.2
Rev: nettle/camellia.h:1.2
---
 ChangeLog       |  33 ++
 Makefile.in     |   4 +-
 camellia-meta.c |  38 +++
 camellia.c      | 826 +++++++++++++++---------------------------------
 camellia.h      |  83 +++--
 5 files changed, 386 insertions(+), 598 deletions(-)
 create mode 100644 camellia-meta.c

diff --git a/ChangeLog b/ChangeLog
index e701f0f2..565f7511 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2010-07-07  Niels M�ller  <nisse@lysator.liu.se>
+
+	* Makefile.in (nettle_SOURCES): Added camellia.c and
+	camellia-meta.c.
+	(HEADERS): Added camellia.h.
+
+	* nettle-meta.h (nettle_camellia128): Declare.
+	(nettle_camellia192): Likewise.
+	(nettle_camellia256): Likewise.
+
+	* camellia-meta.c: New file.
+
+	* camellia.h: Rewrote interface to match nettle conventions.
+
+	* camellia.c: Converted to nettle conventions.
+	(camellia_encrypt128, camellia_encrypt256): Unified to new
+	function...
+	(camellia_encrypt): ...New function, with a loop doing 6
+	regular rounds, one FL round and one FLINV round per iteration,
+	with iteration count depending on the key size.
+
+	(camellia_decrypt128, camellia_decrypt256): Similarly unified
+	as...
+	(camellia_decrypt): ...New function, analogous to
+	camellia_encrypt.
+
+2010-07-06  Niels M�ller  <nisse@lysator.liu.se>
+
+	* camellia.c, camellia.h: New files, copied from
+	http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/camellia-LGPL-1.2.0.tar.gz.
+
+	* testsuite/camellia-test.c: New file.
+
 2010-07-05  Niels M�ller  <nisse@lysator.liu.se>
 
 	* nettle.texinfo: Document new conventions for weak key and des
diff --git a/Makefile.in b/Makefile.in
index 212e7de0..837e8cbc 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -55,7 +55,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
 		 arctwo.c arctwo-meta.c \
 		 base16-encode.c base16-decode.c base16-meta.c \
                  base64-encode.c base64-decode.c base64-meta.c \
-		 cast128.c cast128-meta.c \
+		 camellia.c camellia-meta.c cast128.c cast128-meta.c \
 		 blowfish.c \
 		 cbc.c ctr.c \
 		 des.c \
@@ -97,7 +97,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
 		  der-iterator.c der2rsa.c der2dsa.c
 
 HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \
-	  base16.h base64.h buffer.h cast128.h \
+	  base16.h base64.h buffer.h camellia.h cast128.h \
 	  cbc.h ctr.h \
 	  des.h des-compat.h dsa.h \
 	  hmac.h \
diff --git a/camellia-meta.c b/camellia-meta.c
new file mode 100644
index 00000000..0311af33
--- /dev/null
+++ b/camellia-meta.c
@@ -0,0 +1,38 @@
+/* camellia-meta.c */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2010 Niels M�ller
+ *  
+ * The nettle library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ * 
+ * The nettle library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ * License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "nettle-meta.h"
+
+#include "camellia.h"
+
+const struct nettle_cipher nettle_camellia128
+= _NETTLE_CIPHER(camellia, CAMELLIA, 128);
+
+const struct nettle_cipher nettle_camellia192
+= _NETTLE_CIPHER(camellia, CAMELLIA, 192);
+
+const struct nettle_cipher nettle_camellia256
+= _NETTLE_CIPHER(camellia, CAMELLIA, 256);
diff --git a/camellia.c b/camellia.c
index 79cd49b7..d62d2268 100644
--- a/camellia.c
+++ b/camellia.c
@@ -3,6 +3,8 @@
  * Copyright (C) 2006,2007
  * NTT (Nippon Telegraph and Telephone Corporation).
  *
+ * Copyright (C) 2010 Niels M�ller
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -23,14 +25,18 @@
  *  http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
  */
 
-#include <string.h>
-#include <stdlib.h>
+/* Based on camellia.c ver 1.2.0, see
+   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/camellia-LGPL-1.2.0.tar.gz.
+ */
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
 
 #include "camellia.h"
 
-/* u32 must be 32bit word */
-typedef unsigned int u32;
-typedef unsigned char u8;
+#include "macros.h"
 
 /* key constants */
 
@@ -52,30 +58,8 @@ typedef unsigned char u8;
  */
 
 
-#if defined(_MSC_VER)
-
-# 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 /* not MS-VC */
-
-# 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); }
-
-#endif
-
-#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2])
-#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1])
+#define CamelliaSubkeyL(INDEX) ((ctx)->keys[(INDEX)][0])
+#define CamelliaSubkeyR(INDEX) ((ctx)->keys[(INDEX)][1])
 
 /* rotation right shift 1byte */
 #define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24))
@@ -151,25 +135,34 @@ typedef unsigned char u8;
 
 #define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
     do {								\
-	ir = CAMELLIA_SP1110(xr & 0xff)					\
-	    ^ CAMELLIA_SP0222((xr >> 24) & 0xff)			\
-	    ^ CAMELLIA_SP3033((xr >> 16) & 0xff)			\
-	    ^ CAMELLIA_SP4404((xr >> 8) & 0xff);			\
-	il = CAMELLIA_SP1110((xl >> 24) & 0xff)				\
-	    ^ CAMELLIA_SP0222((xl >> 16) & 0xff)			\
-	    ^ CAMELLIA_SP3033((xl >> 8) & 0xff)				\
-	    ^ CAMELLIA_SP4404(xl & 0xff);				\
+        ir = CAMELLIA_SP1110(xr & 0xff)			/* t8 */	\
+	    ^ CAMELLIA_SP0222((xr >> 24) & 0xff)	/* t5 */	\
+	    ^ CAMELLIA_SP3033((xr >> 16) & 0xff)	/* t6 */	\
+	    ^ CAMELLIA_SP4404((xr >> 8) & 0xff);	/* t7 */	\
+	/* ir == (t6^t7^t8),(t5^t7^t8),(t5^t6^t8),(t5^t6^t7) */		\
+	il = CAMELLIA_SP1110((xl >> 24) & 0xff)		/* t1 */	\
+	    ^ CAMELLIA_SP0222((xl >> 16) & 0xff)	/* t2 */	\
+	    ^ CAMELLIA_SP3033((xl >> 8) & 0xff)		/* t3 */	\
+	    ^ CAMELLIA_SP4404(xl & 0xff);		/* t4 */	\
+	/* il == (t1^t3^t4),(t1^t2^t4),(t1^t2^t3),(t2^t3^t4) */		\
 	il ^= kl;							\
 	ir ^= kr;							\
 	ir ^= il;							\
+	/* ir == (t1^t3^t4^t6^t7^t8),(t1^t2^t4^t5^t7^t8),		\
+	         (t1^t2^t3^t5^t6^t8),(t2^t3^t4^t5^t6^t7)		\
+	      == y1,y2,y3,y4 */						\
 	il = CAMELLIA_RR8(il);						\
+	/* il == (t2^t3^t4),(t1^t3^t4),(t1^t2^t4),(t1^t2^t3) */		\
 	il ^= ir;							\
+	/* il == (t1^t2^t6^t7^t8),(t2^t3^t5^t7^t8),			\
+	         (t3^t4^t5^t6^t8),(t1^t4^t5^t6^t7)			\
+	      == y5,y6,y7,y8 */						\
 	yl ^= ir;							\
 	yr ^= il;							\
     } while(0)
 
 
-static const u32 camellia_sp1110[256] = {
+static const uint32_t camellia_sp1110[256] = {
     0x70707000,0x82828200,0x2c2c2c00,0xececec00,
     0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500,
     0xe4e4e400,0x85858500,0x57575700,0x35353500,
@@ -236,7 +229,7 @@ static const u32 camellia_sp1110[256] = {
     0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00,
 };
 
-static const u32 camellia_sp0222[256] = {
+static const uint32_t camellia_sp0222[256] = {
     0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9,
     0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb,
     0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a,
@@ -303,7 +296,7 @@ static const u32 camellia_sp0222[256] = {
     0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d,
 };
 
-static const u32 camellia_sp3033[256] = {
+static const uint32_t camellia_sp3033[256] = {
     0x38003838,0x41004141,0x16001616,0x76007676,
     0xd900d9d9,0x93009393,0x60006060,0xf200f2f2,
     0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a,
@@ -370,7 +363,7 @@ static const u32 camellia_sp3033[256] = {
     0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f,
 };
 
-static const u32 camellia_sp4404[256] = {
+static const uint32_t camellia_sp4404[256] = {
     0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0,
     0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae,
     0x23230023,0x6b6b006b,0x45450045,0xa5a500a5,
@@ -441,24 +434,26 @@ static const u32 camellia_sp4404[256] = {
 /**
  * Stuff related to the Camellia key schedule
  */
-#define subl(x) subL[(x)]
-#define subr(x) subR[(x)]
+#define subl(x) sub[(x)][0]
+#define subr(x) sub[(x)][1]
 
-void camellia_setup128(const unsigned char *key, u32 *subkey)
+static void
+camellia_setup128(struct camellia_ctx *ctx, uint32_t *key)
 {
-    u32 kll, klr, krl, krr;
-    u32 il, ir, t0, t1, w0, w1;
-    u32 kw4l, kw4r, dw, tl, tr;
-    u32 subL[26];
-    u32 subR[26];
+    uint32_t kll, klr, krl, krr;
+    uint32_t il, ir, t0, t1, w0, w1;
+    uint32_t kw4l, kw4r, dw, tl, tr;
+
+    /* Subkeys according to the spec. */
+    uint32_t sub[26][2];
 
     /**
-     *  k == kll || klr || krl || krr (|| is concatination)
+     *  k == k0 || klr || krl || krr (|| is concatination)
      */
-    kll = GETU32(key     );
-    klr = GETU32(key +  4);
-    krl = GETU32(key +  8);
-    krr = GETU32(key + 12);
+    kll = key[0];
+    klr = key[1];
+    krl = key[2];
+    krr = key[3];
     /**
      * generate KL dependent subkeys
      */
@@ -655,28 +650,30 @@ void camellia_setup128(const unsigned char *key, u32 *subkey)
     return;
 }
 
-void camellia_setup256(const unsigned char *key, u32 *subkey)
+static void
+camellia_setup256(struct camellia_ctx *ctx, uint32_t *key)
 {
-    u32 kll,klr,krl,krr;           /* left half of key */
-    u32 krll,krlr,krrl,krrr;       /* right half of key */
-    u32 il, ir, t0, t1, w0, w1;    /* temporary variables */
-    u32 kw4l, kw4r, dw, tl, tr;
-    u32 subL[34];
-    u32 subR[34];
+    uint32_t kll,klr,krl,krr;           /* left half of key */
+    uint32_t krll,krlr,krrl,krrr;       /* right half of key */
+    uint32_t il, ir, t0, t1, w0, w1;    /* temporary variables */
+    uint32_t kw4l, kw4r, dw, tl, tr;
+
+    /* Subkeys according to the spec. */
+    uint32_t sub[34][2];
 
     /**
      *  key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
      *  (|| is concatination)
      */
 
-    kll  = GETU32(key     );
-    klr  = GETU32(key +  4);
-    krl  = GETU32(key +  8);
-    krr  = GETU32(key + 12);
-    krll = GETU32(key + 16);
-    krlr = GETU32(key + 20);
-    krrl = GETU32(key + 24);
-    krrr = GETU32(key + 28);
+    kll  = key[0];
+    klr  = key[1];
+    krl  = key[2];
+    krr  = key[3];
+    krll = key[4];
+    krlr = key[5];
+    krrl = key[6];
+    krrr = key[7];
 
     /* generate KL dependent subkeys */
     subl(0) = kll; subr(0) = klr;
@@ -941,521 +938,196 @@ void camellia_setup256(const unsigned char *key, u32 *subkey)
     return;
 }
 
-void camellia_setup192(const unsigned char *key, u32 *subkey)
-{
-    unsigned char kk[32];
-    u32 krll, krlr, krrl,krrr;
-
-    memcpy(kk, key, 24);
-    memcpy((unsigned char *)&krll, key+16,4);
-    memcpy((unsigned char *)&krlr, key+20,4);
-    krrl = ~krll;
-    krrr = ~krlr;
-    memcpy(kk+24, (unsigned char *)&krrl, 4);
-    memcpy(kk+28, (unsigned char *)&krrr, 4);
-    camellia_setup256(kk, subkey);
-    return;
-}
-
-
-/**
- * Stuff related to camellia encryption/decryption
- *
- * "io" must be 4byte aligned and big-endian data.
- */
-void camellia_encrypt128(const u32 *subkey, u32 *io)
-{
-    u32 il, ir, t0, t1;
-
-    /* pre whitening but absorb kw2*/
-    io[0] ^= CamelliaSubkeyL(0);
-    io[1] ^= CamelliaSubkeyR(0);
-    /* main iteration */
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
-		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
-		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
-		     io[0],io[1],il,ir,t0,t1);
-
-    /* post whitening but kw4 */
-    io[2] ^= CamelliaSubkeyL(24);
-    io[3] ^= CamelliaSubkeyR(24);
-
-    t0 = io[0];
-    t1 = io[1];
-    io[0] = io[2];
-    io[1] = io[3];
-    io[2] = t0;
-    io[3] = t1;
-	
-    return;
-}
-
-void camellia_decrypt128(const u32 *subkey, u32 *io)
-{
-    u32 il,ir,t0,t1;               /* temporary valiables */
-    
-    /* pre whitening but absorb kw2*/
-    io[0] ^= CamelliaSubkeyL(24);
-    io[1] ^= CamelliaSubkeyR(24);
-
-    /* main iteration */
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
-		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
-		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
-		     io[0],io[1],il,ir,t0,t1);
-
-    /* post whitening but kw4 */
-    io[2] ^= CamelliaSubkeyL(0);
-    io[3] ^= CamelliaSubkeyR(0);
-
-    t0 = io[0];
-    t1 = io[1];
-    io[0] = io[2];
-    io[1] = io[3];
-    io[2] = t0;
-    io[3] = t1;
-
-    return;
-}
-
-/**
- * stuff for 192 and 256bit encryption/decryption
- */
-void camellia_encrypt256(const u32 *subkey, u32 *io)
-{
-    u32 il,ir,t0,t1;           /* temporary valiables */
-
-    /* pre whitening but absorb kw2*/
-    io[0] ^= CamelliaSubkeyL(0);
-    io[1] ^= CamelliaSubkeyR(0);
-
-    /* main iteration */
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
-		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
-		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(24),CamelliaSubkeyR(24),
-		 CamelliaSubkeyL(25),CamelliaSubkeyR(25),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(26),CamelliaSubkeyR(26),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(27),CamelliaSubkeyR(27),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(28),CamelliaSubkeyR(28),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(29),CamelliaSubkeyR(29),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(30),CamelliaSubkeyR(30),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(31),CamelliaSubkeyR(31),
-		     io[0],io[1],il,ir,t0,t1);
-
-    /* post whitening but kw4 */
-    io[2] ^= CamelliaSubkeyL(32);
-    io[3] ^= CamelliaSubkeyR(32);
-
-    t0 = io[0];
-    t1 = io[1];
-    io[0] = io[2];
-    io[1] = io[3];
-    io[2] = t0;
-    io[3] = t1;
-
-    return;
-}
-
-void camellia_decrypt256(const u32 *subkey, u32 *io)
+void
+camellia_set_key(struct camellia_ctx *ctx,
+		 unsigned length, const uint8_t *key)
 {
-    u32 il,ir,t0,t1;           /* temporary valiables */
-
-    /* pre whitening but absorb kw2*/
-    io[0] ^= CamelliaSubkeyL(32);
-    io[1] ^= CamelliaSubkeyR(32);
-	
-    /* main iteration */
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(31),CamelliaSubkeyR(31),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(30),CamelliaSubkeyR(30),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(29),CamelliaSubkeyR(29),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(28),CamelliaSubkeyR(28),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(27),CamelliaSubkeyR(27),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(26),CamelliaSubkeyR(26),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(25),CamelliaSubkeyR(25),
-		 CamelliaSubkeyL(24),CamelliaSubkeyR(24),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(23),CamelliaSubkeyR(23),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(22),CamelliaSubkeyR(22),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(21),CamelliaSubkeyR(21),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(20),CamelliaSubkeyR(20),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(19),CamelliaSubkeyR(19),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(18),CamelliaSubkeyR(18),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(17),CamelliaSubkeyR(17),
-		 CamelliaSubkeyL(16),CamelliaSubkeyR(16),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(15),CamelliaSubkeyR(15),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(14),CamelliaSubkeyR(14),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(13),CamelliaSubkeyR(13),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(12),CamelliaSubkeyR(12),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(11),CamelliaSubkeyR(11),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(10),CamelliaSubkeyR(10),
-		     io[0],io[1],il,ir,t0,t1);
-
-    CAMELLIA_FLS(io[0],io[1],io[2],io[3],
-		 CamelliaSubkeyL(9),CamelliaSubkeyR(9),
-		 CamelliaSubkeyL(8),CamelliaSubkeyR(8),
-		 t0,t1,il,ir);
-
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(7),CamelliaSubkeyR(7),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(6),CamelliaSubkeyR(6),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(5),CamelliaSubkeyR(5),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(4),CamelliaSubkeyR(4),
-		     io[0],io[1],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[0],io[1],
-		     CamelliaSubkeyL(3),CamelliaSubkeyR(3),
-		     io[2],io[3],il,ir,t0,t1);
-    CAMELLIA_ROUNDSM(io[2],io[3],
-		     CamelliaSubkeyL(2),CamelliaSubkeyR(2),
-		     io[0],io[1],il,ir,t0,t1);
-
-    /* post whitening but kw4 */
-    io[2] ^= CamelliaSubkeyL(0);
-    io[3] ^= CamelliaSubkeyR(0);
-
-    t0 = io[0];
-    t1 = io[1];
-    io[0] = io[2];
-    io[1] = io[3];
-    io[2] = t0;
-    io[3] = t1;
-
-    return;
-}
-
-/***
- *
- * API for compatibility
- */
-
-void Camellia_Ekeygen(const int keyBitLength, 
-		      const unsigned char *rawKey, 
-		      KEY_TABLE_TYPE keyTable)
-{
-    switch(keyBitLength) {
-    case 128:
-	camellia_setup128(rawKey, keyTable);
-	break;
-    case 192:
-	camellia_setup192(rawKey, keyTable);
-	break;
-    case 256:
-	camellia_setup256(rawKey, keyTable);
-	break;
-    default:
-	break;
+  uint32_t k[8];
+  k[0] = READ_UINT32(key);
+  k[1] = READ_UINT32(key +  4);
+  k[2] = READ_UINT32(key +  8);
+  k[3] = READ_UINT32(key + 12);
+  
+  if (length == 16)
+    {
+      ctx->camellia128 = 1;
+      camellia_setup128(ctx, k);
     }
-}
-
+  else
+    {
+      ctx->camellia128 = 0;
+      k[4] = READ_UINT32(key + 16);
+      k[5] = READ_UINT32(key + 20);
+
+      if (length == 24)
+	{
+	  k[6] = ~k[4];
+	  k[7] = ~k[5];
+	}
+      else
+	{
+	  assert (length == 32);
+	  k[6] = READ_UINT32(key + 24);
+	  k[7] = READ_UINT32(key + 28);
+	}
+      camellia_setup256(ctx, k);
+    }
+}	
 
-void Camellia_EncryptBlock(const int keyBitLength, 
-			   const unsigned char *plaintext, 
-			   const KEY_TABLE_TYPE keyTable, 
-			   unsigned char *ciphertext)
+void
+camellia_encrypt(const struct camellia_ctx *ctx,
+		 unsigned length, uint8_t *dst,
+		 const uint8_t *src)
 {
-    u32 tmp[4];
-
-    tmp[0] = GETU32(plaintext);
-    tmp[1] = GETU32(plaintext + 4);
-    tmp[2] = GETU32(plaintext + 8);
-    tmp[3] = GETU32(plaintext + 12);
-
-    switch (keyBitLength) {
-    case 128:
-	camellia_encrypt128(keyTable, tmp);
-	break;
-    case 192:
-	/* fall through */
-    case 256:
-	camellia_encrypt256(keyTable, tmp);
-	break;
-    default:
-	break;
+  FOR_BLOCKS(length, dst, src, CAMELLIA_BLOCK_SIZE)
+    {
+      uint32_t i0,i1,i2,i3;
+      uint32_t il,ir,t0,t1;
+      unsigned i;
+
+      i0 = READ_UINT32(src);
+      i1 = READ_UINT32(src +  4);
+      i2 = READ_UINT32(src +  8);
+      i3 = READ_UINT32(src + 12);
+      
+      /* pre whitening but absorb kw2*/
+      i0 ^= CamelliaSubkeyL(0);
+      i1 ^= CamelliaSubkeyR(0);
+
+      /* main iteration */
+
+      CAMELLIA_ROUNDSM(i0,i1,
+		       CamelliaSubkeyL(2),CamelliaSubkeyR(2),
+		       i2,i3,il,ir,t0,t1);
+      CAMELLIA_ROUNDSM(i2,i3,
+		       CamelliaSubkeyL(3),CamelliaSubkeyR(3),
+		       i0,i1,il,ir,t0,t1);
+      CAMELLIA_ROUNDSM(i0,i1,
+		       CamelliaSubkeyL(4),CamelliaSubkeyR(4),
+		       i2,i3,il,ir,t0,t1);
+      CAMELLIA_ROUNDSM(i2,i3,
+		       CamelliaSubkeyL(5),CamelliaSubkeyR(5),
+		       i0,i1,il,ir,t0,t1);
+      CAMELLIA_ROUNDSM(i0,i1,
+		       CamelliaSubkeyL(6),CamelliaSubkeyR(6),
+		       i2,i3,il,ir,t0,t1);
+      CAMELLIA_ROUNDSM(i2,i3,
+		       CamelliaSubkeyL(7),CamelliaSubkeyR(7),
+		       i0,i1,il,ir,t0,t1);
+
+      for (i = 0; i < 16 + 8 * !ctx->camellia128; i+= 8)
+	{
+	  CAMELLIA_FLS(i0,i1,i2,i3,
+		       CamelliaSubkeyL(i+8),CamelliaSubkeyR(i+8),
+		       CamelliaSubkeyL(i+9),CamelliaSubkeyR(i+9),
+		       t0,t1,il,ir);
+
+	  CAMELLIA_ROUNDSM(i0,i1,
+			   CamelliaSubkeyL(i+10),CamelliaSubkeyR(i+10),
+			   i2,i3,il,ir,t0,t1);
+	  CAMELLIA_ROUNDSM(i2,i3,
+			   CamelliaSubkeyL(i+11),CamelliaSubkeyR(i+11),
+			   i0,i1,il,ir,t0,t1);
+	  CAMELLIA_ROUNDSM(i0,i1,
+			   CamelliaSubkeyL(i+12),CamelliaSubkeyR(i+12),
+			   i2,i3,il,ir,t0,t1);
+	  CAMELLIA_ROUNDSM(i2,i3,
+			   CamelliaSubkeyL(i+13),CamelliaSubkeyR(i+13),
+			   i0,i1,il,ir,t0,t1);
+	  CAMELLIA_ROUNDSM(i0,i1,
+			   CamelliaSubkeyL(i+14),CamelliaSubkeyR(i+14),
+			   i2,i3,il,ir,t0,t1);
+	  CAMELLIA_ROUNDSM(i2,i3,
+			   CamelliaSubkeyL(i+15),CamelliaSubkeyR(i+15),
+			   i0,i1,il,ir,t0,t1);
+	}
+
+      /* post whitening but kw4 */
+      i2 ^= CamelliaSubkeyL(i+8);
+      i3 ^= CamelliaSubkeyR(i+8);
+
+      WRITE_UINT32(dst     , i2);
+      WRITE_UINT32(dst +  4, i3);
+      WRITE_UINT32(dst +  8, i0);
+      WRITE_UINT32(dst + 12, i1);
     }
-
-    PUTU32(ciphertext, tmp[0]);
-    PUTU32(ciphertext + 4, tmp[1]);
-    PUTU32(ciphertext + 8, tmp[2]);
-    PUTU32(ciphertext + 12, tmp[3]);
 }
 
-void Camellia_DecryptBlock(const int keyBitLength, 
-			   const unsigned char *ciphertext, 
-			   const KEY_TABLE_TYPE keyTable, 
-			   unsigned char *plaintext)
+void
+camellia_decrypt(const struct camellia_ctx *ctx,
+		 unsigned length, uint8_t *dst,
+		 const uint8_t *src)
 {
-    u32 tmp[4];
-
-    tmp[0] = GETU32(ciphertext);
-    tmp[1] = GETU32(ciphertext + 4);
-    tmp[2] = GETU32(ciphertext + 8);
-    tmp[3] = GETU32(ciphertext + 12);
-
-    switch (keyBitLength) {
-    case 128:
-	camellia_decrypt128(keyTable, tmp);
-	break;
-    case 192:
-	/* fall through */
-    case 256:
-	camellia_decrypt256(keyTable, tmp);
-	break;
-    default:
-	break;
+  FOR_BLOCKS(length, dst, src, CAMELLIA_BLOCK_SIZE)
+    {
+      uint32_t i0,i1,i2,i3;
+      uint32_t il,ir,t0,t1;
+      unsigned i;
+
+      i0 = READ_UINT32(src);
+      i1 = READ_UINT32(src +  4);
+      i2 = READ_UINT32(src +  8);
+      i3 = READ_UINT32(src + 12);
+      
+      i = ctx->camellia128 ? 24 : 32;
+
+      /* pre whitening but absorb kw2*/
+      i0 ^= CamelliaSubkeyL(i);
+      i1 ^= CamelliaSubkeyR(i);
+      /* main iteration */
+
+      for (i -= 8; i >= 8; i -= 8)
+	{	  
+	  CAMELLIA_ROUNDSM(i0,i1,
+			   CamelliaSubkeyL(i+7),CamelliaSubkeyR(i+7),
+			   i2,i3,il,ir,t0,t1);
+	  CAMELLIA_ROUNDSM(i2,i3,
+			   CamelliaSubkeyL(i+6),CamelliaSubkeyR(i+6),
+			   i0,i1,il,ir,t0,t1);
+	  CAMELLIA_ROUNDSM(i0,i1,
+			   CamelliaSubkeyL(i+5),CamelliaSubkeyR(i+5),
+			   i2,i3,il,ir,t0,t1);
+	  CAMELLIA_ROUNDSM(i2,i3,
+			   CamelliaSubkeyL(i+4),CamelliaSubkeyR(i+4),
+			   i0,i1,il,ir,t0,t1);
+	  CAMELLIA_ROUNDSM(i0,i1,
+			   CamelliaSubkeyL(i+3),CamelliaSubkeyR(i+3),
+			   i2,i3,il,ir,t0,t1);
+	  CAMELLIA_ROUNDSM(i2,i3,
+			   CamelliaSubkeyL(i+2),CamelliaSubkeyR(i+2),
+			   i0,i1,il,ir,t0,t1);
+
+	  CAMELLIA_FLS(i0,i1,i2,i3,
+		       CamelliaSubkeyL(i+1),CamelliaSubkeyR(i+1),
+		       CamelliaSubkeyL(i),CamelliaSubkeyR(i),
+		       t0,t1,il,ir);
+	}
+      CAMELLIA_ROUNDSM(i0,i1,
+		       CamelliaSubkeyL(7),CamelliaSubkeyR(7),
+		       i2,i3,il,ir,t0,t1);
+      CAMELLIA_ROUNDSM(i2,i3,
+		       CamelliaSubkeyL(6),CamelliaSubkeyR(6),
+		       i0,i1,il,ir,t0,t1);
+      CAMELLIA_ROUNDSM(i0,i1,
+		       CamelliaSubkeyL(5),CamelliaSubkeyR(5),
+		       i2,i3,il,ir,t0,t1);
+      CAMELLIA_ROUNDSM(i2,i3,
+		       CamelliaSubkeyL(4),CamelliaSubkeyR(4),
+		       i0,i1,il,ir,t0,t1);
+      CAMELLIA_ROUNDSM(i0,i1,
+		       CamelliaSubkeyL(3),CamelliaSubkeyR(3),
+		       i2,i3,il,ir,t0,t1);
+      CAMELLIA_ROUNDSM(i2,i3,
+		       CamelliaSubkeyL(2),CamelliaSubkeyR(2),
+		       i0,i1,il,ir,t0,t1);
+
+      /* post whitening but kw4 */
+      i2 ^= CamelliaSubkeyL(0);
+      i3 ^= CamelliaSubkeyR(0);
+
+      WRITE_UINT32(dst     , i2);
+      WRITE_UINT32(dst +  4, i3);
+      WRITE_UINT32(dst +  8, i0);
+      WRITE_UINT32(dst + 12, i1);
     }
-    PUTU32(plaintext, tmp[0]);
-    PUTU32(plaintext + 4, tmp[1]);
-    PUTU32(plaintext + 8, tmp[2]);
-    PUTU32(plaintext + 12, tmp[3]);
 }
diff --git a/camellia.h b/camellia.h
index 1ac16606..9f9ccc2e 100644
--- a/camellia.h
+++ b/camellia.h
@@ -1,8 +1,10 @@
-/* camellia.h	ver 1.2.0
+/* camellia.h
  *
  * Copyright (C) 2006,2007
  * NTT (Nippon Telegraph and Telephone Corporation).
  *
+ * Copyright (C) 2010 Niels M�ller
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -18,37 +20,80 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#ifndef HEADER_CAMELLIA_H
-#define HEADER_CAMELLIA_H
+#ifndef NETTLE_CAMELLIA_H_INCLUDED
+#define NETTLE_CAMELLIA_H_INCLUDED
 
-#ifdef  __cplusplus
+#include "nettle-types.h"
+
+#ifdef __cplusplus
 extern "C" {
 #endif
 
+/* Name mangling */
+#define camellia_set_key nettle_camellia_set_key
+#define camellia_encrypt nettle_camellia_encrypt
+#define camellia_decrypt nettle_camellia_decrypt
+
 #define CAMELLIA_BLOCK_SIZE 16
-#define CAMELLIA_TABLE_BYTE_LEN 272
-#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
+/* Valid key sizes are 128, 192 or 256 bits (16, 24 or 32 bytes) */
+#define CAMELLIA_MIN_KEY_SIZE 16
+#define CAMELLIA_MAX_KEY_SIZE 32
+#define CAMELLIA_KEY_SIZE 32
 
-typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN];
+struct camellia_ctx
+{
+  int camellia128;
 
+  /* For 128-bit keys, there are 18 regular rounds, pre- and
+     post-whitening, and two FL and FLINV rounds, using a total of 26
+     subkeys, each of 64 bit. For 192- and 256-bit keys, there are 6
+     additional regular rounds and one additional FL and FLINV, using
+     a total of 34 subkeys. */
+  /* The clever combination of subkeys imply one of the pre- and
+     post-whitening keys is folded fith the round keys, so that subkey
+     subkey #1 and the last one (#25 or #33) is not used. FIXME:
+     Renumber to eliminate them. */
+  /* FIXME: For 64-bit machines, don't split in 32-bit halves. */
+  uint32_t keys[34][2];
+};
 
-void Camellia_Ekeygen(const int keyBitLength,
-		      const unsigned char *rawKey, 
-		      KEY_TABLE_TYPE keyTable);
+void
+camellia_set_key(struct camellia_ctx *ctx,
+		 unsigned length, const uint8_t *key);
 
-void Camellia_EncryptBlock(const int keyBitLength,
-			   const unsigned char *plaintext, 
-			   const KEY_TABLE_TYPE keyTable, 
-			   unsigned char *cipherText);
+void
+camellia_encrypt(const struct camellia_ctx *ctx,
+		 unsigned length, uint8_t *dst,
+		 const uint8_t *src);
+void
+camellia_decrypt(const struct camellia_ctx *ctx,
+		 unsigned length, uint8_t *dst,
+		 const uint8_t *src);
 
-void Camellia_DecryptBlock(const int keyBitLength, 
-			   const unsigned char *cipherText, 
-			   const KEY_TABLE_TYPE keyTable, 
-			   unsigned char *plaintext);
+#if 0
+/* FIXME: Use a single crypt function, and let key setup for
+   decryption reverse the order of the subkeys. */
 
+void
+camellia_set_encrypt_key(struct camellia_ctx *ctx,
+			 unsigned length, const uint8_t *key);
 
+void
+camellia_set_decrypt_key(struct camellia_ctx *ctx,
+			 unsigned length, const uint8_t *key);
+
+void
+camellia_crypt(struct camellia_ctx *ctx,
+	       unsigned length, uint8_t *dst,
+	       const uint8_t *src);
+
+void
+camellia_invert_key(struct camellia_ctx *dst,
+		    const struct camellia_ctx *src);
+
+#endif
 #ifdef  __cplusplus
 }
 #endif
 
-#endif /* HEADER_CAMELLIA_H */
+#endif /* NETTLE_CAMELLIA_H_INCLUDED */
-- 
GitLab