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