1 /* Transport Security Layer (TLS)
2 * Copyright (c) 2003-2004 Carlos Guzman Alvarez
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
27 using System.Collections;
28 using System.Security.Cryptography;
29 using System.Security.Cryptography.X509Certificates;
31 using Mono.Security.Cryptography;
32 using Mono.Security.Protocol.Tls.Handshake;
34 namespace Mono.Security.Protocol.Tls
36 internal abstract class Context
38 #region Internal Constants
40 internal const short MAX_FRAGMENT_SIZE = 16384; // 2^14
41 internal const short TLS1_PROTOCOL_CODE = (0x03 << 8) | 0x01;
42 internal const short SSL3_PROTOCOL_CODE = (0x03 << 8) | 0x00;
43 internal const long UNIX_BASE_TICKS = 621355968000000000;
50 private SecurityProtocolType securityProtocol;
53 private byte[] sessionId;
56 private SecurityCompressionType compressionMethod;
58 // Information sent and request by the server in the Handshake protocol
59 private TlsServerSettings serverSettings;
61 // Client configuration
62 private TlsClientSettings clientSettings;
64 // Cipher suite information
65 private CipherSuite cipher;
66 private CipherSuiteCollection supportedCiphers;
68 // Last handshake message received
69 private HandshakeType lastHandshakeMsg;
71 // Handshake negotiation state
72 private HandshakeState handshakeState;
75 private bool isActual;
76 private bool connectionEnd;
77 private bool protocolNegotiated;
80 private long writeSequenceNumber;
81 private long readSequenceNumber;
84 private byte[] clientRandom;
85 private byte[] serverRandom;
86 private byte[] randomCS;
87 private byte[] randomSC;
90 private byte[] masterSecret;
91 private byte[] clientWriteMAC;
92 private byte[] serverWriteMAC;
93 private byte[] clientWriteKey;
94 private byte[] serverWriteKey;
95 private byte[] clientWriteIV;
96 private byte[] serverWriteIV;
99 private TlsStream handshakeMessages;
101 // Secure Random generator
102 private RandomNumberGenerator random;
105 private RecordProtocol recordProtocol;
111 public bool ProtocolNegotiated
113 get { return this.protocolNegotiated; }
114 set { this.protocolNegotiated = value; }
117 public SecurityProtocolType SecurityProtocol
121 if ((this.securityProtocol & SecurityProtocolType.Tls) == SecurityProtocolType.Tls ||
122 (this.securityProtocol & SecurityProtocolType.Default) == SecurityProtocolType.Default)
124 return SecurityProtocolType.Tls;
128 if ((this.securityProtocol & SecurityProtocolType.Ssl3) == SecurityProtocolType.Ssl3)
130 return SecurityProtocolType.Ssl3;
134 throw new NotSupportedException("Unsupported security protocol type");
137 set { this.securityProtocol = value; }
140 public SecurityProtocolType SecurityProtocolFlags
142 get { return this.securityProtocol; }
145 public short Protocol
149 switch (this.SecurityProtocol)
151 case SecurityProtocolType.Tls:
152 case SecurityProtocolType.Default:
153 return Context.TLS1_PROTOCOL_CODE;
155 case SecurityProtocolType.Ssl3:
156 return Context.SSL3_PROTOCOL_CODE;
158 case SecurityProtocolType.Ssl2:
160 throw new NotSupportedException("Unsupported security protocol type");
165 public byte[] SessionId
167 get { return this.sessionId; }
168 set { this.sessionId = value; }
171 public SecurityCompressionType CompressionMethod
173 get { return this.compressionMethod; }
174 set { this.compressionMethod = value; }
177 public TlsServerSettings ServerSettings
179 get { return this.serverSettings; }
180 set { this.serverSettings = value; }
183 public TlsClientSettings ClientSettings
185 get { return this.clientSettings; }
186 set { this.clientSettings = value; }
191 get { return this.isActual; }
192 set { this.isActual = value; }
195 public HandshakeType LastHandshakeMsg
197 get { return this.lastHandshakeMsg; }
198 set { this.lastHandshakeMsg = value; }
201 public HandshakeState HandshakeState
203 get { return this.handshakeState; }
204 set { this.handshakeState = value; }
207 public bool ConnectionEnd
209 get { return this.connectionEnd; }
210 set { this.connectionEnd = value; }
213 public CipherSuite Cipher
215 get { return this.cipher; }
219 this.cipher.Context = this;
223 public CipherSuiteCollection SupportedCiphers
225 get { return supportedCiphers; }
226 set { supportedCiphers = value; }
229 public TlsStream HandshakeMessages
231 get { return this.handshakeMessages; }
234 public long WriteSequenceNumber
236 get { return this.writeSequenceNumber; }
237 set { this.writeSequenceNumber = value; }
240 public long ReadSequenceNumber
242 get { return this.readSequenceNumber; }
243 set { this.readSequenceNumber = value; }
246 public byte[] ClientRandom
248 get { return this.clientRandom; }
249 set { this.clientRandom = value; }
252 public byte[] ServerRandom
254 get { return this.serverRandom; }
255 set { this.serverRandom = value; }
258 public byte[] RandomCS
260 get { return this.randomCS; }
261 set { this.randomCS = value; }
264 public byte[] RandomSC
266 get { return this.randomSC; }
267 set { this.randomSC = value; }
270 public byte[] MasterSecret
272 get { return this.masterSecret; }
273 set { this.masterSecret = value; }
276 public byte[] ClientWriteMAC
278 get { return this.clientWriteMAC; }
279 set { this.clientWriteMAC = value; }
282 public byte[] ServerWriteMAC
284 get { return this.serverWriteMAC; }
285 set { this.serverWriteMAC = value; }
288 public byte[] ClientWriteKey
290 get { return this.clientWriteKey; }
291 set { this.clientWriteKey = value; }
294 public byte[] ServerWriteKey
296 get { return this.serverWriteKey; }
297 set { this.serverWriteKey = value; }
300 public byte[] ClientWriteIV
302 get { return this.clientWriteIV; }
303 set { this.clientWriteIV = value; }
306 public byte[] ServerWriteIV
308 get { return this.serverWriteIV; }
309 set { this.serverWriteIV = value; }
312 public RecordProtocol RecordProtocol
314 get { return this.recordProtocol; }
315 set { this.recordProtocol = value; }
322 public Context(SecurityProtocolType securityProtocolType)
324 this.SecurityProtocol = securityProtocolType;
325 this.compressionMethod = SecurityCompressionType.None;
326 this.serverSettings = new TlsServerSettings();
327 this.clientSettings = new TlsClientSettings();
328 this.handshakeMessages = new TlsStream();
329 this.sessionId = null;
330 this.handshakeState = HandshakeState.None;
331 this.random = RandomNumberGenerator.Create();
338 public int GetUnixTime()
340 DateTime now = DateTime.UtcNow;
342 return (int)(now.Ticks - UNIX_BASE_TICKS / TimeSpan.TicksPerSecond);
345 public byte[] GetSecureRandomBytes(int count)
347 byte[] secureBytes = new byte[count];
349 this.random.GetNonZeroBytes(secureBytes);
354 public virtual void Clear()
356 this.compressionMethod = SecurityCompressionType.None;
357 this.serverSettings = new TlsServerSettings();
358 this.clientSettings = new TlsClientSettings();
359 this.handshakeMessages = new TlsStream();
360 this.sessionId = null;
361 this.handshakeState = HandshakeState.None;
366 public virtual void ClearKeyInfo()
368 // Clear Master Secret
369 this.masterSecret = null;
371 // Clear client and server random
372 this.clientRandom = null;
373 this.serverRandom = null;
374 this.randomCS = null;
375 this.randomSC = null;
378 this.clientWriteKey = null;
379 this.clientWriteIV = null;
382 this.serverWriteKey = null;
383 this.serverWriteIV = null;
385 // Reset handshake messages
386 this.handshakeMessages.Reset();
388 // Clear MAC keys if protocol is different than Ssl3
389 if (this.securityProtocol != SecurityProtocolType.Ssl3)
391 this.clientWriteMAC = null;
392 this.serverWriteMAC = null;
396 public SecurityProtocolType DecodeProtocolCode(short code)
400 case Context.TLS1_PROTOCOL_CODE:
401 return SecurityProtocolType.Tls;
403 case Context.SSL3_PROTOCOL_CODE:
404 return SecurityProtocolType.Ssl3;
407 throw new NotSupportedException("Unsupported security protocol type");