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