2004-03-17 Carlos Guzman Alvarez <carlosga@telefonica.net>
authorCarlos Guzmán Álvarez <carlos@mono-cvs.ximian.com>
Wed, 17 Mar 2004 16:54:32 +0000 (16:54 -0000)
committerCarlos Guzmán Álvarez <carlos@mono-cvs.ximian.com>
Wed, 17 Mar 2004 16:54:32 +0000 (16:54 -0000)
* Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificate.cs:
* Mono.Security.Protocol.Tls.Handshake.Server/TlsServerKeyExchange.cs:

- Initial implementation.

2004-03-16 Carlos Guzman Alvarez  <carlosga@telefonica.net>

* Mono.Security.Protocol.Tls/SslCipherSuite.cs:

- Added changes for allow it to work as server or client.

2004-03-15 Carlos Guzman Alvarez  <carlosga@telefonica.net>

* Mono.Security.Protocol.Tls/TlsStream.cs:
* Mono.Security.Protocol.Tls/CipherSuite.cs:
* Mono.Security.Protocol.Tls/TlsCipherSuite.cs:
* Mono.Security.Protocol.Tls/SslHandshakeHash.cs:
* Mono.Security.Protocol.Tls/RecordProtocol.cs:
* Mono.Security.Cryptography/MD5SHA1.cs:

- Use Buffer.BlockCopy instead of System.Array.Copy

svn path=/trunk/mcs/; revision=24233

16 files changed:
mcs/class/Mono.Security/ChangeLog
mcs/class/Mono.Security/Mono.Security.Cryptography/MD5SHA1.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificateRequest.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificate.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientFinished.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientHello.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsServerKeyExchange.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ChangeLog
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/CipherSuite.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/Context.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslCipherSuite.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslHandshakeHash.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslServerStream.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsCipherSuite.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsStream.cs

index 65d4e01303903cec6797fb1d8c7c8e2a9dd035ec..da39d7310bfea8aad27bd1b29360ae1b06dbe914 100644 (file)
@@ -1,3 +1,29 @@
+2004-03-17 Carlos Guzman Alvarez  <carlosga@telefonica.net>\r
+\r
+       * Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificate.cs:\r
+       * Mono.Security.Protocol.Tls.Handshake.Server/TlsServerKeyExchange.cs:\r
+\r
+               - Initial implementation.\r
+\r
+\r
+2004-03-16 Carlos Guzman Alvarez  <carlosga@telefonica.net>\r
+\r
+       * Mono.Security.Protocol.Tls/SslCipherSuite.cs:\r
+\r
+               - Added changes for allow it to work as server or client.\r
+\r
+\r
+2004-03-15 Carlos Guzman Alvarez  <carlosga@telefonica.net>\r
+\r
+       * Mono.Security.Protocol.Tls/TlsStream.cs:\r
+       * Mono.Security.Protocol.Tls/CipherSuite.cs:\r
+       * Mono.Security.Protocol.Tls/TlsCipherSuite.cs:\r
+       * Mono.Security.Protocol.Tls/SslHandshakeHash.cs:\r
+       * Mono.Security.Protocol.Tls/RecordProtocol.cs:\r
+       * Mono.Security.Cryptography/MD5SHA1.cs:\r
+\r
+               - Use Buffer.BlockCopy instead of System.Array.Copy
+
 2004-03-10 Carlos Guzman Alvarez  <carlosga@telefonica.net>\r
 \r
        * Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs:\r
index 9bc6f77bb75290fab99e64e8c7467beb3b14ac44..38d8e84702210c9bfbf047a95677d98a7f9c6a61 100644 (file)
@@ -73,8 +73,8 @@ namespace Mono.Security.Cryptography
 
                        byte[] hash = new byte[36];
 
-                       System.Array.Copy(this.md5.Hash, 0, hash, 0, 16);
-                       System.Array.Copy(this.sha.Hash, 0, hash, 16, 20);
+                       Buffer.BlockCopy(this.md5.Hash, 0, hash, 0, 16);
+                       Buffer.BlockCopy(this.sha.Hash, 0, hash, 16, 20);
 
                        return hash;
                }
