diff --git a/ChangeLog b/ChangeLog
index 84f1af67da1b386e37aea2b7517b25cdcb644c68..25011669c384ae6b7594b96eec1394cf61062ccf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2010-07-20  Niels M�ller  <nisse@lysator.liu.se>
 
+	* camellia.h (struct camellia_ctx): Replaced flag camellia128 by
+	expanded key length nkeys.
+
+	* camellia.c (camellia_set_encrypt_key): Renamed, from...
+	(camellia_set_key): ... old name.
+	(camellia_invert_key): New function.
+	(camellia_set_decrypt_key): New function, using
+	camellia_invert_key.
+	(camellia_crypt): Renamed, from...
+	(camellia_encrypt): ... old name.
+	(camellia_decrypt): Deleted, no longer needed. camellia_crypt used
+	for both encryption and decryption.
+
 	* nettle-meta.h (_NETTLE_CIPHER_SEP_SET_KEY): New macro.
 
 	* dsa-keygen.c: Removed unnecessary include of memxor.h.
diff --git a/camellia-meta.c b/camellia-meta.c
index 0311af3317e55132fbed0cdb5c5b47cc56963db5..68eef3dde8566b8a72d7bc221d054a8179ca86de 100644
--- a/camellia-meta.c
+++ b/camellia-meta.c
@@ -29,10 +29,10 @@
 #include "camellia.h"
 
 const struct nettle_cipher nettle_camellia128
-= _NETTLE_CIPHER(camellia, CAMELLIA, 128);
+= _NETTLE_CIPHER_SEP_SET_KEY(camellia, CAMELLIA, 128);
 
 const struct nettle_cipher nettle_camellia192
-= _NETTLE_CIPHER(camellia, CAMELLIA, 192);
+= _NETTLE_CIPHER_SEP_SET_KEY(camellia, CAMELLIA, 192);
 
 const struct nettle_cipher nettle_camellia256
-= _NETTLE_CIPHER(camellia, CAMELLIA, 256);
+= _NETTLE_CIPHER_SEP_SET_KEY(camellia, CAMELLIA, 256);
diff --git a/camellia.c b/camellia.c
index 1325a93473344ac7e3c053964ec9182639fc81f1..44b6d9381591cab9e0b6caf7720c8d5fb8986e0c 100644
--- a/camellia.c
+++ b/camellia.c
@@ -751,7 +751,7 @@ camellia_setup256(struct camellia_ctx *ctx, uint64_t *key)
     subkey[4] ^= kw4;
     subkey[2] ^= kw4;
     subkey[0] ^= kw4;
-    
+
     /* key XOR is end of F-function */
     ctx->keys[0] = subkey[0] ^subkey[2];
     
@@ -818,7 +818,7 @@ camellia_setup256(struct camellia_ctx *ctx, uint64_t *key)
     ctx->keys[31] = subkey[30];
     ctx->keys[32] = subkey[32] ^ subkey[31];
 
-    /* apply the inverse of the last half of P-function */
+    /* apply the inverse of the last half of F-function */
     CAMELLIA_F_HALF_INV(ctx->keys[2]);
     CAMELLIA_F_HALF_INV(ctx->keys[3]);
     CAMELLIA_F_HALF_INV(ctx->keys[4]);
@@ -851,8 +851,8 @@ camellia_setup256(struct camellia_ctx *ctx, uint64_t *key)
 }
 
 void
-camellia_set_key(struct camellia_ctx *ctx,
-		 unsigned length, const uint8_t *key)
+camellia_set_encrypt_key(struct camellia_ctx *ctx,
+			 unsigned length, const uint8_t *key)
 {
   uint64_t k[4];
   k[0] = READ_UINT64(key);
@@ -860,12 +860,12 @@ camellia_set_key(struct camellia_ctx *ctx,
   
   if (length == 16)
     {
-      ctx->camellia128 = 1;
+      ctx->nkeys = 26;
       camellia_setup128(ctx, k);
     }
   else
     {
-      ctx->camellia128 = 0;
+      ctx->nkeys = 34;
       k[2] = READ_UINT64(key + 16);
 
       if (length == 24)
@@ -877,10 +877,43 @@ camellia_set_key(struct camellia_ctx *ctx,
 	}
       camellia_setup256(ctx, k);
     }
-}	
+}
+
+#define SWAP(a, b) \
+do { uint64_t t_swap = (a); (a) = (b); (b) = t_swap; } while(0)
+
+void
+camellia_invert_key(struct camellia_ctx *dst,
+		    const struct camellia_ctx *src)
+{
+  unsigned nkeys = src->nkeys;
+  unsigned i;
+  if (dst == src)
+    {
+      SWAP(dst->keys[0], dst->keys[nkeys - 2]);
+      for (i = 2; i < nkeys - 1 - i; i++)
+	SWAP(dst->keys[i], dst->keys[nkeys - 1 - i]);
+    }
+  else
+    {
+      dst->nkeys = nkeys;
+      dst->keys[0] = src->keys[nkeys - 2];
+      for (i = 2; i < nkeys - 2; i++)
+	dst->keys[i] = src->keys[nkeys - 1 - i];
+      dst->keys[nkeys - 2] = src->keys[0];
+    }
+}
 
 void
