public function encodeChangeCipherSpec($data) { $core = $this->core; if ($this->expectedHandshakeType != HandshakeType::FINISHED || $core->isHandshaked) { throw new TLSException("Invalid message"); } $changeCipherSpec = new ChangeCipherSpec(); $changeCipherSpec->encode($data); $this->content = $changeCipherSpec; }
public function encodeHandshake($payload) { $core = $this->core; // Incomming Record $recordIn = $core->getInDuplex()->getRecord(); // Outgoing Record $recordOut = $core->getOutDuplex()->getRecord(); // Buffer to send $bufferOut = $core->getBufferOut(); // Extension $extensions = $core->extensions; if ($core->isHandshaked) { throw new TLSAlertException(Alert::create(Alert::UNEXPECTED_MESSAGE), "Handshake message received after handshake is complete"); } /* * https://tools.ietf.org/html/rfc5246#section-7.4 * * Get Handshake Msg type */ $handshakeType = Core::_unpack('C', $payload[0]); if ($this->expectedHandshakeType != $handshakeType) { throw new TLSAlertException(Alert::create(Alert::UNEXPECTED_MESSAGE), "Unexpected handshake message: {$handshakeType} <=> " . $this->expectedHandshakeType); } $handshake = HandshakeFactory::getInstance($core, $handshakeType); $handshake->encode($payload); $this->content = $handshake; switch ($this->expectedHandshakeType) { case HandshakeType::SERVER_HELLO: $this->expectedHandshakeType = HandshakeType::CERTIFICATE; break; case HandshakeType::CERTIFICATE: if ($core->cipherSuite->isECDHEEnabled()) { $this->expectedHandshakeType = HandshakeType::SERVER_KEY_EXCHANGE; } else { $this->expectedHandshakeType = HandshakeType::SERVER_HELLO_DONE; } break; case HandshakeType::SERVER_KEY_EXCHANGE: $this->expectedHandshakeType = HandshakeType::SERVER_HELLO_DONE; break; case HandshakeType::SERVER_HELLO_DONE: // =========================================== // Send Client Key Exchange // =========================================== $clientKeyExchange = HandshakeFactory::getInstance($core, HandshakeType::CLIENT_KEY_EXCHANGE); $bufferOut->set($this->decodeContent($clientKeyExchange->decode(), ContentType::HANDSHAKE)); // =========================================== // Send Change Cipher Spec // =========================================== $changeCipherSpec = new ChangeCipherSpec(); $bufferOut->append($this->decodeContent($changeCipherSpec->decode(), ContentType::CHANGE_CIPHER_SPEC)); // Enable encryption $recordOut->cipherChanged(); // =========================================== // Send Client finished // =========================================== $clientFinished = HandShakeFactory::getInstance($core, HandshakeType::FINISHED); $bufferOut->append($this->decodeContent($clientFinished->decode(), ContentType::HANDSHAKE)); $this->expectedHandshakeType = HandshakeType::FINISHED; break; case HandshakeType::FINISHED: $core->isHandshaked = true; break; } if (strlen($payload) > $handshake->get('length')) { $payload = substr($payload, $handshake->get('length')); $this->encodeHandshake($payload); } }