Added partial implementation of SSL3 protocol (not finished yet). Renamed TlsAbstract...
authorCarlos Guzmán Álvarez <carlos@mono-cvs.ximian.com>
Thu, 23 Oct 2003 11:35:12 +0000 (11:35 -0000)
committerCarlos Guzmán Álvarez <carlos@mono-cvs.ximian.com>
Thu, 23 Oct 2003 11:35:12 +0000 (11:35 -0000)
svn path=/trunk/mcs/; revision=19339

22 files changed:
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificate.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientHello.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientKeyExchange.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificateRequest.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHello.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHelloDone.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsHandshakeHashes.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake/TlsHandshakeType.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ChangeLog
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuite.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuiteCollection.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuiteFactory.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsContentType.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSession.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionContext.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSessionSettings.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSocket.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsSslCipherSuite.cs

index e12103916f7a10f672fc7688e040a167ecfd739c..93e82d0716a80aff42862396cec74fdb4fbbf400 100644 (file)
@@ -69,8 +69,8 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                        }
 
                        // Compose the message
-                       WriteInt24((int)stream.Length);
-                       Write(stream.ToArray());
+                       this.WriteInt24((int)stream.Length);
+                       this.Write(stream.ToArray());
                }
 
                #endregion
index a8f4f0ee51ab531670fcf66422180f1aaf3a06f8..2e9a73f1c3843058f9c614020520f517d7fbb88c 100644 (file)
@@ -50,9 +50,42 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                #region PROTECTED_METHODS
 
+               private byte[] computeSslHash(string hashName, byte[] hashes, int sender)
+               {
+                       HashAlgorithm           hash    = HashAlgorithm.Create(hashName);
+                       TlsStream                       block   = new TlsStream();
+                       TlsSslCipherSuite       cipher  = (TlsSslCipherSuite)this.Session.Context.Cipher;
+                       byte[]                          pad1    = null;
+                       byte[]                          pad2    = null;
+
+                       cipher.GeneratePad(hashName, ref pad1, ref pad2);
+
+                       block.Write(hashes);
+                       block.Write(sender);
+                       block.Write(this.Session.Context.MasterSecret);
+                       block.Write(cipher.Pad1);
+
+                       byte[] blockHash = hash.ComputeHash(block.ToArray(), 0, (int)block.Length);
+
+                       block.Reset();
+
+                       block.Write(this.Session.Context.MasterSecret);
+                       block.Write(cipher.Pad2);
+                       block.Write(blockHash);
+
+                       blockHash = hash.ComputeHash(block.ToArray(), 0, (int)block.Length);
+
+                       block.Reset();
+
+                       return blockHash;
+               }
+
                protected override void ProcessAsSsl3()
                {
-                       throw new NotSupportedException();
+                       this.Write(computeSslHash("MD5", Session.Context.HandshakeHashes.Messages, 0x434C4E54));
+                       this.Write(computeSslHash("SHA1", Session.Context.HandshakeHashes.Messages, 0x434C4E54));
+                       
+                       Session.Context.HandshakeHashes.Reset();
                }
 
                protected override void ProcessAsTls1()
index 164b039cacb95b913adc9880526f6b740f5de355..3148d9cfd2a84f3ba7368e2e267d86a06b7f7fa7 100644 (file)
@@ -38,9 +38,7 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                #region CONSTRUCTORS
 
                public TlsClientHello(TlsSession session) 
-                                               : base(session, 
-                                                               TlsHandshakeType.ClientHello, 
-                                                               TlsContentType.Handshake)
+                       : base(session, TlsHandshakeType.ClientHello, TlsContentType.Handshake)
                {
                }
 
@@ -63,13 +61,13 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                protected override void ProcessAsSsl3()
                {
-                       throw new NotSupportedException();
+                       this.ProcessAsTls1();
                }
 
                protected override void ProcessAsTls1()
                {
                        // Client Version
-                       Write((short)this.Session.Context.Protocol);
+                       this.Write((short)this.Session.Context.Protocol);
                                                                
                        // Random bytes - Unix time + Radom bytes [28]
                        TlsStream clientRandom = new TlsStream();
@@ -78,37 +76,37 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                        this.random = clientRandom.ToArray();
                        clientRandom.Reset();
 
-                       Write(this.random);
+                       this.Write(this.random);
 
                        // Session id
                        // Send the session ID empty
                        if (this.Session.SessionId != null)
                        {
-                               Write((byte)this.Session.SessionId.Length);
+                               this.Write((byte)this.Session.SessionId.Length);
                                if (this.Session.SessionId.Length > 0)
                                {
-                                       Write(this.Session.SessionId);
+                                       this.Write(this.Session.SessionId);
                                }
                        }
                        else
                        {
-                               Write((byte)0);
+                               this.Write((byte)0);
                        }
                        
                        // Write length of Cipher suites                        
-                       Write((short)(this.Session.SupportedCiphers.Count*2));
+                       this.Write((short)(this.Session.Context.SupportedCiphers.Count*2));
 
                        // Write Supported Cipher suites
-                       for (int i = 0; i < this.Session.SupportedCiphers.Count; i++)
+                       for (int i = 0; i < this.Session.Context.SupportedCiphers.Count; i++)
                        {
-                               Write((short)this.Session.SupportedCiphers[i].Code);
+                               this.Write((short)this.Session.Context.SupportedCiphers[i].Code);
                        }
 
                        // Compression methods length
-                       Write((byte)1);
+                       this.Write((byte)1);
                        
                        // Compression methods ( 0 = none )
-                       Write((byte)TlsCompressionMethod.None);
+                       this.Write((byte)this.Session.Context.CompressionMethod);
                }
 
                #endregion
