Merge branch 'v1.6_develop' into v1.6_develop_rgoose_sntp__merge_develop

pull/521/head
Michael Zillgith 1 year ago
commit 5d7dd6160b

@ -1,7 +1,7 @@
/* /*
* TLS.cs * TLS.cs
* *
* Copyright 2017-2022 Michael Zillgith * Copyright 2017-2024 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -69,7 +69,9 @@ namespace IEC61850
ALM_CERT_EXPIRED = 11, ALM_CERT_EXPIRED = 11,
ALM_CERT_REVOKED = 12, ALM_CERT_REVOKED = 12,
ALM_CERT_NOT_CONFIGURED = 13, ALM_CERT_NOT_CONFIGURED = 13,
ALM_CERT_NOT_TRUSTED = 14 ALM_CERT_NOT_TRUSTED = 14,
ALM_NO_CIPHER = 15,
INF_SESSION_ESTABLISHED = 16
} }
public class TLSConnection public class TLSConnection
@ -261,6 +263,18 @@ namespace IEC61850
[return: MarshalAs(UnmanagedType.I1)] [return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_addCACertificateFromFile(IntPtr self, string filename); static extern bool TLSConfiguration_addCACertificateFromFile(IntPtr self, string filename);
[DllImport("tase2", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setMinTlsVersion(IntPtr self, int version);
[DllImport("tase2", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setMaxTlsVersion(IntPtr self, int version);
[DllImport("tase2", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_addCipherSuite(IntPtr self, int ciphersuite);
[DllImport("tase2", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_clearCipherSuiteList(IntPtr self);
private TLSEventHandler eventHandler = null; private TLSEventHandler eventHandler = null;
private object eventHandlerParameter = null; private object eventHandlerParameter = null;
@ -417,6 +431,53 @@ namespace IEC61850
} }
} }
/// <summary>
/// Set minimal allowed TLS version to use
/// </summary>
/// <param name="version">lowest allowed TLS version</param>
public void SetMinTlsVersion(TLSConfigVersion version)
{
TLSConfiguration_setMinTlsVersion(self, (int)version);
}
/// <summary>
/// Set highest allowed TLS version to use
/// </summary>
/// <param name="version">highest allowed TLS version</param>
public void SetMaxTlsVersion(TLSConfigVersion version)
{
TLSConfiguration_setMaxTlsVersion(self, (int)version);
}
#if NET
/// <summary>
/// Add an allowed ciphersuite to the list of allowed ciphersuites
/// </summary>
/// <param name="ciphersuite"></param>
public void addCipherSuite(TlsCipherSuite ciphersuite)
{
TLSConfiguration_addCipherSuite(self,(int) ciphersuite);
}
#endif
/// <summary>
/// Add an allowed ciphersuite to the list of allowed ciphersuites
/// </summary>
/// <remarks>Version for .NET framework that does not support TlsCipherSuite enum</remarks>
/// <param name="ciphersuite"></param>
public void addCipherSuite(int ciphersuite)
{
TLSConfiguration_addCipherSuite(self, ciphersuite);
}
/// <summary>
/// Clears list of allowed ciphersuites
/// </summary>
/// <returns></returns>
public void clearCipherSuiteList()
{
TLSConfiguration_clearCipherSuiteList(self);
}
public void Dispose() public void Dispose()
{ {
lock (this) lock (this)

@ -0,0 +1,262 @@
#ifndef IANA_TLS_CIPHER_SUITES_H_
#define IANA_TLS_CIPHER_SUITES_H_
#ifdef __cplusplus
extern "C" {
#endif
#define TLS_NULL_WITH_NULL_NULL 0x0000
#define TLS_RSA_WITH_NULL_MD5 0x0001
#define TLS_RSA_WITH_NULL_SHA 0x0002
#define TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003
#define TLS_RSA_WITH_RC4_128_MD5 0x0004
#define TLS_RSA_WITH_RC4_128_SHA 0x0005
#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 0x0006
#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007
#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0008
#define TLS_RSA_WITH_DES_CBC_SHA 0x0009
#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A
#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA 0x000B
#define TLS_DH_DSS_WITH_DES_CBC_SHA 0x000C
#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D
#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA 0x000E
#define TLS_DH_RSA_WITH_DES_CBC_SHA 0x000F
#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010
#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA 0x0011
#define TLS_DHE_DSS_WITH_DES_CBC_SHA 0x0012
#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013
#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0014
#define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x0015
#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016
#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 0x0017
#define TLS_DH_anon_WITH_RC4_128_MD5 0x0018
#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA 0x0019
#define TLS_DH_anon_WITH_DES_CBC_SHA 0x001A
#define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B
#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F
#define TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030
#define TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031
#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032
#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033
#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034
#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
#define TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036
#define TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037
#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038
#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039
#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A
#define TLS_RSA_WITH_NULL_SHA256 0x003B
#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C
#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D
#define TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E
#define TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F
#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040
#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0041
#define TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x0042
#define TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0043
#define TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x0044
#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0045
#define TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA 0x0046
#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067
#define TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068
#define TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069
#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A
#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B
#define TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C
#define TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D
#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0084
#define TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x0085
#define TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0086
#define TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x0087
#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0088
#define TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA 0x0089
#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096
#define TLS_DH_DSS_WITH_SEED_CBC_SHA 0x0097
#define TLS_DH_RSA_WITH_SEED_CBC_SHA 0x0098
#define TLS_DHE_DSS_WITH_SEED_CBC_SHA 0x0099
#define TLS_DHE_RSA_WITH_SEED_CBC_SHA 0x009A
#define TLS_DH_anon_WITH_SEED_CBC_SHA 0x009B
#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C
#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D
#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E
#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F
#define TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0
#define TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1
#define TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2
#define TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3
#define TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4
#define TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5
#define TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6
#define TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7
#define TLS_PSK_WITH_AES_128_CBC_SHA 0x008C
#define TLS_PSK_WITH_AES_256_CBC_SHA 0x008D
#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x008E
#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x008F
#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x0090
#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x0091
#define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE
#define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF
#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0x00B0
#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0x00B1
#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0x00B2
#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0x00B3
#define TLS_PSK_WITH_NULL_SHA 0x002C
#define TLS_DHE_PSK_WITH_NULL_SHA 0x002D
#define TLS_RSA_PSK_WITH_NULL_SHA 0x002E
#define TLS_PSK_WITH_NULL_SHA256 0x00B4
#define TLS_PSK_WITH_NULL_SHA384 0x00B5
#define TLS_DHE_PSK_WITH_NULL_SHA256 0x00B6
#define TLS_DHE_PSK_WITH_NULL_SHA384 0x00B7
#define TLS_RSA_PSK_WITH_NULL_SHA256 0x00B8
#define TLS_RSA_PSK_WITH_NULL_SHA384 0x00B9
#define TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001
#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002
#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003
#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004
#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005
#define TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006
#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007
#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008
#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009
#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A
#define TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B
#define TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C
#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D
#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E
#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F
#define TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010
#define TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011
#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012
#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013
#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014
#define TLS_ECDH_anon_WITH_NULL_SHA 0xC015
#define TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016
#define TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017
#define TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018
#define TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019
#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023
#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024
#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025
#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026
#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027
#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028
#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029
#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A
#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B
#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C
#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D
#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E
#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F
#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030
#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031
#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032
#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035
#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036
#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037
#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038
#define TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039
#define TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A
#define TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B
#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072
#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073
#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074
#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075
#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076
#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077
#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078
#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079
#define TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C
#define TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D
#define TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 0xC03E
#define TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 0xC03F
#define TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 0xC040
#define TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 0xC041
#define TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 0xC042
#define TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 0xC043
#define TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC044
#define TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC045
#define TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 0xC046
#define TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 0xC047
#define TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048
#define TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049
#define TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC04A
#define TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC04B
#define TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC04C
#define TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC04D
#define TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 0xC04E
#define TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 0xC04F
#define TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050
#define TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051
#define TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052
#define TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053
#define TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 0xC054
#define TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 0xC055
#define TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 0xC056
#define TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 0xC057
#define TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 0xC058
#define TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 0xC059
#define TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 0xC05A
#define TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 0xC05B
#define TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C
#define TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D
#define TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05E
#define TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05F
#define TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060
#define TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061
#define TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0xC062
#define TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0xC063
#define TLS_PSK_WITH_ARIA_128_CBC_SHA256 0xC064
#define TLS_PSK_WITH_ARIA_256_CBC_SHA384 0xC065
#define TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC066
#define TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC067
#define TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 0xC068
#define TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 0xC069
#define TLS_PSK_WITH_ARIA_128_GCM_SHA256 0xC06A
#define TLS_PSK_WITH_ARIA_256_GCM_SHA384 0xC06B
#define TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0xC06C
#define TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0xC06D
#define TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0xC06E
#define TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0xC06F
#define TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070
#define TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071
#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC076
#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC077
#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC078
#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC079
#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A
#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B
#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C
#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D
#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC07E
#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC07F
#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC080
#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC081
#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC082
#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC083
#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC084
#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC085
#define TLS_RSA_WITH_AES_128_CCM 0xC09C
#define TLS_RSA_WITH_AES_256_CCM 0xC09D
#define TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E
#define TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F
#define TLS_RSA_WITH_AES_128_CCM_8 0xC0A0
#define TLS_RSA_WITH_AES_256_CCM_8 0xC0A1
#define TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2
#define TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3
#define TLS_PSK_WITH_AES_128_CCM 0xC0A4
#define TLS_PSK_WITH_AES_256_CCM 0xC0A5
#define TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6
#define TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7
#define TLS_PSK_WITH_AES_128_CCM_8 0xC0A8
#define TLS_PSK_WITH_AES_256_CCM_8 0xC0A9
#define TLS_PSK_DHE_WITH_AES_128_CCM_8 0xC0AA
#define TLS_PSK_DHE_WITH_AES_256_CCM_8 0xC0AB
#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC
// ... add more cipher suite codes here ...
#ifdef __cplusplus
}
#endif
#endif /* IANA_TLS_CIPHER_SUITES_H_ */

