cancel
Showing results for 
Search instead for 
Did you mean: 

NFC0541 read Mifare Classic 1K

Olivier Bontron
Associate III

I’m using NFC05A1 and the STMF4xx-Nucle-Polling project.

I’d like to interact with  a Mifare classic card 1K.

I am aware Stm won’t provide any code that would deal with encryption and this is not what I’m asking for.

The issue I encounter is about the first step after SELECT : this is a clear text message, starting with 30 then the sector number. What I expect is the card answering with a nonce.

The issue I encounter is I receive a ‘framing problem’ or ‘timeout’ error message.

Here are the first four requests, which are working fine I think, the fifth one does not.

* Request 1:

Answer to rfalISO14443ATransceiveShortFrame  (with RFAL_14443A_SHORTFRAME_CMD_REQA as a command) is : 04 00.

* Request 2:

Then there is another rfalISO14443ATransceiveShortFrame   instruction this time with RFAL_14443A_SHORTFRAME_CMD_WUPA

*Request 3:

Then a rfalNfcaSelReq  structure is set :

selReq (rfalNfcaSelReq  structure)

selReq.selCmd = 93

selReq.selPar =20

rfalNfcaTxRetry( ret, rfalISO14443ATransceiveAnticollisionFrame( (uint8_t*)&selReq, &bytesTxRx, &bitsTxRx, &bytesRx, RFAL_NFCA_FDTMIN ), ((devLimit==0)?RFAL_NFCA_N_RETRANS:0), RFAL_NFCA_T_RETRANS );

Request answer : the request result consists in

the card Uid  D0 74 CC A4, (correct uid)

and the bcc CC

*Request 4:

Then another request is a SELECT.

selReq.selCmd =93;

selReq.selPar= 70;

selReq.nfcid1[0]= D0

selReq.nfcid1[1]=74;

selReq.nfcid1[2]=CC;

selReq.nfcid1[3]=A4;

selReq.bcc=CC;

       rfalNfcaTxRetry( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&selReq, sizeof(rfalNfcaSelReq), (uint8_t*)selRes, sizeof(rfalNfcaSelRes), &bytesRx, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCA_FDTMIN ), ((devLimit==0)?RFAL_NFCA_N_RETRANS:0), RFAL_NFCA_T_RETRANS );

Its results can be found within selRes :

Sak:  08

So far, the device is a Mifare Classic (sak 08) , this device is device[0] and its uid is known.

*Request 5 : this is where there is an issue.

Ask the card to access sector 00.

As Mr Michael Roland suggested in this post :

https://stackoverflow.com/questions/56334836/is-there-any-function-for-reading-nfc-a-iso14443a-tag-with-x-nucleo-nfc05a1

lenTx = 0;

bufferTx[lenTx++] = 0x30;

bufferTx[lenTx++] = 0x00; // sector

lenRxMax = 16;

lenRx = 0;

status = rfalTransceiveBlockingTxRx(&bufferTx[0], lenTx, &bufferRx[0], lenRxMax, &lenRx, RFAL_TXRX_FLAGS_DEFAULT, rfalConvMsTo1fc(5));

Answer

status value :  9

Another attempt with different flags.

status = rfalTransceiveBlockingTxRx(&bufferTx[0], lenTx, &bufferRx[0], lenRxMax, &lenRx,

RFAL_TXRX_FLAGS_CRC_TX_AUTO | RFAL_TXRX_FLAGS_CRC_RX_REMV | RFAL_TXRX_FLAGS_NFCIP1_OFF | RFAL_TXRX_FLAGS_AGC_ON | RFAL_TXRX_FLAGS_PAR_RX_REMV | RFAL_TXRX_FLAGS_PAR_TX_AUTO | RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO, RFAL_NFCA_T_RETRANS);

Same answer

status value :  9

ERR_FRAMING                          = 9, /*!< Framing error */

I’ve added some logs within rfalTransceiveBlockingRx to have a look at the states :

platformLog("gRFAL.state %d\r\n", gRFAL.state);

do{

    rfalWorker();

    platformLog("gRFAL.TxRx.state %d\r\n", gRFAL.TxRx.state);

  }

