Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pyasn1/codec/ber/decoder.py: 15%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1083 statements  

1# 

2# This file is part of pyasn1 software. 

3# 

4# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com> 

5# License: https://pyasn1.readthedocs.io/en/latest/license.html 

6# 

7import io 

8import os 

9import sys 

10import warnings 

11 

12from pyasn1 import debug 

13from pyasn1 import error 

14from pyasn1.codec.ber import eoo 

15from pyasn1.codec.streaming import asSeekableStream 

16from pyasn1.codec.streaming import isEndOfStream 

17from pyasn1.codec.streaming import peekIntoStream 

18from pyasn1.codec.streaming import readFromStream 

19from pyasn1.compat import _MISSING 

20from pyasn1.error import PyAsn1Error 

21from pyasn1.type import base 

22from pyasn1.type import char 

23from pyasn1.type import tag 

24from pyasn1.type import tagmap 

25from pyasn1.type import univ 

26from pyasn1.type import useful 

27 

28__all__ = ['StreamingDecoder', 'Decoder', 'decode'] 

29 

30LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER) 

31 

32noValue = base.noValue 

33 

34SubstrateUnderrunError = error.SubstrateUnderrunError 

35 

36# Maximum number of continuation octets (high-bit set) allowed per OID arc. 

37# 20 octets allows up to 140-bit integers, supporting UUID-based OIDs 

38MAX_OID_ARC_CONTINUATION_OCTETS = 20 

39 

40# Maximum number of octets in a long-form tag ID (20 octets = up to 

41# 140-bit tag IDs, matching the OID arc limit) 

42MAX_TAG_OCTETS = 20 

43MAX_NESTING_DEPTH = 100 

44 

45# Maximum number of bytes in a BER length field (8 bytes = up to 2^64-1) 

46MAX_LENGTH_OCTETS = 8 

47 

48 

49class AbstractPayloadDecoder(object): 

50 protoComponent = None 

51 

52 def valueDecoder(self, substrate, asn1Spec, 

53 tagSet=None, length=None, state=None, 

54 decodeFun=None, substrateFun=None, 

55 **options): 

56 """Decode value with fixed byte length. 

57 

58 The decoder is allowed to consume as many bytes as necessary. 

59 """ 

60 raise error.PyAsn1Error('SingleItemDecoder not implemented for %s' % (tagSet,)) # TODO: Seems more like an NotImplementedError? 

61 

62 def indefLenValueDecoder(self, substrate, asn1Spec, 

63 tagSet=None, length=None, state=None, 

64 decodeFun=None, substrateFun=None, 

65 **options): 

66 """Decode value with undefined length. 

67 

68 The decoder is allowed to consume as many bytes as necessary. 

69 """ 

70 raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,)) # TODO: Seems more like an NotImplementedError? 

71 

72 @staticmethod 

73 def _passAsn1Object(asn1Object, options): 

74 if 'asn1Object' not in options: 

75 options['asn1Object'] = asn1Object 

76 

77 return options 

78 

79 

80class AbstractSimplePayloadDecoder(AbstractPayloadDecoder): 

81 @staticmethod 

82 def substrateCollector(asn1Object, substrate, length, options): 

83 for chunk in readFromStream(substrate, length, options): 

84 yield chunk 

85 

86 def _createComponent(self, asn1Spec, tagSet, value, **options): 

87 if options.get('native'): 

88 return value 

89 elif asn1Spec is None: 

90 return self.protoComponent.clone(value, tagSet=tagSet) 

91 elif value is noValue: 

92 return asn1Spec 

93 else: 

94 return asn1Spec.clone(value) 

95 

96 

97class RawPayloadDecoder(AbstractSimplePayloadDecoder): 

98 protoComponent = univ.Any('') 

99 

100 def valueDecoder(self, substrate, asn1Spec, 

101 tagSet=None, length=None, state=None, 

102 decodeFun=None, substrateFun=None, 

103 **options): 

104 if substrateFun: 

105 asn1Object = self._createComponent(asn1Spec, tagSet, '', **options) 

106 

107 for chunk in substrateFun(asn1Object, substrate, length, options): 

108 yield chunk 

109 

110 return 

111 

112 for value in decodeFun(substrate, asn1Spec, tagSet, length, **options): 

113 yield value 

114 

115 def indefLenValueDecoder(self, substrate, asn1Spec, 

116 tagSet=None, length=None, state=None, 

117 decodeFun=None, substrateFun=None, 

118 **options): 

119 if substrateFun: 

120 asn1Object = self._createComponent(asn1Spec, tagSet, '', **options) 

121 

122 for chunk in substrateFun(asn1Object, substrate, length, options): 

123 yield chunk 

124 

125 return 

126 

127 while True: 

128 for value in decodeFun( 

129 substrate, asn1Spec, tagSet, length, 

130 allowEoo=True, **options): 

131 

132 if value is eoo.endOfOctets: 

133 return 

134 

135 yield value 

136 

137 

138rawPayloadDecoder = RawPayloadDecoder() 

139 

140 

141class IntegerPayloadDecoder(AbstractSimplePayloadDecoder): 

142 protoComponent = univ.Integer(0) 

143 

144 def valueDecoder(self, substrate, asn1Spec, 

145 tagSet=None, length=None, state=None, 

146 decodeFun=None, substrateFun=None, 

147 **options): 

148 

149 if tagSet[0].tagFormat != tag.tagFormatSimple: 

150 raise error.PyAsn1Error('Simple tag format expected') 

151 

152 for chunk in readFromStream(substrate, length, options): 

153 if isinstance(chunk, SubstrateUnderrunError): 

154 yield chunk 

155 

156 if chunk: 

157 value = int.from_bytes(bytes(chunk), 'big', signed=True) 

158 

159 else: 

160 value = 0 

161 

162 yield self._createComponent(asn1Spec, tagSet, value, **options) 

163 

164 

165class BooleanPayloadDecoder(IntegerPayloadDecoder): 

166 protoComponent = univ.Boolean(0) 

167 

168 def _createComponent(self, asn1Spec, tagSet, value, **options): 

169 return IntegerPayloadDecoder._createComponent( 

170 self, asn1Spec, tagSet, value and 1 or 0, **options) 

171 

172 

173class BitStringPayloadDecoder(AbstractSimplePayloadDecoder): 

174 protoComponent = univ.BitString(()) 

175 supportConstructedForm = True 

176 

177 def valueDecoder(self, substrate, asn1Spec, 

178 tagSet=None, length=None, state=None, 

179 decodeFun=None, substrateFun=None, 

180 **options): 

181 

182 if substrateFun: 

183 asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options) 

184 

185 for chunk in substrateFun(asn1Object, substrate, length, options): 

186 yield chunk 

187 

188 return 

189 

190 if not length: 

191 raise error.PyAsn1Error('Empty BIT STRING substrate') 

192 

193 for chunk in isEndOfStream(substrate): 

194 if isinstance(chunk, SubstrateUnderrunError): 

195 yield chunk 

196 

197 if chunk: 

198 raise error.PyAsn1Error('Empty BIT STRING substrate') 

199 

200 if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check? 

201 

202 for trailingBits in readFromStream(substrate, 1, options): 

203 if isinstance(trailingBits, SubstrateUnderrunError): 

204 yield trailingBits 

205 

206 trailingBits = ord(trailingBits) 

207 if trailingBits > 7: 

208 raise error.PyAsn1Error( 

209 'Trailing bits overflow %s' % trailingBits 

210 ) 

211 

212 for chunk in readFromStream(substrate, length - 1, options): 

213 if isinstance(chunk, SubstrateUnderrunError): 

214 yield chunk 

215 

216 value = self.protoComponent.fromOctetString( 

217 chunk, internalFormat=True, padding=trailingBits) 

218 

219 yield self._createComponent(asn1Spec, tagSet, value, **options) 

220 

221 return 

222 

223 if not self.supportConstructedForm: 

224 raise error.PyAsn1Error('Constructed encoding form prohibited ' 

225 'at %s' % self.__class__.__name__) 

226 

227 if LOG: 

228 LOG('assembling constructed serialization') 

229 

230 # All inner fragments are of the same type, treat them as octet string 

231 substrateFun = self.substrateCollector 

232 

233 bitString = self.protoComponent.fromOctetString(b'', internalFormat=True) 

234 

235 current_position = substrate.tell() 

236 

237 while substrate.tell() - current_position < length: 

238 for component in decodeFun( 

239 substrate, self.protoComponent, substrateFun=substrateFun, 

240 **options): 

241 if isinstance(component, SubstrateUnderrunError): 

242 yield component 

243 

244 trailingBits = component[0] 

245 if trailingBits > 7: 

246 raise error.PyAsn1Error( 

247 'Trailing bits overflow %s' % trailingBits 

248 ) 

249 

250 bitString = self.protoComponent.fromOctetString( 

251 component[1:], internalFormat=True, 

252 prepend=bitString, padding=trailingBits 

253 ) 

254 

255 yield self._createComponent(asn1Spec, tagSet, bitString, **options) 

256 

257 def indefLenValueDecoder(self, substrate, asn1Spec, 

258 tagSet=None, length=None, state=None, 

259 decodeFun=None, substrateFun=None, 

260 **options): 

261 

262 if substrateFun: 

263 asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options) 

264 

265 for chunk in substrateFun(asn1Object, substrate, length, options): 

266 yield chunk 

267 

268 return 

269 

270 # All inner fragments are of the same type, treat them as octet string 

271 substrateFun = self.substrateCollector 

272 

273 bitString = self.protoComponent.fromOctetString(b'', internalFormat=True) 

274 

275 while True: # loop over fragments 

276 

277 for component in decodeFun( 

278 substrate, self.protoComponent, substrateFun=substrateFun, 

279 allowEoo=True, **options): 

280 

281 if component is eoo.endOfOctets: 

282 break 

283 

284 if isinstance(component, SubstrateUnderrunError): 

285 yield component 

286 

287 if component is eoo.endOfOctets: 

288 break 

289 

290 trailingBits = component[0] 

291 if trailingBits > 7: 

