Browse Source

Update pyasn1

pull/5122/head
Ruud 10 years ago
parent
commit
4e6ab1abf9
  1. 4
      libs/pyasn1/__init__.py
  2. 153
      libs/pyasn1/codec/ber/decoder.py
  3. 166
      libs/pyasn1/codec/ber/encoder.py
  4. 61
      libs/pyasn1/codec/cer/encoder.py
  5. 4
      libs/pyasn1/codec/der/decoder.py
  6. 10
      libs/pyasn1/codec/der/encoder.py
  7. 10
      libs/pyasn1/compat/binary.py
  8. 10
      libs/pyasn1/compat/iterfunc.py
  9. 63
      libs/pyasn1/debug.py
  10. 78
      libs/pyasn1/type/base.py
  11. 15
      libs/pyasn1/type/char.py
  12. 27
      libs/pyasn1/type/namedtype.py
  13. 12
      libs/pyasn1/type/namedval.py
  14. 8
      libs/pyasn1/type/tag.py
  15. 18
      libs/pyasn1/type/tagmap.py
  16. 226
      libs/pyasn1/type/univ.py
  17. 5
      libs/pyasn1/type/useful.py

4
libs/pyasn1/__init__.py

@ -1,8 +1,8 @@
import sys
# http://www.python.org/dev/peps/pep-0396/
__version__ = '0.1.7'
__version__ = '0.1.8'
if sys.version_info[:2] < (2, 4):
raise RuntimeError('PyASN1 requires Python 2.4 or later')
raise RuntimeError('PyASN1 requires Python 2.4 or later')

153
libs/pyasn1/codec/ber/decoder.py

