#ifndef PACKETPP_IPSEC_LAYER #define PACKETPP_IPSEC_LAYER /// @file #include "Layer.h" /** * \namespace pcpp * \brief The main namespace for the PcapPlusPlus lib */ namespace pcpp { /** * @struct ipsec_authentication_header * Represents IPSec AuthenticationHeader (AH) structure */ #pragma pack(push, 1) struct ipsec_authentication_header { /** Type of the next header */ uint8_t nextHeader; /** The length of the Authentication Header in 4-octet units, minus 2 */ uint8_t payloadLen; /** Reserved */ uint16_t reserved; /** Security Parameters Index */ uint32_t spi; /** Sequence Number */ uint32_t sequenceNumber; }; #pragma pack(pop) /** * @struct ipsec_esp * Represents IPSec Encapsulating Security Payload (ESP) structure */ #pragma pack(push, 1) struct ipsec_esp { /** Security Parameters Index */ uint32_t spi; /** Sequence Number */ uint32_t sequenceNumber; }; #pragma pack(pop) /** * @class AuthenticationHeaderLayer * Represents an IPSec AuthenticationHeader (AH) layer */ class AuthenticationHeaderLayer : public Layer { public: /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ AuthenticationHeaderLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = AuthenticationHeader; } /** * Get a pointer to the raw AH header. Notice this points directly to the data, so every change will change the actual packet data * @return A pointer to the ipsec_authentication_header */ ipsec_authentication_header* getAHHeader() const { return (ipsec_authentication_header*)m_Data; } /** * @return The Security Parameters Index (SPI) field value */ uint32_t getSPI() const; /** * @return The sequence number value */ uint32_t getSequenceNumber() const; /** * @return The size of the Integrity Check Value (ICV) */ size_t getICVLength() const; /** * @return A pointer to the raw data of the Integrity Check Value (ICV) */ uint8_t* getICVBytes() const; /** * @return The value of the Integrity Check Value (ICV) as a hex string */ std::string getICVHexStream() const; /** * A static method that validates the input data * @param[in] data The pointer to the beginning of a byte stream of a AuthenticationHeader layer * @param[in] dataLen The length of byte stream * @return True if the data is valid and can represent an AuthenticationHeader layer */ static inline bool isDataValid(const uint8_t* data, size_t dataLen); // implement abstract methods /** * @return The size of the AH header */ size_t getHeaderLen() const { return 4*(getAHHeader()->payloadLen + 2); } /** * Currently identifies the following next layers: UdpLayer, TcpLayer, IPv4Layer, IPv6Layer and ESPLayer. Otherwise sets PayloadLayer */ void parseNextLayer(); /** * Does nothing for this layer */ void computeCalculateFields() {} std::string toString() const; OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } private: // this layer supports parsing only AuthenticationHeaderLayer() {} }; /** * @class ESPLayer * Represents an IPSec Encapsulating Security Payload (ESP) layer */ class ESPLayer : public Layer { public: /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ ESPLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = ESP; } ipsec_esp* getESPHeader() const { return (ipsec_esp*)m_Data; } /** * @return The Security Parameters Index (SPI) field value */ uint32_t getSPI() const; /** * @return The sequence number value */ uint32_t getSequenceNumber() const; /** * A static method that validates the input data * @param[in] data The pointer to the beginning of a byte stream of a ESP layer * @param[in] dataLen The length of byte stream * @return True if the data is valid and can represent an ESP layer */ static inline bool isDataValid(const uint8_t* data, size_t dataLen); // implement abstract methods /** * @return The size of the ESP header (8 bytes) */ size_t getHeaderLen() const { return sizeof(ipsec_esp); } /** * The payload of an ESP layer is encrypted, hence the next layer is always a generic payload (PayloadLayer) */ void parseNextLayer(); /** * Does nothing for this layer */ void computeCalculateFields() {} std::string toString() const; OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; } private: // this layer supports parsing only ESPLayer() {} }; // implementation of inline methods bool AuthenticationHeaderLayer::isDataValid(const uint8_t* data, size_t dataLen) { if (dataLen < sizeof(ipsec_authentication_header)) return false; size_t payloadLen = 4 * (data[1] + 2); if (payloadLen < sizeof(ipsec_authentication_header) || payloadLen > dataLen) return false; return true; } bool ESPLayer::isDataValid(const uint8_t* data, size_t dataLen) { return data && dataLen >= sizeof(ipsec_esp); } } #endif // PACKETPP_IPSEC_LAYER