292 raise error.PyAsn1Error( 

293 'Trailing bits overflow %s' % trailingBits 

294 ) 

295 

296 bitString = self.protoComponent.fromOctetString( 

297 component[1:], internalFormat=True, 

298 prepend=bitString, padding=trailingBits 

299 ) 

300 

301 yield self._createComponent(asn1Spec, tagSet, bitString, **options) 

302 

303 

304class OctetStringPayloadDecoder(AbstractSimplePayloadDecoder): 

305 protoComponent = univ.OctetString('') 

306 supportConstructedForm = True 

307 

308 def valueDecoder(self, substrate, asn1Spec, 

309 tagSet=None, length=None, state=None, 

310 decodeFun=None, substrateFun=None, 

311 **options): 

312 if substrateFun: 

313 asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options) 

314 

315 for chunk in substrateFun(asn1Object, substrate, length, options): 

316 yield chunk 

317 

318 return 

319 

320 if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check? 

321 for chunk in readFromStream(substrate, length, options): 

322 if isinstance(chunk, SubstrateUnderrunError): 

323 yield chunk 

324 

325 yield self._createComponent(asn1Spec, tagSet, chunk, **options) 

326 

327 return 

328 

329 if not self.supportConstructedForm: 

330 raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__) 

331 

332 if LOG: 

333 LOG('assembling constructed serialization') 

334 

335 # All inner fragments are of the same type, treat them as octet string 

336 substrateFun = self.substrateCollector 

337 

338 header = b'' 

339 

340 original_position = substrate.tell() 

341 # head = popSubstream(substrate, length) 

342 while substrate.tell() - original_position < length: 

343 for component in decodeFun( 

344 substrate, self.protoComponent, substrateFun=substrateFun, 

345 **options): 

346 if isinstance(component, SubstrateUnderrunError): 

347 yield component 

348 

349 header += component 

350 

351 yield self._createComponent(asn1Spec, tagSet, header, **options) 

352 

353 def indefLenValueDecoder(self, substrate, asn1Spec, 

354 tagSet=None, length=None, state=None, 

355 decodeFun=None, substrateFun=None, 

356 **options): 

357 if substrateFun and substrateFun is not self.substrateCollector: 

358 asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options) 

359 

360 for chunk in substrateFun(asn1Object, substrate, length, options): 

361 yield chunk 

362 

363 return 

364 

365 # All inner fragments are of the same type, treat them as octet string 

366 substrateFun = self.substrateCollector 

367 

368 header = b'' 

369 

370 while True: # loop over fragments 

371 

372 for component in decodeFun( 

373 substrate, self.protoComponent, substrateFun=substrateFun, 

374 allowEoo=True, **options): 

375 

376 if isinstance(component, SubstrateUnderrunError): 

377 yield component 

378 

379 if component is eoo.endOfOctets: 

380 break 

381 

382 if component is eoo.endOfOctets: 

383 break 

384 

385 header += component 

386 

387 yield self._createComponent(asn1Spec, tagSet, header, **options) 

388 

389 

390class NullPayloadDecoder(AbstractSimplePayloadDecoder): 

391 protoComponent = univ.Null('') 

392 

393 def valueDecoder(self, substrate, asn1Spec, 

394 tagSet=None, length=None, state=None, 

395 decodeFun=None, substrateFun=None, 

396 **options): 

397 

398 if tagSet[0].tagFormat != tag.tagFormatSimple: 

399 raise error.PyAsn1Error('Simple tag format expected') 

400 

401 for chunk in readFromStream(substrate, length, options): 

402 if isinstance(chunk, SubstrateUnderrunError): 

403 yield chunk 

404 

405 component = self._createComponent(asn1Spec, tagSet, '', **options) 

406 

407 if chunk: 

408 raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length) 

409 

410 yield component 

411 

412 

413class ObjectIdentifierPayloadDecoder(AbstractSimplePayloadDecoder): 

414 protoComponent = univ.ObjectIdentifier(()) 

415 

416 def valueDecoder(self, substrate, asn1Spec, 

417 tagSet=None, length=None, state=None, 

418 decodeFun=None, substrateFun=None, 

419 **options): 

420 if tagSet[0].tagFormat != tag.tagFormatSimple: 

421 raise error.PyAsn1Error('Simple tag format expected') 

422 

423 for chunk in readFromStream(substrate, length, options): 

424 if isinstance(chunk, SubstrateUnderrunError): 

425 yield chunk 

426 

427 if not chunk: 

428 raise error.PyAsn1Error('Empty substrate') 

429 

430 oid = [] 

431 index = 0 

432 substrateLen = len(chunk) 

433 while index < substrateLen: 

434 subId = chunk[index] 

435 index += 1 

436 if subId < 128: 

437 oid.append(subId) 

438 elif subId > 128: 

439 # Construct subid from a number of octets 

440 nextSubId = subId 

441 subId = 0 

442 continuationOctetCount = 0 

443 while nextSubId >= 128: 

444 continuationOctetCount += 1 

445 if continuationOctetCount > MAX_OID_ARC_CONTINUATION_OCTETS: 

446 raise error.PyAsn1Error( 

447 'OID arc exceeds maximum continuation octets limit (%d) ' 

448 'at position %d' % (MAX_OID_ARC_CONTINUATION_OCTETS, index) 

449 ) 

450 subId = (subId << 7) + (nextSubId & 0x7F) 

451 if index >= substrateLen: 

452 raise error.SubstrateUnderrunError( 

453 'Short substrate for sub-OID past %s' % (tuple(oid),) 

454 ) 

455 nextSubId = chunk[index] 

456 index += 1 

457 oid.append((subId << 7) + nextSubId) 

458 elif subId == 128: 

459 # ASN.1 spec forbids leading zeros (0x80) in OID 

460 # encoding, tolerating it opens a vulnerability. See 

461 # https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf 

462 # page 7 

463 raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding') 

464 

465 # Decode two leading arcs 

466 if 0 <= oid[0] <= 39: 

467 oid.insert(0, 0) 

468 elif 40 <= oid[0] <= 79: 

469 oid[0] -= 40 

470 oid.insert(0, 1) 

471 elif oid[0] >= 80: 

472 oid[0] -= 80 

473 oid.insert(0, 2) 

474 else: 

475 raise error.PyAsn1Error('Malformed first OID octet: %s' % chunk[0]) 

476 

477 yield self._createComponent(asn1Spec, tagSet, tuple(oid), **options) 

478 

479 

480class RelativeOIDPayloadDecoder(AbstractSimplePayloadDecoder): 

481 protoComponent = univ.RelativeOID(()) 

482 

483 def valueDecoder(self, substrate, asn1Spec, 

484 tagSet=None, length=None, state=None, 

485 decodeFun=None, substrateFun=None, 

486 **options): 

487 if tagSet[0].tagFormat != tag.tagFormatSimple: 

488 raise error.PyAsn1Error('Simple tag format expected') 

489 

490 for chunk in readFromStream(substrate, length, options): 

491 if isinstance(chunk, SubstrateUnderrunError): 

492 yield chunk 

493 

494 if not chunk: 

495 raise error.PyAsn1Error('Empty substrate') 

496 

497 reloid = [] 

498 index = 0 

499 substrateLen = len(chunk) 

500 while index < substrateLen: 

501 subId = chunk[index] 

502 index += 1 

503 if subId < 128: 

504 reloid.append(subId) 

505 elif subId > 128: 

506 # Construct subid from a number of octets 

507 nextSubId = subId 

508 subId = 0 

509 continuationOctetCount = 0 

510 while nextSubId >= 128: 

511 continuationOctetCount += 1 

512 if continuationOctetCount > MAX_OID_ARC_CONTINUATION_OCTETS: 

513 raise error.PyAsn1Error( 

514 'RELATIVE-OID arc exceeds maximum continuation octets limit (%d) ' 

515 'at position %d' % (MAX_OID_ARC_CONTINUATION_OCTETS, index) 

516 ) 

517 subId = (subId << 7) + (nextSubId & 0x7F) 

518 if index >= substrateLen: 

519 raise error.SubstrateUnderrunError( 

520 'Short substrate for sub-OID past %s' % (tuple(reloid),) 

521 ) 

522 nextSubId = chunk[index] 

523 index += 1 

524 reloid.append((subId << 7) + nextSubId) 

525 elif subId == 128: 

526 # ASN.1 spec forbids leading zeros (0x80) in OID 

527 # encoding, tolerating it opens a vulnerability. See 

528 # https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf 

529 # page 7 

530 raise error.PyAsn1Error('Invalid octet 0x80 in RELATIVE-OID encoding') 

531 

532 yield self._createComponent(asn1Spec, tagSet, tuple(reloid), **options) 

533 

534 

535class RealPayloadDecoder(AbstractSimplePayloadDecoder): 

536 protoComponent = univ.Real() 

537 

538 def valueDecoder(self, substrate, asn1Spec, 

539 tagSet=None, length=None, state=None, 

540 decodeFun=None, substrateFun=None, 

541 **options): 

542 if tagSet[0].tagFormat != tag.tagFormatSimple: 

543 raise error.PyAsn1Error('Simple tag format expected') 

544 

545 for chunk in readFromStream(substrate, length, options): 

546 if isinstance(chunk, SubstrateUnderrunError): 

547 yield chunk 

548 

549 if not chunk: 

550 yield self._createComponent(asn1Spec, tagSet, 0.0, **options) 

551 return 

552 

553 fo = chunk[0] 

554 chunk = chunk[1:] 

555 if fo & 0x80: # binary encoding 

556 if not chunk: 

557 raise error.PyAsn1Error("Incomplete floating-point value") 

558 

559 if LOG: 

560 LOG('decoding binary encoded REAL') 

561 

562 n = (fo & 0x03) + 1 

563 

564 if n == 4: 

565 n = chunk[0] 

566 chunk = chunk[1:] 

567 

568 eo, chunk = chunk[:n], chunk[n:] 

569 

570 if not eo or not chunk: 

571 raise error.PyAsn1Error('Real exponent screwed') 

572 

573 e = eo[0] & 0x80 and -1 or 0 

574 

575 while eo: # exponent 

