You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

842 lines
37 KiB

13 years ago
# BER decoder
10 years ago
from pyasn1.type import tag, univ, char, useful, tagmap
13 years ago
from pyasn1.codec.ber import eoo
10 years ago
from pyasn1.compat.octets import oct2int, isOctetsType
12 years ago
from pyasn1 import debug, error
13 years ago
class AbstractDecoder:
protoComponent = None
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
raise error.PyAsn1Error('Decoder not implemented for %s' % (tagSet,))
13 years ago
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
10 years ago
length, state, decodeFun, substrateFun):
12 years ago
raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,))
13 years ago
class AbstractSimpleDecoder(AbstractDecoder):
12 years ago
tagFormats = (tag.tagFormatSimple,)
13 years ago
def _createComponent(self, asn1Spec, tagSet, value=None):
12 years ago
if tagSet[0][1] not in self.tagFormats:
10 years ago
raise error.PyAsn1Error('Invalid tag format %s for %s' % (tagSet[0], self.protoComponent.prettyPrintType()))
13 years ago
if asn1Spec is None:
return self.protoComponent.clone(value, tagSet)
elif value is None:
return asn1Spec
else:
return asn1Spec.clone(value)
class AbstractConstructedDecoder(AbstractDecoder):
12 years ago
tagFormats = (tag.tagFormatConstructed,)
13 years ago
def _createComponent(self, asn1Spec, tagSet, value=None):
12 years ago
if tagSet[0][1] not in self.tagFormats:
10 years ago
raise error.PyAsn1Error('Invalid tag format %s for %s' % (tagSet[0], self.protoComponent.prettyPrintType()))
13 years ago
if asn1Spec is None:
return self.protoComponent.clone(tagSet)
else:
return asn1Spec.clone()
class ExplicitTagDecoder(AbstractSimpleDecoder):
12 years ago
protoComponent = univ.Any('')
tagFormats = (tag.tagFormatConstructed,)
13 years ago
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
if substrateFun:
return substrateFun(
self._createComponent(asn1Spec, tagSet, ''),
substrate, length
)
head, tail = substrate[:length], substrate[length:]
value, _ = decodeFun(head, asn1Spec, tagSet, length)
return value, tail
13 years ago
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
if substrateFun:
return substrateFun(
self._createComponent(asn1Spec, tagSet, ''),
substrate, length
)
13 years ago
value, substrate = decodeFun(substrate, asn1Spec, tagSet, length)
10 years ago
terminator, substrate = decodeFun(substrate, allowEoo=True)
12 years ago
if eoo.endOfOctets.isSameTypeWith(terminator) and \
terminator == eoo.endOfOctets:
13 years ago
return value, substrate
else:
raise error.PyAsn1Error('Missing end-of-octets terminator')
explicitTagDecoder = ExplicitTagDecoder()
class IntegerDecoder(AbstractSimpleDecoder):
protoComponent = univ.Integer(0)
precomputedValues = {
'\x00': 0,
'\x01': 1,
'\x02': 2,
'\x03': 3,
'\x04': 4,
'\x05': 5,
'\x06': 6,
'\x07': 7,
'\x08': 8,
'\x09': 9,
'\xff': -1,
'\xfe': -2,
'\xfd': -3,
'\xfc': -4,
'\xfb': -5
}
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
12 years ago
state, decodeFun, substrateFun):
head, tail = substrate[:length], substrate[length:]
if not head:
return self._createComponent(asn1Spec, tagSet, 0), tail
if head in self.precomputedValues:
value = self.precomputedValues[head]
13 years ago
else:
12 years ago
firstOctet = oct2int(head[0])
13 years ago
if firstOctet & 0x80:
value = -1
else:
value = 0
12 years ago
for octet in head:
13 years ago
value = value << 8 | oct2int(octet)
12 years ago
return self._createComponent(asn1Spec, tagSet, value), tail
13 years ago
class BooleanDecoder(IntegerDecoder):
protoComponent = univ.Boolean(0)
12 years ago
def _createComponent(self, asn1Spec, tagSet, value=None):
return IntegerDecoder._createComponent(self, asn1Spec, tagSet, value and 1 or 0)
13 years ago
class BitStringDecoder(AbstractSimpleDecoder):
protoComponent = univ.BitString(())
12 years ago
tagFormats = (tag.tagFormatSimple, tag.tagFormatConstructed)
13 years ago
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
12 years ago
state, decodeFun, substrateFun):
head, tail = substrate[:length], substrate[length:]
13 years ago
if tagSet[0][1] == tag.tagFormatSimple: # XXX what tag to check?
12 years ago
if not head:
raise error.PyAsn1Error('Empty substrate')
trailingBits = oct2int(head[0])
13 years ago
if trailingBits > 7:
raise error.PyAsn1Error(
'Trailing bits overflow %s' % trailingBits
)
12 years ago
head = head[1:]
10 years ago
lsb = p = 0; l = len(head)-1; b = []
13 years ago
while p <= l:
if p == l:
lsb = trailingBits
j = 7
12 years ago
o = oct2int(head[p])
13 years ago
while j >= lsb:
10 years ago
b.append((o>>j)&0x01)
13 years ago
j = j - 1
p = p + 1
12 years ago
return self._createComponent(asn1Spec, tagSet, b), tail
13 years ago
r = self._createComponent(asn1Spec, tagSet, ())
12 years ago
if substrateFun:
return substrateFun(r, substrate, length)
while head:
10 years ago
component, head = decodeFun(head, self.protoComponent)
13 years ago
r = r + component
12 years ago
return r, tail
13 years ago
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
13 years ago
r = self._createComponent(asn1Spec, tagSet, '')
12 years ago
if substrateFun:
return substrateFun(r, substrate, length)
13 years ago
while substrate:
10 years ago
component, substrate = decodeFun(substrate, self.protoComponent,
allowEoo=True)
12 years ago
if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets:
13 years ago
break
r = r + component
else:
raise error.SubstrateUnderrunError(
'No EOO seen before substrate ends'
)
return r, substrate
class OctetStringDecoder(AbstractSimpleDecoder):
protoComponent = univ.OctetString('')
12 years ago
tagFormats = (tag.tagFormatSimple, tag.tagFormatConstructed)
13 years ago
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
12 years ago
state, decodeFun, substrateFun):
head, tail = substrate[:length], substrate[length:]
13 years ago
if tagSet[0][1] == tag.tagFormatSimple: # XXX what tag to check?
12 years ago
return self._createComponent(asn1Spec, tagSet, head), tail
13 years ago
r = self._createComponent(asn1Spec, tagSet, '')
12 years ago
if substrateFun:
return substrateFun(r, substrate, length)
while head:
10 years ago
component, head = decodeFun(head, self.protoComponent)
13 years ago
r = r + component
12 years ago
return r, tail
13 years ago
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
13 years ago
r = self._createComponent(asn1Spec, tagSet, '')
12 years ago
if substrateFun:
return substrateFun(r, substrate, length)
13 years ago
while substrate:
10 years ago
component, substrate = decodeFun(substrate, self.protoComponent,
allowEoo=True)
12 years ago
if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets:
13 years ago
break
r = r + component
else:
raise error.SubstrateUnderrunError(
'No EOO seen before substrate ends'
)
return r, substrate
class NullDecoder(AbstractSimpleDecoder):
protoComponent = univ.Null('')
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
head, tail = substrate[:length], substrate[length:]
13 years ago
r = self._createComponent(asn1Spec, tagSet)
12 years ago
if head:
raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length)
return r, tail
13 years ago
class ObjectIdentifierDecoder(AbstractSimpleDecoder):
protoComponent = univ.ObjectIdentifier(())
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
12 years ago
state, decodeFun, substrateFun):
head, tail = substrate[:length], substrate[length:]
if not head:
13 years ago
raise error.PyAsn1Error('Empty substrate')
12 years ago
10 years ago
oid = ()
index = 0
12 years ago
substrateLen = len(head)
13 years ago
while index < substrateLen:
12 years ago
subId = oct2int(head[index])
10 years ago
index += 1
if subId < 128:
oid = oid + (subId,)
12 years ago
elif subId > 128:
13 years ago
# Construct subid from a number of octets
nextSubId = subId
subId = 0
12 years ago
while nextSubId >= 128:
13 years ago
subId = (subId << 7) + (nextSubId & 0x7F)
12 years ago
if index >= substrateLen:
raise error.SubstrateUnderrunError(
'Short substrate for sub-OID past %s' % (oid,)
10 years ago
)
12 years ago
nextSubId = oct2int(head[index])
10 years ago
index += 1
oid = 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])
12 years ago
return self._createComponent(asn1Spec, tagSet, oid), tail
13 years ago
class RealDecoder(AbstractSimpleDecoder):
protoComponent = univ.Real()
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
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:]
10 years ago
if fo & 0x80: # binary encoding
if not head:
raise error.PyAsn1Error("Incomplete floating-point value")
12 years ago
n = (fo & 0x03) + 1
if n == 4:
n = oct2int(head[0])
10 years ago
head = head[1:]
12 years ago
eo, head = head[:n], head[n:]
if not eo or not head:
13 years ago
raise error.PyAsn1Error('Real exponent screwed')
12 years ago
e = oct2int(eo[0]) & 0x80 and -1 or 0
13 years ago
while eo: # exponent
e <<= 8
e |= oct2int(eo[0])
eo = eo[1:]
10 years ago
b = fo >> 4 & 0x03 # base bits
if b > 2:
raise error.PyAsn1Error('Illegal Real base')
if b == 1: # encbase = 8
e *= 3
elif b == 2: # encbase = 16
e *= 4
13 years ago
p = 0
12 years ago
while head: # value
13 years ago
p <<= 8
12 years ago
p |= oct2int(head[0])
head = head[1:]
13 years ago
if fo & 0x40: # sign bit
p = -p
10 years ago
sf = fo >> 2 & 0x03 # scale bits
p *= 2**sf
13 years ago
value = (p, 2, e)
12 years ago
elif fo & 0x40: # infinite value
value = fo & 0x01 and '-inf' or 'inf'
13 years ago
elif fo & 0xc0 == 0: # character encoding
10 years ago
if not head:
raise error.PyAsn1Error("Incomplete floating-point value")
13 years ago
try:
if fo & 0x3 == 0x1: # NR1
12 years ago
value = (int(head), 10, 0)
13 years ago
elif fo & 0x3 == 0x2: # NR2
12 years ago
value = float(head)
13 years ago
elif fo & 0x3 == 0x3: # NR3
12 years ago
value = float(head)
13 years ago
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
)
12 years ago
return self._createComponent(asn1Spec, tagSet, value), tail
13 years ago
class SequenceDecoder(AbstractConstructedDecoder):
protoComponent = univ.Sequence()
def _getComponentTagMap(self, r, idx):
try:
return r.getComponentTagMapNearPosition(idx)
except error.PyAsn1Error:
return
def _getComponentPositionByType(self, r, t, idx):
return r.getComponentPositionNearType(t, idx)
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
head, tail = substrate[:length], substrate[length:]
13 years ago
r = self._createComponent(asn1Spec, tagSet)
idx = 0
12 years ago
if substrateFun:
return substrateFun(r, substrate, length)
while head:
13 years ago
asn1Spec = self._getComponentTagMap(r, idx)
12 years ago
component, head = decodeFun(head, asn1Spec)
13 years ago
idx = self._getComponentPositionByType(
r, component.getEffectiveTagSet(), idx
)
r.setComponentByPosition(idx, component, asn1Spec is None)
idx = idx + 1
r.setDefaultComponents()
r.verifySizeSpec()
12 years ago
return r, tail
13 years ago
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
13 years ago
r = self._createComponent(asn1Spec, tagSet)
12 years ago
if substrateFun:
return substrateFun(r, substrate, length)
13 years ago
idx = 0
while substrate:
asn1Spec = self._getComponentTagMap(r, idx)
10 years ago
component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
12 years ago
if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets:
13 years ago
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
class SequenceOfDecoder(AbstractConstructedDecoder):
protoComponent = univ.SequenceOf()
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
head, tail = substrate[:length], substrate[length:]
13 years ago
r = self._createComponent(asn1Spec, tagSet)
12 years ago
if substrateFun:
return substrateFun(r, substrate, length)
13 years ago
asn1Spec = r.getComponentType()
idx = 0
12 years ago
while head:
component, head = decodeFun(head, asn1Spec)
13 years ago
r.setComponentByPosition(idx, component, asn1Spec is None)
idx = idx + 1
r.verifySizeSpec()
12 years ago
return r, tail
13 years ago
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
13 years ago
r = self._createComponent(asn1Spec, tagSet)
12 years ago
if substrateFun:
return substrateFun(r, substrate, length)
13 years ago
asn1Spec = r.getComponentType()
idx = 0
while substrate:
10 years ago
component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
12 years ago
if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets:
13 years ago
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
class SetDecoder(SequenceDecoder):
protoComponent = univ.Set()
def _getComponentTagMap(self, r, idx):
return r.getComponentTagMap()
def _getComponentPositionByType(self, r, t, idx):
nextIdx = r.getComponentPositionByType(t)
if nextIdx is None:
return idx
else:
return nextIdx
class SetOfDecoder(SequenceOfDecoder):
protoComponent = univ.SetOf()
class ChoiceDecoder(AbstractConstructedDecoder):
protoComponent = univ.Choice()
12 years ago
tagFormats = (tag.tagFormatSimple, tag.tagFormatConstructed)
13 years ago
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
head, tail = substrate[:length], substrate[length:]
13 years ago
r = self._createComponent(asn1Spec, tagSet)
12 years ago
if substrateFun:
return substrateFun(r, substrate, length)
13 years ago
if r.getTagSet() == tagSet: # explicitly tagged Choice
12 years ago
component, head = decodeFun(
head, r.getComponentTagMap()
13 years ago
)
else:
12 years ago
component, head = decodeFun(
head, r.getComponentTagMap(), tagSet, length, state
13 years ago
)
if isinstance(component, univ.Choice):
effectiveTagSet = component.getEffectiveTagSet()
else:
effectiveTagSet = component.getTagSet()
r.setComponentByType(effectiveTagSet, component, 0, asn1Spec is None)
12 years ago
return r, tail
13 years ago
12 years ago
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
length, state, decodeFun, substrateFun):
r = self._createComponent(asn1Spec, tagSet)
if substrateFun:
return substrateFun(r, substrate, length)
if r.getTagSet() == tagSet: # explicitly tagged Choice
component, substrate = decodeFun(substrate, r.getComponentTagMap())
10 years ago
# eat up EOO marker
eooMarker, substrate = decodeFun(substrate, allowEoo=True)
12 years ago
if not eoo.endOfOctets.isSameTypeWith(eooMarker) or \
eooMarker != eoo.endOfOctets:
raise error.PyAsn1Error('No EOO seen before substrate ends')
else:
component, substrate= decodeFun(
substrate, r.getComponentTagMap(), tagSet, length, state
)
if isinstance(component, univ.Choice):
effectiveTagSet = component.getEffectiveTagSet()
else:
effectiveTagSet = component.getTagSet()
r.setComponentByType(effectiveTagSet, component, 0, asn1Spec is None)
return r, substrate
13 years ago
class AnyDecoder(AbstractSimpleDecoder):
protoComponent = univ.Any()
12 years ago
tagFormats = (tag.tagFormatSimple, tag.tagFormatConstructed)
13 years ago
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
13 years ago
if asn1Spec is None or \
asn1Spec is not None and tagSet != asn1Spec.getTagSet():
# untagged Any container, recover inner header substrate
length = length + len(fullSubstrate) - len(substrate)
substrate = fullSubstrate
12 years ago
if substrateFun:
return substrateFun(self._createComponent(asn1Spec, tagSet),
substrate, length)
head, tail = substrate[:length], substrate[length:]
return self._createComponent(asn1Spec, tagSet, value=head), tail
13 years ago
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
12 years ago
length, state, decodeFun, substrateFun):
13 years ago
if asn1Spec is not None and tagSet == asn1Spec.getTagSet():
# tagged Any type -- consume header substrate
header = ''
else:
# untagged Any, recover header substrate
header = fullSubstrate[:-len(substrate)]
r = self._createComponent(asn1Spec, tagSet, header)
# Any components do not inherit initial tag
asn1Spec = self.protoComponent
12 years ago
if substrateFun:
return substrateFun(r, substrate, length)
13 years ago
while substrate:
10 years ago
component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
12 years ago
if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets:
13 years ago
break
r = r + component
else:
raise error.SubstrateUnderrunError(
'No EOO seen before substrate ends'
)
return r, substrate
# character string types
class UTF8StringDecoder(OctetStringDecoder):
protoComponent = char.UTF8String()
class NumericStringDecoder(OctetStringDecoder):
protoComponent = char.NumericString()
class PrintableStringDecoder(OctetStringDecoder):
protoComponent = char.PrintableString()
class TeletexStringDecoder(OctetStringDecoder):
protoComponent = char.TeletexString()
class VideotexStringDecoder(OctetStringDecoder):
protoComponent = char.VideotexString()
class IA5StringDecoder(OctetStringDecoder):
protoComponent = char.IA5String()
class GraphicStringDecoder(OctetStringDecoder):
protoComponent = char.GraphicString()
class VisibleStringDecoder(OctetStringDecoder):
protoComponent = char.VisibleString()
class GeneralStringDecoder(OctetStringDecoder):
protoComponent = char.GeneralString()
class UniversalStringDecoder(OctetStringDecoder):
protoComponent = char.UniversalString()
class BMPStringDecoder(OctetStringDecoder):
protoComponent = char.BMPString()
# "useful" types
10 years ago
class ObjectDescriptorDecoder(OctetStringDecoder):
protoComponent = useful.ObjectDescriptor()
13 years ago
class GeneralizedTimeDecoder(OctetStringDecoder):
protoComponent = useful.GeneralizedTime()
class UTCTimeDecoder(OctetStringDecoder):
protoComponent = useful.UTCTime()
tagMap = {
univ.Integer.tagSet: IntegerDecoder(),
univ.Boolean.tagSet: BooleanDecoder(),
univ.BitString.tagSet: BitStringDecoder(),
univ.OctetString.tagSet: OctetStringDecoder(),
univ.Null.tagSet: NullDecoder(),
univ.ObjectIdentifier.tagSet: ObjectIdentifierDecoder(),
univ.Enumerated.tagSet: IntegerDecoder(),
univ.Real.tagSet: RealDecoder(),
univ.Sequence.tagSet: SequenceDecoder(), # conflicts with SequenceOf
univ.Set.tagSet: SetDecoder(), # conflicts with SetOf
univ.Choice.tagSet: ChoiceDecoder(), # conflicts with Any
# character string types
char.UTF8String.tagSet: UTF8StringDecoder(),
char.NumericString.tagSet: NumericStringDecoder(),
char.PrintableString.tagSet: PrintableStringDecoder(),
char.TeletexString.tagSet: TeletexStringDecoder(),
char.VideotexString.tagSet: VideotexStringDecoder(),
char.IA5String.tagSet: IA5StringDecoder(),
char.GraphicString.tagSet: GraphicStringDecoder(),
char.VisibleString.tagSet: VisibleStringDecoder(),
char.GeneralString.tagSet: GeneralStringDecoder(),
char.UniversalString.tagSet: UniversalStringDecoder(),
char.BMPString.tagSet: BMPStringDecoder(),
# useful types
10 years ago
useful.ObjectDescriptor.tagSet: ObjectDescriptorDecoder(),
13 years ago
useful.GeneralizedTime.tagSet: GeneralizedTimeDecoder(),
useful.UTCTime.tagSet: UTCTimeDecoder()
10 years ago
}
13 years ago
# Type-to-codec map for ambiguous ASN.1 types
typeMap = {
univ.Set.typeId: SetDecoder(),
univ.SetOf.typeId: SetOfDecoder(),
univ.Sequence.typeId: SequenceDecoder(),
univ.SequenceOf.typeId: SequenceOfDecoder(),
univ.Choice.typeId: ChoiceDecoder(),
univ.Any.typeId: AnyDecoder()
10 years ago
}
13 years ago
( stDecodeTag, stDecodeLength, stGetValueDecoder, stGetValueDecoderByAsn1Spec,
stGetValueDecoderByTag, stTryAsExplicitTag, stDecodeValue,
stDumpRawValue, stErrorCondition, stStop ) = [x for x in range(10)]
class Decoder:
defaultErrorState = stErrorCondition
# defaultErrorState = stDumpRawValue
defaultRawDecoder = AnyDecoder()
10 years ago
supportIndefLength = True
13 years ago
def __init__(self, tagMap, typeMap={}):
self.__tagMap = tagMap
self.__typeMap = typeMap
# Tag & TagSet objects caches
self.__tagCache = {}
self.__tagSetCache = {}
def __call__(self, substrate, asn1Spec=None, tagSet=None,
12 years ago
length=None, state=stDecodeTag, recursiveFlag=1,
10 years ago
substrateFun=None, allowEoo=False):
12 years ago
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)))
13 years ago
fullSubstrate = substrate
while state != stStop:
if state == stDecodeTag:
if not substrate:
raise error.SubstrateUnderrunError(
'Short octet stream on tag decoding'
)
12 years ago
if not isOctetsType(substrate) and \
not isinstance(substrate, univ.OctetString):
raise error.PyAsn1Error('Bad octet stream type')
10 years ago
# Decode tag
13 years ago
firstOctet = substrate[0]
substrate = substrate[1:]
if firstOctet in self.__tagCache:
lastTag = self.__tagCache[firstOctet]
else:
t = oct2int(firstOctet)
10 years ago
# 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')
13 years ago
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
10 years ago
)
13 years ago
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
10 years ago
debug.logger and debug.logger & debug.flagDecoder and debug.logger('tag decoded into %s, decoding length' % tagSet)
13 years ago
if state == stDecodeLength:
# Decode length
if not substrate:
10 years ago
raise error.SubstrateUnderrunError(
'Short octet stream on length decoding'
)
13 years ago
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))
)
10 years ago
if length == -1 and not self.supportIndefLength:
error.PyAsn1Error('Indefinite length encoding not supported by this codec')
12 years ago
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])))
13 years ago
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
12 years ago
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__)
13 years ago
if state == stGetValueDecoderByAsn1Spec:
if isinstance(asn1Spec, (dict, tagmap.TagMap)):
if tagSet in asn1Spec:
__chosenSpec = asn1Spec[tagSet]
else:
__chosenSpec = None
12 years ago
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():
10 years ago
debug.logger(' %s -> %s' % (t, v.__class__.__name__))
12 years ago
if asn1Spec.getNegMap():
debug.logger('but neither of: ')
10 years ago
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))
13 years ago
else:
__chosenSpec = asn1Spec
12 years ago
debug.logger and debug.logger & debug.flagDecoder and debug.logger('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__)
13 years ago
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]
12 years ago
debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen for an ambiguous type by type ID %s' % (__chosenSpec.typeId,))
13 years ago
elif baseTagSet in self.__tagMap:
# base type or tagged subtype
concreteDecoder = self.__tagMap[baseTagSet]
10 years ago
debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen by base %s' % (baseTagSet,))
13 years ago
else:
concreteDecoder = None
if concreteDecoder:
asn1Spec = __chosenSpec
state = stDecodeValue
else:
state = stTryAsExplicitTag
else:
12 years ago
concreteDecoder = None
13 years ago
state = stTryAsExplicitTag
12 years ago
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__)
13 years ago
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:
12 years ago
concreteDecoder = None
13 years ago
state = self.defaultErrorState
12 years ago
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'))
13 years ago
if state == stDumpRawValue:
concreteDecoder = self.defaultRawDecoder
12 years ago
debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__)
13 years ago
state = stDecodeValue
if state == stDecodeValue:
12 years ago
if recursiveFlag == 0 and not substrateFun: # legacy
substrateFun = lambda a,b,c: (a,b[:c])
13 years ago
if length == -1: # indef length
value, substrate = concreteDecoder.indefLenValueDecoder(
fullSubstrate, substrate, asn1Spec, tagSet, length,
12 years ago
stGetValueDecoder, self, substrateFun
13 years ago
)
else:
12 years ago
value, substrate = concreteDecoder.valueDecoder(
13 years ago
fullSubstrate, substrate, asn1Spec, tagSet, length,
12 years ago
stGetValueDecoder, self, substrateFun
13 years ago
)
state = stStop
12 years ago
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>'))
13 years ago
if state == stErrorCondition:
raise error.PyAsn1Error(
10 years ago
'%s not in asn1Spec: %s' % (tagSet, asn1Spec)
)
12 years ago
if debug.logger and debug.logger & debug.flagDecoder:
debug.scope.pop()
debug.logger('decoder left scope %s, call completed' % debug.scope)
13 years ago
return value, substrate
decode = Decoder(tagMap, typeMap)
# XXX
# non-recursive decoding; return position rather than substrate