- added TLSConnection object to provide more context in TLS event callback (LIB61850-366)

pull/417/head
Michael Zillgith 3 years ago
parent 91b0e6ed67
commit df66698b4d

@ -130,7 +130,6 @@ namespace IEC61850
} }
} }
public void SetClientMode() public void SetClientMode()
{ {
TLSConfiguration_setClientMode (self); TLSConfiguration_setClientMode (self);

@ -30,11 +30,15 @@ reportCallbackFunction(void* parameter, ClientReport report)
} }
static void static void
securityEventHandler(void* parameter, TLSConfiguration_EventLevel eventLevel, int eventCode, const char* msg) securityEventHandler(void* parameter, TLSConfiguration_EventLevel eventLevel, int eventCode, const char* msg, TLSConnection con)
{ {
(void)parameter; (void)parameter;
printf("[SECURITY EVENT] %s (t: %i, c: %i)\n", msg, eventLevel, eventCode); char* peerAddr = TLSConnection_getPeerAddress(con, NULL);
printf("[SECURITY EVENT] %s (%s)(t: %i, c: %i)\n", msg, peerAddr, eventLevel, eventCode);
free(peerAddr);
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {

@ -103,11 +103,17 @@ clientAuthenticator(void* parameter, AcseAuthenticationParameter authParameter,
} }
static void static void
securityEventHandler(void* parameter, TLSConfiguration_EventLevel eventLevel, int eventCode, const char* msg) securityEventHandler(void* parameter, TLSConfiguration_EventLevel eventLevel, int eventCode, const char* msg, TLSConnection con)
{ {
(void)parameter; (void)parameter;
printf("[SECURITY EVENT] %s (t: %i, c: %i)\n", msg, eventLevel, eventCode); char* peerAddr = TLSConnection_getPeerAddress(con, NULL);
const char* tlsVersionStr = TLSConfigVersion_toString(TLSConnection_getTLSVersion(con));
printf("[SECURITY EVENT - %s] %s (%s)(t: %i, c: %i)\n", tlsVersionStr, msg, peerAddr, eventLevel, eventCode);
free(peerAddr);
} }
int int

@ -322,7 +322,7 @@ Socket_getPeerAddress(Socket self);
* *
* The peer address has to be returned as null terminated string * The peer address has to be returned as null terminated string
* *
* Implementation of this function is MANDATORY (lib60870) * Implementation of this function is MANDATORY (lib60870 and libiec61850)
* *
* \param self the client, connection or server socket instance * \param self the client, connection or server socket instance
* \param peerAddressString a string to store the peer address (the string should have space * \param peerAddressString a string to store the peer address (the string should have space

@ -3,7 +3,7 @@
* *
* TLS Configuration API for protocol stacks using TCP/IP * TLS Configuration API for protocol stacks using TCP/IP
* *
* Copyright 2017-2021 Michael Zillgith * Copyright 2017-2022 Michael Zillgith
* *
* Abstraction layer for configuration of different TLS implementations * Abstraction layer for configuration of different TLS implementations
* *
@ -50,6 +50,25 @@ TLSConfiguration_create(void);
PAL_API void PAL_API void
TLSConfiguration_setClientMode(TLSConfiguration self); TLSConfiguration_setClientMode(TLSConfiguration self);
typedef enum {
TLS_VERSION_NOT_SELECTED = 0,
TLS_VERSION_SSL_3_0 = 3,
TLS_VERSION_TLS_1_0 = 4,
TLS_VERSION_TLS_1_1 = 5,
TLS_VERSION_TLS_1_2 = 6,
TLS_VERSION_TLS_1_3 = 7
} TLSConfigVersion;
/**
* \brief Convert TLS version number to string
*
* \param version TLS version number
*
* \return the TLS version as null terminated string
*/
PAL_API const char*
TLSConfigVersion_toString(TLSConfigVersion version);
typedef enum { typedef enum {
TLS_SEC_EVT_INFO = 0, TLS_SEC_EVT_INFO = 0,
TLS_SEC_EVT_WARNING = 1, TLS_SEC_EVT_WARNING = 1,
@ -71,10 +90,47 @@ typedef enum {
#define TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED 13 #define TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED 13
#define TLS_EVENT_CODE_ALM_CERT_NOT_TRUSTED 12 #define TLS_EVENT_CODE_ALM_CERT_NOT_TRUSTED 12
typedef void (*TLSConfiguration_EventHandler)(void* parameter, TLSConfiguration_EventLevel eventLevel, int eventCode, const char* message); typedef struct sTLSConnection* TLSConnection;
/**
* \brief Get the peer address of the TLS connection
*
* \param self the TLS connection instance
* \param peerAddrBuf user provided buffer that can hold at least 60 characters, or NULL to allow the function to allocate the memory for the buffer
*
* \returns peer address:port as null terminated string
*/
PAL_API char*
TLSConnection_getPeerAddress(TLSConnection self, char* peerAddrBuf);
/**
* \brief Get the TLS certificate used by the peer
*
* \param self the TLS connection instance
* \param certSize[OUT] the certificate size in bytes
*
* \return address of the certificate buffer
*/
PAL_API uint8_t*
TLSConnection_getPeerCertificate(TLSConnection self, int* certSize);
/**
* \brief Get the TLS version used by the connection
*
* \param self the TLS connection instance
*
* \return TLS version
*/
PAL_API TLSConfigVersion
TLSConnection_getTLSVersion(TLSConnection self);
typedef void (*TLSConfiguration_EventHandler)(void* parameter, TLSConfiguration_EventLevel eventLevel, int eventCode, const char* message, TLSConnection con);
/** /**
* \brief Set the security event handler * \brief Set the security event handler
*
* \param handler the security event callback handler
* \param parameter user provided parameter to be passed to the callback handler
*/ */
PAL_API void PAL_API void
TLSConfiguration_setEventHandler(TLSConfiguration self, TLSConfiguration_EventHandler handler, void* parameter); TLSConfiguration_setEventHandler(TLSConfiguration self, TLSConfiguration_EventHandler handler, void* parameter);
@ -209,15 +265,6 @@ TLSConfiguration_addCACertificateFromFile(TLSConfiguration self, const char* fil
PAL_API void PAL_API void
TLSConfiguration_setRenegotiationTime(TLSConfiguration self, int timeInMs); TLSConfiguration_setRenegotiationTime(TLSConfiguration self, int timeInMs);
typedef enum {
TLS_VERSION_NOT_SELECTED = 0,
TLS_VERSION_SSL_3_0 = 3,
TLS_VERSION_TLS_1_0 = 4,
TLS_VERSION_TLS_1_1 = 5,
TLS_VERSION_TLS_1_2 = 6,
TLS_VERSION_TLS_1_3 = 7
} TLSConfigVersion;
/** /**
* \brief Set minimal allowed TLS version to use * \brief Set minimal allowed TLS version to use
*/ */

@ -105,10 +105,10 @@ struct sTLSSocket {
}; };
static void static void
raiseSecurityEvent(TLSConfiguration config, TLSConfiguration_EventLevel eventCategory, int eventCode, const char* message) raiseSecurityEvent(TLSConfiguration config, TLSConfiguration_EventLevel eventCategory, int eventCode, const char* message, TLSSocket socket)
{ {
if (config->eventHandler) { if (config->eventHandler) {
config->eventHandler(config->eventHandlerParameter, eventCategory, eventCode, message); config->eventHandler(config->eventHandlerParameter, eventCategory, eventCode, message, (TLSConnection)socket);
} }
} }
@ -174,7 +174,7 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
if (certMatches) if (certMatches)
*flags = 0; *flags = 0;
else { else {
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED, "Incident: Certificate not configured"); raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED, "Incident: Certificate not configured", self);
*flags |= MBEDTLS_X509_BADCERT_OTHER; *flags |= MBEDTLS_X509_BADCERT_OTHER;
return 1; return 1;
@ -518,7 +518,7 @@ TLSConfiguration_destroy(TLSConfiguration self)
} }
static void static void
createSecurityEvents(TLSConfiguration config, int ret, uint32_t flags) createSecurityEvents(TLSConfiguration config, int ret, uint32_t flags, TLSSocket socket)
{ {
if (config->eventHandler == NULL) if (config->eventHandler == NULL)
return; return;
@ -526,55 +526,55 @@ createSecurityEvents(TLSConfiguration config, int ret, uint32_t flags)
switch (ret) { switch (ret) {
case MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE: case MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE:
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_ALGO_NOT_SUPPORTED, "Incident: Algorithm not supported"); raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_ALGO_NOT_SUPPORTED, "Incident: Algorithm not supported", socket);
break; break;
case MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION: case MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_UNSECURE_COMMUNICATION, "Incident: Unsecure communication"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_UNSECURE_COMMUNICATION, "Incident: Unsecure communication", socket);
break; break;
case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE: case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_UNAVAILABLE, "Incident: Certificate unavailable"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_UNAVAILABLE, "Incident: Certificate unavailable", socket);
break; break;
case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE: case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_BAD_CERT, "Incident: Bad certificate"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_BAD_CERT, "Incident: Bad certificate", socket);
break; break;
case MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE: case MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_SIZE_EXCEEDED, "Incident: TLS certificate size exceeded"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_SIZE_EXCEEDED, "Incident: TLS certificate size exceeded", socket);
break; break;
case MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED: case MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_VALIDATION_FAILED, "Incident: certificate validation: certificate signature could not be validated"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_VALIDATION_FAILED, "Incident: certificate validation: certificate signature could not be validated", socket);
break; break;
case MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED: case MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_REQUIRED, "Incident: Certificate required"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_REQUIRED, "Incident: Certificate required", socket);
break; break;
case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
{ {
if (flags & MBEDTLS_X509_BADCERT_EXPIRED) { if (flags & MBEDTLS_X509_BADCERT_EXPIRED) {
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_EXPIRED, "Incident: Certificate expired"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_EXPIRED, "Incident: Certificate expired", socket);
} }
else if (flags & MBEDTLS_X509_BADCERT_REVOKED) { else if (flags & MBEDTLS_X509_BADCERT_REVOKED) {
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_REVOKED, "Incident: Certificate revoked"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_REVOKED, "Incident: Certificate revoked", socket);
} }
else if (flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { else if (flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_TRUSTED, "Incident: Certificate validation: CA certificate not available"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_TRUSTED, "Incident: Certificate validation: CA certificate not available", socket);
} }
else if (flags & MBEDTLS_X509_BADCERT_OTHER) { else if (flags & MBEDTLS_X509_BADCERT_OTHER) {
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED, "Incident: Certificate not configured"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED, "Incident: Certificate not configured", socket);
} }
else { else {
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_VALIDATION_FAILED, "Incident: Certificate verification failed"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_VALIDATION_FAILED, "Incident: Certificate verification failed", socket);
} }
} }
break; break;
default: default:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Incident: handshake failed for unknown reason"); raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Incident: handshake failed for unknown reason", socket);
break; break;
} }
} }
@ -753,7 +753,7 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
uint32_t flags = mbedtls_ssl_get_verify_result(&(self->ssl)); uint32_t flags = mbedtls_ssl_get_verify_result(&(self->ssl));
createSecurityEvents(configuration, ret, flags); createSecurityEvents(configuration, ret, flags, self);
mbedtls_ssl_free(&(self->ssl)); mbedtls_ssl_free(&(self->ssl));
@ -793,7 +793,7 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
self->lastRenegotiationTime = Hal_getTimeInMs(); self->lastRenegotiationTime = Hal_getTimeInMs();
if (getTLSVersion(self->ssl.major_ver, self->ssl.minor_ver) < TLS_VERSION_TLS_1_2) { if (getTLSVersion(self->ssl.major_ver, self->ssl.minor_ver) < TLS_VERSION_TLS_1_2) {
raiseSecurityEvent(configuration, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_INSECURE_TLS_VERSION, "Warning: Insecure TLS version"); raiseSecurityEvent(configuration, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_INSECURE_TLS_VERSION, "Warning: Insecure TLS version", self);
} }
} }
@ -817,7 +817,7 @@ TLSSocket_performHandshake(TLSSocket self)
if (ret == 0) { if (ret == 0) {
if (getTLSVersion(self->ssl.major_ver, self->ssl.minor_ver) < TLS_VERSION_TLS_1_2) { if (getTLSVersion(self->ssl.major_ver, self->ssl.minor_ver) < TLS_VERSION_TLS_1_2) {
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_INSECURE_TLS_VERSION, "Warning: Insecure TLS version"); raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_INSECURE_TLS_VERSION, "Warning: Insecure TLS version", self);
} }
return true; return true;
@ -828,7 +828,7 @@ TLSSocket_performHandshake(TLSSocket self)
if (self->tlsConfig->eventHandler) { if (self->tlsConfig->eventHandler) {
uint32_t flags = mbedtls_ssl_get_verify_result(&(self->ssl)); uint32_t flags = mbedtls_ssl_get_verify_result(&(self->ssl));
createSecurityEvents(self->tlsConfig, ret, flags); createSecurityEvents(self->tlsConfig, ret, flags, self);
} }
return false; return false;
@ -849,7 +849,7 @@ TLSSocket_read(TLSSocket self, uint8_t* buf, int size)
if (self->tlsConfig->renegotiationTimeInMs > 0) { if (self->tlsConfig->renegotiationTimeInMs > 0) {
if (Hal_getTimeInMs() > self->lastRenegotiationTime + self->tlsConfig->renegotiationTimeInMs) { if (Hal_getTimeInMs() > self->lastRenegotiationTime + self->tlsConfig->renegotiationTimeInMs) {
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Info: session renegotiation started"); raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Info: session renegotiation started", self);
if (TLSSocket_performHandshake(self) == false) { if (TLSSocket_performHandshake(self) == false) {
DEBUG_PRINT("TLS", " renegotiation failed\n"); DEBUG_PRINT("TLS", " renegotiation failed\n");
@ -885,7 +885,7 @@ TLSSocket_read(TLSSocket self, uint8_t* buf, int size)
{ {
uint32_t flags = mbedtls_ssl_get_verify_result(&(self->ssl)); uint32_t flags = mbedtls_ssl_get_verify_result(&(self->ssl));
createSecurityEvents(self->tlsConfig, ret, flags); createSecurityEvents(self->tlsConfig, ret, flags, self);
} }
return -1; return -1;
@ -912,7 +912,7 @@ TLSSocket_write(TLSSocket self, uint8_t* buf, int size)
if (self->tlsConfig->renegotiationTimeInMs > 0) { if (self->tlsConfig->renegotiationTimeInMs > 0) {
if (Hal_getTimeInMs() > self->lastRenegotiationTime + self->tlsConfig->renegotiationTimeInMs) { if (Hal_getTimeInMs() > self->lastRenegotiationTime + self->tlsConfig->renegotiationTimeInMs) {
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Info: session renegotiation started"); raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Info: session renegotiation started", self);
if (TLSSocket_performHandshake(self) == false) { if (TLSSocket_performHandshake(self) == false) {
DEBUG_PRINT("TLS", " renegotiation failed\n"); DEBUG_PRINT("TLS", " renegotiation failed\n");
@ -970,3 +970,54 @@ TLSSocket_close(TLSSocket self)
GLOBAL_FREEMEM(self); GLOBAL_FREEMEM(self);
} }
char*
TLSConnection_getPeerAddress(TLSConnection self, char* peerAddrBuf)
{
TLSSocket socket = (TLSSocket)self;
if (peerAddrBuf == NULL) {
peerAddrBuf = (char*)GLOBAL_MALLOC(61);
}
if (peerAddrBuf)
return Socket_getPeerAddressStatic(socket->socket, peerAddrBuf);
else
return NULL;
}
uint8_t*
TLSConnection_getPeerCertificate(TLSConnection self, int* certSize)
{
TLSSocket socket = (TLSSocket)self;
return TLSSocket_getPeerCertificate(socket, certSize);
}
TLSConfigVersion
TLSConnection_getTLSVersion(TLSConnection self)
{
TLSSocket socket = (TLSSocket)self;
return getTLSVersion(socket->ssl.major_ver, socket->ssl.minor_ver);
}
const char*
TLSConfigVersion_toString(TLSConfigVersion version)
{
switch (version)
{
case TLS_VERSION_SSL_3_0:
return "SSL 3.0";
case TLS_VERSION_TLS_1_0:
return "TLS 1.0";
case TLS_VERSION_TLS_1_1:
return "TLS 1.1";
case TLS_VERSION_TLS_1_2:
return "TLS 1.2";
case TLS_VERSION_TLS_1_3:
return "TLS 1.3";
default:
return "unknown TLS version";
}
}

Loading…
Cancel
Save