3 The CAST-128 block cipher, described in RFC 2144.
5 Copyright (C) 2001, 2014 Niels Möller
7 This file is part of GNU Nettle.
9 GNU Nettle is free software: you can redistribute it and/or
10 modify it under the terms of either:
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.
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.
22 or both in parallel, as here.
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.
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/.
37 * Written by Steve Reid <sreid@sea-to-sky.net>
38 * 100% Public Domain - no warranty
51 #include "cast128_sboxes.h"
55 #define CAST_SMALL_KEY 10
66 /* Macros to access 8-bit bytes out of a 32-bit word */
67 #define B0(x) ( (uint8_t) (x>>24) )
68 #define B1(x) ( (uint8_t) ((x>>16)&0xff) )
69 #define B2(x) ( (uint8_t) ((x>>8)&0xff) )
70 #define B3(x) ( (uint8_t) ((x)&0xff) )
72 /* NOTE: Depends on ROTL32 supporting a zero shift count. */
74 /* CAST-128 uses three different round functions */
75 #define F1(l, r, i) do { \
77 t = ROTL32(ctx->Kr[i], t); \
78 l ^= ((S1[B0(t)] ^ S2[B1(t)]) - S3[B2(t)]) + S4[B3(t)]; \
80 #define F2(l, r, i) do { \
82 t = ROTL32( ctx->Kr[i], t); \
83 l ^= ((S1[B0(t)] - S2[B1(t)]) + S3[B2(t)]) ^ S4[B3(t)]; \
85 #define F3(l, r, i) do { \
87 t = ROTL32(ctx->Kr[i], t); \
88 l ^= ((S1[B0(t)] + S2[B1(t)]) ^ S3[B2(t)]) - S4[B3(t)]; \
92 /***** Encryption Function *****/
95 cast128_encrypt(const struct cast128_ctx *ctx,
96 size_t length, uint8_t *dst,
99 FOR_BLOCKS(length, dst, src, CAST128_BLOCK_SIZE)
103 /* Get inblock into l,r */
104 l = READ_UINT32(src);
105 r = READ_UINT32(src+4);
120 /* Only do full 16 rounds if key length > 80 bits */
121 if (ctx->rounds & 16) {
127 /* Put l,r into outblock */
128 WRITE_UINT32(dst, r);
129 WRITE_UINT32(dst + 4, l);
134 /***** Decryption Function *****/
137 cast128_decrypt(const struct cast128_ctx *ctx,
138 size_t length, uint8_t *dst,
141 FOR_BLOCKS(length, dst, src, CAST128_BLOCK_SIZE)
145 /* Get inblock into l,r */
146 r = READ_UINT32(src);
147 l = READ_UINT32(src+4);
150 /* Only do full 16 rounds if key length > 80 bits */
151 if (ctx->rounds & 16) {
170 /* Put l,r into outblock */
171 WRITE_UINT32(dst, l);
172 WRITE_UINT32(dst + 4, r);
176 /***** Key Schedule *****/
178 #define SET_KM(i, k) ctx->Km[i] = (k)
179 #define SET_KR(i, k) ctx->Kr[i] = (k) & 31
181 #define EXPAND(set, full) do { \
182 z0 = x0 ^ S5[B1(x3)] ^ S6[B3(x3)] ^ S7[B0(x3)] ^ S8[B2(x3)] ^ S7[B0(x2)]; \
183 z1 = x2 ^ S5[B0(z0)] ^ S6[B2(z0)] ^ S7[B1(z0)] ^ S8[B3(z0)] ^ S8[B2(x2)]; \
184 z2 = x3 ^ S5[B3(z1)] ^ S6[B2(z1)] ^ S7[B1(z1)] ^ S8[B0(z1)] ^ S5[B1(x2)]; \
185 z3 = x1 ^ S5[B2(z2)] ^ S6[B1(z2)] ^ S7[B3(z2)] ^ S8[B0(z2)] ^ S6[B3(x2)]; \
187 set(0, S5[B0(z2)] ^ S6[B1(z2)] ^ S7[B3(z1)] ^ S8[B2(z1)] ^ S5[B2(z0)]); \
188 set(1, S5[B2(z2)] ^ S6[B3(z2)] ^ S7[B1(z1)] ^ S8[B0(z1)] ^ S6[B2(z1)]); \
189 set(2, S5[B0(z3)] ^ S6[B1(z3)] ^ S7[B3(z0)] ^ S8[B2(z0)] ^ S7[B1(z2)]); \
190 set(3, S5[B2(z3)] ^ S6[B3(z3)] ^ S7[B1(z0)] ^ S8[B0(z0)] ^ S8[B0(z3)]); \
192 x0 = z2 ^ S5[B1(z1)] ^ S6[B3(z1)] ^ S7[B0(z1)] ^ S8[B2(z1)] ^ S7[B0(z0)]; \
193 x1 = z0 ^ S5[B0(x0)] ^ S6[B2(x0)] ^ S7[B1(x0)] ^ S8[B3(x0)] ^ S8[B2(z0)]; \
194 x2 = z1 ^ S5[B3(x1)] ^ S6[B2(x1)] ^ S7[B1(x1)] ^ S8[B0(x1)] ^ S5[B1(z0)]; \
195 x3 = z3 ^ S5[B2(x2)] ^ S6[B1(x2)] ^ S7[B3(x2)] ^ S8[B0(x2)] ^ S6[B3(z0)]; \
197 set(4, S5[B3(x0)] ^ S6[B2(x0)] ^ S7[B0(x3)] ^ S8[B1(x3)] ^ S5[B0(x2)]); \
198 set(5, S5[B1(x0)] ^ S6[B0(x0)] ^ S7[B2(x3)] ^ S8[B3(x3)] ^ S6[B1(x3)]); \
199 set(6, S5[B3(x1)] ^ S6[B2(x1)] ^ S7[B0(x2)] ^ S8[B1(x2)] ^ S7[B3(x0)]); \
200 set(7, S5[B1(x1)] ^ S6[B0(x1)] ^ S7[B2(x2)] ^ S8[B3(x2)] ^ S8[B3(x1)]); \
202 z0 = x0 ^ S5[B1(x3)] ^ S6[B3(x3)] ^ S7[B0(x3)] ^ S8[B2(x3)] ^ S7[B0(x2)]; \
203 z1 = x2 ^ S5[B0(z0)] ^ S6[B2(z0)] ^ S7[B1(z0)] ^ S8[B3(z0)] ^ S8[B2(x2)]; \
204 z2 = x3 ^ S5[B3(z1)] ^ S6[B2(z1)] ^ S7[B1(z1)] ^ S8[B0(z1)] ^ S5[B1(x2)]; \
205 z3 = x1 ^ S5[B2(z2)] ^ S6[B1(z2)] ^ S7[B3(z2)] ^ S8[B0(z2)] ^ S6[B3(x2)]; \
207 set(8, S5[B3(z0)] ^ S6[B2(z0)] ^ S7[B0(z3)] ^ S8[B1(z3)] ^ S5[B1(z2)]); \
208 set(9, S5[B1(z0)] ^ S6[B0(z0)] ^ S7[B2(z3)] ^ S8[B3(z3)] ^ S6[B0(z3)]); \
209 set(10, S5[B3(z1)] ^ S6[B2(z1)] ^ S7[B0(z2)] ^ S8[B1(z2)] ^ S7[B2(z0)]); \
210 set(11, S5[B1(z1)] ^ S6[B0(z1)] ^ S7[B2(z2)] ^ S8[B3(z2)] ^ S8[B2(z1)]); \
212 x0 = z2 ^ S5[B1(z1)] ^ S6[B3(z1)] ^ S7[B0(z1)] ^ S8[B2(z1)] ^ S7[B0(z0)]; \
213 x1 = z0 ^ S5[B0(x0)] ^ S6[B2(x0)] ^ S7[B1(x0)] ^ S8[B3(x0)] ^ S8[B2(z0)]; \
214 x2 = z1 ^ S5[B3(x1)] ^ S6[B2(x1)] ^ S7[B1(x1)] ^ S8[B0(x1)] ^ S5[B1(z0)]; \
215 x3 = z3 ^ S5[B2(x2)] ^ S6[B1(x2)] ^ S7[B3(x2)] ^ S8[B0(x2)] ^ S6[B3(z0)]; \
218 set(12, S5[B0(x2)] ^ S6[B1(x2)] ^ S7[B3(x1)] ^ S8[B2(x1)] ^ S5[B3(x0)]); \
219 set(13, S5[B2(x2)] ^ S6[B3(x2)] ^ S7[B1(x1)] ^ S8[B0(x1)] ^ S6[B3(x1)]); \
220 set(14, S5[B0(x3)] ^ S6[B1(x3)] ^ S7[B3(x0)] ^ S8[B2(x0)] ^ S7[B0(x2)]); \
221 set(15, S5[B2(x3)] ^ S6[B3(x3)] ^ S7[B1(x0)] ^ S8[B0(x0)] ^ S8[B1(x3)]); \
226 cast5_set_key(struct cast128_ctx *ctx,
227 size_t length, const uint8_t *key)
229 uint32_t x0, x1, x2, x3, z0, z1, z2, z3;
233 assert (length >= CAST5_MIN_KEY_SIZE);
234 assert (length <= CAST5_MAX_KEY_SIZE);
236 full = (length > CAST_SMALL_KEY);
238 x0 = READ_UINT32 (key);
240 /* Read final word, possibly zero-padded. */
244 w = READ_UINT32 (key + length - 4);
247 w = READ_UINT24 (key + length - 3) << 8;
250 w = READ_UINT16 (key + length - 2) << 16;
253 w = (uint32_t) key[length - 1] << 24;
264 x1 = READ_UINT32 (key + 4);
272 x2 = READ_UINT32 (key + 8);
277 EXPAND(SET_KM, full);
278 EXPAND(SET_KR, full);
280 ctx->rounds = full ? 16 : 12;
284 cast128_set_key(struct cast128_ctx *ctx, const uint8_t *key)
286 cast5_set_key (ctx, CAST128_KEY_SIZE, key);