Logs for the successful requests (REQA, SEL) are :

gRFAL.state 3

gRFAL.TxRx.state 83 (RFAL_TXRX_STATE_RX_WAIT_RXS)

gRFAL.TxRx.state 90 (RFAL_TXRX_STATE_RX_FAIL)

gRFAL.TxRx.state 0 (RFAL_TXRX_STATE_IDLE)

status is 0 ERR_NONE            

Logs for the last read request are :

gRFAL.state 3

gRFAL.TxRx.state 83(RFAL_TXRX_STATE_RX_WAIT_RXS)

gRFAL.TxRx.state 84 (RFAL_TXRX_STATE_RX_WAIT_RXE)

gRFAL.TxRx.state 84

gRFAL.TxRx.state 84

gRFAL.TxRx.state 84

gRFAL.TxRx.state 84

gRFAL.TxRx.state 84

gRFAL.TxRx.state 90(RFAL_TXRX_STATE_RX_FAIL)

gRFAL.TxRx.state 0(RFAL_TXRX_STATE_IDLE)

status is 9 ERR_FRAMING /*!< Framing error */

Many thanks in advance,

Olivier

31 REPLIES 31
Olivier Bontron
Associate III

Dear Ulysses,

Thank you so much for your invaluable answer.

I went through your template and managed to get how you went from 'a2 0f' … to 'a2 1e' …

Despite I’m not at ‘write’stage but still in the ‘authentication’ process, I guess the rationale is alike and if so the template you sent will definitely  help a lot.

The answer the reader should send back to the card for authentication is made of :

8 bytes + 1 parity bit on each byte + 2 bytes CRC (on these 8 bytes) + 1 parity bit on CRC bytes (as you said 'Also the CRC bytes again will have a parity'.).

Once reshifted the way the template is, the size stays unchanged : it makes

8 * 8 bits + 8 * 1 bit + 2 * 8 bits + 1 bit = 89 bits.

This is the situation you described with the 36 bits example, which requires to be sent in raw mode, isn'it?

Could you tell me how to opt for raw mode please ?

Thanks in advance

Olivier Bontron

Ulysses HERNIOSUS
ST Employee

Hi Olivier,

raw mode for sending: RFAL_TXRX_FLAGS_PAR_TX_NONE | RFAL_TXRX_FLAGS_CRC_TX_MANUAL

raw mode for receiving: RFAL_TXRX_FLAGS_CRC_RX_KEEP | RFAL_TXRX_FLAGS_PAR_RX_KEEP

In your example it would be 90 bits as CRC is two bytes. However please carefully check the CRC and parity requirements for the frames. The DS indicates authentication frames are performed without CRC but probably with parity.

Regards, Ulysses

Hi Ulysses,

Great, there is some progress.

There is an answer, so the card handled the message that was sent to her, thanks a lot for your template.

Answer is an error message (but at least it's an answer):

Status is now 9, framing error.

lenRx=0

bufferRx[0] 09

then 00...

Is it related to the 'raw mode for receiving'?

A lenRx=0 and a bufferRx with a content, does the raw mode explain it?

Regards,

Olivier Bontron

Ulysses HERNIOSUS
ST Employee

Hi Olivier,

the convenience functions rfalTransceiveBlockingTxRx() always assume a byte oriented interface. In the end you need to move to rfalStartTransceive(), rfalGetTransceiveStatus(), rfalWorker() usage to get the actual number of received bits.

This does not really explain the lenRx=0. Even in the case of a 4-bit ACK/NAK it should indicate a length of 1 byte. Alternatively I could imagine an overwrite of the buffer on the stack?! bufferRx[0] == Status == 9, ... maybe the lenRxMax=16 bytes does not match the allocated buffer.

Regards, Ulysses

Thanks for answering,

I am expecting uint8_t as a result from the card, so it should be byte-oriented.

lenRxMax=16 bytes;

uint8_t bufferRx[16];

I went through the processes of rfalStartTransceive(), rfalGetTransceiveStatus(), rfalWorker().

Logs tell :

From rfalWorker -> rfalTransceiveRx.

Within rfal_rfst25r3911.c / rfalTransceiveRx, there is a condition which is met (see below).

I think this is where the gRFAL.TxRx.status is set to 'ERR_FRAMING', which the '9'.

/*******************************************************************************/

static void rfalTransceiveRx( void )

{

...

    case RFAL_TXRX_STATE_RX_WAIT_RXE:

      irqs = st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_RXE | ST25R3911_IRQ_MASK_FWL | ST25R3911_IRQ_MASK_EOF) );

      if( irqs == ST25R3911_IRQ_MASK_NONE )

      {

        /*******************************************************************************/

        /* REMARK: Silicon workaround ST25R3911B Errata #1.1              */

        /* ST25R3911 may indicate RXS without RXE afterwards, this happens rarely on  */

        /* corrupted frames.                              */

        /* SW timer is used to timeout upon a missing RXE               */

        if( rfalTimerisExpired( gRFAL.tmr.RXE ) )

        {

          gRFAL.TxRx.status = ERR_FRAMING;

          gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL;

        }

        /*******************************************************************************/

           

        break; /* No interrupt to process */

      }

