Giter VIP home page Giter VIP logo

pycrate's Introduction

The repository has moved to https://github.com/pycrate-org/pycrate and is now archived.

What is pycrate

Pycrate is a french word for qualifying bad wine (when it's close to vinegar !). The present software library has nothing to do with wine (except it is developed in France), it is simply a Python library for manipulating various digital formats in an easy way, with a funny name. Most of the format supported are related in one way or another to cellular network's signalling. It is the glorious successor of libmich, which was started back in 2009, served well and retired in 2017.

It provides basically a runtime for encoding and decoding data structures, including CSN.1 and ASN.1. Additionally, it features a 3G and LTE mobile core network.

License

The whole library is licensed under LGPL v2.1 and is compatible with more recent version of the LGPL: all licensed files have an header making it self-explanatory. For more details, please report to the license.txt file.

Wiki

Pycrate has a growing wiki. Use it as much as possible before opening an issue. Feel free also to propose some additional content.

Installation

Operating systems and Python version

The library is designed to work with Python 3 (3.5 and greater), from the official Python implementation CPython, and is systematically tested both on Linux, MacOS and Windows. It should also support alternative Python engines such as pypy, nuitka or Cython ; this is however not regularly tested. It should also support any other operating systems which has a decent Python 3 support.

Python2 support is entirely abandonned end of 2022, and hence release 0.5.5 is the last one with full support of Python 2.7.

Dependencies

Currently none. Only the Python builtins and few internal modules of Python (e.g. os, system, re, struct, datetime) are required for most of the features. The json internal module is required for supporting the JSON API. If you want to run pycrate in Python2 (which is bad !), you will however need to install the enum34 package.

The pycrate_ether/SCTP module can optionally use the external crc32c module from ICRAR.

The pycrate_mobile/TS24301_EMM and pycrate_mobile/TS24501_FGMM modules use CryptoMobile as optional dependency to encrypt and decrypt LTE and 5G NAS messages.

The pycrate_corenet part requires also pysctp and CryptoMobile to run.

The pycrate_diameter/parse_iana_diameter_xml.py file uses lxml to translate xml files from IANA to Python dictionnaries ; this is however not required for standard runtime.

The pycrate_osmo/SEDebugMux.py module relies on the crcmod to compute custom CRC in the frame format.

Automatic installation

An installation script is available. As soon as you have cloned or downloaded the repository, you can use it to install the library within your Python package directory:

python setup.py install

Run it as superuser for a system-wide install, or as-is for a user home-directory level install. You can also run develop instead of install if you want a developer-friendly installation.

It is also possible to test the library before installing it (this will create two local directories ./test_asn/ and ./pycrate.egg-info/ that you can just delete afterwards):

python -m unittest test.test_pycrate

Or to build the library without installing it in the system:

python setup.py build

It is also possible to recompile all ASN.1 modules, this will take few minutes (but if I did not do any mistake, all ASN.1 modules provided in ./pycrate_asn1dir/ should have been compiled with the latest version of the compiler):

python -m pycrate_asn1c.asnproc

More generally, installation is not required, and simply having all pycrate_* subdirectories into the PYTHONPATH enables to use the entire library.

Installation with pip

Alternatively, you can install the library with the pip command:

pip install pycrate

The install package is available on pypi. It contains the library from the last tagged release on github (which may be months old).

Contributing

Contact and support

This library is free software, and you are free to use it (or not to use it). In case you encounter a problem with it, first read this README completely and then check the Wiki ; moreover many classes, methods and functions are documented with docstrings, and finally you can have a look at the source code (it won't bite you).

If after all those steps, you still have a question or you think you found a bug, please open an issue (see below). Specific support requires time and may not be always possible. In case you require such support, please consider also contributing in one way or another (see below, too).

In case you are using this library in any of your project and you find it useful, do not hesitate to send me an email. It is always a pleasure to know where code provided on the Internet can end up... (I am personally aware of some dark places where a pycrate's fork lies).

Filling an issue

When filling an issue, please provide precise and contextual information about your case and the error you potentially encounter:

  • indicate the version (or commit-level) of pycrate you are using, together with the version of Python.
  • provide a code snippet that leads to the error you are facing, so that it can be reproduced.
  • provide the eventual stacktrace you are getting from Python
  • provide additional and contextual information as needed (e.g. a specific ASN.1 specification being used...)

This is the bare minimum if you want to get help. And when you consider your issue has been addressed, please close it: "A good issue is a closed one !" as would have said my great grandmother.

Extending the library

If you are willing to extend the library, do not hesitate to contact me by email or preferably through the github service (ideally, open a pull request). For important changes, please elaborate about your need and provide some justification. Any patch or submission is always very welcome!

Other contributions

In case you do not want to deep dive in the code, you can still contribute in many ways:

  • highlighting specific issues in the inner-working of the library, and opening an issue with concrete debugging information
  • writing new test cases for more coverage (have a look at the test/ directory)
  • sending captures / real-world data that can be used for writing new test cases
  • writing new parts of the wiki (have a look at the pycrate wiki)

Getting contributions is extremely important to encourage the continuous development of the library, and to confirm the choice made to open-source it.

Components

Pycrate is actually more a software suite than a single library. It is composed of several subdirectories, each providing specific services.

pycrate_core

The core of the library.

  • utils provides basics functions to manipulate integers, bytes and bits
  • charpy provides the Charpy class to handle easily the consumption of a bit-stream
  • elt and base are providing several classes to help when building complex data structures
  • repr provides simple functions to help with the representation of instances from the elt and base modules

Some of the most useful features are provided by the pack_val() functions from the utils module and the Charpy class from the charpy module. They help to deal easily with packing and unpacking bytes and integers (signed / unsigned, little / big endian) in an aligned and unaligned way. All lengths of fields are provided in bits, hence facilitating the handling of unaligned structures.

pycrate_ether

The modules provided here implement Ethernet and IP-oriented protocols and formats.

  • MPLS with structures for MPLS label and header
  • Ethernet with structures for Ethernet and VLAN headers
  • ARP simply providing the structure for ARP
  • IP with structures for IPv4, IPv6, ICMP, UDP and TCP
  • SCTP with structures for SCTP headers and various chunks
  • PCAP with structures for the PCAP global header and the record header

pycrate_media

The modules here implement various multimedia formats.

  • JPEG with detailed structures used in the JPEG format
  • GIF with detailed structures used in the GIF format
  • TIFF with detailed structures used in the TIFF format
  • BMP with structures used in the BMP format
  • PNG with the basic structure used in the PNG format
  • MPEG4 with the basic structure used in the MPEG4 file format
  • MP3 with detailed structures used in the MP3 format, including ID3v1 and ID3v2 tags

Most of the classes here implement a complete recipe to parse all of those format in a single shot, by using their from_char() method.

pycrate_asn1c

All the modules here serve the sole purpose of compiling ASN.1 specifications. The most important ones are:

  • asnobj which is the almighty class when parsing any ASN.1 definition
  • generator which provides two distinct generators to produce source files from the ASN.1 objects processed in Python: PycrateGenerator which produces source file to be used with the pycrate ASN.1 runtime (in pycrate_asn1rt), and JSONDepGraphGenerator which produces json file listing object dependencies (which then can be browsed dynamically thanks to D3).
  • asnproc which is the top-level module for the compiler, it contains for example the compile_text() function which compiles a serie of ASN.1 modules into Python objects

This compiler support most of the ASN.1 language features, including parameterization and class objects and sets (especially useful when working with table constraints). It has however few restrictions, the biggest being the need for the left part of the ASN.1 assignment ::= being on a single line. Also, old-school ASN.1 macros are not supported ; hence, the compiler cannot parse SNMP MIBs.

pycrate_asn1dir

This subdirectory contains several ASN.1 specifications that are supported and precompiled for pycrate. Very few specifications have been changed in order to work with pycrate :

  • Q.775, in which the terrible AllPackagesAS is commented out
  • Q.773 and Q.775, in which the TCInvokeIdSet constraint is modified to be used as a set of values That's all !

pycrate_asn1rt

This subdirectory contains the ASN.1 runtime, that is loaded and used by the ASN.1 specifications compiled with the compiler in pycrate_asn1c. It supports the PER encoding rules (aligned and not, canonical also), and the BER, CER, DER and JER encoding rules.

pycrate_csn1

This subdirectory contains a CSN.1 to Python translater in the file trans.py, and a CSN.1 runtime in the file csnobj.py, in order to encode and decode CSN.1 structures translated to Python objects.

pycrate_csn1dir

This subdirectory contains CSN.1 structures extracted from 3GPP specifications (in the .csn files), and translated into Python objects. The following specifications have been used: TS 44.018, TS 44.060 and TS 24.008.

pycrate_mobile

This subdirectory implements most of the 3GPP NAS protocol formats:

  • GSMTAP: gsmtap header format
  • MCC_MNC: dictionnaries for MCC and MNC look-up
  • NAS: provides two functions to parse any uplink and downlink mobile NAS messages
  • NASLTE: provides two functions to parse LTE uplink and downlink NAS messages
  • NAS5G: provides one function to parse 5G uplink and downlink mobile NAS messages
  • PPP: structures for NCP and LCP protocols used for PPP connection estabishment, as defined in RFC 1661, 1332 and 1334
  • SCCP: structures for SCCP user-data and management messages as defined in ITU-T Q.713
  • ISUP: structures for ISUP messages as defined in ITU-T Q.763
  • SIGTRAN: generic structures for SIGTRAN (i.e. M2UA, M2PA, MTP3 and M3UA) messages
  • M3UA: structures dedicated to the M3UA format from RFC 4666
  • TS102225: structures for SIM card's Secured Packets from ETSI TS 102.225
  • TS23038: structures and routines for SMS encoding from TS 23.038
  • TS23040_SMS: structures for the SMS transport protocol from TS 23.040
  • TS23041_CBS: structures for the Cell Broadcast Service protocol from TS 23.041
  • TS24007: basic structures from the TS 24.007 specification, reused in most of the NAS protocols
  • TS24008_CC : structures for call control messages from TS 24.008
  • TS24008_GMM: structures for GPRS mobility management messages from TS 24.008
  • TS24008_IE: structures for many information elements from TS 24.008
  • TS24008_MM: structures for mobility management messages from TS 24.008
  • TS24008_SM: structures for GPRS session management messages from TS 24.008
  • TS24011_PPSMS: structures for the SMS point-to-point protocol from TS 24.011
  • TS24080_SS: structures for the Supplementary Services protocol from TS 24.080, wrapping some MAP ASN.1 objects
  • TS24301_EMM: structures for the EPS mobility management messages from TS 24.301
  • TS24301_ESM: structures for the EPS session management messages from TS 24.301
  • TS24301_IE: structures for many information elements from TS 24.301
  • TS24501_FGMM: structures for the 5G mobility management messages from TS 24.501
  • TS24501_FGSM: structures for the 5G session management messages from TS 24.501
  • TS24501_IE: structures for many information elements from TS 24.501
  • TS24501_UEPOL, TS24526_UEPOL and TS24588_UEPOL: structures for the 5G UE policy protocol from TS 24.501, 526 and 588
  • TS29002_MAPAppCtx: functions that relies on the Pycrate_TCAP_MAPv2v3 ASN.1 module, dealing mostly with MAP application-contexts
  • TS29002_MAPIE: structure for the MAP AddressString object from TS 29.002
  • TS29244_PFCP: structure for PFCP messages from TS 29.244
  • TS0960_GTPv0: structures for 2G GTP version 0 from TS 09.60
  • TS29060_GTP: structures for 2G/3G GTP-C version 1 from TS 29.060
  • TS29274_GTPC: structures for 4G GTP-C version 2 from TS 29.274
  • TS29281_GTPU: structures for 2G/3G/4G/5G GTP-U from TS 29.281
  • TS31111_SAT: basic structures and dict for the SIM application toolkit from TS 31.111
  • TS31115: structures for SIM card's Secured Packets over SMS from TS 31.115
  • TS38415_PDUSess: structure used in 5G user-place traffic (i.e. GTP-U) from TS 38.415
  • TS44018_GTTP: structure for the single GSM GTTP message from TS 44.018
  • TS44018_IE: structures for many information elements from TS 44.018
  • TS44018_RR: structures for the GSM and GPRS radio ressources messages from TS 44.018
  • TS48058_Abis: few IE structures for the GSM Abis protocol from TS 48.058

pycrate_diameter

This subdirectory contains the following modules:

  • parse_iana_diameter_xml: to translate XML Diameter structures from IANA to Python
  • iana_diameter_dicts.py: that is automatically created by the former, containing Diameter Python dicts
  • Diameter: a generic Diameter module which implements DiameterGeneric and AVPGeneric structures
  • DiameterIETF: a Diameter module which relies on AVP types provided in all IETF RFC
  • Diameter3GPP: a Diameter module which relies on AVP types provided in all 3GPP TS

pycrate_osmo

This subdirectory contains the following modules:

  • L1CTL: structures to control the osmocom-bb GSM embedded stack from the host
  • SEDebugMux: structure used by Sony-Ericsson SoC and basebands to wrap logs
  • RRCTL: structures to interact with the RRC layer of the UE emulator from this fork of srs-lte

pycrate_corenet

This subdirectory implements a signaling server that supports IuCS and IuPS over Iuh interfaces (including HNBAP and RUA/RANAP) for interfacing with 3G femtocells, and S1 interfaces (including S1AP) for interfacing with LTE eNodeBs. It handles many procedures to drive femtocells, eNodeBs and mobile terminals connecting through them. In terms of services, it mostly support short messages and data connectivity. It does not handle call services, neither active mobility procedures (handovers).

It can be easily (common, running a mobile core network is not that easy) configured and used thanks to the corenet project, also open-source.

pycrate_gmr1

This subdirectory contains the main module for the GMR-1 Radio Resources protocol: TS101376_04_08, and the submodule for specific Information Elements: TS101376_04_08_IE. This is a partial implementation of the ETSI specification TS 101 376-04-08 for the GEO-Mobile Radio Interface Specifications (Release 3).

pycrate_gmr1_csn1

This subdirectory contains all the CSN.1 definitions for the GMR-1 Radio Resources protocol, extracted from the 3 ETSI specifications for GEO-Mobile Radio release 3: TS 101 376-04-08, TS 101 376-04-12 and 101 376-04-13.

Usage

Most of the modules have doc strings. I try also to write readable sources and to comment them as much as possible for understanding them easily (and to allow also myself to understand my own code years after...). A wiki is provided and extended from time to time, to bring examples and methods on how to use the different modules (any contribution on this would be very welcome, too). Finally, the code provided in the test/ subdirectory is also representative on how to use the different modules.

Basically, a pycrate's object exposes the following methods:

  • set_val() / get_val() / get_val_d(), which sets value into and gets value from the object
  • from_bytes() / to_bytes(), which converts a buffer into values according to the internal structure of the object, and back
  • from_json() / to_json(), for working with JSON-encoded values
  • hex() / bin(), for getting hexadecimal and binary representation of the serialized obect's value
  • repr() / show(), for providing nice python's internal representation, and printable representation of the object's value

ASN.1 usage

When a Python module from pycrate_asn1dir/ is loaded, it creates Python classes corresponding to ASN.1 modules (all dash characters are converted to underscore). Each ASN.1 object has a corresponding Python instance, exposing the following methods:

  • from_asn1() / to_asn1(), which converts ASN.1 textual value to Python value and back
  • from_aper() / to_aper(), which converts aligned PER encoded value to Python value and back
  • from_uper() / to_uper(), which converts unaligned PER
  • from_ber() / to_ber(), which converts BER
  • from_cer() / to_cer(), which converts CER
  • from_der() / to_der(), which converts DER
  • from_jer() / to_jer(), which converts JER
  • from_oer() / to_oer(), which converts OER
  • from_coer() / to_coer(), which converts canonical OER
  • set_val() / get_val() to set and get Python's values into the ASN.1 object
  • get_proto() to return to internal structure of the ASN.1 object

All the methods useful for working with ASN.1 objects at runtime can be found in the file pycrate_asn1rt/asnobj.py.

Tools

Four different tools are provided (yet):

  • pycrate_showmedia.py parses some media files (jpg, bmp, gif, mp3, png, tiff, mpeg4) and pretty print the file structure on the standard output.
  • pycrate_asn1compile.py compiles ASN.1 source file(s) and produce a Python source file that makes use of the ASN.1 runtime. This source file is then usable to encode / decode any ASN.1 object from the compiled ASN.1 specification.
  • pycrate_berdecode.py parses any BER/CER/DER encoded binary value of ASN.1 objects and prints the corresponding structure.
  • pycrate_map_op_info.py prints prototypes and various information related to TCAP-MAP (Mobile Application Part) and CAMEL operations and application-contexts.
  • pycrate_gtp_type_info.py prints prototypes and various information related to GTP messages and transactions as in version 0, 1 or 2

Examples

It is possible to test the pycrate_showmedia.py tool with media test files provided in ./test/res/, or any other supported media file.

$ ./tools/pycrate_showmedia.py --help
usage: pycrate_showmedia.py [-h] [-bl BL] [-wt] input

print the internal structure of the input media file,supported formats are:
BMP, GIF, JPEG, MP3, MPEG4, PNG, TIFF

positional arguments:
  input       input media file

optional arguments:
  -h, --help  show this help message and exit
  -bl BL      maximum length for buffer representation
  -wt         show also absent / transparent fields

$ ./tools/pycrate_showmedia.py ./test/res/xkcd_wireless_signal.png 
### PNG ###
 <sig [PNG signature] : '\x89PNG\r\n\x1a\n'>
     ### PNGBody ###
      ### PNGChunk ###
       <len : 13>
       <type : 'IHDR'>
       ### IHDR ###
        <width : 238>
        <height : 415>
        <depth [bit depth] : 8>
        <color [color type] : 0 (Greyscale)>
        <comp [compression method] : 0 (inflate/deflate with sliding window)>
        <filter [filter method] : 0 (no interlace)>
        <interlace [interlace method] : 0 (no interlace)>
       <crc : 0x7d8cb12e>
      ### PNGChunk ###
       <len : 9>
       <type : 'pHYs'>
       <data :
        00 00 0c 4e 00 00 0c 4e 01                      | '\x00\x00\x0cN\x00\x00\x0cN\x01'>
       <crc : 0x7f778c23>
      ### PNGChunk ###
       <len : 792>
       <type : 'iCCP'>
       <data :
        50 68 6f 74 6f 73 68 6f 70 20 49 43 43 20 70 72 | 'Photoshop ICC pr'
        6f 66 69 6c 65 00 00 78 da 63 60 60 9e e0 e8 e2 | 'ofile\x00\x00x\xdac``\x9e\xe0\xe8\xe2'
        [...]
        32 fd fc ea eb 82 ef e1 3f 05 7e 9d fa d3 fa cf | '2\xfd\xfc\xea\xeb\x82\xef\xe1?\x05~\x9d\xfa\xd3\xfa\xcf'
        f1 ff 7f 00 0d 00 0f 34                         | '\xf1\xff\x7f\x00\r\x00\x0f4'>
       <crc : 0xfa96f15d>
      ### PNGChunk ###
       <len : 32>
       <type : 'cHRM'>
       <data :
        00 00 6e 27 00 00 73 af 00 00 df f2 00 00 83 30 | "\x00\x00n'\x00\x00s\xaf\x00\x00\xdf\xf2\x00\x00\x830"
        00 00 77 43 00 00 c8 0a 00 00 34 95 00 00 2e dc | '\x00\x00wC\x00\x00\xc8\n\x00\x004\x95\x00\x00.\xdc'>
       <crc : 0x20bf171a>
      ### PNGChunk ###
       <len : 21130>
       <type : 'IDAT'>
       <data :
        78 da ed bd 79 50 8d fd 1f ff ff bc ce 39 73 4e | 'x\xda\xed\xbdyP\x8d\xfd\x1f\xff\xff\xbc\xce9sN'
        db b4 37 95 32 b4 19 94 06 2d 7e 11 26 b2 fc 10 | '\xdb\xb47\x952\xb4\x19\x94\x06-~\x11&\xb2\xfc\x10'
        [...]
        91 a3 d8 5b fc e1 cb 51 fd ab fb c9 cc ec ee 21 | '\x91\xa3\xd8[\xfc\xe1\xcbQ\xfd\xab\xfb\xc9\xcc\xec\xee!'
        7d 70 6e f3 18 ce c1 c1 6d 8c 81 44 32 cf 51 ba | '}pn\xf3\x18\xce\xc1\xc1m\x8c\x81D2\xcfQ\xba'
        ...>
       <crc : 0xa9fbdd38>
      ### PNGChunk ###
       <len : 0>
       <type : 'IEND'>
       <data : >
       <crc : 0xae426082>

It is possible to test the pycrate_asn1compile.py tool with some test ASN.1 specification from ./test/res/, or any other valid ASN.1 specification of your choice.

$ ./tools/pycrate_asn1compile.py --help
usage: pycrate_asn1compile.py [-h] [-s SPEC] [-i INPUT [INPUT ...]] [-o OUTPUT] [-g GENERATOR_PATH] [-j] [-fautotags] [-fextimpl] [-fverifwarn]

compile ASN.1 input file(s) for the pycrate ASN.1 runtime

optional arguments:
  -h, --help            show this help message and exit
  -s SPEC               provide a specification shortname, instead of ASN.1 input file(s)
  -i INPUT [INPUT ...]  ASN.1 input file(s) or directory
  -o OUTPUT             compiled output Python (and json) source file(s)
  -g GENERATOR_PATH, --generator GENERATOR_PATH
                        provide an alternative python generator file path
  -j                    output a json file with information on ASN.1 objects dependency
  -fautotags            force AUTOMATIC TAGS for all ASN.1 modules
  -fextimpl             force EXTENSIBILITY IMPLIED for all ASN.1 modules
  -fverifwarn           force warning instead of raising during the verification stage

$ ./tools/pycrate_asn1compile.py -i ./test/res/Hardcore.asn -o Hardcore
[proc] [./test/res/Hardcore.asn] module HardcoreSyntax (oid: []): 116 ASN.1 assignments found
--- compilation cycle ---
--- compilation cycle ---
--- compilation cycle ---
--- verifications ---
[proc] ASN.1 modules processed: ['HardcoreSyntax']
[proc] ASN.1 objects compiled: 75 types, 3 sets, 37 values
[proc] done

After compiling a module, it is possible to load it in Python and use it for encoding / decoding any objects defined in it.

Python 3.8.5 (default, Jul 28 2020, 12:59:40) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from Hardcore import HardcoreSyntax
>>> HardcoreSyntax # this is the only ASN.1 module provided in Hardcore.asn
<class 'Hardcore.HardcoreSyntax'>
>>> Final = HardcoreSyntax.Final # this is the Final object defined at line 115
>>> Final
<Final (SEQUENCE)>
>>> Final.get_proto() # warning: this can return very laaaaaaarge definitions
('SEQUENCE', {
w1: ('SEQUENCE', {
 r10: ('SEQUENCE', {
  low: 'INTEGER',
  high: 'INTEGER',
  bool: 'BOOLEAN',
  null (OPT): 'NULL'
  }),
 r90: ('SEQUENCE', {
  low: 'INTEGER',
  high: 'INTEGER',
  bool: 'BOOLEAN',
  null (OPT): 'NULL'
  })
 }),
w2: ('SEQUENCE', {
 r10: ('SEQUENCE', {
  low: 'INTEGER',
  high: 'INTEGER',
  bool: 'BOOLEAN',
  null (OPT): 'NULL'
  }),
 r90: ('SEQUENCE', {
  low: 'INTEGER',
  high: 'INTEGER',
  bool: 'BOOLEAN',
  null (OPT): 'NULL'
  })
 }),
bool: 'BOOLEAN'
})
>>> V = {
... 'w1':{'r10':{'low':5, 'high':50, 'bool':False}, 'r90':{'low':50, 'high':95, 'bool':False, 'null':0}},
... 'w2':{'r10':{'low':1, 'high':10, 'bool':False}, 'r90':{'low':90, 'high':100, 'bool':True}},
... 'bool': True}
>>> Final.set_val(V)
>>> print(Final.to_asn1()) # .to_asn1() returns a printable ASN.1 representation of the value
{
  w1 {
    r10 {
      low 5,
      high 50,
      bool FALSE
    },
    r90 {
      low 50,
      high 95,
      bool FALSE,
      null NULL
    }
  },
  w2 {
    r10 {
      low 1,
      high 10,
      bool FALSE
    },
    r90 {
      low 90,
      high 100,
      bool TRUE
    }
  },
  bool TRUE
}
>>> Final.to_aper() # aligned PER
b'*\x85\x92\x80@\x01\x00\x08\x02\xd5`'
>>> Final.to_uper() # unaligned PER
b'*\x85\x92\x80@@\x02\x00\xb5X'
>>> Final.to_ber()
b'05\xa0\x18\xa0\t\x80\x01\x05\x81\x012\x82\x01\x00\xa1\x0b\x80\x012\x81\x01_\x82\x01\x00\x83\x00\xa1\x16\xa0\t\x80\x01\x01\x81\x01\n\x82\x01\x00\xa1\t\x80\x01Z\x81\x01d\x82\x01\xff\x82\x01\xff'
>>> Final.to_cer()
b'0\x80\xa0\x80\xa0\x80\x80\x01\x05\x81\x012\x82\x01\x00\x00\x00\xa1\x80\x80\x012\x81\x01_\x82\x01\x00\x83\x00\x00\x00\x00\x00\xa1\x80\xa0\x80\x80\x01\x01\x81\x01\n\x82\x01\x00\x00\x00\xa1\x80\x80\x01Z\x81\x01d\x82\x01\xff\x00\x00\x00\x00\x82\x01\xff\x00\x00'
>>> Final.to_der()
b'05\xa0\x18\xa0\t\x80\x01\x05\x81\x012\x82\x01\x00\xa1\x0b\x80\x012\x81\x01_\x82\x01\x00\x83\x00\xa1\x16\xa0\t\x80\x01\x01\x81\x01\n\x82\x01\x00\xa1\t\x80\x01Z\x81\x01d\x82\x01\xff\x82\x01\xff'
>>> Final.from_ber( Final.to_ber() )
>>> Final() == V # or Final._val == V
True

For more information about the API exposed for each ASN.1 object, you can check the docstrings of all ASN.1 objects, and also read the source file pycrate_asn1rt/asnobj.py. Do not forget to have a look at the Wiki, too!

pycrate's People

Contributors

arieltm avatar axilirator avatar ayrdim avatar benmaddison avatar fixeria avatar h21lab avatar jewalt avatar jnevrly avatar kenwhitesell avatar l-we avatar mathlag35 avatar mitshell avatar mlg35 avatar p1-bmu avatar p1-olm avatar p1-ra avatar ursine avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pycrate's Issues

[Inconsistancy between encoding and decoding] TCAP_MAP.MAP_MS_DataTypes.CheckIMEI_Arg

Hello,

I dont know if I use encoding or decoding ASN1 object the right way.
I would like to encode and decode fields from CheckIMEI_Arg

  • imei
  • requestedEquipmentInfo

In below, you will find the script to reproduce the test case.
Test case for decoding:

from pycrate_asn1dir import TCAP_MAP
import binascii

test = TCAP_MAP.MAP_MS_DataTypes.CheckIMEI_Arg

pdu = "300e0408010000000000060003020780000000"
test.from_ber(binascii.unhexlify(pdu))

Output:
pycrate_asn1rt.err.ASN1ObjErr: CheckIMEI-Arg.requestedEquipmentInfo: value out of size constraint, (1, 1)
The value of requestedEquipmentInfo is (1, 1)
But the constraint size range between 2 and 8 for the bits length (second item of the tuple).

Test case for encoding:

test_1 = TCAP_MAP.MAP_MS_DataTypes.CheckIMEI_Arg
context={u'imei': '\x01\x00\x00\x00\x00\x00\x06\x00', u'requestedEquipmentInfo': (1, 1)}
test_1.set_val(context)

Output:
pycrate_asn1rt.err.ASN1ObjErr: CheckIMEI-Arg.requestedEquipmentInfo: value out of size constraint, (1, 1)

According to documentation:
for BIT STR object, the way to use set_val() method (in pycrate_asn1rt/asnobj_str.py) is to used set of str (from the object's NamedBitList)

test_3 = TCAP_MAP.MAP_MS_DataTypes.CheckIMEI_Arg
context={u'imei': '\x01\x00\x00\x00\x00\x00\x06\x00', u'requestedEquipmentInfo': set([u'equipmentStatus'])}
test_3.set_val(context)

Traceback (most recent call last):
File "", line 1, in
File "pycrate_asn1rt/asnobj.py", line 607, in set_val
self._safechk_val(self._val)
File "pycrate_asn1rt/asnobj_construct.py", line 566, in _safechk_val
self._cont[k]._safechk_val(val[k])
File "pycrate_asn1rt/asnobj_str.py", line 124, in _safechk_val
raise(ASN1ObjErr('{0}: invalid value, {1!r}'.format(self.fullname(), val)))
pycrate_asn1rt.err.ASN1ObjErr: CheckIMEI-Arg.requestedEquipmentInfo: invalid value, set([u'equipmentStatus'])

How could I suppose to decode this hexadecimal pdu "300e0408010000000000060003020780000000" ?

And what is the way to encode the BIT STRING object ? with tuple object or set of str object ? which is the size contraint to set 2..8 bits ?

I think it has a problem concerning the contraint size interpretation in ASN1 doc:
RequestedEquipmentInfo::= BIT STRING {
equipmentStatus (0),
bmuef (1)} (SIZE (2..8))

Thank you.

"Raw" values output with JER encoding

Hi,

I have not yet figured out to do this myself, so any suggestions would be appreciated:

Currently, the JER encoder "pretty prints" some basic values, e.g. "unavailable" in the following example from J2735:

   "brakes": {
    "abs": "unavailable",
    "auxBrakes": "unavailable",
    "brakeBoost": "unavailable",
    "scs": "unavailable",
    "traction": "unavailable",
    "wheelBrakes": "80"
   },

Is there a way to have the "raw" value (not sure that is the correct term) printed instead, like in the following?

         "brakes":{
            "wheelBrakes":"10000",
            "traction":0,
            "abs":0,
            "scs":0,
            "brakeBoost":0,
            "auxBrakes":0
         },

E.g. in the above example print the integer value of the ENUMs (0 instead of "unavailable") and the binary representation of the BIT STRING ("10000" instead of "80").

Thanks!

GTP Protocol

Can I encode and decode GTP and UDP protocol packets?
Please help!

Decoding into a local rather than a global object

I've poked around a bit and read the documentation, and had a question regarding best-practice usage.
The documentation's example for decoding a buffer into an ASN.1 object decodes the buffer into a global instance of a constructed type. This is a global that is mutated for the entire application. Is there a correct/documented way wherein I could decode my data into a private, local instance of the desired type, rather than mutating global state? A simple attempt involving copy.deepcopy seemed to work, but I don't know if that's a good idea or not. The clone method I saw for some types in the repository isn't present on the compiled types.

spec_files is undefined

Hi,

Recompiling the asn1 specifications with
python -m pycrate_asn1c.proc
generates an error , as spec_files is not defined anymore in pycrate_asn1c/proc.py

This change is from commit faf9c2d.

Wrong encoding/decoding (aper) octet strings bigger than 16384 (2^14) bytes

Hi,

I discovered problem with encoding OCTET STRING with PER ALIGNED.

When I want to encode OCTET STRING with size >= 16384 bytes, pycrate returns different output than encoder available here: http://asn1-playground.oss.com/.

Here is a simple project that shows the issue:
https://github.com/ksiazak/pycrate_test_big_octet_string

Files:

  • encoded_16384_len_payload.per - encoded with "ASN1 Playground" encoder OCTET STRING with content: 16384 * '\x05'
  • scheme.asn1 - simple scheme containing OCTET STRING
  • asn1_codecs.py - codecs generated with pycrate_asn1compile.py
  • main.py - simple script that shows that data generated with pycrate and ASN1 Playground are different and pycrate cannot decode payload encoded by ASN1 Playground

For both pycrate and ASN1 Playground encoded data length is 16386 bytes but the first byte differs.
For pycrate it is \xc0 and for ASN1 Playground it is \xc1.

ASN1 Playground usage:
asn1_playground_encoding

Exceptions in from_ber decoding

Hi,
by running the script test_tcapmap.py the following exceptions has been raised.
Maybe it is ok, but these exceptions does not seem to be ASN1Err exceptions. I do not include the input payload because these errors can be reproduced by running the script.

Thank you for your opinion on this

# decode using pycrate
tcap = TCAP_MAP.TCAP_MAP_Messages.TCAP_MAP_Message
tcap.from_ber(binascii.unhexlify(tcap_hex))

Exceptions:

bitlen overflow: 1600, max 32
Traceback (most recent call last):
  File "test_tcapmap.py", line 89, in <module>
    tcap.from_ber(binascii.unhexlify(tcap_hex))
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj.py", line 856, in from_ber
    self._from_ber(char, TLV)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj.py", line 842, in _from_ber
    self._decode_ber_cont(char, tlv)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj_construct.py", line 506, in _decode_ber_cont
    Cho._from_ber(char, [tlv])
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj.py", line 842, in _from_ber
    self._decode_ber_cont(char, tlv)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj_construct.py", line 1397, in _decode_ber_cont
    Comp._from_ber(char, [tlv[ind]])
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj.py", line 842, in _from_ber
    self._decode_ber_cont(char, tlv)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj_construct.py", line 1397, in _decode_ber_cont
    Comp._from_ber(char, [tlv[ind]])
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj.py", line 842, in _from_ber
    self._decode_ber_cont(char, tlv)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj_construct.py", line 506, in _decode_ber_cont
    Cho._from_ber(char, [tlv])
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj.py", line 842, in _from_ber
    self._decode_ber_cont(char, tlv)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj_ext.py", line 441, in _decode_ber_cont
    self._val = ASN1CodecBER.scan_tlv_ws(char, tlv)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1570, in scan_tlv_ws
    return char.get_bytes(8*lval)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_core/charpy.py", line 376, in get_bytes
    .format(bitlen, self._len_bit-self._cur)))
CharpyErr: bitlen overflow: 1600, max 32
bytes buffer not long enough
Traceback (most recent call last):
  File "test_tcapmap.py", line 89, in <module>
    tcap.from_ber(binascii.unhexlify(tcap_hex))
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/asnobj.py", line 851, in from_ber
    TLV = [ASN1CodecBER.decode_single(char)[0]]
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1535, in decode_single
    V = cla.decode_all(char, lundef=False)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1557, in decode_all
    TLV, EOS = cla.decode_single(char, lundef)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1535, in decode_single
    V = cla.decode_all(char, lundef=False)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1557, in decode_all
    TLV, EOS = cla.decode_single(char, lundef)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1535, in decode_single
    V = cla.decode_all(char, lundef=False)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1557, in decode_all
    TLV, EOS = cla.decode_single(char, lundef)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1535, in decode_single
    V = cla.decode_all(char, lundef=False)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1557, in decode_all
    TLV, EOS = cla.decode_single(char, lundef)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1522, in decode_single
    cl, pc, tval = cla.decode_tag(char)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_asn1rt/codecs.py", line 1337, in decode_tag
    cl = char.get_uint(2)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_core/charpy.py", line 783, in get_uint
    return bytes_to_uint(self._buf[off_byte:1+off_byte+(bitlen>>3)], bitlen)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.2-py2.7.egg/pycrate_core/utils_py2.py", line 1301, in bytes_to_uint
    raise(PycrateErr('bytes buffer not long enough'))
PycrateErr: bytes buffer not long enough

[ESM] ActDefaultEPSBearerCtxtRequest

Hi!
I'm trying to create this ESM message as follows:
ESMActDefaultEPSBearerCtxtRequest(val={ 'EPSBearerId': 20, 'PTI': 1, 'APN': { 'L': 9, 'V': hexlify('name') } })

And i'm getting EltErr: APN [set_val] vals keys are not all integers even if I try to put both APN values as integers. Which is the correct way to fill the APN values?

Thanks a lot for your help.

RecursionError during decoding of Huawei cdr file

I am trying to decode a Huawei cdr file using this asn1 definition of it, which has been compiled into a python module named asn1_obj_pycrate using the command line pycrate_asn1compile.py. My code is as follows to decode "my_cdr_file":
from asn1_obj_pycrate import CS_R99_R4_CHARGING from binascii import hexlify, unhexlify with open(my_cdr_file, 'rb') as fin: encoded_ber = hexlify(fin.read()) ce_data_file.from_ber(encoded_ber)
This code results in RecursionError: maximum recursion depth exceeded in comparison.
My goal is to extract the data in the cdr file into csv or xml.
Will appreciate some pointers on how to get this right.
Thanks.

[pycrate_asn1rt] The "_CONSTRUCT._to_per: [some ASN.1 object name], removing value equal to the default one" warning yields a lot when converting an object back into UPER

For some reason, the following valid ASN.1 UPER sample, when deserialized then serialized back into Pycrate...

from pycrate_asn1dir import RRC3G

pycrate_object = RRC3G.Class_definitions.DL_DCCH_Message

pycrate_object.from_uper(b'\xf4\x00\xb0\x0c\xcbo\x82\x00\x81\xb0\t\x81\xc0\x08\x851\x00\x00bR\xfe\x04\x00\x08%\x88\x00\x10DI\x9e\xd45\xe0\x00g\x01\x0c\xb0\x02\xa0a\x80\x00')

pycrate_object.to_uper()

...produces the following warning:

_CONSTRUCT._to_per: DL-DCCH-Message.message.radioBearerRelease.later-than-r3.criticalExtensions.criticalExtensions.criticalExtensions.criticalExtensions.criticalExtensions.r8.radioBearerRelease-r8.ul-DPCH-Info.modeSpecificInfo.fdd.dpdchPresence.present.numberOfDPDCH, removing value equal to the default one

This warning is yielded from the pycrate_asn1rt.asnobj_construct._CONSTRUCT._to_per function.

This warning seems to happen on a lot when serializing back RRC 3G DCCH frames. It does not seem to impair Pycrate's behavior (the produced payload is identical to the input payload), but pollutes the standard output.

It seems to happen commonly with the following DCCH fields:

  • DL-DCCH-Message.message.measurementControl.later-than-r3.criticalExtensions.later-than-r4.criticalExtensions.criticalExtensions.criticalExtensions.r8.measurementControl-r8.measurementCommand.setup.intraFrequencyMeasurement.intraFreqCellInfoList.newIntraFreqCellList._item_.cellInfo.cellIndividualOffset
  • DL-DCCH-Message.message.measurementControl.later-than-r3.criticalExtensions.later-than-r4.criticalExtensions.criticalExtensions.criticalExtensions.r8.measurementControl-r8.measurementCommand.setup.intraFrequencyMeasurement.reportCriteria.periodicalReportingCriteria.periodicalReportingCriteria.reportingAmount
  • DL-DCCH-Message.message.measurementControl.later-than-r3.criticalExtensions.later-than-r4.criticalExtensions.criticalExtensions.criticalExtensions.r8.measurementControl-r8.measurementCommand.setup.interFrequencyMeasurement.reportCriteria.periodicalReportingCriteria.periodicalReportingCriteria.reportingAmount
  • DL-DCCH-Message.message.measurementControl.later-than-r3.criticalExtensions.later-than-r4.criticalExtensions.criticalExtensions.criticalExtensions.r8.measurementControl-r8.measurementCommand.setup.intraFrequencyMeasurement.intraFreqMeasQuantity.filterCoefficient
  • DL-DCCH-Message.message.radioBearerRelease.later-than-r3.criticalExtensions.criticalExtensions.criticalExtensions.criticalExtensions.criticalExtensions.r8.radioBearerRelease-r8.ul-DPCH-Info.modeSpecificInfo.fdd.dpdchPresence.present.numberOfDPDCH

[Not defined But function] NULL object Conversion to ber ws

Hello,
I try to used the function to_ber_ws and I find a bug in conversion
of NULL object. (see the code below)
But what is the difference between conversion to_ber_ws and and to_ber ?
and the usage between one or another ? What is the meaning of ws suffix ?
My solution is to used exclusively to_ber function to skip this bug.

from pycrate_asn1dir import TCAP_MAP
m = TCAP_MAP.MAP_MS_DataTypes.ProvideSubscriberInfoArg
context = {"requestedInfo": {'subscriberState': 0,
               't-adsData': 0,
               'imei': 0,
               'currentLocation': 0,
               'mnpRequestedInfo': 0,
               'locationInformation': 0}}
m.set_val(context)
m.to_ber_ws()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-17-42ebfab7041a> in <module>()
----> 1 m.to_ber_ws()

/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1rt/asnobj.pyc in to_ber_ws(self, val)
   1034             self.set_val(val)
   1035         if self._val is not None:
-> 1036             return self._to_ber_ws().to_bytes()
   1037         else:
   1038             return None

/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1rt/asnobj.pyc in _to_ber_ws(self)
    989     def _to_ber_ws(self):
    990         # 1) encode the most inner TLV part
--> 991         pc, lval, V = self._encode_ber_cont_ws()
    992         if not self._tagc:
    993             # in case no tag is associated to the object (CHOICE, OPEN / ANY)

/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1rt/asnobj_construct.pyc in _encode_ber_cont_ws(self)
   1463                     Comp._parent = self
   1464                     Comp._val = self._val[ident]
-> 1465                     comp_tlv = Comp._to_ber_ws()
   1466                     TLV.append( comp_tlv )
   1467                     Comp._parent = _par

/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1rt/asnobj.pyc in _to_ber_ws(self)
    989     def _to_ber_ws(self):
    990         # 1) encode the most inner TLV part
--> 991         pc, lval, V = self._encode_ber_cont_ws()
    992         if not self._tagc:
    993             # in case no tag is associated to the object (CHOICE, OPEN / ANY)

/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1rt/asnobj_construct.pyc in _encode_ber_cont_ws(self)
   1463                     Comp._parent = self
   1464                     Comp._val = self._val[ident]
-> 1465                     comp_tlv = Comp._to_ber_ws()
   1466                     TLV.append( comp_tlv )
   1467                     Comp._parent = _par

/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1rt/asnobj.pyc in _to_ber_ws(self)
    989     def _to_ber_ws(self):
    990         # 1) encode the most inner TLV part
--> 991         pc, lval, V = self._encode_ber_cont_ws()
    992         if not self._tagc:
    993             # in case no tag is associated to the object (CHOICE, OPEN / ANY)

/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1rt/asnobj_basic.pyc in _encode_ber_cont_ws(self)
    114 
    115     def _encode_ber_cont_ws(self):
--> 116         return 0, 0, But('V', val=b'', bl=0)
    117 
    118     def _encode_ber_cont(self):

NameError: global name 'But' is not defined

Thank you for your response.
Sincerely,

Dynamic compilation of an ASN.1 object

Is there a way of doing Dynamic ASN.1 compilation in pycrate in similar way as in libmich (in libmich it was by using inline)? Some example would be very useful. Thank you

Improve 5G NAS messaging

I want to improve the 5G NAS message, I hope you can give me some tips. For example, what logic did you implement for 4G NAS messages before?

Ability to return bytes that are not consumed during a decoding operation

In certain circumstances, a byte stream with multiple variably encoded objects is encountered. Is there currently a way to return how many bytes were consumed from an operation like "from_aper"? This way the entire buffer can be passed to the decoder and it will decode the required number of bytes to decode the first object and then pass back the remainder. My current workaround has "from_aper" in "asnobj.py" return the remainder of bytes and "_from_per" in "asnobj_construct.py" return "char.to_bytes()". Is there better way to do this?

Encoding error with extended fields syntax [[ ]]

Testing environment:

  • pycrate version: 0.3
  • python version 2.7.11

Issue description

The following ASN.1 grammar reproduce the observed bug:

World-Schema DEFINITIONS AUTOMATIC TAGS ::= 
BEGIN
  Test ::= SEQUENCE       
  {                                                     
     val1      INTEGER,
	...,
     [[
     ext1	INTEGER OPTIONAL,
     ext2	INTEGER OPTIONAL
     ]]
  }                                                     
END

The following code is expected to be able to encode both messages since ext1 and ext2 are optional:

from example import World_Schema

if __name__ == "__main__":
    msg_ok = {'val1': 1, 'ext1': 2, 'ext2': 3}
    World_Schema.Test.set_val(msg_ok)
    pdu_uper =  World_Schema.Test.to_uper()

    msg_ko = {'val1': 1, 'ext1': 2}
    World_Schema.Test.set_val(msg_ko)
    pdu_uper =  World_Schema.Test.to_uper()

Result, it crashes:

python test.py
Traceback (most recent call last):
  File "test.py", line 9, in <module>
    World_Schema.Test.set_val(msg_ko)
  File "pycrate-0.3-py2.7.egg/pycrate_asn1rt/asnobj.py", line 631, in set_val
    self._safechk_val(self._val)
  File "pycrate-0.3-py2.7.egg/pycrate_asn1rt/asnobj_construct.py", line 569, in _safechk_val
    self._safechk_valcompl(val)
  File "pycrate-0.3-py2.7.egg/pycrate_asn1rt/asnobj_construct.py", line 584, in _safechk_valcompl
    .format(self.fullname(), val)))