576 e <<= 8 

577 e |= eo[0] 

578 eo = eo[1:] 

579 

580 b = fo >> 4 & 0x03 # base bits 

581 

582 if b > 2: 

583 raise error.PyAsn1Error('Illegal Real base') 

584 

585 if b == 1: # encbase = 8 

586 e *= 3 

587 

588 elif b == 2: # encbase = 16 

589 e *= 4 

590 p = 0 

591 

592 while chunk: # value 

593 p <<= 8 

594 p |= chunk[0] 

595 chunk = chunk[1:] 

596 

597 if fo & 0x40: # sign bit 

598 p = -p 

599 

600 sf = fo >> 2 & 0x03 # scale bits 

601 p *= 2 ** sf 

602 value = (p, 2, e) 

603 

604 elif fo & 0x40: # infinite value 

605 if LOG: 

606 LOG('decoding infinite REAL') 

607 

608 value = fo & 0x01 and '-inf' or 'inf' 

609 

610 elif fo & 0xc0 == 0: # character encoding 

611 if not chunk: 

612 raise error.PyAsn1Error("Incomplete floating-point value") 

613 

614 if LOG: 

615 LOG('decoding character encoded REAL') 

616 

617 try: 

618 if fo & 0x3 == 0x1: # NR1 

619 value = (int(chunk), 10, 0) 

620 

621 elif fo & 0x3 == 0x2: # NR2 

622 value = float(chunk) 

623 

624 elif fo & 0x3 == 0x3: # NR3 

625 value = float(chunk) 

626 

627 else: 

628 raise error.SubstrateUnderrunError( 

629 'Unknown NR (tag %s)' % fo 

630 ) 

631 

632 except ValueError: 

633 raise error.SubstrateUnderrunError( 

634 'Bad character Real syntax' 

635 ) 

636 

637 else: 

638 raise error.SubstrateUnderrunError( 

639 'Unknown encoding (tag %s)' % fo 

640 ) 

641 

642 yield self._createComponent(asn1Spec, tagSet, value, **options) 

643 

644 

645class AbstractConstructedPayloadDecoder(AbstractPayloadDecoder): 

646 protoComponent = None 

647 

648 

649class ConstructedPayloadDecoderBase(AbstractConstructedPayloadDecoder): 

650 protoRecordComponent = None 

651 protoSequenceComponent = None 

652 

653 def _getComponentTagMap(self, asn1Object, idx): 

654 raise NotImplementedError 

655 

656 def _getComponentPositionByType(self, asn1Object, tagSet, idx): 

657 raise NotImplementedError 

658 

659 def _decodeComponentsSchemaless( 

660 self, substrate, tagSet=None, decodeFun=None, 

661 length=None, **options): 

662 

663 asn1Object = None 

664 

665 components = [] 

666 componentTypes = set() 

667 

668 original_position = substrate.tell() 

669 

670 while length == -1 or substrate.tell() < original_position + length: 

671 for component in decodeFun(substrate, **options): 

672 if isinstance(component, SubstrateUnderrunError): 

673 yield component 

674 

675 if length == -1 and component is eoo.endOfOctets: 

676 break 

677 

678 components.append(component) 

679 componentTypes.add(component.tagSet) 

680 

681 # Now we have to guess is it SEQUENCE/SET or SEQUENCE OF/SET OF 

682 # The heuristics is: 

683 # * 1+ components of different types -> likely SEQUENCE/SET 

684 # * otherwise -> likely SEQUENCE OF/SET OF 

685 if len(componentTypes) > 1: 

686 protoComponent = self.protoRecordComponent 

687 

688 else: 

689 protoComponent = self.protoSequenceComponent 

690 

691 asn1Object = protoComponent.clone( 

692 # construct tagSet from base tag from prototype ASN.1 object 

693 # and additional tags recovered from the substrate 

694 tagSet=tag.TagSet(protoComponent.tagSet.baseTag, *tagSet.superTags) 

695 ) 

696 

697 if LOG: 

698 LOG('guessed %r container type (pass `asn1Spec` to guide the ' 

699 'decoder)' % asn1Object) 

700 

701 for idx, component in enumerate(components): 

702 asn1Object.setComponentByPosition( 

703 idx, component, 

704 verifyConstraints=False, 

705 matchTags=False, matchConstraints=False 

706 ) 

707 

708 yield asn1Object 

709 

710 def valueDecoder(self, substrate, asn1Spec, 

711 tagSet=None, length=None, state=None, 

712 decodeFun=None, substrateFun=None, 

713 **options): 

714 if tagSet[0].tagFormat != tag.tagFormatConstructed: 

715 raise error.PyAsn1Error('Constructed tag format expected') 

716 

717 original_position = substrate.tell() 

718 

719 if substrateFun: 

720 if asn1Spec is not None: 

721 asn1Object = asn1Spec.clone() 

722 

723 elif self.protoComponent is not None: 

724 asn1Object = self.protoComponent.clone(tagSet=tagSet) 

725 

726 else: 

727 asn1Object = self.protoRecordComponent, self.protoSequenceComponent 

728 

729 for chunk in substrateFun(asn1Object, substrate, length, options): 

730 yield chunk 

731 

732 return 

733 

734 if asn1Spec is None: 

735 for asn1Object in self._decodeComponentsSchemaless( 

736 substrate, tagSet=tagSet, decodeFun=decodeFun, 

737 length=length, **options): 

738 if isinstance(asn1Object, SubstrateUnderrunError): 

739 yield asn1Object 

740 

741 if substrate.tell() < original_position + length: 

742 if LOG: 

743 for trailing in readFromStream(substrate, context=options): 

744 if isinstance(trailing, SubstrateUnderrunError): 

745 yield trailing 

746 

747 LOG('Unused trailing %d octets encountered: %s' % ( 

748 len(trailing), debug.hexdump(trailing))) 

749 

750 yield asn1Object 

751 

752 return 

753 

754 asn1Object = asn1Spec.clone() 

755 asn1Object.clear() 

756 

757 options = self._passAsn1Object(asn1Object, options) 

758 

759 if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId): 

760 

761 namedTypes = asn1Spec.componentType 

762 

763 isSetType = asn1Spec.typeId == univ.Set.typeId 

764 isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault 

765 

766 if LOG: 

767 LOG('decoding %sdeterministic %s type %r chosen by type ID' % ( 

768 not isDeterministic and 'non-' or '', isSetType and 'SET' or '', 

769 asn1Spec)) 

770 

771 seenIndices = set() 

772 idx = 0 

773 while substrate.tell() - original_position < length: 

774 if not namedTypes: 

775 componentType = None 

776 

777 elif isSetType: 

778 componentType = namedTypes.tagMapUnique 

779 

780 else: 

781 try: 

782 if isDeterministic: 

783 componentType = namedTypes[idx].asn1Object 

784 

785 elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: 

786 componentType = namedTypes.getTagMapNearPosition(idx) 

787 

788 else: 

789 componentType = namedTypes[idx].asn1Object 

790 

791 except IndexError: 

792 raise error.PyAsn1Error( 

793 'Excessive components decoded at %r' % (asn1Spec,) 

794 ) 

795 

796 for component in decodeFun(substrate, componentType, **options): 

797 if isinstance(component, SubstrateUnderrunError): 

798 yield component 

799 

800 if not isDeterministic and namedTypes: 

801 if isSetType: 

802 idx = namedTypes.getPositionByType(component.effectiveTagSet) 

803 

804 elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: 

805 idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx) 

806 

807 asn1Object.setComponentByPosition( 

808 idx, component, 

809 verifyConstraints=False, 

810 matchTags=False, matchConstraints=False 

811 ) 

812 

813 seenIndices.add(idx) 

814 idx += 1 

815 

816 if LOG: 

817 LOG('seen component indices %s' % seenIndices) 

818 

819 if namedTypes: 

820 if not namedTypes.requiredComponents.issubset(seenIndices): 

821 raise error.PyAsn1Error( 

822 'ASN.1 object %s has uninitialized ' 

823 'components' % asn1Object.__class__.__name__) 

824 

825 if namedTypes.hasOpenTypes: 

826 

827 openTypes = options.get('openTypes', {}) 

828 

829 if LOG: 

830 LOG('user-specified open types map:') 

831 

832 for k, v in openTypes.items(): 

833 LOG('%s -> %r' % (k, v)) 

834 

835 if openTypes or options.get('decodeOpenTypes', False): 

836 

837 for idx, namedType in enumerate(namedTypes.namedTypes): 

838 if not namedType.openType: 

839 continue 

840 

841 if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue: 

842 continue 

843 

844 governingValue = asn1Object.getComponentByName( 

845 namedType.openType.name 

846 ) 

847 

848 try: 

849 openType = openTypes[governingValue] 

850 

851 except KeyError: 

852 

853 if LOG: 

854 LOG('default open types map of component ' 

855 '"%s.%s" governed by component "%s.%s"' 

856 ':' % (asn1Object.__class__.__name__, 

857 namedType.name, 

858 asn1Object.__class__.__name__, 

859 namedType.openType.name)) 

860 

861 for k, v in namedType.openType.items(): 

862 LOG('%s -> %r' % (k, v)) 

863 

864 try: 

865 openType = namedType.openType[governingValue] 

866 

867 except KeyError: 

868 if LOG: 

869 LOG('failed to resolve open type by governing ' 

870 'value %r' % (governingValue,)) 

871 continue 

872 

873 if LOG: 

874 LOG('resolved open type %r by governing ' 

875 'value %r' % (openType, governingValue)) 

876 

877 containerValue = asn1Object.getComponentByPosition(idx) 

878 

879 if containerValue.typeId in ( 

880 univ.SetOf.typeId, univ.SequenceOf.typeId): 

881 

882 for pos, containerElement in enumerate( 

883 containerValue): 

884 

885 stream = asSeekableStream(containerValue[pos].asOctets()) 

886 

887 for component in decodeFun(stream, asn1Spec=openType, **options): 

888 if isinstance(component, SubstrateUnderrunError): 

889 yield component 

890 

891 containerValue[pos] = component 

892 

893 else: 

894 stream = asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets()) 

