1 // SPDX-License-Identifier: BSD-2-Clause 2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 3 * 4 * LibTomCrypt is a library that provides various cryptographic 5 * algorithms in a highly modular and flexible manner. 6 * 7 * The library is free for all purposes without any express 8 * guarantee it works. 9 */ 10 11 /* Based on idea.cpp - originally written and placed in the public domain by Wei Dai 12 https://github.com/weidai11/cryptopp/blob/master/idea.cpp 13 14 Patents should be expired. On 2017-10-16 wikipedia says: 15 https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm 16 17 A patent application for IDEA was first filed in Switzerland (CH A 1690/90) on May 18, 1990, 18 then an international patent application was filed under the Patent Cooperation Treaty on 19 May 16, 1991. Patents were eventually granted in Austria, France, Germany, Italy, the Netherlands, 20 Spain, Sweden, Switzerland, the United Kingdom, (European Patent Register entry for European 21 patent no. 0482154, filed May 16, 1991, issued June 22, 1994 and expired May 16, 2011), 22 the United States (U.S. Patent 5,214,703, issued May 25, 1993 and expired January 7, 2012) 23 and Japan (JP 3225440) (expired May 16, 2011). 24 */ 25 26 #include "tomcrypt_private.h" 27 28 #ifdef LTC_IDEA 29 30 const struct ltc_cipher_descriptor idea_desc = { 31 "idea", 32 24, /* cipher_ID */ 33 16, 16, 8, 8, /* min_key_len, max_key_len, block_len, default_rounds */ 34 &idea_setup, 35 &idea_ecb_encrypt, 36 &idea_ecb_decrypt, 37 &idea_test, 38 &idea_done, 39 &idea_keysize, 40 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 41 }; 42 43 typedef unsigned short int ushort16; 44 45 #define _LOW16(x) ((x)&0xffff) /* compiler should be able to optimize this away if x is 16 bits */ 46 #define _HIGH16(x) ((x)>>16) 47 #define _MUL(a,b) { \ 48 ulong32 p = (ulong32)_LOW16(a) * b; \ 49 if (p) { \ 50 p = _LOW16(p) - _HIGH16(p); \ 51 a = (ushort16)p - (ushort16)_HIGH16(p); \ 52 } \ 53 else \ 54 a = 1 - a - b; \ 55 } 56 #define _STORE16(x,y) { (y)[0] = (unsigned char)(((x)>>8)&255); (y)[1] = (unsigned char)((x)&255); } 57 #define _LOAD16(x,y) { x = ((ushort16)((y)[0] & 255)<<8) | ((ushort16)((y)[1] & 255)); } 58 59 static ushort16 _mul_inv(ushort16 x) 60 { 61 ushort16 y = x; 62 unsigned i; 63 64 for (i = 0; i < 15; i++) { 65 _MUL(y, _LOW16(y)); 66 _MUL(y, x); 67 } 68 return _LOW16(y); 69 } 70 71 static ushort16 _add_inv(ushort16 x) 72 { 73 return _LOW16(0 - x); 74 } 75 76 static int _setup_key(const unsigned char *key, symmetric_key *skey) 77 { 78 int i, j; 79 ushort16 *e_key = skey->idea.ek; 80 ushort16 *d_key = skey->idea.dk; 81 82 /* prepare enc key */ 83 for (i = 0; i < 8; i++) { 84 _LOAD16(e_key[i], key + 2 * i); 85 } 86 for (; i < LTC_IDEA_KEYLEN; i++) { 87 j = (i - i % 8) - 8; 88 e_key[i] = _LOW16((e_key[j+(i+1)%8] << 9) | (e_key[j+(i+2)%8] >> 7)); 89 } 90 91 /* prepare dec key */ 92 for (i = 0; i < LTC_IDEA_ROUNDS; i++) { 93 d_key[i*6+0] = _mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]); 94 d_key[i*6+1] = _add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1+(i>0 ? 1 : 0)]); 95 d_key[i*6+2] = _add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2-(i>0 ? 1 : 0)]); 96 d_key[i*6+3] = _mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]); 97 d_key[i*6+4] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+4]; 98 d_key[i*6+5] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+5]; 99 } 100 d_key[i*6+0] = _mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]); 101 d_key[i*6+1] = _add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1]); 102 d_key[i*6+2] = _add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2]); 103 d_key[i*6+3] = _mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]); 104 105 return CRYPT_OK; 106 } 107 108 static int _process_block(const unsigned char *in, unsigned char *out, const ushort16 *m_key) 109 { 110 int i; 111 ushort16 x0, x1, x2, x3, t0, t1; 112 113 _LOAD16(x0, in + 0); 114 _LOAD16(x1, in + 2); 115 _LOAD16(x2, in + 4); 116 _LOAD16(x3, in + 6); 117 118 for (i = 0; i < LTC_IDEA_ROUNDS; i++) { 119 _MUL(x0, m_key[i*6+0]); 120 x1 += m_key[i*6+1]; 121 x2 += m_key[i*6+2]; 122 _MUL(x3, m_key[i*6+3]); 123 t0 = x0^x2; 124 _MUL(t0, m_key[i*6+4]); 125 t1 = t0 + (x1^x3); 126 _MUL(t1, m_key[i*6+5]); 127 t0 += t1; 128 x0 ^= t1; 129 x3 ^= t0; 130 t0 ^= x1; 131 x1 = x2^t1; 132 x2 = t0; 133 } 134 135 _MUL(x0, m_key[LTC_IDEA_ROUNDS*6+0]); 136 x2 += m_key[LTC_IDEA_ROUNDS*6+1]; 137 x1 += m_key[LTC_IDEA_ROUNDS*6+2]; 138 _MUL(x3, m_key[LTC_IDEA_ROUNDS*6+3]); 139 140 _STORE16(x0, out + 0); 141 _STORE16(x2, out + 2); 142 _STORE16(x1, out + 4); 143 _STORE16(x3, out + 6); 144 145 return CRYPT_OK; 146 } 147 148 int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) 149 { 150 LTC_ARGCHK(key != NULL); 151 LTC_ARGCHK(skey != NULL); 152 153 if (num_rounds != 0 && num_rounds != 8) return CRYPT_INVALID_ROUNDS; 154 if (keylen != 16) return CRYPT_INVALID_KEYSIZE; 155 156 return _setup_key(key, skey); 157 } 158 159 int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) 160 { 161 int err = _process_block(pt, ct, skey->idea.ek); 162 #ifdef LTC_CLEAN_STACK 163 burn_stack(sizeof(ushort16) * 6 + sizeof(int)); 164 #endif 165 return err; 166 } 167 168 int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) 169 { 170 int err = _process_block(ct, pt, skey->idea.dk); 171 #ifdef LTC_CLEAN_STACK 172 burn_stack(sizeof(ushort16) * 6 + sizeof(int)); 173 #endif 174 return err; 175 } 176 177 void idea_done(symmetric_key *skey) 178 { 179 LTC_UNUSED_PARAM(skey); 180 } 181 182 int idea_keysize(int *keysize) 183 { 184 LTC_ARGCHK(keysize != NULL); 185 if (*keysize < 16) { 186 return CRYPT_INVALID_KEYSIZE; 187 } 188 *keysize = 16; 189 return CRYPT_OK; 190 } 191 192 int idea_test(void) 193 { 194 #ifndef LTC_TEST 195 return CRYPT_NOP; 196 #else 197 static const struct { 198 unsigned char key[16], pt[8], ct[8]; 199 } tests[] = { 200 { 201 /* key */ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 202 /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 203 /* ct */ { 0xB1, 0xF5, 0xF7, 0xF8, 0x79, 0x01, 0x37, 0x0F } 204 }, 205 { 206 /* key */ { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 207 /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 208 /* ct */ { 0xB3, 0x92, 0x7D, 0xFF, 0xB6, 0x35, 0x86, 0x26 } 209 }, 210 { 211 /* key */ { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 212 /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 213 /* ct */ { 0xE9, 0x87, 0xE0, 0x02, 0x9F, 0xB9, 0x97, 0x85 } 214 }, 215 { 216 /* key */ { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 217 /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 218 /* ct */ { 0x75, 0x4A, 0x03, 0xCE, 0x08, 0xDB, 0x7D, 0xAA } 219 }, 220 { 221 /* key */ { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 222 /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 223 /* ct */ { 0xF0, 0x15, 0xF9, 0xFB, 0x0C, 0xFC, 0x7E, 0x1C } 224 }, 225 }; 226 227 unsigned char buf[2][8]; 228 symmetric_key key; 229 int err, x; 230 231 if (sizeof(ushort16) != 2) { 232 return CRYPT_FAIL_TESTVECTOR; 233 } 234 235 for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { 236 if ((err = idea_setup(tests[x].key, 16, 8, &key)) != CRYPT_OK) { 237 return err; 238 } 239 if ((err = idea_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { 240 return err; 241 } 242 if (compare_testvector(buf[0], 8, tests[x].ct, 8, "IDEA Encrypt", x)) { 243 return CRYPT_FAIL_TESTVECTOR; 244 } 245 if ((err = idea_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { 246 return err; 247 } 248 if (compare_testvector(buf[1], 8, tests[x].pt, 8, "IDEA Decrypt", x)) { 249 return CRYPT_FAIL_TESTVECTOR; 250 } 251 } 252 253 return CRYPT_OK; 254 #endif 255 } 256 257 #endif 258 259 /* ref: $Format:%D$ */ 260 /* git commit: $Format:%H$ */ 261 /* commit time: $Format:%ai$ */ 262