xref: /aosp_15_r20/external/scapy/scapy/asn1/ber.py (revision 7dc08ffc4802948ccbc861daaf1e81c405c2c4bd)
1*7dc08ffcSJunyu Lai## This file is part of Scapy
2*7dc08ffcSJunyu Lai## See http://www.secdev.org/projects/scapy for more informations
3*7dc08ffcSJunyu Lai## Copyright (C) Philippe Biondi <[email protected]>
4*7dc08ffcSJunyu Lai## Modified by Maxence Tury <[email protected]>
5*7dc08ffcSJunyu Lai## Acknowledgment: Ralph Broenink
6*7dc08ffcSJunyu Lai## This program is published under a GPLv2 license
7*7dc08ffcSJunyu Lai
8*7dc08ffcSJunyu Lai"""
9*7dc08ffcSJunyu LaiBasic Encoding Rules (BER) for ASN.1
10*7dc08ffcSJunyu Lai"""
11*7dc08ffcSJunyu Lai
12*7dc08ffcSJunyu Laifrom __future__ import absolute_import
13*7dc08ffcSJunyu Laifrom scapy.error import warning
14*7dc08ffcSJunyu Laifrom scapy.compat import *
15*7dc08ffcSJunyu Laifrom scapy.utils import binrepr,inet_aton,inet_ntoa
16*7dc08ffcSJunyu Laifrom scapy.asn1.asn1 import ASN1_Decoding_Error,ASN1_Encoding_Error,ASN1_BadTag_Decoding_Error,ASN1_Codecs,ASN1_Class_UNIVERSAL,ASN1_Error,ASN1_DECODING_ERROR,ASN1_BADTAG
17*7dc08ffcSJunyu Laiimport scapy.modules.six as six
18*7dc08ffcSJunyu Lai
19*7dc08ffcSJunyu Lai##################
20*7dc08ffcSJunyu Lai## BER encoding ##
21*7dc08ffcSJunyu Lai##################
22*7dc08ffcSJunyu Lai
23*7dc08ffcSJunyu Lai
24*7dc08ffcSJunyu Lai
25*7dc08ffcSJunyu Lai#####[ BER tools ]#####
26*7dc08ffcSJunyu Lai
27*7dc08ffcSJunyu Lai
28*7dc08ffcSJunyu Laiclass BER_Exception(Exception):
29*7dc08ffcSJunyu Lai    pass
30*7dc08ffcSJunyu Lai
31*7dc08ffcSJunyu Laiclass BER_Encoding_Error(ASN1_Encoding_Error):
32*7dc08ffcSJunyu Lai    def __init__(self, msg, encoded=None, remaining=None):
33*7dc08ffcSJunyu Lai        Exception.__init__(self, msg)
34*7dc08ffcSJunyu Lai        self.remaining = remaining
35*7dc08ffcSJunyu Lai        self.encoded = encoded
36*7dc08ffcSJunyu Lai    def __str__(self):
37*7dc08ffcSJunyu Lai        s = Exception.__str__(self)
38*7dc08ffcSJunyu Lai        if isinstance(self.encoded, BERcodec_Object):
39*7dc08ffcSJunyu Lai            s+="\n### Already encoded ###\n%s" % self.encoded.strshow()
40*7dc08ffcSJunyu Lai        else:
41*7dc08ffcSJunyu Lai            s+="\n### Already encoded ###\n%r" % self.encoded
42*7dc08ffcSJunyu Lai        s+="\n### Remaining ###\n%r" % self.remaining
43*7dc08ffcSJunyu Lai        return s
44*7dc08ffcSJunyu Lai
45*7dc08ffcSJunyu Laiclass BER_Decoding_Error(ASN1_Decoding_Error):
46*7dc08ffcSJunyu Lai    def __init__(self, msg, decoded=None, remaining=None):
47*7dc08ffcSJunyu Lai        Exception.__init__(self, msg)
48*7dc08ffcSJunyu Lai        self.remaining = remaining
49*7dc08ffcSJunyu Lai        self.decoded = decoded
50*7dc08ffcSJunyu Lai    def __str__(self):
51*7dc08ffcSJunyu Lai        s = Exception.__str__(self)
52*7dc08ffcSJunyu Lai        if isinstance(self.decoded, BERcodec_Object):
53*7dc08ffcSJunyu Lai            s+="\n### Already decoded ###\n%s" % self.decoded.strshow()
54*7dc08ffcSJunyu Lai        else:
55*7dc08ffcSJunyu Lai            s+="\n### Already decoded ###\n%r" % self.decoded
56*7dc08ffcSJunyu Lai        s+="\n### Remaining ###\n%r" % self.remaining
57*7dc08ffcSJunyu Lai        return s
58*7dc08ffcSJunyu Lai
59*7dc08ffcSJunyu Laiclass BER_BadTag_Decoding_Error(BER_Decoding_Error, ASN1_BadTag_Decoding_Error):
60*7dc08ffcSJunyu Lai    pass
61*7dc08ffcSJunyu Lai
62*7dc08ffcSJunyu Laidef BER_len_enc(l, size=0):
63*7dc08ffcSJunyu Lai        if l <= 127 and size==0:
64*7dc08ffcSJunyu Lai            return chb(l)
65*7dc08ffcSJunyu Lai        s = b""
66*7dc08ffcSJunyu Lai        while l or size>0:
67*7dc08ffcSJunyu Lai            s = chb(l&0xff)+s
68*7dc08ffcSJunyu Lai            l >>= 8
69*7dc08ffcSJunyu Lai            size -= 1
70*7dc08ffcSJunyu Lai        if len(s) > 127:
71*7dc08ffcSJunyu Lai            raise BER_Exception("BER_len_enc: Length too long (%i) to be encoded [%r]" % (len(s),s))
72*7dc08ffcSJunyu Lai        return chb(len(s)|0x80)+s
73*7dc08ffcSJunyu Laidef BER_len_dec(s):
74*7dc08ffcSJunyu Lai        l = orb(s[0])
75*7dc08ffcSJunyu Lai        if not l & 0x80:
76*7dc08ffcSJunyu Lai            return l,s[1:]
77*7dc08ffcSJunyu Lai        l &= 0x7f
78*7dc08ffcSJunyu Lai        if len(s) <= l:
79*7dc08ffcSJunyu Lai            raise BER_Decoding_Error("BER_len_dec: Got %i bytes while expecting %i" % (len(s)-1, l),remaining=s)
80*7dc08ffcSJunyu Lai        ll = 0
81*7dc08ffcSJunyu Lai        for c in s[1:l+1]:
82*7dc08ffcSJunyu Lai            ll <<= 8
83*7dc08ffcSJunyu Lai            ll |= orb(c)
84*7dc08ffcSJunyu Lai        return ll,s[l+1:]
85*7dc08ffcSJunyu Lai
86*7dc08ffcSJunyu Laidef BER_num_enc(l, size=1):
87*7dc08ffcSJunyu Lai        x=[]
88*7dc08ffcSJunyu Lai        while l or size>0:
89*7dc08ffcSJunyu Lai            x.insert(0, l & 0x7f)
90*7dc08ffcSJunyu Lai            if len(x) > 1:
91*7dc08ffcSJunyu Lai                x[0] |= 0x80
92*7dc08ffcSJunyu Lai            l >>= 7
93*7dc08ffcSJunyu Lai            size -= 1
94*7dc08ffcSJunyu Lai        return b"".join(chb(k) for k in x)
95*7dc08ffcSJunyu Laidef BER_num_dec(s, cls_id=0):
96*7dc08ffcSJunyu Lai        if len(s) == 0:
97*7dc08ffcSJunyu Lai            raise BER_Decoding_Error("BER_num_dec: got empty string", remaining=s)
98*7dc08ffcSJunyu Lai        x = cls_id
99*7dc08ffcSJunyu Lai        for i, c in enumerate(s):
100*7dc08ffcSJunyu Lai            c = orb(c)
101*7dc08ffcSJunyu Lai            x <<= 7
102*7dc08ffcSJunyu Lai            x |= c&0x7f
103*7dc08ffcSJunyu Lai            if not c&0x80:
104*7dc08ffcSJunyu Lai                break
105*7dc08ffcSJunyu Lai        if c&0x80:
106*7dc08ffcSJunyu Lai            raise BER_Decoding_Error("BER_num_dec: unfinished number description", remaining=s)
107*7dc08ffcSJunyu Lai        return x, s[i+1:]
108*7dc08ffcSJunyu Lai
109*7dc08ffcSJunyu Laidef BER_id_dec(s):
110*7dc08ffcSJunyu Lai    # This returns the tag ALONG WITH THE PADDED CLASS+CONSTRUCTIVE INFO.
111*7dc08ffcSJunyu Lai    # Let's recall that bits 8-7 from the first byte of the tag encode
112*7dc08ffcSJunyu Lai    # the class information, while bit 6 means primitive or constructive.
113*7dc08ffcSJunyu Lai    #
114*7dc08ffcSJunyu Lai    # For instance, with low-tag-number b'\x81', class would be 0b10
115*7dc08ffcSJunyu Lai    # ('context-specific') and tag 0x01, but we return 0x81 as a whole.
116*7dc08ffcSJunyu Lai    # For b'\xff\x22', class would be 0b11 ('private'), constructed, then
117*7dc08ffcSJunyu Lai    # padding, then tag 0x22, but we return (0xff>>5)*128^1 + 0x22*128^0.
118*7dc08ffcSJunyu Lai    # Why the 5-bit-shifting? Because it provides an unequivocal encoding
119*7dc08ffcSJunyu Lai    # on base 128 (note that 0xff would equal 1*128^1 + 127*128^0...),
120*7dc08ffcSJunyu Lai    # as we know that bits 5 to 1 are fixed to 1 anyway.
121*7dc08ffcSJunyu Lai    #
122*7dc08ffcSJunyu Lai    # As long as there is no class differentiation, we have to keep this info
123*7dc08ffcSJunyu Lai    # encoded in scapy's tag in order to reuse it for packet building.
124*7dc08ffcSJunyu Lai    # Note that tags thus may have to be hard-coded with their extended
125*7dc08ffcSJunyu Lai    # information, e.g. a SEQUENCE from asn1.py has a direct tag 0x20|16.
126*7dc08ffcSJunyu Lai        x = orb(s[0])
127*7dc08ffcSJunyu Lai        if x & 0x1f != 0x1f:
128*7dc08ffcSJunyu Lai            # low-tag-number
129*7dc08ffcSJunyu Lai            return x,s[1:]
130*7dc08ffcSJunyu Lai        else:
131*7dc08ffcSJunyu Lai            # high-tag-number
132*7dc08ffcSJunyu Lai            return BER_num_dec(s[1:], cls_id=x>>5)
133*7dc08ffcSJunyu Laidef BER_id_enc(n):
134*7dc08ffcSJunyu Lai        if n < 256:
135*7dc08ffcSJunyu Lai            # low-tag-number
136*7dc08ffcSJunyu Lai            return chb(n)
137*7dc08ffcSJunyu Lai        else:
138*7dc08ffcSJunyu Lai            # high-tag-number
139*7dc08ffcSJunyu Lai            s = BER_num_enc(n)
140*7dc08ffcSJunyu Lai            tag = orb(s[0])             # first byte, as an int
141*7dc08ffcSJunyu Lai            tag &= 0x07                 # reset every bit from 8 to 4
142*7dc08ffcSJunyu Lai            tag <<= 5                   # move back the info bits on top
143*7dc08ffcSJunyu Lai            tag |= 0x1f                 # pad with 1s every bit from 5 to 1
144*7dc08ffcSJunyu Lai            return chb(tag) + s[1:]
145*7dc08ffcSJunyu Lai
146*7dc08ffcSJunyu Lai# The functions below provide implicit and explicit tagging support.
147*7dc08ffcSJunyu Laidef BER_tagging_dec(s, hidden_tag=None, implicit_tag=None,
148*7dc08ffcSJunyu Lai                    explicit_tag=None, safe=False):
149*7dc08ffcSJunyu Lai    # We output the 'real_tag' if it is different from the (im|ex)plicit_tag.
150*7dc08ffcSJunyu Lai    real_tag = None
151*7dc08ffcSJunyu Lai    if len(s) > 0:
152*7dc08ffcSJunyu Lai        err_msg = "BER_tagging_dec: observed tag does not match expected tag"
153*7dc08ffcSJunyu Lai        if implicit_tag is not None:
154*7dc08ffcSJunyu Lai            ber_id,s = BER_id_dec(s)
155*7dc08ffcSJunyu Lai            if ber_id != implicit_tag:
156*7dc08ffcSJunyu Lai                if not safe:
157*7dc08ffcSJunyu Lai                    raise BER_Decoding_Error(err_msg, remaining=s)
158*7dc08ffcSJunyu Lai                else:
159*7dc08ffcSJunyu Lai                    real_tag = ber_id
160*7dc08ffcSJunyu Lai            s = chb(hash(hidden_tag)) + s
161*7dc08ffcSJunyu Lai        elif explicit_tag is not None:
162*7dc08ffcSJunyu Lai            ber_id,s = BER_id_dec(s)
163*7dc08ffcSJunyu Lai            if ber_id != explicit_tag:
164*7dc08ffcSJunyu Lai                if not safe:
165*7dc08ffcSJunyu Lai                    raise BER_Decoding_Error(err_msg, remaining=s)
166*7dc08ffcSJunyu Lai                else:
167*7dc08ffcSJunyu Lai                    real_tag = ber_id
168*7dc08ffcSJunyu Lai            l,s = BER_len_dec(s)
169*7dc08ffcSJunyu Lai    return real_tag, s
170*7dc08ffcSJunyu Laidef BER_tagging_enc(s, implicit_tag=None, explicit_tag=None):
171*7dc08ffcSJunyu Lai    if len(s) > 0:
172*7dc08ffcSJunyu Lai        if implicit_tag is not None:
173*7dc08ffcSJunyu Lai            s = BER_id_enc(implicit_tag) + s[1:]
174*7dc08ffcSJunyu Lai        elif explicit_tag is not None:
175*7dc08ffcSJunyu Lai            s = BER_id_enc(explicit_tag) + BER_len_enc(len(s)) + s
176*7dc08ffcSJunyu Lai    return s
177*7dc08ffcSJunyu Lai
178*7dc08ffcSJunyu Lai#####[ BER classes ]#####
179*7dc08ffcSJunyu Lai
180*7dc08ffcSJunyu Laiclass BERcodec_metaclass(type):
181*7dc08ffcSJunyu Lai    def __new__(cls, name, bases, dct):
182*7dc08ffcSJunyu Lai        c = super(BERcodec_metaclass, cls).__new__(cls, name, bases, dct)
183*7dc08ffcSJunyu Lai        try:
184*7dc08ffcSJunyu Lai            c.tag.register(c.codec, c)
185*7dc08ffcSJunyu Lai        except:
186*7dc08ffcSJunyu Lai            warning("Error registering %r for %r" % (c.tag, c.codec))
187*7dc08ffcSJunyu Lai        return c
188*7dc08ffcSJunyu Lai
189*7dc08ffcSJunyu Lai
190*7dc08ffcSJunyu Laiclass BERcodec_Object(six.with_metaclass(BERcodec_metaclass)):
191*7dc08ffcSJunyu Lai    codec = ASN1_Codecs.BER
192*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.ANY
193*7dc08ffcSJunyu Lai
194*7dc08ffcSJunyu Lai    @classmethod
195*7dc08ffcSJunyu Lai    def asn1_object(cls, val):
196*7dc08ffcSJunyu Lai        return cls.tag.asn1_object(val)
197*7dc08ffcSJunyu Lai
198*7dc08ffcSJunyu Lai    @classmethod
199*7dc08ffcSJunyu Lai    def check_string(cls, s):
200*7dc08ffcSJunyu Lai        if not s:
201*7dc08ffcSJunyu Lai            raise BER_Decoding_Error("%s: Got empty object while expecting tag %r" %
202*7dc08ffcSJunyu Lai                                     (cls.__name__,cls.tag), remaining=s)
203*7dc08ffcSJunyu Lai    @classmethod
204*7dc08ffcSJunyu Lai    def check_type(cls, s):
205*7dc08ffcSJunyu Lai        cls.check_string(s)
206*7dc08ffcSJunyu Lai        tag, remainder = BER_id_dec(s)
207*7dc08ffcSJunyu Lai        if cls.tag != tag:
208*7dc08ffcSJunyu Lai            raise BER_BadTag_Decoding_Error("%s: Got tag [%i/%#x] while expecting %r" %
209*7dc08ffcSJunyu Lai                                            (cls.__name__, tag, tag, cls.tag), remaining=s)
210*7dc08ffcSJunyu Lai        return remainder
211*7dc08ffcSJunyu Lai    @classmethod
212*7dc08ffcSJunyu Lai    def check_type_get_len(cls, s):
213*7dc08ffcSJunyu Lai        s2 = cls.check_type(s)
214*7dc08ffcSJunyu Lai        if not s2:
215*7dc08ffcSJunyu Lai            raise BER_Decoding_Error("%s: No bytes while expecting a length" %
216*7dc08ffcSJunyu Lai                                     cls.__name__, remaining=s)
217*7dc08ffcSJunyu Lai        return BER_len_dec(s2)
218*7dc08ffcSJunyu Lai    @classmethod
219*7dc08ffcSJunyu Lai    def check_type_check_len(cls, s):
220*7dc08ffcSJunyu Lai        l,s3 = cls.check_type_get_len(s)
221*7dc08ffcSJunyu Lai        if len(s3) < l:
222*7dc08ffcSJunyu Lai            raise BER_Decoding_Error("%s: Got %i bytes while expecting %i" %
223*7dc08ffcSJunyu Lai                                     (cls.__name__, len(s3), l), remaining=s)
224*7dc08ffcSJunyu Lai        return l,s3[:l],s3[l:]
225*7dc08ffcSJunyu Lai
226*7dc08ffcSJunyu Lai    @classmethod
227*7dc08ffcSJunyu Lai    def do_dec(cls, s, context=None, safe=False):
228*7dc08ffcSJunyu Lai        if context is None:
229*7dc08ffcSJunyu Lai            context = cls.tag.context
230*7dc08ffcSJunyu Lai        cls.check_string(s)
231*7dc08ffcSJunyu Lai        p,_ = BER_id_dec(s)
232*7dc08ffcSJunyu Lai        if p not in context:
233*7dc08ffcSJunyu Lai            t = s
234*7dc08ffcSJunyu Lai            if len(t) > 18:
235*7dc08ffcSJunyu Lai                t = t[:15]+b"..."
236*7dc08ffcSJunyu Lai            raise BER_Decoding_Error("Unknown prefix [%02x] for [%r]" % (p,t), remaining=s)
237*7dc08ffcSJunyu Lai        codec = context[p].get_codec(ASN1_Codecs.BER)
238*7dc08ffcSJunyu Lai        return codec.dec(s,context,safe)
239*7dc08ffcSJunyu Lai
240*7dc08ffcSJunyu Lai    @classmethod
241*7dc08ffcSJunyu Lai    def dec(cls, s, context=None, safe=False):
242*7dc08ffcSJunyu Lai        if not safe:
243*7dc08ffcSJunyu Lai            return cls.do_dec(s, context, safe)
244*7dc08ffcSJunyu Lai        try:
245*7dc08ffcSJunyu Lai            return cls.do_dec(s, context, safe)
246*7dc08ffcSJunyu Lai        except BER_BadTag_Decoding_Error as e:
247*7dc08ffcSJunyu Lai            o,remain = BERcodec_Object.dec(e.remaining, context, safe)
248*7dc08ffcSJunyu Lai            return ASN1_BADTAG(o),remain
249*7dc08ffcSJunyu Lai        except BER_Decoding_Error as e:
250*7dc08ffcSJunyu Lai            return ASN1_DECODING_ERROR(s, exc=e),""
251*7dc08ffcSJunyu Lai        except ASN1_Error as e:
252*7dc08ffcSJunyu Lai            return ASN1_DECODING_ERROR(s, exc=e),""
253*7dc08ffcSJunyu Lai
254*7dc08ffcSJunyu Lai    @classmethod
255*7dc08ffcSJunyu Lai    def safedec(cls, s, context=None):
256*7dc08ffcSJunyu Lai        return cls.dec(s, context, safe=True)
257*7dc08ffcSJunyu Lai
258*7dc08ffcSJunyu Lai
259*7dc08ffcSJunyu Lai    @classmethod
260*7dc08ffcSJunyu Lai    def enc(cls, s):
261*7dc08ffcSJunyu Lai        if isinstance(s, six.string_types):
262*7dc08ffcSJunyu Lai            return BERcodec_STRING.enc(s)
263*7dc08ffcSJunyu Lai        else:
264*7dc08ffcSJunyu Lai            return BERcodec_INTEGER.enc(int(s))
265*7dc08ffcSJunyu Lai
266*7dc08ffcSJunyu LaiASN1_Codecs.BER.register_stem(BERcodec_Object)
267*7dc08ffcSJunyu Lai
268*7dc08ffcSJunyu Lai
269*7dc08ffcSJunyu Lai##########################
270*7dc08ffcSJunyu Lai#### BERcodec objects ####
271*7dc08ffcSJunyu Lai##########################
272*7dc08ffcSJunyu Lai
273*7dc08ffcSJunyu Laiclass BERcodec_INTEGER(BERcodec_Object):
274*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.INTEGER
275*7dc08ffcSJunyu Lai    @classmethod
276*7dc08ffcSJunyu Lai    def enc(cls, i):
277*7dc08ffcSJunyu Lai        s = []
278*7dc08ffcSJunyu Lai        while True:
279*7dc08ffcSJunyu Lai            s.append(i&0xff)
280*7dc08ffcSJunyu Lai            if -127 <= i < 0:
281*7dc08ffcSJunyu Lai                break
282*7dc08ffcSJunyu Lai            if 128 <= i <= 255:
283*7dc08ffcSJunyu Lai                s.append(0)
284*7dc08ffcSJunyu Lai            i >>= 8
285*7dc08ffcSJunyu Lai            if not i:
286*7dc08ffcSJunyu Lai                break
287*7dc08ffcSJunyu Lai        s = [chb(hash(c)) for c in s]
288*7dc08ffcSJunyu Lai        s.append(BER_len_enc(len(s)))
289*7dc08ffcSJunyu Lai        s.append(chb(hash(cls.tag)))
290*7dc08ffcSJunyu Lai        s.reverse()
291*7dc08ffcSJunyu Lai        return b"".join(s)
292*7dc08ffcSJunyu Lai    @classmethod
293*7dc08ffcSJunyu Lai    def do_dec(cls, s, context=None, safe=False):
294*7dc08ffcSJunyu Lai        l,s,t = cls.check_type_check_len(s)
295*7dc08ffcSJunyu Lai        x = 0
296*7dc08ffcSJunyu Lai        if s:
297*7dc08ffcSJunyu Lai            if orb(s[0])&0x80: # negative int
298*7dc08ffcSJunyu Lai                x = -1
299*7dc08ffcSJunyu Lai            for c in s:
300*7dc08ffcSJunyu Lai                x <<= 8
301*7dc08ffcSJunyu Lai                x |= orb(c)
302*7dc08ffcSJunyu Lai        return cls.asn1_object(x),t
303*7dc08ffcSJunyu Lai
304*7dc08ffcSJunyu Laiclass BERcodec_BOOLEAN(BERcodec_INTEGER):
305*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.BOOLEAN
306*7dc08ffcSJunyu Lai
307*7dc08ffcSJunyu Laiclass BERcodec_BIT_STRING(BERcodec_Object):
308*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.BIT_STRING
309*7dc08ffcSJunyu Lai    @classmethod
310*7dc08ffcSJunyu Lai    def do_dec(cls, s, context=None, safe=False):
311*7dc08ffcSJunyu Lai        # /!\ the unused_bits information is lost after this decoding
312*7dc08ffcSJunyu Lai        l,s,t = cls.check_type_check_len(s)
313*7dc08ffcSJunyu Lai        if len(s) > 0:
314*7dc08ffcSJunyu Lai            unused_bits = orb(s[0])
315*7dc08ffcSJunyu Lai            if safe and unused_bits > 7:
316*7dc08ffcSJunyu Lai                raise BER_Decoding_Error("BERcodec_BIT_STRING: too many unused_bits advertised", remaining=s)
317*7dc08ffcSJunyu Lai            s = "".join(binrepr(orb(x)).zfill(8) for x in s[1:])
318*7dc08ffcSJunyu Lai            if unused_bits > 0:
319*7dc08ffcSJunyu Lai                s = s[:-unused_bits]
320*7dc08ffcSJunyu Lai            return cls.tag.asn1_object(s),t
321*7dc08ffcSJunyu Lai        else:
322*7dc08ffcSJunyu Lai            raise BER_Decoding_Error("BERcodec_BIT_STRING found no content (not even unused_bits byte)", remaining=s)
323*7dc08ffcSJunyu Lai    @classmethod
324*7dc08ffcSJunyu Lai    def enc(cls,s):
325*7dc08ffcSJunyu Lai        # /!\ this is DER encoding (bit strings are only zero-bit padded)
326*7dc08ffcSJunyu Lai        s = raw(s)
327*7dc08ffcSJunyu Lai        if len(s) % 8 == 0:
328*7dc08ffcSJunyu Lai            unused_bits = 0
329*7dc08ffcSJunyu Lai        else:
330*7dc08ffcSJunyu Lai            unused_bits = 8 - len(s)%8
331*7dc08ffcSJunyu Lai            s += b"0"*unused_bits
332*7dc08ffcSJunyu Lai        s = b"".join(chb(int(b"".join(chb(y) for y in x),2)) for x in zip(*[iter(s)]*8))
333*7dc08ffcSJunyu Lai        s = chb(unused_bits) + s
334*7dc08ffcSJunyu Lai        return chb(hash(cls.tag))+BER_len_enc(len(s))+s
335*7dc08ffcSJunyu Lai
336*7dc08ffcSJunyu Laiclass BERcodec_STRING(BERcodec_Object):
337*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.STRING
338*7dc08ffcSJunyu Lai    @classmethod
339*7dc08ffcSJunyu Lai    def enc(cls,s):
340*7dc08ffcSJunyu Lai        s = raw(s)
341*7dc08ffcSJunyu Lai        return chb(hash(cls.tag))+BER_len_enc(len(s))+s  # Be sure we are encoding bytes
342*7dc08ffcSJunyu Lai    @classmethod
343*7dc08ffcSJunyu Lai    def do_dec(cls, s, context=None, safe=False):
344*7dc08ffcSJunyu Lai        l,s,t = cls.check_type_check_len(s)
345*7dc08ffcSJunyu Lai        return cls.tag.asn1_object(s),t
346*7dc08ffcSJunyu Lai
347*7dc08ffcSJunyu Laiclass BERcodec_NULL(BERcodec_INTEGER):
348*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.NULL
349*7dc08ffcSJunyu Lai    @classmethod
350*7dc08ffcSJunyu Lai    def enc(cls, i):
351*7dc08ffcSJunyu Lai        if i == 0:
352*7dc08ffcSJunyu Lai            return chb(hash(cls.tag))+b"\0"
353*7dc08ffcSJunyu Lai        else:
354*7dc08ffcSJunyu Lai            return super(cls,cls).enc(i)
355*7dc08ffcSJunyu Lai
356*7dc08ffcSJunyu Laiclass BERcodec_OID(BERcodec_Object):
357*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.OID
358*7dc08ffcSJunyu Lai    @classmethod
359*7dc08ffcSJunyu Lai    def enc(cls, oid):
360*7dc08ffcSJunyu Lai        oid = raw(oid)
361*7dc08ffcSJunyu Lai        lst = [int(x) for x in oid.strip(b".").split(b".")]
362*7dc08ffcSJunyu Lai        if len(lst) >= 2:
363*7dc08ffcSJunyu Lai            lst[1] += 40*lst[0]
364*7dc08ffcSJunyu Lai            del(lst[0])
365*7dc08ffcSJunyu Lai        s = b"".join(BER_num_enc(k) for k in lst)
366*7dc08ffcSJunyu Lai        return chb(hash(cls.tag))+BER_len_enc(len(s))+s
367*7dc08ffcSJunyu Lai    @classmethod
368*7dc08ffcSJunyu Lai    def do_dec(cls, s, context=None, safe=False):
369*7dc08ffcSJunyu Lai        l,s,t = cls.check_type_check_len(s)
370*7dc08ffcSJunyu Lai        lst = []
371*7dc08ffcSJunyu Lai        while s:
372*7dc08ffcSJunyu Lai            l,s = BER_num_dec(s)
373*7dc08ffcSJunyu Lai            lst.append(l)
374*7dc08ffcSJunyu Lai        if (len(lst) > 0):
375*7dc08ffcSJunyu Lai            lst.insert(0,lst[0]//40)
376*7dc08ffcSJunyu Lai            lst[1] %= 40
377*7dc08ffcSJunyu Lai        return cls.asn1_object(b".".join(str(k).encode('ascii') for k in lst)), t
378*7dc08ffcSJunyu Lai
379*7dc08ffcSJunyu Laiclass BERcodec_ENUMERATED(BERcodec_INTEGER):
380*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.ENUMERATED
381*7dc08ffcSJunyu Lai
382*7dc08ffcSJunyu Laiclass BERcodec_UTF8_STRING(BERcodec_STRING):
383*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.UTF8_STRING
384*7dc08ffcSJunyu Lai
385*7dc08ffcSJunyu Laiclass BERcodec_NUMERIC_STRING(BERcodec_STRING):
386*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING
387*7dc08ffcSJunyu Lai
388*7dc08ffcSJunyu Laiclass BERcodec_PRINTABLE_STRING(BERcodec_STRING):
389*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
390*7dc08ffcSJunyu Lai
391*7dc08ffcSJunyu Laiclass BERcodec_T61_STRING(BERcodec_STRING):
392*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.T61_STRING
393*7dc08ffcSJunyu Lai
394*7dc08ffcSJunyu Laiclass BERcodec_VIDEOTEX_STRING(BERcodec_STRING):
395*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING
396*7dc08ffcSJunyu Lai
397*7dc08ffcSJunyu Laiclass BERcodec_IA5_STRING(BERcodec_STRING):
398*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.IA5_STRING
399*7dc08ffcSJunyu Lai
400*7dc08ffcSJunyu Laiclass BERcodec_UTC_TIME(BERcodec_STRING):
401*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.UTC_TIME
402*7dc08ffcSJunyu Lai
403*7dc08ffcSJunyu Laiclass BERcodec_GENERALIZED_TIME(BERcodec_STRING):
404*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
405*7dc08ffcSJunyu Lai
406*7dc08ffcSJunyu Laiclass BERcodec_ISO646_STRING(BERcodec_STRING):
407*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.ISO646_STRING
408*7dc08ffcSJunyu Lai
409*7dc08ffcSJunyu Laiclass BERcodec_UNIVERSAL_STRING(BERcodec_STRING):
410*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING
411*7dc08ffcSJunyu Lai
412*7dc08ffcSJunyu Laiclass BERcodec_BMP_STRING(BERcodec_STRING):
413*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.BMP_STRING
414*7dc08ffcSJunyu Lai
415*7dc08ffcSJunyu Laiclass BERcodec_SEQUENCE(BERcodec_Object):
416*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.SEQUENCE
417*7dc08ffcSJunyu Lai    @classmethod
418*7dc08ffcSJunyu Lai    def enc(cls, l):
419*7dc08ffcSJunyu Lai        if not isinstance(l, bytes):
420*7dc08ffcSJunyu Lai            l = b"".join(x.enc(cls.codec) for x in l)
421*7dc08ffcSJunyu Lai        return chb(hash(cls.tag))+BER_len_enc(len(l))+l
422*7dc08ffcSJunyu Lai    @classmethod
423*7dc08ffcSJunyu Lai    def do_dec(cls, s, context=None, safe=False):
424*7dc08ffcSJunyu Lai        if context is None:
425*7dc08ffcSJunyu Lai            context = cls.tag.context
426*7dc08ffcSJunyu Lai        l,st = cls.check_type_get_len(s) # we may have len(s) < l
427*7dc08ffcSJunyu Lai        s,t = st[:l],st[l:]
428*7dc08ffcSJunyu Lai        obj = []
429*7dc08ffcSJunyu Lai        while s:
430*7dc08ffcSJunyu Lai            try:
431*7dc08ffcSJunyu Lai                o,s = BERcodec_Object.dec(s, context, safe)
432*7dc08ffcSJunyu Lai            except BER_Decoding_Error as err:
433*7dc08ffcSJunyu Lai                err.remaining += t
434*7dc08ffcSJunyu Lai                if err.decoded is not None:
435*7dc08ffcSJunyu Lai                    obj.append(err.decoded)
436*7dc08ffcSJunyu Lai                err.decoded = obj
437*7dc08ffcSJunyu Lai                raise
438*7dc08ffcSJunyu Lai            obj.append(o)
439*7dc08ffcSJunyu Lai        if len(st) < l:
440*7dc08ffcSJunyu Lai            raise BER_Decoding_Error("Not enough bytes to decode sequence", decoded=obj)
441*7dc08ffcSJunyu Lai        return cls.asn1_object(obj),t
442*7dc08ffcSJunyu Lai
443*7dc08ffcSJunyu Laiclass BERcodec_SET(BERcodec_SEQUENCE):
444*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.SET
445*7dc08ffcSJunyu Lai
446*7dc08ffcSJunyu Laiclass BERcodec_IPADDRESS(BERcodec_STRING):
447*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.IPADDRESS
448*7dc08ffcSJunyu Lai    @classmethod
449*7dc08ffcSJunyu Lai    def enc(cls, ipaddr_ascii):
450*7dc08ffcSJunyu Lai        try:
451*7dc08ffcSJunyu Lai            s = inet_aton(ipaddr_ascii)
452*7dc08ffcSJunyu Lai        except Exception:
453*7dc08ffcSJunyu Lai            raise BER_Encoding_Error("IPv4 address could not be encoded")
454*7dc08ffcSJunyu Lai        return chb(hash(cls.tag))+BER_len_enc(len(s))+s
455*7dc08ffcSJunyu Lai    @classmethod
456*7dc08ffcSJunyu Lai    def do_dec(cls, s, context=None, safe=False):
457*7dc08ffcSJunyu Lai        l,s,t = cls.check_type_check_len(s)
458*7dc08ffcSJunyu Lai        try:
459*7dc08ffcSJunyu Lai            ipaddr_ascii = inet_ntoa(s)
460*7dc08ffcSJunyu Lai        except Exception:
461*7dc08ffcSJunyu Lai            raise BER_Decoding_Error("IP address could not be decoded", remaining=s)
462*7dc08ffcSJunyu Lai        return cls.asn1_object(ipaddr_ascii), t
463*7dc08ffcSJunyu Lai
464*7dc08ffcSJunyu Laiclass BERcodec_COUNTER32(BERcodec_INTEGER):
465*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.COUNTER32
466*7dc08ffcSJunyu Lai
467*7dc08ffcSJunyu Laiclass BERcodec_GAUGE32(BERcodec_INTEGER):
468*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.GAUGE32
469*7dc08ffcSJunyu Lai
470*7dc08ffcSJunyu Laiclass BERcodec_TIME_TICKS(BERcodec_INTEGER):
471*7dc08ffcSJunyu Lai    tag = ASN1_Class_UNIVERSAL.TIME_TICKS
472