chiark / gitweb /
Add some more vectors, and a whinge about how Skipjack test vectors are.
[catacomb] / rc5.c
1 /* -*-c-*-
2  *
3  * $Id: rc5.c,v 1.2 2000/06/17 11:56:00 mdw Exp $
4  *
5  * The RC5-32/12 block cipher
6  *
7  * (c) 1999 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: rc5.c,v $
33  * Revision 1.2  2000/06/17 11:56:00  mdw
34  * New key size interface.  Use secure arena for memory allocation.
35  *
36  * Revision 1.1  1999/09/03 08:41:12  mdw
37  * Initial import.
38  *
39  */
40
41 /*----- Header files ------------------------------------------------------*/
42
43 #include <assert.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include <mLib/alloc.h>
48 #include <mLib/bits.h>
49
50 #include "arena.h"
51 #include "blkc.h"
52 #include "gcipher.h"
53 #include "rc5.h"
54
55 /*----- Global variables --------------------------------------------------*/
56
57 const octet rc5_keysz[] = { KSZ_RANGE, RC5_KEYSZ, 1, 255, 1 };
58
59 /*----- Internal magical constants ----------------------------------------*/
60
61 #define T ((RC5_ROUNDS + 1) * 2)
62 #define P 0xb7e15163
63 #define Q 0x9e3779b9
64
65 /*----- Main code ---------------------------------------------------------*/
66
67 /* --- @rc5_init@ --- *
68  *
69  * Arguments:   @rc5_ctx *k@ = pointer to a key block
70  *              @const void *sbuf@ = pointer to key material
71  *              @size_t sz@ = size of the key material
72  *
73  * Returns:     ---
74  *
75  * Use:         Initializes an RC5 key block.
76  */
77
78 void rc5_init(rc5_ctx *k, const void *sbuf, size_t sz)
79 {
80   uint32 *l;
81   size_t w;
82
83   /* --- Set up the @L@ table --- *
84    *
85    * This is slightly unfortunately defined.
86    */
87
88   KSZ_ASSERT(rc5, sz);
89
90   {
91     int i;
92     const octet *p = sbuf;
93
94     /* --- Create the buffer --- */
95
96     w = (sz + 3) / 4;
97     l = XS_ALLOC(w * sizeof(uint32));
98
99     /* --- Extract the key material --- */
100
101     for (i = 0; sz > 3; i++) {
102       l[i] = LOAD32_L(p);
103       p += 4;
104       sz -= 4;
105     }
106
107     /* --- Fix up the tail end --- */
108
109     if (sz) {
110       uint32 x = U8(*p++);
111       if (sz > 1) x |= (U8(*p++) <<  8);
112       if (sz > 2) x |= (U8(*p++) << 16);
113       l[i] = x;
114     }
115   }
116
117   /* --- Initialize the @S@ table --- */
118
119   {
120     int i;
121
122     k->s[0] = P;
123     for (i = 1; i < T; i++)
124       k->s[i] = k->s[i - 1] + Q;
125   }
126
127   /* --- Mix in the key --- */
128
129   {
130     int m = 3 * (w > T ? w : T);
131     int i, j, c;
132     uint32 a, b;
133
134     for (c = i = j = a = b = 0; c < m; c++) {
135       uint32 x;
136
137       x = k->s[i] + a + b;
138       k->s[i] = a = ROL32(x, 3);
139       i++; if (i >= T) i = 0;
140
141       x = l[j] + a + b;
142       l[j] = b = ROL32(x, a + b);
143       j++; if (j >= w) j = 0;
144     }
145   }
146
147   memset(l, 0, w * sizeof(uint32));
148   XS_FREE(l);
149 }
150
151 /* --- @EROUND@, @DROUND@ --- */
152
153 #define EROUND(x, y, k) do {                                            \
154   uint32 _x;                                                            \
155   _x = x ^ y; x = ROL32(_x, y) + k[0];                                  \
156   _x = y ^ x; y = ROL32(_x, x) + k[1];                                  \
157   k += 2;                                                               \
158 } while (0)
159
160 #define DROUND(x, y, k) do {                                            \
161   uint32 _x;                                                            \
162   k -= 2;                                                               \
163   _x = y - k[1]; y = ROR32(_x, x) ^ x;                                  \
164   _x = x - k[0]; x = ROR32(_x, y) ^ y;                                  \
165 } while (0)
166
167 /* --- @EBLK@, @DBLK@ --- */
168
169 #define EBLK(a, b, c, d, k) do {                                        \
170   uint32 _l, _r;                                                        \
171   const uint32 *_k = (k)->s;                                            \
172                                                                         \
173   _l = (a) + _k[0];                                                     \
174   _r = (b) + _k[1];                                                     \
175   _k += 2;                                                              \
176                                                                         \
177   EROUND(_l, _r, _k);                                                   \
178   EROUND(_l, _r, _k);                                                   \
179   EROUND(_l, _r, _k);                                                   \
180   EROUND(_l, _r, _k);                                                   \
181   EROUND(_l, _r, _k);                                                   \
182   EROUND(_l, _r, _k);                                                   \
183   EROUND(_l, _r, _k);                                                   \
184   EROUND(_l, _r, _k);                                                   \
185   EROUND(_l, _r, _k);                                                   \
186   EROUND(_l, _r, _k);                                                   \
187   EROUND(_l, _r, _k);                                                   \
188   EROUND(_l, _r, _k);                                                   \
189   (c) = _l;                                                             \
190   (d) = _r;                                                             \
191 } while (0)
192
193 #define DBLK(a, b, c, d, k) do {                                        \
194   uint32 _l, _r;                                                        \
195   const uint32 *_k = (k)->s + T;                                        \
196                                                                         \
197   _l = (a);                                                             \
198   _r = (b);                                                             \
199                                                                         \
200   DROUND(_l, _r, _k);                                                   \
201   DROUND(_l, _r, _k);                                                   \
202   DROUND(_l, _r, _k);                                                   \
203   DROUND(_l, _r, _k);                                                   \
204   DROUND(_l, _r, _k);                                                   \
205   DROUND(_l, _r, _k);                                                   \
206   DROUND(_l, _r, _k);                                                   \
207   DROUND(_l, _r, _k);                                                   \
208   DROUND(_l, _r, _k);                                                   \
209   DROUND(_l, _r, _k);                                                   \
210   DROUND(_l, _r, _k);                                                   \
211   DROUND(_l, _r, _k);                                                   \
212                                                                         \
213   _k -= 2;                                                              \
214   (d) = _r - _k[1];                                                     \
215   (c) = _l - _k[0];                                                     \
216 } while (0)
217
218 /* --- @rc5_eblk@, @rc5_dblk@ --- *
219  *
220  * Arguments:   @const rc5_ctx *k@ = pointer to RC5 context block
221  *              @const uint32 s[2]@ = pointer to source block
222  *              @uint32 *d[2]@ = pointer to destination block
223  *
224  * Returns:     ---
225  *
226  * Use:         Low level block encryption and decryption.
227  */
228
229 void rc5_eblk(const rc5_ctx *k, const uint32 *s, uint32 *d)
230 {
231   EBLK(s[0], s[1], d[0], d[1], k);
232 }
233
234 void rc5_dblk(const rc5_ctx *k, const uint32 *s, uint32 *d)
235 {
236   DBLK(s[0], s[1], d[0], d[1], k);
237 }
238
239 /* --- Test rig --- */
240
241 BLKC_TEST(RC5, rc5)
242
243 /*----- That's all, folks -------------------------------------------------*/