Add an internal-representation no-op function.
[u/mdw/catacomb] / rijndael.c
CommitLineData
3a65506d 1/* -*-c-*-
2 *
bb3d2477 3 * $Id: rijndael.c,v 1.3 2001/05/07 15:44:46 mdw Exp $
3a65506d 4 *
5 * The Rijndael 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/*----- Revision history --------------------------------------------------*
31 *
32 * $Log: rijndael.c,v $
bb3d2477 33 * Revision 1.3 2001/05/07 15:44:46 mdw
34 * Fix unusual numbers of rounds. Simplify implementation.
35 *
863e75ff 36 * Revision 1.2 2000/12/06 20:32:59 mdw
37 * Fix round count for weird key sizes.
38 *
3a65506d 39 * Revision 1.1 2000/06/17 11:56:07 mdw
40 * New cipher.
41 *
42 */
43
44/*----- Header files ------------------------------------------------------*/
45
46#include <assert.h>
47#include <stdio.h>
48
49#include <mLib/bits.h>
50
51#include "blkc.h"
52#include "gcipher.h"
53#include "rijndael.h"
54#include "rijndael-tab.h"
55
56/*----- Global variables --------------------------------------------------*/
57
58const octet rijndael_keysz[] = { KSZ_RANGE, RIJNDAEL_KEYSZ, 4, 32, 4 };
59
60/*----- Constant tables ---------------------------------------------------*/
61
62static const octet S[256] = RIJNDAEL_S, SI[256] = RIJNDAEL_SI;
63static const uint32 T[4][256] = RIJNDAEL_T, TI[4][256] = RIJNDAEL_TI;
64static const uint32 U[4][256] = RIJNDAEL_U;
65static const octet rcon[] = RIJNDAEL_RCON;
66
67/*----- Main code ---------------------------------------------------------*/
68
bb3d2477 69#define SUB(s, a, b, c, d) \
70 (s[U8((a) >> 0)] << 0 | s[U8((b) >> 8)] << 8 | \
71 s[U8((c) >> 16)] << 16 | s[U8((d) >> 24)] << 24)
72
73#define MIX(t, a, b, c, d) \
74 (t[0][U8((a) >> 0)] ^ t[1][U8((b) >> 8)] ^ \
75 t[2][U8((c) >> 16)] ^ t[3][U8((d) >> 24)])
3a65506d 76
77/* --- @rijndael_init@ --- *
78 *
79 * Arguments: @rijndael_ctx *k@ = pointer to context to initialize
80 * @const void *buf@ = pointer to buffer of key material
81 * @size_t sz@ = size of the key material
82 *
83 * Returns: ---
84 *
85 * Use: Initializes a Rijndael context with a particular key. This
86 * implementation of Rijndael doesn't impose any particular
87 * limits on the key size except that it must be multiple of 4
88 * bytes long. 256 bits seems sensible, though.
89 */
90
91void rijndael_init(rijndael_ctx *k, const void *buf, size_t sz)
92{
93 unsigned nk, nr, nw;
94 unsigned i, j, jj;
95 const octet *p;
96 uint32 ww;
97
98 /* --- Sort out the key size --- */
99
100 KSZ_ASSERT(rijndael, sz);
101 nk = sz / 4;
102
103 /* --- Select the number of rounds --- */
104
863e75ff 105 nr = nk + 6;
106 if (nr < 10)
3a65506d 107 nr = 10;
3a65506d 108 k->nr = nr;
109
110 /* --- Fetch the first key words out --- */
111
112 p = buf;
113 for (i = 0; i < nk; i++) {
114 k->w[i] = LOAD32_L(p);
115 p += 4;
116 }
117
118 /* --- Expand this material to fill the rest of the table --- */
119
120 nw = (nr + 1) * (RIJNDAEL_BLKSZ / 4);
121 ww = k->w[i - 1];
122 p = rcon;
123 for (; i < nw; i++) {
124 uint32 w = k->w[i - nk];
125 if (i % nk == 0) {
126 ww = ROR32(ww, 8);
bb3d2477 127 w ^= SUB(S, ww, ww, ww, ww) ^ *p++;
3a65506d 128 } else if (nk > 6 && i % nk == 4)
bb3d2477 129 w ^= SUB(S, ww, ww, ww, ww);
3a65506d 130 else
131 w ^= ww;
132 k->w[i] = ww = w;
133 }
134
135 /* --- Make the decryption keys --- */
136
137 j = nw;
138
139 j -= RIJNDAEL_BLKSZ / 4; jj = 0;
140 for (i = 0; i < RIJNDAEL_BLKSZ / 4; i++)
141 k->wi[i] = k->w[j + jj++];
142
143 for (; i < nw - RIJNDAEL_BLKSZ / 4; i += RIJNDAEL_BLKSZ / 4) {
144 j -= RIJNDAEL_BLKSZ / 4;
145 for (jj = 0; jj < RIJNDAEL_BLKSZ / 4; jj++) {
146 uint32 w = k->w[j + jj];
bb3d2477 147 k->wi[i + jj] = MIX(U, w, w, w, w);
3a65506d 148 }
149 }
150
151 j -= RIJNDAEL_BLKSZ / 4; jj = 0;
152 for (; i < nw; i++)
153 k->wi[i] = k->w[j + jj++];
154}
155
156/* --- @rijndael_eblk@, @rijndael_dblk@ --- *
157 *
158 * Arguments: @const rijndael_ctx *k@ = pointer to Rijndael context
159 * @const uint32 s[4]@ = pointer to source block
160 * @uint32 d[4]@ = pointer to destination block
161 *
162 * Returns: ---
163 *
164 * Use: Low-level block encryption and decryption.
165 */
166
bb3d2477 167#define DO(what, t, aa, bb, cc, dd, a, b, c, d, w) do { \
168 aa = what(t, a, b, c, d) ^ *w++; \
169 bb = what(t, b, c, d, a) ^ *w++; \
170 cc = what(t, c, d, a, b) ^ *w++; \
171 dd = what(t, d, a, b, c) ^ *w++; \
3a65506d 172} while (0)
173
bb3d2477 174#define UNDO(what, t, aa, bb, cc, dd, a, b, c, d, w) do { \
175 aa = what(t, a, d, c, b) ^ *w++; \
176 bb = what(t, b, a, d, c) ^ *w++; \
177 cc = what(t, c, b, a, d) ^ *w++; \
178 dd = what(t, d, c, b, a) ^ *w++; \
3a65506d 179} while (0)
180
181void rijndael_eblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
182{
183 uint32 a = s[0], b = s[1], c = s[2], d = s[3];
184 uint32 aa, bb, cc, dd;
185 uint32 *w = k->w;
186
187 a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
bb3d2477 188 aa = a; bb = b; cc = c; dd = d;
3a65506d 189
190 switch (k->nr) {
191 case 14:
bb3d2477 192 DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
193 case 13:
194 DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
3a65506d 195 case 12:
bb3d2477 196 DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
197 case 11:
198 DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
3a65506d 199 case 10:
200 default:
bb3d2477 201 DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
202 DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
203 DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
204 DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
205 DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
206 DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
207 DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
208 DO(MIX, T, a, b, c, d, aa, bb, cc, dd, w);
209 DO(MIX, T, aa, bb, cc, dd, a, b, c, d, w);
3a65506d 210 }
bb3d2477 211 DO(SUB, S, a, b, c, d, aa, bb, cc, dd, w);
3a65506d 212
213 dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
214}
215
216void rijndael_dblk(const rijndael_ctx *k, const uint32 *s, uint32 *dst)
217{
218 uint32 a = s[0], b = s[1], c = s[2], d = s[3];
219 uint32 aa, bb, cc, dd;
220 uint32 *w = k->wi;
221
222 a ^= *w++; b ^= *w++; c ^= *w++; d ^= *w++;
bb3d2477 223 aa = a; bb = b; cc = c; dd = d;
3a65506d 224
225 switch (k->nr) {
226 case 14:
bb3d2477 227 UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
228 case 13:
229 UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
3a65506d 230 case 12:
bb3d2477 231 UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
232 case 11:
233 UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
3a65506d 234 case 10:
235 default:
bb3d2477 236 UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
237 UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
238 UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
239 UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
240 UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
241 UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
242 UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
243 UNDO(MIX, TI, a, b, c, d, aa, bb, cc, dd, w);
244 UNDO(MIX, TI, aa, bb, cc, dd, a, b, c, d, w);
3a65506d 245 }
bb3d2477 246 UNDO(SUB, SI, a, b, c, d, aa, bb, cc, dd, w);
3a65506d 247
248 dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d;
249}
250
251BLKC_TEST(RIJNDAEL, rijndael)
252
253/*----- That's all, folks -------------------------------------------------*/