pycrate_asn1rt.err.ASN1ObjErr: Test: missing extended value, {'val1': 1, 'ext1': 2}

Both messages can be serialized using asn1-playground

Problem with APER encoding empty container of ProtocolIEs in S1AP

Hi, I've tried to use your library but I''ve encountered problem with encoding following S1AP message : ('successfulOutcome', {'procedureCode': 14, 'value': ('ResetAcknowledge', {'protocolIEs': []}), 'criticality': 'reject'})
to_aper function returns following bytes 20 0E 00 01 00 but should return 20 0E 00 03 00 00 00

OctetString value changed in .from_aper()

Hi,
I am trying to send the same example of S1AP InitialUEMessage as found in the wiki, with adding an optional OctetString element 'LHN-ID'. When encoding with .to_aper(), the shown value of this element is correct. However when decoding with .from_aper() there is a 00 added before the actual value , which fails the rest of my code. Here is a small regenerator:

from binascii import unhexlify
import S1AP
PDU = S1AP.S1AP_PDU_Descriptions.S1AP_PDU
c =  S1AP.S1AP_PDU_Contents.InitialUEMessage_IEs().root
for i in c:
    print(i)

IEs = []
IEs.append({'id': 8, 'value': ('ENB-UE-S1AP-ID', 1202), 'criticality': 'reject'})
IEs.append({'id': 26, 'value': ('NAS-PDU', unhexlify('0741720bf600f11040000af910512604e060c04000240205d011d1271d8080211001000010810600000000830600000000000d00000a00001000500bf600f110000101c8d595065200f11000015c0a003103e5e0341300f110400011035758a65d0100c1')), 'criticality': 'reject'})
IEs.append({'id': 67, 'value': ('TAI', {'pLMNidentity': b'\x00\x01\xf1', 'tAC': b'\x00\x01'}), 'criticality': 'reject'})
IEs.append({'id': 100, 'value': ('EUTRAN-CGI', {'cell-ID': (1, 28), 'pLMNidentity': b'\x00\x01\xf1'}), 'criticality': 'ignore'})
IEs.append({'id': 134, 'value': ('RRC-Establishment-Cause', 'highPriorityAccess'), 'criticality': 'ignore'})
IEs.append({'id': 186, 'value': ('LHN-ID',b'11111111112222222222333333333444'), 'criticality': 'ignore'})

