- some updates for mbedtls 3.6 integration (LIB61850-448)

pull/521/head
Michael Zillgith 1 year ago
parent 982e959965
commit fef8f94751

@ -209,6 +209,11 @@ IF(MINGW)
target_link_libraries(hal ws2_32 iphlpapi)
ENDIF(MINGW)
IF (MSVC)
target_link_libraries(hal bcrypt)
target_link_libraries(hal-shared bcrypt)
ENDIF()
iF(WITH_WPCAP)
target_link_libraries(hal
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib

@ -72,7 +72,7 @@ struct sTLSConfiguration {
/* TLS minimum version allowed (default: TLS_VERSION_TLS_1_0) */
TLSConfigVersion minVersion;
/* TLS minimum version allowed (default: TLS_VERSION_TLS_1_2) */
/* TLS maximum version allowed (default: TLS_VERSION_TLS_1_2) */
TLSConfigVersion maxVersion;
TLSConfiguration_EventHandler eventHandler;
@ -308,7 +308,7 @@ TLSConfiguration_create()
{
TLSConfiguration self = (TLSConfiguration) GLOBAL_CALLOC(1, sizeof(struct sTLSConfiguration));
if (self != NULL)
if (self)
{
mbedtls_ssl_config_init( &(self->conf) );
mbedtls_x509_crt_init( &(self->ownCertificate) );

@ -26,6 +26,7 @@
#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
/* mbed TLS modules */
#define MBEDTLS_GCM_C
#define MBEDTLS_AES_C
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_ASN1_WRITE_C

@ -3,7 +3,7 @@
*
* TLS API for TCP/IP protocol stacks
*
* Copyright 2017-2022 Michael Zillgith
* Copyright 2017-2024 Michael Zillgith
*
* Implementation of the TLS abstraction layer for mbedtls
*
@ -38,9 +38,9 @@
#endif
#if (CONFIG_DEBUG_TLS == 1)
#define DEBUG_PRINT(appId, fmt, ...) fprintf(stderr, "%s: " fmt, appId, ## __VA_ARGS__);
#define DEBUG_PRINT(appId, fmt, ...) fprintf(stderr, "%s: " fmt, appId, ## __VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...) {do {} while(0);}
#define DEBUG_PRINT(fmt, ...) do {} while(0)
#endif
static int psaInitCounter = 0;
@ -90,6 +90,9 @@ struct sTLSConfiguration {
bool useSessionResumption;
int sessionResumptionInterval; /* session resumption interval in seconds */
int* ciphersuites;
int maxCiphersuites;
};
struct sTLSSocket {
@ -144,28 +147,32 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
DEBUG_PRINT("TLS", "%s\n", buffer);
if (self->tlsConfig->chainValidation == false) {
if (self->tlsConfig->chainValidation == false)
{
if (certificate_depth != 0)
*flags = 0;
}
if (certificate_depth == 0) {
if (self->tlsConfig->allowOnlyKnownCertificates) {
if (certificate_depth == 0)
{
if (self->tlsConfig->allowOnlyKnownCertificates)
{
DEBUG_PRINT("TLS", "Check against list of allowed certs\n");
bool certMatches = false;
LinkedList certList = LinkedList_getNext(self->tlsConfig->allowedCertificates);
while (certList) {
while (certList)
{
mbedtls_x509_crt* allowedCert = (mbedtls_x509_crt*) LinkedList_getData(certList);
DEBUG_PRINT("TLS", "Compare With:\n");
mbedtls_x509_crt_info(buffer, 1023, " ", allowedCert);
DEBUG_PRINT("TLS", "%s\n", buffer);
if (compareCertificates(allowedCert, crt)) {
if (compareCertificates(allowedCert, crt))
{
certMatches = true;
break;
}
@ -175,7 +182,8 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
if (certMatches)
*flags = 0;
else {
else
{
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED, "Alarm: certificate validation: trusted individual certificate not available", self);
*flags |= MBEDTLS_X509_BADCERT_OTHER;
@ -183,20 +191,19 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
}
}
if (self->storePeerCert) {
if (*flags == 0) {
if (self->storePeerCert)
{
if (*flags == 0)
{
self->peerCertLength = 0;
self->peerCert = (uint8_t*) GLOBAL_MALLOC(crt->raw.len);
if (self->peerCert) {
if (self->peerCert)
{
self->peerCertLength = (int)crt->raw.len;
memcpy(self->peerCert, crt->raw.p, self->peerCertLength);
}
}
}
}
@ -209,10 +216,12 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
static bool
TLSConfiguration_setupComplete(TLSConfiguration self)
{
if (self->setupComplete == false) {
if (self->setupComplete == false)
{
mbedtls_ssl_conf_ca_chain( &(self->conf), &(self->cacerts), &(self->crl) );
if (self->ownCertificate.version > 0) {
if (self->ownCertificate.version > 0)
{
int ret = mbedtls_ssl_conf_own_cert( &(self->conf), &(self->ownCertificate), &(self->ownKey));
if (ret != 0) {
@ -221,11 +230,13 @@ TLSConfiguration_setupComplete(TLSConfiguration self)
}
}
if (self->useSessionResumption) {
if (self->useSessionResumption)
{
if (mbedtls_ssl_conf_get_endpoint(&(self->conf)) == MBEDTLS_SSL_IS_CLIENT) {
}
else {
else
{
mbedtls_ssl_cache_init( &(self->cache) );
// MIGRATE 2.28->3.x.x: https://github.com/Mbed-TLS/mbedtls/blob/development/docs/3.0-migration-guide.md#most-structure-fields-are-now-private
@ -237,18 +248,70 @@ TLSConfiguration_setupComplete(TLSConfiguration self)
}
}
mbedtls_ssl_conf_ciphersuites(&(self->conf), self->ciphersuites);
self->setupComplete = true;
}
return true;
}
void
TLSConfiguration_addCipherSuite(TLSConfiguration self, int ciphersuite)
{
/* search last index */
int nextIndex = 0;
int i;
for (i = 0; i < self->maxCiphersuites; i++)
{
if (self->ciphersuites[i] == 0)
{
nextIndex = i;
break;
}
}
if (nextIndex == self->maxCiphersuites)
{
/* reallocate space for ciphersuites list */
int newMaxCiphersuites = self->maxCiphersuites + 10;
int* newCiphersuites = (int*)GLOBAL_CALLOC(newMaxCiphersuites, sizeof(int));
if (newCiphersuites)
{
for (i = 0; i < self->maxCiphersuites; i++)
{
newCiphersuites[i] = self->ciphersuites[i];
}
GLOBAL_FREEMEM(self->ciphersuites);
self->ciphersuites = newCiphersuites;
self->maxCiphersuites = newMaxCiphersuites;
TLSConfiguration_addCipherSuite(self, ciphersuite);
}
}
else
{
self->ciphersuites[nextIndex] = ciphersuite;
self->ciphersuites[nextIndex + 1] = 0;
}
}
void
TLSConfiguration_clearCipherSuiteList(TLSConfiguration self)
{
self->ciphersuites[0] = 0;
}
TLSConfiguration
TLSConfiguration_create()
{
TLSConfiguration self = (TLSConfiguration) GLOBAL_CALLOC(1, sizeof(struct sTLSConfiguration));
if (self != NULL)
if (self)
{
/* call to psa_crypto_init required -> see https://github.com/Mbed-TLS/mbedtls/issues/9223 */
psa_status_t psaStatus = psa_crypto_init();
@ -276,9 +339,6 @@ TLSConfiguration_create()
mbedtls_ssl_conf_renegotiation(&(self->conf), MBEDTLS_SSL_RENEGOTIATION_ENABLED);
/* static int hashes[] = {3,4,5,6,7,8,0}; */
/* mbedtls_ssl_conf_sig_hashes(&(self->conf), hashes); */
self->minVersion = TLS_VERSION_TLS_1_2;
self->maxVersion = TLS_VERSION_NOT_SELECTED;
@ -298,6 +358,31 @@ TLSConfiguration_create()
self->sessionResumptionInterval = 21600; /* default value: 6h */
self->savedSession = NULL;
self->savedSessionTime = 0;
self->ciphersuites = (int*)GLOBAL_CALLOC(20, sizeof(int));
if (self->ciphersuites)
{
self->maxCiphersuites = 20;
/* mandatory cipher suites by IEC 62351-4:2018 */
self->ciphersuites[0] = MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256;
/* self->ciphersuites[1] = MBEDTLS_TLS_DH_RSA_WITH_AES_128_GCM_SHA256; */ /* weak - not supported? */
self->ciphersuites[1] = MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
self->ciphersuites[2] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
/* recommended cipher suites by IEC 62351-4:2018 */
/* self->ciphersuites[1] = MBEDTLS_TLS_DH_RSA_WITH_AES_128_CBC_SHA256; */ /* weak - not supported?*/
/* self->ciphersuites[1] = MBEDTLS_TLS_DH_RSA_WITH_AES_256_GCM_SHA384; */ /* not supported?*/
self->ciphersuites[3] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
self->ciphersuites[4] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
self->ciphersuites[5] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
/* additional ciphersuites */
self->ciphersuites[6] = MBEDTLS_TLS_RSA_WITH_NULL_SHA256;
self->ciphersuites[7] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
}
}
return self;
@ -407,11 +492,13 @@ TLSConfiguration_addAllowedCertificate(TLSConfiguration self, uint8_t* certifica
int ret = mbedtls_x509_crt_parse(cert, certificate, certLen);
if (ret == 0) {
if (ret == 0)
{
LinkedList_add(self->allowedCertificates, cert);
return true;
}
else {
else
{
GLOBAL_FREEMEM(cert);
return false;
}
@ -424,11 +511,13 @@ TLSConfiguration_addAllowedCertificateFromFile(TLSConfiguration self, const char
int ret = mbedtls_x509_crt_parse_file(cert, filename);
if (ret == 0) {
if (ret == 0)
{
LinkedList_add(self->allowedCertificates, cert);
return true;
}
else {
else
{
GLOBAL_FREEMEM(cert);
return false;
}
@ -439,7 +528,8 @@ TLSConfiguration_addCACertificate(TLSConfiguration self, uint8_t* certificate, i
{
int ret = mbedtls_x509_crt_parse(&(self->cacerts), certificate, certLen);
if (ret != 0) {
if (ret != 0)
{
DEBUG_PRINT("TLS", "mbedtls_x509_crt_parse returned -0x%x\n", -ret);
return false;
}
@ -469,14 +559,6 @@ udpatedCRL(TLSConfiguration self)
if (mbedtls_ssl_conf_get_endpoint(&(self->conf)) == MBEDTLS_SSL_IS_SERVER)
{
// MIGRATE 2.28->3.x.x: https://github.com/Mbed-TLS/mbedtls/blob/development/docs/3.0-migration-guide.md#most-structure-fields-are-now-private
// mbedtls_ssl_cache_entry *cur = self->cache.chain;
// while (cur) {
// cur->timestamp = 0;
// cur = cur->next;
// }
// TODO: @Michael: Confirm if this is a valid replacement for the above code
mbedtls_ssl_cache_free(&(self->cache));
}
}
@ -528,14 +610,18 @@ TLSConfiguration_setRenegotiationTime(TLSConfiguration self, int timeInMs)
void
TLSConfiguration_destroy(TLSConfiguration self)
{
if (self->useSessionResumption) {
if (mbedtls_ssl_conf_get_endpoint(&(self->conf)) == MBEDTLS_SSL_IS_CLIENT) {
if (self->savedSession) {
if (self->useSessionResumption)
{
if (mbedtls_ssl_conf_get_endpoint(&(self->conf)) == MBEDTLS_SSL_IS_CLIENT)
{
if (self->savedSession)
{
mbedtls_ssl_session_free(self->savedSession);
GLOBAL_FREEMEM(self->savedSession);
}
}
else {
else
{
mbedtls_ssl_cache_free(&(self->cache));
}
}
@ -550,7 +636,8 @@ TLSConfiguration_destroy(TLSConfiguration self)
LinkedList certElem = LinkedList_getNext(self->allowedCertificates);
while (certElem) {
while (certElem)
{
mbedtls_x509_crt* cert = (mbedtls_x509_crt*) LinkedList_getData(certElem);
mbedtls_x509_crt_free(cert);
@ -688,7 +775,8 @@ readFunction(void* ctx, unsigned char* buf, size_t len)
{
int ret = Socket_read((Socket) ctx, buf, (int)len);
if ((ret == 0) && (len > 0)) {
if ((ret == 0) && (len > 0))
{
return MBEDTLS_ERR_SSL_WANT_READ;
}
@ -698,7 +786,14 @@ readFunction(void* ctx, unsigned char* buf, size_t len)
static int
writeFunction(void* ctx, unsigned char* buf, size_t len)
{
return Socket_write((Socket)ctx, buf, (int)len);
int ret = Socket_write((Socket)ctx, buf, (int)len);
if ((ret == 0) && (len > 0))
{
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
return ret;
}
static TLSConfigVersion
@ -707,7 +802,8 @@ getTLSVersion(int majorVersion, int minorVersion)
if (majorVersion != 3) {
return TLS_VERSION_NOT_SELECTED;
}
else {
else
{
switch (minorVersion) {
/* TODO: Remove from here (MIGRATE 2.28->3.x.x) */
case 0:
@ -794,7 +890,8 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
self->crlUpdated = configuration->crlUpdated;
if (configuration->minVersion != TLS_VERSION_NOT_SELECTED) {
if (configuration->minVersion != TLS_VERSION_NOT_SELECTED)
{
/* set minimum TLS version */
int majorVer = getMajorVersion(configuration->minVersion);
@ -803,7 +900,8 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
mbedtls_ssl_conf_min_version( &(self->conf), majorVer, minorVer);
}
if (configuration->maxVersion != TLS_VERSION_NOT_SELECTED) {
if (configuration->maxVersion != TLS_VERSION_NOT_SELECTED)
{
/* set maximum TLS version */
int majorVer = getMajorVersion(configuration->maxVersion);
@ -812,7 +910,8 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
mbedtls_ssl_conf_max_version( &(self->conf), majorVer, minorVer);
}
if (configuration->ownCertificate.version > 0) {
if (configuration->ownCertificate.version > 0)
{
ret = mbedtls_ssl_conf_own_cert( &(self->conf), &(configuration->ownCertificate), &(configuration->ownKey));
if (ret != 0)
@ -827,30 +926,31 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
mbedtls_ssl_set_bio(&(self->ssl), socket, (mbedtls_ssl_send_t*) writeFunction,
(mbedtls_ssl_recv_t*) readFunction, NULL);
bool reuseSession = false;
if (configuration->useSessionResumption) {
if (mbedtls_ssl_conf_get_endpoint(&(configuration->conf)) == MBEDTLS_SSL_IS_CLIENT) {
if (configuration->savedSession && configuration->savedSessionTime > 0) {
if (Hal_getTimeInMs() < (configuration->savedSessionTime + configuration->sessionResumptionInterval * 1000)) {
if (configuration->useSessionResumption)
{
if (mbedtls_ssl_conf_get_endpoint(&(configuration->conf)) == MBEDTLS_SSL_IS_CLIENT)
{
if (configuration->savedSession && configuration->savedSessionTime > 0)
{
if (Hal_getTimeInMs() < (configuration->savedSessionTime + configuration->sessionResumptionInterval * 1000))
{
ret = mbedtls_ssl_set_session(&(self->ssl), configuration->savedSession);
if (ret != 0) {
if (ret != 0)
{
DEBUG_PRINT("TLS", "mbedtls_ssl_set_session returned %d\n", ret);
configuration->savedSessionTime = 0;
}
else {
else
{
DEBUG_PRINT("TLS", "resume TLS session\n");
reuseSession = true;
}
}
else {
else
{
configuration->savedSessionTime = 0;
DEBUG_PRINT("TLS", "cached session expired\n");
}
}
}
}
@ -877,22 +977,27 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
}
}
if (configuration->useSessionResumption) {
if (mbedtls_ssl_conf_get_endpoint(&(configuration->conf)) == MBEDTLS_SSL_IS_CLIENT) {
if (configuration->savedSession == NULL) {
if (configuration->useSessionResumption)
{
if (mbedtls_ssl_conf_get_endpoint(&(configuration->conf)) == MBEDTLS_SSL_IS_CLIENT)
{
if (configuration->savedSession == NULL)
{
configuration->savedSession = (mbedtls_ssl_session*)GLOBAL_CALLOC(1, sizeof(mbedtls_ssl_session));
}
if (configuration->savedSession) {
if (configuration->savedSessionTime == 0) {
if (configuration->savedSession)
{
if (configuration->savedSessionTime == 0)
{
ret = mbedtls_ssl_get_session(&(self->ssl), configuration->savedSession);
if (ret != 0) {
if (ret != 0)
{
DEBUG_PRINT("TLS", "mbedtls_ssl_get_session returned %d\n", ret);
}
else {
else
{
configuration->savedSessionTime = Hal_getTimeInMs();
}
}
@ -907,6 +1012,16 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
// raiseSecurityEvent(configuration, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_INSECURE_TLS_VERSION, "Warning: Insecure TLS version", self);
// }
/* create event that TLS session is established */
{
char msg[256];
const char* cipherSuite = mbedtls_ssl_get_ciphersuite(&(self->ssl));
snprintf(msg, 255, "Info: Session established with cipher suite %s", cipherSuite);
raiseSecurityEvent(configuration, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_ESTABLISHED, msg, self);
}
}
return self;
@ -927,7 +1042,8 @@ TLSSocket_performHandshake(TLSSocket self)
int ret = mbedtls_ssl_renegotiate(&(self->ssl));
if (ret == 0 || ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS || ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS || ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS)
{
// MIGRATE 2.28->3.x.x: impossible since mbedtls 3.x.x doesn't support insecure TLS versions
// 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", self);
@ -940,6 +1056,7 @@ TLSSocket_performHandshake(TLSSocket self)
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Alarm: Renegotiation failed", self);
/* mbedtls_ssl_renegotiate mandates to reset the ssl session in case of errors */
ret = mbedtls_ssl_session_reset(&(self->ssl));
if (ret != 0) {
DEBUG_PRINT("TLS", "mbedtls_ssl_session_reset failed -> ret: -0x%X\n", -ret);
@ -977,7 +1094,8 @@ startRenegotiationIfRequired(TLSSocket self)
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");
return false;
}
@ -1033,8 +1151,7 @@ TLSSocket_read(TLSSocket self, uint8_t* buf, int size)
int
TLSSocket_write(TLSSocket self, uint8_t* buf, int size)
{
int ret;
int len = size;
int len = 0;
checkForCRLUpdate(self);
@ -1042,22 +1159,26 @@ TLSSocket_write(TLSSocket self, uint8_t* buf, int size)
return -1;
}
while ((ret = mbedtls_ssl_write(&(self->ssl), buf, len)) <= 0)
while (len < size)
{
if (ret == MBEDTLS_ERR_NET_CONN_RESET)
{
DEBUG_PRINT("TLS", "peer closed the connection\n");
return -1;
int ret = mbedtls_ssl_write(&(self->ssl), (buf + len), (size -len));
if ((ret == MBEDTLS_ERR_SSL_WANT_READ) || (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ||
(ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) || (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS)) {
continue;
}
if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE))
{
DEBUG_PRINT("TLS", "mbedtls_ssl_write returned %d\n", ret);
if (ret < 0) {
DEBUG_PRINT("TLS", "mbedtls_ssl_write returned -0x%X\n", -ret);
if (0 != (ret = mbedtls_ssl_session_reset(&(self->ssl)))) {
DEBUG_PRINT("TLS", "mbedtls_ssl_session_reset failed -0x%X\n", -ret);
}
return -1;
}
}
len = ret;
len += ret;
}
return len;
}

@ -1,9 +1,33 @@
README
------
For TLS support with mbedtls download the source tarball of version 2.28.x and extract here in the subfolder
At the moment libiec61850 provides support for two versions of mbedtls (2.28 and 3.6).
mbedtls version 2.28 support different TLS versions up to TLS 1.2.
mbedtls version 3.6 only support TLS 1.2 and TLS 1.3. Older versions are not supported.
It is recommended that you use version 3.6 unless you need support for older versions of TLS.
mbedtls-2.28
------------
Download the latest source tarball from version 2.27.x and extract it here in the subfolder mbedtls-2.28
After extracting of the archive you may have to rename the folder to match the exact name "mbedtls-2.28". Otherwise the build system will not find the library.
wget https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/v2.28.8.tar.gz
tar xzf v2.28.8.tar.gz
mv mbedtls-2.28.8 mbedtls-2.28
mbedtls-3.6.0
-------------
You just have to download the archive and extract it in this folder.
wget https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/v3.6.0.tar.gz
tar xzf v3.6.0.tar.gz

Loading…
Cancel
Save