index 1d670362bd3bfd8212855b7363181421d48d4fb2..ec5cc20234d946bd020d244f45bffacd1a3a0101 100644 (file)
@@ -45,23 +45,51 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                protected override void ProcessAsSsl3()
                {
-                       throw new NotSupportedException();
+                       // Compute pre master secret
+                       byte[] preMasterSecret = this.Session.Context.Cipher.CreatePremasterSecret();
+
+                       // Create a new RSA key
+                       RSACryptoServiceProvider rsa = null;
+                       if (this.Session.Context.ServerSettings.ServerKeyExchange)
+                       {
+                               rsa = this.Session.Context.Cipher.CreateRSA(this.Session.Context.ServerSettings.RsaParameters);
+                       }
+                       else
+                       {
+                               rsa = this.Session.Context.Cipher.CreateRSA(this.Session.Context.ServerSettings.ServerCertificates[0]);
+                       }                       
+                       
+                       // 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 = Session.Context.Cipher.CreatePremasterSecret();
+                       byte[] preMasterSecret = this.Session.Context.Cipher.CreatePremasterSecret();
 
                        // Create a new RSA key
                        RSACryptoServiceProvider rsa = null;
-                       if (Session.Context.ServerSettings.ServerKeyExchange)
+                       if (this.Session.Context.ServerSettings.ServerKeyExchange)
                        {
-                               rsa = Session.Context.Cipher.CreateRSA(Session.Context.ServerSettings.RsaParameters);
+                               rsa = this.Session.Context.Cipher.CreateRSA(this.Session.Context.ServerSettings.RsaParameters);
                        }
                        else
                        {
-                               rsa = Session.Context.Cipher.CreateRSA(Session.Context.ServerSettings.ServerCertificates[0]);
+                               rsa = this.Session.Context.Cipher.CreateRSA(this.Session.Context.ServerSettings.ServerCertificates[0]);
                        }                       
                        
                        // Encrypt premaster_sercret
@@ -69,14 +97,14 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                        // Write the preMasterSecret encrypted
                        byte[] buffer = formatter.CreateKeyExchange(preMasterSecret);
-                       Write((short)buffer.Length);
-                       Write(buffer);
+                       this.Write((short)buffer.Length);
+                       this.Write(buffer);
 
                        // Create master secret
-                       Session.Context.Cipher.CreateMasterSecret(preMasterSecret);
+                       this.Session.Context.Cipher.ComputeMasterSecret(preMasterSecret);
 
                        // Create keys
-                       Session.Context.Cipher.CreateKeys();
+                       this.Session.Context.Cipher.ComputeKeys();
 
                        // Clear resources
                        rsa.Clear();
index 5a532286509133308db6b1bb23d8e0f7b753b1fc..31ea157e1d6b481205195ded028a76902ce8d4ab 100644 (file)
@@ -70,7 +70,7 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                protected override void ProcessAsSsl3()
                {
-                       throw new NotSupportedException();
+                       this.ProcessAsTls1();
                }
 
                protected override void ProcessAsTls1()
@@ -78,7 +78,7 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                        this.certificates = new X509CertificateCollection();
                        
                        int readed      = 0;
-                       int length      = ReadInt24();
+                       int length      = this.ReadInt24();
 
                        while (readed < length)
                        {
@@ -91,12 +91,12 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                                if (certLength > 0)
                                {
                                        // Read certificate
-                                       X509Certificate certificate = new X509Certificate(ReadBytes(certLength));
+                                       X509Certificate certificate = new X509Certificate(this.ReadBytes(certLength));
                                        certificates.Add(certificate);
 
                                        readed += certLength;
 
-                                       validateCertificate(certificate);
+                                       this.validateCertificate(certificate);
                                }
                        }
                }
index 22628d6226c1483460f8728ae65e9200e7372d98..12f701ec5ae24ce21cd6f8bcb73a8e63e2def1c6 100644 (file)
@@ -52,9 +52,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                {
                        base.UpdateSession();
 
-                       Session.Context.ServerSettings.CertificateTypes         = this.certificateTypes;
-                       Session.Context.ServerSettings.DistinguisedNames        = this.distinguisedNames;
-                       Session.Context.ServerSettings.CertificateRequest       = true;
+                       this.Session.Context.ServerSettings.CertificateTypes    = this.certificateTypes;
+                       this.Session.Context.ServerSettings.DistinguisedNames   = this.distinguisedNames;
+                       this.Session.Context.ServerSettings.CertificateRequest  = true;
                }
 
                #endregion
@@ -69,13 +69,13 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                protected override void ProcessAsTls1()
                {
                        // Read requested certificate types
-                       int typesCount = ReadByte();
+                       int typesCount = this.ReadByte();
                                                
                        certificateTypes = new TlsClientCertificateType[typesCount];
 
                        for (int i = 0; i < typesCount; i++)
                        {
-                               certificateTypes[i] = (TlsClientCertificateType)ReadByte();
+                               certificateTypes[i] = (TlsClientCertificateType)this.ReadByte();
                        }
 
                        /*
@@ -89,8 +89,8 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                         * attributeType OBJECT IDENTIFIER
                         * attributeValue ANY }
                         */
-                       int             tmp = ReadInt16();
-                       ASN1    rdn = new ASN1(ReadBytes(ReadInt16()));
+                       int             tmp = this.ReadInt16();
+                       ASN1    rdn = new ASN1(this.ReadBytes(this.ReadInt16()));
 
                        distinguisedNames = new string[rdn.Count];
 
index 0b1f1e85a44a7a2bfa23c1f8592465e5b75bf797..6c2a35458b8e20dccf7a7b541fea0357cad0c98f 100644 (file)
@@ -44,7 +44,7 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                {
                        base.UpdateSession();
 
-                       Session.HandshakeFinished = true;
+                       this.Session.Context.HandshakeFinished = true;
                }
 
                #endregion
@@ -58,13 +58,13 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                protected override void ProcessAsTls1()
                {
-                       byte[]          serverPRF       = ReadBytes((int)Length);
+                       byte[]          serverPRF       = this.ReadBytes((int)Length);
                        TlsStream       hashes          = new TlsStream();
 
-                       hashes.Write(Session.Context.HandshakeHashes.GetMD5Hash());
-                       hashes.Write(Session.Context.HandshakeHashes.GetSHAHash());
+                       hashes.Write(this.Session.Context.HandshakeHashes.GetMD5Hash());
+                       hashes.Write(this.Session.Context.HandshakeHashes.GetSHAHash());
 
-                       byte[] clientPRF = Session.Context.Cipher.PRF(Session.Context.MasterSecret, "server finished", hashes.ToArray(), 12);
+                       byte[] clientPRF = this.Session.Context.Cipher.PRF(this.Session.Context.MasterSecret, "server finished", hashes.ToArray(), 12);
 
                        hashes.Reset();
 
@@ -81,7 +81,7 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                                }
                        }
 
-                       Session.Context.HandshakeHashes.Clear();
+                       this.Session.Context.HandshakeHashes.Clear();
                }
 
                #endregion
index c76e09644724a4b20eb289648342b9cf55febb34..7a8a8bb969ebaa7522dba27edc6b25ab1fff552e 100644 (file)
@@ -34,7 +34,7 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                private TlsCompressionMethod    compressionMethod;
                private byte[]                                  random;
                private byte[]                                  sessionId;
-               private TlsCipherSuite                  cipherSuite;
+               private CipherSuite     cipherSuite;
                
                #endregion
 
