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 x = 0
466 if s:
467 if s[0] & 0x80: # negative int
468 x = -1
469 for c in s:
470 x <<= 8
471 x |= c
472 return cls.asn1_object(x), t
475class BERcodec_BOOLEAN(BERcodec_INTEGER):
476 tag = ASN1_Class_UNIVERSAL.BOOLEAN
479class BERcodec_BIT_STRING(BERcodec_Object[str]):
480 tag = ASN1_Class_UNIVERSAL.BIT_STRING
482 @classmethod
483 def do_dec(cls,
484 s, # type: bytes
485 context=None, # type: Optional[Type[ASN1_Class]]
486 safe=False, # type: bool
487 _depth=0, # type: int
488 ):
489 # type: (...) -> Tuple[ASN1_Object[str], bytes]
490 # /!\ the unused_bits information is lost after this decoding
491 l, s, t = cls.check_type_check_len(s)
492 if len(s) > 0:
493 unused_bits = s[0]
494 if safe and unused_bits > 7:
495 raise BER_Decoding_Error(
496 "BERcodec_BIT_STRING: too many unused_bits advertised",
497 remaining=s
498 )
499 fs = "".join(binrepr(x).zfill(8) for x in s[1:])
500 if unused_bits > 0:
501 fs = fs[:-unused_bits]
502 return cls.tag.asn1_object(fs), t
503 else:
504 raise BER_Decoding_Error(
505 "BERcodec_BIT_STRING found no content "
506 "(not even unused_bits byte)",
507 remaining=s
508 )
510 @classmethod
511 def enc(cls, _s, size_len=0, **_kwargs): # type: ignore[override]
512 # type: (AnyStr, Optional[int], **Any) -> bytes
513 # /!\ this is DER encoding (bit strings are only zero-bit padded)
514 s = bytes_encode(_s)
515 if len(s) % 8 == 0:
516 unused_bits = 0
517 else:
518 unused_bits = 8 - len(s) % 8
519 s += b"0" * unused_bits
520 s = b"".join(chb(int(b"".join(chb(y) for y in x), 2))
521 for x in zip(*[iter(s)] * 8))
522 s = chb(unused_bits) + s
523 return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s
526class BERcodec_STRING(BERcodec_Object[str]):
527 tag = ASN1_Class_UNIVERSAL.STRING
529 @classmethod
530 def enc(cls, _s, size_len=0, **_kwargs): # type: ignore[override]
531 # type: (Union[str, bytes], Optional[int], **Any) -> bytes
532 s = bytes_encode(_s)
533 # Be sure we are encoding bytes
534 return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s
536 @classmethod
537 def do_dec(cls,
538 s, # type: bytes
539 context=None, # type: Optional[Type[ASN1_Class]]
540 safe=False, # type: bool
541 _depth=0, # type: int
542 ):
543 # type: (...) -> Tuple[ASN1_Object[Any], bytes]
544 l, s, t = cls.check_type_check_len(s)
545 return cls.tag.asn1_object(s), t
548class BERcodec_NULL(BERcodec_INTEGER):
549 tag = ASN1_Class_UNIVERSAL.NULL
551 @classmethod
552 def enc(cls, i, size_len=0, **_kwargs): # type: ignore[override]
553 # type: (int, Optional[int], **Any) -> bytes
554 if i == 0:
555 return chb(int(cls.tag)) + b"\0"
556 else:
557 return super(cls, cls).enc(i, size_len=size_len)
560class BERcodec_OID(BERcodec_Object[bytes]):
561 tag = ASN1_Class_UNIVERSAL.OID
563 @classmethod
564 def enc(cls, _oid, size_len=0, **_kwargs): # type: ignore[override]
565 # type: (AnyStr, Optional[int], **Any) -> bytes
566 oid = bytes_encode(_oid)
567 if oid:
568 lst = [int(x) for x in oid.strip(b".").split(b".")]
569 else:
570 lst = list()
571 if len(lst) >= 2:
572 lst[1] += 40 * lst[0]
573 del lst[0]
574 s = b"".join(BER_num_enc(k) for k in lst)
575 return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s
577 @classmethod
578 def do_dec(cls,
579 s, # type: bytes
580 context=None, # type: Optional[Type[ASN1_Class]]
581 safe=False, # type: bool
582 _depth=0, # type: int
583 ):
584 # type: (...) -> Tuple[ASN1_Object[bytes], bytes]
585 l, s, t = cls.check_type_check_len(s)
586 lst = []
587 while s:
588 l, s = BER_num_dec(s)
589 lst.append(l)
590 if lst:
591 # X.690 sect 8.19.4
592 lst.insert(0, lst[0] // 40)
593 lst[1] %= 40
594 return (
595 cls.asn1_object(b".".join(str(k).encode('ascii') for k in lst)),
596 t,
597 )
600class BERcodec_ENUMERATED(BERcodec_INTEGER):
601 tag = ASN1_Class_UNIVERSAL.ENUMERATED
604class BERcodec_UTF8_STRING(BERcodec_STRING):
605 tag = ASN1_Class_UNIVERSAL.UTF8_STRING
608class BERcodec_NUMERIC_STRING(BERcodec_STRING):
609 tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING
612class BERcodec_PRINTABLE_STRING(BERcodec_STRING):
613 tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
616class BERcodec_T61_STRING(BERcodec_STRING):
617 tag = ASN1_Class_UNIVERSAL.T61_STRING
620class BERcodec_VIDEOTEX_STRING(BERcodec_STRING):
621 tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING
624class BERcodec_IA5_STRING(BERcodec_STRING):
625 tag = ASN1_Class_UNIVERSAL.IA5_STRING
628class BERcodec_GENERAL_STRING(BERcodec_STRING):
629 tag = ASN1_Class_UNIVERSAL.GENERAL_STRING
632class BERcodec_UTC_TIME(BERcodec_STRING):
633 tag = ASN1_Class_UNIVERSAL.UTC_TIME
636class BERcodec_GENERALIZED_TIME(BERcodec_STRING):
637 tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
640class BERcodec_ISO646_STRING(BERcodec_STRING):
641 tag = ASN1_Class_UNIVERSAL.ISO646_STRING
644class BERcodec_UNIVERSAL_STRING(BERcodec_STRING):
645 tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING
648class BERcodec_BMP_STRING(BERcodec_STRING):
649 tag = ASN1_Class_UNIVERSAL.BMP_STRING
652class BERcodec_SEQUENCE(BERcodec_Object[Union[bytes, List[BERcodec_Object[Any]]]]): # noqa: E501
653 tag = ASN1_Class_UNIVERSAL.SEQUENCE
655 @classmethod
656 def enc(cls, _ll, size_len=None, **_kwargs): # type: ignore[override]
657 # type: (Union[bytes, List[BERcodec_Object[Any]]], Optional[int], **Any) -> bytes # noqa: E501
658 if isinstance(_ll, bytes):
659 ll = _ll
660 else:
661 ll = b"".join(x.enc(cls.codec) for x in _ll)
662 # None = apply conf; explicit 0 keeps short-form lengths.
663 if size_len is None:
664 size_len = conf.ASN1_default_long_size
665 return chb(int(cls.tag)) + BER_len_enc(len(ll), size=size_len) + ll
667 @classmethod
668 def do_dec(cls,
669 s, # type: bytes
670 context=None, # type: Optional[Type[ASN1_Class]]
671 safe=False, # type: bool
672 _depth=0, # type: int
673 ):
674 # type: (...) -> Tuple[ASN1_Object[Union[bytes, List[Any]]], bytes]
675 if context is None:
676 context = cls.tag.context
677 if _depth > MAX_BER_DEPTH:
678 raise BER_Exception("Reached maximum BER recursion limit")
679 ll, st = cls.check_type_get_len(s) # we may have len(s) < ll
680 s, t = st[:ll], st[ll:]
681 obj = []
682 while s:
683 try:
684 o, remain = BERcodec_Object.dec(
685 s,
686 context=context,
687 safe=safe,
688 _depth=_depth + 1,
689 ) # type: Tuple[ASN1_Object[Any], bytes]
690 s = remain
691 except BER_Decoding_Error as err:
692 err.remaining += t
693 if err.decoded is not None:
694 obj.append(err.decoded)
695 err.decoded = obj
696 raise
697 obj.append(o)
698 if len(st) < ll:
699 raise BER_Decoding_Error("Not enough bytes to decode sequence",
700 decoded=obj)
701 return cls.asn1_object(obj), t
704class BERcodec_SET(BERcodec_SEQUENCE):
705 tag = ASN1_Class_UNIVERSAL.SET
708class BERcodec_IPADDRESS(BERcodec_STRING):
709 tag = ASN1_Class_UNIVERSAL.IPADDRESS
711 @classmethod
712 def enc(cls, ipaddr_ascii, size_len=0, **_kwargs): # type: ignore[override]
713 # type: (str, Optional[int], **Any) -> bytes
714 try:
715 s = inet_aton(ipaddr_ascii)
716 except Exception:
717 raise BER_Encoding_Error("IPv4 address could not be encoded")
718 return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s
720 @classmethod
721 def do_dec(cls,
722 s, # type: bytes
723 context=None, # type: Optional[Any]
724 safe=False, # type: bool
725 _depth=0, # type: int
726 ):
727 # type: (...) -> Tuple[ASN1_Object[str], bytes]
728 l, s, t = cls.check_type_check_len(s)
729 try:
730 ipaddr_ascii = inet_ntoa(s)
731 except Exception:
732 raise BER_Decoding_Error("IP address could not be decoded",
733 remaining=s)
734 return cls.asn1_object(ipaddr_ascii), t
737class BERcodec_COUNTER32(BERcodec_INTEGER):
738 tag = ASN1_Class_UNIVERSAL.COUNTER32
741class BERcodec_COUNTER64(BERcodec_INTEGER):
742 tag = ASN1_Class_UNIVERSAL.COUNTER64
745class BERcodec_GAUGE32(BERcodec_INTEGER):
746 tag = ASN1_Class_UNIVERSAL.GAUGE32
749class BERcodec_TIME_TICKS(BERcodec_INTEGER):
750 tag = ASN1_Class_UNIVERSAL.TIME_TICKS