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,43 @@
2007-05-22 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientCertificate.cs: Add chain support for x.509 client
certificates. Based on Roy Versteeg patch to fix #80557.
2007-05-07 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientCertificate.cs: A client certficate with a RSA public key
can only be used, protocol wise, to sign. Which means we should always
be checking it's keyUsage for digitalSignature. Fix for bug #81511
2006-09-11 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientCertificate.cs: Use Negotiating.Cipher instead of Cipher.
Fix reading the message length if it's zero (in that case it's not
present two times).
* TlsClientFinished.cs: Use Current.Cipher instead of Cipher. Use
Compare to test client and server digests equality.
* TlsClientHello.cs: Use Negotiating.Cipher instead of Cipher.
* TlsClientKeyExchange.cs: Use Negotiating.Cipher instead of Cipher.
* TlsServerFinished.cs: Use Current.Cipher instead of Cipher.
* TlsServerHello.cs: Use Negotiating.Cipher instead of Cipher.
2005-07-01 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientCertificate.cs: Fix decoding (extra length) and for null
(no certificates). Add basic client certificate validations before
calling the callback (which can override the default decision).
* TlsClientCertificateVerify.cs: Fix signature verification (the first
two bytes are the length of the signature).
* TlsServerCertificateRequest.cs: Sent the list of trusted root DNs.
2004-11-10 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientFinished.cs: ProcessAsTls1 - get out of the loop if PRF are
different.
2004-09-23 Sebastien Pouliot <sebastien@ximian.com>
* TlsClientKeyExchange.cs: Removed .Clear call on private key as itn't
ours (but only a reference). It also requires the callback to recreate
a new key object each time (which is worse). This also implies that
the caller (implementing the callback) is responsible to clear it.

View File

@@ -0,0 +1,272 @@
// 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));
}
}
#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

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

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

