Beispiel #1
0
 public function decodeServerKeyExchange()
 {
     $core = $this->core;
     $extensions = $core->extensions;
     $protoVersion = $core->getProtocolVersion();
     /*
      * ECCurveType
      *
      * We only support named curves, which is 0x03 
      *
      * enum { explicit_prime (1), explicit_char2 (2),
      *        named_curve (3), reserved(248..255) } ECCurveType;
      */
     $data = Core::_pack('C', 0x3);
     // Named curve type
     $data .= Core::_pack('n', $this->namedCurveType);
     // ECDH Public Key
     $this->ecdh = new EcDH($this->namedCurveType);
     $dataPublicKey = $this->ecdh->getPublicKey();
     $data .= Core::_pack('C', strlen($dataPublicKey)) . $dataPublicKey;
     /*
      * Signature
      * 
      * https://tools.ietf.org/html/rfc4492 Page 19
      * signed_params:   A hash of the params, with the signature appropriate
      * to that hash applied.  The private key corresponding to the
      * certified public key in the server's Certificate message is used
      * for signing.
      *
      * ServerKeyExchange.signed_params.sha_hash
      *    SHA(ClientHello.random + ServerHello.random +
      *                                      ServerKeyExchange.params);
      */
     $connIn = $core->getInDuplex();
     $connOut = $core->getOutDuplex();
     $dataSign = $connIn->random . $connOut->random . $data;
     $signature = $extensions->call('SignatureAlgorithm', 'getSignature', null, $dataSign);
     if ($protoVersion >= 32) {
         // Signature Hash Alogorithm
         // [null, null] never happens
         list($hash, $sig) = $extensions->call('SignatureAlgorithm', 'getAlgorithm', [null, null]);
         $data .= Core::_pack('C', $hash) . Core::_pack('C', $sig);
     }
     // Append signature
     $data .= Core::_pack('n', strlen($signature)) . $signature;
     $hs = HandShakeFactory::getInstance($core, HandshakeType::SERVER_KEY_EXCHANGE);
     $hs->setMsgType(HandshakeType::SERVER_KEY_EXCHANGE);
     $hs->set('length', strlen($data));
     return $hs->getBinHeader() . $data;
 }
Beispiel #2
0
 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);
     }
 }