The logs tell this condition is met.

Besides, when status and state values are asked for, the answer are:

status is 9

state is 90

Any thought?

Thanks in advance.

Olivier Bontron

Ulysses HERNIOSUS
ST Employee

Hi Olivier,

this now sounds more low-level. You shouldn't be hitting this timeout.

Please try the method in https://community.st.com/s/question/0D50X0000AlgXJWSQ2/st25tb-tag-not-recognized-by-xnucleonfc05a1-but-recognized-by-st25r3911bdisco.

If it does not help, then please provide logic analyzer traces of this issue.

Regards, Ulysses

Olivier Bontron
Associate III

Hi Ulysses,

Thanks, it sure makes a change.

Now status i 40 and LenRx is 1.

I'll dig a bit more and come back to you with the logs I get.

Regards,

Olivier

Ntuye.1
Associate II

CR95HF

- hello, i am use cr95hf to read, write block with is014443A tag 

- SEND: 02 02 00 00, RECEIVE: 00 00

- SEND: 02 07 02 00 00 00 00 02 02, RECEIVE: 00 00

- SEND: 09 04 3A 00 5A 04, RECEIVE: 00 00

- SEND: 09 04 68 01 01 DF, RECEIVE: 00 00

- SEND: 04 02 26 07, RECEIVE: 80 05 04 00 28 00 00

- SEND: 04 03 93 20 08, RECEIVE: 80 08 4B F3 A7 05 1A 28 00 00

- SEND: 04 08 93 70 4B F3 A7 05 1A 28, RECEIVE: 80 06 08 B6 DD 08 00 00

- after how to authentication with key A, read/write block?

- I send: 04 0D 60 01 FF FF FF FF FF FF 4B F3 A7 05 28, recieve: 87 00?

Ntuye.1
Associate II

CR95HF

- hello, i am use cr95hf to read, write block with is014443A tag 

>> SEND: 02 02 00 00

<< RECEIVE: 00 00

>> SEND: 02 07 02 00 00 00 00 02 02

<< RECEIVE: 00 00

>> SEND: 09 04 3A 00 5A 04

<< RECEIVE: 00 00

>> SEND: 09 04 68 01 01 DF

<< RECEIVE: 00 00

>> SEND: 04 02 26 07

<< RECEIVE: 80 05 04 00 28 00 00

>> SEND: 04 03 93 20 08

<< RECEIVE: 80 08 4B F3 A7 05 1A 28 00 00

>> SEND: 04 08 93 70 4B F3 A7 05 1A 28

<< RECEIVE: 80 06 08 B6 DD 08 00 00

- after how to authentication with key A, read/write block?

>> I send: 04 0D 60 01 FF FF FF FF FF FF 4B F3 A7 05 28

<< recieve: 87 00?

Brian TIDAL
ST Employee

Hi,

as explained in https://community.st.com/s/question/0D53W000003xs2CSAQ/cr95hf, the 87 00 timeout reply is caused by incorrectly formatted Auth with key A command.

Rgds

BT

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.