internal void Receive(ICertificateProvider certProvider, INetState ns, HttpsReader reader) { RecordHandshake(reader.Buffer, reader.Length, !reader.IsDecrypted); EHandshake handshakeType = (EHandshake)reader.ReadByte(); int handshakeMsgLength = reader.Read24BitInt(); HttpsReader.VerifyLengthRemaining(reader, handshakeMsgLength, "Ssl handshake"); switch (handshakeType) { case EHandshake.ClientHello: ReceiveClientHello(certProvider, ns, reader); break; case EHandshake.ClientKeyExchange: ReceiveClientKeyExchange(certProvider, ns, reader); break; case EHandshake.Finished: ReceiveClientFinished(ns, reader); break; default: ns.Send(new HttpsSmsgAlert(ns.Https, 2, 10)); throw new HttpsException($"sent unknown handshake 0x{handshakeType:X}", reader); } }
private bool TryGetReader(HttpsSession https, ref byte[] buffer, ref int length, out HttpsReader reader) { reader = null; if (length < 5) { return(false); } int fragmentLength = (buffer[3] << 8) + buffer[4] + 5; if (length < fragmentLength) { return(false); } else if (length == fragmentLength) { reader = new HttpsReader(https, buffer, length); length = 0; } else { // todo: this is so inefficient! byte[] fragmentBuffer = new byte[fragmentLength]; Array.Copy(buffer, fragmentBuffer, fragmentLength); reader = new HttpsReader(https, fragmentBuffer, fragmentLength); Array.Copy(buffer, fragmentLength, buffer, 0, length - fragmentLength); length -= fragmentLength; } return(true); }
// --- Https Change Cipher Spec --- internal void ReceiveChangeCipherSpec(INetState ns, HttpsReader reader) { byte payload = reader.ReadByte(); HttpsReader.VerifyLengthRemaining(reader, 0, "ChangeClientSpec"); if (payload != 0x01) { throw new HttpsException($"sent ChangeCipherSpec with wrong payload.", reader); } SessionIdentifier = _Handshake.SessionIdentifier; SequenceNumberReceived = 0; SequenceNumberSent = 0; CipherSuite = _Handshake.CipherSuite; _KeyBlock = _Handshake.GetKeyBlock(); Decryptor = CipherSuite.GetTransform(_KeyBlock.ClientWriteKey); Encryptor = CipherSuite.GetTransform(_KeyBlock.ServerWriteKey); // DeMAC = CipherSuite.GetMAC(_KeyBlock.ClientWriteMACKey); // EnMAC = CipherSuite.GetMAC(_KeyBlock.ServerWriteMACKey); IsClientEncrypting = true; }
private void ReceiveClientFinished(INetState ns, HttpsReader reader) { HttpsCmsgFinished packet = new HttpsCmsgFinished(reader); byte[] allHandshakes = _AllHandshakes.ToArray(); KeyedHashAlgorithm verify = CipherSuite.GetHMAC(_MasterSecret); verify.Initialize(); verify.TransformBlock(allHandshakes, 0, allHandshakes.Length - reader.Length, allHandshakes, 0); if (ns.Https.Protocol == EProtocol.SSLv30) { verify.TransformFinalBlock(SslBlocks.SenderClient, 0, SslBlocks.SenderClient.Length); if (!ByteArrayEquality(packet.Verification, 0, verify.Hash, 0, packet.Verification.Length)) { throw new HttpsException("ClientFinished hash did not match computed hash.", reader); } } else { throw new HttpsException($"Unknown protocol {ns.Https.Protocol}", reader); } ns.Https.SendChangeCipherSpec(ns, 0x01); SendServerFinished(ns, allHandshakes); }
// --- Https Handshake --- internal void ReceiveHandshake(ICertificateProvider certProvider, INetState ns, HttpsReader reader) { if (_Handshake == null) { _Handshake = new HttpsHandshakeSession(); } _Handshake.Receive(certProvider, ns, reader); }
// --- Handshake Packets ------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------- private void ReceiveClientHello(ICertificateProvider certProvider, INetState ns, HttpsReader reader) { HttpsCmsgHello packet = new HttpsCmsgHello(reader); if (packet.SessionID != null) { throw new HttpsException($"provided a sessionID (unsupported)", reader); } if (!SupportedCiphers.Select(packet.Ciphers, out CipherSuiteInfo cipherSelected)) { throw new HttpsException("does not support any of our cipher suites", reader); } CipherSuite = cipherSelected; _ClientRandom = packet.ClientRandom; _ServerRandom = new byte[32]; Randoms.NextBytesUnixTimePrefix(_ServerRandom); HttpsWriter serverHello = new HttpsSmsgHello(ns.Https, CipherSuite.CipherSuite, SessionIdentifier, _ServerRandom); HttpsWriter serverCerts = new HttpsSmsgCertificate(ns.Https, certProvider.HttpsGetCerts()); HttpsWriter serverHelloDone = new HttpsSmsgHelloDone(ns.Https); Send(ns, serverHello); Send(ns, serverCerts); Send(ns, serverHelloDone); }
private void ReceiveClientKeyExchange(ICertificateProvider certProvider, INetState ns, HttpsReader reader) { HttpsCmsgKeyExchange packet = new HttpsCmsgKeyExchange(reader); _PreMasterSecret = certProvider.HttpsCertDecrypt(packet.EncryptedPreMasterSecret); }