2004-04-15 Carlos Guzman Alvarez <carlosga@telefonica.net>
authorCarlos Guzmán Álvarez <carlos@mono-cvs.ximian.com>
Thu, 15 Apr 2004 16:43:07 +0000 (16:43 -0000)
committerCarlos Guzmán Álvarez <carlos@mono-cvs.ximian.com>
Thu, 15 Apr 2004 16:43:07 +0000 (16:43 -0000)
* Mono.Security.Protocol.Tls/SslClientStream.cs:
* Mono.Security.Protocol.Tls/SslServerStream.cs:
* Mono.Security.Protocol.Tls/Alert.cs:
* Mono.Security.Protocol.Tls/RecordProtocol.cs:
* Mono.Security.Protocol.Tls/ClientRecordProtocol.cs:
* Mono.Security.Protocol.Tls/ServerRecordProtocol.cs:
* Mono.Security.Protocol.Tls/Context.cs:
* Mono.Security.Protocol.Tls/TlsException.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificate.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHello.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs:
* Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificateVerify.cs:
* Mono.Security.Protocol.Tls.Handshake.Server/TlsClientFinished.cs:
* Mono.Security.Protocol.Tls.Handshake.Server/TlsClientHello.cs:

- Reworked Alert and Exception (TlsException) handling.

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

- Added new CertificateRSA property.

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

- Added two new methods: CreateSignature and VerifySignature.

* Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs:

- Added Ssl3 implementation.

* Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificateVerify.cs:

- Added initial implementation.

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

26 files changed:
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificate.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHello.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificate.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificateVerify.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/TlsServerCertificateRequest.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/Alert.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/CipherSuiteCollection.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ClientContext.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ClientRecordProtocol.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/Context.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RSASslSignatureDeformatter.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RSASslSignatureFormatter.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/ServerRecordProtocol.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslCipherSuite.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.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/TlsClientSettings.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsException.cs
mcs/class/Mono.Security/Mono.Security.Protocol.Tls/TlsStream.cs

index cbf6f5dfd34780253118624844b63dc669617903..4a1fbe8a44e5b63632156235f52e4334e9cec464 100644 (file)
@@ -65,7 +65,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                        if (context.ClientSettings.Certificates == null ||
                                context.ClientSettings.Certificates.Count == 0)
                        {
-                               throw this.Context.CreateException("Client certificate requested by the server and no client certificate specified.");
+                               throw new TlsException(
+                                       AlertDescription.UserCancelled,
+                                       "Client certificate requested by the server and no client certificate specified.");
                        }
                        
                        // Select a valid certificate
@@ -79,7 +81,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                        if (clientCert == null)
                        {
-                               throw this.Context.CreateException("Client certificate requested by the server and no client certificate specified.");
+                               throw new TlsException(
+                                       AlertDescription.UserCancelled,
+                                       "Client certificate requested by the server and no client certificate specified.");
                        }
 
                        // Update the selected client certificate
index aef47c4b887e1b7d64e10a47486e24ff3aa38ab5..bb4a50690a414a61e2d819e09e3f70e841a5469d 100644 (file)
@@ -55,7 +55,34 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                protected override void ProcessAsSsl3()
                {
-                       throw new NotSupportedException();
+                       AsymmetricAlgorithm privKey = null;
+                       ClientContext           context = (ClientContext)this.Context;
+                       
+                       privKey = context.SslStream.RaisePrivateKeySelection(
+                               context.ClientSettings.ClientCertificate,
+                               context.ClientSettings.TargetHost);
+
+                       if (privKey == null)
+                       {
+                               throw new TlsException(
+                                       AlertDescription.UserCancelled,
+                                       "Client certificate Private Key unavailable.");
+                       }
+                       else
+                       {
+                               SslHandshakeHash hash = new SslHandshakeHash(context.MasterSecret);                     
+                               hash.TransformFinalBlock(
+                                       context.HandshakeMessages.ToArray(), 
+                                       0, 
+                                       (int)context.HandshakeMessages.Length);
+
+                               // RSAManaged of the selected ClientCertificate 
+                               // (at this moment the first one)
+                               RSA rsa = this.getClientCertRSA((RSA)privKey);
+
+                               // Write message
+                               this.Write(hash.CreateSignature(rsa));
+                       }
                }
 
                protected override void ProcessAsTls1()
