You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							1683 lines
						
					
					
						
							58 KiB
						
					
					
				
			
		
		
	
	
							1683 lines
						
					
					
						
							58 KiB
						
					
					
				#
 | 
						|
# This file is part of pyasn1 software.
 | 
						|
#
 | 
						|
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
 | 
						|
# License: http://snmplabs.com/pyasn1/license.html
 | 
						|
#
 | 
						|
from pyasn1 import debug
 | 
						|
from pyasn1 import error
 | 
						|
from pyasn1.codec.ber import eoo
 | 
						|
from pyasn1.compat.integer import from_bytes
 | 
						|
from pyasn1.compat.octets import oct2int, octs2ints, ints2octs, null
 | 
						|
from pyasn1.type import base
 | 
						|
from pyasn1.type import char
 | 
						|
from pyasn1.type import tag
 | 
						|
from pyasn1.type import tagmap
 | 
						|
from pyasn1.type import univ
 | 
						|
from pyasn1.type import useful
 | 
						|
 | 
						|
__all__ = ['decode']
 | 
						|
 | 
						|
LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER)
 | 
						|
 | 
						|
noValue = base.noValue
 | 
						|
 | 
						|
 | 
						|
class AbstractDecoder(object):
 | 
						|
    protoComponent = None
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
        raise error.PyAsn1Error('Decoder not implemented for %s' % (tagSet,))
 | 
						|
 | 
						|
    def indefLenValueDecoder(self, substrate, asn1Spec,
 | 
						|
                             tagSet=None, length=None, state=None,
 | 
						|
                             decodeFun=None, substrateFun=None,
 | 
						|
                             **options):
 | 
						|
        raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,))
 | 
						|
 | 
						|
 | 
						|
class AbstractSimpleDecoder(AbstractDecoder):
 | 
						|
    @staticmethod
 | 
						|
    def substrateCollector(asn1Object, substrate, length):
 | 
						|
        return substrate[:length], substrate[length:]
 | 
						|
 | 
						|
    def _createComponent(self, asn1Spec, tagSet, value, **options):
 | 
						|
        if options.get('native'):
 | 
						|
            return value
 | 
						|
        elif asn1Spec is None:
 | 
						|
            return self.protoComponent.clone(value, tagSet=tagSet)
 | 
						|
        elif value is noValue:
 | 
						|
            return asn1Spec
 | 
						|
        else:
 | 
						|
            return asn1Spec.clone(value)
 | 
						|
 | 
						|
 | 
						|
class ExplicitTagDecoder(AbstractSimpleDecoder):
 | 
						|
    protoComponent = univ.Any('')
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
        if substrateFun:
 | 
						|
            return substrateFun(
 | 
						|
                self._createComponent(asn1Spec, tagSet, '', **options),
 | 
						|
                substrate, length
 | 
						|
            )
 | 
						|
 | 
						|
        head, tail = substrate[:length], substrate[length:]
 | 
						|
 | 
						|
        value, _ = decodeFun(head, asn1Spec, tagSet, length, **options)
 | 
						|
 | 
						|
        if LOG:
 | 
						|
            LOG('explicit tag container carries %d octets of trailing payload '
 | 
						|
                '(will be lost!): %s' % (len(_), debug.hexdump(_)))
 | 
						|
 | 
						|
        return value, tail
 | 
						|
 | 
						|
    def indefLenValueDecoder(self, substrate, asn1Spec,
 | 
						|
                             tagSet=None, length=None, state=None,
 | 
						|
                             decodeFun=None, substrateFun=None,
 | 
						|
                             **options):
 | 
						|
        if substrateFun:
 | 
						|
            return substrateFun(
 | 
						|
                self._createComponent(asn1Spec, tagSet, '', **options),
 | 
						|
                substrate, length
 | 
						|
            )
 | 
						|
 | 
						|
        value, substrate = decodeFun(substrate, asn1Spec, tagSet, length, **options)
 | 
						|
 | 
						|
        eooMarker, substrate = decodeFun(substrate, allowEoo=True, **options)
 | 
						|
 | 
						|
        if eooMarker is eoo.endOfOctets:
 | 
						|
            return value, substrate
 | 
						|
        else:
 | 
						|
            raise error.PyAsn1Error('Missing end-of-octets terminator')
 | 
						|
 | 
						|
 | 
						|
explicitTagDecoder = ExplicitTagDecoder()
 | 
						|
 | 
						|
 | 
						|
class IntegerDecoder(AbstractSimpleDecoder):
 | 
						|
    protoComponent = univ.Integer(0)
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
 | 
						|
        if tagSet[0].tagFormat != tag.tagFormatSimple:
 | 
						|
            raise error.PyAsn1Error('Simple tag format expected')
 | 
						|
 | 
						|
        head, tail = substrate[:length], substrate[length:]
 | 
						|
 | 
						|
        if not head:
 | 
						|
            return self._createComponent(asn1Spec, tagSet, 0, **options), tail
 | 
						|
 | 
						|
        value = from_bytes(head, signed=True)
 | 
						|
 | 
						|
        return self._createComponent(asn1Spec, tagSet, value, **options), tail
 | 
						|
 | 
						|
 | 
						|
class BooleanDecoder(IntegerDecoder):
 | 
						|
    protoComponent = univ.Boolean(0)
 | 
						|
 | 
						|
    def _createComponent(self, asn1Spec, tagSet, value, **options):
 | 
						|
        return IntegerDecoder._createComponent(
 | 
						|
            self, asn1Spec, tagSet, value and 1 or 0, **options)
 | 
						|
 | 
						|
 | 
						|
class BitStringDecoder(AbstractSimpleDecoder):
 | 
						|
    protoComponent = univ.BitString(())
 | 
						|
    supportConstructedForm = True
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
        head, tail = substrate[:length], substrate[length:]
 | 
						|
 | 
						|
        if substrateFun:
 | 
						|
            return substrateFun(self._createComponent(
 | 
						|
                asn1Spec, tagSet, noValue, **options), substrate, length)
 | 
						|
 | 
						|
        if not head:
 | 
						|
            raise error.PyAsn1Error('Empty BIT STRING substrate')
 | 
						|
 | 
						|
        if tagSet[0].tagFormat == tag.tagFormatSimple:  # XXX what tag to check?
 | 
						|
 | 
						|
            trailingBits = oct2int(head[0])
 | 
						|
            if trailingBits > 7:
 | 
						|
                raise error.PyAsn1Error(
 | 
						|
                    'Trailing bits overflow %s' % trailingBits
 | 
						|
                )
 | 
						|
 | 
						|
            value = self.protoComponent.fromOctetString(
 | 
						|
                head[1:], internalFormat=True, padding=trailingBits)
 | 
						|
 | 
						|
            return self._createComponent(asn1Spec, tagSet, value, **options), tail
 | 
						|
 | 
						|
        if not self.supportConstructedForm:
 | 
						|
            raise error.PyAsn1Error('Constructed encoding form prohibited '
 | 
						|
                                    'at %s' % self.__class__.__name__)
 | 
						|
 | 
						|
        if LOG:
 | 
						|
            LOG('assembling constructed serialization')
 | 
						|
 | 
						|
        # All inner fragments are of the same type, treat them as octet string
 | 
						|
        substrateFun = self.substrateCollector
 | 
						|
 | 
						|
        bitString = self.protoComponent.fromOctetString(null, internalFormat=True)
 | 
						|
 | 
						|
        while head:
 | 
						|
            component, head = decodeFun(head, self.protoComponent,
 | 
						|
                                        substrateFun=substrateFun, **options)
 | 
						|
 | 
						|
            trailingBits = oct2int(component[0])
 | 
						|
            if trailingBits > 7:
 | 
						|
                raise error.PyAsn1Error(
 | 
						|
                    'Trailing bits overflow %s' % trailingBits
 | 
						|
                )
 | 
						|
 | 
						|
            bitString = self.protoComponent.fromOctetString(
 | 
						|
                component[1:], internalFormat=True,
 | 
						|
                prepend=bitString, padding=trailingBits
 | 
						|
            )
 | 
						|
 | 
						|
        return self._createComponent(asn1Spec, tagSet, bitString, **options), tail
 | 
						|
 | 
						|
    def indefLenValueDecoder(self, substrate, asn1Spec,
 | 
						|
                             tagSet=None, length=None, state=None,
 | 
						|
                             decodeFun=None, substrateFun=None,
 | 
						|
                             **options):
 | 
						|
 | 
						|
        if substrateFun:
 | 
						|
            return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options), substrate, length)
 | 
						|
 | 
						|
        # All inner fragments are of the same type, treat them as octet string
 | 
						|
        substrateFun = self.substrateCollector
 | 
						|
 | 
						|
        bitString = self.protoComponent.fromOctetString(null, internalFormat=True)
 | 
						|
 | 
						|
        while substrate:
 | 
						|
            component, substrate = decodeFun(substrate, self.protoComponent,
 | 
						|
                                             substrateFun=substrateFun,
 | 
						|
                                             allowEoo=True, **options)
 | 
						|
            if component is eoo.endOfOctets:
 | 
						|
                break
 | 
						|
 | 
						|
            trailingBits = oct2int(component[0])
 | 
						|
            if trailingBits > 7:
 | 
						|
                raise error.PyAsn1Error(
 | 
						|
                    'Trailing bits overflow %s' % trailingBits
 | 
						|
                )
 | 
						|
 | 
						|
            bitString = self.protoComponent.fromOctetString(
 | 
						|
                component[1:], internalFormat=True,
 | 
						|
                prepend=bitString, padding=trailingBits
 | 
						|
            )
 | 
						|
 | 
						|
        else:
 | 
						|
            raise error.SubstrateUnderrunError('No EOO seen before substrate ends')
 | 
						|
 | 
						|
        return self._createComponent(asn1Spec, tagSet, bitString, **options), substrate
 | 
						|
 | 
						|
 | 
						|
