From b7ea98953041c984e8555f45380f0845a234c805 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Thu, 18 Oct 2012 23:22:42 -0300 Subject: [PATCH] Added several tests for EAPOL. Now both RadioTap and EAPOL work on big endian architectures. --- Makefile.in | 2 +- include/eapol.h | 185 ++++++++++++++++++++++++++++++++--- include/radiotap.h | 44 ++++++--- include/rsn_information.h | 10 ++ src/dot11.cpp | 1 - src/eapol.cpp | 87 ++++++++++++----- src/radiotap.cpp | 10 +- src/rsn_information.cpp | 33 +++++-- tests/Makefile.in | 2 +- tests/depends.d | 31 ++++-- tests/src/radiotap.cpp | 10 +- tests/src/rsn_eapol.cpp | 200 ++++++++++++++++++++++++++++++++++++++ tests/src/wep_decrypt.cpp | 1 - 13 files changed, 538 insertions(+), 78 deletions(-) create mode 100644 tests/src/rsn_eapol.cpp diff --git a/Makefile.in b/Makefile.in index ab30ddf..290628e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -14,7 +14,7 @@ compile: $(OBJECTS) recompile: clean all -depends: $(SOURCES) $(DEPS) +depends: $(SOURCES) rm -f ./depends.d make do_make_deps diff --git a/include/eapol.h b/include/eapol.h index e2176b4..026708a 100644 --- a/include/eapol.h +++ b/include/eapol.h @@ -368,7 +368,32 @@ namespace Tins { * \brief This PDU's flag. */ static const PDU::PDUType pdu_flag = PDU::RSNEAPOL; + + /** + * The length of the key IV field + */ + static const size_t key_iv_size = 16; + + /** + * The length of the nonce field + */ + static const size_t nonce_size = 32; + /** + * The length of the mic field + */ + static const size_t mic_size = 16; + + /** + * The length of the rsc field + */ + static const size_t rsc_size = 8; + + /** + * The length of the id field + */ + static const size_t id_size = 8; + /** * \brief Creates an instance of RSNEAPOL. */ @@ -411,13 +436,13 @@ namespace Tins { * \brief Getter for the rsc field. * \return The rsc field. */ - uint64_t rsc() const { return Endian::be_to_host(_header.rsc); } + const uint8_t *rsc() const { return _header.rsc; } /** * \brief Getter for the id field. * \return The id field. */ - uint64_t id() const { return Endian::be_to_host(_header.id); } + const uint8_t *id() const { return _header.id; } /** * \brief Getter for the mic field. @@ -437,6 +462,66 @@ namespace Tins { */ const key_type &key() const { return _key; } + /** + * \brief Getter for the key_mic field. + * \return The key_mic field. + */ + small_uint<1> key_mic() const { return _header.key_mic; }; + + /** + * \brief Getter for the secure field. + * \return The secure field. + */ + small_uint<1> secure() const { return _header.secure; }; + + /** + * \brief Getter for the error field. + * \return The error field. + */ + small_uint<1> error() const { return _header.error; }; + + /** + * \brief Getter for the request field. + * \return The request field. + */ + small_uint<1> request() const { return _header.request; }; + + /** + * \brief Getter for the encrypted field. + * \return The encrypted field. + */ + small_uint<1 > encrypted() const { return _header.encrypted; }; + + /** + * \brief Getter for the key_descriptor field. + * \return The key_descriptor field. + */ + small_uint<3> key_descriptor() const { return _header.key_descriptor; }; + + /** + * \brief Getter for the key_t field. + * \return The key_t field. + */ + small_uint<1> key_t() const { return _header.key_t; }; + + /** + * \brief Getter for the key_index field. + * \return The key_index field. + */ + small_uint<2> key_index() const { return _header.key_index; }; + + /** + * \brief Getter for the install field. + * \return The install field. + */ + small_uint<1> install() const { return _header.install; }; + + /** + * \brief Getter for the key_ack field. + * \return The key_ack field. + */ + small_uint<1> key_ack() const { return _header.key_ack; }; + /** * \brief Returns the header size. * @@ -459,7 +544,7 @@ namespace Tins { * \brief Sets the replay counter field. * \param new_replay_counter The new replay counter to be set. */ - void replay_counter(uint16_t new_replay_counter); + void replay_counter(uint64_t new_replay_counter); /** * \brief Sets the key IV field. @@ -480,13 +565,13 @@ namespace Tins { * \brief Sets the rsc field. * \param new_rsc The new rsc to be set. */ - void rsc(uint64_t new_rsc); + void rsc(const uint8_t *new_rsc); /** * \brief Sets the id field. * \param new_id The new id to be set. */ - void id(uint64_t new_id); + void id(const uint8_t *new_id); /** * \brief Sets the mic field. @@ -510,14 +595,64 @@ namespace Tins { void key(const key_type &new_key); /** - * \brief Sets RSN information for this EAPOL PDU. - * - * This method copies the RSN information and copies it in the - * key field. Therefore, if a key has been set, this will remove it. - * \param rsn The RSN information to be set. - * \sa RSNInformation. + * \brief Setter for the key_mic field. + * \param new_key_mic The new to be set. */ - void rsn_information(const RSNInformation &rsn); + void key_mic(small_uint<1> new_key_mic); + + /** + * \brief Setter for the secure field. + * \param new_secure The new to be set. + */ + void secure(small_uint<1> new_secure); + + /** + * \brief Setter for the error field. + * \param new_error The new to be set. + */ + void error(small_uint<1> new_error); + + /** + * \brief Setter for the request field. + * \param new_request The new to be set. + */ + void request(small_uint<1> new_request); + + /** + * \brief Setter for the encrypted field. + * \param new_encrypted The new to be set. + */ + void encrypted(small_uint<1 > new_encrypted); + + /** + * \brief Setter for the key_descriptor field. + * \param new_key_descriptor The new to be set. + */ + void key_descriptor(small_uint<3> new_key_descriptor); + + /** + * \brief Setter for the key_t field. + * \param new_key_t The new to be set. + */ + void key_t(small_uint<1> new_key_t); + + /** + * \brief Setter for the key_index field. + * \param new_key_index The new to be set. + */ + void key_index(small_uint<2> new_key_index); + + /** + * \brief Setter for the install field. + * \param new_install The new to be set. + */ + void install(small_uint<1> new_install); + + /** + * \brief Setter for the key_ack field. + * \param new_key_ack The new to be set. + */ + void key_ack(small_uint<1> new_key_ack); /** * \brief Getter for the PDU's type. @@ -544,6 +679,7 @@ namespace Tins { } private: struct rsnhdr { + #if TINS_IS_LITTLE_ENDIAN uint16_t key_mic:1, secure:1, error:1, @@ -557,10 +693,29 @@ namespace Tins { key_ack:1; uint16_t key_length; uint64_t replay_counter; - uint8_t nonce[32], key_iv[16]; - uint64_t rsc, id; - uint8_t mic[16]; + uint8_t nonce[nonce_size], key_iv[key_iv_size]; + uint8_t rsc[rsc_size], id[id_size]; + uint8_t mic[mic_size]; uint16_t wpa_length; + #else + uint16_t reserved:3, + encrypted:1, + request:1, + error:1, + secure:1, + key_mic:1, + key_ack:1, + install:1, + key_index:2, + key_t:1, + key_descriptor:3; + uint16_t key_length; + uint64_t replay_counter; + uint8_t nonce[nonce_size], key_iv[key_iv_size]; + uint8_t rsc[rsc_size], id[id_size]; + uint8_t mic[mic_size]; + uint16_t wpa_length; + #endif } __attribute__((__packed__)); void write_body(uint8_t *buffer, uint32_t total_sz); diff --git a/include/radiotap.h b/include/radiotap.h index b7feeb5..a6226a4 100644 --- a/include/radiotap.h +++ b/include/radiotap.h @@ -96,23 +96,14 @@ namespace Tins { * \brief Flags used in the RadioTap::flags() method. */ enum FrameFlags { - #if TINS_IS_LITTLE_ENDIAN CFP = 1, PREAMBLE = 2, WEP = 4, FRAGMENTATION = 8, FCS = 16, PADDING = 32, - FAILED_FCS = 64 - #else - CFP = 64, - PREAMBLE = 32, - WEP = 16, - FRAGMENTATION = 8, - FCS = 4, - PADDING = 2, - FAILED_FCS = 1 - #endif + FAILED_FCS = 64, + SHORT_GI = 128 }; /** @@ -154,7 +145,7 @@ namespace Tins { * \brief Setter for the length field. * \param new_length The new length. */ - void length(uint8_t new_length); + void length(uint16_t new_length); /** * \brief Setter for the TSFT field. @@ -223,7 +214,7 @@ namespace Tins { * \brief Getter for the length field. * \return The length field. */ - uint8_t length() const { return _radio.it_len; } + uint16_t length() const { return Endian::le_to_host(_radio.it_len); } /** * \brief Getter for the tsft field. @@ -324,6 +315,7 @@ namespace Tins { PDUType pdu_type() const { return PDU::RADIOTAP; } private: struct radiotap_hdr { + #if TINS_IS_LITTLE_ENDIAN uint8_t it_version; uint8_t it_pad; uint16_t it_len; @@ -346,6 +338,32 @@ namespace Tins { channel_plus:1, reserved2:12, ext:1; + #else + uint8_t it_pad; + uint8_t it_version; + uint16_t it_len; + uint32_t lock_quality:1, + dbm_noise:1, + dbm_signal:1, + fhss:1, + channel:1, + rate:1, + flags:1, + tsft:1, + reserved3:1, + tx_attenuation:1, + db_tx_attenuation:1, + dbm_tx_attenuation:1, + antenna:1, + db_signal:1, + db_noise:1, + rx_flags:1, + reserved2:5, + channel_plus:1, + reserved1:2, + reserved4:7, + ext:1; + #endif } __attribute__((__packed__)); void init(); diff --git a/include/rsn_information.h b/include/rsn_information.h index 7b4e7d5..eb7c80d 100644 --- a/include/rsn_information.h +++ b/include/rsn_information.h @@ -80,6 +80,14 @@ namespace Tins{ */ RSNInformation(); + /** + * \brief Creates an instance of RSNInformation from a + * serialization_type object. + * + * \param buffer The buffer from which to construct this object. + */ + RSNInformation(const serialization_type &buffer); + /** * \brief Constructor from buffer. * @@ -163,6 +171,8 @@ namespace Tins{ */ serialization_type serialize() const; private: + void init(const uint8_t *buffer, uint32_t total_sz); + uint16_t _version, _capabilities; CypherSuites _group_suite; akm_type _akm_cyphers; diff --git a/src/dot11.cpp b/src/dot11.cpp index 344e901..43d41ca 100644 --- a/src/dot11.cpp +++ b/src/dot11.cpp @@ -39,7 +39,6 @@ #endif #include "dot11.h" #include "rawpdu.h" -#include "radiotap.h" #include "rsn_information.h" #include "packet_sender.h" #include "snap.h" diff --git a/src/eapol.cpp b/src/eapol.cpp index e6e2e6a..8060ec5 100644 --- a/src/eapol.cpp +++ b/src/eapol.cpp @@ -90,8 +90,8 @@ void EAPOL::type(uint8_t new_type) { void EAPOL::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) { uint32_t sz = header_size(); assert(total_sz >= sz); - if(!_header.length) - length(sz - sizeof(_header.version) - sizeof(_header.length) - sizeof(_header.type)); + //if(!_header.length) + // length(sz - sizeof(_header.version) - sizeof(_header.length) - sizeof(_header.type)); std::memcpy(buffer, &_header, sizeof(_header)); write_body(buffer + sizeof(_header), total_sz - sizeof(_header)); } @@ -132,7 +132,7 @@ void RC4EAPOL::replay_counter(uint64_t new_replay_counter) { } void RC4EAPOL::key_iv(const uint8_t *new_key_iv) { - std::memcpy(_header.key_iv, new_key_iv, sizeof(_header.key_iv)); + std::copy(new_key_iv, new_key_iv + sizeof(_header.key_iv), _header.key_iv); } void RC4EAPOL::key_flag(small_uint<1> new_key_flag) { @@ -175,7 +175,7 @@ RSNEAPOL::RSNEAPOL() } RSNEAPOL::RSNEAPOL(const uint8_t *buffer, uint32_t total_sz) -: EAPOL(0x03, RSN) +: EAPOL(buffer, total_sz) { buffer += sizeof(eapolhdr); total_sz -= sizeof(eapolhdr); @@ -189,40 +189,84 @@ RSNEAPOL::RSNEAPOL(const uint8_t *buffer, uint32_t total_sz) } void RSNEAPOL::RSNEAPOL::nonce(const uint8_t *new_nonce) { - std::memcpy(_header.nonce, new_nonce, sizeof(_header.nonce)); + std::copy(new_nonce, new_nonce + nonce_size, _header.nonce); } -void RSNEAPOL::rsc(uint64_t new_rsc) { - _header.rsc = Endian::host_to_be(new_rsc); +void RSNEAPOL::rsc(const uint8_t *new_rsc) { + std::copy(new_rsc, new_rsc + rsc_size, _header.rsc); } -void RSNEAPOL::id(uint64_t new_id) { - _header.id = Endian::host_to_be(new_id); +void RSNEAPOL::id(const uint8_t *new_id) { + std::copy(new_id, new_id + id_size, _header.id); +} + +void RSNEAPOL::replay_counter(uint64_t new_replay_counter) { + _header.replay_counter = Endian::host_to_be(new_replay_counter); } void RSNEAPOL::mic(const uint8_t *new_mic) { - std::memcpy(_header.mic, new_mic, sizeof(_header.mic)); + std::copy(new_mic, new_mic + mic_size, _header.mic); } void RSNEAPOL::wpa_length(uint16_t new_wpa_length) { _header.wpa_length = Endian::host_to_be(new_wpa_length); } +void RSNEAPOL::key_iv(const uint8_t *new_key_iv) { + std::copy(new_key_iv, new_key_iv + sizeof(_header.key_iv), _header.key_iv); +} + +void RSNEAPOL::key_length(uint16_t new_key_length) { + _header.key_length = Endian::host_to_be(new_key_length); +} + void RSNEAPOL::key(const key_type &new_key) { _key = new_key; _header.key_t = 0; } -void RSNEAPOL::rsn_information(const RSNInformation &rsn) { - _key = rsn.serialize(); - _header.key_t = 1; +void RSNEAPOL::key_mic(small_uint<1> new_key_mic) { + _header.key_mic = new_key_mic; +} + +void RSNEAPOL::secure(small_uint<1> new_secure) { + _header.secure = new_secure; +} + +void RSNEAPOL::error(small_uint<1> new_error) { + _header.error = new_error; +} + +void RSNEAPOL::request(small_uint<1> new_request) { + _header.request = new_request; +} + +void RSNEAPOL::encrypted(small_uint<1 > new_encrypted) { + _header.encrypted = new_encrypted; +} + +void RSNEAPOL::key_descriptor(small_uint<3> new_key_descriptor) { + _header.key_descriptor = new_key_descriptor; +} + +void RSNEAPOL::key_t(small_uint<1> new_key_t) { + _header.key_t = new_key_t; +} + +void RSNEAPOL::key_index(small_uint<2> new_key_index) { + _header.key_index = new_key_index; +} + +void RSNEAPOL::install(small_uint<1> new_install) { + _header.install = new_install; +} + +void RSNEAPOL::key_ack(small_uint<1> new_key_ack) { + _header.key_ack = new_key_ack; } uint32_t RSNEAPOL::header_size() const { - uint32_t padding(0); - if(_header.key_t && _key.size()) - padding = 2; - return sizeof(eapolhdr) + sizeof(_header) + _key.size() + padding; + return sizeof(eapolhdr) + sizeof(_header) + _key.size(); } void RSNEAPOL::write_body(uint8_t *buffer, uint32_t total_sz) { @@ -234,18 +278,11 @@ void RSNEAPOL::write_body(uint8_t *buffer, uint32_t total_sz) { wpa_length(_key.size()); } else if(_key.size()) { - _header.key_length = 0; - wpa_length(_key.size() + 2); + wpa_length(_key.size()); } - else - wpa_length(0); } std::memcpy(buffer, &_header, sizeof(_header)); buffer += sizeof(_header); - if(_header.key_t && _key.size()) { - *(buffer++) = Dot11::RSN; - *(buffer++) = _key.size(); - } std::copy(_key.begin(), _key.end(), buffer); } } diff --git a/src/radiotap.cpp b/src/radiotap.cpp index ce8e023..e77dfd6 100644 --- a/src/radiotap.cpp +++ b/src/radiotap.cpp @@ -141,8 +141,8 @@ void RadioTap::padding(uint8_t new_padding) { _radio.it_pad = new_padding; } -void RadioTap::length(uint8_t new_length) { - _radio.it_len = new_length; +void RadioTap::length(uint16_t new_length) { + _radio.it_len = Endian::host_to_le(new_length); } void RadioTap::tsft(uint64_t new_tsft) { @@ -162,7 +162,7 @@ void RadioTap::rate(uint8_t new_rate) { void RadioTap::channel(uint16_t new_freq, uint16_t new_type) { _channel_freq = Endian::host_to_le(new_freq); - _channel_type = Endian::host_to_le(new_type); + _channel_type = Endian::host_to_le(new_type); _radio.channel = 1; } void RadioTap::dbm_signal(uint8_t new_dbm_signal) { @@ -309,6 +309,8 @@ void RadioTap::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU buffer += sizeof(_max_power); } if((_flags & 0x10) != 0 && inner_pdu()) - *(uint32_t*)(buffer + inner_pdu()->size()) = Utils::crc32(buffer, inner_pdu()->size()); + *(uint32_t*)(buffer + inner_pdu()->size()) = Endian::host_to_le( + Utils::crc32(buffer, inner_pdu()->size()) + ); } } diff --git a/src/rsn_information.cpp b/src/rsn_information.cpp index 9887a73..f730061 100644 --- a/src/rsn_information.cpp +++ b/src/rsn_information.cpp @@ -31,22 +31,41 @@ #include "rsn_information.h" namespace Tins { +template +void check_size(uint32_t total_sz, const char* err_msg) { + if(total_sz < sizeof(T)) + throw std::runtime_error(err_msg); +} + RSNInformation::RSNInformation() : _version(1), _capabilities(0) { } +RSNInformation::RSNInformation(const serialization_type &buffer) { + init(&buffer[0], buffer.size()); +} + RSNInformation::RSNInformation(const uint8_t *buffer, uint32_t total_sz) { + init(buffer, total_sz); +} + +void RSNInformation::init(const uint8_t *buffer, uint32_t total_sz) { const char *err_msg = "Malformed RSN information structure"; + check_size(total_sz, err_msg); version(Endian::le_to_host(*(uint16_t*)buffer)); buffer += sizeof(uint16_t); + total_sz -= sizeof(uint16_t); group_suite((RSNInformation::CypherSuites)*(uint32_t*)buffer); + + check_size(total_sz, err_msg); buffer += sizeof(uint32_t); + total_sz -= sizeof(uint32_t); + + check_size(total_sz, err_msg); - total_sz -= (sizeof(uint16_t) << 1) + sizeof(uint32_t); - if(total_sz < sizeof(uint16_t)) - throw std::runtime_error(err_msg); uint16_t count = *(uint16_t*)buffer; buffer += sizeof(uint16_t); + total_sz -= sizeof(uint16_t); if(count * sizeof(uint32_t) > total_sz) throw std::runtime_error(err_msg); total_sz -= count * sizeof(uint32_t); @@ -54,8 +73,8 @@ RSNInformation::RSNInformation(const uint8_t *buffer, uint32_t total_sz) { add_pairwise_cypher((RSNInformation::CypherSuites)*(uint32_t*)buffer); buffer += sizeof(uint32_t); } - if(total_sz < sizeof(uint16_t)) - throw std::runtime_error(err_msg); + check_size(total_sz, err_msg); + count = *(uint16_t*)buffer; buffer += sizeof(uint16_t); total_sz -= sizeof(uint16_t); @@ -66,8 +85,8 @@ RSNInformation::RSNInformation(const uint8_t *buffer, uint32_t total_sz) { add_akm_cypher((RSNInformation::AKMSuites)*(uint32_t*)buffer); buffer += sizeof(uint32_t); } - if(total_sz < sizeof(uint16_t)) - throw std::runtime_error(err_msg); + check_size(total_sz, err_msg); + capabilities(Endian::le_to_host(*(uint16_t*)buffer)); } diff --git a/tests/Makefile.in b/tests/Makefile.in index 4240be8..3c6bdf2 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -14,7 +14,7 @@ compile: $(OBJECTS) recompile: clean all -depends: $(SOURCES) $(DEPS) +depends: $(SOURCES) rm -f ./depends.d make do_make_deps diff --git a/tests/depends.d b/tests/depends.d index 89d68e7..08527d1 100644 --- a/tests/depends.d +++ b/tests/depends.d @@ -214,6 +214,26 @@ src/rc4eapol.o: src/rc4eapol.cpp ../include/eapol.h ../include/pdu.h \ ../include/ip_address.h: ../include/hw_address.h: +src/rsn_eapol.o: src/rsn_eapol.cpp ../include/eapol.h ../include/pdu.h \ + ../include/small_uint.h ../include/endianness.h ../include/utils.h \ + ../include/ip_address.h ../include/hw_address.h \ + ../include/rsn_information.h + +../include/eapol.h: + +../include/pdu.h: + +../include/small_uint.h: + +../include/endianness.h: + +../include/utils.h: + +../include/ip_address.h: + +../include/hw_address.h: + +../include/rsn_information.h: src/snap.o: src/snap.cpp ../include/snap.h ../include/pdu.h \ ../include/endianness.h ../include/small_uint.h ../include/utils.h \ ../include/ip_address.h ../include/hw_address.h @@ -319,7 +339,7 @@ src/wep_decrypt.o: src/wep_decrypt.cpp ../include/crypto.h \ ../include/hw_address.h ../include/small_uint.h ../include/pdu_option.h \ ../include/network_interface.h ../include/ip_address.h \ ../include/utils.h ../include/snap.h ../include/rawpdu.h \ - ../include/radiotap.h ../include/arp.h + ../include/arp.h ../include/crypto.h: @@ -345,8 +365,6 @@ src/wep_decrypt.o: src/wep_decrypt.cpp ../include/crypto.h \ ../include/rawpdu.h: -../include/radiotap.h: - ../include/arp.h: src/dot11/ack.o: src/dot11/ack.cpp ../include/dot11.h ../include/pdu.h \ ../include/endianness.h ../include/hw_address.h ../include/small_uint.h \ @@ -917,9 +935,8 @@ include/tests/dot11.h: ../src/dot11.o: ../src/dot11.cpp ../include/dot11.h ../include/pdu.h \ ../include/endianness.h ../include/hw_address.h ../include/small_uint.h \ ../include/pdu_option.h ../include/network_interface.h \ - ../include/ip_address.h ../include/rawpdu.h ../include/radiotap.h \ - ../include/rsn_information.h ../include/packet_sender.h \ - ../include/snap.h + ../include/ip_address.h ../include/rawpdu.h ../include/rsn_information.h \ + ../include/packet_sender.h ../include/snap.h ../include/dot11.h: @@ -939,8 +956,6 @@ include/tests/dot11.h: ../include/rawpdu.h: -../include/radiotap.h: - ../include/rsn_information.h: ../include/packet_sender.h: diff --git a/tests/src/radiotap.cpp b/tests/src/radiotap.cpp index 164d72a..951c872 100644 --- a/tests/src/radiotap.cpp +++ b/tests/src/radiotap.cpp @@ -15,7 +15,7 @@ public: const uint8_t RadioTapTest::expected_packet[] = { '\x00', '\x00', ' ', '\x00', 'g', '\x08', '\x04', '\x00', 'T', '\xc6', - '\xb8', '$', '\x00', '\x00', '\x00', '\x00', '"', '\x0c', '\xda', + '\xb8', '$', '\x00', '\x00', '\x00', '\x00', '\x10', '\x0c', '\xda', '\xa0', '\x02', '\x00', '\x00', '\x00', '@', '\x01', '\x00', '\x00', '<', '\x14', '$', '\x11', '\x80', '\x00', '\x00', '\x00', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\x06', '\x03', '\x7f', @@ -31,7 +31,8 @@ const uint8_t RadioTapTest::expected_packet[] = { '\x1e', '\x9d', '\x01', '\x1e', '\xa1', '\x01', '\x1e', '\xa5', '\x01', '\x1e', ' ', '\x01', '\x00', '\xdd', '\x18', '\x00', 'P', '\xf2', '\x02', '\x01', '\x01', '\x00', '\x00', '\x03', '\xa4', '\x00', '\x00', - '\'', '\xa4', '\x00', '\x00', 'B', 'C', '^', '\x00', 'b', '2', '/', '\x00' + '\'', '\xa4', '\x00', '\x00', 'B', 'C', '^', '\x00', 'b', '2', '/', '\x00', + '\xe5', '\x2d', '\x92', '\x11' }; TEST_F(RadioTapTest, DefaultConstructor) { @@ -48,6 +49,10 @@ TEST_F(RadioTapTest, DefaultConstructor) { TEST_F(RadioTapTest, ConstructorFromBuffer) { RadioTap radio(expected_packet, sizeof(expected_packet)); EXPECT_EQ(radio.version(), 0); + EXPECT_EQ(radio.length(), 32); + EXPECT_EQ(radio.rate(), 0xc); + EXPECT_EQ(radio.flags(), 0x10); + EXPECT_TRUE(radio.flags() & RadioTap::FCS); EXPECT_EQ(radio.channel_type(), 0x140); EXPECT_EQ(radio.tsft(), 616089172); EXPECT_EQ(radio.dbm_signal(), 0xda); @@ -60,6 +65,7 @@ TEST_F(RadioTapTest, Serialize) { RadioTap::serialization_type buffer = radio.serialize(); ASSERT_EQ(buffer.size(), sizeof(expected_packet)); + EXPECT_TRUE(std::equal(buffer.begin(), buffer.end(), expected_packet)); } diff --git a/tests/src/rsn_eapol.cpp b/tests/src/rsn_eapol.cpp new file mode 100644 index 0000000..b9a99c2 --- /dev/null +++ b/tests/src/rsn_eapol.cpp @@ -0,0 +1,200 @@ +#include +#include +#include +#include +#include "eapol.h" +#include "utils.h" +#include "rsn_information.h" + +using namespace std; +using namespace Tins; + +class RSNEAPOLTest : public testing::Test { +public: + static const uint8_t expected_packet[]; + + void test_equals(const RSNEAPOL &eapol1, const RSNEAPOL &eapol2); +}; + +uint8_t empty_iv[RSNEAPOL::key_iv_size] = { 0 }; + +const uint8_t nonce[RSNEAPOL::nonce_size] = { + '\xb9', 'o', '\xe7', '\xfa', '\xca', '[', '\'', '\xe2', 'M', '\x04', + '\xf1', '\xe6', 'l', '\x06', '\xe1', '\x9b', '\xb3', ':', 'k', '$', + '\xb4', '9', '\xbb', '\xe4', '\xde', '\xd9', '\n', '\xcc', '\xd1', + '3', '\x1e', '\x9e' +}; +const uint8_t mic[RSNEAPOL::mic_size] = { + '\xb1', '\xba', '\xac', 'U', '\x96', 'J', '\xbd', '0', 'V', + '\x85', 'e', '*', '\xb2', '&', 'u', '\x82' +}; +const uint8_t key[56] = { + '\xe2', '\xc5', 'O', 'G', '\xf3', '\x0e', '\xc9', '/', 'B', '\xd8', + '\xd5', '\x1e', '1', '\x9d', '\xf5', 'H', '`', 'm', 'N', '\xe3', + '\xd9', '\x84', '\xd3', 'C', 'Z', '\x15', '\xfc', 'X', '\x0f', + '>', 't', '`', '@', '\x91', '\x10', '`', '\xef', '\xb1', 'C', + '\xf8', '\xfd', '\xb6', '\n', '6', '\xcb', '\xa4', 'D', '\x98', + '&', '\x07', '\x1a', '\xff', '\x8b', '\x93', '\xd3', '.' +}; +const uint8_t rsc[RSNEAPOL::rsc_size] = { + '\xb1', '\x06' +}; +const uint8_t id[RSNEAPOL::id_size] = { + 0 +}; + +const uint8_t RSNEAPOLTest::expected_packet[] = { + '\x01', '\x03', '\x00', '\x97', '\x02', '\x13', '\xca', '\x00', + '\x10', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x02', '\xb9', 'o', '\xe7', '\xfa', '\xca', '[', '\'', '\xe2', 'M', + '\x04', '\xf1', '\xe6', 'l', '\x06', '\xe1', '\x9b', '\xb3', ':', + 'k', '$', '\xb4', '9', '\xbb', '\xe4', '\xde', '\xd9', '\n', '\xcc', + '\xd1', '3', '\x1e', '\x9e', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\xb1', '\x06', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\xb1', '\xba', '\xac', 'U', '\x96', 'J', '\xbd', '0', 'V', '\x85', + 'e', '*', '\xb2', '&', 'u', '\x82', '\x00', '8', '\xe2', '\xc5', 'O', + 'G', '\xf3', '\x0e', '\xc9', '/', 'B', '\xd8', '\xd5', '\x1e', '1', + '\x9d', '\xf5', 'H', '`', 'm', 'N', '\xe3', '\xd9', '\x84', '\xd3', + 'C', 'Z', '\x15', '\xfc', 'X', '\x0f', '>', 't', '`', '@', '\x91', + '\x10', '`', '\xef', '\xb1', 'C', '\xf8', '\xfd', '\xb6', '\n', '6', + '\xcb', '\xa4', 'D', '\x98', '&', '\x07', '\x1a', '\xff', '\x8b', + '\x93', '\xd3', '.' +}; + +void RSNEAPOLTest::test_equals(const RSNEAPOL &eapol1, const RSNEAPOL &eapol2) { + EXPECT_EQ(eapol1.version(), eapol2.version()); + EXPECT_EQ(eapol1.packet_type(), eapol2.packet_type()); + EXPECT_EQ(eapol1.type(), eapol2.type()); + EXPECT_EQ(eapol1.length(), eapol2.length()); + EXPECT_EQ(eapol1.key_length(), eapol2.key_length()); + EXPECT_EQ(eapol1.replay_counter(), eapol2.replay_counter()); + EXPECT_TRUE(std::equal(eapol1.key_iv(), eapol1.key_iv() + RSNEAPOL::key_iv_size, eapol2.key_iv())); + EXPECT_TRUE(std::equal(eapol1.id(), eapol1.id() + RSNEAPOL::id_size, eapol2.id())); + EXPECT_TRUE(std::equal(eapol1.rsc(), eapol1.rsc() + RSNEAPOL::rsc_size, eapol2.rsc())); + EXPECT_EQ(eapol1.wpa_length(), eapol2.wpa_length()); + EXPECT_TRUE(std::equal(eapol1.nonce(), eapol1.nonce() + RSNEAPOL::nonce_size, eapol2.nonce())); + EXPECT_TRUE(std::equal(eapol1.mic(), eapol1.mic() + RSNEAPOL::mic_size, eapol2.mic())); + EXPECT_EQ(eapol1.key(), eapol2.key()); +} + +TEST_F(RSNEAPOLTest, DefaultConstructor) { + uint8_t empty_nonce[RSNEAPOL::nonce_size] = { 0 }; + uint8_t empty_rsc[RSNEAPOL::rsc_size] = { 0 }; + + RSNEAPOL eapol; + EXPECT_EQ(1, eapol.version()); + EXPECT_EQ(0x3, eapol.packet_type()); + EXPECT_EQ(EAPOL::RSN, eapol.type()); + EXPECT_EQ(0, eapol.length()); + EXPECT_EQ(0, eapol.key_length()); + EXPECT_EQ(0, eapol.replay_counter()); + EXPECT_TRUE(std::equal(empty_iv, empty_iv + sizeof(empty_iv), eapol.key_iv())); + EXPECT_TRUE(std::equal(empty_rsc, empty_rsc + sizeof(empty_rsc), eapol.id())); + EXPECT_TRUE(std::equal(empty_rsc, empty_rsc + sizeof(empty_rsc), eapol.rsc())); + EXPECT_EQ(0, eapol.wpa_length()); + EXPECT_TRUE(std::equal(empty_nonce, empty_nonce + sizeof(empty_nonce), eapol.nonce())); + EXPECT_TRUE(std::equal(empty_iv, empty_iv + sizeof(empty_iv), eapol.mic())); + EXPECT_EQ(RSNEAPOL::key_type(), eapol.key()); +} + +TEST_F(RSNEAPOLTest, ConstructorFromBuffer) { + RSNEAPOL eapol(expected_packet, sizeof(expected_packet)); + EXPECT_EQ(1, eapol.version()); + EXPECT_EQ(3, eapol.packet_type()); + EXPECT_EQ(151, eapol.length()); + EXPECT_EQ(EAPOL::RSN, eapol.type()); + + EXPECT_EQ(1, eapol.key_t()); + EXPECT_EQ(0, eapol.key_index()); + EXPECT_EQ(1, eapol.install()); + EXPECT_EQ(1, eapol.key_ack()); + EXPECT_EQ(1, eapol.key_mic()); + EXPECT_EQ(1, eapol.secure()); + EXPECT_EQ(0, eapol.error()); + EXPECT_EQ(0, eapol.request()); + EXPECT_EQ(1, eapol.encrypted()); + + EXPECT_EQ(16, eapol.key_length()); + EXPECT_EQ(2, eapol.replay_counter()); + EXPECT_TRUE(std::equal(nonce, nonce + sizeof(nonce), eapol.nonce())); + EXPECT_TRUE(std::equal(empty_iv, empty_iv + sizeof(empty_iv), eapol.key_iv())); + EXPECT_TRUE(std::equal(rsc, rsc + sizeof(rsc), eapol.rsc())); + EXPECT_TRUE(std::equal(id, id + sizeof(id), eapol.id())); + EXPECT_TRUE(std::equal(mic, mic + sizeof(mic), eapol.mic())); + ASSERT_EQ(56, eapol.wpa_length()); + RSNEAPOL::key_type key_found = eapol.key(); + ASSERT_EQ(56, key_found.size()); + EXPECT_TRUE(std::equal(key, key + sizeof(key), key_found.begin())); +} + +TEST_F(RSNEAPOLTest, Serialize) { + RSNEAPOL eapol(expected_packet, sizeof(expected_packet)); + RSNEAPOL::serialization_type buffer = eapol.serialize(); + ASSERT_EQ(sizeof(expected_packet), buffer.size()); + EXPECT_TRUE(std::equal(buffer.begin(), buffer.end(), expected_packet)); +} + +TEST_F(RSNEAPOLTest, ConstructionTest) { + RSNEAPOL eapol; + eapol.version(1); + eapol.packet_type(3); + eapol.length(151); + eapol.key_length(16); + eapol.replay_counter(2); + eapol.nonce(nonce); + eapol.key_iv(empty_iv); + eapol.rsc(rsc); + eapol.id(id); + eapol.mic(mic); + eapol.key(RSNEAPOL::key_type(key, key + sizeof(key))); + + eapol.key_descriptor(2); + eapol.key_t(1); + eapol.install(1); + eapol.key_ack(1); + eapol.key_mic(1); + eapol.secure(1); + eapol.encrypted(1); + + RSNEAPOL::serialization_type buffer = eapol.serialize(); + ASSERT_EQ(sizeof(expected_packet), buffer.size()); + + RSNEAPOL eapol2(&buffer[0], buffer.size()); + test_equals(eapol, eapol2); + + EXPECT_TRUE(std::equal(buffer.begin(), buffer.end(), expected_packet)); +} + +TEST_F(RSNEAPOLTest, ReplayCounter) { + RSNEAPOL eapol; + eapol.replay_counter(0x7af3d91a1fd3abLL); + EXPECT_EQ(0x7af3d91a1fd3abLL, eapol.replay_counter()); +} + +TEST_F(RSNEAPOLTest, WPALength) { + RSNEAPOL eapol; + eapol.wpa_length(0x9af1); + EXPECT_EQ(0x9af1, eapol.wpa_length()); +} + +TEST_F(RSNEAPOLTest, KeyIV) { + RSNEAPOL eapol; + eapol.key_iv(empty_iv); + EXPECT_TRUE(std::equal(empty_iv, empty_iv + sizeof(empty_iv), eapol.key_iv())); +} + +TEST_F(RSNEAPOLTest, Nonce) { + RSNEAPOL eapol; + eapol.nonce(nonce); + EXPECT_TRUE(std::equal(nonce, nonce + sizeof(nonce), eapol.nonce())); +} + +TEST_F(RSNEAPOLTest, Key) { + RSNEAPOL eapol; + uint8_t arr[] = { 1, 9, 2, 0x71, 0x87, 0xfa, 0xdf }; + RSNEAPOL::key_type key(arr, arr + sizeof(arr)); + eapol.key(key); + EXPECT_EQ(key, eapol.key()); +} diff --git a/tests/src/wep_decrypt.cpp b/tests/src/wep_decrypt.cpp index 0db5399..4fa0ba9 100644 --- a/tests/src/wep_decrypt.cpp +++ b/tests/src/wep_decrypt.cpp @@ -3,7 +3,6 @@ #include #include #include "crypto.h" -#include "radiotap.h" #include "arp.h" using namespace Tins;