Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,345 @@
2010-05-10 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientCertificateVerify.cs: Let it compile for Moonlight -
where the file is compiled inside System.dll
2010-04-07 Gonzalo Paniagua Javier <gonzalo@novell.com>
* TlsServerCertificate.cs: display the error code.
2010-03-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
* TlsServerCertificate.cs: chain is built and validated in
System.dll now.
2010-03-01 Gonzalo Paniagua Javier <gonzalo@novell.com>
* TlsServerCertificate.cs:
added a new callback for certificate validation that gets all the
certificates received from the server/client. The callee should
build the chain and validate it.
2009-08-20 Sebastien Pouliot <sebastien@ximian.com>
* TlsServerCertificate.cs: If no usage information is available then
assume it's ok for SSL since we'll (later) check that the CN contains
a host name (that match the server) and such a certificate wouldn't
be much useful for anything but SSL/TLS. Fix the new stmp.gmail.com
certificate usage failure.
2007-12-15 Sebastien Pouliot <sebastien@ximian.com>
* TlsServerCertificate.cs: Add support for wilcard (*) when matching
the target host with the certificate. Fix bug #346812
2007-05-22 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientCertificate.cs: If possible avoid to export the private key
(it could be non-exportable in a different RSA class implementation).
Patch from Roy Versteeg to fix #81592.
* TlsClientCertificateVerify.cs: Add chain support for x.509 client
certificates. Based on Roy Versteeg patch to fix #80557.
2006-12-23 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* TlsServerCertificate.cs: typo.
2006-09-11 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientFinished.cs: Use Write.Cipher instead of Cipher. Remove
usage of TlsStream in ProcessAsSsl3.
* TlsClientKeyExchange.cs: Use Negotiating.Cipher instead of Cipher.
Refactor to avoid code duplication between SSL3 and TLS.
* TlsServerCertificate.cs: Use Negotiating.Cipher instead of Cipher.
* TlsServerFinished.cs: Use Current.Cipher instead of Cipher. Use
Compare to test client and server digests equality. Remove usage of
TlsStream in ProcessAsSsl3.
* TlsServerHello.cs: Use Negotiating.Cipher instead of Cipher. Remove
usage of TlsStream to reduce memory allocations. Remove method
CompareSessionId and use the new base class Compare method instead.
2006-03-16 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientHello.cs: Check to see if we already have a known session
(past or concurrent) with the same target host. If so the use this
session id to try to resume (i.e. abbreviated handshake).
* TlsServerFinished.cs: Don't reset the hasndshake stream here. The
stream must be resetted once BOTH the client and the server are done.
The order of message can be different if we use an abbreviated
handshake sequence which leads to an invalid handshake.
* TlsServerHello.cs: Add this session info to the client cache. If the
server sends the same session id (as we supplied) then we MUST do an
abbreviated handshake.
2005-11-23 Sebastien Pouliot <sebastien@ximian.com>
* TlsServerCertificate.cs: Add support for Netscape Server Gated
Crypto (2.16.840.1.113730.4) as a valid server-side EKU OID. Fix bug
#76804.
2005-06-14 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientCertificate.cs: Add support for _optional_ mutual
authentication. SSL3 and TLS1 deals differently with this. SSL3 tested
with OpenSSL, TSL1 tested with OpenSSL and LDAPS/AD.
2005-04-12 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientCertificateVerify.cs: Add missing data length (16 bits -
not to be confused with the record 24 bits length) before the RSA
signature of the MD5SHA1 hash. Fix #71696.
2004-05-11 Carlos Guzman Alvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs:
- Added fix for better handling of exceptions when
building the X509 Certificate chain.
2004-04-22 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientCertificateVerify.cs: Use Buffer.BlockCopy instead of
Array.Copy.
* TlsServerCertificate.cs: Changed KeyUsage to KeyUsages and CertType
to CertTypes.
2004-03-19 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientKeyExchange.cs: Fixed key pair used to encrypt pre-master
secret for exportable ciphers - must use the public key received in
ServerKeyExchange.
2004-03-10 Carlos Guzman Alvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificateRequest.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs:
* Mono.Security.Protocol.Tls.Handshake.Server/TlsClientCertificateVerify.cs:
* Mono.Security.Protocol.Tls.Handshake.Server/TlsServerCertificateRequest.cs:
* Mono.Security.Protocol.Tls.Handshake.Server/TlsServerFinished.cs:
- Fixed meesage type definition.
2004-03-04 Carlos Guzman Alvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerHelloDone.cs:
* Mono.Security.Protocol.Tls.Handshake.Server/TlsServerHelloDone.cs:
- Fixed message type.
2004-02-26 Sebastien Pouliot <sebastien@ximian.com>
* TlsServerCertificate.cs: Certificate validation has been activated.
2004-02-26 Carlos Guzman Alvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs:
- Added changes for better handling of ClientHelloRequest messages.
2004-02-21 Carlos Guzman Alvarez <carlosga@telefonica.net>
* TlsServerHello: Fix for handle SecurityProtocolType.Default.
2004-02-20 Sebastien Pouliot <sebastien@ximian.com>
* TlsServerCertificate.cs: Added code to validate the server X.509
certificate (identity, usage) and it's chain to a trusted root.
Note that the verification is commented for the time being.
2004-02-14 Carlos Guzmán Álvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs:
- Removed test code.
2003-11-17 Carlos Guzmán Álvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls/SslClientStream.cs:
Removed ReadByte method, use innerStream.ReadByte() method instead.
2003-11-13 Carlos Guzmán Álvarez <carlosga@telefonica.net>
* Added implementation of an SslClientStream class similar to the MS .NET Framework 1.2 documentation.
The next files are no more needed:
- TlsSession.cs
- TlsNetworkStream.cs
- TlsSocket.cs
- TlsSessionState.cs
The next files are renamed:
- TlsSessionSettings.cs -> TlsClientSettings.cs
- TlsSessionContext.cs -> TlsContext.cs
The next files are new:
- SslClientStream.cs ( the name is non definitive yet )
The next files where changed to reflect the new canges:
- TlsHandshakeMessage.cs
- TlsClientCertificate.cs
- TlsClientCertificateVerify.cs
- TlsClientFinished.cs
- TlsClientHello.cs
- TlsClientKeyExchange.cs
- TlsServerCertificate.cs
- TlsServerCertificateRequest.cs
- TlsServerFinished.cs
- TlsServerHello.cs
- TlsServerHelloDone.cs
- TlsServerKeyExchange.cs
- TlsAlert.cs
- TlsCloseNotifyAlert.cs
2003-11-12 Carlos Guzmán Álvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls.Alerts/TlsAlert.cs:
- Changes for give full error message only in debug mode ( Thanks to Sebastién Pouliot. )
* Mono.Security.Protocol.Tls/TlsProtocol.cs:
- Renamed to SecurityProtocolType.cs ( for match .NET 1.2 )
* Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs:
- Renamed to MD5SHA1.cs ( Thanks to Sebastién Pouliot. )
* Mono.Security.Cryptography/TlsCompressionMethod.cs:
- Renamed to SecurityCompressionType.
* Mono.Security.Protocol.Tls/CipherAlgorithmType.cs:
* Mono.Security.Protocol.Tls/HashAlgorithmType.cs:
* Mono.Security.Protocol.Tls/ExchangeAlgorithmType.cs:
- New enumerations that matches .NET 1.2 definitions with some minor differences.
* Mono.Security.Protocol.Tls/CipherSuite.cs:
* Mono.Security.Protocol.Tls/TlsCipherSuite.cs:
* Mono.Security.Protocol.Tls/TlsSslCipherSuite.cs:
* Mono.Security.Protocol.Tls/TlsSessionContext.cs:
- Added changes for make use of new enumerations.
* Mono.Security.Protocol.Tls/TlsClientStream.cs:
- Added new informative properties that matches .NET 1.2 SslClientStream
( Not all the properties are implemented yet ).
2003-11-10 Carlos Guzmán Álvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls.Alerts/TlsAlert.cs:
- Fixed invalid alert message.
* Mono.Security.Protocol.Tls/CipherSuite.cs:
* Mono.Security.Protocol.Tls/TlsSslCipherSuite.cs:
* Mono.Security.Cryptography/HMAC.cs:
* Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs:
- Changed ( Thanks to Sebastién Pouliot for his feedback )
SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
MD5CryptoServiceProvider sha = new MD5CryptoServiceProvider();
to
HashAlgorithm sha = SHA1.Create();
HashAlgorithm md5 = MD5.Create();
2003-11-04 Carlos Guzmán Álvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls/CipherSuite.cs:
- Added custom padding for record encryption.
2003-11-03 Carlos Guzmán Álvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls.Handshake/TlsHandshakeMessages.cs:
- Removed file.
* Mono.Security.Protocol.Tls/TlsSslHandshakeHash.cs:
- New class for handshake hashes calculation on SSL3 protocol.
* Mono.Security.Protocol.Tls/TlsSessionContext.cs:
- Fixed mac keys clearing for SSL3 protocol.
* Mono.Security.Protocol.Tls/TlsSslCipherSuite.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs:
- Added changes for make use of new TlsSslHandshakeHash class.
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs:
- Added initial implementation for SSL3 protocol.
* Mono.Security.Cryptography/MD5SHA1CryptoServiceProvider.cs:
- New class for md5-sha hash calculation.
* Mono.Security.Protocol.Tls.Handshake.Client/TlsClientFinished.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerFinished.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsHandshakeMessage.cs:
- Make use of new MD5SHA1CryptoServiceProvider class.
* Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs:
- Added initial implementation (not finished).
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs:
- Minor change to message processing.
- Changed verify method name to verifySignature.
* Mono.Security.Protocol.Tls/TlsSessionContext.cs:
- Changed handshakeHashes member to be an TlsStream.
2003-10-28 Carlos Guzmán Álvarez <carlosga@telefonica.net>
* Mono.Security.Protocol.Tls/CipherSuite.cs:
* Mono.Security.Protocol.Tls/TlsSessionSettings.cs:
* Mono.Security.Protocol.Tls/TlsServerSettings.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsClientCertificateVerify.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsClientKeyExchange.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs:
* Mono.Security.Protocol.Tls.Handshake.Client/TlsServerKeyExchange.cs:
- Added changes for make use of X509 classes from mono.
2003-10-23 Carlos Guzmán Álvarez <carlosga@telefonica.net>
* Added partial implementation of SSL3 protocol ( not finished yet ).