class OctetStringDecoder(AbstractSimpleDecoder):
 | 
						|
    protoComponent = univ.OctetString('')
 | 
						|
    supportConstructedForm = True
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
        head, tail = substrate[:length], substrate[length:]
 | 
						|
 | 
						|
        if substrateFun:
 | 
						|
            return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options),
 | 
						|
                                substrate, length)
 | 
						|
 | 
						|
        if tagSet[0].tagFormat == tag.tagFormatSimple:  # XXX what tag to check?
 | 
						|
            return self._createComponent(asn1Spec, tagSet, head, **options), tail
 | 
						|
 | 
						|
        if not self.supportConstructedForm:
 | 
						|
            raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__)
 | 
						|
 | 
						|
        if LOG:
 | 
						|
            LOG('assembling constructed serialization')
 | 
						|
 | 
						|
        # All inner fragments are of the same type, treat them as octet string
 | 
						|
        substrateFun = self.substrateCollector
 | 
						|
 | 
						|
        header = null
 | 
						|
 | 
						|
        while head:
 | 
						|
            component, head = decodeFun(head, self.protoComponent,
 | 
						|
                                        substrateFun=substrateFun,
 | 
						|
                                        **options)
 | 
						|
            header += component
 | 
						|
 | 
						|
        return self._createComponent(asn1Spec, tagSet, header, **options), tail
 | 
						|
 | 
						|
    def indefLenValueDecoder(self, substrate, asn1Spec,
 | 
						|
                             tagSet=None, length=None, state=None,
 | 
						|
                             decodeFun=None, substrateFun=None,
 | 
						|
                             **options):
 | 
						|
        if substrateFun and substrateFun is not self.substrateCollector:
 | 
						|
            asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)
 | 
						|
            return substrateFun(asn1Object, substrate, length)
 | 
						|
 | 
						|
        # All inner fragments are of the same type, treat them as octet string
 | 
						|
        substrateFun = self.substrateCollector
 | 
						|
 | 
						|
        header = null
 | 
						|
 | 
						|
        while substrate:
 | 
						|
            component, substrate = decodeFun(substrate,
 | 
						|
                                             self.protoComponent,
 | 
						|
                                             substrateFun=substrateFun,
 | 
						|
                                             allowEoo=True, **options)
 | 
						|
            if component is eoo.endOfOctets:
 | 
						|
                break
 | 
						|
 | 
						|
            header += component
 | 
						|
 | 
						|
        else:
 | 
						|
            raise error.SubstrateUnderrunError(
 | 
						|
                'No EOO seen before substrate ends'
 | 
						|
            )
 | 
						|
 | 
						|
        return self._createComponent(asn1Spec, tagSet, header, **options), substrate
 | 
						|
 | 
						|
 | 
						|
class NullDecoder(AbstractSimpleDecoder):
 | 
						|
    protoComponent = univ.Null('')
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
 | 
						|
        if tagSet[0].tagFormat != tag.tagFormatSimple:
 | 
						|
            raise error.PyAsn1Error('Simple tag format expected')
 | 
						|
 | 
						|
        head, tail = substrate[:length], substrate[length:]
 | 
						|
 | 
						|
        component = self._createComponent(asn1Spec, tagSet, '', **options)
 | 
						|
 | 
						|
        if head:
 | 
						|
            raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length)
 | 
						|
 | 
						|
        return component, tail
 | 
						|
 | 
						|
 | 
						|
class ObjectIdentifierDecoder(AbstractSimpleDecoder):
 | 
						|
    protoComponent = univ.ObjectIdentifier(())
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
        if tagSet[0].tagFormat != tag.tagFormatSimple:
 | 
						|
            raise error.PyAsn1Error('Simple tag format expected')
 | 
						|
 | 
						|
        head, tail = substrate[:length], substrate[length:]
 | 
						|
        if not head:
 | 
						|
            raise error.PyAsn1Error('Empty substrate')
 | 
						|
 | 
						|
        head = octs2ints(head)
 | 
						|
 | 
						|
        oid = ()
 | 
						|
        index = 0
 | 
						|
        substrateLen = len(head)
 | 
						|
        while index < substrateLen:
 | 
						|
            subId = head[index]
 | 
						|
            index += 1
 | 
						|
            if subId < 128:
 | 
						|
                oid += (subId,)
 | 
						|
            elif subId > 128:
 | 
						|
                # Construct subid from a number of octets
 | 
						|
                nextSubId = subId
 | 
						|
                subId = 0
 | 
						|
                while nextSubId >= 128:
 | 
						|
                    subId = (subId << 7) + (nextSubId & 0x7F)
 | 
						|
                    if index >= substrateLen:
 | 
						|
                        raise error.SubstrateUnderrunError(
 | 
						|
                            'Short substrate for sub-OID past %s' % (oid,)
 | 
						|
                        )
 | 
						|
                    nextSubId = head[index]
 | 
						|
                    index += 1
 | 
						|
                oid += ((subId << 7) + nextSubId,)
 | 
						|
            elif subId == 128:
 | 
						|
                # ASN.1 spec forbids leading zeros (0x80) in OID
 | 
						|
                # encoding, tolerating it opens a vulnerability. See
 | 
						|
                # https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf
 | 
						|
                # page 7
 | 
						|
                raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding')
 | 
						|
 | 
						|
        # Decode two leading arcs
 | 
						|
        if 0 <= oid[0] <= 39:
 | 
						|
            oid = (0,) + oid
 | 
						|
        elif 40 <= oid[0] <= 79:
 | 
						|
            oid = (1, oid[0] - 40) + oid[1:]
 | 
						|
        elif oid[0] >= 80:
 | 
						|
            oid = (2, oid[0] - 80) + oid[1:]
 | 
						|
        else:
 | 
						|
            raise error.PyAsn1Error('Malformed first OID octet: %s' % head[0])
 | 
						|
 | 
						|
        return self._createComponent(asn1Spec, tagSet, oid, **options), tail
 | 
						|
 | 
						|
 | 
						|
class RealDecoder(AbstractSimpleDecoder):
 | 
						|
    protoComponent = univ.Real()
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
        if tagSet[0].tagFormat != tag.tagFormatSimple:
 | 
						|
            raise error.PyAsn1Error('Simple tag format expected')
 | 
						|
 | 
						|
        head, tail = substrate[:length], substrate[length:]
 | 
						|
 | 
						|
        if not head:
 | 
						|
            return self._createComponent(asn1Spec, tagSet, 0.0, **options), tail
 | 
						|
 | 
						|
        fo = oct2int(head[0])
 | 
						|
        head = head[1:]
 | 
						|
        if fo & 0x80:  # binary encoding
 | 
						|
            if not head:
 | 
						|
                raise error.PyAsn1Error("Incomplete floating-point value")
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding binary encoded REAL')
 | 
						|
 | 
						|
            n = (fo & 0x03) + 1
 | 
						|
 | 
						|
            if n == 4:
 | 
						|
                n = oct2int(head[0])
 | 
						|
                head = head[1:]
 | 
						|
 | 
						|
            eo, head = head[:n], head[n:]
 | 
						|
 | 
						|
            if not eo or not head:
 | 
						|
                raise error.PyAsn1Error('Real exponent screwed')
 | 
						|
 | 
						|
            e = oct2int(eo[0]) & 0x80 and -1 or 0
 | 
						|
 | 
						|
            while eo:  # exponent
 | 
						|
                e <<= 8
 | 
						|
                e |= oct2int(eo[0])
 | 
						|
                eo = eo[1:]
 | 
						|
 | 
						|
            b = fo >> 4 & 0x03  # base bits
 | 
						|
 | 
						|
            if b > 2:
 | 
						|
                raise error.PyAsn1Error('Illegal Real base')
 | 
						|
 | 
						|
            if b == 1:  # encbase = 8
 | 
						|
                e *= 3
 | 
						|
 | 
						|
            elif b == 2:  # encbase = 16
 | 
						|
                e *= 4
 | 
						|
            p = 0
 | 
						|
 | 
						|
            while head:  # value
 | 
						|
                p <<= 8
 | 
						|
                p |= oct2int(head[0])
 | 
						|
                head = head[1:]
 | 
						|
 | 
						|
            if fo & 0x40:  # sign bit
 | 
						|
                p = -p
 | 
						|
 | 
						|
            sf = fo >> 2 & 0x03  # scale bits
 | 
						|
            p *= 2 ** sf
 | 
						|
            value = (p, 2, e)
 | 
						|
 | 
						|
        elif fo & 0x40:  # infinite value
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding infinite REAL')
 | 
						|
 | 
						|
            value = fo & 0x01 and '-inf' or 'inf'
 | 
						|
 | 
						|
        elif fo & 0xc0 == 0:  # character encoding
 | 
						|
            if not head:
 | 
						|
                raise error.PyAsn1Error("Incomplete floating-point value")
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding character encoded REAL')
 | 
						|
 | 
						|
            try:
 | 
						|
                if fo & 0x3 == 0x1:  # NR1
 | 
						|
                    value = (int(head), 10, 0)
 | 
						|
 | 
						|
                elif fo & 0x3 == 0x2:  # NR2
 | 
						|
                    value = float(head)
 | 
						|
 | 
						|
                elif fo & 0x3 == 0x3:  # NR3
 | 
						|
                    value = float(head)
 | 
						|
 | 
						|
                else:
 | 
						|
                    raise error.SubstrateUnderrunError(
 | 
						|
                        'Unknown NR (tag %s)' % fo
 | 
						|
                    )
 | 
						|
 | 
						|
            except ValueError:
 | 
						|
                raise error.SubstrateUnderrunError(
 | 
						|
                    'Bad character Real syntax'
 | 
						|
                )
 | 
						|
 | 
						|
        else:
 | 
						|
            raise error.SubstrateUnderrunError(
 | 
						|
                'Unknown encoding (tag %s)' % fo
 | 
						|
            )
 | 
						|
 | 
						|
        return self._createComponent(asn1Spec, tagSet, value, **options), tail
 | 
						|
 | 
						|
 | 
						|