895 

896 for component in decodeFun(stream, asn1Spec=openType, **options): 

897 if isinstance(component, SubstrateUnderrunError): 

898 yield component 

899 

900 asn1Object.setComponentByPosition(idx, component) 

901 

902 else: 

903 inconsistency = asn1Object.isInconsistent 

904 if inconsistency: 

905 raise error.PyAsn1Error( 

906 f"ASN.1 object {asn1Object.__class__.__name__} is inconsistent") 

907 

908 else: 

909 componentType = asn1Spec.componentType 

910 

911 if LOG: 

912 LOG('decoding type %r chosen by given `asn1Spec`' % componentType) 

913 

914 idx = 0 

915 

916 while substrate.tell() - original_position < length: 

917 for component in decodeFun(substrate, componentType, **options): 

918 if isinstance(component, SubstrateUnderrunError): 

919 yield component 

920 

921 asn1Object.setComponentByPosition( 

922 idx, component, 

923 verifyConstraints=False, 

924 matchTags=False, matchConstraints=False 

925 ) 

926 

927 idx += 1 

928 

929 yield asn1Object 

930 

931 def indefLenValueDecoder(self, substrate, asn1Spec, 

932 tagSet=None, length=None, state=None, 

933 decodeFun=None, substrateFun=None, 

934 **options): 

935 if tagSet[0].tagFormat != tag.tagFormatConstructed: 

936 raise error.PyAsn1Error('Constructed tag format expected') 

937 

938 if substrateFun is not None: 

939 if asn1Spec is not None: 

940 asn1Object = asn1Spec.clone() 

941 

942 elif self.protoComponent is not None: 

943 asn1Object = self.protoComponent.clone(tagSet=tagSet) 

944 

945 else: 

946 asn1Object = self.protoRecordComponent, self.protoSequenceComponent 

947 

948 for chunk in substrateFun(asn1Object, substrate, length, options): 

949 yield chunk 

950 

951 return 

952 

953 if asn1Spec is None: 

954 for asn1Object in self._decodeComponentsSchemaless( 

955 substrate, tagSet=tagSet, decodeFun=decodeFun, 

956 length=length, **dict(options, allowEoo=True)): 

957 if isinstance(asn1Object, SubstrateUnderrunError): 

958 yield asn1Object 

959 

960 yield asn1Object 

961 

962 return 

963 

964 asn1Object = asn1Spec.clone() 

965 asn1Object.clear() 

966 

967 options = self._passAsn1Object(asn1Object, options) 

968 

969 if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId): 

970 

971 namedTypes = asn1Object.componentType 

972 

973 isSetType = asn1Object.typeId == univ.Set.typeId 

974 isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault 

975 

976 if LOG: 

977 LOG('decoding %sdeterministic %s type %r chosen by type ID' % ( 

978 not isDeterministic and 'non-' or '', isSetType and 'SET' or '', 

979 asn1Spec)) 

980 

981 seenIndices = set() 

982 

983 idx = 0 

984 

985 while True: # loop over components 

986 if len(namedTypes) <= idx: 

987 asn1Spec = None 

988 

989 elif isSetType: 

990 asn1Spec = namedTypes.tagMapUnique 

991 

992 else: 

993 try: 

994 if isDeterministic: 

995 asn1Spec = namedTypes[idx].asn1Object 

996 

997 elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: 

998 asn1Spec = namedTypes.getTagMapNearPosition(idx) 

999 

1000 else: 

1001 asn1Spec = namedTypes[idx].asn1Object 

1002 

1003 except IndexError: 

1004 raise error.PyAsn1Error( 

1005 'Excessive components decoded at %r' % (asn1Object,) 

1006 ) 

1007 

1008 for component in decodeFun(substrate, asn1Spec, allowEoo=True, **options): 

1009 

1010 if isinstance(component, SubstrateUnderrunError): 

1011 yield component 

1012 

1013 if component is eoo.endOfOctets: 

1014 break 

1015 

1016 if component is eoo.endOfOctets: 

1017 break 

1018 

1019 if not isDeterministic and namedTypes: 

1020 if isSetType: 

1021 idx = namedTypes.getPositionByType(component.effectiveTagSet) 

1022 

1023 elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: 

1024 idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx) 

1025 

1026 asn1Object.setComponentByPosition( 

1027 idx, component, 

1028 verifyConstraints=False, 

1029 matchTags=False, matchConstraints=False 

1030 ) 

1031 

1032 seenIndices.add(idx) 

1033 idx += 1 

1034 

1035 if LOG: 

1036 LOG('seen component indices %s' % seenIndices) 

1037 

1038 if namedTypes: 

1039 if not namedTypes.requiredComponents.issubset(seenIndices): 

1040 raise error.PyAsn1Error( 

1041 'ASN.1 object %s has uninitialized ' 

1042 'components' % asn1Object.__class__.__name__) 

1043 

1044 if namedTypes.hasOpenTypes: 

1045 

1046 openTypes = options.get('openTypes', {}) 

1047 

1048 if LOG: 

1049 LOG('user-specified open types map:') 

1050 

1051 for k, v in openTypes.items(): 

1052 LOG('%s -> %r' % (k, v)) 

1053 

1054 if openTypes or options.get('decodeOpenTypes', False): 

1055 

1056 for idx, namedType in enumerate(namedTypes.namedTypes): 

1057 if not namedType.openType: 

1058 continue 

1059 

1060 if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue: 

1061 continue 

1062 

1063 governingValue = asn1Object.getComponentByName( 

1064 namedType.openType.name 

1065 ) 

1066 

1067 try: 

1068 openType = openTypes[governingValue] 

1069 

1070 except KeyError: 

1071 

1072 if LOG: 

1073 LOG('default open types map of component ' 

1074 '"%s.%s" governed by component "%s.%s"' 

1075 ':' % (asn1Object.__class__.__name__, 

1076 namedType.name, 

1077 asn1Object.__class__.__name__, 

1078 namedType.openType.name)) 

1079 

1080 for k, v in namedType.openType.items(): 

1081 LOG('%s -> %r' % (k, v)) 

1082 

1083 try: 

1084 openType = namedType.openType[governingValue] 

1085 

1086 except KeyError: 

1087 if LOG: 

1088 LOG('failed to resolve open type by governing ' 

1089 'value %r' % (governingValue,)) 

1090 continue 

1091 

1092 if LOG: 

1093 LOG('resolved open type %r by governing ' 

1094 'value %r' % (openType, governingValue)) 

1095 

1096 containerValue = asn1Object.getComponentByPosition(idx) 

1097 

1098 if containerValue.typeId in ( 

1099 univ.SetOf.typeId, univ.SequenceOf.typeId): 

1100 

1101 for pos, containerElement in enumerate( 

1102 containerValue): 

1103 

1104 stream = asSeekableStream(containerValue[pos].asOctets()) 

1105 

1106 for component in decodeFun(stream, asn1Spec=openType, 

1107 **dict(options, allowEoo=True)): 

1108 if isinstance(component, SubstrateUnderrunError): 

1109 yield component 

1110 

1111 if component is eoo.endOfOctets: 

1112 break 

1113 

1114 containerValue[pos] = component 

1115 

1116 else: 

1117 stream = asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets()) 

1118 for component in decodeFun(stream, asn1Spec=openType, 

1119 **dict(options, allowEoo=True)): 

1120 if isinstance(component, SubstrateUnderrunError): 

1121 yield component 

1122 

1123 if component is eoo.endOfOctets: 

1124 break 

1125 

1126 asn1Object.setComponentByPosition(idx, component) 

1127 

1128 else: 

1129 inconsistency = asn1Object.isInconsistent 

1130 if inconsistency: 

1131 raise error.PyAsn1Error( 

1132 f"ASN.1 object {asn1Object.__class__.__name__} is inconsistent") 

1133 

1134 else: 

1135 componentType = asn1Spec.componentType 

1136 

1137 if LOG: 

1138 LOG('decoding type %r chosen by given `asn1Spec`' % componentType) 

1139 

1140 idx = 0 

1141 

1142 while True: 

1143 

1144 for component in decodeFun( 

1145 substrate, componentType, allowEoo=True, **options): 

1146 

1147 if isinstance(component, SubstrateUnderrunError): 

1148 yield component 

1149 

1150 if component is eoo.endOfOctets: 

1151 break 

1152 

1153 if component is eoo.endOfOctets: 

1154 break 

1155 

1156 asn1Object.setComponentByPosition( 

1157 idx, component, 

1158 verifyConstraints=False, 

1159 matchTags=False, matchConstraints=False 

1160 ) 

1161 

1162 idx += 1 

1163 

1164 yield asn1Object 

1165 

1166 

1167class SequenceOrSequenceOfPayloadDecoder(ConstructedPayloadDecoderBase): 

1168 protoRecordComponent = univ.Sequence() 

1169 protoSequenceComponent = univ.SequenceOf() 

1170 

1171 

1172class SequencePayloadDecoder(SequenceOrSequenceOfPayloadDecoder): 

1173 protoComponent = univ.Sequence() 

1174 

1175 

1176class SequenceOfPayloadDecoder(SequenceOrSequenceOfPayloadDecoder): 

1177 protoComponent = univ.SequenceOf() 

1178 

1179 

1180class SetOrSetOfPayloadDecoder(ConstructedPayloadDecoderBase): 

1181 protoRecordComponent = univ.Set() 

1182 protoSequenceComponent = univ.SetOf() 

1183 

1184 

1185class SetPayloadDecoder(SetOrSetOfPayloadDecoder): 

1186 protoComponent = univ.Set() 

1187 

1188 

1189class SetOfPayloadDecoder(SetOrSetOfPayloadDecoder): 

1190 protoComponent = univ.SetOf() 

1191 

1192 

1193class ChoicePayloadDecoder(ConstructedPayloadDecoderBase): 

1194 protoComponent = univ.Choice() 

1195 

1196 def valueDecoder(self, substrate, asn1Spec, 

1197 tagSet=None, length=None, state=None, 

1198 decodeFun=None, substrateFun=None, 

1199 **options): 

1200 if asn1Spec is None: 

