3 * $Id: idea.c,v 1.4 2000/07/15 17:47:58 mdw Exp $
5 * Implementation of the IDEA cipher
7 * (c) 1999 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
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.
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.
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,
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.4 2000/07/15 17:47:58 mdw
34 * Fix bug in decryption key scheduling.
36 * Revision 1.3 2000/07/02 18:24:39 mdw
37 * Use a new multiplication function from an Ascom white paper to resist
40 * Revision 1.2 2000/06/17 11:24:08 mdw
41 * New key size interface.
43 * Revision 1.1 1999/09/03 08:41:12 mdw
48 /*----- Header files ------------------------------------------------------*/
55 #include <mLib/bits.h>
61 /*----- Global variables --------------------------------------------------*/
63 const octet idea_keysz
[] = { KSZ_SET
, IDEA_KEYSZ
};
65 /*----- Main code ---------------------------------------------------------*/
69 * Arguments: @uint16 n@ = number to invert
71 * Returns: Multiplicative inverse of @n@ %$\pmod{2^{16} + 1}$%.
73 * Use: Computes multiplicative inverses. This is handy for the
74 * decryption key scheduling.
77 static uint16
inv(uint16 n
)
91 t
= a
; a
= b
- q
* a
; b
= t
;
100 * Arguments @x@ and @y@ are two 32-bit values to multiply. On exit, @x@ is
101 * the product of the two arguments. The result is not normalized back to 16
102 * bits; the arguments are not expected to be normalized.
104 * This code is from `Side Channel Attack Hardening of the IDEA Cipher',
105 * published by Ascom Tech.
108 #define MUL(x, y) do { \
114 _tt = (uint32)x * (uint32)_t + (uint32)x + (uint32)_t + 1; \
116 _t = U16(_tt >> 16); \
117 x = x - _t + (x <= _t); \
120 /* --- @idea_init@ --- *
122 * Arguments: @idea_ctx *k@ = pointer to key block
123 * @const void *buf@ = pointer to key buffer
124 * @size_t sz@ = size of key material
128 * Use: Initializes an IDEA key buffer. The buffer must be exactly
129 * 16 bytes in size, because IDEA is only defined with a key
133 void idea_init(idea_ctx
*k
, const void *buf
, size_t sz
)
135 KSZ_ASSERT(idea
, sz
);
137 /* --- Unpack the encryption key --- */
140 const octet
*p
= buf
;
142 uint32 a
= LOAD32(p
+ 0);
143 uint32 b
= LOAD32(p
+ 4);
144 uint32 c
= LOAD32(p
+ 8);
145 uint32 d
= LOAD32(p
+ 12);
148 /* --- Main unpacking loop --- */
150 for (i
= 0; i
< 6; i
++) {
152 /* --- Spit out the next 8 subkeys --- */
164 /* --- Rotate and permute the subkeys --- */
168 a
= U32((a
<< 25) | (b
>> 7));
169 b
= U32((b
<< 25) | (c
>> 7));
170 c
= U32((c
<< 25) | (d
>> 7));
171 d
= U32((d
<< 25) | (t
>> 7));
175 /* --- Write out the tail-enders --- */
183 /* --- Convert this into the decryption key --- */
186 uint16
*p
= k
->e
+ 52;
190 /* --- Translate the main round keys --- */
192 for (i
= 0; i
< 8; i
++) {
199 q
[1] = 0x10000 - p
[4];
200 q
[2] = 0x10000 - p
[3];
202 q
[1] = 0x10000 - p
[3];
203 q
[2] = 0x10000 - p
[4];
208 /* --- Translate the tail-enders --- */
212 q
[1] = 0x10000 - p
[1];
213 q
[2] = 0x10000 - p
[2];
218 /* --- @ROUND@ --- */
220 #define MIX(k, a, b, c, d) do { \
227 #define MA(k, a, b, c, d) do { \
228 unsigned _u = a ^ c; \
229 unsigned _v = b ^ d; \
240 #define ROUND(k, a, b, c, d) do { \
241 MIX(k, a, b, c, d); \
246 /* --- Encryption --- */
248 #define EBLK(k, a, b, c, d) do { \
249 unsigned _a = U16(a >> 16); \
250 unsigned _b = U16(a >> 0); \
251 unsigned _c = U16(b >> 16); \
252 unsigned _d = U16(b >> 0); \
253 const uint16 *_k = (k); \
255 ROUND(_k, _a, _b, _c, _d); \
256 ROUND(_k, _a, _c, _b, _d); \
257 ROUND(_k, _a, _b, _c, _d); \
258 ROUND(_k, _a, _c, _b, _d); \
259 ROUND(_k, _a, _b, _c, _d); \
260 ROUND(_k, _a, _c, _b, _d); \
261 ROUND(_k, _a, _b, _c, _d); \
262 ROUND(_k, _a, _c, _b, _d); \
263 MIX (_k, _a, _c, _b, _d); \
264 c = ((uint32)U16(_a) << 16) | (uint32)U16(_c); \
265 d = ((uint32)U16(_b) << 16) | (uint32)U16(_d); \
268 #define DBLK(k, a, b) EBLK((k), (a), (b))
270 /* --- @idea_eblk@, @idea_dblk@ --- *
272 * Arguments: @const idea_ctx *k@ = pointer to a key block
273 * @const uint32 s[2]@ = pointer to source block
274 * @uint32 d[2]@ = pointer to destination block
278 * Use: Low-level block encryption and decryption.
281 void idea_eblk(const idea_ctx
*k
, const uint32
*s
, uint32
*d
)
283 EBLK(k
->e
, s
[0], s
[1], d
[0], d
[1]);
286 void idea_dblk(const idea_ctx
*k
, const uint32
*s
, uint32
*d
)
288 EBLK(k
->d
, s
[0], s
[1], d
[0], d
[1]);
291 BLKC_TEST(IDEA
, idea
)
293 /*----- That's all, folks -------------------------------------------------*/