/** * Update statistics about the number of bytes * written to the client. * * \param int $written * Number of additional bytes written. * * \return * This method does not return anything. */ public function updateWriteStats($written) { if (!is_int($written)) { throw new \InvalidArgumentException('Not an integer'); } $time = time(); $this->context['rekeyingBytes'] += $written; if (isset($this->context['rekeying'])) { // Do not restart key exchange // if already rekeying. return; } $logging = \Plop\Plop::getInstance(); $stats = array('bytes' => $this->context['rekeyingBytes'], 'duration' => $time - $this->context['rekeyingTime'] + $this->rekeyingTime); $logging->debug('%(bytes)d bytes sent in %(duration)d seconds', $stats); if ($this->context['rekeyingBytes'] >= $this->rekeyingBytes || $time >= $this->context['rekeyingTime']) { $logging->debug('Initiating rekeying'); $this->context['rekeying'] = 'server'; $this->context['rekeyingBytes'] = 0; $this->context['rekeyingTime'] = $time + $this->rekeyingTime; $kexinit = new \fpoirotte\Pssht\Handlers\InitialState(); $kexinit->handleKEXINIT($this, $this->context); } }
public function handle($msgType, \fpoirotte\Pssht\Wire\Decoder $decoder, \fpoirotte\Pssht\Transport $transport, array &$context) { $algos = \fpoirotte\Pssht\Algorithms::factory(); $kex = \fpoirotte\Pssht\Messages\KEXINIT::unserialize($decoder); $context['kex']['client'] = $kex; if (!isset($context['rekeying'])) { $context['rekeying'] = 'client'; } // KEX method $context['kexAlgo'] = null; foreach ($kex->getKEXAlgos() as $algo) { if ($algos->getClass('KEX', $algo) !== null) { $kexCls = $context['kexAlgo'] = $algos->getClass('KEX', $algo); break; } } // No suitable KEX algorithm found. if (!isset($context['kexAlgo'])) { throw new \RuntimeException(); } $kexCls::addHandlers($transport); // C2S encryption $context['C2S']['Encryption'] = null; foreach ($kex->getC2SEncryptionAlgos() as $algo) { if ($algos->getClass('Encryption', $algo) !== null) { $context['C2S']['Encryption'] = $algos->getClass('Encryption', $algo); break; } } // No suitable C2S encryption cipher found. if (!isset($context['C2S']['Encryption'])) { throw new \RuntimeException(); } // C2S compression $context['C2S']['Compression'] = null; foreach ($kex->getC2SCompressionAlgos() as $algo) { if ($algos->getClass('Compression', $algo) !== null) { $context['C2S']['Compression'] = $algos->getClass('Compression', $algo); break; } } // No suitable C2S compression found. if (!isset($context['C2S']['Compression'])) { throw new \RuntimeException(); } // C2S MAC $context['C2S']['MAC'] = null; $reflector = new \ReflectionClass($context['C2S']['Encryption']); // Skip MAC algorithm selection for AEAD. if ($reflector->implementsInterface('\\fpoirotte\\Pssht\\AEADInterface')) { $context['C2S']['MAC'] = '\\fpoirotte\\Pssht\\MAC\\None'; } else { foreach ($kex->getC2SMACAlgos() as $algo) { if ($algos->getClass('MAC', $algo) !== null) { $context['C2S']['MAC'] = $algos->getClass('MAC', $algo); break; } } } // No suitable C2S MAC found. if (!isset($context['C2S']['MAC'])) { throw new \RuntimeException(); } // S2C encryption $context['S2C']['Encryption'] = null; foreach ($kex->getS2CEncryptionAlgos() as $algo) { if ($algos->getClass('Encryption', $algo) !== null) { $context['S2C']['Encryption'] = $algos->getClass('Encryption', $algo); break; } } // No suitable S2C encryption cipher found. if (!isset($context['S2C']['Encryption'])) { throw new \RuntimeException(); } // S2C compression $context['S2C']['Compression'] = null; foreach ($kex->getS2CCompressionAlgos() as $algo) { if ($algos->getClass('Compression', $algo) !== null) { $context['S2C']['Compression'] = $algos->getClass('Compression', $algo); break; } } // No suitable S2C compression found. if (!isset($context['S2C']['Compression'])) { throw new \RuntimeException(); } // S2C MAC $context['S2C']['MAC'] = null; $reflector = new \ReflectionClass($context['S2C']['Encryption']); // Skip MAC algorithm selection for AEAD. if ($reflector->implementsInterface('\\fpoirotte\\Pssht\\AEADInterface')) { $context['S2C']['MAC'] = '\\fpoirotte\\Pssht\\MAC\\None'; } else { foreach ($kex->getS2CMACAlgos() as $algo) { if ($algos->getClass('MAC', $algo) !== null) { $context['S2C']['MAC'] = $algos->getClass('MAC', $algo); break; } } } // No suitable S2C MAC found. if (!isset($context['S2C']['MAC'])) { throw new \RuntimeException(); } if ($context['rekeying'] === 'client') { $kexinit = new \fpoirotte\Pssht\Handlers\InitialState(); return $kexinit->handleKEXINIT($transport, $context); } return true; }