1 /* 2 * Copyright © 2002 Vita Nuova Holdings Limited. All rights reserved. 3 */ 4 #include <lib9.h> 5 #include <bio.h> 6 7 /* CBC, ECB, integrate, SSL */ 8 9 #define KEYLEN 52 10 11 #define MODA 0x10000 12 #define MODM 0x10001 13 #define MASKA (MODA-1) 14 15 #define OP1(x, y) ((x) ^ (y)) 16 #define OP2(x, y) (((x) + (y)) & MASKA) 17 #define OP3(x, y) mod(x, y) 18 19 #define OP2INV(x) (-(x)) 20 #define OP3INV(x) inv(x) 21 22 #define BIGEND(k, i) ((k[i]<<8)|k[i+1]) 23 #define MSB(x) ((x)>>8) 24 #define LSB(x) ((x)&0xff) 25 26 static ushort 27 mod(ushort x, ushort y) 28 { 29 ushort q, r; 30 uint z; 31 32 if (x == 0) 33 return 1-y; 34 if (y == 0) 35 return 1-x; 36 z = (uint)x*(uint)y; 37 q = z >> 16; 38 r = z & MASKA; 39 return r-q+(r<q); 40 } 41 42 static ushort 43 inv(ushort x) 44 { 45 int q, r0, r1, r2, v0, v1, v2; 46 47 if (x <= 1) 48 return x; 49 r0 = MODM; 50 r1 = x; 51 v0 = 0; 52 v1 = 1; 53 while (r1 != 0) { 54 q = r0/r1; 55 r2 = r0-q*r1; 56 v2 = v0-q*v1; 57 r0 = r1; 58 r1 = r2; 59 v0 = v1; 60 v1 = v2; 61 } 62 if (v0 < 0) 63 v0 += MODM; 64 return v0 & MASKA; 65 } 66 67 static void 68 idea_key_setup_decrypt(ushort ek[KEYLEN], ushort dk[KEYLEN]) 69 { 70 int i; 71 72 for (i = 0; i < 54; i += 6) { 73 dk[i] = OP3INV(ek[48-i]); 74 dk[i+1] = OP2INV(ek[50-i]); 75 dk[i+2] = OP2INV(ek[49-i]); 76 dk[i+3] = OP3INV(ek[51-i]); 77 if (i < 48) { 78 dk[i+4] = ek[46-i]; 79 dk[i+5] = ek[47-i]; 80 } 81 } 82 } 83 84 void 85 idea_key_setup(uchar key[16], ushort ek[2*KEYLEN]) 86 { 87 int i, j; 88 ushort tmp, *e = ek; 89 90 for (i = 0; i < 8; i++) 91 ek[i] = BIGEND(key, 2*i); 92 for (i = 8, j = 1; i < KEYLEN; i++, j++) { 93 ek[i] = (e[j&7]<<9)|(e[(j+1)&7]>>7); 94 if (((i+1) & 7) == 0) 95 e += 8; 96 } 97 tmp = ek[49]; 98 ek[49] = ek[50]; 99 ek[50] = tmp; 100 idea_key_setup_decrypt(ek, &ek[KEYLEN]); 101 } 102 103 void 104 idea_cipher(ushort key[2*KEYLEN], uchar text[8], int decrypting) 105 { 106 int i; 107 ushort *k; 108 ushort x[4]; 109 ushort tmp, yout, zout; 110 111 k = decrypting ? &key[KEYLEN] : key; 112 for (i = 0; i < 4; i++) 113 x[i] = BIGEND(text, 2*i); 114 for (i = 0; i < 17; i++) { 115 if (!(i&1)) { /* odd round */ 116 x[0] = OP3(x[0], k[3*i]); 117 tmp = OP2(x[2], k[3*i+2]); 118 x[2] = OP2(x[1], k[3*i+1]); 119 x[3] = OP3(x[3], k[3*i+3]); 120 x[1] = tmp; 121 } 122 else { 123 tmp = OP3(k[3*i+1], OP1(x[0], x[1])); 124 yout = OP3(OP2(tmp, OP1(x[2], x[3])), k[3*i+2]); 125 zout = OP2(tmp, yout); 126 x[0] = OP1(x[0], yout); 127 x[1] = OP1(x[1], yout); 128 x[2] = OP1(x[2], zout); 129 x[3] = OP1(x[3], zout); 130 } 131 } 132 for (i = 0; i < 4; i++) { 133 text[2*i] = MSB(x[i]); 134 text[2*i+1] = LSB(x[i]); 135 } 136 } 137 138 static void 139 decerr(char *s) 140 { 141 fprint(2, "decrypt error: %s (wrong password ?)\n", s); 142 exits("decrypt"); 143 } 144 145 void 146 main(int argc, char **argv) 147 { 148 /* 149 uchar key[] = { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 150 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }; 151 uchar plain[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 }; 152 uchar cipher[] = { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 }; 153 uchar tmp[8]; 154 */ 155 ushort edkey[2*KEYLEN]; 156 uchar obuf[8], buf[8], key[16]; 157 long i, m, n, om; 158 int dec, stdin = 0, stdout = 1; 159 Biobuf *bin, *bout; 160 161 /* 162 memcpy(tmp, plain, 8); 163 idea_key_setup(key, edkey); 164 idea_cipher(edkey, tmp, 0); 165 if (memcmp(tmp, cipher, 8)) { 166 print("encrypt wrong\n"); 167 exits(""); 168 } 169 idea_cipher(edkey, tmp, 1); 170 if (memcmp(tmp, plain, 8)) { 171 print("decrypt wrong\n"); 172 exits(""); 173 } 174 */ 175 176 if((argc != 3 && argc != 4) || (strcmp(argv[1], "-e") != 0 && strcmp(argv[1], "-d") != 0) || strlen(argv[2]) != 16){ 177 fprint(2, "usage: idea -[e | d] <16 char key> [inputfile]\n"); 178 exits("usage"); 179 } 180 dec = strcmp(argv[1], "-d") == 0; 181 if(argc == 4){ 182 char s[128]; 183 184 stdin = open(argv[3], OREAD); 185 if(stdin < 0){ 186 fprint(2, "cannot open %s\n", argv[3]); 187 exits(""); 188 } 189 strcpy(s, argv[3]); 190 if(dec){ 191 if(strcmp(s+strlen(s)-3, ".id") != 0){ 192 fprint(2, "input file not a .id file\n"); 193 exits(""); 194 } 195 s[strlen(s)-3] = '\0'; 196 } 197 else 198 strcat(s, ".id"); 199 stdout = create(s, OWRITE, 0666); 200 if(stdout < 0){ 201 fprint(2, "cannot create %s\n", s); 202 exits(""); 203 } 204 } 205 for(i = 0; i < 16; i++) 206 key[i] = argv[2][i]; 207 idea_key_setup(key, edkey); 208 m = om = 0; 209 bin = (Biobuf*)malloc(sizeof(Biobuf)); 210 bout = (Biobuf*)malloc(sizeof(Biobuf)); 211 Binit(bin, stdin, OREAD); 212 Binit(bout, stdout, OWRITE); 213 for(;;){ 214 n = Bread(bin, &buf[m], 8-m); 215 if(n <= 0) 216 break; 217 m += n; 218 if(m == 8){ 219 idea_cipher(edkey, buf, dec); 220 if(dec){ /* leave last block around */ 221 if(om > 0) 222 Bwrite(bout, obuf, 8); 223 memcpy(obuf, buf, 8); 224 om = 8; 225 } 226 else 227 Bwrite(bout, buf, 8); 228 m = 0; 229 } 230 } 231 if(dec){ 232 if(om != 8) 233 decerr("no last block"); 234 if(m != 0) 235 decerr("last block not 8 bytes long"); 236 m = obuf[7]; 237 if(m < 0 || m > 7) 238 decerr("bad modulus"); 239 for(i = m; i < 8-1; i++) 240 if(obuf[i] != 0) 241 decerr("byte not 0"); 242 Bwrite(bout, obuf, m); 243 } 244 else{ 245 for(i = m; i < 8; i++) 246 buf[i] = 0; 247 buf[7] = m; 248 idea_cipher(edkey, buf, dec); 249 Bwrite(bout, buf, 8); 250 } 251 Bflush(bout); 252 Bterm(bin); 253 Bterm(bout); 254 } 255