@@ -64,12 +91,14 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                        ClientContext           context = (ClientContext)this.Context;
                        
                        privKey = context.SslStream.RaisePrivateKeySelection(
-                               this.Context.ClientSettings.ClientCertificate,
-                               this.Context.ClientSettings.TargetHost);
+                               context.ClientSettings.ClientCertificate,
+                               context.ClientSettings.TargetHost);
 
                        if (privKey == null)
                        {
-                               throw this.Context.CreateException("Client certificate Private Key unavailable.");
+                               throw new TlsException(
+                                       AlertDescription.UserCancelled,
+                                       "Client certificate Private Key unavailable.");
                        }
                        else
                        {
index 43001263fe8806060e1d997b87a405009b3fe401..4ac57a077ab9b94b0961dc8b0327d326aa1ee41c 100644 (file)
@@ -176,7 +176,8 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                private void validateCertificates(X509CertificateCollection certificates)
                {
-                       ClientContext context = (ClientContext)this.Context;
+                       ClientContext           context                 = (ClientContext)this.Context;
+                       AlertDescription        description             = AlertDescription.BadCertificate;
 
                        // the leaf is the web server certificate
                        X509Certificate leaf = certificates [0];
@@ -225,28 +226,38 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                                                // WinError.h TRUST_E_BASIC_CONSTRAINTS 0x80096019
                                                errors.Add ((int)-2146869223);
                                                break;
+                                       
                                        case X509ChainStatusFlags.NotSignatureValid:
                                                // WinError.h TRUST_E_BAD_DIGEST 0x80096010
                                                errors.Add ((int)-2146869232);
                                                break;
+                                       
                                        case X509ChainStatusFlags.NotTimeNested:
                                                // WinError.h CERT_E_VALIDITYPERIODNESTING 0x800B0102
                                                errors.Add ((int)-2146762494);
                                                break;
+                                       
                                        case X509ChainStatusFlags.NotTimeValid:
                                                // WinError.h CERT_E_EXPIRED 0x800B0101
+                                               description     = AlertDescription.CertificateExpired;
                                                errors.Add ((int)-2146762495);
                                                break;
+                                       
                                        case X509ChainStatusFlags.PartialChain:
                                                // WinError.h CERT_E_CHAINING 0x800B010A
+                                               description     = AlertDescription.UnknownCA;
                                                errors.Add ((int)-2146762486);
                                                break;
+                                       
                                        case X509ChainStatusFlags.UntrustedRoot:
                                                // WinError.h CERT_E_UNTRUSTEDROOT 0x800B0109
+                                               description     = AlertDescription.UnknownCA;
                                                errors.Add ((int)-2146762487);
                                                break;
+                                       
                                        default:
                                                // unknown error
+                                               description     = AlertDescription.CertificateUnknown;
                                                errors.Add ((int)verify.Status);
                                                break;
                                }
@@ -258,7 +269,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                                cert, 
                                certificateErrors))
                        {
-                               throw context.CreateException("Invalid certificate received form server.");
+                               throw new TlsException(
+                                       description,
+                                       "Invalid certificate received form server.");
                        }
                }
 
@@ -307,17 +320,15 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                        ClientContext context = (ClientContext)this.Context;
 
                        string  domainName = String.Empty;
-                       Regex search = new Regex(@"([\w\s\d]*)\s*=\s*([^,]*)");
+                       Regex search = new Regex(@"CN\s*=\s*([^,]*)");
 
                        MatchCollection elements = search.Matches(subjectName);
 
-                       foreach (Match element in elements)
+                       if (elements.Count == 1)
                        {
-                               switch (element.Groups[1].Value.Trim().ToUpper())
+                               if (elements[0].Success)
                                {
-                                       case "CN":
-                                               domainName = element.Groups[2].Value;
-                                               break;
+                                       domainName = elements[0].Groups[1].Value.ToString();
                                }
                        }
 
index f3cdfdf90df1a353d83408d34391bf200b2031d8..d188920d0995caefc8ad158fde7e68c9a5b03208 100644 (file)
@@ -128,7 +128,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                        }
                        else
                        {
-                               throw this.Context.CreateException("Incorrect protocol version received from server");
+                               throw new TlsException(
+                                       AlertDescription.ProtocolVersion,
+                                       "Incorrect protocol version received from server");
                        }
                }
 
index 5d3ec79965459d8efe3748d8e37f99a4a435851f..044deed3f917f46d221043dba4e793c64c81d774 100644 (file)
@@ -110,7 +110,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
 
                        if (!isValidSignature)
                        {
-                               throw this.Context.CreateException("Data was not signed with the server certificate.");
+                               throw new TlsException(
+                                       AlertDescription.DecodeError,
+                                       "Data was not signed with the server certificate.");
                        }
                }
 
index 47020efaa464babfab46c28cf041a130520e9a82..a46cff711b1b1f34026f0e5b19783f07ad5bf89c 100644 (file)
@@ -66,7 +66,16 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
                        int length = this.ReadInt24();
                        this.clientCertificate = new X509Certificate(this.ReadBytes(length));
 
-#warning "Is client certificate validation needed ??"
+                       this.validateCertificate(this.clientCertificate);
+               }
+
+               #endregion
+
+               #region Private Methods
+
+               private void validateCertificate(X509Certificate certificate)
+               {
+                       #warning "Validate client certificate"
                }
 
                #endregion
index d4e9f010d5c3a1496f23d50ac6d95050972f909d..106df595140bb1c55392d20374e4f0acfd65cc03 100644 (file)
@@ -41,25 +41,50 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 
                #endregion
 