1201 asn1Object = self.protoComponent.clone(tagSet=tagSet) 

1202 

1203 else: 

1204 asn1Object = asn1Spec.clone() 

1205 

1206 if substrateFun: 

1207 for chunk in substrateFun(asn1Object, substrate, length, options): 

1208 yield chunk 

1209 

1210 return 

1211 

1212 options = self._passAsn1Object(asn1Object, options) 

1213 

1214 if asn1Object.tagSet == tagSet: 

1215 if LOG: 

1216 LOG('decoding %s as explicitly tagged CHOICE' % (tagSet,)) 

1217 

1218 for component in decodeFun( 

1219 substrate, asn1Object.componentTagMap, **options): 

1220 if isinstance(component, SubstrateUnderrunError): 

1221 yield component 

1222 

1223 else: 

1224 if LOG: 

1225 LOG('decoding %s as untagged CHOICE' % (tagSet,)) 

1226 

1227 for component in decodeFun( 

1228 substrate, asn1Object.componentTagMap, tagSet, length, 

1229 state, **options): 

1230 if isinstance(component, SubstrateUnderrunError): 

1231 yield component 

1232 

1233 effectiveTagSet = component.effectiveTagSet 

1234 

1235 if LOG: 

1236 LOG('decoded component %s, effective tag set %s' % (component, effectiveTagSet)) 

1237 

1238 asn1Object.setComponentByType( 

1239 effectiveTagSet, component, 

1240 verifyConstraints=False, 

1241 matchTags=False, matchConstraints=False, 

1242 innerFlag=False 

1243 ) 

1244 

1245 yield asn1Object 

1246 

1247 def indefLenValueDecoder(self, substrate, asn1Spec, 

1248 tagSet=None, length=None, state=None, 

1249 decodeFun=None, substrateFun=None, 

1250 **options): 

1251 if asn1Spec is None: 

1252 asn1Object = self.protoComponent.clone(tagSet=tagSet) 

1253 

1254 else: 

1255 asn1Object = asn1Spec.clone() 

1256 

1257 if substrateFun: 

1258 for chunk in substrateFun(asn1Object, substrate, length, options): 

1259 yield chunk 

1260 

1261 return 

1262 

1263 options = self._passAsn1Object(asn1Object, options) 

1264 

1265 isTagged = asn1Object.tagSet == tagSet 

1266 

1267 if LOG: 

1268 LOG('decoding %s as %stagged CHOICE' % ( 

1269 tagSet, isTagged and 'explicitly ' or 'un')) 

1270 

1271 while True: 

1272 

1273 if isTagged: 

1274 iterator = decodeFun( 

1275 substrate, asn1Object.componentType.tagMapUnique, 

1276 **dict(options, allowEoo=True)) 

1277 

1278 else: 

1279 iterator = decodeFun( 

1280 substrate, asn1Object.componentType.tagMapUnique, 

1281 tagSet, length, state, **dict(options, allowEoo=True)) 

1282 

1283 for component in iterator: 

1284 

1285 if isinstance(component, SubstrateUnderrunError): 

1286 yield component 

1287 

1288 if component is eoo.endOfOctets: 

1289 break 

1290 

1291 effectiveTagSet = component.effectiveTagSet 

1292 

1293 if LOG: 

1294 LOG('decoded component %s, effective tag set ' 

1295 '%s' % (component, effectiveTagSet)) 

1296 

1297 asn1Object.setComponentByType( 

1298 effectiveTagSet, component, 

1299 verifyConstraints=False, 

1300 matchTags=False, matchConstraints=False, 

1301 innerFlag=False 

1302 ) 

1303 

1304 if not isTagged: 

1305 break 

1306 

1307 if not isTagged or component is eoo.endOfOctets: 

1308 break 

1309 

1310 yield asn1Object 

1311 

1312 

1313class AnyPayloadDecoder(AbstractSimplePayloadDecoder): 

1314 protoComponent = univ.Any() 

1315 

1316 def valueDecoder(self, substrate, asn1Spec, 

1317 tagSet=None, length=None, state=None, 

1318 decodeFun=None, substrateFun=None, 

1319 **options): 

1320 if asn1Spec is None: 

1321 isUntagged = True 

1322 

1323 elif asn1Spec.__class__ is tagmap.TagMap: 

1324 isUntagged = tagSet not in asn1Spec.tagMap 

1325 

1326 else: 

1327 isUntagged = tagSet != asn1Spec.tagSet 

1328 

1329 if isUntagged: 

1330 fullPosition = substrate.markedPosition 

1331 currentPosition = substrate.tell() 

1332 

1333 substrate.seek(fullPosition, os.SEEK_SET) 

1334 length += currentPosition - fullPosition 

1335 

1336 if LOG: 

1337 for chunk in peekIntoStream(substrate, length): 

1338 if isinstance(chunk, SubstrateUnderrunError): 

1339 yield chunk 

1340 LOG('decoding as untagged ANY, substrate ' 

1341 '%s' % debug.hexdump(chunk)) 

1342 

1343 if substrateFun: 

1344 for chunk in substrateFun( 

1345 self._createComponent(asn1Spec, tagSet, noValue, **options), 

1346 substrate, length, options): 

1347 yield chunk 

1348 

1349 return 

1350 

1351 for chunk in readFromStream(substrate, length, options): 

1352 if isinstance(chunk, SubstrateUnderrunError): 

1353 yield chunk 

1354 

1355 yield self._createComponent(asn1Spec, tagSet, chunk, **options) 

1356 

1357 def indefLenValueDecoder(self, substrate, asn1Spec, 

1358 tagSet=None, length=None, state=None, 

1359 decodeFun=None, substrateFun=None, 

1360 **options): 

1361 if asn1Spec is None: 

1362 isTagged = False 

1363 

1364 elif asn1Spec.__class__ is tagmap.TagMap: 

1365 isTagged = tagSet in asn1Spec.tagMap 

1366 

1367 else: 

1368 isTagged = tagSet == asn1Spec.tagSet 

1369 

1370 if isTagged: 

1371 # tagged Any type -- consume header substrate 

1372 chunk = b'' 

1373 

1374 if LOG: 

1375 LOG('decoding as tagged ANY') 

1376 

1377 else: 

1378 # TODO: Seems not to be tested 

1379 fullPosition = substrate.markedPosition 

1380 currentPosition = substrate.tell() 

1381 

1382 substrate.seek(fullPosition, os.SEEK_SET) 

1383 for chunk in readFromStream(substrate, currentPosition - fullPosition, options): 

1384 if isinstance(chunk, SubstrateUnderrunError): 

1385 yield chunk 

1386 

1387 if LOG: 

1388 LOG('decoding as untagged ANY, header substrate %s' % debug.hexdump(chunk)) 

1389 

1390 # Any components do not inherit initial tag 

1391 asn1Spec = self.protoComponent 

1392 

1393 if substrateFun and substrateFun is not self.substrateCollector: 

1394 asn1Object = self._createComponent( 

1395 asn1Spec, tagSet, noValue, **options) 

1396 

1397 for chunk in substrateFun( 

1398 asn1Object, chunk + substrate, length + len(chunk), options): 

1399 yield chunk 

1400 

1401 return 

1402 

1403 if LOG: 

1404 LOG('assembling constructed serialization') 

1405 

1406 # All inner fragments are of the same type, treat them as octet string 

1407 substrateFun = self.substrateCollector 

1408 

1409 while True: # loop over fragments 

1410 

1411 for component in decodeFun( 

1412 substrate, asn1Spec, substrateFun=substrateFun, 

1413 allowEoo=True, **options): 

1414 

1415 if isinstance(component, SubstrateUnderrunError): 

1416 yield component 

1417 

1418 if component is eoo.endOfOctets: 

1419 break 

1420 

1421 if component is eoo.endOfOctets: 

1422 break 

1423 

1424 chunk += component 

1425 

1426 if substrateFun: 

1427 yield chunk # TODO: Weird 

1428 

1429 else: 

1430 yield self._createComponent(asn1Spec, tagSet, chunk, **options) 

1431 

1432 

1433# character string types 

1434class UTF8StringPayloadDecoder(OctetStringPayloadDecoder): 

1435 protoComponent = char.UTF8String() 

1436 

1437 

1438class NumericStringPayloadDecoder(OctetStringPayloadDecoder): 

1439 protoComponent = char.NumericString() 

1440 

1441 

1442class PrintableStringPayloadDecoder(OctetStringPayloadDecoder): 

1443 protoComponent = char.PrintableString() 

1444 

1445 

1446class TeletexStringPayloadDecoder(OctetStringPayloadDecoder): 

1447 protoComponent = char.TeletexString() 

1448 

1449 

1450class VideotexStringPayloadDecoder(OctetStringPayloadDecoder): 

1451 protoComponent = char.VideotexString() 

1452 

1453 

1454class IA5StringPayloadDecoder(OctetStringPayloadDecoder): 

1455 protoComponent = char.IA5String() 

1456 

1457 

1458class GraphicStringPayloadDecoder(OctetStringPayloadDecoder): 

1459 protoComponent = char.GraphicString() 

1460 

1461 

1462class VisibleStringPayloadDecoder(OctetStringPayloadDecoder): 

1463 protoComponent = char.VisibleString() 

1464 

1465 

1466class GeneralStringPayloadDecoder(OctetStringPayloadDecoder): 

1467 protoComponent = char.GeneralString() 

1468 

1469 

1470class UniversalStringPayloadDecoder(OctetStringPayloadDecoder): 

1471 protoComponent = char.UniversalString() 

1472 

1473 

1474class BMPStringPayloadDecoder(OctetStringPayloadDecoder): 

1475 protoComponent = char.BMPString() 

1476 

1477 

1478# "useful" types 

1479class ObjectDescriptorPayloadDecoder(OctetStringPayloadDecoder): 

1480 protoComponent = useful.ObjectDescriptor() 

1481 

1482 

1483class GeneralizedTimePayloadDecoder(OctetStringPayloadDecoder): 

1484 protoComponent = useful.GeneralizedTime() 

1485 

1486 

