Hello Osmocom community,
Has anyone here ever played with the RFM (Remote File Management) feature on sysmoUSIM-SJS1 and sysmoISIM-SJA2 cards? I know that a lot of people play with RAM (Remote Application Management) for installing Java applets, but I am more interested in RFM for doing a different kind of OTA programming - I am seeking to recreate the workflow of traditional GSM network operators where "blank" (not yet activated, but ready to activate) SIM cards sit on store shelves with their IMSI and secret keys (Ki/K/OPc etc) already programmed at the factory, but blank EF_MSISDN because the future user's phone number is not known yet. Customers activate these SIMs by reading the ICCID from the card to customer service over the phone, or salespeople in stores scan the ICCID barcode - and then the operator's customer management system matches that ICCID with its knowledge of the IMSI and secret keys, and the service gets activated on the new SIM. And then the operator's network uses SMS-PP SIM data download to program the EF_MSISDN record in the newly activated SIM - I know full well that a phone does not need to know its own MSISDN to make and receive calls, but every classic GSM dumbphone has a menu command for "Show my number" or whatever it's called, this command displays the MSISDN record from the SIM, and traditional operators program this record OTA so that this menu command will work. I am seeking to recreate this OTA programming step.
I just got the needed KI[CD][23] OTA keys for my sysmoUSIM-SJS1 cards (thanks Sysmocom support!), and I am able to exercise RFM successfully on these cards by uncommenting these lines in the shadysim.py script:
# for RFM testing ac.test_rfm() exit(0)
It appears that the "tribal" knowledge (not written in any formal document, AFAICT) of how to use the RFM feature on sysmoUSIM-SJS1 cards exists only in the following code stanzas in shadysim.py, code that never executes unless you uncomment that ac.test_rfm() call:
def send_wrapped_apdu_rfm_sim(self, data): # TAR RFM SIM: B00010, sysmoSIM SJS1: MSL = 6, second keyset return self.send_wrapped_apdu_internal(data, 'B00010', 6, 2, 2)
def send_wrapped_apdu_rfm_usim(self, data): # TAR RFM USIM: B00011, sysmoSIM SJS1: MSL = 6, third keyset return self.send_wrapped_apdu_internal(data, 'B00011', 6, 3, 3)
It was only thanks to the above code lines and comments that I learned that I need to use keyset 2 for SIM RFM, and how else would we know the needed magic TAR if not for the above code and comments?
In any case, the RFM test function of shadysim.py works like a charm on my sysmoUSIM-SJS1 cards with the right keys (successfully displays the IMSI read out via RFM), and I am now going to work on my own C code that will replace Python and do what I need. However, I also tried the exact same shadysim.py RFM test function on the newer sysmoISIM-SJA2 cards, and it does NOT work. I run the exact same shadysim.py (modified only to uncomment the RFM test) that works against sysmoUSIM-SJS1, but when I run it against sysmoISIM-SJA2 and specify the respective card's KIC2 and KID2 from the webshop key data email, I get this output:
ICCID: 8988211000000471501f ('', '')
Here is the output with a good sysmoUSIM-SJS1:
ICCID: 8988211000000386808f ('089910070000306808', '9000')
Given that the code stays exactly the same and I am merely specifying different keys as needed for each card, there must be something different about the new sysmoISIM-SJA2 cards with respect to RFM. Perhaps the TAR is different? Perhaps the association of which keyset goes for what is different? Some other differences like different crypto algorithms being used? Perhaps a migration from 3DES to AES?
I am fine with just using sysmoUSIM-SJS1 for development of my C tools (tools which will hopefully be extended later to work with other vendors' SIMs beyond just Sysmocom), but it would be nice to fill in the knowledge gap regarding sysmoISIM-SJA2 and get these cards to work as well.
In hacking fellowship, Mother Mychaela
Hello again everyone,
The mystery I reported this morning regarding the test_rfm function of shadysim.py working on sysmoUSIM-SJS1 but not on sysmoISIM-SJA2 has been solved. I have written my own suite of C tools to replace the Python tool for my purposes, and in the process of studying the Python code for the purpose of recreating its logic in C I found the bug that makes the original code not work with the new SIMs.
The bug is in the padding logic. When the application message payload is encrypted with any variant of DES (including the two-key 3DES used on Sysmocom SIMs), the length of the ciphertext has to be a multiple of 8 bytes - hence if the plaintext length is not a multiple of 8 bytes, the plaintext needs to be padded. But what should happen if the plaintext length going into the cipher just happens to be a perfect multiple of 8 bytes? The correct answer (ought to be obvious) is to apply no padding at all, i.e., zero bytes of padding. However, the Python code in shadysim.py adds 8 bytes of padding, and sets the number of padding bytes in the header to 8. The resulting encrypted message should be considered malformed per standard specs, but sysmoUSIM-SJS1 cards are liberal in what they accept in this instance, thus the bug went unnoticed. The newer sysmoISIM-SJA2 cards do not accept such malformed messages with invalid padding, and it just so happens that the message generated by the test_rfm function has 40 bytes of plaintext going into the cipher, perfectly divisible by 8 - hence the test_rfm function fails on the new cards.
I am not able to produce a patch for shadysim.py because Python is a read-only language for me: I can kinda-sorta read Python code and figure out what it's doing, so I can reproduce its logic in C or Bourne shell (my two languages), but writing or modifying Python code is a territory I don't feel ready to venture into.
My new C tools for OTA SIM programming which do work with both sysmoUSIM-SJS1 and sysmoISIM-SJA2 cards reside here:
https://www.freecalypso.org/hg/fc-ota-tools/
These tools go as far as generating the hex string of bytes to feed to the SIM in an ENVELOPE command; to actually interact with the SIM in a CCID "reader" and send this ENVELOPE command, fc-simtool needs to be used:
https://www.freecalypso.org/hg/fc-pcsc-tools/
In hacking fellowship, Mother Mychaela
Hi Mychaela,
On 2/22/21 3:48 AM, Mychaela Falconia wrote:
I am not able to produce a patch for shadysim.py because Python is a read-only language for me: I can kinda-sorta read Python code and figure out what it's doing, so I can reproduce its logic in C or Bourne shell (my two languages), but writing or modifying Python code is a territory I don't feel ready to venture into.
thanks for your detailed report, I have submitted a bugfix:
https://git.osmocom.org/sim/sim-tools/log/?h=fixeria/fixes
Please let us know if it works for you, so we'll merge it to master.
I hope you don't mind that I copy-pasted some sentences from your original message into the commit description.
Best regards, Vadim.
Hi Vadim,
thanks for your detailed report, I have submitted a bugfix:
LGTM.
Please let us know if it works for you, so we'll merge it to master.
I have tested the PoC test_rfm() function in your new version, and it now emits packets that are 8 bytes shorter than before, matching what my own ota-smswrap-sjs1 C-language utility generates. The new way works with both sysmoUSIM-SJS1 and sysmoISIM-SJA2, using each card's respective different keys from webshop emails. KIC2 and KID2 are the keys needed for this operation.
Please note, however, that the only feature of shadysim.py I ever tested (both before and after your fix) is the test_rfm() function which can only be exercised by editing the code to uncomment the two lines that invoke it and exit - there is no command line option for this function, which itself is of course nothing more than a PoC. I have never exercised this program's main intended function of manipulating Java card applets - at the present moment I have no need for those, and I don't know when (if ever) I will get to play with STK and Java applets for it - right now there are too many other areas of GSM that are more interesting to me. :)
I hope you don't mind that I copy-pasted some sentences from your original message into the commit description.
Sure thing - technical knowledge is meant to be shared and reproduced in different media and fora.
In other SIM card news, it looks like Grcard folks (back from their LNY holidays) are reshipping their sample cards to me via a different route (going through HK this time), thus there is a chance that I might finally receive them this week or the next. I am very anxious to find out if they are the same card platform as the short-lived sysmoSIM-GR2, or if it's a newer evolutionary revision given how many years have passed - given that they once made the evolutionary change from GR1 to GR2, we have every reason to expect that other evolutionary changes have followed since then. One of the features I hope to see included on these new cards is RFM - I will be perfectly fine with a non-Java card with no ability to install applications, but I do desire RFM - being able to write the MSISDN record OTA like real operators do is just so cool!
Would anyone happen to know if the short-lived historical sysmoSIM-GR2 cards supported RFM or not? I reason that GR1 cards probably lacked this feature, but I do wonder about GR2.
In hacking fellowship, Mother Mychaela