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

387 statements  

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 

7 

8""" 

9Basic Encoding Rules (BER) for ASN.1 

10""" 

11 

12# Good read: https://luca.ntop.org/Teaching/Appunti/asn1.html 

13 

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) 

32 

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) 

46 

47################## 

48# BER encoding # 

49################## 

50 

51 

52# [ BER tools ] # 

53 

54MAX_BER_DEPTH = 32 

55 

56 

57class BER_Exception(Exception): 

58 pass 

59 

60 

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 

71 

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 

81 

82 

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 

93 

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 

103 

104 

105class BER_BadTag_Decoding_Error(BER_Decoding_Error, 

106 ASN1_BadTag_Decoding_Error): 

107 pass 

108 

109 

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 

128 

129 

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:] 

147 

148 

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) 

159 

160 

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:] 

179 

180 

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) 

206 

207 

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:] 

221 

222# The functions below provide implicit and explicit tagging support. 

223 

224 

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 

262 

263 

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 

274 

275# [ BER classes ] # 

276 

277 

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 

292 

293 

294_K = TypeVar('_K') 

295 

296 

297class BERcodec_Object(Generic[_K], metaclass=BERcodec_metaclass): 

298 codec = ASN1_Codecs.BER 

299 tag = ASN1_Class_UNIVERSAL.ANY 

300 

301 @classmethod 

302 def asn1_object(cls, val): 

303 # type: (_K) -> ASN1_Object[_K] 

304 return cls.tag.asn1_object(val) 

305 

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 ) 

314 

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 

326 

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) 

335 

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:] 

344 

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) 

373 

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"" 

401 

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) 

411 

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 !") 

424 

425 

426ASN1_Codecs.BER.register_stem(BERcodec_Object) 

427ASN1_Codecs.BER.register_tagging(BER_tagging_enc, BER_tagging_dec) 

428 

429 

430########################## 

431# BERcodec objects # 

432########################## 

433 

434class BERcodec_INTEGER(BERcodec_Object[int]): 

435 tag = ASN1_Class_UNIVERSAL.INTEGER 

436 

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) 

455 

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 

467 

468 

469class BERcodec_BOOLEAN(BERcodec_INTEGER): 

470 tag = ASN1_Class_UNIVERSAL.BOOLEAN 

471 

472 

473class BERcodec_BIT_STRING(BERcodec_Object[str]): 

474 tag = ASN1_Class_UNIVERSAL.BIT_STRING 

475 

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 ) 

503 

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 

518 

519 

520class BERcodec_STRING(BERcodec_Object[str]): 

521 tag = ASN1_Class_UNIVERSAL.STRING 

522 

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 

529 

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 

540 

541 

542class BERcodec_NULL(BERcodec_INTEGER): 

543 tag = ASN1_Class_UNIVERSAL.NULL 

544 

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) 

552 

553 

554class BERcodec_OID(BERcodec_Object[bytes]): 

555 tag = ASN1_Class_UNIVERSAL.OID 

556 

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 

570 

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 ) 

592 

593 

594class BERcodec_ENUMERATED(BERcodec_INTEGER): 

595 tag = ASN1_Class_UNIVERSAL.ENUMERATED 

596 

597 

598class BERcodec_UTF8_STRING(BERcodec_STRING): 

599 tag = ASN1_Class_UNIVERSAL.UTF8_STRING 

600 

601 

602class BERcodec_NUMERIC_STRING(BERcodec_STRING): 

603 tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING 

604 

605 

606class BERcodec_PRINTABLE_STRING(BERcodec_STRING): 

607 tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING 

608 

609 

610class BERcodec_T61_STRING(BERcodec_STRING): 

611 tag = ASN1_Class_UNIVERSAL.T61_STRING 

612 

613 

614class BERcodec_VIDEOTEX_STRING(BERcodec_STRING): 

615 tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING 

616 

617 

618class BERcodec_IA5_STRING(BERcodec_STRING): 

619 tag = ASN1_Class_UNIVERSAL.IA5_STRING 

620 

621 

622class BERcodec_GENERAL_STRING(BERcodec_STRING): 

623 tag = ASN1_Class_UNIVERSAL.GENERAL_STRING 

624 

625 

626class BERcodec_UTC_TIME(BERcodec_STRING): 

627 tag = ASN1_Class_UNIVERSAL.UTC_TIME 

628 

629 

630class BERcodec_GENERALIZED_TIME(BERcodec_STRING): 

631 tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME 

632 

633 

634class BERcodec_ISO646_STRING(BERcodec_STRING): 

635 tag = ASN1_Class_UNIVERSAL.ISO646_STRING 

636 

637 

638class BERcodec_UNIVERSAL_STRING(BERcodec_STRING): 

639 tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING 

640 

641 

642class BERcodec_BMP_STRING(BERcodec_STRING): 

643 tag = ASN1_Class_UNIVERSAL.BMP_STRING 

644 

645 

646class BERcodec_SEQUENCE(BERcodec_Object[Union[bytes, List[BERcodec_Object[Any]]]]): # noqa: E501 

647 tag = ASN1_Class_UNIVERSAL.SEQUENCE 

648 

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 

660 

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 

696 

697 

698class BERcodec_SET(BERcodec_SEQUENCE): 

699 tag = ASN1_Class_UNIVERSAL.SET 

700 

701 

702class BERcodec_IPADDRESS(BERcodec_STRING): 

703 tag = ASN1_Class_UNIVERSAL.IPADDRESS 

704 

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 

713 

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 

729 

730 

731class BERcodec_COUNTER32(BERcodec_INTEGER): 

732 tag = ASN1_Class_UNIVERSAL.COUNTER32 

733 

734 

735class BERcodec_COUNTER64(BERcodec_INTEGER): 

736 tag = ASN1_Class_UNIVERSAL.COUNTER64 

737 

738 

739class BERcodec_GAUGE32(BERcodec_INTEGER): 

740 tag = ASN1_Class_UNIVERSAL.GAUGE32 

741 

742 

743class BERcodec_TIME_TICKS(BERcodec_INTEGER): 

744 tag = ASN1_Class_UNIVERSAL.TIME_TICKS