diff --git a/lib/ASN1/ASNObject.php b/lib/ASN1/ASNObject.php index 3b7f162..d338ad9 100644 --- a/lib/ASN1/ASNObject.php +++ b/lib/ASN1/ASNObject.php @@ -330,7 +330,14 @@ protected static function parseContentLength(&$binaryData, &$offsetIndex, $minim if (strlen($binaryData) <= $offsetIndex) { throw new ParserException('Can not parse content length (long form) from data: Offset index larger than input size', $offsetIndex); } - $contentLength = $contentLength->shiftLeft(8)->add(ord($binaryData[$offsetIndex++])); + $octet = ord($binaryData[$offsetIndex++]); + if ($i === 0 && $octet === 0) { + throw new ParserException('Content length cannot have leading zero bytes', $offsetIndex); + } + $contentLength = $contentLength->shiftLeft(8)->add($octet); + } + if ($nrOfLengthOctets < 2 && $contentLength->compare(0x80) < 0) { + throw new ParserException('Extended length used for short message', $offsetIndex); } if ($contentLength->compare(PHP_INT_MAX) > 0) { diff --git a/lib/ASN1/AbstractTime.php b/lib/ASN1/AbstractTime.php index 8e721ae..f67ef26 100644 --- a/lib/ASN1/AbstractTime.php +++ b/lib/ASN1/AbstractTime.php @@ -23,6 +23,9 @@ abstract class AbstractTime extends ASNObject public function __construct($dateTime = null, $dateTimeZone = 'UTC') { if ($dateTime == null || is_string($dateTime)) { + if (is_null($dateTime)) { + $dateTime = 'NOW'; + } $timeZone = new DateTimeZone($dateTimeZone); $dateTimeObject = new DateTime($dateTime, $timeZone); if ($dateTimeObject == false) { diff --git a/lib/ASN1/Universal/OctetString.php b/lib/ASN1/Universal/OctetString.php index 5d69ae7..e12e722 100644 --- a/lib/ASN1/Universal/OctetString.php +++ b/lib/ASN1/Universal/OctetString.php @@ -47,18 +47,25 @@ public function getType() protected function calculateContentLength() { + if (is_null($this->value)) { + return 0; + } return strlen($this->value) / 2; } protected function getEncodedValue() { $value = $this->value; + if (is_null($value)) { + return ''; + } + // This appears to expect hex strings but sometimes is populated by binary data $result = ''; - //Actual content + // Actual content while (strlen($value) >= 2) { - // get the hex value byte by byte from the string and and add it to binary result - $result .= chr(hexdec(substr($value, 0, 2))); + // get the hex value byte by byte from the string and add it to binary result + $result .= @chr(hexdec(substr($value, 0, 2))); $value = substr($value, 2); } @@ -67,6 +74,9 @@ protected function getEncodedValue() public function getContent() { + if (is_null($this->value)) { + return ''; + } return strtoupper($this->value); } diff --git a/tests/ASN1/ObjectTest.php b/tests/ASN1/ObjectTest.php index 9649948..114d3e2 100644 --- a/tests/ASN1/ObjectTest.php +++ b/tests/ASN1/ObjectTest.php @@ -321,6 +321,22 @@ public function testFromBinaryExceedsMaxInt() ASNObject::fromBinary($bin); } + public function testWithLeadingZeroes() + { + $this->expectException(ParserException::class); + $this->expectExceptionMessage("ASN.1 Parser Exception at offset 3: Content length cannot have leading zero bytes"); + $bin = hex2bin('30820066023100814cc9a70febda342d4ada87fc39426f403d5e89808428460c1eca60c897bfd6728da14673854673d7d297ea944a15e202310084f5ef11d22f22d0548af6a50dbf2f6a1bb9054585af5e600c49cf35b1e69b712754dd781c837355ddd41c752193a7cd'); + ASNObject::fromBinary($bin); + } + + public function testExtendedFormShortLength() + { + $this->expectException(ParserException::class); + $this->expectExceptionMessage('ASN.1 Parser Exception at offset 3: Extended length used for short message'); + $bin = hex2bin('30814502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db'); + ASNObject::fromBinary($bin); + } + /** * @depends testFromBinary */