val = ('initiatingMessage', {'procedureCode': 12, 'value': ('InitialUEMessage', {'protocolIEs': IEs}), 'criticality': 'ignore'})
PDU.set_val(val)

print(PDU.to_aper())
print(PDU.to_asn1())

PDU1 = S1AP.S1AP_PDU_Descriptions.S1AP_PDU
PDU1.from_aper(PDU.to_aper())
print(PDU1.to_asn1())

you will notice the value change from
value LHN-ID: '3131313131313131313132323232323232323232333333333333333333343434'H -- 11111111112222222222333333333444 --
to this with the added 00. Apparently, there is a shift in the reading cursor !
value LHN-ID: '0031313131313131313131323232323232323232323333333333333333333434'H

here is the whole output:


{'id': 8, 'criticality': 'reject', 'Value': <Value ([ENB-UE-S1AP-ID] INTEGER)>, 'presence': 'mandatory'}
{'id': 26, 'criticality': 'reject', 'Value': <Value ([NAS-PDU] OCTET STRING)>, 'presence': 'mandatory'}
{'id': 67, 'criticality': 'reject', 'Value': <Value ([TAI] SEQUENCE)>, 'presence': 'mandatory'}
{'id': 100, 'criticality': 'ignore', 'Value': <Value ([EUTRAN-CGI] SEQUENCE)>, 'presence': 'mandatory'}
{'id': 134, 'criticality': 'ignore', 'Value': <Value ([RRC-Establishment-Cause] ENUMERATED)>, 'presence': 'mandatory'}
{'id': 96, 'criticality': 'reject', 'Value': <Value ([S-TMSI] SEQUENCE)>, 'presence': 'optional'}
{'id': 127, 'criticality': 'reject', 'Value': <Value ([CSG-Id] BIT STRING)>, 'presence': 'optional'}
{'id': 75, 'criticality': 'reject', 'Value': <Value ([GUMMEI] SEQUENCE)>, 'presence': 'optional'}
{'id': 145, 'criticality': 'reject', 'Value': <Value ([CellAccessMode] ENUMERATED)>, 'presence': 'optional'}
{'id': 155, 'criticality': 'ignore', 'Value': <Value ([TransportLayerAddress] BIT STRING)>, 'presence': 'optional'}
{'id': 160, 'criticality': 'reject', 'Value': <Value ([RelayNode-Indicator] ENUMERATED)>, 'presence': 'optional'}
{'id': 170, 'criticality': 'ignore', 'Value': <Value ([GUMMEIType] ENUMERATED)>, 'presence': 'optional'}
{'id': 176, 'criticality': 'ignore', 'Value': <Value ([TunnelInformation] SEQUENCE)>, 'presence': 'optional'}
{'id': 184, 'criticality': 'ignore', 'Value': <Value ([TransportLayerAddress] BIT STRING)>, 'presence': 'optional'}
{'id': 186, 'criticality': 'ignore', 'Value': <Value ([LHN-ID] OCTET STRING)>, 'presence': 'optional'}
{'id': 223, 'criticality': 'ignore', 'Value': <Value ([MME-Group-ID] OCTET STRING)>, 'presence': 'optional'}
{'id': 230, 'criticality': 'ignore', 'Value': <Value ([UE-Usage-Type] INTEGER)>, 'presence': 'optional'}
b'\x00\x0c@\x80\xb4\x00\x00\x06\x00\x08\x00\x03@\x04\xb2\x00\x1a\x00ed\x07Ar\x0b\xf6\x00\xf1\x10@\x00\n\xf9\x10Q&\x04\xe0`\xc0@\x00$\x02\x05\xd0\x11\xd1\'\x1d\x80\x80!\x10\x01\x00\x00\x10\x81\x06\x00\x00\x00\x00\x83\x06\x00\x00\x00\x00\x00\r\x00\x00\n\x00\x00\x10\x00P\x0b\xf6\x00\xf1\x10\x00\x01\x01\xc8\xd5\x95\x06R\x00\xf1\x10\x00\x01\\\n\x001\x03\xe5\xe04\x13\x00\xf1\x10@\x00\x11\x03WX\xa6]\x01\x00\xc1\x00C\x00\x06\x00\x00\x01\xf1\x00\x01\x00d@\x08\x00\x00\x01\xf1\x00\x00\x00\x10\x00\x86@\x01\x10\x00\xba@"\x00\x0011111111112222222222333333333444'
initiatingMessage : {
  procedureCode 12,
  criticality ignore,
  value InitialUEMessage: {
    protocolIEs {
      {
        id 8,
        criticality reject,
        value ENB-UE-S1AP-ID: 1202
      },
      {
        id 26,
        criticality reject,
        value NAS-PDU: '0741720BF600F11040000AF910512604E060C04000240205D011D1271D8080211001000010810600000000830600000000000D00000A00001000500BF600F110000101C8D595065200F11000015C0A003103E5E0341300F110400011035758A65D0100C1'H
      },
      {
        id 67,
        criticality reject,
        value TAI: {
          pLMNidentity '0001F1'H,
          tAC '0001'H
        }
      },
      {
        id 100,
        criticality ignore,
        value EUTRAN-CGI: {
          pLMNidentity '0001F1'H,
          cell-ID '0000001'H
        }
      },
      {
        id 134,
        criticality ignore,
        value RRC-Establishment-Cause: highPriorityAccess
      },
      {
        id 186,
        criticality ignore,
        value LHN-ID: '3131313131313131313132323232323232323232333333333333333333343434'H -- 11111111112222222222333333333444 --
      }
    }
  }
}
initiatingMessage : {
  procedureCode 12,
  criticality ignore,
  value InitialUEMessage: {
    protocolIEs {
      {
        id 8,
        criticality reject,
        value ENB-UE-S1AP-ID: 1202
      },
      {
        id 26,
        criticality reject,
        value NAS-PDU: '0741720BF600F11040000AF910512604E060C04000240205D011D1271D8080211001000010810600000000830600000000000D00000A00001000500BF600F110000101C8D595065200F11000015C0A003103E5E0341300F110400011035758A65D0100C1'H
      },
      {
        id 67,
        criticality reject,
        value TAI: {
          pLMNidentity '0001F1'H,
          tAC '0001'H
        }
      },
      {
        id 100,
        criticality ignore,
        value EUTRAN-CGI: {
          pLMNidentity '0001F1'H,
          cell-ID '0000001'H
        }
      },
      {
        id 134,
        criticality ignore,
        value RRC-Establishment-Cause: highPriorityAccess
      },
      {
        id 186,
        criticality ignore,
        value LHN-ID: '0031313131313131313131323232323232323232323333333333333333333434'H
      }
    }
  }
}

