Ejemplo n.º 1
0
 public function setOutput(Core $core)
 {
     $alert = $this->alert;
     if ($alert->fromPeer()) {
         return;
     }
     $recordOut = $core->getOutDuplex()->getRecord();
     $payload = $alert->decode();
     $this->output = $recordOut->set('contentType', ContentType::ALERT)->set('payload', $payload)->decode();
 }
Ejemplo n.º 2
0
 public function decode()
 {
     $core = $this->core;
     $extensions = $core->extensions;
     $connOut = $core->getOutDuplex();
     $sessionID = $core->getSessionID();
     list($vMajor, $vMinor) = $core->getVersion();
     // Set server random
     $connOut->random = Core::getRandom(32);
     $sessionLength = strlen($sessionID);
     $data = Core::_pack('C', $vMajor) . Core::_pack('C', $vMinor) . $connOut->random . Core::_pack('C', $sessionLength);
     if ($sessionLength > 0) {
         $data .= $sessionID;
     }
     $cipherSuite = $core->cipherSuite;
     list($cipher1, $cipher2) = $cipherSuite->getID();
     $data .= Core::_pack('C', $cipher1) . Core::_pack('C', $cipher2);
     // Compression method length
     $data .= Core::_pack('C', 0x0);
     $extData = $extensions->onDecodeServerHello();
     if (strlen($extData) > 0) {
         $data .= Core::_pack('n', strlen($extData)) . $extData;
     }
     $this->msgType = 2;
     $this->length = strlen($data);
     return $this->getBinHeader() . $data;
 }
Ejemplo n.º 3
0
 public function decode()
 {
     $core = $this->core;
     list($vMajor, $vMinor) = $core->getVersion();
     // Client
     $connOut = $core->getOutDuplex();
     // Server
     $connIn = $core->getInDuplex();
     // ECDHE
     if ($core->cipherSuite->isECDHEEnabled()) {
         $extensions = $core->extensions;
         $data = $extensions->call('Curve', 'decodeClientKeyExchange', '');
         $preMaster = $extensions->call('Curve', 'getPremaster', null);
     } else {
         $preMaster = Core::_pack('C', $vMajor) . Core::_pack('C', $vMinor) . Core::getRandom(46);
         $crtDers = $core->getCrtDers();
         $publicKey = X509::getPublicKey($crtDers);
         openssl_public_encrypt($preMaster, $encPreMaster, $publicKey);
         $data = Core::_pack('n', strlen($encPreMaster)) . $encPreMaster;
     }
     // Set Master Secret, IV and MAC
     $this->setKeys($preMaster, $connIn, $connOut);
     $this->msgType = HandshakeType::CLIENT_KEY_EXCHANGE;
     $this->length = strlen($data);
     return $this->getBinHeader() . $data;
 }
Ejemplo n.º 4
0
 protected static function getZeroSeq()
 {
     $seq = [];
     for ($i = 0; $i < 8; $i++) {
         $seq[$i] = Core::_pack('C', 0);
     }
     return $seq;
 }
Ejemplo n.º 5
0
 public function onDecodeClientHello()
 {
     $sigData = '';
     foreach (self::$supportedAlgorithmList as $algorithm) {
         $sigData .= Core::_pack('C', $algorithm >> 8) . Core::_pack('C', $algorithm & 0xff);
     }
     $sigData = Core::_pack('n', strlen($sigData)) . $sigData;
     $this->extType = TLSExtensions::TYPE_SIGNATURE_ALGORITHM;
     $this->length = strlen($sigData);
     $data = $this->decodeHeader() . $sigData;
     return $data;
 }
Ejemplo n.º 6
0
 public function decode()
 {
     $core = $this->core;
     $crtDers = $core->getCrtDers();
     $crtData = '';
     foreach ($crtDers as $crtDer) {
         $crtLength = strlen($crtDer);
         // Cert Length
         $crtData .= Core::_pack('C', 0x0) . Core::_pack('n', $crtLength) . $crtDer;
     }
     $data = Core::_pack('C', 0x0) . Core::_pack('n', strlen($crtData)) . $crtData;
     $this->msgType = HandshakeType::CERTIFICATE;
     $this->length = strlen($data);
     return $this->getBinHeader() . $data;
 }
Ejemplo n.º 7
0
 /**
  * for Client Hello and Server Hello
  */
 protected function encodeExtensions($data)
 {
     $extensions = [];
     for ($j = 0; $j < strlen($data);) {
         $extType = Core::_unpack('n', $data[$j] . $data[$j + 1]);
         $extDataLen = Core::_unpack('n', $data[$j + 2] . $data[$j + 3]);
         if (0 == $extDataLen) {
             $j += 2 + 2;
             continue;
         }
         $extData = substr($data, $j + 4, $extDataLen);
         $j += 2 + 2 + $extDataLen;
         $extensions[] = ['type' => $extType, 'data' => $extData];
     }
     return $extensions;
 }
Ejemplo n.º 8
0
 public static function decodeCipherList()
 {
     $data = '';
     foreach (self::$enabledCipherSuites as $val) {
         $data .= Core::_pack('C', $val >> 8) . Core::_pack('C', $val & 0xff);
     }
     return $data;
 }
