/src/nettle-with-libgmp/cast128.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* cast128.c |
2 | | |
3 | | The CAST-128 block cipher, described in RFC 2144. |
4 | | |
5 | | Copyright (C) 2001, 2014 Niels Möller |
6 | | |
7 | | This file is part of GNU Nettle. |
8 | | |
9 | | GNU Nettle is free software: you can redistribute it and/or |
10 | | modify it under the terms of either: |
11 | | |
12 | | * the GNU Lesser General Public License as published by the Free |
13 | | Software Foundation; either version 3 of the License, or (at your |
14 | | option) any later version. |
15 | | |
16 | | or |
17 | | |
18 | | * the GNU General Public License as published by the Free |
19 | | Software Foundation; either version 2 of the License, or (at your |
20 | | option) any later version. |
21 | | |
22 | | or both in parallel, as here. |
23 | | |
24 | | GNU Nettle is distributed in the hope that it will be useful, |
25 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
26 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
27 | | General Public License for more details. |
28 | | |
29 | | You should have received copies of the GNU General Public License and |
30 | | the GNU Lesser General Public License along with this program. If |
31 | | not, see http://www.gnu.org/licenses/. |
32 | | */ |
33 | | |
34 | | /* Based on: |
35 | | * |
36 | | * CAST-128 in C |
37 | | * Written by Steve Reid <sreid@sea-to-sky.net> |
38 | | * 100% Public Domain - no warranty |
39 | | * Released 1997.10.11 |
40 | | */ |
41 | | |
42 | | #if HAVE_CONFIG_H |
43 | | # include "config.h" |
44 | | #endif |
45 | | |
46 | | #include <assert.h> |
47 | | #include <stdlib.h> |
48 | | #include <string.h> |
49 | | |
50 | | #include "cast128.h" |
51 | | #include "cast128_sboxes.h" |
52 | | |
53 | | #include "macros.h" |
54 | | |
55 | 240 | #define CAST_SMALL_KEY 10 |
56 | | |
57 | 22.5k | #define S1 cast_sbox1 |
58 | 22.5k | #define S2 cast_sbox2 |
59 | 22.5k | #define S3 cast_sbox3 |
60 | 22.5k | #define S4 cast_sbox4 |
61 | 9.60k | #define S5 cast_sbox5 |
62 | 9.60k | #define S6 cast_sbox6 |
63 | 9.60k | #define S7 cast_sbox7 |
64 | 9.60k | #define S8 cast_sbox8 |
65 | | |
66 | | /* Macros to access 8-bit bytes out of a 32-bit word */ |
67 | 32.1k | #define B0(x) ( (uint8_t) (x>>24) ) |
68 | 32.1k | #define B1(x) ( (uint8_t) ((x>>16)&0xff) ) |
69 | 32.1k | #define B2(x) ( (uint8_t) ((x>>8)&0xff) ) |
70 | 32.1k | #define B3(x) ( (uint8_t) ((x)&0xff) ) |
71 | | |
72 | | /* NOTE: Depends on ROTL32 supporting a zero shift count. */ |
73 | | |
74 | | /* CAST-128 uses three different round functions */ |
75 | 7.98k | #define F1(l, r, i) do { \ |
76 | 7.98k | t = ctx->Km[i] + r; \ |
77 | 7.98k | t = ROTL32(ctx->Kr[i], t); \ |
78 | 7.98k | l ^= ((S1[B0(t)] ^ S2[B1(t)]) - S3[B2(t)]) + S4[B3(t)]; \ |
79 | 7.98k | } while (0) |
80 | 7.26k | #define F2(l, r, i) do { \ |
81 | 7.26k | t = ctx->Km[i] ^ r; \ |
82 | 7.26k | t = ROTL32( ctx->Kr[i], t); \ |
83 | 7.26k | l ^= ((S1[B0(t)] - S2[B1(t)]) + S3[B2(t)]) ^ S4[B3(t)]; \ |
84 | 7.26k | } while (0) |
85 | 7.26k | #define F3(l, r, i) do { \ |
86 | 7.26k | t = ctx->Km[i] - r; \ |
87 | 7.26k | t = ROTL32(ctx->Kr[i], t); \ |
88 | 7.26k | l ^= ((S1[B0(t)] + S2[B1(t)]) ^ S3[B2(t)]) - S4[B3(t)]; \ |
89 | 7.26k | } while (0) |
90 | | |
91 | | |
92 | | /***** Encryption Function *****/ |
93 | | |
94 | | void |
95 | | cast128_encrypt(const struct cast128_ctx *ctx, |
96 | | size_t length, uint8_t *dst, |
97 | | const uint8_t *src) |
98 | 98 | { |
99 | 98 | FOR_BLOCKS(length, dst, src, CAST128_BLOCK_SIZE) |
100 | 614 | { |
101 | 614 | uint32_t t, l, r; |
102 | | |
103 | | /* Get inblock into l,r */ |
104 | 614 | l = READ_UINT32(src); |
105 | 614 | r = READ_UINT32(src+4); |
106 | | |
107 | | /* Do the work */ |
108 | 614 | F1(l, r, 0); |
109 | 614 | F2(r, l, 1); |
110 | 614 | F3(l, r, 2); |
111 | 614 | F1(r, l, 3); |
112 | 614 | F2(l, r, 4); |
113 | 614 | F3(r, l, 5); |
114 | 614 | F1(l, r, 6); |
115 | 614 | F2(r, l, 7); |
116 | 614 | F3(l, r, 8); |
117 | 614 | F1(r, l, 9); |
118 | 614 | F2(l, r, 10); |
119 | 614 | F3(r, l, 11); |
120 | | /* Only do full 16 rounds if key length > 80 bits */ |
121 | 614 | if (ctx->rounds & 16) { |
122 | 155 | F1(l, r, 12); |
123 | 155 | F2(r, l, 13); |
124 | 155 | F3(l, r, 14); |
125 | 155 | F1(r, l, 15); |
126 | 155 | } |
127 | | /* Put l,r into outblock */ |
128 | 614 | WRITE_UINT32(dst, r); |
129 | 614 | WRITE_UINT32(dst + 4, l); |
130 | 614 | } |
131 | 98 | } |
132 | | |
133 | | |
134 | | /***** Decryption Function *****/ |
135 | | |
136 | | void |
137 | | cast128_decrypt(const struct cast128_ctx *ctx, |
138 | | size_t length, uint8_t *dst, |
139 | | const uint8_t *src) |
140 | 142 | { |
141 | 142 | FOR_BLOCKS(length, dst, src, CAST128_BLOCK_SIZE) |
142 | 1.02k | { |
143 | 1.02k | uint32_t t, l, r; |
144 | | |
145 | | /* Get inblock into l,r */ |
146 | 1.02k | r = READ_UINT32(src); |
147 | 1.02k | l = READ_UINT32(src+4); |
148 | | |
149 | | /* Do the work */ |
150 | | /* Only do full 16 rounds if key length > 80 bits */ |
151 | 1.02k | if (ctx->rounds & 16) { |
152 | 562 | F1(r, l, 15); |
153 | 562 | F3(l, r, 14); |
154 | 562 | F2(r, l, 13); |
155 | 562 | F1(l, r, 12); |
156 | 562 | } |
157 | 1.02k | F3(r, l, 11); |
158 | 1.02k | F2(l, r, 10); |
159 | 1.02k | F1(r, l, 9); |
160 | 1.02k | F3(l, r, 8); |
161 | 1.02k | F2(r, l, 7); |
162 | 1.02k | F1(l, r, 6); |
163 | 1.02k | F3(r, l, 5); |
164 | 1.02k | F2(l, r, 4); |
165 | 1.02k | F1(r, l, 3); |
166 | 1.02k | F3(l, r, 2); |
167 | 1.02k | F2(r, l, 1); |
168 | 1.02k | F1(l, r, 0); |
169 | | |
170 | | /* Put l,r into outblock */ |
171 | 1.02k | WRITE_UINT32(dst, l); |
172 | 1.02k | WRITE_UINT32(dst + 4, r); |
173 | 1.02k | } |
174 | 142 | } |
175 | | |
176 | | /***** Key Schedule *****/ |
177 | | |
178 | 3.34k | #define SET_KM(i, k) ctx->Km[i] = (k) |
179 | 3.34k | #define SET_KR(i, k) ctx->Kr[i] = (k) & 31 |
180 | | |
181 | 480 | #define EXPAND(set, full) do { \ |
182 | 480 | z0 = x0 ^ S5[B1(x3)] ^ S6[B3(x3)] ^ S7[B0(x3)] ^ S8[B2(x3)] ^ S7[B0(x2)]; \ |
183 | 480 | z1 = x2 ^ S5[B0(z0)] ^ S6[B2(z0)] ^ S7[B1(z0)] ^ S8[B3(z0)] ^ S8[B2(x2)]; \ |
184 | 480 | z2 = x3 ^ S5[B3(z1)] ^ S6[B2(z1)] ^ S7[B1(z1)] ^ S8[B0(z1)] ^ S5[B1(x2)]; \ |
185 | 480 | z3 = x1 ^ S5[B2(z2)] ^ S6[B1(z2)] ^ S7[B3(z2)] ^ S8[B0(z2)] ^ S6[B3(x2)]; \ |
186 | 480 | \ |
187 | 480 | set(0, S5[B0(z2)] ^ S6[B1(z2)] ^ S7[B3(z1)] ^ S8[B2(z1)] ^ S5[B2(z0)]); \ |
188 | 480 | set(1, S5[B2(z2)] ^ S6[B3(z2)] ^ S7[B1(z1)] ^ S8[B0(z1)] ^ S6[B2(z1)]); \ |
189 | 480 | set(2, S5[B0(z3)] ^ S6[B1(z3)] ^ S7[B3(z0)] ^ S8[B2(z0)] ^ S7[B1(z2)]); \ |
190 | 480 | set(3, S5[B2(z3)] ^ S6[B3(z3)] ^ S7[B1(z0)] ^ S8[B0(z0)] ^ S8[B0(z3)]); \ |
191 | 480 | \ |
192 | 480 | x0 = z2 ^ S5[B1(z1)] ^ S6[B3(z1)] ^ S7[B0(z1)] ^ S8[B2(z1)] ^ S7[B0(z0)]; \ |
193 | 480 | x1 = z0 ^ S5[B0(x0)] ^ S6[B2(x0)] ^ S7[B1(x0)] ^ S8[B3(x0)] ^ S8[B2(z0)]; \ |
194 | 480 | x2 = z1 ^ S5[B3(x1)] ^ S6[B2(x1)] ^ S7[B1(x1)] ^ S8[B0(x1)] ^ S5[B1(z0)]; \ |
195 | 480 | x3 = z3 ^ S5[B2(x2)] ^ S6[B1(x2)] ^ S7[B3(x2)] ^ S8[B0(x2)] ^ S6[B3(z0)]; \ |
196 | 480 | \ |
197 | 480 | set(4, S5[B3(x0)] ^ S6[B2(x0)] ^ S7[B0(x3)] ^ S8[B1(x3)] ^ S5[B0(x2)]); \ |
198 | 480 | set(5, S5[B1(x0)] ^ S6[B0(x0)] ^ S7[B2(x3)] ^ S8[B3(x3)] ^ S6[B1(x3)]); \ |
199 | 480 | set(6, S5[B3(x1)] ^ S6[B2(x1)] ^ S7[B0(x2)] ^ S8[B1(x2)] ^ S7[B3(x0)]); \ |
200 | 480 | set(7, S5[B1(x1)] ^ S6[B0(x1)] ^ S7[B2(x2)] ^ S8[B3(x2)] ^ S8[B3(x1)]); \ |
201 | 480 | \ |
202 | 480 | z0 = x0 ^ S5[B1(x3)] ^ S6[B3(x3)] ^ S7[B0(x3)] ^ S8[B2(x3)] ^ S7[B0(x2)]; \ |
203 | 480 | z1 = x2 ^ S5[B0(z0)] ^ S6[B2(z0)] ^ S7[B1(z0)] ^ S8[B3(z0)] ^ S8[B2(x2)]; \ |
204 | 480 | z2 = x3 ^ S5[B3(z1)] ^ S6[B2(z1)] ^ S7[B1(z1)] ^ S8[B0(z1)] ^ S5[B1(x2)]; \ |
205 | 480 | z3 = x1 ^ S5[B2(z2)] ^ S6[B1(z2)] ^ S7[B3(z2)] ^ S8[B0(z2)] ^ S6[B3(x2)]; \ |
206 | 480 | \ |
207 | 480 | set(8, S5[B3(z0)] ^ S6[B2(z0)] ^ S7[B0(z3)] ^ S8[B1(z3)] ^ S5[B1(z2)]); \ |
208 | 480 | set(9, S5[B1(z0)] ^ S6[B0(z0)] ^ S7[B2(z3)] ^ S8[B3(z3)] ^ S6[B0(z3)]); \ |
209 | 480 | set(10, S5[B3(z1)] ^ S6[B2(z1)] ^ S7[B0(z2)] ^ S8[B1(z2)] ^ S7[B2(z0)]); \ |
210 | 480 | set(11, S5[B1(z1)] ^ S6[B0(z1)] ^ S7[B2(z2)] ^ S8[B3(z2)] ^ S8[B2(z1)]); \ |
211 | 480 | \ |
212 | 480 | x0 = z2 ^ S5[B1(z1)] ^ S6[B3(z1)] ^ S7[B0(z1)] ^ S8[B2(z1)] ^ S7[B0(z0)]; \ |
213 | 480 | x1 = z0 ^ S5[B0(x0)] ^ S6[B2(x0)] ^ S7[B1(x0)] ^ S8[B3(x0)] ^ S8[B2(z0)]; \ |
214 | 480 | x2 = z1 ^ S5[B3(x1)] ^ S6[B2(x1)] ^ S7[B1(x1)] ^ S8[B0(x1)] ^ S5[B1(z0)]; \ |
215 | 480 | x3 = z3 ^ S5[B2(x2)] ^ S6[B1(x2)] ^ S7[B3(x2)] ^ S8[B0(x2)] ^ S6[B3(z0)]; \ |
216 | 480 | if (full) \ |
217 | 480 | { \ |
218 | 234 | set(12, S5[B0(x2)] ^ S6[B1(x2)] ^ S7[B3(x1)] ^ S8[B2(x1)] ^ S5[B3(x0)]); \ |
219 | 234 | set(13, S5[B2(x2)] ^ S6[B3(x2)] ^ S7[B1(x1)] ^ S8[B0(x1)] ^ S6[B3(x1)]); \ |
220 | 234 | set(14, S5[B0(x3)] ^ S6[B1(x3)] ^ S7[B3(x0)] ^ S8[B2(x0)] ^ S7[B0(x2)]); \ |
221 | 234 | set(15, S5[B2(x3)] ^ S6[B3(x3)] ^ S7[B1(x0)] ^ S8[B0(x0)] ^ S8[B1(x3)]); \ |
222 | 234 | } \ |
223 | 480 | } while (0) |
224 | | |
225 | | void |
226 | | cast5_set_key(struct cast128_ctx *ctx, |
227 | | size_t length, const uint8_t *key) |
228 | 240 | { |
229 | 240 | uint32_t x0, x1, x2, x3, z0, z1, z2, z3; |
230 | 240 | uint32_t w; |
231 | 240 | int full; |
232 | | |
233 | 240 | assert (length >= CAST5_MIN_KEY_SIZE); |
234 | 240 | assert (length <= CAST5_MAX_KEY_SIZE); |
235 | | |
236 | 240 | full = (length > CAST_SMALL_KEY); |
237 | | |
238 | 240 | x0 = READ_UINT32 (key); |
239 | | |
240 | | /* Read final word, possibly zero-padded. */ |
241 | 240 | switch (length & 3) |
242 | 240 | { |
243 | 160 | case 0: |
244 | 160 | w = READ_UINT32 (key + length - 4); |
245 | 160 | break; |
246 | 10 | case 3: |
247 | 10 | w = READ_UINT24 (key + length - 3) << 8; |
248 | 10 | break; |
249 | 69 | case 2: |
250 | 69 | w = READ_UINT16 (key + length - 2) << 16; |
251 | 69 | break; |
252 | 1 | case 1: |
253 | 1 | w = (uint32_t) key[length - 1] << 24; |
254 | 1 | break; |
255 | 240 | } |
256 | | |
257 | 240 | if (length <= 8) |
258 | 55 | { |
259 | 55 | x1 = w; |
260 | 55 | x2 = x3 = 0; |
261 | 55 | } |
262 | 185 | else |
263 | 185 | { |
264 | 185 | x1 = READ_UINT32 (key + 4); |
265 | 185 | if (length <= 12) |
266 | 171 | { |
267 | 171 | x2 = w; |
268 | 171 | x3 = 0; |
269 | 171 | } |
270 | 14 | else |
271 | 14 | { |
272 | 14 | x2 = READ_UINT32 (key + 8); |
273 | 14 | x3 = w; |
274 | 14 | } |
275 | 185 | } |
276 | | |
277 | 3.34k | EXPAND(SET_KM, full); |
278 | 3.34k | EXPAND(SET_KR, full); |
279 | | |
280 | 240 | ctx->rounds = full ? 16 : 12; |
281 | 240 | } |
282 | | |
283 | | void |
284 | | cast128_set_key(struct cast128_ctx *ctx, const uint8_t *key) |
285 | 0 | { |
286 | 0 | cast5_set_key (ctx, CAST128_KEY_SIZE, key); |
287 | 0 | } |