Imported Upstream version 6.8.0.73

Former-commit-id: d18deab1b47cfd3ad8cba82b3f37d00eec2170af
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-12-10 18:00:56 +00:00
parent bceda29824
commit 73ee7591e8
1043 changed files with 16271 additions and 22080 deletions

View File

@@ -96,14 +96,6 @@ namespace Mono.Security.Interface
ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509CertificateCollection certificates);
}
internal interface ICertificateValidator2 : ICertificateValidator
{
/*
* Internal use only.
*/
ValidationResult ValidateCertificate (string targetHost, bool serverMode, X509Certificate leaf, X509Chain chain);
}
public static class CertificateValidationHelper
{
const string SecurityLibrary = "/System/Library/Frameworks/Security.framework/Security";

View File

@@ -42,59 +42,11 @@ namespace Mono.Security.Interface
get;
}
void AuthenticateAsClient (string targetHost);
void AuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation);
void AuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation);
IAsyncResult BeginAuthenticateAsClient (string targetHost, AsyncCallback asyncCallback, object asyncState);
IAsyncResult BeginAuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState);
IAsyncResult BeginAuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState);
void EndAuthenticateAsClient (IAsyncResult asyncResult);
void AuthenticateAsServer (X509Certificate serverCertificate);
void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation);
void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation);
IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, AsyncCallback asyncCallback, object asyncState);
IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState);
IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState);
void EndAuthenticateAsServer (IAsyncResult asyncResult);
Task AuthenticateAsClientAsync (string targetHost);
Task AuthenticateAsClientAsync (string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation);
Task AuthenticateAsClientAsync (string targetHost, X509CertificateCollection clientCertificates, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation);
Task AuthenticateAsServerAsync (X509Certificate serverCertificate);
Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation);
Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, SSA.SslProtocols enabledSslProtocols, bool checkCertificateRevocation);
int Read (byte[] buffer, int offset, int count);
void Write (byte[] buffer);
void Write (byte[] buffer, int offset, int count);
IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState);
int EndRead (IAsyncResult asyncResult);
IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState);
void EndWrite (IAsyncResult asyncResult);
Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken);
Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken);
@@ -215,12 +167,5 @@ namespace Mono.Security.Interface
Task RenegotiateAsync (CancellationToken cancellationToken);
}
interface IMonoSslStream2 : IMonoSslStream
{
Task AuthenticateAsClientAsync (IMonoSslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken);
Task AuthenticateAsServerAsync (IMonoSslServerAuthenticationOptions sslServerAuthenticationOptions, CancellationToken cancellationToken);
}
}

View File

@@ -121,10 +121,6 @@ namespace Mono.Security.Interface
Stream innerStream, bool leaveInnerStreamOpen,
MonoTlsSettings settings = null);
internal abstract IMonoSslStream CreateSslStreamInternal (
SslStream sslStream, Stream innerStream, bool leaveInnerStreamOpen,
MonoTlsSettings settings);
#endregion
#region Native Certificate Implementation
@@ -133,34 +129,6 @@ namespace Mono.Security.Interface
get { return false; }
}
internal virtual X509Certificate2Impl GetNativeCertificate (
byte[] data, string password, X509KeyStorageFlags flags)
{
throw new InvalidOperationException ();
}
internal virtual X509Certificate2Impl GetNativeCertificate (
X509Certificate certificate)
{
throw new InvalidOperationException ();
}
#endregion
#region Certificate Validation
/*
* If @serverMode is true, then we're a server and want to validate a certificate
* that we received from a client.
*
* On OS X and Mobile, the @chain will be initialized with the @certificates, but not actually built.
*
* Returns `true` if certificate validation has been performed and `false` to invoke the
* default system validator.
*/
internal abstract bool ValidateCertificate (
ICertificateValidator2 validator, string targetHost, bool serverMode,
X509CertificateCollection certificates, bool wantsChain, ref X509Chain chain,
ref MonoSslPolicyErrors errors, ref int status11);
#endregion
#region Misc

View File

@@ -183,9 +183,10 @@ namespace Mono.Security.Interface
* - 1: everything up until May 2018
* - 2: the new ServicePointScheduler changes have landed
* - 3: full support for Client Certificates
* - 4: Legacy TLS Removal
*
*/
internal const int InternalVersion = 3;
internal const int InternalVersion = 4;
#endregion
}

View File

@@ -1,149 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography.X509Certificates;
using Mono.Security.Protocol.Tls;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsClientCertificate : HandshakeMessage
{
private bool clientCertSelected;
private X509Certificate clientCert;
#region Constructors
public TlsClientCertificate(Context context)
: base(context, HandshakeType.Certificate)
{
}
#endregion
#region Properties
public X509Certificate ClientCertificate {
get {
if (!clientCertSelected)
{
GetClientCertificate ();
clientCertSelected = true;
}
return clientCert;
}
}
#endregion
#region Methods
public override void Update()
{
base.Update();
this.Reset();
}
#endregion
#region Protected Methods
private void GetClientCertificate ()
{
// TODO: Client certificate selection is unfinished
ClientContext context = (ClientContext)this.Context;
// note: the server may ask for mutual authentication
// but may not require it (i.e. it can be optional).
if (context.ClientSettings.Certificates != null &&
context.ClientSettings.Certificates.Count > 0)
{
clientCert = context.SslStream.RaiseClientCertificateSelection(
this.Context.ClientSettings.Certificates,
new X509Certificate(this.Context.ServerSettings.Certificates[0].RawData),
this.Context.ClientSettings.TargetHost,
null);
// Note: the application code can raise it's
// own exception to stop the connection too.
}
// Update the selected client certificate
context.ClientSettings.ClientCertificate = clientCert;
}
private void SendCertificates ()
{
TlsStream chain = new TlsStream ();
X509Certificate currentCert = this.ClientCertificate;
while (currentCert != null) {
byte[] rawCert = currentCert.GetRawCertData ();
chain.WriteInt24 (rawCert.Length);
chain.Write(rawCert);
currentCert = FindParentCertificate (currentCert);
}
this.WriteInt24 ((int)chain.Length);
this.Write (chain.ToArray ());
}
protected override void ProcessAsSsl3()
{
if (this.ClientCertificate != null) {
SendCertificates ();
} else {
// an Alert warning for NoCertificate (41)
// should be sent from here - but that would
// break the current message handling
}
}
protected override void ProcessAsTls1()
{
if (this.ClientCertificate != null) {
SendCertificates ();
} else {
// return message with empty certificate (see 7.4.6 in RFC2246)
this.WriteInt24 (0);
}
}
private X509Certificate FindParentCertificate (X509Certificate cert)
{
#pragma warning disable 618
// This certificate is the root certificate
if (cert.GetName () == cert.GetIssuerName ())
return null;
foreach (X509Certificate certificate in this.Context.ClientSettings.Certificates) {
if (certificate.GetName () == cert.GetIssuerName ())
return certificate;
}
return null;
#pragma warning restore 618
}
#endregion
}
}

