Toporin / SatochipApplet

The open source hardware wallet smartcard - Satochip.io
https://satochip.io/shop
GNU Affero General Public License v3.0
117 stars 42 forks source link

Wrong behavior on spurious Select #11

Open antonio-fr opened 10 months ago

antonio-fr commented 10 months ago

When selecting an non-installed AID on a card, after selecting this applet, the applet returns NoError/0x9000 to this command. This confuses some systems as this indicates this selected AID is present and was selected, but it is actually not.

Communication Log This card has the Satochip applet (5361746F4368697000), and nothing else.

 Sending 0xA4 command with 9 bytes data
  with Le=256
-> 00 A4 04 00 09 53 61 74 6F 43 68 69 70 00 00
 Received 0 bytes data : SW 0x9000 - 23.4 ms
 Sending 0xA4 command with 16 bytes data
  with Le=256
-> 00 A4 04 00 10 FF 4C 45 47 52 2E 57 41 4C 54 30 31 2E 49 30 31 00
 Received 0 bytes data : SW 0x9000 - 8.9 ms

This indicates the selection of the last AID was performed successfully. But in fact, the card keeps the same Satochip applet selected, and there's no such AID available on the card.

The practical issue is with the Uniblow wallet. When a user selects a device, it tries to connect to all card readers and if there's a card, it selects the specific AID. If the Select response is OK, it assumes it has found the chosen device, and it marks the device as available and connected. If a user has a Satochip connected, selects the Satochip applet, then selects an other smartcard-based device, the wallet mistakes the Satochip for this other device. Because the Satochip replies OK for this other AID selection. So Uniblow thinks it has found the other device. Then the following command to this -wrong- device returns CLANotSupported/0x6E00, and that leads to an uncaught exception which is displayed to the user "Error : 6E00".

In internal details, the JavaCard runtime routes any Select command with an unknown AID to the current applet. That is called spurious select. When sending a select for a not-installed applet, the JC system calls the process method of the currently selected applet. So this applet is responsible to process this Select command. An application, whether explicitly or implicitly selected, is responsible for correctly managing spurious SELECT commands. The selectingApplet() method returns false, so the application must first determine if it has knowledge on how to handle the particular SELECT command, else it must return an error.

The fact that the AID doesn't not exist, and the select command was not performed must be stated by the Satochip applet by answering an error status (not 0x9000). There are several possibilities to change the 9000 behavior :

The culprit is here https://github.com/Toporin/SatochipApplet/blob/31222b0a65e96a0c14d840ff77ffa3b6fe5771ba/src/org/satochip/applet/CardEdge.java#L614

Toporin commented 10 months ago

Thanks for the notification! I was able to reproduce the issue.

From preliminary testing, this patch would solve this issue:

if ((buffer[ISO7816.OFFSET_CLA] == 0) && (buffer[ISO7816.OFFSET_INS] == (byte) 0xA4))
-            return;
+            ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND); // spurious select