kormax / apple-enhanced-contactless-polling

Reverse-engineering Apple Enhanced Contactless Polling
164 stars 20 forks source link

rpc-nfc for ST25R3916(B) ? #2

Closed jedahan closed 11 months ago

jedahan commented 12 months ago

Thank you for all your work.

I was wondering, for getting these working on the flipper - did you implement a contactlessFrontend for nfcpy using the nfc-rpc, or did you hardcode the bytes in an entirely on-device manner?

kormax commented 12 months ago

Hello!

You should look into this section (link broken on mobile, open README at the bottom), which I think could answer this question.

TLDR: It is hardcoded, I provide an example that you copy directly into source code, didn’t bother doing it “correctly” as NFC refactor is coming. It’s something that’s worth doing when it comes out, but I don’t have a “proper” impl, which I assume should consume configuration from somewhere “up”.

kormax commented 12 months ago

I’ve heard about nfc-rpc, but didn’t try to use it. I thought it was doing isodep only. Have to look into it, perhaps it can send raw frames.

But IMO, i think adding this feature to flipper would make sense when they re-do the NFC stack. ECP can actually be implemented if a would-be nfc stack could allow to set custom NFC-A WUPA frames, which would mean that their code wouldn’t need to contain any proprietary terminology, and high-level apps can just invoke nfc polling with common WUPA and ECP passed in as parameters.

kormax commented 12 months ago

Wanted to add one last thing.

If/when you apply the example to the flipper's codebase, you'll find out that ECP frame there is just an placeholder. You can lookup the proper ECP frame in ecplist.json, but there's a need to calculate crc16a by hand (or find an appropriate parameter inside of ST hal).

jedahan commented 12 months ago

Thank you for all the pointers, I'll stare, and let it stew in my head a bit while I learn more.

jedahan commented 12 months ago

I saw the NFC refactor got merged and released like two weeks ago, so maybe waiting until post-1.0 is best.

Though the flipper devs are asking for specific feedback regarding the new NFC stack, I don't have the experience, maybe it is enough for me to ask them to "provide a mechanism to set custom NFC-A WUPA frames" if that isn't in the codebase already.

jedahan commented 12 months ago

BTW I made those changes described and was able to flash the new firmware, but wasn't sure what client FAP I would also have to create to invoke that code, especially as a response to the AECP examples that use nfcpy.

jedahan commented 12 months ago

Looks like lib/nfc/protocols/nfca.c has something called nfca_get_crc16 which seems promising

kormax commented 12 months ago

BTW I made those changes described and was able to flash the new firmware, but wasn't sure what client FAP I would also have to create to invoke that code, especially as a response to the AECP examples that use nfcpy.

I think that everything that uses ST's HAL works. For instance, the built-in "NFC" section almost fully. In the GIF i display it reading a card using "NFC/Extra Actions/Read Specific Card Type/DESFire" function.

Looks like lib/nfc/protocols/nfca.c has something called nfca_get_crc16 which seems promising

I'd advice not to complicate it for yourself until it starts working. Use online or some other calc for this value.

Full VAS ECP-A frame, for instance, is 6a01000002e4d2 (with crc), try it out at first. Iphone should at least get detected as generic "A" tag.

jedahan commented 12 months ago

Cool - so when I do read DESFire, it triggers apple wallet, but then no read happens.

When I manually read NFC-A data, it does not trigger the wallet, but if I manually trigger to open wallet, it reads data. Seems to be unique each time which is probably a good sign.

btw, that function did work. I can share the patch/diff if you'd like, or not.

kormax commented 12 months ago

You can verify that it's working definitely by setting ecp to one of the car key frames (refer to json file), your phone should display a car pairing popup - in which case it's 100% working.

For DESFire, you have to choose between any of the available transit system ECP, It's up to you. VAS in this case is only for EMV payment.

kormax commented 12 months ago

And if it works with car key, then I think it's worth adding an example where crc doesn't need to be calculated manually.

jedahan commented 12 months ago

Car key popped up immediately.

diff --git a/lib/ST25RFAL002/source/rfal_nfc.c b/lib/ST25RFAL002/source/rfal_nfc.c
index 57ff2e235..cea32c5c5 100644
--- a/lib/ST25RFAL002/source/rfal_nfc.c
+++ b/lib/ST25RFAL002/source/rfal_nfc.c
@@ -52,6 +52,7 @@
 #include "rfal_nfc.h"
 #include "utils.h"
 #include "rfal_analogConfig.h"
+#include "../../nfc/protocols/nfca.h"

 /*
 ******************************************************************************
@@ -993,6 +994,25 @@ static ReturnCode rfalNfcPollTechDetetection(void) {
                 gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_A;
             }

+            else {
+                uint8_t rx_data[0] = {};
+                uint16_t rx_len = 0;
+                #define FRAME_LEN 10
+                uint8_t frame[FRAME_LEN] = {0x6a, 0x02, 0xc3, 0x02, 0x09, 0x01, 0x00, 0x01, /*CRC1*/ 0x00, /*CRC2*/ 0x00};
+                nfca_append_crc16(frame, FRAME_LEN - 2);
+
+                rfalTransceiveBitsBlockingTxRx(
+                    frame,
+                    FRAME_LEN * 8,
+                    rx_data,
+                    0,
+                    &rx_len,
+                    RFAL_TXRX_FLAGS_AGC_ON | RFAL_TXRX_FLAGS_CRC_TX_MANUAL,
+                    6780 // 13560U for 1 ms
+                );
+                #undef FRAME_LEN
+            }
+
             gNfcDev.isTechInit = false;
             gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_A;
         }
jedahan commented 12 months ago

the #define stuff might have been dumb, but yeah basically just making sure the buffer has 2 bytes extra when initialized, and calling nfca_append_crc16 did the trick. There is also nfca_get_crc16 if you prefer less "magic".

kormax commented 12 months ago

LGTM, if you make a PR i'll accept it.