philipWendland / IsoApplet

A Java Card PKI Applet aiming to be ISO 7816 compliant
GNU General Public License v3.0
165 stars 72 forks source link

Error when reading file using GET RESPONSE APDU #12

Closed mjspier closed 7 years ago

mjspier commented 7 years ago

I stumbled upon a strange behaviour. The bug only occurs with the oberthur card on Windows. It seems some cards have different types of reading the data from the card. It also seems that this behaviour depends on the driver.

Setup:

Scenario:

Problem: With other cards or on Linux, it works. I see the problem is reading the pkcs15 file which holds the reference information about the RSA keys. With other cards or on Linux, the file is read by a select command and several read binary commands:

out: 00 A4 08 00 04 50 15 44 02 00 in: 6F 15 81 02 02 00 82 01 01 83 02 44 02 86 08 FF 90 90 90 90 90 90 00 90 00

out: 00 B0 00 00 00 in: 00 00 ...... 90 00 (the data)

out: 00 B1 00 00 00 in: 00 00 ...... 90 00 (more data)

But with the oberthur card on Windows, it tries to read the data with help of Get Response APDUs. The select command does not return the data but the amount of data which can be read.

out: 00 A4 08 00 04 50 15 44 02 in: 61 17

out 00 C0 00 00 17 in: 6F 15 81 02 02 00 82 01 01 83 02 44 02 86 08 FF 90 90 90 90 90 90 00 90 00

The same should happen now when the file is read. The read binary commands should not return the data but only a number of how much data to read. But this is not the case. The data is returned also in the read binary command but with the response code that data needs to be read from the cache.

out: 00 B0 00 00 00 in: 00 00 ...... 61 00 (the data but with response code 61)

out: 00 C0 00 00 00 (try to read the data in the cache) in: 00 00 ..... 90 00 (wrong data returned, all 00)

Try to read second part out: 00 B1 00 00 00 in: 6F 00 (error)

I'm not sure why the second read binary command returns an error in this case. But anyway I think the read binary commands should not return any data but only the number of how much data needs to be retrieved by the get response command.

philipWendland commented 7 years ago

I see the problem is reading the pkcs15 file which holds the reference information about the RSA keys. With other cards or on Linux, the file is read by a select command and several read binary commands:

This is how it should be done. I don't have ISO7816 at hand right now, but IIRC, READ BINARY should be performed using different offsets in P1/P2 - and not by using GET RESPONSE.

out: 00 A4 08 00 04 50 15 44 02 in: 61 17

The card wants to return the FCI. The command APDU in this case is a case 3, where it should be case 4 (See the missing Le byte). Can you debug why this happens in Windows?

I'm not sure why the second read binary command returns an error in this case. But anyway I think the read binary commands should not return any data but only the number of how much data needs to be retrieved by the get response command.

I don't see why READ BINARY should not return data. But the response code should be 9000, not 6100. The applet itself never returns 61XX on a READ BINARY. Where is this coming from?

philipWendland commented 7 years ago

Also, why is there a B1 instruction? See: https://github.com/philipWendland/IsoApplet/blob/master/src/net/pwendland/javacard/pki/isoapplet/IsoFileSystem.java#L652

This was never implemented in IsoApplet, and never used.

martinpaljak commented 7 years ago

Getresponse is handled by jcre

On Sat, Jun 17, 2017, 12:06 Philip Wendland notifications@github.com wrote:

Also, why is there a B1 instruction? See:

https://github.com/philipWendland/IsoApplet/blob/master/src/net/pwendland/javacard/pki/isoapplet/IsoFileSystem.java#L652

This was never implemented in IsoApplet, and never used.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/philipWendland/IsoApplet/issues/12#issuecomment-309203367, or mute the thread https://github.com/notifications/unsubscribe-auth/AACzthRvO3BGuJlgEtNVxTuYMOoevoQlks5sE5b2gaJpZM4N8Wa7 .

--

typos expected due to mobile device

frankmorgner commented 7 years ago

Try forcing T=1 in opensc.conf

mjspier commented 7 years ago

Also, why is there a B1 instruction? See: https://github.com/philipWendland/IsoApplet/blob/master/src/net/pwendland/javacard/pki/isoapplet/IsoFileSystem.java#L652

This was never implemented in IsoApplet, and never used.

Sorry. That was a typo. Correct message is 00 B0 01 00 00

Try forcing T=1 in opensc.conf

Thanks for this advice. I added a section with the ATR from the card and force protocol. But it seems it ignores this configuration. Is there another way?

card_atr <hex encoded ATR (case-sensitive!)> {
        force_protocol = t1;
}
mjspier commented 7 years ago

Ok. Forcing the t1 protocol works actually. I had to set the registry in Windows to make it work.

@philipWendland I couldn't fully figure out where the 6100 return code is coming from. But the Applet does not return the 9000 code neither. I guess the APDU class implementation creates the return code according to the desired protocol. The difference in the applet I saw between the SELECT command and the READ_BINARY command is only the preparation of the APDU.

SELECT: Util.arrayCopy(data, 0, buf, 0, len); apdu.setOutgoingAndSend(0, len);

READ_BINARY: apdu.setOutgoingLength(le) apdu.sendBytesLong(fileData, offset, le)

It might be that the APDU implementation is wrong. Does each card implement this class or does this class come from the SDK?

frankmorgner commented 7 years ago

If the APDU sequence from OpenSC still differs from Windows to Linux (does it?), you might need to set max_recv_size and max_send_size for the reader. This information gets lost in some reader drivers.

philipWendland commented 7 years ago

It might be that the APDU implementation is wrong. Does each card implement this class or does this class come from the SDK?

It should be implemented in the card's firmware.

mjspier commented 7 years ago

@frankmorgner The APDU sequence from OpenSC is the same when T1 is forced.

Was just trying to solve the mystery why T0 worked for some commands but not for others. It could be possible that indeed the card firmware is the issue.

I will close the issue then, as it can not be solved in the Applet.

Fix: Force T1 protocol for the card ATR in opensc.conf. (make sure the registry is set in Windows)

martinpaljak commented 7 years ago

Well, it might still be useful to catch APDUException and check for https://docs.oracle.com/javacard/3.0.5/api/javacard/framework/APDUException.html#NO_T0_GETRESPONSE (what I suspect is the culprit here) and return something else instead of the final 6f00 And maybe carefully re-read the docs for APDU class and applet code, to make sure all the requirements are fulfilled.

philipWendland commented 7 years ago

Thanks everyone for contributing to this discussion. I forgot about it as it was closed.

@superbly I tried forcing T=0 in Linux with my G&D SCE 6.0 card, but had no issues. Do you have any new insights? You could surround the sendBytesLong() call with try, check for APDUException and try to find out the error coude, if you like.