This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / Mono.Security / Mono.Security.Protocol.Tls / Context.cs
1
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
10 // 
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 // 
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 /* Transport Security Layer (TLS)
23  * Copyright (c) 2003-2004 Carlos Guzman Alvarez
24  * 
25  * Permission is hereby granted, free of charge, to any person 
26  * obtaining a copy of this software and associated documentation 
27  * files (the "Software"), to deal in the Software without restriction, 
28  * including without limitation the rights to use, copy, modify, merge, 
29  * publish, distribute, sublicense, and/or sell copies of the Software, 
30  * and to permit persons to whom the Software is furnished to do so, 
31  * subject to the following conditions:
32  * 
33  * The above copyright notice and this permission notice shall be included 
34  * in all copies or substantial portions of the Software.
35  * 
36  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
37  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
38  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
39  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
40  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
41  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
42  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
43  * DEALINGS IN THE SOFTWARE.
44  */
45
46 using System;
47 using System.Text;
48 using System.Collections;
49 using System.Security.Cryptography;
50 using System.Security.Cryptography.X509Certificates;
51
52 using Mono.Security.Cryptography;
53 using Mono.Security.Protocol.Tls.Handshake;
54
55 namespace Mono.Security.Protocol.Tls
56 {
57         internal abstract class Context
58         {
59                 #region Internal Constants
60
61                 internal const short MAX_FRAGMENT_SIZE  = 16384; // 2^14
62                 internal const short TLS1_PROTOCOL_CODE = (0x03 << 8) | 0x01;
63                 internal const short SSL3_PROTOCOL_CODE = (0x03 << 8) | 0x00;
64                 internal const long  UNIX_BASE_TICKS    = 621355968000000000;
65
66                 #endregion
67
68                 #region Fields
69                 
70                 // Protocol version
71                 private SecurityProtocolType securityProtocol;
72                 
73                 // Sesison ID
74                 private byte[] sessionId;
75
76                 // Compression method
77                 private SecurityCompressionType compressionMethod;
78
79                 // Information sent and request by the server in the Handshake protocol
80                 private TlsServerSettings serverSettings;
81
82                 // Client configuration
83                 private TlsClientSettings clientSettings;
84
85                 // Cipher suite information
86                 private CipherSuite                             cipher;
87                 private CipherSuiteCollection   supportedCiphers;
88
89                 // Last handshake message received
90                 private HandshakeType lastHandshakeMsg;
91
92                 // Handshake negotiation state
93                 private HandshakeState handshakeState;
94
95                 // Misc
96                 private bool    isActual;
97                 private bool    connectionEnd;
98                 private bool    protocolNegotiated;
99                 
100                 // Sequence numbers
101                 private long    writeSequenceNumber;
102                 private long    readSequenceNumber;
103
104                 // Random data
105                 private byte[]  clientRandom;
106                 private byte[]  serverRandom;
107                 private byte[]  randomCS;
108                 private byte[]  randomSC;
109
110                 // Key information
111                 private byte[]  masterSecret;
112                 private byte[]  clientWriteMAC;
113                 private byte[]  serverWriteMAC;
114                 private byte[]  clientWriteKey;
115                 private byte[]  serverWriteKey;
116                 private byte[]  clientWriteIV;
117                 private byte[]  serverWriteIV;
118                 
119                 // Handshake hashes
120                 private TlsStream handshakeMessages;
121                 
122                 // Secure Random generator              
123                 private RandomNumberGenerator random;
124
125                 // Record protocol
126                 private RecordProtocol recordProtocol;
127
128                 #endregion
129
130                 #region Properties
131
132                 public bool     ProtocolNegotiated
133                 {
134                         get { return this.protocolNegotiated; }
135                         set { this.protocolNegotiated = value; }
136                 }
137
138                 public SecurityProtocolType SecurityProtocol
139                 {
140                         get 
141                         {
142                                 if ((this.securityProtocol & SecurityProtocolType.Tls) == SecurityProtocolType.Tls ||   
143                                         (this.securityProtocol & SecurityProtocolType.Default) == SecurityProtocolType.Default)
144                                 {
145                                         return SecurityProtocolType.Tls;
146                                 }
147                                 else
148                                 {
149                                         if ((this.securityProtocol & SecurityProtocolType.Ssl3) == SecurityProtocolType.Ssl3)
150                                         {
151                                                 return SecurityProtocolType.Ssl3;
152                                         }
153                                 }
154
155                                 throw new NotSupportedException("Unsupported security protocol type");
156                         }
157
158                         set { this.securityProtocol = value; }
159                 }
160
161                 public SecurityProtocolType SecurityProtocolFlags
162                 {
163                         get { return this.securityProtocol; }
164                 }
165
166                 public short Protocol
167                 {
168                         get 
169                         { 
170                                 switch (this.SecurityProtocol)
171                                 {
172                                         case SecurityProtocolType.Tls:
173                                         case SecurityProtocolType.Default:
174                                                 return Context.TLS1_PROTOCOL_CODE;
175
176                                         case SecurityProtocolType.Ssl3:
177                                                 return Context.SSL3_PROTOCOL_CODE;
178
179                                         case SecurityProtocolType.Ssl2:
180                                         default:
181                                                 throw new NotSupportedException("Unsupported security protocol type");
182                                 }
183                         }
184                 }
185
186                 public byte[] SessionId
187                 {
188                         get { return this.sessionId; }
189                         set { this.sessionId = value; }
190                 }
191
192                 public SecurityCompressionType CompressionMethod
193                 {
194                         get { return this.compressionMethod; }
195                         set { this.compressionMethod = value; }
196                 }
197
198                 public TlsServerSettings ServerSettings
199                 {
200                         get { return this.serverSettings; }
201                 }
202
203                 public TlsClientSettings ClientSettings
204                 {
205                         get { return this.clientSettings; }
206                 }
207
208                 public bool     IsActual
209                 {
210                         get { return this.isActual; }
211                         set { this.isActual = value; }
212                 }
213
214                 public HandshakeType LastHandshakeMsg
215                 {
216                         get { return this.lastHandshakeMsg; }
217                         set { this.lastHandshakeMsg = value; }
218                 }
219
220                 public  HandshakeState HandshakeState
221                 {
222                         get { return this.handshakeState; }
223                         set { this.handshakeState = value; }
224                 }
225
226                 public bool ConnectionEnd
227                 {
228                         get { return this.connectionEnd; }
229                         set { this.connectionEnd = value; }
230                 }
231
232                 public CipherSuite Cipher
233                 {
234                         get { return this.cipher; }
235                         set 
236                         { 
237                                 this.cipher                     = value; 
238                                 this.cipher.Context = this;
239                         }
240                 }
241
242                 public CipherSuiteCollection SupportedCiphers
243                 {
244                         get { return supportedCiphers; }
245                         set { supportedCiphers = value; }
246                 }
247
248                 public TlsStream HandshakeMessages
249                 {
250                         get { return this.handshakeMessages; }
251                 }
252
253                 public long WriteSequenceNumber
254                 {
255                         get { return this.writeSequenceNumber; }
256                         set { this.writeSequenceNumber = value; }
257                 }
258
259                 public long ReadSequenceNumber
260                 {
261                         get { return this.readSequenceNumber; }
262                         set { this.readSequenceNumber = value; }
263                 }
264
265                 public byte[] ClientRandom
266                 {
267                         get { return this.clientRandom; }
268                         set { this.clientRandom = value; }
269                 }
270
271                 public byte[] ServerRandom
272                 {
273                         get { return this.serverRandom; }
274                         set { this.serverRandom = value; }
275                 }
276
277                 public byte[] RandomCS
278                 {
279                         get { return this.randomCS; }
280                         set { this.randomCS = value; }
281                 }
282
283                 public byte[] RandomSC
284                 {
285                         get { return this.randomSC; }
286                         set { this.randomSC = value; }
287                 }
288
289                 public byte[] MasterSecret
290                 {
291                         get { return this.masterSecret; }
292                         set { this.masterSecret = value; }
293                 }
294
295                 public byte[] ClientWriteMAC
296                 {
297                         get { return this.clientWriteMAC; }
298                         set { this.clientWriteMAC = value; }
299                 }
300
301                 public byte[] ServerWriteMAC
302                 {
303                         get { return this.serverWriteMAC; }
304                         set { this.serverWriteMAC = value; }
305                 }
306
307                 public byte[] ClientWriteKey
308                 {
309                         get { return this.clientWriteKey; }
310                         set { this.clientWriteKey = value; }
311                 }
312
313                 public byte[] ServerWriteKey
314                 {
315                         get { return this.serverWriteKey; }
316                         set { this.serverWriteKey = value; }
317                 }
318
319                 public byte[] ClientWriteIV
320                 {
321                         get { return this.clientWriteIV; }
322                         set { this.clientWriteIV = value; }
323                 }
324
325                 public byte[] ServerWriteIV
326                 {
327                         get { return this.serverWriteIV; }
328                         set { this.serverWriteIV = value; }
329                 }
330
331                 public RecordProtocol RecordProtocol
332                 {
333                         get { return this.recordProtocol; }
334                         set { this.recordProtocol = value; }
335                 }
336
337                 #endregion
338
339                 #region Constructors
340
341                 public Context(SecurityProtocolType securityProtocolType)
342                 {
343                         this.SecurityProtocol   = securityProtocolType;
344                         this.compressionMethod  = SecurityCompressionType.None;
345                         this.serverSettings             = new TlsServerSettings();
346                         this.clientSettings             = new TlsClientSettings();
347                         this.handshakeMessages  = new TlsStream();
348                         this.sessionId                  = null;
349                         this.handshakeState             = HandshakeState.None;
350                         this.random                             = RandomNumberGenerator.Create();
351                 }
352
353                 #endregion
354
355                 #region Methods
356                 
357                 public int GetUnixTime()
358                 {
359                         DateTime now = DateTime.UtcNow;
360                                                                                                                                                      
361                         return (int)(now.Ticks - UNIX_BASE_TICKS / TimeSpan.TicksPerSecond);
362                 }
363
364                 public byte[] GetSecureRandomBytes(int count)
365                 {
366                         byte[] secureBytes = new byte[count];
367
368                         this.random.GetNonZeroBytes(secureBytes);
369                         
370                         return secureBytes;
371                 }
372
373                 public virtual void Clear()
374                 {
375                         this.compressionMethod  = SecurityCompressionType.None;
376                         this.serverSettings             = new TlsServerSettings();
377                         this.clientSettings             = new TlsClientSettings();
378                         this.handshakeMessages  = new TlsStream();
379                         this.sessionId                  = null;
380                         this.handshakeState             = HandshakeState.None;
381
382                         this.ClearKeyInfo();
383                 }
384
385                 public virtual void ClearKeyInfo()
386                 {
387                         // Clear Master Secret
388                         this.masterSecret       = null;
389
390                         // Clear client and server random
391                         this.clientRandom       = null;
392                         this.serverRandom       = null;
393                         this.randomCS           = null;
394                         this.randomSC           = null;
395
396                         // Clear client keys
397                         this.clientWriteKey     = null;
398                         this.clientWriteIV      = null;
399                         
400                         // Clear server keys
401                         this.serverWriteKey     = null;
402                         this.serverWriteIV      = null;
403
404                         // Reset handshake messages
405                         this.handshakeMessages.Reset();
406
407                         // Clear MAC keys if protocol is different than Ssl3
408                         if (this.securityProtocol != SecurityProtocolType.Ssl3)
409                         {
410                                 this.clientWriteMAC = null;
411                                 this.serverWriteMAC = null;
412                         }
413                 }
414
415                 public SecurityProtocolType DecodeProtocolCode(short code)
416                 {
417                         switch (code)
418                         {
419                                 case Context.TLS1_PROTOCOL_CODE:
420                                         return SecurityProtocolType.Tls;
421
422                                 case Context.SSL3_PROTOCOL_CODE:
423                                         return SecurityProtocolType.Ssl3;
424
425                                 default:
426                                         throw new NotSupportedException("Unsupported security protocol type");
427                         }
428                 }
429
430                 #endregion
431         }
432 }