/* * Verse encryption routines. Implements RSA encryption/decryption plus fast XORx. */ #if !defined(V_GENERATE_FUNC_MODE) #include #include #include #include "verse.h" #include "v_pack.h" #include "v_bignum.h" #include "v_encryption.h" #define BITS V_ENCRYPTION_LOGIN_KEY_BITS /* Save some typing. */ extern void v_prime_set_random(VBigDig *x); extern void v_prime_set_table(VBigDig *x, int i); const uint8 * v_e_data_create_key(void) /* possibly the worst key gen ever */ { static unsigned int counter = 0; static uint8 buffer[V_ENCRYPTION_DATA_KEY_SIZE]; unsigned int i, temp; for(i = 0; i < V_ENCRYPTION_DATA_KEY_SIZE; i++) { counter++; temp = (counter << 13) ^ counter; temp = (temp * (temp * temp * 15731 + 789221) + 1376312589) & 0x7fffffff; buffer[i] = temp; } /* FIXME: This really isn't very pretty. */ buffer[0] &= 0x3f; /* Make sure top word is... Low. For RSA compatibility. */ /* memset(buffer, 0, sizeof buffer); fprintf(stderr, "**WARNING: XOR data encryption disabled\n"); */ return buffer; } void v_e_data_encrypt_command(uint8 *packet, size_t packet_size, const uint8 *command, size_t command_size, const uint8 *key) { uint32 pos, i; vnp_raw_unpack_uint32(packet, &pos); /* printf("encrypting packet %u", pos);*/ pos = key[pos % V_ENCRYPTION_DATA_KEY_SIZE] + packet_size; /* printf(" -> pos=%u (size %u)", pos, packet_size); printf(", key begins: ["); for(i = 0; i < 16; i++) printf(" %02X", key[(pos + i) % V_ENCRYPTION_DATA_KEY_SIZE]); printf(" ]\n"); */ for(i = 0; i < command_size; i++) packet[packet_size + i] = command[i] ^ key[(i + pos) % V_ENCRYPTION_DATA_KEY_SIZE]; } void v_e_data_decrypt_packet(uint8 *to, const uint8 *from, size_t size, const uint8 *key) { uint32 pos, i; vnp_raw_unpack_uint32(from, &pos); /* printf("decrypting packet %u", pos);*/ pos = key[pos % V_ENCRYPTION_DATA_KEY_SIZE]; /* printf(" -> pos=%u", pos); printf(", key begins: ["); for(i = 0; i < 16; i++) printf(" %02X", key[(i + pos) % V_ENCRYPTION_DATA_KEY_SIZE]); printf(" ]\n"); */ for(i = 0; i < 4; i++) to[i] = from[i]; for(i = 4; i < size; i++) to[i] = from[i] ^ key[(i + pos) % V_ENCRYPTION_DATA_KEY_SIZE]; } #endif /* From Knuth. Computes multiplicative inverse of u, modulo v. */ void v_e_math_inv(VBigDig *inv, const VBigDig *u, const VBigDig *v) { VBigDig VBIGNUM(u1, 2*BITS), VBIGNUM(u3, 2*BITS), VBIGNUM(v1, 2*BITS), VBIGNUM(v3, 2 *BITS), VBIGNUM(t1, 2*BITS), VBIGNUM(t3, 2*BITS), VBIGNUM(q, 2*BITS), VBIGNUM(w, 2*BITS); int iter = 1; v_bignum_set_one(u1); v_bignum_set_bignum(u3, u); v_bignum_set_zero(v1); v_bignum_set_bignum(v3, v); while(!v_bignum_eq_zero(v3)) { v_bignum_set_bignum(q, u3); v_bignum_div(q, v3, t3); v_bignum_set_bignum(w, q); v_bignum_mul(w, v1); v_bignum_set_bignum(t1, u1); v_bignum_add(t1, w); v_bignum_set_bignum(u1, v1); v_bignum_set_bignum(v1, t1); v_bignum_set_bignum(u3, v3); v_bignum_set_bignum(v3, t3); iter = -iter; } if(iter < 0) { v_bignum_set_bignum(inv, v); v_bignum_sub(inv, u1); } else v_bignum_set_bignum(inv, u1); } void v_e_connect_create_key(uint8 *private_key, uint8 *public_key, uint8 *n) { VBigDig VBIGNUM(p, BITS / 2), VBIGNUM(q, BITS / 2), VBIGNUM(qmo, BITS / 2), VBIGNUM(phi, BITS), VBIGNUM(pub, BITS), VBIGNUM(priv, BITS), VBIGNUM(mod, BITS); #if !defined _WIN32 /* FIXME: This is a security backdoor. Intent is simply to save time during testing. */ if(getenv("VERSE_NORSA") != NULL) { printf("VERSE: Found the NORSA envvar, using constant keys\n"); v_prime_set_table(p, 0); v_prime_set_table(q, 1); goto compute_phi; } #endif /* printf("find prime p\n");*/ v_prime_set_random(p); /* printf("find prime q\n");*/ v_prime_set_random(q); compute_phi: /* printf("done, computing key\n");*/ /* printf("p="); v_bignum_print_hex_lf(p); printf("q="); v_bignum_print_hex_lf(q); */ v_bignum_set_bignum(phi, p); v_bignum_sub_digit(phi, 1); v_bignum_set_bignum(qmo, q); v_bignum_sub_digit(qmo, 1); v_bignum_mul(phi, qmo); /* printf("phi="); v_bignum_print_hex_lf(phi); */ v_bignum_set_string_hex(pub, "0x10001"); v_e_math_inv(priv, pub, phi); /* printf(" pub="); v_bignum_print_hex_lf(pub); printf("priv="); v_bignum_print_hex_lf(priv); */ v_bignum_set_bignum(mod, p); v_bignum_mul(mod, q); /* printf(" mod="); v_bignum_print_hex_lf(mod); printf("key-creation finished\n"); */ /* Write out the keys. */ v_bignum_raw_export(pub, public_key); v_bignum_raw_export(priv, private_key); v_bignum_raw_export(mod, n); } void v_e_connect_encrypt(uint8 *output, const uint8 *data, const uint8 *key, const uint8 *key_n) { VBigDig VBIGNUM(packet, BITS), VBIGNUM(expo, BITS), VBIGNUM(mod, BITS); v_bignum_raw_import(packet, data); v_bignum_raw_import(expo, key); v_bignum_raw_import(mod, key_n); /* Verify that data is less than the modulo, this is a prerequisite for encryption. */ if(!v_bignum_gte(mod, packet)) { printf("*** WARNING. Data is not less than modulo, as it should be--encryption will break!\n"); printf(" RSA modulo: "); v_bignum_print_hex_lf(mod); printf(" RSA data: "); v_bignum_print_hex_lf(packet); } /* printf("RSA key: "); v_bignum_print_hex_lf(expo); printf("RSA mod: "); v_bignum_print_hex_lf(mod); printf("RSA in: "); v_bignum_print_hex_lf(packet); printf("bits in packet: %d, ", v_bignum_bit_msb(packet) + 1); printf("bits in modulo: %d\n", v_bignum_bit_msb(mod) + 1); */ v_bignum_pow_mod(packet, expo, mod); /* Blam. */ /* printf("RSA out: "); v_bignum_print_hex_lf(packet); */ v_bignum_raw_export(packet, output); } #if defined CRYPTALONE void v_encrypt_test(void) { uint8 k_priv[BITS / 8], k_pub[BITS / 8], k_n[BITS / 8], cipher[BITS / 8], plain[BITS / 8], decode[BITS / 8], i; printf("testing RSA-crypto\n"); v_e_connect_create_key(k_pub, k_priv, k_n); /* exit(0);*/ printf("key pair generated, encrypting something\n"); memset(plain, 0, sizeof plain); strcpy(plain, "This is some text to encrypt, to give it something to chew on."); printf("plain: %02X (%u)\n", plain[0], strlen(plain)); v_e_connect_encrypt(cipher, plain, k_pub, k_n); printf("plain: %02X, cipher: %02X\n", plain[0], cipher[0]); v_e_connect_encrypt(decode, cipher, k_priv, k_n); printf("decoded: %02X: '", decode[0]); for(i = 0; decode[i] != 0; i++) putchar(decode[i]); printf("'\n"); /* printf("\npublic key: "); v_bignum_print_hex_lf(k_public); printf("private key: "); v_bignum_print_hex_lf(k_private); v_bignum_set_string(msg, "123"); gettimeofday(&t1, NULL); v_bignum_pow_mod(msg, k_private, k_n); gettimeofday(&t2, NULL); printf("encrypted: "); v_bignum_print_hex_lf(msg); printf("encrypted %u bits in %g s\n", BITS, t2.tv_sec - t1.tv_sec + 1.0E-6 * (t2.tv_usec - t1.tv_usec)); gettimeofday(&t1, NULL); v_bignum_pow_mod(msg, k_public, k_n); gettimeofday(&t2, NULL); printf("decrypted: "); v_bignum_print_hex_lf(msg); printf("decrypted %u bits in %g s\n", BITS, t2.tv_sec - t1.tv_sec + 1.0E-6 * (t2.tv_usec - t1.tv_usec)); exit(0); *//* v_e_encrypt(cipher, plain, &k_private, &k_n); printf("encrypted data: "); for(i = 0; i < sizeof cipher; i++) printf("%c", isalnum(cipher[i]) ? cipher[i] : '?'); printf("\n\n"); printf("decrypting\n"); v_e_encrypt(decode, cipher, &k_public, &k_n); printf("decrypted data: "); for(i = 0; i < sizeof cipher; i++) printf("%c", isalnum(decode[i]) ? decode[i] : '?'); printf("\n\n"); */ } int main(void) { v_encrypt_test(); return 0; } #endif