Thread: [pgsqlclient-checkins] pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Protocol.Tls.Handsha
Status: Inactive
Brought to you by:
carlosga_fb
Update of /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1400 Added Files: TlsClientCertificate.cs TlsClientCertificateVerify.cs TlsClientFinished.cs TlsClientHello.cs TlsClientKeyExchange.cs TlsServerCertificate.cs TlsServerCertificateRequest.cs TlsServerFinished.cs TlsServerHello.cs TlsServerHelloDone.cs TlsServerKeyExchange.cs Log Message: Reorganization to match mono:: cvs structure --- NEW FILE: TlsClientCertificate.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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 Mono.Security.Protocol.Tls; namespace Mono.Security.Protocol.Tls.Handshake.Client { internal class TlsClientCertificate : TlsHandshakeMessage { #region Constructors public TlsClientCertificate(TlsContext context) : base(context, TlsHandshakeType.Certificate) { } #endregion #region Methods public override void Update() { base.Update(); this.Reset(); } #endregion #region Protected Methods protected override void ProcessAsSsl3() { this.ProcessAsTls1(); } protected override void ProcessAsTls1() { if (this.Context.ClientSettings.Certificates == null || this.Context.ClientSettings.Certificates.Count == 0) { throw this.Context.CreateException("Client certificate requested by the server and no client certificate specified."); } // Select a valid certificate X509Certificate clientCert = this.Context.ClientSettings.Certificates[0]; /* clientCert = this.Context.SslStream.RaiseClientCertificateSelection( this.Context.ClientSettings.Certificates, this.Context.ServerSettings.Certificates[0], this.Context.ClientSettings.TargetHost, null); */ this.Context.ClientSettings.ClientCertificate = clientCert; // Write client certificates information to a stream TlsStream stream = new TlsStream(); stream.WriteInt24(clientCert.GetRawCertData().Length); stream.Write(clientCert.GetRawCertData()); // Compose the message this.WriteInt24((int)stream.Length); this.Write(stream.ToArray()); } #endregion } } --- NEW FILE: TlsClientCertificateVerify.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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(TlsContext context) : base(context, TlsHandshakeType.Finished) { } #endregion #region Methods public override void Update() { base.Update(); this.Reset(); } #endregion #region Protected Methods protected override void ProcessAsSsl3() { throw new NotSupportedException(); } protected override void ProcessAsTls1() { AsymmetricAlgorithm privKey = null; privKey = this.Context.SslStream.RaisePrivateKeySelection( this.Context.ClientSettings.ClientCertificate, this.Context.ClientSettings.TargetHost); if (privKey == null) { throw this.Context.CreateException("Client certificate Private Key unavailable."); } else { // Compute handshake messages hash MD5SHA1 hash = new MD5SHA1(); hash.ComputeHash( this.Context.HandshakeMessages.ToArray(), 0, (int)this.Context.HandshakeMessages.Length); // RSAManaged of the selected ClientCertificate // (at this moment the first one) RSA rsa = this.getClientCertRSA((RSA)privKey); // Write message this.Write(hash.CreateSignature(rsa)); } } #endregion #region Private methods private RSA getClientCertRSA(RSA privKey) { RSAParameters rsaParams = new RSAParameters(); RSAParameters privateParams = privKey.ExportParameters(true); // for RSA m_publickey contains 2 ASN.1 integers // the modulus and the public exponent ASN1 pubkey = new ASN1 (this.Context.ClientSettings.Certificates[0].GetPublicKey()); ASN1 modulus = pubkey [0]; if ((modulus == null) || (modulus.Tag != 0x02)) { return null; } ASN1 exponent = pubkey [1]; if (exponent.Tag != 0x02) { return null; } rsaParams.Modulus = this.getUnsignedBigInteger(modulus.Value); rsaParams.Exponent = exponent.Value; // Set private key parameters rsaParams.D = privateParams.D; rsaParams.DP = privateParams.DP; rsaParams.DQ = privateParams.DQ; rsaParams.InverseQ = privateParams.InverseQ; rsaParams.P = privateParams.P; rsaParams.Q = privateParams.Q; // 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); RSAManaged rsa = new RSAManaged(keySize); rsa.ImportParameters (rsaParams); return (RSA)rsa; } 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; } } #endregion } } --- NEW FILE: TlsClientFinished.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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(TlsContext context) : base(context, TlsHandshakeType.Finished) { } #endregion #region Methods public override void Update() { base.Update(); this.Reset(); } #endregion #region Protected Methods protected override void ProcessAsSsl3() { // Compute handshake messages hashes HashAlgorithm hash = new TlsSslHandshakeHash(this.Context.MasterSecret); TlsStream data = new TlsStream(); data.Write(this.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 MD5SHA1(); hash.ComputeHash( this.Context.HandshakeMessages.ToArray(), 0, (int)this.Context.HandshakeMessages.Length); // Write message Write(this.Context.Cipher.PRF(this.Context.MasterSecret, "client finished", hash.Hash, 12)); } #endregion } } --- NEW FILE: TlsClientHello.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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(TlsContext context) : base(context, TlsHandshakeType.ClientHello) { } #endregion #region Methods public override void Update() { base.Update(); this.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.Context.Protocol); // Random bytes - Unix time + Radom bytes [28] TlsStream clientRandom = new TlsStream(); clientRandom.Write(this.Context.GetUnixTime()); clientRandom.Write(this.Context.GetSecureRandomBytes(28)); this.random = clientRandom.ToArray(); clientRandom.Reset(); this.Write(this.random); // Session id // Send the session ID empty if (this.Context.SessionId != null) { this.Write((byte)this.Context.SessionId.Length); if (this.Context.SessionId.Length > 0) { this.Write(this.Context.SessionId); } } else { this.Write((byte)0); } // Write length of Cipher suites this.Write((short)(this.Context.SupportedCiphers.Count*2)); // Write Supported Cipher suites for (int i = 0; i < this.Context.SupportedCiphers.Count; i++) { this.Write((short)this.Context.SupportedCiphers[i].Code); } // Compression methods length this.Write((byte)1); // Compression methods ( 0 = none ) this.Write((byte)this.Context.CompressionMethod); } #endregion } } --- NEW FILE: TlsClientKeyExchange.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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 (TlsContext context) : base(context, TlsHandshakeType.ClientKeyExchange) { } #endregion #region Protected Methods protected override void ProcessAsSsl3() { // Compute pre master secret byte[] preMasterSecret = this.Context.Cipher.CreatePremasterSecret(); // Create a new RSA key RSA rsa = this.Context.Cipher.CertificateRSA(); // Encrypt premaster_sercret RSAPKCS1KeyExchangeFormatter formatter = new RSAPKCS1KeyExchangeFormatter(rsa); // Write the preMasterSecret encrypted byte[] buffer = formatter.CreateKeyExchange(preMasterSecret); this.Write(buffer); // Create master secret this.Context.Cipher.ComputeMasterSecret(preMasterSecret); // Create keys this.Context.Cipher.ComputeKeys(); // Clear resources rsa.Clear(); } protected override void ProcessAsTls1() { // Compute pre master secret byte[] preMasterSecret = this.Context.Cipher.CreatePremasterSecret(); // Create a new RSA key RSA rsa = this.Context.Cipher.CertificateRSA(); // 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.Context.Cipher.ComputeMasterSecret(preMasterSecret); // Create keys this.Context.Cipher.ComputeKeys(); // Clear resources rsa.Clear(); } #endregion } } --- NEW FILE: TlsServerCertificate.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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.Net; using System.Collections; using System.Text.RegularExpressions; using System.Security.Cryptography; using X509Cert = System.Security.Cryptography.X509Certificates; 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 Constructors public TlsServerCertificate(TlsContext context, byte[] buffer) : base(context, TlsHandshakeType.Certificate, buffer) { } #endregion #region Methods public override void Update() { base.Update(); this.Context.ServerSettings.Certificates = 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 data byte[] buffer = this.ReadBytes(certLength); // Create a new X509 Certificate X509Certificate certificate = new X509Certificate(buffer); certificates.Add(certificate); /* System.Text.StringBuilder b = new System.Text.StringBuilder(); b.AppendFormat( "\r\nCertificate {0} | Issuer name {1} | Self signed {2} ({3} bytes) \r\n", certificates.Count, certificate.IssuerName, certificate.IsSelfSigned, buffer.Length); b.Append("Contents: \r\n"); int byteCount = 0; for (int i = 0; i < buffer.Length; i++) { if (byteCount == 25) { byteCount = 0; b.Append("\r\n"); } b.AppendFormat("{0} ", buffer[i].ToString("x2")); byteCount++; } System.Diagnostics.Trace.Write(b.ToString()); */ readed += certLength; } } #warning Correct validation needs to be made using a certificate chain // Restrict validation to the first certificate this.validateCertificate(certificates[0]); } #endregion #region Private Methods private void validateCertificate(X509Certificate certificate) { ArrayList errors = new ArrayList(); // 1 step : Validate dates if (!certificate.IsCurrent) { // errors.Add(0x800B0101); errors.Add(0x01); } // 2 step: Validate CA // 3 step: Validate digital sign /* if (!certificate.VerifySignature(certificate.RSA)) { throw this.Context.CreateException("Certificate received from the server has invalid signature."); } */ // 4 step: Validate domain name if (!this.checkDomainName(certificate.SubjectName)) { // errors.Add(0x800B010F); errors.Add(0x02); } if (errors.Count > 0) { int[] certificateErrors = (int[])errors.ToArray(typeof(int)); if (!this.Context.SslStream.RaiseServerCertificateValidation( new X509Cert.X509Certificate(certificate.RawData), new int[]{})) { throw this.Context.CreateException("Invalid certificate received form server."); } } } private bool checkDomainName(string subjectName) { string domainName = String.Empty; Regex search = new Regex(@"([\w\s\d]*)\s*=\s*([^,]*)"); MatchCollection elements = search.Matches(subjectName); foreach (Match element in elements) { switch (element.Groups[1].Value.Trim().ToUpper()) { case "CN": domainName = element.Groups[2].Value; break; } } if (domainName == String.Empty) { return false; } else { string targetHost = this.Context.ClientSettings.TargetHost; // Check that the IP is correct try { IPAddress ipHost = Dns.Resolve(targetHost).AddressList[0]; IPAddress ipDomain = Dns.Resolve(domainName).AddressList[0]; return (ipHost.Address == ipDomain.Address); } catch (Exception) { return false; } } } #endregion } } --- NEW FILE: TlsServerCertificateRequest.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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(TlsContext context, byte[] buffer) : base(context, TlsHandshakeType.ServerHello, buffer) { } #endregion #region Methods public override void Update() { base.Update(); this.Context.ServerSettings.CertificateTypes = this.certificateTypes; this.Context.ServerSettings.DistinguisedNames = this.distinguisedNames; this.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 } } --- NEW FILE: TlsServerFinished.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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(TlsContext context, byte[] buffer) : base(context, TlsHandshakeType.ServerHello, buffer) { } #endregion #region Methods public override void Update() { base.Update(); // Reset Hahdshake messages information this.Context.HandshakeMessages.Reset(); // Hahdshake is finished this.Context.HandshakeFinished = true; } #endregion #region Protected Methods protected override void ProcessAsSsl3() { // Compute handshake messages hashes HashAlgorithm hash = new TlsSslHandshakeHash(this.Context.MasterSecret); TlsStream data = new TlsStream(); data.Write(this.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 MD5SHA1(); hash.ComputeHash( this.Context.HandshakeMessages.ToArray(), 0, (int)this.Context.HandshakeMessages.Length); byte[] clientPRF = this.Context.Cipher.PRF(this.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 } } --- NEW FILE: TlsServerHello.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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 SecurityProtocolType protocol; private SecurityCompressionType compressionMethod; private byte[] random; private byte[] sessionId; private CipherSuite cipherSuite; #endregion #region Constructors public TlsServerHello(TlsContext context, byte[] buffer) : base(context, TlsHandshakeType.ServerHello, buffer) { } #endregion #region Methods public override void Update() { base.Update(); this.Context.SessionId = this.sessionId; this.Context.ServerRandom = this.random; this.Context.Cipher = this.cipherSuite; this.Context.CompressionMethod = this.compressionMethod; this.Context.Cipher.Context = this.Context; // Compute ClientRandom + ServerRandom TlsStream random = new TlsStream(); random.Write(this.Context.ClientRandom); random.Write(this.Context.ServerRandom); this.Context.RandomCS = random.ToArray(); // Server Random + Client Random random.Reset(); random.Write(this.Context.ServerRandom); random.Write(this.Context.ClientRandom); this.Context.RandomSC = random.ToArray(); random.Reset(); } #endregion #region Protected Methods protected override void ProcessAsSsl3() { // Read protocol version this.protocol = (SecurityProtocolType)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.Context.SupportedCiphers.IndexOf(cipherCode) == -1) { // The server has sent an invalid ciphersuite throw new TlsException("Invalid cipher suite received from server"); } this.cipherSuite = this.Context.SupportedCiphers[cipherCode]; // Read compression methods ( always 0 ) this.compressionMethod = (SecurityCompressionType)this.ReadByte(); } protected override void ProcessAsTls1() { // Read protocol version this.protocol = (SecurityProtocolType)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.Context.SupportedCiphers.IndexOf(cipherCode) == -1) { // The server has sent an invalid ciphersuite throw new TlsException("Invalid cipher suite received from server"); } this.cipherSuite = this.Context.SupportedCiphers[cipherCode]; // Read compression methods ( always 0 ) this.compressionMethod = (SecurityCompressionType)this.ReadByte(); } #endregion } } --- NEW FILE: TlsServerHelloDone.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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(TlsContext context, byte[] buffer) : base(context, TlsHandshakeType.ServerHello, buffer) { } #endregion #region Methods public override void Update() { base.Update(); this.Context.HelloDone = true; } #endregion #region Protected Methods protected override void ProcessAsSsl3() { } protected override void ProcessAsTls1() { } #endregion } } --- NEW FILE: TlsServerKeyExchange.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * 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(TlsContext context, byte[] buffer) : base(context, TlsHandshakeType.ServerKeyExchange, buffer) { this.verifySignature(); } #endregion #region Methods public override void Update() { base.Update(); this.Context.ServerSettings.ServerKeyExchange = true; this.Context.ServerSettings.RsaParameters = this.rsaParams; this.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 this.rsaParams.Modulus = this.ReadBytes(this.ReadInt16()); // Read exponent this.rsaParams.Exponent = this.ReadBytes(this.ReadInt16()); // Read signed params this.signedParams = this.ReadBytes(this.ReadInt16()); } #endregion #region Private Methods private void verifySignature() { MD5SHA1 hash = new MD5SHA1(); // Calculate size of server params int size = rsaParams.Modulus.Length + rsaParams.Exponent.Length + 4; // Create server params array TlsStream stream = new TlsStream(); stream.Write(this.Context.RandomCS); stream.Write(this.ToArray(), 0, size); hash.ComputeHash(stream.ToArray()); stream.Reset(); bool isValidSignature = hash.VerifySignature( this.Context.Cipher.CertificateRSA(), this.signedParams); if (!isValidSignature) { throw this.Context.CreateException("Data was not signed with the server certificate."); } } #endregion } } |