-               #region Methods
-
-               public override void Update()
-               {
-                       throw new NotSupportedException();
-               }
-
-               #endregion
-
                #region Protected Methods
 
                protected override void ProcessAsSsl3()
                {
-                       throw new NotSupportedException();
+                       ServerContext   context         = (ServerContext)this.Context;
+                       byte[]                  signature       = this.ReadBytes((int)this.Length);
+
+                       // Verify signature
+                       SslHandshakeHash hash = new SslHandshakeHash(context.MasterSecret);                     
+                       hash.TransformFinalBlock(
+                               context.HandshakeMessages.ToArray(), 
+                               0, 
+                               (int)context.HandshakeMessages.Length);
+
+                       if (!hash.VerifySignature(
+                               context.ClientSettings.CertificateRSA,
+                               signature))
+                       {
+                               throw new TlsException(
+                                       AlertDescription.HandshakeFailiure,
+                                       "Handshake Failiure.");
+                       }
                }
 
                protected override void ProcessAsTls1()
                {
-                       throw new NotSupportedException();
+                       ServerContext   context         = (ServerContext)this.Context;
+                       byte[]                  signature       = this.ReadBytes((int)this.Length);                     
+
+                       // Verify signature
+                       MD5SHA1 hash = new MD5SHA1();
+                       hash.ComputeHash(
+                               context.HandshakeMessages.ToArray(),
+                               0,
+                               (int)context.HandshakeMessages.Length);
+
+                       if (!hash.VerifySignature(
+                               context.ClientSettings.CertificateRSA,
+                               signature))
+                       {
+                               throw new TlsException(
+                                       AlertDescription.HandshakeFailiure,
+                                       "Handshake Failiure.");
+                       }
                }
 
                #endregion
index 66e968f12fb9865f0d0943eae901dfbc6176c700..a46525db0c7b598e7ec697e4d4d90626730fb939 100644 (file)
@@ -79,9 +79,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 
                        if (decryptError)
                        {
-                               this.Context.RecordProtocol.SendAlert(AlertDescription.DecryptError);
-
-                               throw new TlsException("Decrypt error.");
+                               throw new TlsException(
+                                       AlertDescription.DecryptError,
+                                       "Decrypt error.");
                        }
                }
 
@@ -117,9 +117,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 
                        if (decryptError)
                        {
-                               this.Context.RecordProtocol.SendAlert(AlertDescription.DecryptError);
-
-                               throw new TlsException("Decrypt error.");
+                               throw new TlsException(
+                                       AlertDescription.DecryptError,
+                                       "Decrypt error.");
                        }
                }
 
index c05acac07d7ea127592e6565bb3c9d5bce2bf021..8b97797bd187c612bd1e5dcf623d3fee91eb4420 100644 (file)
@@ -118,9 +118,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
                        }
                        else
                        {
-                               this.Context.RecordProtocol.SendAlert(AlertDescription.ProtocolVersion);
-
-                               throw this.Context.CreateException("Incorrect protocol version received from server");
+                               throw new TlsException(
+                                       AlertDescription.ProtocolVersion,
+                                       "Incorrect protocol version received from server");
                        }
                }
 
@@ -139,9 +139,9 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 
                        if (this.Context.Cipher == null)
                        {
-                               this.Context.RecordProtocol.SendAlert(AlertDescription.InsuficientSecurity);
-
-                               throw this.Context.CreateException("Insuficient Security");
+                               throw new TlsException(
+                                       AlertDescription.InsuficientSecurity,
+                                       "Insuficient Security");
                        }
                }
 
index 781bb27ab36c044224116fa553981d0344d90189..f9a0aa143e54c7bc683180290916bb9477e80ea9 100644 (file)
@@ -39,15 +39,6 @@ namespace Mono.Security.Protocol.Tls.Handshake.Server
 
                #endregion
 
-               #region Methods
-
-               public override void Update()
-               {
-                       throw new NotSupportedException();
-               }
-
-               #endregion
-
                #region Protected Methods
 
                protected override void ProcessAsSsl3()
index 350337fd1de140ee09b9843d55704de76ca1e292..20dcdf8568cab301afc909858c05d411f148822d 100644 (file)
@@ -66,46 +66,27 @@ namespace Mono.Security.Protocol.Tls
 
        #endregion
        
