Example #1
0
 def __call__(self, value, defMode=True, maxChunkSize=0):
     if not isinstance(value, base.Asn1Item):
         raise error.PyAsn1Error('value is not valid (should be an instance of an ASN.1 Item)')
     if not defMode and not self.supportIndefLength:
         raise error.PyAsn1Error('Indefinite length encoding not supported by this codec')
     debug.logger & debug.flagEncoder and debug.logger(
         'encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (
             not defMode and 'in' or '', maxChunkSize, value.prettyPrintType(), value.prettyPrint()))
     tagSet = value.getTagSet()
     if len(tagSet) > 1:
         concreteEncoder = explicitlyTaggedItemEncoder
     else:
         if value.typeId is not None and value.typeId in self.__typeMap:
             concreteEncoder = self.__typeMap[value.typeId]
         elif tagSet in self.__tagMap:
             concreteEncoder = self.__tagMap[tagSet]
         else:
             tagSet = value.baseTagSet
             if tagSet in self.__tagMap:
                 concreteEncoder = self.__tagMap[tagSet]
             else:
                 raise Error('No encoder for %s' % (value,))
     debug.logger & debug.flagEncoder and debug.logger(
         'using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet))
     substrate = concreteEncoder.encode(
         self, value, defMode, maxChunkSize
     )
     debug.logger & debug.flagEncoder and debug.logger(
         'built %s octets of substrate: %s\nencoder completed' % (len(substrate), debug.hexdump(substrate)))
     return substrate
Example #2
0
 def __call__(self, value, defMode=True, maxChunkSize=0):
     if not defMode and not self.supportIndefLength:
         raise error.PyAsn1Error('Indefinite length encoding not supported by this codec')
     debug.logger & debug.flagEncoder and debug.logger(
         'encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (
             not defMode and 'in' or '', maxChunkSize, value.prettyPrintType(), value.prettyPrint()))
     tagSet = value.tagSet
     if len(tagSet) > 1:
         concreteEncoder = explicitlyTaggedItemEncoder
     else:
         try:
             concreteEncoder = self.__typeMap[value.typeId]
         except KeyError:
             # use base type for codec lookup to recover untagged types
             baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
             try:
                 concreteEncoder = self.__tagMap[baseTagSet]
             except KeyError:
                 raise error.PyAsn1Error('No encoder for %s' % (value,))
     debug.logger & debug.flagEncoder and debug.logger(
         'using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet))
     substrate = concreteEncoder.encode(
         self, value, defMode, maxChunkSize
     )
     debug.logger & debug.flagEncoder and debug.logger(
         'built %s octets of substrate: %s\nencoder completed' % (len(substrate), debug.hexdump(substrate)))
     return substrate
Example #3
0
 def __call__(self, value, defMode=True, maxChunkSize=0):
     if not defMode and not self.supportIndefLength:
         raise error.PyAsn1Error(
             'Indefinite length encoding not supported by this codec')
     if debug.logger & debug.flagEncoder:
         logger = debug.logger
     else:
         logger = None
     if logger:
         logger(
             'encoder called in %sdef mode, chunk size %s for type %s, value:\n%s'
             % (not defMode and 'in' or '', maxChunkSize,
                value.prettyPrintType(), value.prettyPrint()))
     tagSet = value.tagSet
     if len(tagSet) > 1:
         concreteEncoder = explicitlyTaggedItemEncoder
     else:
         try:
             concreteEncoder = self.__typeMap[value.typeId]
         except KeyError:
             # use base type for codec lookup to recover untagged types
             baseTagSet = tag.TagSet(value.tagSet.baseTag,
                                     value.tagSet.baseTag)
             try:
                 concreteEncoder = self.__tagMap[baseTagSet]
             except KeyError:
                 raise error.PyAsn1Error('No encoder for %s' % (value, ))
         if logger:
             logger('using value codec %s chosen by %s' %
                    (concreteEncoder.__class__.__name__, tagSet))
     substrate = concreteEncoder.encode(self, value, defMode, maxChunkSize)
     if logger:
         logger('built %s octets of substrate: %s\nencoder completed' %
                (len(substrate), debug.hexdump(substrate)))
     return substrate
Example #4
0
 def __call__(self, value, defMode=1, maxChunkSize=0):
     debug.logger & debug.flagEncoder and debug.logger(
         'encoder called for type %s, value:\n%s' %
         (value.__class__.__name__, value.prettyPrint()))
     tagSet = value.getTagSet()
     if len(tagSet) > 1:
         concreteEncoder = explicitlyTaggedItemEncoder
     else:
         if value.typeId is not None and value.typeId in self.__typeMap:
             concreteEncoder = self.__typeMap[value.typeId]
         elif tagSet in self.__tagMap:
             concreteEncoder = self.__tagMap[tagSet]
         else:
             tagSet = value.baseTagSet
             if tagSet in self.__tagMap:
                 concreteEncoder = self.__tagMap[tagSet]
             else:
                 raise Error('No encoder for %s' % (value, ))
     debug.logger & debug.flagEncoder and debug.logger(
         'using value codec %s chosen by %r' %
         (concreteEncoder.__class__.__name__, tagSet))
     substrate = concreteEncoder.encode(self, value, defMode, maxChunkSize)
     debug.logger & debug.flagEncoder and debug.logger(
         'built %s octets of substrate: %s\nencoder completed' %
         (len(substrate), debug.hexdump(substrate)))
     return substrate
Example #5
0
 def __call__(self, value, defMode=True, maxChunkSize=0):
     if not defMode and not self.supportIndefLength:
         raise error.PyAsn1Error(
             'Indefinite length encoding not supported by this codec')
     debug.logger & debug.flagEncoder and debug.logger(
         'encoder called in %sdef mode, chunk size %s for type %s, value:\n%s'
         % (not defMode and 'in' or '', maxChunkSize,
            value.prettyPrintType(), value.prettyPrint()))
     tagSet = value.getTagSet()
     if len(tagSet) > 1:
         concreteEncoder = explicitlyTaggedItemEncoder
     else:
         if value.typeId is not None and value.typeId in self.__typeMap:
             concreteEncoder = self.__typeMap[value.typeId]
         elif tagSet in self.__tagMap:
             concreteEncoder = self.__tagMap[tagSet]
         else:
             tagSet = value.baseTagSet
             if tagSet in self.__tagMap:
                 concreteEncoder = self.__tagMap[tagSet]
             else:
                 raise Error('No encoder for %s' % (value, ))
     debug.logger & debug.flagEncoder and debug.logger(
         'using value codec %s chosen by %s' %
         (concreteEncoder.__class__.__name__, tagSet))
     substrate = concreteEncoder.encode(self, value, defMode, maxChunkSize)
     debug.logger & debug.flagEncoder and debug.logger(
         'built %s octets of substrate: %s\nencoder completed' %
         (len(substrate), debug.hexdump(substrate)))
     return substrate
Example #6
0
    def __call__(self, value, asn1Spec=None, **options):
        try:
            if asn1Spec is None:
                typeId = value.typeId
            else:
                typeId = asn1Spec.typeId

        except AttributeError:
            raise error.PyAsn1Error('Value %r is not ASN.1 type instance '
                                    'and "asn1Spec" not given' % (value, ))

        if LOG:
            LOG('encoder called in %sdef mode, chunk size %s for type %s, '
                'value:\n%s' % (not options.get('defMode', True) and 'in'
                                or '', options.get('maxChunkSize', 0),
                                asn1Spec is None and value.prettyPrintType()
                                or asn1Spec.prettyPrintType(), value))

        if self.fixedDefLengthMode is not None:
            options.update(defMode=self.fixedDefLengthMode)

        if self.fixedChunkSize is not None:
            options.update(maxChunkSize=self.fixedChunkSize)

        try:
            concreteEncoder = self._typeMap[typeId]

            if LOG:
                LOG('using value codec %s chosen by type ID '
                    '%s' % (concreteEncoder.__class__.__name__, typeId))

        except KeyError:
            if asn1Spec is None:
                tagSet = value.tagSet
            else:
                tagSet = asn1Spec.tagSet

            # use base type for codec lookup to recover untagged types
            baseTagSet = tag.TagSet(tagSet.baseTag, tagSet.baseTag)

            try:
                concreteEncoder = self._tagMap[baseTagSet]

            except KeyError:
                raise error.PyAsn1Error('No encoder for %r (%s)' %
                                        (value, tagSet))

            if LOG:
                LOG('using value codec %s chosen by tagSet '
                    '%s' % (concreteEncoder.__class__.__name__, tagSet))

        substrate = concreteEncoder.encode(value, asn1Spec, self, **options)

        if LOG:
            LOG('codec %s built %s octets of substrate: %s\nencoder '
                'completed' %
                (concreteEncoder, len(substrate), debug.hexdump(substrate)))

        return substrate
Example #7
0
    def encode(self, value, asn1Spec=None, encodeFun=None, **options):

        if asn1Spec is None:
            tagSet = value.tagSet
        else:
            tagSet = asn1Spec.tagSet

        # untagged item?
        if not tagSet:
            substrate, isConstructed, isOctets = self.encodeValue(
                value, asn1Spec, encodeFun, **options)
            return substrate

        defMode = options.get('defMode', True)

        substrate = null

        for idx, singleTag in enumerate(tagSet.superTags):

            defModeOverride = defMode

            # base tag?
            if not idx:
                try:
                    substrate, isConstructed, isOctets = self.encodeValue(
                        value, asn1Spec, encodeFun, **options)

                except error.PyAsn1Error:
                    exc = sys.exc_info()
                    raise error.PyAsn1Error('Error encoding %r: %s' %
                                            (value, exc[1]))

                if LOG:
                    LOG('encoded %svalue %s into %s' %
                        (isConstructed and 'constructed '
                         or '', value, substrate))

                if not substrate and isConstructed and options.get(
                        'ifNotEmpty', False):
                    return substrate

                if not isConstructed:
                    defModeOverride = True

                    if LOG:
                        LOG('overridden encoding mode into definitive for primitive type'
                            )

            header = self.encodeTag(singleTag, isConstructed)

            if LOG:
                LOG('encoded %stag %s into %s' %
                    (isConstructed and 'constructed '
                     or '', singleTag, debug.hexdump(ints2octs(header))))

            header += self.encodeLength(len(substrate), defModeOverride)

            if LOG:
                LOG('encoded %s octets (tag + payload) into %s' %
                    (len(substrate), debug.hexdump(ints2octs(header))))

            if isOctets:
                substrate = ints2octs(header) + substrate

                if not defModeOverride:
                    substrate += self.eooOctetsSubstrate

            else:
                substrate = header + substrate

                if not defModeOverride:
                    substrate += self.eooIntegerSubstrate

        if not isOctets:
            substrate = ints2octs(substrate)

        return substrate
Example #8
0
    def __call__(self, substrate, asn1Spec=None, tagSet=None,
                 length=None, state=stDecodeTag, recursiveFlag=1,
                 substrateFun=None, allowEoo=False):
        if debug.logger & debug.flagDecoder:
            debug.logger('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)))
        if asn1Spec is not None and not isinstance(asn1Spec, (base.Asn1Item, tagmap.TagMap)):
            raise error.PyAsn1Error('asn1Spec is not valid (should be an instance of an ASN.1 Item, not %s)' % asn1Spec.__class__.__name__)

        fullSubstrate = substrate
        while state != stStop:
            if state == stDecodeTag:
                if not substrate:
                    raise error.SubstrateUnderrunError(
                        'Short octet stream on tag decoding'
                        )
                if not isOctetsType(substrate) and \
                   not isinstance(substrate, univ.OctetString):
                    raise error.PyAsn1Error('Bad octet stream type')
                # Decode tag
                firstOctet = substrate[0]
                substrate = substrate[1:]
                if firstOctet in self.__tagCache:
                    lastTag = self.__tagCache[firstOctet]
                else:
                    t = oct2int(firstOctet)
                    # Look for end-of-octets sentinel
                    if t == 0:
                        if substrate and oct2int(substrate[0]) == 0:
                            if allowEoo and self.supportIndefLength:
                                debug.logger and debug.logger & debug.flagDecoder and debug.logger('end-of-octets sentinel found')
                                value, substrate = eoo.endOfOctets, substrate[1:]
                                state = stStop
                                continue
                            else:
                                raise error.PyAsn1Error('Unexpected end-of-contents sentinel')
                        else:
                            raise error.PyAsn1Error('Zero tag encountered')
                    tagClass = t&0xC0
                    tagFormat = t&0x20
                    tagId = t&0x1F
                    if tagId == 0x1F:
                        tagId = 0
                        while 1:
                            if not substrate:
                                raise error.SubstrateUnderrunError(
                                    'Short octet stream on long tag decoding'
                                    )
                            t = oct2int(substrate[0])
                            tagId = tagId << 7 | (t&0x7F)
                            substrate = substrate[1:]
                            if not t&0x80:
                                break
                    lastTag = tag.Tag(
                        tagClass=tagClass, tagFormat=tagFormat, tagId=tagId
                    )
                    if tagId < 31:
                        # cache short tags
                        self.__tagCache[firstOctet] = lastTag
                if tagSet is None:
                    if firstOctet in self.__tagSetCache:
                        tagSet = self.__tagSetCache[firstOctet]
                    else:
                        # base tag not recovered
                        tagSet = tag.TagSet((), lastTag)
                        if firstOctet in self.__tagCache:
                            self.__tagSetCache[firstOctet] = tagSet
                else:
                    tagSet = lastTag + tagSet
                state = stDecodeLength
                debug.logger and debug.logger & debug.flagDecoder and debug.logger('tag decoded into %s, decoding length' % tagSet)
            if state == 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 = -1
                elif firstOctet < 128:
                    length, size = firstOctet, 1
                else:
                    size = firstOctet & 0x7F
                    # encoded in size bytes
                    length = 0
                    lengthString = substrate[1:size+1]
                    # missing check on maximum size, which shouldn't be a
                    # problem, we can handle more than is possible
                    if len(lengthString) != size:
                        raise error.SubstrateUnderrunError(
                            '%s<%s at %s' %
                            (size, len(lengthString), tagSet)
                            )
                    for char in lengthString:
                        length = (length << 8) | oct2int(char)
                    size += 1
                substrate = substrate[size:]
                if length != -1 and len(substrate) < length:
                    raise error.SubstrateUnderrunError(
                        '%d-octet short' % (length - len(substrate))
                        )
                if length == -1 and not self.supportIndefLength:
                    error.PyAsn1Error('Indefinite length encoding not supported by this codec')
                state = stGetValueDecoder
                debug.logger and debug.logger & debug.flagDecoder and debug.logger('value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(length == -1 and substrate or substrate[:length])))
            if state == 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 == stGetValueDecoderByTag:
                if tagSet in self.__tagMap:
                    concreteDecoder = self.__tagMap[tagSet]
                else:
                    concreteDecoder = None
                if concreteDecoder:
                    state = stDecodeValue
                else:
                    _k = tagSet[:1]
                    if _k in self.__tagMap:
                        concreteDecoder = self.__tagMap[_k]
                    else:
                        concreteDecoder = None
                    if concreteDecoder:
                        state = stDecodeValue
                    else:
                        state = stTryAsExplicitTag
                if debug.logger and debug.logger & debug.flagDecoder:
                    debug.logger('codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag'))
                    debug.scope.push(concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__)
            if state == stGetValueDecoderByAsn1Spec:
                if isinstance(asn1Spec, (dict, tagmap.TagMap)):
                    if tagSet in asn1Spec:
                        __chosenSpec = asn1Spec[tagSet]
                    else:
                        __chosenSpec = None
                    if debug.logger and debug.logger & debug.flagDecoder:
                        debug.logger('candidate ASN.1 spec is a map of:')
                        for t, v in asn1Spec.getPosMap().items():
                            debug.logger('  %s -> %s' % (t, v.__class__.__name__))
                        if asn1Spec.getNegMap():
                            debug.logger('but neither of: ')
                            for t, v in asn1Spec.getNegMap().items():
                                debug.logger('  %s -> %s' % (t, v.__class__.__name__))
                        debug.logger('new candidate ASN.1 spec is %s, chosen by %s' % (__chosenSpec is None and '<none>' or __chosenSpec.prettyPrintType(), tagSet))
                else:
                    __chosenSpec = asn1Spec
                    debug.logger and debug.logger & debug.flagDecoder and debug.logger('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__)
                if __chosenSpec is not None and (
                       tagSet == __chosenSpec.getTagSet() or \
                       tagSet in __chosenSpec.getTagMap()
                       ):
                    # use base type for codec lookup to recover untagged types
                    baseTagSet = __chosenSpec.baseTagSet
                    if __chosenSpec.typeId is not None and \
                           __chosenSpec.typeId in self.__typeMap:
                        # ambiguous type
                        concreteDecoder = self.__typeMap[__chosenSpec.typeId]
                        debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen for an ambiguous type by type ID %s' % (__chosenSpec.typeId,))
                    elif baseTagSet in self.__tagMap:
                        # base type or tagged subtype
                        concreteDecoder = self.__tagMap[baseTagSet]
                        debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen by base %s' % (baseTagSet,))
                    else:
                        concreteDecoder = None
                    if concreteDecoder:
                        asn1Spec = __chosenSpec
                        state = stDecodeValue
                    else:
                        state = stTryAsExplicitTag
                else:
                    concreteDecoder = None
                    state = stTryAsExplicitTag
                if debug.logger and debug.logger & debug.flagDecoder:
                    debug.logger('codec %s chosen by ASN.1 spec, decoding %s' % (state == stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag'))
                    debug.scope.push(__chosenSpec is None and '?' or __chosenSpec.__class__.__name__)
            if state == stTryAsExplicitTag:
                if tagSet and \
                       tagSet[0][1] == tag.tagFormatConstructed and \
                       tagSet[0][0] != tag.tagClassUniversal:
                    # Assume explicit tagging
                    concreteDecoder = explicitTagDecoder
                    state = stDecodeValue
                else:
                    concreteDecoder = None
                    state = self.defaultErrorState
                debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as failure'))
            if state == stDumpRawValue:
                concreteDecoder = self.defaultRawDecoder
                debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__)
                state = stDecodeValue
            if state == stDecodeValue:
                if recursiveFlag == 0 and not substrateFun: # legacy
                    substrateFun = lambda a,b,c: (a,b[:c])
                if length == -1:  # indef length
                    value, substrate = concreteDecoder.indefLenValueDecoder(
                        fullSubstrate, substrate, asn1Spec, tagSet, length,
                        stGetValueDecoder, self, substrateFun
                        )
                else:
                    value, substrate = concreteDecoder.valueDecoder(
                        fullSubstrate, substrate, asn1Spec, tagSet, length,
                        stGetValueDecoder, self, substrateFun
                        )
                state = stStop
                debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '<none>'))
            if state == stErrorCondition:
                raise error.PyAsn1Error(
                    '%s not in asn1Spec: %s' % (tagSet, asn1Spec)
                )
        if debug.logger and debug.logger & debug.flagDecoder:
            debug.scope.pop()
            debug.logger('decoder left scope %s, call completed' % debug.scope)
        return value, substrate
Example #9
0
    def __call__(self,
                 substrate,
                 asn1Spec=None,
                 tagSet=None,
                 length=None,
                 state=stDecodeTag,
                 recursiveFlag=1,
                 substrateFun=None,
                 allowEoo=False):
        if debug.logger & debug.flagDecoder:
            debug.logger(
                '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)))
        if asn1Spec is not None and not isinstance(
                asn1Spec, (base.Asn1Item, tagmap.TagMap)):
            raise error.PyAsn1Error(
                'asn1Spec is not valid (should be an instance of an ASN.1 Item, not %s)'
                % asn1Spec.__class__.__name__)

        value = base.noValue

        fullSubstrate = substrate
        while state != stStop:
            if state == stDecodeTag:
                if not substrate:
                    raise error.SubstrateUnderrunError(
                        'Short octet stream on tag decoding')
                if not isOctetsType(substrate) and \
                        not isinstance(substrate, univ.OctetString):
                    raise error.PyAsn1Error('Bad octet stream type')
                # Decode tag
                firstOctet = substrate[0]
                substrate = substrate[1:]
                if firstOctet in self.__tagCache:
                    lastTag = self.__tagCache[firstOctet]
                else:
                    t = oct2int(firstOctet)
                    # Look for end-of-octets sentinel
                    if t == 0:
                        if substrate and oct2int(substrate[0]) == 0:
                            if allowEoo and self.supportIndefLength:
                                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                                    'end-of-octets sentinel found')
                                value, substrate = eoo.endOfOctets, substrate[
                                    1:]
                                state = stStop
                                continue
                            else:
                                raise error.PyAsn1Error(
                                    'Unexpected end-of-contents sentinel')
                        else:
                            raise error.PyAsn1Error('Zero tag encountered')
                    tagClass = t & 0xC0
                    tagFormat = t & 0x20
                    tagId = t & 0x1F
                    short = True
                    if tagId == 0x1F:
                        short = False
                        tagId = 0
                        while True:
                            if not substrate:
                                raise error.SubstrateUnderrunError(
                                    'Short octet stream on long tag decoding')
                            t = oct2int(substrate[0])
                            tagId = tagId << 7 | (t & 0x7F)
                            substrate = substrate[1:]
                            if not t & 0x80:
                                break
                    lastTag = tag.Tag(tagClass=tagClass,
                                      tagFormat=tagFormat,
                                      tagId=tagId)
                    if short:
                        # cache short tags
                        self.__tagCache[firstOctet] = lastTag
                if tagSet is None:
                    if firstOctet in self.__tagSetCache:
                        tagSet = self.__tagSetCache[firstOctet]
                    else:
                        # base tag not recovered
                        tagSet = tag.TagSet((), lastTag)
                        if firstOctet in self.__tagCache:
                            self.__tagSetCache[firstOctet] = tagSet
                else:
                    tagSet = lastTag + tagSet
                state = stDecodeLength
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'tag decoded into %s, decoding length' % tagSet)
            if state == 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 = -1
                elif firstOctet < 128:
                    length, size = firstOctet, 1
                else:
                    size = firstOctet & 0x7F
                    # encoded in size bytes
                    length = 0
                    lengthString = substrate[1:size + 1]
                    # missing check on maximum size, which shouldn't be a
                    # problem, we can handle more than is possible
                    if len(lengthString) != size:
                        raise error.SubstrateUnderrunError(
                            '%s<%s at %s' % (size, len(lengthString), tagSet))
                    for char in lengthString:
                        length = (length << 8) | oct2int(char)
                    size += 1
                substrate = substrate[size:]
                if length != -1 and len(substrate) < length:
                    raise error.SubstrateUnderrunError(
                        '%d-octet short' % (length - len(substrate)))
                if length == -1 and not self.supportIndefLength:
                    error.PyAsn1Error(
                        'Indefinite length encoding not supported by this codec'
                    )
                state = stGetValueDecoder
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'value length decoded into %d, payload substrate is: %s' %
                    (length,
                     debug.hexdump(length == -1 and substrate
                                   or substrate[:length])))
            if state == 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 == stGetValueDecoderByTag:
                if tagSet in self.__tagMap:
                    concreteDecoder = self.__tagMap[tagSet]
                else:
                    concreteDecoder = None
                if concreteDecoder:
                    state = stDecodeValue
                else:
                    _k = tagSet[:1]
                    if _k in self.__tagMap:
                        concreteDecoder = self.__tagMap[_k]
                    else:
                        concreteDecoder = None
                    if concreteDecoder:
                        state = stDecodeValue
                    else:
                        state = stTryAsExplicitTag
                if debug.logger and debug.logger & debug.flagDecoder:
                    debug.logger(
                        'codec %s chosen by a built-in type, decoding %s' %
                        (concreteDecoder and concreteDecoder.__class__.__name__
                         or "<none>", state == stDecodeValue and 'value'
                         or 'as explicit tag'))
                    debug.scope.push(
                        concreteDecoder is None and '?'
                        or concreteDecoder.protoComponent.__class__.__name__)
            if state == stGetValueDecoderByAsn1Spec:
                if isinstance(asn1Spec, (dict, tagmap.TagMap)):
                    if tagSet in asn1Spec:
                        __chosenSpec = asn1Spec[tagSet]
                    else:
                        __chosenSpec = None
                    if debug.logger and debug.logger & debug.flagDecoder:
                        debug.logger('candidate ASN.1 spec is a map of:')
                        for t, v in asn1Spec.getPosMap().items():
                            debug.logger('  %s -> %s' %
                                         (t, v.__class__.__name__))
                        if asn1Spec.getNegMap():
                            debug.logger('but neither of: ')
                            for t, v in asn1Spec.getNegMap().items():
                                debug.logger('  %s -> %s' %
                                             (t, v.__class__.__name__))
                        debug.logger(
                            'new candidate ASN.1 spec is %s, chosen by %s' %
                            (__chosenSpec is None and '<none>'
                             or __chosenSpec.prettyPrintType(), tagSet))
                else:
                    __chosenSpec = asn1Spec
                    debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                        'candidate ASN.1 spec is %s' %
                        asn1Spec.__class__.__name__)
                if __chosenSpec is not None and (
                        tagSet == __chosenSpec.getTagSet()
                        or tagSet in __chosenSpec.getTagMap()):
                    # use base type for codec lookup to recover untagged types
                    baseTagSet = __chosenSpec.baseTagSet
                    if __chosenSpec.typeId is not None and \
                            __chosenSpec.typeId in self.__typeMap:
                        # ambiguous type
                        concreteDecoder = self.__typeMap[__chosenSpec.typeId]
                        debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                            'value decoder chosen for an ambiguous type by type ID %s'
                            % (__chosenSpec.typeId, ))
                    elif baseTagSet in self.__tagMap:
                        # base type or tagged subtype
                        concreteDecoder = self.__tagMap[baseTagSet]
                        debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                            'value decoder chosen by base %s' % (baseTagSet, ))
                    else:
                        concreteDecoder = None
                    if concreteDecoder:
                        asn1Spec = __chosenSpec
                        state = stDecodeValue
                    else:
                        state = stTryAsExplicitTag
                else:
                    concreteDecoder = None
                    state = stTryAsExplicitTag
                if debug.logger and debug.logger & debug.flagDecoder:
                    debug.logger(
                        'codec %s chosen by ASN.1 spec, decoding %s' %
                        (state == stDecodeValue
                         and concreteDecoder.__class__.__name__
                         or "<none>", state == stDecodeValue and 'value'
                         or 'as explicit tag'))
                    debug.scope.push(__chosenSpec is None and '?'
                                     or __chosenSpec.__class__.__name__)
            if state == stTryAsExplicitTag:
                if tagSet and tagSet[0][1] == tag.tagFormatConstructed and \
                        tagSet[0][0] != tag.tagClassUniversal:
                    # Assume explicit tagging
                    concreteDecoder = explicitTagDecoder
                    state = stDecodeValue
                else:
                    concreteDecoder = None
                    state = self.defaultErrorState
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'codec %s chosen, decoding %s' %
                    (concreteDecoder and concreteDecoder.__class__.__name__
                     or "<none>", state == stDecodeValue and 'value'
                     or 'as failure'))
            if state == stDumpRawValue:
                concreteDecoder = self.defaultRawDecoder
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'codec %s chosen, decoding value' %
                    concreteDecoder.__class__.__name__)
                state = stDecodeValue
            if state == stDecodeValue:
                if recursiveFlag == 0 and not substrateFun:  # legacy

                    def substrateFun(a, b, c):
                        return a, b[:c]

                if length == -1:  # indef length
                    value, substrate = concreteDecoder.indefLenValueDecoder(
                        fullSubstrate, substrate, asn1Spec, tagSet, length,
                        stGetValueDecoder, self, substrateFun)
                else:
                    value, substrate = concreteDecoder.valueDecoder(
                        fullSubstrate, substrate, asn1Spec, tagSet, length,
                        stGetValueDecoder, self, substrateFun)
                state = stStop
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'codec %s yields type %s, value:\n%s\n...remaining substrate is: %s'
                    % (concreteDecoder.__class__.__name__,
                       value.__class__.__name__, value.prettyPrint(),
                       substrate and debug.hexdump(substrate) or '<none>'))
            if state == stErrorCondition:
                raise error.PyAsn1Error('%s not in asn1Spec: %s' %
                                        (tagSet, asn1Spec))
        if debug.logger and debug.logger & debug.flagDecoder:
            debug.scope.pop()
            debug.logger('decoder left scope %s, call completed' % debug.scope)
        return value, substrate