MSNetCap and ESMContainer are assigned on AttachRequest

Sorry, I am bothering you again, because I don’t know how to solve the two problems now. I hope you can give me some tips. I tried to assign the two IEs ESMContainer and MSNetCap in the NAS message of AttachRequest, but it always went wrong. I don't know where the problem is, I hope I can point it out.

input value:
ESMContainer : [44, [[0, 2, 1, 208], [3], [1], [39, 38, [1, 0, 0, [[32801, 16, [1, 1, 16, [[129, 6, b'\x00\x00\x00\x00'], [131, 6, b'\x00\x00\x00\x00']]]], [3, 0, b''], [10, 0, b''], [2, 0, b''], [12, 0, b''], [1, 0, b''], [13, 0, b'']]]]]] MSNetCap : [49, 3, [1, 1, 1, 0, 1, 0, 1, 0, [1, 1, 0, 0, 0, 0], 0, 0, 0, 1, 1, 1, 1, 0, 0]]
output value:
ESMContainer : [0, b''] MSNetCap : [49, 39, [0, 0, 1, 0, 1, 1, 0, 1, [0, 0, 0, 0, 0, 0], 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]]]
Assignment process:
`PDNConnectivityRequest = ESMPDNConnectivityRequest()
PDNConnectivityRequest['ESMHeader'].set_val([0, 2, 1, 208])
PDNConnectivityRequest['PDNType'].set_val([3])
PDNConnectivityRequest['RequestType'].set_val([1])
PDNConnectivityRequest['ProtConfig'].set_trans(False)
PDNConnectivityRequest['ProtConfig'].set_val([39, 38, [1, 0, 0, [
[32801, 16, [1, 1, 16, [[129, 6, b'\x00\x00\x00\x00'], [131, 6, b'\x00\x00\x00\x00']]]], [3, 0, b''],
[10, 0, b''], [2, 0, b''], [12, 0, b''], [1, 0, b''], [13, 0, b'']]]])
Msg['ESMContainer'].set_val({'V': PDNConnectivityRequest.to_bytes()})

Msg['MSNetCap'].set_trans(False)
Msg['MSNetCap'].set_val({'T': 49, 'V': [1, 1, 1, 0, 1, 0, 1, 0, [1, 1, 0, 0, 0, 0], 0, 0, 0, 1, 1, 1, 1, 0, 0]})
`

