From 87ac5acdd8ed72d2b8364a680f31f0a52b2f4e75 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Sat, 1 Jun 2013 21:29:06 -0300 Subject: [PATCH] WPA2Decrypter now decrypts both CCMP and TKIP encrypted traffic. --- include/crypto.h | 16 ++- include/internals.h | 8 ++ src/crypto.cpp | 195 ++++++++++++++++++++++++++++++++++++- tests/src/wpa2_decrypt.cpp | 164 ++++++++++++++++++++++++++++--- 4 files changed, 359 insertions(+), 24 deletions(-) diff --git a/include/crypto.h b/include/crypto.h index 154f98b..2247946 100644 --- a/include/crypto.h +++ b/include/crypto.h @@ -49,6 +49,7 @@ namespace Crypto { /** * \cond */ + class RC4Key; #ifdef HAVE_WPA2_DECRYPTION namespace WPA2 { class invalid_handshake : public std::exception { @@ -57,21 +58,26 @@ namespace Crypto { return "invalid handshake"; } }; - class CCMPSessionKeys { + class SessionKeys { public: typedef Internals::byte_array<80> ptk_type; typedef Internals::byte_array<32> pmk_type; - CCMPSessionKeys(const RSNHandshake &hs, const pmk_type &pmk); - SNAP *decrypt_unicast(const Dot11Data &dot11, const RawPDU &raw) const; + SessionKeys(const RSNHandshake &hs, const pmk_type &pmk); + SNAP *decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const; private: + SNAP *ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const; + SNAP *tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const; + RC4Key generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw) const; + ptk_type ptk; + bool is_ccmp; }; class SupplicantData { public: typedef HWAddress<6> address_type; - typedef CCMPSessionKeys::pmk_type pmk_type; + typedef SessionKeys::pmk_type pmk_type; SupplicantData(const std::string &psk, const std::string &ssid); @@ -228,7 +234,7 @@ namespace Crypto { typedef std::map pmks_map; typedef std::map bssids_map; typedef std::pair addr_pair; - typedef std::map keys_map; + typedef std::map keys_map; void try_add_keys(const Dot11Data &dot11, const RSNHandshake &hs); addr_pair make_addr_pair(const address_type &addr1, const address_type &addr2) { diff --git a/include/internals.h b/include/internals.h index 9f6938a..e8e2b3b 100644 --- a/include/internals.h +++ b/include/internals.h @@ -60,6 +60,14 @@ public: byte_array(InputIterator start) { std::copy(start, n, data); } + + uint8_t &operator[](size_t i) { + return data[i]; + } + + uint8_t operator[](size_t i) const{ + return data[i]; + } iterator begin() { return data; diff --git a/src/crypto.cpp b/src/crypto.cpp index 1632a69..5164eae 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -123,8 +123,109 @@ void xor_range(InputIterator1 src1, InputIterator2 src2, OutputIterator dst, siz } } +const uint16_t sbox_table[2][256]= { + { + 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, + 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, + 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, + 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, + 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, + 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, + 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, + 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, + 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, + 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, + 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, + 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, + 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, + 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, + 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, + 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, + 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, + 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, + 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, + 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, + 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, + 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, + 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, + 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, + 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, + 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, + 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, + 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, + 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, + 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, + 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, + 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A + }, + { + 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, + 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, + 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, + 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, + 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, + 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, + 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, + 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, + 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, + 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, + 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, + 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, + 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, + 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, + 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, + 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, + 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, + 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, + 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, + 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, + 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, + 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, + 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, + 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, + 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, + 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, + 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, + 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, + 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, + 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, + 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, + 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C + } +}; + +uint16_t sbox(uint16_t i) { + return sbox_table[0][i & 0xff] ^ sbox_table[1][(i >> 8)]; +} + +uint16_t join_bytes(uint8_t b1, uint8_t b2) { + return (static_cast(b1) << 8) | b2; +} + +uint16_t rotate(uint16_t value) { + return ((value >> 1) & 0x7fff) | (value << 15); +} + +uint16_t upper_byte(uint16_t value) { + return (value >> 8) & 0xff; +} + +uint16_t lower_byte(uint16_t value) { + return value & 0xff; +} + +HWAddress<6> get_bssid(const Dot11Data &dot11) { + if(dot11.from_ds() && !dot11.to_ds()) + return dot11.addr3(); + else if(!dot11.from_ds() && dot11.to_ds()) + return dot11.addr2(); + else + return dot11.addr2(); +} + namespace WPA2 { -CCMPSessionKeys::CCMPSessionKeys(const RSNHandshake &hs, const pmk_type &pmk) { + +SessionKeys::SessionKeys(const RSNHandshake &hs, const pmk_type &pmk) { uint8_t PKE[100] = "Pairwise key expansion"; uint8_t MIC[16]; min(hs.client_address(), hs.supplicant_address()).copy(PKE + 23); @@ -152,9 +253,10 @@ CCMPSessionKeys::CCMPSessionKeys(const RSNHandshake &hs, const pmk_type &pmk) { if(!std::equal(MIC, MIC + sizeof(MIC), hs.handshake()[3].mic())) throw invalid_handshake(); + is_ccmp = (hs.handshake()[3].key_descriptor() == 2); } -SNAP *CCMPSessionKeys::decrypt_unicast(const Dot11Data &dot11, const RawPDU &raw) const { +SNAP *SessionKeys::ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const { const RawPDU::payload_type &pload = raw.payload(); uint8_t MIC[16] = {0}; uint8_t PN[6] = { @@ -226,6 +328,93 @@ SNAP *CCMPSessionKeys::decrypt_unicast(const Dot11Data &dot11, const RawPDU &raw 0; } +RC4Key SessionKeys::generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw) const { + const RawPDU::payload_type &pload = raw.payload(); + const uint8_t *tk = ptk.begin() + 32; + Internals::byte_array<16> rc4_key; + uint16_t ppk[6]; + const Dot11::address_type addr = get_bssid(dot11); + if(pload.size() >= 7) { + // Phase 1 + ppk[0] = join_bytes(pload[4], pload[5]); + ppk[1] = join_bytes(pload[6], pload[7]); + ppk[2] = join_bytes(addr[1], addr[0]); + ppk[3] = join_bytes(addr[3], addr[2]); + ppk[4] = join_bytes(addr[5], addr[4]); + + for(size_t i = 0; i < 4; ++i) { + ppk[0] += sbox(ppk[4] ^ join_bytes(tk[1], tk[0])); + ppk[1] += sbox(ppk[0] ^ join_bytes(tk[5], tk[4])); + ppk[2] += sbox(ppk[1] ^ join_bytes(tk[9], tk[8])); + ppk[3] += sbox(ppk[2] ^ join_bytes(tk[13], tk[12])); + ppk[4] += sbox(ppk[3] ^ join_bytes(tk[1], tk[0])) + 2*i; + ppk[0] += sbox(ppk[4] ^ join_bytes(tk[3], tk[2])); + ppk[1] += sbox(ppk[0] ^ join_bytes(tk[7], tk[6])); + ppk[2] += sbox(ppk[1] ^ join_bytes(tk[11], tk[10])); + ppk[3] += sbox(ppk[2] ^ join_bytes(tk[15], tk[14])); + ppk[4] += sbox(ppk[3] ^ join_bytes(tk[3], tk[2])) + 2*i + 1; + } + + // Phase 2, step 1 + ppk[5] = ppk[4] + join_bytes(pload[0], pload[2]); + + // Phase 2, step 2 + ppk[0] += sbox(ppk[5] ^ join_bytes(tk[1], tk[0])); + ppk[1] += sbox(ppk[0] ^ join_bytes(tk[3], tk[2])); + ppk[2] += sbox(ppk[1] ^ join_bytes(tk[5], tk[4])); + ppk[3] += sbox(ppk[2] ^ join_bytes(tk[7], tk[6])); + ppk[4] += sbox(ppk[3] ^ join_bytes(tk[9], tk[8])); + ppk[5] += sbox(ppk[4] ^ join_bytes(tk[11], tk[10])); + + ppk[0] += rotate(ppk[5] ^ join_bytes(tk[13], tk[12])); + ppk[1] += rotate(ppk[0] ^ join_bytes(tk[15], tk[14])); + ppk[2] += rotate(ppk[1]); + ppk[3] += rotate(ppk[2]); + ppk[4] += rotate(ppk[3]); + ppk[5] += rotate(ppk[4]); + + // Phase 2, step 3 + rc4_key[0] = upper_byte(join_bytes(pload[0], pload[2])); + rc4_key[1] = (rc4_key[0] | 0x20) & 0x7f; + rc4_key[2] = lower_byte(join_bytes(pload[0], pload[2])); + rc4_key[3] = lower_byte((ppk[5] ^ join_bytes(tk[1], tk[0])) >> 1); + rc4_key[4] = lower_byte(ppk[0]); + rc4_key[5] = upper_byte(ppk[0]); + rc4_key[6] = lower_byte(ppk[1]); + rc4_key[7] = upper_byte(ppk[1]); + rc4_key[8] = lower_byte(ppk[2]); + rc4_key[9] = upper_byte(ppk[2]); + rc4_key[10] = lower_byte(ppk[3]); + rc4_key[11] = upper_byte(ppk[3]); + rc4_key[12] = lower_byte(ppk[4]); + rc4_key[13] = upper_byte(ppk[4]); + rc4_key[14] = lower_byte(ppk[5]); + rc4_key[15] = upper_byte(ppk[5]); + } + return RC4Key(rc4_key.begin(), rc4_key.end()); +} + +SNAP *SessionKeys::tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const { + Crypto::RC4Key key = generate_rc4_key(dot11, raw); + RawPDU::payload_type &pload = raw.payload(); + rc4(pload.begin() + 8, pload.end(), key, pload.begin()); + + uint32_t crc = Utils::crc32(&pload[0], pload.size() - 12); + if(pload[pload.size() - 12] != (crc & 0xff) || + pload[pload.size() - 11] != ((crc >> 8) & 0xff) || + pload[pload.size() - 10] != ((crc >> 16) & 0xff) || + pload[pload.size() - 9] != ((crc >> 24) & 0xff)) + return 0; + + return new SNAP(&pload[0], pload.size() - 20); +} + +SNAP *SessionKeys::SessionKeys::decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const { + return is_ccmp ? + ccmp_decrypt_unicast(dot11, raw) : + tkip_decrypt_unicast(dot11, raw); +} + // supplicant_data SupplicantData::SupplicantData(const std::string &psk, const std::string &ssid) { @@ -268,7 +457,7 @@ void WPA2Decrypter::try_add_keys(const Dot11Data &dot11, const RSNHandshake &hs) if(it != aps.end()) { addr_pair addr_p = extract_addr_pair(dot11); try { - keys.insert(std::make_pair(addr_p, WPA2::CCMPSessionKeys(hs, it->second.pmk()))); + keys.insert(std::make_pair(addr_p, WPA2::SessionKeys(hs, it->second.pmk()))); } catch(WPA2::invalid_handshake&) { } } diff --git a/tests/src/wpa2_decrypt.cpp b/tests/src/wpa2_decrypt.cpp index 2b14da2..e8e81c8 100644 --- a/tests/src/wpa2_decrypt.cpp +++ b/tests/src/wpa2_decrypt.cpp @@ -5,21 +5,26 @@ #include "crypto.h" #include "radiotap.h" #include "udp.h" +#include "tcp.h" using namespace Tins; class WPA2DecryptTest : public testing::Test { public: - static const uint8_t packets[7][652]; - static const size_t packets_size[]; + static const uint8_t ccmp_packets[7][652]; + static const uint8_t tkip_packets[7][211]; + static const size_t ccmp_packets_size[], tkip_packets_size[]; - void check_packet5(const PDU &pdu); - void check_packet6(const PDU &pdu); + void check_ccmp_packet5(const PDU &pdu); + void check_ccmp_packet6(const PDU &pdu); + + void check_tkip_packet5(const PDU &pdu); + void check_tkip_packet6(const PDU &pdu); }; // packet taken from aircrack's site. -const uint8_t WPA2DecryptTest::packets[7][652] = { +const uint8_t WPA2DecryptTest::ccmp_packets[7][652] = { // Beacon {0, 0, 24, 0, 142, 88, 0, 0, 16, 2, 108, 9, 160, 0, 96, 0, 0, 42, 0, 0, 71, 123, 147, 9, 128, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 12, 65, 130, 178, 85, 0, 12, 65, 130, 178, 85, 128, 252, 134, 225, 42, 28, 1, 0, 0, 0, 100, 0, 17, 4, 0, 7, 67, 111, 104, 101, 114, 101, 114, 1, 8, 130, 132, 139, 150, 36, 48, 72, 108, 3, 1, 1, 5, 4, 0, 1, 0, 0, 42, 1, 2, 47, 1, 2, 48, 24, 1, 0, 0, 15, 172, 2, 2, 0, 0, 15, 172, 4, 0, 15, 172, 2, 1, 0, 0, 15, 172, 2, 0, 0, 50, 4, 12, 18, 24, 96, 221, 6, 0, 16, 24, 2, 0, 4, 221, 28, 0, 80, 242, 1, 1, 0, 0, 80, 242, 2, 2, 0, 0, 80, 242, 4, 0, 80, 242, 2, 1, 0, 0, 80, 242, 2, 0, 0, 71, 123, 147, 9}, // EAPOL keys @@ -33,52 +38,179 @@ const uint8_t WPA2DecryptTest::packets[7][652] = { {0, 0, 24, 0, 142, 88, 0, 0, 16, 108, 108, 9, 192, 0, 100, 0, 0, 41, 0, 0, 190, 202, 53, 174, 8, 66, 44, 0, 0, 13, 147, 130, 54, 58, 0, 12, 65, 130, 178, 85, 0, 12, 65, 130, 178, 83, 240, 252, 1, 0, 0, 32, 0, 0, 0, 0, 119, 49, 71, 116, 105, 136, 85, 205, 132, 196, 180, 119, 142, 132, 254, 142, 107, 185, 34, 64, 127, 182, 129, 59, 98, 183, 207, 159, 167, 27, 149, 169, 74, 170, 255, 149, 57, 187, 223, 19, 162, 165, 18, 63, 50, 153, 100, 9, 247, 29, 231, 199, 141, 125, 148, 9, 183, 62, 244, 101, 50, 254, 146, 237, 122, 204, 152, 151, 197, 153, 31, 122, 219, 59, 230, 26, 123, 231, 100, 31, 201, 119, 175, 228, 12, 189, 233, 235, 65, 148, 46, 143, 49, 144, 44, 76, 79, 143, 126, 163, 219, 81, 122, 250, 102, 252, 179, 97, 116, 151, 128, 138, 29, 29, 171, 64, 93, 233, 245, 44, 35, 244, 249, 140, 160, 198, 188, 44, 120, 38, 104, 52, 107, 70, 115, 34, 239, 117, 195, 195, 20, 193, 85, 224, 22, 142, 205, 27, 155, 34, 62, 19, 32, 199, 200, 3, 59, 253, 188, 180, 177, 41, 150, 247, 98, 199, 127, 43, 239, 236, 116, 51, 19, 185, 188, 97, 156, 151, 64, 144, 20, 103, 61, 23, 210, 236, 235, 23, 216, 116, 121, 14, 191, 150, 210, 255, 195, 230, 167, 53, 254, 207, 35, 28, 18, 209, 240, 112, 156, 181, 151, 30, 81, 215, 6, 225, 106, 153, 48, 91, 102, 171, 115, 62, 46, 70, 255, 39, 183, 219, 199, 73, 97, 127, 92, 18, 153, 206, 150, 200, 7, 153, 82, 151, 34, 170, 177, 94, 178, 149, 202, 164, 210, 176, 112, 106, 73, 213, 101, 14, 195, 115, 168, 153, 217, 52, 76, 130, 116, 159, 226, 247, 234, 238, 6, 250, 141, 149, 133, 208, 40, 106, 172, 130, 187, 114, 216, 250, 124, 47, 4, 227, 198, 97, 125, 69, 2, 219, 87, 123, 79, 150, 116, 187, 239, 120, 236, 199, 185, 96, 30, 112, 233, 237, 179, 28, 46, 149, 102, 253, 150, 133, 179, 71, 7, 119, 201, 39, 196, 106, 251, 100, 195, 201, 47, 109, 227, 158, 27, 70, 207, 241, 222, 179, 225, 220, 189, 224, 97, 134, 11, 150, 127, 235, 224, 222, 110, 141, 224, 0, 167, 126, 72, 155, 185, 162, 128, 141, 120, 39, 165, 5, 211, 222, 20, 11, 129, 222, 142, 149, 130, 136, 106, 105, 118, 135, 9, 220, 180, 196, 117, 66, 82, 215, 186, 107, 252, 85, 41, 131, 238, 85, 233, 197, 228, 157, 49, 42, 57, 52, 40, 235, 240, 208, 248, 180, 26, 153, 227, 223, 33, 247, 236, 162, 226, 253, 63, 144, 199, 157, 164, 56, 185, 19, 8, 197, 210, 129, 90, 177, 16, 119, 165, 208, 244, 247, 253, 121, 10, 51, 15, 215, 140, 231, 51, 198, 168, 11, 54, 126, 135, 145, 13, 161, 192, 119, 16, 184, 30, 235, 23, 133, 20, 247, 139, 30, 235, 110, 211, 13, 39, 76, 4, 153, 83, 236, 215, 52, 107, 75, 188, 73, 74, 60, 203, 80, 194, 127, 7, 65, 225, 195, 139, 166, 176, 22, 151, 54, 204, 159, 5, 254, 82, 145, 230, 163, 254, 191, 206, 29, 198, 78, 198, 232, 238, 247, 104, 245, 100, 67, 108, 90, 88, 177, 136, 32, 28, 76, 108, 195, 172, 251, 121, 158, 23, 52, 33, 118, 205, 239, 50, 163, 118, 65, 150, 69, 109, 152, 70, 31, 235, 102, 126, 254, 209, 228, 148, 203, 137, 34, 20, 69, 141, 180, 177, 154, 155, 35, 101, 1, 78, 207, 67, 117, 29, 104, 9, 244, 3, 220, 131, 61, 190, 202, 53, 174} }; -const size_t WPA2DecryptTest::packets_size[] = { +const uint8_t WPA2DecryptTest::tkip_packets[7][211] = { + // Beacon + {0, 0, 18, 0, 46, 72, 0, 0, 0, 2, 108, 9, 160, 0, 221, 3, 0, 0, 128, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 27, 17, 210, 27, 235, 0, 27, 17, 210, 27, 235, 128, 178, 129, 97, 244, 15, 0, 0, 0, 0, 100, 0, 17, 0, 0, 4, 78, 79, 68, 79, 1, 4, 130, 132, 139, 150, 3, 1, 1, 5, 4, 0, 1, 0, 0, 48, 20, 1, 0, 0, 15, 172, 2, 1, 0, 0, 15, 172, 2, 1, 0, 0, 15, 172, 2, 0, 0, 221, 9, 0, 3, 127, 1, 1, 0, 32, 255, 127}, + // EAPOL keys + {0, 0, 18, 0, 46, 72, 0, 0, 0, 22, 108, 9, 160, 0, 220, 3, 0, 0, 8, 2, 212, 0, 148, 12, 109, 143, 147, 136, 0, 27, 17, 210, 27, 235, 0, 27, 17, 210, 27, 235, 208, 178, 170, 170, 3, 0, 0, 0, 136, 142, 1, 3, 0, 95, 2, 0, 137, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 22, 241, 158, 216, 151, 86, 157, 129, 160, 33, 116, 210, 24, 191, 213, 40, 130, 92, 75, 22, 151, 22, 95, 91, 248, 168, 188, 129, 250, 161, 255, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 18, 0, 46, 72, 0, 0, 0, 4, 108, 9, 160, 0, 217, 3, 0, 0, 8, 1, 2, 1, 0, 27, 17, 210, 27, 235, 148, 12, 109, 143, 147, 136, 0, 27, 17, 210, 27, 235, 16, 0, 170, 170, 3, 0, 0, 0, 136, 142, 1, 3, 0, 117, 2, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 218, 108, 51, 136, 69, 196, 171, 10, 209, 139, 6, 156, 170, 155, 110, 241, 223, 96, 73, 83, 201, 28, 222, 131, 70, 209, 158, 97, 95, 244, 21, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 47, 4, 90, 85, 130, 65, 3, 66, 245, 143, 64, 146, 174, 5, 207, 0, 22, 48, 20, 1, 0, 0, 15, 172, 2, 1, 0, 0, 15, 172, 2, 1, 0, 0, 15, 172, 2, 0, 0}, + {0, 0, 18, 0, 46, 72, 0, 0, 0, 11, 108, 9, 160, 0, 221, 3, 0, 0, 8, 2, 222, 0, 148, 12, 109, 143, 147, 136, 0, 27, 17, 210, 27, 235, 0, 27, 17, 210, 27, 235, 224, 178, 170, 170, 3, 0, 0, 0, 136, 142, 1, 3, 0, 157, 2, 19, 201, 0, 32, 0, 0, 0, 0, 0, 0, 0, 2, 22, 241, 158, 216, 151, 86, 157, 129, 160, 33, 116, 210, 24, 191, 213, 40, 130, 92, 75, 22, 151, 22, 95, 91, 248, 168, 188, 129, 250, 161, 255, 151, 130, 92, 75, 22, 151, 22, 95, 91, 248, 168, 188, 129, 250, 161, 255, 152, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 127, 245, 65, 126, 225, 15, 125, 92, 194, 78, 120, 25, 55, 127, 161, 0, 62, 177, 70, 196, 230, 213, 190, 41, 84, 138, 229, 131, 21, 227, 143, 239, 152, 60, 170, 35, 101, 197, 230, 223, 109, 20, 24, 167, 6, 69, 155, 148, 212, 94, 203, 228, 45, 8, 69, 76, 47, 148, 124, 147, 146, 141, 231, 60, 11, 189, 254, 170, 106, 73, 190, 229, 99, 202, 247, 41, 133, 130, 175}, + {0, 0, 18, 0, 46, 72, 0, 0, 0, 4, 108, 9, 160, 0, 218, 3, 0, 0, 8, 1, 2, 1, 0, 27, 17, 210, 27, 235, 148, 12, 109, 143, 147, 136, 0, 27, 17, 210, 27, 235, 32, 0, 170, 170, 3, 0, 0, 0, 136, 142, 1, 3, 0, 95, 2, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 109, 5, 166, 193, 94, 143, 159, 84, 66, 114, 244, 166, 240, 46, 1, 0, 0}, + // HTTP data + {0, 0, 18, 0, 46, 72, 0, 0, 0, 22, 108, 9, 160, 0, 217, 3, 0, 0, 8, 65, 213, 0, 0, 27, 17, 210, 27, 235, 148, 12, 109, 143, 147, 136, 0, 27, 17, 210, 27, 235, 176, 50, 3, 35, 41, 32, 0, 0, 0, 0, 119, 117, 235, 153, 200, 251, 227, 211, 149, 31, 231, 139, 36, 2, 146, 81, 132, 63, 193, 42, 220, 53, 70, 104, 119, 139, 60, 76, 204, 96, 218, 54, 101, 218, 192, 111, 144, 148, 97, 141, 252, 180, 201, 214, 206, 191, 242, 102, 114, 76, 237, 61, 190, 167, 5, 132, 128, 149, 38, 88, 155, 242, 191, 244, 202, 206, 175, 80, 15, 124, 44, 108, 39, 224, 72, 217, 38, 175, 70, 187, 224, 215, 21, 143}, + {0, 0, 18, 0, 46, 72, 0, 0, 0, 22, 108, 9, 160, 0, 218, 3, 0, 0, 8, 65, 213, 0, 0, 27, 17, 210, 27, 235, 148, 12, 109, 143, 147, 136, 0, 27, 17, 210, 27, 235, 192, 50, 3, 35, 42, 32, 0, 0, 0, 0, 168, 193, 175, 225, 65, 44, 37, 61, 12, 214, 29, 41, 12, 133, 137, 107, 94, 99, 138, 118, 238, 219, 83, 108, 25, 181, 195, 163, 47, 193, 177, 2, 53, 152, 111, 13, 169, 165, 84, 127, 163, 139, 194, 120, 242, 195, 144, 28, 13, 162, 53, 143, 220, 86, 40, 217, 222, 38, 69, 206, 184, 38, 125, 79, 210, 85, 1, 129, 2, 190, 26, 109, 243, 227, 75, 176, 160, 86, 158, 124, 41, 153, 11, 0} +}; + +const size_t WPA2DecryptTest::ccmp_packets_size[] = { 168, 181, 181, 239, 159, 404, 652 }; -void WPA2DecryptTest::check_packet5(const PDU &pdu) { +const size_t WPA2DecryptTest::tkip_packets_size[] = { + 108, 149, 171, 211, 149, 134, 134 +}; + +void WPA2DecryptTest::check_ccmp_packet5(const PDU &pdu) { const UDP *udp = pdu.find_pdu(); ASSERT_TRUE(udp); EXPECT_EQ(udp->sport(), 68); EXPECT_EQ(udp->dport(), 67); } -void WPA2DecryptTest::check_packet6(const PDU &pdu) { +void WPA2DecryptTest::check_ccmp_packet6(const PDU &pdu) { const UDP *udp = pdu.find_pdu(); ASSERT_TRUE(udp); EXPECT_EQ(udp->sport(), 67); EXPECT_EQ(udp->dport(), 68); } -TEST_F(WPA2DecryptTest, DecryptUsingBeacon) { +void WPA2DecryptTest::check_tkip_packet5(const PDU &pdu) { + const TCP *tcp = pdu.find_pdu(); + ASSERT_TRUE(tcp); + EXPECT_EQ(tcp->sport(), 44934); + EXPECT_EQ(tcp->dport(), 80); + EXPECT_EQ(tcp->window(), 1215); +} + +void WPA2DecryptTest::check_tkip_packet6(const PDU &pdu) { + const TCP *tcp = pdu.find_pdu(); + ASSERT_TRUE(tcp); + EXPECT_EQ(tcp->sport(), 44934); + EXPECT_EQ(tcp->dport(), 80); + EXPECT_EQ(tcp->window(), 1204); +} + +TEST_F(WPA2DecryptTest, DecryptCCMPUsingBeacon) { Crypto::WPA2Decrypter decrypter; decrypter.add_supplicant_data("Induction", "Coherer"); for(size_t i = 0; i < 7; ++i) { - RadioTap radio(packets[i], packets_size[i]); + RadioTap radio(ccmp_packets[i], ccmp_packets_size[i]); if(i > 4) { ASSERT_TRUE(decrypter.decrypt(radio)); if(i == 5) - check_packet5(radio); + check_ccmp_packet5(radio); else - check_packet6(radio); + check_ccmp_packet6(radio); } else ASSERT_FALSE(decrypter.decrypt(radio)); } } -TEST_F(WPA2DecryptTest, DecryptWithoutUsingBeacon) { +TEST_F(WPA2DecryptTest, DecryptCCMPWithoutUsingBeacon) { Crypto::WPA2Decrypter decrypter; decrypter.add_supplicant_data("Induction", "Coherer", "00:0c:41:82:b2:55"); for(size_t i = 1; i < 7; ++i) { - RadioTap radio(packets[i], packets_size[i]); + RadioTap radio(ccmp_packets[i], ccmp_packets_size[i]); if(i > 4) { ASSERT_TRUE(decrypter.decrypt(radio)); if(i == 5) - check_packet5(radio); + check_ccmp_packet5(radio); else - check_packet6(radio); + check_ccmp_packet6(radio); + } + else + ASSERT_FALSE(decrypter.decrypt(radio)); + } +} + +TEST_F(WPA2DecryptTest, DecryptTKIPUsingBeacon) { + Crypto::WPA2Decrypter decrypter; + decrypter.add_supplicant_data("libtinstest", "NODO"); + for(size_t i = 0; i < 7; ++i) { + RadioTap radio(tkip_packets[i], tkip_packets_size[i]); + if(i > 4) { + ASSERT_TRUE(decrypter.decrypt(radio)); + if(i == 5) + check_tkip_packet5(radio); + else + check_tkip_packet6(radio); + } + else + ASSERT_FALSE(decrypter.decrypt(radio)); + } +} + +TEST_F(WPA2DecryptTest, DecryptTKIPWithoutUsingBeacon) { + Crypto::WPA2Decrypter decrypter; + decrypter.add_supplicant_data("libtinstest", "NODO", "00:1b:11:d2:1b:eb"); + for(size_t i = 1; i < 7; ++i) { + RadioTap radio(tkip_packets[i], tkip_packets_size[i]); + if(i > 4) { + ASSERT_TRUE(decrypter.decrypt(radio)); + if(i == 5) + check_tkip_packet5(radio); + else + check_tkip_packet6(radio); + } + else + ASSERT_FALSE(decrypter.decrypt(radio)); + } +} + +TEST_F(WPA2DecryptTest, DecryptCCMPAndTKIPUsingBeacon) { + Crypto::WPA2Decrypter decrypter; + decrypter.add_supplicant_data("libtinstest", "NODO"); + decrypter.add_supplicant_data("Induction", "Coherer"); + for(size_t i = 0; i < 7; ++i) { + RadioTap radio(ccmp_packets[i], ccmp_packets_size[i]); + if(i > 4) { + ASSERT_TRUE(decrypter.decrypt(radio)); + if(i == 5) + check_ccmp_packet5(radio); + else + check_ccmp_packet6(radio); + } + else + ASSERT_FALSE(decrypter.decrypt(radio)); + } + for(size_t i = 0; i < 7; ++i) { + RadioTap radio(tkip_packets[i], tkip_packets_size[i]); + if(i > 4) { + ASSERT_TRUE(decrypter.decrypt(radio)); + if(i == 5) + check_tkip_packet5(radio); + else + check_tkip_packet6(radio); + } + else + ASSERT_FALSE(decrypter.decrypt(radio)); + } +} + +TEST_F(WPA2DecryptTest, DecryptCCMPAndTKIPWithoutUsingBeacon) { + Crypto::WPA2Decrypter decrypter; + decrypter.add_supplicant_data("libtinstest", "NODO", "00:1b:11:d2:1b:eb"); + decrypter.add_supplicant_data("Induction", "Coherer", "00:0c:41:82:b2:55"); + for(size_t i = 1; i < 7; ++i) { + RadioTap radio(ccmp_packets[i], ccmp_packets_size[i]); + if(i > 4) { + ASSERT_TRUE(decrypter.decrypt(radio)); + if(i == 5) + check_ccmp_packet5(radio); + else + check_ccmp_packet6(radio); + } + else + ASSERT_FALSE(decrypter.decrypt(radio)); + } + for(size_t i = 1; i < 7; ++i) { + RadioTap radio(tkip_packets[i], tkip_packets_size[i]); + if(i > 4) { + ASSERT_TRUE(decrypter.decrypt(radio)); + if(i == 5) + check_tkip_packet5(radio); + else + check_tkip_packet6(radio); } else ASSERT_FALSE(decrypter.decrypt(radio));