math/mpreduce.h: Missing include files.
[u/mdw/catacomb] / symm / rc5.c
CommitLineData
d03ab969 1/* -*-c-*-
2 *
d03ab969 3 * The RC5-32/12 block cipher
4 *
5 * (c) 1999 Straylight/Edgeware
6 */
7
45c0fd36 8/*----- Licensing notice --------------------------------------------------*
d03ab969 9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
45c0fd36 16 *
d03ab969 17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
45c0fd36 21 *
d03ab969 22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
d03ab969 28/*----- Header files ------------------------------------------------------*/
29
30#include <assert.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include <mLib/alloc.h>
35#include <mLib/bits.h>
36
6134d968 37#include "arena.h"
d03ab969 38#include "blkc.h"
6134d968 39#include "gcipher.h"
d03ab969 40#include "rc5.h"
41
6134d968 42/*----- Global variables --------------------------------------------------*/
d03ab969 43
6134d968 44const octet rc5_keysz[] = { KSZ_RANGE, RC5_KEYSZ, 1, 255, 1 };
45
46/*----- Internal magical constants ----------------------------------------*/
d03ab969 47
48#define T ((RC5_ROUNDS + 1) * 2)
49#define P 0xb7e15163
50#define Q 0x9e3779b9
51
52/*----- Main code ---------------------------------------------------------*/
53
54/* --- @rc5_init@ --- *
55 *
56 * Arguments: @rc5_ctx *k@ = pointer to a key block
57 * @const void *sbuf@ = pointer to key material
58 * @size_t sz@ = size of the key material
59 *
60 * Returns: ---
61 *
62 * Use: Initializes an RC5 key block.
63 */
64
65void rc5_init(rc5_ctx *k, const void *sbuf, size_t sz)
66{
67 uint32 *l;
68 size_t w;
69
70 /* --- Set up the @L@ table --- *
71 *
72 * This is slightly unfortunately defined.
73 */
74
6134d968 75 KSZ_ASSERT(rc5, sz);
d03ab969 76
77 {
78 int i;
79 const octet *p = sbuf;
80
81 /* --- Create the buffer --- */
82
83 w = (sz + 3) / 4;
6134d968 84 l = XS_ALLOC(w * sizeof(uint32));
d03ab969 85
86 /* --- Extract the key material --- */
87
88 for (i = 0; sz > 3; i++) {
89 l[i] = LOAD32_L(p);
90 p += 4;
91 sz -= 4;
92 }
93
94 /* --- Fix up the tail end --- */
95
96 if (sz) {
97 uint32 x = U8(*p++);
98 if (sz > 1) x |= (U8(*p++) << 8);
99 if (sz > 2) x |= (U8(*p++) << 16);
100 l[i] = x;
101 }
102 }
103
104 /* --- Initialize the @S@ table --- */
105
106 {
107 int i;
108
109 k->s[0] = P;
110 for (i = 1; i < T; i++)
111 k->s[i] = k->s[i - 1] + Q;
112 }
113
114 /* --- Mix in the key --- */
115
116 {
117 int m = 3 * (w > T ? w : T);
118 int i, j, c;
119 uint32 a, b;
120
121 for (c = i = j = a = b = 0; c < m; c++) {
122 uint32 x;
123
124 x = k->s[i] + a + b;
125 k->s[i] = a = ROL32(x, 3);
126 i++; if (i >= T) i = 0;
127
128 x = l[j] + a + b;
129 l[j] = b = ROL32(x, a + b);
130 j++; if (j >= w) j = 0;
131 }
132 }
133
6134d968 134 memset(l, 0, w * sizeof(uint32));
135 XS_FREE(l);
d03ab969 136}
137
138/* --- @EROUND@, @DROUND@ --- */
139
140#define EROUND(x, y, k) do { \
141 uint32 _x; \
142 _x = x ^ y; x = ROL32(_x, y) + k[0]; \
143 _x = y ^ x; y = ROL32(_x, x) + k[1]; \
144 k += 2; \
145} while (0)
146
147#define DROUND(x, y, k) do { \
148 uint32 _x; \
149 k -= 2; \
150 _x = y - k[1]; y = ROR32(_x, x) ^ x; \
151 _x = x - k[0]; x = ROR32(_x, y) ^ y; \
152} while (0)
153
154/* --- @EBLK@, @DBLK@ --- */
155
156#define EBLK(a, b, c, d, k) do { \
157 uint32 _l, _r; \
158 const uint32 *_k = (k)->s; \
159 \
160 _l = (a) + _k[0]; \
161 _r = (b) + _k[1]; \
162 _k += 2; \
163 \
164 EROUND(_l, _r, _k); \
165 EROUND(_l, _r, _k); \
166 EROUND(_l, _r, _k); \
167 EROUND(_l, _r, _k); \
168 EROUND(_l, _r, _k); \
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 (c) = _l; \
177 (d) = _r; \
178} while (0)
179
180#define DBLK(a, b, c, d, k) do { \
181 uint32 _l, _r; \
182 const uint32 *_k = (k)->s + T; \
183 \
184 _l = (a); \
185 _r = (b); \
186 \
187 DROUND(_l, _r, _k); \
188 DROUND(_l, _r, _k); \
189 DROUND(_l, _r, _k); \
190 DROUND(_l, _r, _k); \
191 DROUND(_l, _r, _k); \
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 \
200 _k -= 2; \
201 (d) = _r - _k[1]; \
202 (c) = _l - _k[0]; \
203} while (0)
204
205/* --- @rc5_eblk@, @rc5_dblk@ --- *
206 *
207 * Arguments: @const rc5_ctx *k@ = pointer to RC5 context block
208 * @const uint32 s[2]@ = pointer to source block
209 * @uint32 *d[2]@ = pointer to destination block
210 *
211 * Returns: ---
212 *
213 * Use: Low level block encryption and decryption.
214 */
215
216void rc5_eblk(const rc5_ctx *k, const uint32 *s, uint32 *d)
217{
218 EBLK(s[0], s[1], d[0], d[1], k);
219}
220
221void rc5_dblk(const rc5_ctx *k, const uint32 *s, uint32 *d)
222{
223 DBLK(s[0], s[1], d[0], d[1], k);
224}
225
226/* --- Test rig --- */
227
228BLKC_TEST(RC5, rc5)
229
230/*----- That's all, folks -------------------------------------------------*/