View File

@@ -1,220 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using Mono.Security.Cryptography;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsClientCertificateVerify : HandshakeMessage
{
#region Constructors
public TlsClientCertificateVerify(Context context)
: base(context, HandshakeType.CertificateVerify)
{
}
#endregion
#region Methods
public override void Update()
{
base.Update();
this.Reset();
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
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);
// CreateSignature uses ((RSA)privKey).DecryptValue which is not implemented
// in RSACryptoServiceProvider. Other implementations likely implement DecryptValue
// so we will try the CreateSignature method.
byte[] signature = null;
if (!(privKey is RSACryptoServiceProvider))
{
try
{
signature = hash.CreateSignature((RSA)privKey);
}
catch (NotImplementedException)
{ }
}
// If DecryptValue is not implemented, then try to export the private
// key and let the RSAManaged class do the DecryptValue
if (signature == null)
{
// RSAManaged of the selected ClientCertificate
// (at this moment the first one)
RSA rsa = this.getClientCertRSA((RSA)privKey);
// Write message
signature = hash.CreateSignature(rsa);
}
this.Write((short)signature.Length);
this.Write(signature, 0, signature.Length);
}
}
protected override void ProcessAsTls1()
{
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
{
// Compute handshake messages hash
MD5SHA1 hash = new MD5SHA1();
hash.ComputeHash(
context.HandshakeMessages.ToArray(),
0,
(int)context.HandshakeMessages.Length);
// CreateSignature uses ((RSA)privKey).DecryptValue which is not implemented
// in RSACryptoServiceProvider. Other implementations likely implement DecryptValue
// so we will try the CreateSignature method.
byte[] signature = null;
if (!(privKey is RSACryptoServiceProvider))
{
try
{
signature = hash.CreateSignature((RSA)privKey);
}
catch (NotImplementedException)
{ }
}
// If DecryptValue is not implemented, then try to export the private
// key and let the RSAManaged class do the DecryptValue
if (signature == null)
{
// RSAManaged of the selected ClientCertificate
// (at this moment the first one)
RSA rsa = this.getClientCertRSA((RSA)privKey);
// Write message
signature = hash.CreateSignature(rsa);
}
this.Write((short)signature.Length);
this.Write(signature, 0, signature.Length);
}
}
#endregion
#region Private methods
private RSA getClientCertRSA(RSA privKey)
{
RSAParameters rsaParams = new RSAParameters();
RSAParameters privateParams = privKey.ExportParameters(true);
// for RSA m_publickey contains 2 ASN.1 integers
// the modulus and the public exponent
ASN1 pubkey = new ASN1 (this.Context.ClientSettings.Certificates[0].GetPublicKey());
ASN1 modulus = pubkey [0];
if ((modulus == null) || (modulus.Tag != 0x02))
{
return null;
}
ASN1 exponent = pubkey [1];
if (exponent.Tag != 0x02)
{
return null;
}
rsaParams.Modulus = this.getUnsignedBigInteger(modulus.Value);
rsaParams.Exponent = exponent.Value;
// Set private key parameters
rsaParams.D = privateParams.D;
rsaParams.DP = privateParams.DP;
rsaParams.DQ = privateParams.DQ;
rsaParams.InverseQ = privateParams.InverseQ;
rsaParams.P = privateParams.P;
rsaParams.Q = privateParams.Q;
// BUG: MS BCL 1.0 can't import a key which
// isn't the same size as the one present in
// the container.
int keySize = (rsaParams.Modulus.Length << 3);
RSAManaged rsa = new RSAManaged(keySize);
rsa.ImportParameters (rsaParams);
return (RSA)rsa;
}
private byte[] getUnsignedBigInteger(byte[] integer)
{
if (integer [0] == 0x00)
{
// this first byte is added so we're sure it's an unsigned integer
// however we can't feed it into RSAParameters or DSAParameters
int length = integer.Length - 1;
byte[] uinteger = new byte [length];
Buffer.BlockCopy (integer, 1, uinteger, 0, length);
return uinteger;
}
else
{
return integer;
}
}
#endregion
}
}

View File

@@ -1,87 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography;
using Mono.Security.Cryptography;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsClientFinished : HandshakeMessage
{
#region Constructors
public TlsClientFinished(Context context)
: base(context, HandshakeType.Finished)
{
}
#endregion
#region Methods
public override void Update()
{
base.Update();
this.Reset();
}
#endregion
#region Protected Methods
static private byte[] Ssl3Marker = new byte [4] { 0x43, 0x4c, 0x4e, 0x54 };
protected override void ProcessAsSsl3()
{
// Compute handshake messages hashes
HashAlgorithm hash = new SslHandshakeHash(this.Context.MasterSecret);
byte[] data = this.Context.HandshakeMessages.ToArray ();
hash.TransformBlock (data, 0, data.Length, data, 0);
hash.TransformBlock (Ssl3Marker, 0, Ssl3Marker.Length, Ssl3Marker, 0);
// hack to avoid memory allocation
hash.TransformFinalBlock (CipherSuite.EmptyArray, 0, 0);
this.Write (hash.Hash);
}
protected override void ProcessAsTls1()
{
// Compute handshake messages hash
HashAlgorithm hash = new MD5SHA1();
// note: we could call HashAlgorithm.ComputeHash(Stream) but that would allocate (on Mono)
// a 4096 bytes buffer to process the hash - which is bigger than HandshakeMessages
byte[] data = this.Context.HandshakeMessages.ToArray ();
byte[] digest = hash.ComputeHash (data, 0, data.Length);
// Write message
Write(this.Context.Write.Cipher.PRF(this.Context.MasterSecret, "client finished", digest, 12));
}
#endregion
}
}

