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:
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
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.
22 /* Transport Security Layer (TLS)
23 * Copyright (c) 2003-2004 Carlos Guzman Alvarez
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:
33 * The above copyright notice and this permission notice shall be included
34 * in all copies or substantial portions of the Software.
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.
48 using System.Collections;
49 using System.Security.Cryptography;
50 using System.Security.Cryptography.X509Certificates;
52 using Mono.Security.Cryptography;
53 using Mono.Security.Protocol.Tls.Handshake;
55 namespace Mono.Security.Protocol.Tls
57 internal abstract class Context
59 #region Internal Constants
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;
71 private SecurityProtocolType securityProtocol;
74 private byte[] sessionId;
77 private SecurityCompressionType compressionMethod;
79 // Information sent and request by the server in the Handshake protocol
80 private TlsServerSettings serverSettings;
82 // Client configuration
83 private TlsClientSettings clientSettings;
85 // Cipher suite information
86 private CipherSuite cipher;
87 private CipherSuiteCollection supportedCiphers;
89 // Last handshake message received
90 private HandshakeType lastHandshakeMsg;
92 // Handshake negotiation state
93 private HandshakeState handshakeState;
96 private bool isActual;
97 private bool connectionEnd;
98 private bool protocolNegotiated;
101 private long writeSequenceNumber;
102 private long readSequenceNumber;
105 private byte[] clientRandom;
106 private byte[] serverRandom;
107 private byte[] randomCS;
108 private byte[] randomSC;
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;
120 private TlsStream handshakeMessages;
122 // Secure Random generator
123 private RandomNumberGenerator random;
126 private RecordProtocol recordProtocol;
132 public bool ProtocolNegotiated
134 get { return this.protocolNegotiated; }
135 set { this.protocolNegotiated = value; }
138 public SecurityProtocolType SecurityProtocol
142 if ((this.securityProtocol & SecurityProtocolType.Tls) == SecurityProtocolType.Tls ||
143 (this.securityProtocol & SecurityProtocolType.Default) == SecurityProtocolType.Default)
145 return SecurityProtocolType.Tls;
149 if ((this.securityProtocol & SecurityProtocolType.Ssl3) == SecurityProtocolType.Ssl3)
151 return SecurityProtocolType.Ssl3;
155 throw new NotSupportedException("Unsupported security protocol type");
158 set { this.securityProtocol = value; }
161 public SecurityProtocolType SecurityProtocolFlags
163 get { return this.securityProtocol; }
166 public short Protocol
170 switch (this.SecurityProtocol)
172 case SecurityProtocolType.Tls:
173 case SecurityProtocolType.Default:
174 return Context.TLS1_PROTOCOL_CODE;
176 case SecurityProtocolType.Ssl3:
177 return Context.SSL3_PROTOCOL_CODE;
179 case SecurityProtocolType.Ssl2:
181 throw new NotSupportedException("Unsupported security protocol type");
186 public byte[] SessionId
188 get { return this.sessionId; }
189 set { this.sessionId = value; }
192 public SecurityCompressionType CompressionMethod
194 get { return this.compressionMethod; }
195 set { this.compressionMethod = value; }
198 public TlsServerSettings ServerSettings
200 get { return this.serverSettings; }
203 public TlsClientSettings ClientSettings
205 get { return this.clientSettings; }
210 get { return this.isActual; }
211 set { this.isActual = value; }
214 public HandshakeType LastHandshakeMsg
216 get { return this.lastHandshakeMsg; }
217 set { this.lastHandshakeMsg = value; }
220 public HandshakeState HandshakeState
222 get { return this.handshakeState; }
223 set { this.handshakeState = value; }
226 public bool ConnectionEnd
228 get { return this.connectionEnd; }
229 set { this.connectionEnd = value; }
232 public CipherSuite Cipher
234 get { return this.cipher; }
238 this.cipher.Context = this;
242 public CipherSuiteCollection SupportedCiphers
244 get { return supportedCiphers; }
245 set { supportedCiphers = value; }
248 public TlsStream HandshakeMessages
250 get { return this.handshakeMessages; }
253 public long WriteSequenceNumber
255 get { return this.writeSequenceNumber; }
256 set { this.writeSequenceNumber = value; }
259 public long ReadSequenceNumber
261 get { return this.readSequenceNumber; }
262 set { this.readSequenceNumber = value; }
265 public byte[] ClientRandom
267 get { return this.clientRandom; }
268 set { this.clientRandom = value; }
271 public byte[] ServerRandom
273 get { return this.serverRandom; }
274 set { this.serverRandom = value; }
277 public byte[] RandomCS
279 get { return this.randomCS; }
280 set { this.randomCS = value; }
283 public byte[] RandomSC
285 get { return this.randomSC; }
286 set { this.randomSC = value; }
289 public byte[] MasterSecret
291 get { return this.masterSecret; }
292 set { this.masterSecret = value; }
295 public byte[] ClientWriteMAC
297 get { return this.clientWriteMAC; }
298 set { this.clientWriteMAC = value; }
301 public byte[] ServerWriteMAC
303 get { return this.serverWriteMAC; }
304 set { this.serverWriteMAC = value; }
307 public byte[] ClientWriteKey
309 get { return this.clientWriteKey; }
310 set { this.clientWriteKey = value; }
313 public byte[] ServerWriteKey
315 get { return this.serverWriteKey; }
316 set { this.serverWriteKey = value; }
319 public byte[] ClientWriteIV
321 get { return this.clientWriteIV; }
322 set { this.clientWriteIV = value; }
325 public byte[] ServerWriteIV
327 get { return this.serverWriteIV; }
328 set { this.serverWriteIV = value; }
331 public RecordProtocol RecordProtocol
333 get { return this.recordProtocol; }
334 set { this.recordProtocol = value; }
341 public Context(SecurityProtocolType securityProtocolType)
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();
357 public int GetUnixTime()
359 DateTime now = DateTime.UtcNow;
361 return (int)(now.Ticks - UNIX_BASE_TICKS / TimeSpan.TicksPerSecond);
364 public byte[] GetSecureRandomBytes(int count)
366 byte[] secureBytes = new byte[count];
368 this.random.GetNonZeroBytes(secureBytes);
373 public virtual void Clear()
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;
385 public virtual void ClearKeyInfo()
387 // Clear Master Secret
388 this.masterSecret = null;
390 // Clear client and server random
391 this.clientRandom = null;
392 this.serverRandom = null;
393 this.randomCS = null;
394 this.randomSC = null;
397 this.clientWriteKey = null;
398 this.clientWriteIV = null;
401 this.serverWriteKey = null;
402 this.serverWriteIV = null;
404 // Reset handshake messages
405 this.handshakeMessages.Reset();
407 // Clear MAC keys if protocol is different than Ssl3
408 if (this.securityProtocol != SecurityProtocolType.Ssl3)
410 this.clientWriteMAC = null;
411 this.serverWriteMAC = null;
415 public SecurityProtocolType DecodeProtocolCode(short code)
419 case Context.TLS1_PROTOCOL_CODE:
420 return SecurityProtocolType.Tls;
422 case Context.SSL3_PROTOCOL_CODE:
423 return SecurityProtocolType.Ssl3;
426 throw new NotSupportedException("Unsupported security protocol type");