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

1106 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 @staticmethod 

178 def _appendFragment(assembled, component, bitLength): 

179 trailingBits = component[0] 

180 if trailingBits > 7: 

181 raise error.PyAsn1Error( 

182 'Trailing bits overflow %s' % trailingBits 

183 ) 

184 

185 payload = component[1:] 

186 if not payload: 

187 if trailingBits: 

188 raise error.PyAsn1Error('Trailing bits overflow %s' % trailingBits) 

189 return bitLength 

190 

191 if not trailingBits and not bitLength % 8: 

192 assembled.extend(payload) 

193 return bitLength + len(payload) * 8 

194 

195 for idx, byte in enumerate(payload): 

196 significantBits = 8 

197 if idx == len(payload) - 1: 

198 significantBits -= trailingBits 

199 byte >>= trailingBits 

200 

201 usedBits = bitLength % 8 

202 if not usedBits: 

203 assembled.append(byte << (8 - significantBits)) 

204 elif usedBits + significantBits <= 8: 

205 assembled[-1] |= byte << (8 - usedBits - significantBits) 

206 else: 

207 remainingBits = usedBits + significantBits - 8 

208 assembled[-1] |= byte >> remainingBits 

209 assembled.append((byte << (8 - remainingBits)) & 0xff) 

210 

211 bitLength += significantBits 

212 

213 return bitLength 

214 

215 def valueDecoder(self, substrate, asn1Spec, 

216 tagSet=None, length=None, state=None, 

217 decodeFun=None, substrateFun=None, 

218 **options): 

219 

220 if substrateFun: 

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

222 

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

224 yield chunk 

225 

226 return 

227 

228 if not length: 

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

230 

231 for chunk in isEndOfStream(substrate): 

232 if isinstance(chunk, SubstrateUnderrunError): 

233 yield chunk 

234 

235 if chunk: 

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

237 

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

239 

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

241 if isinstance(trailingBits, SubstrateUnderrunError): 

242 yield trailingBits 

243 

244 trailingBits = ord(trailingBits) 

245 if trailingBits > 7: 

246 raise error.PyAsn1Error( 

247 'Trailing bits overflow %s' % trailingBits 

248 ) 

249 

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

251 if isinstance(chunk, SubstrateUnderrunError): 

252 yield chunk 

253 

254 value = self.protoComponent.fromOctetString( 

255 chunk, internalFormat=True, padding=trailingBits) 

256 

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

258 

259 return 

260 

261 if not self.supportConstructedForm: 

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

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

264 

265 if LOG: 

266 LOG('assembling constructed serialization') 

267 

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

269 substrateFun = self.substrateCollector 

270 

271 assembled = bytearray() 

272 bitLength = 0 

273 

274 current_position = substrate.tell() 

275 

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

277 for component in decodeFun( 

278 substrate, self.protoComponent, substrateFun=substrateFun, 

279 **options): 

280 if isinstance(component, SubstrateUnderrunError): 

281 yield component 

282 

283 bitLength = self._appendFragment(assembled, component, bitLength) 

284 

285 bitString = self.protoComponent.fromOctetString( 

286 assembled, internalFormat=True, padding=(-bitLength) % 8 

287 ) 

288 

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

290 

291 def indefLenValueDecoder(self, substrate, asn1Spec, 

292 tagSet=None, length=None, state=None, 

293 decodeFun=None, substrateFun=None, 

294 **options): 

295 

296 if substrateFun: 

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

298 

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

300 yield chunk 

301 

302 return 

303 

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

305 substrateFun = self.substrateCollector 

306 

307 assembled = bytearray() 

308 bitLength = 0 

309 

310 while True: # loop over fragments 

311 

312 for component in decodeFun( 

313 substrate, self.protoComponent, substrateFun=substrateFun, 

314 allowEoo=True, **options): 

315 

316 if component is eoo.endOfOctets: 

317 break 

318 

319 if isinstance(component, SubstrateUnderrunError): 

320 yield component 

321 

322 if component is eoo.endOfOctets: 

323 break 

324 

325 bitLength = self._appendFragment(assembled, component, bitLength) 

326 

327 bitString = self.protoComponent.fromOctetString( 

328 assembled, internalFormat=True, padding=(-bitLength) % 8 

329 ) 

330 

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

332 

333 

334class OctetStringPayloadDecoder(AbstractSimplePayloadDecoder): 

335 protoComponent = univ.OctetString('') 

336 supportConstructedForm = True 

337 

338 def valueDecoder(self, substrate, asn1Spec, 

339 tagSet=None, length=None, state=None, 

340 decodeFun=None, substrateFun=None, 

341 **options): 

342 if substrateFun: 

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

344 

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

346 yield chunk 

347 

348 return 

349 

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

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

352 if isinstance(chunk, SubstrateUnderrunError): 

353 yield chunk 

354 

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

356 

357 return 

358 

359 if not self.supportConstructedForm: 

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

361 

362 if LOG: 

363 LOG('assembling constructed serialization') 

364 

365 # Assemble the logical value of each fragment, including nested ones. 

366 fragments = [] 

367 

368 original_position = substrate.tell() 

369 # head = popSubstream(substrate, length) 

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

371 for component in decodeFun( 

372 substrate, self.protoComponent, **options): 

373 if isinstance(component, SubstrateUnderrunError): 

374 yield component 

375 

376 fragments.append(bytes(component)) 

377 

378 yield self._createComponent(asn1Spec, tagSet, b''.join(fragments), **options) 

379 

380 def indefLenValueDecoder(self, substrate, asn1Spec, 

381 tagSet=None, length=None, state=None, 

382 decodeFun=None, substrateFun=None, 

383 **options): 

384 if substrateFun and substrateFun is not self.substrateCollector: 

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

386 

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

388 yield chunk 

389 

390 return 

391 

392 # Assemble the logical value of each fragment, including nested ones. 

393 fragments = [] 

394 

395 while True: # loop over fragments 

396 

397 for component in decodeFun( 

398 substrate, self.protoComponent, allowEoo=True, **options): 

399 

400 if isinstance(component, SubstrateUnderrunError): 

401 yield component 

402 

403 if component is eoo.endOfOctets: 

404 break 

405 

406 if component is eoo.endOfOctets: 

407 break 

408 

409 fragments.append(bytes(component)) 

410 

411 yield self._createComponent(asn1Spec, tagSet, b''.join(fragments), **options) 

412 

413 

414class NullPayloadDecoder(AbstractSimplePayloadDecoder): 

415 protoComponent = univ.Null('') 

416 

417 def valueDecoder(self, substrate, asn1Spec, 

418 tagSet=None, length=None, state=None, 

419 decodeFun=None, substrateFun=None, 

420 **options): 

421 

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

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

424 

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

426 if isinstance(chunk, SubstrateUnderrunError): 

