예제 #1
0
 void HandleChangeCipherSpecMessage(TLSChangeCipherSpecMessage msg)
 {
     /// Activate the new cipher protocol
     state.ReceiveEncryptionActive = true;
     state.ReadSequenceNumber      = 0;
 }
예제 #2
0
        /// <summary>
        /// A new TLS record has been received... It may contain multiple messages, so these need to be parsed
        /// </summary>
        /// <param name="record"></param>
        List <byte[]> ParseAndHandleTLSRecords(TLSRecord record)
        {
            List <byte[]> ApplicationDataReturned = new List <byte[]>();

            /// Decrypt our message if we are at that stage
            ///
            try
            {
                record = state.DecompressRecord(record);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("!!! Exception decompressing record: {0}", ex);

                SendAlert(AlertLevel.fatal, AlertDescription.BadRecordMAC);
                this.Client.Disconnect();
                return(ApplicationDataReturned);
            }


            /// Let the record parse it's content - couldn't do that until now that it's decrypted
            record.Content = record.RawSetContent;
            if (SocketClient.ShowDebug == true)
            {
                record.DebugDump(true);
            }

            foreach (TLSMessage tlsmsg in record.Messages)
            {
                if (record.ContentType == TLSContentType.Handshake)
                {
                    // Determine next handshake step
                    TLSHandShakeMessage msg = tlsmsg as TLSHandShakeMessage;

                    if (msg.HandShakeMessageType != HandShakeMessageType.Finished)
                    {
                        AllHandShakeMessages.AppendData(msg.RawBytes);
                        if (SocketClient.ShowDebug == true)
                        {
                            System.Diagnostics.Debug.WriteLine("AllHandShakeMessages, adding record of length {0}, Length is now {1}", record.RawSetContent.Length, AllHandShakeMessages.Size);
                        }
                    }
                    else
                    {
                    }

                    HandleHandshakeMessage(msg);
                }
                else if (record.ContentType == TLSContentType.Alert)
                {
                    TLSAlertMessage msg = tlsmsg as TLSAlertMessage;
                }
                else if (record.ContentType == TLSContentType.ChangeCipherSpec)
                {
                    TLSChangeCipherSpecMessage msg = tlsmsg as TLSChangeCipherSpecMessage;
                    HandleChangeCipherSpecMessage(msg);
                }
                else if (record.ContentType == TLSContentType.Application)
                {
                    // decrypt, add to ApplicationDataReturned
                    TLSApplicationMessage msg = tlsmsg as TLSApplicationMessage;
                    ApplicationDataReturned.Add(msg.ApplicationData);
                }
            }

            return(ApplicationDataReturned);
        }