-       internal class Alert : TlsStream
+       internal class Alert
        {
                #region Fields
 
-               private Context                         context;
                private AlertLevel                      level;
                private AlertDescription        description;
 
                #endregion
 
-               #region Constructors
+               #region Properties
 
-               public Alert(
-                       Context                         context,
-                       AlertDescription        description) : base()
+               public AlertLevel Level
                {
-                       this.context            = context;
-                       this.description        = description;
-                       
-                       this.inferAlertLevel();
-
-                       this.fill();
+                       get { return this.level; }
                }
 
-               public Alert(
-                       Context                         context,
-                       AlertLevel                      level,
-                       AlertDescription        description) : base()
+               public AlertDescription Description
                {
-                       this.context            = context;
-                       this.level                      = level;
-                       this.description        = description;
-
-                       this.fill();
+                       get { return this.description; }
                }
 
-               #endregion
-
-               #region Properties
-
                public string Message
                {
                        get { return Alert.GetAlertMessage(this.description); }
@@ -113,18 +94,12 @@ namespace Mono.Security.Protocol.Tls
 
                public bool IsWarning
                {
-                       get
-                       {
-                               return this.level == AlertLevel.Warning ? true : false;
-                       }
+                       get { return this.level == AlertLevel.Warning ? true : false; }
                }
 
                public bool IsFatal
                {
-                       get
-                       {
-                               return this.level == AlertLevel.Fatal ? true : false;
-                       }
+                       get { return this.level == AlertLevel.Fatal ? true : false; }
                }
 
                public bool IsCloseNotify
@@ -143,35 +118,26 @@ namespace Mono.Security.Protocol.Tls
 
                #endregion
 
-               #region Methods
-               
-               public void Update()
+               #region Constructors
+
+               public Alert(AlertDescription description)
                {
-                       if ( this.description == AlertDescription.CloseNotify )
-                       {
-                               this.context.ConnectionEnd = true;
-                       }
+                       this.inferAlertLevel();
+                       this.description = description;
+               }
 
-                       if (this.IsFatal)
-                       {
-                               this.context.ConnectionEnd = true;
-                               if (this.context is ServerContext)
-                               {
-                                       ((ServerContext)this.context).SslStream.Close();
-                               }
-                       }
+               public Alert(
+                       AlertLevel                      level,
+                       AlertDescription        description)
+               {
+                       this.level                      = level;
+                       this.description        = description;
                }
 
                #endregion
 
                #region Private Methods
 
-               private void fill()
-               {
-                       this.Write((byte)level);
-                       this.Write((byte)description);
-               }
-
                private void inferAlertLevel()
                {
                        switch (description)
index a4cec728a41df2bd9a118a23894e0d48130f948d..bbbb089ec9b986d0d3e2b5bbceb5797e11b9db6e 100644 (file)
@@ -72,26 +72,29 @@ namespace Mono.Security.Protocol.Tls
        
                public bool Contains(string name)
                {
-                       return(-1 != IndexOf(name));
+                       return (-1 != this.IndexOf(name));
                }
                
                public int IndexOf(string name)
                {
                        int index = 0;
+
                        foreach (CipherSuite suite in this)
                        {
-                               if (cultureAwareCompare(suite.Name, name))
+                               if (this.cultureAwareCompare(suite.Name, name))
                                {
                                        return index;
                                }
                                index++;
                        }
+
                        return -1;
                }
 
                public int IndexOf(short code)
                {
                        int index = 0;
+
                        foreach (CipherSuite suite in this)
                        {
                                if (suite.Code == code)
@@ -100,12 +103,13 @@ namespace Mono.Security.Protocol.Tls
                                }
                                index++;
                        }
+
                        return -1;
                }
 
                public void RemoveAt(string errorMessage)
                {
-                       RemoveAt(IndexOf(errorMessage));
+                       this.RemoveAt(this.IndexOf(errorMessage));
                }
 
                public CipherSuite Add(
index edef875602269b07a071061b1ec1335b2bdabc1b..ced8c74624b280e8e278046c1dcd1fee3e9fcfd6 100644 (file)
@@ -73,8 +73,7 @@ namespace Mono.Security.Protocol.Tls
 
                public override void Clear()
                {
-                       this.clientHelloProtocol        = 0;
-
+                       this.clientHelloProtocol = 0;
                        base.Clear();
                }
 
index 53887b986da1b69402ae9a985e96086e14cdbfe4..defde352e5e921f0ee17d2f6e1c3b4809c938bf9 100644 (file)
@@ -162,7 +162,9 @@ namespace Mono.Security.Protocol.Tls
                                        return new TlsServerFinished(this.context, buffer);
 
                                default:
-                                       throw this.context.CreateException("Unknown server handshake message received ({0})", type.ToString());
+                                       throw new TlsException(
+                                               AlertDescription.UnexpectedMessage,
+                                               String.Format("Unknown server handshake message received ({0})", type.ToString()));
                        }
                }
 
index 7909ba945f9abb91a776f363ce01315b8753b72f..e9fb03e6ea26a53da8e7d643a9e1e26b39adfadc 100644 (file)
@@ -419,29 +419,5 @@ namespace Mono.Security.Protocol.Tls
                }
 
                #endregion
-
-               #region Exception Methods
-
-               public TlsException CreateException(
-                       AlertLevel                      alertLevel, 
-                       AlertDescription        alertDesc)
-               {
-                       return CreateException(Alert.GetAlertMessage(alertDesc));
-               }
-
-               public TlsException CreateException(string format, params object[] args)
-               {
-                       StringBuilder message = new StringBuilder();
-                       message.AppendFormat(format, args);
-
-                       return CreateException(message.ToString());
-               }
-
-               public TlsException CreateException(string message)
-               {
-                       return new TlsException(message);
-               }
-
-               #endregion
        }
 }