1487class UTCTimePayloadDecoder(OctetStringPayloadDecoder): 

1488 protoComponent = useful.UTCTime() 

1489 

1490 

1491TAG_MAP = { 

1492 univ.Integer.tagSet: IntegerPayloadDecoder(), 

1493 univ.Boolean.tagSet: BooleanPayloadDecoder(), 

1494 univ.BitString.tagSet: BitStringPayloadDecoder(), 

1495 univ.OctetString.tagSet: OctetStringPayloadDecoder(), 

1496 univ.Null.tagSet: NullPayloadDecoder(), 

1497 univ.ObjectIdentifier.tagSet: ObjectIdentifierPayloadDecoder(), 

1498 univ.RelativeOID.tagSet: RelativeOIDPayloadDecoder(), 

1499 univ.Enumerated.tagSet: IntegerPayloadDecoder(), 

1500 univ.Real.tagSet: RealPayloadDecoder(), 

1501 univ.Sequence.tagSet: SequenceOrSequenceOfPayloadDecoder(), # conflicts with SequenceOf 

1502 univ.Set.tagSet: SetOrSetOfPayloadDecoder(), # conflicts with SetOf 

1503 univ.Choice.tagSet: ChoicePayloadDecoder(), # conflicts with Any 

1504 # character string types 

1505 char.UTF8String.tagSet: UTF8StringPayloadDecoder(), 

1506 char.NumericString.tagSet: NumericStringPayloadDecoder(), 

1507 char.PrintableString.tagSet: PrintableStringPayloadDecoder(), 

1508 char.TeletexString.tagSet: TeletexStringPayloadDecoder(), 

1509 char.VideotexString.tagSet: VideotexStringPayloadDecoder(), 

1510 char.IA5String.tagSet: IA5StringPayloadDecoder(), 

1511 char.GraphicString.tagSet: GraphicStringPayloadDecoder(), 

1512 char.VisibleString.tagSet: VisibleStringPayloadDecoder(), 

1513 char.GeneralString.tagSet: GeneralStringPayloadDecoder(), 

1514 char.UniversalString.tagSet: UniversalStringPayloadDecoder(), 

1515 char.BMPString.tagSet: BMPStringPayloadDecoder(), 

1516 # useful types 

1517 useful.ObjectDescriptor.tagSet: ObjectDescriptorPayloadDecoder(), 

1518 useful.GeneralizedTime.tagSet: GeneralizedTimePayloadDecoder(), 

1519 useful.UTCTime.tagSet: UTCTimePayloadDecoder() 

1520} 

1521 

1522# Type-to-codec map for ambiguous ASN.1 types 

1523TYPE_MAP = { 

1524 univ.Set.typeId: SetPayloadDecoder(), 

1525 univ.SetOf.typeId: SetOfPayloadDecoder(), 

1526 univ.Sequence.typeId: SequencePayloadDecoder(), 

1527 univ.SequenceOf.typeId: SequenceOfPayloadDecoder(), 

1528 univ.Choice.typeId: ChoicePayloadDecoder(), 

1529 univ.Any.typeId: AnyPayloadDecoder() 

1530} 

1531 

1532# Put in non-ambiguous types for faster codec lookup 

1533for typeDecoder in TAG_MAP.values(): 

1534 if typeDecoder.protoComponent is not None: 

1535 typeId = typeDecoder.protoComponent.__class__.typeId 

1536 if typeId is not None and typeId not in TYPE_MAP: 

1537 TYPE_MAP[typeId] = typeDecoder 

1538 

1539 

1540(stDecodeTag, 

1541 stDecodeLength, 

1542 stGetValueDecoder, 

1543 stGetValueDecoderByAsn1Spec, 

1544 stGetValueDecoderByTag, 

1545 stTryAsExplicitTag, 

1546 stDecodeValue, 

1547 stDumpRawValue, 

1548 stErrorCondition, 

1549 stStop) = [x for x in range(10)] 

1550 

1551 

1552EOO_SENTINEL = bytes((0, 0)) 

1553 

1554 

1555class SingleItemDecoder(object): 

1556 defaultErrorState = stErrorCondition 

1557 #defaultErrorState = stDumpRawValue 

1558 defaultRawDecoder = AnyPayloadDecoder() 

1559 

1560 supportIndefLength = True 

1561 

1562 TAG_MAP = TAG_MAP 

1563 TYPE_MAP = TYPE_MAP 

1564 

1565 def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored): 

1566 self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP 

1567 self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP 

1568 

1569 # Tag & TagSet objects caches 

1570 self._tagCache = {} 

1571 self._tagSetCache = {} 

1572 

1573 def __call__(self, substrate, asn1Spec=None, 

1574 tagSet=None, length=None, state=stDecodeTag, 

1575 decodeFun=None, substrateFun=None, 

1576 **options): 

1577 

1578 _nestingLevel = options.get('_nestingLevel', 0) 

1579 

1580 if _nestingLevel > MAX_NESTING_DEPTH: 

1581 raise error.PyAsn1Error( 

1582 'ASN.1 structure nesting depth exceeds limit (%d)' % MAX_NESTING_DEPTH 

1583 ) 

1584 

1585 options['_nestingLevel'] = _nestingLevel + 1 

1586 

1587 allowEoo = options.pop('allowEoo', False) 

1588 

1589 if LOG: 

1590 LOG('decoder called at scope %s with state %d, working with up ' 

1591 'to %s octets of substrate: ' 

1592 '%s' % (debug.scope, state, length, substrate)) 

1593 

1594 # Look for end-of-octets sentinel 

1595 if allowEoo and self.supportIndefLength: 

1596 

1597 for eoo_candidate in readFromStream(substrate, 2, options): 

1598 if isinstance(eoo_candidate, SubstrateUnderrunError): 

1599 yield eoo_candidate 

1600 

1601 if eoo_candidate == EOO_SENTINEL: 

1602 if LOG: 

1603 LOG('end-of-octets sentinel found') 

1604 yield eoo.endOfOctets 

1605 return 

1606 

1607 else: 

1608 substrate.seek(-2, os.SEEK_CUR) 

1609 

1610 tagMap = self._tagMap 

1611 typeMap = self._typeMap 

1612 tagCache = self._tagCache 

1613 tagSetCache = self._tagSetCache 

1614 

1615 value = noValue 

1616 

1617 substrate.markedPosition = substrate.tell() 

1618 

1619 while state is not stStop: 

1620 

1621 if state is stDecodeTag: 

1622 # Decode tag 

1623 isShortTag = True 

1624 

1625 for firstByte in readFromStream(substrate, 1, options): 

1626 if isinstance(firstByte, SubstrateUnderrunError): 

1627 yield firstByte 

1628 

1629 firstOctet = ord(firstByte) 

1630 

1631 try: 

1632 lastTag = tagCache[firstOctet] 

1633 

1634 except KeyError: 

1635 integerTag = firstOctet 

1636 tagClass = integerTag & 0xC0 

1637 tagFormat = integerTag & 0x20 

1638 tagId = integerTag & 0x1F 

1639 

1640 if tagId == 0x1F: 

1641 isShortTag = False 

1642 tagOctetCount = 0 

1643 tagId = 0 

1644 

1645 while True: 

1646 for integerByte in readFromStream(substrate, 1, options): 

1647 if isinstance(integerByte, SubstrateUnderrunError): 

1648 yield integerByte 

1649 

1650 if not integerByte: 

1651 raise error.SubstrateUnderrunError( 

1652 'Short octet stream on long tag decoding' 

1653 ) 

1654 

1655 integerTag = ord(integerByte) 

1656 tagOctetCount += 1 

1657 if tagOctetCount > MAX_TAG_OCTETS: 

1658 raise error.PyAsn1Error( 

1659 'Tag ID octet count exceeds limit (%d)' % ( 

1660 MAX_TAG_OCTETS,) 

1661 ) 

1662 tagId <<= 7 

1663 tagId |= (integerTag & 0x7F) 

1664 

1665 if not integerTag & 0x80: 

1666 break 

1667 

1668 lastTag = tag.Tag( 

1669 tagClass=tagClass, tagFormat=tagFormat, tagId=tagId 

1670 ) 

1671 

1672 if isShortTag: 

1673 # cache short tags 

1674 tagCache[firstOctet] = lastTag 

1675 

1676 if tagSet is None: 

1677 if isShortTag: 

1678 try: 

1679 tagSet = tagSetCache[firstOctet] 

1680 

1681 except KeyError: 

1682 # base tag not recovered 

1683 tagSet = tag.TagSet((), lastTag) 

1684 tagSetCache[firstOctet] = tagSet 

1685 else: 

1686 tagSet = tag.TagSet((), lastTag) 

1687 

1688 else: 

1689 tagSet = lastTag + tagSet 

1690 

1691 state = stDecodeLength 

1692 

1693 if LOG: 

1694 LOG('tag decoded into %s, decoding length' % tagSet) 

1695 

1696 if state is stDecodeLength: 

1697 # Decode length 

1698 for firstOctet in readFromStream(substrate, 1, options): 

1699 if isinstance(firstOctet, SubstrateUnderrunError): 

1700 yield firstOctet 

1701 

1702 firstOctet = ord(firstOctet) 

1703 

1704 if firstOctet < 128: 

1705 length = firstOctet 

1706 

1707 elif firstOctet > 128: 

1708 size = firstOctet & 0x7F 

1709 

1710 if size > MAX_LENGTH_OCTETS: 

1711 raise error.PyAsn1Error( 

1712 'BER length field size %d exceeds limit (%d)' % ( 

1713 size, MAX_LENGTH_OCTETS) 

1714 ) 

1715 

1716 # encoded in size bytes 

1717 for encodedLength in readFromStream(substrate, size, options): 

1718 if isinstance(encodedLength, SubstrateUnderrunError): 

1719 yield encodedLength 

1720 encodedLength = list(encodedLength) 

1721 if len(encodedLength) != size: 

1722 raise error.SubstrateUnderrunError( 

1723 '%s<%s at %s' % (size, len(encodedLength), tagSet) 

1724 ) 

1725 

1726 length = 0 

1727 for lengthOctet in encodedLength: 