-camellia_encrypt(const struct camellia_ctx *ctx,
+camellia_set_decrypt_key(struct camellia_ctx *ctx,
+			 unsigned length, const uint8_t *key)
+{
+  camellia_set_encrypt_key(ctx, length, key);
+  camellia_invert_key(ctx, ctx);
+}
+
+void
+camellia_crypt(const struct camellia_ctx *ctx,
 		 unsigned length, uint8_t *dst,
 		 const uint8_t *src)
 {
@@ -904,7 +937,7 @@ camellia_encrypt(const struct camellia_ctx *ctx,
       CAMELLIA_ROUNDSM(i0,ctx->keys[6], i1);
       CAMELLIA_ROUNDSM(i1,ctx->keys[7], i0);
       
-      for (i = 0; i < 16 + 8 * !ctx->camellia128; i+= 8)
+      for (i = 0; i < ctx->nkeys - 10; i+= 8)
 	{
 	  CAMELLIA_FL(i0, ctx->keys[i+8]);
 	  CAMELLIA_FLINV(i1, ctx->keys[i+9]);
@@ -924,50 +957,3 @@ camellia_encrypt(const struct camellia_ctx *ctx,
       WRITE_UINT64(dst +  8, i0);
     }
 }
-
-void
-camellia_decrypt(const struct camellia_ctx *ctx,
-		 unsigned length, uint8_t *dst,
-		 const uint8_t *src)
-{
-  FOR_BLOCKS(length, dst, src, CAMELLIA_BLOCK_SIZE)
-    {
-      uint64_t i0,i1;
-      unsigned i;
-
-      i0 = READ_UINT64(src);
-      i1 = READ_UINT64(src +  8);
-      
-      i = ctx->camellia128 ? 24 : 32;
-
-      /* pre whitening but absorb kw2*/
-      i0 ^= ctx->keys[i];
-
-      /* main iteration */
-
-      for (i -= 8; i >= 8; i -= 8)
-	{	  
-	  CAMELLIA_ROUNDSM(i0,ctx->keys[i+7], i1);
-	  CAMELLIA_ROUNDSM(i1,ctx->keys[i+6], i0);
-	  CAMELLIA_ROUNDSM(i0,ctx->keys[i+5], i1);
-	  CAMELLIA_ROUNDSM(i1,ctx->keys[i+4], i0);
-	  CAMELLIA_ROUNDSM(i0,ctx->keys[i+3], i1);
-	  CAMELLIA_ROUNDSM(i1,ctx->keys[i+2], i0);
-
-	  CAMELLIA_FL(i0, ctx->keys[i+1]);
-	  CAMELLIA_FLINV(i1, ctx->keys[i]);
-	}
-      CAMELLIA_ROUNDSM(i0,ctx->keys[7], i1);
-      CAMELLIA_ROUNDSM(i1,ctx->keys[6], i0);
-      CAMELLIA_ROUNDSM(i0,ctx->keys[5], i1);
-      CAMELLIA_ROUNDSM(i1,ctx->keys[4], i0);
-      CAMELLIA_ROUNDSM(i0,ctx->keys[3], i1);
-      CAMELLIA_ROUNDSM(i1,ctx->keys[2], i0);
-
-      /* post whitening but kw4 */
-      i1 ^= ctx->keys[0];
-
-      WRITE_UINT64(dst     , i1);
-      WRITE_UINT64(dst +  8, i0);
-    }
-}
diff --git a/camellia.h b/camellia.h
index 11ab593de555c052cca3e83a421d2f498f2f6c48..db26628766ae5736597db16006f2b8c2a92776bd 100644
--- a/camellia.h
+++ b/camellia.h
@@ -30,9 +30,11 @@ 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_set_encrypt_key nettle_camellia_set_encrypt_key
+#define camellia_set_decrypt_key nettle_camellia_set_decrypt_key
+#define camellia_invert_key nettle_camellia_invert_key
+#define camellia_crypt nettle_camellia_crypt
+#define camellia_crypt nettle_camellia_crypt
 
 #define CAMELLIA_BLOCK_SIZE 16
 /* Valid key sizes are 128, 192 or 256 bits (16, 24 or 32 bytes) */
@@ -42,37 +44,21 @@ extern "C" {
 
 struct camellia_ctx
 {
-  int camellia128;
-
+  /* Number of subkeys. */
+  unsigned nkeys;
+  
   /* 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. */
+     post-whitening keys is folded with the round keys, so that subkey
+     #1 and the last one (#25 or #33) is not used. FIXME: Renumber to
+     eliminate them. */
   uint64_t keys[34];
 };
 
-void
-camellia_set_key(struct camellia_ctx *ctx,
-		 unsigned length, const uint8_t *key);
-
-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);
-
-#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);
@@ -81,16 +67,14 @@ 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
+  
+void
+camellia_crypt(const struct camellia_ctx *ctx,
+	       unsigned length, uint8_t *dst,
+	       const uint8_t *src);
 #ifdef  __cplusplus
 }
 #endif