Example #10
0
 def __call__(self, value, defMode=1, maxChunkSize=0):
     debug.logger & debug.flagEncoder and debug.logger('encoder called for type %s, value:\n%s' % (value.__class__.__name__, value.prettyPrint()))
     tagSet = value.getTagSet()
     if len(tagSet) > 1:
         concreteEncoder = explicitlyTaggedItemEncoder
     else:
         if value.typeId is not None and value.typeId in self.__typeMap:
             concreteEncoder = self.__typeMap[value.typeId]
         elif tagSet in self.__tagMap:
             concreteEncoder = self.__tagMap[tagSet]
         else:
             tagSet = value.baseTagSet
             if tagSet in self.__tagMap:
                 concreteEncoder = self.__tagMap[tagSet]
             else:
                 raise Error('No encoder for %s' % (value,))
     debug.logger & debug.flagEncoder and debug.logger('using value codec %s chosen by %r' % (concreteEncoder.__class__.__name__, tagSet))
     substrate = concreteEncoder.encode(
         self, value, defMode, maxChunkSize
         )
     debug.logger & debug.flagEncoder and debug.logger('built %s octets of substrate: %s\nencoder completed' % (len(substrate), debug.hexdump(substrate)))
     return substrate
Example #11
0
    def encode(self, value, asn1Spec=None, encodeFun=None, **options):

        if asn1Spec is None:
            tagSet = value.tagSet
        else:
            tagSet = asn1Spec.tagSet

        # untagged item?
        if not tagSet:
            substrate, isConstructed, isOctets = self.encodeValue(
                value, asn1Spec, encodeFun, **options
            )
            return substrate

        defMode = options.get('defMode', True)

        for idx, singleTag in enumerate(tagSet.superTags):

            defModeOverride = defMode

            # base tag?
            if not idx:
                substrate, isConstructed, isOctets = self.encodeValue(
                    value, asn1Spec, encodeFun, **options
                )

                if LOG:
                    LOG('encoded %svalue %s into %s' % (
                        isConstructed and 'constructed ' or '', value, substrate
                    ))

                if not substrate and isConstructed and options.get('ifNotEmpty', False):
                    return substrate

                if not isConstructed:
                    defModeOverride = True

                    if LOG:
                        LOG('overridden encoding mode into definitive for primitive type')

            header = self.encodeTag(singleTag, isConstructed)

            if LOG:
                LOG('encoded %stag %s into %s' % (
                    isConstructed and 'constructed ' or '',
                    singleTag, debug.hexdump(ints2octs(header))))

            header += self.encodeLength(len(substrate), defModeOverride)

            if LOG:
                LOG('encoded %s octets (tag + payload) into %s' % (
                    len(substrate), debug.hexdump(ints2octs(header))))

            if isOctets:
                substrate = ints2octs(header) + substrate

                if not defModeOverride:
                    substrate += self.eooOctetsSubstrate

            else:
                substrate = header + substrate

                if not defModeOverride:
                    substrate += self.eooIntegerSubstrate

        if not isOctets:
            substrate = ints2octs(substrate)

        return substrate
