Beispiel #1
0
 public HandshakeLayer(RecordLayer recordLayer, SecurityOptions options)
 {
     connectionEnd           = options.Entity;
     m_Disposed              = false;
     m_Options               = options;
     m_IsNegotiating         = true;
     m_RNG                   = new RNGCryptoServiceProvider();
     m_RecordLayer           = recordLayer;
     m_State                 = HandshakeType.Nothing;
     m_IncompleteMessage     = new byte[0];
     m_LocalMD5Hash          = new MD5CryptoServiceProvider();
     m_LocalSHA1Hash         = new SHA1CryptoServiceProvider();
     m_RemoteMD5Hash         = new MD5CryptoServiceProvider();
     m_RemoteSHA1Hash        = new SHA1CryptoServiceProvider();
     m_CertSignHash          = new MD5SHA1CryptoServiceProvider();
     m_CertSignHash.Protocol = this.GetProtocol();
     if (options.Entity == ConnectionEnd.Server && ((int)options.Flags & (int)SecurityFlags.MutualAuthentication) != 0)
     {
         m_MutualAuthentication = true;
     }
     else
     {
         m_MutualAuthentication = false;
     }
 }
        protected SslHandshakeStatus ProcessServerKeyExchange(HandshakeMessage message)
        {
            if (m_State != HandshakeType.Certificate)
            {
                throw new SslException(AlertDescription.UnexpectedMessage, "ServerKeyExchange message must be preceded by a Certificate message.");
            }
            CipherDefinition cd = CipherSuites.GetCipherDefinition(m_EncryptionScheme);

            if (!cd.Exportable)
            {
                throw new SslException(AlertDescription.HandshakeFailure, "The ServerKeyExchange message should not be sent for non-exportable ciphers.");
            }
            if (m_RemoteCertificate.GetPublicKeyLength() <= 512)
            {
                throw new SslException(AlertDescription.HandshakeFailure, "The ServerKeyExchange message should not be sent because the server certificate public key is of exportable length.");
            }
            UpdateHashes(message, HashUpdate.All);             // input message
            // extract modulus and exponent
            RSAParameters pars = new RSAParameters();
            int           size = message.fragment[0] * 256 + message.fragment[1];

            pars.Modulus = new byte[size];
            Buffer.BlockCopy(message.fragment, 2, pars.Modulus, 0, size);
            int offset = size + 2;

            size          = message.fragment[offset] * 256 + message.fragment[offset + 1];
            pars.Exponent = new byte[size];
            Buffer.BlockCopy(message.fragment, offset + 2, pars.Exponent, 0, size);
            offset       += size + 2;
            pars.Modulus  = RemoveLeadingZeros(pars.Modulus);
            pars.Exponent = RemoveLeadingZeros(pars.Exponent);
            m_KeyCipher   = new RSACryptoServiceProvider();
            m_KeyCipher.ImportParameters(pars);
            // compute verification hashes
            MD5SHA1CryptoServiceProvider ms = new MD5SHA1CryptoServiceProvider();

            ms.TransformBlock(m_ClientTime, 0, m_ClientTime.Length, m_ClientTime, 0);
            ms.TransformBlock(m_ClientRandom, 0, m_ClientRandom.Length, m_ClientRandom, 0);
            ms.TransformBlock(m_ServerTime, 0, m_ServerTime.Length, m_ServerTime, 0);
            ms.TransformBlock(m_ServerRandom, 0, m_ServerRandom.Length, m_ServerRandom, 0);
            ms.TransformFinalBlock(message.fragment, 0, offset);
            // verify the signature
            size = message.fragment[offset] * 256 + message.fragment[offset + 1];
            byte[] signature = new byte[size];             // holds the signature returned by the server
            Buffer.BlockCopy(message.fragment, offset + 2, signature, 0, size);
            if (!ms.VerifySignature(m_RemoteCertificate, signature))
            {
                throw new SslException(AlertDescription.HandshakeFailure, "The data was not signed by the server certificate.");
            }
            ms.Clear();
            return(new SslHandshakeStatus(SslStatus.MessageIncomplete, null));
        }
		public HandshakeLayer(RecordLayer recordLayer, SecurityOptions options) {
			m_Disposed = false;
			m_Options = options;
			m_IsNegotiating = true;
			m_RNG = new RNGCryptoServiceProvider();
			m_RecordLayer = recordLayer;
			m_State = HandshakeType.Nothing;
			m_IncompleteMessage = new byte[0];
			m_LocalMD5Hash = new MD5CryptoServiceProvider();
			m_LocalSHA1Hash = new SHA1CryptoServiceProvider();
			m_RemoteMD5Hash = new MD5CryptoServiceProvider();
			m_RemoteSHA1Hash = new SHA1CryptoServiceProvider();
			m_CertSignHash = new MD5SHA1CryptoServiceProvider();
			m_CertSignHash.Protocol = this.GetProtocol();
			if (options.Entity == ConnectionEnd.Server && ((int)options.Flags & (int)SecurityFlags.MutualAuthentication) != 0)
				m_MutualAuthentication = true;
			else
				m_MutualAuthentication = false;
		}
 protected SslHandshakeStatus ProcessServerKeyExchange(HandshakeMessage message)
 {
     if (m_State != HandshakeType.Certificate)
         throw new SslException(AlertDescription.UnexpectedMessage, "ServerKeyExchange message must be preceded by a Certificate message.");
     CipherDefinition cd = CipherSuites.GetCipherDefinition(m_EncryptionScheme);
     if (!cd.Exportable)
         throw new SslException(AlertDescription.HandshakeFailure, "The ServerKeyExchange message should not be sent for non-exportable ciphers.");
     if (m_RemoteCertificate.GetPublicKeyLength() <= 512)
         throw new SslException(AlertDescription.HandshakeFailure, "The ServerKeyExchange message should not be sent because the server certificate public key is of exportable length.");
     UpdateHashes(message, HashUpdate.All); // input message
     // extract modulus and exponent
     RSAParameters pars = new RSAParameters();
     int size = message.fragment[0] * 256 + message.fragment[1];
     pars.Modulus = new byte[size];
     Buffer.BlockCopy(message.fragment, 2, pars.Modulus, 0, size);
     int offset = size + 2;
     size = message.fragment[offset] * 256 + message.fragment[offset + 1];
     pars.Exponent = new byte[size];
     Buffer.BlockCopy(message.fragment, offset + 2, pars.Exponent, 0, size);
     offset += size + 2;
     pars.Modulus = RemoveLeadingZeros(pars.Modulus);
     pars.Exponent = RemoveLeadingZeros(pars.Exponent);
     m_KeyCipher = new RSACryptoServiceProvider();
     m_KeyCipher.ImportParameters(pars);
     // compute verification hashes
     MD5SHA1CryptoServiceProvider ms = new MD5SHA1CryptoServiceProvider();
     ms.TransformBlock(m_ClientTime, 0, m_ClientTime.Length, m_ClientTime, 0);
     ms.TransformBlock(m_ClientRandom, 0, m_ClientRandom.Length, m_ClientRandom, 0);
     ms.TransformBlock(m_ServerTime, 0, m_ServerTime.Length, m_ServerTime, 0);
     ms.TransformBlock(m_ServerRandom, 0, m_ServerRandom.Length, m_ServerRandom, 0);
     ms.TransformFinalBlock(message.fragment, 0, offset);
     // verify the signature
     size = message.fragment[offset] * 256 + message.fragment[offset + 1];
     byte[] signature = new byte[size]; // holds the signature returned by the server
     Buffer.BlockCopy(message.fragment, offset + 2, signature, 0, size);
     if (!ms.VerifySignature(m_RemoteCertificate, signature))
         throw new SslException(AlertDescription.HandshakeFailure, "The data was not signed by the server certificate.");
     ms.Clear();
     return new SslHandshakeStatus(SslStatus.MessageIncomplete, null);
 }
 public HandshakeLayer(HandshakeLayer handshakeLayer)
 {
     m_Disposed = false;
     m_RecordLayer = handshakeLayer.m_RecordLayer;
     m_Options = handshakeLayer.m_Options;
     m_IsNegotiating = handshakeLayer.m_IsNegotiating;
     m_RNG = handshakeLayer.m_RNG;
     m_State = handshakeLayer.m_State;
     m_IncompleteMessage = handshakeLayer.m_IncompleteMessage;
     m_LocalMD5Hash = handshakeLayer.m_LocalMD5Hash;
     m_LocalSHA1Hash = handshakeLayer.m_LocalSHA1Hash;
     m_RemoteMD5Hash = handshakeLayer.m_RemoteMD5Hash;
     m_RemoteSHA1Hash = handshakeLayer.m_RemoteSHA1Hash;
     m_CertSignHash = handshakeLayer.m_CertSignHash;
     m_CertSignHash.Protocol = this.GetProtocol();
     m_MutualAuthentication = handshakeLayer.m_MutualAuthentication;
     m_ClientTime = handshakeLayer.m_ClientTime;
     m_ClientRandom = handshakeLayer.m_ClientRandom;
     handshakeLayer.Dispose(false);
 }
		protected SslHandshakeStatus GetClientHelloResult() {
			MemoryStream retMessage = new MemoryStream();
			SslHandshakeStatus ret = new SslHandshakeStatus();
			HandshakeMessage temp;
			byte[] bytes;
			// ServerHello message
			temp = new HandshakeMessage(HandshakeType.ServerHello, new byte[38]);
			m_ServerTime = GetUnixTime();
			m_ServerRandom = new byte[28];
			m_RNG.GetBytes(m_ServerRandom);
			temp.fragment[0] = GetVersion().major;
			temp.fragment[1] = GetVersion().minor;
			Array.Copy(m_ServerTime, 0, temp.fragment, 2, 4);
			Array.Copy(m_ServerRandom, 0, temp.fragment, 6, 28);
			temp.fragment[34] = 0; // do not resume a session, and do not let the other side cache it
			Array.Copy(CipherSuites.GetCipherAlgorithmBytes(m_EncryptionScheme), 0, temp.fragment, 35, 2);
			temp.fragment[37] = CompressionAlgorithm.GetAlgorithmByte(m_CompressionMethod);
			bytes = temp.ToBytes();
			retMessage.Write(bytes, 0, bytes.Length);
			// Certificate message
			byte[] certs = GetCertificateList(m_Options.Certificate);
			temp.type = HandshakeType.Certificate;
			temp.fragment = certs;
			bytes = temp.ToBytes();
			retMessage.Write(bytes, 0, bytes.Length);
			// ServerKeyExchange message [optional] => only with RSA_EXPORT and public key > 512 bits
			if (m_Options.Certificate.GetPublicKeyLength() > 512 && CipherSuites.GetCipherDefinition(m_EncryptionScheme).Exportable) {
				MemoryStream kes = new MemoryStream();
				MD5SHA1CryptoServiceProvider mscsp = new MD5SHA1CryptoServiceProvider();
				// hash the client and server random values
				mscsp.TransformBlock(m_ClientTime, 0, 4, m_ClientTime, 0);
				mscsp.TransformBlock(m_ClientRandom, 0, 28, m_ClientRandom, 0);
				mscsp.TransformBlock(m_ServerTime, 0, 4, m_ServerTime, 0);
				mscsp.TransformBlock(m_ServerRandom, 0, 28, m_ServerRandom, 0);
				// create a new 512 bit RSA key
				m_KeyCipher = new RSACryptoServiceProvider(512);
				RSAParameters p = m_KeyCipher.ExportParameters(false);
				// write the key parameters to the output stream
				bytes = new byte[]{(byte)(p.Modulus.Length / 256), (byte)(p.Modulus.Length % 256)};
				kes.Write(bytes, 0, 2);
				kes.Write(p.Modulus, 0, p.Modulus.Length);
				mscsp.TransformBlock(bytes, 0, 2, bytes, 0);
				mscsp.TransformBlock(p.Modulus, 0, p.Modulus.Length, p.Modulus, 0);
				bytes = new byte[]{(byte)(p.Exponent.Length / 256), (byte)(p.Exponent.Length % 256)};
				kes.Write(bytes, 0, 2);
				kes.Write(p.Exponent, 0, p.Exponent.Length);
				mscsp.TransformBlock(bytes, 0, 2, bytes, 0);
				mscsp.TransformFinalBlock(p.Exponent, 0, p.Exponent.Length);
				// create signature
				bytes = mscsp.CreateSignature(m_Options.Certificate);
				kes.Write(new byte[]{(byte)(bytes.Length / 256), (byte)(bytes.Length % 256)}, 0, 2);
				kes.Write(bytes, 0, bytes.Length);
				// write to output
				temp.type = HandshakeType.ServerKeyExchange;
				temp.fragment = kes.ToArray();
				bytes = temp.ToBytes();
				retMessage.Write(bytes, 0, bytes.Length);
				kes.Close();
			} else {
				m_KeyCipher = (RSACryptoServiceProvider)m_Options.Certificate.PrivateKey;
			}
			// CertificateRequest message [optional]
			if (m_MutualAuthentication) {
				bytes = GetDistinguishedNames();
				if (bytes.Length != 0) { // make sure at least one certificate is returned
					temp.type = HandshakeType.CertificateRequest;
					temp.fragment = new byte[bytes.Length + 4];
					temp.fragment[0] = 1; // one certificate type supported
					temp.fragment[1] = 1; // cert type RSA
					temp.fragment[2] = (byte)(bytes.Length / 256);
					temp.fragment[3] = (byte)(bytes.Length % 256);
					Array.Copy(bytes, 0, temp.fragment, 4, bytes.Length);
					bytes = temp.ToBytes();
					retMessage.Write(bytes, 0, bytes.Length);
				}
			}
			// ServerHelloDone message
			temp.type = HandshakeType.ServerHelloDone;
			temp.fragment = new byte[0];
			bytes = temp.ToBytes();
			retMessage.Write(bytes, 0, bytes.Length);
			// final adjustments
			ret.Status = SslStatus.ContinueNeeded;
			ret.Message = retMessage.ToArray();
			retMessage.Close();
			UpdateHashes(ret.Message, HashUpdate.All); // output message
			ret.Message = m_RecordLayer.EncryptBytes(ret.Message, 0, ret.Message.Length, ContentType.Handshake);
			return ret;
		}
        protected SslHandshakeStatus GetClientHelloResult()
        {
            MemoryStream       retMessage = new MemoryStream();
            SslHandshakeStatus ret        = new SslHandshakeStatus();
            HandshakeMessage   temp;

            byte[] bytes;
            // ServerHello message
            temp           = new HandshakeMessage(HandshakeType.ServerHello, new byte[38]);
            m_ServerTime   = GetUnixTime();
            m_ServerRandom = new byte[28];
            m_RNG.GetBytes(m_ServerRandom);
            temp.fragment[0] = GetVersion().major;
            temp.fragment[1] = GetVersion().minor;
            Array.Copy(m_ServerTime, 0, temp.fragment, 2, 4);
            Array.Copy(m_ServerRandom, 0, temp.fragment, 6, 28);
            temp.fragment[34] = 0;             // do not resume a session, and do not let the other side cache it
            Array.Copy(CipherSuites.GetCipherAlgorithmBytes(m_EncryptionScheme), 0, temp.fragment, 35, 2);
            temp.fragment[37] = CompressionAlgorithm.GetAlgorithmByte(m_CompressionMethod);
            bytes             = temp.ToBytes();
            retMessage.Write(bytes, 0, bytes.Length);
            // Certificate message
            byte[] certs = GetCertificateList(m_Options.Certificate);
            temp.type     = HandshakeType.Certificate;
            temp.fragment = certs;
            bytes         = temp.ToBytes();
            retMessage.Write(bytes, 0, bytes.Length);
            // ServerKeyExchange message [optional] => only with RSA_EXPORT and public key > 512 bits
            if (m_Options.Certificate.GetPublicKeyLength() > 512 && CipherSuites.GetCipherDefinition(m_EncryptionScheme).Exportable)
            {
                MemoryStream kes = new MemoryStream();
                MD5SHA1CryptoServiceProvider mscsp = new MD5SHA1CryptoServiceProvider();
                // hash the client and server random values
                mscsp.TransformBlock(m_ClientTime, 0, 4, m_ClientTime, 0);
                mscsp.TransformBlock(m_ClientRandom, 0, 28, m_ClientRandom, 0);
                mscsp.TransformBlock(m_ServerTime, 0, 4, m_ServerTime, 0);
                mscsp.TransformBlock(m_ServerRandom, 0, 28, m_ServerRandom, 0);
                // create a new 512 bit RSA key
                m_KeyCipher = new RSACryptoServiceProvider(512);
                RSAParameters p = m_KeyCipher.ExportParameters(false);
                // write the key parameters to the output stream
                bytes = new byte[] { (byte)(p.Modulus.Length / 256), (byte)(p.Modulus.Length % 256) };
                kes.Write(bytes, 0, 2);
                kes.Write(p.Modulus, 0, p.Modulus.Length);
                mscsp.TransformBlock(bytes, 0, 2, bytes, 0);
                mscsp.TransformBlock(p.Modulus, 0, p.Modulus.Length, p.Modulus, 0);
                bytes = new byte[] { (byte)(p.Exponent.Length / 256), (byte)(p.Exponent.Length % 256) };
                kes.Write(bytes, 0, 2);
                kes.Write(p.Exponent, 0, p.Exponent.Length);
                mscsp.TransformBlock(bytes, 0, 2, bytes, 0);
                mscsp.TransformFinalBlock(p.Exponent, 0, p.Exponent.Length);
                // create signature
                bytes = mscsp.CreateSignature(m_Options.Certificate);
                kes.Write(new byte[] { (byte)(bytes.Length / 256), (byte)(bytes.Length % 256) }, 0, 2);
                kes.Write(bytes, 0, bytes.Length);
                // write to output
                temp.type     = HandshakeType.ServerKeyExchange;
                temp.fragment = kes.ToArray();
                bytes         = temp.ToBytes();
                retMessage.Write(bytes, 0, bytes.Length);
                kes.Close();
            }
            else
            {
                m_KeyCipher = (RSACryptoServiceProvider)m_Options.Certificate.PrivateKey;
            }
            // CertificateRequest message [optional]
            if (m_MutualAuthentication)
            {
                bytes = GetDistinguishedNames();
                if (bytes.Length != 0)                   // make sure at least one certificate is returned
                {
                    temp.type        = HandshakeType.CertificateRequest;
                    temp.fragment    = new byte[bytes.Length + 4];
                    temp.fragment[0] = 1;                     // one certificate type supported
                    temp.fragment[1] = 1;                     // cert type RSA
                    temp.fragment[2] = (byte)(bytes.Length / 256);
                    temp.fragment[3] = (byte)(bytes.Length % 256);
                    Array.Copy(bytes, 0, temp.fragment, 4, bytes.Length);
                    bytes = temp.ToBytes();
                    retMessage.Write(bytes, 0, bytes.Length);
                }
            }
            // ServerHelloDone message
            temp.type     = HandshakeType.ServerHelloDone;
            temp.fragment = new byte[0];
            bytes         = temp.ToBytes();
            retMessage.Write(bytes, 0, bytes.Length);
            // final adjustments
            ret.Status  = SslStatus.ContinueNeeded;
            ret.Message = retMessage.ToArray();
            retMessage.Close();
            UpdateHashes(ret.Message, HashUpdate.All);             // output message
            ret.Message = m_RecordLayer.EncryptBytes(ret.Message, 0, ret.Message.Length, ContentType.Handshake);
            return(ret);
        }