@@ -53,11 +53,25 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                {
                        base.UpdateSession();
 
-                       Session.SetSessionId(this.sessionId);
-                       Session.Context.ServerRandom            = this.random;
-                       Session.Context.Cipher                          = this.cipherSuite;
-                       Session.Context.CompressionMethod       = this.compressionMethod;
-                       Session.Context.Cipher.Context          = this.Session.Context;
+                       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
@@ -66,7 +80,31 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                protected override void ProcessAsSsl3()
                {
-                       throw new NotSupportedException();
+                       #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()
@@ -86,12 +124,12 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                        // Read cipher suite
                        short cipherCode = this.ReadInt16();
-                       if (this.Session.SupportedCiphers.IndexOf(cipherCode) == -1)
+                       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.SupportedCiphers[cipherCode];
+                       this.cipherSuite = this.Session.Context.SupportedCiphers[cipherCode];
                        
                        // Read compression methods ( always 0 )
                        this.compressionMethod = (TlsCompressionMethod)this.ReadByte();
index b30924814f5e93dd628d40376cff0a57e060c531..70b3bccf0ad1a1bdf8f51b88e3f186b8a840628b 100644 (file)
@@ -43,7 +43,7 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                {
                        base.UpdateSession();
 
-                       Session.HelloDone = true;
+                       this.Session.Context.HelloDone = true;
                }
 
                #endregion
index 0970fcfdb8dfc45e74eaeb547ec816fb11d34754..8637d428f3bcd1ef8344ee36332b2fb3416da4be 100644 (file)
@@ -69,19 +69,19 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                protected override void ProcessAsTls1()
                {
-                       rsaParams = new RSAParameters();
+                       this.rsaParams = new RSAParameters();
                        
                        // Read modulus
-                       short length            = ReadInt16();
-                       rsaParams.Modulus       = ReadBytes(length);
+                       short length            = this.ReadInt16();
+                       rsaParams.Modulus       = this.ReadBytes(length);
 
                        // Read exponent
-                       length                          = ReadInt16();
-                       rsaParams.Exponent      = ReadBytes(length);
+                       length                          = this.ReadInt16();
+                       rsaParams.Exponent      = this.ReadBytes(length);
 
                        // Read signed params
-                       length                          = ReadInt16();
-                       signedParams            = ReadBytes(length);
+                       length                          = this.ReadInt16();
+                       signedParams            = this.ReadBytes(length);
                }
 
                #endregion
@@ -96,8 +96,7 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                        // Create server params array
                        TlsStream stream = new TlsStream();
 
-                       stream.Write(Session.Context.ClientRandom);
-                       stream.Write(Session.Context.ServerRandom);
+                       stream.Write(this.Session.Context.RandomCS);
                        stream.Write(rsaParams.Modulus.Length);
                        stream.Write(rsaParams.Modulus);
                        stream.Write(rsaParams.Exponent.Length);
index adf66115b07ec1848cd93b2e64ae810eeeb0e4a1..44ccb32e6e93c33448d4f00edf13bf40060b5f70 100644 (file)
@@ -37,6 +37,15 @@ namespace Mono.Security.Protocol.Tls.Handshake
 
                #endregion
 
+               #region PROPERTIES
+
+               internal byte[] Messages
+               {
+                       get { return messages.ToArray(); }
+               }
+
+               #endregion
+
                #region CONSTRUCTORS
 
                public TlsHandshakeHashes()
index 6dbbe045d1e40a5c0a1e3c4ff171c684939b8d6c..52322ad68908e56651ecb390e742da7105c7ff9c 100644 (file)
@@ -38,6 +38,5 @@ namespace Mono.Security.Protocol.Tls.Handshake
                CertificateVerify       = 15,
                ClientKeyExchange       = 16,
                Finished                        = 20,
-               Unknown                         = 255
        }
 }
index 377a5033e7b401b3b76a71e17b2a8c3e0192672f..6c39fdae559fe2015a466c2c24e96df42046f90e 100644 (file)
@@ -1,3 +1,11 @@
+2003-10-23 Carlos Guzmán Álvarez <carlosga@telefonica.net>
+
+       * Added partial implementation of SSL3 protocol ( not finished yet ).
+
+       * TlsAbstractCipherSuite.cs: Renamed to CipherSuite.cs.
+
+       * Removed AssemblyInfo.cs file.
+
 2003-10-21 Carlos Guzmán Álvarez <carlosga@telefonica.net>
 
        TlsCipherSuiteFactory.cs: Changed names of private methods.
