Search code examples
c#uwpnfcdesktopproximityapi

Initialize a NDEF tag on Windows 10 Desktop


I'm trying to initialize a new Mifare Classic Tag to the DNEF format, readable by the Proximity API.

According to Microsoft, the proximity API is capable to initialize a mifare classic tag to a NDEF format if needed (as described here and here).

But, using this line of code to publish the message:

proximityDevice.PublishBinaryMessage("NDEF:WriteTag", ndef.ToByteArray().AsBuffer(), MessageTransmittedHandler);

don't initialize the TAG and write anything, just works on a pre-formatted NDEF tag (done by an Android Phone, for example).

There are any way to initialize the TAG to a NDEF format on the Desktop familly, being the NFC reader/writer a proximity device? (NXP NearFieldProximity Provider)


UPDATE:

I found a MIRAFE API for .NET from Onovotny with all low level operations to send the APDU data to Mifare Cards, supporting the WinRT SmartCard framework that I'm using.

The problem now consists on any data operations (getData or setData) when tries to login the card, producing this Exception:

"The smart card has been reset, so any shared state information is invalid. (Exception from HRESULT: 0x80100068)"

I can get the card identification and the card is writabble on Android devices. I also tried to change the KeyA to {0x00,0x00,0x00,0x00,0x00,0x00}, { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} and {0xA0,0xA1,0xA2,0xA3,0xA4,0xA5} but the results are the same.


Solution

  • Just started a Windows Service at services.msc called "Smart Card Device Enumeration Service", and I could be able to write/read data to/from SmartCards.

    About the NDEF formatting, I inserted MAD data on sector 0, block 1 and 2. After that, added the NDEF records on sector 1, block 0..2. Then, I updated the Key A and Key B of MAD and NDEF sectors like this:

    Filling MAD and 2 NDEF records manually:

            //Atualiza KeyB
            mifareCard.AddOrUpdateSectorKeySet(new SectorKeySet {
                Key = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
                KeyType = KeyType.KeyB,
                Sector = 0
            });
            //Seta dados do MAD
            await mifareCard.SetData(0, 1, new byte[] { 0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1 });
            await mifareCard.SetData(0, 2, new byte[] { 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1 });
    
            mifareCard.AddOrUpdateSectorKeySet(new SectorKeySet {
                Key = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
                KeyType = KeyType.KeyB,
                Sector = 1
            });
            //Incluis dois records NDEF
            await mifareCard.SetData(1, 0, new byte[] { 0x00, 0x00, 0x03, 0x11, 0xD1, 0x01, 0x0D, 0x55, 0x01, 0x61, 0x64, 0x61, 0x66, 0x72, 0x75, 0x69 });
            await mifareCard.SetData(1, 1, new byte[] { 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
    
            await mifareCard.Flush();
    

    Updating keys for NDEF records:

            //Get MAD sector
            var setor = mifareCard.GetSector(0);
            //Get Trail data
            await setor.GetData(3);
            //Update chaves. Acess bits are generated by Mirafe API
            await setor.FlushTrailer(
                Extensions.ByteArrayToString(new byte[] { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }),
                Extensions.ByteArrayToString(new byte[] { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 }
            ));
    
            //Set others sectors keys for NDEF
            for (var sector = 1; sector < 16; sector++) {
                try {
                    setor = mifareCard.GetSector(sector);
                    await setor.GetData(3);
                    await setor.FlushTrailer(
                        Extensions.ByteArrayToString(new byte[] { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 }),
                        Extensions.ByteArrayToString(new byte[] { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 }
                    ));
                } catch (Exception ex) {
                    Debug.Write(ex.Message + "\n");
                }
            }