@ -1,7 +1,7 @@
# BER decoder
from pyasn1.type import tag, base, univ, char, useful, tagmap
from pyasn1.type import tag, univ, char, useful, tagmap
from pyasn1.codec.ber import eoo
from pyasn1.compat.octets import oct2int, octs2ints, isOctetsType
from pyasn1.compat.octets import oct2int, isOctetsType
from pyasn1 import debug, error
class AbstractDecoder:
@ -11,14 +11,14 @@ class AbstractDecoder:
raise error.PyAsn1Error('Decoder not implemented for %s' % (tagSet,))
def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
length, state, decodeFun, substrateFun):
length, state, decodeFun, substrateFun):
raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,))
class AbstractSimpleDecoder(AbstractDecoder):
tagFormats = (tag.tagFormatSimple,)
def _createComponent(self, asn1Spec, tagSet, value=None):
if tagSet[0][1] not in self.tagFormats:
raise error.PyAsn1Error('Invalid tag format %r for %r' % (tagSet[0], self.protoComponent,))
raise error.PyAsn1Error('Invalid tag format %s for %s' % (tagSet[0], self.protoComponent.prettyPrintType()))
if asn1Spec is None:
return self.protoComponent.clone(value, tagSet)
elif value is None:
@ -30,17 +30,12 @@ class AbstractConstructedDecoder(AbstractDecoder):
tagFormats = (tag.tagFormatConstructed,)
def _createComponent(self, asn1Spec, tagSet, value=None):
if tagSet[0][1] not in self.tagFormats:
raise error.PyAsn1Error('Invalid tag format %r for %r' % (tagSet[0], self.protoComponent,))
raise error.PyAsn1Error('Invalid tag format %s for %s' % (tagSet[0], self.protoComponent.prettyPrintType()))
if asn1Spec is None:
return self.protoComponent.clone(tagSet)
else:
return asn1Spec.clone()
class EndOfOctetsDecoder(AbstractSimpleDecoder):
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
length, state, decodeFun, substrateFun):
return eoo.endOfOctets, substrate[length:]
class ExplicitTagDecoder(AbstractSimpleDecoder):
protoComponent = univ.Any('')
tagFormats = (tag.tagFormatConstructed,)
@ -63,7 +58,7 @@ class ExplicitTagDecoder(AbstractSimpleDecoder):
substrate, length
)
value, substrate = decodeFun(substrate, asn1Spec, tagSet, length)
terminator, substrate = decodeFun(substrate)
terminator, substrate = decodeFun(substrate, allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(terminator) and \
terminator == eoo.endOfOctets:
return value, substrate
@ -129,14 +124,14 @@ class BitStringDecoder(AbstractSimpleDecoder):
'Trailing bits overflow %s' % trailingBits
)
head = head[1:]
lsb = p = 0; l = len(head)-1; b = ()
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,)
b.append((o>>j)&0x01)
j = j - 1
p = p + 1
return self._createComponent(asn1Spec, tagSet, b), tail
@ -144,7 +139,7 @@ class BitStringDecoder(AbstractSimpleDecoder):
if substrateFun:
return substrateFun(r, substrate, length)
while head:
component, head = decodeFun(head)
component, head = decodeFun(head, self.protoComponent)
r = r + component
return r, tail
@ -154,7 +149,8 @@ class BitStringDecoder(AbstractSimpleDecoder):
if substrateFun:
return substrateFun(r, substrate, length)
while substrate:
component, substrate = decodeFun(substrate)
component, substrate = decodeFun(substrate, self.protoComponent,
allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets:
break
@ -177,7 +173,7 @@ class OctetStringDecoder(AbstractSimpleDecoder):
if substrateFun:
return substrateFun(r, substrate, length)
while head:
component, head = decodeFun(head)
component, head = decodeFun(head, self.protoComponent)
r = r + component
return r, tail
@ -187,7 +183,8 @@ class OctetStringDecoder(AbstractSimpleDecoder):
if substrateFun:
return substrateFun(r, substrate, length)
while substrate:
component, substrate = decodeFun(substrate)
component, substrate = decodeFun(substrate, self.protoComponent,
allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets:
break
@ -216,20 +213,14 @@ class ObjectIdentifierDecoder(AbstractSimpleDecoder):
if not head:
raise error.PyAsn1Error('Empty substrate')
# Get the first subid
subId = oct2int(head[0])
oid = divmod(subId, 40)
index = 1
oid = ()
index = 0
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')
index += 1
if subId < 128:
oid = oid + (subId,)
elif subId > 128:
# Construct subid from a number of octets
nextSubId = subId
@ -239,11 +230,27 @@ class ObjectIdentifierDecoder(AbstractSimpleDecoder):
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,)
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])
return self._createComponent(asn1Spec, tagSet, oid), tail
class RealDecoder(AbstractSimpleDecoder):
@ -254,10 +261,13 @@ class RealDecoder(AbstractSimpleDecoder):
if not head:
return self._createComponent(asn1Spec, tagSet, 0.0), tail
fo = oct2int(head[0]); head = head[1:]
if fo & 0x80: # binary enoding
if fo & 0x80: # binary encoding
if not head:
raise error.PyAsn1Error("Incomplete floating-point value")
n = (fo & 0x03) + 1
if n == 4:
n = oct2int(head[0])
head = head[1:]
eo, head = head[:n], head[n:]
if not eo or not head:
raise error.PyAsn1Error('Real exponent screwed')
@ -266,6 +276,13 @@ class RealDecoder(AbstractSimpleDecoder):
e <<= 8
e |= oct2int(eo[0])
eo = eo[1:]
b = fo >> 4 & 0x03 # base bits
if b > 2:
raise error.PyAsn1Error('Illegal Real base')
if b == 1: # encbase = 8
e *= 3
elif b == 2: # encbase = 16
e *= 4
p = 0
while head: # value
p <<= 8
@ -273,10 +290,14 @@ class RealDecoder(AbstractSimpleDecoder):
head = head[1:]
if fo & 0x40: # sign bit
p = -p
sf = fo >> 2 & 0x03 # scale bits
p *= 2**sf
value = (p, 2, e)
elif fo & 0x40: # infinite value
value = fo & 0x01 and '-inf' or 'inf'
elif fo & 0xc0 == 0: # character encoding
if not head:
raise error.PyAsn1Error("Incomplete floating-point value")
try:
if fo & 0x3 == 0x1: # NR1
value = (int(head), 10, 0)
@ -336,7 +357,7 @@ class SequenceDecoder(AbstractConstructedDecoder):
idx = 0
while substrate:
asn1Spec = self._getComponentTagMap(r, idx)
component, substrate = decodeFun(substrate, asn1Spec)
component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets:
break
@ -378,7 +399,7 @@ class SequenceOfDecoder(AbstractConstructedDecoder):
asn1Spec = r.getComponentType()
idx = 0
while substrate:
component, substrate = decodeFun(substrate, asn1Spec)
component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets:
break
@ -437,7 +458,8 @@ class ChoiceDecoder(AbstractConstructedDecoder):
return substrateFun(r, substrate, length)
if r.getTagSet() == tagSet: # explicitly tagged Choice
component, substrate = decodeFun(substrate, r.getComponentTagMap())
eooMarker, substrate = decodeFun(substrate) # eat up EOO marker
# eat up EOO marker
eooMarker, substrate = decodeFun(substrate, allowEoo=True)
if not eoo.endOfOctets.isSameTypeWith(eooMarker) or \
eooMarker != eoo.endOfOctets:
raise error.PyAsn1Error('No EOO seen before substrate ends')
@ -485,7 +507,7 @@ class AnyDecoder(AbstractSimpleDecoder):
if substrateFun:
return substrateFun(r, substrate, length)
while substrate:
component, substrate = decodeFun(substrate, asn1Spec)
component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
if eoo.endOfOctets.isSameTypeWith(component) and \
component == eoo.endOfOctets:
break
@ -521,13 +543,14 @@ class BMPStringDecoder(OctetStringDecoder):
protoComponent = char.BMPString()
# "useful" types
class ObjectDescriptorDecoder(OctetStringDecoder):
protoComponent = useful.ObjectDescriptor()
class GeneralizedTimeDecoder(OctetStringDecoder):
protoComponent = useful.GeneralizedTime()
class UTCTimeDecoder(OctetStringDecoder):
protoComponent = useful.UTCTime()
tagMap = {
eoo.endOfOctets.tagSet: EndOfOctetsDecoder(),
univ.Integer.tagSet: IntegerDecoder(),
univ.Boolean.tagSet: BooleanDecoder(),
univ.BitString.tagSet: BitStringDecoder(),
@ -552,9 +575,10 @@ tagMap = {
char.UniversalString.tagSet: UniversalStringDecoder(),
char.BMPString.tagSet: BMPStringDecoder(),
# useful types
useful.ObjectDescriptor.tagSet: ObjectDescriptorDecoder(),
useful.GeneralizedTime.tagSet: GeneralizedTimeDecoder(),
useful.UTCTime.tagSet: UTCTimeDecoder()
}
}
# Type-to-codec map for ambiguous ASN.1 types
typeMap = {
@ -564,7 +588,7 @@ typeMap = {
univ.SequenceOf.typeId: SequenceOfDecoder(),
univ.Choice.typeId: ChoiceDecoder(),
univ.Any.typeId: AnyDecoder()
}
}
( stDecodeTag, stDecodeLength, stGetValueDecoder, stGetValueDecoderByAsn1Spec,
stGetValueDecoderByTag, stTryAsExplicitTag, stDecodeValue,
@ -574,23 +598,22 @@ class Decoder:
defaultErrorState = stErrorCondition
# defaultErrorState = stDumpRawValue
defaultRawDecoder = AnyDecoder()
supportIndefLength = True
def __init__(self, tagMap, typeMap={}):
self.__tagMap = tagMap
self.__typeMap = typeMap
self.__endOfOctetsTagSet = eoo.endOfOctets.getTagSet()
# Tag & TagSet objects caches
self.__tagCache = {}
self.__tagSetCache = {}
def __call__(self, substrate, asn1Spec=None, tagSet=None,
length=None, state=stDecodeTag, recursiveFlag=1,
substrateFun=None):
substrateFun=None, allowEoo=False):
if debug.logger & debug.flagDecoder:
debug.logger('decoder called at scope %s with state %d, working with up to %d octets of substrate: %s' % (debug.scope, state, len(substrate), debug.hexdump(substrate)))
fullSubstrate = substrate
while state != stStop:
if state == stDecodeTag:
# Decode tag
if not substrate:
raise error.SubstrateUnderrunError(
'Short octet stream on tag decoding'
@ -598,13 +621,25 @@ class Decoder:
if not isOctetsType(substrate) and \
not isinstance(substrate, univ.OctetString):
raise error.PyAsn1Error('Bad octet stream type')
# Decode tag
firstOctet = substrate[0]
substrate = substrate[1:]
if firstOctet in self.__tagCache:
lastTag = self.__tagCache[firstOctet]
else:
t = oct2int(firstOctet)
# Look for end-of-octets sentinel
if t == 0:
if substrate and oct2int(substrate[0]) == 0:
if allowEoo and self.supportIndefLength:
debug.logger and debug.logger & debug.flagDecoder and debug.logger('end-of-octets sentinel found')
value, substrate = eoo.endOfOctets, substrate[1:]
state = stStop
continue
else:
raise error.PyAsn1Error('Unexpected end-of-contents sentinel')
else:
raise error.PyAsn1Error('Zero tag encountered')
tagClass = t&0xC0
tagFormat = t&0x20
tagId = t&0x1F
@ -622,7 +657,7 @@ class Decoder:
break
lastTag = tag.Tag(
tagClass=tagClass, tagFormat=tagFormat, tagId=tagId
)
)
if tagId < 31:
# cache short tags
self.__tagCache[firstOctet] = lastTag
@ -637,13 +672,13 @@ class Decoder:
else:
tagSet = lastTag + tagSet
state = stDecodeLength
debug.logger and debug.logger & debug.flagDecoder and debug.logger('tag decoded into %r, decoding length' % tagSet)
debug.logger and debug.logger & debug.flagDecoder and debug.logger('tag decoded into %s, decoding length' % tagSet)
if state == stDecodeLength:
# Decode length
if not substrate:
raise error.SubstrateUnderrunError(
'Short octet stream on length decoding'
)
raise error.SubstrateUnderrunError(
'Short octet stream on length decoding'
)
firstOctet = oct2int(substrate[0])
if firstOctet == 128:
size = 1
@ -670,6 +705,8 @@ class Decoder:
raise error.SubstrateUnderrunError(
'%d-octet short' % (length - len(substrate))
)
if length == -1 and not self.supportIndefLength:
error.PyAsn1Error('Indefinite length encoding not supported by this codec')
state = stGetValueDecoder
debug.logger and debug.logger & debug.flagDecoder and debug.logger('value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(length == -1 and substrate or substrate[:length])))
if state == stGetValueDecoder:
@ -722,12 +759,12 @@ class Decoder:
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__))
debug.logger(' %s -> %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))
for t, v in asn1Spec.getNegMap().items():
debug.logger(' %s -> %s' % (t, v.__class__.__name__))
debug.logger('new candidate ASN.1 spec is %s, chosen by %s' % (__chosenSpec is None and '<none>' or __chosenSpec.prettyPrintType(), tagSet))
else:
__chosenSpec = asn1Spec
debug.logger and debug.logger & debug.flagDecoder and debug.logger('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__)
@ -745,7 +782,7 @@ class Decoder:
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,))
debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen by base %s' % (baseTagSet,))
else:
concreteDecoder = None
if concreteDecoder:
@ -753,10 +790,6 @@ class Decoder:
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
@ -795,8 +828,8 @@ class Decoder:
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)
)
'%s not in asn1Spec: %s' % (tagSet, asn1Spec)
)
if debug.logger and debug.logger & debug.flagDecoder:
debug.scope.pop()
debug.logger('decoder left scope %s, call completed' % debug.scope)

