New multiprecision integer arithmetic suite.
[u/mdw/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 -------------------------------------------------*/