// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
+// Copyright 2013-2014 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
//
using System;
-using System.Collections;
-using System.Globalization;
-using System.Security.Cryptography;
-
-namespace Mono.Security.Protocol.Tls
-{
- internal sealed class CipherSuiteCollection : ICollection, IList, IEnumerable
- {
- #region Fields
-
- private ArrayList cipherSuites;
- private SecurityProtocolType protocol;
-
- #endregion
-
- #region Indexers
+using System.Collections.Generic;
- public CipherSuite this[string name]
- {
- get { return (CipherSuite)this.cipherSuites[this.IndexOf(name)]; }
- set { this.cipherSuites[this.IndexOf(name)] = (CipherSuite)value; }
- }
-
- public CipherSuite this[int index]
- {
- get { return (CipherSuite)this.cipherSuites[index]; }
- set { this.cipherSuites[index] = (CipherSuite)value; }
- }
-
- public CipherSuite this[short code]
- {
- get { return (CipherSuite)this.cipherSuites[this.IndexOf(code)]; }
- set { this.cipherSuites[this.IndexOf(code)] = (CipherSuite)value; }
- }
-
- object IList.this[int index]
- {
- get { return this[index]; }
- set { this[index] = (CipherSuite)value; }
- }
-
- #endregion
+namespace Mono.Security.Protocol.Tls {
- #region ICollection Properties
+ internal sealed class CipherSuiteCollection : List<CipherSuite> {
- bool ICollection.IsSynchronized
- {
- get { return this.cipherSuites.IsSynchronized; }
- }
+ #region Fields
- object ICollection.SyncRoot
- {
- get { return this.cipherSuites.SyncRoot; }
- }
+ SecurityProtocolType protocol;
- public int Count
- {
- get { return this.cipherSuites.Count; }
- }
-
#endregion
- #region IList Properties
+ #region Indexers
- public bool IsFixedSize
- {
- get { return this.cipherSuites.IsFixedSize; }
+ public CipherSuite this [string name] {
+ get {
+ int n = IndexOf (name);
+ return n == -1 ? null : this [n];
+ }
}
- public bool IsReadOnly
- {
- get { return this.cipherSuites.IsReadOnly; }
+ public CipherSuite this [short code] {
+ get {
+ int n = IndexOf (code);
+ return n == -1 ? null : this [n];
+ }
}
#endregion
#region Constructors
- public CipherSuiteCollection(SecurityProtocolType protocol) : base()
- {
- this.protocol = protocol;
- this.cipherSuites = new ArrayList();
- }
-
- #endregion
-
- #region ICollection Methods
-
- public void CopyTo(Array array, int index)
- {
- this.cipherSuites.CopyTo(array, index);
- }
-
- #endregion
-
- #region IEnumerable Methods
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return this.cipherSuites.GetEnumerator();
+ public CipherSuiteCollection (SecurityProtocolType protocol)
+ {
+ switch (protocol) {
+ case SecurityProtocolType.Default:
+ case SecurityProtocolType.Tls:
+ case SecurityProtocolType.Ssl3:
+ this.protocol = protocol;
+ break;
+ case SecurityProtocolType.Ssl2:
+ default:
+ throw new NotSupportedException ("Unsupported security protocol type.");
+ }
}
#endregion
- #region IList Methods
+ #region Methods
- public void Clear()
- {
- this.cipherSuites.Clear();
- }
-
- bool IList.Contains(object value)
- {
- return this.cipherSuites.Contains(value as CipherSuite);
- }
-
- public int IndexOf(string name)
+ public int IndexOf (string name)
{
int index = 0;
-
- foreach (CipherSuite cipherSuite in this.cipherSuites)
- {
- if (this.cultureAwareCompare(cipherSuite.Name, name))
- {
+ foreach (CipherSuite cipherSuite in this) {
+ if (String.CompareOrdinal (name, cipherSuite.Name) == 0)
return index;
- }
index++;
}
-
return -1;
}
- public int IndexOf(short code)
+ public int IndexOf (short code)
{
int index = 0;
-
- foreach (CipherSuite cipherSuite in this.cipherSuites)
- {
+ foreach (CipherSuite cipherSuite in this) {
if (cipherSuite.Code == code)
- {
return index;
- }
index++;
}
-
return -1;
}
- int IList.IndexOf(object value)
- {
- return this.cipherSuites.IndexOf(value as CipherSuite);
- }
-
- void IList.Insert(int index, object value)
- {
- this.cipherSuites.Insert(index, value as CipherSuite);
- }
-
- void IList.Remove(object value)
- {
- this.cipherSuites.Remove(value as CipherSuite);
- }
-
- void IList.RemoveAt(int index)
- {
- this.cipherSuites.RemoveAt(index);
- }
-
- public CipherSuite Add(
+ public void Add (
short code, string name, CipherAlgorithmType cipherType,
HashAlgorithmType hashType, ExchangeAlgorithmType exchangeType,
bool exportable, bool blockMode, byte keyMaterialSize,
byte expandedKeyMaterialSize, short effectiveKeyBytes,
byte ivSize, byte blockSize)
{
- switch (this.protocol)
- {
- case SecurityProtocolType.Default:
- case SecurityProtocolType.Tls:
- return this.add(
- new TlsCipherSuite(
- code, name, cipherType, hashType, exchangeType, exportable,
- blockMode, keyMaterialSize, expandedKeyMaterialSize,
- effectiveKeyBytes, ivSize, blockSize));
-
- case SecurityProtocolType.Ssl3:
- return this.add(
- new SslCipherSuite(
- code, name, cipherType, hashType, exchangeType, exportable,
- blockMode, keyMaterialSize, expandedKeyMaterialSize,
- effectiveKeyBytes, ivSize, blockSize));
-
- case SecurityProtocolType.Ssl2:
- default:
- throw new NotSupportedException("Unsupported security protocol type.");
+ switch (protocol) {
+ case SecurityProtocolType.Default:
+ case SecurityProtocolType.Tls:
+ Add (new TlsCipherSuite (code, name, cipherType, hashType, exchangeType, exportable, blockMode,
+ keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize));
+ break;
+
+ case SecurityProtocolType.Ssl3:
+ Add (new SslCipherSuite (code, name, cipherType, hashType, exchangeType, exportable, blockMode,
+ keyMaterialSize, expandedKeyMaterialSize, effectiveKeyBytes, ivSize, blockSize));
+ break;
}
}
- private TlsCipherSuite add(TlsCipherSuite cipherSuite)
- {
- this.cipherSuites.Add(cipherSuite);
-
- return cipherSuite;
- }
-
- private SslCipherSuite add(SslCipherSuite cipherSuite)
- {
- this.cipherSuites.Add(cipherSuite);
-
- return cipherSuite;
- }
-
- int IList.Add(object value)
- {
- return this.cipherSuites.Add(value as CipherSuite);
- }
-
- private bool cultureAwareCompare(string strA, string strB)
+ public IList<string> GetNames ()
{
- return CultureInfo.CurrentCulture.CompareInfo.Compare(
- strA,
- strB,
- CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth |
- CompareOptions.IgnoreCase) == 0 ? true : false;
+ var list = new List<string> (Count);
+ foreach (CipherSuite cipherSuite in this)
+ list.Add (cipherSuite.Name);
+ return list;
}
#endregion
// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
+// Copyright 2013-2014 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
//
using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Net;
namespace Mono.Security.Protocol.Tls
{
- internal class CipherSuiteFactory
+ internal static class CipherSuiteFactory
{
- public static CipherSuiteCollection GetSupportedCiphers(SecurityProtocolType protocol)
+#if !INSIDE_SYSTEM && !BOOTSTRAP_BASIC
+ static Type spm = typeof (ServicePointManager);
+ static PropertyInfo client_callback;
+ static PropertyInfo server_callback;
+#endif
+
+ public static CipherSuiteCollection GetSupportedCiphers (bool server, SecurityProtocolType protocol)
{
- switch (protocol)
- {
- case SecurityProtocolType.Default:
- case SecurityProtocolType.Tls:
- return CipherSuiteFactory.GetTls1SupportedCiphers();
-
- case SecurityProtocolType.Ssl3:
- return CipherSuiteFactory.GetSsl3SupportedCiphers();
-
- case SecurityProtocolType.Ssl2:
- default:
- throw new NotSupportedException("Unsupported security protocol type");
+ CipherSuiteCollection suites;
+ switch (protocol) {
+ case SecurityProtocolType.Default:
+ case SecurityProtocolType.Tls:
+ suites = CipherSuiteFactory.GetTls1SupportedCiphers ();
+ break;
+ case SecurityProtocolType.Ssl3:
+ suites = CipherSuiteFactory.GetSsl3SupportedCiphers ();
+ break;
+ case SecurityProtocolType.Ssl2:
+ default:
+ throw new NotSupportedException ("Unsupported security protocol type");
+ }
+
+ IEnumerable<string> list = null;
+#if INSIDE_SYSTEM
+ // if SSL/TLS support is built-in System.dll (e.g. monotouch) then we can access ServicePointManager
+ // extension directly
+ var cb = server ? ServicePointManager.ServerCipherSuitesCallback : ClientCipherSuitesCallback;
+ if (cb == null)
+ return suites; // e.g. no callback was set
+
+ list = cb ((System.Net.SecurityProtocolType) (int) protocol, suites.GetNames ());
+#elif !BOOTSTRAP_BASIC
+ // Mono.Security must work on MS.NET so it cannot depend on any Mono-specific extensions
+ PropertyInfo pi = null;
+ if (server) {
+ if (server_callback == null)
+ server_callback = spm.GetProperty ("ServerCipherSuitesCallback", BindingFlags.Static | BindingFlags.Public);
+ pi = server_callback;
+ } else {
+ if (client_callback == null)
+ client_callback = spm.GetProperty ("ClientCipherSuitesCallback", BindingFlags.Static | BindingFlags.Public);
+ pi = client_callback;
+ }
+ if (pi == null)
+ return suites; // e.g. MS runtime - return every supported suites
+
+ var cb = (Delegate) pi.GetGetMethod ().Invoke (null, null);
+ if (cb == null)
+ return suites; // e.g. no callback was set - return every supported suites
+
+ list = (IEnumerable<string>) cb.DynamicInvoke (new object[] {
+ (System.Net.SecurityProtocolType) (int) protocol, suites.GetNames ()
+ });
+#else
+ // TODO: right now the callback is only available when using System.Net.* types for SSL/TLS
+ return suites;
+#endif
+ CipherSuiteCollection allowed = new CipherSuiteCollection (protocol);
+ if (list != null) {
+ foreach (var name in list) {
+ // add any supported (ignore unknowns) ciphers requested by the callback
+ var cipher = suites [name];
+ if (cipher != null)
+ allowed.Add (cipher);
+ }
}
+ return allowed;
}
#region Private Static Methods
// Supported ciphers
scs.Add((0x00 << 0x08) | 0x35, "SSL_RSA_WITH_AES_256_CBC_SHA", CipherAlgorithmType.Rijndael, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, false, true, 32, 32, 256, 16, 16);
+ scs.Add((0x00 << 0x08) | 0x2F, "SSL_RSA_WITH_AES_128_CBC_SHA", CipherAlgorithmType.Rijndael, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, false, true, 16, 16, 128, 16, 16);
scs.Add((0x00 << 0x08) | 0x0A, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", CipherAlgorithmType.TripleDes, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, false, true, 24, 24, 168, 8, 8);
scs.Add((0x00 << 0x08) | 0x05, "SSL_RSA_WITH_RC4_128_SHA", CipherAlgorithmType.Rc4, HashAlgorithmType.Sha1, ExchangeAlgorithmType.RsaKeyX, false, false, 16, 16, 128, 0, 0);
scs.Add((0x00 << 0x08) | 0x04, "SSL_RSA_WITH_RC4_128_MD5", CipherAlgorithmType.Rc4, HashAlgorithmType.Md5, ExchangeAlgorithmType.RsaKeyX, false, false, 16, 16, 128, 0, 0);