diff options
Diffstat (limited to 'vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php')
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php b/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php new file mode 100644 index 0000000..b947a95 --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php @@ -0,0 +1,131 @@ +<?php +/* + * This file is part of the PHPASN1 library. + * + * Copyright © Friedrich Große <friedrich.grosse@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\ASN1; + +use FG\ASN1\Exception\ParserException; + +/** + * Class ExplicitlyTaggedObject decorate an inner object with an additional tag that gives information about + * its context specific meaning. + * + * Explanation taken from A Layman's Guide to a Subset of ASN.1, BER, and DER: + * >>> An RSA Laboratories Technical Note + * >>> Burton S. Kaliski Jr. + * >>> Revised November 1, 1993 + * + * [...] + * Explicitly tagged types are derived from other types by adding an outer tag to the underlying type. + * In effect, explicitly tagged types are structured types consisting of one component, the underlying type. + * Explicit tagging is denoted by the ASN.1 keywords [class number] EXPLICIT (see Section 5.2). + * [...] + * + * @see http://luca.ntop.org/Teaching/Appunti/asn1.html + */ +class ExplicitlyTaggedObject extends ASNObject +{ + /** @var \FG\ASN1\ASNObject[] */ + private $decoratedObjects; + private $tag; + + /** + * @param int $tag + * @param \FG\ASN1\ASNObject $objects,... + */ + public function __construct($tag, /* HH_FIXME[4858]: variadic + strict */ ...$objects) + { + $this->tag = $tag; + $this->decoratedObjects = $objects; + } + + protected function calculateContentLength() + { + $length = 0; + foreach ($this->decoratedObjects as $object) { + $length += $object->getObjectLength(); + } + + return $length; + } + + protected function getEncodedValue() + { + $encoded = ''; + foreach ($this->decoratedObjects as $object) { + $encoded .= $object->getBinary(); + } + + return $encoded; + } + + public function getContent() + { + return $this->decoratedObjects; + } + + public function __toString() + { + switch ($length = count($this->decoratedObjects)) { + case 0: + return "Context specific empty object with tag [{$this->tag}]"; + case 1: + $decoratedType = Identifier::getShortName($this->decoratedObjects[0]->getType()); + return "Context specific $decoratedType with tag [{$this->tag}]"; + default: + return "$length context specific objects with tag [{$this->tag}]"; + } + } + + public function getType() + { + return ord($this->getIdentifier()); + } + + public function getIdentifier() + { + $identifier = Identifier::create(Identifier::CLASS_CONTEXT_SPECIFIC, true, $this->tag); + + return is_int($identifier) ? chr($identifier) : $identifier; + } + + public function getTag() + { + return $this->tag; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + $identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex); + $firstIdentifierOctet = ord($identifier); + assert(Identifier::isContextSpecificClass($firstIdentifierOctet), 'identifier octet should indicate context specific class'); + assert(Identifier::isConstructed($firstIdentifierOctet), 'identifier octet should indicate constructed object'); + $tag = Identifier::getTagNumber($identifier); + + $totalContentLength = self::parseContentLength($binaryData, $offsetIndex); + $remainingContentLength = $totalContentLength; + + $offsetIndexOfDecoratedObject = $offsetIndex; + $decoratedObjects = []; + + while ($remainingContentLength > 0) { + $nextObject = ASNObject::fromBinary($binaryData, $offsetIndex); + $remainingContentLength -= $nextObject->getObjectLength(); + $decoratedObjects[] = $nextObject; + } + + if ($remainingContentLength != 0) { + throw new ParserException("Context-Specific explicitly tagged object [$tag] starting at offset $offsetIndexOfDecoratedObject specifies a length of $totalContentLength octets but $remainingContentLength remain after parsing the content", $offsetIndexOfDecoratedObject); + } + + $parsedObject = new self($tag, ...$decoratedObjects); + $parsedObject->setContentLength($totalContentLength); + return $parsedObject; + } +} |