[Malformed packet] SEQ and SEQ_OF object

Hello,

I really enjoy using pycrate, to craft MAP messages and I just discover a bug and share
to you.

I send two MAP messages using InsertSubscriberDataArg.
The first test, I add one SEQ object in the gprsDataList SEQ_OF object, encode in
the InsertSubscriberDataArg object, and send the packet in the network, and it works well.

In the second test, I add two SEQ objects in the grpsDataList SEQ_OF object,
and the packet is malformed according to Wireshark.

I also add more than two SEQ objects in the gprsDataList SEQ_OF object, and it
also fails.

TEST PCAP files
pcap.tar.gz

FIRST TEST:
In [1]: from pycrate_asn1dir import TCAP_MAP

In [2]: m = TCAP_MAP.MAP_MS_DataTypes.InsertSubscriberDataArg

In [3]: m.set_val({u'gprsSubscriptionData': {u'gprsDataList': [{u'pdp-ContextId': 5, u'apn': '\x07P\x05\x07\x07\x07\x07P\x05\x07\x07\x07\x07P\x05\x05', u'pdp-Type': '\xf1!', u'ext-QoS-Subscribed': '\x02k\x96\xfe\xfet\x02\x00\x00', u'ext2-QoS-Subscribed': '\x00\x8e\x00', u'qos-Subscribed': '\x13\x92\x1f'}]}})
In [4]: m.to_ber()
Out[4]: '04\xb02\xa100.\x02\x01\x05\x90\x02\xf1!\x92\x03\x13\x92\x1f\x94\x10\x07P\x05\x07\x07\x07\x07P\x05\x07\x07\x07\x07P\x05\x05\x80\t\x02k\x96\xfe\xfet\x02\x00\x00\x82\x03\x00\x8e\x00'

In [5]: import binascii

In [6]: binascii.hexlify(m.to_ber())
Out[6]: '3034b032a130302e0201059002f121920313921f9410075005070707075005070707075005058009026b96fefe740200008203008e00'

SECOND TEST:
In [1]: from pycrate_asn1dir import TCAP_MAP
In [2]: m = TCAP_MAP.MAP_MS_DataTypes.InsertSubscriberDataArg

In [3]: m.set_val({u'gprsSubscriptionData': {u'gprsDataList': [{u'pdp-ContextId': 5, u'apn': '\x07P\x05\x07\x07\x07\x07P\x05\x07\x07\x07\x07P\x05\x05', u'pdp-Type': '\xf1!', u'ext-QoS-Subscribed': '\x02k\x96\xfe\xfet\x02\x00\x00', u'ext2-QoS-Subscribed': '\x00\x8e\x00', u'qos-Subscribed': '\x13\x92\x1f'},{u'pdp-ContextId': 4, u'apn': '\x07P\x05\x07\x07\x07\x07P\x05\x07\x07\x07\x07P\x05\x05', u'pdp-Type': '\xf1!', u'ext-QoS-Subscribed': '\x02k\x96\xfe\xfet\x02\x00\x00', u'ext2-QoS-Subscribed': '\x00\x8e\x00', u'qos-Subscribed': '\x13\x92\x1f'}]}})

In [4]: m.to_ber()
Out[4]: '0d\xb0b\xa1`0.\x02\x01\x05\x90\x02\xf1!\x92\x03\x13\x92\x1f\x94\x10\x07P\x05\x07\x07\x07\x07P\x05\x07\x07\x07\x07P\x05\x05\x80\t\x02k\x96\xfe\xfet\x02\x00\x00\x82\x03\x00\x8e\x000.\x02\x01\x04\x90\x02\xf1!\x92\x03\x13\x92\x1f\x94\x10\x07P\x05\x07\x07\x07\x07P\x05\x07\x07\x07\x07P\x05\x05\x80\t\x02k\x96\xfe\xfet\x02\x00\x00\x82\x03\x00\x8e\x00'

In [5]: import binascii

In [6]: binascii.hexlify(m.to_ber())
Out[6]: '3064b062a160302e0201059002f121920313921f9410075005070707075005070707075005058009026b96fefe740200008203008e00302e0201049002f121920313921f9410075005070707075005070707075005058009026b96fefe740200008203008e00'

Thank you for the clarification.

Hexadecimal string data cannot be parsed

The hexadecimal data of the NGSetupRequest message I picked up with wireshark cannot be parsed.
`import ngap
import binascii

if name == "main":
content = "00150041000004001b00090002f89850000002010052000a03807465737420674e4200150001400066001a00000100010002f8980002100800006410100000641018000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
# with open("ngsetup2.txt", "r") as f:
# content = f.read()
# ngap.NGAP_PDU_Contents.NGSetupRequest.from_aper(bytes(content))
bytecontent = bytes().fromhex(content)
ngap.NGAP_PDU_Contents.NGSetupRequest.from_aper(bytecontent)`

