#ifndef PACKETPP_SSL_HANDSHAKE_MESSAGE #define PACKETPP_SSL_HANDSHAKE_MESSAGE #include #include "SSLCommon.h" #include "PointerVector.h" /** * @file * See detailed explanation of the TLS/SSL protocol support in PcapPlusPlus in SSLLayer.h */ /** * \namespace pcpp * \brief The main namespace for the PcapPlusPlus lib */ namespace pcpp { /** * @class SSLCipherSuite * Represents a cipher-suite and enables access all information about it such as all algorithms it encapsulates, * its ID (as appears in the client-hello or server-hello messages), * its name (e.g "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA") etc. PcapPlusPlus contains static instances of this type * for all known cipher-suites and enables access to them through name or ID (see getCipherSuiteByID() and * getCipherSuiteByName() ). List of cipher-suite was taken from here: * http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml */ class SSLCipherSuite { public: /** * A c'tor for this class, should never be used by a user * @param[in] id Cipher-suite ID * @param[in] keyExAlg Key-exchange algorithm used in this cipher-suite * @param[in] authAlg Authentication algorithm used in this cipher-suite * @param[in] symKeyAlg Symmetric key algorithm used in this cipher-suite * @param[in] MACAlg MAC algorithm used in this cipher-suite * @param[in] name String representation of this cipher-suite */ SSLCipherSuite(uint16_t id, SSLKeyExchangeAlgorithm keyExAlg, SSLAuthenticationAlgorithm authAlg, SSLSymetricEncryptionAlgorithm symKeyAlg, SSLHashingAlgorithm MACAlg, const char* name) : m_Id(id), m_KeyExAlg(keyExAlg), m_AuthAlg(authAlg), m_SymKeyAlg(symKeyAlg), m_MACAlg(MACAlg), m_Name(name) {} /** * @return Cipher-suite ID */ uint16_t getID() const { return m_Id; } /** * @return String representation of this cipher-suite */ std::string asString() const { return m_Name; } /** * @return Key-exchange algorithm used in this cipher-suite */ SSLKeyExchangeAlgorithm getKeyExchangeAlg() const { return m_KeyExAlg; } /** * @return Authentication algorithm used in this cipher-suite */ SSLAuthenticationAlgorithm getAuthAlg() const { return m_AuthAlg; } /** * @return Symmetric key algorithm used in this cipher-suite */ SSLSymetricEncryptionAlgorithm getSymKeyAlg() const { return m_SymKeyAlg; } /** * @return MAC algorithm used in this cipher-suite */ SSLHashingAlgorithm getMACAlg() const { return m_MACAlg; } /** * A static method that returns a cipher-suite instance by ID * @param[in] id Cipher-suite ID * @return A cipher-suite instance matching this ID or NULL if ID not found */ static SSLCipherSuite* getCipherSuiteByID(uint16_t id); /** * A static method that returns a cipher-suite instance by name * @param[in] name Cipher-suite name (e.g "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA") * @return A cipher-suite instance matching this name or NULL if name not found */ static SSLCipherSuite* getCipherSuiteByName(std::string name); private: uint16_t m_Id; SSLKeyExchangeAlgorithm m_KeyExAlg; SSLAuthenticationAlgorithm m_AuthAlg; SSLSymetricEncryptionAlgorithm m_SymKeyAlg; SSLHashingAlgorithm m_MACAlg; std::string m_Name; }; /** * @class SSLExtension * Represents a SSL/TLS extension. This is a base class that can represent any type of extension. Inherited classes may * contain parsing logic for specific extensions. This class provides capabilities such as getting the extension type, * length and viewing the extension data as raw (byte array) */ class SSLExtension { public: /** * C'tor for this class * @param[in] data The raw data for the extension */ explicit SSLExtension(uint8_t* data); virtual ~SSLExtension() { } /** * @return The type of the extension as enum */ SSLExtensionType getType() const; /** * @return The type of the extension as a numeric value */ uint16_t getTypeAsInt() const; /** * @return The length of the extension data in bytes (not including the type and length fields) */ uint16_t getLength() const; /** * @return The total length of the extension, including type and length fields and the extension data field */ uint16_t getTotalLength() const; /** * @return A pointer to the raw data of the extension */ uint8_t* getData() const; protected: /** * @struct SSLExtensionStruct * Represents the common fields of the extension */ struct SSLExtensionStruct { /** Extension type */ uint16_t extensionType; /** Extension length */ uint16_t extensionDataLength; /** Extension data as raw (byte array) */ uint8_t extensionData[]; }; uint8_t* m_RawData; SSLExtensionStruct* getExtensionStruct() const { return (SSLExtensionStruct*)m_RawData; } }; /** * @class SSLServerNameIndicationExtension * Represents SSL/TLS Server Name Indication extension. Inherits from SSLExtension and add parsing of the hostname * written in the extension data */ class SSLServerNameIndicationExtension : public SSLExtension { public: /** * C'tor for this class * @param[in] data The raw data for the extension */ explicit SSLServerNameIndicationExtension(uint8_t* data) : SSLExtension(data) {} /** * @return The hostname written in the extension data */ std::string getHostName() const; }; /** * @class SSLSupportedVersionsExtension * Represents TLS Supported Versions extension. Inherits from SSLExtension and adds parsing of the list * of supported versions mentioned in the extension data */ class SSLSupportedVersionsExtension : public SSLExtension { public: /** * C'tor for this class * @param[in] data The raw data for the extension */ explicit SSLSupportedVersionsExtension(uint8_t* data) : SSLExtension(data) {} /** * @return The list of supported versions mentioned in the extension data */ std::vector getSupportedVersions() const; }; /** * @class TLSSupportedGroupsExtension * Represents TLS Supported Groups extension. Inherits from SSLExtension and adds parsing of the * supported groups (Elliptic Curves) mentioned in the extension data */ class TLSSupportedGroupsExtension : public SSLExtension { public: /** * C'tor for this class * @param[in] data The raw data for the extension */ explicit TLSSupportedGroupsExtension(uint8_t* data) : SSLExtension(data) {} /** * @return A vector of the supported groups (also known as "Elliptic Curves") */ std::vector getSupportedGroups() const; }; /** * @class TLSECPointFormatExtension * Represents TLS EC (Elliptic Curves) Point Format extension. Inherits from SSLExtension and adds parsing of the * EC point formats mentioned in the extension data */ class TLSECPointFormatExtension : public SSLExtension { public: /** * C'tor for this class * @param[in] data The raw data for the extension */ explicit TLSECPointFormatExtension(uint8_t* data) : SSLExtension(data) {} /** * @return A vector of the elliptic curves point formats */ std::vector getECPointFormatList() const; }; /** * @class SSLx509Certificate * Represents a x509v3 certificate. the SSLCertificateMessage class returns an instance of this class as the certificate. * Currently this class doesn't do much as it doesn't parse the certificate. It only acts as container to the raw data * and returns general info as data as raw, length, etc. In the future I may add full parsing of the certificate */ class SSLx509Certificate { public: /** * C'tor for this class * @param[in] data The raw data of the certificate * @param[in] dataLen The length in bytes of the raw data * @param[in] allDataExists Certificate messages usually spread on more than 1 packet. So a certificate is likely * to split between 2 packets or more. This field indicates whether the raw data contains all ceritificate data * of just a part of it */ SSLx509Certificate(uint8_t* data, size_t dataLen, bool allDataExists) : m_Data(data), m_DataLen(dataLen), m_AllDataExists(allDataExists) {} /** * @return A pointer to the raw data */ uint8_t* getData() const { return m_Data; } /** * @return Raw data length */ size_t getDataLength() const { return m_DataLen; } /** * Certificate messages usually spread on more than 1 packet. So a certificate is likely to split between 2 packets * or more. This method provides an indication whether all certificate data exists or only part of it * @return True if this data contains all certificate data, false otherwise */ bool allDataExists() const { return m_AllDataExists; } private: uint8_t* m_Data; size_t m_DataLen; bool m_AllDataExists; }; class SSLHandshakeLayer; /** * @class SSLHandshakeMessage * A base class for SSL/TLS handshake messages. This is an abstract class and cannot be instantiated. SSL/TLS handshake * messages are contained in SSLHandshakeLayer, meaning a SSLHandshakeLayer instance can contain one or more SSLHandshakeMessage * instances. For example: one SSLHandshakeLayer may contain a server-hello, certificate, * server-key-exchange, and server-hello-done messages (although it's not such a common case, most handshake layers * contain 1 handshake message only) */ class SSLHandshakeMessage { public: virtual ~SSLHandshakeMessage() {} /** * A factory method for creating instances of handshake messages from raw data * @param[in] data The raw data containing 1 handshake message * @param[in] dataLen Raw data length in bytes * @param[in] container A pointer to the SSLHandshakeLayer instance which will contain the created message. * This parameter is required because the handshake message includes a pointer to its container */ static SSLHandshakeMessage* createHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); /** * @return The handshake message type */ virtual SSLHandshakeType getHandshakeType() const; /** * @return The handshake message length in bytes. Notice that sometimes the handshake message is divided between * several packets, in this case this method will return the length of part of the message in the current packet */ virtual size_t getMessageLength() const; /** * @return True if current packet contains the entire message or false otherwise. This method is important * because sometimes handshake messages are divided in consequent packets (happens a lot in certificate messages * which usually contain several KB of data which is larger than standard packet size, so the message is divided between * several packets) */ virtual bool isMessageComplete() const; /** * @return A pointer to the SSLHandshakeLayer instance containing this message */ SSLHandshakeLayer* getContainingLayer() const { return m_Container; } /** * @return A string representation of the message type (e.g "Client Hello message") */ virtual std::string toString() const = 0; protected: SSLHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); uint8_t* m_Data; size_t m_DataLen; SSLHandshakeLayer* m_Container; }; /** * @class SSLClientHelloMessage * Represents a client-hello message (type 1). Inherits from SSLHandshakeMessage and adds parsing of all fields * of this message including the message extensions, cipher-suite list, etc. */ class SSLClientHelloMessage : public SSLHandshakeMessage { public: /** * @struct ClientHelloTLSFingerprint * A struct that contains all the elements needed for creating a Client Hello TLS fingerprinting: * TLS version, a list of Cipher Suite IDs, a list of Extensions IDs, a list of support groups and a list of * EC point formats. * You can read more about this in SSLClientHelloMessage#generateTLSFingerprint(). * This struct contains methods to extract the TLS fingerprint itself: toString() and toMD5() */ struct ClientHelloTLSFingerprint { /** TLS version */ uint16_t tlsVersion; /** A list of Cipher Suite IDs */ std::vector cipherSuites; /** A list of extension IDs */ std::vector extensions; /** A list of Suppotred Groups taken from the "supported groups" TLS extension (if exist in the message) */ std::vector supportedGroups; /** A list of EC point formats taken from the "EC point formats" TLS extension (if exist in the message) */ std::vector ecPointFormats; /** * @return A string representing the TLS fingerprint, for example: * 771,4866-4867-4865-255,0-11-10-35-22-23-13-43-45-51,29-23-30-25-24,0-1-2 * * This string has the following format: TLSVersion,CipherSuiteIDs,ExtensionIDs,SupportedGroups,ECPointFormats * * The extension IDs, supported groups and EC point formats are each separated by a "-". * If the message doesn't include the "supported groups" or "EC point formats" extensions, they will be replaced * by an empty string for example: 771,4866-4867-4865-255,0-11-10-35-22-23-13-43-45-51,, */ std::string toString(); /** * @return An MD5 hash of the string generated by toString() */ std::string toMD5(); /** * @return A pair of the string and MD5 hash (string is first, MD5 is second). * If you want both this method is more efficient than calling toString() and toMD5() separately */ std::pair toStringAndMD5(); }; /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and shouldn't be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLClientHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); virtual ~SSLClientHelloMessage() {} /** * @return A struct containing common fields for client-hello and server-hello messages. Notice this points directly * to the data, so every change will change the actual packet data */ ssl_tls_client_server_hello* getClientHelloHeader() const { return (ssl_tls_client_server_hello*)m_Data; } /** * @return Handshake SSL/TLS version (notice it may be different than SSLLayer#getRecordVersion(). Each client-hello * or server-hello message has both record version and handshake version and they may differ from one another) */ SSLVersion getHandshakeVersion() const; /** * @return Session ID length in bytes. If server-hello message doesn't include session ID 0 will be returned */ uint8_t getSessionIDLength() const; /** * @return Session ID as byte array. If server-hello message doesn't include session ID NULL will be returned */ uint8_t* getSessionID() const; /** * @return The number of cipher-suites included in this message */ int getCipherSuiteCount() const; /** * Get a pointer to a cipher-suite by index. The cipher-suites are numbered according to their order of appearance * in the message. If index is out of bounds (less than 0 or larger than total amount of cipher suites) NULL will be * returned. NULL will also be returned if the cipher-suite ID is unknown. If you still want to get the cipher-suite * ID you can use getCipherSuiteID() * @param[in] index The index of the cipher-suite to return * @return The pointer to the cipher-suite object or NULL if index is out of bounds */ SSLCipherSuite* getCipherSuite(int index) const; /** * Get the cipher-suite ID by index. This method just parses the ID from the client-hello message and returns it. * To get more information on the cipher-suite you can use the getCipherSuite() method * @param[in] index The index of the cipher-suite to return * @param[out] isValid Set to "true" if parsing succeeded and the return value is valid or "false" if: * (1) the index is out-of-bounds (less than 0 or larger than total amount of cipher suites) or (2) the parsing failed. * If the value is "false" the return value can be ignored * @return The cipher-suite ID if "isValid" is set to "true". If "isValid" is set to "false" the return value can be ignored */ uint16_t getCipherSuiteID(int index, bool& isValid) const; /** * @return The value of the compression method byte */ uint8_t getCompressionMethodsValue() const; /** * @return The number of extensions in this message */ int getExtensionCount() const; /** * @return The size (in bytes) of all extensions data in this message. Extracted from the "extensions length" field */ uint16_t getExtensionsLength() const; /** * Get a pointer to an extension by index. The extensions are numbered according to their order of appearance * in the message. If index is out of bounds (less than 0 or larger than total amount of extensions) NULL will be * returned * @param[in] index The index of the extension to return * @return The pointer to the extension or NULL if index is out of bounds */ SSLExtension* getExtension(int index) const; /** * Get a pointer to an extension by numeric type field. Every extension has a 2-byte numeric value representing * its type (for example: renegotiation info extension type is 0x1ff). This method gets the type and returns a * pointer to the extension object * @param[in] type The 2-byte numeric type of the extension * @return A pointer to the extension object of NULL if this type doesn't exist in this message */ SSLExtension* getExtensionOfType(uint16_t type) const; /** * Get a pointer to an extension by its enum type * @param[in] type The type of extension to return * @return A pointer to the extension object or NULL if this type doesn't exist in this message */ SSLExtension* getExtensionOfType(SSLExtensionType type) const; /** * Get a pointer to an extension by its class type. This is a templated method that is used with the type of the * requested extension and returns the first extension instance of this type * @return A pointer to the extension object or NULL if this extension type doesn't exist in this message * */ template TExtension* getExtensionOfType() const; /** * TLS fingerprinting is a way to identify client applications using the details in the TLS Client Hello packet. * It was initially introduced by Lee Brotherston in his 2015 research: * This implementation of TLS fingerprint is a C++ version of Salesforce's JA3 open source project (originally written in * Python and Zeek): * * @return A SSLClientHelloMessage#ClientHelloTLSFingerprint struct that contains all the elements needed for * creating a TLS fingerprint out of this Client Hello message. This struct has also methods to extract the TLS fingerprint * itself in a string or MD5 formats */ ClientHelloTLSFingerprint generateTLSFingerprint() const; // implement abstract methods std::string toString() const; private: PointerVector m_ExtensionList; }; /** * @class SSLServerHelloMessage * Represents SSL/TLS server-hello message (type 2). Inherits from SSLHandshakeMessage and adds parsing of all fields * of this message including the message extensions, cipher-suite, etc. */ class SSLServerHelloMessage : public SSLHandshakeMessage { public: /** * @struct ServerHelloTLSFingerprint * A struct that contains all the elements needed for creating a Server Hello TLS fingerprinting: * TLS version, Cipher Suite ID, and a list of Extensions IDs. * You can read more about this in SSLServerHelloMessage#generateTLSFingerprint(). * This struct contains methods to extract the TLS fingerprint itself: toString() and toMD5() */ struct ServerHelloTLSFingerprint { /** TLS version */ uint16_t tlsVersion; /** Cipher Suite ID */ uint16_t cipherSuite; /** A list of extension IDs */ std::vector extensions; /** * @return A string representing the TLS fingerprint, for example: 771,49195,65281-16-11 * * This string has the following format: TLSVersion,Cipher,Extensions * * The extension ID are separated with a "-" */ std::string toString(); /** * @return An MD5 hash of the string generated by toString() */ std::string toMD5(); /** * @return A pair of the string and MD5 hash (string is first, MD5 is second). * If you want both this method is more efficient than calling toString() and toMD5() separately */ std::pair toStringAndMD5(); }; /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and shouldn't be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLServerHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); virtual ~SSLServerHelloMessage() {} /** * @return A struct containing common fields for client-hello and server-hello messages. Notice this points directly * to the data, so every change will change the actual packet data */ ssl_tls_client_server_hello* getServerHelloHeader() const { return (ssl_tls_client_server_hello*)m_Data; } /** * @return Handshake SSL/TLS version (notice it may be different than SSLLayer#getRecordVersion(). Each client-hello * or server-hello message has both record version and handshake version and they may differ from one another). * * NOTE: for TLS 1.3 the handshake version written in ssl_tls_client_server_hello::handshakeVersion is still TLS 1.2, * so a special check is made here see if a SupportedVersions extension exists and if so extract the version from it. * This is the most straight-forward way to detect TLS 1.3. */ SSLVersion getHandshakeVersion() const; /** * @return Session ID length in bytes. If server-hello message doesn't include session ID 0 will be returned */ uint8_t getSessionIDLength() const; /** * @return Session ID as byte array. If server-hello message doesn't include session ID NULL will be returned */ uint8_t* getSessionID() const; /** * @return A pointer to the cipher suite encapsulated in this message (server-hello message contains one * cipher-suite, the one that will be used to for encryption between client and server). May return NULL * if the parsing of the message failed or the cipher-suite ID is unknown. If you still want to get the * cipher-suite ID you can use the getCipherSuiteID() method */ SSLCipherSuite* getCipherSuite() const; /** * Get the cipher-suite ID. This method just parses the ID from the server-hello message and returns it. * To get more information on the cipher-suite you can use the getCipherSuite() method * @param[out] isValid Set to "true" if parsing succeeded and the return value is valid or "false" otherwise. * If the value is "false" the return value can be ignored * @return The cipher-suite ID if "isValid" is set to "true". If "isValid" is set to "false" the return value can be ignored */ uint16_t getCipherSuiteID(bool& isValid) const; /** * @return The value of the compression method byte */ uint8_t getCompressionMethodsValue() const; /** * @return The number of extensions in this message */ int getExtensionCount() const; /** * @return The size (in bytes) of all extensions data in this message. Extracted from the "extensions length" field */ uint16_t getExtensionsLength() const; /** * Get a pointer to an extension by index. The extensions are numbered according to their order of appearance * in the message. If index is out of bounds (less than 0 or larger than total amount of extensions) NULL will be * returned * @param[in] index The index of the extension to return * @return The pointer to the extension or NULL if index is out of bounds */ SSLExtension* getExtension(int index) const; /** * Get a pointer to an extension by numeric type field. Every extension has a 2-byte numeric value representing * its type (for example: renegotiation info extension type is 0x1ff). This method gets the type and returns a * pointer to the extension object * @param[in] type The 2-byte numeric type of the extension * @return A pointer to the extension object of NULL if this type doesn't exist in this message */ SSLExtension* getExtensionOfType(uint16_t type) const; /** * Get a pointer to an extension by its enum type * @param[in] type The type of extension to return * @return A pointer to the extension object or NULL if this type doesn't exist in this message */ SSLExtension* getExtensionOfType(SSLExtensionType type) const; /** * Get a pointer to an extension by its class type. This is a templated method that is used with the type of the * requested extension and returns the first extension instance of this type * @return A pointer to the extension object or NULL if this extension type doesn't exist in this message * */ template TExtension* getExtensionOfType() const; /** * ServerHello TLS fingerprinting is a way to fingerprint TLS Server Hello messages. In conjunction with * ClientHello TLS fingerprinting it can assist in identifying specific client-server communication (for * example: a malware connecting to its backend server). * ServerHello TLS fingerprinting was introduced in Salesforce's JA3S open source project: * * This implementation is a C++ version of Salesforce's JAS3 (originally written in Python and Zeek) * @return A SSLServerHelloMessage#ServerHelloTLSFingerprint struct that contains all the elements needed for * creating a TLS fingerprint out of this Server Hello message. This struct has also methods to extract the TLS fingerprint * itself in a string or MD5 formats */ ServerHelloTLSFingerprint generateTLSFingerprint() const; // implement abstract methods std::string toString() const; private: PointerVector m_ExtensionList; }; /** * @class SSLCertificateMessage * Represents SSL/TLS certificate message (type 11). Inherits from SSLHandshakeMessage and adds parsing functionality * such as extracting the certificates data. Notice that in most cases this message is spread over more than 1 packet * as its size is too big for a single packet. So SSLCertificateMessage instance will be created just for the first * part of the message - the one encapsulated in the first packet. Other parts (encapsulated in the following packets) * won't be recognized as SSLCertificateMessage messages */ class SSLCertificateMessage : public SSLHandshakeMessage { public: /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLCertificateMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); virtual ~SSLCertificateMessage() {} /** * @return The number of certificates encapsulated in this message (as written in the 'length' field of the * message). Notice that because the message may spread over several packets, not all certificates will necessarily * be in this packet. So, for example, there may be a case where this method return 3 (message contains 3 * certificates) but this message actually contains only 1 certificate as the other 2 are spread over the other * packets */ int getNumOfCertificates() const; /** * Get a certificate by index * @param[in] index The index of the certificate to retrieve * @return A pointer to the certificate object. Notice that if index < 0 or index > num of certificates encapsulated * in current packet a NULL value will be returned */ SSLx509Certificate* getCertificate(int index) const; // implement abstract methods std::string toString() const; private: PointerVector m_CertificateList; }; /** * @class SSLHelloRequestMessage * Represents SSL/TLS hello-request message (type 0). This message has no additional payload except for the common payload * described in SSLHandshakeMessage */ class SSLHelloRequestMessage : public SSLHandshakeMessage { public: /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLHelloRequestMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} virtual ~SSLHelloRequestMessage() {} // implement abstract methods std::string toString() const; }; /** * @class SSLServerKeyExchangeMessage * Represents SSL/TLS server-key-exchange message (type 12). Inherits from SSLHandshakeMessage and adds parsing * functionality such as getting the server key exchange params as raw data (parsing of this may be added in the * future) */ class SSLServerKeyExchangeMessage : public SSLHandshakeMessage { public: /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLServerKeyExchangeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} ~SSLServerKeyExchangeMessage() {} /** * @return A pointer to the raw data of the server key exchange params. Currently this data can only returned as * raw, parsing may be added in the future. Notice that if the message is spread over more than 1 packet in a way * params doesn't exist in the first packet, NULL will be returned */ uint8_t* getServerKeyExchangeParams() const; /** * @return The size of the params field. Notice that if the message is spread over more than 1 packet in a way the * ssl_tls_handshake_layer cannot be parsed from the packet, 0 will be returned. Also, if only part of the params * exist in current packet (and the rest are on consequent packets), the size that will be returned is the size * of the part that exists in the current packet (and not total size of params) */ size_t getServerKeyExchangeParamsLength() const; // implement abstract methods std::string toString() const; }; /** * @class SSLClientKeyExchangeMessage * Represents SSL/TLS client-key-exchange message (type 16). Inherits from SSLHandshakeMessage and adds parsing * functionality such as getting the server key exchange params as raw data (parsing of this may be added in the * future) */ class SSLClientKeyExchangeMessage : public SSLHandshakeMessage { public: /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLClientKeyExchangeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} ~SSLClientKeyExchangeMessage() {} /** * @return A pointer to the raw data of the server key exchange params. Currently this data can only be returned * as raw, parsing may be added in the future. Notice that if the message is spread over more than 1 packet in * a way params doesn't exist in the first packet, NULL will be returned */ uint8_t* getClientKeyExchangeParams() const; /** * @return The size of the params field. Notice that if the message is spread over more than 1 packet in a way the * ssl_tls_handshake_layer cannot be parsed from the packet, 0 will be returned. Also, if only part of the params * exist in current packet (and the rest are on consequent packets), the size that will be returned is the size * of the part that exists in the current packet (and not the total size of params) */ size_t getClientKeyExchangeParamsLength() const; // implement abstract methods std::string toString() const; }; /** * @class SSLCertificateRequestMessage * Represents SSL/TLS certificate-request message (type 13). Inherits from SSLHandshakeMessage and adds parsing * functionality such as retrieving client certificate types and authority data */ class SSLCertificateRequestMessage : public SSLHandshakeMessage { public: /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLCertificateRequestMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); ~SSLCertificateRequestMessage() {} /** * @return A reference to a vector containing all client certificate types exist in this message */ std::vector& getCertificateTypes(); /** * @return A pointer to the certificate authority data as raw data (byte array). Parsing of this data may be added * in the future. Notice that if this message is spread over several packets in a way none of the certificate * authority data exists in this packet, NULL will be returned */ uint8_t* getCertificateAuthorityData() const; /** * @return The length of certificate authority data returned by getCertificateAuthorityData(). Notice that if * this message is spread over several packets in a way none of certificate authority data exists in the current * packet, 0 will be returned. Also, if some of the data exists in the consequent packets, the length that will be * returned is the length of data exists in the current packet only (and not the total length) */ size_t getCertificateAuthorityLength() const; // implement abstract methods std::string toString() const; private: std::vector m_ClientCertificateTypes; }; /** * @class SSLServerHelloDoneMessage * Represents SSL/TLS server-hello-done message (type 14). This message has no additional payload except for the common * payload described in SSLHandshakeMessage */ class SSLServerHelloDoneMessage : public SSLHandshakeMessage { public: /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLServerHelloDoneMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} virtual ~SSLServerHelloDoneMessage() {} // implement abstract methods std::string toString() const; }; /** * @class SSLCertificateVerifyMessage * Represents SSL/TLS certificate-verify message (type 15). Inherits from SSLHandshakeMessage and adds parsing * functionality such as retrieving signed hash data as raw data (parsing may be added in the future) * @todo This message type wasn't tested in unit-tests */ class SSLCertificateVerifyMessage : public SSLHandshakeMessage { public: /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLCertificateVerifyMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} virtual ~SSLCertificateVerifyMessage() {} /** * @return A pointer to the signed hash data as raw data (byte array). Parsing of this data may be added * in the future. Notice that if this message is spread over several packets in a way none of the signed hash data * exists in this packet, NULL will be returned */ uint8_t* getSignedHash() const; /** * @return The length of signed hash data returned by getSignedHash(). Notice that if this message is spread over * several packets in a way none of this data exists in the current packet, 0 will be returned. Also, if some of * the data exists in the consequent packets, the length that will be returned will be the length of data exists in * the current packet only (and not the total length) */ size_t getSignedHashLength() const; // implement abstract methods std::string toString() const; }; /** * @class SSLFinishedMessage * Represents SSL/TLS finished message (type 20). Inherits from SSLHandshakeMessage and adds parsing * functionality such as retrieving signed hash data as raw data (parsing may be added in the future) * @todo This message type wasn't tested in unit-tests */ class SSLFinishedMessage : public SSLHandshakeMessage { public: /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLFinishedMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} virtual ~SSLFinishedMessage() {} /** * @return A pointer to the signed hash data as raw data (byte array). Parsing of this data may be added * in the future. Notice that if this message is spread over several packets in a way none of the signed hash data * exists in this packet, NULL will be returned */ uint8_t* getSignedHash() const; /** * @return The length of signed hash data returned by getSignedHash(). Notice that if the message is spread over * several packets in a way none of this data exists in the current packet, 0 will be returned. Also, if some of * the data exists in the consequent packets, the length that will be returned will be the length of data exists * in the current packet only (and not the total length) */ size_t getSignedHashLength() const; // implement abstract methods std::string toString() const; }; /** * @class SSLNewSessionTicketMessage * Represents SSL/TLS new-session-ticket message (type 4). Inherits from SSLHandshakeMessage and adds parsing * functionality such as retrieving session ticket data as raw data (parsing may be added in the future) */ class SSLNewSessionTicketMessage : public SSLHandshakeMessage { public: /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLNewSessionTicketMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} virtual ~SSLNewSessionTicketMessage() {} /** * @return A pointer to the session ticket data as raw data (byte array). Parsing of this data may be added * in the future. Notice that if this message is spread over several packets in a way none of the signed hash data * exists in current packet, NULL will be returned */ uint8_t* getSessionTicketData() const; /** * @return The length of session ticket data returned by getSessionTicketData(). Notice that if this message is * spread over several packets in a way none of this data exists in the current packet, 0 will be returned. Also, * if some of the data exist in the consequent packets, the length that will be returned will be the length of the * data existing in the current packet only (and not the total length) */ size_t getSessionTicketDataLength() const; // implement abstract methods std::string toString() const; }; /** * @class SSLUnknownMessage * Represents an unknown type of message or an encrypted message that PcapPlusPlus can't determine its type. In these * cases length can't always be determined from the message itself (especially if the message is encrypted), so * the length of this message will always be the size counted from message start until the end of the layer */ class SSLUnknownMessage : public SSLHandshakeMessage { public: /** * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used * by a user * @param[in] data The message as raw data * @param[in] dataLen Message raw data length in bytes * @param[in] container The SSL handshake layer which shall contain this message */ SSLUnknownMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} virtual ~SSLUnknownMessage() {} // implement virtual and abstract methods /** * @return Always ::SSL_HANDSHAKE_UNKNOWN (overridden from SSLHandshakeMessage) */ SSLHandshakeType getHandshakeType() const; /** * @return The length of the data from message start until the end of the layer. Since it's an unknown type * or an encrypted message the length parsed from the message can't be guaranteed to be the correct length. That's * why the length returned is the size until the end of the layer */ size_t getMessageLength() const; std::string toString() const; }; template TExtension* SSLClientHelloMessage::getExtensionOfType() const { size_t vecSize = m_ExtensionList.size(); for (size_t i = 0; i < vecSize; i++) { SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); if (dynamic_cast(curElem) != NULL) return (TExtension*)curElem; } return NULL; } template TExtension* SSLServerHelloMessage::getExtensionOfType() const { size_t vecSize = m_ExtensionList.size(); for (size_t i = 0; i < vecSize; i++) { SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); if (dynamic_cast(curElem) != NULL) return (TExtension*)curElem; } return NULL; } } // namespace pcpp #endif /* PACKETPP_SSL_HANDSHAKE_MESSAGE */