3 * $Id: idea.c,v 1.5 2004/04/08 01:36:15 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 /*----- Header files ------------------------------------------------------*/
37 #include <mLib/bits.h>
43 /*----- Global variables --------------------------------------------------*/
45 const octet idea_keysz[] = { KSZ_SET, IDEA_KEYSZ };
47 /*----- Main code ---------------------------------------------------------*/
51 * Arguments: @uint16 n@ = number to invert
53 * Returns: Multiplicative inverse of @n@ %$\pmod{2^{16} + 1}$%.
55 * Use: Computes multiplicative inverses. This is handy for the
56 * decryption key scheduling.
59 static uint16 inv(uint16 n)
73 t = a; a = b - q * a; b = t;
82 * Arguments @x@ and @y@ are two 32-bit values to multiply. On exit, @x@ is
83 * the product of the two arguments. The result is not normalized back to 16
84 * bits; the arguments are not expected to be normalized.
86 * This code is from `Side Channel Attack Hardening of the IDEA Cipher',
87 * published by Ascom Tech.
90 #define MUL(x, y) do { \
96 _tt = (uint32)x * (uint32)_t + (uint32)x + (uint32)_t + 1; \
98 _t = U16(_tt >> 16); \
99 x = x - _t + (x <= _t); \
102 /* --- @idea_init@ --- *
104 * Arguments: @idea_ctx *k@ = pointer to key block
105 * @const void *buf@ = pointer to key buffer
106 * @size_t sz@ = size of key material
110 * Use: Initializes an IDEA key buffer. The buffer must be exactly
111 * 16 bytes in size, because IDEA is only defined with a key
115 void idea_init(idea_ctx *k, const void *buf, size_t sz)
117 KSZ_ASSERT(idea, sz);
119 /* --- Unpack the encryption key --- */
122 const octet *p = buf;
124 uint32 a = LOAD32(p + 0);
125 uint32 b = LOAD32(p + 4);
126 uint32 c = LOAD32(p + 8);
127 uint32 d = LOAD32(p + 12);
130 /* --- Main unpacking loop --- */
132 for (i = 0; i < 6; i++) {
134 /* --- Spit out the next 8 subkeys --- */
146 /* --- Rotate and permute the subkeys --- */
150 a = U32((a << 25) | (b >> 7));
151 b = U32((b << 25) | (c >> 7));
152 c = U32((c << 25) | (d >> 7));
153 d = U32((d << 25) | (t >> 7));
157 /* --- Write out the tail-enders --- */
165 /* --- Convert this into the decryption key --- */
168 uint16 *p = k->e + 52;
172 /* --- Translate the main round keys --- */
174 for (i = 0; i < 8; i++) {
181 q[1] = 0x10000 - p[4];
182 q[2] = 0x10000 - p[3];
184 q[1] = 0x10000 - p[3];
185 q[2] = 0x10000 - p[4];
190 /* --- Translate the tail-enders --- */
194 q[1] = 0x10000 - p[1];
195 q[2] = 0x10000 - p[2];
200 /* --- @ROUND@ --- */
202 #define MIX(k, a, b, c, d) do { \
209 #define MA(k, a, b, c, d) do { \
210 unsigned _u = a ^ c; \
211 unsigned _v = b ^ d; \
222 #define ROUND(k, a, b, c, d) do { \
223 MIX(k, a, b, c, d); \
228 /* --- Encryption --- */
230 #define EBLK(k, a, b, c, d) do { \
231 unsigned _a = U16(a >> 16); \
232 unsigned _b = U16(a >> 0); \
233 unsigned _c = U16(b >> 16); \
234 unsigned _d = U16(b >> 0); \
235 const uint16 *_k = (k); \
237 ROUND(_k, _a, _b, _c, _d); \
238 ROUND(_k, _a, _c, _b, _d); \
239 ROUND(_k, _a, _b, _c, _d); \
240 ROUND(_k, _a, _c, _b, _d); \
241 ROUND(_k, _a, _b, _c, _d); \
242 ROUND(_k, _a, _c, _b, _d); \
243 ROUND(_k, _a, _b, _c, _d); \
244 ROUND(_k, _a, _c, _b, _d); \
245 MIX (_k, _a, _c, _b, _d); \
246 c = ((uint32)U16(_a) << 16) | (uint32)U16(_c); \
247 d = ((uint32)U16(_b) << 16) | (uint32)U16(_d); \
250 #define DBLK(k, a, b) EBLK((k), (a), (b))
252 /* --- @idea_eblk@, @idea_dblk@ --- *
254 * Arguments: @const idea_ctx *k@ = pointer to a key block
255 * @const uint32 s[2]@ = pointer to source block
256 * @uint32 d[2]@ = pointer to destination block
260 * Use: Low-level block encryption and decryption.
263 void idea_eblk(const idea_ctx *k, const uint32 *s, uint32 *d)
265 EBLK(k->e, s[0], s[1], d[0], d[1]);
268 void idea_dblk(const idea_ctx *k, const uint32 *s, uint32 *d)
270 EBLK(k->d, s[0], s[1], d[0], d[1]);
273 BLKC_TEST(IDEA, idea)
275 /*----- That's all, folks -------------------------------------------------*/