index be433654584f44ff114525c36f20bfabe69632df..3f88b20aa8773b192a996169ab06183a03bcfaa5 100644 (file)
@@ -33,7 +33,7 @@ using Mono.Security.Cryptography;
 
 namespace Mono.Security.Protocol.Tls
 {
-       internal class TlsCipherSuite : TlsAbstractCipherSuite
+       internal class TlsCipherSuite : CipherSuite
        {
                #region CONSTRUCTORS
                
@@ -49,100 +49,64 @@ namespace Mono.Security.Protocol.Tls
 
                #endregion
 
-               #region METHODS
+               #region MAC_GENERATION_METHOD
 
-               public override byte[] EncryptRecord(byte[] fragment, byte[] mac)
+               public override byte[] ComputeServerRecordMAC(TlsContentType contentType, byte[] fragment)
                {
-                       // Encryption ( fragment + mac [+ padding + padding_length] )
-                       MemoryStream ms = new MemoryStream();
-                       CryptoStream cs = new CryptoStream(ms, encryptionCipher, CryptoStreamMode.Write);
+                       TlsStream       data    = new TlsStream();
+                       byte[]          result  = null;
 
-                       cs.Write(fragment, 0, fragment.Length);
-                       cs.Write(mac, 0, mac.Length);
-                       if (cipherMode == CipherMode.CBC)
-                       {
-                               // Calculate padding_length
-                               int fragmentLength      = fragment.Length + mac.Length + 1;
-                               int paddingLength       = (((fragmentLength/blockSize)*blockSize) + blockSize) - fragmentLength;
+                       data.Write(this.Context.ReadSequenceNumber);
+                       data.Write((byte)contentType);
+                       data.Write((short)this.Context.Protocol);
+                       data.Write((short)fragment.Length);
+                       data.Write(fragment);
 
-                               // Write padding length byte
-                               cs.WriteByte((byte)paddingLength);
-                       }
-                       //cs.FlushFinalBlock();
-                       cs.Close();                     
+                       result = this.ServerHMAC.ComputeHash(data.ToArray());
+
+                       data.Reset();
 
-                       return ms.ToArray();
+                       return result;
                }
 
-               public override void DecryptRecord(byte[] fragment, ref byte[] dcrFragment, ref byte[] dcrMAC)
+               public override byte[] ComputeClientRecordMAC(TlsContentType contentType, byte[] fragment)
                {
-                       int     fragmentSize    = 0;
-                       int paddingLength       = 0;
+                       TlsStream       data    = new TlsStream();
+                       byte[]          result  = null;
 
-                       // Decrypt message fragment ( fragment + mac [+ padding + padding_length] )
-                       byte[] buffer = new byte[fragment.Length];
-                       decryptionCipher.TransformBlock(fragment, 0, fragment.Length, buffer, 0);
+                       data.Write(this.Context.WriteSequenceNumber);
+                       data.Write((byte)contentType);
+                       data.Write((short)this.Context.Protocol);
+                       data.Write((short)fragment.Length);
+                       data.Write(fragment);
 
-                       // Calculate fragment size
-                       if (cipherMode == CipherMode.CBC)
-                       {
-                               // Calculate padding_length
-                               paddingLength = buffer[buffer.Length - 1];
-                               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;
-                       }
+                       result = this.ClientHMAC.ComputeHash(data.ToArray());
 
-                       dcrFragment = new byte[fragmentSize];
-                       dcrMAC          = new byte[HashSize];
+                       data.Reset();
 
-                       Buffer.BlockCopy(buffer, 0, dcrFragment, 0, dcrFragment.Length);
-                       Buffer.BlockCopy(buffer, dcrFragment.Length, dcrMAC, 0, dcrMAC.Length);
+                       return result;
                }
 
                #endregion
 
                #region KEY_GENERATION_METODS
 
-               public override void CreateMasterSecret(byte[] preMasterSecret)
+               public override void ComputeMasterSecret(byte[] preMasterSecret)
                {
-                       TlsStream seed = new TlsStream();
-
-                       // Seed
-                       seed.Write(context.ClientRandom);
-                       seed.Write(context.ServerRandom);
-
                        // Create master secret
-                       context.MasterSecret = new byte[preMasterSecret.Length];
-                       context.MasterSecret = PRF(preMasterSecret, "master secret", seed.ToArray(), 48);
-
-                       seed.Reset();
+                       this.Context.MasterSecret = new byte[preMasterSecret.Length];
+                       this.Context.MasterSecret = this.PRF(
+                               preMasterSecret, "master secret", this.Context.RandomCS, 48);
                }
 
-               public override void CreateKeys()
+               public override void ComputeKeys()
                {
-                       TlsStream seed = new TlsStream();
-
-                       // Seed
-                       seed.Write(context.ServerRandom);
-                       seed.Write(context.ClientRandom);
-
                        // Create keyblock
                        TlsStream keyBlock = new TlsStream(
-                               PRF(this.Context.MasterSecret, 
+                               this.PRF(
+                               this.Context.MasterSecret, 
                                "key expansion",
-                               seed.ToArray(),
+                               this.Context.RandomSC,
                                this.KeyBlockSize));
 
                        this.Context.ClientWriteMAC = keyBlock.ReadBytes(this.HashSize);
@@ -165,30 +129,25 @@ namespace Mono.Security.Protocol.Tls
                        }
                        else
                        {
-                               // Seed
-                               seed.Reset();
-                               seed.Write(this.Context.ClientRandom);
-                               seed.Write(this.Context.ServerRandom);
-
                                // Generate final write keys
-                               byte[] finalClientWriteKey      = PRF(this.Context.ClientWriteKey, "client write key", seed.ToArray(), this.KeyMaterialSize);
-                               byte[] finalServerWriteKey      = PRF(this.Context.ServerWriteKey, "server write key", seed.ToArray(), this.KeyMaterialSize);
+                               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", seed.ToArray(), this.IvSize*2);
+                               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
-                       seed.Reset();
                        keyBlock.Reset();
                }
 
index a02ce2b2bacb1bfe1911d96696a4aafc02e3f6ba..9f721f96dada1805c40784a399a8ddc34429103c 100644 (file)
@@ -31,24 +31,39 @@ namespace Mono.Security.Protocol.Tls
 {
        internal sealed class TlsCipherSuiteCollection : ArrayList
        {
+               #region FIELDS
+
+               private TlsProtocol protocol;
+
+               #endregion
+
                #region PROPERTIES
 
-               public TlsCipherSuite this[string name] 
+               public CipherSuite this[string name] 
+               {
+                       get { return (CipherSuite)this[IndexOf(name)]; }
+                       set { this[IndexOf(name)] = (CipherSuite)value; }
+               }
+
+               public CipherSuite this[short code] 
                {
-                       get { return (TlsCipherSuite)this[IndexOf(name)]; }
-                       set { this[IndexOf(name)] = (TlsCipherSuite)value; }
+                       get { return (CipherSuite)base[IndexOf(code)]; }
+                       set { base[IndexOf(code)] = (CipherSuite)value; }
                }
 
-               public TlsCipherSuite this[short code] 
+               public new CipherSuite this[int code] 
                {
-                       get { return (TlsCipherSuite)base[IndexOf(code)]; }
-                       set { base[IndexOf(code)] = (TlsCipherSuite)value; }
+                       get { return (CipherSuite)base[code]; }
+                       set { base[code] = (CipherSuite)value; }
                }
 
-               public new TlsCipherSuite this[int code] 
+               #endregion
+
+               #region CONSTRUCTORS
+
+               public TlsCipherSuiteCollection(TlsProtocol protocol) : base()
                {
-                       get { return (TlsCipherSuite)base[code]; }
-                       set { base[code] = (TlsCipherSuite)value; }
+                       this.protocol = protocol;
                }
 
                #endregion
@@ -63,7 +78,7 @@ namespace Mono.Security.Protocol.Tls
                public int IndexOf(string name)
                {
                        int index = 0;
-                       foreach(TlsCipherSuite suite in this)
+                       foreach (CipherSuite suite in this)
                        {
                                if (cultureAwareCompare(suite.Name, name))
                                {
@@ -77,7 +92,7 @@ namespace Mono.Security.Protocol.Tls
                public int IndexOf(short code)
                {
                        int index = 0;
-                       foreach(TlsCipherSuite suite in this)
+                       foreach (CipherSuite suite in this)
                        {
                                if (suite.Code == code)
                                {
@@ -93,18 +108,35 @@ namespace Mono.Security.Protocol.Tls
                        RemoveAt(IndexOf(errorMessage));
                }
 
-               public TlsCipherSuite Add(TlsCipherSuite cipherSuite)
+               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;
                }
 
-               public TlsCipherSuite Add(short code, string name, string algName, string hashName, bool exportable, bool blockMode, byte keyMaterialSize, byte expandedKeyMaterialSize, short effectiveKeyBytes, byte ivSize, byte blockSize)
+               private TlsSslCipherSuite add(TlsSslCipherSuite cipherSuite)
                {
-                       TlsCipherSuite cipherSuite = new TlsCipherSuite(code, name, algName, hashName, exportable, blockMode, keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize);
+                       base.Add(cipherSuite);
 
-                       return Add(cipherSuite);
+                       return cipherSuite;
                }
 
                private bool cultureAwareCompare(string strA, string strB)
index 83e9d7fe3a96f73edf463fb8712f20390eeac243..415c8b1af7bde088c926ab1a8a61808a17734c37 100755 (executable)
@@ -47,7 +47,7 @@ namespace Mono.Security.Protocol.Tls
 
                private static TlsCipherSuiteCollection GetTls1SupportedCiphers()
                {
-                       TlsCipherSuiteCollection scs = new TlsCipherSuiteCollection();
+                       TlsCipherSuiteCollection scs = new TlsCipherSuiteCollection(TlsProtocol.Tls1);
 
                        // Supported ciphers
                        scs.Add((0x00 << 0x08) | 0x35, "TLS_RSA_WITH_AES_256_CBC_SHA", "Rijndael", "SHA", false, true, 32, 32, 256, 16, 16);
@@ -116,7 +116,7 @@ namespace Mono.Security.Protocol.Tls
 
                private static TlsCipherSuiteCollection GetSsl3SupportedCiphers()
                {
-                       TlsCipherSuiteCollection scs = new TlsCipherSuiteCollection();
+                       TlsCipherSuiteCollection scs = new TlsCipherSuiteCollection(TlsProtocol.Ssl3);
 
                        // Supported ciphers
                        scs.Add((0x00 << 0x08) | 0x0A, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", "3DES", "SHA", false, true, 24, 24, 168, 8, 8);
index 58f79b07bfcf21b46b60a9b6eb9d77201d5000b0..58f63c317c1de4bb137d7fb7208508d1219d5559 100644 (file)
@@ -32,6 +32,5 @@ namespace Mono.Security.Protocol.Tls
                Alert                           = 21,
                Handshake                       = 22,
                ApplicationData         = 23,
-               Unknown                         = 255
        }
 }
index 4d9d62c7e96594ec26a9ca0dd1cb3828b6be6817..1303c7c3b80f66b4937ab99501bf7f87a7605f5f 100644 (file)
@@ -46,10 +46,7 @@ namespace Mono.Security.Protocol.Tls
                
                private byte[]                                          sessionId;
                private TlsSessionContext                       context;
-               private bool                                            helloDone;
-               private bool                                            handshakeFinished;
                private TlsSessionSettings                      settings;
-               private TlsCipherSuiteCollection        supportedCiphers;
                private TlsSocket                                       socket;
                private TlsNetworkStream                        networkStream;
                private bool                                            isSecure;
@@ -83,23 +80,6 @@ namespace Mono.Security.Protocol.Tls
                        get { return context; }
                }
 
-               internal TlsCipherSuiteCollection SupportedCiphers
-               {
-                       get { return supportedCiphers; }
-               }
-                               
-               internal bool HelloDone
-               {
-                       get { return helloDone; }
-                       set { helloDone = value; }
-               }
-
-               internal bool HandshakeFinished
-               {
-                       get { return handshakeFinished; }
-                       set { handshakeFinished = value; }
-               }
-
                internal bool IsSecure
                {
                        get { return isSecure; }
@@ -163,10 +143,10 @@ namespace Mono.Security.Protocol.Tls
                        {
                                this.context.Protocol                   = settings.Protocol;
                                this.context.CompressionMethod  = settings.CompressionMethod;
-                               this.state                                              = TlsSessionState.OpeningSecure;
-                               this.supportedCiphers                   = TlsCipherSuiteFactory.GetSupportedCiphers(context.Protocol);
+                               this.context.SupportedCiphers   = TlsCipherSuiteFactory.GetSupportedCiphers(context.Protocol);
+                               this.state                                              = TlsSessionState.OpeningSecure;                                
                                this.socket.DoHandshake();
-                               this.state                              = TlsSessionState.OpenSecure;
+                               this.state                                              = TlsSessionState.OpenSecure;
                        }
                        catch (TlsException ex)
                        {
@@ -276,8 +256,6 @@ namespace Mono.Security.Protocol.Tls
 
                        // Reset session information
                        this.isSecure                   = false;
-                       this.helloDone                  = false;
-                       this.handshakeFinished  = false;
                        this.context                    = new TlsSessionContext();
                        this.sessionId                  = new byte[0];                  
                }
index fe98dd997040e4cd6ee14adb12d05f2bfe970e39..8456a3ebfe5487522f4a6d35a746a8fa7c0f609e 100644 (file)
@@ -44,11 +44,16 @@ namespace Mono.Security.Protocol.Tls
                // 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;
-               private TlsCipherSuite          cipher;
-
+               
                // Sequence numbers
                private long                            writeSequenceNumber;
                private long                            readSequenceNumber;
@@ -56,6 +61,8 @@ namespace Mono.Security.Protocol.Tls
                // Random data
                private byte[]                          clientRandom;
                private byte[]                          serverRandom;
+               private byte[]                          randomCS;
+               private byte[]                          randomSC;
 
                // Key information
                private byte[]                          masterSecret;
@@ -81,109 +88,139 @@ namespace Mono.Security.Protocol.Tls
 
                public TlsProtocol Protocol
                {
-                       get { return protocol; }
-                       set { protocol = value; }
+                       get { return this.protocol; }
+                       set { this.protocol = value; }
                }
 
                public TlsCompressionMethod CompressionMethod
                {
-                       get { return compressionMethod; }
-                       set { compressionMethod = value; }
+                       get { return this.compressionMethod; }
+                       set { this.compressionMethod = value; }
                }
 
                public TlsServerSettings ServerSettings
                {
-                       get { return serverSettings; }
-                       set { serverSettings = value; }
+                       get { return this.serverSettings; }
+                       set { this.serverSettings = value; }
                }
 
                public bool     IsActual
                {
-                       get { return isActual; }
-                       set { isActual = value; }
+                       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 connectionEnd; }
-                       set { connectionEnd = value; }
+                       get { return this.connectionEnd; }
+                       set { this.connectionEnd = value; }
                }
 
-               public TlsCipherSuite Cipher
+               public CipherSuite Cipher
                {
-                       get { return cipher; }
-                       set { cipher = value; }
+                       get { return this.cipher; }
+                       set { this.cipher = value; }
+               }
+
+               public TlsCipherSuiteCollection SupportedCiphers
+               {
+                       get { return supportedCiphers; }
+                       set { supportedCiphers = value; }
                }
 
                public TlsHandshakeHashes HandshakeHashes
                {
-                       get { return handshakeHashes; }
+                       get { return this.handshakeHashes; }
                }
 
                public long WriteSequenceNumber
                {
-                       get { return writeSequenceNumber; }
-                       set { writeSequenceNumber = value; }
+                       get { return this.writeSequenceNumber; }
+                       set { this.writeSequenceNumber = value; }
                }
 
                public long ReadSequenceNumber
                {
-                       get { return readSequenceNumber; }
-                       set { readSequenceNumber = value; }
+                       get { return this.readSequenceNumber; }
+                       set { this.readSequenceNumber = value; }
                }
 
                public byte[] ClientRandom
                {
-                       get { return clientRandom; }
-                       set { clientRandom = value; }
+                       get { return this.clientRandom; }
+                       set { this.clientRandom = value; }
                }
 
                public byte[] ServerRandom
                {
-                       get { return serverRandom; }
-                       set { serverRandom = value; }
+                       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 masterSecret; }
-                       set { masterSecret = value; }
+                       get { return this.masterSecret; }
+                       set { this.masterSecret = value; }
                }
 
                public byte[] ClientWriteMAC
                {
-                       get { return clientWriteMAC; }
-                       set { clientWriteMAC = value; }
+                       get { return this.clientWriteMAC; }
+                       set { this.clientWriteMAC = value; }
                }
 
                public byte[] ServerWriteMAC
                {
-                       get { return serverWriteMAC; }
-                       set { serverWriteMAC = value; }
+                       get { return this.serverWriteMAC; }
+                       set { this.serverWriteMAC = value; }
                }
 
                public byte[] ClientWriteKey
                {
-                       get { return clientWriteKey; }
-                       set { clientWriteKey = value; }
+                       get { return this.clientWriteKey; }
+                       set { this.clientWriteKey = value; }
                }
 
                public byte[] ServerWriteKey
                {
-                       get { return serverWriteKey; }
-                       set { serverWriteKey = value; }
+                       get { return this.serverWriteKey; }
+                       set { this.serverWriteKey = value; }
                }
 
                public byte[] ClientWriteIV
                {
-                       get { return clientWriteIV; }
-                       set { clientWriteIV = value; }
+                       get { return this.clientWriteIV; }
+                       set { this.clientWriteIV = value; }
                }
 
                public byte[] ServerWriteIV
                {
-                       get { return serverWriteIV; }
-                       set { serverWriteIV = value; }
+                       get { return this.serverWriteIV; }
+                       set { this.serverWriteIV = value; }
                }
 
                #endregion
@@ -223,23 +260,23 @@ namespace Mono.Security.Protocol.Tls
                public void ClearKeyInfo()
                {
                        // Clear Master Secret
-                       masterSecret    = null;
+                       this.masterSecret       = null;
 
                        // Clear client and server random
-                       clientRandom    = null;
-                       serverRandom    = null;
+                       this.clientRandom       = null;
+                       this.serverRandom       = null;
+                       this.randomCS           = null;
+                       this.randomSC           = null;
 
                        // Clear client keys
-                       clientWriteKey  = null;
-                       clientWriteIV   = null;
-                       clientWriteMAC  = null;
+                       this.clientWriteKey     = null;
+                       this.clientWriteIV      = null;
+                       this.clientWriteMAC     = null;
 
                        // Clear server keys
-                       serverWriteKey  = null;
-                       serverWriteIV   = null;
-                       serverWriteMAC  = null;
-
-                       // Force the GC to recollect the memory ??
+                       this.serverWriteKey     = null;
+                       this.serverWriteIV      = null;
+                       this.serverWriteMAC     = null;
                }
 
                #endregion
index 7617eecbb1a205bf52a79ea0bb19a4f50b38513c..7614e99f2079aa8fbea7906042e87785aa28ff33 100644 (file)
@@ -66,7 +66,8 @@ namespace Mono.Security.Protocol.Tls
                        get { return protocol; }
                        set 
                        { 
-                               if (value != TlsProtocol.Tls1)
+                               if (value != TlsProtocol.Tls1 &&
+                                       value != TlsProtocol.Ssl3)
                                {
                                        throw new NotSupportedException("Specified protocol is not supported");
                                }
index e1a2fe375f517d48fda5efd1ca78b3be0bbf8d77..8ddf9d9add51410eb6570c1fff2fa73e6c4d0145 100644 (file)
@@ -54,7 +54,7 @@ namespace Mono.Security.Protocol.Tls
 
                internal BufferedStream InputBuffer
                {
-                       get { return inputBuffer; }
+                       get { return this.inputBuffer; }
                }
 
                #endregion
@@ -112,33 +112,33 @@ namespace Mono.Security.Protocol.Tls
 
                public new int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags)
                {
-                       if (!session.IsSecure)
+                       if (!this.session.IsSecure)
                        {
                                return base.Receive(buffer, offset, size, socketFlags);
                        }
                        
                        // If actual buffer is full readed reset it
-                       if (inputBuffer.Position == inputBuffer.Length)
+                       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 ((inputBuffer.Length - inputBuffer.Position) < size)
+                       while ((this.inputBuffer.Length - this.inputBuffer.Position) < size)
                        {
                                // Read next record and write it into the inputBuffer
-                               long    position        = inputBuffer.Position;                                 
+                               long    position        = this.inputBuffer.Position;                                    
                                byte[]  record          = this.receiveRecord();
 
                                if (record.Length > 0)
                                {
                                        // Write new data to the inputBuffer
-                                       inputBuffer.Seek(0, SeekOrigin.End);
-                                       inputBuffer.Write(record, 0, record.Length);
+                                       this.inputBuffer.Seek(0, SeekOrigin.End);
+                                       this.inputBuffer.Write(record, 0, record.Length);
 
                                        // Restore buffer position
-                                       inputBuffer.Seek(position, SeekOrigin.Begin);
+                                       this.inputBuffer.Seek(position, SeekOrigin.Begin);
                                }
 
                                if (base.Available == 0)
@@ -147,7 +147,7 @@ namespace Mono.Security.Protocol.Tls
                                }
                        }
 
-                       return inputBuffer.Read(buffer, offset, size);
+                       return this.inputBuffer.Read(buffer, offset, size);
                }
 
                public new int Send(byte[] buffer)
@@ -167,7 +167,7 @@ namespace Mono.Security.Protocol.Tls
 
                public new int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags)
                {
-                       if (!session.IsSecure)
+                       if (!this.session.IsSecure)
                        {
                                return base.Send(buffer, offset, size, socketFlags);
                        }
@@ -185,14 +185,14 @@ namespace Mono.Security.Protocol.Tls
 
                private byte[] receiveRecord()
                {
-                       if (session.Context.ConnectionEnd)
+                       if (this.session.Context.ConnectionEnd)
                        {
-                               throw session.CreateException("The session is finished and it's no longer valid.");
+                               throw this.session.CreateException("The session is finished and it's no longer valid.");
                        }
                        
                        TlsContentType  contentType     = (TlsContentType)this.ReadByte();
                        TlsProtocol             protocol        = (TlsProtocol)this.ReadShort();
-                       int                             length          = this.ReadShort();
+                       short                   length          = this.ReadShort();
                        
                        // Read Record data
                        int             received        = 0;
@@ -203,17 +203,16 @@ namespace Mono.Security.Protocol.Tls
                                        buffer, received, buffer.Length - received, SocketFlags.None);
                        }
 
-                       TlsStream message       = new TlsStream(buffer);
+                       TlsStream message = new TlsStream(buffer);
                
-                       // Check that the message as a valid protocol version
-                       if (protocol != session.Context.Protocol)
+                       // 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)
+                       if (contentType == TlsContentType.Alert && length == 2)
                        {
                        }
                        else
@@ -221,9 +220,9 @@ namespace Mono.Security.Protocol.Tls
                                if (session.Context.IsActual &&
                                        contentType != TlsContentType.ChangeCipherSpec)
                                {
-                                       message = decryptRecordFragment(
+                                       message = this.decryptRecordFragment(
                                                contentType, 
-                                               protocol, 
+                                               protocol,
                                                message.ToArray());
                                }
                        }
@@ -234,13 +233,13 @@ namespace Mono.Security.Protocol.Tls
                        switch (contentType)
                        {
                                case TlsContentType.Alert:
-                                       processAlert((TlsAlertLevel)message.ReadByte(),
+                                       this.processAlert((TlsAlertLevel)message.ReadByte(),
                                                (TlsAlertDescription)message.ReadByte());
                                        break;
 
                                case TlsContentType.ChangeCipherSpec:
                                        // Reset sequence numbers
-                                       session.Context.ReadSequenceNumber = 0;
+                                       this.session.Context.ReadSequenceNumber = 0;
                                        break;
 
                                case TlsContentType.ApplicationData:
@@ -249,7 +248,7 @@ namespace Mono.Security.Protocol.Tls
                                case TlsContentType.Handshake:
                                        while (!message.EOF)
                                        {
-                                               processHandshakeMessage(message);
+                                               this.processHandshakeMessage(message);
                                        }
                                        // Update handshakes of current messages
                                        this.session.Context.HandshakeHashes.Update(message.ToArray());
@@ -269,21 +268,21 @@ namespace Mono.Security.Protocol.Tls
                private byte[] encryptRecordFragment(TlsContentType contentType, byte[] fragment)
                {
                        // Calculate message MAC
-                       byte[] mac      = encodeClientRecordMAC(contentType, fragment);
+                       byte[] mac      = this.session.Context.Cipher.ComputeClientRecordMAC(contentType, fragment);
 
                        // Encrypt the message
-                       byte[] ecr = session.Context.Cipher.EncryptRecord(fragment, mac);
+                       byte[] ecr = this.session.Context.Cipher.EncryptRecord(fragment, mac);
 
                        // Set new IV
-                       if (session.Context.Cipher.CipherMode == CipherMode.CBC)
+                       if (this.session.Context.Cipher.CipherMode == CipherMode.CBC)
                        {
-                               byte[] iv = new byte[session.Context.Cipher.IvSize];
+                               byte[] iv = new byte[this.session.Context.Cipher.IvSize];
                                System.Array.Copy(ecr, ecr.Length - iv.Length, iv, 0, iv.Length);
-                               session.Context.Cipher.UpdateClientCipherIV(iv);
+                               this.session.Context.Cipher.UpdateClientCipherIV(iv);
                        }
 
                        // Update sequence number
-                       session.Context.WriteSequenceNumber++;
+                       this.session.Context.WriteSequenceNumber++;
 
                        return ecr;
                }
@@ -296,18 +295,18 @@ namespace Mono.Security.Protocol.Tls
                        byte[]  dcrMAC          = null;
 
                        // Decrypt message
-                       session.Context.Cipher.DecryptRecord(fragment, ref dcrFragment, ref dcrMAC);
+                       this.session.Context.Cipher.DecryptRecord(fragment, ref dcrFragment, ref dcrMAC);
 
                        // Set new IV
-                       if (session.Context.Cipher.CipherMode == CipherMode.CBC)
+                       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);
-                               session.Context.Cipher.UpdateServerCipherIV(iv);
+                               this.session.Context.Cipher.UpdateServerCipherIV(iv);
                        }
                        
                        // Check MAC code
-                       byte[] mac = this.encodeServerRecordMAC(contentType, dcrFragment);
+                       byte[] mac = this.session.Context.Cipher.ComputeServerRecordMAC(contentType, dcrFragment);
 
                        // Check that the mac is correct
                        if (mac.Length != dcrMAC.Length)
@@ -323,7 +322,7 @@ namespace Mono.Security.Protocol.Tls
                        }
 
                        // Update sequence number
-                       session.Context.ReadSequenceNumber++;
+                       this.session.Context.ReadSequenceNumber++;
 
                        return new TlsStream(dcrFragment);
                }
@@ -368,10 +367,10 @@ namespace Mono.Security.Protocol.Tls
                        int bytesSent = this.sendRecord(TlsContentType.ChangeCipherSpec, new byte[] {1});
 
                        // Reset sequence numbers
-                       session.Context.WriteSequenceNumber = 0;
+                       this.session.Context.WriteSequenceNumber = 0;
 
                        // Make the pending state to be the current state
-                       session.Context.IsActual = true;
+                       this.session.Context.IsActual = true;
 
                        // Send Finished message
                        bytesSent += this.sendRecord(TlsHandshakeType.Finished);
@@ -381,9 +380,9 @@ namespace Mono.Security.Protocol.Tls
                
                private int sendRecord(TlsContentType contentType, byte[] recordData)
                {
-                       if (session.Context.ConnectionEnd)
+                       if (this.session.Context.ConnectionEnd)
                        {
-                               throw session.CreateException("The session is finished and it's no longer valid.");
+                               throw this.session.CreateException("The session is finished and it's no longer valid.");
                        }
 
                        int                     bytesSent = 0;
@@ -392,16 +391,16 @@ namespace Mono.Security.Protocol.Tls
                        {
                                byte[] fragment = fragments[i];
 
-                               if (session.Context.IsActual)
+                               if (this.session.Context.IsActual)
                                {
                                        // Encrypt fragment
-                                       fragment = encryptRecordFragment(contentType, fragment);
+                                       fragment = this.encryptRecordFragment(contentType, fragment);
                                }
 
                                // Write tls message
                                TlsStream record = new TlsStream();
                                record.Write((byte)contentType);
-                               record.Write((short)TlsProtocol.Tls1);
+                               record.Write((short)this.session.Context.Protocol);
                                record.Write((short)fragment.Length);
                                record.Write(fragment);
 
@@ -468,7 +467,7 @@ namespace Mono.Security.Protocol.Tls
                        handMsg.Read(data, 0, length);
 
                        // Create and process the server message
-                       message = createServerHandshakeMessage(handshakeType, data);
+                       message = this.createServerHandshakeMessage(handshakeType, data);
 
                        // Update session
                        if (message != null)
@@ -477,27 +476,26 @@ namespace Mono.Security.Protocol.Tls
                        }
                }
 
-               private void processAlert(TlsAlertLevel alertLevel, 
-                       TlsAlertDescription alertDesc)
+               private void processAlert(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc)
                {
                        switch (alertLevel)
                        {
                                case TlsAlertLevel.Fatal:
-                                       throw session.CreateException(alertLevel, alertDesc);                                   
+                                       throw this.session.CreateException(alertLevel, alertDesc);                                      
 
                                case TlsAlertLevel.Warning:
                                default:
                                switch (alertDesc)
                                {
                                        case TlsAlertDescription.CloseNotify:
-                                               session.Context.ConnectionEnd = true;
+                                               this.session.Context.ConnectionEnd = true;
                                                break;
 
                                        default:
-                                               session.RaiseWarningAlert(alertLevel, alertDesc);
+                                               this.session.RaiseWarningAlert(alertLevel, alertDesc);
                                                break;
                                }
-                                       break;
+                               break;
                        }
                }
 
@@ -511,42 +509,6 @@ namespace Mono.Security.Protocol.Tls
                        this.inputBuffer.Position = 0;
                }
 
-               private byte[] encodeServerRecordMAC(TlsContentType contentType, byte[] fragment)
-               {
-                       TlsStream       data    = new TlsStream();
-                       byte[]          result  = null;
-
-                       data.Write(session.Context.ReadSequenceNumber);
-                       data.Write((byte)contentType);
-                       data.Write((short)TlsProtocol.Tls1);
-                       data.Write((short)fragment.Length);
-                       data.Write(fragment);
-
-                       result = session.Context.Cipher.ServerHMAC.ComputeHash(data.ToArray());
-
-                       data.Reset();
-
-                       return result;
-               }
-
-               private byte[] encodeClientRecordMAC(TlsContentType contentType, byte[] fragment)
-               {
-                       TlsStream       data    = new TlsStream();
-                       byte[]          result  = null;
-
-                       data.Write(session.Context.WriteSequenceNumber);
-                       data.Write((byte)contentType);
-                       data.Write((short)TlsProtocol.Tls1);
-                       data.Write((short)fragment.Length);
-                       data.Write(fragment);
-
-                       result = session.Context.Cipher.ClientHMAC.ComputeHash(data.ToArray());
-
-                       data.Reset();
-
-                       return result;
-               }
-
                private byte ReadByte()
                {
                        byte[] b = new byte[1];
@@ -599,14 +561,14 @@ namespace Mono.Security.Protocol.Tls
                        this.sendRecord(TlsHandshakeType.ClientHello);
 
                        // Read server response
-                       while (!session.HelloDone)
+                       while (!this.session.Context.HelloDone)
                        {
                                // Read next record
                                this.receiveRecord();
                        }
                        
                        // Send client certificate if requested
-                       if (session.Context.ServerSettings.CertificateRequest)
+                       if (this.session.Context.ServerSettings.CertificateRequest)
                        {
                                this.sendRecord(TlsHandshakeType.Certificate);
                        }
@@ -618,7 +580,7 @@ namespace Mono.Security.Protocol.Tls
                        this.session.Context.Cipher.InitializeCipher();
 
                        // Send certificate verify if requested
-                       if (session.Context.ServerSettings.CertificateRequest)
+                       if (this.session.Context.ServerSettings.CertificateRequest)
                        {
                                this.sendRecord(TlsHandshakeType.CertificateVerify);
                        }
@@ -630,7 +592,7 @@ namespace Mono.Security.Protocol.Tls
                        this.receiveRecord();
 
                        // Read server finished
-                       if (!session.HandshakeFinished)
+                       if (!this.session.Context.HandshakeFinished)
                        {
                                this.receiveRecord();
                        }
@@ -693,7 +655,7 @@ namespace Mono.Security.Protocol.Tls
                                        return new TlsServerFinished(session, buffer);
 
                                default:
-                                       throw session.CreateException("Unknown server handshake message received ({0})", type.ToString());
+                                       throw this.session.CreateException("Unknown server handshake message received ({0})", type.ToString());
                        }
                }
 
index e05ba3da325f0567040b84dea0592d34b1dbbf0a..1733e1a67f33f2acdb0692a89be7abef31feff44 100755 (executable)
@@ -33,8 +33,29 @@ using Mono.Security.Cryptography;
 
 namespace Mono.Security.Protocol.Tls
 {
-       internal class TlsSslCipherSuite : TlsAbstractCipherSuite
+       internal class TlsSslCipherSuite : CipherSuite
        {
+               #region FIELDS
+
+               private byte[] pad1;
+               private byte[] pad2;
+
+               #endregion
+
+               #region PROPERTIES
+
+               public byte[] Pad1
+               {
+                       get { return pad1; }
+               }
+
+               public byte[] Pad2
+               {
+                       get { return pad2; }
+               }
+
+               #endregion
+
                #region CONSTRUCTORS
                
                public TlsSslCipherSuite(short code, string name, string algName, 
@@ -45,84 +66,207 @@ namespace Mono.Security.Protocol.Tls
                        keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes,
                        ivSize, blockSize)
                {
+                       this.GeneratePad(hashName, ref this.pad1, ref this.pad2);
                }
 
                #endregion
 
-               #region METHODS
+               #region MAC_GENERATION_METHOD
 
-               public override byte[] EncryptRecord(byte[] fragment, byte[] mac)
+               public override byte[] ComputeServerRecordMAC(TlsContentType contentType, byte[] fragment)
                {
-                       // Encryption ( fragment + mac [+ padding + padding_length] )
-                       MemoryStream ms = new MemoryStream();
-                       CryptoStream cs = new CryptoStream(ms, encryptionCipher, CryptoStreamMode.Write);
+                       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);
+                       
+                       byte[] blockHash = hash.ComputeHash(block.ToArray(), 0, (int)block.Length);
+
+                       block.Reset();
+
+                       block.Write(this.Context.ServerWriteMAC);
+                       block.Write(this.pad2);
+                       block.Write(blockHash);
 
-                       cs.Write(fragment, 0, fragment.Length);
-                       cs.Write(mac, 0, mac.Length);
-                       if (cipherMode == CipherMode.CBC)
+                       blockHash = hash.ComputeHash(block.ToArray(), 0, (int)block.Length);
+
+                       block.Reset();
+
+                       return blockHash;
+               }
+
+               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);
+                       
+                       byte[] blockHash = hash.ComputeHash(block.ToArray(), 0, (int)block.Length);
+
+                       block.Reset();
+
+                       block.Write(this.Context.ClientWriteMAC);
+                       block.Write(this.pad2);
+                       block.Write(blockHash);
+
+                       blockHash = hash.ComputeHash(block.ToArray(), 0, (int)block.Length);
+
+                       block.Reset();
+
+                       return blockHash;
+               }
+
+               public void GeneratePad(string hashName, ref byte[] pad1, ref byte[] pad2)
+               {
+                       switch (hashName)
                        {
-                               // Calculate padding_length
-                               int fragmentLength      = fragment.Length + mac.Length + 1;
-                               int paddingLength       = (((fragmentLength/blockSize)*8) + blockSize) - fragmentLength;
+                               case "MD5":
+                                       pad1 = new byte[48];
+                                       pad2 = new byte[48];
+                                       break;
 
-                               // Write padding length byte
-                               cs.WriteByte((byte)paddingLength);
+                               case "SHA":
+                               case "SHA1":
+                                       pad1 = new byte[40];
+                                       pad2 = new byte[40];                                    
+                                       break;
                        }
-                       //cs.FlushFinalBlock();
-                       cs.Close();                     
 
-                       return ms.ToArray();
+                       for (int i = 0; i  < pad1.Length; i++)
+                       {
+                               pad1[i] = (byte)0x36;
+                               pad2[i] = (byte)0x5C;
+                       }
                }
 
-               public override void DecryptRecord(byte[] fragment, ref byte[] dcrFragment, ref byte[] dcrMAC)
+               #endregion
+
+               #region KEY_GENERATION_METODS
+
+               public override void ComputeMasterSecret(byte[] preMasterSecret)
                {
-                       int     fragmentSize    = 0;
-                       int paddingLength       = 0;
+                       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));
 
