/src/nettle/camellia-crypt-internal.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* camellia-crypt-internal.c |
2 | | |
3 | | Copyright (C) 2006,2007 NTT |
4 | | (Nippon Telegraph and Telephone Corporation). |
5 | | |
6 | | Copyright (C) 2010 Niels Möller |
7 | | |
8 | | This file is part of GNU Nettle. |
9 | | |
10 | | GNU Nettle is free software: you can redistribute it and/or |
11 | | modify it under the terms of either: |
12 | | |
13 | | * the GNU Lesser General Public License as published by the Free |
14 | | Software Foundation; either version 3 of the License, or (at your |
15 | | option) any later version. |
16 | | |
17 | | or |
18 | | |
19 | | * the GNU General Public License as published by the Free |
20 | | Software Foundation; either version 2 of the License, or (at your |
21 | | option) any later version. |
22 | | |
23 | | or both in parallel, as here. |
24 | | |
25 | | GNU Nettle is distributed in the hope that it will be useful, |
26 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
27 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
28 | | General Public License for more details. |
29 | | |
30 | | You should have received copies of the GNU General Public License and |
31 | | the GNU Lesser General Public License along with this program. If |
32 | | not, see http://www.gnu.org/licenses/. |
33 | | */ |
34 | | |
35 | | /* |
36 | | * Algorithm Specification |
37 | | * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html |
38 | | */ |
39 | | |
40 | | /* Based on camellia.c ver 1.2.0, see |
41 | | http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/camellia-LGPL-1.2.0.tar.gz. |
42 | | */ |
43 | | #if HAVE_CONFIG_H |
44 | | # include "config.h" |
45 | | #endif |
46 | | |
47 | | #include <assert.h> |
48 | | #include <limits.h> |
49 | | |
50 | | #include "camellia-internal.h" |
51 | | |
52 | | #include "macros.h" |
53 | | |
54 | 0 | #define CAMELLIA_FL(x, k) do { \ |
55 | 0 | uint32_t __xl, __xr, __kl, __kr, __t; \ |
56 | 0 | __xl = (x) >> 32; \ |
57 | 0 | __xr = (x) & 0xffffffff; \ |
58 | 0 | __kl = (k) >> 32; \ |
59 | 0 | __kr = (k) & 0xffffffff; \ |
60 | 0 | __t = __xl & __kl; \ |
61 | 0 | __xr ^= ROTL32(1, __t); \ |
62 | 0 | __xl ^= (__xr | __kr); \ |
63 | 0 | (x) = ((uint64_t) __xl << 32) | __xr; \ |
64 | 0 | } while (0) |
65 | | |
66 | 0 | #define CAMELLIA_FLINV(x, k) do { \ |
67 | 0 | uint32_t __xl, __xr, __kl, __kr, __t; \ |
68 | 0 | __xl = (x) >> 32; \ |
69 | 0 | __xr = (x) & 0xffffffff; \ |
70 | 0 | __kl = (k) >> 32; \ |
71 | 0 | __kr = (k) & 0xffffffff; \ |
72 | 0 | __xl ^= (__xr | __kr); \ |
73 | 0 | __t = __xl & __kl; \ |
74 | 0 | __xr ^= ROTL32(1, __t); \ |
75 | 0 | (x) = ((uint64_t) __xl << 32) | __xr; \ |
76 | 0 | } while (0) |
77 | | |
78 | | #if HAVE_NATIVE_64_BIT |
79 | 0 | #define CAMELLIA_ROUNDSM(T, x, k, y) do { \ |
80 | 0 | uint32_t __il, __ir; \ |
81 | 0 | __ir \ |
82 | 0 | = T->sp1110[(x) & 0xff] \ |
83 | 0 | ^ T->sp0222[((x) >> 24) & 0xff] \ |
84 | 0 | ^ T->sp3033[((x) >> 16) & 0xff] \ |
85 | 0 | ^ T->sp4404[((x) >> 8) & 0xff]; \ |
86 | 0 | /* ir == (t6^t7^t8),(t5^t7^t8),(t5^t6^t8),(t5^t6^t7) */ \ |
87 | 0 | __il \ |
88 | 0 | = T->sp1110[ (x) >> 56] \ |
89 | 0 | ^ T->sp0222[((x) >> 48) & 0xff] \ |
90 | 0 | ^ T->sp3033[((x) >> 40) & 0xff] \ |
91 | 0 | ^ T->sp4404[((x) >> 32) & 0xff]; \ |
92 | 0 | /* il == (t1^t3^t4),(t1^t2^t4),(t1^t2^t3),(t2^t3^t4) */ \ |
93 | 0 | __ir ^= __il; \ |
94 | 0 | /* ir == (t1^t3^t4^t6^t7^t8),(t1^t2^t4^t5^t7^t8), \ |
95 | 0 | (t1^t2^t3^t5^t6^t8),(t2^t3^t4^t5^t6^t7) \ |
96 | 0 | == y1,y2,y3,y4 */ \ |
97 | 0 | __il = ROTL32(24, __il); \ |
98 | 0 | /* il == (t2^t3^t4),(t1^t3^t4),(t1^t2^t4),(t1^t2^t3) */ \ |
99 | 0 | __il ^= __ir; \ |
100 | 0 | /* il == (t1^t2^t6^t7^t8),(t2^t3^t5^t7^t8), \ |
101 | 0 | (t3^t4^t5^t6^t8),(t1^t4^t5^t6^t7) \ |
102 | 0 | == y5,y6,y7,y8 */ \ |
103 | 0 | y ^= (k); \ |
104 | 0 | y ^= ((uint64_t) __ir << 32) | __il; \ |
105 | 0 | } while (0) |
106 | | #else /* !HAVE_NATIVE_64_BIT */ |
107 | | #define CAMELLIA_ROUNDSM(T, x, k, y) do { \ |
108 | | uint32_t __il, __ir; \ |
109 | | __ir \ |
110 | | = T->sp1110[(x) & 0xff] \ |
111 | | ^ T->sp0222[((x) >> 24) & 0xff] \ |
112 | | ^ T->sp3033[((x) >> 16) & 0xff] \ |
113 | | ^ T->sp4404[((x) >> 8) & 0xff]; \ |
114 | | /* ir == (t6^t7^t8),(t5^t7^t8),(t5^t6^t8),(t5^t6^t7) */ \ |
115 | | __il \ |
116 | | = T->sp1110[ (x) >> 56] \ |
117 | | ^ T->sp0222[((x) >> 48) & 0xff] \ |
118 | | ^ T->sp3033[((x) >> 40) & 0xff] \ |
119 | | ^ T->sp4404[((x) >> 32) & 0xff]; \ |
120 | | /* il == (t1^t3^t4),(t1^t2^t4),(t1^t2^t3),(t2^t3^t4) */ \ |
121 | | __il ^= (k) >> 32; \ |
122 | | __ir ^= (k) & 0xffffffff; \ |
123 | | __ir ^= __il; \ |
124 | | /* ir == (t1^t3^t4^t6^t7^t8),(t1^t2^t4^t5^t7^t8), \ |
125 | | (t1^t2^t3^t5^t6^t8),(t2^t3^t4^t5^t6^t7) \ |
126 | | == y1,y2,y3,y4 */ \ |
127 | | __il = ROTL32(24, __il); \ |
128 | | /* il == (t2^t3^t4),(t1^t3^t4),(t1^t2^t4),(t1^t2^t3) */ \ |
129 | | __il ^= __ir; \ |
130 | | /* il == (t1^t2^t6^t7^t8),(t2^t3^t5^t7^t8), \ |
131 | | (t3^t4^t5^t6^t8),(t1^t4^t5^t6^t7) \ |
132 | | == y5,y6,y7,y8 */ \ |
133 | | y ^= ((uint64_t) __ir << 32) | __il; \ |
134 | | } while (0) |
135 | | #endif |
136 | | |
137 | | void |
138 | | _nettle_camellia_crypt(unsigned nkeys, |
139 | | const uint64_t *keys, |
140 | | const struct camellia_table *T, |
141 | | size_t length, uint8_t *dst, |
142 | | const uint8_t *src) |
143 | 0 | { |
144 | 0 | FOR_BLOCKS(length, dst, src, CAMELLIA_BLOCK_SIZE) |
145 | 0 | { |
146 | 0 | uint64_t i0,i1; |
147 | 0 | unsigned i; |
148 | |
|
149 | 0 | i0 = READ_UINT64(src); |
150 | 0 | i1 = READ_UINT64(src + 8); |
151 | | |
152 | | /* pre whitening but absorb kw2*/ |
153 | 0 | i0 ^= keys[0]; |
154 | | |
155 | | /* main iteration */ |
156 | |
|
157 | 0 | CAMELLIA_ROUNDSM(T, i0, keys[1], i1); |
158 | 0 | CAMELLIA_ROUNDSM(T, i1, keys[2], i0); |
159 | 0 | CAMELLIA_ROUNDSM(T, i0, keys[3], i1); |
160 | 0 | CAMELLIA_ROUNDSM(T, i1, keys[4], i0); |
161 | 0 | CAMELLIA_ROUNDSM(T, i0, keys[5], i1); |
162 | 0 | CAMELLIA_ROUNDSM(T, i1, keys[6], i0); |
163 | | |
164 | 0 | for (i = 0; i < nkeys - 8; i+= 8) |
165 | 0 | { |
166 | 0 | CAMELLIA_FL(i0, keys[i+7]); |
167 | 0 | CAMELLIA_FLINV(i1, keys[i+8]); |
168 | | |
169 | 0 | CAMELLIA_ROUNDSM(T, i0, keys[i+9], i1); |
170 | 0 | CAMELLIA_ROUNDSM(T, i1, keys[i+10], i0); |
171 | 0 | CAMELLIA_ROUNDSM(T, i0, keys[i+11], i1); |
172 | 0 | CAMELLIA_ROUNDSM(T, i1, keys[i+12], i0); |
173 | 0 | CAMELLIA_ROUNDSM(T, i0, keys[i+13], i1); |
174 | 0 | CAMELLIA_ROUNDSM(T, i1, keys[i+14], i0); |
175 | 0 | } |
176 | | |
177 | | /* post whitening but kw4 */ |
178 | 0 | i1 ^= keys[i+7]; |
179 | |
|
180 | 0 | WRITE_UINT64(dst , i1); |
181 | 0 | WRITE_UINT64(dst + 8, i0); |
182 | 0 | } |
183 | 0 | } |