#define LOG_MODULE PacketLogModuleSSLLayer
#include "Logger.h"
#include "SSLLayer.h"
#include "EndianPortable.h"
#include <sstream>
namespace pcpp
{
bool SSLLayer::IsSSLMessage(uint16_t srcPort, uint16_t dstPort, uint8_t* data, size_t dataLen, bool ignorePorts)
{
if (!ignorePorts && !isSSLPort(srcPort) && !isSSLPort(dstPort))
return false;
if (dataLen < sizeof(ssl_tls_record_layer))
return false;
ssl_tls_record_layer* recordLayer = (ssl_tls_record_layer*)data;
if (recordLayer->length == 0)
return false;
if (recordLayer->recordType < 20 || recordLayer->recordType > 23)
return false;
SSLVersion::SSLVersionEnum recordVersion = SSLVersion(be16toh(recordLayer->recordVersion)).asEnum(true);
if (recordVersion == SSLVersion::TLS1_3 ||
recordVersion == SSLVersion::TLS1_2 ||
recordVersion == SSLVersion::TLS1_1 ||
recordVersion == SSLVersion::TLS1_0 ||
recordVersion == SSLVersion::SSL3)
return true;
else
return false;
}
SSLLayer* SSLLayer::createSSLMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
{
ssl_tls_record_layer* recordLayer = (ssl_tls_record_layer*)data;
switch (recordLayer->recordType)
{
case SSL_HANDSHAKE:
{
return new SSLHandshakeLayer(data, dataLen, prevLayer, packet);
}
case SSL_ALERT:
{
return new SSLAlertLayer(data, dataLen, prevLayer, packet);
}
case SSL_CHANGE_CIPHER_SPEC:
{
return new SSLChangeCipherSpecLayer(data, dataLen, prevLayer, packet);
}
case SSL_APPLICATION_DATA:
{
return new SSLApplicationDataLayer(data, dataLen, prevLayer, packet);
}
default:
return nullptr;
}
}
SSLVersion SSLLayer::getRecordVersion() const
{
uint16_t recordVersion = be16toh(getRecordLayer()->recordVersion);
return SSLVersion(recordVersion);
}
SSLRecordType SSLLayer::getRecordType() const
{
return (SSLRecordType)(getRecordLayer()->recordType);
}
size_t SSLLayer::getHeaderLen() const
{
size_t len = sizeof(ssl_tls_record_layer) + be16toh(getRecordLayer()->length);
if (len > m_DataLen)
return m_DataLen;
return len;
}
void SSLLayer::parseNextLayer()
{
size_t headerLen = getHeaderLen();
if (m_DataLen <= headerLen)
return;
if (SSLLayer::IsSSLMessage(0, 0, m_Data + headerLen, m_DataLen - headerLen, true))
m_NextLayer = SSLLayer::createSSLMessage(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
}
std::string SSLHandshakeLayer::toString() const
{
std::stringstream result;
result << getRecordVersion().toString(true) << " Layer, Handshake:";
for(size_t i = 0; i < m_MessageList.size(); i++)
{
if (i == 0)
result << " " << m_MessageList.at(i)->toString();
else
result << ", " << m_MessageList.at(i)->toString();
}
return result.str();
}
SSLHandshakeLayer::SSLHandshakeLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
: SSLLayer(data, dataLen, prevLayer, packet)
{
uint8_t* curPos = m_Data + sizeof(ssl_tls_record_layer);
size_t recordDataLen = be16toh(getRecordLayer()->length);
if (recordDataLen > m_DataLen - sizeof(ssl_tls_record_layer))
recordDataLen = m_DataLen - sizeof(ssl_tls_record_layer);
size_t curPosIndex = 0;
while (true)
{
SSLHandshakeMessage* message = SSLHandshakeMessage::createHandshakeMessage(curPos, recordDataLen-curPosIndex, this);
if (message == nullptr)
break;
m_MessageList.pushBack(message);
curPos += message->getMessageLength();
curPosIndex += message->getMessageLength();
}
}
SSLHandshakeMessage* SSLHandshakeLayer::getHandshakeMessageAt(int index) const
{
if (index < 0 || index >= (int)(m_MessageList.size()))
return nullptr;
return const_cast<SSLHandshakeMessage*>(m_MessageList.at(index));
}
std::string SSLChangeCipherSpecLayer::toString() const
{
std::stringstream result;
result << getRecordVersion().toString(true) << " Layer, Change Cipher Spec";
return result.str();
}
SSLAlertLevel SSLAlertLayer::getAlertLevel() const
{
uint8_t* pos = m_Data + sizeof(ssl_tls_record_layer);
uint8_t alertLevel = *pos;
if (alertLevel == SSL_ALERT_LEVEL_WARNING || alertLevel == SSL_ALERT_LEVEL_FATAL)
return (SSLAlertLevel)alertLevel;
else
return SSL_ALERT_LEVEL_ENCRYPTED;
}
SSLAlertDescription SSLAlertLayer::getAlertDescription()
{
if (getAlertLevel() == SSL_ALERT_LEVEL_ENCRYPTED)
return SSL_ALERT_ENCRYPTED;
uint8_t* pos = m_Data + sizeof(ssl_tls_record_layer) + sizeof(uint8_t);
uint8_t alertDesc = *pos;
switch (alertDesc)
{
case SSL_ALERT_CLOSE_NOTIFY:
case SSL_ALERT_UNEXPECTED_MESSAGE:
case SSL_ALERT_BAD_RECORD_MAC:
case SSL_ALERT_DECRYPTION_FAILED:
case SSL_ALERT_RECORD_OVERFLOW:
case SSL_ALERT_DECOMPRESSION_FAILURE:
case SSL_ALERT_HANDSHAKE_FAILURE:
case SSL_ALERT_NO_CERTIFICATE:
case SSL_ALERT_BAD_CERTIFICATE:
case SSL_ALERT_UNSUPPORTED_CERTIFICATE:
case SSL_ALERT_CERTIFICATE_REVOKED:
case SSL_ALERT_CERTIFICATE_EXPIRED:
case SSL_ALERT_CERTIFICATE_UNKNOWN:
case SSL_ALERT_ILLEGAL_PARAMETER:
case SSL_ALERT_UNKNOWN_CA:
case SSL_ALERT_ACCESS_DENIED:
case SSL_ALERT_DECODE_ERROR:
case SSL_ALERT_DECRYPT_ERROR:
case SSL_ALERT_EXPORT_RESTRICTION:
case SSL_ALERT_PROTOCOL_VERSION:
case SSL_ALERT_INSUFFICIENT_SECURITY:
case SSL_ALERT_INTERNAL_ERROR:
case SSL_ALERT_USER_CANCELLED:
case SSL_ALERT_NO_RENEGOTIATION:
return (SSLAlertDescription)alertDesc;
break;
default:
return SSL_ALERT_ENCRYPTED;
}
}
std::string SSLAlertLayer::toString() const
{
std::stringstream result;
result << getRecordVersion().toString(true) << " Layer, ";
if (getAlertLevel() == SSL_ALERT_LEVEL_ENCRYPTED)
result << "Encrypted Alert";
else
result << "Alert";
return result.str();
}
uint8_t* SSLApplicationDataLayer::getEncryptedData() const
{
if (getHeaderLen() <= sizeof(ssl_tls_record_layer))
return nullptr;
return m_Data + sizeof(ssl_tls_record_layer);
}
size_t SSLApplicationDataLayer::getEncryptedDataLen() const
{
int result = (int)getHeaderLen() - (int)sizeof(ssl_tls_record_layer);
if (result < 0)
return 0;
return (size_t)result;
}
std::string SSLApplicationDataLayer::toString() const
{
return getRecordVersion().toString(true) + " Layer, Application Data";
}
}