index 53d5fb8767cead7b45d7a3a3d0cd829281443e53..f5ebb82630b655ec40bac8415889aed58f314e9c 100644 (file)
@@ -55,7 +55,7 @@ namespace Mono.Security.Protocol.Tls
                        byte[] rgbHash,
                        byte[] rgbSignature)
                {
-                       if (key == null)
+                       if (this.key == null)
                        {
                                throw new CryptographicUnexpectedOperationException("The key is a null reference");
                        }
index 2751cb81738f7a741d41f70f5d1711387da0c6c7..1d5e4f348caaf891a4a10fee851eda775d2032db 100644 (file)
@@ -53,7 +53,7 @@ namespace Mono.Security.Protocol.Tls
 
                public override byte[] CreateSignature(byte[] rgbHash)
                {
-                       if (key == null)
+                       if (this.key == null)
                        {
                                throw new CryptographicUnexpectedOperationException("The key is a null reference");
                        }
index ce2ee614bec6520ab6fb25ac126da981bb79c327..f32317868a18882ef3017d9aa56d223d677707a8 100644 (file)
@@ -81,7 +81,9 @@ namespace Mono.Security.Protocol.Tls
                {
                        if (this.context.ConnectionEnd)
                        {
-                               throw this.context.CreateException("The session is finished and it's no longer valid.");
+                               throw new TlsException(
+                                       AlertDescription.InternalError,
+                                       "The session is finished and it's no longer valid.");
                        }
                        
                        // Try to read the Record Content Type
@@ -112,7 +114,9 @@ namespace Mono.Security.Protocol.Tls
                        if (protocol != this.context.Protocol && 
                                this.context.ProtocolNegotiated)
                        {
-                               throw this.context.CreateException("Invalid protocol version on message received from server");
+                               throw new TlsException(
+                                       AlertDescription.ProtocolVersion,
+                                       "Invalid protocol version on message received from server");
                        }
 
                        // Decrypt message contents if needed
@@ -162,7 +166,9 @@ namespace Mono.Security.Protocol.Tls
                                        break;
 
                                default:
-                                       throw this.context.CreateException("Unknown record received from server.");
+                                       throw new TlsException(
+                                               AlertDescription.UnexpectedMessage,
+                                               "Unknown record received from server.");
                        }
 
                        return result;
@@ -185,7 +191,7 @@ namespace Mono.Security.Protocol.Tls
                        switch (alertLevel)
                        {
                                case AlertLevel.Fatal:
-                                       throw this.context.CreateException(alertLevel, alertDesc);                                      
+                                       throw new TlsException(alertLevel, alertDesc);
 
                                case AlertLevel.Warning:
                                default:
@@ -205,26 +211,27 @@ namespace Mono.Security.Protocol.Tls
 
                public void SendAlert(AlertDescription description)
                {
-                       this.SendAlert(new Alert(this.Context, description));
+                       this.SendAlert(new Alert(description));
                }
 
                public void SendAlert(
                        AlertLevel                      level, 
                        AlertDescription        description)
                {
-                       this.SendAlert(new Alert(this.Context, level, description));
+                       this.SendAlert(new Alert(level, description));
                }
 
                public void SendAlert(Alert alert)
                {                       
                        // Write record
-                       this.SendRecord(ContentType.Alert, alert.ToArray());
+                       this.SendRecord(
+                               ContentType.Alert, 
+                               new byte[]{(byte)alert.Level, (byte)alert.Description});
 
-                       // Update session
-                       alert.Update();
-
-                       // Reset message contents
-                       alert.Reset();
+                       if (alert.IsCloseNotify)
+                       {
+                               this.context.ConnectionEnd = true;
+                       }
                }
 
                #endregion
@@ -253,7 +260,9 @@ namespace Mono.Security.Protocol.Tls
                {
                        if (this.context.ConnectionEnd)
                        {
-                               throw this.context.CreateException("The session is finished and it's no longer valid.");
+                               throw new TlsException(
+                                       AlertDescription.InternalError,
+                                       "The session is finished and it's no longer valid.");
                        }
 
                        byte[] record = this.EncodeRecord(contentType, recordData);
@@ -278,7 +287,9 @@ namespace Mono.Security.Protocol.Tls
                {
                        if (this.context.ConnectionEnd)
                        {
-                               throw this.context.CreateException("The session is finished and it's no longer valid.");
+                               throw new TlsException(
+                                       AlertDescription.InternalError,
+                                       "The session is finished and it's no longer valid.");
                        }
 
                        TlsStream record = new TlsStream();
index 900eeda79a23b5995de90a99c5deaac5b72e266f..015a3d2edd6c1f1523330c4cdb2312ef4e16057b 100644 (file)
@@ -122,7 +122,9 @@ namespace Mono.Security.Protocol.Tls
                                        return new TlsClientFinished(this.context, buffer);
 
                                default:
-                                       throw this.context.CreateException("Unknown server handshake message received ({0})", type.ToString());
+                                       throw new TlsException(
+                                               AlertDescription.UnexpectedMessage,
+                                               String.Format("Unknown server handshake message received ({0})", type.ToString()));
                        }
                }
 
index b2c74fa996881cd37839382e0f962a86a081a517..65896adcc6a1e70d58c8b615fbe2804faa358fbb 100644 (file)
@@ -64,8 +64,8 @@ namespace Mono.Security.Protocol.Tls
                        /* Pad the key for inner and outer digest */
                        for (int i = 0; i < padLength; ++i) 
                        {
-                               pad1[i] = 0x36;
-                               pad2[i] = 0x5C;
+                               this.pad1[i] = 0x36;
+                               this.pad2[i] = 0x5C;
                        }
                }
 
@@ -167,6 +167,7 @@ namespace Mono.Security.Protocol.Tls
                        
                        char    labelChar       = 'A';
                        int             count           = 1;
+
                        while (tmp.Length < this.KeyBlockSize)
                        {
                                string label = String.Empty;
@@ -187,8 +188,8 @@ namespace Mono.Security.Protocol.Tls
                        }
                        
                        // Create keyblock
-                       TlsStream keyBlock = new TlsStream(tmp.ToArray());
-
+                       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);
index e08093e34d1963f0ba1084d4e3501072cb347bda..1a480443359d0e72988d8367aef1d912a952c8b4 100644 (file)
@@ -729,8 +729,18 @@ namespace Mono.Security.Protocol.Tls
                                        // Clear Key Info
                                        this.context.ClearKeyInfo();
                                }
