Olcay Ertaş
Olcay Ertaş

Reputation: 6228

iOS: Reading contactless VISA smart card data with Grabba

I have a Grabba smart card reader. I am trying to get card information with APDU commands. I have read a lot about EMV standards and related ISO 7816-4 standard but I am not able to execute simple select command with success. Here is some details:

I have successfully powered my VISA card and get its attributes:

NSError *error = nil;
GRGrabbaSmartcardSession *session = [GRGrabba.sharedGrabba.smartcard startSession:&error];
NSLog(@"EMV : smartCardInsertedEvent : Attribute : %@", [session getATR]);

Result: 3b690000 8072a445 6400ff00 10

When I parse this attribute on here I get this information for my card:

Attribute parser result

My contactless card is a credit card from Akbank from Turkey but it is listed as a Denizbank card from Turkey in this list.

Now I am tring to run a select command on card like this:

NSError *error = nil;
GRGrabbaSmartcardSession *session = [GRGrabba.sharedGrabba.smartcard startSession:&error];
NSLog(@"EMV : smartCardInsertedEvent : Attribute : %@", [session getATR]);
session.protocol = 1;
uint8_t aid[] = {'2', 'P', 'A', 'Y', '.', 'S', 'Y', 'S', '.', 'D', 'D', 'F', '0', '1'};
NSData *data = [NSData dataWithBytes:aid length:sizeof(aid)];
NSError *err = nil;
GRGrabbaCommandAPDU *apduCMD =
        [[GRGrabbaCommandAPDU alloc]
                initWithCLA:0x00
                        INS:0xA4
                         P1:0x04
                         P2:0x00
                       Data:data
                         Le:0x00
                      Error:&err];

GRGrabbaResponseAPDU *response = [[GRGrabbaResponseAPDU alloc] initWithData:nil SW1:0 SW2:0];
BOOL success = [session exchangeAPDUCommand:apduCMD withResponse:response error:&error];

if (!success) {
    NSLog(@"EMV : smartCardInsertedEvent : ERROR: Could not read ADF");
    return;
}

But it is failing with could not read ADF error. Can anyone show me what am I doing wrong?

UPDATE:

I have tried following combinations but still not able to run select command with success:

PROTOCOL DATA           CLA     LE   STATUS
0        1PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 61, SW2 = 52
0        1PAY.SYS.DDF01 0x00    0x00 Smartcard protocol error.
0        2PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 61, SW2 = 66
0        2PAY.SYS.DDF01 0x00    0x00 Smartcard protocol error.
0        1PAY.SYS.DDF01 0x80    -    card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
0        1PAY.SYS.DDF01 0x80    0x00 card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
0        2PAY.SYS.DDF01 0x80    -    card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
0        2PAY.SYS.DDF01 0x80    0x00 card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
1        1PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 00, SW2 = 00
1        1PAY.SYS.DDF01 0x00    0x00 unrecognised SW in response: SW1 = 00, SW2 = 00
1        2PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 00, SW2 = 00
1        2PAY.SYS.DDF01 0x00    0x00 unrecognised SW in response: SW1 = 00, SW2 = 00
1        1PAY.SYS.DDF01 0x80    -    unrecognised SW in response: SW1 = 00, SW2 = 00 
1        1PAY.SYS.DDF01 0x80    0x00 unrecognised SW in response: SW1 = 00, SW2 = 00
1        2PAY.SYS.DDF01 0x80    -    unrecognised SW in response: SW1 = 00, SW2 = 00
1        2PAY.SYS.DDF01 0x80    0x00 unrecognised SW in response: SW1 = 00, SW2 = 00

Upvotes: 5

Views: 781

Answers (2)

Michael Roland
Michael Roland

Reputation: 40821

The following two results look perfectly fine:

PROTOCOL DATA           CLA     LE   STATUS
0        1PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 61, SW2 = 52
0        2PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 61, SW2 = 66

The status word 61xx indicates that there are xx bytes of response data waiting and that you need issue a GET RESPONSE command to obtain the actual response data.

Consequently, you would need to set protocol to 0,

session.protocol = 0;

issue the SELECT command (for 2PAY.SYS.DDF01)

uint8_t aid[] = {'2', 'P', 'A', 'Y', '.', 'S', 'Y', 'S', '.', 'D', 'D', 'F', '0', '1'};
NSData *data = [NSData dataWithBytes:aid length:sizeof(aid)];
NSError *err = nil;
GRGrabbaCommandAPDU *apduCMD =
        [[GRGrabbaCommandAPDU alloc]
                initWithCLA:0x00
                        INS:0xA4
                         P1:0x04
                         P2:0x00
                       Data:data
                      Error:&err];
GRGrabbaResponseAPDU *response = [[GRGrabbaResponseAPDU alloc] initWithData:nil SW1:0 SW2:0];
BOOL success = [session exchangeAPDUCommand:apduCMD withResponse:response error:&error];

and evaluate the SW1. If SW1 equals 0x90 you are set and already have the response data. If it equals 0x61, then you will need to issue a GET RESPONSE command with Le set to the length indicated by SW2:

if (response.sw1 == 0x61) {
    GRGrabbaCommandAPDU *apduGETRESPCMD =
            [[GRGrabbaCommandAPDU alloc]
                    initWithCLA:0x00
                            INS:0xC0
                             P1:0x00
                             P2:0x00
                             Le:response.sw2
                      Error:&err];
    BOOL success = [session exchangeAPDUCommand:apduGETRESPCMD withResponse:response error:&error];
}

Note: I'm not too confident about syntax and field names in the above code...feel free to fix that once you got it to work.

Upvotes: 2

Michal Gluchowski
Michal Gluchowski

Reputation: 1237

I haven't used Grabba and I'm not sure if you are using it in contact or contactless, but since you're dealing with T=0 card, you might try issuing the command without Le.

Upvotes: 1

Related Questions