166
libs/pyasn1/codec/ber/encoder.py

@ -114,13 +114,17 @@ class IntegerEncoder(AbstractItemEncoder):
class BitStringEncoder(AbstractItemEncoder):
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
if not maxChunkSize or len(value) <= maxChunkSize*8:
r = {}; l = len(value); p = 0; j = 7
while p < l:
i, j = divmod(p, 8)
r[i] = r.get(i,0) | value[p]<<(7-j)
p = p + 1
keys = list(r); keys.sort()
return int2oct(7-j) + ints2octs([r[k] for k in keys]), 0
out_len = (len(value) + 7) // 8
out_list = out_len * [0]
j = 7
i = -1
for val in value:
j += 1
if j == 8:
i += 1
j = 0
out_list[i] = out_list[i] | val << (7-j)
return int2oct(7-j) + ints2octs(out_list), 0
else:
pos = 0; substrate = null
while 1:
@ -156,40 +160,46 @@ class ObjectIdentifierEncoder(AbstractItemEncoder):
precomputedValues = {
(1, 3, 6, 1, 2): (43, 6, 1, 2),
(1, 3, 6, 1, 4): (43, 6, 1, 4)
}
}
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
oid = value.asTuple()
if oid[:5] in self.precomputedValues:
octets = self.precomputedValues[oid[:5]]
index = 5
oid = oid[5:]
else:
if len(oid) < 2:
raise error.PyAsn1Error('Short OID %s' % (value,))
octets = ()
# Build the first twos
if oid[0] > 6 or oid[1] > 39 or oid[0] == 6 and oid[1] > 15:
if oid[0] == 0 and 0 <= oid[1] <= 39:
oid = (oid[1],) + oid[2:]
elif oid[0] == 1 and 0 <= oid[1] <= 39:
oid = (oid[1] + 40,) + oid[2:]
elif oid[0] == 2:
oid = (oid[1] + 80,) + oid[2:]
else:
raise error.PyAsn1Error(
'Initial sub-ID overflow %s in OID %s' % (oid[:2], value)
'Impossible initial arcs %s at %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:
# Cycle through subIds
for subId in oid:
if subId > -1 and subId < 128:
# Optimize for the common case
octets = octets + (subid & 0x7f,)
elif subid < 0 or subid > 0xFFFFFFFF:
octets = octets + (subId & 0x7f,)
elif subId < 0:
raise error.PyAsn1Error(
'SubId overflow %s in %s' % (subid, value)
)
'Negative OID arc %s at %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
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
@ -197,6 +207,51 @@ class ObjectIdentifierEncoder(AbstractItemEncoder):
class RealEncoder(AbstractItemEncoder):
supportIndefLenMode = 0
binEncBase = 2 # set to None to choose encoding base automatically
def _dropFloatingPoint(self, m, encbase, e):
ms, es = 1, 1
if m < 0:
ms = -1 # mantissa sign
if e < 0:
es = -1 # exponenta sign
m *= ms
if encbase == 8:
m = m*2**(abs(e) % 3 * es)
e = abs(e) // 3 * es
elif encbase == 16:
m = m*2**(abs(e) % 4 * es)
e = abs(e) // 4 * es
while 1:
if int(m) != m:
m *= encbase
e -= 1
continue
break
return ms, int(m), encbase, e
def _chooseEncBase(self, value):
m, b, e = value
base = [2, 8, 16]
if value.binEncBase in base:
return self._dropFloatingPoint(m, value.binEncBase, e)
elif self.binEncBase in base:
return self._dropFloatingPoint(m, self.binEncBase, e)
# auto choosing base 2/8/16
mantissa = [m, m, m]
exponenta = [e, e, e]
encbase = 2
e = float('inf')
for i in range(3):
sign, mantissa[i], base[i], exponenta[i] = \
self._dropFloatingPoint(mantissa[i], base[i], exponenta[i])
if abs(exponenta[i]) < abs(e) or \
(abs(exponenta[i]) == abs(e) and mantissa[i] < m):
e = exponenta[i]
m = int(mantissa[i])
encbase = base[i]
return sign, m, encbase, e
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
if value.isPlusInfinity():
return int2oct(0x40), 0
@ -208,22 +263,43 @@ class RealEncoder(AbstractItemEncoder):
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
fo = 0x80 # binary encoding
ms, m, encbase, e = self._chooseEncBase(value)
if ms < 0: # mantissa sign
fo = fo | 0x40 # sign bit
# exponenta & mantissa normalization
if encbase == 2:
while m & 0x1 == 0:
m >>= 1
e += 1
elif encbase == 8:
while m & 0x7 == 0:
m >>= 3
e += 1
fo |= 0x10
else: # encbase = 16
while m & 0xf == 0:
m >>= 4
e += 1
fo |= 0x20
sf = 0 # scale factor
while m & 0x1 == 0:
m >>= 1
e += 1
sf += 1
if sf > 3:
raise error.PyAsn1Error('Scale factor overflow') # bug if raised
fo |= sf << 2
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
if e == 0 or e == -1:
eo = int2oct(e&0xff)
else:
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
if e == -1 and eo and not (oct2int(eo[0]) & 0x80):
eo = int2oct(0xff) + eo
n = len(eo)
if n > 0xff:
raise error.PyAsn1Error('Real exponent overflow')
@ -235,7 +311,7 @@ class RealEncoder(AbstractItemEncoder):
fo |= 2
else:
fo |= 3
eo = int2oct(n//0xff+1) + eo
eo = int2oct(n&0xff) + eo
po = null
while m:
po = int2oct(m&0xff) + po
@ -308,6 +384,7 @@ tagMap = {
char.UniversalString.tagSet: OctetStringEncoder(),
char.BMPString.tagSet: OctetStringEncoder(),
# useful types
useful.ObjectDescriptor.tagSet: OctetStringEncoder(),
useful.GeneralizedTime.tagSet: OctetStringEncoder(),
useful.UTCTime.tagSet: OctetStringEncoder()
}
@ -323,12 +400,15 @@ typeMap = {
}
class Encoder:
supportIndefLength = True
def __init__(self, tagMap, typeMap={}):
self.__tagMap = tagMap
self.__typeMap = typeMap
def __call__(self, value, defMode=1, maxChunkSize=0):
debug.logger & debug.flagEncoder and debug.logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not defMode and 'in' or '', maxChunkSize, value.__class__.__name__, value.prettyPrint()))
def __call__(self, value, defMode=True, maxChunkSize=0):
if not defMode and not self.supportIndefLength:
raise error.PyAsn1Error('Indefinite length encoding not supported by this codec')
debug.logger & debug.flagEncoder and debug.logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not defMode and 'in' or '', maxChunkSize, value.prettyPrintType(), value.prettyPrint()))
tagSet = value.getTagSet()
if len(tagSet) > 1:
concreteEncoder = explicitlyTaggedItemEncoder
@ -343,7 +423,7 @@ class Encoder:
concreteEncoder = self.__tagMap[tagSet]
else:
raise Error('No encoder for %s' % (value,))
debug.logger & debug.flagEncoder and debug.logger('using value codec %s chosen by %r' % (concreteEncoder.__class__.__name__, tagSet))
debug.logger & debug.flagEncoder and debug.logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet))
substrate = concreteEncoder.encode(
self, value, defMode, maxChunkSize
)

