From 24375f1045c924b29d9b5b01856ff2e7f78fae38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Guzm=C3=A1n=20=C3=81lvarez?= Date: Mon, 10 Nov 2003 16:13:41 +0000 Subject: Updated TLS/SSL implementation files with unix-like line endings svn path=/trunk/mcs/; revision=19785 --- mcs/class/Mono.Security/ChangeLog | 240 ++-- .../MD5SHA1CryptoServiceProvider.cs | 254 ++-- .../TlsClientCertificate.cs | 164 +-- .../TlsClientCertificateVerify.cs | 176 +-- .../TlsClientFinished.cs | 172 +-- .../TlsClientHello.cs | 226 ++-- .../TlsClientKeyExchange.cs | 198 +-- .../TlsServerCertificate.cs | 264 ++-- .../TlsServerCertificateRequest.cs | 224 ++-- .../TlsServerFinished.cs | 236 ++-- .../TlsServerHello.cs | 278 ++-- .../TlsServerHelloDone.cs | 126 +- .../TlsServerKeyExchange.cs | 238 ++-- .../TlsClientCertificateType.cs | 74 +- .../TlsHandshakeMessage.cs | 276 ++-- .../TlsHandshakeType.cs | 84 +- .../Mono.Security.Protocol.Tls/CipherSuite.cs | 1020 +++++++-------- .../Mono.Security.Protocol.Tls/TlsCipherSuite.cs | 310 ++--- .../TlsCipherSuiteCollection.cs | 312 ++--- .../TlsCipherSuiteFactory.cs | 338 ++--- .../TlsCompressionMethod.cs | 74 +- .../Mono.Security.Protocol.Tls/TlsContentType.cs | 72 +- .../Mono.Security.Protocol.Tls/TlsException.cs | 104 +- .../Mono.Security.Protocol.Tls/TlsNetworkStream.cs | 738 +++++------ .../Mono.Security.Protocol.Tls/TlsProtocol.cs | 66 +- .../TlsServerSettings.cs | 202 +-- .../Mono.Security.Protocol.Tls/TlsSession.cs | 528 ++++---- .../TlsSessionContext.cs | 578 ++++----- .../TlsSessionSettings.cs | 436 +++---- .../Mono.Security.Protocol.Tls/TlsSessionState.cs | 78 +- .../Mono.Security.Protocol.Tls/TlsSocket.cs | 1326 ++++++++++---------- .../TlsSslCipherSuite.cs | 502 ++++---- .../TlsSslHandshakeHash.cs | 314 ++--- .../Mono.Security.Protocol.Tls/TlsStream.cs | 500 ++++---- 34 files changed, 5366 insertions(+), 5362 deletions(-) diff --git a/mcs/class/Mono.Security/ChangeLog b/mcs/class/Mono.Security/ChangeLog index ff53328d6af..20799c3502a 100644 --- a/mcs/class/Mono.Security/ChangeLog +++ b/mcs/class/Mono.Security/ChangeLog @@ -1,118 +1,122 @@ -2003-11-04 Carlos Guzmán Álvarez - - * Mono.Security.Protocol.Tls/CipherSuite.cs: - - - Added custom padding for record encryption. - - -2003-11-03 Carlos Guzmán Álvarez - - * Mono.Security.Protocol.Tls.Handshake/TlsHandshakeMessages.cs: - - - Removed file. - - * Mono.Security.Protocol.Tls/TlsSslHandshakeHash.cs: - - - New class for handshake hashes calculation on SSL3 protocol. - - * Mono.Security.Protocol.Tls/TlsSessionContext.cs: - - - Fixed mac keys clearing for SSL3 protocol. - - * Mono.Security.Protocol.Tls/TlsSslCipherSuite.cs: - * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs: - - - Added changes for make use of new TlsSslHandshakeHash class. - - * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs: - - - Added initial implementation for SSL3 protocol. - - * Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs: - - - New class for md5-sha hash calculation. - - * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs: - * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs: - * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs: - * Mono.Security.Protocol.Tls.Handshake.Client/TlsHandshakeMessage.cs: - - - Make use of new MD5SHA1CryptoServiceProvider class. - - * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs: - - - Added initial implementation (not finished). - - * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs: - - - Minor change to message processing. - - - Changed verify method name to verifySignature. - - * Mono.Security.Protocol.Tls/TlsSessionContext.cs: - - - Changed handshakeHashes member to be an TlsStream. - -2003-10-28 Carlos Guzmán Álvarez - - * Mono.Security.Protocol.Tls/CipherSuite.cs: - * Mono.Security.Protocol.Tls/TlsSessionSettings.cs: - * Mono.Security.Protocol.Tls/TlsServerSettings.cs: - * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs: - * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientKeyExchange.cs: - * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs: - * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs: - - - Added changes for make use of X509 classes from mono. - -2003-10-23 Carlos Guzmán Álvarez - - * Added partial implementation of SSL3 protocol ( not finished yet ) to the TLS sources. - -2003-10-20 Sebastien Pouliot - - * Mono.Security.dll.sources: Removed AssemblyInfo.cs from build. - This file is for TLS not for the complete Mono.Security assembly. - -2003-10-20 Duncan Mak - - * Mono.Security.dll.sources: Added TlsAbstractCipherSuite.cs, - TlsCipherSuiteFactory.cs and TlsCompressMethod.cs. This fixes the - build. - -2003-10-20 Carlos Guzmán Álvarez - - * Mono.Security.dll.sources: Added references for new Tls files. - -2003-10-20 Pedro Martínez Juliá - - * Mono.Security.dll.sources: Added references for Tls files. - -2003-09-05 Sebastien Pouliot - - * KeyAttributesExtension.cs: New. Added for WSE. - -2003-09-01 Sebastien Pouliot - - * Mono.Security.dll.sources: Added support for Authenticode(tm) - signatures. - -2003-07-30 Sebastien Pouliot - - * Mono.Security.dll.sources: Added ExtendedKeyUsageExtension.cs - certificate extension (so MakeCert can now create SSL certificates). - -2003-07-28 Sebastien Pouliot - - * Mono.Security.dll.sources: Added missing SubjectAltNameExtension.cs - -2003-06-14 Sebastien Pouliot - - * list.unix. Added SubjectAltNameExtension.cs - -2003-03-06 Sebastien Pouliot - - * list.unix: New. All C# files required to build the assembly. - * makefile.gnu: New. Makefile to build the assembly under Linux. - * Mono.Security.build: New. NAnt build file. - +2003-11-04 Carlos Guzmán Álvarez (carlosga@telefonica.net) + + * Updated SSL/TLS implementation files with unix like line endings. + +2003-11-04 Carlos Guzmán Álvarez + + * Mono.Security.Protocol.Tls/CipherSuite.cs: + + - Added custom padding for record encryption. + + +2003-11-03 Carlos Guzmán Álvarez + + * Mono.Security.Protocol.Tls.Handshake/TlsHandshakeMessages.cs: + + - Removed file. + + * Mono.Security.Protocol.Tls/TlsSslHandshakeHash.cs: + + - New class for handshake hashes calculation on SSL3 protocol. + + * Mono.Security.Protocol.Tls/TlsSessionContext.cs: + + - Fixed mac keys clearing for SSL3 protocol. + + * Mono.Security.Protocol.Tls/TlsSslCipherSuite.cs: + * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs: + + - Added changes for make use of new TlsSslHandshakeHash class. + + * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs: + + - Added initial implementation for SSL3 protocol. + + * Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs: + + - New class for md5-sha hash calculation. + + * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs: + * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs: + * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs: + * Mono.Security.Protocol.Tls.Handshake.Client/TlsHandshakeMessage.cs: + + - Make use of new MD5SHA1CryptoServiceProvider class. + + * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs: + + - Added initial implementation (not finished). + + * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs: + + - Minor change to message processing. + + - Changed verify method name to verifySignature. + + * Mono.Security.Protocol.Tls/TlsSessionContext.cs: + + - Changed handshakeHashes member to be an TlsStream. + +2003-10-28 Carlos Guzmán Álvarez + + * Mono.Security.Protocol.Tls/CipherSuite.cs: + * Mono.Security.Protocol.Tls/TlsSessionSettings.cs: + * Mono.Security.Protocol.Tls/TlsServerSettings.cs: + * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs: + * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientKeyExchange.cs: + * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs: + * Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs: + + - Added changes for make use of X509 classes from mono. + +2003-10-23 Carlos Guzmán Álvarez + + * Added partial implementation of SSL3 protocol ( not finished yet ) to the TLS sources. + +2003-10-20 Sebastien Pouliot + + * Mono.Security.dll.sources: Removed AssemblyInfo.cs from build. + This file is for TLS not for the complete Mono.Security assembly. + +2003-10-20 Duncan Mak + + * Mono.Security.dll.sources: Added TlsAbstractCipherSuite.cs, + TlsCipherSuiteFactory.cs and TlsCompressMethod.cs. This fixes the + build. + +2003-10-20 Carlos Guzmán Álvarez + + * Mono.Security.dll.sources: Added references for new Tls files. + +2003-10-20 Pedro Martínez Juliá + + * Mono.Security.dll.sources: Added references for Tls files. + +2003-09-05 Sebastien Pouliot + + * KeyAttributesExtension.cs: New. Added for WSE. + +2003-09-01 Sebastien Pouliot + + * Mono.Security.dll.sources: Added support for Authenticode(tm) + signatures. + +2003-07-30 Sebastien Pouliot + + * Mono.Security.dll.sources: Added ExtendedKeyUsageExtension.cs + certificate extension (so MakeCert can now create SSL certificates). + +2003-07-28 Sebastien Pouliot + + * Mono.Security.dll.sources: Added missing SubjectAltNameExtension.cs + +2003-06-14 Sebastien Pouliot + + * list.unix. Added SubjectAltNameExtension.cs + +2003-03-06 Sebastien Pouliot + + * list.unix: New. All C# files required to build the assembly. + * makefile.gnu: New. Makefile to build the assembly under Linux. + * Mono.Security.build: New. NAnt build file. + diff --git a/mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs b/mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs index 5440e3f3a8d..bf97dfd3a82 100755 --- a/mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs +++ b/mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs @@ -1,127 +1,127 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Security.Cryptography; - -namespace Mono.Security.Cryptography -{ - internal class MD5SHA1CryptoServiceProvider : HashAlgorithm - { - #region FIELDS - - private HashAlgorithm md5; - private HashAlgorithm sha; - private bool hashing; - - #endregion - - #region CONSTRUCTORS - - public MD5SHA1CryptoServiceProvider() - { - this.md5 = new MD5CryptoServiceProvider(); - this.sha = new SHA1CryptoServiceProvider(); - - // Set HashSizeValue - this.HashSizeValue = this.md5.HashSize + this.sha.HashSize; - } - - #endregion - - #region METHODS - - public override void Initialize() - { - this.md5.Initialize(); - this.sha.Initialize(); - this.hashing = false; - } - - protected override byte[] HashFinal() - { - if (!hashing) - { - this.hashing = true; - } - // Finalize the original hash - this.md5.TransformFinalBlock(new byte[0], 0, 0); - this.sha.TransformFinalBlock(new byte[0], 0, 0); - - byte[] hash = new byte[36]; - - System.Array.Copy(this.md5.Hash, 0, hash, 0, 16); - System.Array.Copy(this.sha.Hash, 0, hash, 16, 20); - - return hash; - } - - protected override void HashCore( - byte[] array, - int ibStart, - int cbSize) - { - if (!hashing) - { - hashing = true; - } - this.md5.TransformBlock(array, ibStart, cbSize, array, ibStart); - this.sha.TransformBlock(array, ibStart, cbSize, array, ibStart); - } - - public byte[] CreateSignature(RSA rsa) - { - if (rsa == null) - { - throw new CryptographicUnexpectedOperationException ("missing key"); - } - - #warning "MD5SHA1 hash is not supported by .NET" - RSAPKCS1SignatureFormatter f = new RSAPKCS1SignatureFormatter(rsa); - f.SetHashAlgorithm("MD5SHA1"); - - return f.CreateSignature(this.Hash); - } - - public bool VerifySignature(RSA rsa, byte[] rgbSignature) - { - if (rsa == null) - { - throw new CryptographicUnexpectedOperationException ("missing key"); - } - if (rgbSignature == null) - { - throw new ArgumentNullException ("rgbSignature"); - } - - #warning "MD5SHA1 hash is not supported by .NET" - RSAPKCS1SignatureDeformatter d = new RSAPKCS1SignatureDeformatter(rsa); - d.SetHashAlgorithm("MD5SHA1"); - - return d.VerifySignature(this.Hash, rgbSignature); - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Security.Cryptography; + +namespace Mono.Security.Cryptography +{ + internal class MD5SHA1CryptoServiceProvider : HashAlgorithm + { + #region FIELDS + + private HashAlgorithm md5; + private HashAlgorithm sha; + private bool hashing; + + #endregion + + #region CONSTRUCTORS + + public MD5SHA1CryptoServiceProvider() + { + this.md5 = new MD5CryptoServiceProvider(); + this.sha = new SHA1CryptoServiceProvider(); + + // Set HashSizeValue + this.HashSizeValue = this.md5.HashSize + this.sha.HashSize; + } + + #endregion + + #region METHODS + + public override void Initialize() + { + this.md5.Initialize(); + this.sha.Initialize(); + this.hashing = false; + } + + protected override byte[] HashFinal() + { + if (!hashing) + { + this.hashing = true; + } + // Finalize the original hash + this.md5.TransformFinalBlock(new byte[0], 0, 0); + this.sha.TransformFinalBlock(new byte[0], 0, 0); + + byte[] hash = new byte[36]; + + System.Array.Copy(this.md5.Hash, 0, hash, 0, 16); + System.Array.Copy(this.sha.Hash, 0, hash, 16, 20); + + return hash; + } + + protected override void HashCore( + byte[] array, + int ibStart, + int cbSize) + { + if (!hashing) + { + hashing = true; + } + this.md5.TransformBlock(array, ibStart, cbSize, array, ibStart); + this.sha.TransformBlock(array, ibStart, cbSize, array, ibStart); + } + + public byte[] CreateSignature(RSA rsa) + { + if (rsa == null) + { + throw new CryptographicUnexpectedOperationException ("missing key"); + } + + #warning "MD5SHA1 hash is not supported by .NET" + RSAPKCS1SignatureFormatter f = new RSAPKCS1SignatureFormatter(rsa); + f.SetHashAlgorithm("MD5SHA1"); + + return f.CreateSignature(this.Hash); + } + + public bool VerifySignature(RSA rsa, byte[] rgbSignature) + { + if (rsa == null) + { + throw new CryptographicUnexpectedOperationException ("missing key"); + } + if (rgbSignature == null) + { + throw new ArgumentNullException ("rgbSignature"); + } + + #warning "MD5SHA1 hash is not supported by .NET" + RSAPKCS1SignatureDeformatter d = new RSAPKCS1SignatureDeformatter(rsa); + d.SetHashAlgorithm("MD5SHA1"); + + return d.VerifySignature(this.Hash, rgbSignature); + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificate.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificate.cs index 0feec874dca..3ba44de72ff 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificate.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificate.cs @@ -1,82 +1,82 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using Mono.Security.Protocol.Tls; -using System.Security.Cryptography.X509Certificates; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsClientCertificate : TlsHandshakeMessage - { - #region CONSTRUCTORS - - public TlsClientCertificate(TlsSession session) - : base(session, TlsHandshakeType.Certificate, TlsContentType.Handshake) - { - } - - #endregion - - #region METHODS - - public override void UpdateSession() - { - base.UpdateSession(); - this.Reset(); - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - this.ProcessAsTls1(); - } - - protected override void ProcessAsTls1() - { - if (Session.Settings.Certificates == null || - Session.Settings.Certificates.Count == 0) - { - throw this.Session.CreateException("Client certificate requested by the server and no client certificate specified."); - } - - // Write client certificates information to a stream - TlsStream stream = new TlsStream(); - foreach (X509Certificate cert in Session.Settings.Certificates) - { - stream.WriteInt24(cert.GetRawCertData().Length); - stream.Write(cert.GetRawCertData()); - } - - // Compose the message - this.WriteInt24((int)stream.Length); - this.Write(stream.ToArray()); - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using Mono.Security.Protocol.Tls; +using System.Security.Cryptography.X509Certificates; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsClientCertificate : TlsHandshakeMessage + { + #region CONSTRUCTORS + + public TlsClientCertificate(TlsSession session) + : base(session, TlsHandshakeType.Certificate, TlsContentType.Handshake) + { + } + + #endregion + + #region METHODS + + public override void UpdateSession() + { + base.UpdateSession(); + this.Reset(); + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + this.ProcessAsTls1(); + } + + protected override void ProcessAsTls1() + { + if (Session.Settings.Certificates == null || + Session.Settings.Certificates.Count == 0) + { + throw this.Session.CreateException("Client certificate requested by the server and no client certificate specified."); + } + + // Write client certificates information to a stream + TlsStream stream = new TlsStream(); + foreach (X509Certificate cert in Session.Settings.Certificates) + { + stream.WriteInt24(cert.GetRawCertData().Length); + stream.Write(cert.GetRawCertData()); + } + + // Compose the message + this.WriteInt24((int)stream.Length); + this.Write(stream.ToArray()); + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs index fdfc66d2e9c..4d986ffdbe4 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs @@ -1,88 +1,88 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Security.Cryptography.X509Certificates; - -using System.Security.Cryptography; -using Mono.Security.Cryptography; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsClientCertificateVerify : TlsHandshakeMessage - { - #region CONSTRUCTORS - - public TlsClientCertificateVerify(TlsSession session) - : base(session, TlsHandshakeType.Finished, TlsContentType.Handshake) - { - } - - #endregion - - #region METHODS - - public override void UpdateSession() - { - base.UpdateSession(); - this.Reset(); - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - throw new NotSupportedException(); - } - - protected override void ProcessAsTls1() - { - foreach (X509Certificate cert in Session.Settings.Certificates) - { - MD5SHA1CryptoServiceProvider hash = new MD5SHA1CryptoServiceProvider(); - X509.X509Certificate c = new X509.X509Certificate(cert.GetRawCertData()); - RSA rsa = c.RSA; - RSAParameters p = rsa.ExportParameters(false); - TlsStream data = new TlsStream(); - - data.Write(this.Session.Context.RandomCS); - data.Write((short)p.Modulus.Length); - data.Write(p.Modulus); - data.Write((short)p.Exponent.Length); - data.Write(p.Exponent); - - hash.ComputeHash(data.ToArray(), 0, (int)data.Length); - - data.Reset(); - - // Write the signature - Write(hash.CreateSignature(rsa)); - } - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Security.Cryptography.X509Certificates; + +using System.Security.Cryptography; +using Mono.Security.Cryptography; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsClientCertificateVerify : TlsHandshakeMessage + { + #region CONSTRUCTORS + + public TlsClientCertificateVerify(TlsSession session) + : base(session, TlsHandshakeType.Finished, TlsContentType.Handshake) + { + } + + #endregion + + #region METHODS + + public override void UpdateSession() + { + base.UpdateSession(); + this.Reset(); + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + throw new NotSupportedException(); + } + + protected override void ProcessAsTls1() + { + foreach (X509Certificate cert in Session.Settings.Certificates) + { + MD5SHA1CryptoServiceProvider hash = new MD5SHA1CryptoServiceProvider(); + X509.X509Certificate c = new X509.X509Certificate(cert.GetRawCertData()); + RSA rsa = c.RSA; + RSAParameters p = rsa.ExportParameters(false); + TlsStream data = new TlsStream(); + + data.Write(this.Session.Context.RandomCS); + data.Write((short)p.Modulus.Length); + data.Write(p.Modulus); + data.Write((short)p.Exponent.Length); + data.Write(p.Exponent); + + hash.ComputeHash(data.ToArray(), 0, (int)data.Length); + + data.Reset(); + + // Write the signature + Write(hash.CreateSignature(rsa)); + } + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs index 722f7c3ff27..6e65064b739 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs @@ -1,86 +1,86 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Security.Cryptography; - -using Mono.Security.Cryptography; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsClientFinished : TlsHandshakeMessage - { - #region CONSTRUCTORS - - public TlsClientFinished(TlsSession session) - : base(session, TlsHandshakeType.Finished, TlsContentType.Handshake) - { - } - - #endregion - - #region METHODS - - public override void UpdateSession() - { - base.UpdateSession(); - this.Reset(); - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - // Compute handshake messages hashes - HashAlgorithm hash = new TlsSslHandshakeHash(this.Session.Context.MasterSecret); - - TlsStream data = new TlsStream(); - data.Write(this.Session.Context.HandshakeMessages.ToArray()); - data.Write((int)0x434C4E54); - - hash.TransformFinalBlock(data.ToArray(), 0, (int)data.Length); - - this.Write(hash.Hash); - - data.Reset(); - } - - protected override void ProcessAsTls1() - { - // Compute handshake messages hash - HashAlgorithm hash = new MD5SHA1CryptoServiceProvider(); - hash.ComputeHash( - Session.Context.HandshakeMessages.ToArray(), - 0, - (int)Session.Context.HandshakeMessages.Length); - - // Write message - Write(Session.Context.Cipher.PRF(Session.Context.MasterSecret, "client finished", hash.Hash, 12)); - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Security.Cryptography; + +using Mono.Security.Cryptography; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsClientFinished : TlsHandshakeMessage + { + #region CONSTRUCTORS + + public TlsClientFinished(TlsSession session) + : base(session, TlsHandshakeType.Finished, TlsContentType.Handshake) + { + } + + #endregion + + #region METHODS + + public override void UpdateSession() + { + base.UpdateSession(); + this.Reset(); + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + // Compute handshake messages hashes + HashAlgorithm hash = new TlsSslHandshakeHash(this.Session.Context.MasterSecret); + + TlsStream data = new TlsStream(); + data.Write(this.Session.Context.HandshakeMessages.ToArray()); + data.Write((int)0x434C4E54); + + hash.TransformFinalBlock(data.ToArray(), 0, (int)data.Length); + + this.Write(hash.Hash); + + data.Reset(); + } + + protected override void ProcessAsTls1() + { + // Compute handshake messages hash + HashAlgorithm hash = new MD5SHA1CryptoServiceProvider(); + hash.ComputeHash( + Session.Context.HandshakeMessages.ToArray(), + 0, + (int)Session.Context.HandshakeMessages.Length); + + // Write message + Write(Session.Context.Cipher.PRF(Session.Context.MasterSecret, "client finished", hash.Hash, 12)); + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientHello.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientHello.cs index be8387f90e2..3148d9cfd2a 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientHello.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientHello.cs @@ -1,114 +1,114 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Security.Cryptography; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsClientHello : TlsHandshakeMessage - { - #region FIELDS - - private byte[] random; - - #endregion - - #region CONSTRUCTORS - - public TlsClientHello(TlsSession session) - : base(session, TlsHandshakeType.ClientHello, TlsContentType.Handshake) - { - } - - #endregion - - #region METHODS - - public override void UpdateSession() - { - base.UpdateSession(); - - Session.Context.ClientRandom = random; - - random = null; - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - this.ProcessAsTls1(); - } - - protected override void ProcessAsTls1() - { - // Client Version - this.Write((short)this.Session.Context.Protocol); - - // Random bytes - Unix time + Radom bytes [28] - TlsStream clientRandom = new TlsStream(); - clientRandom.Write(this.Session.Context.GetUnixTime()); - clientRandom.Write(this.Session.Context.GetSecureRandomBytes(28)); - this.random = clientRandom.ToArray(); - clientRandom.Reset(); - - this.Write(this.random); - - // Session id - // Send the session ID empty - if (this.Session.SessionId != null) - { - this.Write((byte)this.Session.SessionId.Length); - if (this.Session.SessionId.Length > 0) - { - this.Write(this.Session.SessionId); - } - } - else - { - this.Write((byte)0); - } - - // Write length of Cipher suites - this.Write((short)(this.Session.Context.SupportedCiphers.Count*2)); - - // Write Supported Cipher suites - for (int i = 0; i < this.Session.Context.SupportedCiphers.Count; i++) - { - this.Write((short)this.Session.Context.SupportedCiphers[i].Code); - } - - // Compression methods length - this.Write((byte)1); - - // Compression methods ( 0 = none ) - this.Write((byte)this.Session.Context.CompressionMethod); - } - - #endregion - } +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Security.Cryptography; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsClientHello : TlsHandshakeMessage + { + #region FIELDS + + private byte[] random; + + #endregion + + #region CONSTRUCTORS + + public TlsClientHello(TlsSession session) + : base(session, TlsHandshakeType.ClientHello, TlsContentType.Handshake) + { + } + + #endregion + + #region METHODS + + public override void UpdateSession() + { + base.UpdateSession(); + + Session.Context.ClientRandom = random; + + random = null; + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + this.ProcessAsTls1(); + } + + protected override void ProcessAsTls1() + { + // Client Version + this.Write((short)this.Session.Context.Protocol); + + // Random bytes - Unix time + Radom bytes [28] + TlsStream clientRandom = new TlsStream(); + clientRandom.Write(this.Session.Context.GetUnixTime()); + clientRandom.Write(this.Session.Context.GetSecureRandomBytes(28)); + this.random = clientRandom.ToArray(); + clientRandom.Reset(); + + this.Write(this.random); + + // Session id + // Send the session ID empty + if (this.Session.SessionId != null) + { + this.Write((byte)this.Session.SessionId.Length); + if (this.Session.SessionId.Length > 0) + { + this.Write(this.Session.SessionId); + } + } + else + { + this.Write((byte)0); + } + + // Write length of Cipher suites + this.Write((short)(this.Session.Context.SupportedCiphers.Count*2)); + + // Write Supported Cipher suites + for (int i = 0; i < this.Session.Context.SupportedCiphers.Count; i++) + { + this.Write((short)this.Session.Context.SupportedCiphers[i].Code); + } + + // Compression methods length + this.Write((byte)1); + + // Compression methods ( 0 = none ) + this.Write((byte)this.Session.Context.CompressionMethod); + } + + #endregion + } } \ No newline at end of file diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientKeyExchange.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientKeyExchange.cs index 72bdc418580..1357e733d9d 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientKeyExchange.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientKeyExchange.cs @@ -1,99 +1,99 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.IO; -using System.Security.Cryptography; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsClientKeyExchange : TlsHandshakeMessage - { - #region CONSTRUCTORS - - public TlsClientKeyExchange (TlsSession session) : - base(session, - TlsHandshakeType.ClientKeyExchange, - TlsContentType.Handshake) - { - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - // Compute pre master secret - byte[] preMasterSecret = this.Session.Context.Cipher.CreatePremasterSecret(); - - // Create a new RSA key - RSA rsa = this.Session.Context.Cipher.CreateRSA(); - - // Encrypt premaster_sercret - RSAPKCS1KeyExchangeFormatter formatter = new RSAPKCS1KeyExchangeFormatter(rsa); - - // Write the preMasterSecret encrypted - byte[] buffer = formatter.CreateKeyExchange(preMasterSecret); - this.Write(buffer); - - // Create master secret - this.Session.Context.Cipher.ComputeMasterSecret(preMasterSecret); - - // Create keys - this.Session.Context.Cipher.ComputeKeys(); - - // Clear resources - rsa.Clear(); - } - - protected override void ProcessAsTls1() - { - // Compute pre master secret - byte[] preMasterSecret = this.Session.Context.Cipher.CreatePremasterSecret(); - - // Create a new RSA key - RSA rsa = this.Session.Context.Cipher.CreateRSA(); - - // Encrypt premaster_sercret - RSAPKCS1KeyExchangeFormatter formatter = new RSAPKCS1KeyExchangeFormatter(rsa); - - // Write the preMasterSecret encrypted - byte[] buffer = formatter.CreateKeyExchange(preMasterSecret); - this.Write((short)buffer.Length); - this.Write(buffer); - - // Create master secret - this.Session.Context.Cipher.ComputeMasterSecret(preMasterSecret); - - // Create keys - this.Session.Context.Cipher.ComputeKeys(); - - // Clear resources - rsa.Clear(); - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.IO; +using System.Security.Cryptography; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsClientKeyExchange : TlsHandshakeMessage + { + #region CONSTRUCTORS + + public TlsClientKeyExchange (TlsSession session) : + base(session, + TlsHandshakeType.ClientKeyExchange, + TlsContentType.Handshake) + { + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + // Compute pre master secret + byte[] preMasterSecret = this.Session.Context.Cipher.CreatePremasterSecret(); + + // Create a new RSA key + RSA rsa = this.Session.Context.Cipher.CreateRSA(); + + // Encrypt premaster_sercret + RSAPKCS1KeyExchangeFormatter formatter = new RSAPKCS1KeyExchangeFormatter(rsa); + + // Write the preMasterSecret encrypted + byte[] buffer = formatter.CreateKeyExchange(preMasterSecret); + this.Write(buffer); + + // Create master secret + this.Session.Context.Cipher.ComputeMasterSecret(preMasterSecret); + + // Create keys + this.Session.Context.Cipher.ComputeKeys(); + + // Clear resources + rsa.Clear(); + } + + protected override void ProcessAsTls1() + { + // Compute pre master secret + byte[] preMasterSecret = this.Session.Context.Cipher.CreatePremasterSecret(); + + // Create a new RSA key + RSA rsa = this.Session.Context.Cipher.CreateRSA(); + + // Encrypt premaster_sercret + RSAPKCS1KeyExchangeFormatter formatter = new RSAPKCS1KeyExchangeFormatter(rsa); + + // Write the preMasterSecret encrypted + byte[] buffer = formatter.CreateKeyExchange(preMasterSecret); + this.Write((short)buffer.Length); + this.Write(buffer); + + // Create master secret + this.Session.Context.Cipher.ComputeMasterSecret(preMasterSecret); + + // Create keys + this.Session.Context.Cipher.ComputeKeys(); + + // Clear resources + rsa.Clear(); + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs index 7ca3baca868..15618102c4f 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs @@ -1,132 +1,132 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Security.Cryptography; - -using Mono.Security.Protocol.Tls.Alerts; -using Mono.Security.X509; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsServerCertificate : TlsHandshakeMessage - { - #region FIELDS - - private X509CertificateCollection certificates; - - #endregion - - #region PROPERTIES - - public X509CertificateCollection Certificates - { - get { return certificates; } - } - - #endregion - - #region CONSTRUCTORS - - public TlsServerCertificate(TlsSession session, byte[] buffer) - : base(session, TlsHandshakeType.Certificate, buffer) - { - } - - #endregion - - #region METHODS - - public override void UpdateSession() - { - base.UpdateSession(); - this.Session.Context.ServerSettings.ServerCertificates = certificates; - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - this.ProcessAsTls1(); - } - - protected override void ProcessAsTls1() - { - this.certificates = new X509CertificateCollection(); - - int readed = 0; - int length = this.ReadInt24(); - - while (readed < length) - { - // Read certificate length - int certLength = ReadInt24(); - - // Increment readed - readed += 3; - - if (certLength > 0) - { - // Read certificate - X509Certificate certificate = new X509Certificate(this.ReadBytes(certLength)); - certificates.Add(certificate); - - readed += certLength; - - this.validateCertificate(certificate); - } - } - } - - #endregion - - #region PRIVATE_METHODS - - private void validateCertificate(X509Certificate certificate) - { - #warning "Check validity of certificates" - - // 1 step : Validate dates - if (!certificate.IsCurrent) - { - throw Session.CreateException("Certificate received from the server expired."); - } - - // 2 step: Validate CA - - - // 3 step: Validate digital sign - if (!certificate.VerifySignature(certificate.RSA)) - { - throw Session.CreateException("Certificate received from the server has invalid signature."); - } - - // 4 step: Validate domain name - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Security.Cryptography; + +using Mono.Security.Protocol.Tls.Alerts; +using Mono.Security.X509; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsServerCertificate : TlsHandshakeMessage + { + #region FIELDS + + private X509CertificateCollection certificates; + + #endregion + + #region PROPERTIES + + public X509CertificateCollection Certificates + { + get { return certificates; } + } + + #endregion + + #region CONSTRUCTORS + + public TlsServerCertificate(TlsSession session, byte[] buffer) + : base(session, TlsHandshakeType.Certificate, buffer) + { + } + + #endregion + + #region METHODS + + public override void UpdateSession() + { + base.UpdateSession(); + this.Session.Context.ServerSettings.ServerCertificates = certificates; + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + this.ProcessAsTls1(); + } + + protected override void ProcessAsTls1() + { + this.certificates = new X509CertificateCollection(); + + int readed = 0; + int length = this.ReadInt24(); + + while (readed < length) + { + // Read certificate length + int certLength = ReadInt24(); + + // Increment readed + readed += 3; + + if (certLength > 0) + { + // Read certificate + X509Certificate certificate = new X509Certificate(this.ReadBytes(certLength)); + certificates.Add(certificate); + + readed += certLength; + + this.validateCertificate(certificate); + } + } + } + + #endregion + + #region PRIVATE_METHODS + + private void validateCertificate(X509Certificate certificate) + { + #warning "Check validity of certificates" + + // 1 step : Validate dates + if (!certificate.IsCurrent) + { + throw Session.CreateException("Certificate received from the server expired."); + } + + // 2 step: Validate CA + + + // 3 step: Validate digital sign + if (!certificate.VerifySignature(certificate.RSA)) + { + throw Session.CreateException("Certificate received from the server has invalid signature."); + } + + // 4 step: Validate domain name + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificateRequest.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificateRequest.cs index dd568dd4d73..7250f0a86c4 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificateRequest.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificateRequest.cs @@ -1,112 +1,112 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Text; -using Mono.Security; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsServerCertificateRequest : TlsHandshakeMessage - { - #region FIELDS - - private TlsClientCertificateType[] certificateTypes; - private string[] distinguisedNames; - - #endregion - - #region CONSTRUCTORS - - public TlsServerCertificateRequest(TlsSession session, byte[] buffer) - : base(session, TlsHandshakeType.ServerHello, buffer) - { - } - - #endregion - - #region METHODS - - public override void UpdateSession() - { - base.UpdateSession(); - - this.Session.Context.ServerSettings.CertificateTypes = this.certificateTypes; - this.Session.Context.ServerSettings.DistinguisedNames = this.distinguisedNames; - this.Session.Context.ServerSettings.CertificateRequest = true; - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - throw new NotSupportedException(); - } - - protected override void ProcessAsTls1() - { - // Read requested certificate types - int typesCount = this.ReadByte(); - - this.certificateTypes = new TlsClientCertificateType[typesCount]; - - for (int i = 0; i < typesCount; i++) - { - this.certificateTypes[i] = (TlsClientCertificateType)this.ReadByte(); - } - - /* - * Read requested certificate authorities (Distinguised Names) - * - * Name ::= SEQUENCE OF RelativeDistinguishedName - * - * RelativeDistinguishedName ::= SET OF AttributeValueAssertion - * - * AttributeValueAssertion ::= SEQUENCE { - * attributeType OBJECT IDENTIFIER - * attributeValue ANY } - */ - if (this.ReadInt16() != 0) - { - ASN1 rdn = new ASN1(this.ReadBytes(this.ReadInt16())); - - distinguisedNames = new string[rdn.Count]; - - #warning "needs testing" - for (int i = 0; i < rdn.Count; i++) - { - // element[0] = attributeType - // element[1] = attributeValue - ASN1 element = new ASN1(rdn[i].Value); - - distinguisedNames[i] = Encoding.UTF8.GetString(element[1].Value); - } - } - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Text; +using Mono.Security; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsServerCertificateRequest : TlsHandshakeMessage + { + #region FIELDS + + private TlsClientCertificateType[] certificateTypes; + private string[] distinguisedNames; + + #endregion + + #region CONSTRUCTORS + + public TlsServerCertificateRequest(TlsSession session, byte[] buffer) + : base(session, TlsHandshakeType.ServerHello, buffer) + { + } + + #endregion + + #region METHODS + + public override void UpdateSession() + { + base.UpdateSession(); + + this.Session.Context.ServerSettings.CertificateTypes = this.certificateTypes; + this.Session.Context.ServerSettings.DistinguisedNames = this.distinguisedNames; + this.Session.Context.ServerSettings.CertificateRequest = true; + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + throw new NotSupportedException(); + } + + protected override void ProcessAsTls1() + { + // Read requested certificate types + int typesCount = this.ReadByte(); + + this.certificateTypes = new TlsClientCertificateType[typesCount]; + + for (int i = 0; i < typesCount; i++) + { + this.certificateTypes[i] = (TlsClientCertificateType)this.ReadByte(); + } + + /* + * Read requested certificate authorities (Distinguised Names) + * + * Name ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= SET OF AttributeValueAssertion + * + * AttributeValueAssertion ::= SEQUENCE { + * attributeType OBJECT IDENTIFIER + * attributeValue ANY } + */ + if (this.ReadInt16() != 0) + { + ASN1 rdn = new ASN1(this.ReadBytes(this.ReadInt16())); + + distinguisedNames = new string[rdn.Count]; + + #warning "needs testing" + for (int i = 0; i < rdn.Count; i++) + { + // element[0] = attributeType + // element[1] = attributeValue + ASN1 element = new ASN1(rdn[i].Value); + + distinguisedNames[i] = Encoding.UTF8.GetString(element[1].Value); + } + } + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs index 8539f646fbf..937d4df0661 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs @@ -1,118 +1,118 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Security.Cryptography; - -using Mono.Security.Cryptography; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsServerFinished : TlsHandshakeMessage - { - #region CONSTRUCTORS - - public TlsServerFinished(TlsSession session, byte[] buffer) - : base(session, TlsHandshakeType.ServerHello, buffer) - { - } - - #endregion - - #region METHODS - - public override void UpdateSession() - { - base.UpdateSession(); - - // Reset Hahdshake messages information - this.Session.Context.HandshakeMessages.Reset(); - - // Hahdshake is finished - this.Session.Context.HandshakeFinished = true; - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - // Compute handshake messages hashes - HashAlgorithm hash = new TlsSslHandshakeHash(this.Session.Context.MasterSecret); - - TlsStream data = new TlsStream(); - data.Write(this.Session.Context.HandshakeMessages.ToArray()); - data.Write((int)0x53525652); - - hash.TransformFinalBlock(data.ToArray(), 0, (int)data.Length); - - data.Reset(); - - byte[] serverHash = this.ReadBytes((int)Length); - byte[] clientHash = hash.Hash; - - // Check server prf against client prf - if (clientHash.Length != serverHash.Length) - { - throw new TlsException("Invalid ServerFinished message received."); - } - for (int i = 0; i < serverHash.Length; i++) - { - if (clientHash[i] != serverHash[i]) - { - throw new TlsException("Invalid ServerFinished message received."); - } - } - } - - protected override void ProcessAsTls1() - { - byte[] serverPRF = this.ReadBytes((int)Length); - HashAlgorithm hash = new MD5SHA1CryptoServiceProvider(); - - hash.ComputeHash( - Session.Context.HandshakeMessages.ToArray(), - 0, - (int)Session.Context.HandshakeMessages.Length); - - byte[] clientPRF = this.Session.Context.Cipher.PRF(this.Session.Context.MasterSecret, "server finished", hash.Hash, 12); - - // Check server prf against client prf - if (clientPRF.Length != serverPRF.Length) - { - throw new TlsException("Invalid ServerFinished message received."); - } - for (int i = 0; i < serverPRF.Length; i++) - { - if (clientPRF[i] != serverPRF[i]) - { - throw new TlsException("Invalid ServerFinished message received."); - } - } - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Security.Cryptography; + +using Mono.Security.Cryptography; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsServerFinished : TlsHandshakeMessage + { + #region CONSTRUCTORS + + public TlsServerFinished(TlsSession session, byte[] buffer) + : base(session, TlsHandshakeType.ServerHello, buffer) + { + } + + #endregion + + #region METHODS + + public override void UpdateSession() + { + base.UpdateSession(); + + // Reset Hahdshake messages information + this.Session.Context.HandshakeMessages.Reset(); + + // Hahdshake is finished + this.Session.Context.HandshakeFinished = true; + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + // Compute handshake messages hashes + HashAlgorithm hash = new TlsSslHandshakeHash(this.Session.Context.MasterSecret); + + TlsStream data = new TlsStream(); + data.Write(this.Session.Context.HandshakeMessages.ToArray()); + data.Write((int)0x53525652); + + hash.TransformFinalBlock(data.ToArray(), 0, (int)data.Length); + + data.Reset(); + + byte[] serverHash = this.ReadBytes((int)Length); + byte[] clientHash = hash.Hash; + + // Check server prf against client prf + if (clientHash.Length != serverHash.Length) + { + throw new TlsException("Invalid ServerFinished message received."); + } + for (int i = 0; i < serverHash.Length; i++) + { + if (clientHash[i] != serverHash[i]) + { + throw new TlsException("Invalid ServerFinished message received."); + } + } + } + + protected override void ProcessAsTls1() + { + byte[] serverPRF = this.ReadBytes((int)Length); + HashAlgorithm hash = new MD5SHA1CryptoServiceProvider(); + + hash.ComputeHash( + Session.Context.HandshakeMessages.ToArray(), + 0, + (int)Session.Context.HandshakeMessages.Length); + + byte[] clientPRF = this.Session.Context.Cipher.PRF(this.Session.Context.MasterSecret, "server finished", hash.Hash, 12); + + // Check server prf against client prf + if (clientPRF.Length != serverPRF.Length) + { + throw new TlsException("Invalid ServerFinished message received."); + } + for (int i = 0; i < serverPRF.Length; i++) + { + if (clientPRF[i] != serverPRF[i]) + { + throw new TlsException("Invalid ServerFinished message received."); + } + } + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHello.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHello.cs index 97250707bf2..7a8a8bb969e 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHello.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHello.cs @@ -1,140 +1,140 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsServerHello : TlsHandshakeMessage - { - #region FIELDS - - private TlsProtocol protocol; - private TlsCompressionMethod compressionMethod; - private byte[] random; - private byte[] sessionId; - private CipherSuite cipherSuite; - - #endregion - - #region CONSTRUCTORS - - public TlsServerHello(TlsSession session, byte[] buffer) - : base(session, TlsHandshakeType.ServerHello, buffer) - { - } - - #endregion - - #region METHODS - - public override void UpdateSession() - { - base.UpdateSession(); - - this.Session.SetSessionId(this.sessionId); - this.Session.Context.ServerRandom = this.random; - this.Session.Context.Cipher = this.cipherSuite; - this.Session.Context.CompressionMethod = this.compressionMethod; - this.Session.Context.Cipher.Context = this.Session.Context; - - // Compute ClientRandom + ServerRandom - TlsStream random = new TlsStream(); - random.Write(this.Session.Context.ClientRandom); - random.Write(this.Session.Context.ServerRandom); - this.Session.Context.RandomCS = random.ToArray(); - - // Server Random + Client Random - random.Reset(); - random.Write(this.Session.Context.ServerRandom); - random.Write(this.Session.Context.ClientRandom); - - this.Session.Context.RandomSC = random.ToArray(); - random.Reset(); - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - #warning "Check that the protocol sent by the server is supported" - // Read protocol version - this.protocol = (TlsProtocol)this.ReadInt16(); - - // Read random - Unix time + Random bytes - this.random = this.ReadBytes(32); - - // Read Session id - int length = (int)ReadByte(); - if (length > 0) - { - this.sessionId = this.ReadBytes(length); - } - - // Read cipher suite - short cipherCode = this.ReadInt16(); - if (this.Session.Context.SupportedCiphers.IndexOf(cipherCode) == -1) - { - // The server has sent an invalid ciphersuite - throw new TlsException("Invalid cipher suite received from server"); - } - this.cipherSuite = this.Session.Context.SupportedCiphers[cipherCode]; - - // Read compression methods ( always 0 ) - this.compressionMethod = (TlsCompressionMethod)this.ReadByte(); - } - - protected override void ProcessAsTls1() - { - // Read protocol version - this.protocol = (TlsProtocol)this.ReadInt16(); - - // Read random - Unix time + Random bytes - this.random = this.ReadBytes(32); - - // Read Session id - int length = (int)ReadByte(); - if (length > 0) - { - this.sessionId = this.ReadBytes(length); - } - - // Read cipher suite - short cipherCode = this.ReadInt16(); - if (this.Session.Context.SupportedCiphers.IndexOf(cipherCode) == -1) - { - // The server has sent an invalid ciphersuite - throw new TlsException("Invalid cipher suite received from server"); - } - this.cipherSuite = this.Session.Context.SupportedCiphers[cipherCode]; - - // Read compression methods ( always 0 ) - this.compressionMethod = (TlsCompressionMethod)this.ReadByte(); - } - - #endregion - } +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsServerHello : TlsHandshakeMessage + { + #region FIELDS + + private TlsProtocol protocol; + private TlsCompressionMethod compressionMethod; + private byte[] random; + private byte[] sessionId; + private CipherSuite cipherSuite; + + #endregion + + #region CONSTRUCTORS + + public TlsServerHello(TlsSession session, byte[] buffer) + : base(session, TlsHandshakeType.ServerHello, buffer) + { + } + + #endregion + + #region METHODS + + public override void UpdateSession() + { + base.UpdateSession(); + + this.Session.SetSessionId(this.sessionId); + this.Session.Context.ServerRandom = this.random; + this.Session.Context.Cipher = this.cipherSuite; + this.Session.Context.CompressionMethod = this.compressionMethod; + this.Session.Context.Cipher.Context = this.Session.Context; + + // Compute ClientRandom + ServerRandom + TlsStream random = new TlsStream(); + random.Write(this.Session.Context.ClientRandom); + random.Write(this.Session.Context.ServerRandom); + this.Session.Context.RandomCS = random.ToArray(); + + // Server Random + Client Random + random.Reset(); + random.Write(this.Session.Context.ServerRandom); + random.Write(this.Session.Context.ClientRandom); + + this.Session.Context.RandomSC = random.ToArray(); + random.Reset(); + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + #warning "Check that the protocol sent by the server is supported" + // Read protocol version + this.protocol = (TlsProtocol)this.ReadInt16(); + + // Read random - Unix time + Random bytes + this.random = this.ReadBytes(32); + + // Read Session id + int length = (int)ReadByte(); + if (length > 0) + { + this.sessionId = this.ReadBytes(length); + } + + // Read cipher suite + short cipherCode = this.ReadInt16(); + if (this.Session.Context.SupportedCiphers.IndexOf(cipherCode) == -1) + { + // The server has sent an invalid ciphersuite + throw new TlsException("Invalid cipher suite received from server"); + } + this.cipherSuite = this.Session.Context.SupportedCiphers[cipherCode]; + + // Read compression methods ( always 0 ) + this.compressionMethod = (TlsCompressionMethod)this.ReadByte(); + } + + protected override void ProcessAsTls1() + { + // Read protocol version + this.protocol = (TlsProtocol)this.ReadInt16(); + + // Read random - Unix time + Random bytes + this.random = this.ReadBytes(32); + + // Read Session id + int length = (int)ReadByte(); + if (length > 0) + { + this.sessionId = this.ReadBytes(length); + } + + // Read cipher suite + short cipherCode = this.ReadInt16(); + if (this.Session.Context.SupportedCiphers.IndexOf(cipherCode) == -1) + { + // The server has sent an invalid ciphersuite + throw new TlsException("Invalid cipher suite received from server"); + } + this.cipherSuite = this.Session.Context.SupportedCiphers[cipherCode]; + + // Read compression methods ( always 0 ) + this.compressionMethod = (TlsCompressionMethod)this.ReadByte(); + } + + #endregion + } } \ No newline at end of file diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHelloDone.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHelloDone.cs index cfb8fd4cc16..70b3bccf0ad 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHelloDone.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHelloDone.cs @@ -1,63 +1,63 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsServerHelloDone : TlsHandshakeMessage - { - #region CONSTRUCTORS - - public TlsServerHelloDone(TlsSession session, byte[] buffer) - : base(session, TlsHandshakeType.ServerHello, buffer) - { - } - - #endregion - - #region METHODS - - public override void UpdateSession() - { - base.UpdateSession(); - - this.Session.Context.HelloDone = true; - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - } - - protected override void ProcessAsTls1() - { - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsServerHelloDone : TlsHandshakeMessage + { + #region CONSTRUCTORS + + public TlsServerHelloDone(TlsSession session, byte[] buffer) + : base(session, TlsHandshakeType.ServerHello, buffer) + { + } + + #endregion + + #region METHODS + + public override void UpdateSession() + { + base.UpdateSession(); + + this.Session.Context.HelloDone = true; + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + } + + protected override void ProcessAsTls1() + { + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs index 4c3b534b851..dbd1a346ee7 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs @@ -1,119 +1,119 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Security.Cryptography; - -using Mono.Security.Cryptography; -using Mono.Security.X509; - -namespace Mono.Security.Protocol.Tls.Handshake.Client -{ - internal class TlsServerKeyExchange : TlsHandshakeMessage - { - #region FIELDS - - private RSAParameters rsaParams; - private byte[] signedParams; - - #endregion - - #region CONSTRUCTORS - - public TlsServerKeyExchange(TlsSession session, byte[] buffer) - : base(session, TlsHandshakeType.ServerKeyExchange, buffer) - { - this.verifySignature(); - } - - #endregion - - #region METHODS - - public override void UpdateSession() - { - base.UpdateSession(); - - this.Session.Context.ServerSettings.ServerKeyExchange = true; - this.Session.Context.ServerSettings.RsaParameters = this.rsaParams; - this.Session.Context.ServerSettings.SignedParams = this.signedParams; - } - - #endregion - - #region PROTECTED_METHODS - - protected override void ProcessAsSsl3() - { - this.ProcessAsTls1(); - } - - protected override void ProcessAsTls1() - { - this.rsaParams = new RSAParameters(); - - // Read modulus - rsaParams.Modulus = this.ReadBytes(this.ReadInt16()); - - // Read exponent - rsaParams.Exponent = this.ReadBytes(this.ReadInt16()); - - // Read signed params - signedParams = this.ReadBytes(this.ReadInt16()); - } - - #endregion - - #region PRIVATE_METHODS - - private void verifySignature() - { - MD5SHA1CryptoServiceProvider hash = new MD5SHA1CryptoServiceProvider(); - - // Create server params array - TlsStream stream = new TlsStream(); - - stream.Write(this.Session.Context.RandomCS); - stream.Write(rsaParams.Modulus.Length); - stream.Write(rsaParams.Modulus); - stream.Write(rsaParams.Exponent.Length); - stream.Write(rsaParams.Exponent); - - hash.ComputeHash(stream.ToArray()); - - stream.Reset(); - - // Verify Signature - X509Certificate certificate = this.Session.Context.ServerSettings.ServerCertificates[0]; - - RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(rsaParams.Modulus.Length << 3); - rsa.ImportParameters(rsaParams); - - byte[] sign = hash.CreateSignature(rsa); - hash.VerifySignature(rsa, this.signedParams); - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Security.Cryptography; + +using Mono.Security.Cryptography; +using Mono.Security.X509; + +namespace Mono.Security.Protocol.Tls.Handshake.Client +{ + internal class TlsServerKeyExchange : TlsHandshakeMessage + { + #region FIELDS + + private RSAParameters rsaParams; + private byte[] signedParams; + + #endregion + + #region CONSTRUCTORS + + public TlsServerKeyExchange(TlsSession session, byte[] buffer) + : base(session, TlsHandshakeType.ServerKeyExchange, buffer) + { + this.verifySignature(); + } + + #endregion + + #region METHODS + + public override void UpdateSession() + { + base.UpdateSession(); + + this.Session.Context.ServerSettings.ServerKeyExchange = true; + this.Session.Context.ServerSettings.RsaParameters = this.rsaParams; + this.Session.Context.ServerSettings.SignedParams = this.signedParams; + } + + #endregion + + #region PROTECTED_METHODS + + protected override void ProcessAsSsl3() + { + this.ProcessAsTls1(); + } + + protected override void ProcessAsTls1() + { + this.rsaParams = new RSAParameters(); + + // Read modulus + rsaParams.Modulus = this.ReadBytes(this.ReadInt16()); + + // Read exponent + rsaParams.Exponent = this.ReadBytes(this.ReadInt16()); + + // Read signed params + signedParams = this.ReadBytes(this.ReadInt16()); + } + + #endregion + + #region PRIVATE_METHODS + + private void verifySignature() + { + MD5SHA1CryptoServiceProvider hash = new MD5SHA1CryptoServiceProvider(); + + // Create server params array + TlsStream stream = new TlsStream(); + + stream.Write(this.Session.Context.RandomCS); + stream.Write(rsaParams.Modulus.Length); + stream.Write(rsaParams.Modulus); + stream.Write(rsaParams.Exponent.Length); + stream.Write(rsaParams.Exponent); + + hash.ComputeHash(stream.ToArray()); + + stream.Reset(); + + // Verify Signature + X509Certificate certificate = this.Session.Context.ServerSettings.ServerCertificates[0]; + + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(rsaParams.Modulus.Length << 3); + rsa.ImportParameters(rsaParams); + + byte[] sign = hash.CreateSignature(rsa); + hash.VerifySignature(rsa, this.signedParams); + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsClientCertificateType.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsClientCertificateType.cs index 8a2848c2702..94900630ab7 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsClientCertificateType.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsClientCertificateType.cs @@ -1,37 +1,37 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; - -namespace Mono.Security.Protocol.Tls.Handshake -{ - internal enum TlsClientCertificateType - { - RSA = 1, - DSS = 2, - RSAFixed = 3, - DSSFixed = 4, - Unknown = 255 - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; + +namespace Mono.Security.Protocol.Tls.Handshake +{ + internal enum TlsClientCertificateType + { + RSA = 1, + DSS = 2, + RSAFixed = 3, + DSSFixed = 4, + Unknown = 255 + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsHandshakeMessage.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsHandshakeMessage.cs index 7f65ec9fedf..5a5215779cf 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsHandshakeMessage.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsHandshakeMessage.cs @@ -1,138 +1,138 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -// using Mono.Security.Protocol.Tls; - -namespace Mono.Security.Protocol.Tls.Handshake -{ - internal abstract class TlsHandshakeMessage : TlsStream - { - #region FIELDS - - private TlsSession session; - private TlsHandshakeType handshakeType; - private TlsContentType contentType; - - #endregion - - #region PROPERTIES - - public TlsSession Session - { - get { return session; } - } - - public TlsHandshakeType HandshakeType - { - get { return handshakeType; } - } - - public TlsContentType ContentType - { - get { return contentType; } - } - - #endregion - - #region CONSTRUCTORS - - public TlsHandshakeMessage(TlsSession session, - TlsHandshakeType handshakeType, - TlsContentType contentType) : base() - { - this.session = session; - this.handshakeType = handshakeType; - this.contentType = contentType; - - // Process message - this.process(); - } - - public TlsHandshakeMessage(TlsSession session, - TlsHandshakeType handshakeType, byte[] data) : base(data) - { - this.session = session; - this.handshakeType = handshakeType; - - // Process message - this.process(); - } - - #endregion - - #region ABSTRACT_METHODS - - protected abstract void ProcessAsTls1(); - - protected abstract void ProcessAsSsl3(); - - #endregion - - #region METHODS - - private void process() - { - switch (this.session.Context.Protocol) - { - case TlsProtocol.Tls1: - this.ProcessAsTls1(); - break; - - case TlsProtocol.Ssl3: - this.ProcessAsSsl3(); - break; - } - } - - public virtual void UpdateSession() - { - if (CanWrite) - { - this.session.Context.HandshakeMessages.Write(this.EncodeMessage()); - this.Reset(); - } - } - - public virtual byte[] EncodeMessage() - { - byte[] result = null; - - if (CanWrite) - { - TlsStream c = new TlsStream(); - - c.Write((byte)HandshakeType); - c.WriteInt24((int)this.Length); - c.Write(this.ToArray()); - - result = c.ToArray(); - } - - return result; - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +// using Mono.Security.Protocol.Tls; + +namespace Mono.Security.Protocol.Tls.Handshake +{ + internal abstract class TlsHandshakeMessage : TlsStream + { + #region FIELDS + + private TlsSession session; + private TlsHandshakeType handshakeType; + private TlsContentType contentType; + + #endregion + + #region PROPERTIES + + public TlsSession Session + { + get { return session; } + } + + public TlsHandshakeType HandshakeType + { + get { return handshakeType; } + } + + public TlsContentType ContentType + { + get { return contentType; } + } + + #endregion + + #region CONSTRUCTORS + + public TlsHandshakeMessage(TlsSession session, + TlsHandshakeType handshakeType, + TlsContentType contentType) : base() + { + this.session = session; + this.handshakeType = handshakeType; + this.contentType = contentType; + + // Process message + this.process(); + } + + public TlsHandshakeMessage(TlsSession session, + TlsHandshakeType handshakeType, byte[] data) : base(data) + { + this.session = session; + this.handshakeType = handshakeType; + + // Process message + this.process(); + } + + #endregion + + #region ABSTRACT_METHODS + + protected abstract void ProcessAsTls1(); + + protected abstract void ProcessAsSsl3(); + + #endregion + + #region METHODS + + private void process() + { + switch (this.session.Context.Protocol) + { + case TlsProtocol.Tls1: + this.ProcessAsTls1(); + break; + + case TlsProtocol.Ssl3: + this.ProcessAsSsl3(); + break; + } + } + + public virtual void UpdateSession() + { + if (CanWrite) + { + this.session.Context.HandshakeMessages.Write(this.EncodeMessage()); + this.Reset(); + } + } + + public virtual byte[] EncodeMessage() + { + byte[] result = null; + + if (CanWrite) + { + TlsStream c = new TlsStream(); + + c.Write((byte)HandshakeType); + c.WriteInt24((int)this.Length); + c.Write(this.ToArray()); + + result = c.ToArray(); + } + + return result; + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsHandshakeType.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsHandshakeType.cs index b885429e85c..52322ad6890 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsHandshakeType.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsHandshakeType.cs @@ -1,42 +1,42 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; - -namespace Mono.Security.Protocol.Tls.Handshake -{ - internal enum TlsHandshakeType : byte - { - HelloRequest = 0, - ClientHello = 1, - ServerHello = 2, - Certificate = 11, - ServerKeyExchange = 12, - CertificateRequest = 13, - ServerHelloDone = 14, - CertificateVerify = 15, - ClientKeyExchange = 16, - Finished = 20, - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; + +namespace Mono.Security.Protocol.Tls.Handshake +{ + internal enum TlsHandshakeType : byte + { + HelloRequest = 0, + ClientHello = 1, + ServerHello = 2, + Certificate = 11, + ServerKeyExchange = 12, + CertificateRequest = 13, + ServerHelloDone = 14, + CertificateVerify = 15, + ClientKeyExchange = 16, + Finished = 20, + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/CipherSuite.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/CipherSuite.cs index f99e0e5c7bc..b3926ee28db 100755 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/CipherSuite.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/CipherSuite.cs @@ -1,511 +1,511 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.IO; -using System.Text; -using System.Security.Cryptography; - -using Mono.Security; -using Mono.Security.Cryptography; -using Mono.Security.X509; - -namespace Mono.Security.Protocol.Tls -{ - internal abstract class CipherSuite - { - #region FIELDS - - private short code; - private string name; - private string algName; - private string hashName; - private bool isExportable; - private CipherMode cipherMode; - private byte keyMaterialSize; - private byte expandedKeyMaterialSize; - private short effectiveKeyBits; - private byte ivSize; - private byte blockSize; - private TlsSessionContext context; - private SymmetricAlgorithm encryptionAlgorithm; - private ICryptoTransform encryptionCipher; - private SymmetricAlgorithm decryptionAlgorithm; - private ICryptoTransform decryptionCipher; - private KeyedHashAlgorithm clientHMAC; - private KeyedHashAlgorithm serverHMAC; - - #endregion - - #region PROTECTED_PROPERTIES - - protected ICryptoTransform EncryptionCipher - { - get { return encryptionCipher; } - } - - protected ICryptoTransform DecryptionCipher - { - get { return decryptionCipher; } - } - - protected KeyedHashAlgorithm ClientHMAC - { - get { return clientHMAC; } - } - - protected KeyedHashAlgorithm ServerHMAC - { - get { return serverHMAC; } - } - - #endregion - - #region PROPERTIES - - public short Code - { - get { return code; } - } - - public string Name - { - get { return name; } - } - - public bool IsExportable - { - get { return isExportable; } - } - - public CipherMode CipherMode - { - get { return cipherMode; } - } - - public int HashSize - { - get { return (int)(hashName == "MD5" ? 16 : 20); } - } - - public byte KeyMaterialSize - { - get { return keyMaterialSize; } - } - - public int KeyBlockSize - { - get - { - return keyMaterialSize*2 + HashSize*2 + ivSize*2; - } - } - - public byte ExpandedKeyMaterialSize - { - get { return expandedKeyMaterialSize; } - } - - public byte EffectiveKeyBits - { - get { return EffectiveKeyBits; } - } - - public byte IvSize - { - get { return ivSize; } - } - - public byte BlockSize - { - get { return blockSize; } - } - - public string HashName - { - get { return hashName; } - } - - public TlsSessionContext Context - { - get { return context; } - set { context = value; } - } - - #endregion - - #region CONSTRUCTORS - - public CipherSuite(short code, string name, string algName, string hashName, bool exportable, bool blockMode, byte keyMaterialSize, byte expandedKeyMaterialSize, short effectiveKeyBytes, byte ivSize, byte blockSize) - { - this.code = code; - this.name = name; - this.algName = algName; - this.hashName = hashName; - this.isExportable = exportable; - if (blockMode) - { - this.cipherMode = CipherMode.CBC; - } - this.keyMaterialSize = keyMaterialSize; - this.expandedKeyMaterialSize = expandedKeyMaterialSize; - this.effectiveKeyBits = effectiveKeyBits; - this.ivSize = ivSize; - this.blockSize = blockSize; - } - - #endregion - - #region METHODS - - public void InitializeCipher() - { - createEncryptionCipher(); - createDecryptionCipher(); - } - - public RSA CreateRSA() - { - RSA rsa; - if (this.Context.ServerSettings.ServerKeyExchange) - { - rsa = new RSACryptoServiceProvider(); - rsa.ImportParameters(this.Context.ServerSettings.RsaParameters); - } - else - { - rsa = this.Context.ServerSettings.ServerCertificates[0].RSA; - } - - return rsa; - } - - public RSACryptoServiceProvider CreateRSA(RSAParameters rsaParams) - { - // BUG: MS BCL 1.0 can't import a key which - // isn't the same size as the one present in - // the container. - int keySize = (rsaParams.Modulus.Length << 3); - RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize); - rsa.ImportParameters(rsaParams); - - return rsa; - } - - public void UpdateClientCipherIV(byte[] iv) - { - if (cipherMode == CipherMode.CBC) - { - // Set the new IV - encryptionAlgorithm.IV = iv; - - // Create encryption cipher with the new IV - encryptionCipher = encryptionAlgorithm.CreateEncryptor(); - } - } - - public void UpdateServerCipherIV(byte[] iv) - { - if (cipherMode == CipherMode.CBC) - { - // Set the new IV - decryptionAlgorithm.IV = iv; - - // Create encryption cipher with the new IV - decryptionCipher = decryptionAlgorithm.CreateDecryptor(); - } - } - - public byte[] EncryptRecord(byte[] fragment, byte[] mac) - { - // Encryption ( fragment + mac [+ padding + padding_length] ) - MemoryStream ms = new MemoryStream(); - CryptoStream cs = new CryptoStream(ms, this.EncryptionCipher, CryptoStreamMode.Write); - - cs.Write(fragment, 0, fragment.Length); - cs.Write(mac, 0, mac.Length); - if (this.CipherMode == CipherMode.CBC) - { - // Calculate padding_length - int fragmentLength = fragment.Length + mac.Length + 1; - int paddingLength = this.blockSize - fragmentLength % this.blockSize; - if (paddingLength == this.blockSize) - { - paddingLength = 0; - } - - // Write padding length byte - for (int i = 0; i < (paddingLength + 1); i++) - { - cs.WriteByte((byte)paddingLength); - } - } - // cs.FlushFinalBlock(); - cs.Close(); - - return ms.ToArray(); - } - - public void DecryptRecord(byte[] fragment, ref byte[] dcrFragment, ref byte[] dcrMAC) - { - int fragmentSize = 0; - int paddingLength = 0; - - // Decrypt message fragment ( fragment + mac [+ padding + padding_length] ) - byte[] buffer = new byte[fragment.Length]; - this.DecryptionCipher.TransformBlock(fragment, 0, fragment.Length, buffer, 0); - - // Calculate fragment size - if (this.CipherMode == CipherMode.CBC) - { - // Calculate padding_length - paddingLength = buffer[buffer.Length - 1]; - - /* Review this that is valid way for TLS1 but not for SSL3 - for (int i = (buffer.Length - 1); i > (buffer.Length - (paddingLength + 1)); i--) - { - if (buffer[i] != paddingLength) - { - paddingLength = 0; - break; - } - } - */ - - fragmentSize = (buffer.Length - (paddingLength + 1)) - HashSize; - } - else - { - fragmentSize = buffer.Length - HashSize; - } - - dcrFragment = new byte[fragmentSize]; - dcrMAC = new byte[HashSize]; - - Buffer.BlockCopy(buffer, 0, dcrFragment, 0, dcrFragment.Length); - Buffer.BlockCopy(buffer, dcrFragment.Length, dcrMAC, 0, dcrMAC.Length); - } - - #endregion - - #region ABSTRACT_METHODS - - public abstract byte[] ComputeClientRecordMAC(TlsContentType contentType, byte[] fragment); - - public abstract byte[] ComputeServerRecordMAC(TlsContentType contentType, byte[] fragment); - - public abstract void ComputeMasterSecret(byte[] preMasterSecret); - - public abstract void ComputeKeys(); - - #endregion - - #region KEY_GENERATION_METODS - - public byte[] CreatePremasterSecret() - { - TlsStream stream = new TlsStream(); - - // Write protocol version - stream.Write((short)this.Context.Protocol); - - // Generate random bytes - stream.Write(this.context.GetSecureRandomBytes(46)); - - byte[] preMasterSecret = stream.ToArray(); - - stream.Reset(); - - return preMasterSecret; - } - - public byte[] PRF(byte[] secret, string label, byte[] data, int length) - { - MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); - SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); - - int secretLen = secret.Length / 2; - - // Seed - TlsStream seedStream = new TlsStream(); - seedStream.Write(Encoding.ASCII.GetBytes(label)); - seedStream.Write(data); - byte[] seed = seedStream.ToArray(); - seedStream.Reset(); - - // Secret 1 - byte[] secret1 = new byte[secretLen]; - System.Array.Copy(secret, 0, secret1, 0, secretLen); - - // Secret2 - byte[] secret2 = new byte[secretLen]; - System.Array.Copy(secret, secretLen, secret2, 0, secretLen); - - // Secret 1 processing - byte[] p_md5 = Expand("MD5", secret1, seed, length); - - // Secret 2 processing - byte[] p_sha = Expand("SHA1", secret2, seed, length); - - // Perfor XOR of both results - byte[] masterSecret = new byte[length]; - for (int i = 0; i < masterSecret.Length; i++) - { - masterSecret[i] = (byte)(p_md5[i] ^ p_sha[i]); - } - - return masterSecret; - } - - public byte[] Expand(string hashName, byte[] secret, byte[] seed, int length) - { - int hashLength = hashName == "MD5" ? 16 : 20; - int iterations = (int)(length / hashLength); - if ((length % hashLength) > 0) - { - iterations++; - } - - HMAC hmac = new HMAC(hashName, secret); - TlsStream resMacs = new TlsStream(); - - byte[][] hmacs = new byte[iterations + 1][]; - hmacs[0] = seed; - for (int i = 1; i <= iterations; i++) - { - TlsStream hcseed = new TlsStream(); - hmac.TransformFinalBlock(hmacs[i-1], 0, hmacs[i-1].Length); - hmacs[i] = hmac.Hash; - hcseed.Write(hmacs[i]); - hcseed.Write(seed); - hmac.TransformFinalBlock(hcseed.ToArray(), 0, (int)hcseed.Length); - resMacs.Write(hmac.Hash); - hcseed.Reset(); - } - - byte[] res = new byte[length]; - - System.Array.Copy(resMacs.ToArray(), 0, res, 0, res.Length); - - resMacs.Reset(); - - return res; - } - - #endregion - - #region PRIVATE_METHODS - - // This code is from Mono.Security.X509Certificate class. - private byte[] getUnsignedBigInteger(byte[] integer) - { - if (integer[0] == 0x00) - { - // this first byte is added so we're sure it's an unsigned integer - // however we can't feed it into RSAParameters or DSAParameters - int length = integer.Length - 1; - byte[] uinteger = new byte[length]; - Array.Copy(integer, 1, uinteger, 0, length); - - return uinteger; - } - else - { - return integer; - } - } - - private void createEncryptionCipher() - { - // Create and configure the symmetric algorithm - switch (this.algName) - { - case "RC4": - encryptionAlgorithm = new ARC4Managed(); - break; - - default: - encryptionAlgorithm = SymmetricAlgorithm.Create(algName); - break; - } - - // If it's a block cipher - if (cipherMode == CipherMode.CBC) - { - // Configure encrypt algorithm - encryptionAlgorithm.Mode = this.cipherMode; - encryptionAlgorithm.Padding = PaddingMode.None; - encryptionAlgorithm.KeySize = this.keyMaterialSize * 8; - encryptionAlgorithm.BlockSize = this.blockSize * 8; - } - - // Set the key and IV for the algorithm - encryptionAlgorithm.Key = context.ClientWriteKey; - encryptionAlgorithm.IV = context.ClientWriteIV; - - // Create encryption cipher - encryptionCipher = encryptionAlgorithm.CreateEncryptor(); - - // Create the HMAC algorithm for the client - clientHMAC = new HMAC(hashName, context.ClientWriteMAC); - } - - private void createDecryptionCipher() - { - // Create and configure the symmetric algorithm - switch (this.algName) - { - case "RC4": - decryptionAlgorithm = new ARC4Managed(); - break; - - default: - decryptionAlgorithm = SymmetricAlgorithm.Create(algName); - break; - } - - // If it's a block cipher - if (cipherMode == CipherMode.CBC) - { - // Configure encrypt algorithm - decryptionAlgorithm.Mode = this.cipherMode; - decryptionAlgorithm.Padding = PaddingMode.None; - decryptionAlgorithm.KeySize = this.keyMaterialSize * 8; - decryptionAlgorithm.BlockSize = this.blockSize * 8; - } - - // Set the key and IV for the algorithm - decryptionAlgorithm.Key = context.ServerWriteKey; - decryptionAlgorithm.IV = context.ServerWriteIV; - - // Create decryption cipher - decryptionCipher = decryptionAlgorithm.CreateDecryptor(); - - // Create the HMAC algorithm for the server - serverHMAC = new HMAC(hashName, context.ServerWriteMAC); - } - - #endregion - } +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.IO; +using System.Text; +using System.Security.Cryptography; + +using Mono.Security; +using Mono.Security.Cryptography; +using Mono.Security.X509; + +namespace Mono.Security.Protocol.Tls +{ + internal abstract class CipherSuite + { + #region FIELDS + + private short code; + private string name; + private string algName; + private string hashName; + private bool isExportable; + private CipherMode cipherMode; + private byte keyMaterialSize; + private byte expandedKeyMaterialSize; + private short effectiveKeyBits; + private byte ivSize; + private byte blockSize; + private TlsSessionContext context; + private SymmetricAlgorithm encryptionAlgorithm; + private ICryptoTransform encryptionCipher; + private SymmetricAlgorithm decryptionAlgorithm; + private ICryptoTransform decryptionCipher; + private KeyedHashAlgorithm clientHMAC; + private KeyedHashAlgorithm serverHMAC; + + #endregion + + #region PROTECTED_PROPERTIES + + protected ICryptoTransform EncryptionCipher + { + get { return encryptionCipher; } + } + + protected ICryptoTransform DecryptionCipher + { + get { return decryptionCipher; } + } + + protected KeyedHashAlgorithm ClientHMAC + { + get { return clientHMAC; } + } + + protected KeyedHashAlgorithm ServerHMAC + { + get { return serverHMAC; } + } + + #endregion + + #region PROPERTIES + + public short Code + { + get { return code; } + } + + public string Name + { + get { return name; } + } + + public bool IsExportable + { + get { return isExportable; } + } + + public CipherMode CipherMode + { + get { return cipherMode; } + } + + public int HashSize + { + get { return (int)(hashName == "MD5" ? 16 : 20); } + } + + public byte KeyMaterialSize + { + get { return keyMaterialSize; } + } + + public int KeyBlockSize + { + get + { + return keyMaterialSize*2 + HashSize*2 + ivSize*2; + } + } + + public byte ExpandedKeyMaterialSize + { + get { return expandedKeyMaterialSize; } + } + + public byte EffectiveKeyBits + { + get { return EffectiveKeyBits; } + } + + public byte IvSize + { + get { return ivSize; } + } + + public byte BlockSize + { + get { return blockSize; } + } + + public string HashName + { + get { return hashName; } + } + + public TlsSessionContext Context + { + get { return context; } + set { context = value; } + } + + #endregion + + #region CONSTRUCTORS + + public CipherSuite(short code, string name, string algName, string hashName, bool exportable, bool blockMode, byte keyMaterialSize, byte expandedKeyMaterialSize, short effectiveKeyBytes, byte ivSize, byte blockSize) + { + this.code = code; + this.name = name; + this.algName = algName; + this.hashName = hashName; + this.isExportable = exportable; + if (blockMode) + { + this.cipherMode = CipherMode.CBC; + } + this.keyMaterialSize = keyMaterialSize; + this.expandedKeyMaterialSize = expandedKeyMaterialSize; + this.effectiveKeyBits = effectiveKeyBits; + this.ivSize = ivSize; + this.blockSize = blockSize; + } + + #endregion + + #region METHODS + + public void InitializeCipher() + { + createEncryptionCipher(); + createDecryptionCipher(); + } + + public RSA CreateRSA() + { + RSA rsa; + if (this.Context.ServerSettings.ServerKeyExchange) + { + rsa = new RSACryptoServiceProvider(); + rsa.ImportParameters(this.Context.ServerSettings.RsaParameters); + } + else + { + rsa = this.Context.ServerSettings.ServerCertificates[0].RSA; + } + + return rsa; + } + + public RSACryptoServiceProvider CreateRSA(RSAParameters rsaParams) + { + // BUG: MS BCL 1.0 can't import a key which + // isn't the same size as the one present in + // the container. + int keySize = (rsaParams.Modulus.Length << 3); + RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize); + rsa.ImportParameters(rsaParams); + + return rsa; + } + + public void UpdateClientCipherIV(byte[] iv) + { + if (cipherMode == CipherMode.CBC) + { + // Set the new IV + encryptionAlgorithm.IV = iv; + + // Create encryption cipher with the new IV + encryptionCipher = encryptionAlgorithm.CreateEncryptor(); + } + } + + public void UpdateServerCipherIV(byte[] iv) + { + if (cipherMode == CipherMode.CBC) + { + // Set the new IV + decryptionAlgorithm.IV = iv; + + // Create encryption cipher with the new IV + decryptionCipher = decryptionAlgorithm.CreateDecryptor(); + } + } + + public byte[] EncryptRecord(byte[] fragment, byte[] mac) + { + // Encryption ( fragment + mac [+ padding + padding_length] ) + MemoryStream ms = new MemoryStream(); + CryptoStream cs = new CryptoStream(ms, this.EncryptionCipher, CryptoStreamMode.Write); + + cs.Write(fragment, 0, fragment.Length); + cs.Write(mac, 0, mac.Length); + if (this.CipherMode == CipherMode.CBC) + { + // Calculate padding_length + int fragmentLength = fragment.Length + mac.Length + 1; + int paddingLength = this.blockSize - fragmentLength % this.blockSize; + if (paddingLength == this.blockSize) + { + paddingLength = 0; + } + + // Write padding length byte + for (int i = 0; i < (paddingLength + 1); i++) + { + cs.WriteByte((byte)paddingLength); + } + } + // cs.FlushFinalBlock(); + cs.Close(); + + return ms.ToArray(); + } + + public void DecryptRecord(byte[] fragment, ref byte[] dcrFragment, ref byte[] dcrMAC) + { + int fragmentSize = 0; + int paddingLength = 0; + + // Decrypt message fragment ( fragment + mac [+ padding + padding_length] ) + byte[] buffer = new byte[fragment.Length]; + this.DecryptionCipher.TransformBlock(fragment, 0, fragment.Length, buffer, 0); + + // Calculate fragment size + if (this.CipherMode == CipherMode.CBC) + { + // Calculate padding_length + paddingLength = buffer[buffer.Length - 1]; + + /* Review this that is valid way for TLS1 but not for SSL3 + for (int i = (buffer.Length - 1); i > (buffer.Length - (paddingLength + 1)); i--) + { + if (buffer[i] != paddingLength) + { + paddingLength = 0; + break; + } + } + */ + + fragmentSize = (buffer.Length - (paddingLength + 1)) - HashSize; + } + else + { + fragmentSize = buffer.Length - HashSize; + } + + dcrFragment = new byte[fragmentSize]; + dcrMAC = new byte[HashSize]; + + Buffer.BlockCopy(buffer, 0, dcrFragment, 0, dcrFragment.Length); + Buffer.BlockCopy(buffer, dcrFragment.Length, dcrMAC, 0, dcrMAC.Length); + } + + #endregion + + #region ABSTRACT_METHODS + + public abstract byte[] ComputeClientRecordMAC(TlsContentType contentType, byte[] fragment); + + public abstract byte[] ComputeServerRecordMAC(TlsContentType contentType, byte[] fragment); + + public abstract void ComputeMasterSecret(byte[] preMasterSecret); + + public abstract void ComputeKeys(); + + #endregion + + #region KEY_GENERATION_METODS + + public byte[] CreatePremasterSecret() + { + TlsStream stream = new TlsStream(); + + // Write protocol version + stream.Write((short)this.Context.Protocol); + + // Generate random bytes + stream.Write(this.context.GetSecureRandomBytes(46)); + + byte[] preMasterSecret = stream.ToArray(); + + stream.Reset(); + + return preMasterSecret; + } + + public byte[] PRF(byte[] secret, string label, byte[] data, int length) + { + MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); + SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); + + int secretLen = secret.Length / 2; + + // Seed + TlsStream seedStream = new TlsStream(); + seedStream.Write(Encoding.ASCII.GetBytes(label)); + seedStream.Write(data); + byte[] seed = seedStream.ToArray(); + seedStream.Reset(); + + // Secret 1 + byte[] secret1 = new byte[secretLen]; + System.Array.Copy(secret, 0, secret1, 0, secretLen); + + // Secret2 + byte[] secret2 = new byte[secretLen]; + System.Array.Copy(secret, secretLen, secret2, 0, secretLen); + + // Secret 1 processing + byte[] p_md5 = Expand("MD5", secret1, seed, length); + + // Secret 2 processing + byte[] p_sha = Expand("SHA1", secret2, seed, length); + + // Perfor XOR of both results + byte[] masterSecret = new byte[length]; + for (int i = 0; i < masterSecret.Length; i++) + { + masterSecret[i] = (byte)(p_md5[i] ^ p_sha[i]); + } + + return masterSecret; + } + + public byte[] Expand(string hashName, byte[] secret, byte[] seed, int length) + { + int hashLength = hashName == "MD5" ? 16 : 20; + int iterations = (int)(length / hashLength); + if ((length % hashLength) > 0) + { + iterations++; + } + + HMAC hmac = new HMAC(hashName, secret); + TlsStream resMacs = new TlsStream(); + + byte[][] hmacs = new byte[iterations + 1][]; + hmacs[0] = seed; + for (int i = 1; i <= iterations; i++) + { + TlsStream hcseed = new TlsStream(); + hmac.TransformFinalBlock(hmacs[i-1], 0, hmacs[i-1].Length); + hmacs[i] = hmac.Hash; + hcseed.Write(hmacs[i]); + hcseed.Write(seed); + hmac.TransformFinalBlock(hcseed.ToArray(), 0, (int)hcseed.Length); + resMacs.Write(hmac.Hash); + hcseed.Reset(); + } + + byte[] res = new byte[length]; + + System.Array.Copy(resMacs.ToArray(), 0, res, 0, res.Length); + + resMacs.Reset(); + + return res; + } + + #endregion + + #region PRIVATE_METHODS + + // This code is from Mono.Security.X509Certificate class. + private byte[] getUnsignedBigInteger(byte[] integer) + { + if (integer[0] == 0x00) + { + // this first byte is added so we're sure it's an unsigned integer + // however we can't feed it into RSAParameters or DSAParameters + int length = integer.Length - 1; + byte[] uinteger = new byte[length]; + Array.Copy(integer, 1, uinteger, 0, length); + + return uinteger; + } + else + { + return integer; + } + } + + private void createEncryptionCipher() + { + // Create and configure the symmetric algorithm + switch (this.algName) + { + case "RC4": + encryptionAlgorithm = new ARC4Managed(); + break; + + default: + encryptionAlgorithm = SymmetricAlgorithm.Create(algName); + break; + } + + // If it's a block cipher + if (cipherMode == CipherMode.CBC) + { + // Configure encrypt algorithm + encryptionAlgorithm.Mode = this.cipherMode; + encryptionAlgorithm.Padding = PaddingMode.None; + encryptionAlgorithm.KeySize = this.keyMaterialSize * 8; + encryptionAlgorithm.BlockSize = this.blockSize * 8; + } + + // Set the key and IV for the algorithm + encryptionAlgorithm.Key = context.ClientWriteKey; + encryptionAlgorithm.IV = context.ClientWriteIV; + + // Create encryption cipher + encryptionCipher = encryptionAlgorithm.CreateEncryptor(); + + // Create the HMAC algorithm for the client + clientHMAC = new HMAC(hashName, context.ClientWriteMAC); + } + + private void createDecryptionCipher() + { + // Create and configure the symmetric algorithm + switch (this.algName) + { + case "RC4": + decryptionAlgorithm = new ARC4Managed(); + break; + + default: + decryptionAlgorithm = SymmetricAlgorithm.Create(algName); + break; + } + + // If it's a block cipher + if (cipherMode == CipherMode.CBC) + { + // Configure encrypt algorithm + decryptionAlgorithm.Mode = this.cipherMode; + decryptionAlgorithm.Padding = PaddingMode.None; + decryptionAlgorithm.KeySize = this.keyMaterialSize * 8; + decryptionAlgorithm.BlockSize = this.blockSize * 8; + } + + // Set the key and IV for the algorithm + decryptionAlgorithm.Key = context.ServerWriteKey; + decryptionAlgorithm.IV = context.ServerWriteIV; + + // Create decryption cipher + decryptionCipher = decryptionAlgorithm.CreateDecryptor(); + + // Create the HMAC algorithm for the server + serverHMAC = new HMAC(hashName, context.ServerWriteMAC); + } + + #endregion + } } \ No newline at end of file diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuite.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuite.cs index 1ce50c3f2c8..3f88b20aa87 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuite.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuite.cs @@ -1,156 +1,156 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.IO; -using System.Text; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - -using Mono.Security; -using Mono.Security.Cryptography; - -namespace Mono.Security.Protocol.Tls -{ - internal class TlsCipherSuite : CipherSuite - { - #region CONSTRUCTORS - - public TlsCipherSuite(short code, string name, string algName, - string hashName, bool exportable, bool blockMode, - byte keyMaterialSize, byte expandedKeyMaterialSize, - short effectiveKeyBytes, byte ivSize, byte blockSize) - : base (code, name, algName, hashName, exportable, blockMode, - keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, - ivSize, blockSize) - { - } - - #endregion - - #region MAC_GENERATION_METHOD - - public override byte[] ComputeServerRecordMAC(TlsContentType contentType, byte[] fragment) - { - TlsStream data = new TlsStream(); - byte[] result = null; - - data.Write(this.Context.ReadSequenceNumber); - data.Write((byte)contentType); - data.Write((short)this.Context.Protocol); - data.Write((short)fragment.Length); - data.Write(fragment); - - result = this.ServerHMAC.ComputeHash(data.ToArray()); - - data.Reset(); - - return result; - } - - public override byte[] ComputeClientRecordMAC(TlsContentType contentType, byte[] fragment) - { - TlsStream data = new TlsStream(); - byte[] result = null; - - data.Write(this.Context.WriteSequenceNumber); - data.Write((byte)contentType); - data.Write((short)this.Context.Protocol); - data.Write((short)fragment.Length); - data.Write(fragment); - - result = this.ClientHMAC.ComputeHash(data.ToArray()); - - data.Reset(); - - return result; - } - - #endregion - - #region KEY_GENERATION_METODS - - public override void ComputeMasterSecret(byte[] preMasterSecret) - { - // Create master secret - this.Context.MasterSecret = new byte[preMasterSecret.Length]; - this.Context.MasterSecret = this.PRF( - preMasterSecret, "master secret", this.Context.RandomCS, 48); - } - - public override void ComputeKeys() - { - // Create keyblock - TlsStream keyBlock = new TlsStream( - this.PRF( - this.Context.MasterSecret, - "key expansion", - this.Context.RandomSC, - this.KeyBlockSize)); - - this.Context.ClientWriteMAC = keyBlock.ReadBytes(this.HashSize); - this.Context.ServerWriteMAC = keyBlock.ReadBytes(this.HashSize); - this.Context.ClientWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize); - this.Context.ServerWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize); - - if (!this.IsExportable) - { - if (this.IvSize != 0) - { - this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize); - this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize); - } - else - { - this.Context.ClientWriteIV = new byte[0]; - this.Context.ServerWriteIV = new byte[0]; - } - } - else - { - // Generate final write keys - byte[] finalClientWriteKey = PRF(this.Context.ClientWriteKey, "client write key", this.Context.RandomCS, this.KeyMaterialSize); - byte[] finalServerWriteKey = PRF(this.Context.ServerWriteKey, "server write key", this.Context.RandomCS, this.KeyMaterialSize); - - this.Context.ClientWriteKey = finalClientWriteKey; - this.Context.ServerWriteKey = finalServerWriteKey; - - // Generate IV block - byte[] ivBlock = PRF(new byte[]{}, "IV block", this.Context.RandomCS, this.IvSize*2); - - // Generate IV keys - this.Context.ClientWriteIV = new byte[this.IvSize]; - System.Array.Copy(ivBlock, 0, this.Context.ClientWriteIV, 0, this.Context.ClientWriteIV.Length); - - this.Context.ServerWriteIV = new byte[this.IvSize]; - System.Array.Copy(ivBlock, this.IvSize, this.Context.ServerWriteIV, 0, this.Context.ServerWriteIV.Length); - } - - // Clear no more needed data - keyBlock.Reset(); - } - - #endregion - } +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.IO; +using System.Text; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; + +using Mono.Security; +using Mono.Security.Cryptography; + +namespace Mono.Security.Protocol.Tls +{ + internal class TlsCipherSuite : CipherSuite + { + #region CONSTRUCTORS + + public TlsCipherSuite(short code, string name, string algName, + string hashName, bool exportable, bool blockMode, + byte keyMaterialSize, byte expandedKeyMaterialSize, + short effectiveKeyBytes, byte ivSize, byte blockSize) + : base (code, name, algName, hashName, exportable, blockMode, + keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, + ivSize, blockSize) + { + } + + #endregion + + #region MAC_GENERATION_METHOD + + public override byte[] ComputeServerRecordMAC(TlsContentType contentType, byte[] fragment) + { + TlsStream data = new TlsStream(); + byte[] result = null; + + data.Write(this.Context.ReadSequenceNumber); + data.Write((byte)contentType); + data.Write((short)this.Context.Protocol); + data.Write((short)fragment.Length); + data.Write(fragment); + + result = this.ServerHMAC.ComputeHash(data.ToArray()); + + data.Reset(); + + return result; + } + + public override byte[] ComputeClientRecordMAC(TlsContentType contentType, byte[] fragment) + { + TlsStream data = new TlsStream(); + byte[] result = null; + + data.Write(this.Context.WriteSequenceNumber); + data.Write((byte)contentType); + data.Write((short)this.Context.Protocol); + data.Write((short)fragment.Length); + data.Write(fragment); + + result = this.ClientHMAC.ComputeHash(data.ToArray()); + + data.Reset(); + + return result; + } + + #endregion + + #region KEY_GENERATION_METODS + + public override void ComputeMasterSecret(byte[] preMasterSecret) + { + // Create master secret + this.Context.MasterSecret = new byte[preMasterSecret.Length]; + this.Context.MasterSecret = this.PRF( + preMasterSecret, "master secret", this.Context.RandomCS, 48); + } + + public override void ComputeKeys() + { + // Create keyblock + TlsStream keyBlock = new TlsStream( + this.PRF( + this.Context.MasterSecret, + "key expansion", + this.Context.RandomSC, + this.KeyBlockSize)); + + this.Context.ClientWriteMAC = keyBlock.ReadBytes(this.HashSize); + this.Context.ServerWriteMAC = keyBlock.ReadBytes(this.HashSize); + this.Context.ClientWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize); + this.Context.ServerWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize); + + if (!this.IsExportable) + { + if (this.IvSize != 0) + { + this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize); + this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize); + } + else + { + this.Context.ClientWriteIV = new byte[0]; + this.Context.ServerWriteIV = new byte[0]; + } + } + else + { + // Generate final write keys + byte[] finalClientWriteKey = PRF(this.Context.ClientWriteKey, "client write key", this.Context.RandomCS, this.KeyMaterialSize); + byte[] finalServerWriteKey = PRF(this.Context.ServerWriteKey, "server write key", this.Context.RandomCS, this.KeyMaterialSize); + + this.Context.ClientWriteKey = finalClientWriteKey; + this.Context.ServerWriteKey = finalServerWriteKey; + + // Generate IV block + byte[] ivBlock = PRF(new byte[]{}, "IV block", this.Context.RandomCS, this.IvSize*2); + + // Generate IV keys + this.Context.ClientWriteIV = new byte[this.IvSize]; + System.Array.Copy(ivBlock, 0, this.Context.ClientWriteIV, 0, this.Context.ClientWriteIV.Length); + + this.Context.ServerWriteIV = new byte[this.IvSize]; + System.Array.Copy(ivBlock, this.IvSize, this.Context.ServerWriteIV, 0, this.Context.ServerWriteIV.Length); + } + + // Clear no more needed data + keyBlock.Reset(); + } + + #endregion + } } \ No newline at end of file diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuiteCollection.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuiteCollection.cs index 30433e07929..9f721f96dad 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuiteCollection.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuiteCollection.cs @@ -1,156 +1,156 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Collections; -using System.Globalization; -using System.Security.Cryptography; - -namespace Mono.Security.Protocol.Tls -{ - internal sealed class TlsCipherSuiteCollection : ArrayList - { - #region FIELDS - - private TlsProtocol protocol; - - #endregion - - #region PROPERTIES - - public CipherSuite this[string name] - { - get { return (CipherSuite)this[IndexOf(name)]; } - set { this[IndexOf(name)] = (CipherSuite)value; } - } - - public CipherSuite this[short code] - { - get { return (CipherSuite)base[IndexOf(code)]; } - set { base[IndexOf(code)] = (CipherSuite)value; } - } - - public new CipherSuite this[int code] - { - get { return (CipherSuite)base[code]; } - set { base[code] = (CipherSuite)value; } - } - - #endregion - - #region CONSTRUCTORS - - public TlsCipherSuiteCollection(TlsProtocol protocol) : base() - { - this.protocol = protocol; - } - - #endregion - - #region METHODS - - public bool Contains(string name) - { - return(-1 != IndexOf(name)); - } - - public int IndexOf(string name) - { - int index = 0; - foreach (CipherSuite suite in this) - { - if (cultureAwareCompare(suite.Name, name)) - { - return index; - } - index++; - } - return -1; - } - - public int IndexOf(short code) - { - int index = 0; - foreach (CipherSuite suite in this) - { - if (suite.Code == code) - { - return index; - } - index++; - } - return -1; - } - - public void RemoveAt(string errorMessage) - { - RemoveAt(IndexOf(errorMessage)); - } - - public CipherSuite Add(short code, string name, string algName, string hashName, bool exportable, bool blockMode, byte keyMaterialSize, byte expandedKeyMaterialSize, short effectiveKeyBytes, byte ivSize, byte blockSize) - { - switch (this.protocol) - { - case TlsProtocol.Tls1: - return this.add( - new TlsCipherSuite(code, name, algName, hashName, exportable, blockMode, keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize)); - - case TlsProtocol.Ssl3: - return this.add( - new TlsSslCipherSuite(code, name, algName, hashName, exportable, blockMode, keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize)); - - default: - throw new NotSupportedException(); - } - } - - private TlsCipherSuite add(TlsCipherSuite cipherSuite) - { - base.Add(cipherSuite); - - return cipherSuite; - } - - private TlsSslCipherSuite add(TlsSslCipherSuite cipherSuite) - { - base.Add(cipherSuite); - - return cipherSuite; - } - - private bool cultureAwareCompare(string strA, string strB) - { - try - { - return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase) == 0 ? true : false; - } - catch (NotSupportedException) - { - return strA.ToUpper() == strB.ToUpper() ? true : false; - } - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Collections; +using System.Globalization; +using System.Security.Cryptography; + +namespace Mono.Security.Protocol.Tls +{ + internal sealed class TlsCipherSuiteCollection : ArrayList + { + #region FIELDS + + private TlsProtocol protocol; + + #endregion + + #region PROPERTIES + + public CipherSuite this[string name] + { + get { return (CipherSuite)this[IndexOf(name)]; } + set { this[IndexOf(name)] = (CipherSuite)value; } + } + + public CipherSuite this[short code] + { + get { return (CipherSuite)base[IndexOf(code)]; } + set { base[IndexOf(code)] = (CipherSuite)value; } + } + + public new CipherSuite this[int code] + { + get { return (CipherSuite)base[code]; } + set { base[code] = (CipherSuite)value; } + } + + #endregion + + #region CONSTRUCTORS + + public TlsCipherSuiteCollection(TlsProtocol protocol) : base() + { + this.protocol = protocol; + } + + #endregion + + #region METHODS + + public bool Contains(string name) + { + return(-1 != IndexOf(name)); + } + + public int IndexOf(string name) + { + int index = 0; + foreach (CipherSuite suite in this) + { + if (cultureAwareCompare(suite.Name, name)) + { + return index; + } + index++; + } + return -1; + } + + public int IndexOf(short code) + { + int index = 0; + foreach (CipherSuite suite in this) + { + if (suite.Code == code) + { + return index; + } + index++; + } + return -1; + } + + public void RemoveAt(string errorMessage) + { + RemoveAt(IndexOf(errorMessage)); + } + + public CipherSuite Add(short code, string name, string algName, string hashName, bool exportable, bool blockMode, byte keyMaterialSize, byte expandedKeyMaterialSize, short effectiveKeyBytes, byte ivSize, byte blockSize) + { + switch (this.protocol) + { + case TlsProtocol.Tls1: + return this.add( + new TlsCipherSuite(code, name, algName, hashName, exportable, blockMode, keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize)); + + case TlsProtocol.Ssl3: + return this.add( + new TlsSslCipherSuite(code, name, algName, hashName, exportable, blockMode, keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize)); + + default: + throw new NotSupportedException(); + } + } + + private TlsCipherSuite add(TlsCipherSuite cipherSuite) + { + base.Add(cipherSuite); + + return cipherSuite; + } + + private TlsSslCipherSuite add(TlsSslCipherSuite cipherSuite) + { + base.Add(cipherSuite); + + return cipherSuite; + } + + private bool cultureAwareCompare(string strA, string strB) + { + try + { + return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase) == 0 ? true : false; + } + catch (NotSupportedException) + { + return strA.ToUpper() == strB.ToUpper() ? true : false; + } + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuiteFactory.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuiteFactory.cs index 1fdd42780b1..2fa7313799e 100755 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuiteFactory.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuiteFactory.cs @@ -1,169 +1,169 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; - -namespace Mono.Security.Protocol.Tls -{ - internal class TlsCipherSuiteFactory - { - public static TlsCipherSuiteCollection GetSupportedCiphers(TlsProtocol protocol) - { - switch (protocol) - { - case TlsProtocol.Tls1: - return TlsCipherSuiteFactory.GetTls1SupportedCiphers(); - - case TlsProtocol.Ssl3: - return TlsCipherSuiteFactory.GetSsl3SupportedCiphers(); - - default: - throw new NotSupportedException(); - } - } - - #region PRIVATE_STATIC_METHODS - - private static TlsCipherSuiteCollection GetTls1SupportedCiphers() - { - TlsCipherSuiteCollection scs = new TlsCipherSuiteCollection(TlsProtocol.Tls1); - - // Supported ciphers - // scs.Add((0x00 << 0x08) | 0x06, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", "RC2", "MD5", true, true, 5, 16, 40, 8, 8); - scs.Add((0x00 << 0x08) | 0x35, "TLS_RSA_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); - scs.Add((0x00 << 0x08) | 0x2F, "TLS_RSA_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 16, 16); - scs.Add((0x00 << 0x08) | 0x0A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - scs.Add((0x00 << 0x08) | 0x09, "TLS_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); - scs.Add((0x00 << 0x08) | 0x05, "TLS_RSA_WITH_RC4_128_SHA", "RC4", "SHA1", false, false, 16, 16, 128, 0, 0); - scs.Add((0x00 << 0x08) | 0x04, "TLS_RSA_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); - - // Default CipherSuite - // scs.Add(0, "TLS_NULL_WITH_NULL_NULL", "", "", true, false, 0, 0, 0, 0, 0); - - // RSA Cipher Suites - // scs.Add((0x00 << 0x08) | 0x01, "TLS_RSA_WITH_NULL_MD5", "", "MD5", true, false, 0, 0, 0, 0, 0); - // scs.Add((0x00 << 0x08) | 0x02, "TLS_RSA_WITH_NULL_SHA", "", "SHA1", true, false, 0, 0, 0, 0, 0); - // scs.Add((0x00 << 0x08) | 0x03, "TLS_RSA_EXPORT_WITH_RC4_40_MD5", "RC4", "MD5", true, false, 5, 16, 40, 0, 0); - // scs.Add((0x00 << 0x08) | 0x05, "TLS_RSA_WITH_RC4_128_SHA", "RC4", "SHA1", false, false, 16, 16, 128, 0, 0); - // scs.Add((0x00 << 0x08) | 0x04, "TLS_RSA_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); - // scs.Add((0x00 << 0x08) | 0x06, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", "RC2", "MD5", true, true, 5, 16, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x07, "TLS_RSA_WITH_IDEA_CBC_SHA", "IDEA", "SHA1", false, true, 16, 16, 128, 8, 8); - // scs.Add((0x00 << 0x08) | 0x08, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x09, "TLS_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - - // Diffie-Hellman Cipher Suites - // scs.Add((0x00 << 0x08) | 0x0B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0C, "TLS_DH_DSS_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0F, "TLS_DH_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x10, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - // scs.Add((0x00 << 0x08) | 0x11, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x12, "TLS_DHE_DSS_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x13, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - // scs.Add((0x00 << 0x08) | 0x14, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x15, "TLS_DHE_RSA_WITH_DES_CBC_SHA", "SHA1", "DES", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x16, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - - // Anonymous Diffie-Hellman Cipher Suites - // scs.Add((0x00 << 0x08) | 0x17, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", "RC4", "MD5", true, false, 5, 16, 40, 0, 0); - // scs.Add((0x00 << 0x08) | 0x18, "TLS_DH_anon_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); - // scs.Add((0x00 << 0x08) | 0x19, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", false, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x1A, "TLS_DH_anon_WITH_DES_CBC_SHA", "DES4", "SHA1", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x1B, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - - // AES CipherSuites - // - // Ref: RFC3268 - (http://www.ietf.org/rfc/rfc3268.txt) - - // scs.Add((0x00 << 0x08) | 0x2F, "TLS_RSA_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 16, 16); - // scs.Add((0x00 << 0x08) | 0x30, "TLS_DH_DSS_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 8, 8); - // scs.Add((0x00 << 0x08) | 0x31, "TLS_DH_RSA_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 8, 8); - // scs.Add((0x00 << 0x08) | 0x32, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 8, 8); - // scs.Add((0x00 << 0x08) | 0x33, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 8, 8); - // scs.Add((0x00 << 0x08) | 0x34, "TLS_DH_anon_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 8, 8); - - // scs.Add((0x00 << 0x08) | 0x35, "TLS_RSA_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); - // scs.Add((0x00 << 0x08) | 0x36, "TLS_DH_DSS_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); - // scs.Add((0x00 << 0x08) | 0x37, "TLS_DH_RSA_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); - // scs.Add((0x00 << 0x08) | 0x38, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); - // scs.Add((0x00 << 0x08) | 0x39, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); - // scs.Add((0x00 << 0x08) | 0x3A, "TLS_DH_anon_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); - - return scs; - } - - private static TlsCipherSuiteCollection GetSsl3SupportedCiphers() - { - TlsCipherSuiteCollection scs = new TlsCipherSuiteCollection(TlsProtocol.Ssl3); - - // Supported ciphers - scs.Add((0x00 << 0x08) | 0x0A, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - scs.Add((0x00 << 0x08) | 0x09, "SSL_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); - scs.Add((0x00 << 0x08) | 0x05, "SSL_RSA_WITH_RC4_128_SHA", "RC4", "SHA1", false, false, 16, 16, 128, 0, 0); - scs.Add((0x00 << 0x08) | 0x04, "SSL_RSA_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); - - // Default CipherSuite - // scs.Add(0, "SSL_NULL_WITH_NULL_NULL", "", "", true, false, 0, 0, 0, 0, 0); - - // RSA Cipher Suites - // scs.Add((0x00 << 0x08) | 0x01, "SSL_RSA_WITH_NULL_MD5", "", "MD5", true, false, 0, 0, 0, 0, 0); - // scs.Add((0x00 << 0x08) | 0x02, "SSL_RSA_WITH_NULL_SHA", "", "SHA1", true, false, 0, 0, 0, 0, 0); - // scs.Add((0x00 << 0x08) | 0x03, "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "RC4", "MD5", true, false, 5, 16, 40, 0, 0); - // scs.Add((0x00 << 0x08) | 0x05, "SSL_RSA_WITH_RC4_128_SHA", "RC4", "SHA1", false, false, 16, 16, 128, 0, 0); - // scs.Add((0x00 << 0x08) | 0x04, "SSL_RSA_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); - // scs.Add((0x00 << 0x08) | 0x06, "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", "RC2", "MD5", true, true, 5, 16, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x07, "SSL_RSA_WITH_IDEA_CBC_SHA", "IDEA", "SHA1", false, true, 16, 16, 128, 8, 8); - // scs.Add((0x00 << 0x08) | 0x08, "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x09, "SSL_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0A, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - - // Diffie-Hellman Cipher Suites - // scs.Add((0x00 << 0x08) | 0x0B, "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0C, "SSL_DH_DSS_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0D, "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0E, "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x0F, "SSL_DH_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x10, "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - // scs.Add((0x00 << 0x08) | 0x11, "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x12, "SSL_DHE_DSS_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x13, "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - // scs.Add((0x00 << 0x08) | 0x14, "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x15, "SSL_DHE_RSA_WITH_DES_CBC_SHA", "SHA1", "DES", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x16, "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - - // Anonymous Diffie-Hellman Cipher Suites - // scs.Add((0x00 << 0x08) | 0x17, "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", "RC4", "MD5", true, false, 5, 16, 40, 0, 0); - // scs.Add((0x00 << 0x08) | 0x18, "SSL_DH_anon_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); - // scs.Add((0x00 << 0x08) | 0x19, "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", false, true, 5, 8, 40, 8, 8); - // scs.Add((0x00 << 0x08) | 0x1A, "SSL_DH_anon_WITH_DES_CBC_SHA", "DES4", "SHA1", false, true, 8, 8, 56, 8, 8); - // scs.Add((0x00 << 0x08) | 0x1B, "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); - - return scs; - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; + +namespace Mono.Security.Protocol.Tls +{ + internal class TlsCipherSuiteFactory + { + public static TlsCipherSuiteCollection GetSupportedCiphers(TlsProtocol protocol) + { + switch (protocol) + { + case TlsProtocol.Tls1: + return TlsCipherSuiteFactory.GetTls1SupportedCiphers(); + + case TlsProtocol.Ssl3: + return TlsCipherSuiteFactory.GetSsl3SupportedCiphers(); + + default: + throw new NotSupportedException(); + } + } + + #region PRIVATE_STATIC_METHODS + + private static TlsCipherSuiteCollection GetTls1SupportedCiphers() + { + TlsCipherSuiteCollection scs = new TlsCipherSuiteCollection(TlsProtocol.Tls1); + + // Supported ciphers + // scs.Add((0x00 << 0x08) | 0x06, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", "RC2", "MD5", true, true, 5, 16, 40, 8, 8); + scs.Add((0x00 << 0x08) | 0x35, "TLS_RSA_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); + scs.Add((0x00 << 0x08) | 0x2F, "TLS_RSA_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 16, 16); + scs.Add((0x00 << 0x08) | 0x0A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + scs.Add((0x00 << 0x08) | 0x09, "TLS_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); + scs.Add((0x00 << 0x08) | 0x05, "TLS_RSA_WITH_RC4_128_SHA", "RC4", "SHA1", false, false, 16, 16, 128, 0, 0); + scs.Add((0x00 << 0x08) | 0x04, "TLS_RSA_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); + + // Default CipherSuite + // scs.Add(0, "TLS_NULL_WITH_NULL_NULL", "", "", true, false, 0, 0, 0, 0, 0); + + // RSA Cipher Suites + // scs.Add((0x00 << 0x08) | 0x01, "TLS_RSA_WITH_NULL_MD5", "", "MD5", true, false, 0, 0, 0, 0, 0); + // scs.Add((0x00 << 0x08) | 0x02, "TLS_RSA_WITH_NULL_SHA", "", "SHA1", true, false, 0, 0, 0, 0, 0); + // scs.Add((0x00 << 0x08) | 0x03, "TLS_RSA_EXPORT_WITH_RC4_40_MD5", "RC4", "MD5", true, false, 5, 16, 40, 0, 0); + // scs.Add((0x00 << 0x08) | 0x05, "TLS_RSA_WITH_RC4_128_SHA", "RC4", "SHA1", false, false, 16, 16, 128, 0, 0); + // scs.Add((0x00 << 0x08) | 0x04, "TLS_RSA_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); + // scs.Add((0x00 << 0x08) | 0x06, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", "RC2", "MD5", true, true, 5, 16, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x07, "TLS_RSA_WITH_IDEA_CBC_SHA", "IDEA", "SHA1", false, true, 16, 16, 128, 8, 8); + // scs.Add((0x00 << 0x08) | 0x08, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x09, "TLS_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x0A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + + // Diffie-Hellman Cipher Suites + // scs.Add((0x00 << 0x08) | 0x0B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x0C, "TLS_DH_DSS_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x0D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + // scs.Add((0x00 << 0x08) | 0x0E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x0F, "TLS_DH_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x10, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + // scs.Add((0x00 << 0x08) | 0x11, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x12, "TLS_DHE_DSS_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x13, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + // scs.Add((0x00 << 0x08) | 0x14, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x15, "TLS_DHE_RSA_WITH_DES_CBC_SHA", "SHA1", "DES", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x16, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + + // Anonymous Diffie-Hellman Cipher Suites + // scs.Add((0x00 << 0x08) | 0x17, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", "RC4", "MD5", true, false, 5, 16, 40, 0, 0); + // scs.Add((0x00 << 0x08) | 0x18, "TLS_DH_anon_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); + // scs.Add((0x00 << 0x08) | 0x19, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", false, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x1A, "TLS_DH_anon_WITH_DES_CBC_SHA", "DES4", "SHA1", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x1B, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + + // AES CipherSuites + // + // Ref: RFC3268 - (http://www.ietf.org/rfc/rfc3268.txt) + + // scs.Add((0x00 << 0x08) | 0x2F, "TLS_RSA_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 16, 16); + // scs.Add((0x00 << 0x08) | 0x30, "TLS_DH_DSS_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 8, 8); + // scs.Add((0x00 << 0x08) | 0x31, "TLS_DH_RSA_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 8, 8); + // scs.Add((0x00 << 0x08) | 0x32, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 8, 8); + // scs.Add((0x00 << 0x08) | 0x33, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 8, 8); + // scs.Add((0x00 << 0x08) | 0x34, "TLS_DH_anon_WITH_AES_128_CBC_SHA", "Rijndael", "SHA1", false, true, 16, 16, 128, 8, 8); + + // scs.Add((0x00 << 0x08) | 0x35, "TLS_RSA_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); + // scs.Add((0x00 << 0x08) | 0x36, "TLS_DH_DSS_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); + // scs.Add((0x00 << 0x08) | 0x37, "TLS_DH_RSA_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); + // scs.Add((0x00 << 0x08) | 0x38, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); + // scs.Add((0x00 << 0x08) | 0x39, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); + // scs.Add((0x00 << 0x08) | 0x3A, "TLS_DH_anon_WITH_AES_256_CBC_SHA", "Rijndael", "SHA1", false, true, 32, 32, 256, 16, 16); + + return scs; + } + + private static TlsCipherSuiteCollection GetSsl3SupportedCiphers() + { + TlsCipherSuiteCollection scs = new TlsCipherSuiteCollection(TlsProtocol.Ssl3); + + // Supported ciphers + scs.Add((0x00 << 0x08) | 0x0A, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + scs.Add((0x00 << 0x08) | 0x09, "SSL_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); + scs.Add((0x00 << 0x08) | 0x05, "SSL_RSA_WITH_RC4_128_SHA", "RC4", "SHA1", false, false, 16, 16, 128, 0, 0); + scs.Add((0x00 << 0x08) | 0x04, "SSL_RSA_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); + + // Default CipherSuite + // scs.Add(0, "SSL_NULL_WITH_NULL_NULL", "", "", true, false, 0, 0, 0, 0, 0); + + // RSA Cipher Suites + // scs.Add((0x00 << 0x08) | 0x01, "SSL_RSA_WITH_NULL_MD5", "", "MD5", true, false, 0, 0, 0, 0, 0); + // scs.Add((0x00 << 0x08) | 0x02, "SSL_RSA_WITH_NULL_SHA", "", "SHA1", true, false, 0, 0, 0, 0, 0); + // scs.Add((0x00 << 0x08) | 0x03, "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "RC4", "MD5", true, false, 5, 16, 40, 0, 0); + // scs.Add((0x00 << 0x08) | 0x05, "SSL_RSA_WITH_RC4_128_SHA", "RC4", "SHA1", false, false, 16, 16, 128, 0, 0); + // scs.Add((0x00 << 0x08) | 0x04, "SSL_RSA_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); + // scs.Add((0x00 << 0x08) | 0x06, "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", "RC2", "MD5", true, true, 5, 16, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x07, "SSL_RSA_WITH_IDEA_CBC_SHA", "IDEA", "SHA1", false, true, 16, 16, 128, 8, 8); + // scs.Add((0x00 << 0x08) | 0x08, "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x09, "SSL_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x0A, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + + // Diffie-Hellman Cipher Suites + // scs.Add((0x00 << 0x08) | 0x0B, "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x0C, "SSL_DH_DSS_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x0D, "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + // scs.Add((0x00 << 0x08) | 0x0E, "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x0F, "SSL_DH_RSA_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x10, "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + // scs.Add((0x00 << 0x08) | 0x11, "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x12, "SSL_DHE_DSS_WITH_DES_CBC_SHA", "DES", "SHA1", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x13, "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + // scs.Add((0x00 << 0x08) | 0x14, "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", true, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x15, "SSL_DHE_RSA_WITH_DES_CBC_SHA", "SHA1", "DES", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x16, "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + + // Anonymous Diffie-Hellman Cipher Suites + // scs.Add((0x00 << 0x08) | 0x17, "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", "RC4", "MD5", true, false, 5, 16, 40, 0, 0); + // scs.Add((0x00 << 0x08) | 0x18, "SSL_DH_anon_WITH_RC4_128_MD5", "RC4", "MD5", false, false, 16, 16, 128, 0, 0); + // scs.Add((0x00 << 0x08) | 0x19, "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "DES", "SHA1", false, true, 5, 8, 40, 8, 8); + // scs.Add((0x00 << 0x08) | 0x1A, "SSL_DH_anon_WITH_DES_CBC_SHA", "DES4", "SHA1", false, true, 8, 8, 56, 8, 8); + // scs.Add((0x00 << 0x08) | 0x1B, "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA1", false, true, 24, 24, 168, 8, 8); + + return scs; + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs index f04e3fe9558..371ad6ec72f 100755 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCompressionMethod.cs @@ -1,37 +1,37 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; - -namespace Mono.Security.Protocol.Tls -{ - // Information about compression methods allowed by TLS - // can be found in: - // draft-ietf-tls-compression-05.txt (http://www.ietf.org/internet-drafts/draft-ietf-tls-compression-05.txt) - public enum TlsCompressionMethod : byte - { - None = 0, - Zlib = 1 - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; + +namespace Mono.Security.Protocol.Tls +{ + // Information about compression methods allowed by TLS + // can be found in: + // draft-ietf-tls-compression-05.txt (http://www.ietf.org/internet-drafts/draft-ietf-tls-compression-05.txt) + public enum TlsCompressionMethod : byte + { + None = 0, + Zlib = 1 + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsContentType.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsContentType.cs index a6472f67e0a..58f63c317c1 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsContentType.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsContentType.cs @@ -1,36 +1,36 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; - -namespace Mono.Security.Protocol.Tls -{ - internal enum TlsContentType : byte - { - ChangeCipherSpec = 20, - Alert = 21, - Handshake = 22, - ApplicationData = 23, - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; + +namespace Mono.Security.Protocol.Tls +{ + internal enum TlsContentType : byte + { + ChangeCipherSpec = 20, + Alert = 21, + Handshake = 22, + ApplicationData = 23, + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsException.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsException.cs index 81cdfe97306..adbac8e0d05 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsException.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsException.cs @@ -1,52 +1,52 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Text; -using System.Runtime.Serialization; - -using Mono.Security.Protocol.Tls.Alerts; - -namespace Mono.Security.Protocol.Tls -{ - [Serializable] - public sealed class TlsException : Exception - { - #region CONSTRUCTORS - - internal TlsException(string message) : base(message) - { - } - - internal TlsException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } - - internal TlsException(string message, Exception ex) : base(message, ex) - { - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Text; +using System.Runtime.Serialization; + +using Mono.Security.Protocol.Tls.Alerts; + +namespace Mono.Security.Protocol.Tls +{ + [Serializable] + public sealed class TlsException : Exception + { + #region CONSTRUCTORS + + internal TlsException(string message) : base(message) + { + } + + internal TlsException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + + internal TlsException(string message, Exception ex) : base(message, ex) + { + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs index 2d8766c7188..e30730eaf87 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsNetworkStream.cs @@ -1,369 +1,369 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.IO; -using System.Net; -using System.Net.Sockets; - -namespace Mono.Security.Protocol.Tls -{ - public class TlsNetworkStream : Stream, IDisposable - { - #region PROPERTIES - - private TlsSocket socket; - private bool ownsSocket; - private bool canRead; - private bool canWrite; - private bool disposed; - - #endregion - - #region PROPERTIES - - public override bool CanRead - { - get { return canRead; } - } - - public override bool CanSeek - { - get { return false; } - } - - public override bool CanWrite - { - get { return canWrite; } - } - - public override long Length - { - get { throw new NotSupportedException(); } - } - - public override long Position - { - get { throw new NotSupportedException(); } - set { throw new NotSupportedException(); } - - } - - public bool DataAvailable - { - get - { - if (socket == null) - { - throw new IOException(); - } - - if (this.socket.Session.IsSecure) - { - if ((this.socket.InputBuffer.Length - this.socket.InputBuffer.Position) > 0) - { - return true; - } - } - - // If there are bytes in the socket buffer return true - // otherwise false - return this.socket.Available != 0; - } - } - - #endregion - - #region DESTRUCTOR - - ~TlsNetworkStream() - { - this.Dispose(false); - } - - #endregion - - #region IDISPOSABLE - - void IDisposable.Dispose() - { - this.Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (!disposed) - { - if (disposing) - { - if (this.socket != null) - { - if (this.ownsSocket) - { - try - { - this.socket.Shutdown(SocketShutdown.Both); - } - catch{} - finally - { - this.socket.Close(); - } - } - } - this.ownsSocket = false; - this.canRead = false; - this.canWrite = false; - this.socket = null; - } - - disposed = true; - } - } - - #endregion - - #region PROTECTED_PROPERTIES - - protected bool Readable - { - get { return this.canRead; } - set { this.canRead = value;} - } - - protected TlsSocket Socket - { - get { return socket; } - } - - protected bool Writeable - { - get { return this.canWrite; } - set { this.canWrite = value; } - } - - #endregion - - #region CONSTRUCTORS - - public TlsNetworkStream(TlsSocket socket) - : this(socket, FileAccess.ReadWrite, false) - { - } - - public TlsNetworkStream(TlsSocket socket, bool ownsSocket) - : this(socket, FileAccess.ReadWrite, ownsSocket) - { - } - - public TlsNetworkStream(TlsSocket socket, FileAccess access) - : this(socket, FileAccess.ReadWrite, false) - { - } - - public TlsNetworkStream(TlsSocket socket, FileAccess access, bool ownsSocket) - { - if (socket == null) - { - throw new ArgumentNullException("socket is a null reference."); - } - if (!socket.Blocking) - { - throw new IOException("socket is in a nonblocking state."); - } - if (socket.SocketType != SocketType.Stream) - { - throw new IOException("The SocketType property of socket is not SocketType.Stream."); - } - if (!socket.Connected) - { - throw new IOException("socket is not connected."); - } - - this.socket = socket; - this.ownsSocket = ownsSocket; - switch (access) - { - case FileAccess.Read: - this.canRead = true; - break; - - case FileAccess.ReadWrite: - this.canRead = true; - this.canWrite = true; - break; - - case FileAccess.Write: - this.canWrite = true; - break; - } - } - - #endregion - - #region METHODS - - public override IAsyncResult BeginRead( - byte[] buffer, - int offset, - int count, - AsyncCallback callback, - object state) - { - throw new NotSupportedException(); - } - - public override IAsyncResult BeginWrite( - byte[] buffer, - int offset, - int count, - AsyncCallback callback, - object state) - { - throw new NotSupportedException(); - } - - public override int EndRead(IAsyncResult asyncResult) - { - throw new NotSupportedException(); - } - - public override void EndWrite(IAsyncResult asyncResult) - { - throw new NotSupportedException(); - } - - public override void Close() - { - ((IDisposable)this).Dispose(); - } - - public override void Flush() - { - } - - public override int Read(byte[] buffer, int offset, int size) - { - if (buffer == null) - { - throw new ArgumentNullException("buffer is a null reference."); - } - if (offset < 0) - { - throw new ArgumentOutOfRangeException("offset is less than 0."); - } - if (offset > buffer.Length) - { - throw new ArgumentOutOfRangeException("offset is greater than the length of buffer."); - } - if (size < 0) - { - throw new ArgumentOutOfRangeException("size is less than 0."); - } - if (size > (buffer.Length - offset)) - { - throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter."); - } - if (disposed) - { - throw new ObjectDisposedException("The NetworkStream is closed."); - } - if (!socket.Connected) - { - throw new IOException("The underlying Socket is closed."); - } - - try - { - return socket.Receive(buffer, offset, size, SocketFlags.None); - } - catch (TlsException ex) - { - throw ex; - } - catch (Exception ex) - { - throw new IOException("IO exception during read.", ex); - } - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public override void Write(byte[] buffer, int offset, int size) - { - if (buffer == null) - { - throw new ArgumentNullException("buffer is a null reference."); - } - if (offset < 0) - { - throw new ArgumentOutOfRangeException("offset is less than 0."); - } - if (offset > buffer.Length) - { - throw new ArgumentOutOfRangeException("offset is greater than the length of buffer."); - } - if (size < 0) - { - throw new ArgumentOutOfRangeException("size is less than 0."); - } - if (size > (buffer.Length - offset)) - { - throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter."); - } - if (disposed) - { - throw new ObjectDisposedException("The NetworkStream is closed."); - } - if (!socket.Connected) - { - throw new IOException("The underlying Socket is closed."); - } - - try - { - socket.Send(buffer, offset, size, SocketFlags.None); - } - catch (TlsException ex) - { - throw ex; - } - catch (Exception ex) - { - throw new IOException("IO exception during Write.", ex); - } - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; + +namespace Mono.Security.Protocol.Tls +{ + public class TlsNetworkStream : Stream, IDisposable + { + #region PROPERTIES + + private TlsSocket socket; + private bool ownsSocket; + private bool canRead; + private bool canWrite; + private bool disposed; + + #endregion + + #region PROPERTIES + + public override bool CanRead + { + get { return canRead; } + } + + public override bool CanSeek + { + get { return false; } + } + + public override bool CanWrite + { + get { return canWrite; } + } + + public override long Length + { + get { throw new NotSupportedException(); } + } + + public override long Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + + } + + public bool DataAvailable + { + get + { + if (socket == null) + { + throw new IOException(); + } + + if (this.socket.Session.IsSecure) + { + if ((this.socket.InputBuffer.Length - this.socket.InputBuffer.Position) > 0) + { + return true; + } + } + + // If there are bytes in the socket buffer return true + // otherwise false + return this.socket.Available != 0; + } + } + + #endregion + + #region DESTRUCTOR + + ~TlsNetworkStream() + { + this.Dispose(false); + } + + #endregion + + #region IDISPOSABLE + + void IDisposable.Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposed) + { + if (disposing) + { + if (this.socket != null) + { + if (this.ownsSocket) + { + try + { + this.socket.Shutdown(SocketShutdown.Both); + } + catch{} + finally + { + this.socket.Close(); + } + } + } + this.ownsSocket = false; + this.canRead = false; + this.canWrite = false; + this.socket = null; + } + + disposed = true; + } + } + + #endregion + + #region PROTECTED_PROPERTIES + + protected bool Readable + { + get { return this.canRead; } + set { this.canRead = value;} + } + + protected TlsSocket Socket + { + get { return socket; } + } + + protected bool Writeable + { + get { return this.canWrite; } + set { this.canWrite = value; } + } + + #endregion + + #region CONSTRUCTORS + + public TlsNetworkStream(TlsSocket socket) + : this(socket, FileAccess.ReadWrite, false) + { + } + + public TlsNetworkStream(TlsSocket socket, bool ownsSocket) + : this(socket, FileAccess.ReadWrite, ownsSocket) + { + } + + public TlsNetworkStream(TlsSocket socket, FileAccess access) + : this(socket, FileAccess.ReadWrite, false) + { + } + + public TlsNetworkStream(TlsSocket socket, FileAccess access, bool ownsSocket) + { + if (socket == null) + { + throw new ArgumentNullException("socket is a null reference."); + } + if (!socket.Blocking) + { + throw new IOException("socket is in a nonblocking state."); + } + if (socket.SocketType != SocketType.Stream) + { + throw new IOException("The SocketType property of socket is not SocketType.Stream."); + } + if (!socket.Connected) + { + throw new IOException("socket is not connected."); + } + + this.socket = socket; + this.ownsSocket = ownsSocket; + switch (access) + { + case FileAccess.Read: + this.canRead = true; + break; + + case FileAccess.ReadWrite: + this.canRead = true; + this.canWrite = true; + break; + + case FileAccess.Write: + this.canWrite = true; + break; + } + } + + #endregion + + #region METHODS + + public override IAsyncResult BeginRead( + byte[] buffer, + int offset, + int count, + AsyncCallback callback, + object state) + { + throw new NotSupportedException(); + } + + public override IAsyncResult BeginWrite( + byte[] buffer, + int offset, + int count, + AsyncCallback callback, + object state) + { + throw new NotSupportedException(); + } + + public override int EndRead(IAsyncResult asyncResult) + { + throw new NotSupportedException(); + } + + public override void EndWrite(IAsyncResult asyncResult) + { + throw new NotSupportedException(); + } + + public override void Close() + { + ((IDisposable)this).Dispose(); + } + + public override void Flush() + { + } + + public override int Read(byte[] buffer, int offset, int size) + { + if (buffer == null) + { + throw new ArgumentNullException("buffer is a null reference."); + } + if (offset < 0) + { + throw new ArgumentOutOfRangeException("offset is less than 0."); + } + if (offset > buffer.Length) + { + throw new ArgumentOutOfRangeException("offset is greater than the length of buffer."); + } + if (size < 0) + { + throw new ArgumentOutOfRangeException("size is less than 0."); + } + if (size > (buffer.Length - offset)) + { + throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter."); + } + if (disposed) + { + throw new ObjectDisposedException("The NetworkStream is closed."); + } + if (!socket.Connected) + { + throw new IOException("The underlying Socket is closed."); + } + + try + { + return socket.Receive(buffer, offset, size, SocketFlags.None); + } + catch (TlsException ex) + { + throw ex; + } + catch (Exception ex) + { + throw new IOException("IO exception during read.", ex); + } + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int size) + { + if (buffer == null) + { + throw new ArgumentNullException("buffer is a null reference."); + } + if (offset < 0) + { + throw new ArgumentOutOfRangeException("offset is less than 0."); + } + if (offset > buffer.Length) + { + throw new ArgumentOutOfRangeException("offset is greater than the length of buffer."); + } + if (size < 0) + { + throw new ArgumentOutOfRangeException("size is less than 0."); + } + if (size > (buffer.Length - offset)) + { + throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter."); + } + if (disposed) + { + throw new ObjectDisposedException("The NetworkStream is closed."); + } + if (!socket.Connected) + { + throw new IOException("The underlying Socket is closed."); + } + + try + { + socket.Send(buffer, offset, size, SocketFlags.None); + } + catch (TlsException ex) + { + throw ex; + } + catch (Exception ex) + { + throw new IOException("IO exception during Write.", ex); + } + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs index 10e41c91cb2..4315a1e2c5d 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsProtocol.cs @@ -1,34 +1,34 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; - -namespace Mono.Security.Protocol.Tls -{ - public enum TlsProtocol : short - { - Tls1 = (0x03 << 8) | 0x01, - Ssl3 = (0x03 << 8) | 0x00 - } +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; + +namespace Mono.Security.Protocol.Tls +{ + public enum TlsProtocol : short + { + Tls1 = (0x03 << 8) | 0x01, + Ssl3 = (0x03 << 8) | 0x00 + } } \ No newline at end of file diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsServerSettings.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsServerSettings.cs index 316f9ab2da8..737c990ed38 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsServerSettings.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsServerSettings.cs @@ -1,101 +1,101 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Security.Cryptography; - -using Mono.Security.X509; -using Mono.Security.Protocol.Tls.Handshake; - -namespace Mono.Security.Protocol.Tls -{ - internal class TlsServerSettings - { - #region FIELDS - - private X509CertificateCollection serverCertificates; - private bool serverKeyExchange; - private bool certificateRequest; - private TlsClientCertificateType[] certificateTypes; - private string[] distinguisedNames; - private RSAParameters rsaParameters; - private byte[] signedParams; - - #endregion - - #region PROPERTIES - - public bool ServerKeyExchange - { - get { return serverKeyExchange; } - set { serverKeyExchange = value; } - } - - public RSAParameters RsaParameters - { - get { return rsaParameters; } - set { rsaParameters = value; } - } - - public byte[] SignedParams - { - get { return signedParams; } - set { signedParams = value; } - } - - public bool CertificateRequest - { - get { return certificateRequest; } - set { certificateRequest = value; } - } - - public TlsClientCertificateType[] CertificateTypes - { - get { return certificateTypes; } - set { certificateTypes = value; } - } - - public string[] DistinguisedNames - { - get { return distinguisedNames; } - set { distinguisedNames = value; } - } - - public X509CertificateCollection ServerCertificates - { - get { return serverCertificates; } - set { serverCertificates = value; } - } - - #endregion - - #region CONSTRUCTORS - - public TlsServerSettings() - { - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Security.Cryptography; + +using Mono.Security.X509; +using Mono.Security.Protocol.Tls.Handshake; + +namespace Mono.Security.Protocol.Tls +{ + internal class TlsServerSettings + { + #region FIELDS + + private X509CertificateCollection serverCertificates; + private bool serverKeyExchange; + private bool certificateRequest; + private TlsClientCertificateType[] certificateTypes; + private string[] distinguisedNames; + private RSAParameters rsaParameters; + private byte[] signedParams; + + #endregion + + #region PROPERTIES + + public bool ServerKeyExchange + { + get { return serverKeyExchange; } + set { serverKeyExchange = value; } + } + + public RSAParameters RsaParameters + { + get { return rsaParameters; } + set { rsaParameters = value; } + } + + public byte[] SignedParams + { + get { return signedParams; } + set { signedParams = value; } + } + + public bool CertificateRequest + { + get { return certificateRequest; } + set { certificateRequest = value; } + } + + public TlsClientCertificateType[] CertificateTypes + { + get { return certificateTypes; } + set { certificateTypes = value; } + } + + public string[] DistinguisedNames + { + get { return distinguisedNames; } + set { distinguisedNames = value; } + } + + public X509CertificateCollection ServerCertificates + { + get { return serverCertificates; } + set { serverCertificates = value; } + } + + #endregion + + #region CONSTRUCTORS + + public TlsServerSettings() + { + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs index c0cd2adfcf7..1303c7c3b80 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs @@ -1,265 +1,265 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.IO; -using System.Collections; -using System.Text; -using System.Net; -using System.Net.Sockets; -using System.Security.Cryptography; - -using Mono.Security.Protocol.Tls.Alerts; - -namespace Mono.Security.Protocol.Tls -{ - public sealed class TlsSession - { - #region EVENTS - - public event TlsWarningAlertEventHandler WarningAlert; - - #endregion - - #region FIELDS - - private byte[] sessionId; - private TlsSessionContext context; - private TlsSessionSettings settings; - private TlsSocket socket; - private TlsNetworkStream networkStream; - private bool isSecure; - private TlsSessionState state; - - #endregion - - #region PROPERTIES - - public byte[] SessionId - { - get { return sessionId; } - } - - public TlsNetworkStream NetworkStream - { - get { return networkStream; } - } - - public TlsSessionState State - { - get { return state; } - } - - #endregion - - #region INTERNAL_PROPERTIES - - internal TlsSessionContext Context - { - get { return context; } - } - - internal bool IsSecure - { - get { return isSecure; } - set { isSecure = value; } - } - - internal TlsSessionSettings Settings - { - get { return settings; } - } - - #endregion - - #region CONSTRUCTORS - - public TlsSession(TlsSessionSettings settings) - { - this.settings = settings; - this.context = new TlsSessionContext(); - this.sessionId = new byte[0]; - - // Initialize socket for connection - this.initializeSocket(); - } - - #endregion - - #region EXCEPTION_METHODS - - internal TlsException CreateException(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc) - { - return CreateException(TlsAlert.GetAlertMessage(alertDesc)); - } - - internal TlsException CreateException(string format, params object[] args) - { - StringBuilder message = new StringBuilder(); - message.AppendFormat(format, args); - - return CreateException(message.ToString()); - } - - internal TlsException CreateException(string message) - { - this.state = TlsSessionState.Broken; - - // Throw an exception will made the connection unavailable - // for this both streams will be closed - closeStreams(); - - return new TlsException(message); - } - - #endregion - - #region METHODS - - public void Open() - { - try - { - this.context.Protocol = settings.Protocol; - this.context.CompressionMethod = settings.CompressionMethod; - this.context.SupportedCiphers = TlsCipherSuiteFactory.GetSupportedCiphers(context.Protocol); - this.state = TlsSessionState.OpeningSecure; - this.socket.DoHandshake(); - this.state = TlsSessionState.OpenSecure; - } - catch (TlsException ex) - { - this.state = TlsSessionState.Broken; - throw ex; - } - catch (Exception ex) - { - this.state = TlsSessionState.Broken; - this.closeStreams(); - throw ex; - } - } - - public void Close() - { - try - { - this.state = TlsSessionState.Closing; - - if (isSecure) - { - TlsCloseNotifyAlert alert = new TlsCloseNotifyAlert(this); - - // Write close notify - this.socket.SendAlert(alert); - - // Check that the session is finished by the client and by server - if (!this.context.ConnectionEnd) - { - throw new TlsException("Invalid session termination"); - } - } - } - catch (Exception ex) - { - this.state = TlsSessionState.Broken; - throw ex; - } - finally - { - // Close streams - closeStreams(); - - this.state = TlsSessionState.Closed; - } - } - - #endregion - - #region INTERNAL_METHODS - - internal void RaiseWarningAlert(TlsAlertLevel level, TlsAlertDescription description) - { - if (WarningAlert != null) - { - WarningAlert(this, new TlsWarningAlertEventArgs(level, description)); - } - } - - internal void SetSessionId(byte[] sessionId) - { - this.sessionId = sessionId; - } - - #endregion - - #region PRIVATE_METHODS - - private void initializeSocket() - { - try - { - this.state = TlsSessionState.Opening; - - // Initialize socket - IPAddress hostadd = Dns.Resolve(settings.ServerName).AddressList[0]; - IPEndPoint EPhost = new IPEndPoint(hostadd, settings.ServerPort); - - // Create the socket - socket = new TlsSocket( - this, - AddressFamily.InterNetwork, - SocketType.Stream, - ProtocolType.IP); - - // Make the socket to connect to the Server - socket.Connect(EPhost); - networkStream = new TlsNetworkStream(socket, true); - - this.state = TlsSessionState.Open; - } - catch (Exception ex) - { - this.state = TlsSessionState.Broken; - throw ex; - } - } - - private void closeStreams() - { - // Reset session state - this.context.IsActual = false; - - // Close the socket and the networkStream - this.networkStream.Close(); - - // Reset session information - this.isSecure = false; - this.context = new TlsSessionContext(); - this.sessionId = new byte[0]; - } - - #endregion - } +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.IO; +using System.Collections; +using System.Text; +using System.Net; +using System.Net.Sockets; +using System.Security.Cryptography; + +using Mono.Security.Protocol.Tls.Alerts; + +namespace Mono.Security.Protocol.Tls +{ + public sealed class TlsSession + { + #region EVENTS + + public event TlsWarningAlertEventHandler WarningAlert; + + #endregion + + #region FIELDS + + private byte[] sessionId; + private TlsSessionContext context; + private TlsSessionSettings settings; + private TlsSocket socket; + private TlsNetworkStream networkStream; + private bool isSecure; + private TlsSessionState state; + + #endregion + + #region PROPERTIES + + public byte[] SessionId + { + get { return sessionId; } + } + + public TlsNetworkStream NetworkStream + { + get { return networkStream; } + } + + public TlsSessionState State + { + get { return state; } + } + + #endregion + + #region INTERNAL_PROPERTIES + + internal TlsSessionContext Context + { + get { return context; } + } + + internal bool IsSecure + { + get { return isSecure; } + set { isSecure = value; } + } + + internal TlsSessionSettings Settings + { + get { return settings; } + } + + #endregion + + #region CONSTRUCTORS + + public TlsSession(TlsSessionSettings settings) + { + this.settings = settings; + this.context = new TlsSessionContext(); + this.sessionId = new byte[0]; + + // Initialize socket for connection + this.initializeSocket(); + } + + #endregion + + #region EXCEPTION_METHODS + + internal TlsException CreateException(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc) + { + return CreateException(TlsAlert.GetAlertMessage(alertDesc)); + } + + internal TlsException CreateException(string format, params object[] args) + { + StringBuilder message = new StringBuilder(); + message.AppendFormat(format, args); + + return CreateException(message.ToString()); + } + + internal TlsException CreateException(string message) + { + this.state = TlsSessionState.Broken; + + // Throw an exception will made the connection unavailable + // for this both streams will be closed + closeStreams(); + + return new TlsException(message); + } + + #endregion + + #region METHODS + + public void Open() + { + try + { + this.context.Protocol = settings.Protocol; + this.context.CompressionMethod = settings.CompressionMethod; + this.context.SupportedCiphers = TlsCipherSuiteFactory.GetSupportedCiphers(context.Protocol); + this.state = TlsSessionState.OpeningSecure; + this.socket.DoHandshake(); + this.state = TlsSessionState.OpenSecure; + } + catch (TlsException ex) + { + this.state = TlsSessionState.Broken; + throw ex; + } + catch (Exception ex) + { + this.state = TlsSessionState.Broken; + this.closeStreams(); + throw ex; + } + } + + public void Close() + { + try + { + this.state = TlsSessionState.Closing; + + if (isSecure) + { + TlsCloseNotifyAlert alert = new TlsCloseNotifyAlert(this); + + // Write close notify + this.socket.SendAlert(alert); + + // Check that the session is finished by the client and by server + if (!this.context.ConnectionEnd) + { + throw new TlsException("Invalid session termination"); + } + } + } + catch (Exception ex) + { + this.state = TlsSessionState.Broken; + throw ex; + } + finally + { + // Close streams + closeStreams(); + + this.state = TlsSessionState.Closed; + } + } + + #endregion + + #region INTERNAL_METHODS + + internal void RaiseWarningAlert(TlsAlertLevel level, TlsAlertDescription description) + { + if (WarningAlert != null) + { + WarningAlert(this, new TlsWarningAlertEventArgs(level, description)); + } + } + + internal void SetSessionId(byte[] sessionId) + { + this.sessionId = sessionId; + } + + #endregion + + #region PRIVATE_METHODS + + private void initializeSocket() + { + try + { + this.state = TlsSessionState.Opening; + + // Initialize socket + IPAddress hostadd = Dns.Resolve(settings.ServerName).AddressList[0]; + IPEndPoint EPhost = new IPEndPoint(hostadd, settings.ServerPort); + + // Create the socket + socket = new TlsSocket( + this, + AddressFamily.InterNetwork, + SocketType.Stream, + ProtocolType.IP); + + // Make the socket to connect to the Server + socket.Connect(EPhost); + networkStream = new TlsNetworkStream(socket, true); + + this.state = TlsSessionState.Open; + } + catch (Exception ex) + { + this.state = TlsSessionState.Broken; + throw ex; + } + } + + private void closeStreams() + { + // Reset session state + this.context.IsActual = false; + + // Close the socket and the networkStream + this.networkStream.Close(); + + // Reset session information + this.isSecure = false; + this.context = new TlsSessionContext(); + this.sessionId = new byte[0]; + } + + #endregion + } } \ No newline at end of file diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs index cc6d72f0470..c9e85cee0d2 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs @@ -1,289 +1,289 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Text; -using System.Security.Cryptography; - -using Mono.Security.Cryptography; -using Mono.Security.Protocol.Tls.Handshake; - -namespace Mono.Security.Protocol.Tls -{ - internal class TlsSessionContext - { - #region FIELDS - - // Protocol version - private TlsProtocol protocol; - - // Compression method - private TlsCompressionMethod compressionMethod; - - // Information sent and request by the server in the Handshake protocol - private TlsServerSettings serverSettings; - - // Cipher suite information - private CipherSuite cipher; - private TlsCipherSuiteCollection supportedCiphers; - - // Misc - private bool isActual; - private bool helloDone; - private bool handshakeFinished; - private bool connectionEnd; - - // Sequence numbers - private long writeSequenceNumber; - private long readSequenceNumber; - - // Random data - private byte[] clientRandom; - private byte[] serverRandom; - private byte[] randomCS; - private byte[] randomSC; - - // Key information - private byte[] masterSecret; - private byte[] clientWriteMAC; - private byte[] serverWriteMAC; - private byte[] clientWriteKey; - private byte[] serverWriteKey; - private byte[] clientWriteIV; - private byte[] serverWriteIV; - - // Handshake hashes - private TlsStream handshakeMessages; - - #endregion - - #region INTERNAL_CONSTANTS - - internal const short MAX_FRAGMENT_SIZE = 16384; // 2^14 - - #endregion - - #region PROPERTIES - - public TlsProtocol Protocol - { - get { return this.protocol; } - set { this.protocol = value; } - } - - public TlsCompressionMethod CompressionMethod - { - get { return this.compressionMethod; } - set { this.compressionMethod = value; } - } - - public TlsServerSettings ServerSettings - { - get { return this.serverSettings; } - set { this.serverSettings = value; } - } - - public bool IsActual - { - get { return this.isActual; } - set { this.isActual = value; } - } - - public bool HelloDone - { - get { return helloDone; } - set { helloDone = value; } - } - - public bool HandshakeFinished - { - get { return handshakeFinished; } - set { handshakeFinished = value; } - } - - public bool ConnectionEnd - { - get { return this.connectionEnd; } - set { this.connectionEnd = value; } - } - - public CipherSuite Cipher - { - get { return this.cipher; } - set { this.cipher = value; } - } - - public TlsCipherSuiteCollection SupportedCiphers - { - get { return supportedCiphers; } - set { supportedCiphers = value; } - } - - public TlsStream HandshakeMessages - { - get { return this.handshakeMessages; } - } - - public long WriteSequenceNumber - { - get { return this.writeSequenceNumber; } - set { this.writeSequenceNumber = value; } - } - - public long ReadSequenceNumber - { - get { return this.readSequenceNumber; } - set { this.readSequenceNumber = value; } - } - - public byte[] ClientRandom - { - get { return this.clientRandom; } - set { this.clientRandom = value; } - } - - public byte[] ServerRandom - { - get { return this.serverRandom; } - set { this.serverRandom = value; } - } - - public byte[] RandomCS - { - get { return this.randomCS; } - set { this.randomCS = value; } - } - - public byte[] RandomSC - { - get { return this.randomSC; } - set { this.randomSC = value; } - } - - public byte[] MasterSecret - { - get { return this.masterSecret; } - set { this.masterSecret = value; } - } - - public byte[] ClientWriteMAC - { - get { return this.clientWriteMAC; } - set { this.clientWriteMAC = value; } - } - - public byte[] ServerWriteMAC - { - get { return this.serverWriteMAC; } - set { this.serverWriteMAC = value; } - } - - public byte[] ClientWriteKey - { - get { return this.clientWriteKey; } - set { this.clientWriteKey = value; } - } - - public byte[] ServerWriteKey - { - get { return this.serverWriteKey; } - set { this.serverWriteKey = value; } - } - - public byte[] ClientWriteIV - { - get { return this.clientWriteIV; } - set { this.clientWriteIV = value; } - } - - public byte[] ServerWriteIV - { - get { return this.serverWriteIV; } - set { this.serverWriteIV = value; } - } - - #endregion - - #region CONSTRUCTORS - - public TlsSessionContext() - { - this.protocol = TlsProtocol.Tls1; - this.compressionMethod = TlsCompressionMethod.None; - this.serverSettings = new TlsServerSettings(); - this.handshakeMessages = new TlsStream(); - } - - #endregion - - #region METHODS - - public int GetUnixTime() - { - DateTime now = DateTime.Now.ToUniversalTime(); - TimeSpan unixTime = now.Subtract(new DateTime(1970, 1, 1)); - - return (int)unixTime.TotalSeconds; - } - - public byte[] GetSecureRandomBytes(int count) - { - byte[] secureBytes = new byte[count]; - - RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); - rng.GetNonZeroBytes(secureBytes); - - return secureBytes; - } - - public void ClearKeyInfo() - { - // Clear Master Secret - this.masterSecret = null; - - // Clear client and server random - this.clientRandom = null; - this.serverRandom = null; - this.randomCS = null; - this.randomSC = null; - - // Clear client keys - this.clientWriteKey = null; - this.clientWriteIV = null; - - // Clear server keys - this.serverWriteKey = null; - this.serverWriteIV = null; - - // Clear MAC keys if protocol is different than Ssl3 - if (this.protocol != TlsProtocol.Ssl3) - { - this.clientWriteMAC = null; - this.serverWriteMAC = null; - } - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Text; +using System.Security.Cryptography; + +using Mono.Security.Cryptography; +using Mono.Security.Protocol.Tls.Handshake; + +namespace Mono.Security.Protocol.Tls +{ + internal class TlsSessionContext + { + #region FIELDS + + // Protocol version + private TlsProtocol protocol; + + // Compression method + private TlsCompressionMethod compressionMethod; + + // Information sent and request by the server in the Handshake protocol + private TlsServerSettings serverSettings; + + // Cipher suite information + private CipherSuite cipher; + private TlsCipherSuiteCollection supportedCiphers; + + // Misc + private bool isActual; + private bool helloDone; + private bool handshakeFinished; + private bool connectionEnd; + + // Sequence numbers + private long writeSequenceNumber; + private long readSequenceNumber; + + // Random data + private byte[] clientRandom; + private byte[] serverRandom; + private byte[] randomCS; + private byte[] randomSC; + + // Key information + private byte[] masterSecret; + private byte[] clientWriteMAC; + private byte[] serverWriteMAC; + private byte[] clientWriteKey; + private byte[] serverWriteKey; + private byte[] clientWriteIV; + private byte[] serverWriteIV; + + // Handshake hashes + private TlsStream handshakeMessages; + + #endregion + + #region INTERNAL_CONSTANTS + + internal const short MAX_FRAGMENT_SIZE = 16384; // 2^14 + + #endregion + + #region PROPERTIES + + public TlsProtocol Protocol + { + get { return this.protocol; } + set { this.protocol = value; } + } + + public TlsCompressionMethod CompressionMethod + { + get { return this.compressionMethod; } + set { this.compressionMethod = value; } + } + + public TlsServerSettings ServerSettings + { + get { return this.serverSettings; } + set { this.serverSettings = value; } + } + + public bool IsActual + { + get { return this.isActual; } + set { this.isActual = value; } + } + + public bool HelloDone + { + get { return helloDone; } + set { helloDone = value; } + } + + public bool HandshakeFinished + { + get { return handshakeFinished; } + set { handshakeFinished = value; } + } + + public bool ConnectionEnd + { + get { return this.connectionEnd; } + set { this.connectionEnd = value; } + } + + public CipherSuite Cipher + { + get { return this.cipher; } + set { this.cipher = value; } + } + + public TlsCipherSuiteCollection SupportedCiphers + { + get { return supportedCiphers; } + set { supportedCiphers = value; } + } + + public TlsStream HandshakeMessages + { + get { return this.handshakeMessages; } + } + + public long WriteSequenceNumber + { + get { return this.writeSequenceNumber; } + set { this.writeSequenceNumber = value; } + } + + public long ReadSequenceNumber + { + get { return this.readSequenceNumber; } + set { this.readSequenceNumber = value; } + } + + public byte[] ClientRandom + { + get { return this.clientRandom; } + set { this.clientRandom = value; } + } + + public byte[] ServerRandom + { + get { return this.serverRandom; } + set { this.serverRandom = value; } + } + + public byte[] RandomCS + { + get { return this.randomCS; } + set { this.randomCS = value; } + } + + public byte[] RandomSC + { + get { return this.randomSC; } + set { this.randomSC = value; } + } + + public byte[] MasterSecret + { + get { return this.masterSecret; } + set { this.masterSecret = value; } + } + + public byte[] ClientWriteMAC + { + get { return this.clientWriteMAC; } + set { this.clientWriteMAC = value; } + } + + public byte[] ServerWriteMAC + { + get { return this.serverWriteMAC; } + set { this.serverWriteMAC = value; } + } + + public byte[] ClientWriteKey + { + get { return this.clientWriteKey; } + set { this.clientWriteKey = value; } + } + + public byte[] ServerWriteKey + { + get { return this.serverWriteKey; } + set { this.serverWriteKey = value; } + } + + public byte[] ClientWriteIV + { + get { return this.clientWriteIV; } + set { this.clientWriteIV = value; } + } + + public byte[] ServerWriteIV + { + get { return this.serverWriteIV; } + set { this.serverWriteIV = value; } + } + + #endregion + + #region CONSTRUCTORS + + public TlsSessionContext() + { + this.protocol = TlsProtocol.Tls1; + this.compressionMethod = TlsCompressionMethod.None; + this.serverSettings = new TlsServerSettings(); + this.handshakeMessages = new TlsStream(); + } + + #endregion + + #region METHODS + + public int GetUnixTime() + { + DateTime now = DateTime.Now.ToUniversalTime(); + TimeSpan unixTime = now.Subtract(new DateTime(1970, 1, 1)); + + return (int)unixTime.TotalSeconds; + } + + public byte[] GetSecureRandomBytes(int count) + { + byte[] secureBytes = new byte[count]; + + RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); + rng.GetNonZeroBytes(secureBytes); + + return secureBytes; + } + + public void ClearKeyInfo() + { + // Clear Master Secret + this.masterSecret = null; + + // Clear client and server random + this.clientRandom = null; + this.serverRandom = null; + this.randomCS = null; + this.randomSC = null; + + // Clear client keys + this.clientWriteKey = null; + this.clientWriteIV = null; + + // Clear server keys + this.serverWriteKey = null; + this.serverWriteIV = null; + + // Clear MAC keys if protocol is different than Ssl3 + if (this.protocol != TlsProtocol.Ssl3) + { + this.clientWriteMAC = null; + this.serverWriteMAC = null; + } + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs index 72d716fa7cd..7614e99f207 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs @@ -1,218 +1,218 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Text; -using System.Security.Cryptography.X509Certificates; - -namespace Mono.Security.Protocol.Tls -{ - public sealed class TlsSessionSettings - { - #region FIELDS - - private string serverName; - private int serverPort; - private Encoding encoding; - private TlsProtocol protocol; - private TlsCompressionMethod compressionMethod; - private X509CertificateCollection certificates; - - #endregion - - #region PROPERTIES - - public string ServerName - { - get { return serverName; } - set { serverName = value; } - } - - public int ServerPort - { - get { return serverPort; } - set { serverPort = value; } - } - - public Encoding Encoding - { - get { return encoding; } - set { encoding = value; } - } - - public TlsProtocol Protocol - { - get { return protocol; } - set - { - if (value != TlsProtocol.Tls1 && - value != TlsProtocol.Ssl3) - { - throw new NotSupportedException("Specified protocol is not supported"); - } - protocol = value; - } - } - - public TlsCompressionMethod CompressionMethod - { - get { return compressionMethod; } - set - { - if (value != TlsCompressionMethod.None) - { - throw new NotSupportedException("Specified compression method is not supported"); - } - compressionMethod = value; - } - } - - public X509CertificateCollection Certificates - { - get { return certificates; } - set { certificates = value; } - } - - #endregion - - #region CONSTRUCTORS - - public TlsSessionSettings() - { - this.protocol = TlsProtocol.Tls1; - this.compressionMethod = TlsCompressionMethod.None; - this.certificates = new X509CertificateCollection(); - this.serverName = "localhost"; - this.serverPort = 443; - this.encoding = Encoding.Default; - } - - public TlsSessionSettings(TlsProtocol protocol) : this() - { - this.Protocol = protocol; - } - - public TlsSessionSettings(TlsProtocol protocol, Encoding encoding) : this(protocol) - { - this.encoding = encoding; - } - - public TlsSessionSettings(string serverName) : this() - { - this.serverName = serverName; - } - - public TlsSessionSettings(string serverName, Encoding encoding) : this() - { - this.serverName = serverName; - this.encoding = encoding; - } - - public TlsSessionSettings(string serverName, int serverPort) : this() - { - this.serverName = serverName; - this.serverPort = serverPort; - } - - public TlsSessionSettings(string serverName, int serverPort, Encoding encoding) : this() - { - this.serverName = serverName; - this.serverPort = serverPort; - this.encoding = encoding; - } - - public TlsSessionSettings(TlsProtocol protocol, string serverName) : this(protocol) - { - this.serverName = serverName; - } - - public TlsSessionSettings(TlsProtocol protocol, string serverName, Encoding encoding) : this(protocol) - { - this.serverName = serverName; - this.encoding = encoding; - } - - - public TlsSessionSettings(TlsProtocol protocol, string serverName, int serverPort) : this(protocol) - { - this.serverName = serverName; - this.serverPort = serverPort; - } - - public TlsSessionSettings(TlsProtocol protocol, string serverName, int serverPort, Encoding encoding) : this(protocol) - { - this.serverName = serverName; - this.serverPort = serverPort; - this.encoding = encoding; - } - - public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates) : this(protocol) - { - this.certificates = certificates; - } - - public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, Encoding encoding) : this(protocol) - { - this.certificates = certificates; - this.encoding = encoding; - } - - public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, string serverName, int serverPort) : this(protocol) - { - this.certificates = certificates; - this.serverName = serverName; - this.serverPort = serverPort; - } - - public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, string serverName, int serverPort, Encoding encoding) : this(protocol) - { - this.certificates = certificates; - this.serverName = serverName; - this.serverPort = serverPort; - this.encoding = encoding; - } - - public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates) - : this(protocol, new X509CertificateCollection(certificates)) - { - } - - public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, Encoding encoding) - : this(protocol, new X509CertificateCollection(certificates), encoding) - { - } - - public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, string serverName, int serverPort) : - this(protocol, new X509CertificateCollection(certificates), serverName, serverPort) - { - } - - public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, string serverName, int serverPort, Encoding encoding) : - this(protocol, new X509CertificateCollection(certificates), serverName, serverPort, encoding) - { - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Text; +using System.Security.Cryptography.X509Certificates; + +namespace Mono.Security.Protocol.Tls +{ + public sealed class TlsSessionSettings + { + #region FIELDS + + private string serverName; + private int serverPort; + private Encoding encoding; + private TlsProtocol protocol; + private TlsCompressionMethod compressionMethod; + private X509CertificateCollection certificates; + + #endregion + + #region PROPERTIES + + public string ServerName + { + get { return serverName; } + set { serverName = value; } + } + + public int ServerPort + { + get { return serverPort; } + set { serverPort = value; } + } + + public Encoding Encoding + { + get { return encoding; } + set { encoding = value; } + } + + public TlsProtocol Protocol + { + get { return protocol; } + set + { + if (value != TlsProtocol.Tls1 && + value != TlsProtocol.Ssl3) + { + throw new NotSupportedException("Specified protocol is not supported"); + } + protocol = value; + } + } + + public TlsCompressionMethod CompressionMethod + { + get { return compressionMethod; } + set + { + if (value != TlsCompressionMethod.None) + { + throw new NotSupportedException("Specified compression method is not supported"); + } + compressionMethod = value; + } + } + + public X509CertificateCollection Certificates + { + get { return certificates; } + set { certificates = value; } + } + + #endregion + + #region CONSTRUCTORS + + public TlsSessionSettings() + { + this.protocol = TlsProtocol.Tls1; + this.compressionMethod = TlsCompressionMethod.None; + this.certificates = new X509CertificateCollection(); + this.serverName = "localhost"; + this.serverPort = 443; + this.encoding = Encoding.Default; + } + + public TlsSessionSettings(TlsProtocol protocol) : this() + { + this.Protocol = protocol; + } + + public TlsSessionSettings(TlsProtocol protocol, Encoding encoding) : this(protocol) + { + this.encoding = encoding; + } + + public TlsSessionSettings(string serverName) : this() + { + this.serverName = serverName; + } + + public TlsSessionSettings(string serverName, Encoding encoding) : this() + { + this.serverName = serverName; + this.encoding = encoding; + } + + public TlsSessionSettings(string serverName, int serverPort) : this() + { + this.serverName = serverName; + this.serverPort = serverPort; + } + + public TlsSessionSettings(string serverName, int serverPort, Encoding encoding) : this() + { + this.serverName = serverName; + this.serverPort = serverPort; + this.encoding = encoding; + } + + public TlsSessionSettings(TlsProtocol protocol, string serverName) : this(protocol) + { + this.serverName = serverName; + } + + public TlsSessionSettings(TlsProtocol protocol, string serverName, Encoding encoding) : this(protocol) + { + this.serverName = serverName; + this.encoding = encoding; + } + + + public TlsSessionSettings(TlsProtocol protocol, string serverName, int serverPort) : this(protocol) + { + this.serverName = serverName; + this.serverPort = serverPort; + } + + public TlsSessionSettings(TlsProtocol protocol, string serverName, int serverPort, Encoding encoding) : this(protocol) + { + this.serverName = serverName; + this.serverPort = serverPort; + this.encoding = encoding; + } + + public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates) : this(protocol) + { + this.certificates = certificates; + } + + public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, Encoding encoding) : this(protocol) + { + this.certificates = certificates; + this.encoding = encoding; + } + + public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, string serverName, int serverPort) : this(protocol) + { + this.certificates = certificates; + this.serverName = serverName; + this.serverPort = serverPort; + } + + public TlsSessionSettings(TlsProtocol protocol, X509CertificateCollection certificates, string serverName, int serverPort, Encoding encoding) : this(protocol) + { + this.certificates = certificates; + this.serverName = serverName; + this.serverPort = serverPort; + this.encoding = encoding; + } + + public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates) + : this(protocol, new X509CertificateCollection(certificates)) + { + } + + public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, Encoding encoding) + : this(protocol, new X509CertificateCollection(certificates), encoding) + { + } + + public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, string serverName, int serverPort) : + this(protocol, new X509CertificateCollection(certificates), serverName, serverPort) + { + } + + public TlsSessionSettings(TlsProtocol protocol, X509Certificate[] certificates, string serverName, int serverPort, Encoding encoding) : + this(protocol, new X509CertificateCollection(certificates), serverName, serverPort, encoding) + { + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionState.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionState.cs index efcd0746572..6856cd9bdd6 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionState.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionState.cs @@ -1,39 +1,39 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; - -namespace Mono.Security.Protocol.Tls -{ - public enum TlsSessionState - { - Broken, - Open, - Closed, - OpenSecure, - OpeningSecure, - Opening, - Closing - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; + +namespace Mono.Security.Protocol.Tls +{ + public enum TlsSessionState + { + Broken, + Open, + Closed, + OpenSecure, + OpeningSecure, + Opening, + Closing + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs index 1d798ad96f4..dce8206a683 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs @@ -1,664 +1,664 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.IO; -using System.Net; -using System.Collections; -using System.Net.Sockets; -using System.Security.Cryptography; - -using Mono.Security.Protocol.Tls; -using Mono.Security.Protocol.Tls.Alerts; -using Mono.Security.Protocol.Tls.Handshake; -using Mono.Security.Protocol.Tls.Handshake.Client; - -namespace Mono.Security.Protocol.Tls -{ - public sealed class TlsSocket : Socket - { - #region FIELDS - - private TlsSession session; - private BufferedStream inputBuffer; - - #endregion - - #region PROPERTIES - - internal TlsSession Session - { - get { return this.session; } - } - - internal BufferedStream InputBuffer - { - get { return this.inputBuffer; } - } - - #endregion - - #region CONSTRUCTORS - - private TlsSocket( - AddressFamily addressFamily, - SocketType socketType, - ProtocolType protocolType - ) : base(addressFamily, socketType, protocolType) - { - this.inputBuffer = new BufferedStream(new MemoryStream()); - } - - public TlsSocket( - TlsSession session, - AddressFamily addressFamily, - SocketType socketType, - ProtocolType protocolType - ) : this(addressFamily, socketType, protocolType) - { - this.session = session; - } - - #endregion - - #region REPLACED_METHODS - - public new void Close() - { - this.resetBuffer(); - base.Close(); - if (this.session.State != TlsSessionState.Closing && - this.session.State != TlsSessionState.Closed) - { - this.session.Close(); - } - } - - public new int Receive(byte[] buffer) - { - return this.Receive(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None); - } - - public new int Receive(byte[] buffer, SocketFlags socketFlags) - { - return this.Receive(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags); - } - - public new int Receive(byte[] buffer, int size, SocketFlags socketFlags) - { - return this.Receive(buffer, 0, size, socketFlags); - } - - public new int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags) - { - if (!this.session.IsSecure) - { - return base.Receive(buffer, offset, size, socketFlags); - } - - // If actual buffer is full readed reset it - if (this.inputBuffer.Position == this.inputBuffer.Length) - { - this.resetBuffer(); - } - - // Check if we have space in the middle buffer - // if not Read next TLS record and update the inputBuffer - while ((this.inputBuffer.Length - this.inputBuffer.Position) < size) - { - // Read next record and write it into the inputBuffer - long position = this.inputBuffer.Position; - byte[] record = this.receiveRecord(); - - if (record.Length > 0) - { - // Write new data to the inputBuffer - this.inputBuffer.Seek(0, SeekOrigin.End); - this.inputBuffer.Write(record, 0, record.Length); - - // Restore buffer position - this.inputBuffer.Seek(position, SeekOrigin.Begin); - } - - if (base.Available == 0) - { - break; - } - } - - return this.inputBuffer.Read(buffer, offset, size); - } - - public new int Send(byte[] buffer) - { - return this.Send(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None); - } - - public new int Send(byte[] buffer, SocketFlags socketFlags) - { - return this.Send(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags); - } - - public new int Send(byte[] buffer, int size, SocketFlags socketFlags) - { - return this.Send(buffer, 0, size, socketFlags); - } - - public new int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags) - { - if (!this.session.IsSecure) - { - return base.Send(buffer, offset, size, socketFlags); - } - - // Send the buffer as a TLS record - byte[] recordData = new byte[size]; - System.Array.Copy(buffer, offset, recordData, 0, size); - - return this.sendRecord(TlsContentType.ApplicationData, recordData); - } - - #endregion - - #region TLS_RECORD_METHODS - - private byte[] receiveRecord() - { - if (this.session.Context.ConnectionEnd) - { - throw this.session.CreateException("The session is finished and it's no longer valid."); - } - - TlsContentType contentType = (TlsContentType)this.ReadByte(); - TlsProtocol protocol = (TlsProtocol)this.ReadShort(); - short length = this.ReadShort(); - - // Read Record data - int received = 0; - byte[] buffer = new byte[length]; - while (received != length) - { - received += base.Receive( - buffer, received, buffer.Length - received, SocketFlags.None); - } - - TlsStream message = new TlsStream(buffer); - - // Check that the message has a valid protocol version - if (protocol != this.session.Context.Protocol) - { - throw session.CreateException("Invalid protocol version on message received from server"); - } - - // Decrypt message contents if needed - if (contentType == TlsContentType.Alert && length == 2) - { - } - else - { - if (session.Context.IsActual && - contentType != TlsContentType.ChangeCipherSpec) - { - message = this.decryptRecordFragment( - contentType, - protocol, - message.ToArray()); - } - } - - byte[] result = message.ToArray(); - - // Process record - switch (contentType) - { - case TlsContentType.Alert: - this.processAlert((TlsAlertLevel)message.ReadByte(), - (TlsAlertDescription)message.ReadByte()); - break; - - case TlsContentType.ChangeCipherSpec: - // Reset sequence numbers - this.session.Context.ReadSequenceNumber = 0; - break; - - case TlsContentType.ApplicationData: - break; - - case TlsContentType.Handshake: - while (!message.EOF) - { - this.processHandshakeMessage(message); - } - // Update handshakes of current messages - this.session.Context.HandshakeMessages.Write(message.ToArray()); - break; - - default: - throw session.CreateException("Unknown record received from server."); - } - - return result; - } - - #endregion - - #region TLS_CRYPTO_METHODS - - private byte[] encryptRecordFragment(TlsContentType contentType, byte[] fragment) - { - // Calculate message MAC - byte[] mac = this.session.Context.Cipher.ComputeClientRecordMAC(contentType, fragment); - - // Encrypt the message - byte[] ecr = this.session.Context.Cipher.EncryptRecord(fragment, mac); - - // Set new IV - if (this.session.Context.Cipher.CipherMode == CipherMode.CBC) - { - byte[] iv = new byte[this.session.Context.Cipher.IvSize]; - System.Array.Copy(ecr, ecr.Length - iv.Length, iv, 0, iv.Length); - this.session.Context.Cipher.UpdateClientCipherIV(iv); - } - - // Update sequence number - this.session.Context.WriteSequenceNumber++; - - return ecr; - } - - private TlsStream decryptRecordFragment(TlsContentType contentType, - TlsProtocol protocol, - byte[] fragment) - { - byte[] dcrFragment = null; - byte[] dcrMAC = null; - - // Decrypt message - this.session.Context.Cipher.DecryptRecord(fragment, ref dcrFragment, ref dcrMAC); - - // Set new IV - if (this.session.Context.Cipher.CipherMode == CipherMode.CBC) - { - byte[] iv = new byte[session.Context.Cipher.IvSize]; - System.Array.Copy(fragment, fragment.Length - iv.Length, iv, 0, iv.Length); - this.session.Context.Cipher.UpdateServerCipherIV(iv); - } - - // Check MAC code - byte[] mac = this.session.Context.Cipher.ComputeServerRecordMAC(contentType, dcrFragment); - - // Check that the mac is correct - if (mac.Length != dcrMAC.Length) - { - throw new TlsException("Invalid MAC received from server."); - } - for (int i = 0; i < mac.Length; i++) - { - if (mac[i] != dcrMAC[i]) - { - throw new TlsException("Invalid MAC received from server."); - } - } - - // Update sequence number - this.session.Context.ReadSequenceNumber++; - - return new TlsStream(dcrFragment); - } - - #endregion - - #region TLS_SEND_METHODS - - internal int SendAlert(TlsAlert alert) - { - // Write record - int bytesSent = this.sendRecord(TlsContentType.Alert, alert.ToArray()); - - // Update session - alert.UpdateSession(); - - // Reset message contents - alert.Reset(); - - return bytesSent; - } - - private int sendRecord(TlsHandshakeType type) - { - TlsHandshakeMessage msg = createClientHandshakeMessage(type); - - // Write record - int bytesSent = this.sendRecord(msg.ContentType, msg.EncodeMessage()); - - // Update session - msg.UpdateSession(); - - // Reset message contents - msg.Reset(); - - return bytesSent; - } - - private int sendChangeCipherSpec() - { - // Send Change Cipher Spec message - int bytesSent = this.sendRecord(TlsContentType.ChangeCipherSpec, new byte[] {1}); - - // Reset sequence numbers - this.session.Context.WriteSequenceNumber = 0; - - // Make the pending state to be the current state - this.session.Context.IsActual = true; - - // Send Finished message - bytesSent += this.sendRecord(TlsHandshakeType.Finished); - - return bytesSent; - } - - private int sendRecord(TlsContentType contentType, byte[] recordData) - { - if (this.session.Context.ConnectionEnd) - { - throw this.session.CreateException("The session is finished and it's no longer valid."); - } - - int bytesSent = 0; - byte[][] fragments = fragmentData(recordData); - for (int i = 0; i < fragments.Length; i++) - { - byte[] fragment = fragments[i]; - - if (this.session.Context.IsActual) - { - // Encrypt fragment - fragment = this.encryptRecordFragment(contentType, fragment); - } - - // Write tls message - TlsStream record = new TlsStream(); - record.Write((byte)contentType); - record.Write((short)this.session.Context.Protocol); - record.Write((short)fragment.Length); - record.Write(fragment); - - // Write record - bytesSent += base.Send(record.ToArray()); - - // Reset record data - record.Reset(); - } - - return bytesSent; - } - - private byte[][] fragmentData(byte[] messageData) - { - ArrayList d = new ArrayList(); - - int position = 0; - - while (position < messageData.Length) - { - short fragmentLength = 0; - byte[] fragmentData; - if ((messageData.Length - position) > TlsSessionContext.MAX_FRAGMENT_SIZE) - { - fragmentLength = TlsSessionContext.MAX_FRAGMENT_SIZE; - } - else - { - fragmentLength = (short)(messageData.Length - position); - } - fragmentData = new byte[fragmentLength]; - - System.Array.Copy(messageData, position, fragmentData, 0, fragmentLength); - - d.Add(fragmentData); - - position += fragmentLength; - } - - byte[][] result = new byte[d.Count][]; - for (int i = 0; i < d.Count; i++) - { - result[i] = (byte[])d[i]; - } - - return result; - } - - #endregion - - #region MESSAGE_PROCESSING - - private void processHandshakeMessage(TlsStream handMsg) - { - TlsHandshakeType handshakeType = (TlsHandshakeType)handMsg.ReadByte(); - TlsHandshakeMessage message = null; - - // Read message length - int length = handMsg.ReadInt24(); - - // Read message data - byte[] data = new byte[length]; - handMsg.Read(data, 0, length); - - // Create and process the server message - message = this.createServerHandshakeMessage(handshakeType, data); - - // Update session - if (message != null) - { - message.UpdateSession(); - } - } - - private void processAlert(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc) - { - switch (alertLevel) - { - case TlsAlertLevel.Fatal: - throw this.session.CreateException(alertLevel, alertDesc); - - case TlsAlertLevel.Warning: - default: - switch (alertDesc) - { - case TlsAlertDescription.CloseNotify: - this.session.Context.ConnectionEnd = true; - break; - - default: - this.session.RaiseWarningAlert(alertLevel, alertDesc); - break; - } - break; - } - } - - #endregion - - #region MISC_METHODS - - private void resetBuffer() - { - this.inputBuffer.SetLength(0); - this.inputBuffer.Position = 0; - } - - private byte ReadByte() - { - byte[] b = new byte[1]; - base.Receive(b); - - return b[0]; - } - - private short ReadShort() - { - byte[] b = new byte[2]; - base.Receive(b); - - short val = BitConverter.ToInt16(b, 0); - - return System.Net.IPAddress.HostToNetworkOrder(val); - } - - #endregion - - #region HANDSHAKE_METHODS - - /* - Client Server - - ClientHello --------> - ServerHello - Certificate* - ServerKeyExchange* - CertificateRequest* - <-------- ServerHelloDone - Certificate* - ClientKeyExchange - CertificateVerify* - [ChangeCipherSpec] - Finished --------> - [ChangeCipherSpec] - <-------- Finished - Application Data <-------> Application Data - - Fig. 1 - Message flow for a full handshake - */ - - internal void DoHandshake() - { - // Reset isSecure field - this.session.IsSecure = false; - - // Send client hello - this.sendRecord(TlsHandshakeType.ClientHello); - - // Read server response - while (!this.session.Context.HelloDone) - { - // Read next record - this.receiveRecord(); - } - - // Send client certificate if requested - if (this.session.Context.ServerSettings.CertificateRequest) - { - this.sendRecord(TlsHandshakeType.Certificate); - } - - // Send Client Key Exchange - this.sendRecord(TlsHandshakeType.ClientKeyExchange); - - // Now initialize session cipher with the generated keys - this.session.Context.Cipher.InitializeCipher(); - - // Send certificate verify if requested - if (this.session.Context.ServerSettings.CertificateRequest) - { - this.sendRecord(TlsHandshakeType.CertificateVerify); - } - - // Send Cipher Spec protocol - this.sendChangeCipherSpec(); - - // Read Cipher Spec protocol - this.receiveRecord(); - - // Read server finished - if (!this.session.Context.HandshakeFinished) - { - this.receiveRecord(); - } - - // Clear Key Info - this.session.Context.ClearKeyInfo(); - - // Set isSecure - this.session.IsSecure = true; - } - - private TlsHandshakeMessage createClientHandshakeMessage(TlsHandshakeType type) - { - switch (type) - { - case TlsHandshakeType.ClientHello: - return new TlsClientHello(session); - - case TlsHandshakeType.Certificate: - return new TlsClientCertificate(session); - - case TlsHandshakeType.ClientKeyExchange: - return new TlsClientKeyExchange(session); - - case TlsHandshakeType.CertificateVerify: - return new TlsClientCertificateVerify(session); - - case TlsHandshakeType.Finished: - return new TlsClientFinished(session); - - default: - throw new InvalidOperationException("Unknown client handshake message type: " + type.ToString() ); - } - } - - private TlsHandshakeMessage createServerHandshakeMessage(TlsHandshakeType type, byte[] buffer) - { - switch (type) - { - case TlsHandshakeType.HelloRequest: - this.sendRecord(TlsHandshakeType.ClientHello); - return null; - - case TlsHandshakeType.ServerHello: - return new TlsServerHello(session, buffer); - - case TlsHandshakeType.Certificate: - return new TlsServerCertificate(session, buffer); - - case TlsHandshakeType.ServerKeyExchange: - return new TlsServerKeyExchange(session, buffer); - - case TlsHandshakeType.CertificateRequest: - return new TlsServerCertificateRequest(session, buffer); - - case TlsHandshakeType.ServerHelloDone: - return new TlsServerHelloDone(session, buffer); - - case TlsHandshakeType.Finished: - return new TlsServerFinished(session, buffer); - - default: - throw this.session.CreateException("Unknown server handshake message received ({0})", type.ToString()); - } - } - - #endregion - } +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.IO; +using System.Net; +using System.Collections; +using System.Net.Sockets; +using System.Security.Cryptography; + +using Mono.Security.Protocol.Tls; +using Mono.Security.Protocol.Tls.Alerts; +using Mono.Security.Protocol.Tls.Handshake; +using Mono.Security.Protocol.Tls.Handshake.Client; + +namespace Mono.Security.Protocol.Tls +{ + public sealed class TlsSocket : Socket + { + #region FIELDS + + private TlsSession session; + private BufferedStream inputBuffer; + + #endregion + + #region PROPERTIES + + internal TlsSession Session + { + get { return this.session; } + } + + internal BufferedStream InputBuffer + { + get { return this.inputBuffer; } + } + + #endregion + + #region CONSTRUCTORS + + private TlsSocket( + AddressFamily addressFamily, + SocketType socketType, + ProtocolType protocolType + ) : base(addressFamily, socketType, protocolType) + { + this.inputBuffer = new BufferedStream(new MemoryStream()); + } + + public TlsSocket( + TlsSession session, + AddressFamily addressFamily, + SocketType socketType, + ProtocolType protocolType + ) : this(addressFamily, socketType, protocolType) + { + this.session = session; + } + + #endregion + + #region REPLACED_METHODS + + public new void Close() + { + this.resetBuffer(); + base.Close(); + if (this.session.State != TlsSessionState.Closing && + this.session.State != TlsSessionState.Closed) + { + this.session.Close(); + } + } + + public new int Receive(byte[] buffer) + { + return this.Receive(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None); + } + + public new int Receive(byte[] buffer, SocketFlags socketFlags) + { + return this.Receive(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags); + } + + public new int Receive(byte[] buffer, int size, SocketFlags socketFlags) + { + return this.Receive(buffer, 0, size, socketFlags); + } + + public new int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags) + { + if (!this.session.IsSecure) + { + return base.Receive(buffer, offset, size, socketFlags); + } + + // If actual buffer is full readed reset it + if (this.inputBuffer.Position == this.inputBuffer.Length) + { + this.resetBuffer(); + } + + // Check if we have space in the middle buffer + // if not Read next TLS record and update the inputBuffer + while ((this.inputBuffer.Length - this.inputBuffer.Position) < size) + { + // Read next record and write it into the inputBuffer + long position = this.inputBuffer.Position; + byte[] record = this.receiveRecord(); + + if (record.Length > 0) + { + // Write new data to the inputBuffer + this.inputBuffer.Seek(0, SeekOrigin.End); + this.inputBuffer.Write(record, 0, record.Length); + + // Restore buffer position + this.inputBuffer.Seek(position, SeekOrigin.Begin); + } + + if (base.Available == 0) + { + break; + } + } + + return this.inputBuffer.Read(buffer, offset, size); + } + + public new int Send(byte[] buffer) + { + return this.Send(buffer, 0, buffer != null ? buffer.Length : 0, SocketFlags.None); + } + + public new int Send(byte[] buffer, SocketFlags socketFlags) + { + return this.Send(buffer, 0, buffer != null ? buffer.Length : 0, socketFlags); + } + + public new int Send(byte[] buffer, int size, SocketFlags socketFlags) + { + return this.Send(buffer, 0, size, socketFlags); + } + + public new int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags) + { + if (!this.session.IsSecure) + { + return base.Send(buffer, offset, size, socketFlags); + } + + // Send the buffer as a TLS record + byte[] recordData = new byte[size]; + System.Array.Copy(buffer, offset, recordData, 0, size); + + return this.sendRecord(TlsContentType.ApplicationData, recordData); + } + + #endregion + + #region TLS_RECORD_METHODS + + private byte[] receiveRecord() + { + if (this.session.Context.ConnectionEnd) + { + throw this.session.CreateException("The session is finished and it's no longer valid."); + } + + TlsContentType contentType = (TlsContentType)this.ReadByte(); + TlsProtocol protocol = (TlsProtocol)this.ReadShort(); + short length = this.ReadShort(); + + // Read Record data + int received = 0; + byte[] buffer = new byte[length]; + while (received != length) + { + received += base.Receive( + buffer, received, buffer.Length - received, SocketFlags.None); + } + + TlsStream message = new TlsStream(buffer); + + // Check that the message has a valid protocol version + if (protocol != this.session.Context.Protocol) + { + throw session.CreateException("Invalid protocol version on message received from server"); + } + + // Decrypt message contents if needed + if (contentType == TlsContentType.Alert && length == 2) + { + } + else + { + if (session.Context.IsActual && + contentType != TlsContentType.ChangeCipherSpec) + { + message = this.decryptRecordFragment( + contentType, + protocol, + message.ToArray()); + } + } + + byte[] result = message.ToArray(); + + // Process record + switch (contentType) + { + case TlsContentType.Alert: + this.processAlert((TlsAlertLevel)message.ReadByte(), + (TlsAlertDescription)message.ReadByte()); + break; + + case TlsContentType.ChangeCipherSpec: + // Reset sequence numbers + this.session.Context.ReadSequenceNumber = 0; + break; + + case TlsContentType.ApplicationData: + break; + + case TlsContentType.Handshake: + while (!message.EOF) + { + this.processHandshakeMessage(message); + } + // Update handshakes of current messages + this.session.Context.HandshakeMessages.Write(message.ToArray()); + break; + + default: + throw session.CreateException("Unknown record received from server."); + } + + return result; + } + + #endregion + + #region TLS_CRYPTO_METHODS + + private byte[] encryptRecordFragment(TlsContentType contentType, byte[] fragment) + { + // Calculate message MAC + byte[] mac = this.session.Context.Cipher.ComputeClientRecordMAC(contentType, fragment); + + // Encrypt the message + byte[] ecr = this.session.Context.Cipher.EncryptRecord(fragment, mac); + + // Set new IV + if (this.session.Context.Cipher.CipherMode == CipherMode.CBC) + { + byte[] iv = new byte[this.session.Context.Cipher.IvSize]; + System.Array.Copy(ecr, ecr.Length - iv.Length, iv, 0, iv.Length); + this.session.Context.Cipher.UpdateClientCipherIV(iv); + } + + // Update sequence number + this.session.Context.WriteSequenceNumber++; + + return ecr; + } + + private TlsStream decryptRecordFragment(TlsContentType contentType, + TlsProtocol protocol, + byte[] fragment) + { + byte[] dcrFragment = null; + byte[] dcrMAC = null; + + // Decrypt message + this.session.Context.Cipher.DecryptRecord(fragment, ref dcrFragment, ref dcrMAC); + + // Set new IV + if (this.session.Context.Cipher.CipherMode == CipherMode.CBC) + { + byte[] iv = new byte[session.Context.Cipher.IvSize]; + System.Array.Copy(fragment, fragment.Length - iv.Length, iv, 0, iv.Length); + this.session.Context.Cipher.UpdateServerCipherIV(iv); + } + + // Check MAC code + byte[] mac = this.session.Context.Cipher.ComputeServerRecordMAC(contentType, dcrFragment); + + // Check that the mac is correct + if (mac.Length != dcrMAC.Length) + { + throw new TlsException("Invalid MAC received from server."); + } + for (int i = 0; i < mac.Length; i++) + { + if (mac[i] != dcrMAC[i]) + { + throw new TlsException("Invalid MAC received from server."); + } + } + + // Update sequence number + this.session.Context.ReadSequenceNumber++; + + return new TlsStream(dcrFragment); + } + + #endregion + + #region TLS_SEND_METHODS + + internal int SendAlert(TlsAlert alert) + { + // Write record + int bytesSent = this.sendRecord(TlsContentType.Alert, alert.ToArray()); + + // Update session + alert.UpdateSession(); + + // Reset message contents + alert.Reset(); + + return bytesSent; + } + + private int sendRecord(TlsHandshakeType type) + { + TlsHandshakeMessage msg = createClientHandshakeMessage(type); + + // Write record + int bytesSent = this.sendRecord(msg.ContentType, msg.EncodeMessage()); + + // Update session + msg.UpdateSession(); + + // Reset message contents + msg.Reset(); + + return bytesSent; + } + + private int sendChangeCipherSpec() + { + // Send Change Cipher Spec message + int bytesSent = this.sendRecord(TlsContentType.ChangeCipherSpec, new byte[] {1}); + + // Reset sequence numbers + this.session.Context.WriteSequenceNumber = 0; + + // Make the pending state to be the current state + this.session.Context.IsActual = true; + + // Send Finished message + bytesSent += this.sendRecord(TlsHandshakeType.Finished); + + return bytesSent; + } + + private int sendRecord(TlsContentType contentType, byte[] recordData) + { + if (this.session.Context.ConnectionEnd) + { + throw this.session.CreateException("The session is finished and it's no longer valid."); + } + + int bytesSent = 0; + byte[][] fragments = fragmentData(recordData); + for (int i = 0; i < fragments.Length; i++) + { + byte[] fragment = fragments[i]; + + if (this.session.Context.IsActual) + { + // Encrypt fragment + fragment = this.encryptRecordFragment(contentType, fragment); + } + + // Write tls message + TlsStream record = new TlsStream(); + record.Write((byte)contentType); + record.Write((short)this.session.Context.Protocol); + record.Write((short)fragment.Length); + record.Write(fragment); + + // Write record + bytesSent += base.Send(record.ToArray()); + + // Reset record data + record.Reset(); + } + + return bytesSent; + } + + private byte[][] fragmentData(byte[] messageData) + { + ArrayList d = new ArrayList(); + + int position = 0; + + while (position < messageData.Length) + { + short fragmentLength = 0; + byte[] fragmentData; + if ((messageData.Length - position) > TlsSessionContext.MAX_FRAGMENT_SIZE) + { + fragmentLength = TlsSessionContext.MAX_FRAGMENT_SIZE; + } + else + { + fragmentLength = (short)(messageData.Length - position); + } + fragmentData = new byte[fragmentLength]; + + System.Array.Copy(messageData, position, fragmentData, 0, fragmentLength); + + d.Add(fragmentData); + + position += fragmentLength; + } + + byte[][] result = new byte[d.Count][]; + for (int i = 0; i < d.Count; i++) + { + result[i] = (byte[])d[i]; + } + + return result; + } + + #endregion + + #region MESSAGE_PROCESSING + + private void processHandshakeMessage(TlsStream handMsg) + { + TlsHandshakeType handshakeType = (TlsHandshakeType)handMsg.ReadByte(); + TlsHandshakeMessage message = null; + + // Read message length + int length = handMsg.ReadInt24(); + + // Read message data + byte[] data = new byte[length]; + handMsg.Read(data, 0, length); + + // Create and process the server message + message = this.createServerHandshakeMessage(handshakeType, data); + + // Update session + if (message != null) + { + message.UpdateSession(); + } + } + + private void processAlert(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc) + { + switch (alertLevel) + { + case TlsAlertLevel.Fatal: + throw this.session.CreateException(alertLevel, alertDesc); + + case TlsAlertLevel.Warning: + default: + switch (alertDesc) + { + case TlsAlertDescription.CloseNotify: + this.session.Context.ConnectionEnd = true; + break; + + default: + this.session.RaiseWarningAlert(alertLevel, alertDesc); + break; + } + break; + } + } + + #endregion + + #region MISC_METHODS + + private void resetBuffer() + { + this.inputBuffer.SetLength(0); + this.inputBuffer.Position = 0; + } + + private byte ReadByte() + { + byte[] b = new byte[1]; + base.Receive(b); + + return b[0]; + } + + private short ReadShort() + { + byte[] b = new byte[2]; + base.Receive(b); + + short val = BitConverter.ToInt16(b, 0); + + return System.Net.IPAddress.HostToNetworkOrder(val); + } + + #endregion + + #region HANDSHAKE_METHODS + + /* + Client Server + + ClientHello --------> + ServerHello + Certificate* + ServerKeyExchange* + CertificateRequest* + <-------- ServerHelloDone + Certificate* + ClientKeyExchange + CertificateVerify* + [ChangeCipherSpec] + Finished --------> + [ChangeCipherSpec] + <-------- Finished + Application Data <-------> Application Data + + Fig. 1 - Message flow for a full handshake + */ + + internal void DoHandshake() + { + // Reset isSecure field + this.session.IsSecure = false; + + // Send client hello + this.sendRecord(TlsHandshakeType.ClientHello); + + // Read server response + while (!this.session.Context.HelloDone) + { + // Read next record + this.receiveRecord(); + } + + // Send client certificate if requested + if (this.session.Context.ServerSettings.CertificateRequest) + { + this.sendRecord(TlsHandshakeType.Certificate); + } + + // Send Client Key Exchange + this.sendRecord(TlsHandshakeType.ClientKeyExchange); + + // Now initialize session cipher with the generated keys + this.session.Context.Cipher.InitializeCipher(); + + // Send certificate verify if requested + if (this.session.Context.ServerSettings.CertificateRequest) + { + this.sendRecord(TlsHandshakeType.CertificateVerify); + } + + // Send Cipher Spec protocol + this.sendChangeCipherSpec(); + + // Read Cipher Spec protocol + this.receiveRecord(); + + // Read server finished + if (!this.session.Context.HandshakeFinished) + { + this.receiveRecord(); + } + + // Clear Key Info + this.session.Context.ClearKeyInfo(); + + // Set isSecure + this.session.IsSecure = true; + } + + private TlsHandshakeMessage createClientHandshakeMessage(TlsHandshakeType type) + { + switch (type) + { + case TlsHandshakeType.ClientHello: + return new TlsClientHello(session); + + case TlsHandshakeType.Certificate: + return new TlsClientCertificate(session); + + case TlsHandshakeType.ClientKeyExchange: + return new TlsClientKeyExchange(session); + + case TlsHandshakeType.CertificateVerify: + return new TlsClientCertificateVerify(session); + + case TlsHandshakeType.Finished: + return new TlsClientFinished(session); + + default: + throw new InvalidOperationException("Unknown client handshake message type: " + type.ToString() ); + } + } + + private TlsHandshakeMessage createServerHandshakeMessage(TlsHandshakeType type, byte[] buffer) + { + switch (type) + { + case TlsHandshakeType.HelloRequest: + this.sendRecord(TlsHandshakeType.ClientHello); + return null; + + case TlsHandshakeType.ServerHello: + return new TlsServerHello(session, buffer); + + case TlsHandshakeType.Certificate: + return new TlsServerCertificate(session, buffer); + + case TlsHandshakeType.ServerKeyExchange: + return new TlsServerKeyExchange(session, buffer); + + case TlsHandshakeType.CertificateRequest: + return new TlsServerCertificateRequest(session, buffer); + + case TlsHandshakeType.ServerHelloDone: + return new TlsServerHelloDone(session, buffer); + + case TlsHandshakeType.Finished: + return new TlsServerFinished(session, buffer); + + default: + throw this.session.CreateException("Unknown server handshake message received ({0})", type.ToString()); + } + } + + #endregion + } } \ No newline at end of file diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSslCipherSuite.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSslCipherSuite.cs index 0b6610a1369..46e8caa1573 100755 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSslCipherSuite.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSslCipherSuite.cs @@ -1,252 +1,252 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.IO; -using System.Text; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - -using Mono.Security; -using Mono.Security.Cryptography; - -namespace Mono.Security.Protocol.Tls -{ - internal class TlsSslCipherSuite : CipherSuite - { - #region FIELDS - - private byte[] pad1; - private byte[] pad2; - - #endregion - - #region CONSTRUCTORS - - public TlsSslCipherSuite(short code, string name, string algName, - string hashName, bool exportable, bool blockMode, - byte keyMaterialSize, byte expandedKeyMaterialSize, - short effectiveKeyBytes, byte ivSize, byte blockSize) - : base (code, name, algName, hashName, exportable, blockMode, - keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, - ivSize, blockSize) - { - int padLength = (hashName == "MD5") ? 48 : 40; - - // Fill pad arrays - this.pad1 = new byte[padLength]; - this.pad2 = new byte[padLength]; - - /* Pad the key for inner and outer digest */ - for (int i = 0; i < padLength; ++i) - { - pad1[i] = 0x36; - pad2[i] = 0x5C; - } - } - - #endregion - - #region MAC_GENERATION_METHOD - - public override byte[] ComputeServerRecordMAC(TlsContentType contentType, byte[] fragment) - { - HashAlgorithm hash = HashAlgorithm.Create(this.HashName); - TlsStream block = new TlsStream(); - - block.Write(this.Context.ServerWriteMAC); - block.Write(this.pad1); - block.Write(this.Context.ReadSequenceNumber); - block.Write((byte)contentType); - block.Write((short)fragment.Length); - block.Write(fragment); - - hash.ComputeHash(block.ToArray(), 0, (int)block.Length); - - byte[] blockHash = hash.Hash; - - block.Reset(); - - block.Write(this.Context.ServerWriteMAC); - block.Write(this.pad2); - block.Write(blockHash); - - hash.ComputeHash(block.ToArray(), 0, (int)block.Length); - - block.Reset(); - - return hash.Hash; - } - - public override byte[] ComputeClientRecordMAC(TlsContentType contentType, byte[] fragment) - { - HashAlgorithm hash = HashAlgorithm.Create(this.HashName); - TlsStream block = new TlsStream(); - - block.Write(this.Context.ClientWriteMAC); - block.Write(this.pad1); - block.Write(this.Context.WriteSequenceNumber); - block.Write((byte)contentType); - block.Write((short)fragment.Length); - block.Write(fragment); - - hash.ComputeHash(block.ToArray(), 0, (int)block.Length); - - byte[] blockHash = hash.Hash; - - block.Reset(); - - block.Write(this.Context.ClientWriteMAC); - block.Write(this.pad2); - block.Write(blockHash); - - hash.ComputeHash(block.ToArray(), 0, (int)block.Length); - - block.Reset(); - - return hash.Hash; - } - - #endregion - - #region KEY_GENERATION_METODS - - public override void ComputeMasterSecret(byte[] preMasterSecret) - { - TlsStream masterSecret = new TlsStream(); - - masterSecret.Write(this.prf(preMasterSecret, "A", this.Context.RandomCS)); - masterSecret.Write(this.prf(preMasterSecret, "BB", this.Context.RandomCS)); - masterSecret.Write(this.prf(preMasterSecret, "CCC", this.Context.RandomCS)); - - this.Context.MasterSecret = masterSecret.ToArray(); - } - - public override void ComputeKeys() - { - // Compute KeyBlock - TlsStream tmp = new TlsStream(); - - char labelChar = 'A'; - int count = 1; - while (tmp.Length < this.KeyBlockSize) - { - string label = String.Empty; - - for (int i = 0; i < count; i++) - { - label += labelChar.ToString(); - } - - byte[] block = this.prf(this.Context.MasterSecret, label.ToString(), this.Context.RandomSC); - - int size = (tmp.Length + block.Length) > this.KeyBlockSize ? (this.KeyBlockSize - (int)tmp.Length) : block.Length; - - tmp.Write(block, 0, size); - - labelChar++; - count++; - } - - // Create keyblock - TlsStream keyBlock = new TlsStream(tmp.ToArray()); - - this.Context.ClientWriteMAC = keyBlock.ReadBytes(this.HashSize); - this.Context.ServerWriteMAC = keyBlock.ReadBytes(this.HashSize); - this.Context.ClientWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize); - this.Context.ServerWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize); - - if (!this.IsExportable) - { - if (this.IvSize != 0) - { - this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize); - this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize); - } - else - { - this.Context.ClientWriteIV = new byte[0]; - this.Context.ServerWriteIV = new byte[0]; - } - } - else - { - MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); - - // Generate final write keys - byte[] finalClientWriteKey = new byte[md5.HashSize]; - md5.TransformBlock(this.Context.ClientWriteKey, 0, this.Context.ClientWriteKey.Length, finalClientWriteKey, 0); - finalClientWriteKey = md5.TransformFinalBlock(this.Context.RandomCS, 0, this.Context.RandomCS.Length); - - byte[] finalServerWriteKey = new byte[md5.HashSize]; - md5.TransformBlock(this.Context.ServerWriteKey, 0, this.Context.ServerWriteKey.Length, finalServerWriteKey, 0); - finalClientWriteKey = md5.TransformFinalBlock(this.Context.RandomSC, 0, this.Context.RandomSC.Length); - - this.Context.ClientWriteKey = finalClientWriteKey; - this.Context.ServerWriteKey = finalServerWriteKey; - - // Generate IV keys - this.Context.ClientWriteIV = md5.TransformFinalBlock(this.Context.RandomCS, 0, this.Context.RandomCS.Length); - this.Context.ServerWriteIV = md5.TransformFinalBlock(this.Context.RandomSC, 0, this.Context.RandomSC.Length); - } - - // Clear no more needed data - keyBlock.Reset(); - tmp.Reset(); - } - - #endregion - - #region PRIVATE_METHODS - - private byte[] prf(byte[] secret, string label, byte[] random) - { - HashAlgorithm md5 = new MD5CryptoServiceProvider(); - SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider(); - - // Compute SHA hash - TlsStream block = new TlsStream(); - block.Write(Encoding.ASCII.GetBytes(label)); - block.Write(secret); - block.Write(random); - - byte[] shaHash = sha.ComputeHash(block.ToArray(), 0, (int)block.Length); - - block.Reset(); - - // Compute MD5 hash - block.Write(secret); - block.Write(shaHash); - - byte[] result = md5.ComputeHash(block.ToArray(), 0, (int)block.Length); - - // Free resources - block.Reset(); - - return result; - } - - #endregion - } +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.IO; +using System.Text; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; + +using Mono.Security; +using Mono.Security.Cryptography; + +namespace Mono.Security.Protocol.Tls +{ + internal class TlsSslCipherSuite : CipherSuite + { + #region FIELDS + + private byte[] pad1; + private byte[] pad2; + + #endregion + + #region CONSTRUCTORS + + public TlsSslCipherSuite(short code, string name, string algName, + string hashName, bool exportable, bool blockMode, + byte keyMaterialSize, byte expandedKeyMaterialSize, + short effectiveKeyBytes, byte ivSize, byte blockSize) + : base (code, name, algName, hashName, exportable, blockMode, + keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, + ivSize, blockSize) + { + int padLength = (hashName == "MD5") ? 48 : 40; + + // Fill pad arrays + this.pad1 = new byte[padLength]; + this.pad2 = new byte[padLength]; + + /* Pad the key for inner and outer digest */ + for (int i = 0; i < padLength; ++i) + { + pad1[i] = 0x36; + pad2[i] = 0x5C; + } + } + + #endregion + + #region MAC_GENERATION_METHOD + + public override byte[] ComputeServerRecordMAC(TlsContentType contentType, byte[] fragment) + { + HashAlgorithm hash = HashAlgorithm.Create(this.HashName); + TlsStream block = new TlsStream(); + + block.Write(this.Context.ServerWriteMAC); + block.Write(this.pad1); + block.Write(this.Context.ReadSequenceNumber); + block.Write((byte)contentType); + block.Write((short)fragment.Length); + block.Write(fragment); + + hash.ComputeHash(block.ToArray(), 0, (int)block.Length); + + byte[] blockHash = hash.Hash; + + block.Reset(); + + block.Write(this.Context.ServerWriteMAC); + block.Write(this.pad2); + block.Write(blockHash); + + hash.ComputeHash(block.ToArray(), 0, (int)block.Length); + + block.Reset(); + + return hash.Hash; + } + + public override byte[] ComputeClientRecordMAC(TlsContentType contentType, byte[] fragment) + { + HashAlgorithm hash = HashAlgorithm.Create(this.HashName); + TlsStream block = new TlsStream(); + + block.Write(this.Context.ClientWriteMAC); + block.Write(this.pad1); + block.Write(this.Context.WriteSequenceNumber); + block.Write((byte)contentType); + block.Write((short)fragment.Length); + block.Write(fragment); + + hash.ComputeHash(block.ToArray(), 0, (int)block.Length); + + byte[] blockHash = hash.Hash; + + block.Reset(); + + block.Write(this.Context.ClientWriteMAC); + block.Write(this.pad2); + block.Write(blockHash); + + hash.ComputeHash(block.ToArray(), 0, (int)block.Length); + + block.Reset(); + + return hash.Hash; + } + + #endregion + + #region KEY_GENERATION_METODS + + public override void ComputeMasterSecret(byte[] preMasterSecret) + { + TlsStream masterSecret = new TlsStream(); + + masterSecret.Write(this.prf(preMasterSecret, "A", this.Context.RandomCS)); + masterSecret.Write(this.prf(preMasterSecret, "BB", this.Context.RandomCS)); + masterSecret.Write(this.prf(preMasterSecret, "CCC", this.Context.RandomCS)); + + this.Context.MasterSecret = masterSecret.ToArray(); + } + + public override void ComputeKeys() + { + // Compute KeyBlock + TlsStream tmp = new TlsStream(); + + char labelChar = 'A'; + int count = 1; + while (tmp.Length < this.KeyBlockSize) + { + string label = String.Empty; + + for (int i = 0; i < count; i++) + { + label += labelChar.ToString(); + } + + byte[] block = this.prf(this.Context.MasterSecret, label.ToString(), this.Context.RandomSC); + + int size = (tmp.Length + block.Length) > this.KeyBlockSize ? (this.KeyBlockSize - (int)tmp.Length) : block.Length; + + tmp.Write(block, 0, size); + + labelChar++; + count++; + } + + // Create keyblock + TlsStream keyBlock = new TlsStream(tmp.ToArray()); + + this.Context.ClientWriteMAC = keyBlock.ReadBytes(this.HashSize); + this.Context.ServerWriteMAC = keyBlock.ReadBytes(this.HashSize); + this.Context.ClientWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize); + this.Context.ServerWriteKey = keyBlock.ReadBytes(this.KeyMaterialSize); + + if (!this.IsExportable) + { + if (this.IvSize != 0) + { + this.Context.ClientWriteIV = keyBlock.ReadBytes(this.IvSize); + this.Context.ServerWriteIV = keyBlock.ReadBytes(this.IvSize); + } + else + { + this.Context.ClientWriteIV = new byte[0]; + this.Context.ServerWriteIV = new byte[0]; + } + } + else + { + MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); + + // Generate final write keys + byte[] finalClientWriteKey = new byte[md5.HashSize]; + md5.TransformBlock(this.Context.ClientWriteKey, 0, this.Context.ClientWriteKey.Length, finalClientWriteKey, 0); + finalClientWriteKey = md5.TransformFinalBlock(this.Context.RandomCS, 0, this.Context.RandomCS.Length); + + byte[] finalServerWriteKey = new byte[md5.HashSize]; + md5.TransformBlock(this.Context.ServerWriteKey, 0, this.Context.ServerWriteKey.Length, finalServerWriteKey, 0); + finalClientWriteKey = md5.TransformFinalBlock(this.Context.RandomSC, 0, this.Context.RandomSC.Length); + + this.Context.ClientWriteKey = finalClientWriteKey; + this.Context.ServerWriteKey = finalServerWriteKey; + + // Generate IV keys + this.Context.ClientWriteIV = md5.TransformFinalBlock(this.Context.RandomCS, 0, this.Context.RandomCS.Length); + this.Context.ServerWriteIV = md5.TransformFinalBlock(this.Context.RandomSC, 0, this.Context.RandomSC.Length); + } + + // Clear no more needed data + keyBlock.Reset(); + tmp.Reset(); + } + + #endregion + + #region PRIVATE_METHODS + + private byte[] prf(byte[] secret, string label, byte[] random) + { + HashAlgorithm md5 = new MD5CryptoServiceProvider(); + SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider(); + + // Compute SHA hash + TlsStream block = new TlsStream(); + block.Write(Encoding.ASCII.GetBytes(label)); + block.Write(secret); + block.Write(random); + + byte[] shaHash = sha.ComputeHash(block.ToArray(), 0, (int)block.Length); + + block.Reset(); + + // Compute MD5 hash + block.Write(secret); + block.Write(shaHash); + + byte[] result = md5.ComputeHash(block.ToArray(), 0, (int)block.Length); + + // Free resources + block.Reset(); + + return result; + } + + #endregion + } } \ No newline at end of file diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSslHandshakeHash.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSslHandshakeHash.cs index e296e477472..77048c660f6 100755 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSslHandshakeHash.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSslHandshakeHash.cs @@ -1,157 +1,157 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Security.Cryptography; - -namespace Mono.Security.Protocol.Tls -{ - internal class TlsSslHandshakeHash : System.Security.Cryptography.HashAlgorithm - { - #region FIELDS - - private HashAlgorithm md5; - private HashAlgorithm sha; - private bool hashing; - private byte[] secret; - private byte[] innerPadMD5; - private byte[] outerPadMD5; - private byte[] innerPadSHA; - private byte[] outerPadSHA; - - #endregion - - #region CONSTRUCTORS - - public TlsSslHandshakeHash(byte[] secret) - { - // Create md5 and sha1 hashes - this.md5 = HashAlgorithm.Create("MD5"); - this.sha = HashAlgorithm.Create("SHA1"); - - // Set HashSizeValue - this.HashSizeValue = md5.HashSize + sha.HashSize; - - // Update secret - this.secret = secret; - - this.Initialize(); - } - - #endregion - - #region METHODS - - public override void Initialize() - { - md5.Initialize(); - sha.Initialize(); - initializePad(); - hashing = false; - } - - protected override byte[] HashFinal() - { - if (!hashing) - { - hashing = true; - } - - // Finalize the md5 hash - md5.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0); - md5.TransformFinalBlock(this.innerPadMD5, 0, this.innerPadMD5.Length); - - byte[] firstResultMD5 = md5.Hash; - - md5.Initialize(); - md5.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0); - md5.TransformBlock(this.outerPadMD5, 0, this.outerPadMD5.Length, this.outerPadMD5, 0); - md5.TransformFinalBlock(firstResultMD5, 0, firstResultMD5.Length); - - // Finalize the sha1 hash - sha.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0); - sha.TransformFinalBlock(this.innerPadSHA, 0, this.innerPadSHA.Length); - - byte[] firstResultSHA = sha.Hash; - - sha.Initialize(); - sha.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0); - sha.TransformBlock(this.outerPadSHA, 0, this.outerPadSHA.Length, this.outerPadSHA, 0); - sha.TransformFinalBlock(firstResultSHA, 0, firstResultSHA.Length); - - this.Initialize(); - - byte[] result = new byte[36]; - - System.Array.Copy(md5.Hash, 0, result, 0, 16); - System.Array.Copy(sha.Hash, 0, result, 16, 20); - - return result; - } - - protected override void HashCore( - byte[] array, - int ibStart, - int cbSize) - { - if (!hashing) - { - hashing = true; - } - md5.TransformBlock(array, ibStart, cbSize, array, ibStart); - sha.TransformBlock(array, ibStart, cbSize, array, ibStart); - } - - #endregion - - #region PRIVATE_METHODS - - private void initializePad() - { - // Fill md5 arrays - this.innerPadMD5 = new byte[48]; - this.outerPadMD5 = new byte[48]; - - /* Pad the key for inner and outer digest */ - for (int i = 0; i < 48; ++i) - { - this.innerPadMD5[i] = 0x36; - this.outerPadMD5[i] = 0x5C; - } - - // Fill sha arrays - this.innerPadSHA = new byte[40]; - this.outerPadSHA = new byte[40]; - - /* Pad the key for inner and outer digest */ - for (int i = 0; i < 40; ++i) - { - this.innerPadSHA[i] = 0x36; - this.outerPadSHA[i] = 0x5C; - } - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Security.Cryptography; + +namespace Mono.Security.Protocol.Tls +{ + internal class TlsSslHandshakeHash : System.Security.Cryptography.HashAlgorithm + { + #region FIELDS + + private HashAlgorithm md5; + private HashAlgorithm sha; + private bool hashing; + private byte[] secret; + private byte[] innerPadMD5; + private byte[] outerPadMD5; + private byte[] innerPadSHA; + private byte[] outerPadSHA; + + #endregion + + #region CONSTRUCTORS + + public TlsSslHandshakeHash(byte[] secret) + { + // Create md5 and sha1 hashes + this.md5 = HashAlgorithm.Create("MD5"); + this.sha = HashAlgorithm.Create("SHA1"); + + // Set HashSizeValue + this.HashSizeValue = md5.HashSize + sha.HashSize; + + // Update secret + this.secret = secret; + + this.Initialize(); + } + + #endregion + + #region METHODS + + public override void Initialize() + { + md5.Initialize(); + sha.Initialize(); + initializePad(); + hashing = false; + } + + protected override byte[] HashFinal() + { + if (!hashing) + { + hashing = true; + } + + // Finalize the md5 hash + md5.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0); + md5.TransformFinalBlock(this.innerPadMD5, 0, this.innerPadMD5.Length); + + byte[] firstResultMD5 = md5.Hash; + + md5.Initialize(); + md5.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0); + md5.TransformBlock(this.outerPadMD5, 0, this.outerPadMD5.Length, this.outerPadMD5, 0); + md5.TransformFinalBlock(firstResultMD5, 0, firstResultMD5.Length); + + // Finalize the sha1 hash + sha.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0); + sha.TransformFinalBlock(this.innerPadSHA, 0, this.innerPadSHA.Length); + + byte[] firstResultSHA = sha.Hash; + + sha.Initialize(); + sha.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0); + sha.TransformBlock(this.outerPadSHA, 0, this.outerPadSHA.Length, this.outerPadSHA, 0); + sha.TransformFinalBlock(firstResultSHA, 0, firstResultSHA.Length); + + this.Initialize(); + + byte[] result = new byte[36]; + + System.Array.Copy(md5.Hash, 0, result, 0, 16); + System.Array.Copy(sha.Hash, 0, result, 16, 20); + + return result; + } + + protected override void HashCore( + byte[] array, + int ibStart, + int cbSize) + { + if (!hashing) + { + hashing = true; + } + md5.TransformBlock(array, ibStart, cbSize, array, ibStart); + sha.TransformBlock(array, ibStart, cbSize, array, ibStart); + } + + #endregion + + #region PRIVATE_METHODS + + private void initializePad() + { + // Fill md5 arrays + this.innerPadMD5 = new byte[48]; + this.outerPadMD5 = new byte[48]; + + /* Pad the key for inner and outer digest */ + for (int i = 0; i < 48; ++i) + { + this.innerPadMD5[i] = 0x36; + this.outerPadMD5[i] = 0x5C; + } + + // Fill sha arrays + this.innerPadSHA = new byte[40]; + this.outerPadSHA = new byte[40]; + + /* Pad the key for inner and outer digest */ + for (int i = 0; i < 40; ++i) + { + this.innerPadSHA[i] = 0x36; + this.outerPadSHA[i] = 0x5C; + } + } + + #endregion + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsStream.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsStream.cs index c6ebee5de8d..4eeea2d28ae 100644 --- a/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsStream.cs +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsStream.cs @@ -1,250 +1,250 @@ -/* Transport Security Layer (TLS) - * Copyright (c) 2003 Carlos Guzmán Álvarez - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.IO; -using System.Net; - -namespace Mono.Security.Protocol.Tls -{ - internal class TlsStream : Stream - { - #region FIELDS - - private bool canRead; - private bool canWrite; - private MemoryStream buffer; - - #endregion - - #region PROPERTIES - - public bool EOF - { - get - { - if (this.Position < this.Length) - { - return false; - } - else - { - return true; - } - } - } - - #endregion - - #region STREAM_PROPERTIES - - public override bool CanWrite - { - get { return canWrite; } - } - - public override bool CanRead - { - get { return canRead; } - } - - public override bool CanSeek - { - get { return buffer.CanSeek; } - } - - public override long Position - { - get { return buffer.Position; } - set { buffer.Position = value; } - } - - public override long Length - { - get { return buffer.Length; } - } - - #endregion - - #region CONSTRUCTORS - - public TlsStream() : base() - { - this.buffer = new MemoryStream(0); - this.canRead = false; - this.canWrite = true; - } - - public TlsStream(byte[] data) : base() - { - this.buffer = new MemoryStream(data); - this.canRead = true; - this.canWrite = false; - } - - #endregion - - #region SPECIFIC_READ_METHODS - - public new byte ReadByte() - { - return (byte)base.ReadByte(); - } - - public short ReadInt16() - { - byte[] bytes = this.ReadBytes(2); - - return IPAddress.HostToNetworkOrder(BitConverter.ToInt16(bytes, 0)); - } - - public int ReadInt24() - { - byte[] b = this.ReadBytes(3); - - return ((b[0] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[2] & 0xff); - } - - public int ReadInt32() - { - byte[] bytes = this.ReadBytes(4); - - return IPAddress.HostToNetworkOrder(BitConverter.ToInt32(bytes, 0)); - } - - public long ReadInt64() - { - byte[] bytes = this.ReadBytes(8); - - return IPAddress.HostToNetworkOrder(BitConverter.ToInt64(bytes, 0)); - } - - public byte[] ReadBytes(int count) - { - byte[] bytes = new byte[count]; - this.Read(bytes, 0, count); - - return bytes; - } - - #endregion - - #region SPECIFIC_WRITE_METHODS - - public void Write(byte value) - { - WriteByte(value); - } - - public void Write(short value) - { - byte[] bytes = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder(value)); - Write(bytes); - } - - public void WriteInt24(int value) - { - int int24 = IPAddress.HostToNetworkOrder(value); - byte[] content = new byte[3]; - - System.Array.Copy(BitConverter.GetBytes(int24), 1, content, 0, 3); - - Write(content); - } - - public void Write(int value) - { - byte[] bytes = BitConverter.GetBytes((int)IPAddress.HostToNetworkOrder(value)); - Write(bytes); - } - - public void Write(long value) - { - byte[] bytes = BitConverter.GetBytes((long)IPAddress.HostToNetworkOrder(value)); - Write(bytes); - } - - public void Write(byte[] buffer) - { - Write(buffer, 0, buffer.Length); - } - - #endregion - - #region METHODS - - public void Reset() - { - buffer.SetLength(0); - buffer.Position = 0; - } - - public byte[] ToArray() - { - return buffer.ToArray(); - } - - #endregion - - #region STREAM_METHODS - - public override void Flush() - { - buffer.Flush(); - } - - public override void SetLength(long length) - { - buffer.SetLength(length); - } - - public override long Seek(long offset, System.IO.SeekOrigin loc) - { - return buffer.Seek(offset, loc); - } - - public override int Read(byte[] buffer, int offset, int count) - { - if (canRead) - { - return this.buffer.Read(buffer, offset, count); - } - throw new InvalidOperationException("Read operations are not allowed by this stream"); - } - - public override void Write(byte[] buffer, int offset, int count) - { - if (canWrite) - { - this.buffer.Write(buffer, offset, count); - } - else - { - throw new InvalidOperationException("Write operations are not allowed by this stream"); - } - } - - #endregion - } -} +/* Transport Security Layer (TLS) + * Copyright (c) 2003 Carlos Guzmán Álvarez + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.IO; +using System.Net; + +namespace Mono.Security.Protocol.Tls +{ + internal class TlsStream : Stream + { + #region FIELDS + + private bool canRead; + private bool canWrite; + private MemoryStream buffer; + + #endregion + + #region PROPERTIES + + public bool EOF + { + get + { + if (this.Position < this.Length) + { + return false; + } + else + { + return true; + } + } + } + + #endregion + + #region STREAM_PROPERTIES + + public override bool CanWrite + { + get { return canWrite; } + } + + public override bool CanRead + { + get { return canRead; } + } + + public override bool CanSeek + { + get { return buffer.CanSeek; } + } + + public override long Position + { + get { return buffer.Position; } + set { buffer.Position = value; } + } + + public override long Length + { + get { return buffer.Length; } + } + + #endregion + + #region CONSTRUCTORS + + public TlsStream() : base() + { + this.buffer = new MemoryStream(0); + this.canRead = false; + this.canWrite = true; + } + + public TlsStream(byte[] data) : base() + { + this.buffer = new MemoryStream(data); + this.canRead = true; + this.canWrite = false; + } + + #endregion + + #region SPECIFIC_READ_METHODS + + public new byte ReadByte() + { + return (byte)base.ReadByte(); + } + + public short ReadInt16() + { + byte[] bytes = this.ReadBytes(2); + + return IPAddress.HostToNetworkOrder(BitConverter.ToInt16(bytes, 0)); + } + + public int ReadInt24() + { + byte[] b = this.ReadBytes(3); + + return ((b[0] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[2] & 0xff); + } + + public int ReadInt32() + { + byte[] bytes = this.ReadBytes(4); + + return IPAddress.HostToNetworkOrder(BitConverter.ToInt32(bytes, 0)); + } + + public long ReadInt64() + { + byte[] bytes = this.ReadBytes(8); + + return IPAddress.HostToNetworkOrder(BitConverter.ToInt64(bytes, 0)); + } + + public byte[] ReadBytes(int count) + { + byte[] bytes = new byte[count]; + this.Read(bytes, 0, count); + + return bytes; + } + + #endregion + + #region SPECIFIC_WRITE_METHODS + + public void Write(byte value) + { + WriteByte(value); + } + + public void Write(short value) + { + byte[] bytes = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder(value)); + Write(bytes); + } + + public void WriteInt24(int value) + { + int int24 = IPAddress.HostToNetworkOrder(value); + byte[] content = new byte[3]; + + System.Array.Copy(BitConverter.GetBytes(int24), 1, content, 0, 3); + + Write(content); + } + + public void Write(int value) + { + byte[] bytes = BitConverter.GetBytes((int)IPAddress.HostToNetworkOrder(value)); + Write(bytes); + } + + public void Write(long value) + { + byte[] bytes = BitConverter.GetBytes((long)IPAddress.HostToNetworkOrder(value)); + Write(bytes); + } + + public void Write(byte[] buffer) + { + Write(buffer, 0, buffer.Length); + } + + #endregion + + #region METHODS + + public void Reset() + { + buffer.SetLength(0); + buffer.Position = 0; + } + + public byte[] ToArray() + { + return buffer.ToArray(); + } + + #endregion + + #region STREAM_METHODS + + public override void Flush() + { + buffer.Flush(); + } + + public override void SetLength(long length) + { + buffer.SetLength(length); + } + + public override long Seek(long offset, System.IO.SeekOrigin loc) + { + return buffer.Seek(offset, loc); + } + + public override int Read(byte[] buffer, int offset, int count) + { + if (canRead) + { + return this.buffer.Read(buffer, offset, count); + } + throw new InvalidOperationException("Read operations are not allowed by this stream"); + } + + public override void Write(byte[] buffer, int offset, int count) + { + if (canWrite) + { + this.buffer.Write(buffer, offset, count); + } + else + { + throw new InvalidOperationException("Write operations are not allowed by this stream"); + } + } + + #endregion + } +} -- cgit v1.2.3