def prettyIn(self, value): """Dotted -> tuple of numerics OID converter""" if isinstance(value, tuple): pass elif isinstance(value, ObjectIdentifier): return tuple(value) elif isinstance(value, str): r = [] for element in [x for x in value.split('.') if x != '']: try: r.append(int(element, 0)) except ValueError: raise error.PyAsn1Error( 'Malformed Object ID %s at %s: %s' % (str(value), self.__class__.__name__, sys.exc_info()[1])) value = tuple(r) else: try: value = tuple(value) except TypeError: raise error.PyAsn1Error( 'Malformed Object ID %s at %s: %s' % (str(value), self.__class__.__name__, sys.exc_info()[1])) for x in value: if not isinstance(x, intTypes) or x < 0: raise error.PyAsn1Error('Invalid sub-ID in %s at %s' % (value, self.__class__.__name__)) return value
def encodeValue(self, encodeFun, value, defMode, maxChunkSize): oid = value.asTuple() if oid[:5] in self.precomputedValues: octets = self.precomputedValues[oid[:5]] index = 5 else: if len(oid) < 2: raise error.PyAsn1Error('Short OID %s' % (value, )) # Build the first twos if oid[0] > 6 or oid[1] > 39 or oid[0] == 6 and oid[1] > 15: raise error.PyAsn1Error( 'Initial sub-ID overflow %s in OID %s' % (oid[:2], value)) octets = (oid[0] * 40 + oid[1], ) index = 2 # Cycle through subids for subid in oid[index:]: if subid > -1 and subid < 128: # Optimize for the common case octets = octets + (subid & 0x7f, ) elif subid < 0 or subid > 0xFFFFFFFF: raise error.PyAsn1Error('SubId overflow %s in %s' % (subid, value)) else: # Pack large Sub-Object IDs res = (subid & 0x7f, ) subid = subid >> 7 while subid > 0: res = (0x80 | (subid & 0x7f), ) + res subid = subid >> 7 # Add packed Sub-Object ID to resulted Object ID octets += res return ints2octs(octets), 0
def prettyIn(self, value): if isinstance(value, tuple) and len(value) == 3: for d in value: if not isinstance(d, intTypes): raise error.PyAsn1Error('Lame Real value syntax: %s' % (value, )) if value[1] not in (2, 10): raise error.PyAsn1Error('Prohibited base for Real value: %s' % (value[1], )) if value[1] == 10: value = self.__normalizeBase10(value) return value elif isinstance(value, intTypes): return self.__normalizeBase10((value, 10, 0)) elif isinstance(value, float): if self._inf and value in self._inf: return value else: e = 0 while int(value) != value: value = value * 10 e = e - 1 return self.__normalizeBase10((int(value), 10, e)) elif isinstance(value, Real): return tuple(value) elif isinstance(value, str): # handle infinite literal try: return float(value) except ValueError: pass raise error.PyAsn1Error('Bad real value syntax: %s' % (value, ))
def setComponentByPosition(self, idx, value=None, verifyConstraints=True): l = len(self._componentValues) if idx >= l: self._componentValues = self._componentValues + (idx - l + 1) * [None] if value is None: if self._componentValues[idx] is None: if self._componentType is None: raise error.PyAsn1Error('Component type not defined') self._componentValues[idx] = self._componentType.clone() self._componentValuesSet = self._componentValuesSet + 1 return self elif not isinstance(value, base.Asn1Item): if self._componentType is None: raise error.PyAsn1Error('Component type not defined') if isinstance(self._componentType, base.AbstractSimpleAsn1Item): value = self._componentType.clone(value=value) else: raise error.PyAsn1Error('Instance value required') if verifyConstraints: if self._componentType is not None: self._verifyComponent(idx, value) self._verifySubtypeSpec(value, idx) if self._componentValues[idx] is None: self._componentValuesSet = self._componentValuesSet + 1 self._componentValues[idx] = value return self
def _verifyComponent(self, idx, value): if idx >= self._componentTypeLen: raise error.PyAsn1Error('Component type error out of range') t = self._componentType[idx].getType() if not t.isSuperTypeOf(value): raise error.PyAsn1Error('Component type error %r vs %r' % (t, value))
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: raise error.PyAsn1Error('Empty substrate') # Get the first subid subId = oct2int(head[0]) oid = divmod(subId, 40) index = 1 substrateLen = len(head) while index < substrateLen: subId = oct2int(head[index]) index = index + 1 if subId == 128: # ASN.1 spec forbids leading zeros (0x80) in sub-ID OID # encoding, tolerating it opens a vulnerability. # See http://www.cosic.esat.kuleuven.be/publications/article-1432.pdf page 7 raise error.PyAsn1Error('Invalid leading 0x80 in sub-OID') elif subId > 128: # Construct subid from a number of octets nextSubId = subId subId = 0 while nextSubId >= 128: subId = (subId << 7) + (nextSubId & 0x7F) if index >= substrateLen: raise error.SubstrateUnderrunError( 'Short substrate for sub-OID past %s' % (oid,) ) nextSubId = oct2int(head[index]) index = index + 1 subId = (subId << 7) + nextSubId oid = oid + (subId,) return self._createComponent(asn1Spec, tagSet, oid), tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if tagSet[0][1] == tag.tagFormatSimple: # XXX what tag to check? if not head: raise error.PyAsn1Error('Empty substrate') trailingBits = oct2int(head[0]) if trailingBits > 7: raise error.PyAsn1Error( 'Trailing bits overflow %s' % trailingBits ) head = head[1:] lsb = p = 0; l = len(head)-1; b = () while p <= l: if p == l: lsb = trailingBits j = 7 o = oct2int(head[p]) while j >= lsb: b = b + ((o>>j)&0x01,) j = j - 1 p = p + 1 return self._createComponent(asn1Spec, tagSet, b), tail r = self._createComponent(asn1Spec, tagSet, ()) if substrateFun: return substrateFun(r, substrate, length) while head: component, head = decodeFun(head) r = r + component return r, tail
def prettyIn(self, value): r = [] if not value: return () elif isinstance(value, str): if value[0] == '\'': if value[-2:] == '\'B': for v in value[1:-2]: if v == '0': r.append(0) elif v == '1': r.append(1) else: raise error.PyAsn1Error( 'Non-binary BIT STRING initializer %s' % (v, )) return tuple(r) elif value[-2:] == '\'H': for v in value[1:-2]: i = 4 v = int(v, 16) while i: i = i - 1 r.append((v >> i) & 0x01) return tuple(r) else: raise error.PyAsn1Error( 'Bad BIT STRING value notation %s' % (value, )) else: for i in value.split(','): j = self.__namedValues.getValue(i) if j is None: raise error.PyAsn1Error( 'Unknown bit identifier \'%s\'' % (i, )) if j >= len(r): r.extend([0] * (j - len(r) + 1)) r[j] = 1 return tuple(r) elif isinstance(value, (tuple, list)): r = tuple(value) for b in r: if b and b != 1: raise error.PyAsn1Error( 'Non-binary BitString initializer \'%s\'' % (r, )) return r elif isinstance(value, BitString): return tuple(value) else: raise error.PyAsn1Error('Bad BitString initializer type \'%s\'' % (value, ))
def prettyIn(self, value): if not isinstance(value, str): try: return int(value) except: raise error.PyAsn1Error('Can\'t coerce %s into integer: %s' % (value, sys.exc_info()[1])) r = self.__namedValues.getValue(value) if r is not None: return r try: return int(value) except: raise error.PyAsn1Error('Can\'t coerce %s into integer: %s' % (value, sys.exc_info()[1]))
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: raise error.PyAsn1Error('Empty substrate') byte = oct2int(head[0]) # CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while # BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1 # in http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf if byte == 0xff: value = 1 elif byte == 0x00: value = 0 else: raise error.PyAsn1Error('Boolean CER violation: %s' % byte) return self._createComponent(asn1Spec, tagSet, value), tail
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] r = self._createComponent(asn1Spec, tagSet) if head: raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length) return r, tail
def encodeValue(self, encodeFun, value, defMode, maxChunkSize): if value.isPlusInfinity(): return int2oct(0x40), 0 if value.isMinusInfinity(): return int2oct(0x41), 0 m, b, e = value if not m: return null, 0 if b == 10: return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), 0 elif b == 2: fo = 0x80 # binary enoding if m < 0: fo = fo | 0x40 # sign bit m = -m while int(m) != m: # drop floating point m *= 2 e -= 1 while m & 0x1 == 0: # mantissa normalization m >>= 1 e += 1 eo = null while e not in (0, -1): eo = int2oct(e & 0xff) + eo e >>= 8 if e == 0 and eo and oct2int(eo[0]) & 0x80: eo = int2oct(0) + eo n = len(eo) if n > 0xff: raise error.PyAsn1Error('Real exponent overflow') if n == 1: pass elif n == 2: fo |= 1 elif n == 3: fo |= 2 else: fo |= 3 eo = int2oct(n // 0xff + 1) + eo po = null while m: po = int2oct(m & 0xff) + po m >>= 8 substrate = int2oct(fo) + eo + po return substrate, 0 else: raise error.PyAsn1Error('Prohibited Real base %s' % b)
def __init__(self, *flags): self._flags = flagNone self._printer = self.defaultPrinter for f in flags: if f not in flagMap: raise error.PyAsn1Error('bad debug flag %s' % (f, )) self._flags = self._flags | flagMap[f] self('debug category %s enabled' % f)
def __init__(self, tagClass, tagFormat, tagId): if tagId < 0: raise error.PyAsn1Error( 'Negative tag ID (%s) not allowed' % (tagId,) ) self.__tag = (tagClass, tagFormat, tagId) self.uniq = (tagClass, tagId) self.__hashedUniqTag = hash(self.uniq)
def getName(self, innerFlag=0): if self._currentIdx is None: raise error.PyAsn1Error('Component not chosen') else: if innerFlag: c = self._componentValues[self._currentIdx] if isinstance(c, Choice): return c.getName(innerFlag) return self._componentType.getNameByPosition(self._currentIdx)
def getComponent(self, innerFlag=0): if self._currentIdx is None: raise error.PyAsn1Error('Component not chosen') else: c = self._componentValues[self._currentIdx] if innerFlag and isinstance(c, Choice): return c.getComponent(innerFlag) else: return c
def __getitem__(self, tagSet): if tagSet in self.__posMap: return self.__posMap[tagSet] elif tagSet in self.__negMap: raise error.PyAsn1Error('Key in negative map') elif self.__defType is not None: return self.__defType else: raise KeyError()
def tagExplicitly(self, superTag): tagClass, tagFormat, tagId = superTag if tagClass == tagClassUniversal: raise error.PyAsn1Error( 'Can\'t tag with UNIVERSAL-class tag' ) if tagFormat != tagFormatConstructed: superTag = Tag(tagClass, tagFormatConstructed, tagId) return self + superTag
def prettyIn(self, value): if isinstance(value, bytes): return value elif isinstance(value, OctetString): return value.asOctets() elif isinstance(value, (tuple, list, map)): try: return bytes(value) except ValueError: raise error.PyAsn1Error( 'Bad OctetString initializer \'%s\'' % (value, )) else: try: return str(value).encode(self._encoding) except UnicodeEncodeError: raise error.PyAsn1Error( 'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding))
def __init__(self, *namedValues): self.nameToValIdx = {} self.valToNameIdx = {} self.namedValues = () automaticVal = 1 for namedValue in namedValues: if isinstance(namedValue, tuple): name, val = namedValue else: name = namedValue val = automaticVal if name in self.nameToValIdx: raise error.PyAsn1Error('Duplicate name %s' % (name, )) self.nameToValIdx[name] = val if val in self.valToNameIdx: raise error.PyAsn1Error('Duplicate value %s=%s' % (name, val)) self.valToNameIdx[val] = name self.namedValues = self.namedValues + ((name, val), ) automaticVal = automaticVal + 1
def clone(self, parentType, tagMap, uniq=False): if self.__defType is not None and tagMap.getDef() is not None: raise error.PyAsn1Error('Duplicate default value at %s' % (self,)) if tagMap.getDef() is not None: defType = tagMap.getDef() else: defType = self.__defType posMap = self.__posMap.copy() for k in tagMap.getPosMap(): if uniq and k in posMap: raise error.PyAsn1Error('Duplicate positive key %s' % (k,)) posMap[k] = parentType negMap = self.__negMap.copy() negMap.update(tagMap.getNegMap()) return self.__class__( posMap, negMap, defType, )
def prettyIn(self, value): if isinstance(value, str): return value elif isinstance(value, (tuple, list)): try: return ''.join([chr(x) for x in value]) except ValueError: raise error.PyAsn1Error( 'Bad OctetString initializer \'%s\'' % (value, )) else: return str(value)
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): if substrateFun: return substrateFun( self._createComponent(asn1Spec, tagSet, ''), substrate, length ) value, substrate = decodeFun(substrate, asn1Spec, tagSet, length) terminator, substrate = decodeFun(substrate) if terminator == eoo.endOfOctets: return value, substrate else: raise error.PyAsn1Error('Missing end-of-octets terminator')
def setDefaultComponents(self): if self._componentTypeLen == self._componentValuesSet: return idx = self._componentTypeLen while idx: idx = idx - 1 if self._componentType[idx].isDefaulted: if self.getComponentByPosition(idx) is None: self.setComponentByPosition(idx) elif not self._componentType[idx].isOptional: if self.getComponentByPosition(idx) is None: raise error.PyAsn1Error( 'Uninitialized component #%s at %r' % (idx, self))
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: raise error.SubstrateUnderrunError('Short substrate for Real') fo = oct2int(head[0]); head = head[1:] if fo & 0x40: # infinite value value = fo & 0x01 and '-inf' or 'inf' elif fo & 0x80: # binary enoding n = (fo & 0x03) + 1 if n == 4: n = oct2int(head[0]) eo, head = head[:n], head[n:] if not eo or not head: raise error.PyAsn1Error('Real exponent screwed') e = oct2int(eo[0]) & 0x80 and -1 or 0 while eo: # exponent e <<= 8 e |= oct2int(eo[0]) eo = eo[1:] p = 0 while head: # value p <<= 8 p |= oct2int(head[0]) head = head[1:] if fo & 0x40: # sign bit p = -p value = (p, 2, e) elif fo & 0xc0 == 0: # character encoding try: if fo & 0x3 == 0x1: # NR1 value = (int(head), 10, 0) elif fo & 0x3 == 0x2: # NR2 value = float(head) elif fo & 0x3 == 0x3: # NR3 value = float(head) else: raise error.SubstrateUnderrunError( 'Unknown NR (tag %s)' % fo ) except ValueError: raise error.SubstrateUnderrunError( 'Bad character Real syntax' ) elif fo & 0xc0 == 0x40: # special real value pass else: raise error.SubstrateUnderrunError( 'Unknown encoding (tag %s)' % fo ) return self._createComponent(asn1Spec, tagSet, value), tail
def ToPythonEpochTime(self): """Takes a ASN.1 Time choice, and returns seconds since epoch in UTC.""" utc_time = self.getComponentByName('utcTime') general_time = self.getComponentByName('generalTime') if utc_time and general_time: raise error.PyAsn1Error('Both elements of a choice are present.') if general_time: format_str = '%Y%m%d%H%M%SZ' time_str = str(general_time) else: format_str = '%y%m%d%H%M%SZ' time_str = str(utc_time) time_tpl = time.strptime(time_str, format_str) return calendar.timegm(time_tpl)
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: raise error.PyAsn1Error('Empty substrate') if head in self.precomputedValues: value = self.precomputedValues[head] else: firstOctet = oct2int(head[0]) if firstOctet & 0x80: value = -1 else: value = 0 for octet in head: value = value << 8 | oct2int(octet) return self._createComponent(asn1Spec, tagSet, value), tail
def fromBinaryString(self, value): bitNo = 8 byte = 0 r = () for v in value: if bitNo: bitNo = bitNo - 1 else: bitNo = 7 r = r + (byte, ) byte = 0 if v == '0': v = 0 elif v == '1': v = 1 else: raise error.PyAsn1Error( 'Non-binary OCTET STRING initializer %s' % (v, )) byte = byte | (v << bitNo) return octets.ints2octs(r + (byte, ))
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): raise error.PyAsn1Error('Decoder not implemented for %s' % (tagSet,))
def __call__(self, substrate, asn1Spec=None, tagSet=None, length=None, state=stDecodeTag, recursiveFlag=1, substrateFun=None): 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))) fullSubstrate = substrate while state != stStop: if state == stDecodeTag: # Decode tag 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') 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[: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(' %r -> %s' % (t, v.__class__.__name__)) if asn1Spec.getNegMap(): debug.logger('but neither of: ') for i in asn1Spec.getNegMap().items(): debug.logger(' %r -> %s' % (t, v.__class__.__name__)) debug.logger('new candidate ASN.1 spec is %s, chosen by %r' % (__chosenSpec is None and '<none>' or __chosenSpec.__class__.__name__, 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 %r' % (baseTagSet,)) else: concreteDecoder = None if concreteDecoder: asn1Spec = __chosenSpec state = stDecodeValue else: state = stTryAsExplicitTag elif tagSet == self.__endOfOctetsTagSet: concreteDecoder = self.__tagMap[tagSet] state = stDecodeValue debug.logger and debug.logger & debug.flagDecoder and debug.logger('end-of-octets found') 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( '%r not in asn1Spec: %r' % (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