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