From f3d3dd3c25484f46c5dd762a6be32fe213815c19 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Tue, 30 Aug 2011 00:05:16 -0300 Subject: [PATCH] RSNEAPOL is working. Key flags accessors are not implemented yet. --- include/eapol.h | 171 ++++++++++++++++++++++++++++++++++++++++++++++-- src/eapol.cpp | 83 ++++++++++++++++++++++- 2 files changed, 248 insertions(+), 6 deletions(-) diff --git a/include/eapol.h b/include/eapol.h index 7293110..1ebe37c 100644 --- a/include/eapol.h +++ b/include/eapol.h @@ -7,13 +7,21 @@ namespace Tins { + + /** \cond + * Forward declaration. Avoid header inclusion. + */ + class RSNInformation; + /** \endcond */ + /** * \brief Class that represents the EAP encapsulation over LAN. */ class EAPOL : public PDU { public: enum EAPOLTYPE { - RC4 = 1 + RC4 = 1, + RSN, }; /** @@ -158,7 +166,7 @@ namespace Tins { * \brief Getter for the replay counter field. * \return The replay counter field. */ - uint64_t replay_counter() const { return _header.replay_counter; } + uint64_t replay_counter() const { return Utils::net_to_host_ll(_header.replay_counter); } /** * \brief Getter for the key IV field. @@ -269,7 +277,155 @@ namespace Tins { */ class RSNEAPOL : public EAPOL { public: - + /** + * \brief Creates an instance of RSNEAPOL. + */ + RSNEAPOL(); + + /** + * \brief Destructor. + * + * Memory allocated for the key field is freed(if any). + */ + ~RSNEAPOL(); + + /* Getters */ + + /** + * \brief Getter for the key length field. + * \return The key length field. + */ + uint16_t key_length() const { return Utils::net_to_host_s(_header.key_length); } + + /** + * \brief Getter for the replay counter field. + * \return The replay counter field. + */ + uint64_t replay_counter() const { return Utils::net_to_host_ll(_header.replay_counter); } + + /** + * \brief Getter for the key IV field. + * \return The key IV field. + */ + const uint8_t *key_iv() const { return _header.key_iv; } + + /** + * \brief Getter for the nonce field. + * \return The nonce field. + */ + const uint8_t *nonce() const { return _header.nonce; } + + /** + * \brief Getter for the rsc field. + * \return The rsc field. + */ + uint64_t rsc() const { return Utils::net_to_host_ll(_header.rsc); } + + /** + * \brief Getter for the id field. + * \return The id field. + */ + uint64_t id() const { return Utils::net_to_host_ll(_header.id); } + + /** + * \brief Getter for the mic field. + * \return The mic field. + */ + const uint8_t *mic() const { return _header.mic; } + + /** + * \brief Getter for the wpa length field. + * \return The wpa length field. + */ + uint16_t wpa_length() const { return Utils::net_to_host_s(_header.wpa_length); } + + /** + * \brief Getter for the key field. + * \return The key field. + */ + const uint8_t *key() const { return _key; } + + /** + * \brief Returns the header size. + * + * This metod overrides PDU::header_size. This size includes the + * payload and options size. + * + * \sa PDU::header_size + */ + uint32_t header_size() const; + + /* Setters */ + + /** + * \brief Sets the key length field. + * \param new_key_length The new key length to be set. + */ + void key_length(uint16_t new_key_length); + + /** + * \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); + + /** + * \brief Sets the key IV field. + * \param new_key_iv The new key IV to be set. + */ + void key_iv(const uint8_t *new_key_iv); + + /** + * \brief Sets the nonce field. + * + * This method sets the nonce field. This field is 32 bytes long, + * therefore the input buffer should be at least that length. + * \param new_nonce The new nonce to be set. + */ + void nonce(const uint8_t *new_nonce); + + /** + * \brief Sets the rsc field. + * \param new_rsc The new rsc to be set. + */ + void rsc(uint64_t new_rsc); + + /** + * \brief Sets the id field. + * \param new_id The new id to be set. + */ + void id(uint64_t new_id); + + /** + * \brief Sets the mic field. + * + * This method sets the mic field. This field is 16 bytes long, + * therefore the input buffer should be at least that length. + * \param new_mic The new mic to be set. + */ + void mic(const uint8_t *new_mic); + + /** + * \brief Sets the wpa length field. + * \param new_wpa_length The new wpa length to be set. + */ + void wpa_length(uint16_t new_wpa_length); + + /** + * \brief Sets the key field. + * \param new_key The new key to be set. + */ + void key(const uint8_t *new_key, uint32_t sz); + + /** + * \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. + */ + void rsn_information(const RSNInformation &rsn); private: struct rsnhdr { uint16_t key_mic:1, @@ -282,7 +438,7 @@ namespace Tins { key_type:1, key_index:2, install:1, - key_ack:1; + key_ack:1; uint16_t key_length; uint64_t replay_counter; uint8_t nonce[32], key_iv[16]; @@ -290,6 +446,13 @@ namespace Tins { uint8_t mic[16]; uint16_t wpa_length; } __attribute__((__packed__)); + + void write_body(uint8_t *buffer, uint32_t total_sz); + + + rsnhdr _header; + uint8_t *_key; + uint32_t _key_size; }; }; diff --git a/src/eapol.cpp b/src/eapol.cpp index fba59ec..90330ee 100644 --- a/src/eapol.cpp +++ b/src/eapol.cpp @@ -2,6 +2,7 @@ #include #include #include "eapol.h" +#include "ieee802-11.h" Tins::EAPOL::EAPOL(uint8_t packet_type, EAPOLTYPE type) : PDU(0xff) { @@ -82,11 +83,11 @@ Tins::RC4EAPOL::~RC4EAPOL() { } void Tins::RC4EAPOL::key_length(uint16_t new_key_length) { - _header.key_length = new_key_length; + _header.key_length = Utils::net_to_host_s(new_key_length); } void Tins::RC4EAPOL::replay_counter(uint16_t new_replay_counter) { - _header.replay_counter = new_replay_counter; + _header.replay_counter = Utils::net_to_host_s(new_replay_counter); } void Tins::RC4EAPOL::key_iv(const uint8_t *new_key_iv) { @@ -127,3 +128,81 @@ void Tins::RC4EAPOL::write_body(uint8_t *buffer, uint32_t total_sz) { std::memcpy(buffer, _key, _key_size); } + +/* RSNEAPOL */ + + +Tins::RSNEAPOL::RSNEAPOL() : EAPOL(0x03, RSN), _key(0), _key_size(0) { + std::memset(&_header, 0, sizeof(_header)); +} + +Tins::RSNEAPOL::~RSNEAPOL() { + delete[] _key; +} + +void Tins::RSNEAPOL::RSNEAPOL::nonce(const uint8_t *new_nonce) { + std::memcpy(_header.nonce, new_nonce, sizeof(_header.nonce)); +} + +void Tins::RSNEAPOL::rsc(uint64_t new_rsc) { + _header.rsc = Utils::net_to_host_ll(new_rsc); +} + +void Tins::RSNEAPOL::id(uint64_t new_id) { + _header.id = Utils::net_to_host_ll(new_id); +} + +void Tins::RSNEAPOL::mic(const uint8_t *new_mic) { + std::memcpy(_header.mic, new_mic, sizeof(_header.mic)); +} + +void Tins::RSNEAPOL::wpa_length(uint16_t new_wpa_length) { + _header.wpa_length = Utils::net_to_host_s(new_wpa_length); +} + +void Tins::RSNEAPOL::key(const uint8_t *new_key, uint32_t sz) { + delete[] _key; + _key = new uint8_t[sz]; + _key_size = sz; + _header.key_type = 0; + std::memcpy(_key, new_key, sz); +} + +void Tins::RSNEAPOL::rsn_information(const RSNInformation &rsn) { + _key = rsn.serialize(_key_size); + _header.key_type = 1; +} + +uint32_t Tins::RSNEAPOL::header_size() const { + uint32_t padding(0); + if(_header.key_type && _key_size) + padding = 2; + return sizeof(eapolhdr) + sizeof(_header) + _key_size + padding; +} + +void Tins::RSNEAPOL::write_body(uint8_t *buffer, uint32_t total_sz) { + uint32_t sz = header_size() - sizeof(eapolhdr); + assert(total_sz >= sz); + if(_key) { + if(!_header.key_type) { + _header.key_length = Utils::net_to_host_s(32); + wpa_length(_key_size); + } + else if(_key_size) { + _header.key_length = 0; + wpa_length(_key_size + 2); + } + else + wpa_length(0); + } + std::memcpy(buffer, &_header, sizeof(_header)); + buffer += sizeof(_header); + if(_key) { + if(_header.key_type && _key_size) { + *(buffer++) = IEEE802_11::RSN; + *(buffer++) = _key_size; + } + std::memcpy(buffer, _key, _key_size); + } +} +