Release 2.1.3.
[u/mdw/catacomb] / serpent.c
1 /* -*-c-*-
2 *
3 * $Id: serpent.c,v 1.2 2004/04/08 01:36:15 mdw Exp $
4 *
5 * The Serpent block cipher
6 *
7 * (c) 2000 Straylight/Edgeware
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Catacomb.
13 *
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30 /*----- Header files ------------------------------------------------------*/
31
32 #include <assert.h>
33 #include <stdio.h>
34
35 #include <mLib/bits.h>
36
37 #include "blkc.h"
38 #include "gcipher.h"
39 #include "serpent.h"
40 #include "serpent-sbox.h"
41
42 /*----- Global variables --------------------------------------------------*/
43
44 const octet serpent_keysz[] = { KSZ_RANGE, SERPENT_KEYSZ, 0, 32, 1 };
45
46 /*----- Main code ---------------------------------------------------------*/
47
48 /* --- @serpent_init@ --- *
49 *
50 * Arguments: @serpent_ctx *k@ = pointer to context block to initialize
51 * @const void *buf@ = pointer to input buffer
52 * @size_t sz@ = size of input buffer
53 *
54 * Returns: ---
55 *
56 * Use: Initializes a Serpent context. The key may be any length of
57 * up to 32 bytes (256 bits).
58 */
59
60 void serpent_init(serpent_ctx *k, const void *buf, size_t sz)
61 {
62 uint32 a;
63 unsigned b;
64 const octet *p, *q;
65 size_t i;
66 uint32 pk[8 + 132];
67
68 KSZ_ASSERT(serpent, sz);
69
70 /* --- Read the key into the buffer --- */
71
72 if (sz > 32)
73 sz = 32;
74 i = 0; p = buf; q = p + sz;
75 a = 0; b = 0;
76 while (p < q) {
77 a |= (uint32)*p++ << b;
78 b += 8;
79 if (b == 32) {
80 pk[i++] = a;
81 a = 0; b = 0;
82 }
83 }
84
85 /* --- Pad short keys --- */
86
87 if (i < 8) {
88 a |= 0x01 << b;
89 b += 8;
90 pk[i++] = a;
91 for (; i < 8; i++)
92 pk[i] = 0;
93 }
94
95 /* --- Expand the prekeys to fill the buffer --- */
96
97 for (i = 8; i < 8 + 132; i++) {
98 uint32 x = (pk[i - 8] ^ pk[i - 5] ^ pk[i - 3] ^ pk[i - 1] ^
99 (i - 8) ^ 0x9e3779b9);
100 k->k[i - 8] = pk[i] = ROL32(x, 11);
101 }
102
103 /* --- Now substitute everything --- */
104
105 i = 0;
106 goto midway;
107 while (i < 132) {
108 #define KSUB(r) do { \
109 uint32 a, b, c, d; \
110 a = k->k[i]; b = k->k[i + 1]; c = k->k[i + 2]; d = k->k[i + 3]; \
111 S##r(a, b, c, d); \
112 k->k[i] = a; k->k[i + 1] = b; k->k[i + 2] = c; k->k[i + 3] = d; \
113 i += 4; \
114 } while (0)
115 KSUB(2); KSUB(1); KSUB(0); KSUB(7);
116 KSUB(6); KSUB(5); KSUB(4);
117 midway:
118 KSUB(3);
119 #undef KSUB
120 }
121 }
122
123 /* --- @serpent_eblk@, @serpent_dblk@ --- *
124 *
125 * Arguments: @const serpent_ctx *k@ = pointer to key context
126 * @const uint32 s[4]@ = pointer to source block
127 * @uint32 d[4]@ = pointer to destination block
128 *
129 * Returns: ---
130 *
131 * Use: Low-level block encryption.
132 */
133
134 #define EROUND(a, b, c, d, r, k) do { \
135 a ^= *k++; b ^= *k++; c ^= *k++; d ^= *k++; \
136 S##r(a, b, c, d); \
137 a = ROL32(a, 13); c = ROL32(c, 3); b ^= a ^ c; d ^= c ^ (a << 3); \
138 b = ROL32(b, 1); d = ROL32(d, 7); a ^= b ^ d; c ^= d ^ (b << 7); \
139 a = ROL32(a, 5); c = ROL32(c, 22); \
140 } while (0)
141
142 #define DROUND(a, b, c, d, r, k) do { \
143 IS##r(a, b, c, d); \
144 d ^= *--k; c ^= *--k; b ^= *--k; a ^= *--k; \
145 a = ROR32(a, 5); c = ROR32(c, 22); a ^= b ^ d; c ^= d ^ (b << 7); \
146 b = ROR32(b, 1); d = ROR32(d, 7); b ^= a ^ c; d ^= c ^ (a << 3); \
147 a = ROR32(a, 13); c = ROR32(c, 3); \
148 } while (0)
149
150 void serpent_eblk(const serpent_ctx *k, const uint32 *s, uint32 *d)
151 {
152 uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
153 const uint32 *kk = k->k;
154
155 EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
156 EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
157 EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
158 EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk);
159
160 EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
161 EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
162 EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
163 EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk);
164
165 EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
166 EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
167 EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
168 EROUND(aa, bb, cc, dd, 6, kk); EROUND(aa, bb, cc, dd, 7, kk);
169
170 EROUND(aa, bb, cc, dd, 0, kk); EROUND(aa, bb, cc, dd, 1, kk);
171 EROUND(aa, bb, cc, dd, 2, kk); EROUND(aa, bb, cc, dd, 3, kk);
172 EROUND(aa, bb, cc, dd, 4, kk); EROUND(aa, bb, cc, dd, 5, kk);
173 EROUND(aa, bb, cc, dd, 6, kk);
174
175 aa ^= *kk++; bb ^= *kk++; cc ^= *kk++; dd ^= *kk++;
176 S7(aa, bb, cc, dd);
177 aa ^= *kk++; bb ^= *kk++; cc ^= *kk++; dd ^= *kk++;
178 d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
179 }
180
181 void serpent_dblk(const serpent_ctx *k, const uint32 *s, uint32 *d)
182 {
183 uint32 aa = s[0], bb = s[1], cc = s[2], dd = s[3];
184 const uint32 *kk = k->k + 132;
185
186 dd ^= *--kk; cc ^= *--kk; bb ^= *--kk; aa ^= *--kk;
187
188 DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
189 DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
190 DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
191 DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk);
192
193 DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
194 DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
195 DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
196 DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk);
197
198 DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
199 DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
200 DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
201 DROUND(aa, bb, cc, dd, 1, kk); DROUND(aa, bb, cc, dd, 0, kk);
202
203 DROUND(aa, bb, cc, dd, 7, kk); DROUND(aa, bb, cc, dd, 6, kk);
204 DROUND(aa, bb, cc, dd, 5, kk); DROUND(aa, bb, cc, dd, 4, kk);
205 DROUND(aa, bb, cc, dd, 3, kk); DROUND(aa, bb, cc, dd, 2, kk);
206 DROUND(aa, bb, cc, dd, 1, kk);
207
208 IS0(aa, bb, cc, dd);
209 dd ^= *--kk; cc ^= *--kk; bb ^= *--kk; aa ^= *--kk;
210 d[0] = aa; d[1] = bb; d[2] = cc; d[3] = dd;
211 }
212
213 BLKC_TEST(SERPENT, serpent)
214
215 /*----- That's all, folks -------------------------------------------------*/