class AbstractConstructedDecoder(AbstractDecoder):
 | 
						|
    protoComponent = None
 | 
						|
 | 
						|
 | 
						|
class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
 | 
						|
    protoRecordComponent = None
 | 
						|
    protoSequenceComponent = None
 | 
						|
 | 
						|
    def _getComponentTagMap(self, asn1Object, idx):
 | 
						|
        raise NotImplementedError()
 | 
						|
 | 
						|
    def _getComponentPositionByType(self, asn1Object, tagSet, idx):
 | 
						|
        raise NotImplementedError()
 | 
						|
 | 
						|
    def _decodeComponents(self, substrate, tagSet=None, decodeFun=None, **options):
 | 
						|
        components = []
 | 
						|
        componentTypes = set()
 | 
						|
 | 
						|
        while substrate:
 | 
						|
            component, substrate = decodeFun(substrate, **options)
 | 
						|
            if component is eoo.endOfOctets:
 | 
						|
                break
 | 
						|
 | 
						|
            components.append(component)
 | 
						|
            componentTypes.add(component.tagSet)
 | 
						|
 | 
						|
        # Now we have to guess is it SEQUENCE/SET or SEQUENCE OF/SET OF
 | 
						|
        # The heuristics is:
 | 
						|
        # * 1+ components of different types -> likely SEQUENCE/SET
 | 
						|
        # * otherwise -> likely SEQUENCE OF/SET OF
 | 
						|
        if len(componentTypes) > 1:
 | 
						|
            protoComponent = self.protoRecordComponent
 | 
						|
 | 
						|
        else:
 | 
						|
            protoComponent = self.protoSequenceComponent
 | 
						|
 | 
						|
        asn1Object = protoComponent.clone(
 | 
						|
            # construct tagSet from base tag from prototype ASN.1 object
 | 
						|
            # and additional tags recovered from the substrate
 | 
						|
            tagSet=tag.TagSet(protoComponent.tagSet.baseTag, *tagSet.superTags)
 | 
						|
        )
 | 
						|
 | 
						|
        if LOG:
 | 
						|
            LOG('guessed %r container type (pass `asn1Spec` to guide the '
 | 
						|
                'decoder)' % asn1Object)
 | 
						|
 | 
						|
        for idx, component in enumerate(components):
 | 
						|
            asn1Object.setComponentByPosition(
 | 
						|
                idx, component,
 | 
						|
                verifyConstraints=False,
 | 
						|
                matchTags=False, matchConstraints=False
 | 
						|
            )
 | 
						|
 | 
						|
        return asn1Object, substrate
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
        if tagSet[0].tagFormat != tag.tagFormatConstructed:
 | 
						|
            raise error.PyAsn1Error('Constructed tag format expected')
 | 
						|
 | 
						|
        head, tail = substrate[:length], substrate[length:]
 | 
						|
 | 
						|
        if substrateFun is not None:
 | 
						|
            if asn1Spec is not None:
 | 
						|
                asn1Object = asn1Spec.clone()
 | 
						|
 | 
						|
            elif self.protoComponent is not None:
 | 
						|
                asn1Object = self.protoComponent.clone(tagSet=tagSet)
 | 
						|
 | 
						|
            else:
 | 
						|
                asn1Object = self.protoRecordComponent, self.protoSequenceComponent
 | 
						|
 | 
						|
            return substrateFun(asn1Object, substrate, length)
 | 
						|
 | 
						|
        if asn1Spec is None:
 | 
						|
            asn1Object, trailing = self._decodeComponents(
 | 
						|
                head, tagSet=tagSet, decodeFun=decodeFun, **options
 | 
						|
            )
 | 
						|
 | 
						|
            if trailing:
 | 
						|
                if LOG:
 | 
						|
                    LOG('Unused trailing %d octets encountered: %s' % (
 | 
						|
                        len(trailing), debug.hexdump(trailing)))
 | 
						|
 | 
						|
            return asn1Object, tail
 | 
						|
 | 
						|
        asn1Object = asn1Spec.clone()
 | 
						|
        asn1Object.clear()
 | 
						|
 | 
						|
        if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId):
 | 
						|
 | 
						|
            namedTypes = asn1Spec.componentType
 | 
						|
 | 
						|
            isSetType = asn1Spec.typeId == univ.Set.typeId
 | 
						|
            isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding %sdeterministic %s type %r chosen by type ID' % (
 | 
						|
                    not isDeterministic and 'non-' or '', isSetType and 'SET' or '',
 | 
						|
                    asn1Spec))
 | 
						|
 | 
						|
            seenIndices = set()
 | 
						|
            idx = 0
 | 
						|
            while head:
 | 
						|
                if not namedTypes:
 | 
						|
                    componentType = None
 | 
						|
 | 
						|
                elif isSetType:
 | 
						|
                    componentType = namedTypes.tagMapUnique
 | 
						|
 | 
						|
                else:
 | 
						|
                    try:
 | 
						|
                        if isDeterministic:
 | 
						|
                            componentType = namedTypes[idx].asn1Object
 | 
						|
 | 
						|
                        elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
 | 
						|
                            componentType = namedTypes.getTagMapNearPosition(idx)
 | 
						|
 | 
						|
                        else:
 | 
						|
                            componentType = namedTypes[idx].asn1Object
 | 
						|
 | 
						|
                    except IndexError:
 | 
						|
                        raise error.PyAsn1Error(
 | 
						|
                            'Excessive components decoded at %r' % (asn1Spec,)
 | 
						|
                        )
 | 
						|
 | 
						|
                component, head = decodeFun(head, componentType, **options)
 | 
						|
 | 
						|
                if not isDeterministic and namedTypes:
 | 
						|
                    if isSetType:
 | 
						|
                        idx = namedTypes.getPositionByType(component.effectiveTagSet)
 | 
						|
 | 
						|
                    elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
 | 
						|
                        idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx)
 | 
						|
 | 
						|
                asn1Object.setComponentByPosition(
 | 
						|
                    idx, component,
 | 
						|
                    verifyConstraints=False,
 | 
						|
                    matchTags=False, matchConstraints=False
 | 
						|
                )
 | 
						|
 | 
						|
                seenIndices.add(idx)
 | 
						|
                idx += 1
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('seen component indices %s' % seenIndices)
 | 
						|
 | 
						|
            if namedTypes:
 | 
						|
                if not namedTypes.requiredComponents.issubset(seenIndices):
 | 
						|
                    raise error.PyAsn1Error(
 | 
						|
                        'ASN.1 object %s has uninitialized '
 | 
						|
                        'components' % asn1Object.__class__.__name__)
 | 
						|
 | 
						|
                if  namedTypes.hasOpenTypes:
 | 
						|
 | 
						|
                    openTypes = options.get('openTypes', {})
 | 
						|
 | 
						|
                    if LOG:
 | 
						|
                        LOG('user-specified open types map:')
 | 
						|
 | 
						|
                        for k, v in openTypes.items():
 | 
						|
                            LOG('%s -> %r' % (k, v))
 | 
						|
 | 
						|
                    if openTypes or options.get('decodeOpenTypes', False):
 | 
						|
 | 
						|
                        for idx, namedType in enumerate(namedTypes.namedTypes):
 | 
						|
                            if not namedType.openType:
 | 
						|
                                continue
 | 
						|
 | 
						|
                            if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue:
 | 
						|
                                continue
 | 
						|
 | 
						|
                            governingValue = asn1Object.getComponentByName(
 | 
						|
                                namedType.openType.name
 | 
						|
                            )
 | 
						|
 | 
						|
                            try:
 | 
						|
                                openType = openTypes[governingValue]
 | 
						|
 | 
						|
                            except KeyError:
 | 
						|
 | 
						|
                                if LOG:
 | 
						|
                                    LOG('default open types map of component '
 | 
						|
                                        '"%s.%s" governed by component "%s.%s"'
 | 
						|
                                        ':' % (asn1Object.__class__.__name__,
 | 
						|
                                               namedType.name,
 | 
						|
                                               asn1Object.__class__.__name__,
 | 
						|
                                               namedType.openType.name))
 | 
						|
 | 
						|
                                    for k, v in namedType.openType.items():
 | 
						|
                                        LOG('%s -> %r' % (k, v))
 | 
						|
 | 
						|
                                try:
 | 
						|
                                    openType = namedType.openType[governingValue]
 | 
						|
 | 
						|
                                except KeyError:
 | 
						|
                                    if LOG:
 | 
						|
                                        LOG('failed to resolve open type by governing '
 | 
						|
                                            'value %r' % (governingValue,))
 | 
						|
                                    continue
 | 
						|
 | 
						|
                            if LOG:
 | 
						|
                                LOG('resolved open type %r by governing '
 | 
						|
                                    'value %r' % (openType, governingValue))
 | 
						|
 | 
						|
                            containerValue = asn1Object.getComponentByPosition(idx)
 | 
						|
 | 
						|
                            if containerValue.typeId in (
 | 
						|
                                    univ.SetOf.typeId, univ.SequenceOf.typeId):
 | 
						|
 | 
						|
                                for pos, containerElement in enumerate(
 | 
						|
                                        containerValue):
 | 
						|
 | 
						|
                                    component, rest = decodeFun(
 | 
						|
                                        containerValue[pos].asOctets(),
 | 
						|
                                        asn1Spec=openType, **options
 | 
						|
                                    )
 | 
						|
 | 
						|
                                    containerValue[pos] = component
 | 
						|
 | 
						|
                            else:
 | 
						|
                                component, rest = decodeFun(
 | 
						|
                                    asn1Object.getComponentByPosition(idx).asOctets(),
 | 
						|
                                    asn1Spec=openType, **options
 | 
						|
                                )
 | 
						|
 | 
						|
                                asn1Object.setComponentByPosition(idx, component)
 | 
						|
 | 
						|
            else:
 | 
						|
                inconsistency = asn1Object.isInconsistent
 | 
						|
                if inconsistency:
 | 
						|
                    raise inconsistency
 | 
						|
 | 
						|
        else:
 | 
						|
            asn1Object = asn1Spec.clone()
 | 
						|
            asn1Object.clear()
 | 
						|
 | 
						|
            componentType = asn1Spec.componentType
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding type %r chosen by given `asn1Spec`' % componentType)
 | 
						|
 | 
						|
            idx = 0
 | 
						|
 | 
						|
            while head:
 | 
						|
                component, head = decodeFun(head, componentType, **options)
 | 
						|
                asn1Object.setComponentByPosition(
 | 
						|
                    idx, component,
 | 
						|
                    verifyConstraints=False,
 | 
						|
                    matchTags=False, matchConstraints=False
 | 
						|
                )
 | 
						|
 | 
						|
                idx += 1
 | 
						|
 | 
						|
        return asn1Object, tail
 | 
						|
 | 
						|
    def indefLenValueDecoder(self, substrate, asn1Spec,
 | 
						|
                             tagSet=None, length=None, state=None,
 | 
						|
                             decodeFun=None, substrateFun=None,
 | 
						|
                             **options):
 | 
						|
        if tagSet[0].tagFormat != tag.tagFormatConstructed:
 | 
						|
            raise error.PyAsn1Error('Constructed tag format expected')
 | 
						|
 | 
						|
        if substrateFun is not None:
 | 
						|
            if asn1Spec is not None:
 | 
						|
                asn1Object = asn1Spec.clone()
 | 
						|
 | 
						|
            elif self.protoComponent is not None:
 | 
						|
                asn1Object = self.protoComponent.clone(tagSet=tagSet)
 | 
						|
 | 
						|
            else:
 | 
						|
                asn1Object = self.protoRecordComponent, self.protoSequenceComponent
 | 
						|
 | 
						|
            return substrateFun(asn1Object, substrate, length)
 | 
						|
 | 
						|
        if asn1Spec is None:
 | 
						|
            return self._decodeComponents(
 | 
						|
                substrate, tagSet=tagSet, decodeFun=decodeFun,
 | 
						|
                **dict(options, allowEoo=True)
 | 
						|
            )
 | 
						|
 | 
						|
        asn1Object = asn1Spec.clone()
 | 
						|
        asn1Object.clear()
 | 
						|
 | 
						|
        if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId):
 | 
						|
 | 
						|
            namedTypes = asn1Object.componentType
 | 
						|
 | 
						|
            isSetType = asn1Object.typeId == univ.Set.typeId
 | 
						|
            isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding %sdeterministic %s type %r chosen by type ID' % (
 | 
						|
                    not isDeterministic and 'non-' or '', isSetType and 'SET' or '',
 | 
						|
                    asn1Spec))
 | 
						|
 | 
						|
            seenIndices = set()
 | 
						|
            idx = 0
 | 
						|
            while substrate:
 | 
						|
                if len(namedTypes) <= idx:
 | 
						|
                    asn1Spec = None
 | 
						|
 | 
						|
                elif isSetType:
 | 
						|
                    asn1Spec = namedTypes.tagMapUnique
 | 
						|
 | 
						|
                else:
 | 
						|
                    try:
 | 
						|
                        if isDeterministic:
 | 
						|
                            asn1Spec = namedTypes[idx].asn1Object
 | 
						|
 | 
						|
                        elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
 | 
						|
                            asn1Spec = namedTypes.getTagMapNearPosition(idx)
 | 
						|
 | 
						|
                        else:
 | 
						|
                            asn1Spec = namedTypes[idx].asn1Object
 | 
						|
 | 
						|
                    except IndexError:
 | 
						|
                        raise error.PyAsn1Error(
 | 
						|
                            'Excessive components decoded at %r' % (asn1Object,)
 | 
						|
                        )
 | 
						|
 | 
						|
                component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True, **options)
 | 
						|
                if component is eoo.endOfOctets:
 | 
						|
                    break
 | 
						|
 | 
						|
                if not isDeterministic and namedTypes:
 | 
						|
                    if isSetType:
 | 
						|
                        idx = namedTypes.getPositionByType(component.effectiveTagSet)
 | 
						|
                    elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
 | 
						|
                        idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx)
 | 
						|
 | 
						|
                asn1Object.setComponentByPosition(
 | 
						|
                    idx, component,
 | 
						|
                    verifyConstraints=False,
 | 
						|
                    matchTags=False, matchConstraints=False
 | 
						|
                )
 | 
						|
 | 
						|
                seenIndices.add(idx)
 | 
						|
                idx += 1
 | 
						|
 | 
						|
            else:
 | 
						|
                raise error.SubstrateUnderrunError(
 | 
						|
                    'No EOO seen before substrate ends'
 | 
						|
                )
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('seen component indices %s' % seenIndices)
 | 
						|
 | 
						|
            if namedTypes:
 | 
						|
                if not namedTypes.requiredComponents.issubset(seenIndices):
 | 
						|
                    raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__)
 | 
						|
 | 
						|
                if namedTypes.hasOpenTypes:
 | 
						|
 | 
						|
                    openTypes = options.get('openTypes', {})
 | 
						|
 | 
						|
                    if LOG:
 | 
						|
                        LOG('user-specified open types map:')
 | 
						|
 | 
						|
                        for k, v in openTypes.items():
 | 
						|
                            LOG('%s -> %r' % (k, v))
 | 
						|
 | 
						|
                    if openTypes or options.get('decodeOpenTypes', False):
 | 
						|
 | 
						|
                        for idx, namedType in enumerate(namedTypes.namedTypes):
 | 
						|
                            if not namedType.openType:
 | 
						|
                                continue
 | 
						|
 | 
						|
                            if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue:
 | 
						|
                                continue
 | 
						|
 | 
						|
                            governingValue = asn1Object.getComponentByName(
 | 
						|
                                namedType.openType.name
 | 
						|
                            )
 | 
						|
 | 
						|
                            try:
 | 
						|
                                openType = openTypes[governingValue]
 | 
						|
 | 
						|
                            except KeyError:
 | 
						|
 | 
						|
                                if LOG:
 | 
						|
                                    LOG('default open types map of component '
 | 
						|
                                        '"%s.%s" governed by component "%s.%s"'
 | 
						|
                                        ':' % (asn1Object.__class__.__name__,
 | 
						|
                                               namedType.name,
 | 
						|
                                               asn1Object.__class__.__name__,
 | 
						|
                                               namedType.openType.name))
 | 
						|
 | 
						|
                                    for k, v in namedType.openType.items():
 | 
						|
                                        LOG('%s -> %r' % (k, v))
 | 
						|
 | 
						|
                                try:
 | 
						|
                                    openType = namedType.openType[governingValue]
 | 
						|
 | 
						|
                                except KeyError:
 | 
						|
                                    if LOG:
 | 
						|
                                        LOG('failed to resolve open type by governing '
 | 
						|
                                            'value %r' % (governingValue,))
 | 
						|
                                    continue
 | 
						|
 | 
						|
                            if LOG:
 | 
						|
                                LOG('resolved open type %r by governing '
 | 
						|
                                    'value %r' % (openType, governingValue))
 | 
						|
 | 
						|
                            containerValue = asn1Object.getComponentByPosition(idx)
 | 
						|
 | 
						|
                            if containerValue.typeId in (
 | 
						|
                                    univ.SetOf.typeId, univ.SequenceOf.typeId):
 | 
						|
 | 
						|
                                for pos, containerElement in enumerate(
 | 
						|
                                        containerValue):
 | 
						|
 | 
						|
                                    component, rest = decodeFun(
 | 
						|
                                        containerValue[pos].asOctets(),
 | 
						|
                                        asn1Spec=openType, **dict(options, allowEoo=True)
 | 
						|
                                    )
 | 
						|
 | 
						|
                                    containerValue[pos] = component
 | 
						|
 | 
						|
                            else:
 | 
						|
                                component, rest = decodeFun(
 | 
						|
                                    asn1Object.getComponentByPosition(idx).asOctets(),
 | 
						|
                                    asn1Spec=openType, **dict(options, allowEoo=True)
 | 
						|
                                )
 | 
						|
 | 
						|
                                if component is not eoo.endOfOctets:
 | 
						|
                                    asn1Object.setComponentByPosition(idx, component)
 | 
						|
 | 
						|
                else:
 | 
						|
                    inconsistency = asn1Object.isInconsistent
 | 
						|
                    if inconsistency:
 | 
						|
                        raise inconsistency
 | 
						|
 | 
						|
        else:
 | 
						|
            asn1Object = asn1Spec.clone()
 | 
						|
            asn1Object.clear()
 | 
						|
 | 
						|
            componentType = asn1Spec.componentType
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding type %r chosen by given `asn1Spec`' % componentType)
 | 
						|
 | 
						|
            idx = 0
 | 
						|
 | 
						|
            while substrate:
 | 
						|
                component, substrate = decodeFun(substrate, componentType, allowEoo=True, **options)
 | 
						|
 | 
						|
                if component is eoo.endOfOctets:
 | 
						|
                    break
 | 
						|
 | 
						|
                asn1Object.setComponentByPosition(
 | 
						|
                    idx, component,
 | 
						|
                    verifyConstraints=False,
 | 
						|
                    matchTags=False, matchConstraints=False
 | 
						|
                )
 | 
						|
 | 
						|
                idx += 1
 | 
						|
 | 
						|
            else:
 | 
						|
                raise error.SubstrateUnderrunError(
 | 
						|
                    'No EOO seen before substrate ends'
 | 
						|
                )
 | 
						|
 | 
						|
        return asn1Object, substrate
 | 
						|
 | 
						|
 | 
						|