-                               catch
+                               catch (TlsException ex)
                                {
+                                       this.protocol.SendAlert(ex.Alert);
+                                       this.Close();
+
+                                       throw new IOException("The authentication or decryption has failed.");
+                               }
+                               catch (Exception)
+                               {
+                                       this.protocol.SendAlert(AlertDescription.InternalError);
+                                       this.Close();
+
                                        throw new IOException("The authentication or decryption has failed.");
                                }
                        }
index cba39b08dad828eb54a91bf1e5dc0c8e8a755738..bc6a87739ec259f926be42840b448025a42d0590 100644 (file)
@@ -65,62 +65,90 @@ namespace Mono.Security.Protocol.Tls
 
                public override void Initialize()
                {
-                       md5.Initialize();
-                       sha.Initialize();
-                       initializePad();
-                       hashing = false;
+                       this.md5.Initialize();
+                       this.sha.Initialize();
+                       this.initializePad();
+                       this.hashing = false;
                }
 
                protected override byte[] HashFinal()
                {
-                       if (!hashing)
+                       if (!this.hashing)
                        {
-                               hashing = true;
+                               this.hashing = true;
                        }
 
                        // Finalize the md5 hash
-                       md5.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0);
-                       md5.TransformFinalBlock(this.innerPadMD5, 0, this.innerPadMD5.Length);
+                       this.md5.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0);
+                       this.md5.TransformFinalBlock(this.innerPadMD5, 0, this.innerPadMD5.Length);
 
-                       byte[] firstResultMD5 = md5.Hash;
+                       byte[] firstResultMD5 = this.md5.Hash;
 
-                       md5.Initialize();
-                       md5.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0);
-                       md5.TransformBlock(this.outerPadMD5, 0, this.outerPadMD5.Length, this.outerPadMD5, 0);
-                       md5.TransformFinalBlock(firstResultMD5, 0, firstResultMD5.Length);
+                       this.md5.Initialize();
+                       this.md5.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0);
+                       this.md5.TransformBlock(this.outerPadMD5, 0, this.outerPadMD5.Length, this.outerPadMD5, 0);
+                       this.md5.TransformFinalBlock(firstResultMD5, 0, firstResultMD5.Length);
                        
                        // Finalize the sha1 hash
-                       sha.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0);
-                       sha.TransformFinalBlock(this.innerPadSHA, 0, this.innerPadSHA.Length);
+                       this.sha.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0);
+                       this.sha.TransformFinalBlock(this.innerPadSHA, 0, this.innerPadSHA.Length);
 
-                       byte[] firstResultSHA = sha.Hash;
+                       byte[] firstResultSHA = this.sha.Hash;
                        
-                       sha.Initialize();
-                       sha.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0);
-                       sha.TransformBlock(this.outerPadSHA, 0, this.outerPadSHA.Length, this.outerPadSHA, 0);
-                       sha.TransformFinalBlock(firstResultSHA, 0, firstResultSHA.Length);
+                       this.sha.Initialize();
+                       this.sha.TransformBlock(this.secret, 0, this.secret.Length, this.secret, 0);
+                       this.sha.TransformBlock(this.outerPadSHA, 0, this.outerPadSHA.Length, this.outerPadSHA, 0);
+                       this.sha.TransformFinalBlock(firstResultSHA, 0, firstResultSHA.Length);
 
                        this.Initialize();
 
                        byte[] result = new byte[36];
 
-                       Buffer.BlockCopy(md5.Hash, 0, result, 0, 16);
-                       Buffer.BlockCopy(sha.Hash, 0, result, 16, 20);
+                       Buffer.BlockCopy(this.md5.Hash, 0, result, 0, 16);
+                       Buffer.BlockCopy(this.sha.Hash, 0, result, 16, 20);
 
                        return result;
                }
 
