Received: (from cpunk@localhost) by slack.lne.com (8.11.0/8.11.0) id g4R9crb01035 for [EMAIL PROTECTED]; Mon, 27 May 2002 02:38:53 -0700 Received: from weltregierung.koeln.ccc.de (w11g.ff.c0re.23.nu [213.221.113.45]) by slack.lne.com (8.11.0/8.11.0) with ESMTP id g4R9cZe01019 for <[EMAIL PROTECTED]>; Mon, 27 May 2002 02:38:36 -0700 Received: (qmail 9955 invoked by uid 900); 27 May 2002 09:33:53 -0000 X-Mailsort: cypherpunks Received: (qmail 9937 invoked by uid 0); 27 May 2002 09:33:50 -0000 Received: from unknown (HELO einstein.ssz.com) ([EMAIL PROTECTED]) by w11g.ff.c0re.23.nu with SMTP; 27 May 2002 09:33:50 -0000 Received: (from cpunks@localhost) by einstein.ssz.com (8.8.8/8.8.8) id EAA19338 for [EMAIL PROTECTED]; Mon, 27 May 2002 04:55:40 -0500 Received: (from mdom@localhost) by einstein.ssz.com (8.8.8/8.8.8) id EAA19320 for cypherpunks-outgoing; Mon, 27 May 2002 04:55:31 -0500 Received: (from cpunks_anon@localhost) by einstein.ssz.com (8.8.8/8.8.8) id EAA19315 for [EMAIL PROTECTED]; Mon, 27 May 2002 04:55:29 -0500 From: CDR Anonymizer <[EMAIL PROTECTED]> Message-Id: <[EMAIL PROTECTED]> Subject: Meganet VME decryptor Date: Mon, 27 May 2002 11:18:05 +0200 (CEST) To: [EMAIL PROTECTED] Sender: [EMAIL PROTECTED] Precedence: bulk X-Unsubscription-Info: http://einstein.ssz.com/cdr
/* * You might have heard of Meganet's "Virtual Matrix Encryption." They've * had a series of "crack this code" contests, but won't tell us how * their code works. The program below was reverse-engineered from the * shareware software which is available on their web site, and can * decrypt VME files. It's very different from Meganet's software, but * produces exactly the same results in all my tests. This is not a * cracking program (you need to supply the required secret information * in order to decrypt) but maybe someone can use it to build one. * * I've added the ability to decode the VME98 file header. I couldn't * find an executable to work with, so my only source of information was * a few encrypted (probably garbage) files. Only the header is decoded, * not the file contents. * * Meganet claims that the "Targeted Delivery System" increases security * by limiting decryption to copies of VME with certain serial numbers. * It's possible for anyone to compute the required decryption * parameters, though, as the program below demonstrates. It can decrypt * messages targeted to any serial number (provided you know the proper * passwords and such, of course). * * The "Date Limiting Algorithm" is supposed to prevent decryption after * a certain date. Meganet's VME software extracts the date limit from * the encrypted file, compares it to the current date, and refuses to * decrypt the file if the date isn't right. This program has no such * limitation, so it can decrypt regardless of the date limit. * * VME computes a "Transaction Code" and "Authentication Number" to * verify file integrity. These are basically dressed-up 8-bit checksums. * * VME has an alternate encryption mode which tries to be faster by doing * fewer computations per character. You can access this mode by typing & "av" in the "Link Parameter" field of their shareware program. This * program supports both modes. * * If you try to decrypt Meganet's old encrypted challenge files with * this code (using the passwords given on their web site), you'll get * garbage. However, it's exactly the same garbage that you'll get if * you decrypt the files with their shareware software. Apparantly * either a) the shareware version is broken, or b) Meganet decided to * make certain nobody would win the challenge by encrypting random * numbers instead of a meaningful file. This code can correctly decrypt * files that were encrypted with the shareware version. */ #include <stdio.h> #include <string.h> #include <ctype.h> int vme_decrypt(FILE *data_file, char *passwords[], FILE *config_file, FILE *secret_file, FILE *out_file); /* Test driver. Sorry there isn't a proper user interface here. */ int main() { FILE *data_file, *config_file, *secret_file, *out_file; char *passwords[] = { "[EMAIL PROTECTED]", /* source user */ "[EMAIL PROTECTED]", /* target user */ "VME Challenge 2001", /* description */ "", /* password */ }; data_file = fopen("vme2001.vme", "rb"); config_file = fopen("vme2001.cfg", "rb"); secret_file = fopen("vme2001.txt", "rb"); out_file = fopen("decrypt.out", "wb"); if (vme_decrypt(data_file,passwords,config_file,secret_file,out_file)) printf("Decryption failed\n"); return 0; } /* main */ #define VME_NUM_PASS 4 #define VME_PASS_SIZE 0x40 #define VME_KEY_SIZE 0x10 #define VME_MAX_FUNCS 100 #define VME_BUF_SIZE 0x100 #define VME_MBK_SIZE 0x8000 #define VME_MAXINT 0xffffffffu #define SWAP(x,y) { int temp = (x); (x) = (y); (y) = temp; } #define LROT(x,y) ( ((x)<<(y) | (x)>>(8-(y))) & 0xff ) #define RROT(x,y) ( ((x)>>(y) | (x)<<(8-(y))) & 0xff ) #define VME_RAND(r) ( (r)=((r)*0x19660du+0x3c6ef35fu)&VME_MAXINT ) #define VME_RAND4(r) ( (r)=((r)*(-3)-1)&0xf ) #define VME_RAND8(r) ( (r)=((r)*0x0d+0x5f)&0xff ) #define VME_RAND15(r) ( (r)=((r)*0x660d+0x735f)&0x7fff ) #define VME98_RAND8(r) ( ((r)=((r)*5+1)&0x1ff)>>1 ) struct vme_state { int version, fast_mode, num_funcs, secret_size; int stk_xor, stk_sum, key_sum; int rand_byte1, rand_byte2; unsigned main_key; unsigned char recipient[VME_KEY_SIZE], key3[VME_KEY_SIZE]; unsigned char func_order[VME_MAX_FUNCS], key_order[VME_MAX_FUNCS]; unsigned char key1[VME_BUF_SIZE], key2[VME_BUF_SIZE]; unsigned char stk[VME_BUF_SIZE], mul[VME_BUF_SIZE]; unsigned char perm1[VME_BUF_SIZE]; unsigned char perm2[VME_BUF_SIZE], invperm2[VME_BUF_SIZE]; unsigned char rmbk1[VME_BUF_SIZE], rmbk2[VME_BUF_SIZE]; unsigned char rmbk3[VME_BUF_SIZE], rmbk4[VME_BUF_SIZE]; unsigned char mbk1[VME_MBK_SIZE], mbk2[VME_MBK_SIZE]; unsigned char mbk3[VME_MBK_SIZE], mbk4[VME_MBK_SIZE]; }; static int vme_load_config(FILE *config_file, struct vme_state *vme); static int vme_load_stk(FILE *data_file, struct vme_state *vme); static int vme_main_init(FILE *data_file, char *passwords[], FILE *secret_file, struct vme_state *vme); static void vme_key_init(struct vme_state *vme); static void vme_mbk_init(FILE *secret_file, struct vme_state *vme); static void vme_calc_code(char *label, int sum); static void vme00_decrypt(FILE *data_file, FILE *out_file, struct vme_state *vme); static void vme00_fastdecrypt(FILE *data_file, FILE *out_file, struct vme_state *vme); static void vme02_decrypt(FILE *data_file, FILE *out_file, struct vme_state *vme); static void vme02_fastdecrypt(FILE *data_file, FILE *out_file, struct vme_state *vme); static int vme_table1(int c, int n, int k, struct vme_state *vme); static int vme_table2(int c, int n, unsigned rand); /* Main decryption function */ int vme_decrypt(FILE *data_file, char *passwords[], FILE *config_file, FILE *secret_file, FILE *out_file) { struct vme_state vme; if ( vme_load_config(config_file, &vme) ) return 1; if ( vme_load_stk(data_file, &vme) ) return 1; if ( vme_main_init(data_file, passwords, secret_file, &vme) ) return 1; vme_key_init(&vme); vme_mbk_init(secret_file, &vme); if (vme.version > 2000) { if (vme.fast_mode) vme02_fastdecrypt(data_file, out_file, &vme); else vme02_decrypt(data_file, out_file, &vme); } else { if (vme.fast_mode) vme00_fastdecrypt(data_file, out_file, &vme); else vme00_decrypt(data_file, out_file, &vme); } return 0; } /* vme_decrypt */ /* * The configuration file gives the initial order of the functions * applied to the data as it is encrypted. */ static int vme_load_config(FILE *config_file, struct vme_state *vme) { int i, c, f, n, rand_state; if (config_file == NULL) { vme->func_order[0] = vme->key_order[0] = 0xf; vme->num_funcs = 1; } else { fseek(config_file, 0, SEEK_SET); rand_state = 0xff; n = 0; for (i = 0; i < VME_MAX_FUNCS; i++) { c = getc(config_file); if (c == EOF) return 1; c ^= VME_RAND8(rand_state); f = c >> 4; vme->func_order[i] = f; vme->key_order[i] = (f == 0xe) ? 0xe : c & 0xf; if (f != 0xf) n = i; } vme->num_funcs = n + 1; } return 0; } /* vme_load_config */ /* * The encrypted file is prefixed with a 256-byte header which makes up * the Specific Transaction Key (STK). Note that the STK is only one of * several "keys" you need to know in order to decrypt the rest of the * file. There are several encoded pieces of information encoded into * the STK. Instead of using the manufacturer-recommended procedure to * decode the header information using the passwords, this code just * does an exhaustive key search. You're going to bust a gut laughing * when you see this. */ static int vme_load_stk(FILE *data_file, struct vme_state *vme) { int i, j, r, s, c; int found, isgood, pos, xor, sum, rand_state; char date[VME_KEY_SIZE], file_id[VME_KEY_SIZE], recip[VME_KEY_SIZE]; char serial[VME_KEY_SIZE], time[VME_KEY_SIZE]; if (data_file == NULL) return 1; fseek(data_file, 0, SEEK_SET); for (i = 0; i < VME_BUF_SIZE; i++) { c = getc(data_file); if (c == EOF) return 1; vme->stk[i] = c; } /* Search the entire 7-bit keyspace */ found = 0; for (i = 0; i < 0xff; i += 2) { rand_state = i; for (j = 0; j < VME_KEY_SIZE; j++) { pos = j << 4; r = VME_RAND8(rand_state); s = VME_RAND8(rand_state) & 3; date[j] = vme->stk[pos+s] ^ r; file_id[j] = vme->stk[pos + ((s+1)&3)] ^ ((pos+0x7f)&0xff); r = VME_RAND8(rand_state); s = VME_RAND8(rand_state) & 3; recip[j] = vme->stk[pos+s+4] ^ r; r = VME_RAND8(rand_state); s = VME_RAND8(rand_state) & 3; serial[j] = vme->stk[pos+s+8] ^ r; r = VME_RAND8(rand_state); s = VME_RAND8(rand_state) & 3; time[j] = vme->stk[pos+s+12] ^ r; } isgood = 1; for (j = 0; isgood && j < VME_KEY_SIZE; j++) if (!isdigit(date[j])) isgood = 0; for (j = 0; isgood && j < 14; j++) if (!isdigit(time[j])) isgood = 0; if (!isgood) continue; if (strncmp(file_id, "VVVVVVVVVVVVVVVV", 16) == 0) vme->fast_mode = 0; else if (strncmp(file_id, "vvvvvvvvvvvvvvvv", 16) == 0) vme->fast_mode = 1; else continue; found = 1; vme->version = time[14]*100 + time[15]; memcpy(vme->recipient, recip, VME_KEY_SIZE); printf("Guessed header key: 0x%02x\n", i); printf("Date limit: from %.4s/%.2s/%.2s ", date, date+4, date+6); printf("to %.4s/%.2s/%.2s\n", date+8, date+12, date+14); printf("Recipient: %.16s\n", recip); printf("Encryptor serial number: %.4s-%.4s-%.4s-%.4s\n", serial, serial+4, serial+8, serial+12); printf("Encryption time: %.4s/%.2s/%.2s ", time, time+4, time+6); printf("%.2s:%.2s:%.2s\n", time+8, time+10, time+12); printf("VME version: %d\n", vme->version); if (vme->fast_mode) printf("Encrypted in fast mode\n"); } if (!found) { /* Try to decode a VME98 header. 4-bit keyspace, it seems. */ for (i = 1; i < 0x1ff; i += 0x20) { rand_state = i; for (j = 0; j < VME_KEY_SIZE; j++) { pos = j << 4; r = VME98_RAND8(rand_state); s = VME98_RAND8(rand_state) & 3; date[j] = vme->stk[pos+s] ^ r; r = VME98_RAND8(rand_state); s = VME98_RAND8(rand_state) & 3; recip[j] = vme->stk[pos+s+4] ^ r; r = VME98_RAND8(rand_state); s = VME98_RAND8(rand_state) & 3; serial[j] = vme->stk[pos+s+8] ^ r; r = VME98_RAND8(rand_state); s = VME98_RAND8(rand_state) & 3; time[j] = vme->stk[pos+s+12] ^ r; } isgood = 1; for (j = 0; isgood && j < VME_KEY_SIZE; j++) if (!isdigit(date[j])) isgood = 0; for (j = 0; isgood && j < 14; j++) if (!isdigit(time[j])) isgood = 0; if (!isgood) continue; found = 1; vme->fast_mode = 0; vme->version = time[14]*100 + time[15]; memcpy(vme->recipient, recip, VME_KEY_SIZE); printf("Guessed header key: 0x%03x\n", i); printf("Date limit: from %.4s/%.2s/%.2s ", date, date+4, date+6); printf("to %.4s/%.2s/%.2s\n", date+8, date+12, date+14); printf("Recipient: %.16s\n", recip); printf("Encryptor serial number: %.4s-%.4s-%.4s-%.4s\n", serial, serial+4, serial+8, serial+12); printf("Encryption time: %.4s/%.2s/%.2s ", time, time+4, time+6); printf("%.2s:%.2s:%.2s\n", time+8, time+10, time+12); printf("VME version: %d\n", vme->version); } if (!found) { printf("Warning: couldn't find header key\n"); vme->fast_mode = 0; vme->version = 2000; memset(vme->recipient, 0, VME_KEY_SIZE); } } rand_state = 0x2d; xor = 0x7b; sum = 0; for (i = 0; i < VME_BUF_SIZE; i++) { c = vme->stk[i]; sum += c; c ^= VME_RAND8(rand_state); xor ^= c; vme->stk[i] = c; } vme->stk_xor = xor; vme->stk_sum = sum & 0xff; return 0; } /* vme_load_stk */ /* * Use the passwords and file sizes to determine the 32-bit main_key * and two other 256-byte keys. */ static int vme_main_init(FILE *data_file, char *passwords[], FILE *secret_file, struct vme_state *vme) { int i, j, r; int xor1, xor2, data_size; unsigned sum, recip_sum, pass_sum; unsigned main_key, header_key, rand_state, rand_state2; unsigned char key_str[VME_PASS_SIZE]; unsigned char pass[VME_NUM_PASS][VME_PASS_SIZE]; unsigned char fixed_key[VME_NUM_PASS][VME_PASS_SIZE]; if (data_file == NULL) return 1; rand_state = 3; pass_sum = 0; for (i = 0; i < VME_NUM_PASS; i++) { for (j = 0; j < VME_PASS_SIZE && passwords[i][j] != '\0'; j++) pass_sum += pass[i][j] = passwords[i][j]; for (; j < VME_PASS_SIZE; j++) pass_sum += pass[i][j] = VME_RAND8(rand_state); } rand_state = 0x30; for (i = 0; i < VME_NUM_PASS; i++) for (j = 0; j < VME_PASS_SIZE; j++) fixed_key[i][j] = VME_RAND8(rand_state); /* Recompute the header key to validate the key search above. */ rand_state = pass_sum & 0xff; sum = 0; header_key = 0; for (j = 0; j < VME_PASS_SIZE; j++) { for (i = 0; i < VME_NUM_PASS; i++) sum += VME_RAND8(rand_state) * pass[i][j]; rand_state = (sum + j) & 0xff; header_key += VME_RAND8(rand_state); } rand_state = (header_key + 0x61) & 0xff; header_key = VME_RAND8(rand_state); header_key *= VME_RAND8(rand_state); printf("Computed header key: 0x%02x\n", header_key & 0xff); fseek(data_file, 0, SEEK_END); data_size = ftell(data_file) - VME_BUF_SIZE; if (data_size < 0) return 1; if (secret_file == NULL) vme->secret_size = 0; else { fseek(secret_file, 0, SEEK_END); vme->secret_size = ftell(secret_file); } if (strncmp(vme->recipient, "Global ", 16) == 0) { sprintf(key_str, " %d %d ", data_size, vme->secret_size); recip_sum = 0xdf2; } else if (strncmp(vme->recipient+8, "Local ", 8) == 0) { sprintf(key_str, " %d %d %.8s", data_size, vme->secret_size, vme->recipient); rand_state = 0xe; recip_sum = 0x1c0; for (i = 0; i < 8; i++) recip_sum += VME_RAND4(rand_state) * vme->recipient[i]; } else { /* specific recipient */ sprintf(key_str, " %d %d %.16s", data_size, vme->secret_size, vme->recipient); rand_state = 0x76593361; for (i = 0; i < 8; i++) { VME_RAND(rand_state); rand_state = (rand_state % 0x7919) * vme->recipient[i] * vme->recipient[(VME_KEY_SIZE - 1) - i]; VME_RAND(rand_state); while (rand_state >= 0x7fffffff) rand_state -= 0x7fffffff; } rand_state2 = 0xe; recip_sum = 0xdf2; for (i = 0; i < VME_KEY_SIZE; i++) { VME_RAND(rand_state); rand_state = (rand_state % 32767001) + 0xe4a03; r = vme->recipient[i]; for (j = 0; j < r; j++) VME_RAND(rand_state); recip_sum += (VME_RAND(rand_state) & 0xff) * VME_RAND4(rand_state2); for (j++; j < 0x100; j++) VME_RAND(rand_state); } } rand_state = 0x67; for (i = strlen(key_str); i < VME_PASS_SIZE; i++) key_str[i] = VME_RAND8(rand_state); sum = pass_sum + 0x7f80; for (i = 0; i < VME_PASS_SIZE; i++) sum += key_str[i]; for (i = 0; i < VME_BUF_SIZE; i++) sum += vme->stk[i]; rand_state = sum; sum = vme->stk_xor; main_key = vme->stk_xor << 6; for (i = 0; i < VME_PASS_SIZE; i++) { for (j = i; j < VME_BUF_SIZE; j += VME_PASS_SIZE) sum += (VME_RAND(rand_state) & 0xfffff) * vme->stk[j]; sum += (VME_RAND(rand_state) & 0xfffff) * key_str[i]; for (j = 0; j < VME_NUM_PASS; j++) { sum += (VME_RAND(rand_state) & 0xfffff) * pass[j][i]; sum += (VME_RAND(rand_state) & 0xfffff) * fixed_key[j][i]; } rand_state = sum + i; main_key += VME_RAND(rand_state) & 0x1ffffff; for (j = 0; j < VME_NUM_PASS; j++) { r = VME_RAND(rand_state) & 0xff; vme->key1[j<<6 | i] = pass[j][i] ^ r; vme->key2[j<<6 | i] = fixed_key[j][i] ^ r; } } vme->main_key = main_key & VME_MAXINT; rand_state = (main_key + 0x7f) & 0xff; xor1 = 0x9b; xor2 = 0xa7; for (i = 0; i < VME_BUF_SIZE; i++) { r = VME_RAND8(rand_state); xor1 ^= vme->key1[i] ^= r; xor2 ^= vme->key2[i] ^= r; } vme->key_sum = vme->stk_xor + recip_sum + xor1 + xor2; return 0; } /* vme_main_init */ /* Initialize some other keys */ static void vme_key_init(struct vme_state *vme) { int i, j, rand_state; rand_state = (vme->main_key + 0x4d) & 0xff; for (i = 0; i < VME_BUF_SIZE; i++) vme->perm1[i] = i; for (i = 0; i < VME_BUF_SIZE; i++) { j = VME_RAND8(rand_state); SWAP(vme->perm1[i], vme->perm1[j]); } rand_state = (vme->main_key + 0x4e) & 0xff; for (i = 0; i < VME_BUF_SIZE; i++) vme->perm2[i] = i; for (i = 0; i < VME_BUF_SIZE; i++) { j = VME_RAND8(rand_state); SWAP(vme->perm2[i], vme->perm2[j]); } for (i = 0; i < VME_BUF_SIZE; i++) vme->invperm2[ vme->perm2[i] ] = i; /* This generates a permutation of two copies of the multiplicative units of Z/256 */ rand_state = (vme->main_key + vme->key_sum) & 0xff; for (i = 1; i < VME_BUF_SIZE; i += 2) { j = 1; while ( (i*j & 0xff) != 1 ) j += 2; vme->mul[VME_RAND8(rand_state)] = j; vme->mul[VME_RAND8(rand_state)] = j; } } /* vme_key_init */ /* * Initialize the infamous Million Bit Key using the main_key and * secret_file. Also compute a reduced version. */ static void vme_mbk_init(FILE *secret_file, struct vme_state *vme) { int i, j, c, rand_state; rand_state = (vme->main_key + 0xbd) & 0xff; for (i = 0; i < VME_MBK_SIZE; i++) { vme->mbk1[i] = VME_RAND8(rand_state); vme->mbk2[i] = VME_RAND8(rand_state); vme->mbk3[i] = VME_RAND8(rand_state); vme->mbk4[i] = VME_RAND8(rand_state); } if (secret_file != NULL) fseek(secret_file, 0, SEEK_SET); if (vme->version > 2000) { if (vme->secret_size <= 0) ; else if (vme->secret_size <= 4*VME_MBK_SIZE) { for (i = 0; i < 4*VME_MBK_SIZE; i++) { c = getc(secret_file); if (c == EOF) { fseek(secret_file, 0, SEEK_SET); c = getc(secret_file); } j = i & (VME_MBK_SIZE - 1); vme->mbk1[j] ^= c; vme->mbk2[j] ^= c; vme->mbk3[j] ^= c; vme->mbk4[j] ^= c; } } else { /* big secret file */ i = 0; while ( (c = getc(secret_file)) != EOF ) { vme->mbk1[i] ^= c; vme->mbk2[i] ^= c; vme->mbk3[i] ^= c; vme->mbk4[i] ^= c; i = (i + 1) & (VME_MBK_SIZE - 1); } } } else { /* VME 2000 */ if (vme->secret_size <= 0) ; else if (vme->secret_size <= VME_MBK_SIZE) { for (i = 0; i < VME_MBK_SIZE; i++) { c = getc(secret_file); if (c == EOF) { fseek(secret_file, 0, SEEK_SET); c = getc(secret_file); } vme->mbk4[i] ^= vme->mbk3[i] ^= vme->mbk2[i] ^= vme->mbk1[i] ^= c; } } else { /* big secret file */ i = 0; while ( (c = getc(secret_file)) != EOF ) { vme->mbk4[i] ^= vme->mbk3[i] ^= vme->mbk2[i] ^= vme->mbk1[i] ^= c; i = (i + 1) & (VME_MBK_SIZE - 1); } } } for (i = 0; i < VME_BUF_SIZE; i++) { vme->rmbk1[i] = vme->mbk1[i]; vme->rmbk2[i] = vme->mbk2[i]; vme->rmbk3[i] = vme->mbk3[i]; vme->rmbk4[i] = vme->mbk4[i]; for (j = i + VME_BUF_SIZE; j < VME_MBK_SIZE; j += VME_BUF_SIZE) { vme->rmbk1[i] ^= vme->mbk1[j]; vme->rmbk2[i] ^= vme->mbk2[j]; vme->rmbk3[i] ^= vme->mbk3[j]; vme->rmbk4[i] ^= vme->mbk4[j]; } } } /* vme_mbk_init */ /* Calculate transaction code / authentication number */ static void vme_calc_code(char *label, int sum) { int i, rand_state; char code[8]; rand_state = sum & 0xff; for (i = 0; i < 8; i++) code[i] = VME_RAND8(rand_state) % 10 + '0'; printf("%s: %.4s-%.4s\n", label, code, code+4); } /* vme_calc_code */ /* VME 2000 normal decrypt */ static void vme00_decrypt(FILE *data_file, FILE *out_file, struct vme_state *vme) { int c, i, r, buf_pos, mbk_pos; int curr_cipher_byte, last_cipher_byte, last_plain_byte; int auth_sum, trans_sum; unsigned rand_state; unsigned char rand_byte[8], rand_func[4]; unsigned short rand_word[8]; fseek(data_file, VME_BUF_SIZE, SEEK_SET); buf_pos = 0; last_plain_byte = 0xaa; last_cipher_byte = 0x55; auth_sum = trans_sum = vme->stk_sum; while ( (c = getc(data_file)) != EOF ) { curr_cipher_byte = c; trans_sum += c; rand_state = vme->main_key + vme->key_sum + last_plain_byte + last_cipher_byte; r = VME_RAND(rand_state) & 1; for (i = 1; i < 8; i++) r |= VME_RAND(rand_state) & (1 << i); vme->rand_byte2 = r; vme->rand_byte1 = VME_RAND(rand_state) & 0xff; for (i = 0; i < 8; i++) rand_byte[i] = VME_RAND(rand_state) & 0xff; for (i = 0; i < 4; i++) rand_func[i] = VME_RAND(rand_state) % vme->num_funcs; for (i = 0; i < 8; i++) rand_word[i] = VME_RAND15(rand_state); vme->key3[0] = last_plain_byte; vme->key3[1] = last_cipher_byte; vme->key3[2] = vme->rand_byte2; vme->key3[3] = vme->rand_byte1; vme->key3[4] = rand_byte[0]; vme->key3[5] = rand_byte[3]; vme->key3[6] = rand_byte[4]; vme->key3[7] = rand_byte[2]; vme->key3[8] = rand_byte[1]; vme->key3[9] = vme->stk[buf_pos]; vme->key3[10] = vme->key1[buf_pos]; vme->key3[11] = vme->key2[buf_pos]; vme->key3[12] = vme->rmbk1[buf_pos] ^ vme->mbk1[rand_word[0]]; vme->key3[13] = vme->rmbk2[buf_pos] ^ vme->mbk2[rand_word[1]]; vme->key3[14] = vme->rmbk3[buf_pos] ^ vme->mbk3[rand_word[2]]; vme->key3[15] = vme->rmbk4[buf_pos] ^ vme->mbk4[rand_word[3]]; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = vme->invperm2[c]; r = rand_byte[0]; SWAP(vme->perm2[r], vme->perm2[c]); vme->invperm2[ vme->perm2[c] ] = c; vme->invperm2[ vme->perm2[r] ] = r; c ^= vme->rmbk1[buf_pos] ^ vme->rmbk2[buf_pos] ^ vme->rmbk3[buf_pos] ^ vme->rmbk4[buf_pos] ^ vme->rand_byte2 ^ rand_byte[2] ^ 0xff; i = (rand_byte[1]%7 - rand_byte[4]%7) & 7; c = LROT(c, i); c ^= 1 << (rand_byte[3] & 7); c = vme_table1(c, rand_byte[0] >> 4, vme->rand_byte1 & 0xf, vme); c = vme_table1(c, last_plain_byte >> 4, last_plain_byte & 0xf, vme); c = ((c + last_cipher_byte) * vme->mul[vme->key2[buf_pos]]) & 0xff; mbk_pos = (vme->rand_byte1<<8 | vme->stk[buf_pos]) & (VME_MBK_SIZE - 1); c ^= vme->mbk1[mbk_pos] ^ vme->mbk2[mbk_pos] ^ vme->mbk3[mbk_pos] ^ vme->mbk4[mbk_pos] ^ vme->key1[buf_pos] ^ vme->rand_byte2 ^ 0xff; c = vme_table2(c, last_plain_byte, vme->main_key); r = vme->rand_byte1; SWAP(vme->perm1[r], vme->perm1[c]); c = vme->perm1[r]; SWAP(vme->stk[buf_pos], vme->stk[rand_byte[5]]); SWAP(vme->key1[buf_pos], vme->key1[rand_byte[6]]); SWAP(vme->key2[buf_pos], vme->key2[rand_byte[7]]); SWAP(vme->func_order[rand_func[0]], vme->func_order[rand_func[1]]); SWAP(vme->key_order[rand_func[2]], vme->key_order[rand_func[3]]); SWAP(vme->mbk1[mbk_pos], vme->mbk1[rand_word[4]]); SWAP(vme->mbk2[mbk_pos], vme->mbk2[rand_word[5]]); SWAP(vme->mbk3[mbk_pos], vme->mbk3[rand_word[6]]); SWAP(vme->mbk4[mbk_pos], vme->mbk4[rand_word[7]]); auth_sum += c; last_plain_byte = c; last_cipher_byte = curr_cipher_byte; buf_pos = (buf_pos + 1) & (VME_BUF_SIZE - 1); vme->main_key++; putc(c, out_file); } vme_calc_code("Transaction Code", trans_sum); vme_calc_code("Authentication Number", auth_sum); } /* vme00_decrypt */ /* VME 2000 fast mode decrypt */ static void vme00_fastdecrypt(FILE *data_file, FILE *out_file, struct vme_state *vme) { int c, i, r, buf_pos, mbk_pos; int curr_cipher_byte, last_cipher_byte, last_plain_byte; int auth_sum, trans_sum; unsigned rand_state; unsigned char rand_byte[8], rand_func[4]; unsigned short rand_word[8]; fseek(data_file, VME_BUF_SIZE, SEEK_SET); buf_pos = mbk_pos = 0; last_plain_byte = 0xaa; last_cipher_byte = 0x55; auth_sum = trans_sum = vme->stk_sum; while ( (c = getc(data_file)) != EOF ) { trans_sum += c; if (buf_pos == 0) { rand_state = vme->main_key + vme->key_sum + last_plain_byte + last_cipher_byte; r = VME_RAND(rand_state) & 1; for (i = 1; i < 8; i++) r |= VME_RAND(rand_state) & (1 << i); vme->rand_byte2 = r; vme->rand_byte1 = VME_RAND(rand_state) & 0xff; for (i = 0; i < 8; i++) rand_byte[i] = VME_RAND(rand_state) & 0xff; for (i = 0; i < 4; i++) rand_func[i] = VME_RAND(rand_state) % vme->num_funcs; for (i = 0; i < 8; i++) rand_word[i] = VME_RAND15(rand_state); vme->key3[0] = last_plain_byte; vme->key3[1] = last_cipher_byte; vme->key3[2] = vme->rand_byte2; vme->key3[3] = vme->rand_byte1; vme->key3[4] = rand_byte[0]; vme->key3[5] = rand_byte[3]; vme->key3[6] = rand_byte[4]; vme->key3[7] = rand_byte[2]; vme->key3[8] = rand_byte[1]; vme->key3[9] = vme->stk[0]; vme->key3[10] = vme->key1[0]; vme->key3[11] = vme->key2[0]; vme->key3[12] = vme->rmbk1[0] ^ vme->mbk1[rand_word[0]]; vme->key3[13] = vme->rmbk2[0] ^ vme->mbk2[rand_word[1]]; vme->key3[14] = vme->rmbk3[0] ^ vme->mbk3[rand_word[2]]; vme->key3[15] = vme->rmbk4[0] ^ vme->mbk4[rand_word[3]]; } for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); r = vme->rand_byte1; SWAP(vme->perm1[r], vme->perm1[c]); c = vme->perm1[r]; auth_sum += c; vme->main_key++; putc(c, out_file); SWAP(vme->stk[buf_pos], vme->stk[rand_byte[5]]); SWAP(vme->key1[buf_pos], vme->key1[rand_byte[6]]); SWAP(vme->key2[buf_pos], vme->key2[rand_byte[7]]); SWAP(vme->func_order[rand_func[0]], vme->func_order[rand_func[1]]); SWAP(vme->key_order[rand_func[2]], vme->key_order[rand_func[3]]); SWAP(vme->mbk1[mbk_pos], vme->mbk1[rand_word[4]]); SWAP(vme->mbk2[mbk_pos], vme->mbk2[rand_word[5]]); SWAP(vme->mbk3[mbk_pos], vme->mbk3[rand_word[6]]); SWAP(vme->mbk4[mbk_pos], vme->mbk4[rand_word[7]]); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = vme_table2(c, last_plain_byte, vme->main_key); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); mbk_pos = (vme->rand_byte1<<8 | vme->stk[rand_byte[5]]) & (VME_MBK_SIZE - 1); c ^= vme->mbk1[mbk_pos] ^ vme->mbk2[mbk_pos] ^ vme->mbk3[mbk_pos] ^ vme->mbk4[mbk_pos]; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= vme->key1[rand_byte[6]] ^ vme->rand_byte2 ^ 0xff; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = (c * vme->mul[vme->key2[rand_byte[7]]]) & 0xff; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = (c + last_cipher_byte) & 0xff; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = vme_table1(c, last_plain_byte >> 4, last_plain_byte & 0xf, vme); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = vme_table1(c, rand_byte[0] >> 4, vme->rand_byte1 & 0xf, vme); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= 1 << (rand_byte[3] & 7); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); r = rand_byte[4] % 7 + 1; c = RROT(c, r); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); r = rand_byte[1] % 7 + 1; c = LROT(c, r); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= rand_byte[2]; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= vme->rand_byte2 ^ 0xff; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); i = buf_pos + 13; c ^= vme->rmbk1[i] ^ vme->rmbk2[i]; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); i = buf_pos + 14; c ^= vme->rmbk3[i] ^ vme->rmbk4[i]; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; curr_cipher_byte = c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = vme->invperm2[c]; r = rand_byte[0]; SWAP(vme->perm2[r], vme->perm2[c]); vme->invperm2[ vme->perm2[r] ] = r; vme->invperm2[ vme->perm2[c] ] = c; last_plain_byte = c; last_cipher_byte = curr_cipher_byte; auth_sum += c; vme->main_key++; putc(c, out_file); buf_pos = (buf_pos + 0x10) & (VME_BUF_SIZE - 1); } vme_calc_code("Transaction Code", trans_sum); vme_calc_code("Authentication Number", auth_sum); } /* vme00_fastdecrypt */ /* VME 2002 normal decrypt */ static void vme02_decrypt(FILE *data_file, FILE *out_file, struct vme_state *vme) { int c, i, r, buf_pos, mbk_pos; int curr_cipher_byte, last_cipher_byte, last_plain_byte; int auth_sum, trans_sum; unsigned rand_state; unsigned char rand_byte[8], rand_func[4]; unsigned short rand_word[8]; fseek(data_file, VME_BUF_SIZE, SEEK_SET); buf_pos = 0; last_plain_byte = 0xaa; last_cipher_byte = 0x55; auth_sum = trans_sum = vme->stk_sum; while ( (c = getc(data_file)) != EOF ) { curr_cipher_byte = c; trans_sum += c; rand_state = vme->main_key + vme->key_sum + last_plain_byte + last_cipher_byte; vme->rand_byte1 = VME_RAND(rand_state) & 0xff; for (i = 0; i < 8; i++) rand_byte[i] = VME_RAND(rand_state) & 0xff; r = vme->rand_byte1 & 1; for (i = 0; i < 7; i++) r = (rand_byte[i] + r) & (2 << i); vme->rand_byte2 = rand_byte[7] ^ r; if (vme->num_funcs > 1) for (i = 0; i < 4; i++) rand_func[i] = VME_RAND(rand_state) % vme->num_funcs; r = (vme->secret_size > 0) ? 8 : 4; for (i = 0; i < r; i++) rand_word[i] = VME_RAND15(rand_state); vme->key3[0] = vme->rmbk1[buf_pos] ^ vme->mbk1[rand_word[0]]; vme->key3[1] = last_plain_byte ^ vme->rand_byte2; vme->key3[2] = vme->stk[buf_pos]; vme->key3[3] = vme->key1[buf_pos]; vme->key3[4] = vme->key2[buf_pos]; vme->key3[5] = last_cipher_byte ^ vme->rand_byte2; vme->key3[6] = rand_byte[4] & 0xf; vme->key3[7] = vme->rand_byte1 & 0xf; vme->key3[8] = rand_byte[3]; vme->key3[9] = rand_byte[4]; vme->key3[10] = rand_byte[1]; vme->key3[11] = rand_byte[2]; vme->key3[12] = vme->rand_byte2; vme->key3[13] = vme->rmbk1[buf_pos] ^ vme->mbk2[rand_word[1]]; vme->key3[14] = vme->rmbk1[buf_pos] ^ vme->mbk3[rand_word[2]]; vme->key3[15] = vme->rmbk1[buf_pos] ^ vme->mbk4[rand_word[3]]; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = vme->invperm2[c ^ vme->key3[15]]; r = rand_byte[0]; SWAP(vme->perm2[r], vme->perm2[c]); vme->invperm2[ vme->perm2[c] ] = c; vme->invperm2[ vme->perm2[r] ] = r; c ^= vme->key3[14] ^ vme->key3[13] ^ vme->key3[12] ^ vme->key3[11] ^ 0xff; i = (vme->key3[10]%7 - vme->key3[9]%7) & 7; c = LROT(c, i); c ^= 1 << (vme->key3[8] & 7); c = vme_table2(c, vme->key3[vme->key3[7]], vme->main_key); c = vme_table2(c, vme->key3[vme->key3[6]], vme->main_key); c = ((c + vme->key3[5]) * vme->mul[vme->key3[4]]) & 0xff; mbk_pos = (vme->rand_byte1<<8 | vme->key3[2]) & (VME_MBK_SIZE - 1); c ^= vme->mbk1[mbk_pos] ^ vme->mbk2[mbk_pos] ^ vme->mbk3[mbk_pos] ^ vme->mbk4[mbk_pos] ^ vme->key3[3] ^ vme->rand_byte2 ^ 0xff; c = vme_table2(c, vme->key3[1], vme->main_key); c ^= vme->key3[0]; r = vme->rand_byte1; SWAP(vme->perm1[r], vme->perm1[c]); c = vme->perm1[r]; SWAP(vme->stk[buf_pos], vme->stk[rand_byte[5]]); SWAP(vme->key1[buf_pos], vme->key1[rand_byte[6]]); SWAP(vme->key2[buf_pos], vme->key2[rand_byte[7]]); if (vme->num_funcs > 1) { SWAP(vme->func_order[rand_func[0]], vme->func_order[rand_func[1]]); SWAP(vme->key_order[rand_func[2]], vme->key_order[rand_func[3]]); } if (vme->secret_size > 0) { SWAP(vme->mbk1[mbk_pos], vme->mbk1[rand_word[4]]); SWAP(vme->mbk2[mbk_pos], vme->mbk2[rand_word[5]]); SWAP(vme->mbk3[mbk_pos], vme->mbk3[rand_word[6]]); SWAP(vme->mbk4[mbk_pos], vme->mbk4[rand_word[7]]); } auth_sum += c; last_plain_byte = c; last_cipher_byte = curr_cipher_byte; buf_pos = (buf_pos + 1) & (VME_BUF_SIZE - 1); vme->main_key++; putc(c, out_file); } vme_calc_code("Transaction Code", trans_sum); vme_calc_code("Authentication Number", auth_sum); } /* vme02_decrypt */ /* VME 2002 fast mode decrypt */ static void vme02_fastdecrypt(FILE *data_file, FILE *out_file, struct vme_state *vme) { int c, i, r, buf_pos, mbk_pos, file_pos; int curr_cipher_byte, last_cipher_byte, last_plain_byte; int auth_sum, trans_sum; unsigned rand_state; unsigned char rand_byte[8], rand_func[4]; unsigned short rand_word[8]; fseek(data_file, VME_BUF_SIZE, SEEK_SET); file_pos = mbk_pos = 0; last_plain_byte = 0xaa; last_cipher_byte = 0x55; auth_sum = trans_sum = vme->stk_sum; while ( (c = getc(data_file)) != EOF ) { trans_sum += c; rand_state = vme->main_key + vme->key_sum + last_plain_byte + last_cipher_byte; vme->rand_byte1 = VME_RAND(rand_state) & 0xff; for (i = 0; i < 7; i++) rand_byte[i] = VME_RAND(rand_state) & 0xff; vme->rand_byte2 = VME_RAND(rand_state) & 0xff; if (vme->num_funcs > 1) for (i = 0; i < 4; i++) rand_func[i] = VME_RAND(rand_state) % vme->num_funcs; if (vme->secret_size > 0) { for (i = 0; i < 8; i++) rand_word[i] = VME_RAND15(rand_state); } else { for (i = 0; i < 4; i++) rand_word[i] = file_pos; } buf_pos = file_pos & (VME_BUF_SIZE - 1); vme->key3[0] = vme->rmbk1[buf_pos] ^ vme->mbk1[rand_word[0]]; vme->key3[1] = last_plain_byte ^ vme->rand_byte2; vme->key3[2] = vme->stk[buf_pos]; vme->key3[3] = vme->key1[buf_pos]; vme->key3[4] = vme->key2[buf_pos]; vme->key3[5] = last_cipher_byte ^ vme->rand_byte2; vme->key3[6] = rand_byte[4] & 0xf; vme->key3[7] = vme->rand_byte1 & 0xf; vme->key3[8] = rand_byte[3]; vme->key3[9] = rand_byte[4]; vme->key3[10] = rand_byte[1]; vme->key3[11] = rand_byte[2]; vme->key3[12] = vme->rand_byte2; vme->key3[13] = vme->rmbk1[buf_pos] ^ vme->mbk2[rand_word[1]]; vme->key3[14] = vme->rmbk1[buf_pos] ^ vme->mbk3[rand_word[2]]; vme->key3[15] = vme->rmbk1[buf_pos] ^ vme->mbk4[rand_word[3]]; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= vme->key3[0]; r = vme->rand_byte1; SWAP(vme->perm1[r], vme->perm1[c]); c = vme->perm1[r]; auth_sum += c; vme->main_key++; putc(c, out_file); SWAP(vme->stk[buf_pos], vme->stk[rand_byte[5]]); SWAP(vme->key1[buf_pos], vme->key1[rand_byte[6]]); if (vme->num_funcs > 1) { SWAP(vme->func_order[rand_func[0]], vme->func_order[rand_func[1]]); SWAP(vme->key_order[rand_func[2]], vme->key_order[rand_func[3]]); } if (vme->secret_size > 0) { SWAP(vme->mbk1[mbk_pos], vme->mbk1[rand_word[4]]); SWAP(vme->mbk2[mbk_pos], vme->mbk2[rand_word[5]]); SWAP(vme->mbk3[mbk_pos], vme->mbk3[rand_word[6]]); SWAP(vme->mbk4[mbk_pos], vme->mbk4[rand_word[7]]); } if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = vme_table2(c, vme->key3[1], vme->main_key); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); mbk_pos = (vme->rand_byte1<<8 | vme->key3[2]) & (VME_MBK_SIZE - 1); c ^= vme->mbk1[mbk_pos] ^ vme->mbk2[mbk_pos] ^ vme->mbk3[mbk_pos] ^ vme->mbk4[mbk_pos]; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= vme->rand_byte2 ^ vme->key3[3] ^ 0xff; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = (c * vme->mul[vme->key3[4]]) & 0xff; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = (c + vme->key3[5]) & 0xff; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = vme_table2(c, vme->key3[vme->key3[6]], vme->main_key); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = vme_table2(c, vme->key3[vme->key3[7]], vme->main_key); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= 1 << (vme->key3[8] & 0x7); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); r = vme->key3[9] % 7 + 1; c = RROT(c, r); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); r = vme->key3[10] % 7 + 1; c = LROT(c, r); auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= vme->key3[11]; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= vme->key3[12] ^ 0xff; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= vme->key3[13]; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c ^= vme->key3[14]; auth_sum += c; vme->main_key++; putc(c, out_file); if ((c = getc(data_file)) == EOF) break; trans_sum += c; curr_cipher_byte = c; for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); c = vme->invperm2[c ^ vme->key3[15]]; r = rand_byte[0]; SWAP(vme->perm2[r], vme->perm2[c]); vme->invperm2[ vme->perm2[c] ] = c; vme->invperm2[ vme->perm2[r] ] = r; last_plain_byte = c; last_cipher_byte = curr_cipher_byte; auth_sum += c; vme->main_key++; putc(c, out_file); file_pos = (file_pos + 0x10) & (VME_MBK_SIZE - 1); } vme_calc_code("Transaction Code", trans_sum); vme_calc_code("Authentication Number", auth_sum); } /* vme02_fastdecrypt */ /* A small table of functions */ static int vme_table1(int c, int n, int k, struct vme_state *vme) { int i; k = vme->key3[k]; if (n == 9) { n = k >> 4; k = vme->key3[k & 0xf]; } switch (n) { case 0: c = vme_table2(c, k, vme->main_key); break; case 1: i = (vme->rand_byte1<<8 | k) & (VME_MBK_SIZE - 1); c ^= vme->mbk1[i] ^ vme->mbk2[i] ^ vme->mbk3[i] ^ vme->mbk4[i]; break; case 2: c ^= k ^ vme->rand_byte2 ^ 0xff; break; case 3: c = (c * vme->mul[k]) & 0xff; break; case 4: c = (c + k) & 0xff; break; case 5: c ^= 1 << (k & 7); break; case 6: i = k % 7 + 1; c = RROT(c, i); break; case 7: i = k % 7 + 1; c = LROT(c, i); break; case 8: case 9: case 13: case 14: c ^= k; break; case 10: case 11: case 12: c ^= k ^ 0xff; break; case 15: break; } return c; } /* vme_table1 */ /* A big table of functions */ static int vme_table2(int c, int n, unsigned rand) { int i; rand += n; VME_RAND(rand); switch (n) { case 1: c ^= 0x20 << (rand % 3); break; case 2: c ^= (rand & 0x1f) + 2; break; case 5: c ^= (rand & 0x0f) ^ 0x7f; break; case 7: c ^= (rand & 0x3f) + 8; break; case 8: c ^= (rand & 3) ^ 0x7f; break; case 9: c ^= (rand & 1) ^ 0x3f; break; case 11: c ^= (rand & 7) ^ 0x7f; break; case 12: c ^= 4 << (rand % 6); break; case 13: c ^= rand & 0x7f; break; case 14: c ^= (rand & 0x1f) ^ 0xff; break; case 16: c ^= 1 << (rand % 6); break; case 17: c ^= 2 >> (rand & 1); break; case 18: c ^= (rand & 0x0f) ^ 0x3f; break; case 19: c ^= (rand & 0x3f) << 2; break; case 20: c ^= rand & 0xff; break; case 21: c ^= 0x20 >> (rand & 1); break; case 23: c ^= (rand & 0x0f) ^ 0x80; break; case 26: c ^= 0x80 >> (rand % 7); break; case 27: c ^= (rand & 3) ^ 8; break; case 28: c ^= rand & 1; break; case 29: c ^= (rand & 0x3f) + 0x10; break; case 31: c ^= (rand & 0x3f) + 0x20; break; case 32: c ^= (rand & 0x0f) << 1; break; case 33: c ^= 1 << (rand & 1); break; case 34: c ^= (rand & 3) ^ 7; break; case 35: c ^= 2 << (rand % 5); break; case 36: c ^= (rand & 1) ^ 0x80; break; case 37: c ^= 0x20 >> (rand % 6); break; case 38: c ^= (rand & 1) ^ 0x20; break; case 43: c ^= (rand & 0x1f) << 1; break; case 45: c ^= (rand & 7) ^ 0x10; break; case 48: c ^= (rand & 0x0f) << 2; break; case 50: c ^= (rand & 1) ^ 0x40; break; case 51: c ^= (rand & 1) ^ 0x0f; break; case 52: c ^= (rand & 1) ^ 0x1f; break; case 53: c ^= (rand & 7) ^ 0x3f; break; case 55: c ^= 0x80 >> (rand & 7); break; case 57: c ^= 0x80 >> (rand & 3); break; case 58: c ^= rand & 0x1f; break; case 59: c ^= (rand & 7) << 3; break; case 60: c ^= (rand & 3) ^ 0x80; break; case 61: c ^= (rand & 0x7f) ^ 0xff; break; case 62: c ^= rand & 7; break; case 63: c ^= 4 << (rand % 3); break; case 65: c ^= 4 << (rand & 1); break; case 66: c ^= (rand & 0x7f) + 8; break; case 67: c ^= (rand & 0x1f) + 4; break; case 68: c ^= (rand & 3) << 1; break; case 69: c ^= (rand & 0x1f) ^ 0x7f; break; case 70: c ^= (rand & 3) ^ 4; break; case 71: c ^= (rand & 7) ^ 0x80; break; case 74: c ^= (rand & 3) << 2; break; case 75: c ^= (rand & 0x7f) + 0x20; break; case 76: c ^= 4 << (rand & 3); break; case 79: c ^= (rand & 7) << 1; break; case 80: c ^= (rand & 0x7f) << 1; break; case 81: c ^= 1 << (rand % 5); break; case 84: c ^= (rand & 7) ^ 0xff; break; case 87: c ^= (rand & 3) ^ 3; break; case 88: c ^= (rand & 0x7f) + 2; break; case 91: c ^= (rand & 1) ^ 1; break; case 92: c ^= (rand & 3) ^ 0xff; break; case 93: c ^= (rand & 0x3f) << 1; break; case 94: c ^= (rand & 3) ^ 0x40; break; case 95: c ^= (rand & 3) << 3; break; case 97: c ^= 0x40 >> (rand % 5); break; case 98: c ^= (rand & 3) + 2; break; case 100: c ^= 1 << (rand % 3); break; case 101: c ^= (rand & 7) ^ 0x1f; break; case 102: c ^= 2 << (rand & 3); break; case 103: c ^= (rand & 0x0f) + 2; break; case 104: c ^= 0x20 >> (rand & 3); break; case 105: c ^= 0x40 >> (rand % 3); break; case 106: c ^= 1 << (rand & 7); break; case 107: c ^= (rand & 0x0f) + 4; break; case 108: c ^= (rand & 0x7f) + 4; break; case 109: c ^= (rand & 0x1f) << 3; break; case 111: c ^= 8 << (rand & 3); break; case 113: c ^= rand & 0x0f; break; case 116: c ^= 2 << (rand & 1); break; case 117: c ^= (rand & 3) ^ 0x3f; break; case 119: c ^= 0x10 >> (rand % 5); break; case 120: c ^= (rand & 1) ^ 0x10; break; case 121: c ^= 0x10 >> (rand & 3); break; case 124: c ^= 0x10 << (rand & 1); break; case 125: c ^= (rand & 0x0f) + 8; break; case 126: c ^= (rand & 0x0f) << 4; break; case 128: c ^= 0x10 << (rand % 3); break; case 129: c ^= (rand & 1) << 1; break; case 130: c ^= (rand & 0x7f) ^ 0x7f; break; case 131: c ^= (rand & 0x1f) ^ 0x80; break; case 132: c ^= 8 << (rand % 5); break; case 133: c ^= (rand & 0x0f) ^ 0x1f; break; case 135: c ^= 0x20 >> (rand % 5); break; case 137: c ^= (rand & 0x3f) ^ 0x40; break; case 138: c ^= rand & 3; break; case 139: c ^= (rand & 1) ^ 4; break; case 140: c ^= (rand & 3) ^ 0x0f; break; case 141: c ^= (rand & 3) ^ 0x20; break; case 142: c ^= (rand & 7) ^ 0x0f; break; case 143: c ^= (rand & 1) << 4; break; case 144: c ^= (rand & 0x1f) + 0x10; break; case 145: c ^= (rand & 7) ^ 0x20; break; case 147: c ^= 0x20 >> (rand % 3); break; case 152: c ^= (rand & 0x0f) << 3; break; case 153: c ^= 8 << (rand % 3); break; case 156: c ^= 0x40 << (rand & 1); break; case 157: c ^= (rand & 0x1f) ^ 0x40; break; case 158: c ^= 8 << (rand & 1); break; case 159: c ^= 0x80 >> (rand % 3); break; case 160: c ^= (rand & 1) << 3; break; case 161: c ^= (rand & 0x0f) ^ 0x20; break; case 166: c ^= 0x80 >> (rand % 6); break; case 167: c ^= (rand & 0x3f) ^ 0xff; break; case 168: c ^= (rand & 7) + 4; break; case 169: c ^= (rand & 0x7f) ^ 0x80; break; case 170: c ^= 8 >> (rand & 1); break; case 171: c ^= (rand & 3) ^ 0x1f; break; case 172: c ^= 4 << (rand % 5); break; case 173: c ^= (rand & 7) << 2; break; case 175: c ^= (rand & 1) ^ 8; break; case 177: c ^= (rand & 0xff) ^ 0xff; break; case 179: c ^= (rand & 0x1f) ^ 0x20; break; case 181: c ^= 2 << (rand % 3); break; case 182: c ^= (rand & 3) << 4; break; case 188: c ^= 0x40 >> (rand % 7); break; case 189: c ^= (rand & 3) ^ 0x10; break; case 190: c ^= (rand & 1) ^ 0x7f; break; case 193: c ^= (rand & 7) << 4; break; case 194: c ^= 8 >> (rand % 3); break; case 195: c ^= (rand & 1) ^ 2; break; case 196: c ^= 0x10 >> (rand & 1); break; case 197: c ^= 0x40 >> (rand % 6); break; case 199: c ^= (rand & 7) + 2; break; case 200: c ^= (rand & 0x7f) + 0x40; break; case 201: c ^= 2 << (rand % 6); break; case 204: c ^= 0x40 >> (rand & 1); break; case 205: c ^= (rand & 7) ^ 8; break; case 206: c ^= 1 << (rand & 3); break; case 208: c ^= (rand & 1) ^ 3; break; case 209: c ^= rand & 0x3f; break; case 211: c ^= 0x20 << (rand & 1); break; case 212: c ^= (rand & 0x3f) ^ 0x7f; break; case 214: c ^= (rand & 0x1f) << 2; break; case 215: c ^= (rand & 0x1f) ^ 0x3f; break; case 216: c ^= 2 << (rand % 7); break; case 218: c ^= (rand & 0x1f) ^ 0x1f; break; case 221: c ^= (rand & 0x0f) ^ 0xff; break; case 223: c ^= (rand & 0x3f) + 2; break; case 224: c ^= (rand & 0x1f) + 8; break; case 225: c ^= (rand & 0x7f) + 0x10; break; case 226: c ^= (rand & 1) ^ 7; break; case 228: c ^= 0x40 >> (rand & 3); break; case 230: c ^= (rand & 0x3f) + 4; break; case 232: c ^= 0x80 >> (rand & 1); break; case 233: c ^= 0x10 << (rand & 3); break; case 235: c ^= (rand & 0x0f) ^ 0x10; break; case 236: c ^= 4 >> (rand % 3); break; case 237: c ^= (rand & 7) << 5; break; case 238: c ^= 0x10 >> (rand % 3); break; case 240: c ^= (rand & 1) << 2; break; case 241: c ^= (rand & 0x0f) ^ 0x40; break; case 242: c ^= (rand & 0x3f) ^ 0x80; break; case 243: c ^= (rand & 1) ^ 0xff; break; case 244: c ^= 1 << (rand % 7); break; case 246: c ^= (rand & 0x0f) ^ 0x0f; break; case 248: c ^= 4 >> (rand & 1); break; case 249: c ^= (rand & 7) ^ 0x40; break; case 250: c ^= 0x80 >> (rand % 5); break; case 252: c ^= (rand & 7) ^ 7; break; case 253: c ^= (rand & 0x3f) ^ 0x3f; break; case 255: c ^= 8 >> (rand & 3); break; case 0: case 180: i = 3 - (rand % 3); c = LROT(c, i); break; case 3: case 202: i = 4 - (rand & 1); c = LROT(c, i); break; case 4: case 89: i = 4 - (rand & 3); c = LROT(c, i); break; case 6: case 184: i = 6 + (rand & 1); c = LROT(c, i); break; case 10: case 64: i = 1 + (rand % 6); c = LROT(c, i); break; case 15: case 46: i = 3 + (rand % 3); c = LROT(c, i); break; case 22: case 176: i = 3 + (rand % 5); c = LROT(c, i); break; case 24: case 40: i = 2 + (rand % 5); c = LROT(c, i); break; case 25: case 164: i = 7 - (rand & 3); c = LROT(c, i); break; case 30: case 220: i = 2 + (rand & 3); c = LROT(c, i); break; case 39: case 44: i = 1 + (rand % 3); c = LROT(c, i); break; case 41: case 155: i = 2 + (rand % 3); c = LROT(c, i); break; case 42: case 146: i = 4 + (rand % 3); c = LROT(c, i); break; case 47: case 56: i = 3 - (rand & 1); c = LROT(c, i); break; case 49: case 186: i = 6 - (rand % 5); c = LROT(c, i); break; case 54: case 251: i = 6 - (rand & 1); c = LROT(c, i); break; case 72: case 77: i = 3 + (rand & 3); c = LROT(c, i); break; case 73: case 149: i = 5 - (rand & 1); c = LROT(c, i); break; case 78: case 90: i = 7 - (rand & 1); c = LROT(c, i); break; case 82: case 165: i = 5 + (rand & 1); c = LROT(c, i); break; case 83: case 198: i = 7 - (rand % 3); c = LROT(c, i); break; case 85: case 191: i = 2 + (rand % 6); c = LROT(c, i); break; case 86: case 187: i = 1 + (rand % 5); c = LROT(c, i); break; case 96: case 162: i = 4 + (rand & 3); c = LROT(c, i); break; case 99: case 254: i = 1 + (rand & 3); c = LROT(c, i); break; case 110: case 245: i = 4 + (rand & 1); c = LROT(c, i); break; case 112: case 234: i = 1 + (rand % 7); c = LROT(c, i); break; case 114: case 154: i = 3 + (rand & 1); c = LROT(c, i); break; case 115: case 150: i = 6 - (rand % 6); c = LROT(c, i); break; case 118: case 148: i = 4 - (rand % 3); c = LROT(c, i); break; case 122: case 227: i = 6 - (rand & 3); c = LROT(c, i); break; case 123: case 127: i = 2 - (rand & 1); c = LROT(c, i); break; case 134: case 247: i = 6 - (rand % 3); c = LROT(c, i); break; case 136: case 231: i = 5 - (rand % 3); c = LROT(c, i); break; case 151: case 207: i = 7 - (rand % 6); c = LROT(c, i); break; case 163: case 219: i = 5 + (rand % 3); c = LROT(c, i); break; case 174: case 222: i = 7 - (rand % 7); c = LROT(c, i); break; case 178: case 239: i = 5 - (rand % 5); c = LROT(c, i); break; case 183: case 185: i = 2 + (rand & 1); c = LROT(c, i); break; case 192: case 210: i = 1 + (rand & 1); c = LROT(c, i); break; case 203: case 213: i = 7 - (rand % 5); c = LROT(c, i); break; case 217: case 229: i = 5 - (rand & 3); c = LROT(c, i); break; } return c; } /* vme_table2 */