View File

@@ -0,0 +1,147 @@
// 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 ()
{
#warning "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)
{
// This certificate is the root certificate
if (cert.GetName () == cert.GetIssuerName ())
return null;
foreach (X509Certificate certificate in this.Context.ClientSettings.Certificates) {
if (cert.GetName () == cert.GetIssuerName ())
return certificate;
}
return null;
}
#endregion
}
}

View File

@@ -0,0 +1,220 @@
// 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

@@ -0,0 +1,87 @@
// 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

@@ -0,0 +1,118 @@
// 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;
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()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
// 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);
}
#endregion
}
}

View File

@@ -0,0 +1,98 @@
// 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

@@ -0,0 +1,440 @@
// 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;
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;
}
static private void VerifyOSX (X509CertificateCollection certificates)
{
}
private void validateCertificates(X509CertificateCollection certificates)
{
ClientContext context = (ClientContext)this.Context;
AlertDescription description = AlertDescription.BadCertificate;
#if NET_2_0
if (context.SslStream.HaveRemoteValidation2Callback) {
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 ("0x{0:x}", error);
throw new TlsException (description, "Invalid certificate received from server. Error code: " + err);
}
#endif
// 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

@@ -0,0 +1,111 @@
// 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

@@ -0,0 +1,102 @@
// 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))
{
#warning 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

@@ -0,0 +1,152 @@
// 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.Clear();
this.Context.SupportedCiphers = null;
this.Context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers(serverProtocol);
DebugHelper.WriteLine("Selected protocol {0}", serverProtocol);
}
else
{
throw new TlsException(
AlertDescription.ProtocolVersion,
"Incorrect protocol version received from server");
}
}
#endregion
}
}

View File

@@ -0,0 +1,52 @@
// 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

@@ -0,0 +1,121 @@
// 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
}
}