1 // Transport Security Layer (TLS)
2 // Copyright (c) 2003-2004 Carlos Guzman Alvarez
3 
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 
25 using System;
26 using System.Collections;
27 using System.Globalization;
28 using System.Security.Cryptography;
29 
30 namespace Mono.Security.Protocol.Tls
31 {
32 	internal sealed class CipherSuiteCollection : ICollection, IList, IEnumerable
33 	{
34 		#region Fields
35 
36 		private ArrayList				cipherSuites;
37 		private SecurityProtocolType	protocol;
38 
39 		#endregion
40 
41 		#region Indexers
42 
43 		public CipherSuite this[string name]
44 		{
45 			get { return (CipherSuite)this.cipherSuites[this.IndexOf(name)]; }
46 			set { this.cipherSuites[this.IndexOf(name)] = (CipherSuite)value; }
47 		}
48 
49 		public CipherSuite this[int index]
50 		{
51 			get { return (CipherSuite)this.cipherSuites[index]; }
52 			set { this.cipherSuites[index] = (CipherSuite)value; }
53 		}
54 
55 		public CipherSuite this[short code]
56 		{
57 			get { return (CipherSuite)this.cipherSuites[this.IndexOf(code)]; }
58 			set { this.cipherSuites[this.IndexOf(code)] = (CipherSuite)value; }
59 		}
60 
61 		object IList.this[int index]
62 		{
63 			get { return this[index]; }
64 			set { this[index] = (CipherSuite)value; }
65 		}
66 
67 		#endregion
68 
69 		#region ICollection Properties
70 
71 		bool ICollection.IsSynchronized
72 		{
73 			get { return this.cipherSuites.IsSynchronized; }
74 		}
75 
76 		object ICollection.SyncRoot
77 		{
78 			get { return this.cipherSuites.SyncRoot; }
79 		}
80 
81 		public int Count
82 		{
83 			get { return this.cipherSuites.Count; }
84 		}
85 
86 		#endregion
87 
88 		#region IList Properties
89 
90 		public bool IsFixedSize
91 		{
92 			get { return this.cipherSuites.IsFixedSize; }
93 		}
94 
95 		public bool IsReadOnly
96 		{
97 			get { return this.cipherSuites.IsReadOnly; }
98 		}
99 
100 		#endregion
101 
102 		#region Constructors
103 
CipherSuiteCollection(SecurityProtocolType protocol)104 		public CipherSuiteCollection(SecurityProtocolType protocol) : base()
105 		{
106 			this.protocol		= protocol;
107 			this.cipherSuites	= new ArrayList();
108 		}
109 
110 		#endregion
111 
112 		#region ICollection Methods
113 
CopyTo(Array array, int index)114 		public void CopyTo(Array array, int index)
115 		{
116 			this.cipherSuites.CopyTo(array, index);
117 		}
118 
119 		#endregion
120 
121 		#region IEnumerable Methods
122 
IEnumerable.GetEnumerator()123 		IEnumerator IEnumerable.GetEnumerator()
124 		{
125 			return this.cipherSuites.GetEnumerator();
126 		}
127 
128 		#endregion
129 
130 		#region IList Methods
131 
Clear()132 		public void Clear()
133 		{
134 			this.cipherSuites.Clear();
135 		}
136 
IList.Contains(object value)137 		bool IList.Contains(object value)
138 		{
139 			return this.cipherSuites.Contains(value as CipherSuite);
140 		}
141 
IndexOf(string name)142 		public int IndexOf(string name)
143 		{
144 			int index = 0;
145 
146 			foreach (CipherSuite cipherSuite in this.cipherSuites)
147 			{
148 				if (this.cultureAwareCompare(cipherSuite.Name, name))
149 				{
150 					return index;
151 				}
152 				index++;
153 			}
154 
155 			return -1;
156 		}
157 
IndexOf(short code)158 		public int IndexOf(short code)
159 		{
160 			int index = 0;
161 
162 			foreach (CipherSuite cipherSuite in this.cipherSuites)
163 			{
164 				if (cipherSuite.Code == code)
165 				{
166 					return index;
167 				}
168 				index++;
169 			}
170 
171 			return -1;
172 		}
173 
IList.IndexOf(object value)174 		int IList.IndexOf(object value)
175 		{
176 			return this.cipherSuites.IndexOf(value as CipherSuite);
177 		}
178 
IList.Insert(int index, object value)179 		void IList.Insert(int index, object value)
180 		{
181 			this.cipherSuites.Insert(index, value as CipherSuite);
182 		}
183 
IList.Remove(object value)184 		void IList.Remove(object value)
185 		{
186 			this.cipherSuites.Remove(value as CipherSuite);
187 		}
188 
IList.RemoveAt(int index)189 		void IList.RemoveAt(int index)
190 		{
191 			this.cipherSuites.RemoveAt(index);
192 		}
193 
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)194 		public CipherSuite Add(
195 			short code, string name, CipherAlgorithmType cipherType,
196 			HashAlgorithmType hashType, ExchangeAlgorithmType exchangeType,
197 			bool exportable, bool blockMode, byte keyMaterialSize,
198 			byte expandedKeyMaterialSize, short effectiveKeyBytes,
199 			byte ivSize, byte blockSize)
200 		{
201 			switch (this.protocol)
202 			{
203 				case SecurityProtocolType.Default:
204 				case SecurityProtocolType.Tls:
205 					return this.add(
206 						new TlsCipherSuite(
207 						code, name, cipherType, hashType, exchangeType, exportable,
208 						blockMode, keyMaterialSize, expandedKeyMaterialSize,
209 						effectiveKeyBytes, ivSize, blockSize));
210 
211 				case SecurityProtocolType.Ssl3:
212 					return this.add(
213 						new SslCipherSuite(
214 						code, name, cipherType, hashType, exchangeType, exportable,
215 						blockMode, keyMaterialSize, expandedKeyMaterialSize,
216 						effectiveKeyBytes, ivSize, blockSize));
217 
218 				case SecurityProtocolType.Ssl2:
219 				default:
220 					throw new NotSupportedException("Unsupported security protocol type.");
221 			}
222 		}
223 
add(TlsCipherSuite cipherSuite)224 		private TlsCipherSuite add(TlsCipherSuite cipherSuite)
225 		{
226 			this.cipherSuites.Add(cipherSuite);
227 
228 			return cipherSuite;
229 		}
230 
add(SslCipherSuite cipherSuite)231 		private SslCipherSuite add(SslCipherSuite cipherSuite)
232 		{
233 			this.cipherSuites.Add(cipherSuite);
234 
235 			return cipherSuite;
236 		}
237 
IList.Add(object value)238 		int IList.Add(object value)
239 		{
240 			return this.cipherSuites.Add(value as CipherSuite);
241 		}
242 
cultureAwareCompare(string strA, string strB)243 		private bool cultureAwareCompare(string strA, string strB)
244 		{
245 			return CultureInfo.CurrentCulture.CompareInfo.Compare(
246 				strA,
247 				strB,
248 				CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth |
249 				CompareOptions.IgnoreCase) == 0 ? true : false;
250 		}
251 
252 		#endregion
253 	}
254 }
255