Renamed from `rsa-decrypt', since the name was no longer appropriate.
[u/mdw/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 -------------------------------------------------*/