/* * 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. * 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. * * If you try to decrypt Meganet's old encrypted challenge files with this * code, you'll get garbage. However, it's exactly the same garbage that * you'll get if you decrypt the files with their shareware software. This * is not due to the much-hyped "Date Limiting Algorithm" (see below for * details). 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]", /* sender */ "[EMAIL PROTECTED]", /* recipient */ "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; } /* There are a number of incompatible changes between the 2000 and 2002 versions. */ /* #define VME_2002 1 */ #define VME_NUM_PASS 4 #define VME_PASS_SIZE 0x40 #define VME_KEY_SIZE 0x10 #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_RAND8(r) ( (r)=((r)*0x0d+0x5f)&0xff ) struct vme_state { int num_funcs, have_secret, key_xor, randb1, randb10; unsigned main_key; unsigned char func_order[VME_KEY_SIZE], key_order[VME_KEY_SIZE]; unsigned char key3[VME_KEY_SIZE]; unsigned char stk[VME_BUF_SIZE], key1[VME_BUF_SIZE], key2[VME_BUF_SIZE]; unsigned char perm1[VME_BUF_SIZE], perm2[VME_BUF_SIZE]; unsigned char invperm2[VME_BUF_SIZE], mul[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_decrypt_loop(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); 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); vme_decrypt_loop(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) return 1; fseek(config_file, 0, SEEK_SET); rand_state = 0xff; n = 0; for (i = 0; i < VME_KEY_SIZE; 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 enrypted file is prefixed with a 256-byte header which contains * the Specific Transaction Key (STK) and some encoded information. * Instead of using the manufacturer-recommended procedure to decode * the 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, 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 whole 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; j < VME_KEY_SIZE; j++) if (!isdigit(date[j])) isgood = 0; for (j = 0; j < 14; j++) if (!isdigit(time[j])) isgood = 0; if (!isgood) continue; found = 1; printf("Guessed header key: 0x%02x\n", i); /* Meganet's VME software deliberately trashes the STK if it discovers that the current date is not within the date limit. I don't. */ 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 verion: %02d%02d\n", time[14], time[15]); if (strncmp(file_id, "VVVVVVVVVVVVVVVV", 16) != 0) printf("Warning: unsupported encryption mode\n"); if (strncmp(recip, "Global ", 16) != 0) printf("Warning: unsupported recipient type\n"); } if (!found) printf("Warning: couldn't find header key\n"); rand_state = 0x2d; xor = 0x7b; for (i = 0; i < VME_BUF_SIZE; i++) xor ^= vme->stk[i] ^= VME_RAND8(rand_state); vme->key_xor = xor; return 0; } /* vme_load_stk */ /* * Use the passwords and file sizes to determine the 32-bit main_key * and two other 16-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; int data_size, secret_size; unsigned sum, main_key, header_key, rand_state; unsigned char sizes[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; for (i = 0; i < VME_NUM_PASS; i++) { for (j = 0; j < VME_PASS_SIZE && passwords[i][j] != '\0'; j++) pass[i][j] = passwords[i][j]; for (; j < VME_PASS_SIZE; j++) 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. */ sum = 0; for (i = 0; i < VME_NUM_PASS; i++) for (j = 0; j < VME_PASS_SIZE; j++) sum += pass[i][j]; rand_state = sum; 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; header_key += VME_RAND8(rand_state); } rand_state = header_key + 0x61; 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) secret_size = 0; else { fseek(secret_file, 0, SEEK_END); secret_size = ftell(secret_file); } rand_state = 0x67; sprintf(sizes, " %d %d ", data_size, secret_size); for (i = strlen(sizes); i < VME_PASS_SIZE; i++) sizes[i] = VME_RAND8(rand_state); sum = 0x7f80; for (i = 0; i < VME_PASS_SIZE; i++) { sum += sizes[i]; for (j = 0; j < VME_NUM_PASS; j++) sum += pass[j][i]; } for (i = 0; i < VME_BUF_SIZE; i++) sum += vme->stk[i]; rand_state = sum; sum = vme->key_xor; main_key = vme->key_xor << 6; for (i = 0; i < VME_PASS_SIZE; i++) { sum += (VME_RAND(rand_state) & 0xfffff) * vme->stk[i]; sum += (VME_RAND(rand_state) & 0xfffff) * vme->stk[i+0x40]; sum += (VME_RAND(rand_state) & 0xfffff) * vme->stk[i+0x80]; sum += (VME_RAND(rand_state) & 0xfffff) * vme->stk[i+0xc0]; sum += (VME_RAND(rand_state) & 0xfffff) * sizes[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; 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_xor += 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; 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; 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_xor + 0xf2; 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 * the secret_file. Also compute a reduced version. */ static void vme_mbk_init(FILE *secret_file, struct vme_state *vme) { int i, j, c; int secret_size, rand_state; rand_state = vme->main_key + 0xbd; 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) secret_size = 0; else { fseek(secret_file, 0, SEEK_END); secret_size = ftell(secret_file); fseek(secret_file, 0, SEEK_SET); } #ifdef VME_2002 if (secret_size <= 0) vme->have_secret = 0; else if (secret_size <= 4*VME_MBK_SIZE) { vme->have_secret = 1; 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 { vme->have_secret = 1; 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 */ vme->have_secret = 1; if (secret_size <= 0) ; else if (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 { 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); } } #endif 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 = VME_BUF_SIZE; j < VME_MBK_SIZE; j += VME_BUF_SIZE) { vme->rmbk1[i] ^= vme->mbk1[i + j]; vme->rmbk2[i] ^= vme->mbk2[i + j]; vme->rmbk3[i] ^= vme->mbk3[i + j]; vme->rmbk4[i] ^= vme->mbk4[i + j]; } } } /* vme_mbk_init */ /* * Actual encryption happens here. */ static void vme_decrypt_loop(FILE *data_file, FILE *out_file, struct vme_state *vme) { int c, i; int buf_pos, mbk_pos; int curr_cipher_byte, last_cipher_byte, last_plain_byte; int randb1, randb2, randb3, randb4, randb5; int randb6, randb7, randb8, randb9, randb10; int randf1, randf2, randf3, randf4; int randw1, randw2, randw3, randw4; int randw5, randw6, randw7, randw8; unsigned rand_state; fseek(data_file, VME_BUF_SIZE, SEEK_SET); buf_pos = 0; last_plain_byte = 0xaa; last_cipher_byte = 0x55; while ( (c = getc(data_file)) != EOF ) { curr_cipher_byte = c; rand_state = vme->main_key + vme->key_xor + last_plain_byte + last_cipher_byte + 0xdf2; #ifndef VME_2002 randb10 = 0; for (i = 0; i < 8; i++) randb10 |= VME_RAND(rand_state) & (1 << i); vme->randb10 = randb10; #endif vme->randb1 = randb1 = VME_RAND(rand_state) & 0xff; randb2 = VME_RAND(rand_state) & 0xff; randb3 = VME_RAND(rand_state) & 0xff; randb4 = VME_RAND(rand_state) & 0xff; randb5 = VME_RAND(rand_state) & 0xff; randb6 = VME_RAND(rand_state) & 0xff; randb7 = VME_RAND(rand_state) & 0xff; randb8 = VME_RAND(rand_state) & 0xff; randb9 = VME_RAND(rand_state) & 0xff; #ifdef VME_2002 randb10 = randb1 & 1; randb10 = (randb2 + randb10) & 2; randb10 = (randb3 + randb10) & 4; randb10 = (randb4 + randb10) & 8; randb10 = (randb5 + randb10) & 0x10; randb10 = (randb6 + randb10) & 0x20; randb10 = (randb7 + randb10) & 0x40; randb10 = (randb8 + randb10) & 0x80; vme->randb10 = randb10 ^= randb9; #endif if (vme->num_funcs > 1) { randf1 = VME_RAND(rand_state) % vme->num_funcs; randf2 = VME_RAND(rand_state) % vme->num_funcs; randf3 = VME_RAND(rand_state) % vme->num_funcs; randf4 = VME_RAND(rand_state) % vme->num_funcs; } randw1 = VME_RAND(rand_state) & (VME_MBK_SIZE - 1); randw2 = VME_RAND(rand_state) & (VME_MBK_SIZE - 1); randw3 = VME_RAND(rand_state) & (VME_MBK_SIZE - 1); randw4 = VME_RAND(rand_state) & (VME_MBK_SIZE - 1); if (vme->have_secret) { randw5 = VME_RAND(rand_state) & (VME_MBK_SIZE - 1); randw6 = VME_RAND(rand_state) & (VME_MBK_SIZE - 1); randw7 = VME_RAND(rand_state) & (VME_MBK_SIZE - 1); randw8 = VME_RAND(rand_state) & (VME_MBK_SIZE - 1); } #ifdef VME_2002 vme->key3[0] = vme->rmbk1[buf_pos] ^ vme->mbk1[randw1]; vme->key3[1] = last_plain_byte ^ randb10; 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 ^ randb10; vme->key3[6] = randb6 & 0xf; vme->key3[7] = randb1 & 0xf; vme->key3[8] = randb5; vme->key3[9] = randb6; vme->key3[10] = randb3; vme->key3[11] = randb4; vme->key3[12] = randb10; vme->key3[13] = vme->rmbk2[buf_pos] ^ vme->mbk2[randw2]; vme->key3[14] = vme->rmbk3[buf_pos] ^ vme->mbk3[randw3]; vme->key3[15] = vme->rmbk4[buf_pos] ^ vme->mbk4[randw4]; #else /* VME 2000 */ vme->key3[0] = last_plain_byte; vme->key3[1] = last_cipher_byte; vme->key3[2] = randb10; vme->key3[3] = randb1; vme->key3[4] = randb2; vme->key3[5] = randb5; vme->key3[6] = randb6; vme->key3[7] = randb4; vme->key3[8] = randb3; 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[randw1]; vme->key3[13] = vme->rmbk2[buf_pos] ^ vme->mbk2[randw2]; vme->key3[14] = vme->rmbk3[buf_pos] ^ vme->mbk3[randw3]; vme->key3[15] = vme->rmbk4[buf_pos] ^ vme->mbk4[randw4]; #endif for (i = vme->num_funcs - 1; i >= 0; i--) c = vme_table1(c, vme->func_order[i], vme->key_order[i], vme); #ifdef VME_2002 c = vme->invperm2[c ^ vme->key3[15]]; SWAP(vme->perm2[randb2], vme->perm2[c]); vme->invperm2[ vme->perm2[c] ] = c; vme->invperm2[ vme->perm2[randb2] ] = randb2; c ^= vme->key3[14] ^ vme->key3[13] ^ randb10 ^ randb4 ^ 0xff; i = randb3 % 7; c = LROT(c, i); i = randb6 % 7; c = RROT(c, i); c ^= 1 << (randb5 & 7); c = vme_table2(c, vme->key3[randb1 & 0xf], vme->main_key); c = vme_table2(c, vme->key3[randb6 & 0xf], vme->main_key); c = ((c + vme->key3[5]) * vme->mul[vme->key3[4]]) & 0xff; mbk_pos = (randb1<<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] ^ randb10 ^ 0xff; c = vme_table2(c, vme->key3[1], vme->main_key); c ^= vme->key3[0]; SWAP(vme->perm1[randb1], vme->perm1[c]); c = vme->perm1[randb1]; #else /* VME 2000 */ c = vme->invperm2[c]; SWAP(vme->perm2[randb2], vme->perm2[c]); vme->invperm2[ vme->perm2[c] ] = c; vme->invperm2[ vme->perm2[randb2] ] = randb2; c ^= randb10 ^ randb4 ^ 0xff; i = randb3 % 7; c = LROT(c, i); i = randb6 % 7; c = RROT(c, i); c ^= 1 << (randb5 & 7); c = vme_table1(c, randb2 >> 4, randb1 & 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 = (randb1<<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] ^ randb10 ^ 0xff; c = vme_table2(c, last_plain_byte, vme->main_key); SWAP(vme->perm1[randb1], vme->perm1[c]); c = vme->perm1[randb1]; #endif SWAP(vme->stk[buf_pos], vme->stk[randb7]); SWAP(vme->key1[buf_pos], vme->key1[randb8]); SWAP(vme->key2[buf_pos], vme->key2[randb9]); if (vme->num_funcs > 1) { SWAP(vme->func_order[randf1], vme->func_order[randf2]); SWAP(vme->key_order[randf3], vme->key_order[randf4]); } if (vme->have_secret) { SWAP(vme->mbk1[mbk_pos], vme->mbk1[randw5]); SWAP(vme->mbk2[mbk_pos], vme->mbk2[randw6]); SWAP(vme->mbk3[mbk_pos], vme->mbk3[randw7]); SWAP(vme->mbk4[mbk_pos], vme->mbk4[randw8]); } 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_decrypt_loop */ /* * 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->randb1<<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->randb10 ^ 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 0: i = 3 - (rand % 3); c = LROT(c, i); break; case 1: c ^= 1 << (5 + (rand % 3)); break; case 2: c ^= 2 + (rand & 0x1f); break; case 3: i = 4 - (rand & 1); c = LROT(c, i); break; case 4: i = 4 + (rand & 3); c = RROT(c, i); break; case 5: c ^= 127 - (rand & 0xf); break; case 6: i = 2 - (rand & 1); c = RROT(c, i); break; case 7: c ^= 8 + (rand & 0x3f); break; case 8: c ^= 127 - (rand & 3); break; case 9: c ^= 63 - (rand & 1); break; case 10: i = 7 - (rand % 6); c = RROT(c, i); break; case 11: c ^= 127 - (rand & 7); break; case 12: c ^= 1 << (2 + (rand % 6)); break; case 13: c ^= (rand & 0x7f); break; case 14: c ^= 255 - (rand & 0x1f); break; case 15: i = 3 + (rand % 3); c = LROT(c, i); break; case 16: c ^= 1 << (rand % 6); break; case 17: c ^= 1 << (1 - (rand & 1)); break; case 18: c ^= 63 - (rand & 0xf); break; case 19: c ^= (rand & 0x3f) << 2; break; case 20: c ^= (rand & 0xff); break; case 21: c ^= 1 << (5 - (rand & 1)); break; case 22: i = 3 + (rand % 5); c = LROT(c, i); break; case 23: c ^= 128 + (rand & 0xf); break; case 24: i = 2 + (rand % 5); c = LROT(c, i); break; case 25: i = 7 - (rand & 3); c = LROT(c, i); break; case 26: c ^= 1 << (7 - (rand % 7)); break; case 27: c ^= 8 + (rand & 3); break; case 28: c ^= (rand & 1); break; case 29: c ^= 16 + (rand & 0x3f); break; case 30: i = 2 + (rand & 3); c = LROT(c, i); break; case 31: c ^= 32 + (rand & 0x3f); break; case 32: c ^= (rand & 0xf) << 1; break; case 33: c ^= 1 << (rand & 1); break; case 34: c ^= 7 - (rand & 3); break; case 35: c ^= 1 << (1 + (rand % 5)); break; case 36: c ^= 128 + (rand & 1); break; case 37: c ^= 1 << (5 - (rand % 6)); break; case 38: c ^= 32 + (rand & 1); break; case 39: i = 7 - (rand % 3); c = RROT(c, i); break; case 40: i = 6 - (rand % 5); c = RROT(c, i); break; case 41: i = 2 + (rand % 3); c = LROT(c, i); break; case 42: i = 4 + (rand % 3); c = LROT(c, i); break; case 43: c ^= (rand & 0x1f) << 1; break; case 44: i = 1 + (rand % 3); c = LROT(c, i); break; case 45: c ^= 16 + (rand & 7); break; case 46: i = 5 - (rand % 3); c = RROT(c, i); break; case 47: i = 3 - (rand & 1); c = LROT(c, i); break; case 48: c ^= (rand & 0xf) << 2; break; case 49: i = 6 - (rand % 5); c = LROT(c, i); break; case 50: c ^= 64 + (rand & 1); break; case 51: c ^= 15 - (rand & 1); break; case 52: c ^= 31 - (rand & 1); break; case 53: c ^= 63 - (rand & 7); break; case 54: i = 2 + (rand & 1); c = RROT(c, i); break; case 55: c ^= 1 << (7 - (rand & 7)); break; case 56: i = 5 + (rand & 1); c = RROT(c, i); break; case 57: c ^= 1 << (7 - (rand & 3)); break; case 58: c ^= (rand & 0x1f); break; case 59: c ^= (rand & 7) << 3; break; case 60: c ^= 128 + (rand & 3); break; case 61: c ^= 255 - (rand & 0x7f); break; case 62: c ^= (rand & 7); break; case 63: c ^= 1 << (2 + (rand % 3)); break; case 64: i = 1 + (rand % 6); c = LROT(c, i); break; case 65: c ^= 1 << (2 + (rand & 1)); break; case 66: c ^= 8 + (rand & 0x7f); break; case 67: c ^= 4 + (rand & 0x1f); break; case 68: c ^= (rand & 3) << 1; break; case 69: c ^= 127 - (rand & 0x1f); break; case 70: c ^= 4 + (rand & 3); break; case 71: c ^= 128 + (rand & 7); break; case 72: i = 5 - (rand & 3); c = RROT(c, i); break; case 73: i = 5 - (rand & 1); c = LROT(c, i); break; case 74: c ^= (rand & 3) << 2; break; case 75: c ^= 32 + (rand & 0x7f); break; case 76: c ^= 1 << (2 + (rand & 3)); break; case 77: i = 3 + (rand & 3); c = LROT(c, i); break; case 78: i = 1 + (rand & 1); c = RROT(c, i); break; case 79: c ^= (rand & 7) << 1; break; case 80: c ^= (rand & 0x7f) << 1; break; case 81: c ^= 1 << (rand % 5); break; case 82: i = 5 + (rand & 1); c = LROT(c, i); break; case 83: i = 1 + (rand % 3); c = RROT(c, i); break; case 84: c ^= 255 - (rand & 7); break; case 85: i = 6 - (rand % 6); c = RROT(c, i); break; case 86: i = 1 + (rand % 5); c = LROT(c, i); break; case 87: c ^= 3 - (rand & 3); break; case 88: c ^= 2 + (rand & 0x7f); break; case 89: i = 4 - (rand & 3); c = LROT(c, i); break; case 90: i = 7 - (rand & 1); c = LROT(c, i); break; case 91: c ^= 1 - (rand & 1); break; case 92: c ^= 255 - (rand & 3); break; case 93: c ^= (rand & 0x3f) << 1; break; case 94: c ^= 64 + (rand & 3); break; case 95: c ^= (rand & 3) << 3; break; case 96: i = 4 + (rand & 3); c = LROT(c, i); break; case 97: c ^= 1 << (6 - (rand % 5)); break; case 98: c ^= 2 + (rand & 3); break; case 99: i = 7 - (rand & 3); c = RROT(c, i); break; case 100: c ^= 1 << (rand % 3); break; case 101: c ^= 31 - (rand & 7); break; case 102: c ^= 1 << (1 + (rand & 3)); break; case 103: c ^= 2 + (rand & 0xf); break; case 104: c ^= 1 << (5 - (rand & 3)); break; case 105: c ^= 1 << (6 - (rand % 3)); break; case 106: c ^= 1 << (rand & 7); break; case 107: c ^= 4 + (rand & 0xf); break; case 108: c ^= 4 + (rand & 0x7f); break; case 109: c ^= (rand & 0x1f) << 3; break; case 110: i = 4 - (rand & 1); c = RROT(c, i); break; case 111: c ^= 1 << (3 + (rand & 3)); break; case 112: i = 1 + (rand % 7); c = LROT(c, i); break; case 113: c ^= (rand & 0xf); break; case 114: i = 5 - (rand & 1); c = RROT(c, i); break; case 115: i = 6 - (rand % 6); c = LROT(c, i); break; case 116: c ^= 1 << (1 + (rand & 1)); break; case 117: c ^= 63 - (rand & 3); break; case 118: i = 4 - (rand % 3); c = LROT(c, i); break; case 119: c ^= 1 << (4 - (rand % 5)); break; case 120: c ^= 16 + (rand & 1); break; case 121: c ^= 1 << (4 - (rand & 3)); break; case 122: i = 6 - (rand & 3); c = LROT(c, i); break; case 123: i = 6 + (rand & 1); c = RROT(c, i); break; case 124: c ^= 1 << (4 + (rand & 1)); break; case 125: c ^= 8 + (rand & 0xf); break; case 126: c ^= (rand & 0xf) << 4; break; case 127: i = 2 - (rand & 1); c = LROT(c, i); break; case 128: c ^= 1 << (4 + (rand % 3)); break; case 129: c ^= (rand & 1) << 1; break; case 130: c ^= 127 - (rand & 0x7f); break; case 131: c ^= 128 + (rand & 0x1f); break; case 132: c ^= 1 << (3 + (rand % 5)); break; case 133: c ^= 31 - (rand & 0xf); break; case 134: i = 2 + (rand % 3); c = RROT(c, i); break; case 135: c ^= 1 << (5 - (rand % 5)); break; case 136: i = 5 - (rand % 3); c = LROT(c, i); break; case 137: c ^= 64 + (rand & 0x3f); break; case 138: c ^= (rand & 3); break; case 139: c ^= 4 + (rand & 1); break; case 140: c ^= 15 - (rand & 3); break; case 141: c ^= 32 + (rand & 3); break; case 142: c ^= 15 - (rand & 7); break; case 143: c ^= (rand & 1) << 4; break; case 144: c ^= 16 + (rand & 0x1f); break; case 145: c ^= 32 + (rand & 7); break; case 146: i = 4 - (rand % 3); c = RROT(c, i); break; case 147: c ^= 1 << (5 - (rand % 3)); break; case 148: i = 4 + (rand % 3); c = RROT(c, i); break; case 149: i = 3 + (rand & 1); c = RROT(c, i); break; case 150: i = 2 + (rand % 6); c = RROT(c, i); break; case 151: i = 1 + (rand % 6); c = RROT(c, i); break; case 152: c ^= (rand & 0xf) << 3; break; case 153: c ^= 1 << (3 + (rand % 3)); break; case 154: i = 3 + (rand & 1); c = LROT(c, i); break; case 155: i = 6 - (rand % 3); c = RROT(c, i); break; case 156: c ^= 1 << (6 + (rand & 1)); break; case 157: c ^= 64 + (rand & 0x1f); break; case 158: c ^= 1 << (3 + (rand & 1)); break; case 159: c ^= 1 << (7 - (rand % 3)); break; case 160: c ^= (rand & 1) << 3; break; case 161: c ^= 32 + (rand & 0xf); break; case 162: i = 4 - (rand & 3); c = RROT(c, i); break; case 163: i = 3 - (rand % 3); c = RROT(c, i); break; case 164: i = 1 + (rand & 3); c = RROT(c, i); break; case 165: i = 3 - (rand & 1); c = RROT(c, i); break; case 166: c ^= 1 << (7 - (rand % 6)); break; case 167: c ^= 255 - (rand & 0x3f); break; case 168: c ^= 4 + (rand & 7); break; case 169: c ^= 128 + (rand & 0x7f); break; case 170: c ^= 1 << (3 - (rand & 1)); break; case 171: c ^= 31 - (rand & 3); break; case 172: c ^= 1 << (2 + (rand % 5)); break; case 173: c ^= (rand & 7) << 2; break; case 174: i = 1 + (rand % 7); c = RROT(c, i); break; case 175: c ^= 8 + (rand & 1); break; case 176: i = 5 - (rand % 5); c = RROT(c, i); break; case 177: c ^= 255 - (rand & 0xff); break; case 178: i = 5 - (rand % 5); c = LROT(c, i); break; case 179: c ^= 32 + (rand & 0x1f); break; case 180: i = 5 + (rand % 3); c = RROT(c, i); break; case 181: c ^= 1 << (1 + (rand % 3)); break; case 182: c ^= (rand & 3) << 4; break; case 183: i = 2 + (rand & 1); c = LROT(c, i); break; case 184: i = 6 + (rand & 1); c = LROT(c, i); break; case 185: i = 6 - (rand & 1); c = RROT(c, i); break; case 186: i = 2 + (rand % 5); c = RROT(c, i); break; case 187: i = 7 - (rand % 5); c = RROT(c, i); break; case 188: c ^= 1 << (6 - (rand % 7)); break; case 189: c ^= 16 + (rand & 3); break; case 190: c ^= 127 - (rand & 1); break; case 191: i = 2 + (rand % 6); c = LROT(c, i); break; case 192: i = 7 - (rand & 1); c = RROT(c, i); break; case 193: c ^= (rand & 7) << 4; break; case 194: c ^= 1 << (3 - (rand % 3)); break; case 195: c ^= 2 + (rand & 1); break; case 196: c ^= 1 << (4 - (rand & 1)); break; case 197: c ^= 1 << (6 - (rand % 6)); break; case 198: i = 7 - (rand % 3); c = LROT(c, i); break; case 199: c ^= 2 + (rand & 7); break; case 200: c ^= 64 + (rand & 0x7f); break; case 201: c ^= 1 << (1 + (rand % 6)); break; case 202: i = 4 + (rand & 1); c = RROT(c, i); break; case 203: i = 1 + (rand % 5); c = RROT(c, i); break; case 204: c ^= 1 << (6 - (rand & 1)); break; case 205: c ^= 8 + (rand & 7); break; case 206: c ^= 1 << (rand & 3); break; case 207: i = 7 - (rand % 6); c = LROT(c, i); break; case 208: c ^= 3 - (rand & 1); break; case 209: c ^= (rand & 0x3f); break; case 210: i = 1 + (rand & 1); c = LROT(c, i); break; case 211: c ^= 1 << (5 + (rand & 1)); break; case 212: c ^= 127 - (rand & 0x3f); break; case 213: i = 7 - (rand % 5); c = LROT(c, i); break; case 214: c ^= (rand & 0x1f) << 2; break; case 215: c ^= 63 - (rand & 0x1f); break; case 216: c ^= 1 << (1 + (rand % 7)); break; case 217: i = 5 - (rand & 3); c = LROT(c, i); break; case 218: c ^= 31 - (rand & 0x1f); break; case 219: i = 5 + (rand % 3); c = LROT(c, i); break; case 220: i = 6 - (rand & 3); c = RROT(c, i); break; case 221: c ^= 255 - (rand & 0xf); break; case 222: i = 7 - (rand % 7); c = LROT(c, i); break; case 223: c ^= 2 + (rand & 0x3f); break; case 224: c ^= 8 + (rand & 0x1f); break; case 225: c ^= 16 + (rand & 0x7f); break; case 226: c ^= 7 - (rand & 1); break; case 227: i = 2 + (rand & 3); c = RROT(c, i); break; case 228: c ^= 1 << (6 - (rand & 3)); break; case 229: i = 3 + (rand & 3); c = RROT(c, i); break; case 230: c ^= 4 + (rand & 0x3f); break; case 231: i = 3 + (rand % 3); c = RROT(c, i); break; case 232: c ^= 1 << (7 - (rand & 1)); break; case 233: c ^= 1 << (4 + (rand & 3)); break; case 234: i = 7 - (rand % 7); c = RROT(c, i); break; case 235: c ^= 16 + (rand & 0xf); break; case 236: c ^= 1 << (2 - (rand % 3)); break; case 237: c ^= (rand & 7) << 5; break; case 238: c ^= 1 << (4 - (rand % 3)); break; case 239: i = 3 + (rand % 5); c = RROT(c, i); break; case 240: c ^= (rand & 1) << 2; break; case 241: c ^= 64 + (rand & 0xf); break; case 242: c ^= 128 + (rand & 0x3f); break; case 243: c ^= 255 - (rand & 1); break; case 244: c ^= 1 << (rand % 7); break; case 245: i = 4 + (rand & 1); c = LROT(c, i); break; case 246: c ^= 15 - (rand & 0xf); break; case 247: i = 6 - (rand % 3); c = LROT(c, i); break; case 248: c ^= 1 << (2 - (rand & 1)); break; case 249: c ^= 64 + (rand & 7); break; case 250: c ^= 1 << (7 - (rand % 5)); break; case 251: i = 6 - (rand & 1); c = LROT(c, i); break; case 252: c ^= 7 - (rand & 7); break; case 253: c ^= 63 - (rand & 0x3f); break; case 254: i = 1 + (rand & 3); c = LROT(c, i); break; case 255: c ^= 1 << (3 - (rand & 3)); break; } return c; } /* vme_table2 */