Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/asn1/ber.py: 79%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Philippe Biondi <phil@secdev.org>
5# Acknowledgment: Maxence Tury <maxence.tury@ssi.gouv.fr>
6# Acknowledgment: Ralph Broenink
8"""
9Basic Encoding Rules (BER) for ASN.1
10"""
12# Good read: https://luca.ntop.org/Teaching/Appunti/asn1.html
14from scapy.config import conf
15from scapy.error import warning
16from scapy.compat import chb, bytes_encode
17from scapy.utils import binrepr, inet_aton, inet_ntoa
18from scapy.asn1.asn1 import (
19 ASN1Tag,
20 ASN1_BADTAG,
21 ASN1_BadTag_Decoding_Error,
22 ASN1_Class,
23 ASN1_Class_UNIVERSAL,
24 ASN1_Codecs,
25 ASN1_DECODING_ERROR,
26 ASN1_Decoding_Error,
27 ASN1_Encoding_Error,
28 ASN1_Error,
29 ASN1_Object,
30 _ASN1_ERROR,
31)
33from typing import (
34 Any,
35 AnyStr,
36 Dict,
37 Generic,
38 List,
39 Optional,
40 Tuple,
41 Type,
42 TypeVar,
43 Union,
44 cast,
45)
47##################
48# BER encoding #
49##################
52# [ BER tools ] #
54MAX_BER_DEPTH = 32
57class BER_Exception(Exception):
58 pass
61class BER_Encoding_Error(ASN1_Encoding_Error):
62 def __init__(self,
63 msg, # type: str
64 encoded=None, # type: Optional[Union[BERcodec_Object[Any], str]] # noqa: E501
65 remaining=b"" # type: bytes
66 ):
67 # type: (...) -> None
68 Exception.__init__(self, msg)
69 self.remaining = remaining
70 self.encoded = encoded
72 def __str__(self):
73 # type: () -> str
74 s = Exception.__str__(self)
75 if isinstance(self.encoded, ASN1_Object):
76 s += "\n### Already encoded ###\n%s" % self.encoded.strshow()
77 else:
78 s += "\n### Already encoded ###\n%r" % self.encoded
79 s += "\n### Remaining ###\n%r" % self.remaining
80 return s
83class BER_Decoding_Error(ASN1_Decoding_Error):
84 def __init__(self,
85 msg, # type: str
86 decoded=None, # type: Optional[Any]
87 remaining=b"" # type: bytes
88 ):
89 # type: (...) -> None
90 Exception.__init__(self, msg)
91 self.remaining = remaining
92 self.decoded = decoded
94 def __str__(self):
95 # type: () -> str
96 s = Exception.__str__(self)
97 if isinstance(self.decoded, ASN1_Object):
98 s += "\n### Already decoded ###\n%s" % self.decoded.strshow()
99 else:
100 s += "\n### Already decoded ###\n%r" % self.decoded
101 s += "\n### Remaining ###\n%r" % self.remaining
102 return s
105class BER_BadTag_Decoding_Error(BER_Decoding_Error,
106 ASN1_BadTag_Decoding_Error):
107 pass
110def BER_len_enc(ll, size=0):
111 # type: (int, Optional[int]) -> bytes
112 from scapy.config import conf
113 if size is None:
114 size = conf.ASN1_default_long_size
115 if ll <= 127 and size == 0:
116 return chb(ll)
117 s = b""
118 while ll or size > 0:
119 s = chb(ll & 0xff) + s
120 ll >>= 8
121 size -= 1
122 if len(s) > 127:
123 raise BER_Exception(
124 "BER_len_enc: Length too long (%i) to be encoded [%r]" %
125 (len(s), s)
126 )
127 return chb(len(s) | 0x80) + s
130def BER_len_dec(s):
131 # type: (bytes) -> Tuple[int, bytes]
132 tmp_len = s[0]
133 if not tmp_len & 0x80:
134 return tmp_len, s[1:]
135 tmp_len &= 0x7f
136 if len(s) <= tmp_len:
137 raise BER_Decoding_Error(
138 "BER_len_dec: Got %i bytes while expecting %i" %
139 (len(s) - 1, tmp_len),
140 remaining=s
141 )
142 ll = 0
143 for c in s[1:tmp_len + 1]:
144 ll <<= 8
145 ll |= c
146 return ll, s[tmp_len + 1:]
149def BER_num_enc(ll, size=1):
150 # type: (int, int) -> bytes
151 x = [] # type: List[int]
152 while ll or size > 0:
153 x.insert(0, ll & 0x7f)
154 if len(x) > 1:
155 x[0] |= 0x80
156 ll >>= 7
157 size -= 1
158 return b"".join(chb(k) for k in x)
161def BER_num_dec(s, cls_id=0, max_pow=32):
162 # type: (bytes, int, int) -> Tuple[int, bytes]
163 if len(s) == 0:
164 raise BER_Decoding_Error("BER_num_dec: got empty string", remaining=s)
165 x = cls_id
166 for i, c in enumerate(s):
167 c = c
168 x <<= 7
169 x |= c & 0x7f
170 if not c & 0x80:
171 break
172 if i > max_pow:
173 raise BER_Decoding_Error("BER_num_dec: maximum value reached (2^32-1)",
174 remaining=s)
175 if c & 0x80:
176 raise BER_Decoding_Error("BER_num_dec: unfinished number description",
177 remaining=s)
178 return x, s[i + 1:]
181def BER_id_dec(s):
182 # type: (bytes) -> Tuple[int, bytes]
183 # This returns the tag ALONG WITH THE PADDED CLASS+CONSTRUCTIVE INFO.
184 # Let's recall that bits 8-7 from the first byte of the tag encode
185 # the class information, while bit 6 means primitive or constructive.
186 #
187 # For instance, with low-tag-number b'\x81', class would be 0b10
188 # ('context-specific') and tag 0x01, but we return 0x81 as a whole.
189 # For b'\xff\x22', class would be 0b11 ('private'), constructed, then
190 # padding, then tag 0x22, but we return (0xff>>5)*128^1 + 0x22*128^0.
191 # Why the 5-bit-shifting? Because it provides an unequivocal encoding
192 # on base 128 (note that 0xff would equal 1*128^1 + 127*128^0...),
193 # as we know that bits 5 to 1 are fixed to 1 anyway.
194 #
195 # As long as there is no class differentiation, we have to keep this info
196 # encoded in scapy's tag in order to reuse it for packet building.
197 # Note that tags thus may have to be hard-coded with their extended
198 # information, e.g. a SEQUENCE from asn1.py has a direct tag 0x20|16.
199 x = s[0]
200 if x & 0x1f != 0x1f:
201 # low-tag-number
202 return x, s[1:]
203 else:
204 # high-tag-number
205 return BER_num_dec(s[1:], cls_id=x >> 5)
208def BER_id_enc(n):
209 # type: (int) -> bytes
210 if n < 256:
211 # low-tag-number
212 return chb(n)
213 else:
214 # high-tag-number
215 s = BER_num_enc(n)
216 tag = s[0] # first byte, as an int
217 tag &= 0x07 # reset every bit from 8 to 4
218 tag <<= 5 # move back the info bits on top
219 tag |= 0x1f # pad with 1s every bit from 5 to 1
220 return chb(tag) + s[1:]
222# The functions below provide implicit and explicit tagging support.
225def BER_tagging_dec(s, # type: bytes
226 hidden_tag=None, # type: Optional[int | ASN1Tag]
227 implicit_tag=None, # type: Optional[int]
228 explicit_tag=None, # type: Optional[int]
229 safe=False, # type: Optional[bool]
230 _fname="", # type: str
231 ):
232 # type: (...) -> Tuple[Optional[int], bytes]
233 # We output the 'real_tag' if it is different from the (im|ex)plicit_tag.
234 # 'hidden_tag' is the type tag that is implicited when 'implicit_tag' is used.
235 real_tag = None
236 if len(s) > 0:
237 err_msg = (
238 "BER_tagging_dec: observed tag 0x%.02x does not "
239 "match expected tag 0x%.02x (%s)"
240 )
241 if implicit_tag is not None:
242 ber_id, s = BER_id_dec(s)
243 if ber_id != implicit_tag:
244 if not safe and ber_id != implicit_tag:
245 raise BER_Decoding_Error(err_msg % (
246 ber_id, implicit_tag, _fname),
247 remaining=s)
248 else:
249 real_tag = ber_id
250 s = chb(int(hidden_tag)) + s # type: ignore
251 elif explicit_tag is not None:
252 ber_id, s = BER_id_dec(s)
253 if ber_id != explicit_tag:
254 if not safe:
255 raise BER_Decoding_Error(
256 err_msg % (ber_id, explicit_tag, _fname),
257 remaining=s)
258 else:
259 real_tag = ber_id
260 l, s = BER_len_dec(s)
261 return real_tag, s
264def BER_tagging_enc(s, implicit_tag=None, explicit_tag=None):
265 # type: (bytes, Optional[int], Optional[int]) -> bytes
266 if len(s) > 0:
267 if implicit_tag is not None:
268 s = BER_id_enc(implicit_tag) + s[1:]
269 elif explicit_tag is not None:
270 s = BER_id_enc(explicit_tag) + BER_len_enc(
271 len(s), size=conf.ASN1_default_long_size,
272 ) + s
273 return s
275# [ BER classes ] #
278class BERcodec_metaclass(type):
279 def __new__(cls,
280 name, # type: str
281 bases, # type: Tuple[type, ...]
282 dct # type: Dict[str, Any]
283 ):
284 # type: (...) -> Type[BERcodec_Object[Any]]
285 c = cast('Type[BERcodec_Object[Any]]',
286 super(BERcodec_metaclass, cls).__new__(cls, name, bases, dct))
287 try:
288 c.tag.register(c.codec, c)
289 except Exception:
290 warning("Error registering %r for %r" % (c.tag, c.codec))
291 return c
294_K = TypeVar('_K')
297class BERcodec_Object(Generic[_K], metaclass=BERcodec_metaclass):
298 codec = ASN1_Codecs.BER
299 tag = ASN1_Class_UNIVERSAL.ANY
301 @classmethod
302 def asn1_object(cls, val):
303 # type: (_K) -> ASN1_Object[_K]
304 return cls.tag.asn1_object(val)
306 @classmethod
307 def check_string(cls, s):
308 # type: (bytes) -> None
309 if not s:
310 raise BER_Decoding_Error(
311 "%s: Got empty object while expecting tag %r" %
312 (cls.__name__, cls.tag), remaining=s
313 )
315 @classmethod
316 def check_type(cls, s):
317 # type: (bytes) -> bytes
318 cls.check_string(s)
319 tag, remainder = BER_id_dec(s)
320 if not isinstance(tag, int) or cls.tag != tag:
321 raise BER_BadTag_Decoding_Error(
322 "%s: Got tag [%i/%#x] while expecting %r" %
323 (cls.__name__, tag, tag, cls.tag), remaining=s
324 )
325 return remainder
327 @classmethod
328 def check_type_get_len(cls, s):
329 # type: (bytes) -> Tuple[int, bytes]
330 s2 = cls.check_type(s)
331 if not s2:
332 raise BER_Decoding_Error("%s: No bytes while expecting a length" %
333 cls.__name__, remaining=s)
334 return BER_len_dec(s2)
336 @classmethod
337 def check_type_check_len(cls, s):
338 # type: (bytes) -> Tuple[int, bytes, bytes]
339 l, s3 = cls.check_type_get_len(s)
340 if len(s3) < l:
341 raise BER_Decoding_Error("%s: Got %i bytes while expecting %i" %
342 (cls.__name__, len(s3), l), remaining=s)
343 return l, s3[:l], s3[l:]
345 @classmethod
346 def do_dec(cls,
347 s, # type: bytes
348 context=None, # type: Optional[Type[ASN1_Class]]
349 safe=False, # type: bool
350 _depth=0, # type: int
351 ):
352 # type: (...) -> Tuple[ASN1_Object[Any], bytes]
353 if context is not None:
354 _context = context
355 else:
356 _context = cls.tag.context
357 cls.check_string(s)
358 p, remainder = BER_id_dec(s)
359 if p not in _context:
360 t = s
361 if len(t) > 18:
362 t = t[:15] + b"..."
363 raise BER_Decoding_Error("Unknown prefix [%02x] for [%r]" %
364 (p, t), remaining=s)
365 tag = _context[p]
366 codec = cast('Type[BERcodec_Object[_K]]',
367 tag.get_codec(ASN1_Codecs.BER))
368 if codec == BERcodec_Object:
369 # Value type defined as Unknown
370 l, s = BER_num_dec(remainder)
371 return ASN1_BADTAG(s[:l]), s[l:]
372 return codec.dec(s, _context, safe, _depth=_depth)
374 @classmethod
375 def dec(cls,
376 s, # type: bytes
377 context=None, # type: Optional[Type[ASN1_Class]]
378 safe=False, # type: bool
379 _depth=0, # type: int
380 **_kwargs # type: Any
381 ):
382 # type: (...) -> Tuple[Union[_ASN1_ERROR, ASN1_Object[_K]], bytes]
383 if _depth > MAX_BER_DEPTH:
384 raise BER_Exception("Reached maximum BER recursion limit")
385 if not safe:
386 return cls.do_dec(s, context, safe, _depth=_depth)
387 try:
388 return cls.do_dec(s, context, safe, _depth=_depth)
389 except BER_BadTag_Decoding_Error as e:
390 o, remain = BERcodec_Object.dec(
391 e.remaining,
392 context=context,
393 safe=safe,
394 _depth=_depth + 1,
395 ) # type: Tuple[ASN1_Object[Any], bytes]
396 return ASN1_BADTAG(o), remain
397 except BER_Decoding_Error as e:
398 return ASN1_DECODING_ERROR(s, exc=e), b""
399 except ASN1_Error as e:
400 return ASN1_DECODING_ERROR(s, exc=e), b""
402 @classmethod
403 def safedec(cls,
404 s, # type: bytes
405 context=None, # type: Optional[Type[ASN1_Class]]
406 _depth=0, # type: int
407 **_kwargs # type: Any
408 ):
409 # type: (...) -> Tuple[Union[_ASN1_ERROR, ASN1_Object[_K]], bytes]
410 return cls.dec(s, context, safe=True, _depth=_depth)
412 @classmethod
413 def enc(cls, s, size_len=0, **_kwargs):
414 # type: (_K, Optional[int], **Any) -> bytes
415 # Ignore unknown kwargs so shared field._codec_kwargs() dicts (OER/UPER
416 # keys) do not TypeError on BER packets.
417 if isinstance(s, (str, bytes)):
418 return BERcodec_STRING.enc(s, size_len=size_len)
419 else:
420 try:
421 return BERcodec_INTEGER.enc(int(s), size_len=size_len) # type: ignore
422 except TypeError:
423 raise TypeError("Trying to encode an invalid value !")
426ASN1_Codecs.BER.register_stem(BERcodec_Object)
427ASN1_Codecs.BER.register_tagging(BER_tagging_enc, BER_tagging_dec)
430##########################
431# BERcodec objects #
432##########################
434class BERcodec_INTEGER(BERcodec_Object[int]):
435 tag = ASN1_Class_UNIVERSAL.INTEGER
437 @classmethod
438 def enc(cls, i, size_len=0, **_kwargs): # type: ignore[override]
439 # type: (int, Optional[int], **Any) -> bytes
440 ls = []
441 while True:
442 ls.append(i & 0xff)
443 if -127 <= i < 0:
444 break
445 if 128 <= i <= 255:
446 ls.append(0)
447 i >>= 8
448 if not i:
449 break
450 s = [chb(int(c)) for c in ls]
451 s.append(BER_len_enc(len(s), size=size_len))
452 s.append(chb(int(cls.tag)))
453 s.reverse()
454 return b"".join(s)
456 @classmethod
457 def do_dec(cls,
458 s, # type: bytes
459 context=None, # type: Optional[Type[ASN1_Class]]
460 safe=False, # type: bool
461 _depth=0, # type: int
462 ):
463 # type: (...) -> Tuple[ASN1_Object[int], bytes]
464 l, s, t = cls.check_type_check_len(s)
465 # One pass: shifting a growing integer per octet was quadratic in width.
466 return cls.asn1_object(int.from_bytes(s, "big", signed=True)), t
469class BERcodec_BOOLEAN(BERcodec_INTEGER):
470 tag = ASN1_Class_UNIVERSAL.BOOLEAN
473class BERcodec_BIT_STRING(BERcodec_Object[str]):
474 tag = ASN1_Class_UNIVERSAL.BIT_STRING
476 @classmethod
477 def do_dec(cls,
478 s, # type: bytes
479 context=None, # type: Optional[Type[ASN1_Class]]
480 safe=False, # type: bool
481 _depth=0, # type: int
482 ):
483 # type: (...) -> Tuple[ASN1_Object[str], bytes]
484 # /!\ the unused_bits information is lost after this decoding
485 l, s, t = cls.check_type_check_len(s)
486 if len(s) > 0:
487 unused_bits = s[0]
488 if safe and unused_bits > 7:
489 raise BER_Decoding_Error(
490 "BERcodec_BIT_STRING: too many unused_bits advertised",
491 remaining=s
492 )
493 fs = "".join(binrepr(x).zfill(8) for x in s[1:])
494 if unused_bits > 0:
495 fs = fs[:-unused_bits]
496 return cls.tag.asn1_object(fs), t
497 else:
498 raise BER_Decoding_Error(
499 "BERcodec_BIT_STRING found no content "
500 "(not even unused_bits byte)",
501 remaining=s
502 )
504 @classmethod
505 def enc(cls, _s, size_len=0, **_kwargs): # type: ignore[override]
506 # type: (AnyStr, Optional[int], **Any) -> bytes
507 # /!\ this is DER encoding (bit strings are only zero-bit padded)
508 s = bytes_encode(_s)
509 if len(s) % 8 == 0:
510 unused_bits = 0
511 else:
512 unused_bits = 8 - len(s) % 8
513 s += b"0" * unused_bits
514 s = b"".join(chb(int(b"".join(chb(y) for y in x), 2))
515 for x in zip(*[iter(s)] * 8))
516 s = chb(unused_bits) + s
517 return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s
520class BERcodec_STRING(BERcodec_Object[str]):
521 tag = ASN1_Class_UNIVERSAL.STRING
523 @classmethod
524 def enc(cls, _s, size_len=0, **_kwargs): # type: ignore[override]
525 # type: (Union[str, bytes], Optional[int], **Any) -> bytes
526 s = bytes_encode(_s)
527 # Be sure we are encoding bytes
528 return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s
530 @classmethod
531 def do_dec(cls,
532 s, # type: bytes
533 context=None, # type: Optional[Type[ASN1_Class]]
534 safe=False, # type: bool
535 _depth=0, # type: int
536 ):
537 # type: (...) -> Tuple[ASN1_Object[Any], bytes]
538 l, s, t = cls.check_type_check_len(s)
539 return cls.tag.asn1_object(s), t
542class BERcodec_NULL(BERcodec_INTEGER):
543 tag = ASN1_Class_UNIVERSAL.NULL
545 @classmethod
546 def enc(cls, i, size_len=0, **_kwargs): # type: ignore[override]
547 # type: (int, Optional[int], **Any) -> bytes
548 if i == 0:
549 return chb(int(cls.tag)) + b"\0"
550 else:
551 return super(cls, cls).enc(i, size_len=size_len)
554class BERcodec_OID(BERcodec_Object[bytes]):
555 tag = ASN1_Class_UNIVERSAL.OID
557 @classmethod
558 def enc(cls, _oid, size_len=0, **_kwargs): # type: ignore[override]
559 # type: (AnyStr, Optional[int], **Any) -> bytes
560 oid = bytes_encode(_oid)
561 if oid:
562 lst = [int(x) for x in oid.strip(b".").split(b".")]
563 else:
564 lst = list()
565 if len(lst) >= 2:
566 lst[1] += 40 * lst[0]
567 del lst[0]
568 s = b"".join(BER_num_enc(k) for k in lst)
569 return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s
571 @classmethod
572 def do_dec(cls,
573 s, # type: bytes
574 context=None, # type: Optional[Type[ASN1_Class]]
575 safe=False, # type: bool
576 _depth=0, # type: int
577 ):
578 # type: (...) -> Tuple[ASN1_Object[bytes], bytes]
579 l, s, t = cls.check_type_check_len(s)
580 lst = []
581 while s:
582 l, s = BER_num_dec(s)
583 lst.append(l)
584 if lst:
585 # X.690 sect 8.19.4
586 lst.insert(0, lst[0] // 40)
587 lst[1] %= 40
588 return (
589 cls.asn1_object(b".".join(str(k).encode('ascii') for k in lst)),
590 t,
591 )
594class BERcodec_ENUMERATED(BERcodec_INTEGER):
595 tag = ASN1_Class_UNIVERSAL.ENUMERATED
598class BERcodec_UTF8_STRING(BERcodec_STRING):
599 tag = ASN1_Class_UNIVERSAL.UTF8_STRING
602class BERcodec_NUMERIC_STRING(BERcodec_STRING):
603 tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING
606class BERcodec_PRINTABLE_STRING(BERcodec_STRING):
607 tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
610class BERcodec_T61_STRING(BERcodec_STRING):
611 tag = ASN1_Class_UNIVERSAL.T61_STRING
614class BERcodec_VIDEOTEX_STRING(BERcodec_STRING):
615 tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING
618class BERcodec_IA5_STRING(BERcodec_STRING):
619 tag = ASN1_Class_UNIVERSAL.IA5_STRING
622class BERcodec_GENERAL_STRING(BERcodec_STRING):
623 tag = ASN1_Class_UNIVERSAL.GENERAL_STRING
626class BERcodec_UTC_TIME(BERcodec_STRING):
627 tag = ASN1_Class_UNIVERSAL.UTC_TIME
630class BERcodec_GENERALIZED_TIME(BERcodec_STRING):
631 tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
634class BERcodec_ISO646_STRING(BERcodec_STRING):
635 tag = ASN1_Class_UNIVERSAL.ISO646_STRING
638class BERcodec_UNIVERSAL_STRING(BERcodec_STRING):
639 tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING
642class BERcodec_BMP_STRING(BERcodec_STRING):
643 tag = ASN1_Class_UNIVERSAL.BMP_STRING
646class BERcodec_SEQUENCE(BERcodec_Object[Union[bytes, List[BERcodec_Object[Any]]]]): # noqa: E501
647 tag = ASN1_Class_UNIVERSAL.SEQUENCE
649 @classmethod
650 def enc(cls, _ll, size_len=None, **_kwargs): # type: ignore[override]
651 # type: (Union[bytes, List[BERcodec_Object[Any]]], Optional[int], **Any) -> bytes # noqa: E501
652 if isinstance(_ll, bytes):
653 ll = _ll
654 else:
655 ll = b"".join(x.enc(cls.codec) for x in _ll)
656 # None = apply conf; explicit 0 keeps short-form lengths.
657 if size_len is None:
658 size_len = conf.ASN1_default_long_size
659 return chb(int(cls.tag)) + BER_len_enc(len(ll), size=size_len) + ll
661 @classmethod
662 def do_dec(cls,
663 s, # type: bytes
664 context=None, # type: Optional[Type[ASN1_Class]]
665 safe=False, # type: bool
666 _depth=0, # type: int
667 ):
668 # type: (...) -> Tuple[ASN1_Object[Union[bytes, List[Any]]], bytes]
669 if context is None:
670 context = cls.tag.context
671 if _depth > MAX_BER_DEPTH:
672 raise BER_Exception("Reached maximum BER recursion limit")
673 ll, st = cls.check_type_get_len(s) # we may have len(s) < ll
674 s, t = st[:ll], st[ll:]
675 obj = []
676 while s:
677 try:
678 o, remain = BERcodec_Object.dec(
679 s,
680 context=context,
681 safe=safe,
682 _depth=_depth + 1,
683 ) # type: Tuple[ASN1_Object[Any], bytes]
684 s = remain
685 except BER_Decoding_Error as err:
686 err.remaining += t
687 if err.decoded is not None:
688 obj.append(err.decoded)
689 err.decoded = obj
690 raise
691 obj.append(o)
692 if len(st) < ll:
693 raise BER_Decoding_Error("Not enough bytes to decode sequence",
694 decoded=obj)
695 return cls.asn1_object(obj), t
698class BERcodec_SET(BERcodec_SEQUENCE):
699 tag = ASN1_Class_UNIVERSAL.SET
702class BERcodec_IPADDRESS(BERcodec_STRING):
703 tag = ASN1_Class_UNIVERSAL.IPADDRESS
705 @classmethod
706 def enc(cls, ipaddr_ascii, size_len=0, **_kwargs): # type: ignore[override]
707 # type: (str, Optional[int], **Any) -> bytes
708 try:
709 s = inet_aton(ipaddr_ascii)
710 except Exception:
711 raise BER_Encoding_Error("IPv4 address could not be encoded")
712 return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s
714 @classmethod
715 def do_dec(cls,
716 s, # type: bytes
717 context=None, # type: Optional[Any]
718 safe=False, # type: bool
719 _depth=0, # type: int
720 ):
721 # type: (...) -> Tuple[ASN1_Object[str], bytes]
722 l, s, t = cls.check_type_check_len(s)
723 try:
724 ipaddr_ascii = inet_ntoa(s)
725 except Exception:
726 raise BER_Decoding_Error("IP address could not be decoded",
727 remaining=s)
728 return cls.asn1_object(ipaddr_ascii), t
731class BERcodec_COUNTER32(BERcodec_INTEGER):
732 tag = ASN1_Class_UNIVERSAL.COUNTER32
735class BERcodec_COUNTER64(BERcodec_INTEGER):
736 tag = ASN1_Class_UNIVERSAL.COUNTER64
739class BERcodec_GAUGE32(BERcodec_INTEGER):
740 tag = ASN1_Class_UNIVERSAL.GAUGE32
743class BERcodec_TIME_TICKS(BERcodec_INTEGER):
744 tag = ASN1_Class_UNIVERSAL.TIME_TICKS