diff --git a/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php b/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php index 937aef5d..d5a9db4e 100644 --- a/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php +++ b/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php @@ -327,12 +327,15 @@ abstract class PKCS8 extends PKCS $meta['meta']['algorithm'] = $algorithm; $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); + if (!$temp) { + throw new \RuntimeException('Unable to decode BER'); + } extract(ASN1::asn1map($temp[0], Maps\PBEParameter::MAP)); $iterationCount = (int) $iterationCount->toString(); $cipher->setPassword($password, $kdf, $hash, $salt, $iterationCount); $key = $cipher->decrypt($decrypted['encryptedData']); $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { + if (!$decoded) { throw new \RuntimeException('Unable to decode BER 2'); } @@ -341,6 +344,9 @@ abstract class PKCS8 extends PKCS $meta['meta']['algorithm'] = $algorithm; $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); + if (!$temp) { + throw new \RuntimeException('Unable to decode BER'); + } $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP); extract($temp); @@ -348,6 +354,9 @@ abstract class PKCS8 extends PKCS $meta['meta']['cipher'] = $encryptionScheme['algorithm']; $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); + if (!$temp) { + throw new \RuntimeException('Unable to decode BER'); + } $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP); extract($temp); @@ -355,6 +364,9 @@ abstract class PKCS8 extends PKCS $cipher->setIV($encryptionScheme['parameters']['octetString']); } else { $temp = ASN1::decodeBER($encryptionScheme['parameters']); + if (!$temp) { + throw new \RuntimeException('Unable to decode BER'); + } extract(ASN1::asn1map($temp[0], Maps\RC2CBCParameter::MAP)); $effectiveKeyLength = (int) $rc2ParametersVersion->toString(); switch ($effectiveKeyLength) { @@ -377,6 +389,9 @@ abstract class PKCS8 extends PKCS switch ($keyDerivationFunc['algorithm']) { case 'id-PBKDF2': $temp = ASN1::decodeBER($keyDerivationFunc['parameters']); + if (!$temp) { + throw new \RuntimeException('Unable to decode BER'); + } $prf = ['algorithm' => 'id-hmacWithSHA1']; $params = ASN1::asn1map($temp[0], Maps\PBKDF2params::MAP); extract($params); @@ -395,7 +410,7 @@ abstract class PKCS8 extends PKCS $cipher->setPassword(...$params); $key = $cipher->decrypt($decrypted['encryptedData']); $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { + if (!$decoded) { throw new \RuntimeException('Unable to decode BER 3'); } break; @@ -619,7 +634,7 @@ abstract class PKCS8 extends PKCS } $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { + if (!$decoded) { throw new \RuntimeException('Unable to decode BER'); } @@ -640,12 +655,18 @@ abstract class PKCS8 extends PKCS if ($r['encryptionAlgorithm']['algorithm'] == 'id-PBES2') { $decoded = ASN1::decodeBER($r['encryptionAlgorithm']['parameters']->element); + if (!$decoded) { + throw new \RuntimeException('Unable to decode BER'); + } $r['encryptionAlgorithm']['parameters'] = ASN1::asn1map($decoded[0], ASN1\Maps\PBES2params::MAP); $kdf = &$r['encryptionAlgorithm']['parameters']['keyDerivationFunc']; switch ($kdf['algorithm']) { case 'id-PBKDF2': $decoded = ASN1::decodeBER($kdf['parameters']->element); + if (!$decoded) { + throw new \RuntimeException('Unable to decode BER'); + } $kdf['parameters'] = ASN1::asn1map($decoded[0], Maps\PBKDF2params::MAP); } } diff --git a/phpseclib/Crypt/DH/Formats/Keys/PKCS1.php b/phpseclib/Crypt/DH/Formats/Keys/PKCS1.php index 41c62aac..96d19b0b 100644 --- a/phpseclib/Crypt/DH/Formats/Keys/PKCS1.php +++ b/phpseclib/Crypt/DH/Formats/Keys/PKCS1.php @@ -46,7 +46,7 @@ abstract class PKCS1 extends Progenitor $key = parent::load($key, $password); $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { + if (!$decoded) { throw new \RuntimeException('Unable to decode BER'); } diff --git a/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php b/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php index c8e7f5d5..8880aa6f 100644 --- a/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php +++ b/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php @@ -91,8 +91,7 @@ abstract class PKCS8 extends Progenitor $decoded = ASN1::decodeBER($key[$type]); switch (true) { - case empty($decoded): - case !is_array($decoded): + case !isset($decoded): case !isset($decoded[0]['content']): case !$decoded[0]['content'] instanceof BigInteger: throw new \RuntimeException('Unable to decode BER of parameters'); diff --git a/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php b/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php index 0f10ca2d..00832bbb 100644 --- a/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php +++ b/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php @@ -53,7 +53,7 @@ abstract class PKCS1 extends Progenitor $key = parent::load($key, $password); $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { + if (!$decoded) { throw new \RuntimeException('Unable to decode BER'); } diff --git a/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php b/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php index 15b23939..a62d4b1a 100644 --- a/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php +++ b/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php @@ -85,7 +85,7 @@ abstract class PKCS8 extends Progenitor } $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element); - if (empty($decoded)) { + if (!$decoded) { throw new \RuntimeException('Unable to decode BER of parameters'); } $components = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP); diff --git a/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php b/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php index d3167edd..dbd89141 100644 --- a/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php +++ b/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php @@ -68,7 +68,7 @@ abstract class PKCS1 extends Progenitor preg_match('#-*BEGIN EC PRIVATE KEY-*[^-]*-*END EC PRIVATE KEY-*#s', $key, $matches); $decoded = parent::load($matches[0], $password); $decoded = ASN1::decodeBER($decoded); - if (empty($decoded)) { + if (!$decoded) { throw new \RuntimeException('Unable to decode BER'); } @@ -84,7 +84,7 @@ abstract class PKCS1 extends Progenitor preg_match('#-*BEGIN EC PARAMETERS-*[^-]*-*END EC PARAMETERS-*#s', $key, $matches); $decoded = parent::load($matches[0], ''); $decoded = ASN1::decodeBER($decoded); - if (empty($decoded)) { + if (!$decoded) { throw new \RuntimeException('Unable to decode BER'); } $ecParams = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP); @@ -115,7 +115,7 @@ abstract class PKCS1 extends Progenitor $key = parent::load($key, $password); $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { + if (!$decoded) { throw new \RuntimeException('Unable to decode BER'); } diff --git a/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php b/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php index f56faf16..77ab1881 100644 --- a/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php +++ b/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php @@ -100,6 +100,9 @@ abstract class PKCS8 extends Progenitor } $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element); + if (!$decoded) { + throw new \RuntimeException('Unable to decode BER'); + } $params = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP); if (!$params) { throw new \RuntimeException('Unable to decode the parameters using Maps\ECParameters'); @@ -115,6 +118,9 @@ abstract class PKCS8 extends Progenitor } $decoded = ASN1::decodeBER($key['privateKey']); + if (!$decoded) { + throw new \RuntimeException('Unable to decode BER'); + } $key = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP); if (isset($key['parameters']) && $params != $key['parameters']) { throw new \RuntimeException('The PKCS8 parameter field does not match the private key parameter field'); diff --git a/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php b/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php index 0b8e767d..1bb347cf 100644 --- a/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php +++ b/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php @@ -60,7 +60,7 @@ abstract class PKCS1 extends Progenitor $key = parent::load($key, $password); $decoded = ASN1::decodeBER($key); - if (empty($decoded)) { + if (!$decoded) { throw new \RuntimeException('Unable to decode BER'); } diff --git a/phpseclib/File/ASN1.php b/phpseclib/File/ASN1.php index 1c01decf..20c0ae63 100644 --- a/phpseclib/File/ASN1.php +++ b/phpseclib/File/ASN1.php @@ -194,7 +194,7 @@ abstract class ASN1 * * @param Element|string $encoded */ - public static function decodeBER($encoded): array + public static function decodeBER($encoded): ?array { if ($encoded instanceof Element) { $encoded = $encoded->element; @@ -202,10 +202,12 @@ abstract class ASN1 self::$encoded = $encoded; - $decoded = [self::decode_ber($encoded)]; + $decoded = self::decode_ber($encoded); + if ($decoded === false) { + return null; + } - // encapsulate in an array for BC with the old decodeBER - return $decoded; + return [self::decode_ber($encoded)]; } /** @@ -512,12 +514,8 @@ abstract class ASN1 * @param array|bool $decoded * @return array|bool|Element|string|null */ - public static function asn1map($decoded, array $mapping, array $special = []) + public static function asn1map(array $decoded, array $mapping, array $special = []) { - if (!is_array($decoded)) { - return false; - } - if (isset($mapping['explicit']) && is_array($decoded['content'])) { $decoded = $decoded['content'][0]; } diff --git a/phpseclib/File/X509.php b/phpseclib/File/X509.php index 480c0299..c3b5f755 100644 --- a/phpseclib/File/X509.php +++ b/phpseclib/File/X509.php @@ -426,7 +426,7 @@ class X509 * * Returns an associative array describing the X.509 cert or a false if the cert failed to load * - * @param string|array $cert + * @param array|string $cert */ public function loadX509($cert, int $mode = self::FORMAT_AUTO_DETECT) { @@ -462,7 +462,7 @@ class X509 $decoded = ASN1::decodeBER($cert); - if (!empty($decoded)) { + if ($decoded) { $x509 = ASN1::asn1map($decoded[0], Maps\Certificate::MAP); } if (!isset($x509) || $x509 === false) { @@ -497,8 +497,7 @@ class X509 /** * Save X.509 certificate * - * @param int $format optional - * @return string + * @return string|false */ public function saveX509(array $cert, int $format = self::FORMAT_PEM) { @@ -566,8 +565,6 @@ class X509 /** * Map extension values from octet string to extension-specific internal * format. - * - * @param array $root (by reference) */ private function mapInExtensions(array &$root, string $path): void { @@ -585,6 +582,9 @@ class X509 [static::class, 'decodeNameConstraintIP'] : [static::class, 'decodeIP']; $decoded = ASN1::decodeBER($value); + if (!$decoded) { + continue; + } $mapped = ASN1::asn1map($decoded[0], $map, ['iPAddress' => $decoder]); $value = $mapped === false ? $decoded[0] : $mapped; @@ -599,6 +599,9 @@ class X509 $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier']; if ($map !== false) { $decoded = ASN1::decodeBER($subvalue); + if (!$decoded) { + continue; + } $mapped = ASN1::asn1map($decoded[0], $map); $subvalue = $mapped === false ? $decoded[0] : $mapped; } @@ -613,8 +616,6 @@ class X509 /** * Map extension values from extension-specific internal format to * octet string. - * - * @param array $root (by reference) */ private function mapOutExtensions(array &$root, string $path): void { @@ -712,6 +713,9 @@ class X509 $value = ASN1::encodeDER($values[$j], Maps\AttributeValue::MAP); $decoded = ASN1::decodeBER($value); if (!is_bool($map)) { + if (!$decoded) { + continue; + } $mapped = ASN1::asn1map($decoded[0], $map); if ($mapped !== false) { $values[$j] = $mapped; @@ -760,6 +764,9 @@ class X509 if (!is_bool($map)) { $temp = ASN1::encodeDER($values[$j], $map); $decoded = ASN1::decodeBER($temp); + if (!$decoded) { + continue; + } $values[$j] = ASN1::asn1map($decoded[0], Maps\AttributeValue::MAP); } } @@ -771,8 +778,6 @@ class X509 /** * Map DN values from ANY type to DN-specific internal * format. - * - * @param array $root (by reference) */ private function mapInDNs(array &$root, string $path): void { @@ -787,6 +792,9 @@ class X509 $map = $this->getMapping($type); if (!is_bool($map)) { $decoded = ASN1::decodeBER($value); + if (!$decoded) { + continue; + } $value = ASN1::asn1map($decoded[0], $map); } } @@ -1615,9 +1623,6 @@ class X509 /** * Get Distinguished Name properties - * - * @param array|null $dn optional - * @param bool $withType optional */ public function getDNProp(string $propName, array $dn = null, bool $withType = false) { @@ -1661,6 +1666,9 @@ class X509 $map = $this->getMapping($propName); if (!is_bool($map)) { $decoded = ASN1::decodeBER($v); + if (!$decoded) { + return false; + } $v = ASN1::asn1map($decoded[0], $map); } } @@ -2099,7 +2107,7 @@ class X509 $decoded = ASN1::decodeBER($csr); - if (empty($decoded)) { + if (!$decoded) { $this->currentCert = false; return false; } @@ -2136,8 +2144,7 @@ class X509 /** * Save CSR request * - * @param int $format optional - * @return string + * @return string|false */ public function saveCSR(array $csr, int $format = self::FORMAT_PEM) { @@ -2208,7 +2215,7 @@ class X509 $decoded = ASN1::decodeBER($spkac); - if (empty($decoded)) { + if (!$decoded) { $this->currentCert = false; return false; } @@ -2242,7 +2249,7 @@ class X509 * Save a SPKAC CSR request * * @param int $format optional - * @return string + * @return string|false */ public function saveSPKAC(array $spkac, int $format = self::FORMAT_PEM) { @@ -2301,7 +2308,7 @@ class X509 $decoded = ASN1::decodeBER($crl); - if (empty($decoded)) { + if (!$decoded) { $this->currentCert = false; return false; } @@ -2420,8 +2427,7 @@ class X509 * $subject can be either an existing X.509 cert (if you want to resign it), * a CSR or something with the DN and public key explicitly set. * - * @param \phpseclib3\File\X509 $issuer - * @param \phpseclib3\File\X509 $subject + * @return mixed */ public function sign(X509 $issuer, X509 $subject) { @@ -2725,8 +2731,7 @@ class X509 * * $issuer's private key needs to be loaded. * - * @param \phpseclib3\File\X509 $issuer - * @param \phpseclib3\File\X509 $crl + * @return mixed */ public function signCRL(X509 $issuer, X509 $crl) { @@ -2971,8 +2976,6 @@ class X509 * This is intended for use in conjunction with _subArrayUnchecked(), * implementing the checks included in _subArray() but without copying * a potentially large array by passing its reference by-value to is_array(). - * - * @return boolean */ private function isSubArrayValid(array $root, string $path): bool { @@ -3474,7 +3477,7 @@ class X509 case $key instanceof Element: // Assume the element is a bitstring-packed key. $decoded = ASN1::decodeBER($key->element); - if (empty($decoded)) { + if (!$decoded) { return false; } $raw = ASN1::asn1map($decoded[0], ['type' => ASN1::TYPE_BIT_STRING]); @@ -3533,6 +3536,9 @@ class X509 $publicKey = base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->toString($format))); $decoded = ASN1::decodeBER($publicKey); + if (!$decoded) { + return false; + } $mapped = ASN1::asn1map($decoded[0], Maps\SubjectPublicKeyInfo::MAP); if (!is_array($mapped)) { return false; diff --git a/phpseclib/System/SSH/Agent.php b/phpseclib/System/SSH/Agent.php index 615fff36..c3508290 100644 --- a/phpseclib/System/SSH/Agent.php +++ b/phpseclib/System/SSH/Agent.php @@ -38,6 +38,7 @@ use phpseclib3\Common\Functions\Strings; use phpseclib3\Crypt\PublicKeyLoader; use phpseclib3\Crypt\RSA; use phpseclib3\Exception\BadConfigurationException; +use phpseclib3\Net\SSH2; use phpseclib3\System\SSH\Agent\Identity; /** @@ -211,7 +212,7 @@ class Agent /** * Request agent forwarding of remote server */ - private function request_forwarding(\phpseclib3\Net\SSH2 $ssh): bool + private function request_forwarding(SSH2 $ssh) { if (!$ssh->requestAgentForwarding()) { return false; @@ -229,7 +230,7 @@ class Agent * open to give the SSH Agent an opportunity * to take further action. i.e. request agent forwarding */ - public function registerChannelOpen(\phpseclib3\Net\SSH2 $ssh): void + public function registerChannelOpen(SSH2 $ssh) { if ($this->forward_status == self::FORWARD_REQUEST) { $this->request_forwarding($ssh); diff --git a/tests/Unit/File/ASN1Test.php b/tests/Unit/File/ASN1Test.php index 8a9a016e..53dc504d 100644 --- a/tests/Unit/File/ASN1Test.php +++ b/tests/Unit/File/ASN1Test.php @@ -409,47 +409,47 @@ class ASN1Test extends PhpseclibTestCase { $em = pack('H*', '3080305c0609608648016503040201054f8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888804207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); $decoded = ASN1::decodeBER($em); - $this->assertFalse($decoded[0]); + $this->assertNull($decoded); $em = pack('H*', '3080307f0609608648016503040201057288888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888804207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca90000'); $decoded = ASN1::decodeBER($em); - $this->assertFalse($decoded[0]); + $this->assertNull($decoded); } public function testOIDGarbage(): void { $em = pack('H*', '3080305c065860864801650304020188888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888050004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); $decoded = ASN1::decodeBER($em); - $this->assertFalse($decoded[0]); + $this->assertNull($decoded); $em = pack('H*', '3080307f067d608648016503040201888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888804207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); $decoded = ASN1::decodeBER($em); - $this->assertFalse($decoded[0]); + $this->assertNull($decoded); } public function testConstructedMismatch(): void { $em = pack('H*', '1031300d0609608648016503040201050004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); $decoded = ASN1::decodeBER($em); - $this->assertFalse($decoded[0]); + $this->assertNull($decoded); $em = pack('H*', '3031100d0609608648016503040201050004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); $decoded = ASN1::decodeBER($em); - $this->assertFalse($decoded[0]); + $this->assertNull($decoded); $em = pack('H*', '3031300d2609608648016503040201050004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); $decoded = ASN1::decodeBER($em); - $this->assertFalse($decoded[0]); + $this->assertNull($decoded); $em = pack('H*', '3031300d06096086480165030402012d0004207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); $decoded = ASN1::decodeBER($em); - $this->assertFalse($decoded[0]); + $this->assertNull($decoded); } public function testBadTagSecondOctet(): void { $em = pack('H*', '3033300f1f808080060960864801650304020104207509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'); $decoded = ASN1::decodeBER($em); - $this->assertFalse($decoded[0]); + $this->assertNull($decoded); } } diff --git a/tests/Unit/Math/BigInteger/TestCase.php b/tests/Unit/Math/BigInteger/TestCase.php index 2a39ec4c..bf27adfe 100644 --- a/tests/Unit/Math/BigInteger/TestCase.php +++ b/tests/Unit/Math/BigInteger/TestCase.php @@ -384,9 +384,6 @@ abstract class TestCase extends PhpseclibTestCase ); } - /** - * @requires PHP 5.6 - */ public function testDebugInfo(): void { $num = $this->getInstance(50);