ASN1 struct:
('SEQUENCE', {
protocolIEs: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
value: ('OPEN_TYPE', {
('NGAP-IEs', 'GlobalRANNodeID'): ('CHOICE', {
globalGNB-ID: ('SEQUENCE', {
pLMNIdentity: 'OCTET STRING',
gNB-ID: ('CHOICE', {
gNB-ID: 'BIT STRING',
choice-Extensions: ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
value: 'OPEN_TYPE'
})
}),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
}),
globalNgENB-ID: ('SEQUENCE', {
pLMNIdentity: 'OCTET STRING',
ngENB-ID: ('CHOICE', {
macroNgENB-ID: 'BIT STRING',
shortMacroNgENB-ID: 'BIT STRING',
longMacroNgENB-ID: 'BIT STRING',
choice-Extensions: ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
value: 'OPEN_TYPE'
})
}),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
}),
globalN3IWF-ID: ('SEQUENCE', {
pLMNIdentity: 'OCTET STRING',
n3IWF-ID: ('CHOICE', {
n3IWF-ID: 'BIT STRING',
choice-Extensions: ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
value: 'OPEN_TYPE'
})
}),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
}),
choice-Extensions: ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
value: 'OPEN_TYPE'
})
}),
GlobalRANNodeID: ('CHOICE', {
globalGNB-ID: ('SEQUENCE', {
pLMNIdentity: 'OCTET STRING',
gNB-ID: ('CHOICE', {
gNB-ID: 'BIT STRING',
choice-Extensions: ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
value: 'OPEN_TYPE'
})
}),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
}),
globalNgENB-ID: ('SEQUENCE', {
pLMNIdentity: 'OCTET STRING',
ngENB-ID: ('CHOICE', {
macroNgENB-ID: 'BIT STRING',
shortMacroNgENB-ID: 'BIT STRING',
longMacroNgENB-ID: 'BIT STRING',
choice-Extensions: ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
value: 'OPEN_TYPE'
})
}),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
}),
globalN3IWF-ID: ('SEQUENCE', {
pLMNIdentity: 'OCTET STRING',
n3IWF-ID: ('CHOICE', {
n3IWF-ID: 'BIT STRING',
choice-Extensions: ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
value: 'OPEN_TYPE'
})
}),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
}),
choice-Extensions: ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
value: 'OPEN_TYPE'
})
}),
('NGAP-IEs', 'RANNodeName'): 'PrintableString',
RANNodeName: 'PrintableString',
('NGAP-IEs', 'SupportedTAList'): ('SEQUENCE OF', ('SEQUENCE', {
tAC: 'OCTET STRING',
broadcastPLMNList: ('SEQUENCE OF', ('SEQUENCE', {
pLMNIdentity: 'OCTET STRING',
tAISliceSupportList: ('SEQUENCE OF', ('SEQUENCE', {
s-NSSAI: ('SEQUENCE', {
sST: 'OCTET STRING',
sD: 'OCTET STRING',
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
}),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
})),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
})),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
})),
SupportedTAList: ('SEQUENCE OF', ('SEQUENCE', {
tAC: 'OCTET STRING',
broadcastPLMNList: ('SEQUENCE OF', ('SEQUENCE', {
pLMNIdentity: 'OCTET STRING',
tAISliceSupportList: ('SEQUENCE OF', ('SEQUENCE', {
s-NSSAI: ('SEQUENCE', {
sST: 'OCTET STRING',
sD: 'OCTET STRING',
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
}),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
})),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
})),
iE-Extensions: ('SEQUENCE OF', ('SEQUENCE', {
id: 'INTEGER',
criticality: 'ENUMERATED',
extensionValue: ('OPEN_TYPE', {})
}))
})),
('NGAP-IEs', 'PagingDRX'): 'ENUMERATED',
PagingDRX: 'ENUMERATED',
('NGAP-IEs', 'UERetentionInformation'): 'ENUMERATED',
UERetentionInformation: 'ENUMERATED'
})
}))
})

long integer no longer exists in python3

can't compile module with python3 because of long int literals, like for example 'ub=4294967295L' in SNMP.py line 148
int and long int are unified since python3, thus 'L' suffix does not exists. The good news is that python2.7 automatically use long integer when needed. You could remove all terminating 'L' on integer literals to make your code python2/3 compatible

Encoding RP_ACK_MO SMS

Dear pycrate team,

I have an issue with the following simple code :

#! /usr/bin/env python3

import sys
from binascii import unhexlify

from pycrate_mobile.TS24011_PPSMS import SMS_DELIVER_REPORT_RP_ACK
from pycrate_mobile.TS24011_PPSMS import RP_ACK_MO

Message = '020641020000'

def main():

    # Parsing SMS with RP_ACK_MO header
    original_rp_ack = RP_ACK_MO()
    original_rp_ack.from_bytes(unhexlify(Message))
    print(original_rp_ack.show())
    print("---------------------------------------")

    # # Creating SMS message with RP_ACK_MO header
    #
    new_rp_ack = RP_ACK_MO(val = {'Ref':6 })
    SMS_deliver_Report = SMS_DELIVER_REPORT_RP_ACK(val = {'TP_UDHI': 0,\
                                           'TP_MTI': 0, \
                                           'TP_PI': {'TP_UDL': 0, 'TP_DCS': 0, 'TP_PID': 0}, \
                                           })
    new_rp_ack.set_tpdu(SMS_deliver_Report)

    print('\n')
    print(SMS_deliver_Report.show())
    print('\n')
    print(new_rp_ack.show())

    assert(Message == new_rp_ack.hex())

if __name__ == '__main__':
    sys.exit(main())

The function set_tpdu seems to have an issue or my instanciation of RP_ACK_MO is not correct.
Thanks a lot for your help,
Regards.

class ASN1Obj(Element) attributes

Hello,

I have a question about implementation of attributes in class ASN1Obj:

   _name    = ''
   _mode    = MODE_TYPE
   _tag     = None
   _typeref = None
   _tr      = None
   _param   = False
   _parent  = None
   _opt     = False
   _def     = None
   _uniq    = False
   _group   = None
   _cont    = None
   _root    = None
   _ext     = None
   _val     = None

and I didn't catch up why there is in the Class, so it is a static value.
Especially, when you use decode an object with method from_ber(), and then you
decode another object with the same method (but empty value). The _val
variable will keep the value of the first object.
What is the reason of the class-level implementation vs the obj-level implementation?

Thanks,

About NAS codec

Hello, I am sorry to always bother you to help you solve the problem. I have successfully packaged a NAS message.
I have a few questions, I want to ask you, google has not been able to find an answer for a long time.

  1. Why not use asn.1 as a codec tool for NAS messages?
  2. What is the role of CSN.1 in NAS message encoding and decoding? Why can't I use asn.1 instead?

I have read the introduction of csn.1 on the website http://csn1.info. It also mentions that the protocol TS24.007 and TS24.008 have the format encoding MSNetCap using csn.1. But I don't know why I have to write it.

I hope I can receive the answer, thank you.****

uint_bytelen returns 0 for value 0

First off. awesome library. Thanks for making it public.

Second, I think I may have found a bug. The following function in "pycrate_asn1rt/utils.py"

def uint_bytelen(val):
   bl = val.bit_length()
   if bl % 8:
       return 1 + (bl>>3)
   else:
       return bl>>3

returns 0 byte length if the value passed is 0. Unfortunately then when it's used in PER encoding for example, if you have a field with an Integer that is set to zero, this function returns 0 and the encoded string returned is not correct. As a workaround I added

if val == 0:
    return 1

similar to what is defined in "int_bytelen" in the same file. As this is a utility function used all over, I didn't want to presume this is the intended behavior for all of it's uses so I figured I'd put it in as an issue rather than a pull request.

APER decoding Issue when 0 sized INTEGER

I have found inconsistencies when decoding APER encoded objects that contain Integers that have been encoded with lengths fields of 0. Microsoft's implementation seems to have the expectation that 0 means at least 1. The instance of this I'm seeing this in is in the Microsoft RDP protocol, https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-RDPBCGR/%5bMS-RDPBCGR%5d.pdf, page 334 - Section 4.1.7. Server MCS Attach-User Confirm PDU, with the AttachUserConfirm::initiator field. When I parse this using APER, the initiator field returns None because ldet in the following code in codecs.py returns 0.

def decode_intunconst(cla, char, offset=None):
    if cla.ALIGNED and cla._off[-1] % 8:
        cla.decode_pad(char)
    # 1) get byte-length determinant
    ldet = cla.decode_count(char)

I'm not sure if this is the expected behavior or a inconsistency in Microsoft's implementation of APER. Either way I figured I'd bring it to your attention. For my purposes, I have added

    if ldet == 0:
       ldet = 1

to decode_intunconst in codecs.py as a work-around to get my parser working.

An error occurred while trying to import a NAS asn file

Hello, I want to ask you two questions.
1, I saw your library is to support 2G to 3G NAS message analysis, I would like to ask if the support does not support 5G NAS message parsing. I can't pass my NAS message in your program.
`python
import gNB.NGAP as NGAP
import binascii
from pycrate_mobile.NAS import *

PDU = NGAP.NGAP_PDU_Descriptions.NGAP_PDU

PDU.from_aper(binascii.unhexlify(
"000f00814a000008005500020080002600810281007e02cd5c1994fe7e02410fd0cc1001032e0211225201000200000003170201024002000150020002b12b01022502000118010151010270000134817b00013491530222117100013400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007900121002f8290000007002f82901f82902f82906005a000100001a0007301bc0746d7369000300024040007000010000000005028001020300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002114000000000000b8718445ce7f0000b8718445ce7f00004054ed01000000004054ed01000000000080adfbce7f0000906fed0100000000906fed0100000000906fed0100000000906fed01000000003670ed0100000000908fed01000000000000000000000000908fed0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007055ed010000000000000000000000000000000000000000ffffffffffffffff000000000000000000000000000000000000000000000000ffffffff0000000000000000000000000000000000000000e0538445ce7f000030615045ce7f0000f0645045ce7f0000781e297aff7f0000801e297aff7f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010020000000000001002000000000000000008005500020080002600810281007e02cd5c1994fe7e02410fd0cc1001032e0211225201000200000003170201024002000150020002b11100000000000098718445ce7f000098718445ce7f0000b056ed0100000000b056ed01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007900121002f8290000007002f82901f82902f82906005a000100001a0007301bc0746d7369000300024040007000010000000005028001020300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e10f000000000000786b8445ce7f00005036ed010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"))

print(PDU.to_asn1())
`
This is after my message is running, you can get the data in the NAS-PDU. I want to know if the data in the NAS-PDU is hexadecimal data? Or other coded data?

2、I tried to import the asn file I found on this site about nas, but I can't import it into the program. Can you help me find out what went wrong?

[ASN1] Error while parsing open type value with CHOICE

errorIndication F1AP-PDU ::= initiatingMessage :
{
    procedureCode id-ErrorIndication,
    criticality ignore,
    value ErrorIndication : {
      protocolIEs{
        {
          id id-Cause,
          criticality ignore,
          value Cause : protocol : abstract-syntax-error-reject
        }
      }
    }
}

It looks like another colon from choice syntax is the problem, since all other open type value types worked correctly.

Here's the traceback:

Traceback (most recent call last):
  File "pycrate_asn1compile.py", line 145, in <module>
    sys.exit(main())
  File "pycrate_asn1compile.py", line 133, in main
    compile_text(''.join(txt), **ckw)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/proc.py", line 350, in compile_text
    compile_modules(remain)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/proc.py", line 884, in compile_modules
    ObjNew = asnobj_compile(Obj)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/proc.py", line 831, in asnobj_compile
    rest = Obj.parse_value(Obj._text_def)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 4537, in parse_value
    return getattr(self, self._PARSE_VALUE_DISPATCH[self._type])(text)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 5176, in _parse_value_choice
    text = ObjProxy.parse_value(text)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 4537, in parse_value
    return getattr(self, self._PARSE_VALUE_DISPATCH[self._type])(text)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 5251, in _parse_value_seq
    restval = ObjProxy.parse_value(value)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 4537, in parse_value
    return getattr(self, self._PARSE_VALUE_DISPATCH[self._type])(text)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 5459, in _parse_value_open
    textval = Obj.parse_value(textval)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 4537, in parse_value
    return getattr(self, self._PARSE_VALUE_DISPATCH[self._type])(text)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 5251, in _parse_value_seq
    restval = ObjProxy.parse_value(value)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 4537, in parse_value
    return getattr(self, self._PARSE_VALUE_DISPATCH[self._type])(text)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 5385, in _parse_value_seqof
    restval = ObjProxy.parse_value(value)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 4537, in parse_value
    return getattr(self, self._PARSE_VALUE_DISPATCH[self._type])(text)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 5251, in _parse_value_seq
    restval = ObjProxy.parse_value(value)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 4537, in parse_value
    return getattr(self, self._PARSE_VALUE_DISPATCH[self._type])(text)
  File "/usr/local/lib/python2.7/dist-packages/pycrate-0.3-py2.7.egg/pycrate_asn1c/asnobj.py", line 5432, in _parse_value_open
    .format(self.fullname(), text)))
