From 982775563f27b0fa2b92f8d4df1a950f001949a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se>
Date: Thu, 10 Oct 2013 22:13:02 +0200
Subject: [PATCH] Reorganized camellia interface

Use distinct context structs and functions for camellia128 and
camellia256.
---
 ChangeLog                                     |  38 ++
 Makefile.in                                   |  12 +-
 camellia-absorb.c                             | 135 +++++++
 camellia-crypt-internal.c                     |   4 +-
 camellia-internal.h                           |  57 ++-
 camellia-meta.c => camellia-invert-key.c      |  30 +-
 camellia-set-encrypt-key.c                    | 336 ------------------
 camellia.h                                    | 111 ++++--
 camellia-crypt.c => camellia128-crypt.c       |  12 +-
 camellia128-meta.c                            |  54 +++
 camellia128-set-decrypt-key.c                 |  45 +++
 camellia128-set-encrypt-key.c                 | 113 ++++++
 camellia192-meta.c                            |  54 +++
 camellia256-crypt.c                           |  46 +++
 camellia256-meta.c                            |  54 +++
 ...ypt-key.c => camellia256-set-decrypt-key.c |  42 +--
 camellia256-set-encrypt-key.c                 | 157 ++++++++
 testsuite/camellia-test.c                     |  55 ++-
 x86/camellia-crypt-internal.asm               |   6 +-
 x86_64/camellia-crypt-internal.asm            |   8 +-
 20 files changed, 932 insertions(+), 437 deletions(-)
 create mode 100644 camellia-absorb.c
 rename camellia-meta.c => camellia-invert-key.c (66%)
 delete mode 100644 camellia-set-encrypt-key.c
 rename camellia-crypt.c => camellia128-crypt.c (85%)
 create mode 100644 camellia128-meta.c
 create mode 100644 camellia128-set-decrypt-key.c
 create mode 100644 camellia128-set-encrypt-key.c
 create mode 100644 camellia192-meta.c
 create mode 100644 camellia256-crypt.c
 create mode 100644 camellia256-meta.c
 rename camellia-set-decrypt-key.c => camellia256-set-decrypt-key.c (57%)
 create mode 100644 camellia256-set-encrypt-key.c

diff --git a/ChangeLog b/ChangeLog
index f0e7faa1..0409cab2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+2013-10-10  Niels Möller  <nisse@lysator.liu.se>
+
+	* Makefile.in (nettle_SOURCES): Updated list of camellia files.
+
+	* testsuite/camellia-test.c (test_invert): Updated for new
+	camellia interface.
+
+	* camellia.h: Reorganized camellia interface, with distinct
+	context structs and functions for camellia128 and camellia256.
+
+	* camellia-meta.c: Deleted file.
+	* camellia256-meta.c: New file.
+	* camellia192-meta.c: New file.
+	* camellia128-meta.c: New file.
+
+	* camellia-set-decrypt-key.c: Deleted file, code moved to:
+	* camellia128-set-decrypt-key.c: New file.
+	(camellia128_invert_key, camellia128_set_decrypt_key): New
+	functions.
+	* camellia256-set-decrypt-key.c: New file.
+	(camellia256_invert_key, camellia256_set_decrypt_key)
+	(camellia192_set_decrypt_key): New functions.
+	* camellia-invert-key.c (_camellia_invert_key): New file and
+	function.
+
+	* camellia-set-encrypt-key.c: Deleted file, code moved to:
+	* camellia128-set-encrypt-key.c: New file.
+	(camellia128_set_encrypt_key): New function.
+	* camellia256-set-encrypt-key.c: New file.
+	(_camellia256_set_encrypt_key, camellia256_set_encrypt_key)
+	(camellia192_set_encrypt_key): New functions.
+	* camellia-absorb.c (_camellia_absorb): New file and function.
+	* camellia-internal.h: Moved key schedule macros here.
+
+	* camellia-crypt.c: Deleted file, code moved to:
+	* camellia128-crypt.c (camellia128_crypt): New file and function.
+	* camellia256-crypt.c (camellia256_crypt): New file and function.
+
 2013-10-07  Niels Möller  <nisse@lysator.liu.se>
 
 	* configure.ac: Delete check for ALIGNOF_UINT64_T, no longer
diff --git a/Makefile.in b/Makefile.in
index 13acde64..53307238 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -76,9 +76,15 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
 		 arctwo.c arctwo-meta.c gosthash94-meta.c \
 		 base16-encode.c base16-decode.c base16-meta.c \
                  base64-encode.c base64-decode.c base64-meta.c \
-		 camellia-crypt.c camellia-crypt-internal.c \
-		 camellia-set-encrypt-key.c camellia-set-decrypt-key.c \
-		 camellia-table.c camellia-meta.c \
+		 camellia-crypt-internal.c camellia-table.c \
+		 camellia-absorb.c camellia-invert-key.c \
+		 camellia128-set-encrypt-key.c camellia128-crypt.c \
+		 camellia128-set-decrypt-key.c \
+		 camellia128-meta.c \
+		 camellia192-meta.c \
+		 camellia256-set-encrypt-key.c camellia256-crypt.c \
+		 camellia256-set-decrypt-key.c \
+		 camellia256-meta.c \
 		 cast128.c cast128-meta.c \
 		 blowfish.c \
 		 cbc.c ctr.c gcm.c gcm-aes.c \