View File

@@ -1,139 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Net;
using System.Security.Cryptography;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsClientHello : HandshakeMessage
{
#region Fields
private byte[] random;
#endregion
#region Constructors
public TlsClientHello(Context context)
: base(context, HandshakeType.ClientHello)
{
}
#endregion
#region Methods
public override void Update()
{
ClientContext context = (ClientContext)this.Context;
base.Update();
context.ClientRandom = random;
context.ClientHelloProtocol = this.Context.Protocol;
random = null;
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
// Client Version
this.Write(this.Context.Protocol);
// Random bytes - Unix time + Radom bytes [28]
TlsStream clientRandom = new TlsStream();
clientRandom.Write(this.Context.GetUnixTime());
clientRandom.Write(this.Context.GetSecureRandomBytes(28));
this.random = clientRandom.ToArray();
clientRandom.Reset();
this.Write(this.random);
// Session id
// Check if we have a cache session we could reuse
this.Context.SessionId = ClientSessionCache.FromHost (this.Context.ClientSettings.TargetHost);
if (this.Context.SessionId != null)
{
this.Write((byte)this.Context.SessionId.Length);
if (this.Context.SessionId.Length > 0)
{
this.Write(this.Context.SessionId);
}
}
else
{
this.Write((byte)0);
}
// Write length of Cipher suites
this.Write((short)(this.Context.SupportedCiphers.Count*2));
// Write Supported Cipher suites
for (int i = 0; i < this.Context.SupportedCiphers.Count; i++)
{
this.Write((short)this.Context.SupportedCiphers[i].Code);
}
// Compression methods length
this.Write((byte)1);
// Compression methods ( 0 = none )
this.Write((byte)this.Context.CompressionMethod);
}
protected override void ProcessAsTls1()
{
ProcessAsSsl3 ();
// If applicable add the "server_name" extension to the hello message
// http://www.ietf.org/rfc/rfc3546.txt
string host = Context.ClientSettings.TargetHost;
// Our TargetHost might be an address (not a host *name*) - see bug #8553
// RFC3546 -> Literal IPv4 and IPv6 addresses are not permitted in "HostName".
IPAddress addr;
if (IPAddress.TryParse (host, out addr))
return;
TlsStream extensions = new TlsStream ();
byte[] server_name = System.Text.Encoding.UTF8.GetBytes (host);
extensions.Write ((short) 0x0000); // ExtensionType: server_name (0)
extensions.Write ((short) (server_name.Length + 5)); // ServerNameList (length)
extensions.Write ((short) (server_name.Length + 3)); // ServerName (length)
extensions.Write ((byte) 0x00); // NameType: host_name (0)
extensions.Write ((short) server_name.Length); // HostName (length)
extensions.Write (server_name); // HostName (UTF8)
this.Write ((short) extensions.Length);
this.Write (extensions.ToArray ());
}
#endregion
}
}

View File

@@ -1,98 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography;
using Mono.Security.Cryptography;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsClientKeyExchange : HandshakeMessage
{
#region Constructors
public TlsClientKeyExchange (Context context) :
base(context, HandshakeType.ClientKeyExchange)
{
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
// a large chunk of code is common to both SSL3 and TLS1
// SSL3 doesn't send the length of the buffer
ProcessCommon (false);
}
protected override void ProcessAsTls1()
{
// a large chunk of code is common to both SSL3 and TLS1
// TLS1 does send the length of the buffer
ProcessCommon (true);
}
public void ProcessCommon (bool sendLength)
{
// Compute pre master secret
byte[] preMasterSecret = this.Context.Negotiating.Cipher.CreatePremasterSecret ();
// Create a new RSA key
RSA rsa = null;
if (this.Context.ServerSettings.ServerKeyExchange)
{
// this is the case for "exportable" ciphers
rsa = new RSAManaged ();
rsa.ImportParameters (this.Context.ServerSettings.RsaParameters);
}
else
{
rsa = this.Context.ServerSettings.CertificateRSA;
}
// Encrypt premaster_sercret
RSAPKCS1KeyExchangeFormatter formatter = new RSAPKCS1KeyExchangeFormatter (rsa);
// Write the preMasterSecret encrypted
byte[] buffer = formatter.CreateKeyExchange (preMasterSecret);
if (sendLength)
this.Write ((short) buffer.Length);
this.Write (buffer);
// Create master secret
this.Context.Negotiating.Cipher.ComputeMasterSecret (preMasterSecret);
// Create keys
this.Context.Negotiating.Cipher.ComputeKeys ();
// Clear resources
rsa.Clear ();
}
#endregion
}
}

View File

