void challenge_34() { gmp_randstate_t *state = gmp_rand(); mpz_t p, g, a, A, b, B; unsigned char server_key[16], client_key[16]; unsigned char server_ct[256] = {0}, client_ct[256] = {0}; unsigned char server_iv[16], client_iv[16]; unsigned char message[128] = "this is a message of 30 bytes."; int mlen = 30, ctlen_server, ctlen_client, ptlen; fill_random_bytes(server_iv, 16); fill_random_bytes(client_iv, 16); // ServerKeyExchange: // Sends generated p, g, A dh_params(p, g); dh_keyexchange(state, p, g, a, A); // MITM relays p, g, and p instead of A // ClientKeyExchange: // Send generated B dh_keyexchange(state, p, g, b, B); // MITM relays p instead of B // Finished (server): // Received p from client, sends iv + encrypted message dh_finished(p, p, a, server_key); ctlen_server = encrypt_AES_CBC(message, server_ct, mlen, server_key, server_iv); // MITM relays as is // Finished (client): // Received p from server, sends iv + encrypted message dh_finished(p, p, b, client_key); ctlen_client = encrypt_AES_CBC(message, client_ct, mlen, client_key, client_iv); // MITM relays as is // Key should now be kdf(0), since // p mod p = 0 and 0^a = 0^b = 0 unsigned char mitm_key[16]; unsigned char pt[256] = {0}; dh_kdf_from_ui(0, mitm_key); ptlen = decrypt_AES_CBC(server_ct, pt, ctlen_server, mitm_key, server_iv); print_str("Recovered plaintext from server message:"); print_binary(pt, ptlen); memset(pt, 0, 256); ptlen = decrypt_AES_CBC(client_ct, pt, ctlen_client, mitm_key, client_iv); print_str("Recovered plaintext from client message:"); print_binary(pt, ptlen); dh_cleanup(state, p, g, a, A, b, B); }
/* * Generates UUID based on DCE Version 4 */ void uuid_generate_random(uuid_t uu) { struct uuid uuid; if (uu == NULL) return; (void) memset(uu, 0, sizeof (uuid_t)); (void) memset(&uuid, 0, sizeof (struct uuid)); fill_random_bytes(uu, sizeof (uuid_t)); string_to_struct(&uuid, uu); /* * This is version 4, so say so in the UUID version field (4 bits) */ uuid.time_hi_and_version |= (1 << 14); /* * we don't want the bit 1 to be set also which is for version 1 */ uuid.time_hi_and_version &= VER1_MASK; /* * The variant for this format is the 2 high bits set to 10, * so here it is */ uuid.clock_seq_hi_and_reserved |= 0x80; /* * Set MSB of Ethernet address to 1 to indicate that it was generated * randomly */ uuid.node_addr[0] |= 0x80; struct_to_string(uu, &uuid); }
unsigned char *get_static_key() { static unsigned char static_key[16]; static int init = 0; if (!init) { fill_random_bytes(static_key, 16); init = 1; } return static_key; }
/* * Fills system_node with Ethernet address if available, * else fills random numbers */ static void gen_ethernet_address(uuid_node_t *system_node) { uchar_t node[6]; if (get_ethernet_address(system_node) != 0) { fill_random_bytes(node, 6); (void) memcpy(system_node->nodeID, node, 6); /* * use 8:0:20 with the multicast bit set * to avoid namespace collisions. */ system_node->nodeID[0] = 0x88; system_node->nodeID[1] = 0x00; system_node->nodeID[2] = 0x20; } }
void challenge_35() { gmp_randstate_t *state = gmp_rand(); mpz_t p, g, a, A, b, B; unsigned char server_key[16], client_key[16]; unsigned char server_ct[256] = {0}, client_ct[256] = {0}; unsigned char server_iv[16], client_iv[16]; unsigned char message[128] = "this is a message of 30 bytes."; int mlen = 30, ctlen_server, ptlen; fill_random_bytes(server_iv, 16); fill_random_bytes(client_iv, 16); // Negotiate group (server): // Send p, g dh_params(p, g); // MITM replaces g mpz_t g_client; //mpz_init_set_ui(g_client, 1); //mpz_init_set(g_client, p); mpz_init(g_client); mpz_sub_ui(g_client, p, 1); // Negotiate group (client): // Send ACK // ServerKeyExchange: // Sends generated A dh_keyexchange(state, p, g, a, A); // MITM relays as is // ClientKeyExchange: // Send generated B dh_keyexchange(state, p, g_client, b, B); // MITM relays as is // Finished (server): // Received p from client, sends iv + encrypted message dh_finished(p, B, a, server_key); ctlen_server = encrypt_AES_CBC(message, server_ct, mlen, server_key, server_iv); // MITM relays as is // Finished (client): // Received p from server, sends iv + encrypted message dh_finished(p, A, b, client_key); encrypt_AES_CBC(message, client_ct, mlen, client_key, client_iv); // MITM relays as is // For g = 1: // Server key should now be kdf(1), since // B^a = (1^b)^a = 1 // Client key unknown if A cannot be modified // For g = p: // Server key should now be kdf(0), since // B^a = 0^a = 0 // Client key unknown if A cannot be modified // For g = p - 1: // Server key should now be kdf(1) 75% of the time, // and kdf(p-1) 25% of the time, since // B^a = ((p-1)^b)^a mod p = 1 if a*b even // = p - 1 if a*b odd // Client key unknown if A cannot be modified unsigned char mitm_key[16]; unsigned char pt[256] = {0}; dh_kdf_from_ui(1, mitm_key); ptlen = decrypt_AES_CBC(server_ct, pt, ctlen_server, mitm_key, server_iv); if (ptlen == 0) { dh_kdf(g_client, mitm_key); ptlen = decrypt_AES_CBC(server_ct, pt, ctlen_server, mitm_key, server_iv); } print_str("Recovered plaintext from server message:"); print_binary(pt, ptlen); dh_cleanup(state, p, g, a, A, b, B); mpz_clear(g_client); }