chiark / gitweb /
Release 2.4.0.
[catacomb] / symm / square.c
1 /* -*-c-*-
2  *
3  * The Square block cipher
4  *
5  * (c) 2000 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Catacomb.
11  *
12  * Catacomb is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * Catacomb is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with Catacomb; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 #include <assert.h>
31 #include <stdio.h>
32
33 #include <mLib/bits.h>
34 #include <mLib/macros.h>
35
36 #include "blkc.h"
37 #include "gcipher.h"
38 #include "paranoia.h"
39 #include "square.h"
40
41 /*----- Global variables --------------------------------------------------*/
42
43 const octet square_keysz[] = { KSZ_RANGE, SQUARE_KEYSZ, 4, 16, 4 };
44
45 /*----- Constant tables ---------------------------------------------------*/
46
47 extern const octet square_s[256], square_si[256];
48 extern const uint32 square_t[4][256], square_ti[4][256];
49 extern const uint32 square_u[4][256];
50 extern const octet square_rcon[32];
51
52 #define S square_s
53 #define SI square_si
54 #define T square_t
55 #define TI square_ti
56 #define U square_u
57 #define RCON square_rcon
58
59 /*----- Main code ---------------------------------------------------------*/
60
61 /* --- @square_init@ --- *
62  *
63  * Arguments:   @square_ctx *k@ = pointer to context to initialize
64  *              @const void *buf@ = pointer to buffer of key material
65  *              @size_t sz@ = size of the key material
66  *
67  * Returns:     ---
68  *
69  * Use:         Initializes a Square context with a particular key.  Square
70  *              keys must be a multiple of 32 bits long, and may be at most
71  *              128 bits.
72  */
73
74 void square_init(square_ctx *k, const void *buf, size_t sz)
75 {
76   unsigned nk, nr, nw;
77   unsigned i, j, jj;
78   const octet *p;
79   uint32 ww;
80   uint32 kk[SQUARE_KWORDS];
81
82   /* --- Sort out the key size --- */
83
84   KSZ_ASSERT(square, sz);
85   nk = sz / 4;
86
87   /* --- Fetch the first key words out --- */
88
89   p = buf;
90   for (i = 0; i < nk; i++) {
91     kk[i] = LOAD32_L(p);
92     p += 4;
93   }
94   nr = 8;
95
96   /* --- GCC complains about an out-of-bounds subscript here --- *
97    *
98    * This is impossible.  Thanks to @KSZ_ASSERT@, we know that @4 <= sz <=
99    * 16@ and hence @1 <= i <= nk <= 4@; but @SQUARE_KWORDS == 36@.
100    */
101
102   ww = MUFFLE_WARNINGS_EXPR(GCC_WARNING("-Warray-bounds"), kk[i - 1]);
103
104   /* --- Expand this material to fill the rest of the table --- */
105
106   nw = (nr + 1) * 4;
107   p = RCON;
108   for (; i < nw; i++) {
109     uint32 w = kk[i - nk];
110     if (i % nk == 0) {
111       ww = ROR32(ww, 8);
112       w ^= ww ^ *p++;
113     } else
114       w ^= ww;
115     kk[i] = ww = w;
116   }
117
118   /* --- Make the encryption and decryption keys --- */
119
120   for (i = 0; i < nr * 4; i++) {
121     uint32 w = kk[i];
122     k->w[i] = (U[0][U8(w >>  0)] ^ U[1][U8(w >>  8)] ^
123                U[2][U8(w >> 16)] ^ U[3][U8(w >> 24)]);
124   }
125   for (; i < nw; i++)
126     k->w[i] = kk[i];
127
128   jj = nw;
129   for (i = 0; i < nr * 4; i += 4) {
130     jj -= 4;
131     for (j = 0; j < 4; j++)
132       k->wi[i + j] = kk[jj + j];
133   }
134   for (j = 0; j < 4; j++)
135     k->wi[i + j] = k->w[j];
136
137   BURN(kk);
138 }
139
140 /* --- @square_eblk@, @square_dblk@ --- *
141  *
142  * Arguments:   @const square_ctx *k@ = pointer to Square context
143  *              @const uint32 s[4]@ = pointer to source block
144  *              @uint32 d[4]@ = pointer to destination block
145  *
146  * Returns:     ---
147  *
148  * Use:         Low-level block encryption and decryption.
149  */
150
151 #define SUB(s, sh, a, b, c, d)                                          \
152   (s[U8((a) >> sh)] <<  0 | s[U8((b) >> sh)] <<  8 |                    \
153    s[U8((c) >> sh)] << 16 | s[U8((d) >> sh)] << 24)
154
155 #define MIX(t, sh, a, b, c, d)                                          \
156   (t[0][U8((a) >> sh)] ^ t[1][U8((b) >> sh)] ^                          \
157    t[2][U8((c) >> sh)] ^ t[3][U8((d) >> sh)])
158
159 #define DO(what, t, aa, bb, cc, dd, a, b, c, d, w) do {                 \
160   aa = what(t,  0, a, b, c, d) ^ *w++;                                  \
161   bb = what(t,  8, a, b, c, d) ^ *w++;                                  \
162   cc = what(t, 16, a, b, c, d) ^ *w++;                                  \
163   dd = what(t, 24, a, b, c, d) ^ *w++;                                  \
164 } while (0)
165
166 void square_eblk(const square_ctx *k, const uint32 *s, uint32 *dst)
167 {
168   uint32 a = s[0], b = s[1], c = s[2], d = s[3];
169   uint32 aa, bb, cc, dd;
170   const uint32 *w = k->w;
171
172   a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
173
174   DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
175   DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
176   DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
177   DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
178   DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
179   DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
180   DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
181   DO(SUB, S, a, b, c, d, aa, bb, cc, dd, w);
182
183   dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
184 }
185
186 void square_dblk(const square_ctx *k, const uint32 *s, uint32 *dst)
187 {
188   uint32 a = s[0], b = s[1], c = s[2], d = s[3];
189   uint32 aa, bb, cc, dd;
190   const uint32 *w = k->wi;
191
192   a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
193
194   DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
195   DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
196   DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
197   DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
198   DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
199   DO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
200   DO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
201   DO(SUB, SI, a, b, c, d, aa, bb, cc, dd, w);
202
203   dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
204 }
205
206 BLKC_TEST(SQUARE, square)
207
208 /*----- That's all, folks -------------------------------------------------*/