void SendClientHello() { ClientTLSState = ClientTLSState.SentClientHello; /// Send out Client Hello /// TLSHandShakeMessage msg = new TLSHandShakeMessage(); msg.HandShakeMessageType = HandShakeMessageType.ClientHello; msg.HandShakeClientHello.CompressionMethods.Add(CompressionMethod.null0); //msg.HandShakeClientHello.CipherSuites.Add(CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA); msg.HandShakeClientHello.CipherSuites.Add(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA); msg.HandShakeClientHello.Version = 0x0301; RNGCryptoServiceProvider.GetBytes(msg.HandShakeClientHello.RandomStruct.random_bytes); this.state.SecurityParameters.ClientRandom = msg.HandShakeClientHello.RandomStruct.Bytes; TLSRecord record = new TLSRecord(); record.MajorVersion = 3; record.MinorVersion = 1; record.ContentType = TLSContentType.Handshake; record.Messages.Add(msg); SendTLSRecord(record, true); }
public static void GenerateStuff() { string strPreMasterSecret = "03 01 7B 4C D6 CC FA A3 B6 52 1B 8B 46 92 25 3D F3 C1 1A F7 9E 99 95 B3 3E 96 B3 F7 90 B4 8D 6E B4 7A 46 C2 F8 7D 71 FE 32 19 E6 96 58 19 3E 78"; string strClientRandom = "4f 1b a0 34 2b f8 ad ba f4 97 4c 39 0f e1 e1 dd 4a a9 b1 af 39 f2 e4 25 ad 27 b0 ce a1 43 c4 49"; string strServerRandom = "4f 1b a0 6b 88 c1 1a 57 96 dd 83 79 aa ab 4f 99 0c c8 e2 31 74 9a af 16 a1 46 c7 da 88 d6 27 b5"; byte[] bPreMasterSecret = ByteHelper.ByteFromHexString(strPreMasterSecret); byte[] bClientRandom = ByteHelper.ByteFromHexString(strClientRandom); byte[] bServerRandom = ByteHelper.ByteFromHexString(strServerRandom); xmedianet.socketserver.TLS.ConnectionState trans = new xmedianet.socketserver.TLS.ConnectionState(); ByteBuffer buf = new ByteBuffer(); buf.AppendData(bClientRandom); buf.AppendData(bServerRandom); byte[] bCSRandom = buf.GetAllSamples(); // Do it in reverse order for different algorithms buf.AppendData(bServerRandom); buf.AppendData(bClientRandom); byte[] bSCRandom = buf.GetAllSamples(); byte[] MasterSecret = trans.PRF(bPreMasterSecret, "master secret", bCSRandom, 48); System.Diagnostics.Debug.WriteLine("Master Secret found is:\r\n{0}", ByteHelper.HexStringFromByte(MasterSecret, true, 16)); /// check... our master secret calulation matches what we see in wireshark, so all is well up to this point trans.SecurityParameters.Cipher = Cipher.FindCipher(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA); trans.ComputeKeys(MasterSecret, bSCRandom); string strClientHello = "0100003103014f1ba0342bf8adbaf4974c390fe1e1dd4aa9b1af39f2e425ad27b0cea143c449000004002f00ff0100000400230000"; string strServerHello = "0200003103014f1ba06b88c11a5796dd8379aaab4f990cc8e231749aaf16a146c7da88d627b500002f000009ff0100010000230000"; string strServerCert = "0b00029a00029700029430820290308201f9a00302010202090086c664416cd7cd31300d06092a864886f70d01010505003061310b3009060355040613025553310b300906035504080c025458310f300d06035504070c0644616c6c61733121301f060355040a0c18496e7465726e6574205769646769747320507479204c74643111300f06035504030c086d656c6c6c766172301e170d3132303132313138343235385a170d3132303232303138343235385a3061310b3009060355040613025553310b300906035504080c025458310f300d06035504070c0644616c6c61733121301f060355040a0c18496e7465726e6574205769646769747320507479204c74643111300f06035504030c086d656c6c6c76617230819f300d06092a864886f70d010101050003818d0030818902818100b393188b70c857fc0f7511f7322e6f91d2761f335de29c488416d82a091b428d315321cb44c7970a7618f5d6e84b0cdd5dbda847cd819ed98dae5c5dec79994b1ad76989150ca551dcbf6a9876e417558eceb78aa094f8c645a6898270a6402a038ad5e7e90303632455b7a1adf07d02633cb56bada5a1a22a0a8f3d842f40f30203010001a350304e301d0603551d0e0416041456326c3cb4f1d784c483fe7e167b80a67e421b63301f0603551d2304183016801456326c3cb4f1d784c483fe7e167b80a67e421b63300c0603551d13040530030101ff300d06092a864886f70d0101050500038181000e38924f5b9f57562bf95b163d0611b512d458866d4de9db94ce56efab9f198ef81247277612b4758728f4aececb54a122641fa0396792fe3f945d99dbc75de378f381071ae3bb11b53d18235f36cedab94670816b1c0b53f0a62daa0850cc368adadb3335d4bebff111e9fbba76ac5be7175279680ebb62e640927e3f6074fe"; string strServerDone = "0e000000"; string strClientKE = "1000008200809f6af68a96205955bfa0a8b793cb78720f063ef7c3ef82aa10a4f306bfdd8ace898eb5546b873e7b80a7ec95a817b3acf7cf64b45058deaf498bc270ad2901fd921a566c0ddc68c59225350b89f4289aa6f30cb5944cdebc62ed75a9907aee36687b5882fc4bbe9a571137ea2142a465f5278168319cca1646e33706be614091"; string strEncryptedHS = "59 09 86 f1 79 de 71 f4 b4 14 b1 ad 1a 70 c0 81 d5 24 32 8b 18 1a c4 a6 63 3a 27 d8 31 ad 54 5f 0d 85 37 a2 0f 6c 7b 9c 4b fc 83 18 e6 88 a6 67"; ByteBuffer objHandShakeBuffer = new ByteBuffer(); objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strClientHello)); objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerHello)); objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerCert)); objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerDone)); objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strClientKE)); /// Example says handshake has read 976 bytes of data and written 256... let's check with wireshark /// Sent: 53 + 134 170 /// Recv: 53 + 670 + 4 48 SHA1Managed sha1 = new SHA1Managed(); byte[] bAllHandShakeData = objHandShakeBuffer.GetAllSamples(); 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 = trans.PRF(MasterSecret, "client finished", bCombinedHashes, 12); TLSRecord recordFinished = new TLSRecord(); recordFinished.MajorVersion = 3; recordFinished.MinorVersion = 1; recordFinished.ContentType = TLSContentType.Handshake; recordFinished.Messages.Add(msgFinished); trans.WriteSequenceNumber = 0; byte[] bEncryptedGenericBlockCipher = trans.CompressEncryptOutgoingData(recordFinished); /// Check. The value here is the same as strEncryptedHS above System.Diagnostics.Debug.WriteLine("Encrypted Client Done is:\r\n{0}", ByteHelper.HexStringFromByte(bEncryptedGenericBlockCipher, true, 16)); }
public static void GenerateStuff2() { string strPreMasterSecret = "03 01 9A 04 0E DA 89 8C 97 01 53 0D DE 42 EE CF 69 09 8A D1 99 D2 B8 93 1B DA 4C 01 BA 1C A0 B6 01 B5 5F 5B 7A A0 F5 5B 3C B1 7D 72 96 33 BC DC"; string strClientRandom = "4f1c89f895eb17b8419927796ce5b6f20401a6e96262031f0b37a7872665f9ab"; string strServerRandom = "4f1c89cd4170867e7a5a2d6daa4e8d01237096c70bf891d7ff650554433b7ba5"; byte[] bPreMasterSecret = ByteHelper.ByteFromHexString(strPreMasterSecret); byte[] bClientRandom = ByteHelper.ByteFromHexString(strClientRandom); byte[] bServerRandom = ByteHelper.ByteFromHexString(strServerRandom); xmedianet.socketserver.TLS.ConnectionState trans = new xmedianet.socketserver.TLS.ConnectionState(); ByteBuffer buf = new ByteBuffer(); buf.AppendData(bClientRandom); buf.AppendData(bServerRandom); byte[] bCSRandom = buf.GetAllSamples(); // Do it in reverse order for different algorithms buf.AppendData(bServerRandom); buf.AppendData(bClientRandom); byte[] bSCRandom = buf.GetAllSamples(); byte[] MasterSecret = trans.PRF(bPreMasterSecret, "master secret", bCSRandom, 48); System.Diagnostics.Debug.WriteLine("Master Secret found is:\r\n{0}", ByteHelper.HexStringFromByte(MasterSecret, true, 16)); /// check... our master secret calulation matches what we see in wireshark, so all is well up to this point trans.SecurityParameters.Cipher = Cipher.FindCipher(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA); trans.ComputeKeys(MasterSecret, bSCRandom); string strClientHello = "0100002903014f1c89f895eb17b8419927796ce5b6f20401a6e96262031f0b37a7872665f9ab000002002f0100"; string strServerHello = "0200004603014f1c89cd4170867e7a5a2d6daa4e8d01237096c70bf891d7ff650554433b7ba520880100006ddf3cb09c0eb6e40d0167000f03ca81ac58eec4c3c760a70143524d002f00"; string strServerCert = "0b0004ba0004b70004b4308204b030820298a003020102021062be99f31b21039a47bcad3b019383c0300d06092a864886f70d0101050500301431123010060355040313096c6f63616c686f7374301e170d3132303130383036303030305a170d3232303131353036303030305a301431123010060355040313096c6f63616c686f737430820222300d06092a864886f70d01010105000382020f003082020a0282020100a0c647622204207c3948269a4338eba9b86e9494e5f18f3f024ef6850da59045f09ec8f55ed13d0407adb0f0eef2ea99c5ff6f2078a47b27a64eab77b4a1a709af8255d2b2bfd859149296dc5d93c91728165d484ec55ded72d34828ad43d782bcb81b4e3966b7cdccc88bb41355b42e0fd3ed8b24dbc99903ffb73d27d2f26bce18dd2712a84105eb6a0f4152e7a01ad7e8f1ad6d32c3b21ca3a0a6206398fbb1ac7e85f4586f5535ff35e693b5094bf7360a7a33fc9c2693087ae5777aa761a1fa016f02c320eacb51ea879f6a1dc078daab3e134bf0ae5bba774c6bdb95efe35ea7f8d8b0736ec2e28369b457b3d1c1522b810c2e7340a61b6a8c830af7c8de8047eb5f4b624d782a41e330d983515118182c6709ff41373f74d601aa5c9cb8c6a940549ab6f1f8ca11c945d17d2625acb7fe8a10109afddb9cd495da1f3e88261a063273344efb865e6d86fb0f6384f97685fb992af866616da81499a3223a2a557849c0507f27932063b73d9d2d47a2725c28dbce7b32f7f85d568142cad7c1a9cb9132a977b6e6c164a16fa0b77af027afc6dfb28a5d9e8a4babccac66e569f74a4689158a299100540230c9fdfcddc4649232e0af348d4f833f0a9344eb8f64b48f572cf9653280c2b26e6ea3fecb214ace7643e61f4c74dc79373505352f22408ed883252628b557ad749c80445d8acbe97cf9395c1897deb30dea850203010001300d06092a864886f70d010105050003820201004089ae88bd71245d1863b96505aa1342047088680f2078ca79b733eb542a4c1c267055de24210adc682f48f4d18d27d06100179a85bba5b21749cb8e71b200fb97c37b3e9ad64c197a4d4b7befdfceb67a69a80a7be24ac4cc6307ea3241f55b6800ecedee86b5fe8a21869cf8653cc0b653b71b5132c51ad2e334c16c1247155e82d744d0fdb9546d5c14bdbd9b8952d575e34335d85bd2c6079cf2adba910f98dc48a51217b617cf78ca91f57fe2b7ff88e2e78f5882530d55d63ec466a9d02e72f2a4269779880c66136a3dac96a26f334771e59cc89f3c66ddf5d21492b5d40565dbfdc0a9833d57c68728e969088612dbe655dc98a4d2449b2cf06208a4f26d831fa4d90eb79ea59d1934e61029a81c4795f28ec91df7b82b8f2ab85783f12e334d98e2313a7829f73630edd47a891de3b241ecf6aa3afd1d6c6e43db1d177a31b306bf7b05fb4fd56f462179e0efc439fa10391ce010c12607336e6379aa192bb106e86eb875a66919cc5a08692aefaebddbd92736f21b2410889530b8ceeded969624e1f9ab08957254d0029b20881f820276ede7987e86d705f88715e21e950e45624add2ee6cb682f2e9ecd37839ccda82290c5b6638981c45270f75a6c786fa734877a560e7d48c8abc122070ae0792a213de33ccfe0456f31e91c3be4833e50463e2a97ce828bbaae8324482bc07181ba7ee50fb87c65be66bb56"; string strServerDone = "0e000000"; string strClientKE = "1000020202000fab10111b3822b4fd32d0a73046b8d4f605eadf98bbf89bbd6924fea2e545e6ecbf2844f98de744edda195b73a4f10f9d473808697d03b3d34b947256f0f9395d914eb6a570091c559d27100c5897b8d66f4572955bc242f01d9328fe052f1e240aad72dece482aadb5440931d8271db0f59d558392013522f83c2cc9b11db4f654997f0293decd9a1a2ec950cfb2f2264158a7112ad3626fb51b368497fa4d5ef93b637b95b93b533ae9decd26e22d85a5f5d8b8ac1d151e7b11be23ff1cf341d78c42e281a536da9be3e4560a78fa428d9e44ee200504ba4d4146cbd64b5fb0179f8e015e64ccb13c5581119eb953b44f9d7081266d88fcfed08d632297fe2a94a98f2f930c5f8e564b89598e805bc3b143ea0acc1faa0e7d1d0799cb925b0f6d04f3c68b5d0cff0838ec881575b7aece5b481b17f193e9ad559c1426fa5f7407ba80e81b50ab6c5e589335fdb0861d6b351715cde0b13746b664928d640f1883760623ef867c4dd0568ffd08f03837f511abbc2821fe2d676bf2f742eeb50f27fadacbd211649a7889f0b38aedaab331747c424add3a13fe4575fffb120cbdd544b5d353b1dfbf5dd5be16545d70b436fac29fe12942b63a9dae438e0a5d3f3b116b39317161943474c477371001b3be844908799ec44aeab0f82607cf0e0ba86561c1d8a49298a17b6f2733c1340d185d337e349c58526d8407d3b38498"; string strEncryptedHS = "35275a481265bd929ede8056ed23ad42bebd2da9d8bc841b813ce8fae921b044fb37f03604fec9de92e1873155212143"; ByteBuffer objHandShakeBuffer = new ByteBuffer(); objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strClientHello)); objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerHello)); objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerCert)); objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strServerDone)); objHandShakeBuffer.AppendData(ByteHelper.ByteFromHexString(strClientKE)); /// Example says handshake has read 976 bytes of data and written 256... let's check with wireshark /// Sent: 53 + 134 170 /// Recv: 53 + 670 + 4 48 SHA1Managed sha1 = new SHA1Managed(); byte[] bAllHandShakeData = objHandShakeBuffer.GetAllSamples(); 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 = trans.PRF(MasterSecret, "client finished", bCombinedHashes, 12); TLSRecord recordFinished = new TLSRecord(); recordFinished.MajorVersion = 3; recordFinished.MinorVersion = 1; recordFinished.ContentType = TLSContentType.Handshake; recordFinished.Messages.Add(msgFinished); trans.WriteSequenceNumber = 0; byte[] bEncryptedGenericBlockCipher = trans.CompressEncryptOutgoingData(recordFinished); /// Check. The value here is the same as strEncryptedHS above System.Diagnostics.Debug.WriteLine("Encrypted Client Done is:\r\n{0}", ByteHelper.HexStringFromByte(bEncryptedGenericBlockCipher, true, 16)); }
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]; } } } }
/// <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); }
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; } } }