class SequenceOrSequenceOfDecoder(UniversalConstructedTypeDecoder):
 | 
						|
    protoRecordComponent = univ.Sequence()
 | 
						|
    protoSequenceComponent = univ.SequenceOf()
 | 
						|
 | 
						|
 | 
						|
class SequenceDecoder(SequenceOrSequenceOfDecoder):
 | 
						|
    protoComponent = univ.Sequence()
 | 
						|
 | 
						|
 | 
						|
class SequenceOfDecoder(SequenceOrSequenceOfDecoder):
 | 
						|
    protoComponent = univ.SequenceOf()
 | 
						|
 | 
						|
 | 
						|
class SetOrSetOfDecoder(UniversalConstructedTypeDecoder):
 | 
						|
    protoRecordComponent = univ.Set()
 | 
						|
    protoSequenceComponent = univ.SetOf()
 | 
						|
 | 
						|
 | 
						|
class SetDecoder(SetOrSetOfDecoder):
 | 
						|
    protoComponent = univ.Set()
 | 
						|
 | 
						|
 | 
						|
 | 
						|
class SetOfDecoder(SetOrSetOfDecoder):
 | 
						|
    protoComponent = univ.SetOf()
 | 
						|
 | 
						|
 | 
						|
class ChoiceDecoder(AbstractConstructedDecoder):
 | 
						|
    protoComponent = univ.Choice()
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
        head, tail = substrate[:length], substrate[length:]
 | 
						|
 | 
						|
        if asn1Spec is None:
 | 
						|
            asn1Object = self.protoComponent.clone(tagSet=tagSet)
 | 
						|
 | 
						|
        else:
 | 
						|
            asn1Object = asn1Spec.clone()
 | 
						|
 | 
						|
        if substrateFun:
 | 
						|
            return substrateFun(asn1Object, substrate, length)
 | 
						|
 | 
						|
        if asn1Object.tagSet == tagSet:
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding %s as explicitly tagged CHOICE' % (tagSet,))
 | 
						|
 | 
						|
            component, head = decodeFun(
 | 
						|
                head, asn1Object.componentTagMap, **options
 | 
						|
            )
 | 
						|
 | 
						|
        else:
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding %s as untagged CHOICE' % (tagSet,))
 | 
						|
 | 
						|
            component, head = decodeFun(
 | 
						|
                head, asn1Object.componentTagMap,
 | 
						|
                tagSet, length, state, **options
 | 
						|
            )
 | 
						|
 | 
						|
        effectiveTagSet = component.effectiveTagSet
 | 
						|
 | 
						|
        if LOG:
 | 
						|
            LOG('decoded component %s, effective tag set %s' % (component, effectiveTagSet))
 | 
						|
 | 
						|
        asn1Object.setComponentByType(
 | 
						|
            effectiveTagSet, component,
 | 
						|
            verifyConstraints=False,
 | 
						|
            matchTags=False, matchConstraints=False,
 | 
						|
            innerFlag=False
 | 
						|
        )
 | 
						|
 | 
						|
        return asn1Object, tail
 | 
						|
 | 
						|
    def indefLenValueDecoder(self, substrate, asn1Spec,
 | 
						|
                             tagSet=None, length=None, state=None,
 | 
						|
                             decodeFun=None, substrateFun=None,
 | 
						|
                             **options):
 | 
						|
        if asn1Spec is None:
 | 
						|
            asn1Object = self.protoComponent.clone(tagSet=tagSet)
 | 
						|
        else:
 | 
						|
            asn1Object = asn1Spec.clone()
 | 
						|
 | 
						|
        if substrateFun:
 | 
						|
            return substrateFun(asn1Object, substrate, length)
 | 
						|
 | 
						|
        if asn1Object.tagSet == tagSet:
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding %s as explicitly tagged CHOICE' % (tagSet,))
 | 
						|
 | 
						|
            component, substrate = decodeFun(
 | 
						|
                substrate, asn1Object.componentType.tagMapUnique, **options
 | 
						|
            )
 | 
						|
 | 
						|
            # eat up EOO marker
 | 
						|
            eooMarker, substrate = decodeFun(
 | 
						|
                substrate, allowEoo=True, **options
 | 
						|
            )
 | 
						|
 | 
						|
            if eooMarker is not eoo.endOfOctets:
 | 
						|
                raise error.PyAsn1Error('No EOO seen before substrate ends')
 | 
						|
 | 
						|
        else:
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding %s as untagged CHOICE' % (tagSet,))
 | 
						|
 | 
						|
            component, substrate = decodeFun(
 | 
						|
                substrate, asn1Object.componentType.tagMapUnique,
 | 
						|
                tagSet, length, state, **options
 | 
						|
            )
 | 
						|
 | 
						|
        effectiveTagSet = component.effectiveTagSet
 | 
						|
 | 
						|
        if LOG:
 | 
						|
            LOG('decoded component %s, effective tag set %s' % (component, effectiveTagSet))
 | 
						|
 | 
						|
        asn1Object.setComponentByType(
 | 
						|
            effectiveTagSet, component,
 | 
						|
            verifyConstraints=False,
 | 
						|
            matchTags=False, matchConstraints=False,
 | 
						|
            innerFlag=False
 | 
						|
        )
 | 
						|
 | 
						|
        return asn1Object, substrate
 | 
						|
 | 
						|
 | 
						|