@ -3,7 +3,7 @@
* *
* TLS Configuration API for protocol stacks using TCP/IP * TLS Configuration API for protocol stacks using TCP/IP
* *
* Copyright 2017-2022 Michael Zillgith * Copyright 2017-2024 Michael Zillgith
* *
* Abstraction layer for configuration of different TLS implementations * Abstraction layer for configuration of different TLS implementations
* *
@ -17,6 +17,7 @@ extern "C" {
#endif #endif
#include "hal_base.h" #include "hal_base.h"
#include "tls_ciphers.h"
/** /**
* \file tls_config.h * \file tls_config.h
@ -90,6 +91,7 @@ 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 14 #define TLS_EVENT_CODE_ALM_CERT_NOT_TRUSTED 14
#define TLS_EVENT_CODE_ALM_NO_CIPHER 15 #define TLS_EVENT_CODE_ALM_NO_CIPHER 15
#define TLS_EVENT_CODE_INF_SESSION_ESTABLISHED 16
typedef struct sTLSConnection* TLSConnection; typedef struct sTLSConnection* TLSConnection;
@ -303,6 +305,23 @@ TLSConfiguration_addCRLFromFile(TLSConfiguration self, const char* filename);
PAL_API void PAL_API void
TLSConfiguration_resetCRL(TLSConfiguration self); TLSConfiguration_resetCRL(TLSConfiguration self);
/**
* \brief Add an allowed ciphersuite to the list of allowed ciphersuites
*
* \param self the TLS configuration instance
* \param ciphersuite the ciphersuite to add (IANA cipher suite ID)
*/
PAL_API void
TLSConfiguration_addCipherSuite(TLSConfiguration self, int ciphersuite);
/**
* \brief Clear the list of allowed ciphersuites
*
* \param self the TLS configuration instance
*/
PAL_API void
TLSConfiguration_clearCipherSuiteList(TLSConfiguration self);
/** /**
* Release all resource allocated by the TLSConfiguration instance * Release all resource allocated by the TLSConfiguration instance
* *

@ -17,6 +17,8 @@
#define MBEDTLS_SSL_PROTO_TLS1_1 #define MBEDTLS_SSL_PROTO_TLS1_1
#define MBEDTLS_SSL_PROTO_TLS1 #define MBEDTLS_SSL_PROTO_TLS1
#define MBEDTLS_SSL_RENEGOTIATION #define MBEDTLS_SSL_RENEGOTIATION
#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES
#define MBEDTLS_CIPHER_NULL_CIPHER
#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES

@ -3,7 +3,7 @@
* *
* TLS API for TCP/IP protocol stacks * 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 * Implementation of the TLS abstraction layer for mbedtls
* *
@ -20,7 +20,6 @@
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#include "mbedtls/entropy.h" #include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h" #include "mbedtls/ctr_drbg.h"
#include "mbedtls/certs.h"
#include "mbedtls/x509.h" #include "mbedtls/x509.h"
#include "mbedtls/ssl.h" #include "mbedtls/ssl.h"
#include "mbedtls/net_sockets.h" #include "mbedtls/net_sockets.h"
@ -86,6 +85,9 @@ struct sTLSConfiguration {
bool useSessionResumption; bool useSessionResumption;
int sessionResumptionInterval; /* session resumption interval in seconds */ int sessionResumptionInterval; /* session resumption interval in seconds */
int* ciphersuites;
int maxCiphersuites;
}; };
struct sTLSSocket { struct sTLSSocket {
@ -115,9 +117,10 @@ raiseSecurityEvent(TLSConfiguration config, TLSEventLevel eventCategory, int eve
static bool static bool
compareCertificates(mbedtls_x509_crt *crt1, mbedtls_x509_crt *crt2) compareCertificates(mbedtls_x509_crt *crt1, mbedtls_x509_crt *crt2)
{ {
if (crt1 != NULL && crt2 != NULL) { if (crt1 != NULL && crt2 != NULL)
{
if (crt1->sig.len == crt2->sig.len) { if (crt1->sig.len == crt2->sig.len)
{
if (memcmp(crt1->sig.p, crt2->sig.p, crt1->sig.len) == 0) if (memcmp(crt1->sig.p, crt2->sig.p, crt1->sig.len) == 0)
return true; return true;
} }
@ -142,28 +145,32 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
DEBUG_PRINT("TLS", "%s\n", buffer); DEBUG_PRINT("TLS", "%s\n", buffer);
if (self->tlsConfig->chainValidation == false) { if (self->tlsConfig->chainValidation == false)
{
if (certificate_depth != 0) if (certificate_depth != 0)
*flags = 0; *flags = 0;
} }
if (certificate_depth == 0) { if (certificate_depth == 0)
if (self->tlsConfig->allowOnlyKnownCertificates) { {
if (self->tlsConfig->allowOnlyKnownCertificates)
{
DEBUG_PRINT("TLS", "Check against list of allowed certs\n"); DEBUG_PRINT("TLS", "Check against list of allowed certs\n");
bool certMatches = false; bool certMatches = false;
LinkedList certList = LinkedList_getNext(self->tlsConfig->allowedCertificates); LinkedList certList = LinkedList_getNext(self->tlsConfig->allowedCertificates);
while (certList) { while (certList)
{
mbedtls_x509_crt* allowedCert = (mbedtls_x509_crt*) LinkedList_getData(certList); mbedtls_x509_crt* allowedCert = (mbedtls_x509_crt*) LinkedList_getData(certList);
DEBUG_PRINT("TLS", "Compare With:\n"); DEBUG_PRINT("TLS", "Compare With:\n");
mbedtls_x509_crt_info(buffer, 1023, " ", allowedCert); mbedtls_x509_crt_info(buffer, 1023, " ", allowedCert);
DEBUG_PRINT("TLS", "%s\n", buffer); DEBUG_PRINT("TLS", "%s\n", buffer);
if (compareCertificates(allowedCert, crt)) { if (compareCertificates(allowedCert, crt))
{
certMatches = true; certMatches = true;
break; break;
} }
@ -173,7 +180,8 @@ 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, "Alarm: certificate validation: trusted individual certificate not available", self); 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; *flags |= MBEDTLS_X509_BADCERT_OTHER;
@ -181,20 +189,19 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
} }
} }
if (self->storePeerCert) { if (self->storePeerCert)
{
if (*flags == 0) { if (*flags == 0)
{
self->peerCertLength = 0; self->peerCertLength = 0;
self->peerCert = (uint8_t*) GLOBAL_MALLOC(crt->raw.len); self->peerCert = (uint8_t*) GLOBAL_MALLOC(crt->raw.len);
if (self->peerCert) { if (self->peerCert)
{
self->peerCertLength = (int)crt->raw.len; self->peerCertLength = (int)crt->raw.len;
memcpy(self->peerCert, crt->raw.p, self->peerCertLength); memcpy(self->peerCert, crt->raw.p, self->peerCertLength);
} }
} }
} }
} }
@ -207,10 +214,12 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
static bool static bool
TLSConfiguration_setupComplete(TLSConfiguration self) TLSConfiguration_setupComplete(TLSConfiguration self)
{ {
if (self->setupComplete == false) { if (self->setupComplete == false)
{
mbedtls_ssl_conf_ca_chain( &(self->conf), &(self->cacerts), &(self->crl) ); 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)); int ret = mbedtls_ssl_conf_own_cert( &(self->conf), &(self->ownCertificate), &(self->ownKey));
if (ret != 0) { if (ret != 0) {
@ -219,11 +228,13 @@ TLSConfiguration_setupComplete(TLSConfiguration self)
} }
} }
if (self->useSessionResumption) { if (self->useSessionResumption)
{
if (self->conf.endpoint == MBEDTLS_SSL_IS_CLIENT) { if (self->conf.endpoint == MBEDTLS_SSL_IS_CLIENT) {
} }
else { else
{
mbedtls_ssl_cache_init( &(self->cache) ); mbedtls_ssl_cache_init( &(self->cache) );
self->cache.timeout = self->sessionResumptionInterval; self->cache.timeout = self->sessionResumptionInterval;
@ -234,18 +245,71 @@ TLSConfiguration_setupComplete(TLSConfiguration self)
} }
} }
mbedtls_ssl_conf_ciphersuites(&(self->conf), self->ciphersuites);
self->setupComplete = true; self->setupComplete = true;
} }
return 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
TLSConfiguration_create() TLSConfiguration_create()
{ {
TLSConfiguration self = (TLSConfiguration) GLOBAL_CALLOC(1, sizeof(struct sTLSConfiguration)); TLSConfiguration self = (TLSConfiguration) GLOBAL_CALLOC(1, sizeof(struct sTLSConfiguration));
if (self != NULL) { if (self != NULL)
{
mbedtls_ssl_config_init( &(self->conf) ); mbedtls_ssl_config_init( &(self->conf) );
mbedtls_x509_crt_init( &(self->ownCertificate) ); mbedtls_x509_crt_init( &(self->ownCertificate) );
mbedtls_x509_crt_init( &(self->cacerts) ); mbedtls_x509_crt_init( &(self->cacerts) );
@ -267,10 +331,7 @@ TLSConfiguration_create()
mbedtls_ssl_conf_renegotiation(&(self->conf), MBEDTLS_SSL_RENEGOTIATION_ENABLED); mbedtls_ssl_conf_renegotiation(&(self->conf), MBEDTLS_SSL_RENEGOTIATION_ENABLED);
/* static int hashes[] = {3,4,5,6,7,8,0}; */ self->minVersion = TLS_VERSION_TLS_1_2;
/* mbedtls_ssl_conf_sig_hashes(&(self->conf), hashes); */
self->minVersion = TLS_VERSION_TLS_1_0;
self->maxVersion = TLS_VERSION_NOT_SELECTED; self->maxVersion = TLS_VERSION_NOT_SELECTED;
self->renegotiationTimeInMs = -1; /* no automatic renegotiation */ self->renegotiationTimeInMs = -1; /* no automatic renegotiation */
@ -289,6 +350,31 @@ TLSConfiguration_create()
self->sessionResumptionInterval = 21600; /* default value: 6h */ self->sessionResumptionInterval = 21600; /* default value: 6h */
self->savedSession = NULL; self->savedSession = NULL;
self->savedSessionTime = 0; 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; return self;
@ -394,11 +480,13 @@ TLSConfiguration_addAllowedCertificate(TLSConfiguration self, uint8_t* certifica
int ret = mbedtls_x509_crt_parse(cert, certificate, certLen); int ret = mbedtls_x509_crt_parse(cert, certificate, certLen);
if (ret == 0) { if (ret == 0)
{
LinkedList_add(self->allowedCertificates, cert); LinkedList_add(self->allowedCertificates, cert);
return true; return true;
} }
else { else
{
GLOBAL_FREEMEM(cert); GLOBAL_FREEMEM(cert);
return false; return false;
} }
@ -411,11 +499,13 @@ TLSConfiguration_addAllowedCertificateFromFile(TLSConfiguration self, const char
int ret = mbedtls_x509_crt_parse_file(cert, filename); int ret = mbedtls_x509_crt_parse_file(cert, filename);
if (ret == 0) { if (ret == 0)
{
LinkedList_add(self->allowedCertificates, cert); LinkedList_add(self->allowedCertificates, cert);
return true; return true;
} }
else { else
{
GLOBAL_FREEMEM(cert); GLOBAL_FREEMEM(cert);
return false; return false;
} }
@ -426,7 +516,8 @@ TLSConfiguration_addCACertificate(TLSConfiguration self, uint8_t* certificate, i
{ {
int ret = mbedtls_x509_crt_parse(&(self->cacerts), certificate, certLen); 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); DEBUG_PRINT("TLS", "mbedtls_x509_crt_parse returned -0x%x\n", -ret);
return false; return false;
} }
@ -458,7 +549,8 @@ udpatedCRL(TLSConfiguration self)
{ {
mbedtls_ssl_cache_entry *cur = self->cache.chain; mbedtls_ssl_cache_entry *cur = self->cache.chain;
while (cur) { while (cur)
{
cur->timestamp = 0; cur->timestamp = 0;
cur = cur->next; cur = cur->next;
} }
@ -512,14 +604,18 @@ TLSConfiguration_setRenegotiationTime(TLSConfiguration self, int timeInMs)
void void
TLSConfiguration_destroy(TLSConfiguration self) TLSConfiguration_destroy(TLSConfiguration self)
{ {
if (self->useSessionResumption) { if (self->useSessionResumption)
if (self->conf.endpoint == MBEDTLS_SSL_IS_CLIENT) { {
if (self->savedSession) { if (self->conf.endpoint == MBEDTLS_SSL_IS_CLIENT)
{
if (self->savedSession)
{
mbedtls_ssl_session_free(self->savedSession); mbedtls_ssl_session_free(self->savedSession);
GLOBAL_FREEMEM(self->savedSession); GLOBAL_FREEMEM(self->savedSession);
} }
} }
else { else
{
mbedtls_ssl_cache_free(&(self->cache)); mbedtls_ssl_cache_free(&(self->cache));
} }
} }
@ -532,7 +628,8 @@ TLSConfiguration_destroy(TLSConfiguration self)
LinkedList certElem = LinkedList_getNext(self->allowedCertificates); LinkedList certElem = LinkedList_getNext(self->allowedCertificates);
while (certElem) { while (certElem)
{
mbedtls_x509_crt* cert = (mbedtls_x509_crt*) LinkedList_getData(certElem); mbedtls_x509_crt* cert = (mbedtls_x509_crt*) LinkedList_getData(certElem);
mbedtls_x509_crt_free(cert); mbedtls_x509_crt_free(cert);
@ -621,7 +718,8 @@ readFunction(void* ctx, unsigned char* buf, size_t len)
{ {
int ret = Socket_read((Socket) ctx, buf, (int)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; return MBEDTLS_ERR_SSL_WANT_READ;
} }
@ -631,7 +729,14 @@ readFunction(void* ctx, unsigned char* buf, size_t len)
static int static int
writeFunction(void* ctx, unsigned char* buf, size_t len) 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 static TLSConfigVersion
@ -640,7 +745,8 @@ getTLSVersion(int majorVersion, int minorVersion)
if (majorVersion != 3) { if (majorVersion != 3) {
return TLS_VERSION_NOT_SELECTED; return TLS_VERSION_NOT_SELECTED;
} }
else { else
{
switch (minorVersion) { switch (minorVersion) {
case 0: case 0:
return TLS_VERSION_SSL_3_0; return TLS_VERSION_SSL_3_0;
@ -721,7 +827,8 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
self->crlUpdated = configuration->crlUpdated; self->crlUpdated = configuration->crlUpdated;
if (configuration->minVersion != TLS_VERSION_NOT_SELECTED) { if (configuration->minVersion != TLS_VERSION_NOT_SELECTED)
{
/* set minimum TLS version */ /* set minimum TLS version */
int majorVer = getMajorVersion(configuration->minVersion); int majorVer = getMajorVersion(configuration->minVersion);
@ -730,7 +837,8 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
mbedtls_ssl_conf_min_version( &(self->conf), majorVer, minorVer); 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 */ /* set maximum TLS version */
int majorVer = getMajorVersion(configuration->maxVersion); int majorVer = getMajorVersion(configuration->maxVersion);
@ -739,7 +847,8 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
mbedtls_ssl_conf_max_version( &(self->conf), majorVer, minorVer); 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)); ret = mbedtls_ssl_conf_own_cert( &(self->conf), &(configuration->ownCertificate), &(configuration->ownKey));
if (ret != 0) if (ret != 0)
@ -754,30 +863,31 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
mbedtls_ssl_set_bio(&(self->ssl), socket, (mbedtls_ssl_send_t*) writeFunction, mbedtls_ssl_set_bio(&(self->ssl), socket, (mbedtls_ssl_send_t*) writeFunction,
(mbedtls_ssl_recv_t*) readFunction, NULL); (mbedtls_ssl_recv_t*) readFunction, NULL);
bool reuseSession = false; if (configuration->useSessionResumption)
{
if (configuration->useSessionResumption) { if (configuration->conf.endpoint == MBEDTLS_SSL_IS_CLIENT)
if (configuration->conf.endpoint == MBEDTLS_SSL_IS_CLIENT) { {
if (configuration->savedSession && configuration->savedSessionTime > 0) { if (configuration->savedSession && configuration->savedSessionTime > 0)
{
if (Hal_getTimeInMs() < (configuration->savedSessionTime + configuration->sessionResumptionInterval * 1000)) { if (Hal_getTimeInMs() < (configuration->savedSessionTime + configuration->sessionResumptionInterval * 1000))
{
ret = mbedtls_ssl_set_session(&(self->ssl), configuration->savedSession); 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); DEBUG_PRINT("TLS", "mbedtls_ssl_set_session returned %d\n", ret);
configuration->savedSessionTime = 0; configuration->savedSessionTime = 0;
} }
else { else
{
DEBUG_PRINT("TLS", "resume TLS session\n"); DEBUG_PRINT("TLS", "resume TLS session\n");
reuseSession = true;
} }
} }
else { else
{
configuration->savedSessionTime = 0; configuration->savedSessionTime = 0;
DEBUG_PRINT("TLS", "cached session expired\n"); DEBUG_PRINT("TLS", "cached session expired\n");
} }
} }
} }
} }
@ -804,22 +914,27 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
} }
} }
if (configuration->useSessionResumption) { if (configuration->useSessionResumption)
if (configuration->conf.endpoint == MBEDTLS_SSL_IS_CLIENT) { {
if (configuration->conf.endpoint == MBEDTLS_SSL_IS_CLIENT)
if (configuration->savedSession == NULL) { {
if (configuration->savedSession == NULL)
{
configuration->savedSession = (mbedtls_ssl_session*)GLOBAL_CALLOC(1, sizeof(mbedtls_ssl_session)); configuration->savedSession = (mbedtls_ssl_session*)GLOBAL_CALLOC(1, sizeof(mbedtls_ssl_session));
} }
if (configuration->savedSession) { if (configuration->savedSession)
{
if (configuration->savedSessionTime == 0) { if (configuration->savedSessionTime == 0)
{
ret = mbedtls_ssl_get_session(&(self->ssl), configuration->savedSession); 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); DEBUG_PRINT("TLS", "mbedtls_ssl_get_session returned %d\n", ret);
} }
else { else
{
configuration->savedSessionTime = Hal_getTimeInMs(); configuration->savedSessionTime = Hal_getTimeInMs();
} }
} }
@ -833,6 +948,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); 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; return self;
@ -853,17 +978,18 @@ TLSSocket_performHandshake(TLSSocket self)
int ret = mbedtls_ssl_renegotiate(&(self->ssl)); int ret = mbedtls_ssl_renegotiate(&(self->ssl));
if (ret == 0 || ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE || 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)
{
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", self); raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_INSECURE_TLS_VERSION, "Warning: Insecure TLS version", self);
} }
DEBUG_PRINT("TLS", "TLSSocket_performHandshake Success -> ret=%i\n", ret); DEBUG_PRINT("TLS", "TLSSocket_performHandshake Success -> ret=%i\n", ret);
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "TLS session renegotiation completed", self); raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "TLS session renegotiation completed", self);
return true; return true;
} }
else { else
{
DEBUG_PRINT("TLS", "TLSSocket_performHandshake failed -> ret=%i\n", ret); DEBUG_PRINT("TLS", "TLSSocket_performHandshake failed -> ret=%i\n", ret);
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Alarm: TLS session renegotiation failed", self); raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Alarm: TLS session renegotiation failed", self);
@ -904,10 +1030,17 @@ startRenegotiationIfRequired(TLSSocket self)
if (Hal_getTimeInMs() <= self->lastRenegotiationTime + self->tlsConfig->renegotiationTimeInMs) if (Hal_getTimeInMs() <= self->lastRenegotiationTime + self->tlsConfig->renegotiationTimeInMs)
return true; return true;
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; return false;
}
DEBUG_PRINT("TLS", " started renegotiation\n");
self->lastRenegotiationTime = Hal_getTimeInMs(); self->lastRenegotiationTime = Hal_getTimeInMs();
return true; return true;
} }
@ -1024,7 +1157,6 @@ TLSSocket_close(TLSSocket self)
if (self->peerCert) if (self->peerCert)
GLOBAL_FREEMEM(self->peerCert); GLOBAL_FREEMEM(self->peerCert);
GLOBAL_FREEMEM(self); GLOBAL_FREEMEM(self);
} }

@ -667,7 +667,8 @@ DataObject_create(const char* name, ModelNode* parent, int arrayElements)
{ {
DataObject* arrayElement = (DataObject*) GLOBAL_MALLOC(sizeof(DataObject)); DataObject* arrayElement = (DataObject*) GLOBAL_MALLOC(sizeof(DataObject));
if (arrayElement) { if (arrayElement)
{
arrayElement->name = NULL; arrayElement->name = NULL;
arrayElement->modelType = DataObjectModelType; arrayElement->modelType = DataObjectModelType;
arrayElement->firstChild = NULL; arrayElement->firstChild = NULL;

@ -707,26 +707,30 @@ ModelNode_getChild(ModelNode* self, const char* name)
/* check for array separator */ /* check for array separator */
const char* arraySeparator = strchr(name, '('); const char* arraySeparator = strchr(name, '(');
if (arraySeparator) { if (arraySeparator)
{
const char* arraySeparator2 = strchr(arraySeparator, ')'); const char* arraySeparator2 = strchr(arraySeparator, ')');
if (arraySeparator2) { if (arraySeparator2)
{
int idx = (int) strtol(arraySeparator + 1, NULL, 10); int idx = (int) strtol(arraySeparator + 1, NULL, 10);
ModelNode* arrayNode = NULL; ModelNode* arrayNode = NULL;
if (name == arraySeparator) { if (name == arraySeparator)
{
arrayNode = ModelNode_getChildWithIdx(self, idx); arrayNode = ModelNode_getChildWithIdx(self, idx);
} }
else { else
{
char nameCopy[65]; char nameCopy[65];
const char* pos = name; const char* pos = name;
int cpyIdx = 0; int cpyIdx = 0;
while (pos < arraySeparator) { while (pos < arraySeparator)
{
nameCopy[cpyIdx] = *pos; nameCopy[cpyIdx] = *pos;
cpyIdx++; cpyIdx++;
pos++; pos++;
@ -743,18 +747,19 @@ ModelNode_getChild(ModelNode* self, const char* name)
return NULL; return NULL;
} }
if (arrayNode) { if (arrayNode)
{
if (*(arraySeparator2 + 1) == 0) { if (*(arraySeparator2 + 1) == 0)
{
return arrayNode; return arrayNode;
} }
else { else
{
if (*(arraySeparator2 + 1) == '.') if (*(arraySeparator2 + 1) == '.')
return ModelNode_getChild(arrayNode, arraySeparator2 + 2); return ModelNode_getChild(arrayNode, arraySeparator2 + 2);
else else
return ModelNode_getChild(arrayNode, arraySeparator2 + 1); return ModelNode_getChild(arrayNode, arraySeparator2 + 1);
} }
} }
else else
return NULL; return NULL;
@ -787,7 +792,8 @@ ModelNode_getChild(ModelNode* self, const char* name)
if (nodeNameLen == nameElementLength) if (nodeNameLen == nameElementLength)
{ {
if (memcmp(nextNode->name, name, nodeNameLen) == 0) { if (memcmp(nextNode->name, name, nodeNameLen) == 0)
{
matchingNode = nextNode; matchingNode = nextNode;
break; break;
} }
@ -816,7 +822,8 @@ ModelNode_getChildWithIdx(ModelNode* self, int idx)
while (nextNode) while (nextNode)
{ {
if (currentIdx == idx) { if (currentIdx == idx)
{
foundElement = nextNode; foundElement = nextNode;
break; break;
} }
@ -855,7 +862,8 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint
{ {
if (memcmp(nextNode->name, name, nodeNameLen) == 0) if (memcmp(nextNode->name, name, nodeNameLen) == 0)
{ {
if (separator == NULL) { if (separator == NULL)
{
if (nextNode->modelType == DataAttributeModelType) if (nextNode->modelType == DataAttributeModelType)
{ {
DataAttribute* da = (DataAttribute*) nextNode; DataAttribute* da = (DataAttribute*) nextNode;
@ -872,7 +880,8 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint
{ {
DataAttribute* da = (DataAttribute*) nextNode; DataAttribute* da = (DataAttribute*) nextNode;
if (da->fc == fc) { if (da->fc == fc)
{
matchingNode = nextNode; matchingNode = nextNode;
break; break;
} }
@ -881,7 +890,6 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint
matchingNode = nextNode; matchingNode = nextNode;
break; break;
} }
} }
} }
} }

@ -111,13 +111,15 @@ preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* in
else else
Ethernet_getInterfaceMACAddress(CONFIG_ETHERNET_INTERFACE_ID, srcAddr); Ethernet_getInterfaceMACAddress(CONFIG_ETHERNET_INTERFACE_ID, srcAddr);
if (parameters == NULL) { if (parameters == NULL)
{
dstAddr = defaultDstAddr; dstAddr = defaultDstAddr;
priority = CONFIG_SV_DEFAULT_PRIORITY; priority = CONFIG_SV_DEFAULT_PRIORITY;
vlanId = CONFIG_SV_DEFAULT_VLAN_ID; vlanId = CONFIG_SV_DEFAULT_VLAN_ID;
appId = CONFIG_SV_DEFAULT_APPID; appId = CONFIG_SV_DEFAULT_APPID;
} }
else { else
{
dstAddr = parameters->dstAddress; dstAddr = parameters->dstAddress;
priority = parameters->vlanPriority; priority = parameters->vlanPriority;
vlanId = parameters->vlanId; vlanId = parameters->vlanId;
@ -129,8 +131,8 @@ preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* in
else else
self->ethernetSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, dstAddr); self->ethernetSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, dstAddr);
if (self->ethernetSocket == NULL) { if (self->ethernetSocket == NULL)
{
if (DEBUG_SV_PUBLISHER) if (DEBUG_SV_PUBLISHER)
printf("SV_PUBLISHER: Failed to allocate Ethernet interface\n"); printf("SV_PUBLISHER: Failed to allocate Ethernet interface\n");
@ -139,13 +141,15 @@ preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* in
self->buffer = (uint8_t*) GLOBAL_MALLOC(SV_MAX_MESSAGE_SIZE); self->buffer = (uint8_t*) GLOBAL_MALLOC(SV_MAX_MESSAGE_SIZE);
if (self->buffer) { if (self->buffer)
{
memcpy(self->buffer, dstAddr, 6); memcpy(self->buffer, dstAddr, 6);
memcpy(self->buffer + 6, srcAddr, 6); memcpy(self->buffer + 6, srcAddr, 6);
int bufPos = 12; int bufPos = 12;
if (useVlanTags) { if (useVlanTags)
{
/* Priority tag - IEEE 802.1Q */ /* Priority tag - IEEE 802.1Q */
self->buffer[bufPos++] = 0x81; self->buffer[bufPos++] = 0x81;
self->buffer[bufPos++] = 0x00; self->buffer[bufPos++] = 0x00;
@ -183,7 +187,8 @@ preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* in
self->payloadStart = bufPos; self->payloadStart = bufPos;
} }
else { else
{
return false; return false;
} }
@ -303,11 +308,13 @@ SVPublisher_createEx(CommParameters* parameters, const char* interfaceId, bool u
{ {
SVPublisher self = (SVPublisher) GLOBAL_CALLOC(1, sizeof(struct sSVPublisher)); SVPublisher self = (SVPublisher) GLOBAL_CALLOC(1, sizeof(struct sSVPublisher));
if (self) { if (self)
{
self->asduList = NULL; self->asduList = NULL;
self->lengthField = 0; self->lengthField = 0;
if (preparePacketBuffer(self, parameters, interfaceId, useVlanTag) == false) { if (preparePacketBuffer(self, parameters, interfaceId, useVlanTag) == false)
{
SVPublisher_destroy(self); SVPublisher_destroy(self);
self = NULL; self = NULL;
} }
@ -337,10 +344,11 @@ SVPublisher_addASDU(SVPublisher self, const char* svID, const char* datset, uint
/* append new ASDU to list */ /* append new ASDU to list */
if (self->asduList == NULL) if (self->asduList == NULL)
self->asduList = newAsdu; self->asduList = newAsdu;
else { else
{
SVPublisher_ASDU lastAsdu = self->asduList; SVPublisher_ASDU lastAsdu = self->asduList;
while (lastAsdu->_next != NULL) while (lastAsdu->_next)
lastAsdu = lastAsdu->_next; lastAsdu = lastAsdu->_next;
lastAsdu->_next = newAsdu; lastAsdu->_next = newAsdu;
@ -359,7 +367,8 @@ SVPublisher_ASDU_getEncodedSize(SVPublisher_ASDU self)
encodedSize += (1 + BerEncoder_determineLengthSize(svIdLen) + svIdLen); encodedSize += (1 + BerEncoder_determineLengthSize(svIdLen) + svIdLen);
/* datset */ /* datset */
if (self->datset != NULL) { if (self->datset)
{
int datSetLen = strlen(self->datset); int datSetLen = strlen(self->datset);
encodedSize += (1 + BerEncoder_determineLengthSize(datSetLen) + datSetLen); encodedSize += (1 + BerEncoder_determineLengthSize(datSetLen) + datSetLen);
} }
@ -417,7 +426,8 @@ SVPublisher_ASDU_encodeToBuffer(SVPublisher_ASDU self, uint8_t* buffer, int bufP
bufPos = encodeUInt32FixedSize(self->confRev, buffer, bufPos); bufPos = encodeUInt32FixedSize(self->confRev, buffer, bufPos);
/* RefrTm */ /* RefrTm */
if (self->hasRefrTm) { if (self->hasRefrTm)
{
bufPos = BerEncoder_encodeTL(0x84, 8, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x84, 8, buffer, bufPos);
self->refrTm = (Timestamp*) (buffer + bufPos); self->refrTm = (Timestamp*) (buffer + bufPos);
bufPos += 8; bufPos += 8;
@ -429,7 +439,8 @@ SVPublisher_ASDU_encodeToBuffer(SVPublisher_ASDU self, uint8_t* buffer, int bufP
buffer[bufPos++] = self->smpSynch; buffer[bufPos++] = self->smpSynch;
/* SmpRate */ /* SmpRate */
if (self->hasSmpRate) { if (self->hasSmpRate)
{
bufPos = BerEncoder_encodeTL(0x86, 2, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x86, 2, buffer, bufPos);
bufPos = encodeUInt16FixedSize(self->smpRate, buffer, bufPos); bufPos = encodeUInt16FixedSize(self->smpRate, buffer, bufPos);
} }
@ -442,7 +453,8 @@ SVPublisher_ASDU_encodeToBuffer(SVPublisher_ASDU self, uint8_t* buffer, int bufP
bufPos += self->dataSize; /* data has to be inserted by user before sending message */ bufPos += self->dataSize; /* data has to be inserted by user before sending message */
/* SmpMod */ /* SmpMod */
if (self->hasSmpMod) { if (self->hasSmpMod)
{
bufPos = BerEncoder_encodeTL(0x88, 2, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x88, 2, buffer, bufPos);
bufPos = encodeUInt16FixedSize(self->smpMod, buffer, bufPos); bufPos = encodeUInt16FixedSize(self->smpMod, buffer, bufPos);
} }
@ -459,7 +471,8 @@ SVPublisher_setupComplete(SVPublisher self)
SVPublisher_ASDU nextAsdu = self->asduList; SVPublisher_ASDU nextAsdu = self->asduList;
int totalASDULength = 0; int totalASDULength = 0;
while (nextAsdu != NULL) { while (nextAsdu != NULL)
{
numberOfAsdu++; numberOfAsdu++;
int asduLength = SVPublisher_ASDU_getEncodedSize(nextAsdu); int asduLength = SVPublisher_ASDU_getEncodedSize(nextAsdu);
@ -489,7 +502,8 @@ SVPublisher_setupComplete(SVPublisher self)
nextAsdu = self->asduList; nextAsdu = self->asduList;
while (nextAsdu != NULL) { while (nextAsdu != NULL)
{
bufPos = SVPublisher_ASDU_encodeToBuffer(nextAsdu, buffer, bufPos); bufPos = SVPublisher_ASDU_encodeToBuffer(nextAsdu, buffer, bufPos);
nextAsdu = nextAsdu->_next; nextAsdu = nextAsdu->_next;
@ -533,7 +547,8 @@ SVPublisher_publish(SVPublisher self)
void void
SVPublisher_destroy(SVPublisher self) SVPublisher_destroy(SVPublisher self)
{ {
if (self) { if (self)
{
if (self->ethernetSocket) if (self->ethernetSocket)
Ethernet_destroySocket(self->ethernetSocket); Ethernet_destroySocket(self->ethernetSocket);
@ -542,7 +557,8 @@ SVPublisher_destroy(SVPublisher self)
SVPublisher_ASDU asdu = self->asduList; SVPublisher_ASDU asdu = self->asduList;
while (asdu) { while (asdu)
{
SVPublisher_ASDU nextAsdu = asdu->_next; SVPublisher_ASDU nextAsdu = asdu->_next;
GLOBAL_FREEMEM(asdu); GLOBAL_FREEMEM(asdu);
@ -554,14 +570,12 @@ SVPublisher_destroy(SVPublisher self)
} }
} }
void void
SVPublisher_ASDU_resetBuffer(SVPublisher_ASDU self) SVPublisher_ASDU_resetBuffer(SVPublisher_ASDU self)
{ {
self->dataSize = 0; self->dataSize = 0;
} }
int int
SVPublisher_ASDU_addINT8(SVPublisher_ASDU self) SVPublisher_ASDU_addINT8(SVPublisher_ASDU self)
{ {
@ -633,12 +647,12 @@ SVPublisher_ASDU_setFLOAT(SVPublisher_ASDU self, int index, float value)
uint8_t* buffer = self->_dataBuffer + index; uint8_t* buffer = self->_dataBuffer + index;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++)
{
buffer[i] = buf[i]; buffer[i] = buf[i];
} }
} }
int int
SVPublisher_ASDU_addFLOAT64(SVPublisher_ASDU self) SVPublisher_ASDU_addFLOAT64(SVPublisher_ASDU self)
{ {
@ -660,7 +674,8 @@ SVPublisher_ASDU_setFLOAT64(SVPublisher_ASDU self, int index, double value)
uint8_t* buffer = self->_dataBuffer + index; uint8_t* buffer = self->_dataBuffer + index;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++)
{
buffer[i] = buf[i]; buffer[i] = buf[i];
} }
} }
@ -680,7 +695,8 @@ SVPublisher_ASDU_setTimestamp(SVPublisher_ASDU self, int index, Timestamp value)
uint8_t* buffer = self->_dataBuffer + index; uint8_t* buffer = self->_dataBuffer + index;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++)
{
buffer[i] = value.val[i]; buffer[i] = value.val[i];
} }
} }
@ -714,7 +730,7 @@ SVPublisher_ASDU_setSmpCnt(SVPublisher_ASDU self, uint16_t value)
{ {
self->smpCnt = value; self->smpCnt = value;
if (self->smpCntBuf != NULL) if (self->smpCntBuf)
encodeUInt16FixedSize(self->smpCnt, self->smpCntBuf, 0); encodeUInt16FixedSize(self->smpCnt, self->smpCntBuf, 0);
} }
@ -729,7 +745,7 @@ SVPublisher_ASDU_increaseSmpCnt(SVPublisher_ASDU self)
{ {
self->smpCnt = ((self->smpCnt + 1) % self->smpCntLimit); self->smpCnt = ((self->smpCnt + 1) % self->smpCntLimit);
if (self->smpCntBuf != NULL) if (self->smpCntBuf)
encodeUInt16FixedSize(self->smpCnt, self->smpCntBuf, 0); encodeUInt16FixedSize(self->smpCnt, self->smpCntBuf, 0);
} }
@ -744,7 +760,8 @@ SVPublisher_ASDU_setRefrTmNs(SVPublisher_ASDU self, nsSinceEpoch refrTmNs)
{ {
self->hasRefrTm = true; self->hasRefrTm = true;
if (self->refrTm) { if (self->refrTm)
{
Timestamp_setTimeInNanoseconds(self->refrTm, refrTmNs); Timestamp_setTimeInNanoseconds(self->refrTm, refrTmNs);
Timestamp_setSubsecondPrecision(self->refrTm, 20); Timestamp_setSubsecondPrecision(self->refrTm, 20);
} }
@ -755,7 +772,8 @@ SVPublisher_ASDU_setRefrTm(SVPublisher_ASDU self, msSinceEpoch refrTm)
{ {
self->hasRefrTm = true; self->hasRefrTm = true;
if (self->refrTm) { if (self->refrTm)
{
Timestamp_setTimeInMilliseconds(self->refrTm, refrTm); Timestamp_setTimeInMilliseconds(self->refrTm, refrTm);
Timestamp_setSubsecondPrecision(self->refrTm, 10); Timestamp_setSubsecondPrecision(self->refrTm, 10);
} }

@ -45,7 +45,8 @@
#define ETH_P_SV 0x88ba #define ETH_P_SV 0x88ba
struct sSVReceiver { struct sSVReceiver
{
bool running; bool running;
bool stopped; bool stopped;
@ -69,7 +70,8 @@ struct sSVReceiver {
}; };
struct sSVSubscriber { struct sSVSubscriber
{
uint8_t ethAddr[6]; uint8_t ethAddr[6];
uint16_t appId; uint16_t appId;
@ -78,8 +80,8 @@ struct sSVSubscriber {
void* listenerParameter; void* listenerParameter;
}; };
struct sSVSubscriber_ASDU { struct sSVSubscriber_ASDU
{
char* svId; char* svId;
char* datSet; char* datSet;
@ -191,13 +193,15 @@ svReceiverLoop(void* threadParameter)
{ {
SVReceiver self = (SVReceiver) threadParameter; SVReceiver self = (SVReceiver) threadParameter;
if (self->ethSocket) { if (self->ethSocket)
{
EthernetHandleSet handleSet = EthernetHandleSet_new(); EthernetHandleSet handleSet = EthernetHandleSet_new();
EthernetHandleSet_addSocket(handleSet, self->ethSocket); EthernetHandleSet_addSocket(handleSet, self->ethSocket);
self->stopped = false; self->stopped = false;
while (self->running) { while (self->running)
{
switch (EthernetHandleSet_waitReady(handleSet, 100)) switch (EthernetHandleSet_waitReady(handleSet, 100))
{ {
case -1: case -1:
@ -214,14 +218,16 @@ svReceiverLoop(void* threadParameter)
EthernetHandleSet_destroy(handleSet); EthernetHandleSet_destroy(handleSet);
} }
#if (CONFIG_IEC61850_R_SMV == 1) #if (CONFIG_IEC61850_R_SMV == 1)
else if (self->session) { else if (self->session)
{
self->stopped = false; self->stopped = false;
HandleSet handleSet = Handleset_new(); HandleSet handleSet = Handleset_new();
Handleset_addSocket(handleSet, RSession_getSocket(self->session)); Handleset_addSocket(handleSet, RSession_getSocket(self->session));
while (self->running) { while (self->running)
{
switch (Handleset_waitReady(handleSet, 100)) switch (Handleset_waitReady(handleSet, 100))
{ {
case -1: case -1:
@ -247,9 +253,10 @@ svReceiverLoop(void* threadParameter)
void void
SVReceiver_start(SVReceiver self) SVReceiver_start(SVReceiver self)
{ {
if (SVReceiver_startThreadless(self)) { if (SVReceiver_startThreadless(self))
{
if (self->interfaceId) { if (self->interfaceId)
{
if (DEBUG_SV_SUBSCRIBER) if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: SV receiver started for interface %s\n", self->interfaceId); printf("SV_SUBSCRIBER: SV receiver started for interface %s\n", self->interfaceId);
} }
@ -262,17 +269,20 @@ SVReceiver_start(SVReceiver self)
self->thread = Thread_create((ThreadExecutionFunction) svReceiverLoop, (void*) self, false); self->thread = Thread_create((ThreadExecutionFunction) svReceiverLoop, (void*) self, false);
if (self->thread) { if (self->thread)
{
Thread_start(self->thread); Thread_start(self->thread);
} }
else { else
{
if (DEBUG_SV_SUBSCRIBER) if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: Failed to start thread\n"); printf("SV_SUBSCRIBER: Failed to start thread\n");
} }
#endif /* (CONFIG_MMS_THREADLESS_STACK == 0) */ #endif /* (CONFIG_MMS_THREADLESS_STACK == 0) */
} }
else { else
{
if (DEBUG_SV_SUBSCRIBER) if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: Starting SV receiver failed for interface %s\n", self->interfaceId); printf("SV_SUBSCRIBER: Starting SV receiver failed for interface %s\n", self->interfaceId);
} }
@ -284,15 +294,16 @@ SVReceiver_isRunning(SVReceiver self)
return self->running; return self->running;
} }
void void
SVReceiver_stop(SVReceiver self) SVReceiver_stop(SVReceiver self)
{ {
if (self->running) { if (self->running)
{
self->running = false; self->running = false;
#if (CONFIG_MMS_THREADLESS_STACK == 0) #if (CONFIG_MMS_THREADLESS_STACK == 0)
if (self->thread) { if (self->thread)
{
Thread_destroy(self->thread); Thread_destroy(self->thread);
self->thread = NULL; self->thread = NULL;
} }
@ -310,7 +321,7 @@ SVReceiver_destroy(SVReceiver self)
LinkedList_destroyDeep(self->subscriberList, LinkedList_destroyDeep(self->subscriberList,
(LinkedListValueDeleteFunction) SVSubscriber_destroy); (LinkedListValueDeleteFunction) SVSubscriber_destroy);
if (self->interfaceId != NULL) if (self->interfaceId)
GLOBAL_FREEMEM(self->interfaceId); GLOBAL_FREEMEM(self->interfaceId);
#if (CONFIG_MMS_THREADLESS_STACK == 0) #if (CONFIG_MMS_THREADLESS_STACK == 0)
@ -330,25 +341,29 @@ bool
SVReceiver_startThreadless(SVReceiver self) SVReceiver_startThreadless(SVReceiver self)
{ {
#if (CONFIG_IEC61850_R_SMV == 1) #if (CONFIG_IEC61850_R_SMV == 1)
if (self->session) { if (self->session)
if (RSession_start(self->session) == R_SESSION_ERROR_OK) { {
if (RSession_start(self->session) == R_SESSION_ERROR_OK)
{
self->running = true; self->running = true;
return true; return true;
} }
else { else
{
return false; return false;
} }
} }
else { else
{
#endif /* (CONFIG_IEC61850_R_SMV == 1) */ #endif /* (CONFIG_IEC61850_R_SMV == 1) */
if (self->interfaceId == NULL) if (self->interfaceId == NULL)
self->ethSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, NULL); self->ethSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, NULL);
else else
self->ethSocket = Ethernet_createSocket(self->interfaceId, NULL); self->ethSocket = Ethernet_createSocket(self->interfaceId, NULL);
if (self->ethSocket) { if (self->ethSocket)
{
Ethernet_setProtocolFilter(self->ethSocket, ETH_P_SV); Ethernet_setProtocolFilter(self->ethSocket, ETH_P_SV);
self->running = true; self->running = true;
@ -390,19 +405,21 @@ parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length)
struct sSVSubscriber_ASDU asdu; struct sSVSubscriber_ASDU asdu;
memset(&asdu, 0, sizeof(struct sSVSubscriber_ASDU)); memset(&asdu, 0, sizeof(struct sSVSubscriber_ASDU));
while (bufPos < length) { while (bufPos < length)
{
int elementLength; int elementLength;
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, length); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, length);
if (bufPos < 0) { if (bufPos < 0)
{
if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n"); if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return; return;
} }
switch (tag) { switch (tag)
{
case 0x80: case 0x80:
asdu.svId = (char*) (buffer + bufPos); asdu.svId = (char*) (buffer + bufPos);
svIdLength = elementLength; svIdLength = elementLength;
@ -455,7 +472,8 @@ parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length)
if (asdu.datSet != NULL) if (asdu.datSet != NULL)
asdu.datSet[datSetLength] = 0; asdu.datSet[datSetLength] = 0;
if (DEBUG_SV_SUBSCRIBER) { if (DEBUG_SV_SUBSCRIBER)
{
printf("SV_SUBSCRIBER: SV ASDU: ----------------\n"); printf("SV_SUBSCRIBER: SV ASDU: ----------------\n");
printf("SV_SUBSCRIBER: DataLength: %d\n", asdu.dataBufferLength); printf("SV_SUBSCRIBER: DataLength: %d\n", asdu.dataBufferLength);
printf("SV_SUBSCRIBER: SvId: %s\n", asdu.svId); printf("SV_SUBSCRIBER: SvId: %s\n", asdu.svId);
@ -478,7 +496,8 @@ parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length)
} }
/* Call callback handler */ /* Call callback handler */
if (subscriber) { if (subscriber)
{
if (subscriber->listener != NULL) if (subscriber->listener != NULL)
subscriber->listener(subscriber, subscriber->listenerParameter, &asdu); subscriber->listener(subscriber, subscriber->listenerParameter, &asdu);
} }
@ -489,18 +508,21 @@ parseSequenceOfASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, i
{ {
int bufPos = 0; int bufPos = 0;
while (bufPos < length) { while (bufPos < length)
{
int elementLength; int elementLength;
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, length); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, length);
if (bufPos < 0) { if (bufPos < 0)
{
if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n"); if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return; return;
} }
switch (tag) { switch (tag)
{
case 0x30: case 0x30:
parseASDU(self, subscriber, buffer + bufPos, elementLength); parseASDU(self, subscriber, buffer + bufPos, elementLength);
break; break;
@ -519,25 +541,29 @@ parseSVPayload(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int ap
{ {
int bufPos = 0; int bufPos = 0;
if (buffer[bufPos++] == 0x60) { if (buffer[bufPos++] == 0x60)
{
int elementLength; int elementLength;
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, apduLength); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, apduLength);
if (bufPos < 0) { if (bufPos < 0)
{
if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n"); if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return; return;
} }
int svEnd = bufPos + elementLength; int svEnd = bufPos + elementLength;
while (bufPos < svEnd) { while (bufPos < svEnd)
{
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, svEnd); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, svEnd);
if (bufPos < 0) if (bufPos < 0)
goto exit_error; goto exit_error;
switch(tag) { switch(tag)
{
case 0x80: /* noASDU (INTEGER) */ case 0x80: /* noASDU (INTEGER) */
/* ignore */ /* ignore */
break; break;
@ -551,7 +577,6 @@ parseSVPayload(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int ap
break; break;
} }
bufPos += elementLength; bufPos += elementLength;
} }
@ -648,7 +673,8 @@ parseSVMessage(SVReceiver self, int numbytes)
int headerLength = 14; int headerLength = 14;
/* check for VLAN tag */ /* check for VLAN tag */
if ((buffer[bufPos] == 0x81) && (buffer[bufPos + 1] == 0x00)) { if ((buffer[bufPos] == 0x81) && (buffer[bufPos + 1] == 0x00))
{
bufPos += 4; /* skip VLAN tag */ bufPos += 4; /* skip VLAN tag */
headerLength += 4; headerLength += 4;
} }
@ -674,7 +700,8 @@ parseSVMessage(SVReceiver self, int numbytes)
int apduLength = length - 8; int apduLength = length - 8;
if (numbytes < length + headerLength) { if (numbytes < length + headerLength)
{
if (DEBUG_SV_SUBSCRIBER) if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: Invalid PDU size\n"); printf("SV_SUBSCRIBER: Invalid PDU size\n");
return; return;
@ -694,16 +721,19 @@ handleSessionPayloadElement(void* parameter, uint16_t appId, uint8_t* payloadDat
bool bool
SVReceiver_tick(SVReceiver self) SVReceiver_tick(SVReceiver self)
{ {
if (self->ethSocket) { if (self->ethSocket)
{
int packetSize = Ethernet_receivePacket(self->ethSocket, self->buffer, ETH_BUFFER_LENGTH); int packetSize = Ethernet_receivePacket(self->ethSocket, self->buffer, ETH_BUFFER_LENGTH);
if (packetSize > 0) { if (packetSize > 0)
{
parseSVMessage(self, packetSize); parseSVMessage(self, packetSize);
return true; return true;
} }
} }
#if (CONFIG_IEC61850_R_SMV == 1) #if (CONFIG_IEC61850_R_SMV == 1)
else if (self->session) { else if (self->session)
{
if (RSession_receiveMessage(self->session, handleSessionPayloadElement, (void*) self) == R_SESSION_ERROR_OK) if (RSession_receiveMessage(self->session, handleSessionPayloadElement, (void*) self) == R_SESSION_ERROR_OK)
return true; return true;
} }
@ -717,10 +747,11 @@ SVSubscriber_create(const uint8_t* ethAddr, uint16_t appID)
{ {
SVSubscriber self = (SVSubscriber) GLOBAL_CALLOC(1, sizeof(struct sSVSubscriber)); SVSubscriber self = (SVSubscriber) GLOBAL_CALLOC(1, sizeof(struct sSVSubscriber));
if (self != NULL) { if (self != NULL)
{
self->appId = appID; self->appId = appID;
if (ethAddr != NULL) if (ethAddr)
memcpy(self->ethAddr, ethAddr, 6); memcpy(self->ethAddr, ethAddr, 6);
} }
@ -734,7 +765,6 @@ SVSubscriber_destroy(SVSubscriber self)
GLOBAL_FREEMEM(self); GLOBAL_FREEMEM(self);
} }
void void
SVSubscriber_setListener(SVSubscriber self, SVUpdateListener listener, void* parameter) SVSubscriber_setListener(SVSubscriber self, SVUpdateListener listener, void* parameter)
{ {
@ -748,7 +778,6 @@ SVSubscriber_ASDU_getSmpSynch(SVSubscriber_ASDU self)
return self->smpSynch[0]; return self->smpSynch[0];
} }
uint16_t uint16_t
SVSubscriber_ASDU_getSmpCnt(SVSubscriber_ASDU self) SVSubscriber_ASDU_getSmpCnt(SVSubscriber_ASDU self)
{ {
@ -1150,4 +1179,3 @@ SVClientASDU_getDataSize(SVSubscriber_ASDU self)
{ {
return SVSubscriber_ASDU_getDataSize(self); return SVSubscriber_ASDU_getDataSize(self);
} }

Loading…
Cancel
Save