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

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

473 

474 

475class BERcodec_BOOLEAN(BERcodec_INTEGER): 

476 tag = ASN1_Class_UNIVERSAL.BOOLEAN 

477 

478 

479class BERcodec_BIT_STRING(BERcodec_Object[str]): 

480 tag = ASN1_Class_UNIVERSAL.BIT_STRING 

481 

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 ) 

509 

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 

524 

525 

526class BERcodec_STRING(BERcodec_Object[str]): 

527 tag = ASN1_Class_UNIVERSAL.STRING 

528 

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 

535 

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 

546 

547 

548class BERcodec_NULL(BERcodec_INTEGER): 

549 tag = ASN1_Class_UNIVERSAL.NULL 

550 

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) 

558 

559 

560class BERcodec_OID(BERcodec_Object[bytes]): 

561 tag = ASN1_Class_UNIVERSAL.OID 

562 

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 

576 

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 ) 

598 

599 

600class BERcodec_ENUMERATED(BERcodec_INTEGER): 

601 tag = ASN1_Class_UNIVERSAL.ENUMERATED 

602 

603 

604class BERcodec_UTF8_STRING(BERcodec_STRING): 

605 tag = ASN1_Class_UNIVERSAL.UTF8_STRING 

606 

607 

608class BERcodec_NUMERIC_STRING(BERcodec_STRING): 

609 tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING 

610 

611 

612class BERcodec_PRINTABLE_STRING(BERcodec_STRING): 

613 tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING 

614 

615 

616class BERcodec_T61_STRING(BERcodec_STRING): 

617 tag = ASN1_Class_UNIVERSAL.T61_STRING 

618 

619 

620class BERcodec_VIDEOTEX_STRING(BERcodec_STRING): 

621 tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING 

622 

623 

624class BERcodec_IA5_STRING(BERcodec_STRING): 

625 tag = ASN1_Class_UNIVERSAL.IA5_STRING 

626 

627 

628class BERcodec_GENERAL_STRING(BERcodec_STRING): 

629 tag = ASN1_Class_UNIVERSAL.GENERAL_STRING 

630 

631 

632class BERcodec_UTC_TIME(BERcodec_STRING): 

633 tag = ASN1_Class_UNIVERSAL.UTC_TIME 

634 

635 

636class BERcodec_GENERALIZED_TIME(BERcodec_STRING): 

637 tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME 

638 

639 

640class BERcodec_ISO646_STRING(BERcodec_STRING): 

641 tag = ASN1_Class_UNIVERSAL.ISO646_STRING 

642 

643 

644class BERcodec_UNIVERSAL_STRING(BERcodec_STRING): 

645 tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING 

646 

647 

648class BERcodec_BMP_STRING(BERcodec_STRING): 

649 tag = ASN1_Class_UNIVERSAL.BMP_STRING 

650 

651 

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

653 tag = ASN1_Class_UNIVERSAL.SEQUENCE 

654 

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 

666 

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 

702 

703 

704class BERcodec_SET(BERcodec_SEQUENCE): 

705 tag = ASN1_Class_UNIVERSAL.SET 

706 

707 

708class BERcodec_IPADDRESS(BERcodec_STRING): 

709 tag = ASN1_Class_UNIVERSAL.IPADDRESS 

710 

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 

719 

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 

735 

736 

737class BERcodec_COUNTER32(BERcodec_INTEGER): 

738 tag = ASN1_Class_UNIVERSAL.COUNTER32 

739 

740 

741class BERcodec_COUNTER64(BERcodec_INTEGER): 

742 tag = ASN1_Class_UNIVERSAL.COUNTER64 

743 

744 

745class BERcodec_GAUGE32(BERcodec_INTEGER): 

746 tag = ASN1_Class_UNIVERSAL.GAUGE32 

747 

748 

749class BERcodec_TIME_TICKS(BERcodec_INTEGER): 

750 tag = ASN1_Class_UNIVERSAL.TIME_TICKS