class AnyDecoder(AbstractSimpleDecoder):
 | 
						|
    protoComponent = univ.Any()
 | 
						|
 | 
						|
    def valueDecoder(self, substrate, asn1Spec,
 | 
						|
                     tagSet=None, length=None, state=None,
 | 
						|
                     decodeFun=None, substrateFun=None,
 | 
						|
                     **options):
 | 
						|
        if asn1Spec is None:
 | 
						|
            isUntagged = True
 | 
						|
 | 
						|
        elif asn1Spec.__class__ is tagmap.TagMap:
 | 
						|
            isUntagged = tagSet not in asn1Spec.tagMap
 | 
						|
 | 
						|
        else:
 | 
						|
            isUntagged = tagSet != asn1Spec.tagSet
 | 
						|
 | 
						|
        if isUntagged:
 | 
						|
            fullSubstrate = options['fullSubstrate']
 | 
						|
 | 
						|
            # untagged Any container, recover inner header substrate
 | 
						|
            length += len(fullSubstrate) - len(substrate)
 | 
						|
            substrate = fullSubstrate
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding as untagged ANY, substrate %s' % debug.hexdump(substrate))
 | 
						|
 | 
						|
        if substrateFun:
 | 
						|
            return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options),
 | 
						|
                                substrate, length)
 | 
						|
 | 
						|
        head, tail = substrate[:length], substrate[length:]
 | 
						|
 | 
						|
        return self._createComponent(asn1Spec, tagSet, head, **options), tail
 | 
						|
 | 
						|
    def indefLenValueDecoder(self, substrate, asn1Spec,
 | 
						|
                             tagSet=None, length=None, state=None,
 | 
						|
                             decodeFun=None, substrateFun=None,
 | 
						|
                             **options):
 | 
						|
        if asn1Spec is None:
 | 
						|
            isTagged = False
 | 
						|
 | 
						|
        elif asn1Spec.__class__ is tagmap.TagMap:
 | 
						|
            isTagged = tagSet in asn1Spec.tagMap
 | 
						|
 | 
						|
        else:
 | 
						|
            isTagged = tagSet == asn1Spec.tagSet
 | 
						|
 | 
						|
        if isTagged:
 | 
						|
            # tagged Any type -- consume header substrate
 | 
						|
            header = null
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding as tagged ANY')
 | 
						|
 | 
						|
        else:
 | 
						|
            fullSubstrate = options['fullSubstrate']
 | 
						|
 | 
						|
            # untagged Any, recover header substrate
 | 
						|
            header = fullSubstrate[:-len(substrate)]
 | 
						|
 | 
						|
            if LOG:
 | 
						|
                LOG('decoding as untagged ANY, header substrate %s' % debug.hexdump(header))
 | 
						|
 | 
						|
        # Any components do not inherit initial tag
 | 
						|
        asn1Spec = self.protoComponent
 | 
						|
 | 
						|
        if substrateFun and substrateFun is not self.substrateCollector:
 | 
						|
            asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)
 | 
						|
            return substrateFun(asn1Object, header + substrate, length + len(header))
 | 
						|
 | 
						|
        if LOG:
 | 
						|
            LOG('assembling constructed serialization')
 | 
						|
 | 
						|
        # All inner fragments are of the same type, treat them as octet string
 | 
						|
        substrateFun = self.substrateCollector
 | 
						|
 | 
						|
        while substrate:
 | 
						|
            component, substrate = decodeFun(substrate, asn1Spec,
 | 
						|
                                             substrateFun=substrateFun,
 | 
						|
                                             allowEoo=True, **options)
 | 
						|
            if component is eoo.endOfOctets:
 | 
						|
                break
 | 
						|
 | 
						|
            header += component
 | 
						|
 | 
						|
        else:
 | 
						|
            raise error.SubstrateUnderrunError(
 | 
						|
                'No EOO seen before substrate ends'
 | 
						|
            )
 | 
						|
 | 
						|
        if substrateFun:
 | 
						|
            return header, substrate
 | 
						|
 | 
						|
        else:
 | 
						|
            return self._createComponent(asn1Spec, tagSet, header, **options), substrate
 | 
						|
 | 
						|
 | 
						|