427 yield chunk 

428 

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

430 

431 if chunk: 

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

433 

434 yield component 

435 

436 

437class ObjectIdentifierPayloadDecoder(AbstractSimplePayloadDecoder): 

438 protoComponent = univ.ObjectIdentifier(()) 

439 

440 def valueDecoder(self, substrate, asn1Spec, 

441 tagSet=None, length=None, state=None, 

442 decodeFun=None, substrateFun=None, 

443 **options): 

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

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

446 

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

448 if isinstance(chunk, SubstrateUnderrunError): 

449 yield chunk 

450 

451 if not chunk: 

452 raise error.PyAsn1Error('Empty substrate') 

453 

454 oid = [] 

455 index = 0 

456 substrateLen = len(chunk) 

457 while index < substrateLen: 

458 subId = chunk[index] 

459 index += 1 

460 if subId < 128: 

461 oid.append(subId) 

462 elif subId > 128: 

463 # Construct subid from a number of octets 

464 nextSubId = subId 

465 subId = 0 

466 continuationOctetCount = 0 

467 while nextSubId >= 128: 

468 continuationOctetCount += 1 

469 if continuationOctetCount > MAX_OID_ARC_CONTINUATION_OCTETS: 

470 raise error.PyAsn1Error( 

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

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

473 ) 

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

475 if index >= substrateLen: 

476 raise error.SubstrateUnderrunError( 

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

478 ) 

479 nextSubId = chunk[index] 

480 index += 1 

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

482 elif subId == 128: 

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

484 # encoding, tolerating it opens a vulnerability. See 

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

486 # page 7 

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

488 

489 # Decode two leading arcs 

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

491 oid.insert(0, 0) 

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

493 oid[0] -= 40 

494 oid.insert(0, 1) 

495 elif oid[0] >= 80: 

496 oid[0] -= 80 

497 oid.insert(0, 2) 

498 else: 

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

500 

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

502 

503 

504class RelativeOIDPayloadDecoder(AbstractSimplePayloadDecoder): 

505 protoComponent = univ.RelativeOID(()) 

506 

507 def valueDecoder(self, substrate, asn1Spec, 

508 tagSet=None, length=None, state=None, 

509 decodeFun=None, substrateFun=None, 

510 **options): 

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

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

513 

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

515 if isinstance(chunk, SubstrateUnderrunError): 

516 yield chunk 

517 

518 if not chunk: 

519 raise error.PyAsn1Error('Empty substrate') 

520 

521 reloid = [] 

522 index = 0 

523 substrateLen = len(chunk) 

524 while index < substrateLen: 

525 subId = chunk[index] 

526 index += 1 

527 if subId < 128: 

528 reloid.append(subId) 

529 elif subId > 128: 

530 # Construct subid from a number of octets 

531 nextSubId = subId 

532 subId = 0 

533 continuationOctetCount = 0 

534 while nextSubId >= 128: 

535 continuationOctetCount += 1 

536 if continuationOctetCount > MAX_OID_ARC_CONTINUATION_OCTETS: 

537 raise error.PyAsn1Error( 

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

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

540 ) 

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

542 if index >= substrateLen: 

543 raise error.SubstrateUnderrunError( 

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

545 ) 

546 nextSubId = chunk[index] 

547 index += 1 

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

549 elif subId == 128: 

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

551 # encoding, tolerating it opens a vulnerability. See 

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

553 # page 7 

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

555 

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

557 

558 

559class RealPayloadDecoder(AbstractSimplePayloadDecoder): 

560 protoComponent = univ.Real() 

561 

562 def valueDecoder(self, substrate, asn1Spec, 

563 tagSet=None, length=None, state=None, 

564 decodeFun=None, substrateFun=None, 

565 **options): 

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

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

568 

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

570 if isinstance(chunk, SubstrateUnderrunError): 

571 yield chunk 

572 

573 if not chunk: 

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

575 return 

576 

577 fo = chunk[0] 

578 chunk = chunk[1:] 

579 if fo & 0x80: # binary encoding 

580 if not chunk: 

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

582 

583 if LOG: 

584 LOG('decoding binary encoded REAL') 

585 

586 n = (fo & 0x03) + 1 

587 

588 if n == 4: 

589 n = chunk[0] 

590 chunk = chunk[1:] 

591 

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

593 

594 if not eo or not chunk: 

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

596 

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

598 

599 while eo: # exponent 

600 e <<= 8 

601 e |= eo[0] 

602 eo = eo[1:] 

603 

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

605 

606 if b > 2: 

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

608 

609 if b == 1: # encbase = 8 

610 e *= 3 

611 

612 elif b == 2: # encbase = 16 

613 e *= 4 

614 p = int.from_bytes(bytes(chunk), 'big') 

615 

616 if fo & 0x40: # sign bit 

617 p = -p 

618 

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

620 p *= 2 ** sf 

621 value = (p, 2, e) 

622 

623 elif fo & 0x40: # infinite value 

624 if LOG: 

625 LOG('decoding infinite REAL') 

626 

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

628 

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

630 if not chunk: 

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

632 

633 if LOG: 

634 LOG('decoding character encoded REAL') 

635 

636 try: 

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

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

639 

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

641 value = float(chunk) 

642 

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

644 value = float(chunk) 

645 

646 else: 

647 raise error.SubstrateUnderrunError( 

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

649 ) 

650 

651 except ValueError: 

652 raise error.SubstrateUnderrunError( 

653 'Bad character Real syntax' 

654 ) 

655 

656 else: 

657 raise error.SubstrateUnderrunError( 

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

659 ) 

660 

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

662 

663 

664class AbstractConstructedPayloadDecoder(AbstractPayloadDecoder): 

665 protoComponent = None 

666 

667 

668class ConstructedPayloadDecoderBase(AbstractConstructedPayloadDecoder): 

669 protoRecordComponent = None 

670 protoSequenceComponent = None 

671 

672 def _getComponentTagMap(self, asn1Object, idx): 

673 raise NotImplementedError 

674 

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

676 raise NotImplementedError 

677 

678 def _decodeComponentsSchemaless( 

679 self, substrate, tagSet=None, decodeFun=None, 

680 length=None, **options): 

681 

682 asn1Object = None 

683 

684 components = [] 

685 componentTypes = set() 

686 

687 original_position = substrate.tell() 

688 

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

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

691 if isinstance(component, SubstrateUnderrunError): 

692 yield component 

693 

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

695 break 

696 

697 components.append(component) 

698 # Two distinct types settle the choice; keep the set bounded 

699 # to avoid quadratic comparisons for colliding tag hashes. 

700 if len(componentTypes) < 2: 

701 componentTypes.add(component.tagSet) 

702 

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

704 # The heuristics is: 

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

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

707 if len(componentTypes) > 1: 