61
libs/pyasn1/codec/cer/encoder.py

@ -1,7 +1,9 @@
# CER encoder
from pyasn1.type import univ
from pyasn1.type import useful
from pyasn1.codec.ber import encoder
from pyasn1.compat.octets import int2oct, null
from pyasn1.compat.octets import int2oct, str2octs, null
from pyasn1 import error
class BooleanEncoder(encoder.IntegerEncoder):
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
@ -15,18 +17,56 @@ class BitStringEncoder(encoder.BitStringEncoder):
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
return encoder.BitStringEncoder.encodeValue(
self, encodeFun, client, defMode, 1000
)
)
class OctetStringEncoder(encoder.OctetStringEncoder):
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
return encoder.OctetStringEncoder.encodeValue(
self, encodeFun, client, defMode, 1000
)
)
class RealEncoder(encoder.RealEncoder):
def _chooseEncBase(self, value):
m, b, e = value
return self._dropFloatingPoint(m, b, e)
# specialized RealEncoder here
# specialized GeneralStringEncoder here
# specialized GeneralizedTimeEncoder here
# specialized UTCTimeEncoder here
class GeneralizedTimeEncoder(OctetStringEncoder):
zchar = str2octs('Z')
pluschar = str2octs('+')
minuschar = str2octs('-')
zero = str2octs('0')
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
octets = client.asOctets()
# This breaks too many existing data items
# if '.' not in octets:
# raise error.PyAsn1Error('Format must include fraction of second: %r' % octets)
if len(octets) < 15:
raise error.PyAsn1Error('Bad UTC time length: %r' % octets)
if self.pluschar in octets or self.minuschar in octets:
raise error.PyAsn1Error('Must be UTC time: %r' % octets)
if octets[-1] != self.zchar[0]:
raise error.PyAsn1Error('Missing timezone specifier: %r' % octets)
return encoder.OctetStringEncoder.encodeValue(
self, encodeFun, client, defMode, 1000
)
class UTCTimeEncoder(encoder.OctetStringEncoder):
zchar = str2octs('Z')
pluschar = str2octs('+')
minuschar = str2octs('-')
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
octets = client.asOctets()
if self.pluschar in octets or self.minuschar in octets:
raise error.PyAsn1Error('Must be UTC time: %r' % octets)
if octets and octets[-1] != self.zchar[0]:
client = client.clone(octets + self.zchar)
if len(client) != 13:
raise error.PyAsn1Error('Bad UTC time length: %r' % client)
return encoder.OctetStringEncoder.encodeValue(
self, encodeFun, client, defMode, 1000
)
class SetOfEncoder(encoder.SequenceOfEncoder):
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
@ -69,17 +109,20 @@ tagMap.update({
univ.Boolean.tagSet: BooleanEncoder(),
univ.BitString.tagSet: BitStringEncoder(),
univ.OctetString.tagSet: OctetStringEncoder(),
univ.Real.tagSet: RealEncoder(),
useful.GeneralizedTime.tagSet: GeneralizedTimeEncoder(),
useful.UTCTime.tagSet: UTCTimeEncoder(),
univ.SetOf().tagSet: SetOfEncoder() # conflcts with Set
})
})
typeMap = encoder.typeMap.copy()
typeMap.update({
univ.Set.typeId: SetOfEncoder(),
univ.SetOf.typeId: SetOfEncoder()
})
})
class Encoder(encoder.Encoder):
def __call__(self, client, defMode=0, maxChunkSize=0):
def __call__(self, client, defMode=False, maxChunkSize=0):
return encoder.Encoder.__call__(self, client, defMode, maxChunkSize)
encode = Encoder(tagMap, typeMap)

4
libs/pyasn1/codec/der/decoder.py

@ -1,9 +1,9 @@
# DER decoder
from pyasn1.type import univ
from pyasn1.codec.cer import decoder
tagMap = decoder.tagMap
typeMap = decoder.typeMap
Decoder = decoder.Decoder
class Decoder(decoder.Decoder):
supportIndefLength = False
decode = Decoder(tagMap, typeMap)

10
libs/pyasn1/codec/der/encoder.py

@ -1,6 +1,7 @@
# DER encoder
from pyasn1.type import univ
from pyasn1.codec.cer import encoder
from pyasn1 import error
class SetOfEncoder(encoder.SetOfEncoder):
def _cmpSetComponents(self, c1, c2):
@ -12,17 +13,20 @@ class SetOfEncoder(encoder.SetOfEncoder):
tagMap = encoder.tagMap.copy()
tagMap.update({
# Overload CER encodrs with BER ones (a bit hackerish XXX)
# Overload CER encoders with BER ones (a bit hackerish XXX)
univ.BitString.tagSet: encoder.encoder.BitStringEncoder(),
univ.OctetString.tagSet: encoder.encoder.OctetStringEncoder(),
# Set & SetOf have same tags
univ.SetOf().tagSet: SetOfEncoder()
})
})
typeMap = encoder.typeMap
class Encoder(encoder.Encoder):
def __call__(self, client, defMode=1, maxChunkSize=0):
supportIndefLength = False
def __call__(self, client, defMode=True, maxChunkSize=0):
if not defMode:
raise error.PyAsn1Error('DER forbids indefinite length mode')
return encoder.Encoder.__call__(self, client, defMode, maxChunkSize)
encode = Encoder(tagMap, typeMap)

10
libs/pyasn1/compat/binary.py

@ -0,0 +1,10 @@
from sys import version_info
if version_info[0:2] < (2, 6):
def bin(x):
if x <= 1:
return '0b'+str(x)
else:
return bin(x>>1) + str(x&1)
else:
bin = bin

10
libs/pyasn1/compat/iterfunc.py