pycrate_asn1c.err.ASN1ProcTextErr: value: invalid OPEN value, Cause : protocol : abstract-syntax-error-reject

ESM info response is not decoding correctly

Hi,
i was trying to execute the test folder examples found that mobile NAS message (ESM info Response : 0202da2807066f72616e6765) throwing error : (None, 97)

but the same buffer decoded by external decoder as follows
DLT: 147, Payload: nas-eps_plain (Non-Access-Stratum (NAS)PDU)

Non-Access-Stratum (NAS)PDU

0000 .... = EPS bearer identity: No EPS bearer identity assigned (0)

.... 0010 = Protocol discriminator: EPS session management messages (0x2)

Procedure transaction identity: 2

NAS EPS session management messages: ESM information response (0xda)

Access Point Name

    Element ID: 0x28

    Length: 7

    APN: orange

S1AP S1SetuResponse ServedGUMMEIsItem

Hi,
I'm trying to create a S1SetupResponse that must contain ServedGUMMEIs and RelativeMMECapacity as protocolIE fields but, after running:

  • PDU = S1AP.S1AP_PDU_Descriptions.S1AP_PDU
  • PP.pprint(PDU._cont['successfulOutcome']._cont['value']._get_const_tr()['S1SetupResponse'])
    <SuccessfulOutcome ([S1SetupResponse] SEQUENCE)>
    I tried to store both ServedGUMMEIs and RelativeMMECapacity in the PDU obj as follows:
    IEs.append({ 'id': 105, 'criticality': 'reject', 'value': ('servedGUMMEIs', { 'servedPLMNs': {'PLMNidentity': b'\x00\x01\xf1'}, 'servedGroupIDs': {'MME-Group-ID': b'\x00\x04'}, 'servedMMECs': {'MME-Code': b'\x01'}} ) })

IEs.append({'id': 87, 'criticality': 'ignore', 'value': ('RelativeMMECapacity', 10)})
val = ('successfulOutcome', {'procedureCode': 17, 'value': ('S1SetupResponse', {'protocolIEs': IEs}), 'criticality': 'ignore'})
PDU.set_val(val)

and I got this error message:
S1SetupResponse.protocolIEs._item_.value: invalid object reference, 'servedGUMMEIs'

It seems that those items are not implemented. If this is true, is there any way to add it?

Thanks in advance!

[NAS] Building EMMSecurityModeCommand message

Hi,
I have been trying to create a EMMSecurityModeCommand(). I read about NAS in the documentation but I cannot find a clean way to do it. I did it by using the from_bytes() function and also creating an empty EMMSecurityModeCommand Object and setting its parameters but I couldn't, for example, to pass all the information when creating the object.

Is there any way to do it?

Thanks a lot for your help :)

parsing NAS

Which method is the method of parsing NAS?

Encapsulate LTE NAS messages

(<EMMAttachRequest : <EMMHeader : <SecHdr : 0 (No security)><ProtDisc : 7 (EMM)><Type : 65 (Attach request)>><NAS_KSI : <NAS_KSI : <TSC : 0 ( native security context)><Value : 7 (no key available)>>><EPSAttachType : <V : 2 (combined EPS / IMSI attach)>><EPSID : <L : 8><EPSID [IMSI] : 110010000000001>><UENetCap : <L : 4><UENetCap : <EEA0 : 1><EEA1_128 : 1><EEA2_128 : 1><EEA3_128 : 1><EEA4 : 0><EEA5 : 0><EEA6 : 0><EEA7 : 0><EIA0 : 1><EIA1_128 : 1><EIA2_128 : 1><EIA3_128 : 1><EIA4 : 0><EIA5 : 0><EIA6 : 0><EIA7 : 0><UEA0 : 1><UEA1 : 1><UEA2 : 0><UEA3 : 0><UEA4 : 0><UEA5 : 0><UEA6 : 0><UEA7 : 0><UCS2 : 1><UIA1 : 1><UIA2 : 0><UIA3 : 0><UIA4 : 0><UIA5 : 0><UIA6 : 0><UIA7 : 0><ProSe_dd [transparent] : 0><ProSe [transparent] : 0><H245_ASH [transparent] : 0><ACC_CSFB [transparent] : 0><LPP [transparent] : 0><LCS [transparent] : 0><X1_SRVCC [transparent] : 0><NF [transparent] : 0><ePCO [transparent] : 0><HC_CP_CIoT [transparent] : 0><ERw_oPDN [transparent] : 0><S1U_data [transparent] : 0><UP_CIoT [transparent] : 0><CP_CIoT [transparent] : 0><ProSe_relay [transparent] : 0><ProSe_dc [transparent] : 0><spare [transparent] : 0><spare [transparent] : 0><spare [transparent] : 0><spare [transparent] : 0><spare [transparent] : 0><spare [transparent] : 0><spare [transparent] : 0><MultiDRB [transparent] : 0><spare [transparent] : 0x>>><ESMContainer : <L : 44><ESMPDNConnectivityRequest : <ESMHeader : <EPSBearerId : 0><ProtDisc : 2><PTI : 1><Type : 208 (PDN connectivity request)>><PDNType : <V : 3 (IPv4v6)>><RequestType : <V : 1 (Initial request)>><ESMInfoTransferFlag [transparent] : <T : 13><V : 0>><APN [transparent] : <T : 40><L : 1><V : 0x00>><ProtConfig : <T : 39><L : 38><ProtConfig : <Ext : 1><spare : 0><Prot : 0 (PPP with IP PDP)><Config : <ProtConfigElt : <ID : 32801 (IPCP)><Len : 16><Cont : <Code : 1 (Configure-Request)><Id : 1><Len : 16><Data : <NCPOpt : <Type : 129 (Primary DNS Server Address)><Len : 6><Data : 0x00000000>><NCPOpt : <Type : 131 (Secondary DNS Server Address)><Len : 6><Data : 0x00000000>>>>><ProtConfigElt : <ID : 3 (DNS Server IPv6 Address Request)><Len : 0><Cont : 0x>><ProtConfigElt : <ID : 10 (IP address allocation via NAS signalling)><Len : 0><Cont : 0x>><ProtConfigElt : <ID : 2 (IM CN Subsystem Signaling Flag)><Len : 0><Cont : 0x>><ProtConfigElt : <ID : 12 (P-CSCF IPv4 Address)><Len : 0><Cont : 0x>><ProtConfigElt : <ID : 1 (P-CSCF IPv6 Address Request)><Len : 0><Cont : 0x>><ProtConfigElt : <ID : 13 (DNS server IPv4 address request)><Len : 0><Cont : 0x>>>>><DeviceProp [transparent] : <T : 12><V : 0>><NBIFOMContainer [transparent] : <T : 51><L : 1><V : 0x00>><HdrCompConfig [transparent] : <T : 102><L : 3><V : 0x000000>><ExtProtConfig [transparent] : <T : 123><L : 1><V : 0x00>>>><OldPTMSISign [transparent] : <T : 25><V : 0x000000>><AddGUTI [transparent] : <T : 80><L : 11><V : 0xf600000000000000000000>><OldTAI [transparent] : <T : 82><V : 0x0000000000>><DRXParam : <T : 92><DRXParam : <SPLIT_PG_CYCLE_CODE : 32><DRXCycleLen : 0 (DRX not specified by the MS)><SPLITonCCCH : 0><NonDRXTimer : 0 (no non-DRX mode after transfer state)>>><MSNetCap : <T : 49><L : 3><ms_network_capability_value_part (CSN1List): [<(CSN1Ref): <gea1_bits (CSN1Bit): 1>><sm_capabilities_via_dedicated_channels (CSN1Bit): 1><sm_capabilities_via_gprs_channels (CSN1Bit): 1><ucs2_support (CSN1Bit): 0><ss_screening_indicator (CSN1Bit): 1><solsa_capability (CSN1Bit): 0><revision_level_indicator (CSN1Bit): 1><pfc_feature_mode (CSN1Bit): 0><(CSN1Ref): <extended_gea_bits (CSN1List): [<gea_2 (CSN1Bit): 1><gea_3 (CSN1Bit): 1><gea_4 (CSN1Bit): 0><gea_5 (CSN1Bit): 0><gea_6 (CSN1Bit): 0><gea_7 (CSN1Bit): 0>]>><lcs_va_capability (CSN1Bit): 0><ps_inter_rat_ho_from_geran_to_utran_iu_mode_capability (CSN1Bit): 0><ps_inter_rat_ho_from_geran_to_e_utran_s1_mode_capability (CSN1Bit): 0><emm_combined_procedures_capability (CSN1Bit): 1><isr_support (CSN1Bit): 1><srvcc_to_geran_utran_capability (CSN1Bit): 1><epc_capability (CSN1Bit): 1><nf_capability (CSN1Bit): 0><geran_network_sharing_capability (CSN1Bit): 0>]>><OldLAI [transparent] : <T : 19><V : 0x0000000000>><TMSIStatus : <T : 9><TMSIStatus : <spare : 0><Flag : 0 (no valid TMSI available)>>><MSCm2 : <T : 17><L : 3><MSCm2 : <spare : 0><RevLevel : 2 (MS supporting R99 or later)><EarlyCmCap : 1><NoA51 : 0><RFClass : 7><spare : 0><PSCap : 1><SSScreeningCap : 1 (capability of handling of ellipsis notation and phase 2 error handling)><MTSMSCap : 1><VBSNotifCap : 0><VGCSNotifCap : 0><FCFreqCap : 0><MSCm3Cap : 1><spare : 0><LCSVACap : 0><UCS2 : 0><SoLSACap : 0><CMServPrompt : 1><A53 : 1><A52 : 0>>><MSCm3 : <T : 32><L : 9><classmark_3_value_part (CSN1List): [<(CSN1Ref): <spare_bit (CSN1Bit): 0>><(CSN1Alt): { 110 (multiband_supported) : [<(CSN1Ref): <a5_bits (CSN1List): [<a5_7 (CSN1Bit): 0><a5_6 (CSN1Bit): 0><a5_5 (CSN1Bit): 0><a5_4 (CSN1Bit): 0>]>><associated_radio_capability_2 (CSN1Bit): 1><associated_radio_capability_1 (CSN1Bit): 4>]}><(CSN1Alt): { 0 : []}><(CSN1Alt): { 0 : []}><ucs2_treatment (CSN1Bit): 0><extended_measurement_capability (CSN1Bit): 0><(CSN1Alt): { 0 : []}><(CSN1Alt): { 0 : []}><(CSN1Alt): { 0 : []}><(CSN1Alt): { 0 : []}><(CSN1Alt): { 0 : []}><(CSN1Alt): { 1 : [<gsm_850_associated_radio_capability (CSN1Bit): 4>]}><(CSN1Alt): { 1 : [<gsm_1900_associated_radio_capability (CSN1Bit): 1>]}><umts_fdd_radio_access_technology_capability (CSN1Bit): 1><umts_3_84_mcps_tdd_radio_access_technology_capability (CSN1Bit): 0><cdma_2000_radio_access_technology_capability (CSN1Bit): 0><(CSN1Alt): { 0 : []}><(CSN1Alt): { 0 : []}><(CSN1Alt): { 0 : []}><umts_1_28_mcps_tdd_radio_access_technology_capability (CSN1Bit): 0><geran_feature_package_1 (CSN1Bit): 1><(CSN1Alt): { 0 : []}><(CSN1Alt): { 0 : []}><(CSN1Val): 0><geran_feature_package_2 (CSN1Bit): 0><gmsk_multislot_power_profile (CSN1Bit): 0><_8_psk_multislot_power_profile (CSN1Bit): 0><(CSN1Alt): { 0 : []}><(CSN1Val): 0><downlink_advanced_receiver_performance (CSN1Bit): 1><dtm_enhancements_capability (CSN1Bit): 0><(CSN1Alt): { 0 : []}><repeated_acch_capability (CSN1Bit): 1><(CSN1Alt): { 0 : []}><(CSN1Alt): { 0 : []}><ciphering_mode_setting_capability (CSN1Bit): 0><additional_positioning_capabilities (CSN1Bit): 0><e_utra_fdd_support (CSN1Bit): 1><e_utra_tdd_support (CSN1Bit): 1><e_utra_measurement_and_reporting_support (CSN1Bit): 1><priority_based_reselection_support (CSN1Bit): 1><utra_csg_cells_reporting (CSN1Bit): 0><vamos_level (CSN1Bit): 0><tighter_capability (CSN1Bit): 0><selective_ciphering_of_downlink_sacch (CSN1Bit): 0>]>><SuppCodecs : <T : 64><L : 8><SuppCodecList : <SuppCodec : <SysID : 4><BMLen : 2><CodecBM : 0b0110000000000000>><SuppCodec : <SysID : 0><BMLen : 2><CodecBM : 0b0001111100000000>>>><AddUpdateType [transparent] : <T : 15><V : 0>><VoiceDomPref : <T : 93><L : 1><VoiceDomPref : <spare : 0><UEUsage : 0 (Voice centric)><VoiceDomPref : 0 (CS Voice only)>>><DeviceProp [transparent] : <T : 13><V : 0>><OldGUTIType [transparent] : <T : 14><V : 0>><MSNetFeatSupp [transparent] : <T : 12><V : 0>><TMSIBasedNRICont [transparent] : <T : 16><L : 2><V : 0x0000>><T3324 [transparent] : <T : 106><L : 1><V : 0x00>><T3412Ext [transparent] : <T : 94><L : 1><V : 0x00>><ExtDRXParam [transparent] : <T : 110><L : 1><V : 0x00>>>, 0)

