3 * The RC5-32/12 block cipher
5 * (c) 1999 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
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.
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.
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,
28 /*----- Header files ------------------------------------------------------*/
34 #include <mLib/alloc.h>
35 #include <mLib/bits.h>
42 /*----- Global variables --------------------------------------------------*/
44 const octet rc5_keysz
[] = { KSZ_RANGE
, RC5_KEYSZ
, 1, 255, 1 };
46 /*----- Internal magical constants ----------------------------------------*/
48 #define T ((RC5_ROUNDS + 1) * 2)
52 /*----- Main code ---------------------------------------------------------*/
54 /* --- @rc5_init@ --- *
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
62 * Use: Initializes an RC5 key block.
65 void rc5_init(rc5_ctx
*k
, const void *sbuf
, size_t sz
)
70 /* --- Set up the @L@ table --- *
72 * This is slightly unfortunately defined.
79 const octet
*p
= sbuf
;
81 /* --- Create the buffer --- */
84 l
= XS_ALLOC(w
* sizeof(uint32
));
86 /* --- Extract the key material --- */
88 for (i
= 0; sz
> 3; i
++) {
94 /* --- Fix up the tail end --- */
98 if (sz
> 1) x
|= (U8(*p
++) << 8);
99 if (sz
> 2) x
|= (U8(*p
++) << 16);
104 /* --- Initialize the @S@ table --- */
110 for (i
= 1; i
< T
; i
++)
111 k
->s
[i
] = k
->s
[i
- 1] + Q
;
114 /* --- Mix in the key --- */
117 int m
= 3 * (w
> T ? w
: T
);
121 for (c
= i
= j
= a
= b
= 0; c
< m
; c
++) {
125 k
->s
[i
] = a
= ROL32(x
, 3);
126 i
++; if (i
>= T
) i
= 0;
129 l
[j
] = b
= ROL32(x
, a
+ b
);
130 j
++; if (j
>= w
) j
= 0;
134 memset(l
, 0, w
* sizeof(uint32
));
138 /* --- @EROUND@, @DROUND@ --- */
140 #define EROUND(x, y, k) do { \
142 _x = x ^ y; x = ROL32(_x, y) + k[0]; \
143 _x = y ^ x; y = ROL32(_x, x) + k[1]; \
147 #define DROUND(x, y, k) do { \
150 _x = y - k[1]; y = ROR32(_x, x) ^ x; \
151 _x = x - k[0]; x = ROR32(_x, y) ^ y; \
154 /* --- @EBLK@, @DBLK@ --- */
156 #define EBLK(a, b, c, d, k) do { \
158 const uint32 *_k = (k)->s; \
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); \
180 #define DBLK(a, b, c, d, k) do { \
182 const uint32 *_k = (k)->s + T; \
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); \
205 /* --- @rc5_eblk@, @rc5_dblk@ --- *
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
213 * Use: Low level block encryption and decryption.
216 void rc5_eblk(const rc5_ctx
*k
, const uint32
*s
, uint32
*d
)
218 EBLK(s
[0], s
[1], d
[0], d
[1], k
);
221 void rc5_dblk(const rc5_ctx
*k
, const uint32
*s
, uint32
*d
)
223 DBLK(s
[0], s
[1], d
[0], d
[1], k
);
226 /* --- Test rig --- */
230 /*----- That's all, folks -------------------------------------------------*/