index 0ca678d92b64226e91727f0e5762d07042b57fcb..809d644a1eb2084ad7a79fad3cc2c430b01f314c 100644 (file)
@@ -91,11 +91,10 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                         */
                        if (this.ReadInt16() != 0)
                        {
-                               ASN1    rdn = new ASN1(this.ReadBytes(this.ReadInt16()));
+                               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
index b6ae6375ee3f6c06a826e35c15d03e77a01c47bb..47020efaa464babfab46c28cf041a130520e9a82 100644 (file)
@@ -30,6 +30,12 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 {
        internal class TlsClientCertificate : HandshakeMessage
        {
+               #region Fields
+
+               private X509Certificate clientCertificate;
+
+               #endregion
+
                #region Constructors
 
                public TlsClientCertificate(Context context, byte[] buffer)
@@ -43,7 +49,7 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 
                public override void Update()
                {
-                       throw new NotSupportedException();
+                       this.Context.ClientSettings.Certificates.Add(clientCertificate);
                }
 
                #endregion
@@ -57,7 +63,10 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 
                protected override void ProcessAsTls1()
                {
-                       throw new NotSupportedException();
+                       int length = this.ReadInt24();
+                       this.clientCertificate = new X509Certificate(this.ReadBytes(length));
+
+#warning "Is client certificate validation needed ??"
                }
 
                #endregion
index 1099c02b6b54a866c158b85c0952e73ba9ca260f..66e968f12fb9865f0d0943eae901dfbc6176c700 100644 (file)
@@ -44,6 +44,8 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 
                protected override void ProcessAsSsl3()
                {
+                       bool decryptError = false;
+
                        // Compute handshake messages hashes
                        HashAlgorithm hash = new SslHandshakeHash(this.Context.MasterSecret);
 
@@ -61,22 +63,33 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
                        // Check client prf against server prf
                        if (clientHash.Length != serverHash.Length)
                        {
-                               throw new TlsException("Invalid ServerFinished message received.");
+                               decryptError = true;
                        }
-
-                       for (int i = 0; i < clientHash.Length; i++)
+                       else
                        {
-                               if (clientHash[i] != serverHash[i])
+                               for (int i = 0; i < clientHash.Length; i++)
                                {
-                                       throw new TlsException("Invalid ServerFinished message received.");
+                                       if (clientHash[i] != serverHash[i])
+                                       {
+                                               decryptError = true;
+                                               break;
+                                       }
                                }
                        }
+
+                       if (decryptError)
+                       {
+                               this.Context.RecordProtocol.SendAlert(AlertDescription.DecryptError);
+
+                               throw new TlsException("Decrypt error.");
+                       }
                }
 
                protected override void ProcessAsTls1()
                {
-                       byte[]                  clientPRF       = this.ReadBytes((int)this.Length);
-                       HashAlgorithm   hash            = new MD5SHA1();
+                       byte[]                  clientPRF               = this.ReadBytes((int)this.Length);
+                       HashAlgorithm   hash                    = new MD5SHA1();
+                       bool                    decryptError    = false;
 
                        hash.ComputeHash(
                                this.Context.HandshakeMessages.ToArray(), 
@@ -89,16 +102,25 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
                        // Check client prf against server prf
                        if (clientPRF.Length != serverPRF.Length)
                        {
-                               throw new TlsException("Invalid ServerFinished message received.");
+                               decryptError = true;
                        }
-
-                       for (int i = 0; i < serverPRF.Length; i++)
+                       else
                        {
-                               if (clientPRF[i] != serverPRF[i])
+                               for (int i = 0; i < serverPRF.Length; i++)
                                {
-                                       throw new TlsException("Invalid ServerFinished message received.");
+                                       if (clientPRF[i] != serverPRF[i])
+                                       {
+                                               decryptError = true;
+                                       }
                                }
                        }
+
+                       if (decryptError)
+                       {
+                               this.Context.RecordProtocol.SendAlert(AlertDescription.DecryptError);
+
+                               throw new TlsException("Decrypt error.");
+                       }
                }
 
                #endregion
index ac94f34b931b11ed14841d95dafc24486601bbbe..e248da0a862f671b13bb6192f7e9ceab54e8c233 100644 (file)
@@ -118,7 +118,8 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
                        }
                        else
                        {
-#warning "Send alert"
+                               this.Context.RecordProtocol.SendAlert(AlertDescription.ProtocolVersion);
+
                                throw this.Context.CreateException("Incorrect protocol version received from server");
                        }
                }
@@ -126,6 +127,7 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
                private void selectCipherSuite()
                {
                        int index = 0;
+
                        for (int i = 0; i < this.cipherSuites.Length; i++)
                        {
                                if ((index = this.Context.SupportedCiphers.IndexOf(this.cipherSuites[i])) != -1)        
@@ -136,7 +138,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 
                        if (this.Context.Cipher == null)
                        {
-#warning "Send an Alert and Throw and exception"
+                               this.Context.RecordProtocol.SendAlert(AlertDescription.InsuficientSecurity);
+
+                               throw this.Context.CreateException("Insuficient Security");
                        }
                }
 
index 761affb347bddc402fc5eb7104605dea38ceab62..6049c5948de727f569eea72b33b849585ea54805 100644 (file)
@@ -25,6 +25,8 @@
 using System;
 using System.Security.Cryptography;
 
+using SX509 = System.Security.Cryptography.X509Certificates;
+
 using Mono.Security.Cryptography;
 using Mono.Security.X509;
 
@@ -59,7 +61,48 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 
                protected override void ProcessAsTls1()
                {
-                       throw new NotSupportedException();
+                       ServerContext context = (ServerContext)this.Context;
+
+                       // Select the private key information
+                       RSA rsa = (RSA)context.SslStream.PrivateKeyCertSelectionDelegate(
+                               new SX509.X509Certificate(context.ServerSettings.Certificates[0].RawData),
+                               null);
+
+                       RSAParameters rsaParams = rsa.ExportParameters(false);
+
+                       // Write Modulus
+                       this.WriteInt24(rsaParams.Modulus.Length);
+                       this.Write(rsaParams.Modulus, 0, rsaParams.Modulus.Length);
+                       
+                       // Write exponent
+                       this.WriteInt24(rsaParams.Exponent.Length);
+                       this.Write(rsaParams.Exponent, 0, rsaParams.Exponent.Length);
+
+                       // Write signed params
+                       byte[] signature = this.createSignature(rsa, this.ToArray());
+                       this.WriteInt24(signature.Length);
+                       this.Write(signature);
+               }
+
+               #endregion
+
+               #region Private Methods
+
+               private byte[] createSignature(RSA rsa, byte[] buffer)
+               {
+                       MD5SHA1 hash = new MD5SHA1();
+
+                       // Create server params array
+                       TlsStream stream = new TlsStream();
+
+                       stream.Write(this.Context.RandomCS);
+                       stream.Write(buffer, 0, buffer.Length);
+
+                       hash.ComputeHash(stream.ToArray());
+
+                       stream.Reset();
+
+                       return hash.CreateSignature(rsa);                       
                }
 
                #endregion
index dae07bf116c44bc738169287c935869e48c4bedd..f356280191ef3a6f97af3af59a40548211465771 100644 (file)
@@ -1,3 +1,19 @@
+2004-03-16 Carlos Guzman Alvarez  <carlosga@telefonica.net>\r
+\r
+       * Mono.Security.Protocol.Tls/SslCipherSuite.cs:\r
+\r
+               - Added changes for allow it to work as server or client.\r
+\r
+2004-03-15 Carlos Guzman Alvarez  <carlosga@telefonica.net>\r
+\r
+       * Mono.Security.Protocol.Tls/TlsStream.cs:\r
+       * Mono.Security.Protocol.Tls/CipherSuite.cs:\r
+       * Mono.Security.Protocol.Tls/TlsCipherSuite.cs:\r
+       * Mono.Security.Protocol.Tls/SslHandshakeHash.cs:\r
+       * Mono.Security.Protocol.Tls/RecordProtocol.cs:\r
+\r
+               - Use Buffer.BlockCopy instead of System.Array.Copy
+
 2004-03-10 Carlos Guzman Alvarez  <carlosga@telefonica.net>\r
 \r
        * Mono.Security.Protocol.Tls/Ciphersuite.cs:\r
index e8db72d48137c8919daefbe88170c5310d024949..92802bc0ed9d50e4090a91ad9c12f7d864505207 100755 (executable)
@@ -390,11 +390,11 @@ namespace Mono.Security.Protocol.Tls
 
                        // Secret 1
                        byte[] secret1 = new byte[secretLen];
-                       System.Array.Copy(secret, 0, secret1, 0, secretLen);
+                       Buffer.BlockCopy(secret, 0, secret1, 0, secretLen);
 
                        // Secret2
                        byte[] secret2 = new byte[secretLen];
-                       System.Array.Copy(secret, secretLen, secret2, 0, secretLen);
+                       Buffer.BlockCopy(secret, secretLen, secret2, 0, secretLen);
 
                        // Secret 1 processing
                        byte[] p_md5 = Expand("MD5", secret1, seed, length);
@@ -440,7 +440,7 @@ namespace Mono.Security.Protocol.Tls
 
                        byte[] res = new byte[length];
                        
-                       System.Array.Copy(resMacs.ToArray(), 0, res, 0, res.Length);
+                       Buffer.BlockCopy(resMacs.ToArray(), 0, res, 0, res.Length);
 
                        resMacs.Reset();
 
index ef19154e1cf7a6170af4bcfed4e0770c812dc993..7909ba945f9abb91a776f363ce01315b8753b72f 100644 (file)
@@ -101,6 +101,9 @@ namespace Mono.Security.Protocol.Tls
                // Secure Random generator              
                private RandomNumberGenerator random;
 
+               // Record protocol
+               private RecordProtocol recordProtocol;
+
                #endregion
 
                #region Properties
@@ -306,6 +309,12 @@ namespace Mono.Security.Protocol.Tls
                        set { this.serverWriteIV = value; }
                }
 
+               public RecordProtocol RecordProtocol
+               {
+                       get { return this.recordProtocol; }
+                       set { this.recordProtocol = value; }
+               }
+
                #endregion
 
                #region Constructors
index 547d9ef77337316823b5c6ace523db2213fc0a01..ce2ee614bec6520ab6fb25ac126da981bb79c327 100644 (file)
@@ -60,8 +60,9 @@ namespace Mono.Security.Protocol.Tls
 
                public RecordProtocol(Stream innerStream, Context context)
                {
-                       this.innerStream        = innerStream;
-                       this.context            = context;
+                       this.innerStream                        = innerStream;
+                       this.context                            = context;
+                       this.context.RecordProtocol = this;
                }
 
                #endregion
@@ -348,7 +349,7 @@ namespace Mono.Security.Protocol.Tls
                        if (this.context.Cipher.CipherMode == CipherMode.CBC)
                        {
                                byte[] iv = new byte[this.context.Cipher.IvSize];
-                               System.Array.Copy(ecr, ecr.Length - iv.Length, iv, 0, iv.Length);
+                               Buffer.BlockCopy(ecr, ecr.Length - iv.Length, iv, 0, iv.Length);
 
                                this.context.Cipher.UpdateClientCipherIV(iv);
                        }
@@ -363,14 +364,27 @@ namespace Mono.Security.Protocol.Tls
                        ContentType     contentType, 
                        byte[]          fragment)
                {
-                       byte[]  dcrFragment     = null;
-                       byte[]  dcrMAC          = null;
+                       byte[]  dcrFragment             = null;
+                       byte[]  dcrMAC                  = null;
+                       bool    badRecordMac    = false;
 
-                       // Decrypt message
-                       this.context.Cipher.DecryptRecord(fragment, ref dcrFragment, ref dcrMAC);
+                       try
+                       {
+                               this.context.Cipher.DecryptRecord(fragment, ref dcrFragment, ref dcrMAC);
+                       }
+                       catch
+                       {
+                               if (this.context is ServerContext)
+                               {
+                                       this.Context.RecordProtocol.SendAlert(AlertDescription.DecryptionFailed);
+                               }
+
+                               throw;
+                       }
                        
-                       // Check MAC code
+                       // Generate record MAC
                        byte[] mac = null;
+
                        if (this.Context is ClientContext)
                        {
                                mac = this.context.Cipher.ComputeServerRecordMAC(contentType, dcrFragment);
@@ -380,18 +394,31 @@ namespace Mono.Security.Protocol.Tls
                                mac = this.context.Cipher.ComputeClientRecordMAC(contentType, dcrFragment);
                        }
 
-                       // Check that the mac is correct
+                       // Check record MAC
                        if (mac.Length != dcrMAC.Length)
                        {
-                               throw new TlsException("Invalid MAC received from server.");
+                               badRecordMac = true;
+                       }
+                       else
+                       {
+                               for (int i = 0; i < mac.Length; i++)
+                               {
+                                       if (mac[i] != dcrMAC[i])
+                                       {
+                                               badRecordMac = true;
+                                               break;
+                                       }
+                               }
                        }
 
-                       for (int i = 0; i < mac.Length; i++)
+                       if (badRecordMac)
                        {
-                               if (mac[i] != dcrMAC[i])
+                               if (this.context is ServerContext)
                                {
-                                       throw new TlsException("Invalid MAC received from server.");
+                                       this.Context.RecordProtocol.SendAlert(AlertDescription.BadRecordMAC);
                                }
+
+                               throw new TlsException("Bad record MAC");
                        }
 
                        // Update sequence number
index 37d9c525b2cf40f4fa61a95703df3c02b48bb329..50da7e079f8ba62b1679d68d41403df5c331c798 100644 (file)
@@ -80,7 +80,14 @@ namespace Mono.Security.Protocol.Tls
 
                        block.Write(this.Context.ServerWriteMAC);
                        block.Write(this.pad1);
-                       block.Write(this.Context.ReadSequenceNumber);
+                       if (this.Context is ClientContext)
+                       {
+                               block.Write(this.Context.ReadSequenceNumber);
+                       }
+                       else
+                       {
+                               block.Write(this.Context.WriteSequenceNumber);
+                       }
                        block.Write((byte)contentType);
                        block.Write((short)fragment.Length);
                        block.Write(fragment);
@@ -109,7 +116,14 @@ namespace Mono.Security.Protocol.Tls
 
                        block.Write(this.Context.ClientWriteMAC);
                        block.Write(this.pad1);
-                       block.Write(this.Context.WriteSequenceNumber);
+                       if (this.Context is ClientContext)
+                       {
+                               block.Write(this.Context.ReadSequenceNumber);
+                       }
+                       else
+                       {
+                               block.Write(this.Context.WriteSequenceNumber);
+                       }
                        block.Write((byte)contentType);
                        block.Write((short)fragment.Length);
                        block.Write(fragment);
index 17af23674f21096451b452cdcbad356171eb5db0..cba39b08dad828eb54a91bf1e5dc0c8e8a755738 100644 (file)
@@ -104,8 +104,8 @@ namespace Mono.Security.Protocol.Tls
 
                        byte[] result = new byte[36];
 
-                       System.Array.Copy(md5.Hash, 0, result, 0, 16);
-                       System.Array.Copy(sha.Hash, 0, result, 16, 20);
+                       Buffer.BlockCopy(md5.Hash, 0, result, 0, 16);
+                       Buffer.BlockCopy(sha.Hash, 0, result, 16, 20);
 
                        return result;
                }
index 95b935934cd7dbb3adecf702de6d6a6f929af634..2f8df57ba1083fbdf04f4f0cd8fe08f0dadf2824 100644 (file)
@@ -664,7 +664,6 @@ namespace Mono.Security.Protocol.Tls
                                if (this.context.Cipher.ExchangeAlgorithmType == ExchangeAlgorithmType.RsaKeyX)
                                {
                                        this.protocol.SendRecord(HandshakeType.ServerKeyExchange);
-                                       
                                }
 
                                // If the negotiated cipher is a KeyEx cipher or
index 776ccaa5d2427a817d9afd5cf22662dc269c95a5..87683b8f4ad6edb15b02362342448d0176231ee5 100644 (file)
@@ -159,10 +159,10 @@ namespace Mono.Security.Protocol.Tls
 
                                // Generate IV keys
                                this.Context.ClientWriteIV = new byte[this.IvSize];                             
-                               System.Array.Copy(ivBlock, 0, this.Context.ClientWriteIV, 0, this.Context.ClientWriteIV.Length);
+                               Buffer.BlockCopy(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);
+                               Buffer.BlockCopy(ivBlock, this.IvSize, this.Context.ServerWriteIV, 0, this.Context.ServerWriteIV.Length);
                        }
 
                        // Clear no more needed data
index f21d005edca87ec006cfe66420c7c79c3698ee2c..196c566e51c4ce6422a0904c55474b8ba1b04434 100644 (file)
@@ -168,7 +168,7 @@ namespace Mono.Security.Protocol.Tls
                        int int24 = IPAddress.HostToNetworkOrder(value);
                        byte[] content = new byte[3];
                                
-                       System.Array.Copy(BitConverter.GetBytes(int24), 1, content, 0, 3);
+                       Buffer.BlockCopy(BitConverter.GetBytes(int24), 1, content, 0, 3);
 
                        Write(content);
                }