I'm trying to emulate a PoS, point of sale :), system and complete a transaction with Google wallet running on a 2013 Nexus 7 (no secure element) v4.4.2.
My PoS prototype is also running on a 2013 Nexus 7 v4.4.2.
I'm able to get NFC responses from the 2PAY_SYS_DDF01 request. I'm able to select the MasterCard application ID. I'm able to get Processing Options. When I Read Records it doesn't look like Google wallet is returning all the mandatory EMV fields. And finally when I request the Generate AC command it always returns 6D00 unsupported.
Area of the code that is a problem:
//set P1 to '40', to request an Transaction Certificate (offline transaction)
//and execute the Generate AC command.
byte[] generateAC = new byte[] {(byte)0x80, (byte)0xAE, 0x40, 0x00,
0x1D, //data length
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, //amount1
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //amount2
0x08, 0x40, //term country
0x00, 0x00, 0x00, 0x00, 0x00, //tvr
0x09, 0x62, //tx curr
0x14, 0x04, 0x1B, //tx date
0x00, //tx type
0x12, 0x34, 0x56, 0x78, //random
0x00}; //le
response = isoDep.transceive(generateAC);
I was following Tim Beckers video https://www.youtube.com/watch?v=qqobg1-HrfY approx. 46 minutes in. and Tim Beckers code sample: https://github.com/a2800276/29c3/blob/master/smartshell.rb
UPDATE:
The response to the GPO command (80 a8 00 00 02 83 00 00
) is
770a820200009404080101009000
77 Response Message Template Format 2
82 Application Interchange Profile
0000
94 Application File Locator (AFL)
08010100
UPDATE:
I tried:
byte[] computeCC = new byte[] {
(byte)0x80, // CLA = proprietary
(byte)0x2A, // INS = COMPUTE CRYPTOGRAPHIC CHECKSUM
(byte)0x8E, // P1
(byte)0x80, // P2
(byte)0x04, // Lc
(byte)0x00, 0x00, (byte)0x00, (byte)0x99, // Unpredicatable Number (numeric)
(byte)0x00, // Le
};
response = isoDep.transceive(computeCC);
hoping to at least get an error that indicated the wrong unpredictable number but I got 6700 incorrect length returned.
Earlier I got a response to Read Record 00 B2 01 0C 00 Part of that response is Card Authentication Related Data [9F69]: Data (Binary): XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX fDDA Version Number: 9F (Card) Unpredictable Number: 6A 04 9F 7E
So I tried that Unpredictable number
byte[] computeCC = new byte[] {
(byte)0x80, // CLA = proprietary
(byte)0x2A, // INS = COMPUTE CRYPTOGRAPHIC CHECKSUM
(byte)0x8E, // P1
(byte)0x80, // P2
(byte)0x04, // Lc
(byte)0x6A, 0x04, (byte)0x9F, (byte)0x7E, // Unpredicatable Number (numeric)
(byte)0x00, // Le
};
response = isoDep.transceive(computeCC);
But I still get 6700 wrong length
UPDATE:
The response to READ RECORD (Record = 1, SFI = 1) command (00 B2 01 0C 00) is:
70 7c 9f 6c 02
00 01 9f 62 06
00 00 00 00 00
38 9f 63 06 00
00 00 00 03 c6
56 29 42 35 33
39 36 XX XX XX
XX 31 XX XX 39
XX XX XX XX 5e
20 2f 5e 31 34
30 37 31 30 31
34 30 31 30 30
30 30 30 30 30
30 30 30 9f 64
01 04 9f 65 02
00 38 9f 66 02
03 c6 9f 6b 13
53 96 XX XX 1X
X9 XX XX d1 40
71 01 40 10 00
00 00 00 0f 9f
67 01 04 9f 69
0f 9f 6a 04 9f
7e 01 9f 02 06
5f 2a 02 9f 1a
02 90 00
--------------------------TLV-------------------------------
Output:
READ RECORD Response Message Template [70]:
Card Transaction Qualifiers (CTQ) [9F6C]:
Data (Binary): 00 01
Bit flags set:
1Bxb8: 0 - Online PIN not Required
1Bxb7: 0 - Signature Not Required
1Bxb6: 0 - Not applicable: Go Online if Offline Data Authentication Fails and Reader is online capable.
1Bxb5: 0 - Not applicable: Switch Interface if Offline Data Authentication fails and Reader supports VIS.
1Bxb4: 0 - Not applicable: Go Online if Application Expired
1Bxb3: 0 - Not applicable: Switch Interface for Cash Transactions
1Bxb2: 0 - Not applicable: Switch Interface for Cashback Transactions
1Bxb1: 0 - RFU
2Bxb8: 0 - Consumer Device CVM not Performed
2Bxb7: 0 - Card doesn't support Issuer Update Processing at the POS
2Bxb6: 0 - RFU
2Bxb5: 0 - RFU
2Bxb4: 0 - RFU
2Bxb3: 0 - RFU
2Bxb2: 0 - RFU
2Bxb1: 1 - RFU
PCVC3 (Track1) [9F62]:
Data (Binary): 00 00 00 00 00 38
Offline Counter Initial Value [9F63]:
Data (Binary): 00 00 00 00 03 C6
Track 1 Data [56]:
Data (ASCII): B5396XXXXXXXXXXXX^ /^14071014010000000000
NATC (Track1) [9F64]:
Data (Binary): 04
PCVC3 (Track2) [9F65]:
Data (Binary): 00 38
Terminal Transaction Qualifiers (TTQ) [9F66]:
Data (Binary): 03 C6
Card CVM Limit [9F6B]:
Data (Binary): 53 96 48 50 17 69 62 32 D1 40 71 01 40 10 00 00 00 00 0F
MSD Offset [9F67]:
Data (Binary): 04
Card Authentication Related Data [9F69]:
Data (Binary): 9F 6A 04 9F 7E 01 9F 02 06 5F 2A 02 9F 1A 02
fDDA Version Number: 9F
(Card) Unpredictable Number: 6A 04 9F 7E
Card Transaction Qualifiers: 01 9F
----------------------------------------
The response to the GET PROCESSING OPTIONS command indicates the following Application Interchange Profile (AIP):
Google Wallet is basically a MasterCard (EMV contactless kernel 2), so decoding the AIP according to the rules of Kernel 2 results in the following:
The important part is byte 2, bit 8: It indicates that your card does not support EMV mode. Hence, your card/Google Wallet is a PayPass card that supports only Mag-Stripe mode. Therefore, you cannot authenticate transactions using GENERATE AC. Instead, you can only let the card generate dynamic card verification codes (CVC3) using COMPUTE CRYPTOGRAPHIC CHECKSUM:
Note that the data field of the COMPUTE CRYPTOGRAPHIC CHECKSUM command must be filled with values according to the UDOL (in case there is no UDOL, the default UDOL is
9F6A04
, indicating the unpredictable number, numeric).The unpredictable number (numeric) is a BCD coded number in the range that is defined by the mag-stripe data file (see the AFL). In the past, for Google Wallet, this was a value between 0 and 99 (i.e.
WW='00'
,XX='00'
,YY='00'
,ZZ='00'..'99'
).UPDATE:
The data read from the card decodes as follows:
So the card does provide a UDOL. Therefore, the COMPUTE CRYPTOGRAPHIC CHECKSUM command has to be adapted accordingly: