summaryrefslogtreecommitdiff
path: root/pyasn1
diff options
context:
space:
mode:
authorIlya Etingof <etingof@gmail.com>2019-07-12 22:42:04 +0200
committerGitHub <noreply@github.com>2019-07-12 22:42:04 +0200
commit62efcb94b15ca7fbd5261ca999bf5eca5680de5f (patch)
tree94cd7ed5091c5f1421ba6b186116bbc86303ca23 /pyasn1
parent7b3f79cac2ce765537baa406762d59eae47de04c (diff)
downloadpyasn1-git-62efcb94b15ca7fbd5261ca999bf5eca5680de5f.tar.gz
Fix CER/DER encoders to respect open types (#167)
* Fix CER/DER encoders to respect open types Added a bunch of unit tests to CER/DER codecs covering open types.
Diffstat (limited to 'pyasn1')
-rw-r--r--pyasn1/codec/ber/encoder.py80
-rw-r--r--pyasn1/codec/cer/encoder.py76
2 files changed, 72 insertions, 84 deletions
diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py
index b17fca8..fbad7e7 100644
--- a/pyasn1/codec/ber/encoder.py
+++ b/pyasn1/codec/ber/encoder.py
@@ -559,20 +559,20 @@ class SequenceEncoder(AbstractItemEncoder):
options.update(ifNotEmpty=namedType.isOptional)
# wrap open type blob if needed
- if (namedTypes and namedType.openType
- and namedType.asn1Object.tagSet):
+ if namedTypes and namedType.openType:
- if component.typeId in (
- univ.SetOf.typeId, univ.SequenceOf.typeId):
- substrate += encodeFun(
+ wrapType = namedType.asn1Object
+
+ if wrapType.typeId in (
+ univ.SetOf.typeId, univ.SequenceOf.typeId):
+
+ substrate += encodeFun(
component, asn1Spec,
- **dict(options, openType=True))
+ **dict(options, wrapType=wrapType.componentType))
else:
chunk = encodeFun(component, asn1Spec, **options)
- wrapType = namedType.asn1Object
-
if wrapType.isSameTypeWith(component):
substrate += chunk
@@ -609,67 +609,69 @@ class SequenceEncoder(AbstractItemEncoder):
if omitEmptyOptionals:
options.update(ifNotEmpty=namedType.isOptional)
+ componentSpec = namedType.asn1Object
+
# wrap open type blob if needed
- if namedType.openType and namedType.asn1Object.tagSet:
+ if namedType.openType:
- if component.typeId in (
- univ.SetOf.typeId, univ.SequenceOf.typeId):
- substrate += encodeFun(
- component, asn1Spec[idx],
- **dict(options, openType=True))
+ if componentSpec.typeId in (
+ univ.SetOf.typeId, univ.SequenceOf.typeId):
- else:
- chunk = encodeFun(component, asn1Spec[idx], **options)
+ substrate += encodeFun(
+ component, componentSpec,
+ **dict(options, wrapType=componentSpec.componentType))
- wrapType = namedType.asn1Object
+ else:
+ chunk = encodeFun(component, componentSpec, **options)
- if wrapType.isSameTypeWith(component):
+ if componentSpec.isSameTypeWith(component):
substrate += chunk
else:
- substrate += encodeFun(chunk, wrapType, **options)
+ substrate += encodeFun(chunk, componentSpec, **options)
if LOG:
- LOG('wrapped with wrap type %r' % (wrapType,))
+ LOG('wrapped with wrap type %r' % (componentSpec,))
else:
- substrate += encodeFun(component, asn1Spec[idx], **options)
+ substrate += encodeFun(component, componentSpec, **options)
return substrate, True, True
class SequenceOfEncoder(AbstractItemEncoder):
- def encodeValue(self, value, asn1Spec, encodeFun, **options):
+ def _encodeComponents(self, value, asn1Spec, encodeFun, **options):
+
if asn1Spec is None:
value.verifySizeSpec()
- wrapType = value.componentType
-
else:
- asn1Spec = wrapType = asn1Spec.componentType
+ asn1Spec = asn1Spec.componentType
- openType = options.pop('openType', False)
+ chunks = []
- substrate = null
+ wrapType = options.pop('wrapType', None)
for idx, component in enumerate(value):
- if openType:
- # do not use asn1Spec even if given because it's a wrapper
- chunk = encodeFun(component, **options)
+ chunk = encodeFun(component, asn1Spec, **options)
- if not wrapType.isSameTypeWith(component):
- # wrap encoded value with wrapper container (e.g. ANY)
- chunk = encodeFun(chunk, wrapType, **options)
+ if (wrapType is not None and
+ not wrapType.isSameTypeWith(component)):
+ # wrap encoded value with wrapper container (e.g. ANY)
+ chunk = encodeFun(chunk, wrapType, **options)
- if LOG:
- LOG('wrapped with wrap type %r' % (wrapType,))
+ if LOG:
+ LOG('wrapped with wrap type %r' % (wrapType,))
- else:
- chunk = encodeFun(component, asn1Spec, **options)
+ chunks.append(chunk)
- substrate += chunk
+ return chunks
- return substrate, True, True
+ def encodeValue(self, value, asn1Spec, encodeFun, **options):
+ chunks = self._encodeComponents(
+ value, asn1Spec, encodeFun, **options)
+
+ return null.join(chunks), True, True
class ChoiceEncoder(AbstractItemEncoder):
diff --git a/pyasn1/codec/cer/encoder.py b/pyasn1/codec/cer/encoder.py
index 3fdcc1d..d7a1dfe 100644
--- a/pyasn1/codec/cer/encoder.py
+++ b/pyasn1/codec/cer/encoder.py
@@ -109,6 +109,37 @@ class UTCTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder):
MAX_LENGTH = 14
+class SetOfEncoder(encoder.SequenceOfEncoder):
+ def encodeValue(self, value, asn1Spec, encodeFun, **options):
+ chunks = self._encodeComponents(
+ value, asn1Spec, encodeFun, **options)
+
+ # sort by serialised and padded components
+ if len(chunks) > 1:
+ zero = str2octs('\x00')
+ maxLen = max(map(len, chunks))
+ paddedChunks = [
+ (x.ljust(maxLen, zero), x) for x in chunks
+ ]
+ paddedChunks.sort(key=lambda x: x[0])
+
+ chunks = [x[1] for x in paddedChunks]
+
+ return null.join(chunks), True, True
+
+
+class SequenceOfEncoder(encoder.SequenceOfEncoder):
+ def encodeValue(self, value, asn1Spec, encodeFun, **options):
+
+ if options.get('ifNotEmpty', False) and not len(value):
+ return null, True, True
+
+ chunks = self._encodeComponents(
+ value, asn1Spec, encodeFun, **options)
+
+ return null.join(chunks), True, True
+
+
class SetEncoder(encoder.SequenceEncoder):
@staticmethod
def _componentSortKey(componentAndType):
@@ -197,55 +228,10 @@ class SetEncoder(encoder.SequenceEncoder):
return substrate, True, True
-class SetOfEncoder(encoder.SequenceOfEncoder):
- def encodeValue(self, value, asn1Spec, encodeFun, **options):
- if asn1Spec is None:
- value.verifySizeSpec()
- else:
- asn1Spec = asn1Spec.componentType
-
- components = [encodeFun(x, asn1Spec, **options)
- for x in value]
-
- # sort by serialised and padded components
- if len(components) > 1:
- zero = str2octs('\x00')
- maxLen = max(map(len, components))
- paddedComponents = [
- (x.ljust(maxLen, zero), x) for x in components
- ]
- paddedComponents.sort(key=lambda x: x[0])
-
- components = [x[1] for x in paddedComponents]
-
- substrate = null.join(components)
-
- return substrate, True, True
-
-
class SequenceEncoder(encoder.SequenceEncoder):
omitEmptyOptionals = True
-class SequenceOfEncoder(encoder.SequenceOfEncoder):
- def encodeValue(self, value, asn1Spec, encodeFun, **options):
-
- if options.get('ifNotEmpty', False) and not len(value):
- return null, True, True
-
- if asn1Spec is None:
- value.verifySizeSpec()
- else:
- asn1Spec = asn1Spec.componentType
-
- substrate = null
-
- for idx, component in enumerate(value):
- substrate += encodeFun(value[idx], asn1Spec, **options)
-
- return substrate, True, True
-
-
tagMap = encoder.tagMap.copy()
tagMap.update({
univ.Boolean.tagSet: BooleanEncoder(),