@@ -1,450 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
// Copyright (C) 2004, 2006-2010 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Net;
using System.Collections;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using X509Cert = System.Security.Cryptography.X509Certificates;
using Mono.Security.X509;
using Mono.Security.X509.Extensions;
using Mono.Security.Interface;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsServerCertificate : HandshakeMessage
{
#region Fields
private X509CertificateCollection certificates;
#endregion
#region Constructors
public TlsServerCertificate(Context context, byte[] buffer)
: base(context, HandshakeType.Certificate, buffer)
{
}
#endregion
#region Methods
public override void Update()
{
base.Update();
this.Context.ServerSettings.Certificates = this.certificates;
this.Context.ServerSettings.UpdateCertificateRSA();
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
this.certificates = new X509CertificateCollection();
int readed = 0;
int length = this.ReadInt24();
while (readed < length)
{
// Read certificate length
int certLength = ReadInt24();
// Increment readed
readed += 3;
if (certLength > 0)
{
// Read certificate data
byte[] buffer = this.ReadBytes(certLength);
// Create a new X509 Certificate
X509Certificate certificate = new X509Certificate(buffer);
certificates.Add(certificate);
readed += certLength;
DebugHelper.WriteLine(
String.Format("Server Certificate {0}", certificates.Count),
buffer);
}
}
this.validateCertificates(certificates);
}
#endregion
#region Private Methods
// Note: this method only works for RSA certificates
// DH certificates requires some changes - does anyone use one ?
private bool checkCertificateUsage (X509Certificate cert)
{
ClientContext context = (ClientContext)this.Context;
// certificate extensions are required for this
// we "must" accept older certificates without proofs
if (cert.Version < 3)
return true;
KeyUsages ku = KeyUsages.none;
switch (context.Negotiating.Cipher.ExchangeAlgorithmType)
{
case ExchangeAlgorithmType.RsaSign:
ku = KeyUsages.digitalSignature;
break;
case ExchangeAlgorithmType.RsaKeyX:
ku = KeyUsages.keyEncipherment;
break;
case ExchangeAlgorithmType.DiffieHellman:
ku = KeyUsages.keyAgreement;
break;
case ExchangeAlgorithmType.Fortezza:
return false; // unsupported certificate type
}
KeyUsageExtension kux = null;
ExtendedKeyUsageExtension eku = null;
X509Extension xtn = cert.Extensions ["2.5.29.15"];
if (xtn != null)
kux = new KeyUsageExtension (xtn);
xtn = cert.Extensions ["2.5.29.37"];
if (xtn != null)
eku = new ExtendedKeyUsageExtension (xtn);
if ((kux != null) && (eku != null))
{
// RFC3280 states that when both KeyUsageExtension and
// ExtendedKeyUsageExtension are present then BOTH should
// be valid
if (!kux.Support (ku))
return false;
return (eku.KeyPurpose.Contains ("1.3.6.1.5.5.7.3.1") ||
eku.KeyPurpose.Contains ("2.16.840.1.113730.4.1"));
}
else if (kux != null)
{
return kux.Support (ku);
}
else if (eku != null)
{
// Server Authentication (1.3.6.1.5.5.7.3.1) or
// Netscape Server Gated Crypto (2.16.840.1.113730.4)
return (eku.KeyPurpose.Contains ("1.3.6.1.5.5.7.3.1") ||
eku.KeyPurpose.Contains ("2.16.840.1.113730.4.1"));
}
// last chance - try with older (deprecated) Netscape extensions
xtn = cert.Extensions ["2.16.840.1.113730.1.1"];
if (xtn != null)
{
NetscapeCertTypeExtension ct = new NetscapeCertTypeExtension (xtn);
return ct.Support (NetscapeCertTypeExtension.CertTypes.SslServer);
}
// if the CN=host (checked later) then we assume this is meant for SSL/TLS
// e.g. the new smtp.gmail.com certificate
return true;
}
private void validateCertificates(X509CertificateCollection certificates)
{
ClientContext context = (ClientContext)this.Context;
AlertDescription description = AlertDescription.BadCertificate;
#if INSIDE_SYSTEM
// This helps the linker to remove a lot of validation code that will never be used since
// System.dll will, for OSX and iOS, uses the operating system X.509 certificate validations
RemoteValidation (context, description);
#else
if (context.SslStream.HaveRemoteValidation2Callback)
RemoteValidation (context, description);
else
LocalValidation (context, description);
#endif
}
void RemoteValidation (ClientContext context, AlertDescription description)
{
ValidationResult res = context.SslStream.RaiseServerCertificateValidation2 (certificates);
if (res.Trusted)
return;
long error = res.ErrorCode;
switch (error) {
case 0x800B0101:
description = AlertDescription.CertificateExpired;
break;
case 0x800B010A:
description = AlertDescription.UnknownCA;
break;
case 0x800B0109:
description = AlertDescription.UnknownCA;
break;
default:
description = AlertDescription.CertificateUnknown;
break;
}
string err = String.Format ("Invalid certificate received from server. Error code: 0x{0:x}", error);
throw new TlsException (description, err);
}
void LocalValidation (ClientContext context, AlertDescription description)
{
// the leaf is the web server certificate
X509Certificate leaf = certificates [0];
X509Cert.X509Certificate cert = new X509Cert.X509Certificate (leaf.RawData);
ArrayList errors = new ArrayList();
// SSL specific check - not all certificates can be
// used to server-side SSL some rules applies after
// all ;-)
if (!checkCertificateUsage (leaf))
{
// WinError.h CERT_E_PURPOSE 0x800B0106
errors.Add ((int)-2146762490);
}
// SSL specific check - does the certificate match
// the host ?
if (!checkServerIdentity (leaf))
{
// WinError.h CERT_E_CN_NO_MATCH 0x800B010F
errors.Add ((int)-2146762481);
}
// Note: building and verifying a chain can take much time
// so we do it last (letting simple things fails first)
// Note: In TLS the certificates MUST be in order (and
// optionally include the root certificate) so we're not
// building the chain using LoadCertificate (it's faster)
// Note: IIS doesn't seem to send the whole certificate chain
// but only the server certificate :-( it's assuming that you
// already have this chain installed on your computer. duh!
// http://groups.google.ca/groups?q=IIS+server+certificate+chain&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=85058s%24avd%241%40nnrp1.deja.com&rnum=3
// we must remove the leaf certificate from the chain
X509CertificateCollection chain = new X509CertificateCollection (certificates);
chain.Remove (leaf);
X509Chain verify = new X509Chain (chain);
bool result = false;
try
{
result = verify.Build (leaf);
}
catch (Exception)
{
result = false;
}
if (!result)
{
switch (verify.Status)
{
case X509ChainStatusFlags.InvalidBasicConstraints:
// 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;
}
}
int[] certificateErrors = (int[])errors.ToArray(typeof(int));
if (!context.SslStream.RaiseServerCertificateValidation(
cert,
certificateErrors))
{
throw new TlsException(
description,
"Invalid certificate received from server.");
}
}
// RFC2818 - HTTP Over TLS, Section 3.1
// http://www.ietf.org/rfc/rfc2818.txt
//
// 1. if present MUST use subjectAltName dNSName as identity
// 1.1. if multiples entries a match of any one is acceptable
// 1.2. wildcard * is acceptable
// 2. URI may be an IP address -> subjectAltName.iPAddress
// 2.1. exact match is required
// 3. Use of the most specific Common Name (CN=) in the Subject
// 3.1 Existing practice but DEPRECATED
private bool checkServerIdentity (X509Certificate cert)
{
ClientContext context = (ClientContext)this.Context;
string targetHost = context.ClientSettings.TargetHost;
X509Extension ext = cert.Extensions ["2.5.29.17"];
// 1. subjectAltName
if (ext != null)
{
SubjectAltNameExtension subjectAltName = new SubjectAltNameExtension (ext);
// 1.1 - multiple dNSName
foreach (string dns in subjectAltName.DNSNames)
{
// 1.2 TODO - wildcard support
if (Match (targetHost, dns))
return true;
}
// 2. ipAddress
foreach (string ip in subjectAltName.IPAddresses)
{
// 2.1. Exact match required
if (ip == targetHost)
return true;
}
}
// 3. Common Name (CN=)
return checkDomainName (cert.SubjectName);
}
private bool checkDomainName(string subjectName)
{
ClientContext context = (ClientContext)this.Context;
string domainName = String.Empty;
Regex search = new Regex(@"CN\s*=\s*([^,]*)");
MatchCollection elements = search.Matches(subjectName);
if (elements.Count == 1)
{
if (elements[0].Success)
{
domainName = elements[0].Groups[1].Value.ToString();
}
}
return Match (context.ClientSettings.TargetHost, domainName);
}
// ensure the pattern is valid wrt to RFC2595 and RFC2818
// http://www.ietf.org/rfc/rfc2595.txt
// http://www.ietf.org/rfc/rfc2818.txt
static bool Match (string hostname, string pattern)
{
// check if this is a pattern
int index = pattern.IndexOf ('*');
if (index == -1) {
// not a pattern, do a direct case-insensitive comparison
return (String.Compare (hostname, pattern, true, CultureInfo.InvariantCulture) == 0);
}
// check pattern validity
// A "*" wildcard character MAY be used as the left-most name component in the certificate.
// unless this is the last char (valid)
if (index != pattern.Length - 1) {
// then the next char must be a dot .'.
if (pattern [index + 1] != '.')
return false;
}
// only one (A) wildcard is supported
int i2 = pattern.IndexOf ('*', index + 1);
if (i2 != -1)
return false;
// match the end of the pattern
string end = pattern.Substring (index + 1);
int length = hostname.Length - end.Length;
// no point to check a pattern that is longer than the hostname
if (length <= 0)
return false;
if (String.Compare (hostname, length, end, 0, end.Length, true, CultureInfo.InvariantCulture) != 0)
return false;
// special case, we start with the wildcard
if (index == 0) {
// ensure we hostname non-matched part (start) doesn't contain a dot
int i3 = hostname.IndexOf ('.');
return ((i3 == -1) || (i3 >= (hostname.Length - end.Length)));
}
// match the start of the pattern
string start = pattern.Substring (0, index);
return (String.Compare (hostname, 0, start, 0, start.Length, true, CultureInfo.InvariantCulture) == 0);
}
#endregion
}
}

