PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / lib / packages / FG / ASN1 / ASNObject.php

ASNObject.php in Defender Security – Malware Scanner, Login Security & Firewall 6.3.0, at lib/packages/FG/ASN1/ASNObject.php

356 lines 13.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * This file is part of the PHPASN1 library.
4 *
5 * Copyright © Friedrich Große <[email protected]>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11 namespace WP_DEFENDER_VENDOR\FG\ASN1;
12
13 use WP_DEFENDER_VENDOR\FG\ASN1\Exception\ParserException;
14 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\BitString;
15 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\Boolean;
16 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\Enumerated;
17 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\GeneralizedTime;
18 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\Integer;
19 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\NullObject;
20 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\ObjectIdentifier;
21 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\RelativeObjectIdentifier;
22 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\OctetString;
23 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\Sequence;
24 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\Set;
25 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\UTCTime;
26 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\IA5String;
27 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\PrintableString;
28 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\NumericString;
29 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\UTF8String;
30 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\UniversalString;
31 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\CharacterString;
32 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\GeneralString;
33 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\VisibleString;
34 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\GraphicString;
35 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\BMPString;
36 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\T61String;
37 use WP_DEFENDER_VENDOR\FG\ASN1\Universal\ObjectDescriptor;
38 use WP_DEFENDER_VENDOR\FG\Utility\BigInteger;
39 use LogicException;
40
41 /**
42 * Class ASNObject is the base class for all concrete ASN.1 objects.
43 */
44 abstract class ASNObject implements Parsable
45 {
46 private $contentLength;
47 private $nrOfLengthOctets;
48
49 /**
50 * Must return the number of octets of the content part.
51 *
52 * @return int
53 */
54 abstract protected function calculateContentLength();
55
56 /**
57 * Encode the object using DER encoding.
58 *
59 * @see http://en.wikipedia.org/wiki/X.690#DER_encoding
60 *
61 * @return string the binary representation of an objects value
62 */
63 abstract protected function getEncodedValue();
64
65 /**
66 * Return the content of this object in a non encoded form.
67 * This can be used to print the value in human readable form.
68 *
69 * @return mixed
70 */
71 abstract public function getContent();
72
73 /**
74 * Return the object type octet.
75 * This should use the class constants of Identifier.
76 *
77 * @see Identifier
78 *
79 * @return int
80 */
81 abstract public function getType();
82
83 /**
84 * Returns all identifier octets. If an inheriting class models a tag with
85 * the long form identifier format, it MUST reimplement this method to
86 * return all octets of the identifier.
87 *
88 * @throws LogicException If the identifier format is long form
89 *
90 * @return string Identifier as a set of octets
91 */
92 public function getIdentifier()
93 {
94 $firstOctet = $this->getType();
95
96 if (Identifier::isLongForm($firstOctet)) {
97 throw new LogicException(sprintf('Identifier of %s uses the long form and must therefor override "ASNObject::getIdentifier()".', get_class($this)));
98 }
99
100 return chr($firstOctet);
101 }
102
103 /**
104 * Encode this object using DER encoding.
105 *
106 * @return string the full binary representation of the complete object
107 */
108 public function getBinary()
109 {
110 $result = $this->getIdentifier();
111 $result .= $this->createLengthPart();
112 $result .= $this->getEncodedValue();
113
114 return $result;
115 }
116
117 private function createLengthPart()
118 {
119 $contentLength = $this->getContentLength();
120 $nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength);
121
122 if ($nrOfLengthOctets == 1) {
123 return chr($contentLength);
124 } else {
125 // the first length octet determines the number subsequent length octets
126 $lengthOctets = chr(0x80 | ($nrOfLengthOctets - 1));
127 for ($shiftLength = 8 * ($nrOfLengthOctets - 2); $shiftLength >= 0; $shiftLength -= 8) {
128 $lengthOctets .= chr($contentLength >> $shiftLength);
129 }
130
131 return $lengthOctets;
132 }
133 }
134
135 protected function getNumberOfLengthOctets($contentLength = null)
136 {
137 if (!isset($this->nrOfLengthOctets)) {
138 if ($contentLength == null) {
139 $contentLength = $this->getContentLength();
140 }
141
142 $this->nrOfLengthOctets = 1;
143 if ($contentLength > 127) {
144 do { // long form
145 $this->nrOfLengthOctets++;
146 $contentLength = $contentLength >> 8;
147 } while ($contentLength > 0);
148 }
149 }
150
151 return $this->nrOfLengthOctets;
152 }
153
154 protected function getContentLength()
155 {
156 if (!isset($this->contentLength)) {
157 $this->contentLength = $this->calculateContentLength();
158 }
159
160 return $this->contentLength;
161 }
162
163 protected function setContentLength($newContentLength)
164 {
165 $this->contentLength = $newContentLength;
166 $this->getNumberOfLengthOctets($newContentLength);
167 }
168
169 /**
170 * Returns the length of the whole object (including the identifier and length octets).
171 */
172 public function getObjectLength()
173 {
174 $nrOfIdentifierOctets = strlen($this->getIdentifier());
175 $contentLength = $this->getContentLength();
176 $nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength);
177
178 return $nrOfIdentifierOctets + $nrOfLengthOctets + $contentLength;
179 }
180
181 public function __toString()
182 {
183 return $this->getContent();
184 }
185
186 /**
187 * Returns the name of the ASN.1 Type of this object.
188 *
189 * @see Identifier::getName()
190 */
191 public function getTypeName()
192 {
193 return Identifier::getName($this->getType());
194 }
195
196 /**
197 * @param string $binaryData
198 * @param int $offsetIndex
199 *
200 * @throws ParserException
201 *
202 * @return \WP_DEFENDER_VENDOR\FG\ASN1\ASNObject
203 */
204 public static function fromBinary(&$binaryData, &$offsetIndex = 0)
205 {
206 if (strlen($binaryData) <= $offsetIndex) {
207 throw new ParserException('Can not parse binary from data: Offset index larger than input size', $offsetIndex);
208 }
209
210 $identifierOctet = ord($binaryData[$offsetIndex]);
211 if (Identifier::isContextSpecificClass($identifierOctet) && Identifier::isConstructed($identifierOctet)) {
212 return ExplicitlyTaggedObject::fromBinary($binaryData, $offsetIndex);
213 }
214
215 switch ($identifierOctet) {
216 case Identifier::BITSTRING:
217 return BitString::fromBinary($binaryData, $offsetIndex);
218 case Identifier::BOOLEAN:
219 return Boolean::fromBinary($binaryData, $offsetIndex);
220 case Identifier::ENUMERATED:
221 return Enumerated::fromBinary($binaryData, $offsetIndex);
222 case Identifier::INTEGER:
223 return Integer::fromBinary($binaryData, $offsetIndex);
224 case Identifier::NULL:
225 return NullObject::fromBinary($binaryData, $offsetIndex);
226 case Identifier::OBJECT_IDENTIFIER:
227 return ObjectIdentifier::fromBinary($binaryData, $offsetIndex);
228 case Identifier::RELATIVE_OID:
229 return RelativeObjectIdentifier::fromBinary($binaryData, $offsetIndex);
230 case Identifier::OCTETSTRING:
231 return OctetString::fromBinary($binaryData, $offsetIndex);
232 case Identifier::SEQUENCE:
233 return Sequence::fromBinary($binaryData, $offsetIndex);
234 case Identifier::SET:
235 return Set::fromBinary($binaryData, $offsetIndex);
236 case Identifier::UTC_TIME:
237 return UTCTime::fromBinary($binaryData, $offsetIndex);
238 case Identifier::GENERALIZED_TIME:
239 return GeneralizedTime::fromBinary($binaryData, $offsetIndex);
240 case Identifier::IA5_STRING:
241 return IA5String::fromBinary($binaryData, $offsetIndex);
242 case Identifier::PRINTABLE_STRING:
243 return PrintableString::fromBinary($binaryData, $offsetIndex);
244 case Identifier::NUMERIC_STRING:
245 return NumericString::fromBinary($binaryData, $offsetIndex);
246 case Identifier::UTF8_STRING:
247 return UTF8String::fromBinary($binaryData, $offsetIndex);
248 case Identifier::UNIVERSAL_STRING:
249 return UniversalString::fromBinary($binaryData, $offsetIndex);
250 case Identifier::CHARACTER_STRING:
251 return CharacterString::fromBinary($binaryData, $offsetIndex);
252 case Identifier::GENERAL_STRING:
253 return GeneralString::fromBinary($binaryData, $offsetIndex);
254 case Identifier::VISIBLE_STRING:
255 return VisibleString::fromBinary($binaryData, $offsetIndex);
256 case Identifier::GRAPHIC_STRING:
257 return GraphicString::fromBinary($binaryData, $offsetIndex);
258 case Identifier::BMP_STRING:
259 return BMPString::fromBinary($binaryData, $offsetIndex);
260 case Identifier::T61_STRING:
261 return T61String::fromBinary($binaryData, $offsetIndex);
262 case Identifier::OBJECT_DESCRIPTOR:
263 return ObjectDescriptor::fromBinary($binaryData, $offsetIndex);
264 default:
265 // At this point the identifier may be >1 byte.
266 if (Identifier::isConstructed($identifierOctet)) {
267 return new UnknownConstructedObject($binaryData, $offsetIndex);
268 } else {
269 $identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
270 $lengthOfUnknownObject = self::parseContentLength($binaryData, $offsetIndex);
271 $offsetIndex += $lengthOfUnknownObject;
272
273 return new UnknownObject($identifier, $lengthOfUnknownObject);
274 }
275 }
276 }
277
278 protected static function parseIdentifier($identifierOctet, $expectedIdentifier, $offsetForExceptionHandling)
279 {
280 if (is_string($identifierOctet) || is_numeric($identifierOctet) == false) {
281 $identifierOctet = ord($identifierOctet);
282 }
283
284 if ($identifierOctet != $expectedIdentifier) {
285 $message = 'Can not create an '.Identifier::getName($expectedIdentifier).' from an '.Identifier::getName($identifierOctet);
286 throw new ParserException($message, $offsetForExceptionHandling);
287 }
288 }
289
290 protected static function parseBinaryIdentifier($binaryData, &$offsetIndex)
291 {
292 if (strlen($binaryData) <= $offsetIndex) {
293 throw new ParserException('Can not parse identifier from data: Offset index larger than input size', $offsetIndex);
294 }
295
296 $identifier = $binaryData[$offsetIndex++];
297
298 if (Identifier::isLongForm(ord($identifier)) == false) {
299 return $identifier;
300 }
301
302 while (true) {
303 if (strlen($binaryData) <= $offsetIndex) {
304 throw new ParserException('Can not parse identifier (long form) from data: Offset index larger than input size', $offsetIndex);
305 }
306 $nextOctet = $binaryData[$offsetIndex++];
307 $identifier .= $nextOctet;
308
309 if ((ord($nextOctet) & 0x80) === 0) {
310 // the most significant bit is 0 to we have reached the end of the identifier
311 break;
312 }
313 }
314
315 return $identifier;
316 }
317
318 protected static function parseContentLength(&$binaryData, &$offsetIndex, $minimumLength = 0)
319 {
320 if (strlen($binaryData) <= $offsetIndex) {
321 throw new ParserException('Can not parse content length from data: Offset index larger than input size', $offsetIndex);
322 }
323
324 $contentLength = ord($binaryData[$offsetIndex++]);
325 if (($contentLength & 0x80) != 0) {
326 // bit 8 is set -> this is the long form
327 $nrOfLengthOctets = $contentLength & 0x7F;
328 $contentLength = BigInteger::create(0x00);
329 for ($i = 0; $i < $nrOfLengthOctets; $i++) {
330 if (strlen($binaryData) <= $offsetIndex) {
331 throw new ParserException('Can not parse content length (long form) from data: Offset index larger than input size', $offsetIndex);
332 }
333 $contentLength = $contentLength->shiftLeft(8)->add(ord($binaryData[$offsetIndex++]));
334 }
335
336 if ($contentLength->compare(PHP_INT_MAX) > 0) {
337 throw new ParserException("Can not parse content length from data: length > maximum integer", $offsetIndex);
338 }
339
340 $contentLength = $contentLength->toInteger();
341 }
342
343 if ($contentLength < $minimumLength) {
344 throw new ParserException('A '.get_called_class()." should have a content length of at least {$minimumLength}. Extracted length was {$contentLength}", $offsetIndex);
345 }
346
347 $lenDataRemaining = strlen($binaryData) - $offsetIndex;
348
349 if ($lenDataRemaining < $contentLength) {
350 throw new ParserException("Content length {$contentLength} exceeds remaining data length {$lenDataRemaining}", $offsetIndex);
351 }
352
353 return $contentLength;
354 }
355 }
356