-               protected override void HashCore(
-                       byte[] array,
-                       int ibStart,
-                       int cbSize)
+               protected override void HashCore(byte[] array, int ibStart, int cbSize)
                {
-                       if (!hashing)
+                       if (!this.hashing)
                        {
-                               hashing = true;
+                               this.hashing = true;
                        }
-                       md5.TransformBlock(array, ibStart, cbSize, array, ibStart);
-                       sha.TransformBlock(array, ibStart, cbSize, array, ibStart);
+
+                       this.md5.TransformBlock(array, ibStart, cbSize, array, ibStart);
+                       this.sha.TransformBlock(array, ibStart, cbSize, array, ibStart);
+               }
+
+               public byte[] CreateSignature(RSA rsa) 
+               {
+                       if (rsa == null)
+                       {
+                               throw new CryptographicUnexpectedOperationException ("missing key");
+                       }
+
+                       RSASslSignatureFormatter f = new RSASslSignatureFormatter(rsa);
+                       f.SetHashAlgorithm("SslHash");
+
+                       return f.CreateSignature(this.Hash);
+               }
+
+               public bool VerifySignature(RSA rsa, byte[] rgbSignature) 
+               {
+                       if (rsa == null)
+                       {
+                               throw new CryptographicUnexpectedOperationException ("missing key");
+                       }
+                       if (rgbSignature == null)
+                       {
+                               throw new ArgumentNullException ("rgbSignature");
+                       }
+
+                       RSASslSignatureDeformatter d = new RSASslSignatureDeformatter(rsa);
+                       d.SetHashAlgorithm("SslHash");
+
+                       return d.VerifySignature(this.Hash, rgbSignature);
                }
 
                #endregion
index 2f8df57ba1083fbdf04f4f0cd8fe08f0dadf2824..864887f031a8df5f099066ce0a420bf17f76719c 100644 (file)
@@ -436,8 +436,11 @@ namespace Mono.Security.Protocol.Tls
                                        asyncResult = this.inputBuffer.BeginRead(
                                                buffer, offset, count, callback, state);
                                }
-                               catch (TlsException)
+                               catch (TlsException ex)
                                {
+                                       this.protocol.SendAlert(ex.Alert);
+                                       this.Close();
+
                                        throw new IOException("The authentication or decryption has failed.");
                                }
                                catch (Exception)
@@ -494,16 +497,18 @@ namespace Mono.Security.Protocol.Tls
                        {
                                try
                                {
-                                       // Send the buffer as a TLS record
-                                       
+                                       // Send the buffer as a TLS record                                      
                                        byte[] record = this.protocol.EncodeRecord(
                                                ContentType.ApplicationData, buffer, offset, count);
                                
                                        asyncResult = this.innerStream.BeginWrite(
                                                record, 0, record.Length, callback, state);
                                }
-                               catch (TlsException)
+                               catch (TlsException ex)
                                {
+                                       this.protocol.SendAlert(ex.Alert);
+                                       this.Close();
+
                                        throw new IOException("The authentication or decryption has failed.");
                                }
                                catch (Exception)
@@ -693,8 +698,18 @@ namespace Mono.Security.Protocol.Tls
                                // Clear Key Info
                                this.context.ClearKeyInfo();
                        }
-                       catch
+                       catch (TlsException ex)
+                       {
+                               this.protocol.SendAlert(ex.Alert);
+                               this.Close();
+
+                               throw new IOException("The authentication or decryption has failed.");
+                       }
+                       catch (Exception)
                        {
+                               this.protocol.SendAlert(AlertDescription.InternalError);
+                               this.Close();
+
                                throw new IOException("The authentication or decryption has failed.");
                        }
                }
index fe858834aa171ffa9a5dd3d8c95fab7478c1657d..d0ca874f568309f9c3911a86aa9a3a7d6cb0521a 100644 (file)
@@ -25,6 +25,8 @@
 using System;
 using System.Text;
 using System.Security.Cryptography.X509Certificates;
+using Mono.Security.Cryptography;
+using X509 = Mono.Security.X509;
 
 namespace Mono.Security.Protocol.Tls
 {
@@ -36,6 +38,7 @@ namespace Mono.Security.Protocol.Tls
                private X509CertificateCollection       certificates;
                private SecurityCompressionType         compressionMethod;
                private X509Certificate                         clientCertificate;
+               private RSAManaged                                      certificateRSA;
        
                #endregion
 
@@ -69,9 +72,17 @@ namespace Mono.Security.Protocol.Tls
                public X509Certificate ClientCertificate
                {
                        get { return this.clientCertificate; }
-                       set { this.clientCertificate = value; }
+                       set 
+                       { 
+                               this.clientCertificate = value; 
+                               this.UpdateCertificateRSA();
+                       }
                }
 
+               public RSAManaged CertificateRSA
+               {
+                       get { return this.certificateRSA; }
+               }
 
                #endregion
 
@@ -85,5 +96,27 @@ namespace Mono.Security.Protocol.Tls
                }
 
                #endregion
+
+               #region Methods
+
+               public void UpdateCertificateRSA()
+               {
+                       if (this.clientCertificate == null)
+                       {
+                               this.certificateRSA = null;
+                       }
+                       else
+                       {
+                               X509.X509Certificate cert = new X509.X509Certificate(this.clientCertificate.GetRawCertData());
+
+                               this.certificateRSA = new RSAManaged(
+                                       cert.RSA.KeySize);
+
+                               this.certificateRSA.ImportParameters(
+                                       cert.RSA.ExportParameters(false));
+                       }
+               }
+
+               #endregion
        }
 }