1728 length <<= 8 

1729 length |= lengthOctet 

1730 size += 1 

1731 

1732 else: # 128 means indefinite 

1733 length = -1 

1734 

1735 if length == -1 and not self.supportIndefLength: 

1736 raise error.PyAsn1Error('Indefinite length encoding not supported by this codec') 

1737 

1738 state = stGetValueDecoder 

1739 

1740 if LOG: 

1741 LOG('value length decoded into %d' % length) 

1742 

1743 if state is stGetValueDecoder: 

1744 if asn1Spec is None: 

1745 state = stGetValueDecoderByTag 

1746 

1747 else: 

1748 state = stGetValueDecoderByAsn1Spec 

1749 # 

1750 # There're two ways of creating subtypes in ASN.1 what influences 

1751 # decoder operation. These methods are: 

1752 # 1) Either base types used in or no IMPLICIT tagging has been 

1753 # applied on subtyping. 

1754 # 2) Subtype syntax drops base type information (by means of 

1755 # IMPLICIT tagging. 

1756 # The first case allows for complete tag recovery from substrate 

1757 # while the second one requires original ASN.1 type spec for 

1758 # decoding. 

1759 # 

1760 # In either case a set of tags (tagSet) is coming from substrate 

1761 # in an incremental, tag-by-tag fashion (this is the case of 

1762 # EXPLICIT tag which is most basic). Outermost tag comes first 

1763 # from the wire. 

1764 # 

1765 if state is stGetValueDecoderByTag: 

1766 try: 

1767 concreteDecoder = tagMap[tagSet] 

1768 

1769 except KeyError: 

1770 concreteDecoder = None 

1771 

1772 if concreteDecoder: 

1773 state = stDecodeValue 

1774 

1775 else: 

1776 try: 

1777 concreteDecoder = tagMap[tagSet[:1]] 

1778 

1779 except KeyError: 

1780 concreteDecoder = None 

1781 

1782 if concreteDecoder: 

1783 state = stDecodeValue 

1784 else: 

1785 state = stTryAsExplicitTag 

1786 

1787 if LOG: 

1788 LOG('codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as explicit tag')) 

1789 debug.scope.push(concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__) 

1790 

1791 if state is stGetValueDecoderByAsn1Spec: 

1792 

1793 if asn1Spec.__class__ is tagmap.TagMap: 

1794 try: 

1795 chosenSpec = asn1Spec[tagSet] 

1796 

1797 except KeyError: 

1798 chosenSpec = None 

1799 

1800 if LOG: 

1801 LOG('candidate ASN.1 spec is a map of:') 

1802 

1803 for firstOctet, v in asn1Spec.presentTypes.items(): 

1804 LOG(' %s -> %s' % (firstOctet, v.__class__.__name__)) 

1805 

1806 if asn1Spec.skipTypes: 

1807 LOG('but neither of: ') 

1808 for firstOctet, v in asn1Spec.skipTypes.items(): 

1809 LOG(' %s -> %s' % (firstOctet, v.__class__.__name__)) 

1810 LOG('new candidate ASN.1 spec is %s, chosen by %s' % (chosenSpec is None and '<none>' or chosenSpec.prettyPrintType(), tagSet)) 

1811 

1812 elif tagSet == asn1Spec.tagSet or tagSet in asn1Spec.tagMap: 

1813 chosenSpec = asn1Spec 

1814 if LOG: 

