2004-11-10 Sebastien Pouliot <sebastien@ximian.com>
authorSebastien Pouliot <sebastien@ximian.com>
Wed, 10 Nov 2004 16:50:09 +0000 (16:50 -0000)
committerSebastien Pouliot <sebastien@ximian.com>
Wed, 10 Nov 2004 16:50:09 +0000 (16:50 -0000)
* CipherSuiteFactory.cs: Activated RSA_WITH_AES_256_CBC_SHA as it is
supported by some browsers.
* ContentType.cs: Removed ClientHelloV2 from the enum as it is not a
"true" content type (it just looks so where we're processing it).
* Context.cs: Added support to switch protocol (e.g. SSL2->SSL3 or
SSL2->TLS1). Contributed by Carlos Guzman Alvarez.
* RecordProtocol.cs: Added support for ClientHelloV2 message
(contributed by Carlos Guzman Alvarez). This is a Handshake message
so it must be MACed. Also fixed the challenge length because some
browsers implementation don't interpret "This value must be 32." as
having 32 bytes.

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

mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ChangeLog
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/CipherSuiteFactory.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ContentType.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/Context.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs

index bfafd8d7a6d0e8bc0ef087a1a5fc9f540b319008..2672c0576c9609beca7e8bfbb604406b55694fd6 100644 (file)
@@ -1,3 +1,17 @@
+2004-11-10  Sebastien Pouliot  <sebastien@ximian.com>
+
+       * CipherSuiteFactory.cs: Activated RSA_WITH_AES_256_CBC_SHA as it is
+       supported by some browsers.
+       * ContentType.cs: Removed ClientHelloV2 from the enum as it is not a
+       "true" content type (it just looks so where we're processing it).
+       * Context.cs: Added support to switch protocol (e.g. SSL2->SSL3 or 
+       SSL2->TLS1). Contributed by Carlos Guzman Alvarez.
+       * RecordProtocol.cs: Added support for ClientHelloV2 message 
+       (contributed by Carlos Guzman Alvarez). This is a Handshake message
+       so it must be MACed. Also fixed the challenge length because some
+       browsers implementation don't interpret "This value must be 32." as
+       having 32 bytes.
+
 2004-10-05  Sebastien Pouliot  <sebastien@ximian.com>
 
        * SslClientStream.cs: Changed InputBuffer to internal (was protected).
index ad744b33a2e23b0a084798ba925d311bbc3dc3df..f03cd18a959caff543d0679f43c280e416d6c76a 100644 (file)
@@ -130,8 +130,9 @@ namespace Mono.Security.Protocol.Tls
                {
                        CipherSuiteCollection scs = new CipherSuiteCollection(SecurityProtocolType.Ssl3);
 
-                       // Supported ciphers
-                       scs.Add((0x00 << 0x08) | 0x0A, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", CipherAlgorithmType.TripleDes, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaSign, false, true, 24, 24, 168, 8, 8);
+                       // Supported ciphers\r
+                       scs.Add((0x00 << 0x08) | 0x35, "SSL_RSA_WITH_AES_256_CBC_SHA", CipherAlgorithmType.Rijndael, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaSign, false, true, 32, 32, 256, 16, 16);\r
+                       scs.Add((0x00 << 0x08) | 0x0A, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", CipherAlgorithmType.TripleDes, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaSign, false, true, 24, 24, 168, 8, 8);\r
                        scs.Add((0x00 << 0x08) | 0x05, "SSL_RSA_WITH_RC4_128_SHA", CipherAlgorithmType.Rc4, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaSign, false, false, 16, 16, 128, 0, 0);
                        scs.Add((0x00 << 0x08) | 0x04, "SSL_RSA_WITH_RC4_128_MD5", CipherAlgorithmType.Rc4, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaSign, false, false, 16, 16, 128, 0, 0);
                        scs.Add((0x00 << 0x08) | 0x09, "SSL_RSA_WITH_DES_CBC_SHA", CipherAlgorithmType.Des, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaSign, false, true, 8, 8, 56, 8, 8);
index 6995ad55a068a73790c4adf6e286dba892b2b9ee..e07d64e461e75737b0d4496e9f894fb73f70e147 100644 (file)
@@ -29,7 +29,6 @@ namespace Mono.Security.Protocol.Tls
        [Serializable]
        internal enum ContentType : byte
        {
-               ClientHelloV2           = 1,
                ChangeCipherSpec        = 20,
                Alert                           = 21,
                Handshake                       = 22,
index eafceb3ecb3fadf233ce305364bcc6a0d33e04c9..579548d5e3b9c97237370e38cd3faf43c1d7f356 100644 (file)
@@ -406,6 +406,24 @@ namespace Mono.Security.Protocol.Tls
                        }
                }
 
+               public void ChangeProtocol(short protocol)
+               {
+                       SecurityProtocolType protocolType = this.DecodeProtocolCode(protocol);
+
+                       if ((protocolType & this.SecurityProtocolFlags) == protocolType ||
+                               (this.SecurityProtocolFlags & SecurityProtocolType.Default) == SecurityProtocolType.Default)
+                       {
+                               this.SecurityProtocol = protocolType;
+                               this.SupportedCiphers.Clear();
+                               this.SupportedCiphers = null;
+                               this.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers(protocolType);
+                       }
+                       else
+                       {
+                               throw new TlsException(AlertDescription.ProtocolVersion, "Incorrect protocol version received from server");
+                       }
+               }
+
                #endregion
        }
 }
index ec39ea3eea77169fe8d893baa95d42adfb043bcf..d5965ab7e313d0d9df2aedd266bf32a8705bd1f9 100644 (file)
@@ -89,7 +89,7 @@ namespace Mono.Security.Protocol.Tls
                        }
 
                        ContentType     contentType     = (ContentType)type;
-                       byte[] buffer = this.ReadRecordBuffer(contentType);
+                       byte[] buffer = this.ReadRecordBuffer(type);
 
                        TlsStream message = new TlsStream(buffer);
                
@@ -115,12 +115,6 @@ namespace Mono.Security.Protocol.Tls
 
                        switch (contentType)
                        {
-                               case ContentType.ClientHelloV2:
-                                       // Set the last handshake message received as the standard ClientHello
-                                       this.context.LastHandshakeMsg = HandshakeType.ClientHello;
-                                       result = null;
-                                       break;
-
                                case ContentType.Alert:
                                        this.ProcessAlert((AlertLevel)message.ReadByte(), (AlertDescription)message.ReadByte());
                                        result = null;
@@ -143,24 +137,34 @@ namespace Mono.Security.Protocol.Tls
                                        this.context.HandshakeMessages.Write(message.ToArray());
                                        break;
 
+// FIXME / MCS bug - http://bugzilla.ximian.com/show_bug.cgi?id=67711
+//                             case (ContentType)0x80:
+//                                     this.context.HandshakeMessages.Write (result);
+//                                     break;
+
                                default:
-                                       throw new TlsException(
-                                               AlertDescription.UnexpectedMessage,
-                                               "Unknown record received from server.");
+                                       if (contentType != (ContentType)0x80)
+                                       {
+                                               throw new TlsException(
+                                                       AlertDescription.UnexpectedMessage,
+                                                       "Unknown record received from server.");
+                                       }
+                                       this.context.HandshakeMessages.Write (result);
+                                       break;
                        }
 
                        return result;
                }
 