index 4ff1259ce10d865a3064b98e4ae44399bbbbd04e..065904cd3edc6ae7074d6637f5c1d8a5d007493b 100644 (file)
@@ -29,8 +29,23 @@ using System.Runtime.Serialization;
 namespace Mono.Security.Protocol.Tls
 {
        [Serializable]
-       public sealed class TlsException : Exception
+       internal sealed class TlsException : Exception
        {       
+               #region Fields
+
+               private Alert alert;
+
+               #endregion
+
+               #region Properties
+
+               public Alert Alert
+               {
+                       get { return this.alert; }
+               }
+
+               #endregion
+
                #region Constructors
                
                internal TlsException(string message) : base(message)
@@ -45,6 +60,34 @@ namespace Mono.Security.Protocol.Tls
                {
                }
 
+               internal TlsException(
+                       AlertLevel                      level,
+                       AlertDescription        description) 
+                       : this (level, description, Alert.GetAlertMessage(description))
+               {
+               }
+
+               internal TlsException(
+                       AlertLevel                      level,
+                       AlertDescription        description,
+                       string                          message) : base (message)
+               {
+                       this.alert = new Alert(level, description);
+               }
+
+               internal TlsException(
+                       AlertDescription description) 
+                       : this (description, Alert.GetAlertMessage(description))
+               {
+               }
+
+               internal TlsException(
+                       AlertDescription        description,
+                       string                          message) : base (message)
+               {
+                       this.alert = new Alert(description);
+               }
+
                #endregion
        }
 }
index 196c566e51c4ce6422a0904c55474b8ba1b04434..1723d317a05e21db9aa5daf9b5f22403f20422b1 100644 (file)
@@ -61,28 +61,28 @@ namespace Mono.Security.Protocol.Tls
 
                public override bool CanWrite
                {
-                       get { return canWrite; }
+                       get { return this.canWrite; }
                }
 
                public override bool CanRead
                {
-                       get { return canRead; }
+                       get { return this.canRead; }
                }
 
                public override bool CanSeek
                {
-                       get { return buffer.CanSeek; }
+                       get { return this.buffer.CanSeek; }
                }
 
                public override long Position
                {
-                       get { return buffer.Position; }
-                       set { buffer.Position = value; }
+                       get { return this.buffer.Position; }
+                       set { this.buffer.Position = value; }
                }
 
                public override long Length
                {
-                       get { return buffer.Length; }
+                       get { return this.buffer.Length; }
                }
 
                #endregion
@@ -154,13 +154,13 @@ namespace Mono.Security.Protocol.Tls
 
                public void Write(byte value)
                {
-                       WriteByte(value);
+                       this.WriteByte(value);
                }
 
                public void Write(short value)
                {
                        byte[] bytes = BitConverter.GetBytes((short)IPAddress.HostToNetworkOrder(value));
-                       Write(bytes);
+                       this.Write(bytes);
                }
 
                public void WriteInt24(int value)
@@ -170,24 +170,24 @@ namespace Mono.Security.Protocol.Tls
                                
                        Buffer.BlockCopy(BitConverter.GetBytes(int24), 1, content, 0, 3);
 
-                       Write(content);
+                       this.Write(content);
                }
 
                public void Write(int value)
                {
                        byte[] bytes = BitConverter.GetBytes((int)IPAddress.HostToNetworkOrder(value));
-                       Write(bytes);
+                       this.Write(bytes);
                }
 
                public void Write(long value)
                {
                        byte[] bytes = BitConverter.GetBytes((long)IPAddress.HostToNetworkOrder(value));
-                       Write(bytes);
+                       this.Write(bytes);
                }
 
                public void Write(byte[] buffer)
                {
-                       Write(buffer, 0, buffer.Length);
+                       this.Write(buffer, 0, buffer.Length);
                }
 
                #endregion
@@ -196,13 +196,13 @@ namespace Mono.Security.Protocol.Tls
 
                public void Reset()
                {
-                       buffer.SetLength(0);
-                       buffer.Position = 0;
+                       this.buffer.SetLength(0);
+                       this.buffer.Position = 0;
                }
 
                public byte[] ToArray()
                {
-                       return buffer.ToArray();
+                       return this.buffer.ToArray();
                }
 
                #endregion
@@ -211,22 +211,22 @@ namespace Mono.Security.Protocol.Tls
 
                public override void Flush()
                {
-                       buffer.Flush();
+                       this.buffer.Flush();
                }
 
                public override void SetLength(long length)
                {
-                       buffer.SetLength(length);
+                       this.buffer.SetLength(length);
                }
 
                public override long Seek(long offset, System.IO.SeekOrigin loc)
                {
-                       return buffer.Seek(offset, loc);
+                       return this.buffer.Seek(offset, loc);
                }
 
                public override int Read(byte[] buffer, int offset, int count)
                {
-                       if (canRead)
+                       if (this.canRead)
                        {
                                return this.buffer.Read(buffer, offset, count);
                        }
@@ -235,7 +235,7 @@ namespace Mono.Security.Protocol.Tls
 
                public override void Write(byte[] buffer, int offset, int count)
                {
-                       if (canWrite)
+                       if (this.canWrite)
                        {
                                this.buffer.Write(buffer, offset, count);
                        }