From 49d06cc9d37888c633057f894fd4a81e7f078dbd Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Sun, 27 May 2018 20:16:27 +0200 Subject: [PATCH] - NET API: added TLS support for server side --- dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs | 25 +- dotnet/IEC61850forCSharp/TLS.cs | 8 - dotnet/dotnet.sln | 6 + dotnet/tls_server_example/Program.cs | 85 +++++++ .../Properties/AssemblyInfo.cs | 27 ++ dotnet/tls_server_example/model.cfg | 237 ++++++++++++++++++ dotnet/tls_server_example/root.cer | Bin 0 -> 785 bytes dotnet/tls_server_example/server-key.pem | 27 ++ dotnet/tls_server_example/server.cer | Bin 0 -> 767 bytes .../tls_server_example.csproj | 58 +++++ 10 files changed, 457 insertions(+), 16 deletions(-) create mode 100644 dotnet/tls_server_example/Program.cs create mode 100644 dotnet/tls_server_example/Properties/AssemblyInfo.cs create mode 100644 dotnet/tls_server_example/model.cfg create mode 100644 dotnet/tls_server_example/root.cer create mode 100644 dotnet/tls_server_example/server-key.pem create mode 100644 dotnet/tls_server_example/server.cer create mode 100644 dotnet/tls_server_example/tls_server_example.csproj diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs index 4b95c19ed..efff22eff 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs @@ -27,6 +27,7 @@ using System.Collections; using IEC61850.Common; +using IEC61850.TLS; /// /// IEC 61850 API for the libiec61850 .NET wrapper library @@ -558,9 +559,6 @@ public delegate CheckHandlerResult CheckHandler (DataObject controlObject, objec /// public class IedServer { - [DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)] - static extern IntPtr IedServer_create(IntPtr modelRef); - [DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)] static extern IntPtr IedServer_createWithConfig(IntPtr modelRef, IntPtr tlsConfiguration, IntPtr serverConfiguratio); @@ -789,19 +787,30 @@ private void connectionIndicationHandler (IntPtr iedServer, IntPtr clientConnect private Dictionary clientConnections = new Dictionary (); - public IedServer(IedModel iedModel) + + + public IedServer(IedModel iedModel, IedServerConfig config = null) { - self = IedServer_create(iedModel.self); + IntPtr nativeConfig = IntPtr.Zero; + + if (config != null) + nativeConfig = config.self; + + self = IedServer_createWithConfig (iedModel.self, IntPtr.Zero, nativeConfig); } - public IedServer(IedModel iedModel, IedServerConfig config) + public IedServer(IedModel iedModel, TLSConfiguration tlsConfig, IedServerConfig config = null) { IntPtr nativeConfig = IntPtr.Zero; + IntPtr nativeTLSConfig = IntPtr.Zero; if (config != null) nativeConfig = config.self; - self = IedServer_createWithConfig (iedModel.self, IntPtr.Zero, nativeConfig); + if (tlsConfig != null) + nativeTLSConfig = tlsConfig.GetNativeInstance (); + + self = IedServer_createWithConfig (iedModel.self, nativeTLSConfig, nativeConfig); } // causes undefined behavior @@ -850,7 +859,7 @@ public void Start(int tcpPort) /// Start MMS server public void Start () { - Start(102); + Start(-1); } /// diff --git a/dotnet/IEC61850forCSharp/TLS.cs b/dotnet/IEC61850forCSharp/TLS.cs index b7d67dc03..69a273b05 100644 --- a/dotnet/IEC61850forCSharp/TLS.cs +++ b/dotnet/IEC61850forCSharp/TLS.cs @@ -139,7 +139,6 @@ public void SetClientMode() public void SetOwnCertificate(string filename) { if (TLSConfiguration_setOwnCertificateFromFile (self, filename) == false) { - Console.WriteLine ("Failed to read certificate from file!"); throw new CryptographicException ("Failed to read certificate from file"); } } @@ -149,7 +148,6 @@ public void SetOwnCertificate(X509Certificate2 cert) byte[] certBytes = cert.GetRawCertData (); if (TLSConfiguration_setOwnCertificate (self, certBytes, certBytes.Length) == false) { - Console.WriteLine ("Failed to set certificate!"); throw new CryptographicException ("Failed to set certificate"); } } @@ -157,7 +155,6 @@ public void SetOwnCertificate(X509Certificate2 cert) public void AddAllowedCertificate(string filename) { if (TLSConfiguration_addAllowedCertificateFromFile (self, filename) == false) { - Console.WriteLine ("Failed to read allowed certificate from file!"); throw new CryptographicException ("Failed to read allowed certificate from file"); } } @@ -167,7 +164,6 @@ public void AddAllowedCertificate(X509Certificate2 cert) byte[] certBytes = cert.GetRawCertData (); if (TLSConfiguration_addAllowedCertificate (self, certBytes, certBytes.Length) == false) { - Console.WriteLine ("Failed to add allowed certificate!"); throw new CryptographicException ("Failed to add allowed certificate"); } } @@ -175,7 +171,6 @@ public void AddAllowedCertificate(X509Certificate2 cert) public void AddCACertificate(string filename) { if (TLSConfiguration_addCACertificateFromFile (self, filename) == false) { - Console.WriteLine ("Failed to read CA certificate from file!"); throw new CryptographicException ("Failed to read CA certificate from file"); } } @@ -185,7 +180,6 @@ public void AddCACertificate(X509Certificate2 cert) byte[] certBytes = cert.GetRawCertData (); if (TLSConfiguration_addCACertificate (self, certBytes, certBytes.Length) == false) { - Console.WriteLine ("Failed to add CA certificate!"); throw new CryptographicException ("Failed to add CA certificate"); } } @@ -193,7 +187,6 @@ public void AddCACertificate(X509Certificate2 cert) public void SetOwnKey (string filename, string password) { if (TLSConfiguration_setOwnKeyFromFile (self, filename, password) == false) { - Console.WriteLine ("Failed to read own key from file!"); throw new CryptographicException ("Failed to read own key from file"); } } @@ -203,7 +196,6 @@ public void SetOwnKey (X509Certificate2 key, string password) byte[] certBytes = key.Export (X509ContentType.Pkcs12); if (TLSConfiguration_setOwnKey (self, certBytes, certBytes.Length, password) == false) { - Console.WriteLine ("Failed to set own key!"); throw new CryptographicException ("Failed to set own key"); } } diff --git a/dotnet/dotnet.sln b/dotnet/dotnet.sln index 067ccaf99..ba1be6f49 100644 --- a/dotnet/dotnet.sln +++ b/dotnet/dotnet.sln @@ -42,6 +42,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "goose_subscriber", "goose_s EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sv_subscriber", "sv_subscriber\sv_subscriber.csproj", "{44651D2D-3252-4FD5-8B8B-5552DBE1B499}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tls_server_example", "tls_server_example\tls_server_example.csproj", "{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -96,6 +98,10 @@ Global {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Release|Any CPU.Build.0 = Release|Any CPU + {B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Release|Any CPU.Build.0 = Release|Any CPU {C351CFA4-E54E-49A1-86CE-69643535541A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C351CFA4-E54E-49A1-86CE-69643535541A}.Debug|Any CPU.Build.0 = Debug|Any CPU {C351CFA4-E54E-49A1-86CE-69643535541A}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/dotnet/tls_server_example/Program.cs b/dotnet/tls_server_example/Program.cs new file mode 100644 index 000000000..e7aa0cfce --- /dev/null +++ b/dotnet/tls_server_example/Program.cs @@ -0,0 +1,85 @@ +using System; +using System.Threading; +using System.Security.Cryptography.X509Certificates; + +using IEC61850.Server; +using IEC61850.Common; +using IEC61850.TLS; + +namespace tls_server_example +{ + class MainClass + { + public static void Main (string[] args) + { + bool running = true; + + /* run until Ctrl-C is pressed */ + Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { + e.Cancel = true; + running = false; + }; + + IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("model.cfg"); + + if (iedModel == null) { + Console.WriteLine ("No valid data model found!"); + return; + } + + DataObject spcso1 = (DataObject)iedModel.GetModelNodeByShortObjectReference ("GenericIO/GGIO1.SPCSO1"); + + TLSConfiguration tlsConfig = new TLSConfiguration (); + + tlsConfig.SetOwnCertificate (new X509Certificate2 ("server.cer")); + + tlsConfig.SetOwnKey ("server-key.pem", null); + + // Add a CA certificate to check the certificate provided by the server - not required when ChainValidation == false + tlsConfig.AddCACertificate (new X509Certificate2 ("root.cer")); + + // Check if the certificate is signed by a provided CA + tlsConfig.ChainValidation = true; + + // Check that the shown server certificate is in the list of allowed certificates + tlsConfig.AllowOnlyKnownCertificates = false; + + IedServer iedServer = new IedServer (iedModel, tlsConfig); + + iedServer.SetControlHandler (spcso1, delegate(DataObject controlObject, object parameter, MmsValue ctlVal, bool test) { + bool val = ctlVal.GetBoolean(); + + if (val) + Console.WriteLine("received binary control command: on"); + else + Console.WriteLine("received binary control command: off"); + + return ControlHandlerResult.OK; + }, null); + + iedServer.Start (); + Console.WriteLine ("Server started"); + + GC.Collect (); + + DataObject ggio1AnIn1 = (DataObject)iedModel.GetModelNodeByShortObjectReference ("GenericIO/GGIO1.AnIn1"); + + DataAttribute ggio1AnIn1magF = (DataAttribute)ggio1AnIn1.GetChild ("mag.f"); + DataAttribute ggio1AnIn1T = (DataAttribute)ggio1AnIn1.GetChild ("t"); + + float floatVal = 1.0f; + + while (running) { + floatVal += 1f; + iedServer.UpdateTimestampAttributeValue (ggio1AnIn1T, new Timestamp (DateTime.Now)); + iedServer.UpdateFloatAttributeValue (ggio1AnIn1magF, floatVal); + Thread.Sleep (100); + } + + iedServer.Stop (); + Console.WriteLine ("Server stopped"); + + iedServer.Destroy (); + } + } +} diff --git a/dotnet/tls_server_example/Properties/AssemblyInfo.cs b/dotnet/tls_server_example/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..638df6352 --- /dev/null +++ b/dotnet/tls_server_example/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("tls_server_example")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("mzillgit")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/dotnet/tls_server_example/model.cfg b/dotnet/tls_server_example/model.cfg new file mode 100644 index 000000000..6f332425a --- /dev/null +++ b/dotnet/tls_server_example/model.cfg @@ -0,0 +1,237 @@ +MODEL(simpleIO){ +LD(GenericIO){ +LN(LLN0){ +DO(Mod 0){ +DA(stVal 0 12 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +DA(ctlModel 0 12 4 0 0)=0; +} +DO(Beh 0){ +DA(stVal 0 12 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(Health 0){ +DA(stVal 0 3 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(NamPlt 0){ +DA(vendor 0 20 5 0 0); +DA(swRev 0 20 5 0 0); +DA(d 0 20 5 0 0); +DA(configRev 0 20 5 0 0); +DA(ldNs 0 20 11 0 0); +} +DS(Events){ +DE(GGIO1$ST$SPCSO1$stVal); +DE(GGIO1$ST$SPCSO2$stVal); +DE(GGIO1$ST$SPCSO3$stVal); +DE(GGIO1$ST$SPCSO4$stVal); +} +DS(AnalogValues){ +DE(GGIO1$MX$AnIn1); +DE(GGIO1$MX$AnIn2); +DE(GGIO1$MX$AnIn3); +DE(GGIO1$MX$AnIn4); +} +RC(EventsRCB01 Events 0 Events 1 24 111 50 1000); +RC(AnalogValuesRCB01 AnalogValues 0 AnalogValues 1 24 111 50 1000); +LC(EventLog Events GenericIO/LLN0$EventLog 19 0 0 1); +LC(GeneralLog - - 19 0 0 1); +LOG(GeneralLog); +LOG(EventLog); +GC(gcbEvents events Events 2 0 -1 -1 ){ +PA(4 273 4096 010ccd010001); +} +GC(gcbAnalogValues analog AnalogValues 2 0 -1 -1 ){ +PA(4 273 4096 010ccd010001); +} +} +LN(LPHD1){ +DO(PhyNam 0){ +DA(vendor 0 20 5 0 0); +} +DO(PhyHealth 0){ +DA(stVal 0 3 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(Proxy 0){ +DA(stVal 0 0 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +} +LN(GGIO1){ +DO(Mod 0){ +DA(stVal 0 12 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +DA(ctlModel 0 12 4 0 0)=0; +} +DO(Beh 0){ +DA(stVal 0 12 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(Health 0){ +DA(stVal 0 3 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(NamPlt 0){ +DA(vendor 0 20 5 0 0); +DA(swRev 0 20 5 0 0); +DA(d 0 20 5 0 0); +} +DO(AnIn1 0){ +DA(mag 0 27 1 1 0){ +DA(f 0 10 1 1 0); +} +DA(q 0 23 1 2 0); +DA(t 0 22 1 0 0); +} +DO(AnIn2 0){ +DA(mag 0 27 1 1 101){ +DA(f 0 10 1 1 0); +} +DA(q 0 23 1 2 0); +DA(t 0 22 1 0 102); +} +DO(AnIn3 0){ +DA(mag 0 27 1 1 0){ +DA(f 0 10 1 1 0); +} +DA(q 0 23 1 2 0); +DA(t 0 22 1 0 0); +} +DO(AnIn4 0){ +DA(mag 0 27 1 1 0){ +DA(f 0 10 1 1 0); +} +DA(q 0 23 1 2 0); +DA(t 0 22 1 0 0); +} +DO(SPCSO1 0){ +DA(stVal 0 0 0 1 0); +DA(q 0 23 0 2 0); +DA(Oper 0 27 12 0 0){ +DA(ctlVal 0 0 12 0 0); +DA(origin 0 27 12 0 0){ +DA(orCat 0 12 12 0 0); +DA(orIdent 0 13 12 0 0); +} +DA(ctlNum 0 6 12 0 0); +DA(T 0 22 12 0 0); +DA(Test 0 0 12 0 0); +DA(Check 0 24 12 0 0); +} +DA(ctlModel 0 12 4 0 0)=1; +DA(t 0 22 0 0 0); +} +DO(SPCSO2 0){ +DA(stVal 0 0 0 1 0); +DA(q 0 23 0 2 0); +DA(Oper 0 27 12 0 0){ +DA(ctlVal 0 0 12 0 0); +DA(origin 0 27 12 0 0){ +DA(orCat 0 12 12 0 0); +DA(orIdent 0 13 12 0 0); +} +DA(ctlNum 0 6 12 0 0); +DA(T 0 22 12 0 0); +DA(Test 0 0 12 0 0); +DA(Check 0 24 12 0 0); +} +DA(ctlModel 0 12 4 0 0)=1; +DA(t 0 22 0 0 0); +} +DO(SPCSO3 0){ +DA(stVal 0 0 0 1 0); +DA(q 0 23 0 2 0); +DA(Oper 0 27 12 0 0){ +DA(ctlVal 0 0 12 0 0); +DA(origin 0 27 12 0 0){ +DA(orCat 0 12 12 0 0); +DA(orIdent 0 13 12 0 0); +} +DA(ctlNum 0 6 12 0 0); +DA(T 0 22 12 0 0); +DA(Test 0 0 12 0 0); +DA(Check 0 24 12 0 0); +} +DA(ctlModel 0 12 4 0 0)=1; +DA(t 0 22 0 0 0); +} +DO(SPCSO4 0){ +DA(stVal 0 0 0 1 0); +DA(q 0 23 0 2 0); +DA(Oper 0 27 12 0 0){ +DA(ctlVal 0 0 12 0 0); +DA(origin 0 27 12 0 0){ +DA(orCat 0 12 12 0 0); +DA(orIdent 0 13 12 0 0); +} +DA(ctlNum 0 6 12 0 0); +DA(T 0 22 12 0 0); +DA(Test 0 0 12 0 0); +DA(Check 0 24 12 0 0); +} +DA(ctlModel 0 12 4 0 0)=1; +DA(t 0 22 0 0 0); +} +DO(Ind1 0){ +DA(stVal 0 0 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(Ind2 0){ +DA(stVal 0 0 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(Ind3 0){ +DA(stVal 0 0 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(Ind4 0){ +DA(stVal 0 0 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +} +LN(PDUP1){ +DO(Beh 0){ +DA(stVal 0 12 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(Mod 0){ +DA(stVal 0 12 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +DA(ctlModel 0 12 4 0 0)=0; +} +DO(Str 0){ +DA(general 0 0 0 1 0); +DA(dirGeneral 0 12 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(Op 0){ +DA(general 0 0 0 1 0); +DA(q 0 23 0 2 0); +DA(t 0 22 0 0 0); +} +DO(OpDlTmms 0){ +DA(setVal 0 3 2 1 0); +} +DO(RsDlTmms 0){ +DA(setVal 0 3 2 1 0); +} +} +} +} diff --git a/dotnet/tls_server_example/root.cer b/dotnet/tls_server_example/root.cer new file mode 100644 index 0000000000000000000000000000000000000000..87683444999a84b86230a7a7af3e8ae5f43de456 GIT binary patch literal 785 zcmXqLV&*kyV*I&)nTe5!Nuct==g24KTiYGuKQ`@snRCd1lZ{oIkC{o9mBB#VP}D$} zjX9KsS(v9JwYWr~C_leMAvw`NPMp`!+`!V%z`)eh!pJa6oY&aW(8w5wOf5|` z(wWYiKOLyEJDq62&(eRT@%!?cffsk(2{qzp?3i|LPg0^I z|3lW;x$){3^KEY}i!BO|$}-AMs4^C4cP!ZW=&9nDPhvj~U474^mv+d=U_zFY{BEl+ zCtTf5O|W#ZeB=Ig_opwfx_%y=H2sM%o6x!Rl+|8NL3KNVKlBQOmi@J4*c>@^bCAou zI};2iACBrQKasWOf>D}@*!o)MlEjb6PoFP&b|r4DxevR9zxKk}lIA92)4Qjqe6!Y; zcls_?@a<`Pn`P|u1?TthN?3_0?wA$wfKB2B+o7L<6$d^>%UJf;GBGnUFfNWYh&JE{ zhP$jVBjbM-Rs&`rW#9o4U}SMLux}8USd{(u$~})AH-eYjB`xX`SSX1z$eZxRFfi~L z84mxQHa%&11#VjF7vG}U-PY%L*=*YJ^S(M?MLC@M_bm_ z?CkRJ{Hieb&DO0EY#cW$EaQb*yT8AkZE?uXic68-skyfG@}|xxp~lSC#6M)USQ3{1a@a{C}tQ&+P(d!mVw;%cg~dZP1!8#g(e7899&ZS6)q4 z*UIzX+OJgGIUKt8;nQB8lWT4j40$|3PQ~ literal 0 HcmV?d00001 diff --git a/dotnet/tls_server_example/server-key.pem b/dotnet/tls_server_example/server-key.pem new file mode 100644 index 000000000..6fe35295d --- /dev/null +++ b/dotnet/tls_server_example/server-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAu3Fjxb904UdyV/dDfvs8SFi6zJeNoMYjmpXm/LBcFSH3zGoK +wdcMovrUTED3Cc6Ww84AYpJ5MRMPTct7DfKJkWfSnkzOPmLldTSTv3RvzGVb4NzK +QqA5aSVDqAzPiP5RnFT6Q4KWRe69TMFxpw7zMXCJx9jDggqN1oojGGkmSgYGXnFd +Nc20Mujejh5pihgwnN4Y/bPFyxJwvIMj+D8qr9klhEmXKPTiX9UFd8oLkn9JCB6+ +SiHhNyFIo+Llossn1Q2hxCGty36fAhEWzpfBTaY510VLjie9y4q9GPTwxITDqSQd +xcX8IuvrbxX0DyEK507SMmTJmB9448eF9ZCWFQIDAQABAoIBAC80BuQtqslwrKLq +adz4d93gOmp7X/c07pJnXZwU7ZuEylp3+e2Gsm/4qq3pTkzx8ZWtsvsf19U774av +z3VbtrkfZDLpNKcRUKeLbgmw0NawT8r4zxaoMsz/zWHsl/bv1K2B2ORXZnCGBrXl +oTFo2mWA6bGiLNn6vm1grCXhlPreywyG/kFK3pi2VvkpvG3XZSI7mmZ0Dq/MD3nO +03oOZBqwwnMObfQQdhKE7646/+KgeuF/JsXaUH4bkHmtzYWyocWYMqpC0hjpNWlQ +cKuQ7t1kfmpsGD9aNW4+ND2ok9BdxIiC+rPXS9NDqZxoWLp+a8seU++uqk1l8RPq +tPE3LqECgYEAz1NmemNLiUsKvyemUvjp8+dJupzWtdV7fsnCbYhj/5gDA2UhFKCf +dP9xiHCdNe0797oAqHY7c3JhS4ug8haDy9aDIu5GG2DNYzjX/oYm4ywbCdRx+uEN +RcTw69FjSYVGkObmxWYszwsFybRasV6PYamg65qYR3FlvW2Td4Fndy8CgYEA53L/ +zHtBRQiNGJU9jfMHeX0bTtXIAt622Qn78jw0it/rhXWi2RwG2Cw5Q2aPRJ6uMt9F +yk1+GAPZcwYqwjq/nKRrl71Tn+KDWIk5rz1fNYRkaXtnMLs2MOogqoDTBshW0QBq +tnPrFNsaLKX6V92Az69wHjd2uwvLQLTvS/EuNfsCgYEAr3to/uhytAd3VirKRep3 +o0E+D5zWw1upxrwhPDK4aUuSKVp8sIfvz8iyoQiomE9vdZPTIMPKOEI1BgtuM9pI +vcyYfIVvg5bg4T3o3H9SBPB9BknyG6ZHZKl4PjGht0X+X4GBDM4Z2Tj8Mijcpsph +1AkOsrzMbZQWyEoqCnnWSHMCgYAFEHUcak4BTrCXqxxPsNOnCt/AF9lqhqkFkrxa +joqvxzqGDw7jJUPZEw6ltObJn5c8Mbp7NLrfl6X4aFgjK9npeYeJKHFd/DzXgRks +BnHA4Aa6cCLP5CjJZTYVxP/ZFCUiKZosJ9kq+ahW9cLGjWg2IyaW4qvMZ/OolMzv +onVaZQKBgQCir8u1vDsyA4JQXMytPHBJe27XaLRGULvteNydVB59Vt21a99o5gt1 +5B9gwWArZdZby3/KZiliNmzp8lMCrLJYjTL5WK6dbWdq92X5hCOofKPIjEcgHjhk +mvnAos3HeC83bJQtADXhw9jR7Vr6GJLM9HDcIgeIMzX7+BuqlMgaHA== +-----END RSA PRIVATE KEY----- diff --git a/dotnet/tls_server_example/server.cer b/dotnet/tls_server_example/server.cer new file mode 100644 index 0000000000000000000000000000000000000000..957bdc30f978d52f7ef9b5aa73375a9a21b7d6de GIT binary patch literal 767 zcmXqLV)|{+#Q1yxGZP~dlfcF$T&n{mk2X1Hu@+U&Yh7l*$;PV9$IK+l%3vUFC~6?g z#vIDREX-4qT3n(~l%HRskep~BC(dhVZeVF>U|?ooY-AoK&TDLGXk-jTrk19bQ3hg$ zA_hVbjocuOy2YtQWvN9#Yn2Rm**LY@JlekVGBPr1y6jofFe9&GR{Dm-MvMWb*!!{4=T15AK|DT40%}>b!#Ie8<1QIU&ECo2I$G z+v{_%a5>*+!-CG^Hx4&(^;34=NJB>rwbdRnMp zPqXq5d#&|1Ra-o#YkYYWf0ecT6!)ZhPY$_#UWyOR6+IR|db;Se`c>YAM-A`gOkO7k)*q=YE%rQclj0uXudC z_3MObqD;(;42+9?47?0HfT1VL$l_>V-ykrtDEse~dmcM(1TVKsTGS`7P!ea%GznB* z_#FAfd~3U7{KuxfFLMqd#V0VV85z_X5Aq+fxo*FBLA!nRf40v@?yqIdGWfc4*JM!> zt$wo&YR2=0t!-!RILa5m?eeIE+kc)37srHKV!8XST{P|D&E3atlJWDngFNGwPYwk} zae8^{g~9@oBAN~v)mHHzf7_V)qQAQ)l}FApI%hS@ysH`>QnME=GoABm@;9OB@xsUd zY|B@igY~1rOhO&iJ=7*nRRg`ByzZ^d_=> zIr44Av<_+G164WU*JW?^@5ts${Al;^-O(+cW-`V*rf3@ + + + Debug + AnyCPU + {B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307} + Exe + tls_server_example + tls_server_example + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + + + full + true + bin\Release + prompt + 4 + true + + + + + + + + + + + + {C35D624E-5506-4560-8074-1728F1FA1A4D} + IEC61850.NET + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + \ No newline at end of file