@ -0,0 +1,10 @@
from sys import version_info
if version_info[0] <= 2 and version_info[1] <= 4:
def all(iterable):
for element in iterable:
if not element:
return False
return True
else:
all = all

63
libs/pyasn1/debug.py

@ -1,4 +1,5 @@
import sys
import time
import logging
from pyasn1.compat.octets import octs2ints
from pyasn1 import error
from pyasn1 import __version__
@ -14,23 +15,67 @@ flagMap = {
'all': flagAll
}
class Printer:
def __init__(self, logger=None, handler=None, formatter=None):
if logger is None:
logger = logging.getLogger('pyasn1')
logger.setLevel(logging.DEBUG)
if handler is None:
handler = logging.StreamHandler()
if formatter is None:
formatter = logging.Formatter('%(asctime)s %(name)s: %(message)s')
handler.setFormatter(formatter)
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
self.__logger = logger
def __call__(self, msg): self.__logger.debug(msg)
def __str__(self): return '<python built-in logging>'
if hasattr(logging, 'NullHandler'):
NullHandler = logging.NullHandler
else:
# Python 2.6 and older
class NullHandler(logging.Handler):
def emit(self, record):
pass
class Debug:
defaultPrinter = sys.stderr.write
def __init__(self, *flags):
defaultPrinter = None
def __init__(self, *flags, **options):
self._flags = flagNone
self._printer = self.defaultPrinter
if options.get('printer') is not None:
self._printer = options.get('printer')
elif self.defaultPrinter is not None:
self._printer = self.defaultPrinter
if 'loggerName' in options:
# route our logs to parent logger
self._printer = Printer(
logger=logging.getLogger(options['loggerName']),
handler=NullHandler()
)
else:
self._printer = Printer()
self('running pyasn1 version %s' % __version__)
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)
inverse = f and f[0] in ('!', '~')
if inverse:
f = f[1:]
try:
if inverse:
self._flags &= ~flagMap[f]
else:
self._flags |= flagMap[f]
except KeyError:
raise error.PyAsn1Error('bad debug flag %s' % f)
self('debug category \'%s\' %s' % (f, inverse and 'disabled' or 'enabled'))
def __str__(self):
return 'logger %s, flags %x' % (self._printer, self._flags)
def __call__(self, msg):
self._printer('DBG: %s\n' % msg)
self._printer(msg)
def __and__(self, flag):
return self._flags & flag

78
libs/pyasn1/type/base.py

@ -1,13 +1,13 @@
# Base classes for ASN.1 types
import sys
from pyasn1.type import constraint, tagmap
from pyasn1.type import constraint, tagmap, tag
from pyasn1 import error
class Asn1Item: pass
class Asn1ItemBase(Asn1Item):
# Set of tags for this ASN.1 type
tagSet = ()
tagSet = tag.TagSet()
# A list of constraint.Constraint instances for checking values
subtypeSpec = constraint.ConstraintsIntersection()
@ -38,22 +38,28 @@ class Asn1ItemBase(Asn1Item):
def getEffectiveTagSet(self): return self._tagSet # used by untagged types
def getTagMap(self): return tagmap.TagMap({self._tagSet: self})
def isSameTypeWith(self, other):
def isSameTypeWith(self, other, matchTags=True, matchConstraints=True):
return self is other or \
self._tagSet == other.getTagSet() and \
self._subtypeSpec == other.getSubtypeSpec()
def isSuperTypeOf(self, other):
(not matchTags or \
self._tagSet == other.getTagSet()) and \
(not matchConstraints or \
self._subtypeSpec==other.getSubtypeSpec())
def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True):
"""Returns true if argument is a ASN1 subtype of ourselves"""
return self._tagSet.isSuperTagSetOf(other.getTagSet()) and \
self._subtypeSpec.isSuperTypeOf(other.getSubtypeSpec())
return (not matchTags or \
self._tagSet.isSuperTagSetOf(other.getTagSet())) and \
(not matchConstraints or \
(self._subtypeSpec.isSuperTypeOf(other.getSubtypeSpec())))
class __NoValue:
class NoValue:
def __getattr__(self, attr):
raise error.PyAsn1Error('No value for %s()' % attr)
def __getitem__(self, i):
raise error.PyAsn1Error('No value')
def __repr__(self): return '%s()' % self.__class__.__name__
noValue = __NoValue()
noValue = NoValue()
# Base class for "simple" ASN.1 objects. These are immutable.
class AbstractSimpleAsn1Item(Asn1ItemBase):
@ -72,10 +78,15 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
self._len = None
def __repr__(self):
if self._value is noValue:
return self.__class__.__name__ + '()'
else:
return self.__class__.__name__ + '(%s)' % (self.prettyOut(self._value),)
r = []
if self._value is not self.defaultValue:
r.append(self.prettyOut(self._value))
if self._tagSet is not self.tagSet:
r.append('tagSet=%r' % (self._tagSet,))
if self._subtypeSpec is not self.subtypeSpec:
r.append('subtypeSpec=%r' % (self._subtypeSpec,))
return '%s(%s)' % (self.__class__.__name__, ', '.join(r))
def __str__(self): return str(self._value)
def __eq__(self, other):
return self is other and True or self._value == other
@ -90,6 +101,9 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
def __bool__(self): return bool(self._value)
def __hash__(self): return self.__hashedValue
def hasValue(self):
return not isinstance(self._value, NoValue)
def clone(self, value=None, tagSet=None, subtypeSpec=None):
if value is None and tagSet is None and subtypeSpec is None:
return self
@ -121,14 +135,17 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
def prettyOut(self, value): return str(value)
def prettyPrint(self, scope=0):
if self._value is noValue:
return '<no value>'
else:
if self.hasValue():
return self.prettyOut(self._value)
else:
return '<no value>'
# XXX Compatibility stub
def prettyPrinter(self, scope=0): return self.prettyPrint(scope)
def prettyPrintType(self, scope=0):
return '%s -> %s' % (self.getTagSet(), self.__class__.__name__)
#
# Constructed types:
# * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice
@ -166,13 +183,16 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
self._componentValuesSet = 0
def __repr__(self):
r = self.__class__.__name__ + '()'
for idx in range(len(self._componentValues)):
if self._componentValues[idx] is None:
continue
r = r + '.setComponentByPosition(%s, %r)' % (
idx, self._componentValues[idx]
)
r = []
if self._componentType is not self.componentType:
r.append('componentType=%r' % (self._componentType,))
if self._tagSet is not self.tagSet:
r.append('tagSet=%r' % (self._tagSet,))
if self._subtypeSpec is not self.subtypeSpec:
r.append('subtypeSpec=%r' % (self._subtypeSpec,))
r = '%s(%s)' % (self.__class__.__name__, ', '.join(r))
if self._componentValues:
r += '.setComponents(%s)' % ', '.join([repr(x) for x in self._componentValues])
return r
def __eq__(self, other):
@ -235,8 +255,17 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
def setComponentByPosition(self, idx, value, verifyConstraints=True):
raise error.PyAsn1Error('Method not implemented')
def setComponents(self, *args, **kwargs):
for idx in range(len(args)):
self[idx] = args[idx]
for k in kwargs:
self[k] = kwargs[k]
return self
def getComponentType(self): return self._componentType
def setDefaultComponents(self): pass
def __getitem__(self, idx): return self.getComponentByPosition(idx)
def __setitem__(self, idx, value): self.setComponentByPosition(idx, value)
@ -246,4 +275,3 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
self._componentValues = []
self._componentValuesSet = 0
def setDefaultComponents(self): pass