Ejemplo n.º 9
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);
     }
 }
Ejemplo n.º 10
0
 public function decode()
 {
     return Core::_pack('C', $this->level) . Core::_pack('C', $this->descCode);
 }
Ejemplo n.º 11
0
 public function getPublicKey()
 {
     $privateKey = $this->getPrivateKey();
     $this->publicKey = $publicKey = $privateKey->getPublicKey();
     $publicPoint = $publicKey->getPoint();
     // Convert to binary - Uncompressed
     $publicKeyBin = Core::_pack('C', 0x4) . gmp_export($publicPoint->getX(), 1, GMP_BIG_ENDIAN) . gmp_export($publicPoint->getY(), 1, GMP_BIG_ENDIAN);
     return $publicKeyBin;
 }
Ejemplo n.º 12
0
 public function calculateMAC()
 {
     $conn = $this->conn;
     $core = $conn->getCore();
     $cipherSuite = $core->cipherSuite;
     list($vMajor, $vMinor) = $core->getVersion();
     if (is_null($this->seq)) {
         $this->seq = self::getZeroSeq();
     }
     $secretMAC = $conn->MAC;
     $contentType = Core::_pack('C', $this->contentType);
     $major = Core::_pack('C', $vMajor);
     $minor = Core::_pack('C', $vMinor);
     $length = Core::_pack('n', strlen($this->payload));
     /*
      * https://tools.ietf.org/html/rfc5246#section-6.2.3.1
      *
      * The MAC is generated as:
      *
      * MAC(MAC_write_key, seq_num +
      *                    TLSCompressed.type +
      *                    TLSCompressed.version +
      *                    TLSCompressed.length +
      *                    TLSCompressed.fragment);
      */
     $concat = implode('', $this->seq) . $contentType . $major . $minor . $length . $this->payload;
     //$macStr = $cipherSuite->hashHmac($concat, $secretMAC, false );
     $mac = $cipherSuite->hashHmac($concat, $secretMAC);
     return $mac;
 }
Ejemplo n.º 13
0
 /**
  * Additional Authentication Data
  */
 public function getAAD($length)
 {
     $conn = $this->conn;
     $core = $conn->getCore();
     $cipherSuite = $core->cipherSuite;
     list($vMajor, $vMinor) = $core->getVersion();
     if (is_null($this->seq)) {
         $this->seq = self::getZeroSeq();
     }
     $contentType = Core::_pack('C', $this->contentType);
     $major = Core::_pack('C', $vMajor);
     $minor = Core::_pack('C', $vMinor);
     $length = Core::_pack('n', $length);
     /*
      * https://tools.ietf.org/html/rfc5246#section-6.2.3.3
      *
      *  additional_data = seq_num + TLSCompressed.type +
      *               TLSCompressed.version + TLSCompressed.length;
      *
      */
     $concat = implode('', $this->seq) . $contentType . $major . $minor . $length;
     return $concat;
 }
Ejemplo n.º 14
0
 public function decode()
 {
     $core = $this->core;
     $connOut = $core->getOutDuplex();
     list($vMajor, $vMinor) = $core->getVersion();
     // Set client random
     $connOut->random = Core::getRandom(32);
     // Set TLS Version
     $data = Core::_pack('C', $vMajor) . Core::_pack('C', $vMinor);
     // Client Random
     $data .= $connOut->random;
     // Session ID - no session
     $data .= Core::_pack('C', 0x0);
     // Cipher Suite
     $cipherSuiteList = CipherSuites::decodeCipherList();
     $data .= Core::_pack('n', strlen($cipherSuiteList)) . $cipherSuiteList;
     // Compression method
     $data .= Core::_pack('C', 0x1) . Core::_pack('C', $core->getCompressionMethod());
     // Extension Length
     //$data .= Core::_pack('n', 0x00);
     $extensionData = $core->extensions->onDecodeClientHello();
     $data .= Core::_pack('n', strlen($extensionData)) . $extensionData;
     $this->msgType = HandshakeType::CLIENT_HELLO;
     $this->length = strlen($data);
     return $this->getBinHeader() . $data;
 }
Ejemplo n.º 15
0
 public function decode()
 {
     return Core::_pack('C', 0x1);
 }
Ejemplo n.º 16
0
 protected function decodeHeader()
 {
     // MsgType
     $header = Core::_pack('C', 0) . Core::_pack('C', $this->extType) . Core::_pack('n', $this->length);
     return $header;
 }
Ejemplo n.º 17
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;
 }
Ejemplo n.º 18
0
 public function decode()
 {
     $core = $this->getCore();
     list($vMajor, $vMinor) = $core->getVersion();
     // type
     $data = Core::_pack('C', $this->contentType) . Core::_pack('C', $vMajor) . Core::_pack('C', $vMinor) . Core::_pack('n', $this->length) . $this->payload;
     // Handshake
     if ($this->contentType == ContentType::HANDSHAKE && !$this->conn->isCipherChanged) {
         $core->countHandshakeMessages($this->payload);
     }
     $this->reset();
     return $data;
 }