View File

@@ -1,111 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Text;
using Mono.Security;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsServerCertificateRequest : HandshakeMessage
{
#region Fields
private ClientCertificateType[] certificateTypes;
private string[] distinguisedNames;
#endregion
#region Constructors
public TlsServerCertificateRequest(Context context, byte[] buffer)
: base(context, HandshakeType.CertificateRequest, buffer)
{
}
#endregion
#region Methods
public override void Update()
{
base.Update();
this.Context.ServerSettings.CertificateTypes = this.certificateTypes;
this.Context.ServerSettings.DistinguisedNames = this.distinguisedNames;
this.Context.ServerSettings.CertificateRequest = true;
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
// Read requested certificate types
int typesCount = this.ReadByte();
this.certificateTypes = new ClientCertificateType[typesCount];
for (int i = 0; i < typesCount; i++)
{
this.certificateTypes[i] = (ClientCertificateType)this.ReadByte();
}
/*
* Read requested certificate authorities (Distinguised Names)
*
* Name ::= SEQUENCE OF RelativeDistinguishedName
*
* RelativeDistinguishedName ::= SET OF AttributeValueAssertion
*
* AttributeValueAssertion ::= SEQUENCE {
* attributeType OBJECT IDENTIFIER
* attributeValue ANY }
*/
if (this.ReadInt16() != 0)
{
ASN1 rdn = new ASN1(this.ReadBytes(this.ReadInt16()));
distinguisedNames = new string[rdn.Count];
for (int i = 0; i < rdn.Count; i++)
{
// element[0] = attributeType
// element[1] = attributeValue
ASN1 element = new ASN1(rdn[i].Value);
distinguisedNames[i] = Encoding.UTF8.GetString(element[1].Value);
}
}
}
#endregion
}
}

View File

@@ -1,102 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography;
using Mono.Security.Cryptography;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsServerFinished : HandshakeMessage
{
#region Constructors
public TlsServerFinished(Context context, byte[] buffer)
: base(context, HandshakeType.Finished, buffer)
{
}
#endregion
#region Methods
public override void Update()
{
base.Update();
// Hahdshake is finished
this.Context.HandshakeState = HandshakeState.Finished;
}
#endregion
#region Protected Methods
static private byte[] Ssl3Marker = new byte [4] { 0x53, 0x52, 0x56, 0x52 };
protected override void ProcessAsSsl3()
{
// Compute handshake messages hashes
HashAlgorithm hash = new SslHandshakeHash(this.Context.MasterSecret);
byte[] data = this.Context.HandshakeMessages.ToArray ();
hash.TransformBlock (data, 0, data.Length, data, 0);
hash.TransformBlock (Ssl3Marker, 0, Ssl3Marker.Length, Ssl3Marker, 0);
// hack to avoid memory allocation
hash.TransformFinalBlock (CipherSuite.EmptyArray, 0, 0);
byte[] serverHash = this.ReadBytes((int)Length);
byte[] clientHash = hash.Hash;
// Check server prf against client prf
if (!Compare (clientHash, serverHash))
{
// TODO: Review that selected alert is correct
throw new TlsException(AlertDescription.InsuficientSecurity, "Invalid ServerFinished message received.");
}
}
protected override void ProcessAsTls1()
{
byte[] serverPRF = this.ReadBytes((int)Length);
HashAlgorithm hash = new MD5SHA1();
// note: we could call HashAlgorithm.ComputeHash(Stream) but that would allocate (on Mono)
// a 4096 bytes buffer to process the hash - which is bigger than HandshakeMessages
byte[] data = this.Context.HandshakeMessages.ToArray ();
byte[] digest = hash.ComputeHash (data, 0, data.Length);
byte[] clientPRF = this.Context.Current.Cipher.PRF(this.Context.MasterSecret, "server finished", digest, 12);
// Check server prf against client prf
if (!Compare (clientPRF, serverPRF))
{
throw new TlsException("Invalid ServerFinished message received.");
}
}
#endregion
}
}

