1162911Ssimon/* crypto/camellia/camellia.c -*- mode:C; c-file-style: "eay" -*- */
2162911Ssimon/* ====================================================================
3296341Sdelphij * Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) .
4162911Ssimon * ALL RIGHTS RESERVED.
5162911Ssimon *
6162911Ssimon * Intellectual Property information for Camellia:
7162911Ssimon *     http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html
8162911Ssimon *
9162911Ssimon * News Release for Announcement of Camellia open source:
10162911Ssimon *     http://www.ntt.co.jp/news/news06e/0604/060413a.html
11162911Ssimon *
12162911Ssimon * The Camellia Code included herein is developed by
13162911Ssimon * NTT (Nippon Telegraph and Telephone Corporation), and is contributed
14162911Ssimon * to the OpenSSL project.
15162911Ssimon *
16162911Ssimon * The Camellia Code is licensed pursuant to the OpenSSL open source
17162911Ssimon * license provided below.
18162911Ssimon */
19162911Ssimon/* ====================================================================
20162911Ssimon * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
21162911Ssimon *
22162911Ssimon * Redistribution and use in source and binary forms, with or without
23162911Ssimon * modification, are permitted provided that the following conditions
24162911Ssimon * are met:
25162911Ssimon *
26162911Ssimon * 1. Redistributions of source code must retain the above copyright
27296341Sdelphij *    notice, this list of conditions and the following disclaimer.
28162911Ssimon *
29162911Ssimon * 2. Redistributions in binary form must reproduce the above copyright
30162911Ssimon *    notice, this list of conditions and the following disclaimer in
31162911Ssimon *    the documentation and/or other materials provided with the
32162911Ssimon *    distribution.
33162911Ssimon *
34162911Ssimon * 3. All advertising materials mentioning features or use of this
35162911Ssimon *    software must display the following acknowledgment:
36162911Ssimon *    "This product includes software developed by the OpenSSL Project
37162911Ssimon *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
38162911Ssimon *
39162911Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
40162911Ssimon *    endorse or promote products derived from this software without
41162911Ssimon *    prior written permission. For written permission, please contact
42162911Ssimon *    openssl-core@openssl.org.
43162911Ssimon *
44162911Ssimon * 5. Products derived from this software may not be called "OpenSSL"
45162911Ssimon *    nor may "OpenSSL" appear in their names without prior written
46162911Ssimon *    permission of the OpenSSL Project.
47162911Ssimon *
48162911Ssimon * 6. Redistributions of any form whatsoever must retain the following
49162911Ssimon *    acknowledgment:
50162911Ssimon *    "This product includes software developed by the OpenSSL Project
51162911Ssimon *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
52162911Ssimon *
53162911Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
54162911Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55162911Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56162911Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
57162911Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
58162911Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59162911Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
60162911Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61162911Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
62162911Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63162911Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
64162911Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
65162911Ssimon * ====================================================================
66162911Ssimon */
67162911Ssimon
68238405Sjkim/*
69296341Sdelphij * Algorithm Specification
70296341Sdelphij * http://info.isl.llia/specicrypt/eng/camellia/specifications.html
71296341Sdelphij */
72296341Sdelphij
73296341Sdelphij/*
74238405Sjkim * This release balances code size and performance. In particular key
75238405Sjkim * schedule setup is fully unrolled, because doing so *significantly*
76238405Sjkim * reduces amount of instructions per setup round and code increase is
77238405Sjkim * justifiable. In block functions on the other hand only inner loops
78238405Sjkim * are unrolled, as full unroll gives only nominal performance boost,
79238405Sjkim * while code size grows 4 or 7 times. Also, unlike previous versions
80238405Sjkim * this one "encourages" compiler to keep intermediate variables in
81238405Sjkim * registers, which should give better "all round" results, in other
82238405Sjkim * words reasonable performance even with not so modern compilers.
83238405Sjkim */
84162911Ssimon
85238405Sjkim#include "camellia.h"
86238405Sjkim#include "cmll_locl.h"
87162911Ssimon#include <string.h>
88162911Ssimon#include <stdlib.h>
89162911Ssimon
90238405Sjkim/* 32-bit rotations */
91238405Sjkim#if !defined(PEDANTIC) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
92238405Sjkim# if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
93238405Sjkim#  define RightRotate(x, s) _lrotr(x, s)
94238405Sjkim#  define LeftRotate(x, s)  _lrotl(x, s)
95238405Sjkim#  if _MSC_VER >= 1400
96238405Sjkim#   define SWAP(x) _byteswap_ulong(x)
97238405Sjkim#  else
98238405Sjkim#   define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
99238405Sjkim#  endif
100238405Sjkim#  define GETU32(p)   SWAP(*((u32 *)(p)))
101238405Sjkim#  define PUTU32(p,v) (*((u32 *)(p)) = SWAP((v)))
102238405Sjkim# elif defined(__GNUC__) && __GNUC__>=2
103238405Sjkim#  if defined(__i386) || defined(__x86_64)
104238405Sjkim#   define RightRotate(x,s) ({u32 ret; asm ("rorl %1,%0":"=r"(ret):"I"(s),"0"(x):"cc"); ret; })
105238405Sjkim#   define LeftRotate(x,s)  ({u32 ret; asm ("roll %1,%0":"=r"(ret):"I"(s),"0"(x):"cc"); ret; })
106296341Sdelphij#   if defined(B_ENDIAN)        /* stratus.com does it */
107238405Sjkim#    define GETU32(p)   (*(u32 *)(p))
108238405Sjkim#    define PUTU32(p,v) (*(u32 *)(p)=(v))
109238405Sjkim#   else
110238405Sjkim#    define GETU32(p)   ({u32 r=*(const u32 *)(p); asm("bswapl %0":"=r"(r):"0"(r)); r; })
111238405Sjkim#    define PUTU32(p,v) ({u32 r=(v); asm("bswapl %0":"=r"(r):"0"(r)); *(u32 *)(p)=r; })
112238405Sjkim#   endif
113238405Sjkim#  elif defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
114238405Sjkim        defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__)
115238405Sjkim#   define LeftRotate(x,s)  ({u32 ret; asm ("rlwinm %0,%1,%2,0,31":"=r"(ret):"r"(x),"I"(s)); ret; })
116238405Sjkim#   define RightRotate(x,s) LeftRotate(x,(32-s))
117238405Sjkim#  elif defined(__s390x__)
118238405Sjkim#   define LeftRotate(x,s)  ({u32 ret; asm ("rll %0,%1,%2":"=r"(ret):"r"(x),"I"(s)); ret; })
119238405Sjkim#   define RightRotate(x,s) LeftRotate(x,(32-s))
120238405Sjkim#   define GETU32(p)   (*(u32 *)(p))
121238405Sjkim#   define PUTU32(p,v) (*(u32 *)(p)=(v))
122238405Sjkim#  endif
123238405Sjkim# endif
124238405Sjkim#endif
125162911Ssimon
126238405Sjkim#if !defined(RightRotate) && !defined(LeftRotate)
127238405Sjkim# define RightRotate(x, s) ( ((x) >> (s)) + ((x) << (32 - s)) )
128238405Sjkim# define LeftRotate(x, s)  ( ((x) << (s)) + ((x) >> (32 - s)) )
129238405Sjkim#endif
130162911Ssimon
131238405Sjkim#if !defined(GETU32) && !defined(PUTU32)
132238405Sjkim# define GETU32(p)   (((u32)(p)[0] << 24) ^ ((u32)(p)[1] << 16) ^ ((u32)(p)[2] <<  8) ^ ((u32)(p)[3]))
133238405Sjkim# define PUTU32(p,v) ((p)[0] = (u8)((v) >> 24), (p)[1] = (u8)((v) >> 16), (p)[2] = (u8)((v) >>  8), (p)[3] = (u8)(v))
134238405Sjkim#endif
135162911Ssimon
136238405Sjkim/* S-box data */
137238405Sjkim#define SBOX1_1110 Camellia_SBOX[0]
138238405Sjkim#define SBOX4_4404 Camellia_SBOX[1]
139238405Sjkim#define SBOX2_0222 Camellia_SBOX[2]
140238405Sjkim#define SBOX3_3033 Camellia_SBOX[3]
141238405Sjkimstatic const u32 Camellia_SBOX[][256] = {
142296341Sdelphij    {0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700,
143296341Sdelphij     0xc0c0c000, 0xe5e5e500, 0xe4e4e400, 0x85858500, 0x57575700, 0x35353500,
144296341Sdelphij     0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, 0x23232300, 0xefefef00,
145296341Sdelphij     0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100,
146296341Sdelphij     0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500,
147296341Sdelphij     0x92929200, 0xbdbdbd00, 0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00,
148296341Sdelphij     0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, 0x3e3e3e00, 0x30303000,
149296341Sdelphij     0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00,
150296341Sdelphij     0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700,
151296341Sdelphij     0x5d5d5d00, 0x3d3d3d00, 0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600,
152296341Sdelphij     0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, 0x8b8b8b00, 0x0d0d0d00,
153296341Sdelphij     0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00,
154296341Sdelphij     0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100,
155296341Sdelphij     0x84848400, 0x99999900, 0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200,
156296341Sdelphij     0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, 0x6d6d6d00, 0xb7b7b700,
157296341Sdelphij     0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700,
158296341Sdelphij     0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00,
159296341Sdelphij     0x11111100, 0x1c1c1c00, 0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600,
160296341Sdelphij     0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, 0xfefefe00, 0x44444400,
161296341Sdelphij     0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100,
162296341Sdelphij     0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00,
163296341Sdelphij     0x69696900, 0x50505000, 0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00,
164296341Sdelphij     0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, 0x54545400, 0x5b5b5b00,
165296341Sdelphij     0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200,
166296341Sdelphij     0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700,
167296341Sdelphij     0x75757500, 0xdbdbdb00, 0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00,
168296341Sdelphij     0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, 0x87878700, 0x5c5c5c00,
169296341Sdelphij     0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300,
170296341Sdelphij     0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00,
171296341Sdelphij     0xbfbfbf00, 0xe2e2e200, 0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600,
172296341Sdelphij     0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, 0x81818100, 0x96969600,
173296341Sdelphij     0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00,
174296341Sdelphij     0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00,
175296341Sdelphij     0xbcbcbc00, 0x8e8e8e00, 0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600,
176296341Sdelphij     0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, 0x78787800, 0x98989800,
177296341Sdelphij     0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00,
178296341Sdelphij     0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200,
179296341Sdelphij     0x8d8d8d00, 0xfafafa00, 0x72727200, 0x07070700, 0xb9b9b900, 0x55555500,
180296341Sdelphij     0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, 0x36363600, 0x49494900,
181296341Sdelphij     0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400,
182296341Sdelphij     0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900,
183296341Sdelphij     0x43434300, 0xc1c1c100, 0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400,
184296341Sdelphij     0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00},
185296341Sdelphij    {0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057,
186296341Sdelphij     0xeaea00ea, 0xaeae00ae, 0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5,
187296341Sdelphij     0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, 0x86860086, 0xafaf00af,
188296341Sdelphij     0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b,
189296341Sdelphij     0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a,
190296341Sdelphij     0x51510051, 0x6c6c006c, 0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0,
191296341Sdelphij     0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, 0xdfdf00df, 0xcbcb00cb,
192296341Sdelphij     0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004,
193296341Sdelphij     0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c,
194296341Sdelphij     0x53530053, 0xf2f200f2, 0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a,
195296341Sdelphij     0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, 0xaaaa00aa, 0xa0a000a0,
196296341Sdelphij     0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064,
197296341Sdelphij     0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6,
198296341Sdelphij     0x09090009, 0xdddd00dd, 0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090,
199296341Sdelphij     0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, 0x52520052, 0xd8d800d8,
200296341Sdelphij     0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063,
201296341Sdelphij     0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9,
202296341Sdelphij     0x2f2f002f, 0xb4b400b4, 0x78780078, 0x06060006, 0xe7e700e7, 0x71710071,
203296341Sdelphij     0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, 0x72720072, 0xb9b900b9,
204296341Sdelphij     0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1,
205296341Sdelphij     0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad,
206296341Sdelphij     0x77770077, 0x80800080, 0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5,
207296341Sdelphij     0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, 0xefef00ef, 0x93930093,
208296341Sdelphij     0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd,
209296341Sdelphij     0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f,
210296341Sdelphij     0xc5c500c5, 0x1a1a001a, 0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d,
211296341Sdelphij     0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, 0x0d0d000d, 0x66660066,
212296341Sdelphij     0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099,
213296341Sdelphij     0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031,
214296341Sdelphij     0x17170017, 0xd7d700d7, 0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c,
215296341Sdelphij     0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, 0x44440044, 0xb2b200b2,
216296341Sdelphij     0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050,
217296341Sdelphij     0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095,
218296341Sdelphij     0xffff00ff, 0xd2d200d2, 0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db,
219296341Sdelphij     0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, 0x5c5c005c, 0x02020002,
220296341Sdelphij     0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2,
221296341Sdelphij     0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b,
222296341Sdelphij     0xbebe00be, 0x2e2e002e, 0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e,
223296341Sdelphij     0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, 0x98980098, 0x6a6a006a,
224296341Sdelphij     0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa,
225296341Sdelphij     0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068,
226296341Sdelphij     0x38380038, 0xa4a400a4, 0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1,
227296341Sdelphij     0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e},
228296341Sdelphij    {0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e,
229296341Sdelphij     0x00818181, 0x00cbcbcb, 0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a,
230296341Sdelphij     0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, 0x00464646, 0x00dfdfdf,
231296341Sdelphij     0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242,
232296341Sdelphij     0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca,
233296341Sdelphij     0x00252525, 0x007b7b7b, 0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f,
234296341Sdelphij     0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, 0x007c7c7c, 0x00606060,
235296341Sdelphij     0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434,
236296341Sdelphij     0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e,
237296341Sdelphij     0x00bababa, 0x007a7a7a, 0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad,
238296341Sdelphij     0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, 0x00171717, 0x001a1a1a,
239296341Sdelphij     0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a,
240296341Sdelphij     0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363,
241296341Sdelphij     0x00090909, 0x00333333, 0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585,
242296341Sdelphij     0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, 0x00dadada, 0x006f6f6f,
243296341Sdelphij     0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf,
244296341Sdelphij     0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636,
245296341Sdelphij     0x00222222, 0x00383838, 0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c,
246296341Sdelphij     0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, 0x00fdfdfd, 0x00888888,
247296341Sdelphij     0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323,
248296341Sdelphij     0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9,
249296341Sdelphij     0x00d2d2d2, 0x00a0a0a0, 0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa,
250296341Sdelphij     0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, 0x00a8a8a8, 0x00b6b6b6,
251296341Sdelphij     0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5,
252296341Sdelphij     0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef,
253296341Sdelphij     0x00eaeaea, 0x00b7b7b7, 0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5,
254296341Sdelphij     0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, 0x000f0f0f, 0x00b8b8b8,
255296341Sdelphij     0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666,
256296341Sdelphij     0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe,
257296341Sdelphij     0x007f7f7f, 0x00c5c5c5, 0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c,
258296341Sdelphij     0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, 0x00030303, 0x002d2d2d,
259296341Sdelphij     0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c,
260296341Sdelphij     0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc,
261296341Sdelphij     0x00797979, 0x001d1d1d, 0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d,
262296341Sdelphij     0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, 0x00f0f0f0, 0x00313131,
263296341Sdelphij     0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575,
264296341Sdelphij     0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545,
265296341Sdelphij     0x001b1b1b, 0x00f5f5f5, 0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa,
266296341Sdelphij     0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, 0x006c6c6c, 0x00929292,
267296341Sdelphij     0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949,
268296341Sdelphij     0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393,
269296341Sdelphij     0x00868686, 0x00838383, 0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9,
270296341Sdelphij     0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d},
271296341Sdelphij    {0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393,
272296341Sdelphij     0x60006060, 0xf200f2f2, 0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a,
273296341Sdelphij     0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, 0x91009191, 0xf700f7f7,
274296341Sdelphij     0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090,
275296341Sdelphij     0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2,
276296341Sdelphij     0x49004949, 0xde00dede, 0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7,
277296341Sdelphij     0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, 0x1f001f1f, 0x18001818,
278296341Sdelphij     0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d,
279296341Sdelphij     0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3,
280296341Sdelphij     0xae00aeae, 0x9e009e9e, 0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b,
281296341Sdelphij     0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, 0xc500c5c5, 0x86008686,
282296341Sdelphij     0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696,
283296341Sdelphij     0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8,
284296341Sdelphij     0x42004242, 0xcc00cccc, 0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161,
285296341Sdelphij     0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, 0xb600b6b6, 0xdb00dbdb,
286296341Sdelphij     0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb,
287296341Sdelphij     0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d,
288296341Sdelphij     0x88008888, 0x0e000e0e, 0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b,
289296341Sdelphij     0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, 0x7f007f7f, 0x22002222,
290296341Sdelphij     0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8,
291296341Sdelphij     0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e,
292296341Sdelphij     0xb400b4b4, 0x28002828, 0x55005555, 0x68006868, 0x50005050, 0xbe00bebe,
293296341Sdelphij     0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, 0x2a002a2a, 0xad00adad,
294296341Sdelphij     0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969,
295296341Sdelphij     0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb,
296296341Sdelphij     0xba00baba, 0xed00eded, 0x45004545, 0x81008181, 0x73007373, 0x6d006d6d,
297296341Sdelphij     0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, 0xc300c3c3, 0x2e002e2e,
298296341Sdelphij     0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999,
299296341Sdelphij     0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf,
300296341Sdelphij     0xdf00dfdf, 0x71007171, 0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313,
301296341Sdelphij     0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, 0xc000c0c0, 0x4b004b4b,
302296341Sdelphij     0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717,
303296341Sdelphij     0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737,
304296341Sdelphij     0x5e005e5e, 0x47004747, 0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b,
305296341Sdelphij     0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, 0x3c003c3c, 0x4c004c4c,
306296341Sdelphij     0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d,
307296341Sdelphij     0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151,
308296341Sdelphij     0xc600c6c6, 0x7d007d7d, 0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa,
309296341Sdelphij     0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, 0x1b001b1b, 0xa400a4a4,
310296341Sdelphij     0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252,
311296341Sdelphij     0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4,
312296341Sdelphij     0xa100a1a1, 0xe000e0e0, 0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a,
313296341Sdelphij     0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f}
314238405Sjkim};
315162911Ssimon
316238405Sjkim/* Key generation constants */
317238405Sjkimstatic const u32 SIGMA[] = {
318238405Sjkim    0xa09e667f, 0x3bcc908b, 0xb67ae858, 0x4caa73b2, 0xc6ef372f, 0xe94f82be,
319238405Sjkim    0x54ff53a5, 0xf1d36f1c, 0x10e527fa, 0xde682d1d, 0xb05688c2, 0xb3e6c1fd
320238405Sjkim};
321162911Ssimon
322238405Sjkim/* The phi algorithm given in C.2.7 of the Camellia spec document. */
323162911Ssimon/*
324238405Sjkim * This version does not attempt to minimize amount of temporary
325238405Sjkim * variables, but instead explicitly exposes algorithm's parallelism.
326238405Sjkim * It is therefore most appropriate for platforms with not less than
327238405Sjkim * ~16 registers. For platforms with less registers [well, x86 to be
328238405Sjkim * specific] assembler version should be/is provided anyway...
329162911Ssimon */
330238405Sjkim#define Camellia_Feistel(_s0,_s1,_s2,_s3,_key) do {\
331296341Sdelphij        register u32 _t0,_t1,_t2,_t3;\
332238405Sjkim\
333296341Sdelphij        _t0  = _s0 ^ (_key)[0];\
334296341Sdelphij        _t3  = SBOX4_4404[_t0&0xff];\
335296341Sdelphij        _t1  = _s1 ^ (_key)[1];\
336296341Sdelphij        _t3 ^= SBOX3_3033[(_t0 >> 8)&0xff];\
337296341Sdelphij        _t2  = SBOX1_1110[_t1&0xff];\
338296341Sdelphij        _t3 ^= SBOX2_0222[(_t0 >> 16)&0xff];\
339296341Sdelphij        _t2 ^= SBOX4_4404[(_t1 >> 8)&0xff];\
340296341Sdelphij        _t3 ^= SBOX1_1110[(_t0 >> 24)];\
341296341Sdelphij        _t2 ^= _t3;\
342296341Sdelphij        _t3  = RightRotate(_t3,8);\
343296341Sdelphij        _t2 ^= SBOX3_3033[(_t1 >> 16)&0xff];\
344296341Sdelphij        _s3 ^= _t3;\
345296341Sdelphij        _t2 ^= SBOX2_0222[(_t1 >> 24)];\
346296341Sdelphij        _s2 ^= _t2; \
347296341Sdelphij        _s3 ^= _t2;\
348238405Sjkim} while(0)
349162911Ssimon
350238405Sjkim/*
351238405Sjkim * Note that n has to be less than 32. Rotations for larger amount
352238405Sjkim * of bits are achieved by "rotating" order of s-elements and
353238405Sjkim * adjusting n accordingly, e.g. RotLeft128(s1,s2,s3,s0,n-32).
354162911Ssimon */
355238405Sjkim#define RotLeft128(_s0,_s1,_s2,_s3,_n) do {\
356296341Sdelphij        u32 _t0=_s0>>(32-_n);\
357296341Sdelphij        _s0 = (_s0<<_n) | (_s1>>(32-_n));\
358296341Sdelphij        _s1 = (_s1<<_n) | (_s2>>(32-_n));\
359296341Sdelphij        _s2 = (_s2<<_n) | (_s3>>(32-_n));\
360296341Sdelphij        _s3 = (_s3<<_n) | _t0;\
361238405Sjkim} while (0)
362162911Ssimon
363238405Sjkimint Camellia_Ekeygen(int keyBitLength, const u8 *rawKey, KEY_TABLE_TYPE k)
364296341Sdelphij{
365296341Sdelphij    register u32 s0, s1, s2, s3;
366162911Ssimon
367296341Sdelphij    k[0] = s0 = GETU32(rawKey);
368296341Sdelphij    k[1] = s1 = GETU32(rawKey + 4);
369296341Sdelphij    k[2] = s2 = GETU32(rawKey + 8);
370296341Sdelphij    k[3] = s3 = GETU32(rawKey + 12);
371162911Ssimon
372296341Sdelphij    if (keyBitLength != 128) {
373296341Sdelphij        k[8] = s0 = GETU32(rawKey + 16);
374296341Sdelphij        k[9] = s1 = GETU32(rawKey + 20);
375296341Sdelphij        if (keyBitLength == 192) {
376296341Sdelphij            k[10] = s2 = ~s0;
377296341Sdelphij            k[11] = s3 = ~s1;
378296341Sdelphij        } else {
379296341Sdelphij            k[10] = s2 = GETU32(rawKey + 24);
380296341Sdelphij            k[11] = s3 = GETU32(rawKey + 28);
381296341Sdelphij        }
382296341Sdelphij        s0 ^= k[0], s1 ^= k[1], s2 ^= k[2], s3 ^= k[3];
383296341Sdelphij    }
384162911Ssimon
385296341Sdelphij    /* Use the Feistel routine to scramble the key material */
386296341Sdelphij    Camellia_Feistel(s0, s1, s2, s3, SIGMA + 0);
387296341Sdelphij    Camellia_Feistel(s2, s3, s0, s1, SIGMA + 2);
388162911Ssimon
389296341Sdelphij    s0 ^= k[0], s1 ^= k[1], s2 ^= k[2], s3 ^= k[3];
390296341Sdelphij    Camellia_Feistel(s0, s1, s2, s3, SIGMA + 4);
391296341Sdelphij    Camellia_Feistel(s2, s3, s0, s1, SIGMA + 6);
392162911Ssimon
393296341Sdelphij    /* Fill the keyTable. Requires many block rotations. */
394296341Sdelphij    if (keyBitLength == 128) {
395296341Sdelphij        k[4] = s0, k[5] = s1, k[6] = s2, k[7] = s3;
396296341Sdelphij        RotLeft128(s0, s1, s2, s3, 15); /* KA <<< 15 */
397296341Sdelphij        k[12] = s0, k[13] = s1, k[14] = s2, k[15] = s3;
398296341Sdelphij        RotLeft128(s0, s1, s2, s3, 15); /* KA <<< 30 */
399296341Sdelphij        k[16] = s0, k[17] = s1, k[18] = s2, k[19] = s3;
400296341Sdelphij        RotLeft128(s0, s1, s2, s3, 15); /* KA <<< 45 */
401296341Sdelphij        k[24] = s0, k[25] = s1;
402296341Sdelphij        RotLeft128(s0, s1, s2, s3, 15); /* KA <<< 60 */
403296341Sdelphij        k[28] = s0, k[29] = s1, k[30] = s2, k[31] = s3;
404296341Sdelphij        RotLeft128(s1, s2, s3, s0, 2); /* KA <<< 94 */
405296341Sdelphij        k[40] = s1, k[41] = s2, k[42] = s3, k[43] = s0;
406296341Sdelphij        RotLeft128(s1, s2, s3, s0, 17); /* KA <<<111 */
407296341Sdelphij        k[48] = s1, k[49] = s2, k[50] = s3, k[51] = s0;
408162911Ssimon
409296341Sdelphij        s0 = k[0], s1 = k[1], s2 = k[2], s3 = k[3];
410296341Sdelphij        RotLeft128(s0, s1, s2, s3, 15); /* KL <<< 15 */
411296341Sdelphij        k[8] = s0, k[9] = s1, k[10] = s2, k[11] = s3;
412296341Sdelphij        RotLeft128(s0, s1, s2, s3, 30); /* KL <<< 45 */
413296341Sdelphij        k[20] = s0, k[21] = s1, k[22] = s2, k[23] = s3;
414296341Sdelphij        RotLeft128(s0, s1, s2, s3, 15); /* KL <<< 60 */
415296341Sdelphij        k[26] = s2, k[27] = s3;
416296341Sdelphij        RotLeft128(s0, s1, s2, s3, 17); /* KL <<< 77 */
417296341Sdelphij        k[32] = s0, k[33] = s1, k[34] = s2, k[35] = s3;
418296341Sdelphij        RotLeft128(s0, s1, s2, s3, 17); /* KL <<< 94 */
419296341Sdelphij        k[36] = s0, k[37] = s1, k[38] = s2, k[39] = s3;
420296341Sdelphij        RotLeft128(s0, s1, s2, s3, 17); /* KL <<<111 */
421296341Sdelphij        k[44] = s0, k[45] = s1, k[46] = s2, k[47] = s3;
422162911Ssimon
423296341Sdelphij        return 3;               /* grand rounds */
424296341Sdelphij    } else {
425296341Sdelphij        k[12] = s0, k[13] = s1, k[14] = s2, k[15] = s3;
426296341Sdelphij        s0 ^= k[8], s1 ^= k[9], s2 ^= k[10], s3 ^= k[11];
427296341Sdelphij        Camellia_Feistel(s0, s1, s2, s3, (SIGMA + 8));
428296341Sdelphij        Camellia_Feistel(s2, s3, s0, s1, (SIGMA + 10));
429162911Ssimon
430296341Sdelphij        k[4] = s0, k[5] = s1, k[6] = s2, k[7] = s3;
431296341Sdelphij        RotLeft128(s0, s1, s2, s3, 30); /* KB <<< 30 */
432296341Sdelphij        k[20] = s0, k[21] = s1, k[22] = s2, k[23] = s3;
433296341Sdelphij        RotLeft128(s0, s1, s2, s3, 30); /* KB <<< 60 */
434296341Sdelphij        k[40] = s0, k[41] = s1, k[42] = s2, k[43] = s3;
435296341Sdelphij        RotLeft128(s1, s2, s3, s0, 19); /* KB <<<111 */
436296341Sdelphij        k[64] = s1, k[65] = s2, k[66] = s3, k[67] = s0;
437162911Ssimon
438296341Sdelphij        s0 = k[8], s1 = k[9], s2 = k[10], s3 = k[11];
439296341Sdelphij        RotLeft128(s0, s1, s2, s3, 15); /* KR <<< 15 */
440296341Sdelphij        k[8] = s0, k[9] = s1, k[10] = s2, k[11] = s3;
441296341Sdelphij        RotLeft128(s0, s1, s2, s3, 15); /* KR <<< 30 */
442296341Sdelphij        k[16] = s0, k[17] = s1, k[18] = s2, k[19] = s3;
443296341Sdelphij        RotLeft128(s0, s1, s2, s3, 30); /* KR <<< 60 */
444296341Sdelphij        k[36] = s0, k[37] = s1, k[38] = s2, k[39] = s3;
445296341Sdelphij        RotLeft128(s1, s2, s3, s0, 2); /* KR <<< 94 */
446296341Sdelphij        k[52] = s1, k[53] = s2, k[54] = s3, k[55] = s0;
447162911Ssimon
448296341Sdelphij        s0 = k[12], s1 = k[13], s2 = k[14], s3 = k[15];
449296341Sdelphij        RotLeft128(s0, s1, s2, s3, 15); /* KA <<< 15 */
450296341Sdelphij        k[12] = s0, k[13] = s1, k[14] = s2, k[15] = s3;
451296341Sdelphij        RotLeft128(s0, s1, s2, s3, 30); /* KA <<< 45 */
452296341Sdelphij        k[28] = s0, k[29] = s1, k[30] = s2, k[31] = s3;
453296341Sdelphij        /* KA <<< 77 */
454296341Sdelphij        k[48] = s1, k[49] = s2, k[50] = s3, k[51] = s0;
455296341Sdelphij        RotLeft128(s1, s2, s3, s0, 17); /* KA <<< 94 */
456296341Sdelphij        k[56] = s1, k[57] = s2, k[58] = s3, k[59] = s0;
457162911Ssimon
458296341Sdelphij        s0 = k[0], s1 = k[1], s2 = k[2], s3 = k[3];
459296341Sdelphij        RotLeft128(s1, s2, s3, s0, 13); /* KL <<< 45 */
460296341Sdelphij        k[24] = s1, k[25] = s2, k[26] = s3, k[27] = s0;
461296341Sdelphij        RotLeft128(s1, s2, s3, s0, 15); /* KL <<< 60 */
462296341Sdelphij        k[32] = s1, k[33] = s2, k[34] = s3, k[35] = s0;
463296341Sdelphij        RotLeft128(s1, s2, s3, s0, 17); /* KL <<< 77 */
464296341Sdelphij        k[44] = s1, k[45] = s2, k[46] = s3, k[47] = s0;
465296341Sdelphij        RotLeft128(s2, s3, s0, s1, 2); /* KL <<<111 */
466296341Sdelphij        k[60] = s2, k[61] = s3, k[62] = s0, k[63] = s1;
467162911Ssimon
468296341Sdelphij        return 4;               /* grand rounds */
469296341Sdelphij    }
470296341Sdelphij    /*
471296341Sdelphij     * It is possible to perform certain precalculations, which
472296341Sdelphij     * would spare few cycles in block procedure. It's not done,
473296341Sdelphij     * because it upsets the performance balance between key
474296341Sdelphij     * setup and block procedures, negatively affecting overall
475296341Sdelphij     * throughput in applications operating on short messages
476296341Sdelphij     * and volatile keys.
477296341Sdelphij     */
478296341Sdelphij}
479162911Ssimon
480296341Sdelphijvoid Camellia_EncryptBlock_Rounds(int grandRounds, const u8 plaintext[],
481296341Sdelphij                                  const KEY_TABLE_TYPE keyTable,
482296341Sdelphij                                  u8 ciphertext[])
483296341Sdelphij{
484296341Sdelphij    register u32 s0, s1, s2, s3;
485296341Sdelphij    const u32 *k = keyTable, *kend = keyTable + grandRounds * 16;
486162911Ssimon
487296341Sdelphij    s0 = GETU32(plaintext) ^ k[0];
488296341Sdelphij    s1 = GETU32(plaintext + 4) ^ k[1];
489296341Sdelphij    s2 = GETU32(plaintext + 8) ^ k[2];
490296341Sdelphij    s3 = GETU32(plaintext + 12) ^ k[3];
491296341Sdelphij    k += 4;
492162911Ssimon
493296341Sdelphij    while (1) {
494296341Sdelphij        /* Camellia makes 6 Feistel rounds */
495296341Sdelphij        Camellia_Feistel(s0, s1, s2, s3, k + 0);
496296341Sdelphij        Camellia_Feistel(s2, s3, s0, s1, k + 2);
497296341Sdelphij        Camellia_Feistel(s0, s1, s2, s3, k + 4);
498296341Sdelphij        Camellia_Feistel(s2, s3, s0, s1, k + 6);
499296341Sdelphij        Camellia_Feistel(s0, s1, s2, s3, k + 8);
500296341Sdelphij        Camellia_Feistel(s2, s3, s0, s1, k + 10);
501296341Sdelphij        k += 12;
502162911Ssimon
503296341Sdelphij        if (k == kend)
504296341Sdelphij            break;
505162911Ssimon
506296341Sdelphij        /*
507296341Sdelphij         * This is the same function as the diffusion function D of the
508296341Sdelphij         * accompanying documentation. See section 3.2 for properties of the
509296341Sdelphij         * FLlayer function.
510296341Sdelphij         */
511296341Sdelphij        s1 ^= LeftRotate(s0 & k[0], 1);
512296341Sdelphij        s2 ^= s3 | k[3];
513296341Sdelphij        s0 ^= s1 | k[1];
514296341Sdelphij        s3 ^= LeftRotate(s2 & k[2], 1);
515296341Sdelphij        k += 4;
516296341Sdelphij    }
517162911Ssimon
518296341Sdelphij    s2 ^= k[0], s3 ^= k[1], s0 ^= k[2], s1 ^= k[3];
519162911Ssimon
520296341Sdelphij    PUTU32(ciphertext, s2);
521296341Sdelphij    PUTU32(ciphertext + 4, s3);
522296341Sdelphij    PUTU32(ciphertext + 8, s0);
523296341Sdelphij    PUTU32(ciphertext + 12, s1);
524296341Sdelphij}
525162911Ssimon
526296341Sdelphijvoid Camellia_EncryptBlock(int keyBitLength, const u8 plaintext[],
527296341Sdelphij                           const KEY_TABLE_TYPE keyTable, u8 ciphertext[])
528296341Sdelphij{
529296341Sdelphij    Camellia_EncryptBlock_Rounds(keyBitLength == 128 ? 3 : 4,
530296341Sdelphij                                 plaintext, keyTable, ciphertext);
531296341Sdelphij}
532162911Ssimon
533296341Sdelphijvoid Camellia_DecryptBlock_Rounds(int grandRounds, const u8 ciphertext[],
534296341Sdelphij                                  const KEY_TABLE_TYPE keyTable,
535296341Sdelphij                                  u8 plaintext[])
536296341Sdelphij{
537296341Sdelphij    u32 s0, s1, s2, s3;
538296341Sdelphij    const u32 *k = keyTable + grandRounds * 16, *kend = keyTable + 4;
539162911Ssimon
540296341Sdelphij    s0 = GETU32(ciphertext) ^ k[0];
541296341Sdelphij    s1 = GETU32(ciphertext + 4) ^ k[1];
542296341Sdelphij    s2 = GETU32(ciphertext + 8) ^ k[2];
543296341Sdelphij    s3 = GETU32(ciphertext + 12) ^ k[3];
544162911Ssimon
545296341Sdelphij    while (1) {
546296341Sdelphij        /* Camellia makes 6 Feistel rounds */
547296341Sdelphij        k -= 12;
548296341Sdelphij        Camellia_Feistel(s0, s1, s2, s3, k + 10);
549296341Sdelphij        Camellia_Feistel(s2, s3, s0, s1, k + 8);
550296341Sdelphij        Camellia_Feistel(s0, s1, s2, s3, k + 6);
551296341Sdelphij        Camellia_Feistel(s2, s3, s0, s1, k + 4);
552296341Sdelphij        Camellia_Feistel(s0, s1, s2, s3, k + 2);
553296341Sdelphij        Camellia_Feistel(s2, s3, s0, s1, k + 0);
554162911Ssimon
555296341Sdelphij        if (k == kend)
556296341Sdelphij            break;
557162911Ssimon
558296341Sdelphij        /*
559296341Sdelphij         * This is the same function as the diffusion function D of the
560296341Sdelphij         * accompanying documentation. See section 3.2 for properties of the
561296341Sdelphij         * FLlayer function.
562296341Sdelphij         */
563296341Sdelphij        k -= 4;
564296341Sdelphij        s1 ^= LeftRotate(s0 & k[2], 1);
565296341Sdelphij        s2 ^= s3 | k[1];
566296341Sdelphij        s0 ^= s1 | k[3];
567296341Sdelphij        s3 ^= LeftRotate(s2 & k[0], 1);
568296341Sdelphij    }
569162911Ssimon
570296341Sdelphij    k -= 4;
571296341Sdelphij    s2 ^= k[0], s3 ^= k[1], s0 ^= k[2], s1 ^= k[3];
572296341Sdelphij
573296341Sdelphij    PUTU32(plaintext, s2);
574296341Sdelphij    PUTU32(plaintext + 4, s3);
575296341Sdelphij    PUTU32(plaintext + 8, s0);
576296341Sdelphij    PUTU32(plaintext + 12, s1);
577296341Sdelphij}
578296341Sdelphij
579296341Sdelphijvoid Camellia_DecryptBlock(int keyBitLength, const u8 plaintext[],
580296341Sdelphij                           const KEY_TABLE_TYPE keyTable, u8 ciphertext[])
581296341Sdelphij{
582296341Sdelphij    Camellia_DecryptBlock_Rounds(keyBitLength == 128 ? 3 : 4,
583296341Sdelphij                                 plaintext, keyTable, ciphertext);
584296341Sdelphij}
585