@@ -0,0 +1,151 @@
// 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)
{
SecurityProtocolType clientProtocol = this.Context.DecodeProtocolCode(protocol);
if ((clientProtocol & this.Context.SecurityProtocolFlags) == clientProtocol ||
(this.Context.SecurityProtocolFlags & SecurityProtocolType.Default) == SecurityProtocolType.Default)
{
this.Context.SecurityProtocol = clientProtocol;
this.Context.SupportedCiphers.Clear();
this.Context.SupportedCiphers = null;
this.Context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers(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

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

View File

@@ -0,0 +1,74 @@
// 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.Collections;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using X509Cert = System.Security.Cryptography.X509Certificates;
using Mono.Security.X509;
namespace Mono.Security.Protocol.Tls.Handshake.Server
{
internal class TlsServerCertificate : HandshakeMessage
{
#region Constructors
public TlsServerCertificate(Context context)
: base(context, HandshakeType.Certificate)
{
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
TlsStream certs = new TlsStream();
foreach (X509Certificate certificate in this.Context.ServerSettings.Certificates)
{
// Write certificate length
certs.WriteInt24(certificate.RawData.Length);
// Write certificate data
certs.Write(certificate.RawData);
}
this.WriteInt24(Convert.ToInt32(certs.Length));
this.Write(certs.ToArray());
certs.Close();
}
#endregion
}
}

View File

@@ -0,0 +1,97 @@
// 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;
using Mono.Security.X509;
namespace Mono.Security.Protocol.Tls.Handshake.Server
{
internal class TlsServerCertificateRequest : HandshakeMessage
{
#region Constructors
public TlsServerCertificateRequest(Context context)
: base(context, HandshakeType.CertificateRequest)
{
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
ServerContext context = (ServerContext)this.Context;
int count = context.ServerSettings.CertificateTypes.Length;
this.WriteByte(Convert.ToByte(count));
// Write requested certificate types
for (int i = 0; i < count; i++)
{
this.WriteByte((byte)context.ServerSettings.CertificateTypes[i]);
}
/*
* Write requested certificate authorities (Distinguised Names)
*
* Name ::= SEQUENCE OF RelativeDistinguishedName
*
* RelativeDistinguishedName ::= SET OF AttributeValueAssertion
*
* AttributeValueAssertion ::= SEQUENCE {
* attributeType OBJECT IDENTIFIER
* attributeValue ANY }
*/
if (context.ServerSettings.DistinguisedNames.Length > 0)
{
TlsStream list = new TlsStream ();
// this is the worst formating ever :-|
foreach (string dn in context.ServerSettings.DistinguisedNames)
{
byte[] name = X501.FromString (dn).GetBytes ();
list.Write ((short)name.Length);
list.Write (name);
}
this.Write ((short)list.Length);
this.Write (list.ToArray ());
}
else
{
this.Write ((short)0);
}
}
#endregion
}
}

View File

@@ -0,0 +1,75 @@
// 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 TlsServerFinished : HandshakeMessage
{
#region Constructors
public TlsServerFinished(Context context)
: base(context, HandshakeType.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);
this.Write(hash.Hash);
}
protected override void ProcessAsTls1()
{
// Compute handshake messages hash
HashAlgorithm hash = new MD5SHA1();
byte[] data = this.Context.HandshakeMessages.ToArray ();
byte[] digest = hash.ComputeHash (data, 0, data.Length);
// Write message
this.Write(this.Context.Current.Cipher.PRF(
this.Context.MasterSecret, "server finished", digest, 12));
}
#endregion
}
}

View File

@@ -0,0 +1,122 @@
// 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.Server
{
internal class TlsServerHello : HandshakeMessage
{
#region Private Fields
private int unixTime;
private byte[] random;
#endregion
#region Constructors
public TlsServerHello(Context context)
: base(context, HandshakeType.ServerHello)
{
}
#endregion
#region Methods
public override void Update()
{
base.Update();
TlsStream random = new TlsStream();
// Compute Server Random
random.Write(this.unixTime);
random.Write(this.random);
this.Context.ServerRandom = random.ToArray();
// Compute ClientRandom + ServerRandom
random.Reset();
random.Write(this.Context.ClientRandom);
random.Write(this.Context.ServerRandom);
this.Context.RandomCS = random.ToArray();
// Server Random + Client Random
random.Reset();
random.Write(this.Context.ServerRandom);
random.Write(this.Context.ClientRandom);
this.Context.RandomSC = random.ToArray();
random.Reset();
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
// Write protocol version
this.Write(this.Context.Protocol);
// Write Unix time
this.unixTime = this.Context.GetUnixTime();
this.Write(this.unixTime);
// Write Random bytes
random = this.Context.GetSecureRandomBytes(28);
this.Write(this.random);
if (this.Context.SessionId == null)
{
this.WriteByte(0);
}
else
{
// Write Session ID length
this.WriteByte((byte)this.Context.SessionId.Length);
// Write Session ID
this.Write(this.Context.SessionId);
}
// Write selected cipher suite
this.Write(this.Context.Negotiating.Cipher.Code);
// Write selected compression method
this.WriteByte((byte)this.Context.CompressionMethod);
}
#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.Server
{
internal class TlsServerHelloDone : HandshakeMessage
{
#region Constructors
public TlsServerHelloDone(Context context)
: base(context, HandshakeType.ServerHelloDone)
{
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
}
protected override void ProcessAsTls1()
{
}
#endregion
}
}

View File

@@ -0,0 +1,110 @@
// 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 SX509 = System.Security.Cryptography.X509Certificates;
using Mono.Security.Cryptography;
using Mono.Security.X509;
namespace Mono.Security.Protocol.Tls.Handshake.Server
{
internal class TlsServerKeyExchange : HandshakeMessage
{
#region Constructors
public TlsServerKeyExchange(Context context)
: base(context, HandshakeType.ServerKeyExchange)
{
}
#endregion
#region Methods
public override void Update()
{
throw new NotSupportedException();
}
#endregion
#region Protected Methods
protected override void ProcessAsSsl3()
{
this.ProcessAsTls1();
}
protected override void ProcessAsTls1()
{
ServerContext context = (ServerContext)this.Context;
// Select the private key information
RSA rsa = (RSA)context.SslStream.PrivateKeyCertSelectionDelegate(
new SX509.X509Certificate(context.ServerSettings.Certificates[0].RawData),
null);
RSAParameters rsaParams = rsa.ExportParameters(false);
// Write Modulus
this.WriteInt24(rsaParams.Modulus.Length);
this.Write(rsaParams.Modulus, 0, rsaParams.Modulus.Length);
// Write exponent
this.WriteInt24(rsaParams.Exponent.Length);
this.Write(rsaParams.Exponent, 0, rsaParams.Exponent.Length);
// Write signed params
byte[] signature = this.createSignature(rsa, this.ToArray());
this.WriteInt24(signature.Length);
this.Write(signature);
}
#endregion
#region Private Methods
private byte[] createSignature(RSA rsa, byte[] buffer)
{
MD5SHA1 hash = new MD5SHA1();
// Create server params array
TlsStream stream = new TlsStream();
stream.Write(this.Context.RandomCS);
stream.Write(buffer, 0, buffer.Length);
hash.ComputeHash(stream.ToArray());
stream.Reset();
return hash.CreateSignature(rsa);
}
#endregion
}
}