Example #12
0
    def __call__(self, value, asn1Spec=None, **options):
        try:
            if asn1Spec is None:
                typeId = value.typeId
            else:
                typeId = asn1Spec.typeId

        except AttributeError:
            raise error.PyAsn1Error('Value %r is not ASN.1 type instance '
                                    'and "asn1Spec" not given' % (value,))

        if LOG:
            LOG('encoder called in %sdef mode, chunk size %s for '
                   'type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), asn1Spec is None and value.prettyPrintType() or asn1Spec.prettyPrintType(), value))

        if self.fixedDefLengthMode is not None:
            options.update(defMode=self.fixedDefLengthMode)

        if self.fixedChunkSize is not None:
            options.update(maxChunkSize=self.fixedChunkSize)


        try:
            concreteEncoder = self.__typeMap[typeId]

            if LOG:
                LOG('using value codec %s chosen by type ID %s' % (concreteEncoder.__class__.__name__, typeId))

        except KeyError:
            if asn1Spec is None:
                tagSet = value.tagSet
            else:
                tagSet = asn1Spec.tagSet

            # use base type for codec lookup to recover untagged types
            baseTagSet = tag.TagSet(tagSet.baseTag, tagSet.baseTag)

            try:
                concreteEncoder = self.__tagMap[baseTagSet]

            except KeyError:
                raise error.PyAsn1Error('No encoder for %r (%s)' % (value, tagSet))

            if LOG:
                LOG('using value codec %s chosen by tagSet %s' % (concreteEncoder.__class__.__name__, tagSet))

        substrate = concreteEncoder.encode(value, asn1Spec, self, **options)

        if LOG:
            LOG('codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate)))

        return substrate
Example #13
0
    def __call__(self,
                 substrate,
                 asn1Spec=None,
                 tagSet=None,
                 length=None,
                 state=stDecodeTag,
                 recursiveFlag=True,
                 substrateFun=None,
                 allowEoo=False):
        if debug.logger & debug.flagDecoder:
            logger = debug.logger
        else:
            logger = None

        if logger:
            logger(
                '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)))

        substrate = ensureString(substrate)

        # Look for end-of-octets sentinel
        if allowEoo and self.supportIndefLength:
            if substrate.startswith(self.__eooSentinel):
                if logger:
                    logger('end-of-octets sentinel found')
                return eoo.endOfOctets, substrate[2:]

        value = base.noValue

        fullSubstrate = substrate
        while not state is 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 = self.__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
                        self.__tagCache[firstOctet] = lastTag
                if tagSet is None:
                    if isShortTag:
                        try:
                            tagSet = self.__tagSetCache[firstOctet]
                        except KeyError:
                            # base tag not recovered
                            tagSet = tag.TagSet((), lastTag)
                            self.__tagSetCache[firstOctet] = tagSet
                    else:
                        tagSet = tag.TagSet((), lastTag)
                else:
                    tagSet = lastTag + tagSet
                state = stDecodeLength
                if logger:
                    logger('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 = 1
                    length = -1
                else:
                    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
                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 logger:
                    logger(
                        '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 = self.__tagMap[tagSet]
                except KeyError:
                    concreteDecoder = None
                if concreteDecoder:
                    state = stDecodeValue
                else:
                    try:
                        concreteDecoder = self.__tagMap[tagSet[:1]]
                    except KeyError:
                        concreteDecoder = None
                    if concreteDecoder:
                        state = stDecodeValue
                    else:
                        state = stTryAsExplicitTag
                if logger:
                    logger(
                        '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 dict or asn1Spec.__class__ is tagmap.TagMap:
                    try:
                        chosenSpec = asn1Spec[tagSet]
                    except KeyError:
                        chosenSpec = None
                    if logger:
                        logger('candidate ASN.1 spec is a map of:')
                        for firstOctet, v in asn1Spec.presentTypes.items():
                            logger('  %s -> %s' %
                                   (firstOctet, v.__class__.__name__))
                        if asn1Spec.skipTypes:
                            logger('but neither of: ')
                            for firstOctet, v in asn1Spec.skipTypes.items():
                                logger('  %s -> %s' %
                                       (firstOctet, v.__class__.__name__))
                        logger('new candidate ASN.1 spec is %s, chosen by %s' %
                               (chosenSpec is None and '<none>'
                                or chosenSpec.prettyPrintType(), tagSet))
                else:
                    if tagSet == asn1Spec.tagSet or tagSet in asn1Spec.tagMap:
                        chosenSpec = asn1Spec
                        if logger:
                            logger('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 = self.__typeMap[chosenSpec.typeId]
                        if logger:
                            logger(
                                '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 = self.__tagMap[baseTagSet]
                            if logger:
                                logger('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 logger:
                    logger('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 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 logger:
                    logger(
                        '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 logger:
                    logger('codec %s chosen, decoding value' %
                           concreteDecoder.__class__.__name__)
                state = stDecodeValue
            if state is stDecodeValue:
                if not recursiveFlag and not substrateFun:  # legacy

                    def substrateFun(a, b, c):
                        return a, b[:c]

                if length == -1:  # indef length
                    value, substrate = concreteDecoder.indefLenValueDecoder(
                        fullSubstrate, substrate, asn1Spec, tagSet, length,
                        stGetValueDecoder, self, substrateFun)
                else:
                    value, substrate = concreteDecoder.valueDecoder(
                        fullSubstrate, substrate, asn1Spec, tagSet, length,
                        stGetValueDecoder, self, substrateFun)
                state = stStop
                if logger:
                    logger(
                        'codec %s yields type %s, value:\n%s\n...remaining substrate is: %s'
                        % (concreteDecoder.__class__.__name__,
                           value.__class__.__name__, value.prettyPrint(),
                           substrate and debug.hexdump(substrate) or '<none>'))
            if state is stErrorCondition:
                raise error.PyAsn1Error('%s not in asn1Spec: %r' %
                                        (tagSet, asn1Spec))
        if logger:
            debug.scope.pop()
            logger('decoder left scope %s, call completed' % debug.scope)
        return value, substrate
Example #14
0
    def __call__(self, value, **options):

        if debug.logger & debug.flagEncoder:
            logger = debug.logger
        else:
            logger = None

        if logger:
            logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), value.prettyPrintType(), value.prettyPrint()))

        if self.fixedDefLengthMode is not None:
            options.update(defMode=self.fixedDefLengthMode)

        if self.fixedChunkSize is not None:
            options.update(maxChunkSize=self.fixedChunkSize)

        tagSet = value.tagSet

        try:
            concreteEncoder = self.__typeMap[value.typeId]

        except KeyError:
            # use base type for codec lookup to recover untagged types
            baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)

            try:
                concreteEncoder = self.__tagMap[baseTagSet]

            except KeyError:
                raise error.PyAsn1Error('No encoder for %s' % (value,))

        if logger:
            logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet))

        substrate = concreteEncoder.encode(value, self, **options)

        if logger:
            logger('codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate)))

        return substrate
Example #15
0
    def __call__(self,
                 substrate,
                 asn1Spec=None,
                 tagSet=None,
                 length=None,
                 state=stDecodeTag,
                 recursiveFlag=1):
        debug.logger & debug.flagDecoder and debug.logger(
            'decoder called with state %d, working with up to %d octets of substrate: %s'
            % (state, len(substrate), debug.hexdump(substrate)))
        fullSubstrate = substrate
        while state != stStop:
            if state == stDecodeTag:
                # Decode tag
                if not substrate:
                    raise error.SubstrateUnderrunError(
                        'Short octet stream on tag decoding')

                firstOctet = substrate[0]
                substrate = substrate[1:]
                if firstOctet in self.__tagCache:
                    lastTag = self.__tagCache[firstOctet]
                else:
                    t = oct2int(firstOctet)
                    tagClass = t & 0xC0
                    tagFormat = t & 0x20
                    tagId = t & 0x1F
                    if tagId == 0x1F:
                        tagId = 0
                        while 1:
                            if not substrate:
                                raise error.SubstrateUnderrunError(
                                    'Short octet stream on long tag decoding')
                            t = oct2int(substrate[0])
                            tagId = tagId << 7 | (t & 0x7F)
                            substrate = substrate[1:]
                            if not t & 0x80:
                                break
                    lastTag = tag.Tag(tagClass=tagClass,
                                      tagFormat=tagFormat,
                                      tagId=tagId)
                    if tagId < 31:
                        # cache short tags
                        self.__tagCache[firstOctet] = lastTag
                if tagSet is None:
                    if firstOctet in self.__tagSetCache:
                        tagSet = self.__tagSetCache[firstOctet]
                    else:
                        # base tag not recovered
                        tagSet = tag.TagSet((), lastTag)
                        if firstOctet in self.__tagCache:
                            self.__tagSetCache[firstOctet] = tagSet
                else:
                    tagSet = lastTag + tagSet
                state = stDecodeLength
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'tag decoded into %r, decoding length' % tagSet)
            if state == 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 = -1
                elif firstOctet < 128:
                    length, size = firstOctet, 1
                else:
                    size = firstOctet & 0x7F
                    # encoded in size bytes
                    length = 0
                    lengthString = substrate[1:size + 1]
                    # missing check on maximum size, which shouldn't be a
                    # problem, we can handle more than is possible
                    if len(lengthString) != size:
                        raise error.SubstrateUnderrunError(
                            '%s<%s at %s' % (size, len(lengthString), tagSet))
                    for char in lengthString:
                        length = (length << 8) | oct2int(char)
                    size = size + 1
                substrate = substrate[size:]
                if length != -1 and len(substrate) < length:
                    raise error.SubstrateUnderrunError(
                        '%d-octet short' % (length - len(substrate)))
                state = stGetValueDecoder
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'value length decoded into %d, payload substrate is: %s' %
                    (length, debug.hexdump(substrate)))
            if state == 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 == stGetValueDecoderByTag:
                if tagSet in self.__tagMap:
                    concreteDecoder = self.__tagMap[tagSet]
                else:
                    concreteDecoder = None
                if concreteDecoder:
                    state = stDecodeValue
                else:
                    _k = tagSet[:1]
                    if _k in self.__tagMap:
                        concreteDecoder = self.__tagMap[_k]
                    else:
                        concreteDecoder = None
                    if concreteDecoder:
                        state = stDecodeValue
                    else:
                        state = stTryAsExplicitTag
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'codec %s chosen by a built-in type, decoding %s' %
                    (concreteDecoder and concreteDecoder.__class__.__name__
                     or "<none>", state == stDecodeValue and 'value'
                     or 'explicit tag'))
            if state == stGetValueDecoderByAsn1Spec:
                if isinstance(asn1Spec, (dict, tagmap.TagMap)):
                    if tagSet in asn1Spec:
                        __chosenSpec = asn1Spec[tagSet]
                    else:
                        __chosenSpec = None
                else:
                    __chosenSpec = asn1Spec
                if __chosenSpec is not None and (
                       tagSet == __chosenSpec.getTagSet() or \
                       tagSet in __chosenSpec.getTagMap()
                       ):
                    # use base type for codec lookup to recover untagged types
                    baseTagSet = __chosenSpec.baseTagSet
                    if __chosenSpec.typeId is not None and \
                           __chosenSpec.typeId in self.__typeMap:
                        # ambiguous type
                        concreteDecoder = self.__typeMap[__chosenSpec.typeId]
                    elif baseTagSet in self.__tagMap:
                        # base type or tagged subtype
                        concreteDecoder = self.__tagMap[baseTagSet]
                    else:
                        concreteDecoder = None
                    if concreteDecoder:
                        asn1Spec = __chosenSpec
                        state = stDecodeValue
                    else:
                        state = stTryAsExplicitTag
                elif tagSet == self.__endOfOctetsTagSet:
                    concreteDecoder = self.__tagMap[tagSet]
                    state = stDecodeValue
                else:
                    state = stTryAsExplicitTag
                if debug.logger and debug.logger & debug.flagDecoder:
                    if isinstance(asn1Spec, base.Asn1Item):
                        debug.logger(
                            'choosing value codec by ASN.1 spec:\n  %r -> %r' %
                            (asn1Spec.getTagSet(),
                             asn1Spec.__class__.__name__))
                    else:
                        debug.logger(
                            'choosing value codec by ASN.1 spec that offers either of the following: '
                        )
                        for t, v in list(asn1Spec.getPosMap().items()):
                            debug.logger('  %r -> %s' %
                                         (t, v.__class__.__name__))
                        debug.logger('but neither of: ')
                        for i in list(asn1Spec.getNegMap().items()):
                            debug.logger('  %r -> %s' %
                                         (t, v.__class__.__name__))
                    debug.logger(
                        'codec %s chosen by ASN.1 spec, decoding %s' %
                        (state == stDecodeValue
                         and concreteDecoder.__class__.__name__ or "<none>",
                         state == stDecodeValue and 'value' or 'explicit tag'))
            if state == stTryAsExplicitTag:
                if tagSet and \
                       tagSet[0][1] == tag.tagFormatConstructed and \
                       tagSet[0][0] != tag.tagClassUniversal:
                    # Assume explicit tagging
                    concreteDecoder = explicitTagDecoder
                    state = stDecodeValue
                else:
                    state = self.defaultErrorState
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'codec %s chosen, decoding %s' %
                    (concreteDecoder and concreteDecoder.__class__.__name__
                     or "<none>", state == stDecodeValue and 'value'
                     or 'as failure'))
            if state == stDumpRawValue:
                concreteDecoder = self.defaultRawDecoder
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'codec %s chosen, decoding value' %
                    concreteDecoder.__class__.__name__)
                state = stDecodeValue
            if state == stDecodeValue:
                if recursiveFlag:
                    decodeFun = self
                else:
                    decodeFun = None
                if length == -1:  # indef length
                    value, substrate = concreteDecoder.indefLenValueDecoder(
                        fullSubstrate, substrate, asn1Spec, tagSet, length,
                        stGetValueDecoder, decodeFun)
                else:
                    value, _substrate = concreteDecoder.valueDecoder(
                        fullSubstrate, substrate, asn1Spec, tagSet, length,
                        stGetValueDecoder, decodeFun)
                    if recursiveFlag:
                        substrate = substrate[length:]
                    else:
                        substrate = _substrate
                state = stStop
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'codec %s yields type %s, value:\n%s\n...remaining substrate is: %s'
                    % (concreteDecoder.__class__.__name__,
                       value.__class__.__name__, value.prettyPrint(),
                       substrate and debug.hexdump(substrate) or '<none>'))
            if state == stErrorCondition:
                raise error.PyAsn1Error('%r not in asn1Spec: %r' %
                                        (tagSet, asn1Spec))
        debug.logger and debug.logger & debug.flagDecoder and debug.logger(
            'decoder call completed')
        return value, substrate