diff --git a/camellia-absorb.c b/camellia-absorb.c
new file mode 100644
index 00000000..0d5cb769
--- /dev/null
+++ b/camellia-absorb.c
@@ -0,0 +1,135 @@
+/* camellia-absorb.c
+ *
+ * Final key setup processing for the camellia block cipher.
+ */
+/*
+ * 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
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * Algorithm Specification 
+ *  http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
+ */
+
+/* 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 "camellia-internal.h"
+
+#include "macros.h"
+
+void
+_camellia_absorb(unsigned nkeys, uint64_t *dst, uint64_t *subkey)
+{
+  uint64_t kw2, kw4;
+  uint32_t dw, tl, tr;
+  unsigned i;
+  
+  /* At this point, the subkey array contains the subkeys as described
+     in the spec, 26 for short keys and 34 for large keys. */
+
+  /* absorb kw2 to other subkeys */
+  kw2 = subkey[1];
+
+  subkey[3] ^= kw2;
+  subkey[5] ^= kw2;
+  subkey[7] ^= kw2;
+  for (i = 8; i < nkeys; i += 8)
+    {
+      /* FIXME: gcc for x86_32 is smart enough to fetch the 32 low bits
+	 and xor the result into the 32 high bits, but it still generates
+	 worse code than for explicit 32-bit operations. */
+      kw2 ^= (kw2 & ~subkey[i+1]) << 32;
+      dw = (kw2 & subkey[i+1]) >> 32; kw2 ^= ROTL32(1, dw); 
+
+      subkey[i+3] ^= kw2;
+      subkey[i+5] ^= kw2;
+      subkey[i+7] ^= kw2;
+    }
+  subkey[i] ^= kw2;
+  
+  /* absorb kw4 to other subkeys */  
+  kw4 = subkey[nkeys + 1];
+
+  for (i = nkeys - 8; i > 0; i -= 8)
+    {
+      subkey[i+6] ^= kw4;
+      subkey[i+4] ^= kw4;
+      subkey[i+2] ^= kw4;
+      kw4 ^= (kw4 & ~subkey[i]) << 32;
+      dw = (kw4 & subkey[i]) >> 32; kw4 ^= ROTL32(1, dw);      
+    }
+
+  subkey[6] ^= kw4;
+  subkey[4] ^= kw4;
+  subkey[2] ^= kw4;
+  subkey[0] ^= kw4;
+
+  /* key XOR is end of F-function */
+  dst[0] = subkey[0] ^ subkey[2];
+  dst[1] = subkey[3];
+
+  dst[2] = subkey[2] ^ subkey[4];
+  dst[3] = subkey[3] ^ subkey[5];
+  dst[4] = subkey[4] ^ subkey[6];
+  dst[5] = subkey[5] ^ subkey[7];
+
+  for (i = 8; i < nkeys; i += 8)
+    {
+      tl = (subkey[i+2] >> 32) ^ (subkey[i+2] & ~subkey[i]);
+      dw = tl & (subkey[i] >> 32);
+      tr = subkey[i+2] ^ ROTL32(1, dw);
+      dst[i-2] = subkey[i-2] ^ ( ((uint64_t) tl << 32) | tr);
+
+      dst[i-1] = subkey[i];
+      dst[i] = subkey[i+1];
+
+      tl = (subkey[i-1] >> 32) ^ (subkey[i-1] & ~subkey[i+1]);
+      dw = tl & (subkey[i+1] >> 32);
+      tr = subkey[i-1] ^ ROTL32(1, dw);
+      dst[i+1] = subkey[i+3] ^ ( ((uint64_t) tl << 32) | tr);
+
+      dst[i+2] = subkey[i+2] ^ subkey[i+4];
+      dst[i+3] = subkey[i+3] ^ subkey[i+5];
+      dst[i+4] = subkey[i+4] ^ subkey[i+6];
+      dst[i+5] = subkey[i+5] ^ subkey[i+7];
+    }
+  dst[i-2] = subkey[i-2];
+  dst[i-1] = subkey[i] ^ subkey[i-1];
+
+#if !HAVE_NATIVE_64_BIT
+  for (i = 0; i < nkeys; i += 8)
+    {
+      /* apply the inverse of the last half of F-function */
+      CAMELLIA_F_HALF_INV(dst[i+1]);
+      CAMELLIA_F_HALF_INV(dst[i+2]);
+      CAMELLIA_F_HALF_INV(dst[i+3]);
+      CAMELLIA_F_HALF_INV(dst[i+4]);
+      CAMELLIA_F_HALF_INV(dst[i+5]);
+      CAMELLIA_F_HALF_INV(dst[i+6]);
+    }
+#endif
+  
+}
diff --git a/camellia-crypt-internal.c b/camellia-crypt-internal.c
index 62090945..2d4e85be 100644
--- a/camellia-crypt-internal.c
+++ b/camellia-crypt-internal.c
@@ -123,7 +123,7 @@
 #endif
 
 void
