Use READ BINARY to read more than 256 bytes

偶尔善良 提交于 2019-12-28 17:45:13

问题


I am trying to read a smartcard(German Gesundheitskarte) using javax.smartcardio

In the definition of the EF "PD" its length is specified as 850 bytes. The content should be a gzipped ISO5589-15 encoded XML string as specified here

As CommandAPDU I send

00 B0 00 00 00

to get the first 256 bytes. After sending

00 B0 00 FF 00

I get the next 256 bytes.

But how do I get the rest?

How will I know when the binary data ends?

German Specification Part 1 | German Specification Part 2


回答1:


READ BINARY APDUs allow 2 bytes for the file offset, coded in P1 and P2, and use Le for the length, for READ BINARY the number of bytes in the response. P1 is the high byte, or the most significant byte. The topmost bit of P1 is however reserved to indicate if P1 also contains a short file identifier. It should remain at value 0 if you are already reading a file, leaving you with a maximum offset of 32Ki - 1.

I can't read the specs that you've linked but let's assume that the READ BINARY APDU on your card works the same way.

Your command to read the first 256 bytes seems correct, noting that Le==0x00 indicates a read for 256 bytes.

To read the bytes beginning at offset 256, 512, etc., start incrementing P1, e.g.:

00 B0 01 00 00
00 B0 02 00 00
00 B0 03 00 00

To read 256 bytes beginning at offset 257 (0x101):

00 B0 01 01 00

Offset 600 (0x258):

00 B0 02 58 00

In your code, if you're using Java int to store the offset, you'll usually end up incrementing P1 with something like this:

int offset;
int P1, P2;

while (continueReading)
{
    // ...
    P1 = (offset >> 8) & 0xFF;
    P2 = offset & 0x00FF;
    // ...
    // send APDU
}

How the size of a file is indicated depends on the implementation. Usually you can get the file size from the File Control Information (FCI) structure returned by a SELECT on the EF (00 A4 00 00 02 fileId). The size of the file may however also be embedded in the contents of the file. If possible you should not rely on status words to tell you the size of the file.


Addition: Le, Ne and odd INS

It's important that you only increase the offset with the amount of bytes that you actually receive within the response data (RDATA). Note that if P3 = Le that Le encodes Ne, which is the maximum size of the response data. You may receive less than that.

If the file size is 32Ki or more then you need to use READ BINARY with odd INS (B7) to read the data above 32Ki. In that case the RDATA may also contain overhead. Obviously that - in turn - may influence the offset calculations and the calculations to read to then end of the file.




回答2:


The offset is in P1 & P2, although the highest bit is used to indicate that you want to select something with a given SFI. So you can use P1 as well for the bytes. After that you will have to move towards READ BINARY with an odd INS (B1).

So you can read up to 2^15 - 1 bytes using the normal read binary. That's 32Ki - 1. And of course an additional few bytes because of the returned bytes by the APDU.

I would always read out files from smart cards using the following method: 1 determine file size, e.g. using the FCI (File Control Information) returned with a SELECT by FILE ID (00 A4 02 00 02 ${FILE_ID}), you need to parse the response. Then increase the offset by the number of returned bytes each time. Never ask more than the maximum file size, as the behaviour of most cards differs, is not defined or just plain wrong).

Advanced topic: If you use READ BINARY with ODD INS, you need to substract the header of the DO each time you increase the offset. In that case reading up to the end becomes a bit troublesome because you would need to add the overhead of the header to the Le byte.




回答3:


A small addition to the IMO very helpful answer by Maarten Bodewes about reading larger files, and the suggestion by stajo to use extended Le. I hope this saves others some time and effort.

Trying to use Le for long reads is tricky:

  • Extended Le requires to use extended Lc as well.
  • Extended Lc must not be 0, according to the standard, so you cannot start at offset 0
  • And if your Lc is not 0, you need to use the "B1" INS.
  • The B1 then makes it a bit more complicated to calculate the correct sizes, as Maarten Bodewes explained.

In addition to that, you need to find out first whether the card supports extended Lc/Le at all; the information about this is spread over the ATR historical bytes, the EF.ATR, and the current EF info.

So while it is possible in theory to read large batches of data from a single file, it is a lot of effort in practice, and you cannot do read the entire file with one command either.

Consider above before you take the effort to use extended Le for reading.




回答4:


if the card supports it you probably can use the extended length format. if you specify 00 in the lc/le field you can use two following bytes for the length



来源:https://stackoverflow.com/questions/11297880/use-read-binary-to-read-more-than-256-bytes

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!