View File

@@ -1,150 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsServerHello : HandshakeMessage
{
#region Fields
private SecurityCompressionType compressionMethod;
private byte[] random;
private byte[] sessionId;
private CipherSuite cipherSuite;
#endregion
#region Constructors
public TlsServerHello(Context context, byte[] buffer)
: base(context, HandshakeType.ServerHello, buffer)
{
}
#endregion
#region Methods
public override void Update()
{
base.Update();
this.Context.SessionId = this.sessionId;
this.Context.ServerRandom = this.random;
this.Context.Negotiating.Cipher = this.cipherSuite;
this.Context.CompressionMethod = this.compressionMethod;
this.Context.ProtocolNegotiated = true;
DebugHelper.WriteLine("Selected Cipher Suite {0}", this.cipherSuite.Name);
DebugHelper.WriteLine("Client random", this.Context.ClientRandom);
DebugHelper.WriteLine("Server random", this.Context.ServerRandom);
// Compute ClientRandom + ServerRandom
int clen = this.Context.ClientRandom.Length;
int slen = this.Context.ServerRandom.Length;
int rlen = clen + slen;
byte[] cs = new byte[rlen];
Buffer.BlockCopy (this.Context.ClientRandom, 0, cs, 0, clen);
Buffer.BlockCopy (this.Context.ServerRandom, 0, cs, clen, slen);
this.Context.RandomCS = cs;
// Server Random + Client Random
byte[] sc = new byte[rlen];
Buffer.BlockCopy (this.Context.ServerRandom, 0, sc, 0, slen);
Buffer.BlockCopy (this.Context.ClientRandom, 0, sc, slen, clen);
this.Context.RandomSC = sc;
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
// Read protocol version
this.processProtocol(this.ReadInt16());
// Read random - Unix time + Random bytes
this.random = this.ReadBytes(32);
// Read Session id
int length = (int) ReadByte ();
if (length > 0)
{
this.sessionId = this.ReadBytes(length);
ClientSessionCache.Add (this.Context.ClientSettings.TargetHost, this.sessionId);
this.Context.AbbreviatedHandshake = Compare (this.sessionId, this.Context.SessionId);
}
else
{
this.Context.AbbreviatedHandshake = false;
}
// Read cipher suite
short cipherCode = this.ReadInt16();
if (this.Context.SupportedCiphers.IndexOf(cipherCode) == -1)
{
// The server has sent an invalid ciphersuite
throw new TlsException(AlertDescription.InsuficientSecurity, "Invalid cipher suite received from server");
}
this.cipherSuite = this.Context.SupportedCiphers[cipherCode];
// Read compression methods ( always 0 )
this.compressionMethod = (SecurityCompressionType)this.ReadByte();
}
#endregion
#region Private Methods
private void processProtocol(short protocol)
{
SecurityProtocolType serverProtocol = this.Context.DecodeProtocolCode(protocol);
if ((serverProtocol & this.Context.SecurityProtocolFlags) == serverProtocol ||
(this.Context.SecurityProtocolFlags & SecurityProtocolType.Default) == SecurityProtocolType.Default)
{
this.Context.SecurityProtocol = serverProtocol;
this.Context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers (false, serverProtocol);
DebugHelper.WriteLine("Selected protocol {0}", serverProtocol);
}
else
{
throw new TlsException(
AlertDescription.ProtocolVersion,
"Incorrect protocol version received from server");
}
}
#endregion
}
}

View File

@@ -1,52 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsServerHelloDone : HandshakeMessage
{
#region Constructors
public TlsServerHelloDone(Context context, byte[] buffer)
: base(context, HandshakeType.ServerHelloDone, buffer)
{
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
}
protected override void ProcessAsTls1()
{
}
#endregion
}
}

View File

@@ -1,121 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography;
using Mono.Security.Cryptography;
using Mono.Security.X509;
namespace Mono.Security.Protocol.Tls.Handshake.Client
{
internal class TlsServerKeyExchange : HandshakeMessage
{
#region Fields
private RSAParameters rsaParams;
private byte[] signedParams;
#endregion
#region Constructors
public TlsServerKeyExchange(Context context, byte[] buffer)
: base(context, HandshakeType.ServerKeyExchange, buffer)
{
this.verifySignature();
}
#endregion
#region Methods
public override void Update()
{
base.Update();
this.Context.ServerSettings.ServerKeyExchange = true;
this.Context.ServerSettings.RsaParameters = this.rsaParams;
this.Context.ServerSettings.SignedParams = this.signedParams;
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
this.rsaParams = new RSAParameters();
// Read modulus
this.rsaParams.Modulus = this.ReadBytes(this.ReadInt16());
// Read exponent
this.rsaParams.Exponent = this.ReadBytes(this.ReadInt16());
// Read signed params
this.signedParams = this.ReadBytes(this.ReadInt16());
}
#endregion
#region Private Methods
private void verifySignature()
{
MD5SHA1 hash = new MD5SHA1();
// Calculate size of server params
int size = rsaParams.Modulus.Length + rsaParams.Exponent.Length + 4;
// Create server params array
TlsStream stream = new TlsStream();
stream.Write(this.Context.RandomCS);
stream.Write(this.ToArray(), 0, size);
hash.ComputeHash(stream.ToArray());
stream.Reset();
bool isValidSignature = hash.VerifySignature(
this.Context.ServerSettings.CertificateRSA,
this.signedParams);
if (!isValidSignature)
{
throw new TlsException(
AlertDescription.DecodeError,
"Data was not signed with the server certificate.");
}
}
#endregion
}
}

View File