708 protoComponent = self.protoRecordComponent 

709 

710 else: 

711 protoComponent = self.protoSequenceComponent 

712 

713 asn1Object = protoComponent.clone( 

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

715 # and additional tags recovered from the substrate 

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

717 ) 

718 

719 if LOG: 

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

721 'decoder)' % asn1Object) 

722 

723 for idx, component in enumerate(components): 

724 asn1Object.setComponentByPosition( 

725 idx, component, 

726 verifyConstraints=False, 

727 matchTags=False, matchConstraints=False 

728 ) 

729 

730 yield asn1Object 

731 

732 def valueDecoder(self, substrate, asn1Spec, 

733 tagSet=None, length=None, state=None, 

734 decodeFun=None, substrateFun=None, 

735 **options): 

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

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

738 

739 original_position = substrate.tell() 

740 

741 if substrateFun: 

742 if asn1Spec is not None: 

743 asn1Object = asn1Spec.clone() 

744 

745 elif self.protoComponent is not None: 

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

747 

748 else: 

749 asn1Object = self.protoRecordComponent, self.protoSequenceComponent 

750 

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

752 yield chunk 

753 

754 return 

755 

756 if asn1Spec is None: 

757 for asn1Object in self._decodeComponentsSchemaless( 

758 substrate, tagSet=tagSet, decodeFun=decodeFun, 

759 length=length, **options): 

760 if isinstance(asn1Object, SubstrateUnderrunError): 

761 yield asn1Object 

762 

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

764 if LOG: 

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

766 if isinstance(trailing, SubstrateUnderrunError): 

767 yield trailing 

768 

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

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

771 

772 yield asn1Object 

773 

774 return 

775 

776 asn1Object = asn1Spec.clone() 

777 asn1Object.clear() 

778 

779 options = self._passAsn1Object(asn1Object, options) 

780 

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

782 

783 namedTypes = asn1Spec.componentType 

784 

785 isSetType = asn1Spec.typeId == univ.Set.typeId 

786 isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault 

787 

788 if LOG: 

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

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

791 asn1Spec)) 

792 

793 seenIndices = set() 

794 idx = 0 

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

796 if not namedTypes: 

797 componentType = None 

798 

799 elif isSetType: 

800 componentType = namedTypes.tagMapUnique 

801 

802 else: 

803 try: 

804 if isDeterministic: 

805 componentType = namedTypes[idx].asn1Object 

806 

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

808 componentType = namedTypes.getTagMapNearPosition(idx) 

809 

810 else: 

811 componentType = namedTypes[idx].asn1Object 

812 

813 except IndexError: 

814 raise error.PyAsn1Error( 

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

816 ) 

817 

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

819 if isinstance(component, SubstrateUnderrunError): 

820 yield component 

821 

822 if not isDeterministic and namedTypes: 

823 if isSetType: 

824 idx = namedTypes.getPositionByType(component.effectiveTagSet) 

825 

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

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

828 

829 asn1Object.setComponentByPosition( 

830 idx, component, 

831 verifyConstraints=False, 

832 matchTags=False, matchConstraints=False 

833 ) 

834 

835 seenIndices.add(idx) 

836 idx += 1 

837 

838 if LOG: 

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

840 

841 if namedTypes: 

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

843 raise error.PyAsn1Error( 

844 'ASN.1 object %s has uninitialized ' 

845 'components' % asn1Object.__class__.__name__) 

846 

847 if namedTypes.hasOpenTypes: 

848 

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

850 

851 if LOG: 

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

853 

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

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

856 

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

858 

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

860 if not namedType.openType: 

861 continue 

862 

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

864 continue 

865 

866 governingValue = asn1Object.getComponentByName( 

867 namedType.openType.name 

868 ) 

869 

870 try: 

871 openType = openTypes[governingValue] 

872 

873 except KeyError: 

874 

875 if LOG: 

876 LOG('default open types map of component ' 

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

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

879 namedType.name, 

880 asn1Object.__class__.__name__, 

881 namedType.openType.name)) 

882 

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

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

885 

886 try: 

887 openType = namedType.openType[governingValue] 

888 

889 except KeyError: 

890 if LOG: 

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

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

893 continue 

894 

895 if LOG: 

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

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

898 

899 containerValue = asn1Object.getComponentByPosition(idx) 

900 

901 if containerValue.typeId in ( 

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

903 

904 for pos, containerElement in enumerate( 

905 containerValue): 

906 

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

908 

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

910 if isinstance(component, SubstrateUnderrunError): 

911 yield component 

912 

913 containerValue[pos] = component 

914 

915 else: 

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

917 

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

919 if isinstance(component, SubstrateUnderrunError): 

920 yield component 

921 

922 asn1Object.setComponentByPosition(idx, component) 

923 

924 else: 

925 inconsistency = asn1Object.isInconsistent 

926 if inconsistency: 

927 raise error.PyAsn1Error( 

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

929 

930 else: 

931 componentType = asn1Spec.componentType 

932 

933 if LOG: 

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

935 

936 idx = 0 

937 

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

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

940 if isinstance(component, SubstrateUnderrunError): 

941 yield component 

942 

943 asn1Object.setComponentByPosition( 

944 idx, component, 

945 verifyConstraints=False, 

946 matchTags=False, matchConstraints=False 

947 ) 

948 

949 idx += 1 

950 

951 yield asn1Object 

952 

953 def indefLenValueDecoder(self, substrate, asn1Spec, 

954 tagSet=None, length=None, state=None, 

955 decodeFun=None, substrateFun=None, 

956 **options): 

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

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

959 

960 if substrateFun is not None: 

961 if asn1Spec is not None: 

962 asn1Object = asn1Spec.clone() 

963 

964 elif self.protoComponent is not None: 

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

966 

967 else: 

968 asn1Object = self.protoRecordComponent, self.protoSequenceComponent 

969 

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

971 yield chunk 

972 

973 return 

974 

975 if asn1Spec is None: 

976 for asn1Object in self._decodeComponentsSchemaless( 

977 substrate, tagSet=tagSet, decodeFun=decodeFun, 

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

979 if isinstance(asn1Object, SubstrateUnderrunError): 

980 yield asn1Object 

981 

982 yield asn1Object 

983 

984 return 

985 

986 asn1Object = asn1Spec.clone() 

987 asn1Object.clear() 

988 

989 options = self._passAsn1Object(asn1Object, options) 

990 

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

992 

993 namedTypes = asn1Object.componentType 

994 

995 isSetType = asn1Object.typeId == univ.Set.typeId 

996 isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault 

997 

998 if LOG: 

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

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

1001 asn1Spec)) 

1002 

1003 seenIndices = set() 

1004 

1005 idx = 0 

1006 

1007 while True: # loop over components 

1008 if len(namedTypes) <= idx: 

1009 asn1Spec = None 

1010 

1011 elif isSetType: 

1012 asn1Spec = namedTypes.tagMapUnique 

1013 

1014 else: 

1015 try: 

1016 if isDeterministic: 

1017 asn1Spec = namedTypes[idx].asn1Object 

1018 

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

1020 asn1Spec = namedTypes.getTagMapNearPosition(idx) 

1021 

1022 else: 

1023 asn1Spec = namedTypes[idx].asn1Object 

1024 

1025 except IndexError: 

1026 raise error.PyAsn1Error( 

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

1028 ) 

1029 

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

1031 

1032 if isinstance(component, SubstrateUnderrunError): 

1033 yield component 

1034 

1035 if component is eoo.endOfOctets: 

1036 break 

1037 

1038 if component is eoo.endOfOctets: 

1039 break 

1040 

1041 if not isDeterministic and namedTypes: 

1042 if isSetType: 

1043 idx = namedTypes.getPositionByType(component.effectiveTagSet) 

1044 

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

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

1047 

1048 asn1Object.setComponentByPosition( 

1049 idx, component, 

1050 verifyConstraints=False, 

1051 matchTags=False, matchConstraints=False 

1052 ) 

1053 

1054 seenIndices.add(idx) 

1055 idx += 1 

1056 

1057 if LOG: 

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

1059 

1060 if namedTypes: 

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

1062 raise error.PyAsn1Error( 

1063 'ASN.1 object %s has uninitialized ' 

1064 'components' % asn1Object.__class__.__name__) 

1065 

1066 if namedTypes.hasOpenTypes: 

1067 

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

1069 

1070 if LOG: 

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

1072 

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

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

1075 

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

1077 

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

1079 if not namedType.openType: 

1080 continue 

1081 

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

1083 continue 

1084 

1085 governingValue = asn1Object.getComponentByName( 

1086 namedType.openType.name 

1087 ) 

1088 

1089 try: 

1090 openType = openTypes[governingValue] 

1091 

1092 except KeyError: 

1093 

1094 if LOG: 

1095 LOG('default open types map of component ' 

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

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

1098 namedType.name, 

1099 asn1Object.__class__.__name__, 

1100 namedType.openType.name)) 