This is the Attach request NAS message that I parsed through pycrate. Can you give a packaged example?

Weird behavior when parsing a SCCP payload and trying to extract GT

Hello,

When parsing a SCCP payload:

from pycrate_mobile.SCCP import parse_SCCP

sccp, _ = parse_SCCP(bytes.fromhex('0901030e190b12080012041491500050440b12080012042143650070055e625c4804000200006b1a2818060700118605010101a00d600ba1090607040000010019026c38a13602010102012e302e800589674523f18406a121436587f9041d24090421436587f90400819071516363000ce7f79b0c6abfe5eeb4fb0c'))

If we try to print the verbose representation of a Calling or Called Party Address structure, we can see that four "GT" objects are contained at the same level, three of which are called "GT [transparent]" (I guess that this is meant to correspond to the four existing types of GTs, of which one may be used at a time as a Calling or Called address):

>>> print(sccp['CalledPartyAddr'])
<CalledPartyAddr : <Len : 11><Value : <AddrInd : <res : 0><RoutingInd : 0 (route on GT)><GTInd : 4 (global title includes translation type, numbering plan, encoding scheme and nature of address indicator)><SSNInd : 1><PCInd : 0>><PC [transparent] : 0><SSN : 8 (mobile switching centre (MSC))><GT [transparent] : <OE : 0 (even number of address signals)><NAI : 1 (subscriber number)><Addr : >><GT [transparent] : <TranslationType : 0><Addr : 0x>><GT [transparent] : <TranslationType : 0><NumberingPlan : 1 (ISDN/telephony numbering plan (ITU-T E.163 and E.164))><EncodingScheme : 1><Addr : ><Addr [transparent] : 0x>><GT : <TranslationType : 0><NumberingPlan : 1 (ISDN/telephony numbering plan (ITU-T E.163 and E.164))><EncodingScheme : 2><spare : 0><NAI : 4 (international number)><Addr : 411905000544><Addr [transparent] : 0x>>>>

Only the used type is displayed when we print a prettified representation with show():

>>> print(sccp['CalledPartyAddr']['Value'].show())
### Value ###
 ### AddrInd ###
  <res : 0>
  <RoutingInd : 0 (route on GT)>
  <GTInd : 4 (global title includes translation type, numbering plan, encoding scheme and nature of address indicator)>
  <SSNInd : 1>
  <PCInd : 0>
 <SSN : 8 (mobile switching centre (MSC))>
 ### GT ###
  <TranslationType : 0>
  <NumberingPlan : 1 (ISDN/telephony numbering plan (ITU-T E.163 and E.164))>
  <EncodingScheme : 2>
  <spare : 0>
  <NAI : 4 (international number)>
  <Addr : 411905000544>

However, when trying to obtain the string, we obtain an empty entry instead of the actual GT (here 411905000544):

>>> print(sccp['CalledPartyAddr']['Value']['GT'].show())
### GT [transparent] ###
 <OE : 0 (even number of address signals)>
 <NAI : 1 (subscriber number)>
 <Addr : >

>>> sccp['CalledPartyAddr']['Value']['GT']['Addr']
<Addr : >

Is this normal? Is there a way to retrieve the actual GT programatically?

Regards

Empty sequence are wrongly serialized in UPER

A Sequence with only an extension marker is somehow ignored in unaligned PER

Pycrate versions

  • pycrate-0.2
  • pycrate-0.3

Steps to reproduce

The following ASN.1 definition reproduce the bug:

BEGIN
OneByteMessage ::= SEQUENCE {
      fourBits   INTEGER (0..15),
      oneBit     SEQUENCE {...},
      threeBits BIT STRING (SIZE(3))
  }
END

Using pycrate with the following test set:

test = {'fourBits': 15,
    'oneBit': {},
    'threeBits': (7,3)
}

Results in 0xFE where it should have been 0xF7.
The first four bits are indeed set to 0xF in both cases, but then with pycrate the oneBit field is elided and we find the threeBits set to 0b111 which makes the 0xE.

Expected result can be checked at asn1-playground by using the following data to encode:

data OneByteMessage ::= 
{  
    fourBits   15,
    oneBit     {},
    threeBits '111'B
}

Compatibility with Python 3.6

I could use the ASN.1 compiler fine with Python2.7 but faced following issues with Python3.6

In pycrate/tools/pycrate_asn1compile.py line 157: I had to change it from fd = open(f) to fd = open(f, 'rb') to read all the input files

I still got
Traceback (most recent call last):
File "pycrate/tools/pycrate_asn1compile.py", line 185, in
sys.exit(main())
File "pycrate/tools/pycrate_asn1compile.py", line 173, in main
compile_text(txt, **ckw)
File "/home/ec2-user/anaconda3/lib/python3.6/site-packages/pycrate_asn1c/asnproc.py", line 209, in compile_text
raise(ASN1Err('[proc] need only textual definition'))
pycrate_asn1c.err.ASN1Err: [proc] need only textual definition

solidify static datasets

There is several instances of using huge named tuples/dicts mixed in with python files. moving this data to a representation such as CSV or BSON and caching (Ahead-of-time if pycrate can support asynchronous execution [python 3.6+]) when called would boost performance and make importing/navigating a namespace easier.

NGAP (3GPP -38413) - Failure while decoding APER encoded hex string

I've ngap data that is being encoded by another c++ asn compiler OSS (Nokalava) - 0000040082000a0c1dcd6500301dcd6500008b000a01f00a0a0b0b0800000200860001000088000700010000052d00

But I'm getting following error while decoding it:
import NGAP from binascii import hexlify, unhexlify PDU = NGAP.NGAP_PDU_Descriptions.NGAP_PDU p = "0000040082000a0c1dcd6500301dcd6500008b000a01f00a0a0b0b0800000200860001000088000700010000052d00" PDU.from_aper(unhexlify(p)) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/root/Umakant/n1n2Decoder/compiler/pycrate-master/pycrate_asn1rt/asnobj.py", line 1190, in from_aper self._from_per(char) File "/root/Umakant/n1n2Decoder/compiler/pycrate-master/pycrate_asn1rt/asnobj_construct.py", line 247, in _from_per Cho._from_per(char) File "/root/Umakant/n1n2Decoder/compiler/pycrate-master/pycrate_asn1rt/asnobj_construct.py", line 795, in _from_per Comp._from_per(char) File "/root/Umakant/n1n2Decoder/compiler/pycrate-master/pycrate_asn1rt/asnobj_ext.py", line 309, in _from_per val = ASN1CodecPER.decode_unconst_open(char, wrapped=Obj) File "/root/Umakant/n1n2Decoder/compiler/pycrate-master/pycrate_asn1rt/codecs.py", line 864, in decode_unconst_open wrapped.from_aper(char) File "/root/Umakant/n1n2Decoder/compiler/pycrate-master/pycrate_asn1rt/asnobj.py", line 1190, in from_aper self._from_per(char) File "/root/Umakant/n1n2Decoder/compiler/pycrate-master/pycrate_asn1rt/asnobj_construct.py", line 767, in _from_per E = char.get_uint(1) File "/root/Umakant/n1n2Decoder/compiler/pycrate-master/pycrate_core/charpy.py", line 776, in get_uint .format(bitlen, self._len_bit-self._cur))) pycrate_core.charpy.CharpyErr: bitlen overflow: 1, max 0
Any idea what's wrong here?
Compiled Python Library - https://raw.githubusercontent.com/P1sec/pycrate/master/pycrate_asn1dir/NGAP.py

ServerAuC make_4g_vector() function

Hi,
I'm trying to generate the authentication vector using this function, but I got the following error:

  • global name "xor_buf" is not defined
    where can I find the function implementation?

Thanks in advance!

[pycrate_asn1rt] Converting a Pycrate object into a dict makes ASN booleans into Python integers, but "set_val" expects a Python boolean

When an user calls pycrate_object.set_val(python_dictionary) in order to serialize back a Python dictionary into a given Pycrate object, and some field in the given dictionary corresponds to an ASN.1 boolean, we check whether the corresponding value in the dictionary is a Python boolean in the pycrate_asn1rt.asnobj_basic.BOOL._safechk_val function, and raise an error otherwise.

However, when converting a Pycrate object (produced from parsing a raw UPER payload) to a Python dictionary by doing pycrate_object(), the resulting dictionary will contain a Python integer with the value 0 or 1 instead of proper Python boolean.

Because of this, the Python dictionary produced by doing python_dictionary = pycrate_object() can't be fed back to the dictionary when calling pycrate_object.set_val(python_dictionary).

Sample code to reproduce the issue:

from pycrate_asn1dir import RRC3G

pycrate_object = RRC3G.Class_definitions.UL_DCCH_Message

pycrate_object.from_uper(b'K\x88\x00\x02\xa0\x00\x142\xaa\xd5\x06\xa5V\xa8\x8aH0D\x80\x01\x80\x01\x10\x0c\xc0\xd5\xd6)\x92\xc0(\t\x9e\xcaF\x04<H\t\x98B1\xee\x89\x9e\xbbe\xea\x11\x8ftL\xf5\xdb/=\xc3\x88!(u\xd0\xd13\xd7l\xb2\x00t\x072\xc6\xa0I\xed!\x17\xe4\x8a5\x92\x00\xa6\x06\x81')

python_dict = pycrate_object()

print(python_dict)

pycrate_object.set_val(python_dict)

Produced behavior: pycrate will complain that a dictionary field that should be boolean while it is an integer (not always on the same field, likely because we iterate over an unsorted dictionary somewhere):

>>> pycrate_object.set_val(python_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj.py", line 631, in set_val
    self._safechk_val(self._val)
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 566, in _safechk_val
    self._cont[k]._safechk_val(val[k])
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 82, in _safechk_val
    self._cont[val[0]]._safechk_val(val[1])
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 566, in _safechk_val
    self._cont[k]._safechk_val(val[k])
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 566, in _safechk_val
    self._cont[k]._safechk_val(val[k])
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 566, in _safechk_val
    self._cont[k]._safechk_val(val[k])
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 566, in _safechk_val
    self._cont[k]._safechk_val(val[k])
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 1946, in _safechk_val
    self._cont._safechk_val(v)
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 566, in _safechk_val
    self._cont[k]._safechk_val(val[k])
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 566, in _safechk_val
    self._cont[k]._safechk_val(val[k])
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 1946, in _safechk_val
    self._cont._safechk_val(v)
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_construct.py", line 566, in _safechk_val
    self._cont[k]._safechk_val(val[k])
  File "/usr/local/lib/python3.5/dist-packages/pycrate_asn1rt/asnobj_basic.py", line 139, in _safechk_val
    raise(ASN1ObjErr('{0}: invalid value, {1!r}'.format(self.fullname(), val)))
pycrate_asn1rt.err.ASN1ObjErr: CompressedModeMeasCapabFDD.dl-MeasurementsFDD: invalid value, 1

A functional workaround is that we can add a line casting the value returned when doing pycrate_object() to a boolean (self._val = bool(self._val)) to the pycrate_asn1rt.asnobj_basic.BOOL._from_per function.

However, this seems not optimal, because

  • It does not seem consistent with the intent to perform this conversion through a look-up table (there is likely an error with the present code)
  • It does not make that we accept integers when inputting back a Python dictionary into a Pycrate object, which could be a desirable feature

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.