// Transport Security Layer (TLS)
// Copyright (c) 2003-2004 Carlos Guzman Alvarez
-
+// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
private TlsClientSettings clientSettings;
// Cipher suite information
- private CipherSuite cipher;
- private CipherSuiteCollection supportedCiphers;
+ private SecurityParameters current;
+ private SecurityParameters negotiating;
+ private SecurityParameters read;
+ private SecurityParameters write;
+ private CipherSuiteCollection supportedCiphers;
// Last handshake message received
private HandshakeType lastHandshakeMsg;
private HandshakeState handshakeState;
// Misc
- private bool isActual;
- private bool connectionEnd;
+ private bool abbreviatedHandshake;
+ private bool receivedConnectionEnd;
+ private bool sentConnectionEnd;
private bool protocolNegotiated;
// Sequence numbers
- private long writeSequenceNumber;
- private long readSequenceNumber;
+ private ulong writeSequenceNumber;
+ private ulong readSequenceNumber;
// Random data
private byte[] clientRandom;
// Key information
private byte[] masterSecret;
- private byte[] clientWriteMAC;
- private byte[] serverWriteMAC;
private byte[] clientWriteKey;
private byte[] serverWriteKey;
private byte[] clientWriteIV;
#region Properties
+ public bool AbbreviatedHandshake
+ {
+ get { return abbreviatedHandshake; }
+ set { abbreviatedHandshake = value; }
+ }
+
public bool ProtocolNegotiated
{
get { return this.protocolNegotiated; }
get { return this.clientSettings; }
}
- public bool IsActual
- {
- get { return this.isActual; }
- set { this.isActual = value; }
- }
-
public HandshakeType LastHandshakeMsg
{
get { return this.lastHandshakeMsg; }
set { this.handshakeState = value; }
}
- public bool ConnectionEnd
+ public bool ReceivedConnectionEnd
{
- get { return this.connectionEnd; }
- set { this.connectionEnd = value; }
+ get { return this.receivedConnectionEnd; }
+ set { this.receivedConnectionEnd = value; }
}
- public CipherSuite Cipher
+ public bool SentConnectionEnd
{
- get { return this.cipher; }
- set
- {
- this.cipher = value;
- this.cipher.Context = this;
- }
+ get { return this.sentConnectionEnd; }
+ set { this.sentConnectionEnd = value; }
}
public CipherSuiteCollection SupportedCiphers
get { return this.handshakeMessages; }
}
- public long WriteSequenceNumber
+ public ulong WriteSequenceNumber
{
get { return this.writeSequenceNumber; }
set { this.writeSequenceNumber = value; }
}
- public long ReadSequenceNumber
+ public ulong ReadSequenceNumber
{
get { return this.readSequenceNumber; }
set { this.readSequenceNumber = value; }
set { this.masterSecret = value; }
}
- public byte[] ClientWriteMAC
- {
- get { return this.clientWriteMAC; }
- set { this.clientWriteMAC = value; }
- }
-
- public byte[] ServerWriteMAC
- {
- get { return this.serverWriteMAC; }
- set { this.serverWriteMAC = value; }
- }
-
public byte[] ClientWriteKey
{
get { return this.clientWriteKey; }
{
DateTime now = DateTime.UtcNow;
- return (int)(now.Ticks - UNIX_BASE_TICKS / TimeSpan.TicksPerSecond);
+ return (int)((now.Ticks - UNIX_BASE_TICKS) / TimeSpan.TicksPerSecond);
}
public byte[] GetSecureRandomBytes(int count)
public virtual void ClearKeyInfo()
{
// Clear Master Secret
- this.masterSecret = null;
+ if (masterSecret != null) {
+ Array.Clear (masterSecret, 0, masterSecret.Length);
+ masterSecret = null;
+ }
// Clear client and server random
- this.clientRandom = null;
- this.serverRandom = null;
- this.randomCS = null;
- this.randomSC = null;
+ if (clientRandom != null) {
+ Array.Clear (clientRandom, 0, clientRandom.Length);
+ clientRandom = null;
+ }
+ if (serverRandom != null) {
+ Array.Clear (serverRandom, 0, serverRandom.Length);
+ serverRandom = null;
+ }
+ if (randomCS != null) {
+ Array.Clear (randomCS, 0, randomCS.Length);
+ randomCS = null;
+ }
+ if (randomSC != null) {
+ Array.Clear (randomSC, 0, randomSC.Length);
+ randomSC = null;
+ }
// Clear client keys
- this.clientWriteKey = null;
- this.clientWriteIV = null;
+ if (clientWriteKey != null) {
+ Array.Clear (clientWriteKey, 0, clientWriteKey.Length);
+ clientWriteKey = null;
+ }
+ if (clientWriteIV != null) {
+ Array.Clear (clientWriteIV, 0, clientWriteIV.Length);
+ clientWriteIV = null;
+ }
// Clear server keys
- this.serverWriteKey = null;
- this.serverWriteIV = null;
+ if (serverWriteKey != null) {
+ Array.Clear (serverWriteKey, 0, serverWriteKey.Length);
+ serverWriteKey = null;
+ }
+ if (serverWriteIV != null) {
+ Array.Clear (serverWriteIV, 0, serverWriteIV.Length);
+ serverWriteIV = null;
+ }
// Reset handshake messages
this.handshakeMessages.Reset();
// Clear MAC keys if protocol is different than Ssl3
+ // SSLv3 needs them inside Mono.Security.Protocol.Tls.SslCipherSuite.Compute[Client|Server]RecordMAC
if (this.securityProtocol != SecurityProtocolType.Ssl3)
{
- this.clientWriteMAC = null;
- this.serverWriteMAC = null;
+// this.clientWriteMAC = null;
+// this.serverWriteMAC = null;
}
}
}
}
+
+ public SecurityParameters Current
+ {
+ get
+ {
+ if (current == null)
+ current = new SecurityParameters ();
+ if (current.Cipher != null)
+ current.Cipher.Context = this;
+ return current;
+ }
+ }
+
+ public SecurityParameters Negotiating
+ {
+ get
+ {
+ if (negotiating == null)
+ negotiating = new SecurityParameters ();
+ if (negotiating.Cipher != null)
+ negotiating.Cipher.Context = this;
+ return negotiating;
+ }
+ }
+
+ public SecurityParameters Read
+ {
+ get { return read; }
+ }
+
+ public SecurityParameters Write
+ {
+ get { return write; }
+ }
+
+ public void StartSwitchingSecurityParameters (bool client)
+ {
+ if (client) {
+ // everything we write from now on is encrypted
+ write = negotiating;
+ // but we still read with the older cipher until we
+ // receive the ChangeCipherSpec message
+ read = current;
+ } else {
+ // everything we read from now on is encrypted
+ read = negotiating;
+ // but we still write with the older cipher until we
+ // receive the ChangeCipherSpec message
+ write = current;
+ }
+ current = negotiating;
+ }
+
+ public void EndSwitchingSecurityParameters (bool client)
+ {
+ SecurityParameters temp;
+ if (client) {
+ temp = read;
+ // we now read with the new, negotiated, security parameters
+ read = current;
+ } else {
+ temp = write;
+ // we now write with the new, negotiated, security parameters
+ write = current;
+ }
+ // so we clear the old one (last reference)
+ if (temp != null)
+ temp.Clear ();
+ negotiating = temp;
+ // and are now ready for a future renegotiation
+ }
+
#endregion
}
}