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