apdu

How to know if a SCard includes extra digit in hexa or not?


I have to read ICCID from cards and compare them if they are included in a shipment or not. I get a list of ICCID which should be includet in the shippment to sort out wrong cards.

Now as I tested different cards I once had a ICCID which was correct with what I had known from a list and with what I did read. But I also had a card hich had a "F" as last digit and the numbers were correct but I didn't had that last digit on my list.

What is this last digit and how do I know if a card includes it or not?

I am using Delphi. And to get the ICCID I use Chilkat DLL.

My code looks like this:

function TCardReader.ReadICCID(var Output: String): Boolean;
var
  Success: Boolean;
  numBytes: Integer;
  bdRecv: HCkBinData;
  Buf: PWideChar;
begin
  Success := self.ConnectCard;
  if Success then begin
    if CkSCard_getLastMethodSuccess(self.FScard) = True then begin
      bdRecv := CkBinData_Create();

      //Select MF
      Success := self.SendCommand('A0A40000023F00', bdRecv);
      if Success then begin

        //Select ICCID
        Success := self.SendCommand('A0A40000022FE2', bdRecv);
        if Success then begin

          //Read the 10 bytes of ICCID EF
          Success := self.SendCommand('A0B000000A', bdRecv, Buf);
          if Success
            then Output := self.ByteToStrICCID(Buf);
        end;
      end;

      CkBinData_Dispose(bdRecv);
    end else Success := False;

    self.DisconnectCard;
  end;
  TLog.InfoLog('Read ICCID: ' + THelper.BoolToStr(Success));

  result := Success;
end;

As Output I had the results (just examples): 8944501606231037754 8944501606231037345F

Correct would have been: 8944501606231037754 8944501606231037345

What is that "F"? I did read that is a extra digit but how do I know that my APDU command will get me one or not? Sadly can't process that "8944501606231037345F".

Or is there an APDU command to filter it out or get the extra digit?


Solution

  • ICCID is coded in BCD where each nibble contains a single digit.

    For ICCIDs with number of digits under 20 additional padding 0xF characters are added to the end.

    Citing article about ICCID checksum (emphasis mine):

    The coding of the serial number for cards of Phase2/2+ onwards it is defined in ITU-T E118. CCITT E118 specifies a Serial Number length between 0 and 18 digits plus an extra byte containing a checksum written in its least significant (that is, rightmost) digit. The checksum is always stored in this byte whatever the length of the serial number (if the serial number is shorter than 18 digits it is padded (One or more bits appended to a message in order to ensure that it contains the required number of bits or bytes.) with Fh up to digit 20. Coding the serial number on 20 digits overwrites the checksum. Some operators today use 19 digits followed by the checksum without any padding.

    So you need to right pad your ICCIDs in the list to the length of 20 by adding Fs to the end before comparing them to the value read from the 2FE2 file.