# character string types
 | 
						|
class UTF8StringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.UTF8String()
 | 
						|
 | 
						|
 | 
						|
class NumericStringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.NumericString()
 | 
						|
 | 
						|
 | 
						|
class PrintableStringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.PrintableString()
 | 
						|
 | 
						|
 | 
						|
class TeletexStringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.TeletexString()
 | 
						|
 | 
						|
 | 
						|
class VideotexStringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.VideotexString()
 | 
						|
 | 
						|
 | 
						|
class IA5StringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.IA5String()
 | 
						|
 | 
						|
 | 
						|
class GraphicStringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.GraphicString()
 | 
						|
 | 
						|
 | 
						|
class VisibleStringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.VisibleString()
 | 
						|
 | 
						|
 | 
						|
class GeneralStringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.GeneralString()
 | 
						|
 | 
						|
 | 
						|
class UniversalStringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.UniversalString()
 | 
						|
 | 
						|
 | 
						|
class BMPStringDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = char.BMPString()
 | 
						|
 | 
						|
 | 
						|
# "useful" types
 | 
						|
class ObjectDescriptorDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = useful.ObjectDescriptor()
 | 
						|
 | 
						|
 | 
						|
class GeneralizedTimeDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = useful.GeneralizedTime()
 | 
						|
 | 
						|
 | 
						|
class UTCTimeDecoder(OctetStringDecoder):
 | 
						|
    protoComponent = useful.UTCTime()
 | 
						|
 | 
						|
 | 
						|
tagMap = {
 | 
						|
    univ.Integer.tagSet: IntegerDecoder(),
 | 
						|
    univ.Boolean.tagSet: BooleanDecoder(),
 | 
						|
    univ.BitString.tagSet: BitStringDecoder(),
 | 
						|
    univ.OctetString.tagSet: OctetStringDecoder(),
 | 
						|
    univ.Null.tagSet: NullDecoder(),
 | 
						|
    univ.ObjectIdentifier.tagSet: ObjectIdentifierDecoder(),
 | 
						|
    univ.Enumerated.tagSet: IntegerDecoder(),
 | 
						|
    univ.Real.tagSet: RealDecoder(),
 | 
						|
    univ.Sequence.tagSet: SequenceOrSequenceOfDecoder(),  # conflicts with SequenceOf
 | 
						|
    univ.Set.tagSet: SetOrSetOfDecoder(),  # conflicts with SetOf
 | 
						|
    univ.Choice.tagSet: ChoiceDecoder(),  # conflicts with Any
 | 
						|
    # character string types
 | 
						|
    char.UTF8String.tagSet: UTF8StringDecoder(),
 | 
						|
    char.NumericString.tagSet: NumericStringDecoder(),
 | 
						|
    char.PrintableString.tagSet: PrintableStringDecoder(),
 | 
						|
    char.TeletexString.tagSet: TeletexStringDecoder(),
 | 
						|
    char.VideotexString.tagSet: VideotexStringDecoder(),
 | 
						|
    char.IA5String.tagSet: IA5StringDecoder(),
 | 
						|
    char.GraphicString.tagSet: GraphicStringDecoder(),
 | 
						|
    char.VisibleString.tagSet: VisibleStringDecoder(),
 | 
						|
    char.GeneralString.tagSet: GeneralStringDecoder(),
 | 
						|
    char.UniversalString.tagSet: UniversalStringDecoder(),
 | 
						|
    char.BMPString.tagSet: BMPStringDecoder(),
 | 
						|
    # useful types
 | 
						|
    useful.ObjectDescriptor.tagSet: ObjectDescriptorDecoder(),
 | 
						|
    useful.GeneralizedTime.tagSet: GeneralizedTimeDecoder(),
 | 
						|
    useful.UTCTime.tagSet: UTCTimeDecoder()
 | 
						|
}
 | 
						|
 | 
						|
# Type-to-codec map for ambiguous ASN.1 types
 | 
						|
typeMap = {
 | 
						|
    univ.Set.typeId: SetDecoder(),
 | 
						|
    univ.SetOf.typeId: SetOfDecoder(),
 | 
						|
    univ.Sequence.typeId: SequenceDecoder(),
 | 
						|
    univ.SequenceOf.typeId: SequenceOfDecoder(),
 | 
						|
    univ.Choice.typeId: ChoiceDecoder(),
 | 
						|
    univ.Any.typeId: AnyDecoder()
 | 
						|
}
 | 
						|
 | 
						|
# Put in non-ambiguous types for faster codec lookup
 | 
						|
for typeDecoder in tagMap.values():
 | 
						|
    if typeDecoder.protoComponent is not None:
 | 
						|
        typeId = typeDecoder.protoComponent.__class__.typeId
 | 
						|
        if typeId is not None and typeId not in typeMap:
 | 
						|
            typeMap[typeId] = typeDecoder
 | 
						|
 | 
						|
 | 
						|
(stDecodeTag,
 | 
						|
 stDecodeLength,
 | 
						|
 stGetValueDecoder,
 | 
						|
 stGetValueDecoderByAsn1Spec,
 | 
						|
 stGetValueDecoderByTag,
 | 
						|
 stTryAsExplicitTag,
 | 
						|
 stDecodeValue,
 | 
						|
 stDumpRawValue,
 | 
						|
 stErrorCondition,
 | 
						|
 stStop) = [x for x in range(10)]
 | 
						|
 | 
						|
 | 
						|
