Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sc_get_response() behavior with multiple GET RESPONSE #131

Closed
hongquan opened this issue Feb 25, 2013 · 10 comments
Closed

sc_get_response() behavior with multiple GET RESPONSE #131

hongquan opened this issue Feb 25, 2013 · 10 comments

Comments

@hongquan
Copy link
Contributor

Hello,

I have difficulty geting response data from card when the card only
support shorts APDU and have to use multiple GET RESPONSE commands, done
internally by sc_transmit_apdu and sc_get_response functions.

Because I don't know how big returned data will be, I set apdu.resplen
to a maximum number (say 2048), but after getting enough data (actual
length is less than 2048), the sc_get_response() still try to acquire
more and fall to "6D 00" error.

If I set apdu.resplen = 256, sc_get_response() stop when 256 bytes data
was got, regardless there is still more data.

How can I make sc_get_response() stop right after it receives "90 00"
from card?

I'm working with OpenPGP card in Gnuk device.

@viktorTarasov
Copy link
Member

If card still has data to return, it should return status value 61xx (6100 if more then 256) .
If so,
get-response() will read all (or 'resplen' bytes) the data until it receives 9000 .

@hongquan
Copy link
Contributor Author

The problem is that it does not stop right at 90 00.
After receive 90 00, it still request for more data from card. Please see at https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/apdu.c#L500

As long as minle > 0 (last apdu.le - this apdu.resplen), the function still request for data.

@viktorTarasov
Copy link
Member

"For me it works."

Are you implementing your own get-response() handle ?
What 'main' command (followed by get-response) are you using ?
What is the real size that you are getting (is it multiple of 256 ?).

The standard get-response handle (from iso7816.c) returns the number of bytes that are still to be read.
That's why you have to look not
https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/apdu.c#L500
but
https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/apdu.c#L496
and
https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/apdu.c#L503

@hongquan
Copy link
Contributor Author

Are you sure you tested with the card supporting short APDU only? This problem is not revealed when extended APDU is used.
The

minlen = minlen - le;

at https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/apdu.c#L496 is not always = 0, so the

while (rv != 0 || minlen != 0);

at https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/apdu.c#L503 is true and the loop continues.
Why minle is not always = 0?
That's because there is some cases that le < minle, because le variable at this step is the actual response length:

    rv = card->ops->get_response(card, &resp_len, resp);
...
    le = resp_len;

(https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/apdu.c#L483)
which maybe < 256, while minle == 256 because minle was assigned with APDU expected length Le before

le = apdu->sw2 != 0 ? (size_t)apdu->sw2 : 256;
minlen = le;

https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/apdu.c#L463.
(Note that that le variable is used inconsistently)

Are you implementing your own get-response() handle ?
What 'main' command (followed by get-response) are you using ?

No, I just use sc_transmit_apdu() to read data, and this function in turn calls sc_get_response().

What is the real size that you are getting (is it multiple of 256 ?).

More than 256 but not multiple of 256. In fact, the total response length is 270, via two GET RESPONSE (inside sc_transmit_apdu()) if I pre-set exactly 270 for buffer length.
If I set buffer length longer, there is 1 loop that:

resplen = 14
minle = 256 - 14 = 242

and one more GET RESPONSE is sent.

@viktorTarasov
Copy link
Member

Sorry, I still do not understand what are you doing.
Probably logs will help?

resplen = 14
minle = 256 - 14 = 242

How can it be possible?

If resplen is 14 (<256),
it means that the previous command (or do{}while cycle of get-response) returned 610E.

It means that:
in previous do{}while cycle rv was 14, and at the end of this previous cycle le =minlen = 14,
or, if the 'get-response()' is called only once, to get the rest from previous, not 'get-response()' command,
minlen is 14 because of

le = apdu->sw2 != 0 ? (size_t)apdu->sw2 : 256;
minlen = le;

And so in the last get-response do{}while cycle it has to be:

resplen = 14
minle = 14- 14 = 0

@hongquan
Copy link
Contributor Author

it means that the previous command (or do{}while cycle of get-response) returned 610E.

This is the point of problem: My card (Gnuk) always return 6100, no matter how much data remain. So

le = apdu->sw2 != 0 ? (size_t)apdu->sw2 : 256;

always yield 256.
About the log, I will recreate later (I had to put many logging line to track le, minle but now I has removed all of them).

@viktorTarasov
Copy link
Member

As for me, it's not standard behavior.
Probably you have implement your own card specific get-response().

@hongquan
Copy link
Contributor Author

Thank Viktor,
I will contact Gnuk's author for this problem.

@viktorTarasov
Copy link
Member

Attempt to use standard common routines for the non-standard card.

@hongquan
Copy link
Contributor Author

Of course I use standard common routine, which is sc_transmit_apdu() (I don't call directly sc_get_response(), but sc_transmit_apdu() does).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants