diff --git a/dotnet/IEC61850forCSharp/TLS.cs b/dotnet/IEC61850forCSharp/TLS.cs index 05512a9b..d645c547 100644 --- a/dotnet/IEC61850forCSharp/TLS.cs +++ b/dotnet/IEC61850forCSharp/TLS.cs @@ -1,7 +1,7 @@ /* * TLS.cs * - * Copyright 2017-2022 Michael Zillgith + * Copyright 2017-2024 Michael Zillgith * * This file is part of libIEC61850. * @@ -69,7 +69,9 @@ namespace IEC61850 ALM_CERT_EXPIRED = 11, ALM_CERT_REVOKED = 12, 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 @@ -261,6 +263,18 @@ namespace IEC61850 [return: MarshalAs(UnmanagedType.I1)] 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 object eventHandlerParameter = null; @@ -417,6 +431,53 @@ namespace IEC61850 } } + /// + /// Set minimal allowed TLS version to use + /// + /// lowest allowed TLS version + public void SetMinTlsVersion(TLSConfigVersion version) + { + TLSConfiguration_setMinTlsVersion(self, (int)version); + } + + /// + /// Set highest allowed TLS version to use + /// + /// highest allowed TLS version + public void SetMaxTlsVersion(TLSConfigVersion version) + { + TLSConfiguration_setMaxTlsVersion(self, (int)version); + } + +#if NET + /// + /// Add an allowed ciphersuite to the list of allowed ciphersuites + /// + /// + public void addCipherSuite(TlsCipherSuite ciphersuite) + { + TLSConfiguration_addCipherSuite(self,(int) ciphersuite); + } +#endif + /// + /// Add an allowed ciphersuite to the list of allowed ciphersuites + /// + /// Version for .NET framework that does not support TlsCipherSuite enum + /// + public void addCipherSuite(int ciphersuite) + { + TLSConfiguration_addCipherSuite(self, ciphersuite); + } + + /// + /// Clears list of allowed ciphersuites + /// + /// + public void clearCipherSuiteList() + { + TLSConfiguration_clearCipherSuiteList(self); + } + public void Dispose() { lock (this) diff --git a/hal/inc/tls_ciphers.h b/hal/inc/tls_ciphers.h new file mode 100644 index 00000000..63918f1e --- /dev/null +++ b/hal/inc/tls_ciphers.h @@ -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_ */ \ No newline at end of file diff --git a/hal/inc/tls_config.h b/hal/inc/tls_config.h index 2896a108..c91f180a 100644 --- a/hal/inc/tls_config.h +++ b/hal/inc/tls_config.h @@ -3,7 +3,7 @@ * * 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 * @@ -17,6 +17,7 @@ extern "C" { #endif #include "hal_base.h" +#include "tls_ciphers.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_TRUSTED 14 #define TLS_EVENT_CODE_ALM_NO_CIPHER 15 +#define TLS_EVENT_CODE_INF_SESSION_ESTABLISHED 16 typedef struct sTLSConnection* TLSConnection; @@ -303,6 +305,23 @@ TLSConfiguration_addCRLFromFile(TLSConfiguration self, const char* filename); PAL_API void 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 * diff --git a/hal/tls/mbedtls/mbedtls_config.h b/hal/tls/mbedtls/mbedtls_config.h index 1773bc2c..9b98fe02 100644 --- a/hal/tls/mbedtls/mbedtls_config.h +++ b/hal/tls/mbedtls/mbedtls_config.h @@ -17,6 +17,8 @@ #define MBEDTLS_SSL_PROTO_TLS1_1 #define MBEDTLS_SSL_PROTO_TLS1 #define MBEDTLS_SSL_RENEGOTIATION +#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#define MBEDTLS_CIPHER_NULL_CIPHER #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES diff --git a/hal/tls/mbedtls/tls_mbedtls.c b/hal/tls/mbedtls/tls_mbedtls.c index 06b98234..7470e3d2 100644 --- a/hal/tls/mbedtls/tls_mbedtls.c +++ b/hal/tls/mbedtls/tls_mbedtls.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 * @@ -20,7 +20,6 @@ #include "mbedtls/platform.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" -#include "mbedtls/certs.h" #include "mbedtls/x509.h" #include "mbedtls/ssl.h" #include "mbedtls/net_sockets.h" @@ -86,6 +85,9 @@ struct sTLSConfiguration { bool useSessionResumption; int sessionResumptionInterval; /* session resumption interval in seconds */ + + int* ciphersuites; + int maxCiphersuites; }; struct sTLSSocket { @@ -115,9 +117,10 @@ raiseSecurityEvent(TLSConfiguration config, TLSEventLevel eventCategory, int eve static bool compareCertificates(mbedtls_x509_crt *crt1, mbedtls_x509_crt *crt2) { - if (crt1 != NULL && crt2 != NULL) { - - if (crt1->sig.len == crt2->sig.len) { + if (crt1 != NULL && crt2 != NULL) + { + if (crt1->sig.len == crt2->sig.len) + { if (memcmp(crt1->sig.p, crt2->sig.p, crt1->sig.len) == 0) return true; } @@ -142,28 +145,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; } @@ -173,7 +180,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; @@ -181,20 +189,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); } - } - } } @@ -207,10 +214,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) { @@ -219,11 +228,13 @@ TLSConfiguration_setupComplete(TLSConfiguration self) } } - if (self->useSessionResumption) { + if (self->useSessionResumption) + { if (self->conf.endpoint == MBEDTLS_SSL_IS_CLIENT) { } - else { + else + { mbedtls_ssl_cache_init( &(self->cache) ); self->cache.timeout = self->sessionResumptionInterval; @@ -234,18 +245,71 @@ 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 != NULL) + { mbedtls_ssl_config_init( &(self->conf) ); mbedtls_x509_crt_init( &(self->ownCertificate) ); mbedtls_x509_crt_init( &(self->cacerts) ); @@ -267,10 +331,7 @@ 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_0; + self->minVersion = TLS_VERSION_TLS_1_2; self->maxVersion = TLS_VERSION_NOT_SELECTED; self->renegotiationTimeInMs = -1; /* no automatic renegotiation */ @@ -289,6 +350,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; @@ -394,11 +480,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; } @@ -411,11 +499,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; } @@ -426,7 +516,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; } @@ -458,7 +549,8 @@ udpatedCRL(TLSConfiguration self) { mbedtls_ssl_cache_entry *cur = self->cache.chain; - while (cur) { + while (cur) + { cur->timestamp = 0; cur = cur->next; } @@ -512,14 +604,18 @@ TLSConfiguration_setRenegotiationTime(TLSConfiguration self, int timeInMs) void TLSConfiguration_destroy(TLSConfiguration self) { - if (self->useSessionResumption) { - if (self->conf.endpoint == MBEDTLS_SSL_IS_CLIENT) { - if (self->savedSession) { + if (self->useSessionResumption) + { + if (self->conf.endpoint == 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)); } } @@ -532,7 +628,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); @@ -621,7 +718,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; } @@ -631,7 +729,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 @@ -640,7 +745,8 @@ getTLSVersion(int majorVersion, int minorVersion) if (majorVersion != 3) { return TLS_VERSION_NOT_SELECTED; } - else { + else + { switch (minorVersion) { case 0: return TLS_VERSION_SSL_3_0; @@ -721,7 +827,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); @@ -730,7 +837,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); @@ -739,7 +847,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) @@ -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_recv_t*) readFunction, NULL); - bool reuseSession = false; - - if (configuration->useSessionResumption) { - if (configuration->conf.endpoint == MBEDTLS_SSL_IS_CLIENT) { - if (configuration->savedSession && configuration->savedSessionTime > 0) { - - if (Hal_getTimeInMs() < (configuration->savedSessionTime + configuration->sessionResumptionInterval * 1000)) { - + if (configuration->useSessionResumption) + { + if (configuration->conf.endpoint == 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"); } - } } } @@ -804,22 +914,27 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient } } - if (configuration->useSessionResumption) { - if (configuration->conf.endpoint == MBEDTLS_SSL_IS_CLIENT) { - - if (configuration->savedSession == NULL) { + if (configuration->useSessionResumption) + { + if (configuration->conf.endpoint == 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(); } } @@ -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); } + /* 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; @@ -853,17 +978,18 @@ 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) + { 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); } - 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); return true; } - else { + else + { 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); @@ -904,10 +1030,17 @@ startRenegotiationIfRequired(TLSSocket self) if (Hal_getTimeInMs() <= self->lastRenegotiationTime + self->tlsConfig->renegotiationTimeInMs) 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) + { + DEBUG_PRINT("TLS", " renegotiation failed\n"); return false; + } + DEBUG_PRINT("TLS", " started renegotiation\n"); self->lastRenegotiationTime = Hal_getTimeInMs(); + return true; } @@ -1024,7 +1157,6 @@ TLSSocket_close(TLSSocket self) if (self->peerCert) GLOBAL_FREEMEM(self->peerCert); - GLOBAL_FREEMEM(self); } diff --git a/src/iec61850/server/model/dynamic_model.c b/src/iec61850/server/model/dynamic_model.c index bfe266ed..2290918e 100644 --- a/src/iec61850/server/model/dynamic_model.c +++ b/src/iec61850/server/model/dynamic_model.c @@ -667,7 +667,8 @@ DataObject_create(const char* name, ModelNode* parent, int arrayElements) { DataObject* arrayElement = (DataObject*) GLOBAL_MALLOC(sizeof(DataObject)); - if (arrayElement) { + if (arrayElement) + { arrayElement->name = NULL; arrayElement->modelType = DataObjectModelType; arrayElement->firstChild = NULL; diff --git a/src/iec61850/server/model/model.c b/src/iec61850/server/model/model.c index 55b6409e..53d3b38b 100644 --- a/src/iec61850/server/model/model.c +++ b/src/iec61850/server/model/model.c @@ -707,26 +707,30 @@ ModelNode_getChild(ModelNode* self, const char* name) /* check for array separator */ const char* arraySeparator = strchr(name, '('); - if (arraySeparator) { - + if (arraySeparator) + { const char* arraySeparator2 = strchr(arraySeparator, ')'); - if (arraySeparator2) { + if (arraySeparator2) + { int idx = (int) strtol(arraySeparator + 1, NULL, 10); ModelNode* arrayNode = NULL; - if (name == arraySeparator) { + if (name == arraySeparator) + { arrayNode = ModelNode_getChildWithIdx(self, idx); } - else { + else + { char nameCopy[65]; const char* pos = name; int cpyIdx = 0; - while (pos < arraySeparator) { + while (pos < arraySeparator) + { nameCopy[cpyIdx] = *pos; cpyIdx++; pos++; @@ -743,18 +747,19 @@ ModelNode_getChild(ModelNode* self, const char* name) return NULL; } - if (arrayNode) { - - if (*(arraySeparator2 + 1) == 0) { + if (arrayNode) + { + if (*(arraySeparator2 + 1) == 0) + { return arrayNode; } - else { + else + { if (*(arraySeparator2 + 1) == '.') return ModelNode_getChild(arrayNode, arraySeparator2 + 2); else return ModelNode_getChild(arrayNode, arraySeparator2 + 1); } - } else return NULL; @@ -787,7 +792,8 @@ ModelNode_getChild(ModelNode* self, const char* name) if (nodeNameLen == nameElementLength) { - if (memcmp(nextNode->name, name, nodeNameLen) == 0) { + if (memcmp(nextNode->name, name, nodeNameLen) == 0) + { matchingNode = nextNode; break; } @@ -816,7 +822,8 @@ ModelNode_getChildWithIdx(ModelNode* self, int idx) while (nextNode) { - if (currentIdx == idx) { + if (currentIdx == idx) + { foundElement = nextNode; break; } @@ -855,7 +862,8 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint { if (memcmp(nextNode->name, name, nodeNameLen) == 0) { - if (separator == NULL) { + if (separator == NULL) + { if (nextNode->modelType == DataAttributeModelType) { DataAttribute* da = (DataAttribute*) nextNode; @@ -872,7 +880,8 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint { DataAttribute* da = (DataAttribute*) nextNode; - if (da->fc == fc) { + if (da->fc == fc) + { matchingNode = nextNode; break; } @@ -881,7 +890,6 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint matchingNode = nextNode; break; } - } } } diff --git a/src/sampled_values/sv_publisher.c b/src/sampled_values/sv_publisher.c index d14b788d..f69b90cd 100644 --- a/src/sampled_values/sv_publisher.c +++ b/src/sampled_values/sv_publisher.c @@ -111,13 +111,15 @@ preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* in else Ethernet_getInterfaceMACAddress(CONFIG_ETHERNET_INTERFACE_ID, srcAddr); - if (parameters == NULL) { + if (parameters == NULL) + { dstAddr = defaultDstAddr; priority = CONFIG_SV_DEFAULT_PRIORITY; vlanId = CONFIG_SV_DEFAULT_VLAN_ID; appId = CONFIG_SV_DEFAULT_APPID; } - else { + else + { dstAddr = parameters->dstAddress; priority = parameters->vlanPriority; vlanId = parameters->vlanId; @@ -129,8 +131,8 @@ preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* in else self->ethernetSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, dstAddr); - if (self->ethernetSocket == NULL) { - + if (self->ethernetSocket == NULL) + { if (DEBUG_SV_PUBLISHER) 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); - if (self->buffer) { + if (self->buffer) + { memcpy(self->buffer, dstAddr, 6); memcpy(self->buffer + 6, srcAddr, 6); int bufPos = 12; - if (useVlanTags) { + if (useVlanTags) + { /* Priority tag - IEEE 802.1Q */ self->buffer[bufPos++] = 0x81; self->buffer[bufPos++] = 0x00; @@ -183,7 +187,8 @@ preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* in self->payloadStart = bufPos; } - else { + else + { return false; } @@ -303,11 +308,13 @@ SVPublisher_createEx(CommParameters* parameters, const char* interfaceId, bool u { SVPublisher self = (SVPublisher) GLOBAL_CALLOC(1, sizeof(struct sSVPublisher)); - if (self) { + if (self) + { self->asduList = NULL; self->lengthField = 0; - if (preparePacketBuffer(self, parameters, interfaceId, useVlanTag) == false) { + if (preparePacketBuffer(self, parameters, interfaceId, useVlanTag) == false) + { SVPublisher_destroy(self); self = NULL; } @@ -337,10 +344,11 @@ SVPublisher_addASDU(SVPublisher self, const char* svID, const char* datset, uint /* append new ASDU to list */ if (self->asduList == NULL) self->asduList = newAsdu; - else { + else + { SVPublisher_ASDU lastAsdu = self->asduList; - while (lastAsdu->_next != NULL) + while (lastAsdu->_next) lastAsdu = lastAsdu->_next; lastAsdu->_next = newAsdu; @@ -359,7 +367,8 @@ SVPublisher_ASDU_getEncodedSize(SVPublisher_ASDU self) encodedSize += (1 + BerEncoder_determineLengthSize(svIdLen) + svIdLen); /* datset */ - if (self->datset != NULL) { + if (self->datset) + { int datSetLen = strlen(self->datset); 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); /* RefrTm */ - if (self->hasRefrTm) { + if (self->hasRefrTm) + { bufPos = BerEncoder_encodeTL(0x84, 8, buffer, bufPos); self->refrTm = (Timestamp*) (buffer + bufPos); bufPos += 8; @@ -429,7 +439,8 @@ SVPublisher_ASDU_encodeToBuffer(SVPublisher_ASDU self, uint8_t* buffer, int bufP buffer[bufPos++] = self->smpSynch; /* SmpRate */ - if (self->hasSmpRate) { + if (self->hasSmpRate) + { bufPos = BerEncoder_encodeTL(0x86, 2, 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 */ /* SmpMod */ - if (self->hasSmpMod) { + if (self->hasSmpMod) + { bufPos = BerEncoder_encodeTL(0x88, 2, buffer, bufPos); bufPos = encodeUInt16FixedSize(self->smpMod, buffer, bufPos); } @@ -459,7 +471,8 @@ SVPublisher_setupComplete(SVPublisher self) SVPublisher_ASDU nextAsdu = self->asduList; int totalASDULength = 0; - while (nextAsdu != NULL) { + while (nextAsdu != NULL) + { numberOfAsdu++; int asduLength = SVPublisher_ASDU_getEncodedSize(nextAsdu); @@ -489,7 +502,8 @@ SVPublisher_setupComplete(SVPublisher self) nextAsdu = self->asduList; - while (nextAsdu != NULL) { + while (nextAsdu != NULL) + { bufPos = SVPublisher_ASDU_encodeToBuffer(nextAsdu, buffer, bufPos); nextAsdu = nextAsdu->_next; @@ -533,7 +547,8 @@ SVPublisher_publish(SVPublisher self) void SVPublisher_destroy(SVPublisher self) { - if (self) { + if (self) + { if (self->ethernetSocket) Ethernet_destroySocket(self->ethernetSocket); @@ -542,7 +557,8 @@ SVPublisher_destroy(SVPublisher self) SVPublisher_ASDU asdu = self->asduList; - while (asdu) { + while (asdu) + { SVPublisher_ASDU nextAsdu = asdu->_next; GLOBAL_FREEMEM(asdu); @@ -554,14 +570,12 @@ SVPublisher_destroy(SVPublisher self) } } - void SVPublisher_ASDU_resetBuffer(SVPublisher_ASDU self) { self->dataSize = 0; } - int 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; - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) + { buffer[i] = buf[i]; } } - int 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; - for (i = 0; i < 8; i++) { + for (i = 0; i < 8; 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; - for (i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) + { buffer[i] = value.val[i]; } } @@ -714,7 +730,7 @@ SVPublisher_ASDU_setSmpCnt(SVPublisher_ASDU self, uint16_t value) { self->smpCnt = value; - if (self->smpCntBuf != NULL) + if (self->smpCntBuf) encodeUInt16FixedSize(self->smpCnt, self->smpCntBuf, 0); } @@ -729,7 +745,7 @@ SVPublisher_ASDU_increaseSmpCnt(SVPublisher_ASDU self) { self->smpCnt = ((self->smpCnt + 1) % self->smpCntLimit); - if (self->smpCntBuf != NULL) + if (self->smpCntBuf) encodeUInt16FixedSize(self->smpCnt, self->smpCntBuf, 0); } @@ -744,7 +760,8 @@ SVPublisher_ASDU_setRefrTmNs(SVPublisher_ASDU self, nsSinceEpoch refrTmNs) { self->hasRefrTm = true; - if (self->refrTm) { + if (self->refrTm) + { Timestamp_setTimeInNanoseconds(self->refrTm, refrTmNs); Timestamp_setSubsecondPrecision(self->refrTm, 20); } @@ -755,7 +772,8 @@ SVPublisher_ASDU_setRefrTm(SVPublisher_ASDU self, msSinceEpoch refrTm) { self->hasRefrTm = true; - if (self->refrTm) { + if (self->refrTm) + { Timestamp_setTimeInMilliseconds(self->refrTm, refrTm); Timestamp_setSubsecondPrecision(self->refrTm, 10); } diff --git a/src/sampled_values/sv_subscriber.c b/src/sampled_values/sv_subscriber.c index 0d86a69c..48d8bfc8 100644 --- a/src/sampled_values/sv_subscriber.c +++ b/src/sampled_values/sv_subscriber.c @@ -45,7 +45,8 @@ #define ETH_P_SV 0x88ba -struct sSVReceiver { +struct sSVReceiver +{ bool running; bool stopped; @@ -69,7 +70,8 @@ struct sSVReceiver { }; -struct sSVSubscriber { +struct sSVSubscriber +{ uint8_t ethAddr[6]; uint16_t appId; @@ -78,8 +80,8 @@ struct sSVSubscriber { void* listenerParameter; }; -struct sSVSubscriber_ASDU { - +struct sSVSubscriber_ASDU +{ char* svId; char* datSet; @@ -191,13 +193,15 @@ svReceiverLoop(void* threadParameter) { SVReceiver self = (SVReceiver) threadParameter; - if (self->ethSocket) { + if (self->ethSocket) + { EthernetHandleSet handleSet = EthernetHandleSet_new(); EthernetHandleSet_addSocket(handleSet, self->ethSocket); self->stopped = false; - while (self->running) { + while (self->running) + { switch (EthernetHandleSet_waitReady(handleSet, 100)) { case -1: @@ -214,14 +218,16 @@ svReceiverLoop(void* threadParameter) EthernetHandleSet_destroy(handleSet); } #if (CONFIG_IEC61850_R_SMV == 1) - else if (self->session) { + else if (self->session) + { self->stopped = false; HandleSet handleSet = Handleset_new(); Handleset_addSocket(handleSet, RSession_getSocket(self->session)); - while (self->running) { + while (self->running) + { switch (Handleset_waitReady(handleSet, 100)) { case -1: @@ -247,9 +253,10 @@ svReceiverLoop(void* threadParameter) void SVReceiver_start(SVReceiver self) { - if (SVReceiver_startThreadless(self)) { - - if (self->interfaceId) { + if (SVReceiver_startThreadless(self)) + { + if (self->interfaceId) + { if (DEBUG_SV_SUBSCRIBER) 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); - if (self->thread) { + if (self->thread) + { Thread_start(self->thread); } - else { + else + { if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Failed to start thread\n"); } #endif /* (CONFIG_MMS_THREADLESS_STACK == 0) */ } - else { + else + { if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Starting SV receiver failed for interface %s\n", self->interfaceId); } @@ -284,15 +294,16 @@ SVReceiver_isRunning(SVReceiver self) return self->running; } - void SVReceiver_stop(SVReceiver self) { - if (self->running) { + if (self->running) + { self->running = false; #if (CONFIG_MMS_THREADLESS_STACK == 0) - if (self->thread) { + if (self->thread) + { Thread_destroy(self->thread); self->thread = NULL; } @@ -310,7 +321,7 @@ SVReceiver_destroy(SVReceiver self) LinkedList_destroyDeep(self->subscriberList, (LinkedListValueDeleteFunction) SVSubscriber_destroy); - if (self->interfaceId != NULL) + if (self->interfaceId) GLOBAL_FREEMEM(self->interfaceId); #if (CONFIG_MMS_THREADLESS_STACK == 0) @@ -330,25 +341,29 @@ bool SVReceiver_startThreadless(SVReceiver self) { #if (CONFIG_IEC61850_R_SMV == 1) - if (self->session) { - if (RSession_start(self->session) == R_SESSION_ERROR_OK) { + if (self->session) + { + if (RSession_start(self->session) == R_SESSION_ERROR_OK) + { self->running = true; return true; } - else { + else + { return false; } } - else { + else + { #endif /* (CONFIG_IEC61850_R_SMV == 1) */ if (self->interfaceId == NULL) self->ethSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, NULL); else self->ethSocket = Ethernet_createSocket(self->interfaceId, NULL); - if (self->ethSocket) { - + if (self->ethSocket) + { Ethernet_setProtocolFilter(self->ethSocket, ETH_P_SV); self->running = true; @@ -390,19 +405,21 @@ parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length) struct sSVSubscriber_ASDU asdu; memset(&asdu, 0, sizeof(struct sSVSubscriber_ASDU)); - while (bufPos < length) { + while (bufPos < length) + { int elementLength; uint8_t tag = buffer[bufPos++]; 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"); return; } - switch (tag) { - + switch (tag) + { case 0x80: asdu.svId = (char*) (buffer + bufPos); svIdLength = elementLength; @@ -455,7 +472,8 @@ parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length) if (asdu.datSet != NULL) asdu.datSet[datSetLength] = 0; - if (DEBUG_SV_SUBSCRIBER) { + if (DEBUG_SV_SUBSCRIBER) + { printf("SV_SUBSCRIBER: SV ASDU: ----------------\n"); printf("SV_SUBSCRIBER: DataLength: %d\n", asdu.dataBufferLength); 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 */ - if (subscriber) { + if (subscriber) + { if (subscriber->listener != NULL) subscriber->listener(subscriber, subscriber->listenerParameter, &asdu); } @@ -489,18 +508,21 @@ parseSequenceOfASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, i { int bufPos = 0; - while (bufPos < length) { + while (bufPos < length) + { int elementLength; uint8_t tag = buffer[bufPos++]; 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"); return; } - switch (tag) { + switch (tag) + { case 0x30: parseASDU(self, subscriber, buffer + bufPos, elementLength); break; @@ -519,25 +541,29 @@ parseSVPayload(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int ap { int bufPos = 0; - if (buffer[bufPos++] == 0x60) { + if (buffer[bufPos++] == 0x60) + { int elementLength; 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"); return; } int svEnd = bufPos + elementLength; - while (bufPos < svEnd) { + while (bufPos < svEnd) + { uint8_t tag = buffer[bufPos++]; bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, svEnd); if (bufPos < 0) goto exit_error; - switch(tag) { + switch(tag) + { case 0x80: /* noASDU (INTEGER) */ /* ignore */ break; @@ -551,7 +577,6 @@ parseSVPayload(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int ap break; } - bufPos += elementLength; } @@ -648,7 +673,8 @@ parseSVMessage(SVReceiver self, int numbytes) int headerLength = 14; /* 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 */ headerLength += 4; } @@ -674,7 +700,8 @@ parseSVMessage(SVReceiver self, int numbytes) int apduLength = length - 8; - if (numbytes < length + headerLength) { + if (numbytes < length + headerLength) + { if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Invalid PDU size\n"); return; @@ -694,16 +721,19 @@ handleSessionPayloadElement(void* parameter, uint16_t appId, uint8_t* payloadDat bool SVReceiver_tick(SVReceiver self) { - if (self->ethSocket) { + if (self->ethSocket) + { int packetSize = Ethernet_receivePacket(self->ethSocket, self->buffer, ETH_BUFFER_LENGTH); - if (packetSize > 0) { + if (packetSize > 0) + { parseSVMessage(self, packetSize); return true; } } #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) return true; } @@ -717,10 +747,11 @@ SVSubscriber_create(const uint8_t* ethAddr, uint16_t appID) { SVSubscriber self = (SVSubscriber) GLOBAL_CALLOC(1, sizeof(struct sSVSubscriber)); - if (self != NULL) { + if (self != NULL) + { self->appId = appID; - if (ethAddr != NULL) + if (ethAddr) memcpy(self->ethAddr, ethAddr, 6); } @@ -734,7 +765,6 @@ SVSubscriber_destroy(SVSubscriber self) GLOBAL_FREEMEM(self); } - void SVSubscriber_setListener(SVSubscriber self, SVUpdateListener listener, void* parameter) { @@ -748,7 +778,6 @@ SVSubscriber_ASDU_getSmpSynch(SVSubscriber_ASDU self) return self->smpSynch[0]; } - uint16_t SVSubscriber_ASDU_getSmpCnt(SVSubscriber_ASDU self) { @@ -1150,4 +1179,3 @@ SVClientASDU_getDataSize(SVSubscriber_ASDU self) { return SVSubscriber_ASDU_getDataSize(self); } -