-                       // Decrypt message fragment ( fragment + mac [+ padding + padding_length] )
-                       byte[] buffer = new byte[fragment.Length];
-                       decryptionCipher.TransformBlock(fragment, 0, fragment.Length, buffer, 0);
+                       this.Context.MasterSecret = masterSecret.ToArray();
+               }
 
-                       // Calculate fragment size
-                       if (cipherMode == CipherMode.CBC)
+               public override void ComputeKeys()
+               {
+                       // Compute KeyBlock
+                       TlsStream tmp = new TlsStream();
+                       
+                       char    labelChar       = 'A';
+                       int             count           = 1;
+                       while (tmp.Length < this.KeyBlockSize)
                        {
-                               // Calculate padding_length
-                               paddingLength = buffer[buffer.Length - 1];
-                               for (int i = (buffer.Length - 1); i > (buffer.Length - (paddingLength + 1)); i--)
+                               string label = String.Empty;
+
+                               for (int i = 0; i < count; i++)
                                {
-                                       if (buffer[i] != paddingLength)
-                                       {
-                                               paddingLength = 0;
-                                               break;
-                                       }
+                                       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);
 
-                               fragmentSize = (buffer.Length - (paddingLength + 1)) - HashSize;
+                               labelChar++;
+                               count++;
                        }
-                       else
+                       
+                       // 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)
                        {
-                               fragmentSize = buffer.Length - HashSize;
+                               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();
 
-                       dcrFragment = new byte[fragmentSize];
-                       dcrMAC          = new byte[HashSize];
+                               // 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);
 
-                       Buffer.BlockCopy(buffer, 0, dcrFragment, 0, dcrFragment.Length);
-                       Buffer.BlockCopy(buffer, dcrFragment.Length, dcrMAC, 0, dcrMAC.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 KEY_GENERATION_METODS
+               #region PRIVATE_METHODS
 
-               public override void CreateMasterSecret(byte[] preMasterSecret)
+               private byte[] prf(byte[] secret, string label, byte[] random)
                {
-                       throw new NotSupportedException();
-               }
+                       MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
+                       SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
 
-               public override void CreateKeys()
-               {
-                       throw new NotSupportedException();
+                       // 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