1#
2# This file is part of pyasn1 software.
3#
4# Copyright (c) 2005-2019, Ilya Etingof <[email protected]>
5# License: http://snmplabs.com/pyasn1/license.html
6#
7from pyasn1.codec.cer import decoder
8from pyasn1.type import univ
9
10__all__ = ['decode']
11
12
13class BitStringDecoder(decoder.BitStringDecoder):
14    supportConstructedForm = False
15
16
17class OctetStringDecoder(decoder.OctetStringDecoder):
18    supportConstructedForm = False
19
20# TODO: prohibit non-canonical encoding
21RealDecoder = decoder.RealDecoder
22
23tagMap = decoder.tagMap.copy()
24tagMap.update(
25    {univ.BitString.tagSet: BitStringDecoder(),
26     univ.OctetString.tagSet: OctetStringDecoder(),
27     univ.Real.tagSet: RealDecoder()}
28)
29
30typeMap = decoder.typeMap.copy()
31
32# Put in non-ambiguous types for faster codec lookup
33for typeDecoder in tagMap.values():
34    if typeDecoder.protoComponent is not None:
35        typeId = typeDecoder.protoComponent.__class__.typeId
36        if typeId is not None and typeId not in typeMap:
37            typeMap[typeId] = typeDecoder
38
39
40class Decoder(decoder.Decoder):
41    supportIndefLength = False
42
43
44#: Turns DER octet stream into an ASN.1 object.
45#:
46#: Takes DER octet-stream and decode it into an ASN.1 object
47#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
48#: may be a scalar or an arbitrary nested structure.
49#:
50#: Parameters
51#: ----------
52#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
53#:     DER octet-stream
54#:
55#: Keyword Args
56#: ------------
57#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
58#:     A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure
59#:     being decoded, *asn1Spec* may or may not be required. Most common reason for
60#:     it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode.
61#:
62#: Returns
63#: -------
64#: : :py:class:`tuple`
65#:     A tuple of pyasn1 object recovered from DER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
66#:     and the unprocessed trailing portion of the *substrate* (may be empty)
67#:
68#: Raises
69#: ------
70#: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError
71#:     On decoding errors
72#:
73#: Examples
74#: --------
75#: Decode DER serialisation without ASN.1 schema
76#:
77#: .. code-block:: pycon
78#:
79#:    >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03')
80#:    >>> str(s)
81#:    SequenceOf:
82#:     1 2 3
83#:
84#: Decode DER serialisation with ASN.1 schema
85#:
86#: .. code-block:: pycon
87#:
88#:    >>> seq = SequenceOf(componentType=Integer())
89#:    >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq)
90#:    >>> str(s)
91#:    SequenceOf:
92#:     1 2 3
93#:
94decode = Decoder(tagMap, typeMap)
95