1815 LOG('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__) 

1816 

1817 else: 

1818 chosenSpec = None 

1819 

1820 if chosenSpec is not None: 

1821 try: 

1822 # ambiguous type or just faster codec lookup 

1823 concreteDecoder = typeMap[chosenSpec.typeId] 

1824 

1825 if LOG: 

1826 LOG('value decoder chosen for an ambiguous type by type ID %s' % (chosenSpec.typeId,)) 

1827 

1828 except KeyError: 

1829 # use base type for codec lookup to recover untagged types 

1830 baseTagSet = tag.TagSet(chosenSpec.tagSet.baseTag, chosenSpec.tagSet.baseTag) 

1831 try: 

1832 # base type or tagged subtype 

1833 concreteDecoder = tagMap[baseTagSet] 

1834 

1835 if LOG: 

1836 LOG('value decoder chosen by base %s' % (baseTagSet,)) 

1837 

1838 except KeyError: 

1839 concreteDecoder = None 

1840 

1841 if concreteDecoder: 

1842 asn1Spec = chosenSpec 

1843 state = stDecodeValue 

1844 

1845 else: 

1846 state = stTryAsExplicitTag 

1847 

1848 else: 

1849 concreteDecoder = None 

1850 state = stTryAsExplicitTag 

1851 

1852 if LOG: 

1853 LOG('codec %s chosen by ASN.1 spec, decoding %s' % (state is stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as explicit tag')) 

1854 debug.scope.push(chosenSpec is None and '?' or chosenSpec.__class__.__name__) 

1855 

1856 if state is stDecodeValue: 

1857 if not options.get('recursiveFlag', True) and not substrateFun: # deprecate this 

1858 def substrateFun(asn1Object, _substrate, _length, _options): 

1859 """Legacy hack to keep the recursiveFlag=False option supported. 

1860 

1861 The decode(..., substrateFun=userCallback) option was introduced in 0.1.4 as a generalization 

1862 of the old recursiveFlag=False option. Users should pass their callback instead of using 

1863 recursiveFlag. 

1864 """ 

1865 yield asn1Object 

1866 

1867 original_position = substrate.tell() 

1868 

1869 if length == -1: # indef length 

1870 for value in concreteDecoder.indefLenValueDecoder( 

1871 substrate, asn1Spec, 

1872 tagSet, length, stGetValueDecoder, 

1873 self, substrateFun, **options): 

1874 if isinstance(value, SubstrateUnderrunError): 

1875 yield value 

1876 

1877 else: 

1878 for value in concreteDecoder.valueDecoder( 

1879 substrate, asn1Spec, 

1880 tagSet, length, stGetValueDecoder, 

1881 self, substrateFun, **options): 

1882 if isinstance(value, SubstrateUnderrunError): 

1883 yield value 

1884 

1885 bytesRead = substrate.tell() - original_position 

1886 if not substrateFun and bytesRead != length: 

1887 raise PyAsn1Error( 

1888 "Read %s bytes instead of expected %s." % (bytesRead, length)) 

1889 elif substrateFun and bytesRead > length: 

1890 # custom substrateFun may be used for partial decoding, reading less is expected there 

1891 raise PyAsn1Error( 

1892 "Read %s bytes are more than expected %s." % (bytesRead, length)) 

1893 

1894 if LOG: 

1895 LOG('codec %s yields type %s, value:\n%s\n...' % ( 

1896 concreteDecoder.__class__.__name__, value.__class__.__name__, 

1897 isinstance(value, base.Asn1Item) and value.prettyPrint() or value)) 

1898 

1899 state = stStop 

1900 break 

1901 

1902 if state is stTryAsExplicitTag: 

1903 if (tagSet and 

1904 tagSet[0].tagFormat == tag.tagFormatConstructed and 

1905 tagSet[0].tagClass != tag.tagClassUniversal): 

1906 # Assume explicit tagging 

1907 concreteDecoder = rawPayloadDecoder 

1908 state = stDecodeValue 

1909 

1910 else: 

1911 concreteDecoder = None 

1912 state = self.defaultErrorState 

1913 

1914 if LOG: 

1915 LOG('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as failure')) 

1916 

1917 if state is stDumpRawValue: 

1918 concreteDecoder = self.defaultRawDecoder 

1919 

1920 if LOG: 

1921 LOG('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__) 

1922 

1923 state = stDecodeValue 

1924 

1925 if state is stErrorCondition: 

1926 raise error.PyAsn1Error( 

1927 '%s not in asn1Spec: %r' % (tagSet, asn1Spec) 

1928 ) 

1929 

1930 if LOG: 

1931 debug.scope.pop() 

1932 LOG('decoder left scope %s, call completed' % debug.scope) 

1933 

1934 yield value 

1935 

1936 

1937class StreamingDecoder(object): 

1938 """Create an iterator that turns BER/CER/DER byte stream into ASN.1 objects. 

1939 

1940 On each iteration, consume whatever BER/CER/DER serialization is 

1941 available in the `substrate` stream-like object and turns it into 

1942 one or more, possibly nested, ASN.1 objects. 

1943 

1944 Parameters 

1945 ---------- 

1946 substrate: :py:class:`file`, :py:class:`io.BytesIO` 

1947 BER/CER/DER serialization in form of a byte stream 

1948 

1949 Keyword Args 

1950 ------------ 

1951 asn1Spec: :py:class:`~pyasn1.type.base.PyAsn1Item` 

1952 A pyasn1 type object to act as a template guiding the decoder. 

1953 Depending on the ASN.1 structure being decoded, `asn1Spec` may 

1954 or may not be required. One of the reasons why `asn1Spec` may 

1955 me required is that ASN.1 structure is encoded in the *IMPLICIT* 

1956 tagging mode. 

1957 

1958 Yields 

1959 ------ 

1960 : :py:class:`~pyasn1.type.base.PyAsn1Item`, :py:class:`~pyasn1.error.SubstrateUnderrunError` 

1961 Decoded ASN.1 object (possibly, nested) or 

1962 :py:class:`~pyasn1.error.SubstrateUnderrunError` object indicating 

1963 insufficient BER/CER/DER serialization on input to fully recover ASN.1 

1964 objects from it. 

1965 

1966 In the latter case the caller is advised to ensure some more data in 

1967 the input stream, then call the iterator again. The decoder will resume 

1968 the decoding process using the newly arrived data. 

1969 

1970 The `context` property of :py:class:`~pyasn1.error.SubstrateUnderrunError` 

1971 object might hold a reference to the partially populated ASN.1 object 

1972 being reconstructed. 

1973 

1974 Raises 

1975 ------ 

1976 ~pyasn1.error.PyAsn1Error, ~pyasn1.error.EndOfStreamError 

1977 `PyAsn1Error` on deserialization error, `EndOfStreamError` on 

1978 premature stream closure. 

1979 

1980 Examples 

1981 -------- 

1982 Decode BER serialisation without ASN.1 schema 

1983 

1984 .. code-block:: pycon 

1985 

1986 >>> stream = io.BytesIO( 

1987 ... b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03') 

1988 >>> 

1989 >>> for asn1Object in StreamingDecoder(stream): 

1990 ... print(asn1Object) 

1991 >>> 

1992 SequenceOf: 

1993 1 2 3 

1994 

1995 Decode BER serialisation with ASN.1 schema 

1996 

1997 .. code-block:: pycon 

1998 

1999 >>> stream = io.BytesIO( 

2000 ... b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03') 

2001 >>> 

2002 >>> schema = SequenceOf(componentType=Integer()) 

2003 >>> 

2004 >>> decoder = StreamingDecoder(stream, asn1Spec=schema) 

2005 >>> for asn1Object in decoder: 

2006 ... print(asn1Object) 

2007 >>> 

2008 SequenceOf: 

2009 1 2 3 

2010 """ 

2011 

2012 SINGLE_ITEM_DECODER = SingleItemDecoder 

2013 

2014 def __init__(self, substrate, asn1Spec=None, **options): 

2015 self._singleItemDecoder = self.SINGLE_ITEM_DECODER(**options) 

2016 self._substrate = asSeekableStream(substrate) 

2017 self._asn1Spec = asn1Spec 

2018 self._options = options 

2019 

2020 def __iter__(self): 

2021 while True: 

2022 for asn1Object in self._singleItemDecoder( 

2023 self._substrate, self._asn1Spec, **self._options): 

2024 yield asn1Object 

2025 

2026 for chunk in isEndOfStream(self._substrate): 

2027 if isinstance(chunk, SubstrateUnderrunError): 

2028 yield 

2029 

2030 break 

2031 

2032 if chunk: 

2033 break 

2034 

2035 

2036class Decoder(object): 

2037 """Create a BER decoder object. 

2038 

2039 Parse BER/CER/DER octet-stream into one, possibly nested, ASN.1 object. 

2040 """ 

2041 STREAMING_DECODER = StreamingDecoder 

2042 

2043 @classmethod 

2044 def __call__(cls, substrate, asn1Spec=None, **options): 

2045 """Turns BER/CER/DER octet stream into an ASN.1 object. 

2046 

2047 Takes BER/CER/DER octet-stream in form of :py:class:`bytes` 

2048 and decode it into an ASN.1 object 

2049 (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which 

2050 may be a scalar or an arbitrary nested structure. 

2051 

2052 Parameters 

2053 ---------- 

2054 substrate: :py:class:`bytes` 

2055 BER/CER/DER octet-stream to parse 

2056 

2057 Keyword Args 

2058 ------------ 

2059 asn1Spec: :py:class:`~pyasn1.type.base.PyAsn1Item` 

2060 A pyasn1 type object (:py:class:`~pyasn1.type.base.PyAsn1Item` 

2061 derivative) to act as a template guiding the decoder. 

2062 Depending on the ASN.1 structure being decoded, `asn1Spec` may or 

2063 may not be required. Most common reason for it to require is that 

2064 ASN.1 structure is encoded in *IMPLICIT* tagging mode. 

2065 

2066 substrateFun: :py:class:`Union[ 

2067 Callable[[pyasn1.type.base.PyAsn1Item, bytes, int], 

2068 Tuple[pyasn1.type.base.PyAsn1Item, bytes]], 

2069 Callable[[pyasn1.type.base.PyAsn1Item, io.BytesIO, int, dict], 

2070 Generator[Union[pyasn1.type.base.PyAsn1Item, 

2071 pyasn1.error.SubstrateUnderrunError], 

2072 None, None]] 

2073 ]` 

2074 User callback meant to generalize special use cases like non-recursive or 

2075 partial decoding. A 3-arg non-streaming variant is supported for backwards 

2076 compatiblilty in addition to the newer 4-arg streaming variant. 

2077 The callback will receive the uninitialized object recovered from substrate 

2078 as 1st argument, the uninterpreted payload as 2nd argument, and the length 

2079 of the uninterpreted payload as 3rd argument. The streaming variant will 

2080 additionally receive the decode(..., **options) kwargs as 4th argument. 

2081 The non-streaming variant shall return an object that will be propagated 

2082 as decode() return value as 1st item, and the remainig payload for further 

2083 decode passes as 2nd item. 

2084 The streaming variant shall yield an object that will be propagated as 

2085 decode() return value, and leave the remaining payload in the stream. 

2086 

2087 Returns 

2088 ------- 

2089 : :py:class:`tuple` 

2090 A tuple of :py:class:`~pyasn1.type.base.PyAsn1Item` object 

2091 recovered from BER/CER/DER substrate and the unprocessed trailing 

2092 portion of the `substrate` (may be empty) 

2093 

2094 Raises 

2095 ------ 

2096 : :py:class:`~pyasn1.error.PyAsn1Error` 

2097 :py:class:`~pyasn1.error.SubstrateUnderrunError` on insufficient 

2098 input or :py:class:`~pyasn1.error.PyAsn1Error` on decoding error. 

2099 

2100 Examples 

2101 -------- 

2102 Decode BER/CER/DER serialisation without ASN.1 schema 

2103 

2104 .. code-block:: pycon 

2105 

2106 >>> s, unprocessed = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03') 

2107 >>> str(s) 

2108 SequenceOf: 

2109 1 2 3 

2110 

2111 Decode BER/CER/DER serialisation with ASN.1 schema 

2112 

2113 .. code-block:: pycon 

2114 

2115 >>> seq = SequenceOf(componentType=Integer()) 

2116 >>> s, unprocessed = decode( 

2117 b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq) 

2118 >>> str(s) 

2119 SequenceOf: 

2120 1 2 3 

2121 

2122 """ 

2123 substrate = asSeekableStream(substrate) 

2124 

2125 if "substrateFun" in options: 

2126 origSubstrateFun = options["substrateFun"] 

2127 

2128 def substrateFunWrapper(asn1Object, substrate, length, options=None): 

2129 """Support both 0.4 and 0.5 style APIs. 

2130 

2131 substrateFun API has changed in 0.5 for use with streaming decoders. To stay backwards compatible, 

2132 we first try if we received a streaming user callback. If that fails,we assume we've received a 

2133 non-streaming v0.4 user callback and convert it for streaming on the fly 

2134 """ 

2135 try: 

2136 substrate_gen = origSubstrateFun(asn1Object, substrate, length, options) 

2137 except TypeError as _value: 

2138 if _value.__traceback__.tb_next: 

2139 # Traceback depth > 1 means TypeError from inside user provided function 

2140 raise 

2141 # invariant maintained at Decoder.__call__ entry 

2142 assert isinstance(substrate, io.BytesIO) # nosec assert_used 

2143 substrate_gen = Decoder._callSubstrateFunV4asV5(origSubstrateFun, asn1Object, substrate, length) 

2144 for value in substrate_gen: 

2145 yield value 

2146 

2147 options["substrateFun"] = substrateFunWrapper 

2148 

2149 streamingDecoder = cls.STREAMING_DECODER( 

2150 substrate, asn1Spec, **options) 

2151 

2152 for asn1Object in streamingDecoder: 

2153 if isinstance(asn1Object, SubstrateUnderrunError): 

2154 raise error.SubstrateUnderrunError('Short substrate on input') 

2155 

2156 try: 

2157 tail = next(readFromStream(substrate)) 

2158 

2159 except error.EndOfStreamError: 

2160 tail = b'' 

2161 

2162 return asn1Object, tail 

2163 

2164 @staticmethod 

2165 def _callSubstrateFunV4asV5(substrateFunV4, asn1Object, substrate, length): 

2166 substrate_bytes = substrate.read() 

2167 if length == -1: 

2168 length = len(substrate_bytes) 

2169 value, nextSubstrate = substrateFunV4(asn1Object, substrate_bytes, length) 

2170 nbytes = substrate.write(nextSubstrate) 

2171 substrate.truncate() 

2172 substrate.seek(-nbytes, os.SEEK_CUR) 

2173 yield value 

2174 

2175#: Turns BER octet stream into an ASN.1 object. 

2176#: 

2177#: Takes BER octet-stream and decode it into an ASN.1 object 

2178#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which 

2179#: may be a scalar or an arbitrary nested structure. 

2180#: 

2181#: Parameters 

2182#: ---------- 

2183#: substrate: :py:class:`bytes` 

2184#: BER octet-stream 

2185#: 

2186#: Keyword Args 

2187#: ------------ 

2188#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative 

2189#: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure 

2190#: being decoded, *asn1Spec* may or may not be required. Most common reason for 

2191#: it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode. 

2192#: 

2193#: Returns 

2194#: ------- 

2195#: : :py:class:`tuple` 

2196#: A tuple of pyasn1 object recovered from BER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative) 

2197#: and the unprocessed trailing portion of the *substrate* (may be empty) 

2198#: 

2199#: Raises 

2200#: ------ 

2201#: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError 

2202#: On decoding errors 

2203#: 

2204#: Notes 

2205#: ----- 

2206#: This function is deprecated. Please use :py:class:`Decoder` or 

2207#: :py:class:`StreamingDecoder` class instance. 

2208#: 

2209#: Examples 

2210#: -------- 

2211#: Decode BER serialisation without ASN.1 schema 

2212#: 

2213#: .. code-block:: pycon 

2214#: 

2215#: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03') 

2216#: >>> str(s) 

2217#: SequenceOf: 

2218#: 1 2 3 

2219#: 

2220#: Decode BER serialisation with ASN.1 schema 

2221#: 

2222#: .. code-block:: pycon 

2223#: 

2224#: >>> seq = SequenceOf(componentType=Integer()) 

2225#: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq) 

2226#: >>> str(s) 

2227#: SequenceOf: 

2228#: 1 2 3 

2229#: 

2230decode = Decoder() 

2231 

2232def __getattr__(attr: str): 

2233 if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr): 

2234 warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning, stacklevel=2) 

2235 return globals()[newAttr] 

2236 raise AttributeError(attr)