15
libs/pyasn1/type/char.py

@ -1,12 +1,6 @@
# ASN.1 "character string" types
from pyasn1.type import univ, tag
class UTF8String(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
)
encoding = "utf-8"
class NumericString(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 18)
@ -22,6 +16,7 @@ class TeletexString(univ.OctetString):
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 20)
)
class T61String(TeletexString): pass
class VideotexString(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly(
@ -43,6 +38,8 @@ class VisibleString(univ.OctetString):
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 26)
)
class ISO646String(VisibleString): pass
class GeneralString(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 27)
@ -59,3 +56,9 @@ class BMPString(univ.OctetString):
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 30)
)
encoding = "utf-16-be"
class UTF8String(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
)
encoding = "utf-8"

27
libs/pyasn1/type/namedtype.py

@ -8,9 +8,17 @@ class NamedType:
isDefaulted = 0
def __init__(self, name, t):
self.__name = name; self.__type = t
def __repr__(self): return '%s(%s, %s)' % (
def __repr__(self): return '%s(%r, %r)' % (
self.__class__.__name__, self.__name, self.__type
)
def __eq__(self, other): return tuple(self) == tuple(other)
def __ne__(self, other): return tuple(self) != tuple(other)
def __lt__(self, other): return tuple(self) < tuple(other)
def __le__(self, other): return tuple(self) <= tuple(other)
def __gt__(self, other): return tuple(self) > tuple(other)
def __ge__(self, other): return tuple(self) >= tuple(other)
def __hash__(self): return hash(tuple(self))
def getType(self): return self.__type
def getName(self): return self.__name
def __getitem__(self, idx):
@ -33,10 +41,17 @@ class NamedTypes:
self.__ambigiousTypes = {}
def __repr__(self):
r = '%s(' % self.__class__.__name__
for n in self.__namedTypes:
r = r + '%r, ' % (n,)
return r + ')'
return '%s(%s)' % (
self.__class__.__name__,
', '.join([ repr(x) for x in self.__namedTypes ])
)
def __eq__(self, other): return tuple(self) == tuple(other)
def __ne__(self, other): return tuple(self) != tuple(other)
def __lt__(self, other): return tuple(self) < tuple(other)
def __le__(self, other): return tuple(self) <= tuple(other)
def __gt__(self, other): return tuple(self) > tuple(other)
def __ge__(self, other): return tuple(self) >= tuple(other)
def __hash__(self): return hash(tuple(self))
def __getitem__(self, idx): return self.__namedTypes[idx]
@ -46,6 +61,8 @@ class NamedTypes:
def __bool__(self): return bool(self.__namedTypesLen)
def __len__(self): return self.__namedTypesLen
def clone(self): return self.__class__(*self.__namedTypes)
def getTypeByPosition(self, idx):
if idx < 0 or idx >= self.__namedTypesLen:
raise error.PyAsn1Error('Type position out of range')

12
libs/pyasn1/type/namedval.py

@ -22,8 +22,20 @@ class NamedValues:
self.valToNameIdx[val] = name
self.namedValues = self.namedValues + ((name, val),)
automaticVal = automaticVal + 1
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, ', '.join([repr(x) for x in self.namedValues]))
def __str__(self): return str(self.namedValues)
def __eq__(self, other): return tuple(self) == tuple(other)
def __ne__(self, other): return tuple(self) != tuple(other)
def __lt__(self, other): return tuple(self) < tuple(other)
def __le__(self, other): return tuple(self) <= tuple(other)
def __gt__(self, other): return tuple(self) > tuple(other)
def __ge__(self, other): return tuple(self) >= tuple(other)
def __hash__(self): return hash(tuple(self))
def getName(self, value):
if value in self.valToNameIdx:
return self.valToNameIdx[value]

8
libs/pyasn1/type/tag.py

