I am trying to send a URL in a NDEF Message from my Computer and ACR 122 to a phone.
To Achieve that, I use SNEP.
The thing is that it works perfectly with Android and Blackberry, but not with any Windows Phone.
These are the commands I send using the java library Smartcardio, and the responses I got from the phone (android or Windows)
Command 1 : (configure PN532 as Target)
FF 00 00 00 2D D4 8C 00 08 00 12 34 56 40 01 FE0100000000000000000000000000FFFF01FE01000000000000000646666D01011000
Response Android : D5 8D 25 1E D4 00 D5 65 D7 84 0E 59 F9 CF B2 BA 00 00 00 32 46 66 6D 01 01 11 03 02 00 13 04 01 96 90 00
Response Windows Phone : D5 8D 05 22 D4 00 C2 65 AD 78 F4 3D 81 F8 72 8F 00 00 00 32 46 66 6D 01 01 11 02 02 03 80 03 02 00 01 04 01 64 90 00
Command 2 : (tg get data)
FF00000002 D486
Response Android : D5870000009000
Response WP : D5870000009000
Command 3 : (tg set data, ndef with "urn:nfc:sn:snep")
FF00000015 D48E 0520060F 75726E3A6E66633A736E3A736E6570
Response Android : D58F009000
Reponse WP : D58F009000
Command 4 : (tg get data)
FF00000002 D486
Response Android : D587 000000 9000
Response WP : D587 00 05 20 02 02 03 80 050105060F75726E3A6E66633A736E3A736E6570 9000
Command 5 : (tg set data)
FF00000004D48E 0000
Response Android : D5 8F 00 9000
Response WP : D5 8F 00 9000
Command 6 : (tg get data)
FF00000002 D486
Response Android : D587 00 8184 9000
Response WP : D587 00 8184 02020380050105 9000
Command 7 : (tg set data, ndef with url "journaldugeek.com")
FF00000021 D48E 132000100200000016 D1 01 12 55 01 6A6F75726E616C64756765656B2E636F6D
Response Android : D58F 00 9000
Response WP : D58F 00 9000
Command 8 : (tg get data)
FF00000002D486
Response Android : D587 00 83 44 01 9000
Response WP : D587 00 83 44 01 9000
Command 9 : (tg set data)
FF00000004D48E0000
Response Android : D58F009000
Response WP : D58F009000
Command 10 : (tg get data)
FF00000002D486
Response Android : D587 00830401108100000000 9000
Response WP : D587 00830401108100000000 9000
Command 11 : (tg set data)
FF00000005 D48E 136001
Response Android : D58F009000
Response WP : D58F009000
Command 12 : (tg get data)
FF00000002D486
Response Android : D5870000009000
Response WP : D5870000009000
Command 13 : disconnect?
FF00000004D48E1160
Response Android : D58F009000
Response WP : D58F009000
Command 14 : disconnect?
FF00000002D486
Response Android : D587 0081C400 9000
Response WP : D587 0081C400 9000
You can see that only Command 6 is different for Android and Windows Phone, however the other ones are the sames. The WP basically send a OK Message, but the url is not displayed in a browser on the phone. Does anybody know why, and know if there is another way to do SNEP with APDU Commands so that it works for Android, WP and Blackberry ?
Related
I am trying to read the information stored on my German Sparkasse Girocard. My app successfully recognizes the (ISODEP) tag. To read the stored information, I need to send a sequence of APDU commands, but I am not sure which.
From my understanding I need to send a SELECT command first:
byte[] SELECT = {
(byte) 0x00, // CLA Class
(byte) 0xA4, // INS Instruction
(byte) 0x04, // P1 Parameter 1
(byte) 0x00, // P2 Parameter 2
(byte) 0x09, // Lc
(byte) 0xD2,0x76,0x00,0x00,0x25,0x47,0x41,0x01,0x00, // AID
(byte) 0x00 //Le
};
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
IsoDep tag = IsoDep.get(tagFromIntent);
tag.connect();
byte[] result = tag.transceive(SELECT);
text.setText(Integer.toHexString(result[0]) + ", " + Integer.toHexString(result[1]));
The status response should be 9000 if it works. I am getting 6F44 which indicates that there was some sort of error (I think). I am also not quite sure if I am using the correct AID, but it has also not worked using others, which I thought could be correct.
What is my error and which commands do I have to send to retrieve the data?
Thanks in advance.
Getting data from an EMV card (e.g. Girocard, Mastercard, Visacard) is more a "question and answer" puzzle - you are asking the card, get a response, analyze the data and ask the next question.
The analyzing part is done here by using the "TLV Utilities" from emvlab.org (https://emvlab.org/tlvutils/).
To get more information about the Application Identifier ("AID"s) see the complete list at: https://www.eftlab.com/knowledge-base/211-emv-aid-rid-pix/.
Here is an example of reading a German Girocard (mine is from a "Volksbank"):
Step 1: ask the card which applications are on the card using the "select PPSE" command. The 2 bytes at the end "90 00" say that the answer is successfull:
selectPpseCommand: 00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 00
selectPpseResponse: 6F 67 84 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 55 BF 0C 52 61 19 4F 09 A0 00 00 00 59 45 43 01 00 87 01 01 9F 0A 08 00 01 05 01 00 00 00 00 61 1A 4F 0A A0 00 00 03 59 10 10 02 80 01 87 01 01 9F 0A 08 00 01 05 01 00 00 00 00 61 19 4F 09 D2 76 00 00 25 47 41 01 00 87 01 01 9F 0A 08 00 01 05 01 00 00 00 00 90 00
Parsed response:
6F File Control Information (FCI) Template
84 Dedicated File (DF) Name
325041592E5359532E4444463031
A5 File Control Information (FCI) Proprietary Template
BF0C File Control Information (FCI) Issuer Discretionary Data
61 Application Template
4F Application Identifier (AID) – card
A00000005945430100
87 Application Priority Indicator
01
9F0A Unknown tag
0001050100000000
61 Application Template
4F Application Identifier (AID) – card
A0000003591010028001
87 Application Priority Indicator
01
9F0A Unknown tag
0001050100000000
61 Application Template
4F Application Identifier (AID) – card
D27600002547410100
87 Application Priority Indicator
01
9F0A Unknown tag
0001050100000000
There are 3 applications with 3 different AIDs available on the card:
A00000005945430100: Zentraler Kreditausschuss (ZKA) Germany Girocard Electronic Cash
A0000003591010028001: Euro Alliance of Payment Schemes s.c.r.l. – EAPS Belgium Girocard EAPS ZKA (Germany)
D27600002547410100: ZKA Germany Girocard ATM
Step 2: Now I'm reading the first AID using the "Select AID" command - the AID is 18 characters = 9 bytes long:
selectAidCommand: 00 A4 04 00 09 A0 00 00 00 59 45 43 01 00 00
selectAidResponse: 6F 47 84 09 A0 00 00 00 59 45 43 01 00 A5 3A 50 08 67 69 72 6F 63 61 72 64 87 01 01 9F 38 06 9F 02 06 9F 1D 02 5F 2D 04 64 65 65 6E BF 0C 1A 9F 4D 02 19 0A 9F 6E 07 02 80 00 00 30 30 00 9F 0A 08 00 01 05 01 00 00 00 00 90 00
Parsed response:
6F File Control Information (FCI) Template
84 Dedicated File (DF) Name
A00000005945430100
A5 File Control Information (FCI) Proprietary Template
50 Application Label
g i r o c a r d
87 Application Priority Indicator
01
9F38 Processing Options Data Object List (PDOL)
9F02 06
9F1D 02
5F2D Language Preference
d e e n
BF0C File Control Information (FCI) Issuer Discretionary Data
9F4D Log Entry
190A
9F6E Unknown tag
02800000303000
9F0A Unknown tag
0001050100000000
Step 3: get the processing options to read the card details
This is the first "tricky" point as it is not easy how to explain to get the right data for your card/AID. In the above response there is a section for the Processing Options Data Object List (PDOL) the card is requesting and the length of the fields - here we do have 2 fields with a length of 6 and 2 bytes, in total 8 bytes. The 8 bytes are just 8 "x00"s with the "header" 83 08, so the complete length is 10 bytes = x0A:
9F38 Processing Options Data Object List (PDOL)
9F02 06
9F1D 02
A more detailed explanation can be found here: https://stackoverflow.com/a/20810855/8166854
getProcessingOptionsCommand: 80 A8 00 00 0A 83 08 00 00 00 00 00 01 00 00 00
getProcessingOptionsResponse: 77 1E 82 02 19 80 94 18 18 01 01 00 20 01 01 00 20 04 04 00 08 05 05 01 08 07 07 01 08 03 03 01
Parsed response:
77 Response Message Template Format 2
82 Application Interchange Profile
1980
94 Application File Locator (AFL)
18010100 20010100 20040400 08050501 08070701 08030301
The most important part for the next step is the "Application File Locator (AFL)" - we need to read the file system with the data that are coded in these 4 byte blocks.
Step 4: read the records from the card
This is the part where I get lost when trying to read the card. You need to get the SFI and RECORD from the first 3 bytes of an AFL block and run a read record command. The following command reads the 4th sector of the AFL list - the command may work or not with your card and if it works you may get different data from your card.
WARNING: providing the response data to an internet form may reveal data like account number or
credit card number - my response is masked so the account number is not 1111111111:
readRecordCommand: 00 B2 05 0C 00
readRecordResponse: 70 38 5F 24 03 21 12 31 5A 0A 67 26 42 89 11 11 11 11 11 7F 5F 34 01 02 5F 28 02 02 80 9F 07 02 FF C0 9F 0D 05 FC 40 A4 80 00 9F 0E 05 00 10 18 00 00 9F 0F 05 FC 40 A4 98 00 90 00
Parsed response:
70 EMV Proprietary Template
5F24 Application Expiration Date
211231
5A Application Primary Account Number (PAN)
6726428911111111117F
5F34 Application Primary Account Number (PAN) Sequence Number
02
5F28 Issuer Country Code
0280
9F07 Application Usage Control
FFC0
9F0D Issuer Action Code – Default
FC40A48000
9F0E Issuer Action Code – Denial
0010180000
9F0F Issuer Action Code – Online
FC40A49800
I strongly recommend that you use a library for the steps 3 and 4; I'm using
https://github.com/devnied/EMV-NFC-Paycard-Enrollment
for this.
This is just a basic explanation for the first steps but now you get some useful responds from your card - good luck for your next steps.
A complete Android example app for the above mentioned library is here (disclaimer: I'm the author):
https://github.com/AndroidCrypto/Android-EMV-NFC-Paycard-Example
Trying to detect an iBeacon setup on raspberry PI using the android beacon library (with xamarin bindings)
Wondering what Im doing wrong here:
sudo hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 00 01 00 00 C8 00
And setting up Beacon Parser like so
beaconManager.BeaconParsers.Add(new BeaconParser().SetBeaconLayout("m:0-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
I can detect this beacon with for example "BeaconScope" on Android but I can not get it detected using the android beacon library.
I can see the following output from debug
[BeaconParser] Processing pdu type FF: 02011a1aff4c000215e20a39f473f54bc4a12f17d1ad07a96100010000c80000000000000000000000000000000000000000000000000000000000000000 with startIndex: 5, endIndex: 29
[BeaconParser] Ignoring pdu type 06
[BeaconParser] This is not a matching Beacon advertisement. (Was expecting be ac. The bytes I see are: 02011a1aff4c000215e20a39f473f54bc4a12f17d1ad07a96100010000c80000000000000000000000000000000000000000000000000000000000000000
Setting up as AltBeacon works!
sudo hcitool -i hci0 cmd 0x08 0x0008 1F 02 01 1A 1B FF 18 01 BE AC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 C5 01
This one the library detects.
What am I missing?
I detect a RadButton setup as iBeacon but can not get it to work from raspberry PI
Try changing this:
"m:0-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"
to this:
"m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"
Note the first digit is a 2 instead of a 0
I'm currently working a project with Open Mobile API. Basically, I got this problem when i exchange apdu to the UICC, all my commands converted automatically to the extended logical APDU command (CLA : 0xC1). I'm using Samsung Galaxy S6 Edge during this test with android version : 5.0.2.
APDU > Header [CLA INS P1 P2] 00 70 00 00 194,69 etu MANAGE CHANNEL
< Outgoing data 01
< Return code [SW1 SW2] 90 00
APDU > Header [CLA INS P1 P2] 01 A4 04 00 194,69 etu SELECT
Incoming data A0 00 00 05 59 10 10 FF FF FF FF 89 00 00 01 00
< Outgoing data 6F 1A 84 10 A0 00 00 05 59 10 10 FF FF FF FF 89
00 00 01 00 A5 06 73 00 9F 65 01 FF
< Return code [SW1 SW2] 90 00
APDU > Header [CLA INS P1 P2] C1 E2 91 00 187,69 etu
Incoming data BF 2D 00
< Return code [SW1 SW2] 6D 00
APDU > Header [CLA INS P1 P2] 00 70 80 01 192,69 etu MANAGE CHANNEL
< Return code [SW1 SW2] 90 00
What could be a problem? Who is responsible to change my CLA command to 0xC1? Why the phone change the CLA command to 0xC1?
Note : Based on my application log, I send this 81 E2 91 00 02 BF 2D 00
Thanks for your help.
I'm still trying to emulate a point of sale (POS) system and complete a transaction with Google wallet.
I've gotten further with great answers on stack overflow.
See Android isoDep.transceive on Generate AC command always returns 6D00 unsupported
Even though every step of the communication from the POS and Google Wallet is successful, I can't get past Google wallet stating
"Status unknown, Check with cashier to see if the payment was successful".
I just need Google wallet to state "Status pending" just like at McDonalds (in the US).
I actually don't care if the whole transaction processes and clears my bank.
I'm new to transaction processing and it seems like I'm missing a fundamental step.
Any ideas would be greatly appreciated.
The following are the successful steps.
Step 1 Select Proximity Payment System Environment (2PAY.SYS.DDF01)
Send = 00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 00
Response = 6f2f 840e 325041592e5359532e4444463031 a51d bf0c1a61184f07a00000 00041010870101500a4d 617374657243617264 9000 (Success)
Step 2 Select Payment Service
Send = 00 A4 04 00 07 A0 00 00 00 04 10 10 00
Response = 6f1e 8407 a0000000041010 a513 500a 4d617374657243617264 870101 9f11 01 01 9000 (Success)
Step 3 Get Processing Options
Send = 80 a8 00 00 02 83 00 00
Response = 770a 8202 0000 9404 08010100 9000 (Success)
Step 4 Read Record
Send = 00 B2 01 0C 00
Response = 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 9000 (Success)
Step 5 Compute Crytographic Checksum
Send = 80 2A 8E 80 0F 00 00 00 12 00 00 00 00 00 01 00 08 40 08 40 00
Response = 77 0f 9f 61 02 XX XX 9f 60 02 XX XX 9f 36 02 20 fa 9000 (Success)
The "PayPass – M/Chip Transaction Processing" specification states
"After the completion of the COMPUTE CRYPTOGRAPHIC CHECKSUM response, the
PayPass card can be removed from the PayPass reader."
So I assumed POS to Google Wallet communication was done, but Google Wallet seems to need more information.
So I assumed POS to Google Wallet communication was done, but Google Wallet seems to need more information.
Correct. Google Wallet retrieves information about transactions trough the card issuer's online backend system (at least that was the case with pre 2.0 version of GW, but I would assume that's still the case). Thus if you do not perform a real transaction (one that runs through the Master Card network), Google Wallet has no means to retrieve details about the transaction for the online backend.
I'm developing a NFC environment consisting of a tag (AS3953 chip + microcontroller) and a smartphone (Samsung Galaxy Fame runnung Android 4.1.2).
While reading a NDEF message works I'm stuck on writing the message to the tag.
I copied most of the code from http://tapintonfc.blogspot.de/2012/07/the-above-footage-from-our-nfc-workshop.html
and modified it to accept ISO14443A Tag Type 4 by searching the tag techlist for IsoDep, NfcA and Ndef in supportedTechs().
Since all of them are listed the app continues to writeTag():
public WriteResponse writeTag(NdefMessage message, Tag tag) {
try {
Ndef ndef = Ndef.get(tag);
if (ndef != null) {
Log.d(TAG, "writeTag: tag type: "+ndef.getType());
ndef.connect();
Log.d(TAG, "writeTag: connected!");
if (!ndef.isWritable()) {
return new WriteResponse(0, "Tag is read-only");
}
if (ndef.getMaxSize() < message.toByteArray().length) {
return new WriteResponse(0, "size error");
}
Log.d(TAG, "writeTag: write ndef...");
ndef.writeNdefMessage(message);
Log.d(TAG, "writeTag: wrote ndef!");
if (writeProtect)
ndef.makeReadOnly();
return new WriteResponse(1, "Wrote message to pre-formatted tag.");
} else {
Log.d(TAG, "writeTag: ndef==null!");
return new WriteResponse(0, "writeTag: ndef==null!");
}
} catch (Exception e) {
Log.d(TAG, "writeTag: exception: " + e.toString());
return new WriteResponse(0, "Failed to write tag");
}
}
LogCat shows:
11:08:46.400: onNewIntent
11:08:46.400: supportedTechs: techlist: android.nfc.tech.IsoDep,android.nfc.tech.NfcA,android.nfc.tech.Ndef,
11:08:46.400: supportedTechs: tech is supported!
11:08:46.400: writeTag: tag type: org.nfcforum.ndef.type4
11:08:46.410: writeTag: connected!
11:08:46.410: writeTag: write ndef...
11:08:46.490: writeTag: exception: java.io.IOException: Tag is not ndef
As you can see an IOException is thrown saying the Tag is not ndef which contradicts
the techlist. Looking further into the android code writeNdefMessage() tries to get
a TagService and a ServiceHandle from the tag to match them against. This fails so
the exception is thrown (no message written up to now):
public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException {
...
INfcTag tagService = mTag.getTagService();
...
int serviceHandle = mTag.getServiceHandle();
if (tagService.isNdef(serviceHandle)) {
...
}
else {
throw new IOException("Tag is not ndef");
}
...
}
Is there a workaround for that or is it not possible at all with my kind of tag?
As I'm also programming the tag the error might be on the other side, but it
seems to be a Java problem.
Edit 1:
I don't connect to any technology before so there shouldn't be any opened connection. If
I open an connection before ndef.connect() there is IllegalStateException: Close other technology first!
I configured AS3953 to ISO14443A Level-4 so only Tag Type 4 Blocks are forwarded
to the microcontroller. Only I-Blocks are handled but even if there are other commands the µC has to read it out
over the SPI port which isn't the case by logic analysis. As I said reading the ndef file works and I tested it
for a 4KB file. Looking at the logic analysis the following steps are made (all returning a positive 9000-code):
(c=command, r=response) (corrected due to renaming mistake)
select by name:
c: 02 00 a4 04 00 07 d2 76 00 00 85 01 01 00
r: 02 90 00
select by id - select cc file
c: 03 00 a4 00 0c 02 e1 03
r: 03 90 00
read 0x0f bytes of cc file
c: 02 00 b0 00 00 0f
r: 02 00 0f 20 00 3b 00 34 04 06 e1 04 0f ff 00 00 90 00
select by id - select ndef file
c: 03 00 a4 00 0c 02 e1 04
r: 03 90 00
read 0x02 bytes (first 2 bytes are apdu-size)
c: 02 00 b0 00 00 02
r: 02 0f d3 90 00
read 0x3b bytes (frame size) of first part of ndef file (external type, jpeg image as payload)
c: 03 00 b0 00 02 3b
r: 03 c4 0c 00 00 0f c1 64 65 2e 74 65 73 74 61 70 70 3a 61 01 ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 60 00 60 00 00 ff db 00 43 00 49 32 36 40 36 2d 49 40 3b 40 52 4d 49 56 6d 90 00
[ndef file]
read 0x26 bytes of last part of ndef file
c: 03 00 b0 0f ae 27
r: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 FF D9 00 00 90 00
Using the same app for writing I start the activity which filters NfcAdapter.ACTION_TAG_DISCOVERED intents.
Just as in the linked example the phone touches the tag calling onResume() doing
mNfcAdapter.enableForegroundDispatch(...);
When I log the SPI communication the same reading procedure as above is done. Since LogCat
shows a working intent dispatcher I guess the app stops at the IOException, closing the connection
and immediately going over to read out as android found the tag again.
Edit 2:
There might be a hint as one of the first interrupts issue a deselect command
which is handled by AS3953 itself:
(count * interrupt)
3 * power up
1 * Wake-up IRQ at entry in ACTIVE(*) state
1 * Deselect command
1 * Wake-up IRQ at entry in ACTIVE(*) state
1 * IRQ due to start of receive
It works now. I figured out that a startup routine which checks and sets the configuration word
was transmitted with a too high baud rate for the AS3953. This worked for reading but something
must have been mixed up for writing to the tag.
I cannot tell for sure if this is the only reason why it didn't work. There is also a problem
with slow reading of the 32Byte FIFO as waterlevel interrupts are handled too late - I simply expected
the problem to be on the android side since I couldn't find the write command in the logic analysis
and the exception didn't describe the reason enough.
Thanks a lot to Michael Roland for further debugging, I still don't unterstand why the tag is
read at first if I want to write to it but well - there should be a workaround reading an
empty ndef message so the writing process will be done quickly.
For now I have to work on the firmware and cannot forecast any further problems but the actual
issue (ndef.writeNdefMessage()) returns successfully.