@@ -1,276 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using SSCX = System.Security.Cryptography.X509Certificates;
using Mono.Security.X509;
using Mono.Security.X509.Extensions;
namespace Mono.Security.Protocol.Tls.Handshake.Server
{
internal class TlsClientCertificate : HandshakeMessage
{
#region Fields
private X509CertificateCollection clientCertificates;
#endregion
#region Constructors
public TlsClientCertificate(Context context, byte[] buffer)
: base(context, HandshakeType.Certificate, buffer)
{
}
#endregion
#region Methods
public override void Update()
{
foreach (X509Certificate certificate in clientCertificates) {
this.Context.ClientSettings.Certificates.Add (new SSCX.X509Certificate (certificate.RawData));
}
}
public bool HasCertificate {
get { return clientCertificates.Count > 0; }
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
int bytesRead = 0;
int length = this.ReadInt24 ();
this.clientCertificates = new X509CertificateCollection ();
while (length > bytesRead) {
int certLength = this.ReadInt24 ();
bytesRead += certLength + 3;
byte[] cert = this.ReadBytes (certLength);
this.clientCertificates.Add (new X509Certificate (cert));
}
if (this.clientCertificates.Count > 0)
{
this.validateCertificates (this.clientCertificates);
}
else if ((this.Context as ServerContext).ClientCertificateRequired)
{
throw new TlsException (AlertDescription.NoCertificate);
}
}
#endregion
#region Private Methods
private bool checkCertificateUsage (X509Certificate cert)
{
ServerContext context = (ServerContext)this.Context;
// certificate extensions are required for this
// we "must" accept older certificates without proofs
if (cert.Version < 3)
return true;
KeyUsages ku = KeyUsages.none;
switch (context.Negotiating.Cipher.ExchangeAlgorithmType)
{
case ExchangeAlgorithmType.RsaSign:
case ExchangeAlgorithmType.RsaKeyX:
ku = KeyUsages.digitalSignature;
break;
case ExchangeAlgorithmType.DiffieHellman:
ku = KeyUsages.keyAgreement;
break;
case ExchangeAlgorithmType.Fortezza:
return false; // unsupported certificate type
}
KeyUsageExtension kux = null;
ExtendedKeyUsageExtension eku = null;
X509Extension xtn = cert.Extensions["2.5.29.15"];
if (xtn != null)
kux = new KeyUsageExtension (xtn);
xtn = cert.Extensions["2.5.29.37"];
if (xtn != null)
eku = new ExtendedKeyUsageExtension (xtn);
if ((kux != null) && (eku != null))
{
// RFC3280 states that when both KeyUsageExtension and
// ExtendedKeyUsageExtension are present then BOTH should
// be valid
return (kux.Support (ku) &&
eku.KeyPurpose.Contains ("1.3.6.1.5.5.7.3.2"));
}
else if (kux != null)
{
return kux.Support (ku);
}
else if (eku != null)
{
// Client Authentication (1.3.6.1.5.5.7.3.2)
return eku.KeyPurpose.Contains ("1.3.6.1.5.5.7.3.2");
}
// last chance - try with older (deprecated) Netscape extensions
xtn = cert.Extensions["2.16.840.1.113730.1.1"];
if (xtn != null)
{
NetscapeCertTypeExtension ct = new NetscapeCertTypeExtension (xtn);
return ct.Support (NetscapeCertTypeExtension.CertTypes.SslClient);
}
// certificate isn't valid for SSL server usage
return false;
}
private void validateCertificates (X509CertificateCollection certificates)
{
ServerContext context = (ServerContext)this.Context;
AlertDescription description = AlertDescription.BadCertificate;
SSCX.X509Certificate client = null;
int[] certificateErrors = null;
// note: certificate may be null is no certificate is sent
// (e.g. optional mutual authentication)
if (certificates.Count > 0) {
X509Certificate leaf = certificates[0];
ArrayList errors = new ArrayList ();
// SSL specific check - not all certificates can be
// used to server-side SSL some rules applies after
// all ;-)
if (!checkCertificateUsage (leaf))
{
// WinError.h CERT_E_PURPOSE 0x800B0106
errors.Add ((int)-2146762490);
}
X509Chain verify;
// was a chain supplied ? if so use it, if not
if (certificates.Count > 1) {
// if so use it (and don't build our own)
X509CertificateCollection chain = new X509CertificateCollection (certificates);
chain.Remove (leaf);
verify = new X509Chain (chain);
} else {
// if not, then let's build our own (based on what's available in the stores)
verify = new X509Chain ();
}
bool result = false;
try
{
result = verify.Build (leaf);
}
catch (Exception)
{
result = false;
}
if (!result)
{
switch (verify.Status)
{
case X509ChainStatusFlags.InvalidBasicConstraints:
// 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;
}
}
client = new SSCX.X509Certificate (leaf.RawData);
certificateErrors = (int[])errors.ToArray (typeof (int));
}
else
{
certificateErrors = new int[0];
}
SSCX.X509CertificateCollection certCollection = new SSCX.X509CertificateCollection ();
foreach (X509Certificate certificate in certificates) {
certCollection.Add (new SSCX.X509Certificate (certificate.RawData));
}
if (!context.SslStream.RaiseClientCertificateValidation(client, certificateErrors))
{
throw new TlsException (
description,
"Invalid certificate received from client.");
}
this.Context.ClientSettings.ClientCertificate = client;
}
#endregion
}
}

View File

@@ -1,86 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using Mono.Security.Cryptography;
namespace Mono.Security.Protocol.Tls.Handshake.Server
{
internal class TlsClientCertificateVerify : HandshakeMessage
{
#region Constructors
public TlsClientCertificateVerify(Context context, byte[] buffer)
: base(context, HandshakeType.CertificateVerify, buffer)
{
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
ServerContext context = (ServerContext)this.Context;
int length = this.ReadInt16 ();
byte[] signature = this.ReadBytes (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 Failure.");
}
}
protected override void ProcessAsTls1()
{
ServerContext context = (ServerContext)this.Context;
int length = this.ReadInt16 ();
byte[] signature = this.ReadBytes (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 Failure.");
}
}
#endregion
}
}

View File