-_camellia_crypt(unsigned rounds,
+_camellia_crypt(unsigned nkeys,
 		const uint64_t *keys,
 		const struct camellia_table *T,
 		size_t length, uint8_t *dst,
@@ -149,7 +149,7 @@ _camellia_crypt(unsigned rounds,
       CAMELLIA_ROUNDSM(T, i0, keys[5], i1);
       CAMELLIA_ROUNDSM(T, i1, keys[6], i0);
       
-      for (i = 0; i < rounds - 8; i+= 8)
+      for (i = 0; i < nkeys - 8; i+= 8)
 	{
 	  CAMELLIA_FL(i0, keys[i+7]);
 	  CAMELLIA_FLINV(i1, keys[i+8]);
diff --git a/camellia-internal.h b/camellia-internal.h
index 1ce600b8..824b6327 100644
--- a/camellia-internal.h
+++ b/camellia-internal.h
@@ -39,6 +39,8 @@
 
 /* Name mangling */
 #define _camellia_crypt _nettle_camellia_crypt
+#define _camellia_absorb _nettle_camellia_absorb
+#define _camellia_invert_key _nettle_camellia_invert_key
 #define _camellia_table _nettle_camellia_table
 
 /*
@@ -60,12 +62,65 @@ struct camellia_table
   uint32_t sp4404[256];
 };
 
+/* key constants */
+
+#define SIGMA1 0xA09E667F3BCC908BULL
+#define SIGMA2 0xB67AE8584CAA73B2ULL
+#define SIGMA3 0xC6EF372FE94F82BEULL
+#define SIGMA4 0x54FF53A5F1D36F1CULL
+#define SIGMA5 0x10E527FADE682D1DULL
+#define SIGMA6 0xB05688C2B3E6C1FDULL
+
+#define CAMELLIA_SP1110(INDEX) (_nettle_camellia_table.sp1110[(int)(INDEX)])
+#define CAMELLIA_SP0222(INDEX) (_nettle_camellia_table.sp0222[(int)(INDEX)])
+#define CAMELLIA_SP3033(INDEX) (_nettle_camellia_table.sp3033[(int)(INDEX)])
+#define CAMELLIA_SP4404(INDEX) (_nettle_camellia_table.sp4404[(int)(INDEX)])
+
+#define CAMELLIA_F(x, k, y) do {		\
+    uint32_t __yl, __yr;			\
+    uint64_t __i = (x) ^ (k);			\
+    __yl					\
+      = CAMELLIA_SP1110( __i & 0xff)		\
+      ^ CAMELLIA_SP0222((__i >> 24) & 0xff)	\
+      ^ CAMELLIA_SP3033((__i >> 16) & 0xff)	\
+      ^ CAMELLIA_SP4404((__i >> 8) & 0xff);	\
+    __yr					\
+      = CAMELLIA_SP1110( __i >> 56)		\
+      ^ CAMELLIA_SP0222((__i >> 48) & 0xff)	\
+      ^ CAMELLIA_SP3033((__i >> 40) & 0xff)	\
+      ^ CAMELLIA_SP4404((__i >> 32) & 0xff);	\
+    __yl ^= __yr;				\
+    __yr = ROTL32(24, __yr);			\
+    __yr ^= __yl;				\
+    (y) = ((uint64_t) __yl << 32) | __yr;	\
+  } while (0)
+
+#if ! HAVE_NATIVE_64_BIT
+#define CAMELLIA_F_HALF_INV(x) do {            \
+    uint32_t __t, __w;                         \
+    __t = (x) >> 32;                           \
+    __w = __t ^(x);                            \
+    __w = ROTL32(8, __w);                       \
+    (x) = ((uint64_t) __w << 32) | (__t ^ __w);        \
+  } while (0)
+#endif
+
 void
-_camellia_crypt(unsigned rounds, const uint64_t *keys,
+_camellia_crypt(unsigned nkeys, const uint64_t *keys,
 		const struct camellia_table *T,
 		size_t length, uint8_t *dst,
 		const uint8_t *src);
 
+/* The initial NKEYS + 2 subkeys in SUBKEY are reduced to the final
+   NKEYS subkeys stored in DST. SUBKEY data is modified in the
+   process. */
+void
+_camellia_absorb(unsigned nkeys, uint64_t *dst, uint64_t *subkey);
+
+void
+_camellia_invert_key(unsigned nkeys,
+		     uint64_t *dst, const uint64_t *src);
+
 extern const struct camellia_table _camellia_table;
 
 #endif /* NETTLE_CAMELLIA_INTERNAL_H_INCLUDED */
diff --git a/camellia-meta.c b/camellia-invert-key.c
similarity index 66%
rename from camellia-meta.c
rename to camellia-invert-key.c
index a8a8494b..b3b586fa 100644
--- a/camellia-meta.c
+++ b/camellia-invert-key.c
@@ -1,4 +1,7 @@
-/* camellia-meta.c */
+/* camellia-invert-key.c
+ *
+ * Inverting a key means reversing order of subkeys.
+ */
 
 /* nettle, low-level cryptographics library
  *
@@ -24,15 +27,20 @@
 # include "config.h"
 #endif
 
-#include "nettle-meta.h"
-
-#include "camellia.h"
-
-const struct nettle_cipher nettle_camellia128
-= _NETTLE_CIPHER_SEP_SET_KEY(camellia, CAMELLIA, 128);
+#include "camellia-internal.h"
 
-const struct nettle_cipher nettle_camellia192
-= _NETTLE_CIPHER_SEP_SET_KEY(camellia, CAMELLIA, 192);
+#define SWAP(a, b) \
+do { uint64_t t_swap = (a); (a) = (b); (b) = t_swap; } while(0)
 
-const struct nettle_cipher nettle_camellia256
-= _NETTLE_CIPHER_SEP_SET_KEY(camellia, CAMELLIA, 256);
+void
+_camellia_invert_key(unsigned nkeys,
+		     uint64_t *dst, const uint64_t *src)
+{
+  unsigned i;
+  if (dst == src)
+    for (i = 0; i < nkeys - 1 - i; i++)
+	SWAP (dst[i], dst[nkeys - 1- i]);
+  else
+    for (i = 0; i < nkeys; i++)
+      dst[i] = src[nkeys - 1 - i];
+}
diff --git a/camellia-set-encrypt-key.c b/camellia-set-encrypt-key.c
deleted file mode 100644
index 7dd90775..00000000
--- a/camellia-set-encrypt-key.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/* camellia-set-encrypt-key.c
- *
- * Key setup for the camellia block cipher.
- */
-/*
- * 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
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This 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 this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-/*
- * Algorithm Specification 
- *  http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
- */
-
-/* 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 <limits.h>
-
-#include "camellia-internal.h"
-
-#include "macros.h"
-
-/* key constants */
-
-#define SIGMA1 0xA09E667F3BCC908BULL
-#define SIGMA2 0xB67AE8584CAA73B2ULL
-#define SIGMA3 0xC6EF372FE94F82BEULL
-#define SIGMA4 0x54FF53A5F1D36F1CULL
-#define SIGMA5 0x10E527FADE682D1DULL
-#define SIGMA6 0xB05688C2B3E6C1FDULL
-
-#define CAMELLIA_SP1110(INDEX) (_nettle_camellia_table.sp1110[(int)(INDEX)])
-#define CAMELLIA_SP0222(INDEX) (_nettle_camellia_table.sp0222[(int)(INDEX)])
-#define CAMELLIA_SP3033(INDEX) (_nettle_camellia_table.sp3033[(int)(INDEX)])
-#define CAMELLIA_SP4404(INDEX) (_nettle_camellia_table.sp4404[(int)(INDEX)])
-
-#define CAMELLIA_F(x, k, y) do {		\
-    uint32_t __yl, __yr;			\
-    uint64_t __i = (x) ^ (k);			\
-    __yl					\
-      = CAMELLIA_SP1110( __i & 0xff)		\
-      ^ CAMELLIA_SP0222((__i >> 24) & 0xff)	\
-      ^ CAMELLIA_SP3033((__i >> 16) & 0xff)	\
-      ^ CAMELLIA_SP4404((__i >> 8) & 0xff);	\
-    __yr					\
-      = CAMELLIA_SP1110( __i >> 56)		\
-      ^ CAMELLIA_SP0222((__i >> 48) & 0xff)	\
-      ^ CAMELLIA_SP3033((__i >> 40) & 0xff)	\
-      ^ CAMELLIA_SP4404((__i >> 32) & 0xff);	\
-    __yl ^= __yr;				\
-    __yr = ROTL32(24, __yr);			\
-    __yr ^= __yl;				\
-    (y) = ((uint64_t) __yl << 32) | __yr;	\
-  } while (0)
-
-#if ! HAVE_NATIVE_64_BIT
-#define CAMELLIA_F_HALF_INV(x) do {            \
-    uint32_t __t, __w;                         \
-    __t = (x) >> 32;                           \
-    __w = __t ^(x);                            \
-    __w = ROTL32(8, __w);                       \
-    (x) = ((uint64_t) __w << 32) | (__t ^ __w);        \
-  } while (0)
-#endif
-
-void
-camellia_set_encrypt_key(struct camellia_ctx *ctx,
-			 size_t length, const uint8_t *key)
-{
-  uint64_t k0, k1;
-
-  uint64_t subkey[34];
-  uint64_t w, kw2, kw4;
-  
-  uint32_t dw, tl, tr;
-  unsigned i;
-
-  k0 = READ_UINT64(key);
-  k1 = READ_UINT64(key +  8);
-  
-  if (length == 16)
-    {
-      ctx->nkeys = 24;
-      /**
-       * generate KL dependent subkeys
-       */
-      subkey[0] = k0; subkey[1] = k1;
-      ROTL128(15, k0, k1);
-      subkey[4] = k0; subkey[5] = k1;
-      ROTL128(30, k0, k1);
-      subkey[10] = k0; subkey[11] = k1;
-      ROTL128(15, k0, k1);
-      subkey[13] = k1;
-      ROTL128(17, k0, k1);
-      subkey[16] = k0; subkey[17] = k1;
-      ROTL128(17, k0, k1);
-      subkey[18] = k0; subkey[19] = k1;
-      ROTL128(17, k0, k1);
-      subkey[22] = k0; subkey[23] = k1;
-
-      /* generate KA. D1 is k0, d2 is k1. */
-      /* FIXME: Make notation match the spec better. */
-      /* For the 128-bit case, KR = 0, the construction of KA reduces to:
-
-	 D1 = KL >> 64;
-	 W = KL & MASK64;
-	 D2 = F(D1, Sigma1);
-	 W = D2 ^ W
-	 D1 = F(W, Sigma2)
-	 D2 = D2 ^ F(D1, Sigma3);
-	 D1 = D1 ^ F(D2, Sigma4);
-	 KA = (D1 << 64) | D2;
-      */
-      k0 = subkey[0]; w = subkey[1];
-      CAMELLIA_F(k0, SIGMA1, k1);
-      w ^= k1;
-      CAMELLIA_F(w, SIGMA2, k0);
-      CAMELLIA_F(k0, SIGMA3, w);
-      k1 ^= w;
-      CAMELLIA_F(k1, SIGMA4, w);
-      k0 ^= w;
-
-      /* generate KA dependent subkeys */
-      subkey[2] = k0; subkey[3] = k1;
-      ROTL128(15, k0, k1);
-      subkey[6] = k0; subkey[7] = k1;
-      ROTL128(15, k0, k1);
-      subkey[8] = k0; subkey[9] = k1;
-      ROTL128(15, k0, k1);
-      subkey[12] = k0;
-      ROTL128(15, k0, k1);
-      subkey[14] = k0; subkey[15] = k1;
-      ROTL128(34, k0, k1);
-      subkey[20] = k0; subkey[21] = k1;
-      ROTL128(17, k0, k1);
-      subkey[24] = k0; subkey[25] = k1;
-    }
-  else
-    {
-      uint64_t k2, k3;
-
-      ctx->nkeys = 32;
-      k2 = READ_UINT64(key + 16);
-
-      if (length == 24)
-	k3 = ~k2;
-      else
-	{
-	  assert (length == 32);
-	  k3 = READ_UINT64(key + 24);
-	}
-      /* generate KL dependent subkeys */
-      subkey[0] = k0; subkey[1] = k1;
-      ROTL128(45, k0, k1);
-      subkey[12] = k0; subkey[13] = k1;
-      ROTL128(15, k0, k1);
-      subkey[16] = k0; subkey[17] = k1;
-      ROTL128(17, k0, k1);
-      subkey[22] = k0; subkey[23] = k1;
-      ROTL128(34, k0, k1);
-      subkey[30] = k0; subkey[31] = k1;
-
-      /* generate KR dependent subkeys */
-      ROTL128(15, k2, k3);
-      subkey[4] = k2; subkey[5] = k3;
-      ROTL128(15, k2, k3);
-      subkey[8] = k2; subkey[9] = k3;
-      ROTL128(30, k2, k3);
-      subkey[18] = k2; subkey[19] = k3;
-      ROTL128(34, k2, k3);
-      subkey[26] = k2; subkey[27] = k3;
-      ROTL128(34, k2, k3);
-
-      /* generate KA */
-      /* The construction of KA is done as
-
-	 D1 = (KL ^ KR) >> 64
-	 D2 = (KL ^ KR) & MASK64
-	 W = F(D1, SIGMA1)
-	 D2 = D2 ^ W
-	 D1 = F(D2, SIGMA2) ^ (KR >> 64)
-	 D2 = F(D1, SIGMA3) ^ W ^ (KR & MASK64)
-	 D1 = D1 ^ F(W, SIGMA2)
-	 D2 = D2 ^ F(D1, SIGMA3)
-	 D1 = D1 ^ F(D2, SIGMA4)
-      */
-
-      k0 = subkey[0] ^ k2;
-      k1 = subkey[1] ^ k3;
-
-      CAMELLIA_F(k0, SIGMA1, w);
-      k1 ^= w;
-
-      CAMELLIA_F(k1, SIGMA2, k0);
-      k0 ^= k2;
-
-      CAMELLIA_F(k0, SIGMA3, k1);
-      k1 ^= w ^ k3;
-
-      CAMELLIA_F(k1, SIGMA4, w);
-      k0 ^= w;
-
-      /* generate KB */
-      k2 ^= k0; k3 ^= k1;
-      CAMELLIA_F(k2, SIGMA5, w);
-      k3 ^= w;
-      CAMELLIA_F(k3, SIGMA6, w);
-      k2 ^= w;
-
-      /* generate KA dependent subkeys */
-      ROTL128(15, k0, k1);
-      subkey[6] = k0; subkey[7] = k1;
-      ROTL128(30, k0, k1);
-      subkey[14] = k0; subkey[15] = k1;
-      ROTL128(32, k0, k1);
-      subkey[24] = k0; subkey[25] = k1;
-      ROTL128(17, k0, k1);
-      subkey[28] = k0; subkey[29] = k1;
-
-      /* generate KB dependent subkeys */
-      subkey[2] = k2; subkey[3] = k3;
-      ROTL128(30, k2, k3);
-      subkey[10] = k2; subkey[11] = k3;
-      ROTL128(30, k2, k3);
-      subkey[20] = k2; subkey[21] = k3;
-      ROTL128(51, k2, k3);
-      subkey[32] = k2; subkey[33] = k3;
-    }
-
-  /* At this point, the subkey array contains the subkeys as described
-     in the spec, 26 for short keys and 34 for large keys. */
-
-  /* absorb kw2 to other subkeys */
-  kw2 = subkey[1];
-
-  subkey[3] ^= kw2;
-  subkey[5] ^= kw2;
-  subkey[7] ^= kw2;
-  for (i = 8; i < ctx->nkeys; i += 8)
-    {
-      /* FIXME: gcc for x86_32 is smart enough to fetch the 32 low bits
-	 and xor the result into the 32 high bits, but it still generates
-	 worse code than for explicit 32-bit operations. */
-      kw2 ^= (kw2 & ~subkey[i+1]) << 32;
-      dw = (kw2 & subkey[i+1]) >> 32; kw2 ^= ROTL32(1, dw); 
-
-      subkey[i+3] ^= kw2;
-      subkey[i+5] ^= kw2;
-      subkey[i+7] ^= kw2;
-    }
-  subkey[i] ^= kw2;
-  
-  /* absorb kw4 to other subkeys */  
-  kw4 = subkey[ctx->nkeys + 1];
-
-  for (i = ctx->nkeys - 8; i > 0; i -= 8)
-    {
-      subkey[i+6] ^= kw4;
-      subkey[i+4] ^= kw4;
-      subkey[i+2] ^= kw4;
-      kw4 ^= (kw4 & ~subkey[i]) << 32;
-      dw = (kw4 & subkey[i]) >> 32; kw4 ^= ROTL32(1, dw);      
-    }
-
-  subkey[6] ^= kw4;
-  subkey[4] ^= kw4;
-  subkey[2] ^= kw4;
-  subkey[0] ^= kw4;
-
-  /* key XOR is end of F-function */
-  ctx->keys[0] = subkey[0] ^ subkey[2];
-  ctx->keys[1] = subkey[3];
-
-  ctx->keys[2] = subkey[2] ^ subkey[4];
-  ctx->keys[3] = subkey[3] ^ subkey[5];
-  ctx->keys[4] = subkey[4] ^ subkey[6];
-  ctx->keys[5] = subkey[5] ^ subkey[7];
-
-  for (i = 8; i < ctx->nkeys; i += 8)
-    {
-      tl = (subkey[i+2] >> 32) ^ (subkey[i+2] & ~subkey[i]);
-      dw = tl & (subkey[i] >> 32);
-      tr = subkey[i+2] ^ ROTL32(1, dw);
-      ctx->keys[i-2] = subkey[i-2] ^ ( ((uint64_t) tl << 32) | tr);
-
-      ctx->keys[i-1] = subkey[i];
-      ctx->keys[i] = subkey[i+1];
-
-      tl = (subkey[i-1] >> 32) ^ (subkey[i-1] & ~subkey[i+1]);
-      dw = tl & (subkey[i+1] >> 32);
-      tr = subkey[i-1] ^ ROTL32(1, dw);
-      ctx->keys[i+1] = subkey[i+3] ^ ( ((uint64_t) tl << 32) | tr);
-
-      ctx->keys[i+2] = subkey[i+2] ^ subkey[i+4];
-      ctx->keys[i+3] = subkey[i+3] ^ subkey[i+5];
-      ctx->keys[i+4] = subkey[i+4] ^ subkey[i+6];
-      ctx->keys[i+5] = subkey[i+5] ^ subkey[i+7];
-    }
-  ctx->keys[i-2] = subkey[i-2];
-  ctx->keys[i-1] = subkey[i] ^ subkey[i-1];
-
-#if !HAVE_NATIVE_64_BIT
-  for (i = 0; i < ctx->nkeys; i += 8)
-    {
-      /* apply the inverse of the last half of F-function */
-      CAMELLIA_F_HALF_INV(ctx->keys[i+1]);
-      CAMELLIA_F_HALF_INV(ctx->keys[i+2]);
-      CAMELLIA_F_HALF_INV(ctx->keys[i+3]);
-      CAMELLIA_F_HALF_INV(ctx->keys[i+4]);
-      CAMELLIA_F_HALF_INV(ctx->keys[i+5]);
-      CAMELLIA_F_HALF_INV(ctx->keys[i+6]);
-    }
-#endif
-}
diff --git a/camellia.h b/camellia.h
index c0b45761..dcc43ae7 100644
--- a/camellia.h
+++ b/camellia.h
@@ -3,7 +3,7 @@
  * Copyright (C) 2006,2007
  * NTT (Nippon Telegraph and Telephone Corporation).
  *
- * Copyright (C) 2010 Niels Möller
+ * Copyright (C) 2010, 2013 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
@@ -30,51 +30,100 @@ extern "C" {
 #endif
 
 /* Name mangling */
-#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 camellia128_set_encrypt_key nettle_camellia128_set_encrypt_key
+#define camellia128_set_decrypt_key nettle_camellia_set_decrypt_key
+#define camellia128_invert_key nettle_camellia128_invert_key
+#define camellia128_crypt nettle_camellia128_crypt
+
+#define camellia192_set_encrypt_key nettle_camellia192_set_encrypt_key
+#define camellia192_set_decrypt_key nettle_camellia192_set_decrypt_key
+
+#define camellia256_set_encrypt_key nettle_camellia256_set_encrypt_key
+#define camellia256_set_decrypt_key nettle_camellia256_set_decrypt_key
+#define camellia256_invert_key nettle_camellia256_invert_key
+#define camellia256_crypt nettle_camellia256_crypt
+
 
 #define CAMELLIA_BLOCK_SIZE 16
 /* 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
+#define CAMELLIA128_KEY_SIZE 16
+#define CAMELLIA192_KEY_SIZE 24
+#define CAMELLIA256_KEY_SIZE 32
 
-struct camellia_ctx
+/* 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 with the round keys, so that subkey
+   #1 and the last one (#25 or #33) is not used. The result is that we
+   have only 24 or 32 subkeys at the end of key setup. */
+
+#define _CAMELLIA128_NKEYS 24
+#define _CAMELLIA256_NKEYS 32
+
+struct camellia128_ctx
 {
-  /* Number of subkeys. */
-  unsigned nkeys;
+  uint64_t keys[_CAMELLIA128_NKEYS];
+};
+
+void
+camellia128_set_encrypt_key(struct camellia128_ctx *ctx,
+			    const uint8_t *key);
+
+void
+camellia128_set_decrypt_key(struct camellia128_ctx *ctx,
+			    const uint8_t *key);
+
+void
+camellia128_invert_key(struct camellia128_ctx *dst,
+		       const struct camellia128_ctx *src);
   
-  /* 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 with the round keys, so that subkey
-     #1 and the last one (#25 or #33) is not used. The result is that
-     we have only 24 or 32 subkeys at the end of key setup. */
-  uint64_t keys[32];
+void
+camellia128_crypt(const struct camellia128_ctx *ctx,
+		  size_t length, uint8_t *dst,
+		  const uint8_t *src);
+
+struct camellia256_ctx
+{
+  uint64_t keys[_CAMELLIA256_NKEYS];
 };
 
 void
-camellia_set_encrypt_key(struct camellia_ctx *ctx,
-			 size_t length, const uint8_t *key);
+camellia256_set_encrypt_key(struct camellia256_ctx *ctx,
+			    const uint8_t *key);
 
 void
-camellia_set_decrypt_key(struct camellia_ctx *ctx,
-			 size_t length, const uint8_t *key);
+camellia256_set_decrypt_key(struct camellia256_ctx *ctx,
+			    const uint8_t *key);
 
 void
-camellia_invert_key(struct camellia_ctx *dst,
-		    const struct camellia_ctx *src);
+camellia256_invert_key(struct camellia256_ctx *dst,
+		       const struct camellia256_ctx *src);
   
 void
-camellia_crypt(const struct camellia_ctx *ctx,
-	       size_t length, uint8_t *dst,
-	       const uint8_t *src);
+camellia256_crypt(const struct camellia256_ctx *ctx,
+		  size_t length, uint8_t *dst,
+		  const uint8_t *src);
+
+/* camellia192 is the same as camellia256, except for the key
+   schedule. */
+/* Slightly ugly with a #define on a struct tag, since it might cause
+   surprises if also used as a name of a variable. */
+#define camellia192_ctx camellia256_ctx
+
+void
+camellia192_set_encrypt_key(struct camellia256_ctx *ctx,
+			    const uint8_t *key);
+
+void
+camellia192_set_decrypt_key(struct camellia256_ctx *ctx,
+			    const uint8_t *key);
+
+#define camellia192_invert_key camellia256_invert_key
+#define camellia192_crypt camellia256_crypt
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/camellia-crypt.c b/camellia128-crypt.c
similarity index 85%
rename from camellia-crypt.c
rename to camellia128-crypt.c
index de6d34b5..b9f355e9 100644
--- a/camellia-crypt.c
+++ b/camellia128-crypt.c
@@ -1,11 +1,11 @@
-/* camellia-encrypt.c
+/* camellia128-crypt.c
  *
  * Crypt function for the camellia block cipher.
  */
 
 /* nettle, low-level cryptographics library
  *
- * Copyright (C) 2010 Niels Möller
+ * Copyright (C) 2010, 2013 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
@@ -35,12 +35,12 @@
    implementations of _nettle_camellia_crypt to get the table pointer.
    For PIC code, the details can be complex and system dependent. */
 void
-camellia_crypt(const struct camellia_ctx *ctx,
-	       size_t length, uint8_t *dst,
-	       const uint8_t *src)
+camellia128_crypt(const struct camellia128_ctx *ctx,
+		  size_t length, uint8_t *dst,
+		  const uint8_t *src)
 {
   assert(!(length % CAMELLIA_BLOCK_SIZE) );
-  _camellia_crypt(ctx->nkeys, ctx->keys,
+  _camellia_crypt(_CAMELLIA128_NKEYS, ctx->keys,
 		  &_camellia_table,
 		  length, dst, src);
 }
diff --git a/camellia128-meta.c b/camellia128-meta.c
new file mode 100644
index 00000000..cac7b485
--- /dev/null
+++ b/camellia128-meta.c
@@ -0,0 +1,54 @@
+/* camellia128-meta.c */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2010, 2013 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "nettle-meta.h"
+
+#include "camellia.h"
+
+static void
+camellia128_set_encrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == CAMELLIA128_KEY_SIZE);
+  camellia128_set_encrypt_key (ctx, key);
+}
+
+static void
+camellia128_set_decrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == CAMELLIA128_KEY_SIZE);
+  camellia128_set_decrypt_key (ctx, key);
+}
+
+const struct nettle_cipher nettle_camellia128 =
+  { "camellia128", sizeof(struct camellia128_ctx),
+    CAMELLIA_BLOCK_SIZE, CAMELLIA128_KEY_SIZE,
+    camellia128_set_encrypt_key_wrapper,
+    camellia128_set_decrypt_key_wrapper,
+    (nettle_crypt_func *) camellia128_crypt,
+    (nettle_crypt_func *) camellia128_crypt
+  };
diff --git a/camellia128-set-decrypt-key.c b/camellia128-set-decrypt-key.c
new file mode 100644
index 00000000..afd93751
--- /dev/null
+++ b/camellia128-set-decrypt-key.c
@@ -0,0 +1,45 @@
+/* camellia128-set-decrypt-key.c
+ *
+ * Inverse key setup for the camellia block cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2010, 2013 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "camellia-internal.h"
+
+void
+camellia128_invert_key(struct camellia128_ctx *dst,
+		       const struct camellia128_ctx *src)
+{
+  _camellia_invert_key (_CAMELLIA128_NKEYS, dst->keys, src->keys);
+}
+
+void
+camellia128_set_decrypt_key(struct camellia128_ctx *ctx,
+			    const uint8_t *key)
+{
+  camellia128_set_encrypt_key(ctx, key);
+  camellia128_invert_key(ctx, ctx);
+}
diff --git a/camellia128-set-encrypt-key.c b/camellia128-set-encrypt-key.c
new file mode 100644
index 00000000..715828b4
--- /dev/null
+++ b/camellia128-set-encrypt-key.c
@@ -0,0 +1,113 @@
+/* camellia128-set-encrypt-key.c
+ *
+ * Key setup for the camellia block cipher.
+ */
+/*
+ * Copyright (C) 2006,2007
+ * NTT (Nippon Telegraph and Telephone Corporation).
+ *
+ * Copyright (C) 2010, 2013 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
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * Algorithm Specification 
+ *  http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
+ */
+
+/* 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 <limits.h>
+
+#include "camellia-internal.h"
+
+#include "macros.h"
+
+void
+camellia128_set_encrypt_key (struct camellia128_ctx *ctx,
+			     const uint8_t *key)
+{
+  uint64_t k0, k1;
+
+  uint64_t subkey[_CAMELLIA128_NKEYS + 2];
+  uint64_t w;
+
+  k0 = READ_UINT64(key);
+  k1 = READ_UINT64(key +  8);
+  
+  /**
+   * generate KL dependent subkeys
+   */
+  subkey[0] = k0; subkey[1] = k1;
+  ROTL128(15, k0, k1);
+  subkey[4] = k0; subkey[5] = k1;
+  ROTL128(30, k0, k1);
+  subkey[10] = k0; subkey[11] = k1;
+  ROTL128(15, k0, k1);
+  subkey[13] = k1;
+  ROTL128(17, k0, k1);
+  subkey[16] = k0; subkey[17] = k1;
+  ROTL128(17, k0, k1);
+  subkey[18] = k0; subkey[19] = k1;
+  ROTL128(17, k0, k1);
+  subkey[22] = k0; subkey[23] = k1;
+
+  /* generate KA. D1 is k0, d2 is k1. */
+  /* FIXME: Make notation match the spec better. */
+  /* For the 128-bit case, KR = 0, the construction of KA reduces to:
+
+     D1 = KL >> 64;
+     W = KL & MASK64;
+     D2 = F(D1, Sigma1);
+     W = D2 ^ W
+     D1 = F(W, Sigma2)
+     D2 = D2 ^ F(D1, Sigma3);
+     D1 = D1 ^ F(D2, Sigma4);
+     KA = (D1 << 64) | D2;
+  */
+  k0 = subkey[0]; w = subkey[1];
+  CAMELLIA_F(k0, SIGMA1, k1);
+  w ^= k1;
+  CAMELLIA_F(w, SIGMA2, k0);
+  CAMELLIA_F(k0, SIGMA3, w);
+  k1 ^= w;
+  CAMELLIA_F(k1, SIGMA4, w);
+  k0 ^= w;
+
+  /* generate KA dependent subkeys */
+  subkey[2] = k0; subkey[3] = k1;
+  ROTL128(15, k0, k1);
+  subkey[6] = k0; subkey[7] = k1;
+  ROTL128(15, k0, k1);
+  subkey[8] = k0; subkey[9] = k1;
+  ROTL128(15, k0, k1);
+  subkey[12] = k0;
+  ROTL128(15, k0, k1);
+  subkey[14] = k0; subkey[15] = k1;
+  ROTL128(34, k0, k1);
+  subkey[20] = k0; subkey[21] = k1;
+  ROTL128(17, k0, k1);
+  subkey[24] = k0; subkey[25] = k1;
+
+  /* Common final processing */
+  _camellia_absorb (_CAMELLIA128_NKEYS, ctx->keys, subkey);
+}
diff --git a/camellia192-meta.c b/camellia192-meta.c
new file mode 100644
index 00000000..bdb5c130
--- /dev/null
+++ b/camellia192-meta.c
@@ -0,0 +1,54 @@
+/* camellia192-meta.c */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2010, 2013 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "nettle-meta.h"
+
+#include "camellia.h"
+
+static void
+camellia192_set_encrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == CAMELLIA192_KEY_SIZE);
+  camellia192_set_encrypt_key (ctx, key);
+}
+
+static void
+camellia192_set_decrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == CAMELLIA192_KEY_SIZE);
+  camellia192_set_decrypt_key (ctx, key);
+}
+
+const struct nettle_cipher nettle_camellia192 =
+  { "camellia192", sizeof(struct camellia256_ctx),
+    CAMELLIA_BLOCK_SIZE, CAMELLIA192_KEY_SIZE,
+    camellia192_set_encrypt_key_wrapper,
+    camellia192_set_decrypt_key_wrapper,
+    (nettle_crypt_func *) camellia256_crypt,
+    (nettle_crypt_func *) camellia256_crypt
+  };
diff --git a/camellia256-crypt.c b/camellia256-crypt.c
new file mode 100644
index 00000000..de6d4daf
--- /dev/null
+++ b/camellia256-crypt.c
@@ -0,0 +1,46 @@
+/* camellia256-crypt.c
+ *
+ * Crypt function for the camellia block cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2010, 2013 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "camellia-internal.h"
+
+/* The main point on this function is to help the assembler
+   implementations of _nettle_camellia_crypt to get the table pointer.
+   For PIC code, the details can be complex and system dependent. */
+void
+camellia256_crypt(const struct camellia256_ctx *ctx,
+		  size_t length, uint8_t *dst,
+		  const uint8_t *src)
+{
+  assert(!(length % CAMELLIA_BLOCK_SIZE) );
+  _camellia_crypt(_CAMELLIA256_NKEYS, ctx->keys,
+		  &_camellia_table,
+		  length, dst, src);
+}
diff --git a/camellia256-meta.c b/camellia256-meta.c
new file mode 100644
index 00000000..1a1e2a2d
--- /dev/null
+++ b/camellia256-meta.c
@@ -0,0 +1,54 @@
+/* camellia256-meta.c */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2010, 2013 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "nettle-meta.h"
+
+#include "camellia.h"
+
+static void
+camellia256_set_encrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == CAMELLIA256_KEY_SIZE);
+  camellia256_set_encrypt_key (ctx, key);
+}
+
+static void
+camellia256_set_decrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == CAMELLIA256_KEY_SIZE);
+  camellia256_set_decrypt_key (ctx, key);
+}
+
+const struct nettle_cipher nettle_camellia256 =
+  { "camellia256", sizeof(struct camellia256_ctx),
+    CAMELLIA_BLOCK_SIZE, CAMELLIA256_KEY_SIZE,
+    camellia256_set_encrypt_key_wrapper,
+    camellia256_set_decrypt_key_wrapper,
+    (nettle_crypt_func *) camellia256_crypt,
+    (nettle_crypt_func *) camellia256_crypt
+  };
diff --git a/camellia-set-decrypt-key.c b/camellia256-set-decrypt-key.c
similarity index 57%
rename from camellia-set-decrypt-key.c
rename to camellia256-set-decrypt-key.c
index 329fa3c9..134fc311 100644
--- a/camellia-set-decrypt-key.c
+++ b/camellia256-set-decrypt-key.c
@@ -1,11 +1,11 @@
-/* camellia-set-decrypt-key.c
+/* camellia256-set-decrypt-key.c
  *
  * Inverse key setup for the camellia block cipher.
  */
 
 /* nettle, low-level cryptographics library
  *
- * Copyright (C) 2010 Niels Möller
+ * Copyright (C) 2010, 2013 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
@@ -27,35 +27,27 @@
 # include "config.h"
 #endif
 
-#include "camellia.h"
-
-#define SWAP(a, b) \
-do { uint64_t t_swap = (a); (a) = (b); (b) = t_swap; } while(0)
+#include "camellia-internal.h"
 
 void
-camellia_invert_key(struct camellia_ctx *dst,
-		    const struct camellia_ctx *src)
+camellia256_invert_key(struct camellia256_ctx *dst,
+		       const struct camellia256_ctx *src)
 {
-  unsigned nkeys = src->nkeys;
-  unsigned i;
-  if (dst == src)
-    {
-      for (i = 0; i < nkeys - 1 - i; i++)
-	SWAP(dst->keys[i], dst->keys[nkeys - 1 - i]);
-    }
-  else
-    {
-      dst->nkeys = nkeys;
+  _camellia_invert_key (_CAMELLIA256_NKEYS, dst->keys, src->keys);
+}
 
-      for (i = 0; i < nkeys; i++)
-	dst->keys[i] = src->keys[nkeys - 1 - i];
-    }
+void
+camellia256_set_decrypt_key(struct camellia256_ctx *ctx,
+			    const uint8_t *key)
+{
+  camellia256_set_encrypt_key(ctx, key);
+  camellia256_invert_key(ctx, ctx);
 }
 
 void
-camellia_set_decrypt_key(struct camellia_ctx *ctx,
-			 size_t length, const uint8_t *key)
+camellia192_set_decrypt_key(struct camellia256_ctx *ctx,
+			    const uint8_t *key)
 {
-  camellia_set_encrypt_key(ctx, length, key);
-  camellia_invert_key(ctx, ctx);
+  camellia192_set_encrypt_key(ctx, key);
+  camellia256_invert_key(ctx, ctx);
 }
diff --git a/camellia256-set-encrypt-key.c b/camellia256-set-encrypt-key.c
new file mode 100644
index 00000000..189ff5d2
--- /dev/null
+++ b/camellia256-set-encrypt-key.c
@@ -0,0 +1,157 @@
+/* camellia256-set-encrypt-key.c
+ *
+ * Key setup for the camellia block cipher.
+ */
+/*
+ * Copyright (C) 2006,2007
+ * NTT (Nippon Telegraph and Telephone Corporation).
+ *
+ * Copyright (C) 2010, 2013 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
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * Algorithm Specification 
+ *  http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
+ */
+
+/* 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 <limits.h>
+
+#include "camellia-internal.h"
+
+#include "macros.h"
+
+static void
+_camellia256_set_encrypt_key (struct camellia256_ctx *ctx,
+			      uint64_t k0, uint64_t k1,
+			      uint64_t k2, uint64_t k3)
+{
+  uint64_t subkey[_CAMELLIA256_NKEYS + 2];
+  uint64_t w;
+  
+  /* generate KL dependent subkeys */
+  subkey[0] = k0; subkey[1] = k1;
+  ROTL128(45, k0, k1);
+  subkey[12] = k0; subkey[13] = k1;
+  ROTL128(15, k0, k1);
+  subkey[16] = k0; subkey[17] = k1;
+  ROTL128(17, k0, k1);
+  subkey[22] = k0; subkey[23] = k1;
+  ROTL128(34, k0, k1);
+  subkey[30] = k0; subkey[31] = k1;
+
+  /* generate KR dependent subkeys */
+  ROTL128(15, k2, k3);
+  subkey[4] = k2; subkey[5] = k3;
+  ROTL128(15, k2, k3);
+  subkey[8] = k2; subkey[9] = k3;
+  ROTL128(30, k2, k3);
+  subkey[18] = k2; subkey[19] = k3;
+  ROTL128(34, k2, k3);
+  subkey[26] = k2; subkey[27] = k3;
+  ROTL128(34, k2, k3);
+
+  /* generate KA */
+  /* The construction of KA is done as
+
+     D1 = (KL ^ KR) >> 64
+     D2 = (KL ^ KR) & MASK64
+     W = F(D1, SIGMA1)
+     D2 = D2 ^ W
+     D1 = F(D2, SIGMA2) ^ (KR >> 64)
+     D2 = F(D1, SIGMA3) ^ W ^ (KR & MASK64)
+     D1 = D1 ^ F(W, SIGMA2)
+     D2 = D2 ^ F(D1, SIGMA3)
+     D1 = D1 ^ F(D2, SIGMA4)
+  */
+
+  k0 = subkey[0] ^ k2;
+  k1 = subkey[1] ^ k3;
+
+  CAMELLIA_F(k0, SIGMA1, w);
+  k1 ^= w;
+
+  CAMELLIA_F(k1, SIGMA2, k0);
+  k0 ^= k2;
+
+  CAMELLIA_F(k0, SIGMA3, k1);
+  k1 ^= w ^ k3;
+
+  CAMELLIA_F(k1, SIGMA4, w);
+  k0 ^= w;
+
+  /* generate KB */
+  k2 ^= k0; k3 ^= k1;
+  CAMELLIA_F(k2, SIGMA5, w);
+  k3 ^= w;
+  CAMELLIA_F(k3, SIGMA6, w);
+  k2 ^= w;
+
+  /* generate KA dependent subkeys */
+  ROTL128(15, k0, k1);
+  subkey[6] = k0; subkey[7] = k1;
+  ROTL128(30, k0, k1);
+  subkey[14] = k0; subkey[15] = k1;
+  ROTL128(32, k0, k1);
+  subkey[24] = k0; subkey[25] = k1;
+  ROTL128(17, k0, k1);
+  subkey[28] = k0; subkey[29] = k1;
+
+  /* generate KB dependent subkeys */
+  subkey[2] = k2; subkey[3] = k3;
+  ROTL128(30, k2, k3);
+  subkey[10] = k2; subkey[11] = k3;
+  ROTL128(30, k2, k3);
+  subkey[20] = k2; subkey[21] = k3;
+  ROTL128(51, k2, k3);
+  subkey[32] = k2; subkey[33] = k3;
+
+  /* Common final processing */
+  _camellia_absorb (_CAMELLIA256_NKEYS, ctx->keys, subkey);
+}
+
+void
+camellia256_set_encrypt_key(struct camellia256_ctx *ctx,
+			    const uint8_t *key)
+{
+  uint64_t k0, k1, k2, k3;
+  k0 = READ_UINT64(key);
+  k1 = READ_UINT64(key +  8);
+  k2 = READ_UINT64(key + 16);
+  k3 = READ_UINT64(key + 24);
+
+  _camellia256_set_encrypt_key (ctx, k0, k1, k2, k3);
+}
+
+void
+camellia192_set_encrypt_key(struct camellia256_ctx *ctx,
+			    const uint8_t *key)
+{
+  uint64_t k0, k1, k2;
+  k0 = READ_UINT64(key);
+  k1 = READ_UINT64(key +  8);
+  k2 = READ_UINT64(key + 16);
+
+  _camellia256_set_encrypt_key (ctx, k0, k1, k2, ~k2);
+}
diff --git a/testsuite/camellia-test.c b/testsuite/camellia-test.c
index 9a1cb8ca..f6c850a5 100644
--- a/testsuite/camellia-test.c
+++ b/testsuite/camellia-test.c
@@ -6,8 +6,6 @@ test_invert(const struct tstring *key,
 	    const struct tstring *cleartext,
 	    const struct tstring *ciphertext)
 {
-  struct camellia_ctx encrypt;
-  struct camellia_ctx decrypt;
   uint8_t *data;
   size_t length;
 
@@ -16,22 +14,49 @@ test_invert(const struct tstring *key,
 
   data = xalloc(length);
 
-  camellia_set_encrypt_key (&encrypt, key->length, key->data);
-  camellia_crypt (&encrypt, length, data, cleartext->data);
-  
-  if (!MEMEQ(length, data, ciphertext->data))
+  if (key->length == 16)
     {
-      tstring_print_hex(cleartext);
-      fprintf(stderr, "\nOutput: ");
-      print_hex(length, data);
-      fprintf(stderr, "\nExpected:");
-      tstring_print_hex(ciphertext);
-      fprintf(stderr, "\n");
-      FAIL();
+      struct camellia128_ctx encrypt;
+      struct camellia128_ctx decrypt;
+
+      camellia128_set_encrypt_key (&encrypt, key->data);
+      camellia128_crypt (&encrypt, length, data, cleartext->data);
+  
+      if (!MEMEQ(length, data, ciphertext->data))
+	{
+	fail_encrypt:
+	  tstring_print_hex(cleartext);
+	  fprintf(stderr, "\nOutput: ");
+	  print_hex(length, data);
+	  fprintf(stderr, "\nExpected:");
+	  tstring_print_hex(ciphertext);
+	  fprintf(stderr, "\n");
+	  FAIL();
+	}
+
+      camellia128_invert_key (&decrypt, &encrypt);
+      camellia128_crypt (&decrypt, length, data, data);
     }
+  else
+    {
+      struct camellia256_ctx encrypt;
+      struct camellia256_ctx decrypt;
 
-  camellia_invert_key (&decrypt, &encrypt);
-  camellia_crypt (&decrypt, length, data, data);
+      if (key->length == 24)
+	camellia192_set_encrypt_key (&encrypt, key->data);
+      else if (key->length == 32)
+	camellia256_set_encrypt_key (&encrypt, key->data);
+      else
+	abort ();
+
+      camellia256_crypt (&encrypt, length, data, cleartext->data);
+  
+      if (!MEMEQ(length, data, ciphertext->data))
+	goto fail_encrypt;
+
+      camellia256_invert_key (&decrypt, &encrypt);
+      camellia256_crypt (&decrypt, length, data, data);
+    }
 
   if (!MEMEQ(length, data, cleartext->data))
     {
diff --git a/x86/camellia-crypt-internal.asm b/x86/camellia-crypt-internal.asm
index 1d7290bc..77921fa4 100644
--- a/x86/camellia-crypt-internal.asm
+++ b/x86/camellia-crypt-internal.asm
@@ -40,7 +40,7 @@ define(<FRAME_H1>,	<12(%esp)>)
 define(<FRAME_CNT>,	<16(%esp)>)
 	
 C Arguments on stack.
-define(<FRAME_ROUNDS>,	<40(%esp)>)
+define(<FRAME_NKEYS>,	<40(%esp)>)
 define(<FRAME_KEYS>,	<44(%esp)>)
 define(<FRAME_TABLE>,	<48(%esp)>)
 define(<FRAME_LENGTH>,	<52(%esp)>)
@@ -137,7 +137,7 @@ define(<FLINV>, <
 
 .file "camellia-crypt-internal.asm"
 	
-	C _camellia_crypt(unsigned rounds, const uint64_t *keys,
+	C _camellia_crypt(unsigned nkeys, const uint64_t *keys,
 	C	          const struct camellia_table *T,
 	C	          size_t length, uint8_t *dst,
 	C	          uint8_t *src)
@@ -169,7 +169,7 @@ PROLOGUE(_nettle_camellia_crypt)
 	bswap	L1
 	addl	$16, FRAME_SRC
 	movl	FRAME_KEYS, KEY
-	movl	FRAME_ROUNDS, TMP
+	movl	FRAME_NKEYS, TMP
 	subl	$8, TMP
 	movl	TMP, FRAME_CNT
 	xorl	(KEY), L0
diff --git a/x86_64/camellia-crypt-internal.asm b/x86_64/camellia-crypt-internal.asm
index d78637f4..b8d201e3 100644
--- a/x86_64/camellia-crypt-internal.asm
+++ b/x86_64/camellia-crypt-internal.asm
@@ -26,7 +26,7 @@ C Camellia-256  543  461
 
 C Register usage:
 
-define(<ROUNDS>, <%rdi>)
+define(<NKEYS>, <%rdi>)
 define(<KEYS>, <%rsi>)
 define(<TABLE>, <%rdx>)
 define(<LENGTH>, <%rcx>)
@@ -117,7 +117,7 @@ C	xorl	XREG(TMP), XREG($1)
 
 	.file "camellia-crypt-internal.asm"
 	
-	C _camellia_crypt(unsigned rounds, const uint64_t *keys, 
+	C _camellia_crypt(unsigned nkeys, const uint64_t *keys, 
 	C	          const struct camellia_table *T,
 	C	          size_t length, uint8_t *dst,
 	C	          uint8_t *src)
@@ -133,7 +133,7 @@ PROLOGUE(_nettle_camellia_crypt)
 	push	%rbp
 	push	%r12
 	push	%r13
-	sub	$8, ROUNDS
+	sub	$8, NKEYS
 .Lblock_loop:
 	C Load data, note that we'll happily do unaligned loads
 	mov	(SRC), I0
@@ -141,7 +141,7 @@ PROLOGUE(_nettle_camellia_crypt)
 	mov	8(SRC), I1
 	bswap	I1
 	add	$16, SRC
-	mov	XREG(ROUNDS), XREG(CNT)
+	mov	XREG(NKEYS), XREG(CNT)
 	mov	KEYS, KEY
 
 	C 	Whitening using first subkey 
-- 
GitLab