예제 #3
0
        void HandleHandshakeMessage(TLSHandShakeMessage msg)
        {
            /// Append all our handshake data because we'll need it later for some stupid reason

            if (msg.HandShakeMessageType == HandShakeMessageType.ServerHello)
            {
                ClientTLSState = TLS.ClientTLSState.ReceivedServerHello;
            }
            else if (msg.HandShakeMessageType == HandShakeMessageType.ServerHelloDone)
            {
                if (m_bSendClientCertificate == true) /// got a certificate request from the server, but we don't have any, so send an empty one
                {
                    TLSHandShakeMessage msgclientcert = new TLSHandShakeMessage();
                    msgclientcert.HandShakeMessageType = HandShakeMessageType.Certificate;
                    TLSRecord recordclientcert = new TLSRecord();
                    recordclientcert.MajorVersion = 3;
                    recordclientcert.MinorVersion = 1;
                    recordclientcert.ContentType  = TLSContentType.Handshake;
                    recordclientcert.Messages.Add(msgclientcert);

                    SendTLSRecord(recordclientcert, true);
                }

                /// Server has sent the algorithm they want us to use, certificates, parameters,
                /// and any request for certificates from us.  Now let's respond
                /// First generate, encrypt, and send the PreMasterSecret

                byte [] bKey             = state.SecurityParameters.PeerCertificate.GetPublicKey();
                byte [] bPreMasterSecret = new byte[48];
                RNGCryptoServiceProvider.GetBytes(bPreMasterSecret); /// Get some random bytes
                bPreMasterSecret[0] = 0x03;                          /// first two bytes get set to the version
                bPreMasterSecret[1] = 0x01;

                /// Openssl is showing our modulus as having an extra 00 on the front when using this command
                /// (ignore this, the modulus lower in the output doesn't show the 0)
                /// rsa -in test_key.pem -text

                if (SocketClient.ShowDebug == true)
                {
                    System.Diagnostics.Debug.WriteLine("Client Random: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(state.SecurityParameters.ClientRandom, true, 16));
                    System.Diagnostics.Debug.WriteLine("Server Random: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(state.SecurityParameters.ServerRandom, true, 16));
                    System.Diagnostics.Debug.WriteLine("PreMasterSecret: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(bPreMasterSecret, true, 16));
                }

                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                // Need to use this guys' class to parse the DER encoded ASN.1 described certificate to
                // extract the modulus and e from the certificate - these two are the public key
                RSAParameters rsaparams = Kishore.X509.Parser.X509PublicKeyParser.GetRSAPublicKeyParameters(bKey);
                provider.ImportParameters(rsaparams);

                //System.Diagnostics.Debug.WriteLine("Public key modulus: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(rsaparams.Modulus, true, 16));
                //System.Diagnostics.Debug.WriteLine("Public key exponent: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(rsaparams.Exponent, true, 16));
                //System.Diagnostics.Debug.WriteLine("Key Exchange Algorithm: {0}, KeySize: {1}", provider.KeyExchangeAlgorithm, provider.KeySize);
                byte[] EncryptedPreMasterSecret = provider.Encrypt(bPreMasterSecret, false);
                provider.Dispose();

                /// Send a Client Key Exchange method with our PreMasterSecret
                ///
                TLSHandShakeMessage msgsend = new TLSHandShakeMessage();
                msgsend.HandShakeMessageType = HandShakeMessageType.ClientKeyExchange;
                msgsend.HandShakeClientKeyExchange.EncryptedPreMasterSecret = EncryptedPreMasterSecret;
                msgsend.HandShakeClientKeyExchange.KeyExchangeAlgorithm     = KeyExchangeAlgorithm.rsa;
                msgsend.HandShakeClientKeyExchange.PublicValueEncoding      = PublicValueEncoding.explicit_en;
                TLSRecord record = new TLSRecord();
                record.MajorVersion = 3;
                record.MinorVersion = 1;
                record.ContentType  = TLSContentType.Handshake;
                record.Messages.Add(msgsend);

                SendTLSRecord(record, true);



                /// Now generate all our keys, etc
                /// Section 8.1
                /// master_secret = PRF(pre_master_secret, "master secret",ClientHello.random + ServerHello.random) [0..47];

                // Combine ClientHello.Random and ServerHello.Random
                ByteBuffer buf = new ByteBuffer();
                buf.AppendData(state.SecurityParameters.ClientRandom);
                buf.AppendData(state.SecurityParameters.ServerRandom);
                byte [] bCSRandom = buf.GetAllSamples();

                // Do it in reverse order for different algorithms
                buf.AppendData(state.SecurityParameters.ServerRandom);
                buf.AppendData(state.SecurityParameters.ClientRandom);
                byte [] bSCRandom = buf.GetAllSamples();

                state.SecurityParameters.MasterSecret = state.PRF(bPreMasterSecret, "master secret", bCSRandom, 48);

                if (SocketClient.ShowDebug == true)
                {
                    System.Diagnostics.Debug.WriteLine("MasterSecret: +++++++++++\r\n{0}\r\n++++++++++++", ByteHelper.HexStringFromByte(state.SecurityParameters.MasterSecret, true, 16));
                }

                /// Verified that we are computing all our keys correctly by using the same input into the Mentalis library
                /// If we coded ours independently and get the same answers, it has to be correct, or we made the same mistakes :)
                state.ComputeKeys(state.SecurityParameters.MasterSecret, bSCRandom);



                /// Now send out a change cipher-spec, followed by a client finished message that is encrypted
                ///
                TLSChangeCipherSpecMessage msgChangeCipherSpec = new TLSChangeCipherSpecMessage();
                msgChangeCipherSpec.CCSProtocolType = CCSProtocolType.Default;
                TLSRecord recordccs = new TLSRecord();
                recordccs.MajorVersion = 3;
                recordccs.MinorVersion = 1;
                recordccs.ContentType  = TLSContentType.ChangeCipherSpec;
                recordccs.Messages.Add(msgChangeCipherSpec);
                SendTLSRecord(recordccs, false);

                state.SendEncryptionActive = true;
                state.WriteSequenceNumber  = 0; /// reset on changecipherspec

                /// Now send a finished method, encrypted with our generated things
                /// RFC2246 section 7.4.9

                if (SocketClient.ShowDebug == true)
                {
                    System.Diagnostics.Debug.WriteLine("FINAL:  AllHandShakeMessages Length is now {0}", AllHandShakeMessages.Size);
                }

                SHA1Managed sha1 = new SHA1Managed();
                byte[]      bAllHandshakeData        = AllHandShakeMessages.PeekAllSamples();
                byte[]      bmd5OfHandshakeMessages  = MD5Core.GetHash(bAllHandshakeData);
                byte[]      bsha1OfHandshakeMessages = sha1.ComputeHash(bAllHandshakeData);
                ByteBuffer  bSum = new ByteBuffer();
                bSum.AppendData(bmd5OfHandshakeMessages);
                bSum.AppendData(bsha1OfHandshakeMessages);

                byte [] bCombinedHashes = bSum.GetAllSamples();

                /// No use in writing out this debug, only a few of the characters get seen, the rest are dropped
                ///System.Diagnostics.Debug.WriteLine("**** Start all handshake data ****\r\n{0}\r\n**** End all handshake data ****", ByteHelper.HexStringFromByte(bAllHandshakeData, true, 32));
                /// verify_data
                ///     PRF(master_secret, finished_label, MD5(handshake_messages) + SHA-1(handshake_messages)) [0..11];

                TLSHandShakeMessage msgFinished = new TLSHandShakeMessage();
                msgFinished.HandShakeMessageType          = HandShakeMessageType.Finished;
                msgFinished.HandShakeFinished.verify_data = state.PRF(state.SecurityParameters.MasterSecret, "client finished", bCombinedHashes, 12);

                TLSRecord recordFinished = new TLSRecord();
                recordFinished.MajorVersion = 3;
                recordFinished.MinorVersion = 1;
                recordFinished.ContentType  = TLSContentType.Handshake;
                recordFinished.Messages.Add(msgFinished);

                state.WriteSequenceNumber = 0;
                /// This record must now be encrypted before it can be sent
                SendTLSRecord(recordFinished, true);


                ClientTLSState = ClientTLSState.SentClientFinished;
            }
            else if (msg.HandShakeMessageType == HandShakeMessageType.Finished)
            {
                /// Got the server finished method, let's verify the data
                ///
                SHA1Managed sha1 = new SHA1Managed();
                byte[]      bAllHandshakeData        = AllHandShakeMessages.GetAllSamples(); // no need to peek here, just get it all and clear it
                byte[]      bmd5OfHandshakeMessages  = MD5Core.GetHash(bAllHandshakeData);
                byte[]      bsha1OfHandshakeMessages = sha1.ComputeHash(bAllHandshakeData);
                ByteBuffer  bSum = new ByteBuffer();
                bSum.AppendData(bmd5OfHandshakeMessages);
                bSum.AppendData(bsha1OfHandshakeMessages);

                byte[] bCombinedHashes = bSum.GetAllSamples();

                /// No use in writing out this debug, only a few of the characters get seen, the rest are dropped
                ///System.Diagnostics.Debug.WriteLine("**** Start all handshake data ****\r\n{0}\r\n**** End all handshake data ****", ByteHelper.HexStringFromByte(bAllHandshakeData, true, 32));
                /// verify_data
                ///     PRF(master_secret, finished_label, MD5(handshake_messages) + SHA-1(handshake_messages)) [0..11];

                byte [] bComputedVerify = state.PRF(state.SecurityParameters.MasterSecret, "server finished", bCombinedHashes, 12);
                bool    bMatch          = ByteHelper.CompareArrays(msg.HandShakeFinished.verify_data, bComputedVerify);
                if (bMatch == false)
                {
                    SendAlert(AlertLevel.fatal, AlertDescription.HandshakeFailure);
                    Client.Disconnect();
                }
                else
                {
                    NegotiationFinished();
                }
            }
            else if (msg.HandShakeMessageType == HandShakeMessageType.CertificateRequest)
            {
                m_bSendClientCertificate = true;
            }



            if (ClientTLSState == TLS.ClientTLSState.ReceivedServerHello)
            {
                /// Gathering information
                ///
                if (msg.HandShakeMessageType == HandShakeMessageType.ServerHello)
                {
                    state.SecurityParameters.Cipher            = Cipher.FindCipher(msg.HandShakeServerHello.CipherSuite);
                    state.SecurityParameters.CompressionMethod = CompressionMethod.null0;
                    state.SecurityParameters.ConnectionEnd     = ConnectionEnd.client;
                    state.SecurityParameters.ServerRandom      = msg.HandShakeServerHello.RandomStruct.Bytes;
                }
                else if (msg.HandShakeMessageType == HandShakeMessageType.Certificate)
                {
                    if (msg.HandShakeCertificateMessage.Certificates.Count > 0)
                    {
                        state.SecurityParameters.PeerCertificate = msg.HandShakeCertificateMessage.Certificates[0];
                    }
                }
            }
        }
예제 #4
0
        void ParseContentForRecords(byte [] bContent)
        {
            Messages.Clear();

            uint nIndexAt = 0;

            while (nIndexAt < bContent.Length) // Read all the sub records of type ContentType in this TLSRecord
            {
                if (ContentType == TLSContentType.Handshake)
                {
                    // Determine next handshake step
                    TLSHandShakeMessage msg = new TLSHandShakeMessage();
                    uint nRead = msg.ReadFromArray(bContent, (int)nIndexAt);
                    if (nRead == 0)
                    {
                        break;
                    }
                    Messages.Add(msg);

                    nIndexAt += nRead;
                }
                else if (ContentType == TLSContentType.Alert)
                {
                    TLSAlertMessage msg   = new TLSAlertMessage();
                    uint            nRead = msg.ReadFromArray(bContent, (int)nIndexAt);
                    if (nRead == 0)
                    {
                        break;
                    }
                    Messages.Add(msg);
                    nIndexAt += nRead;
                }
                else if (ContentType == TLSContentType.ChangeCipherSpec)
                {
                    TLSChangeCipherSpecMessage msg = new TLSChangeCipherSpecMessage();
                    uint nRead = msg.ReadFromArray(bContent, (int)nIndexAt);
                    if (nRead == 0)
                    {
                        break;
                    }
                    Messages.Add(msg);
                    nIndexAt += nRead;
                }
                else if (ContentType == TLSContentType.Application)
                {
                    // decrypt, add to ApplicationDataReturned
                    TLSApplicationMessage msg = new TLSApplicationMessage();
                    uint nRead = msg.ReadFromArray(bContent, (int)nIndexAt);
                    if (nRead == 0)
                    {
                        break;
                    }
                    Messages.Add(msg);
                    nIndexAt += nRead;
                }
                else
                {
                    break;
                }
            }
        }