IMSIs shorter than 15 are not encoded properly
When programming a (sysmoUSIM-SJS1) SIM with an IMSI shorter than 15, the encoded format isn't correct.
This is demonstrated in two ways:
1) pySim-read.py fails to read the IMSI back (private details removed):
[ben@thoth pysim]$ ./pySim-prog.py -p 0 -t sysmoUSIM-SJS1 -a $adm -n $name -x 1 -y 1 -i 00101234567 -s $iccid -o $opc -k $ki Insert card now (or CTRL-C to cancel) Generated card parameters : > Name : $name > SMSP : --- > ICCID : $iccid > MCC/MNC : 1/1 > IMSI : 00101234567 > Ki : $ki > OPC : $opc > ACC : None Programming ... Done ! [ben@thoth pysim]$ ./pySim-read.py -p 0 Reading ... ICCID: $iccid Traceback (most recent call last): File "./pySim-read.py", line 100, in <module> print("IMSI: %s" % (dec_imsi(res),)) File "/home/ben/pysim/pySim/utils.py", line 65, in dec_imsi oe = (int(swapped)>>3) & 1 # Odd (1) / Even (0) ValueError: invalid literal for int() with base 10: 'f'
2) Our Essential PH-1s running Android 7.1.1 don't detect the SIM programmed this way.
I believe the issue occurs because of a misunderstanding of the TS 31.102 spec regarding IMSI encoding.
The two relevant parts are:
the length indicator refers to the number of significant bytes, not including this length byte, required for the IMSIand
if a network operator chooses an IMSI of less than 15 digits, unused nibbles shall be set to 'F'.
The current code base left pads with F, which I think should be right padded instead.
It also encodes the length as half the number of digits in the IMSI (rounded up). This isn't correct for even length IMSIs.
With even length IMSIs, the odd/even parity bit bumps the last digit into an extra byte, which should be counted as well.
I have attached a patch which fixes both of these issues, and also fixes decoding IMSIs with this encoding.
Using this patch, I have tested shorter IMSIs (both even and odd length) on the Essential phone mentioned above, as well as an iPhone 6.
In both cases, the S1 InitialUEMessage now contains the correct IMSI.