New tests.
[mono.git] / mcs / class / Mono.Security / Mono.Security.Protocol.Tls / Context.cs
index 579548d5e3b9c97237370e38cd3faf43c1d7f356..792a9970a1774369fcd68897cbe3a3a17fb05aa0 100644 (file)
@@ -1,6 +1,6 @@
 // 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
@@ -62,8 +62,11 @@ namespace Mono.Security.Protocol.Tls
                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;
@@ -72,13 +75,14 @@ namespace Mono.Security.Protocol.Tls
                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;
@@ -88,8 +92,6 @@ namespace Mono.Security.Protocol.Tls
 
                // Key information
                private byte[]  masterSecret;
-               private byte[]  clientWriteMAC;
-               private byte[]  serverWriteMAC;
                private byte[]  clientWriteKey;
                private byte[]  serverWriteKey;
                private byte[]  clientWriteIV;
@@ -108,6 +110,12 @@ namespace Mono.Security.Protocol.Tls
 
                #region Properties
 
+               public bool AbbreviatedHandshake
+               {
+                       get { return abbreviatedHandshake; }
+                       set { abbreviatedHandshake = value; }
+               }
+
                public bool     ProtocolNegotiated
                {
                        get { return this.protocolNegotiated; }
@@ -184,12 +192,6 @@ namespace Mono.Security.Protocol.Tls
                        get { return this.clientSettings; }
                }
 
-               public bool     IsActual
-               {
-                       get { return this.isActual; }
-                       set { this.isActual = value; }
-               }
-
                public HandshakeType LastHandshakeMsg
                {
                        get { return this.lastHandshakeMsg; }
@@ -202,20 +204,16 @@ namespace Mono.Security.Protocol.Tls
                        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
@@ -229,13 +227,13 @@ namespace Mono.Security.Protocol.Tls
                        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; }
@@ -271,18 +269,6 @@ namespace Mono.Security.Protocol.Tls
                        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; }
@@ -337,7 +323,7 @@ namespace Mono.Security.Protocol.Tls
                {
                        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)
@@ -364,30 +350,58 @@ namespace Mono.Security.Protocol.Tls
                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;
                        }
                }
 
@@ -424,6 +438,78 @@ namespace Mono.Security.Protocol.Tls
                        }
                }
 
+
+               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
        }
 }