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