def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): asn1Object = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(asn1Object, substrate, length) namedTypes = asn1Object.componentType if not namedTypes or namedTypes.hasOptionalOrDefault: seenIndices = set() idx = 0 while substrate: asn1Spec = self._getComponentTagMap(asn1Object, idx) component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True) if component is eoo.endOfOctets: break idx = self._getComponentPositionByType( asn1Object, component.effectiveTagSet, idx) asn1Object.setComponentByPosition(idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False) seenIndices.add(idx) idx += 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') if namedTypes and not namedTypes.requiredComponents.issubset( seenIndices): raise error.PyAsn1Error( 'ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) else: for idx, asn1Spec in enumerate(namedTypes.values()): component, substrate = decodeFun(substrate, asn1Spec) asn1Object.setComponentByPosition(idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False) component, substrate = decodeFun(substrate, eoo.endOfOctets, allowEoo=True) if component is not eoo.endOfOctets: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') if not namedTypes: asn1Object.verifySizeSpec() return asn1Object, substrate
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): asn1Object = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(asn1Object, substrate, length) namedTypes = asn1Object.getComponentType() if not namedTypes or namedTypes.hasOptionalOrDefault: idx = 0 while substrate: asn1Spec = self._getComponentTagMap(asn1Object, idx) component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True) if eoo.endOfOctets.isSameTypeWith( component) and component == eoo.endOfOctets: break idx = self._getComponentPositionByType( asn1Object, component.getEffectiveTagSet(), idx) asn1Object.setComponentByPosition(idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False) idx += 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') asn1Object.setDefaultComponents() else: for idx, asn1Spec in enumerate(namedTypes.values()): component, substrate = decodeFun(substrate, asn1Spec) asn1Object.setComponentByPosition(idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False) component, substrate = decodeFun(substrate, eoo.endOfOctets, allowEoo=True) if not eoo.endOfOctets.isSameTypeWith( component) or component != eoo.endOfOctets: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') if not namedTypes: asn1Object.verifySizeSpec() return asn1Object, substrate
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): head, tail = substrate[:length], substrate[length:] if not head: return self._createComponent(asn1Spec, tagSet, 0.0), tail fo = oct2int(head[0]); head = head[1:] if 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 & 0x40: # infinite value value = fo & 0x01 and '-inf' or 'inf' 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' ) else: raise error.SubstrateUnderrunError( 'Unknown encoding (tag %s)' % fo ) return self._createComponent(asn1Spec, tagSet, value), tail
def readFromStream(substrate, size=-1, context=None): """Read from the stream. Parameters ---------- substrate: :py:class:`IOBase` Stream to read from. Keyword parameters ------------------ size: :py:class:`int` How many bytes to read (-1 = all available) context: :py:class:`dict` Opaque caller context will be attached to exception objects created by this function. Yields ------ : :py:class:`bytes` or :py:class:`str` or :py:class:`SubstrateUnderrunError` Read data or :py:class:`~pyasn1.error.SubstrateUnderrunError` object if no `size` bytes is readily available in the stream. The data type depends on Python major version Raises ------ : :py:class:`~pyasn1.error.EndOfStreamError` Input stream is exhausted """ while True: # this will block unless stream is non-blocking received = substrate.read(size) if received is None: # non-blocking stream can do this yield error.SubstrateUnderrunError(context=context) elif not received and size != 0: # end-of-stream raise error.EndOfStreamError(context=context) elif len(received) < size: substrate.seek(-len(received), os.SEEK_CUR) # behave like a non-blocking stream yield error.SubstrateUnderrunError(context=context) else: break yield received
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, substrate, asn1Spec, tagSet, length, state, decodeFun): r = self._createComponent(tagSet, asn1Spec) # XXX use default tagset if not substrate: raise error.PyAsn1Error('Empty substrate') oid = [] index = 0 # Get the first subid subId = ord(substrate[index]) oid.append(int(subId / 40)) oid.append(int(subId % 40)) index = index + 1 substrateLen = len(substrate) while index < substrateLen: subId = ord(substrate[index]) if subId < 128: oid.append(subId) index = index + 1 else: # Construct subid from a number of octets nextSubId = subId subId = 0 while nextSubId >= 128 and index < substrateLen: subId = (subId << 7) + (nextSubId & 0x7F) index = index + 1 nextSubId = ord(substrate[index]) if index == substrateLen: raise error.SubstrateUnderrunError( 'Short substrate for OID %s' % oid) subId = (subId << 7) + nextSubId oid.append(subId) index = index + 1 return r.clone(tuple(oid)), substrate[index:]
def indefLenValueDecoder(self, substrate, asn1Spec, tagSet, length, state, decodeFun): r = self._createComponent(tagSet, asn1Spec) idx = 0 while substrate: try: asn1Spec = self._getAsn1SpecByPosition(r, idx) except error.PyAsn1Error: asn1Spec = None # XXX if not decodeFun: return r, substrate component, substrate = decodeFun(substrate, asn1Spec) if component == eoo.endOfOctets: break idx = self._getPositionByType(r, component, idx) r.setComponentByPosition(idx, component) idx = idx + 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) if hasattr(r, 'setDefaultComponents'): r.setDefaultComponents() r.verifySizeSpec() return r, substrate
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): if asn1Spec is not None and tagSet == asn1Spec.tagSet: # tagged Any type -- consume header substrate header = null else: # untagged Any, recover header substrate header = fullSubstrate[:-len(substrate)] # Any components do not inherit initial tag asn1Spec = self.protoComponent if substrateFun and substrateFun is not self.substrateCollector: asn1Object = self._createComponent(asn1Spec, tagSet) return substrateFun(asn1Object, header + substrate, length + len(header)) # All inner fragments are of the same type, treat them as octet string substrateFun = self.substrateCollector while substrate: component, substrate = decodeFun(substrate, asn1Spec, substrateFun=substrateFun, allowEoo=True) if component is eoo.endOfOctets: break header += component else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') if substrateFun: return header, substrate else: return self._createComponent(asn1Spec, tagSet, header), substrate
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): r = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(r, substrate, length) idx = 0 while substrate: asn1Spec = self._getComponentTagMap(r, idx) component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True) if eoo.endOfOctets.isSameTypeWith(component) and \ component == eoo.endOfOctets: break idx = self._getComponentPositionByType( r, component.getEffectiveTagSet(), idx) r.setComponentByPosition(idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False) idx += 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') r.setDefaultComponents() r.verifySizeSpec() return r, substrate
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): if tagSet[0].tagFormat != tag.tagFormatSimple: raise error.PyAsn1Error('Simple tag format expected') head, tail = substrate[:length], substrate[length:] if not head: raise error.PyAsn1Error('Empty substrate') head = octs2ints(head) oid = () index = 0 substrateLen = len(head) while index < substrateLen: subId = head[index] index += 1 if subId < 128: oid += (subId,) elif subId > 128: # Construct subid from a number of octets nextSubId = subId subId = 0 while nextSubId >= 128: subId = (subId << 7) + (nextSubId & 0x7F) if index >= substrateLen: raise error.SubstrateUnderrunError( 'Short substrate for sub-OID past %s' % (oid,) ) nextSubId = head[index] index += 1 oid += ((subId << 7) + nextSubId,) elif subId == 128: # ASN.1 spec forbids leading zeros (0x80) in OID # encoding, tolerating it opens a vulnerability. See # http://www.cosic.esat.kuleuven.be/publications/article-1432.pdf # page 7 raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding') # Decode two leading arcs if 0 <= oid[0] <= 39: oid = (0,) + oid elif 40 <= oid[0] <= 79: oid = (1, oid[0] - 40) + oid[1:] elif oid[0] >= 80: oid = (2, oid[0] - 80) + oid[1:] else: raise error.PyAsn1Error('Malformed first OID octet: %s' % head[0]) return self._createComponent(asn1Spec, tagSet, oid), tail
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun): r = self._createComponent(asn1Spec, tagSet, '') if not decodeFun: return r, substrate while substrate: component, substrate = decodeFun(substrate) if component == eoo.endOfOctets: break r = r + component else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') return r, substrate
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): bitString = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(bitString, substrate, length) while substrate: component, substrate = decodeFun(substrate, self.protoComponent, allowEoo=True) if component is eoo.endOfOctets: break bitString += component else: raise error.SubstrateUnderrunError('No EOO seen before substrate ends') return bitString, substrate
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun): r = self._createComponent(asn1Spec, tagSet) asn1Spec = r.getComponentType() idx = 0 if not decodeFun: return r, substrate while substrate: component, substrate = decodeFun(substrate, asn1Spec) if component == eoo.endOfOctets: break r.setComponentByPosition(idx, component, asn1Spec is None) idx = idx + 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') r.verifySizeSpec() return r, substrate
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): r = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(r, substrate, length) asn1Spec = r.getComponentType() idx = 0 while substrate: component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True) if eoo.endOfOctets.isSameTypeWith(component) and \ component == eoo.endOfOctets: break r.setComponentByPosition(idx, component, asn1Spec is None) idx += 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) r.verifySizeSpec() return r, substrate
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun): r = self._createComponent(asn1Spec, tagSet) idx = 0 while substrate: asn1Spec = self._getComponentTagMap(r, idx) if not decodeFun: return r, substrate component, substrate = decodeFun(substrate, asn1Spec) if component == eoo.endOfOctets: break idx = self._getComponentPositionByType( r, component.getEffectiveTagSet(), idx) r.setComponentByPosition(idx, component, asn1Spec is None) idx = idx + 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') r.setDefaultComponents() r.verifySizeSpec() return r, substrate
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): if substrateFun and substrateFun is not self.substrateCollector: asn1Object = self._createComponent(asn1Spec, tagSet) return substrateFun(asn1Object, substrate, length) # All inner fragments are of the same type, treat them as octet string substrateFun = self.substrateCollector header = null while substrate: component, substrate = decodeFun(substrate, self.protoComponent, substrateFun=substrateFun, allowEoo=True) if component is eoo.endOfOctets: break header += component else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') return self._createComponent(asn1Spec, tagSet, header), substrate
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
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
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): if tagSet[0].tagFormat != tag.tagFormatConstructed: raise error.PyAsn1Error('Constructed tag format expected') if substrateFun is not None: if asn1Spec is not None: asn1Object = asn1Spec.clone() elif self.protoComponent is not None: asn1Object = self.protoComponent.clone(tagSet=tagSet) else: asn1Object = self.protoRecordComponent, self.protoSequenceComponent return substrateFun(asn1Object, substrate, length) if asn1Spec is None: return self._decodeComponents(substrate, decodeFun, tagSet, allowEoo=True) asn1Object = asn1Spec.clone() if asn1Object.typeId in (univ.Sequence.typeId, univ.Set.typeId): namedTypes = asn1Object.componentType isSetType = asn1Object.typeId == univ.Set.typeId isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault seenIndices = set() idx = 0 while substrate: if len(namedTypes) <= idx: asn1Spec = None elif isSetType: asn1Spec = namedTypes.tagMapUnique else: try: if isDeterministic: asn1Spec = namedTypes[idx].asn1Object elif namedTypes[idx].isOptional or namedTypes[ idx].isDefaulted: asn1Spec = namedTypes.getTagMapNearPosition(idx) else: asn1Spec = namedTypes[idx].asn1Object except IndexError: raise error.PyAsn1Error( 'Excessive components decoded at %r' % (asn1Object, )) component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True) if component is eoo.endOfOctets: break if not isDeterministic and namedTypes: if isSetType: idx = namedTypes.getPositionByType( component.effectiveTagSet) elif namedTypes[idx].isOptional or namedTypes[ idx].isDefaulted: idx = namedTypes.getPositionNearType( component.effectiveTagSet, idx) asn1Object.setComponentByPosition(idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False) seenIndices.add(idx) idx += 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') if namedTypes: if not namedTypes.requiredComponents.issubset(seenIndices): raise error.PyAsn1Error( 'ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) else: asn1Object.verifySizeSpec() else: asn1Spec = asn1Object.componentType idx = 0 while substrate: component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True) if component is eoo.endOfOctets: break asn1Object.setComponentByPosition(idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False) idx += 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends') asn1Object.verifySizeSpec() return asn1Object, substrate
def __call__(self, substrate, asn1Spec=None, tagSet=None, length=None, state=stDecodeTag, recursiveFlag=1): # Decode tag & length while state != stStop: if state == stDecodeTag: # Decode tag if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on tag decoding') t = ord(substrate[0]) tagClass = t & 0xC0 tagFormat = t & 0x20 tagId = t & 0x1F substrate = substrate[1:] if tagId == 0x1F: tagId = 0 # 0L while 1: if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on long tag decoding') t = ord(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 tagSet is None: tagSet = tag.TagSet((), lastTag) # base tag not recovered else: tagSet = lastTag + tagSet state = stDecodeLength if state == stDecodeLength: # Decode length if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on length decoding') firstOctet = ord(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) | ord(char) size = size + 1 state = stGetValueDecoder substrate = substrate[size:] if length != -1 and len(substrate) < length: raise error.SubstrateUnderrunError( '%d-octet short' % (length - len(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: concreteDecoder = self.__codecMap.get(tagSet) if concreteDecoder: state = stDecodeValue else: concreteDecoder = self.__codecMap.get(tagSet[:1]) if concreteDecoder: state = stDecodeValue else: state = stTryAsExplicitTag if state == stGetValueDecoderByAsn1Spec: if tagSet == eoo.endOfOctets.getTagSet(): concreteDecoder = self.__codecMap[tagSet] state = stDecodeValue continue if type(asn1Spec) == types.DictType: __chosenSpec = asn1Spec.get(tagSet) elif asn1Spec is not None: __chosenSpec = asn1Spec else: __chosenSpec = None if __chosenSpec is None or not\ __chosenSpec.getTypeMap().has_key(tagSet): state = stTryAsExplicitTag else: # use base type for codec lookup to recover untagged types baseTag = __chosenSpec.getTagSet().getBaseTag() if baseTag: # XXX ugly baseTagSet = tag.TagSet(baseTag, baseTag) else: baseTagSet = tag.TagSet() concreteDecoder = self.__codecMap.get( # tagged subtype baseTagSet) if concreteDecoder: asn1Spec = __chosenSpec state = stDecodeValue else: state = stTryAsExplicitTag if state == stTryAsExplicitTag: if tagSet and \ tagSet[0][1] == tag.tagFormatConstructed and \ tagSet[0][0] != tag.tagClassUniversal: # Assume explicit tagging state = stDecodeTag else: raise error.PyAsn1Error('%s not in asn1Spec: %s' % (tagSet, asn1Spec)) if state == stDecodeValue: if recursiveFlag: decodeFun = self else: decodeFun = None if length == -1: # indef length value, substrate = concreteDecoder.indefLenValueDecoder( substrate, asn1Spec, tagSet, length, stGetValueDecoder, decodeFun) else: value, _substrate = concreteDecoder.valueDecoder( substrate[:length], asn1Spec, tagSet, length, stGetValueDecoder, decodeFun) if recursiveFlag: substrate = substrate[length:] else: substrate = _substrate state = stStop return value, substrate
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, state, decodeFun, substrateFun): if tagSet[0].tagFormat != tag.tagFormatConstructed: raise error.PyAsn1Error('Constructed tag format expected') if substrateFun is not None: if asn1Spec is not None: asn1Object = asn1Spec.clone() elif self.protoComponent is not None: asn1Object = self.protoComponent.clone(tagSet=tagSet) else: asn1Object = self.protoRecordComponent, self.protoSequenceComponent return substrateFun(asn1Object, substrate, length) if asn1Spec is None: return self._decodeComponents(substrate, decodeFun, allowEoo=True) asn1Object = asn1Spec.clone() if asn1Object.typeId in (univ.Sequence.typeId, univ.Set.typeId): namedTypes = asn1Object.componentType if not namedTypes or namedTypes.hasOptionalOrDefault: seenIndices = set() idx = 0 while substrate: asn1Spec = self._getComponentTagMap(asn1Object, idx) component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True) if component is eoo.endOfOctets: break idx = self._getComponentPositionByType( asn1Object, component.effectiveTagSet, idx ) asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) seenIndices.add(idx) idx += 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) if namedTypes and not namedTypes.requiredComponents.issubset(seenIndices): raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) else: for idx, asn1Spec in enumerate(namedTypes.values()): component, substrate = decodeFun(substrate, asn1Spec) asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) component, substrate = decodeFun(substrate, eoo.endOfOctets, allowEoo=True) if component is not eoo.endOfOctets: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) if not namedTypes: asn1Object.verifySizeSpec() else: asn1Spec = asn1Object.componentType idx = 0 while substrate: component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True) if component is eoo.endOfOctets: break asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) idx += 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) asn1Object.verifySizeSpec() return asn1Object, substrate