class Decoder(object):
 | 
						|
    defaultErrorState = stErrorCondition
 | 
						|
    #defaultErrorState = stDumpRawValue
 | 
						|
    defaultRawDecoder = AnyDecoder()
 | 
						|
    supportIndefLength = True
 | 
						|
 | 
						|
    # noinspection PyDefaultArgument
 | 
						|
    def __init__(self, tagMap, typeMap={}):
 | 
						|
        self.__tagMap = tagMap
 | 
						|
        self.__typeMap = typeMap
 | 
						|
        # Tag & TagSet objects caches
 | 
						|
        self.__tagCache = {}
 | 
						|
        self.__tagSetCache = {}
 | 
						|
        self.__eooSentinel = ints2octs((0, 0))
 | 
						|
 | 
						|
    def __call__(self, substrate, asn1Spec=None,
 | 
						|
                 tagSet=None, length=None, state=stDecodeTag,
 | 
						|
                 decodeFun=None, substrateFun=None,
 | 
						|
                 **options):
 | 
						|
 | 
						|
        if LOG:
 | 
						|
            LOG('decoder called at scope %s with state %d, working with up to %d octets of substrate: %s' % (debug.scope, state, len(substrate), debug.hexdump(substrate)))
 | 
						|
 | 
						|
        allowEoo = options.pop('allowEoo', False)
 | 
						|
 | 
						|
        # Look for end-of-octets sentinel
 | 
						|
        if allowEoo and self.supportIndefLength:
 | 
						|
            if substrate[:2] == self.__eooSentinel:
 | 
						|
                if LOG:
 | 
						|
                    LOG('end-of-octets sentinel found')
 | 
						|
                return eoo.endOfOctets, substrate[2:]
 | 
						|
 | 
						|
        value = noValue
 | 
						|
 | 
						|
        tagMap = self.__tagMap
 | 
						|
        typeMap = self.__typeMap
 | 
						|
        tagCache = self.__tagCache
 | 
						|
        tagSetCache = self.__tagSetCache
 | 
						|
 | 
						|
        fullSubstrate = substrate
 | 
						|
 | 
						|
        while state is not stStop:
 | 
						|
 | 
						|
            if state is stDecodeTag:
 | 
						|
                if not substrate:
 | 
						|
                    raise error.SubstrateUnderrunError(
 | 
						|
                        'Short octet stream on tag decoding'
 | 
						|
                    )
 | 
						|
 | 
						|
                # Decode tag
 | 
						|
                isShortTag = True
 | 
						|
                firstOctet = substrate[0]
 | 
						|
                substrate = substrate[1:]
 | 
						|
 | 
						|
                try:
 | 
						|
                    lastTag = tagCache[firstOctet]
 | 
						|
 | 
						|
                except KeyError:
 | 
						|
                    integerTag = oct2int(firstOctet)
 | 
						|
                    tagClass = integerTag & 0xC0
 | 
						|
                    tagFormat = integerTag & 0x20
 | 
						|
                    tagId = integerTag & 0x1F
 | 
						|
 | 
						|
                    if tagId == 0x1F:
 | 
						|
                        isShortTag = False
 | 
						|
                        lengthOctetIdx = 0
 | 
						|
                        tagId = 0
 | 
						|
 | 
						|
                        try:
 | 
						|
                            while True:
 | 
						|
                                integerTag = oct2int(substrate[lengthOctetIdx])
 | 
						|
                                lengthOctetIdx += 1
 | 
						|
                                tagId <<= 7
 | 
						|
                                tagId |= (integerTag & 0x7F)
 | 
						|
                                if not integerTag & 0x80:
 | 
						|
                                    break
 | 
						|
 | 
						|
                            substrate = substrate[lengthOctetIdx:]
 | 
						|
 | 
						|
                        except IndexError:
 | 
						|
                            raise error.SubstrateUnderrunError(
 | 
						|
                                'Short octet stream on long tag decoding'
 | 
						|
                            )
 | 
						|
 | 
						|
                    lastTag = tag.Tag(
 | 
						|
                        tagClass=tagClass, tagFormat=tagFormat, tagId=tagId
 | 
						|
                    )
 | 
						|
 | 
						|
                    if isShortTag:
 | 
						|
                        # cache short tags
 | 
						|
                        tagCache[firstOctet] = lastTag
 | 
						|
 | 
						|
                if tagSet is None:
 | 
						|
                    if isShortTag:
 | 
						|
                        try:
 | 
						|
                            tagSet = tagSetCache[firstOctet]
 | 
						|
 | 
						|
                        except KeyError:
 | 
						|
                            # base tag not recovered
 | 
						|
                            tagSet = tag.TagSet((), lastTag)
 | 
						|
                            tagSetCache[firstOctet] = tagSet
 | 
						|
                    else:
 | 
						|
                        tagSet = tag.TagSet((), lastTag)
 | 
						|
 | 
						|
                else:
 | 
						|
                    tagSet = lastTag + tagSet
 | 
						|
 | 
						|
                state = stDecodeLength
 | 
						|
 | 
						|
                if LOG:
 | 
						|
                    LOG('tag decoded into %s, decoding length' % tagSet)
 | 
						|
 | 
						|
            if state is stDecodeLength:
 | 
						|
                # Decode length
 | 
						|
                if not substrate:
 | 
						|
                    raise error.SubstrateUnderrunError(
 | 
						|
                        'Short octet stream on length decoding'
 | 
						|
                    )
 | 
						|
 | 
						|
                firstOctet = oct2int(substrate[0])
 | 
						|
 | 
						|
                if firstOctet < 128:
 | 
						|
                    size = 1
 | 
						|
                    length = firstOctet
 | 
						|
 | 
						|
                elif firstOctet > 128:
 | 
						|
                    size = firstOctet & 0x7F
 | 
						|
                    # encoded in size bytes
 | 
						|
                    encodedLength = octs2ints(substrate[1:size + 1])
 | 
						|
                    # missing check on maximum size, which shouldn't be a
 | 
						|
                    # problem, we can handle more than is possible
 | 
						|
                    if len(encodedLength) != size:
 | 
						|
                        raise error.SubstrateUnderrunError(
 | 
						|
                            '%s<%s at %s' % (size, len(encodedLength), tagSet)
 | 
						|
                        )
 | 
						|
 | 
						|
                    length = 0
 | 
						|
                    for lengthOctet in encodedLength:
 | 
						|
                        length <<= 8
 | 
						|
                        length |= lengthOctet
 | 
						|
                    size += 1
 | 
						|
 | 
						|
                else:
 | 
						|
                    size = 1
 | 
						|
                    length = -1
 | 
						|
 | 
						|
                substrate = substrate[size:]
 | 
						|
 | 
						|
                if length == -1:
 | 
						|
                    if not self.supportIndefLength:
 | 
						|
                        raise error.PyAsn1Error('Indefinite length encoding not supported by this codec')
 | 
						|
 | 
						|
                else:
 | 
						|
                    if len(substrate) < length:
 | 
						|
                        raise error.SubstrateUnderrunError('%d-octet short' % (length - len(substrate)))
 | 
						|
 | 
						|
                state = stGetValueDecoder
 | 
						|
 | 
						|
                if LOG:
 | 
						|
                    LOG('value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(length == -1 and substrate or substrate[:length])))
 | 
						|
 | 
						|
            if state is stGetValueDecoder:
 | 
						|
                if asn1Spec is None:
 | 
						|
                    state = stGetValueDecoderByTag
 | 
						|
 | 
						|
                else:
 | 
						|
                    state = stGetValueDecoderByAsn1Spec
 | 
						|
            #
 | 
						|
            # There're two ways of creating subtypes in ASN.1 what influences
 | 
						|
            # decoder operation. These methods are:
 | 
						|
            # 1) Either base types used in or no IMPLICIT tagging has been
 | 
						|
            #    applied on subtyping.
 | 
						|
            # 2) Subtype syntax drops base type information (by means of
 | 
						|
            #    IMPLICIT tagging.
 | 
						|
            # The first case allows for complete tag recovery from substrate
 | 
						|
            # while the second one requires original ASN.1 type spec for
 | 
						|
            # decoding.
 | 
						|
            #
 | 
						|
            # In either case a set of tags (tagSet) is coming from substrate
 | 
						|
            # in an incremental, tag-by-tag fashion (this is the case of
 | 
						|
            # EXPLICIT tag which is most basic). Outermost tag comes first
 | 
						|
            # from the wire.
 | 
						|
            #
 | 
						|
            if state is stGetValueDecoderByTag:
 | 
						|
                try:
 | 
						|
                    concreteDecoder = tagMap[tagSet]
 | 
						|
 | 
						|
                except KeyError:
 | 
						|
                    concreteDecoder = None
 | 
						|
 | 
						|
                if concreteDecoder:
 | 
						|
                    state = stDecodeValue
 | 
						|
 | 
						|
                else:
 | 
						|
                    try:
 | 
						|
                        concreteDecoder = tagMap[tagSet[:1]]
 | 
						|
 | 
						|
                    except KeyError:
 | 
						|
                        concreteDecoder = None
 | 
						|
 | 
						|
                    if concreteDecoder:
 | 
						|
                        state = stDecodeValue
 | 
						|
                    else:
 | 
						|
                        state = stTryAsExplicitTag
 | 
						|
 | 
						|
                if LOG:
 | 
						|
                    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'))
 | 
						|
                    debug.scope.push(concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__)
 | 
						|
 | 
						|
            if state is stGetValueDecoderByAsn1Spec:
 | 
						|
 | 
						|
                if asn1Spec.__class__ is tagmap.TagMap:
 | 
						|
                    try:
 | 
						|
                        chosenSpec = asn1Spec[tagSet]
 | 
						|
 | 
						|
                    except KeyError:
 | 
						|
                        chosenSpec = None
 | 
						|
 | 
						|
                    if LOG:
 | 
						|
                        LOG('candidate ASN.1 spec is a map of:')
 | 
						|
 | 
						|
                        for firstOctet, v in asn1Spec.presentTypes.items():
 | 
						|
                            LOG('  %s -> %s' % (firstOctet, v.__class__.__name__))
 | 
						|
 | 
						|
                        if asn1Spec.skipTypes:
 | 
						|
                            LOG('but neither of: ')
 | 
						|
                            for firstOctet, v in asn1Spec.skipTypes.items():
 | 
						|
                                LOG('  %s -> %s' % (firstOctet, v.__class__.__name__))
 | 
						|
                        LOG('new candidate ASN.1 spec is %s, chosen by %s' % (chosenSpec is None and '<none>' or chosenSpec.prettyPrintType(), tagSet))
 | 
						|
 | 
						|
                elif tagSet == asn1Spec.tagSet or tagSet in asn1Spec.tagMap:
 | 
						|
                    chosenSpec = asn1Spec
 | 
						|
                    if LOG:
 | 
						|
                        LOG('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__)
 | 
						|
 | 
						|
                else:
 | 
						|
                    chosenSpec = None
 | 
						|
 | 
						|
                if chosenSpec is not None:
 | 
						|
                    try:
 | 
						|
                        # ambiguous type or just faster codec lookup
 | 
						|
                        concreteDecoder = typeMap[chosenSpec.typeId]
 | 
						|
 | 
						|
                        if LOG:
 | 
						|
                            LOG('value decoder chosen for an ambiguous type by type ID %s' % (chosenSpec.typeId,))
 | 
						|
 | 
						|
                    except KeyError:
 | 
						|
                        # use base type for codec lookup to recover untagged types
 | 
						|
                        baseTagSet = tag.TagSet(chosenSpec.tagSet.baseTag,  chosenSpec.tagSet.baseTag)
 | 
						|
                        try:
 | 
						|
                            # base type or tagged subtype
 | 
						|
                            concreteDecoder = tagMap[baseTagSet]
 | 
						|
 | 
						|
                            if LOG:
 | 
						|
                                LOG('value decoder chosen by base %s' % (baseTagSet,))
 | 
						|
 | 
						|
                        except KeyError:
 | 
						|
                            concreteDecoder = None
 | 
						|
 | 
						|
                    if concreteDecoder:
 | 
						|
                        asn1Spec = chosenSpec
 | 
						|
                        state = stDecodeValue
 | 
						|
 | 
						|
                    else:
 | 
						|
                        state = stTryAsExplicitTag
 | 
						|
 | 
						|
                else:
 | 
						|
                    concreteDecoder = None
 | 
						|
                    state = stTryAsExplicitTag
 | 
						|
 | 
						|
                if LOG:
 | 
						|
                    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'))
 | 
						|
                    debug.scope.push(chosenSpec is None and '?' or chosenSpec.__class__.__name__)
 | 
						|
 | 
						|
            if state is stDecodeValue:
 | 
						|
                if not options.get('recursiveFlag', True) and not substrateFun:  # deprecate this
 | 
						|
                    substrateFun = lambda a, b, c: (a, b[:c])
 | 
						|
 | 
						|
                options.update(fullSubstrate=fullSubstrate)
 | 
						|
 | 
						|
                if length == -1:  # indef length
 | 
						|
                    value, substrate = concreteDecoder.indefLenValueDecoder(
 | 
						|
                        substrate, asn1Spec,
 | 
						|
                        tagSet, length, stGetValueDecoder,
 | 
						|
                        self, substrateFun,
 | 
						|
                        **options
 | 
						|
                    )
 | 
						|
 | 
						|
                else:
 | 
						|
                    value, substrate = concreteDecoder.valueDecoder(
 | 
						|
                        substrate, asn1Spec,
 | 
						|
                        tagSet, length, stGetValueDecoder,
 | 
						|
                        self, substrateFun,
 | 
						|
                        **options
 | 
						|
                    )
 | 
						|
 | 
						|
                if LOG:
 | 
						|
                    LOG('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, isinstance(value, base.Asn1Item) and value.prettyPrint() or value, substrate and debug.hexdump(substrate) or '<none>'))
 | 
						|
 | 
						|
                state = stStop
 | 
						|
                break
 | 
						|
 | 
						|
            if state is stTryAsExplicitTag:
 | 
						|
                if (tagSet and
 | 
						|
                        tagSet[0].tagFormat == tag.tagFormatConstructed and
 | 
						|
                        tagSet[0].tagClass != tag.tagClassUniversal):
 | 
						|
                    # Assume explicit tagging
 | 
						|
                    concreteDecoder = explicitTagDecoder
 | 
						|
                    state = stDecodeValue
 | 
						|
 | 
						|
                else:
 | 
						|
                    concreteDecoder = None
 | 
						|
                    state = self.defaultErrorState
 | 
						|
 | 
						|
                if LOG:
 | 
						|
                    LOG('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as failure'))
 | 
						|
 | 
						|
            if state is stDumpRawValue:
 | 
						|
                concreteDecoder = self.defaultRawDecoder
 | 
						|
 | 
						|
                if LOG:
 | 
						|
                    LOG('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__)
 | 
						|
 | 
						|
                state = stDecodeValue
 | 
						|
 | 
						|
            if state is stErrorCondition:
 | 
						|
                raise error.PyAsn1Error(
 | 
						|
                    '%s not in asn1Spec: %r' % (tagSet, asn1Spec)
 | 
						|
                )
 | 
						|
 | 
						|
        if LOG:
 | 
						|
            debug.scope.pop()
 | 
						|
            LOG('decoder left scope %s, call completed' % debug.scope)
 | 
						|
 | 
						|
        return value, substrate
 | 
						|
 | 
						|
 | 
						|
#: Turns BER octet stream into an ASN.1 object.
 | 
						|
#:
 | 
						|
#: Takes BER octet-stream and decode it into an ASN.1 object
 | 
						|
#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
 | 
						|
#: may be a scalar or an arbitrary nested structure.
 | 
						|
#:
 | 
						|
#: Parameters
 | 
						|
#: ----------
 | 
						|
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
 | 
						|
#:     BER octet-stream
 | 
						|
#:
 | 
						|
#: Keyword Args
 | 
						|
#: ------------
 | 
						|
#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
 | 
						|
#:     A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure
 | 
						|
#:     being decoded, *asn1Spec* may or may not be required. Most common reason for
 | 
						|
#:     it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode.
 | 
						|
#:
 | 
						|
#: Returns
 | 
						|
#: -------
 | 
						|
#: : :py:class:`tuple`
 | 
						|
#:     A tuple of pyasn1 object recovered from BER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
 | 
						|
#:     and the unprocessed trailing portion of the *substrate* (may be empty)
 | 
						|
#:
 | 
						|
#: Raises
 | 
						|
#: ------
 | 
						|
#: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError
 | 
						|
#:     On decoding errors
 | 
						|
#:
 | 
						|
#: Examples
 | 
						|
#: --------
 | 
						|
#: Decode BER serialisation without ASN.1 schema
 | 
						|
#:
 | 
						|
#: .. code-block:: pycon
 | 
						|
#:
 | 
						|
#:    >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03')
 | 
						|
#:    >>> str(s)
 | 
						|
#:    SequenceOf:
 | 
						|
#:     1 2 3
 | 
						|
#:
 | 
						|
#: Decode BER serialisation with ASN.1 schema
 | 
						|
#:
 | 
						|
#: .. code-block:: pycon
 | 
						|
#:
 | 
						|
#:    >>> seq = SequenceOf(componentType=Integer())
 | 
						|
#:    >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq)
 | 
						|
#:    >>> str(s)
 | 
						|
#:    SequenceOf:
 | 
						|
#:     1 2 3
 | 
						|
#:
 | 
						|
decode = Decoder(tagMap, typeMap)
 | 
						|
 | 
						|
# XXX
 | 
						|
# non-recursive decoding; return position rather than substrate
 |