P1sec / pycrate

A Python library to ease the development of encoders and decoders for various protocols and file formats; contains ASN.1 and CSN.1 compilers.
GNU Lesser General Public License v2.1
380 stars 130 forks source link

errors parsing OIDs in eUICC profile package #210

Closed laf0rge closed 1 year ago

laf0rge commented 1 year ago

I'm trying to parse [portions of] the eUICC test profiles at https://github.com/GSMATerminals/Generic-eUICC-Test-Profile-for-Device-Testing-Public.git

It seems pycrate fails every time there is an OID to be parsed. For example

header : {
  major-version 2,
  minor-version 1,
  profileType "GSMA Generic eUICC Test Profile",
  iccid '89000123456789012341'H,
  eUICC-Mandatory-services {
    usim NULL,
    isim NULL,
    csim NULL,
    usim-test-algorithm NULL,
    ber-tlv NULL
  },
  eUICC-Mandatory-GFSTEList {
    { 2 23 143 1 2 1 },
    { 2 23 143 1 2 3 },
    { 2 23 143 1 2 4 },
    { 2 23 143 1 2 5 },
    { 2 23 143 1 2 7 },
    { 2 23 143 1 2 8 },
    { 2 23 143 1 2 9 },
    { 2 23 143 1 2 10 },
    { 2 23 143 1 2 11 }
  }
}

from TS48 V2 eSIM_GTP_SAIP2.1_BERTLV.txt leads to

pycrate_asn1rt.err.ASN1ASNDecodeErr: ProfileElement.header.eUICC-Mandatory-GFSTEList._item_: invalid remaining OID definition,  2 23 143 1 2 1

when using pycrate_asn1dir.eUICCPP_IFTv2.PEDefinitions.ProfileElement.from_asn1() to parse

p1-bmu commented 1 year ago

Good catch. This is solved with https://github.com/P1sec/pycrate/commit/18f4e4485e2005cde90790811b95f2fa2c3c7b9c Thanks

laf0rge commented 1 year ago

Thanks. Strangely, with this fix applied I'm now getting the following behavior:

>>> asn_txt
'header : {\n  major-version 2,\n  minor-version 1,\n  profileType "GSMA Generic eUICC Test Profile",\n  iccid \'89000123456789012341\'H,\n  eUICC-Mandatory-services {\n    usim NULL,\n    isim NULL,\n    csim NULL,\n    usim-test-algorithm NULL,\n    ber-tlv NULL\n  },\n  eUICC-Mandatory-GFSTEList {\n  }\n}\n'
>>> PEDefinitions.ProfileElement.from_asn1(asn_txt)
''

so the from_asn1() method is not returning any object but just the empty string. no error/warning/info printed :/

p1-bmu commented 1 year ago

This is expected. When everything gets fine, you get no exception, and the value is stored within the object. See: https://github.com/P1sec/pycrate/wiki/Using-the-pycrate-asn1-runtime

laf0rge commented 1 year ago

This is expected. When everything gets fine, you get no exception, and the value is stored within the object. See: https://github.com/P1sec/pycrate/wiki/Using-the-pycrate-asn1-runtime

I was looking at that page but still don't seem to have understood it. I guess I would normally expect to either have to explicitly create an object/instance with () calling a constructor of a class, or if I simply call a staticmethod or classmethod which then returns an instance of the class.

So... looking at this in more detail:

How would one then work on multiple instances of the same ASN.1 definition at the same time (to represent multiple values of that type)?

Sorry for hijacking this issue for the discussion. If there's a better place for that, let me know.

p1-bmu commented 1 year ago

Yep, this ASN.1 runtime is not thread-safe. On the other side, Python has the GIL, and making multi-threaded applications in Python is quite rare I suppose. If you think you are in this case, then it's recommended to do a deepcopy of the object you are using for encoding / decoding : 1 per thread. See : https://github.com/P1sec/pycrate/issues/26

laf0rge commented 1 year ago

I'm not even thinking of any multi-threading. Just think you're writing some kind of gateway/translator that has to deal with multiple messages of the same type in one function. All from a single thread.