1101 

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

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

1104 

1105 try: 

1106 openType = namedType.openType[governingValue] 

1107 

1108 except KeyError: 

1109 if LOG: 

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

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

1112 continue 

1113 

1114 if LOG: 

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

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

1117 

1118 containerValue = asn1Object.getComponentByPosition(idx) 

1119 

1120 if containerValue.typeId in ( 

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

1122 

1123 for pos, containerElement in enumerate( 

1124 containerValue): 

1125 

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

1127 

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

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

1130 if isinstance(component, SubstrateUnderrunError): 

1131 yield component 

1132 

1133 if component is eoo.endOfOctets: 

1134 break 

1135 

1136 containerValue[pos] = component 

1137 

1138 else: 

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

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

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

1142 if isinstance(component, SubstrateUnderrunError): 

1143 yield component 

1144 

1145 if component is eoo.endOfOctets: 

1146 break 

1147 

1148 asn1Object.setComponentByPosition(idx, component) 

1149 

1150 else: 

1151 inconsistency = asn1Object.isInconsistent 

1152 if inconsistency: 

1153 raise error.PyAsn1Error( 

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

1155 

1156 else: 

1157 componentType = asn1Spec.componentType 

1158 

1159 if LOG: 

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

1161 

1162 idx = 0 

1163 

1164 while True: 

1165 

1166 for component in decodeFun( 

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

1168 

1169 if isinstance(component, SubstrateUnderrunError): 

1170 yield component 

1171 

1172 if component is eoo.endOfOctets: 

1173 break 

1174 

1175 if component is eoo.endOfOctets: 

1176 break 

1177 

1178 asn1Object.setComponentByPosition( 

1179 idx, component, 

1180 verifyConstraints=False, 

1181 matchTags=False, matchConstraints=False 

1182 ) 

1183 

1184 idx += 1 

1185 

1186 yield asn1Object 

1187 

1188 

1189class SequenceOrSequenceOfPayloadDecoder(ConstructedPayloadDecoderBase): 

1190 protoRecordComponent = univ.Sequence() 

1191 protoSequenceComponent = univ.SequenceOf() 

1192 

1193 

1194class SequencePayloadDecoder(SequenceOrSequenceOfPayloadDecoder): 

1195 protoComponent = univ.Sequence() 

1196 

1197 

1198class SequenceOfPayloadDecoder(SequenceOrSequenceOfPayloadDecoder): 

1199 protoComponent = univ.SequenceOf() 

1200 

1201 

1202class SetOrSetOfPayloadDecoder(ConstructedPayloadDecoderBase): 

1203 protoRecordComponent = univ.Set() 

1204 protoSequenceComponent = univ.SetOf() 

1205 

1206 

1207class SetPayloadDecoder(SetOrSetOfPayloadDecoder): 

1208 protoComponent = univ.Set() 

1209 

1210 

1211class SetOfPayloadDecoder(SetOrSetOfPayloadDecoder): 

1212 protoComponent = univ.SetOf() 

1213 

1214 

1215class ChoicePayloadDecoder(ConstructedPayloadDecoderBase): 

1216 protoComponent = univ.Choice() 

1217 

1218 def valueDecoder(self, substrate, asn1Spec, 

1219 tagSet=None, length=None, state=None, 

1220 decodeFun=None, substrateFun=None, 

1221 **options): 

1222 if asn1Spec is None: 

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

1224 

1225 else: 

1226 asn1Object = asn1Spec.clone() 

1227 

1228 if substrateFun: 

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

1230 yield chunk 

1231 

1232 return 

1233 

1234 options = self._passAsn1Object(asn1Object, options) 

1235 

1236 if asn1Object.tagSet == tagSet: 

1237 if LOG: 

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

1239 

1240 for component in decodeFun( 

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

1242 if isinstance(component, SubstrateUnderrunError): 

1243 yield component 

1244 

1245 else: 

1246 if LOG: 

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

1248 

1249 for component in decodeFun( 

1250 substrate, asn1Object.componentTagMap, tagSet, length, 

1251 state, **options): 

1252 if isinstance(component, SubstrateUnderrunError): 

1253 yield component 

1254 

1255 effectiveTagSet = component.effectiveTagSet 

1256 

1257 if LOG: 

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

1259 

1260 asn1Object.setComponentByType( 

1261 effectiveTagSet, component, 

1262 verifyConstraints=False, 

1263 matchTags=False, matchConstraints=False, 

1264 innerFlag=False 

1265 ) 

1266 

1267 yield asn1Object 

1268 

1269 def indefLenValueDecoder(self, substrate, asn1Spec, 

1270 tagSet=None, length=None, state=None, 

1271 decodeFun=None, substrateFun=None, 

1272 **options): 

1273 if asn1Spec is None: 

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

1275 

1276 else: 

1277 asn1Object = asn1Spec.clone() 

1278 

1279 if substrateFun: 

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

1281 yield chunk 

1282 

1283 return 

1284 

1285 options = self._passAsn1Object(asn1Object, options) 

1286 

1287 isTagged = asn1Object.tagSet == tagSet 

1288 

1289 if LOG: 

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

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

1292 

1293 while True: 

1294 

1295 if isTagged: 

1296 iterator = decodeFun( 

1297 substrate, asn1Object.componentType.tagMapUnique, 

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

1299 

1300 else: 

1301 iterator = decodeFun( 

1302 substrate, asn1Object.componentType.tagMapUnique, 

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

1304 

1305 for component in iterator: 

1306 

1307 if isinstance(component, SubstrateUnderrunError): 

1308 yield component 

1309 

1310 if component is eoo.endOfOctets: 

1311 break 

1312 

1313 effectiveTagSet = component.effectiveTagSet 

1314 

1315 if LOG: 

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

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

1318 

1319 asn1Object.setComponentByType( 

1320 effectiveTagSet, component, 

1321 verifyConstraints=False, 

1322 matchTags=False, matchConstraints=False, 

1323 innerFlag=False 

1324 ) 

1325 

1326 if not isTagged: 

1327 break 

1328 

1329 if not isTagged or component is eoo.endOfOctets: 

1330 break 

1331 

1332 yield asn1Object 

1333 

1334 

1335class AnyPayloadDecoder(AbstractSimplePayloadDecoder): 

1336 protoComponent = univ.Any() 

1337 

1338 def valueDecoder(self, substrate, asn1Spec, 

1339 tagSet=None, length=None, state=None, 

1340 decodeFun=None, substrateFun=None, 

1341 **options): 

1342 if asn1Spec is None: 

1343 isUntagged = True 

1344 

1345 elif asn1Spec.__class__ is tagmap.TagMap: 

1346 isUntagged = tagSet not in asn1Spec.tagMap 

1347 

1348 else: 

1349 isUntagged = tagSet != asn1Spec.tagSet 

1350 

1351 if isUntagged: 

1352 fullPosition = substrate.markedPosition 

1353 currentPosition = substrate.tell() 

1354 

1355 substrate.seek(fullPosition, os.SEEK_SET) 

1356 length += currentPosition - fullPosition 

1357 

1358 if LOG: 

1359 for chunk in peekIntoStream(substrate, length): 

1360 if isinstance(chunk, SubstrateUnderrunError): 

1361 yield chunk 

1362 LOG('decoding as untagged ANY, substrate ' 

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

1364 

1365 if substrateFun: 

1366 for chunk in substrateFun( 

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

1368 substrate, length, options): 

1369 yield chunk 

1370 

1371 return 

1372 

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

1374 if isinstance(chunk, SubstrateUnderrunError): 

1375 yield chunk 

1376 

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

1378 

1379 def indefLenValueDecoder(self, substrate, asn1Spec, 

1380 tagSet=None, length=None, state=None, 

1381 decodeFun=None, substrateFun=None, 

1382 **options): 

1383 if asn1Spec is None: 

1384 isTagged = False 

1385 

1386 elif asn1Spec.__class__ is tagmap.TagMap: 

1387 isTagged = tagSet in asn1Spec.tagMap 

1388 

1389 else: 

1390 isTagged = tagSet == asn1Spec.tagSet 

1391 

1392 if isTagged: 

1393 # tagged Any type -- consume header substrate 

1394 chunk = b'' 

1395 

1396 if LOG: 

1397 LOG('decoding as tagged ANY') 

1398 

1399 else: 

1400 # TODO: Seems not to be tested 

1401 fullPosition = substrate.markedPosition 

1402 currentPosition = substrate.tell() 

1403 

1404 substrate.seek(fullPosition, os.SEEK_SET) 

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

1406 if isinstance(chunk, SubstrateUnderrunError): 

1407 yield chunk 

1408 

1409 if LOG: 

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

1411 

1412 # Any components do not inherit initial tag 

1413 asn1Spec = self.protoComponent 

1414 

1415 if substrateFun and substrateFun is not self.substrateCollector: 

1416 asn1Object = self._createComponent( 

1417 asn1Spec, tagSet, noValue, **options) 

1418 

1419 for chunk in substrateFun( 

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

1421 yield chunk 

1422 

1423 return 

1424 

1425 if LOG: 

1426 LOG('assembling constructed serialization') 

1427 

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

1429 substrateFun = self.substrateCollector 

1430 

1431 fragments = [chunk] 

1432 

1433 while True: # loop over fragments 

1434 

1435 for component in decodeFun( 

1436 substrate, asn1Spec, substrateFun=substrateFun, 

1437 allowEoo=True, **options): 

1438 

1439 if isinstance(component, SubstrateUnderrunError): 

1440 yield component 

1441 

1442 if component is eoo.endOfOctets: 

1443 break 

1444 

1445 if component is eoo.endOfOctets: 

1446 break 

1447 

1448 fragments.append(component) 

1449 

1450 chunk = b''.join(fragments) 

1451 

1452 if substrateFun: 

1453 yield chunk # TODO: Weird 

1454 

1455 else: 

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

1457 

1458 

1459# character string types 

1460class UTF8StringPayloadDecoder(OctetStringPayloadDecoder): 

1461 protoComponent = char.UTF8String() 

1462 

1463 

1464class NumericStringPayloadDecoder(OctetStringPayloadDecoder): 

1465 protoComponent = char.NumericString() 

1466 

1467 

1468class PrintableStringPayloadDecoder(OctetStringPayloadDecoder): 

1469 protoComponent = char.PrintableString() 

1470 

1471 

1472class TeletexStringPayloadDecoder(OctetStringPayloadDecoder): 

1473 protoComponent = char.TeletexString() 

1474 

1475 

1476class VideotexStringPayloadDecoder(OctetStringPayloadDecoder): 

1477 protoComponent = char.VideotexString() 

1478 

1479 

1480class IA5StringPayloadDecoder(OctetStringPayloadDecoder): 

1481 protoComponent = char.IA5String() 

1482 

1483 

1484class GraphicStringPayloadDecoder(OctetStringPayloadDecoder): 

1485 protoComponent = char.GraphicString() 

1486 

1487 

1488class VisibleStringPayloadDecoder(OctetStringPayloadDecoder): 

1489 protoComponent = char.VisibleString() 

1490 

1491 

1492class GeneralStringPayloadDecoder(OctetStringPayloadDecoder): 

1493 protoComponent = char.GeneralString() 

1494 

1495 

1496class UniversalStringPayloadDecoder(OctetStringPayloadDecoder): 

1497 protoComponent = char.UniversalString() 

1498 

1499 

1500class BMPStringPayloadDecoder(OctetStringPayloadDecoder): 

1501 protoComponent = char.BMPString() 

1502 

1503 

1504# "useful" types 

1505class ObjectDescriptorPayloadDecoder(OctetStringPayloadDecoder): 

1506 protoComponent = useful.ObjectDescriptor() 

1507 

1508 

1509class GeneralizedTimePayloadDecoder(OctetStringPayloadDecoder): 

1510 protoComponent = useful.GeneralizedTime() 

1511 

1512 

1513class UTCTimePayloadDecoder(OctetStringPayloadDecoder): 

1514 protoComponent = useful.UTCTime() 

1515 

1516 

1517TAG_MAP = { 

1518 univ.Integer.tagSet: IntegerPayloadDecoder(), 

1519 univ.Boolean.tagSet: BooleanPayloadDecoder(), 

1520 univ.BitString.tagSet: BitStringPayloadDecoder(), 

1521 univ.OctetString.tagSet: OctetStringPayloadDecoder(), 

1522 univ.Null.tagSet: NullPayloadDecoder(), 

1523 univ.ObjectIdentifier.tagSet: ObjectIdentifierPayloadDecoder(), 

1524 univ.RelativeOID.tagSet: RelativeOIDPayloadDecoder(), 

1525 univ.Enumerated.tagSet: IntegerPayloadDecoder(), 

1526 univ.Real.tagSet: RealPayloadDecoder(), 

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

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

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

1530 # character string types 

1531 char.UTF8String.tagSet: UTF8StringPayloadDecoder(), 

1532 char.NumericString.tagSet: NumericStringPayloadDecoder(), 

1533 char.PrintableString.tagSet: PrintableStringPayloadDecoder(), 

1534 char.TeletexString.tagSet: TeletexStringPayloadDecoder(), 

1535 char.VideotexString.tagSet: VideotexStringPayloadDecoder(), 

1536 char.IA5String.tagSet: IA5StringPayloadDecoder(), 

1537 char.GraphicString.tagSet: GraphicStringPayloadDecoder(), 

1538 char.VisibleString.tagSet: VisibleStringPayloadDecoder(), 

1539 char.GeneralString.tagSet: GeneralStringPayloadDecoder(), 

1540 char.UniversalString.tagSet: UniversalStringPayloadDecoder(), 

1541 char.BMPString.tagSet: BMPStringPayloadDecoder(), 

1542 # useful types 

1543 useful.ObjectDescriptor.tagSet: ObjectDescriptorPayloadDecoder(), 

1544 useful.GeneralizedTime.tagSet: GeneralizedTimePayloadDecoder(), 

1545 useful.UTCTime.tagSet: UTCTimePayloadDecoder() 

1546} 

1547 

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

1549TYPE_MAP = { 

1550 univ.Set.typeId: SetPayloadDecoder(), 

1551 univ.SetOf.typeId: SetOfPayloadDecoder(), 

1552 univ.Sequence.typeId: SequencePayloadDecoder(), 

1553 univ.SequenceOf.typeId: SequenceOfPayloadDecoder(), 

1554 univ.Choice.typeId: ChoicePayloadDecoder(), 

1555 univ.Any.typeId: AnyPayloadDecoder() 

1556} 

1557 

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

1559for typeDecoder in TAG_MAP.values(): 

1560 if typeDecoder.protoComponent is not None: 

1561 typeId = typeDecoder.protoComponent.__class__.typeId 

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

1563 TYPE_MAP[typeId] = typeDecoder 

1564 

1565 

1566(stDecodeTag, 

1567 stDecodeLength, 

1568 stGetValueDecoder, 

1569 stGetValueDecoderByAsn1Spec, 

1570 stGetValueDecoderByTag, 

1571 stTryAsExplicitTag, 

1572 stDecodeValue, 

1573 stDumpRawValue, 

1574 stErrorCondition, 

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

1576 

1577 

1578EOO_SENTINEL = bytes((0, 0)) 

1579 

1580 

1581class SingleItemDecoder(object): 

1582 defaultErrorState = stErrorCondition 

1583 #defaultErrorState = stDumpRawValue 

1584 defaultRawDecoder = AnyPayloadDecoder() 

1585 

1586 supportIndefLength = True 

1587 

1588 TAG_MAP = TAG_MAP 

1589 TYPE_MAP = TYPE_MAP 

1590 

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

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

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

1594 

1595 # Tag & TagSet objects caches 

1596 self._tagCache = {} 

1597 self._tagSetCache = {} 

1598 

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

1600 tagSet=None, length=None, state=stDecodeTag, 

1601 decodeFun=None, substrateFun=None, 

1602 **options): 

1603 

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

1605 

1606 if _nestingLevel > MAX_NESTING_DEPTH: 

1607 raise error.PyAsn1Error( 

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

1609 ) 

1610 

1611 options['_nestingLevel'] = _nestingLevel + 1 

1612 

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

1614 

1615 if LOG: 

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

1617 'to %s octets of substrate: ' 

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

1619 

1620 # Look for end-of-octets sentinel 

1621 if allowEoo and self.supportIndefLength: 

1622 

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

1624 if isinstance(eoo_candidate, SubstrateUnderrunError): 

1625 yield eoo_candidate 

1626 

1627 if eoo_candidate == EOO_SENTINEL: 

1628 if LOG: 

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

1630 yield eoo.endOfOctets 

1631 return 

1632 

1633 else: 

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

1635 

1636 tagMap = self._tagMap 

1637 typeMap = self._typeMap 

1638 tagCache = self._tagCache 

1639 tagSetCache = self._tagSetCache 

1640 

1641 value = noValue 

1642 

1643 substrate.markedPosition = substrate.tell() 

1644 

1645 while state is not stStop: 

1646 

1647 if state is stDecodeTag: 

1648 # Decode tag 

1649 isShortTag = True 

1650 

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

1652 if isinstance(firstByte, SubstrateUnderrunError): 

1653 yield firstByte 

1654 

1655 firstOctet = ord(firstByte) 

1656 

1657 try: 

1658 lastTag = tagCache[firstOctet] 

1659 

1660 except KeyError: 

1661 integerTag = firstOctet 

1662 tagClass = integerTag & 0xC0 

1663 tagFormat = integerTag & 0x20 

1664 tagId = integerTag & 0x1F 

1665 

1666 if tagId == 0x1F: 

1667 isShortTag = False 

1668 tagOctetCount = 0 

1669 tagId = 0 

1670 

1671 while True: 

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

1673 if isinstance(integerByte, SubstrateUnderrunError): 

1674 yield integerByte 

1675 

1676 if not integerByte: 

1677 raise error.SubstrateUnderrunError( 

1678 'Short octet stream on long tag decoding' 

1679 ) 

1680 

1681 integerTag = ord(integerByte) 

1682 tagOctetCount += 1 

1683 if tagOctetCount > MAX_TAG_OCTETS: 

1684 raise error.PyAsn1Error( 

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

1686 MAX_TAG_OCTETS,) 

1687 ) 

1688 tagId <<= 7 

1689 tagId |= (integerTag & 0x7F) 

1690 

1691 if not integerTag & 0x80: 

1692 break 

1693 

1694 lastTag = tag.Tag( 

1695 tagClass=tagClass, tagFormat=tagFormat, tagId=tagId 

1696 ) 

1697 

1698 if isShortTag: 

1699 # cache short tags 

1700 tagCache[firstOctet] = lastTag 

1701 

1702 if tagSet is None: 

1703 if isShortTag: 

1704 try: 

1705 tagSet = tagSetCache[firstOctet] 

1706 

1707 except KeyError: 

1708 # base tag not recovered 

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

1710 tagSetCache[firstOctet] = tagSet 

1711 else: 

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

1713 

1714 else: 

1715 tagSet = lastTag + tagSet 

1716 

1717 state = stDecodeLength 

1718 

1719 if LOG: 

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

1721 

1722 if state is stDecodeLength: 

1723 # Decode length 

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

1725 if isinstance(firstOctet, SubstrateUnderrunError): 

1726 yield firstOctet 

1727 

1728 firstOctet = ord(firstOctet) 

1729 

1730 if firstOctet < 128: 

1731 length = firstOctet 

1732 

1733 elif firstOctet > 128: 

1734 size = firstOctet & 0x7F 

1735 

1736 if size > MAX_LENGTH_OCTETS: 

1737 raise error.PyAsn1Error( 

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

1739 size, MAX_LENGTH_OCTETS) 

1740 ) 

1741 

1742 # encoded in size bytes 

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

1744 if isinstance(encodedLength, SubstrateUnderrunError): 

1745 yield encodedLength 

1746 encodedLength = list(encodedLength) 

1747 if len(encodedLength) != size: 

1748 raise error.SubstrateUnderrunError( 

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

1750 ) 

1751 

1752 length = 0 

1753 for lengthOctet in encodedLength: 

1754 length <<= 8 

1755 length |= lengthOctet 

1756 size += 1 

1757 

1758 else: # 128 means indefinite 

1759 length = -1 

1760 

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

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

1763 

1764 state = stGetValueDecoder 

1765 

1766 if LOG: 

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

1768 

1769 if state is stGetValueDecoder: 

1770 if asn1Spec is None: 

1771 state = stGetValueDecoderByTag 

1772 

1773 else: 

1774 state = stGetValueDecoderByAsn1Spec 

1775 # 

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

1777 # decoder operation. These methods are: 

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

1779 # applied on subtyping. 

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

1781 # IMPLICIT tagging. 

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

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

1784 # decoding. 

1785 # 

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

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

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

1789 # from the wire. 

1790 # 

1791 if state is stGetValueDecoderByTag: 

1792 try: 

1793 concreteDecoder = tagMap[tagSet] 

1794 

1795 except KeyError: 

1796 concreteDecoder = None 

1797 

1798 if concreteDecoder: 

1799 state = stDecodeValue 

1800 

1801 else: 

1802 try: 

1803 concreteDecoder = tagMap[tagSet[:1]] 

1804 

1805 except KeyError: 

1806 concreteDecoder = None 

1807 

1808 if concreteDecoder: 

1809 state = stDecodeValue 

1810 else: 

1811 state = stTryAsExplicitTag 

1812 

1813 if LOG: 

1814 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')) 

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

1816 

1817 if state is stGetValueDecoderByAsn1Spec: 

1818 

1819 if asn1Spec.__class__ is tagmap.TagMap: 

1820 try: 

1821 chosenSpec = asn1Spec[tagSet] 

1822 

1823 except KeyError: 

1824 chosenSpec = None 

1825 

1826 if LOG: 

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

1828 

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

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

1831 

1832 if asn1Spec.skipTypes: 

1833 LOG('but neither of: ') 

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

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

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

1837 

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

1839 chosenSpec = asn1Spec 

1840 if LOG: 

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

1842 

1843 else: 

1844 chosenSpec = None 

1845 

1846 if chosenSpec is not None: 

1847 try: 

1848 # ambiguous type or just faster codec lookup 

1849 concreteDecoder = typeMap[chosenSpec.typeId] 

1850 

1851 if LOG: 

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

1853 

1854 except KeyError: 

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

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

1857 try: 

1858 # base type or tagged subtype 

1859 concreteDecoder = tagMap[baseTagSet] 

1860 

1861 if LOG: 

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

1863 

1864 except KeyError: 

1865 concreteDecoder = None 

1866 

1867 if concreteDecoder: 

1868 asn1Spec = chosenSpec 

1869 state = stDecodeValue 

1870 

1871 else: 

1872 state = stTryAsExplicitTag 

1873 

1874 else: 

1875 concreteDecoder = None 

1876 state = stTryAsExplicitTag 

1877 

1878 if LOG: 

1879 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')) 

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

1881 

1882 if state is stDecodeValue: 

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

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

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

1886 

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

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

1889 recursiveFlag. 

1890 """ 

1891 yield asn1Object 

1892 

1893 original_position = substrate.tell() 

1894 

1895 if length == -1: # indef length 

1896 for value in concreteDecoder.indefLenValueDecoder( 

1897 substrate, asn1Spec, 

1898 tagSet, length, stGetValueDecoder, 

1899 self, substrateFun, **options): 

1900 if isinstance(value, SubstrateUnderrunError): 

1901 yield value 

1902 

1903 else: 

1904 for value in concreteDecoder.valueDecoder( 

1905 substrate, asn1Spec, 

1906 tagSet, length, stGetValueDecoder, 

1907 self, substrateFun, **options): 

1908 if isinstance(value, SubstrateUnderrunError): 

1909 yield value 

1910 

1911 bytesRead = substrate.tell() - original_position 

1912 if not substrateFun and bytesRead != length: 

1913 raise PyAsn1Error( 

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

1915 elif substrateFun and bytesRead > length: 

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

1917 raise PyAsn1Error( 

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

1919 

1920 if LOG: 

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

1922 concreteDecoder.__class__.__name__, value.__class__.__name__, 

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

1924 

1925 state = stStop 

1926 break 

1927 

1928 if state is stTryAsExplicitTag: 

1929 if (tagSet and 

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

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

1932 # Assume explicit tagging 

1933 concreteDecoder = rawPayloadDecoder 

1934 state = stDecodeValue 

1935 

1936 else: 

1937 concreteDecoder = None 

1938 state = self.defaultErrorState 

1939 

1940 if LOG: 

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

1942 

1943 if state is stDumpRawValue: 

1944 concreteDecoder = self.defaultRawDecoder 

1945 

1946 if LOG: 

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

1948 

1949 state = stDecodeValue 

1950 

1951 if state is stErrorCondition: 

1952 raise error.PyAsn1Error( 

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

1954 ) 

1955 

1956 if LOG: 

1957 debug.scope.pop() 

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

1959 

1960 yield value 

1961 

1962 

1963class StreamingDecoder(object): 

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

1965 

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

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

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

1969 

1970 Parameters 

1971 ---------- 

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

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

1974 

1975 Keyword Args 

1976 ------------ 

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

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

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

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

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

1982 tagging mode. 

1983 

1984 Yields 

1985 ------ 

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

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

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

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

1990 objects from it. 

1991 

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

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

1994 the decoding process using the newly arrived data. 

1995 

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

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

1998 being reconstructed. 

1999 

2000 Raises 

2001 ------ 

2002 ~pyasn1.error.PyAsn1Error, ~pyasn1.error.EndOfStreamError 

2003 `PyAsn1Error` on deserialization error, `EndOfStreamError` on 

2004 premature stream closure. 

2005 

2006 Examples 

2007 -------- 

2008 Decode BER serialisation without ASN.1 schema 

2009 

2010 .. code-block:: pycon 

2011 

2012 >>> stream = io.BytesIO( 

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

2014 >>> 

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

2016 ... print(asn1Object) 

2017 >>> 

2018 SequenceOf: 

2019 1 2 3 

2020 

2021 Decode BER serialisation with ASN.1 schema 

2022 

2023 .. code-block:: pycon 

2024 

2025 >>> stream = io.BytesIO( 

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

2027 >>> 

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

2029 >>> 

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

2031 >>> for asn1Object in decoder: 

2032 ... print(asn1Object) 

2033 >>> 

2034 SequenceOf: 

2035 1 2 3 

2036 """ 

2037 

2038 SINGLE_ITEM_DECODER = SingleItemDecoder 

2039 

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

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

2042 self._substrate = asSeekableStream(substrate) 

2043 self._asn1Spec = asn1Spec 

2044 self._options = options 

2045 

2046 def __iter__(self): 

2047 while True: 

2048 for asn1Object in self._singleItemDecoder( 

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

2050 yield asn1Object 

2051 

2052 for chunk in isEndOfStream(self._substrate): 

2053 if isinstance(chunk, SubstrateUnderrunError): 

2054 yield 

2055 

2056 break 

2057 

2058 if chunk: 

2059 break 

2060 

2061 

2062class Decoder(object): 

2063 """Create a BER decoder object. 

2064 

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

2066 """ 

2067 STREAMING_DECODER = StreamingDecoder 

2068 

2069 @classmethod 

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

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

2072 

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

2074 and decode it into an ASN.1 object 

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

2076 may be a scalar or an arbitrary nested structure. 

2077 

2078 Parameters 

2079 ---------- 

2080 substrate: :py:class:`bytes` 

2081 BER/CER/DER octet-stream to parse 

2082 

2083 Keyword Args 

2084 ------------ 

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

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

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

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

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

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

2091 

2092 substrateFun: :py:class:`Union[ 

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

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

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

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

2097 pyasn1.error.SubstrateUnderrunError], 

2098 None, None]] 

2099 ]` 

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

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

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

2103 The callback will receive the uninitialized object recovered from substrate 

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

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

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

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

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

2109 decode passes as 2nd item. 

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

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

2112 

2113 Returns 

2114 ------- 

2115 : :py:class:`tuple` 

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

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

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

2119 

2120 Raises 

2121 ------ 

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

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

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

2125 

2126 Examples 

2127 -------- 

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

2129 

2130 .. code-block:: pycon 

2131 

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

2133 >>> str(s) 

2134 SequenceOf: 

2135 1 2 3 

2136 

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

2138 

2139 .. code-block:: pycon 

2140 

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

2142 >>> s, unprocessed = decode( 

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

2144 >>> str(s) 

2145 SequenceOf: 

2146 1 2 3 

2147 

2148 """ 

2149 substrate = asSeekableStream(substrate) 

2150 

2151 if "substrateFun" in options: 

2152 origSubstrateFun = options["substrateFun"] 

2153 

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

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

2156 

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

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

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

2160 """ 

2161 try: 

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

2163 except TypeError as _value: 

2164 if _value.__traceback__.tb_next: 

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

2166 raise 

2167 # invariant maintained at Decoder.__call__ entry 

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

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

2170 for value in substrate_gen: 

2171 yield value 

2172 

2173 options["substrateFun"] = substrateFunWrapper 

2174 

2175 streamingDecoder = cls.STREAMING_DECODER( 

2176 substrate, asn1Spec, **options) 

2177 

2178 for asn1Object in streamingDecoder: 

2179 if isinstance(asn1Object, SubstrateUnderrunError): 

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

2181 

2182 try: 

2183 tail = next(readFromStream(substrate)) 

2184 

2185 except error.EndOfStreamError: 

2186 tail = b'' 

2187 

2188 return asn1Object, tail 

2189 

2190 @staticmethod 

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

2192 substrate_bytes = substrate.read() 

2193 if length == -1: 

2194 length = len(substrate_bytes) 

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

2196 nbytes = substrate.write(nextSubstrate) 

2197 substrate.truncate() 

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

2199 yield value 

2200 

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

2202#: 

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

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

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

2206#: 

2207#: Parameters 

2208#: ---------- 

2209#: substrate: :py:class:`bytes` 

2210#: BER octet-stream 

2211#: 

2212#: Keyword Args 

2213#: ------------ 

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

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

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

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

2218#: 

2219#: Returns 

2220#: ------- 

2221#: : :py:class:`tuple` 

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

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

2224#: 

2225#: Raises 

2226#: ------ 

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

2228#: On decoding errors 

2229#: 

2230#: Notes 

2231#: ----- 

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

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

2234#: 

2235#: Examples 

2236#: -------- 

2237#: Decode BER serialisation without ASN.1 schema 

2238#: 

2239#: .. code-block:: pycon 

2240#: 

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

2242#: >>> str(s) 

2243#: SequenceOf: 

2244#: 1 2 3 

2245#: 

2246#: Decode BER serialisation with ASN.1 schema 

2247#: 

2248#: .. code-block:: pycon 

2249#: 

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

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

2252#: >>> str(s) 

2253#: SequenceOf: 

2254#: 1 2 3 

2255#: 

2256decode = Decoder() 

2257 

2258def __getattr__(attr: str): 

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

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

2261 return globals()[newAttr] 

2262 raise AttributeError(attr)