Example #16
0
    def __call__(self, substrate, asn1Spec=None, tagSet=None,
                 length=None, state=stDecodeTag, recursiveFlag=True,
                 substrateFun=None, allowEoo=False):
        if debug.logger and debug.logger & debug.flagDecoder:
            debug.logger('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)))

        substrate = ensureString(substrate)

        # Look for end-of-octets sentinel
        if allowEoo and self.supportIndefLength:
            if substrate.startswith(self.__eooSentinel):
                debug.logger and debug.logger & debug.flagDecoder and debug.logger('end-of-octets sentinel found')
                return eoo.endOfOctets, substrate[2:]

        value = base.noValue

        fullSubstrate = substrate
        while state != stStop:
            if state == 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 = self.__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
                        self.__tagCache[firstOctet] = lastTag
                if tagSet is None:
                    if isShortTag:
                        try:
                            tagSet = self.__tagSetCache[firstOctet]
                        except KeyError:
                            # base tag not recovered
                            tagSet = tag.TagSet((), lastTag)
                            self.__tagSetCache[firstOctet] = tagSet
                    else:
                        tagSet = tag.TagSet((), lastTag)
                else:
                    tagSet = lastTag + tagSet
                state = stDecodeLength
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'tag decoded into %s, decoding length' % tagSet)
            if state == 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 = 1
                    length = -1
                else:
                    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
                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
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(length == -1 and substrate or substrate[:length]))
                )
            if state == 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 == stGetValueDecoderByTag:
                try:
                    concreteDecoder = self.__tagMap[tagSet]
                except KeyError:
                    concreteDecoder = None
                if concreteDecoder:
                    state = stDecodeValue
                else:
                    try:
                        concreteDecoder = self.__tagMap[tagSet[:1]]
                    except KeyError:
                        concreteDecoder = None
                    if concreteDecoder:
                        state = stDecodeValue
                    else:
                        state = stTryAsExplicitTag
                if debug.logger and debug.logger & debug.flagDecoder:
                    debug.logger('codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag'))
                    debug.scope.push(
                        concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__)
            if state == stGetValueDecoderByAsn1Spec:
                if asn1Spec.__class__ is dict or asn1Spec.__class__ is tagmap.TagMap:
                    try:
                        chosenSpec = asn1Spec[tagSet]
                    except KeyError:
                        chosenSpec = None
                    if debug.logger and debug.logger & debug.flagDecoder:
                        debug.logger('candidate ASN.1 spec is a map of:')
                        for firstOctet, v in asn1Spec.presentTypes.items():
                            debug.logger('  %s -> %s' % (firstOctet, v.__class__.__name__))
                        if asn1Spec.skipTypes:
                            debug.logger('but neither of: ')
                            for firstOctet, v in asn1Spec.skipTypes.items():
                                debug.logger('  %s -> %s' % (firstOctet, v.__class__.__name__))
                        debug.logger('new candidate ASN.1 spec is %s, chosen by %s' % (chosenSpec is None and '<none>' or chosenSpec.prettyPrintType(), tagSet))
                else:
                    if tagSet == asn1Spec.tagSet or tagSet in asn1Spec.tagMap:
                        chosenSpec = asn1Spec
                        debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                            '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 = self.__typeMap[chosenSpec.typeId]
                        debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                            '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 = self.__tagMap[baseTagSet]
                            debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                                '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 debug.logger and debug.logger & debug.flagDecoder:
                    debug.logger('codec %s chosen by ASN.1 spec, decoding %s' % (state == stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag'))
                    debug.scope.push(chosenSpec is None and '?' or chosenSpec.__class__.__name__)
            if state == 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
                debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as failure'))
            if state == stDumpRawValue:
                concreteDecoder = self.defaultRawDecoder
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'codec %s chosen, decoding value' % concreteDecoder.__class__.__name__)
                state = stDecodeValue
            if state == stDecodeValue:
                if not recursiveFlag and not substrateFun:  # legacy
                    def substrateFun(a, b, c):
                        return a, b[:c]
                if length == -1:  # indef length
                    value, substrate = concreteDecoder.indefLenValueDecoder(
                        fullSubstrate, substrate, asn1Spec, tagSet, length,
                        stGetValueDecoder, self, substrateFun
                    )
                else:
                    value, substrate = concreteDecoder.valueDecoder(
                        fullSubstrate, substrate, asn1Spec, tagSet, length,
                        stGetValueDecoder, self, substrateFun
                    )
                state = stStop
                debug.logger and debug.logger & debug.flagDecoder and debug.logger(
                    'codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '<none>'))
            if state == stErrorCondition:
                raise error.PyAsn1Error(
                    '%s not in asn1Spec: %s' % (tagSet, asn1Spec)
                )
        if debug.logger and debug.logger & debug.flagDecoder:
            debug.scope.pop()
            debug.logger('decoder left scope %s, call completed' % debug.scope)
        return value, substrate
Example #17
0
 def __call__(self, substrate, asn1Spec=None, tagSet=None,
              length=None, state=stDecodeTag, recursiveFlag=1):
     debug.logger & debug.flagDecoder and debug.logger('decoder called with state %d, working with up to %d octets of substrate: %s' % (state, len(substrate), debug.hexdump(substrate)))
     fullSubstrate = substrate
     while state != stStop:
         if state == stDecodeTag:
             # Decode tag
             if not substrate:
                 raise error.SubstrateUnderrunError(
                     'Short octet stream on tag decoding'
                     )
             
             firstOctet = substrate[0]
             substrate = substrate[1:]
             if firstOctet in self.__tagCache:
                 lastTag = self.__tagCache[firstOctet]
             else:
                 t = oct2int(firstOctet)
                 tagClass = t&0xC0
                 tagFormat = t&0x20
                 tagId = t&0x1F
                 if tagId == 0x1F:
                     tagId = 0
                     while 1:
                         if not substrate:
                             raise error.SubstrateUnderrunError(
                                 'Short octet stream on long tag decoding'
                                 )
                         t = oct2int(substrate[0])
                         tagId = tagId << 7 | (t&0x7F)
                         substrate = substrate[1:]
                         if not t&0x80:
                             break
                 lastTag = tag.Tag(
                     tagClass=tagClass, tagFormat=tagFormat, tagId=tagId
                     )
                 if tagId < 31:
                     # cache short tags
                     self.__tagCache[firstOctet] = lastTag
             if tagSet is None:
                 if firstOctet in self.__tagSetCache:
                     tagSet = self.__tagSetCache[firstOctet]
                 else:
                     # base tag not recovered
                     tagSet = tag.TagSet((), lastTag)
                     if firstOctet in self.__tagCache:
                         self.__tagSetCache[firstOctet] = tagSet
             else:
                 tagSet = lastTag + tagSet
             state = stDecodeLength
             debug.logger and debug.logger & debug.flagDecoder and debug.logger('tag decoded into %r, decoding length' % tagSet)
         if state == 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 = -1
             elif firstOctet < 128:
                 length, size = firstOctet, 1
             else:
                 size = firstOctet & 0x7F
                 # encoded in size bytes
                 length = 0
                 lengthString = substrate[1:size+1]
                 # missing check on maximum size, which shouldn't be a
                 # problem, we can handle more than is possible
                 if len(lengthString) != size:
                     raise error.SubstrateUnderrunError(
                         '%s<%s at %s' %
                         (size, len(lengthString), tagSet)
                         )
                 for char in lengthString:
                     length = (length << 8) | oct2int(char)
                 size = size + 1
             substrate = substrate[size:]
             if length != -1 and len(substrate) < length:
                 raise error.SubstrateUnderrunError(
                     '%d-octet short' % (length - len(substrate))
                     )
             state = stGetValueDecoder
             debug.logger and debug.logger & debug.flagDecoder and debug.logger('value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(substrate)))
         if state == 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 == stGetValueDecoderByTag:
             if tagSet in self.__tagMap:
                 concreteDecoder = self.__tagMap[tagSet]
             else:
                 concreteDecoder = None
             if concreteDecoder:
                 state = stDecodeValue
             else:
                 _k = tagSet[:1]
                 if _k in self.__tagMap:
                     concreteDecoder = self.__tagMap[_k]
                 else:
                     concreteDecoder = None
                 if concreteDecoder:
                     state = stDecodeValue
                 else:
                     state = stTryAsExplicitTag
             debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'explicit tag'))
         if state == stGetValueDecoderByAsn1Spec:
             if isinstance(asn1Spec, (dict, tagmap.TagMap)):
                 if tagSet in asn1Spec:
                     __chosenSpec = asn1Spec[tagSet]
                 else:
                     __chosenSpec = None
             else:
                 __chosenSpec = asn1Spec
             if __chosenSpec is not None and (
                    tagSet == __chosenSpec.getTagSet() or \
                    tagSet in __chosenSpec.getTagMap()
                    ):
                 # use base type for codec lookup to recover untagged types
                 baseTagSet = __chosenSpec.baseTagSet
                 if __chosenSpec.typeId is not None and \
                        __chosenSpec.typeId in self.__typeMap:
                     # ambiguous type
                     concreteDecoder = self.__typeMap[__chosenSpec.typeId]
                 elif baseTagSet in self.__tagMap:
                     # base type or tagged subtype
                     concreteDecoder = self.__tagMap[baseTagSet]
                 else:
                     concreteDecoder = None
                 if concreteDecoder:
                     asn1Spec = __chosenSpec
                     state = stDecodeValue
                 else:
                     state = stTryAsExplicitTag
             elif tagSet == self.__endOfOctetsTagSet:
                 concreteDecoder = self.__tagMap[tagSet]
                 state = stDecodeValue
             else:
                 state = stTryAsExplicitTag
             if debug.logger and debug.logger & debug.flagDecoder:
                 if isinstance(asn1Spec, base.Asn1Item):
                     debug.logger('choosing value codec by ASN.1 spec:\n  %r -> %r' % (asn1Spec.getTagSet(), asn1Spec.__class__.__name__))
                 else:
                     debug.logger('choosing value codec by ASN.1 spec that offers either of the following: ')
                     for t, v in asn1Spec.getPosMap().items():
                         debug.logger('  %r -> %s' % (t, v.__class__.__name__))
                     debug.logger('but neither of: ')
                     for i in asn1Spec.getNegMap().items():
                         debug.logger('  %r -> %s' % (t, v.__class__.__name__))
                 debug.logger('codec %s chosen by ASN.1 spec, decoding %s' % (state == stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'explicit tag'))
         if state == stTryAsExplicitTag:
             if tagSet and \
                    tagSet[0][1] == tag.tagFormatConstructed and \
                    tagSet[0][0] != tag.tagClassUniversal:
                 # Assume explicit tagging
                 concreteDecoder = explicitTagDecoder
                 state = stDecodeValue
             else:                    
                 state = self.defaultErrorState
             debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as failure'))
         if state == stDumpRawValue:
             concreteDecoder = self.defaultRawDecoder
             debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__)
             state = stDecodeValue
         if state == stDecodeValue:
             if recursiveFlag:
                 decodeFun = self
             else:
                 decodeFun = None
             if length == -1:  # indef length
                 value, substrate = concreteDecoder.indefLenValueDecoder(
                     fullSubstrate, substrate, asn1Spec, tagSet, length,
                     stGetValueDecoder, decodeFun
                     )
             else:
                 value, _substrate = concreteDecoder.valueDecoder(
                     fullSubstrate, substrate, asn1Spec, tagSet, length,
                     stGetValueDecoder, decodeFun
                     )
                 if recursiveFlag:
                     substrate = substrate[length:]
                 else:
                     substrate = _substrate
             state = stStop
             debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '<none>'))
         if state == stErrorCondition:
             raise error.PyAsn1Error(
                 '%r not in asn1Spec: %r' % (tagSet, asn1Spec)
                 )
     debug.logger and debug.logger & debug.flagDecoder and debug.logger('decoder call completed')
     return value, substrate