chiark / gitweb /
Improve analysis section.
[storin] / storin.c
1 /* -*-c-*-
2  *
3  * $Id: storin.c,v 1.1 2000/05/21 11:28:30 mdw Exp $
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 REGENTS 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.1  2000/05/21 11:28:30  mdw
53  * Initial check-in.
54  *
55  */
56
57 /*----- Header files ------------------------------------------------------*/
58
59 #include "storin.h"
60 #include "storin-tab.h"
61
62 #include "matrix.h"
63
64 /*----- Debugging output --------------------------------------------------*/
65
66 /* #define DEBUG */
67 /* #define TIMER */
68
69 #ifdef DEBUG
70 #  include <stdio.h>
71 #  define D(x) x
72 #else
73 #  define D(x)
74 #endif
75
76 /*----- The constant matrix -----------------------------------------------*/
77
78 static const uint24 m[] = STORIN_M, mi[] = STORIN_MI;
79
80 /*----- Main code ---------------------------------------------------------*/
81
82 /* --- @storin_init24@ --- *
83  *
84  * Arguments:   @storin_ctx *k@ = pointer to cipher context to initialize
85  *              @const uint24 *buf@ = pointer to buffer of key material
86  *              @size_t sz@ = size of the key material
87  *
88  * Returns:     ---
89  *
90  * Use:         Initializes the storin for use.
91  */
92
93 void storin_init24(storin_ctx *k, const uint24 *buf, size_t sz)
94 {
95   unsigned i, n;
96   uint24 mm[16];
97   const uint24 *d;
98   uint24 *dd;
99
100 #define KEYS (4 * (STORIN_ROUNDS + 1))
101
102   D( puts("Key schedule...\n"); )
103
104   /* --- Seed the subkey array --- */
105
106   d = m;
107   dd = k->k;
108   n = KEYS;
109   while (n > 15) {
110     matmul(dd, d, m, 4, 4, 4);
111     n -= 16;
112     d = dd;
113     dd += 16;
114   }
115   matmul(mm, d, m, 4, 4, 4);
116   for (i = 0; i < n; i++)
117     *dd++ = mm[i];
118
119   D( puts("Constant initial array contents:");
120      for (i = 0; i < KEYS; i++) {
121        printf("%06x ", k->k[i]);
122        if (i % 4 == 3)
123          fputc('\n', stdout);
124      }
125      fputc('\n', stdout); )
126
127   /* --- Mix in the real key material --- */
128
129   dd = k->k;
130   d = buf;
131   n = sz;
132   for (i = 0; i < KEYS; i++) {
133     *dd++ ^= *d++;
134     n--;
135     if (n == 0) {
136       n = sz;
137       d = buf;
138     }
139   }
140
141   D( puts("Array after mixing in key material:");
142      for (i = 0; i < KEYS; i++) {
143        printf("%06x ", k->k[i]);
144        if (i % 4 == 3)
145          fputc('\n', stdout);
146      }
147      fputc('\n', stdout); )
148
149   /* --- Now mangle the key material horribly --- */
150
151   for (i = 0; i < 4; i++)
152     mm[i] = 0;
153
154   dd = k->k;
155   for (i = 0; i < KEYS; i += 4) {
156     storin_eblk24(k, mm, mm);
157     for (n = 0; n < 4; n++)
158       dd[n] = mm[n];
159     dd += 4;
160   }
161
162   D( puts("Final round subkeys:");
163      for (i = 0; i < KEYS; i++) {
164        printf("%06x ", k->k[i]);
165        if (i % 4 == 3)
166          fputc('\n', stdout);
167      }
168      fputc('\n', stdout); )
169 }
170
171 /* --- @storin_eblk24@, @storin_dblk24@ --- *
172  *
173  * Arguments:   @const storin_ctx *k@ = pointer to cipher context
174  *              @const uint24 s[4]@ = pointer to source block
175  *              @uint24 d[4]@ = pointer to destination block
176  *
177  * Returns:     ---
178  *
179  * Use:         Low-level block encryption and decryption.
180  */
181
182 void storin_eblk24(const storin_ctx *k, const uint24 *s, uint24 *d)
183 {
184   unsigned i, j;
185   uint24 p[4], q[4];
186   const uint24 *kk = k->k;
187
188   D( puts("Encryption...");
189      printf(" plaintext: %06x %06x %06x %06x\n", s[0], s[1], s[2], s[3]); )
190
191   for (j = 0; j < 4; j++)
192     p[j] = s[j];
193
194   /* --- Main cipher guts --- */
195
196   for (i = 0; i < STORIN_ROUNDS; i++) {
197     D( printf("round %2i\n", i); )
198     for (j = 0; j < 4; j++)
199       q[j] = p[j] ^ *kk++;
200     D( printf("   mix key: %06x %06x %06x %06x\n", q[0], q[1], q[2], q[3]); )
201     matmul(p, m, q, 4, 4, 1);
202     D( printf("    matrix: %06x %06x %06x %06x\n", p[0], p[1], p[2], p[3]); )
203     for (j = 0; j < 4; j++)
204       p[j] ^= p[j] >> 12;
205     D( printf(" lin trans: %06x %06x %06x %06x\n", p[0], p[1], p[2], p[3]); )
206   }
207
208   /* --- Postwhitening and output --- */
209
210   for (j = 0; j < 4; j++)
211     d[j] = p[j] ^ *kk++;
212
213   D( printf("ciphertext: %06x %06x %06x %06x\n", d[0], d[1], d[2], d[3]); )
214 }
215
216
217 void storin_dblk24(const storin_ctx *k, const uint24 *s, uint24 *d)
218 {
219   unsigned i, j;
220   uint24 p[4], q[4];
221   const uint24 *kk = k->k + KEYS;
222
223   D( puts("Decryption...");
224      printf("ciphertext: %06x %06x %06x %06x\n", s[0], s[1], s[2], s[3]); )
225
226   for (j = 0; j < 4; j++)
227     p[j] = s[j];
228
229   /* --- Main cipher guts --- */
230
231   for (i = 0; i < STORIN_ROUNDS; i++) {
232     D( printf("round %2i\n", i); )
233     for (j = 0; j < 4; j++)
234       q[3 - j] = p[3 - j] ^ *--kk;
235     D( printf("   mix key: %06x %06x %06x %06x\n", q[0], q[1], q[2], q[3]); )
236     for (j = 0; j < 4; j++)
237       q[j] ^= q[j] >> 12;
238     D( printf(" lin trans: %06x %06x %06x %06x\n", p[0], p[1], p[2], p[3]); )
239     matmul(p, mi, q, 4, 4, 1);
240     D( printf("    matrix: %06x %06x %06x %06x\n", p[0], p[1], p[2], p[3]); )
241   }
242
243   /* --- Postwhitening and output --- */
244
245   for (j = 0; j < 4; j++)
246     d[3 - j] = p[3 - j] ^ *--kk;
247
248   D( printf(" plaintext: %06x %06x %06x %06x\n", d[0], d[1], d[2], d[3]); )
249 }
250
251 /*----- Test rig ----------------------------------------------------------*/
252
253 #if defined(DEBUG) || defined(TIMER)
254
255 #include <time.h>
256
257 int main(void)
258 {
259   uint24 kk[] = { 1, 2, 3, 4, 5 };
260   uint24 p[4] = { 6, 7, 8, 9 };
261   uint24 q[4];
262   storin_ctx c;
263
264   storin_init24(&c, kk, 5);
265
266 #ifdef DEBUG
267   storin_eblk24(&c, p, q);
268   storin_dblk24(&c, q, q);
269 #endif
270
271 #ifdef TIMER
272   {
273     time_t now, then;
274     unsigned n = 0;
275
276     then = time(0);
277     for (;;) {
278       storin_eblk24(&c, p, q);
279       n++;
280       now = time(0);
281       if (difftime(now, then) > 10.0)
282         break;
283     }
284     printf("%g blocks/s = %g bits/s\n", n / 10.0, n * 96.0 / 10.0);
285   }
286 #endif
287   return (0);
288 }
289
290 #endif
291
292 /*----- That's all, folks -------------------------------------------------*/