@@ -1,88 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography;
using Mono.Security.Cryptography;
namespace Mono.Security.Protocol.Tls.Handshake.Server
{
internal class TlsClientFinished : HandshakeMessage
{
#region Constructors
public TlsClientFinished(Context context, byte[] buffer)
: base(context, HandshakeType.Finished, buffer)
{
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
// Compute handshake messages hashes
HashAlgorithm hash = new SslHandshakeHash(this.Context.MasterSecret);
TlsStream data = new TlsStream();
data.Write(this.Context.HandshakeMessages.ToArray());
data.Write((int)0x434C4E54);
hash.TransformFinalBlock(data.ToArray(), 0, (int)data.Length);
data.Reset();
byte[] clientHash = this.ReadBytes((int)Length);
byte[] serverHash = hash.Hash;
// Check client prf against server prf
if (!Compare (clientHash, serverHash))
{
throw new TlsException(AlertDescription.DecryptError, "Decrypt error.");
}
}
protected override void ProcessAsTls1()
{
byte[] clientPRF = this.ReadBytes((int)this.Length);
HashAlgorithm hash = new MD5SHA1();
byte[] data = this.Context.HandshakeMessages.ToArray ();
byte[] digest = hash.ComputeHash (data, 0, data.Length);
byte[] serverPRF = this.Context.Current.Cipher.PRF(
this.Context.MasterSecret, "client finished", digest, 12);
// Check client prf against server prf
if (!Compare (clientPRF, serverPRF))
{
throw new TlsException(AlertDescription.DecryptError, "Decrypt error.");
}
}
#endregion
}
}

View File

@@ -1,152 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography;
namespace Mono.Security.Protocol.Tls.Handshake.Server
{
internal class TlsClientHello : HandshakeMessage
{
#region Private Fields
private byte[] random;
private byte[] sessionId;
private short[] cipherSuites;
private byte[] compressionMethods;
#endregion
#region Constructors
public TlsClientHello(Context context, byte[] buffer)
: base(context, HandshakeType.ClientHello, buffer)
{
}
#endregion
#region Methods
public override void Update()
{
base.Update();
this.selectCipherSuite();
this.selectCompressionMethod();
this.Context.SessionId = this.sessionId;
this.Context.ClientRandom = this.random;
this.Context.ProtocolNegotiated = true;
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
// Client Version
this.processProtocol(this.ReadInt16());
// Random bytes - Unix time + Radom bytes [28]
this.random = this.ReadBytes(32);
// Session id
// Send the session ID empty
this.sessionId = this.ReadBytes(this.ReadByte());
// Read Supported Cipher Suites count
this.cipherSuites = new short[this.ReadInt16()/2];
// Read Cipher Suites
for (int i = 0; i < this.cipherSuites.Length; i++)
{
this.cipherSuites[i] = this.ReadInt16();
}
// Compression methods length
this.compressionMethods = new byte[this.ReadByte()];
for (int i = 0; i < this.compressionMethods.Length; i++)
{
this.compressionMethods[i] = this.ReadByte();
}
}
#endregion
#region Private Methods
private void processProtocol(short protocol)
{
// a server MUST reply with the hight version supported (`true` for fallback)
// so a TLS 1.2 client (like Google Chrome) will be returned that the server uses TLS 1.0
// instead of an alert about the protocol
SecurityProtocolType clientProtocol = Context.DecodeProtocolCode (protocol, true);
if ((clientProtocol & this.Context.SecurityProtocolFlags) == clientProtocol ||
(this.Context.SecurityProtocolFlags & SecurityProtocolType.Default) == SecurityProtocolType.Default)
{
this.Context.SecurityProtocol = clientProtocol;
this.Context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers (true, clientProtocol);
}
else
{
throw new TlsException(AlertDescription.ProtocolVersion, "Incorrect protocol version received from 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)
{
this.Context.Negotiating.Cipher = this.Context.SupportedCiphers[index];
break;
}
}
if (this.Context.Negotiating.Cipher == null)
{
throw new TlsException(AlertDescription.InsuficientSecurity, "Insuficient Security");
}
}
private void selectCompressionMethod()
{
this.Context.CompressionMethod = SecurityCompressionType.None;
}
#endregion
}
}

View File

@@ -1,116 +0,0 @@
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
namespace Mono.Security.Protocol.Tls.Handshake.Server
{
internal class TlsClientKeyExchange : HandshakeMessage
{
#region Constructors
public TlsClientKeyExchange(Context context, byte[] buffer) :
base(context,
HandshakeType.ClientKeyExchange,
buffer)
{
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
AsymmetricAlgorithm privKey = null;
ServerContext context = (ServerContext)this.Context;
// Select the private key information
privKey = context.SslStream.RaisePrivateKeySelection(
new X509Certificate(context.ServerSettings.Certificates[0].RawData),
null);
if (privKey == null)
{
throw new TlsException(AlertDescription.UserCancelled, "Server certificate Private Key unavailable.");
}
// Read client premaster secret
byte[] clientSecret = this.ReadBytes((int)this.Length);
// Decrypt premaster secret
RSAPKCS1KeyExchangeDeformatter deformatter = new RSAPKCS1KeyExchangeDeformatter(privKey);
byte[] preMasterSecret = deformatter.DecryptKeyExchange(clientSecret);
// Create master secret
this.Context.Negotiating.Cipher.ComputeMasterSecret(preMasterSecret);
// Create keys
this.Context.Negotiating.Cipher.ComputeKeys ();
// Initialize Cipher Suite
this.Context.Negotiating.Cipher.InitializeCipher ();
}
protected override void ProcessAsTls1()
{
AsymmetricAlgorithm privKey = null;
ServerContext context = (ServerContext)this.Context;
// Select the private key information
// Select the private key information
privKey = context.SslStream.RaisePrivateKeySelection(
new X509Certificate(context.ServerSettings.Certificates[0].RawData),
null);
if (privKey == null)
{
throw new TlsException(AlertDescription.UserCancelled, "Server certificate Private Key unavailable.");
}
// Read client premaster secret
byte[] clientSecret = this.ReadBytes(this.ReadInt16());
// Decrypt premaster secret
RSAPKCS1KeyExchangeDeformatter deformatter = new RSAPKCS1KeyExchangeDeformatter(privKey);
byte[] preMasterSecret = deformatter.DecryptKeyExchange(clientSecret);
// Create master secret
this.Context.Negotiating.Cipher.ComputeMasterSecret(preMasterSecret);
// Create keys
this.Context.Negotiating.Cipher.ComputeKeys();
// Initialize Cipher Suite
this.Context.Negotiating.Cipher.InitializeCipher();
}
#endregion
}
}

Some files were not shown because too many files have changed in this diff Show More