chiark / gitweb /
The Great Upheaval -- step 1.
[storin] / storin.c
1 /* -*-c-*-
2  *
3  * $Id$
4  *
5  * Block cipher optimized for DSPs
6  *
7  * (c) 2000 Mark Wooding
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * Copyright (c) 2000 Mark Wooding
13  * All rights reserved.
14  * 
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions are
17  * met:
18  * 
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 
22  * 2, Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 
26  * 3. The name of the authors may not be used to endorse or promote
27  *    products derived from this software without specific prior written
28  *    permission.
29  * 
30  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
31  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
32  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
33  * NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
36  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
38  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
39  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40  * POSSIBILITY OF SUCH DAMAGE.
41  * 
42  * Instead of accepting the above terms, you may redistribute and/or modify
43  * this software under the terms of either the GNU General Public License,
44  * or the GNU Library General Public License, published by the Free
45  * Software Foundation; either version 2 of the License, or (at your
46  * option) any later version.
47  */
48
49 /*----- Revision history --------------------------------------------------* 
50  *
51  * $Log: storin.c,v $
52  * Revision 1.2  2000/07/02 15:21:20  mdw
53  * Fix licence text.
54  *
55  * Revision 1.1  2000/05/21 11:28:30  mdw
56  * Initial check-in.
57  *
58  */
59
60 /*----- Header files ------------------------------------------------------*/
61
62 #include "storin.h"
63 #include "storin-tab.h"
64
65 #include "matrix.h"
66
67 /*----- Debugging output --------------------------------------------------*/
68
69 /* #define DEBUG */
70 /* #define TIMER */
71
72 #ifdef DEBUG
73 #  include <stdio.h>
74 #  define D(x) x
75 #else
76 #  define D(x)
77 #endif
78
79 /*----- The constant matrix -----------------------------------------------*/
80
81 static const uint24 m[] = STORIN_M, mi[] = STORIN_MI;
82
83 /*----- Main code ---------------------------------------------------------*/
84
85 /* --- @storin_init24@ --- *
86  *
87  * Arguments:   @storin_ctx *k@ = pointer to cipher context to initialize
88  *              @const uint24 *buf@ = pointer to buffer of key material
89  *              @size_t sz@ = size of the key material
90  *
91  * Returns:     ---
92  *
93  * Use:         Initializes the storin for use.
94  */
95
96 void storin_init24(storin_ctx *k, const uint24 *buf, size_t sz)
97 {
98   unsigned i, n;
99   uint24 mm[16];
100   const uint24 *d;
101   uint24 *dd;
102
103 #define KEYS (4 * (STORIN_ROUNDS + 1))
104
105   D( puts("Key schedule...\n"); )
106
107   /* --- Seed the subkey array --- */
108
109   d = m;
110   dd = k->k;
111   n = KEYS;
112   while (n > 15) {
113     matmul(dd, d, m, 4, 4, 4);
114     n -= 16;
115     d = dd;
116     dd += 16;
117   }
118   matmul(mm, d, m, 4, 4, 4);
119   for (i = 0; i < n; i++)
120     *dd++ = mm[i];
121
122   D( puts("Constant initial array contents:");
123      for (i = 0; i < KEYS; i++) {
124        printf("%06x ", k->k[i]);
125        if (i % 4 == 3)
126          fputc('\n', stdout);
127      }
128      fputc('\n', stdout); )
129
130   /* --- Mix in the real key material --- */
131
132   dd = k->k;
133   d = buf;
134   n = sz;
135   for (i = 0; i < KEYS; i++) {
136     *dd++ ^= *d++;
137     n--;
138     if (n == 0) {
139       n = sz;
140       d = buf;
141     }
142   }
143
144   D( puts("Array after mixing in key material:");
145      for (i = 0; i < KEYS; i++) {
146        printf("%06x ", k->k[i]);
147        if (i % 4 == 3)
148          fputc('\n', stdout);
149      }
150      fputc('\n', stdout); )
151
152   /* --- Now mangle the key material horribly --- */
153
154   for (i = 0; i < 4; i++)
155     mm[i] = 0;
156
157   dd = k->k;
158   for (i = 0; i < KEYS; i += 4) {
159     storin_eblk24(k, mm, mm);
160     for (n = 0; n < 4; n++)
161       dd[n] = mm[n];
162     dd += 4;
163   }
164
165   D( puts("Final round subkeys:");
166      for (i = 0; i < KEYS; i++) {
167        printf("%06x ", k->k[i]);
168        if (i % 4 == 3)
169          fputc('\n', stdout);
170      }
171      fputc('\n', stdout); )
172 }
173
174 /* --- @storin_eblk24@, @storin_dblk24@ --- *
175  *
176  * Arguments:   @const storin_ctx *k@ = pointer to cipher context
177  *              @const uint24 s[4]@ = pointer to source block
178  *              @uint24 d[4]@ = pointer to destination block
179  *
180  * Returns:     ---
181  *
182  * Use:         Low-level block encryption and decryption.
183  */
184
185 void storin_eblk24(const storin_ctx *k, const uint24 *s, uint24 *d)
186 {
187   unsigned i, j;
188   uint24 p[4], q[4];
189   const uint24 *kk = k->k;
190
191   D( puts("Encryption...");
192      printf(" plaintext: %06x %06x %06x %06x\n", s[0], s[1], s[2], s[3]); )
193
194   for (j = 0; j < 4; j++)
195     p[j] = s[j];
196
197   /* --- Main cipher guts --- */
198
199   for (i = 0; i < STORIN_ROUNDS; i++) {
200     D( printf("round %2i\n", i); )
201     for (j = 0; j < 4; j++)
202       q[j] = p[j] ^ *kk++;
203     D( printf("   mix key: %06x %06x %06x %06x\n", q[0], q[1], q[2], q[3]); )
204     matmul(p, m, q, 4, 4, 1);
205     D( printf("    matrix: %06x %06x %06x %06x\n", p[0], p[1], p[2], p[3]); )
206     for (j = 0; j < 4; j++)
207       p[j] ^= p[j] >> 12;
208     D( printf(" lin trans: %06x %06x %06x %06x\n", p[0], p[1], p[2], p[3]); )
209   }
210
211   /* --- Postwhitening and output --- */
212
213   for (j = 0; j < 4; j++)
214     d[j] = p[j] ^ *kk++;
215
216   D( printf("ciphertext: %06x %06x %06x %06x\n", d[0], d[1], d[2], d[3]); )
217 }
218
219
220 void storin_dblk24(const storin_ctx *k, const uint24 *s, uint24 *d)
221 {
222   unsigned i, j;
223   uint24 p[4], q[4];
224   const uint24 *kk = k->k + KEYS;
225
226   D( puts("Decryption...");
227      printf("ciphertext: %06x %06x %06x %06x\n", s[0], s[1], s[2], s[3]); )
228
229   for (j = 0; j < 4; j++)
230     p[j] = s[j];
231
232   /* --- Main cipher guts --- */
233
234   for (i = 0; i < STORIN_ROUNDS; i++) {
235     D( printf("round %2i\n", i); )
236     for (j = 0; j < 4; j++)
237       q[3 - j] = p[3 - j] ^ *--kk;
238     D( printf("   mix key: %06x %06x %06x %06x\n", q[0], q[1], q[2], q[3]); )
239     for (j = 0; j < 4; j++)
240       q[j] ^= q[j] >> 12;
241     D( printf(" lin trans: %06x %06x %06x %06x\n", p[0], p[1], p[2], p[3]); )
242     matmul(p, mi, q, 4, 4, 1);
243     D( printf("    matrix: %06x %06x %06x %06x\n", p[0], p[1], p[2], p[3]); )
244   }
245
246   /* --- Postwhitening and output --- */
247
248   for (j = 0; j < 4; j++)
249     d[3 - j] = p[3 - j] ^ *--kk;
250
251   D( printf(" plaintext: %06x %06x %06x %06x\n", d[0], d[1], d[2], d[3]); )
252 }
253
254 /*----- Test rig ----------------------------------------------------------*/
255
256 #if defined(DEBUG) || defined(TIMER)
257
258 #include <time.h>
259
260 int main(void)
261 {
262   uint24 kk[] = { 1, 2, 3, 4, 5 };
263   uint24 p[4] = { 6, 7, 8, 9 };
264   uint24 q[4];
265   storin_ctx c;
266
267   storin_init24(&c, kk, 5);
268
269 #ifdef DEBUG
270   storin_eblk24(&c, p, q);
271   storin_dblk24(&c, q, q);
272 #endif
273
274 #ifdef TIMER
275   {
276     time_t now, then;
277     unsigned n = 0;
278
279     then = time(0);
280     for (;;) {
281       storin_eblk24(&c, p, q);
282       n++;
283       now = time(0);
284       if (difftime(now, then) > 10.0)
285         break;
286     }
287     printf("%g blocks/s = %g bits/s\n", n / 10.0, n * 96.0 / 10.0);
288   }
289 #endif
290   return (0);
291 }
292
293 #endif
294
295 /*----- That's all, folks -------------------------------------------------*/