-               private byte[] ReadRecordBuffer(ContentType contentType)
+               private byte[] ReadRecordBuffer(int contentType)
                {
                        switch (contentType)
                        {
-                               case ContentType.ClientHelloV2:
+                               case 0x80:
                                        return this.ReadClientHelloV2();
 
                                default:
-                                       if (!Enum.IsDefined(typeof(ContentType), contentType))
+                                       if (!Enum.IsDefined(typeof(ContentType), (ContentType)contentType))
                                        {
                                                throw new TlsException(AlertDescription.DecodeError);
                                        }
@@ -170,31 +174,32 @@ namespace Mono.Security.Protocol.Tls
 
                private byte[] ReadClientHelloV2()
                {
-                       short protocol                  = this.ReadShort();
-                       short cipherSpecLength  = this.ReadShort();
-                       short sessionIdLength   = this.ReadShort();
-                       short challengeLength   = this.ReadShort();
-                       short length = (challengeLength > 32) ? (short)32 : challengeLength;
+                       int msgLength                   = this.innerStream.ReadByte();
+                       byte[] message = new byte [msgLength];
+                       this.innerStream.Read (message, 0, msgLength);
+
+                       int msgType             = message [0];
+                       if (msgType != 1)
+                       {
+                               throw new TlsException(AlertDescription.DecodeError);
+                       }
+                       int protocol = (message [1] << 8 | message [2]);
+                       int cipherSpecLength = (message [3] << 8 | message [4]);
+                       int sessionIdLength = (message [5] << 8 | message [6]);
+                       int challengeLength = (message [7] << 8 | message [8]);
+                       int length = (challengeLength > 32) ? 32 : challengeLength;
 
                        // Read CipherSpecs
                        byte[] cipherSpecV2 = new byte[cipherSpecLength];
-                       this.innerStream.Read(cipherSpecV2, 0, cipherSpecV2.Length);                    
+                       Buffer.BlockCopy (message, 9, cipherSpecV2, 0, cipherSpecLength);
 
                        // Read session ID
                        byte[] sessionId = new byte[sessionIdLength];
-                       this.innerStream.Read(sessionId, 0, sessionId.Length);
+                       Buffer.BlockCopy (message, 9 + cipherSpecLength, sessionId, 0, sessionIdLength);
 
                        // Read challenge ID
                        byte[] challenge = new byte[challengeLength];
-                       this.innerStream.Read(challenge, 0, challenge.Length);
-
-                       // Check that the message has a valid protocol version
-                       SecurityProtocolType protocolType = this.context.DecodeProtocolCode(protocol);
-                       if (protocolType != SecurityProtocolType.Ssl3 && protocolType != SecurityProtocolType.Tls)
-                       {
-                               throw new TlsException(
-                                       AlertDescription.ProtocolVersion, "Invalid protocol version on message received");
-                       }
+                       Buffer.BlockCopy (message, 9 + cipherSpecLength + sessionIdLength, challenge, 0, challengeLength);
                
                        if (challengeLength < 16 || cipherSpecLength == 0 || (cipherSpecLength % 3) != 0)
                        {
@@ -207,17 +212,23 @@ namespace Mono.Security.Protocol.Tls
                                this.context.SessionId = sessionId;
                        }
 
-                       // Select the cipher suite collection
-                       this.Context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers(protocolType);
+                       // Update the protocol version
+                       this.Context.ChangeProtocol((short)protocol);
 
                        // Select the Cipher suite
-                       this.ProcessCipherSpecV2Buffer(protocolType, cipherSpecV2);
-
-                       // Updated the Client Random
-                       this.context.ClientRandom = new byte[32];                       
-                       Buffer.BlockCopy(challenge, 0, this.context.ClientRandom, 0, length);
-
-                       return new byte[0];
+                       this.ProcessCipherSpecV2Buffer(this.Context.SecurityProtocol, cipherSpecV2);
+
+                       // Updated the Client Random\r
+                       this.context.ClientRandom = new byte [32]; // Always 32\r
+                       // 1. if challenge is bigger than 32 bytes only use the last 32 bytes\r
+                       // 2. right justify (0) challenge in ClientRandom if less than 32\r
+                       Buffer.BlockCopy (challenge, challenge.Length - length, this.context.ClientRandom, 32 - length, length);\r
+\r
+                       // Set 
+                       this.context.LastHandshakeMsg = HandshakeType.ClientHello;
+                       this.context.ProtocolNegotiated = true;
+
+                       return message;
                }
 
                private byte[] ReadStandardRecordBuffer()