@ -24,6 +24,9 @@ class Tag:
self.uniq = (tagClass, tagId)
self.__hashedUniqTag = hash(self.uniq)
def __str__(self):
return '[%s:%s:%s]' % self.__tag
def __repr__(self):
return '%s(tagClass=%s, tagFormat=%s, tagId=%s)' % (
(self.__class__.__name__,) + self.__tag
@ -63,10 +66,13 @@ class TagSet:
self.uniq = _uniq
self.__lenOfSuperTags = len(superTags)
def __str__(self):
return self.__superTags and '+'.join([str(x) for x in self.__superTags]) or '[untagged]'
def __repr__(self):
return '%s(%s)' % (
self.__class__.__name__,
', '.join([repr(x) for x in self.__superTags])
'(), ' + ', '.join([repr(x) for x in self.__superTags])
)
def __add__(self, superTag):

18
libs/pyasn1/type/tagmap.py

@ -21,9 +21,23 @@ class TagMap:
raise KeyError()
def __repr__(self):
s = '%r/%r' % (self.__posMap, self.__negMap)
s = self.__class__.__name__ + '('
if self.__posMap:
s = s + 'posMap=%r, ' % (self.__posMap,)
if self.__negMap:
s = s + 'negMap=%r, ' % (self.__negMap,)
if self.__defType is not None:
s = s + '/%r' % (self.__defType,)
s = s + 'defType=%r' % (self.__defType,)
return s + ')'
def __str__(self):
s = self.__class__.__name__ + ':\n'
if self.__posMap:
s = s + 'posMap:\n%s, ' % ',\n '.join([ x.prettyPrintType() for x in self.__posMap.values()])
if self.__negMap:
s = s + 'negMap:\n%s, ' % ',\n '.join([ x.prettyPrintType() for x in self.__negMap.values()])
if self.__defType is not None:
s = s + 'defType:\n%s, ' % self.__defType.prettyPrintType()
return s
def clone(self, parentType, tagMap, uniq=False):

226
libs/pyasn1/type/univ.py

@ -1,5 +1,5 @@
# ASN.1 "universal" data types
import operator, sys
import operator, sys, math
from pyasn1.type import base, tag, constraint, namedtype, namedval, tagmap
from pyasn1.codec.ber import eoo
from pyasn1.compat import octets
@ -22,6 +22,12 @@ class Integer(base.AbstractSimpleAsn1Item):
self, value, tagSet, subtypeSpec
)
def __repr__(self):
if self.__namedValues is not self.namedValues:
return '%s, %r)' % (base.AbstractSimpleAsn1Item.__repr__(self)[:-1], self.__namedValues)
else:
return base.AbstractSimpleAsn1Item.__repr__(self)
def __and__(self, value): return self.clone(self._value & value)
def __rand__(self, value): return self.clone(value & self._value)
def __or__(self, value): return self.clone(self._value | value)
@ -57,8 +63,21 @@ class Integer(base.AbstractSimpleAsn1Item):
if sys.version_info[0] <= 2:
def __long__(self): return long(self._value)
def __float__(self): return float(self._value)
def __abs__(self): return abs(self._value)
def __abs__(self): return self.clone(abs(self._value))
def __index__(self): return int(self._value)
def __pos__(self): return self.clone(+self._value)
def __neg__(self): return self.clone(-self._value)
def __invert__(self): return self.clone(~self._value)
def __round__(self, n=0):
r = round(self._value, n)
if n:
return self.clone(r)
else:
return r
def __floor__(self): return math.floor(self._value)
def __ceil__(self): return math.ceil(self._value)
if sys.version_info[0:2] > (2, 5):
def __trunc__(self): return self.clone(math.trunc(self._value))
def __lt__(self, value): return self._value < value
def __le__(self, value): return self._value <= value
@ -73,7 +92,7 @@ class Integer(base.AbstractSimpleAsn1Item):
return int(value)
except:
raise error.PyAsn1Error(
'Can\'t coerce %s into integer: %s' % (value, sys.exc_info()[1])
'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1])
)
r = self.__namedValues.getValue(value)
if r is not None:
@ -82,7 +101,7 @@ class Integer(base.AbstractSimpleAsn1Item):
return int(value)
except:
raise error.PyAsn1Error(
'Can\'t coerce %s into integer: %s' % (value, sys.exc_info()[1])
'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1])
)
def prettyOut(self, value):
@ -260,6 +279,15 @@ class BitString(base.AbstractSimpleAsn1Item):
def prettyOut(self, value):
return '\"\'%s\'B\"' % ''.join([str(x) for x in value])
try:
all
except NameError: # Python 2.4
def all(iterable):
for element in iterable:
if not element:
return False
return True
class OctetString(base.AbstractSimpleAsn1Item):
tagSet = baseTagSet = tag.initTagSet(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04)
@ -280,7 +308,7 @@ class OctetString(base.AbstractSimpleAsn1Item):
value = self.defaultHexValue
if value is None or value is base.noValue:
value = self.defaultBinValue
self.__intValue = None
self.__asNumbersCache = None
base.AbstractSimpleAsn1Item.__init__(self, value, tagSet, subtypeSpec)
def clone(self, value=None, tagSet=None, subtypeSpec=None,
@ -304,19 +332,33 @@ class OctetString(base.AbstractSimpleAsn1Item):
def prettyIn(self, value):
if isinstance(value, str):
return value
elif isinstance(value, unicode):
try:
return value.encode(self._encoding)
except (LookupError, UnicodeEncodeError):
raise error.PyAsn1Error(
'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding)
)
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)
else:
def prettyIn(self, value):
if isinstance(value, bytes):
return value
elif isinstance(value, str):
try:
return value.encode(self._encoding)
except UnicodeEncodeError:
raise error.PyAsn1Error(
'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding)
)
elif isinstance(value, OctetString):
return value.asOctets()
elif isinstance(value, (tuple, list, map)):
@ -325,14 +367,14 @@ class OctetString(base.AbstractSimpleAsn1Item):
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 fromBinaryString(self, value):
@ -369,21 +411,33 @@ class OctetString(base.AbstractSimpleAsn1Item):
def prettyOut(self, value):
if sys.version_info[0] <= 2:
numbers = tuple([ ord(x) for x in value ])
numbers = tuple(( ord(x) for x in value ))
else:
numbers = tuple(value)
if [ x for x in numbers if x < 32 or x > 126 ]:
return '0x' + ''.join([ '%.2x' % x for x in numbers ])
else:
if all(x >= 32 and x <= 126 for x in numbers):
return str(value)
else:
return '0x' + ''.join(( '%.2x' % x for x in numbers ))
def __repr__(self):
if self._value is base.noValue:
return self.__class__.__name__ + '()'
if [ x for x in self.asNumbers() if x < 32 or x > 126 ]:
return self.__class__.__name__ + '(hexValue=\'' + ''.join([ '%.2x' % x for x in self.asNumbers() ])+'\')'
else:
return self.__class__.__name__ + '(\'' + self.prettyOut(self._value) + '\')'
r = []
doHex = False
if self._value is not self.defaultValue:
for x in self.asNumbers():
if x < 32 or x > 126:
doHex = True
break
if not doHex:
r.append('%r' % (self._value,))
if self._tagSet is not self.tagSet:
r.append('tagSet=%r' % (self._tagSet,))
if self._subtypeSpec is not self.subtypeSpec:
r.append('subtypeSpec=%r' % (self._subtypeSpec,))
if self.encoding is not self._encoding:
r.append('encoding=%r' % (self._encoding,))
if doHex:
r.append('hexValue=%r' % ''.join([ '%.2x' % x for x in self.asNumbers() ]))
return '%s(%s)' % (self.__class__.__name__, ', '.join(r))
if sys.version_info[0] <= 2:
def __str__(self): return str(self._value)
@ -391,17 +445,17 @@ class OctetString(base.AbstractSimpleAsn1Item):
return self._value.decode(self._encoding, 'ignore')
def asOctets(self): return self._value
def asNumbers(self):
if self.__intValue is None:
self.__intValue = tuple([ ord(x) for x in self._value ])
return self.__intValue
if self.__asNumbersCache is None:
self.__asNumbersCache = tuple([ ord(x) for x in self._value ])
return self.__asNumbersCache
else:
def __str__(self): return self._value.decode(self._encoding, 'ignore')
def __bytes__(self): return self._value
def asOctets(self): return self._value
def asNumbers(self):
if self.__intValue is None:
self.__intValue = tuple(self._value)
return self.__intValue
if self.__asNumbersCache is None:
self.__asNumbersCache = tuple(self._value)
return self.__asNumbersCache
# Immutable sequence object protocol
@ -419,6 +473,8 @@ class OctetString(base.AbstractSimpleAsn1Item):
def __radd__(self, value): return self.clone(self.prettyIn(value) + self._value)
def __mul__(self, value): return self.clone(self._value * value)
def __rmul__(self, value): return self * value
def __int__(self): return int(self._value)
def __float__(self): return float(self._value)
class Null(OctetString):
defaultValue = ''.encode() # This is tightly constrained
@ -430,7 +486,9 @@ class Null(OctetString):
if sys.version_info[0] <= 2:
intTypes = (int, long)
else:
intTypes = int
intTypes = (int,)
numericTypes = intTypes + (float,)
class ObjectIdentifier(base.AbstractSimpleAsn1Item):
tagSet = baseTagSet = tag.initTagSet(
@ -456,6 +514,8 @@ class ObjectIdentifier(base.AbstractSimpleAsn1Item):
return self._value[i]
def __str__(self): return self.prettyPrint()
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.prettyPrint())
def index(self, suboid): return self._value.index(suboid)
@ -504,6 +564,7 @@ class ObjectIdentifier(base.AbstractSimpleAsn1Item):
def prettyOut(self, value): return '.'.join([ str(x) for x in value ])
class Real(base.AbstractSimpleAsn1Item):
binEncBase = None # binEncBase = 16 is recommended for large numbers
try:
_plusInf = float('inf')
_minusInf = float('-inf')
@ -526,11 +587,13 @@ class Real(base.AbstractSimpleAsn1Item):
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 not isinstance(value[0], numericTypes) or \
not isinstance(value[1], intTypes) or \
not isinstance(value[2], intTypes):
raise error.PyAsn1Error('Lame Real value syntax: %s' % (value,))
if isinstance(value[0], float) and \
self._inf and value[0] in self._inf:
return value[0]
if value[1] not in (2, 10):
raise error.PyAsn1Error(
'Prohibited base for Real value: %s' % (value[1],)
@ -540,7 +603,14 @@ class Real(base.AbstractSimpleAsn1Item):
return value
elif isinstance(value, intTypes):
return self.__normalizeBase10((value, 10, 0))
elif isinstance(value, float):
elif isinstance(value, (str, float)):
if isinstance(value, str):
try:
value = float(value)
except ValueError:
raise error.PyAsn1Error(
'Bad real value syntax: %s' % (value,)
)
if self._inf and value in self._inf:
return value
else:
@ -551,11 +621,6 @@ class Real(base.AbstractSimpleAsn1Item):
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,)
)
@ -566,6 +631,12 @@ class Real(base.AbstractSimpleAsn1Item):
else:
return str(value)
def prettyPrint(self, scope=0):
if self.isInfinity():
return self.prettyOut(self._value)
else:
return str(float(self))
def isPlusInfinity(self): return self._value == self._plusInf
def isMinusInfinity(self): return self._value == self._minusInf
def isInfinity(self): return self._value in self._inf
@ -601,8 +672,20 @@ class Real(base.AbstractSimpleAsn1Item):
else:
return float(
self._value[0] * pow(self._value[1], self._value[2])
)
def __abs__(self): return abs(float(self))
)
def __abs__(self): return self.clone(abs(float(self)))
def __pos__(self): return self.clone(+float(self))
def __neg__(self): return self.clone(-float(self))
def __round__(self, n=0):
r = round(float(self), n)
if n:
return self.clone(r)
else:
return r
def __floor__(self): return self.clone(math.floor(float(self)))
def __ceil__(self): return self.clone(math.ceil(float(self)))
if sys.version_info[0:2] > (2, 5):
def __trunc__(self): return self.clone(math.trunc(float(self)))
def __lt__(self, value): return float(self) < value
def __le__(self, value): return float(self) <= value
@ -636,6 +719,7 @@ class SetOf(base.AbstractConstructedAsn1Item):
tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
)
typeId = 1
strictConstraints = False
def _cloneComponentValues(self, myClone, cloneValueFlag):
idx = 0; l = len(self._componentValues)
@ -651,9 +735,14 @@ class SetOf(base.AbstractConstructedAsn1Item):
idx = idx + 1
def _verifyComponent(self, idx, value):
if self._componentType is not None and \
not self._componentType.isSuperTypeOf(value):
raise error.PyAsn1Error('Component type error %s' % (value,))
t = self._componentType
if t is None:
return
if not t.isSameTypeWith(value,matchConstraints=self.strictConstraints):
raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, t))
if self.strictConstraints and \
not t.isSuperTypeOf(value, matchTags=False):
raise error.PyAsn1Error('Component value is constraints-incompatible: %r vs %r' % (value, t))
def getComponentByPosition(self, idx): return self._componentValues[idx]
def setComponentByPosition(self, idx, value=None, verifyConstraints=True):
@ -698,6 +787,14 @@ class SetOf(base.AbstractConstructedAsn1Item):
r = r + self._componentValues[idx].prettyPrint(scope)
return r
def prettyPrintType(self, scope=0):
scope = scope + 1
r = '%s -> %s {\n' % (self.getTagSet(), self.__class__.__name__)
if self._componentType is not None:
r = r + ' '*scope
r = r + self._componentType.prettyPrintType(scope)
return r + '\n' + ' '*(scope-1) + '}'
class SequenceOf(SetOf):
tagSet = baseTagSet = tag.initTagSet(
tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
@ -706,15 +803,15 @@ class SequenceOf(SetOf):
class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
componentType = namedtype.NamedTypes()
strictConstraints = False
def __init__(self, componentType=None, tagSet=None,
subtypeSpec=None, sizeSpec=None):
if componentType is None:
componentType = self.componentType
base.AbstractConstructedAsn1Item.__init__(
self, componentType, tagSet, subtypeSpec, sizeSpec
)
if self._componentType is None:
self._componentTypeLen = 0
else:
self._componentTypeLen = len(self._componentType)
self, componentType.clone(), tagSet, subtypeSpec, sizeSpec
)
self._componentTypeLen = len(self._componentType)
def __getitem__(self, idx):
if isinstance(idx, str):
@ -747,8 +844,11 @@ class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
'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))
if not t.isSameTypeWith(value,matchConstraints=self.strictConstraints):
raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, t))
if self.strictConstraints and \
not t.isSuperTypeOf(value, matchTags=False):
raise error.PyAsn1Error('Component value is constraints-incompatible: %r vs %r' % (value, t))
def getComponentByName(self, name):
return self.getComponentByPosition(
@ -756,9 +856,8 @@ class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
)
def setComponentByName(self, name, value=None, verifyConstraints=True):
return self.setComponentByPosition(
self._componentType.getPositionByName(name), value,
verifyConstraints
)
self._componentType.getPositionByName(name),value,verifyConstraints
)
def getComponentByPosition(self, idx):
try:
@ -767,7 +866,11 @@ class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
if idx < self._componentTypeLen:
return
raise
def setComponentByPosition(self, idx, value=None, verifyConstraints=True):
def setComponentByPosition(self, idx, value=None,
verifyConstraints=True,
exactTypes=False,
matchTags=True,
matchConstraints=True):
l = len(self._componentValues)
if idx >= l:
self._componentValues = self._componentValues + (idx-l+1)*[None]
@ -834,6 +937,17 @@ class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
)
return r
def prettyPrintType(self, scope=0):
scope = scope + 1
r = '%s -> %s {\n' % (self.getTagSet(), self.__class__.__name__)
for idx in range(len(self.componentType)):
r = r + ' '*scope
r = r + '"%s"' % self.componentType.getNameByPosition(idx)
r = '%s = %s\n' % (
r, self._componentType.getTypeByPosition(idx).prettyPrintType(scope)
)
return r + '\n' + ' '*(scope-1) + '}'
class Sequence(SequenceAndSetBase):
tagSet = baseTagSet = tag.initTagSet(
tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
@ -877,16 +991,16 @@ class Set(SequenceAndSetBase):
if t.getTagSet():
return self.setComponentByPosition(
idx, value, verifyConstraints
)
)
else:
t = self.setComponentByPosition(idx).getComponentByPosition(idx)
return t.setComponentByType(
tagSet, value, innerFlag, verifyConstraints
)
)
else: # set outer component by inner tagSet
return self.setComponentByPosition(
idx, value, verifyConstraints
)
)
def getComponentTagMap(self):
if self._componentType:

5
libs/pyasn1/type/useful.py

@ -1,6 +1,11 @@
# ASN.1 "useful" types
from pyasn1.type import char, tag
class ObjectDescriptor(char.GraphicString):
tagSet = char.GraphicString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 7)
)
class GeneralizedTime(char.VisibleString):
tagSet = char.VisibleString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 24)

Loading…
Cancel
Save