Mifare Classic authentication

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Mifare Classic authentication

5,875 Views
r5d1
Contributor I

Hi all,

I have PNEV5180 board and Mifare Plus card in SL1  Mifare Classic emulation mode.

I try to work with sector number 8 and known keys.

This Android application works with this card without problem https://github.com/gshevtsov/TroikaDumper

I tried sample NfcrdlibEx4_MIFAREClassic from NFC Reader Library package. 

In result:

UID:  04 4D 3C 92 61 36 80
ATQA: 44 00
SAK: 0x8
Product: MIFARE Classic
Authentication Failed!!! Please correct the used key

I change only the NUMBER_OF_KEYENTRIES, Key and sector number in example. 

What is wrong? Should I make anything else?

---------------------------------------------------

/*
*         Copyright (c), NXP Semiconductors Bangalore
*/

//NFC Reader Library v4.040.05.011646 R1 for PNEV512B including all software examples.

/**
* Reader Library Headers
*/
#include <phApp_Init.h>

#include "NfcrdlibEx4_MIFAREClassic.h"

//#define NUMBER_OF_KEYENTRIES        2 // original
#define NUMBER_OF_KEYENTRIES        16    // !!!
#define NUMBER_OF_KEYVERSIONPAIRS   2
#define NUMBER_OF_KUCENTRIES        1

#define DATA_BUFFER_LEN             16 /* Buffer length */
#define MFC_BLOCK_DATA_SIZE         16 /* Block Data size - 16 Bytes */

/*******************************************************************************
**   Global Variable Declaration
*******************************************************************************/

/*HAL variables*/
uint8_t                            bHalBufferTx[128];          /* HAL  TX buffer */
uint8_t                            bHalBufferRx[128];          /* HAL  RX buffer */

/*PAL variables*/
phKeyStore_Sw_KeyEntry_t           sKeyEntries[NUMBER_OF_KEYENTRIES];                                  /* Sw KeyEntry structure */
phKeyStore_Sw_KUCEntry_t           sKUCEntries[NUMBER_OF_KUCENTRIES];                                  /* Sw Key usage counter structure */
phKeyStore_Sw_KeyVersionPair_t     sKeyVersionPairs[NUMBER_OF_KEYVERSIONPAIRS * NUMBER_OF_KEYENTRIES]; /* Sw KeyVersionPair structure */

uint8_t                            bDataBuffer[DATA_BUFFER_LEN];  /* universal data buffer */

uint8_t                            bSak;                      /* SAK  card type information */
uint16_t                           wAtqa;                     /* ATQA card type information */

#define SECTOR    8 // !!!

/* Set the key for the MIFARE (R) Classic cards. */
uint8_t Key_8B[6] = { 0x13U, 0x51U, 0x23U, 0x49U, 0x3AU, 0x81U };    // !!!
uint8_t Key_8A[6] = { 0x17U, 0x3FU, 0x2DU, 0xC1U, 0x33U, 0x33U };   // !!!

uint8_t Key[6] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};


/* Don't change the following line */
uint8_t Original_Key[6] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};

#ifdef PHOSAL_FREERTOS_STATIC_MEM_ALLOCATION
uint32_t aMfClscTaskBuffer[MIFARECLASSIC_TASK_STACK];
#else /* PHOSAL_FREERTOS_STATIC_MEM_ALLOCATION */
#define aMfClscTaskBuffer       NULL
#endif /* PHOSAL_FREERTOS_STATIC_MEM_ALLOCATION */

/*******************************************************************************
**   Function Declarations
*******************************************************************************/
void NfcrdlibEx4_MIFAREClassic(void *pParams);
static phStatus_t Ex4_NfcRdLibInit(void);

/*******************************************************************************
**   Function Definitions
*******************************************************************************/

/*******************************************************************************
**   Main Function
*******************************************************************************/
int main (void)
{
    do{
        phStatus_t status = PH_ERR_INTERNAL_ERROR;

        /* Initialize the Controller */
        phPlatform_Controller_Init();

        /* Print Example application name */
        DEBUG_PRINTF("\n *** MIFARE Classic Example *** \n");

        phOsal_Init();

        /* Perform Platform Init */
        status = phPlatform_Init(&sPlatform, bHalBufferTx, sizeof(bHalBufferTx), bHalBufferRx, sizeof(bHalBufferRx));
        CHECK_STATUS(status);
        if(status != PH_ERR_SUCCESS) break;

        /* Initialize Reader Library PAL/AL Components */
        status = phApp_RdLibInit();
        CHECK_STATUS(status);
        if(status != PH_ERR_SUCCESS) break;

        /* Set the generic pointer */
        pHal = &sPlatform.sHal;

#ifndef NXPBUILD__PH_OSAL_NULLOS

        phOsal_ThreadObj_t MfClsc;

        MfClsc.pTaskName = (uint8_t *) "MfClsc";
        MfClsc.pStackBuffer = aMfClscTaskBuffer;
        MfClsc.priority = MIFARECLASSIC_TASK_PRIO;
        MfClsc.stackSizeInNum = MIFARECLASSIC_TASK_STACK;
        phOsal_ThreadCreate(&MfClsc.ThreadHandle, &MfClsc, &NfcrdlibEx4_MIFAREClassic, NULL);

        phOsal_StartScheduler();

        /* Print Error info */
        DEBUG_PRINTF("RTOS Error : Scheduler exited. \n");

#else
        (void)NfcrdlibEx4_MIFAREClassic(&sDiscLoop);
#endif
    } while(0);

    while(1); //Comes here if initialization failure or scheduler exit due to error

    return 0;
}

/***********************************************************************************************
 * \brief   This function demonstrates the MIFARE Classic card detection, Block authentication,
 *          Block Read and Block Write operation.
 * \param   *pParams
 * \return  This function will never return
 **********************************************************************************************/
void NfcrdlibEx4_MIFAREClassic(void *pParams)
{
    phStatus_t  status = 0;
    uint16_t    wTagsDetected = 0;
    uint8_t     bUid[PHAC_DISCLOOP_I3P3A_MAX_UID_LENGTH];
    uint8_t     bUidSize;

    /* Initialize components required by this example. */
    status = Ex4_NfcRdLibInit();

    while(1)    /* Continuous loop */
    {
        DEBUG_PRINTF("\nReady to detect\n");

        do
        {
            /* Field OFF */
            status = phhalHw_FieldOff(pHal);
            CHECK_STATUS(status);

            status = phhalHw_Wait(sDiscLoop.pHalDataParams,PHHAL_HW_TIME_MICROSECONDS, 5100);
            CHECK_STATUS(status);

            /* Configure Discovery loop for Poll Mode */
            status = phacDiscLoop_SetConfig(&sDiscLoop, PHAC_DISCLOOP_CONFIG_NEXT_POLL_STATE, PHAC_DISCLOOP_POLL_STATE_DETECTION);
            CHECK_STATUS(status);

            /* Run Discovery loop */
            status = phacDiscLoop_Run(&sDiscLoop, PHAC_DISCLOOP_ENTRY_POINT_POLL);

        }while((status & PH_ERR_MASK) != PHAC_DISCLOOP_DEVICE_ACTIVATED); /* Exit on Card detection */

        /* Card detected */
        /* Get the tag types detected info */
        status = phacDiscLoop_GetConfig(&sDiscLoop, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &wTagsDetected);

        /* Check for Status */
        if ((status & PH_ERR_MASK) == PH_ERR_SUCCESS)
        {
            /* Check for Type A tag detection */
            if (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A))
            {
                /* Check for MIFARE Classic */
                if (0x08 == (sDiscLoop.sTypeATargetInfo.aTypeA_I3P3[0].aSak & 0x08))
                {
                    do
                    {
                        /* Print UID */
                        DEBUG_PRINTF ("\nUID: ");
                        phApp_Print_Buff(sDiscLoop.sTypeATargetInfo.aTypeA_I3P3[0].aUid,
                                sDiscLoop.sTypeATargetInfo.aTypeA_I3P3[0].bUidSize);

                        /* Print ATQA  and SAK */
                        DEBUG_PRINTF("\nATQA:");
                        phApp_Print_Buff(sDiscLoop.sTypeATargetInfo.aTypeA_I3P3[0].aAtqa, 2);
                        DEBUG_PRINTF ("\nSAK: 0x%x",sDiscLoop.sTypeATargetInfo.aTypeA_I3P3[0].aSak);

                        /* Print Product type */
                        DEBUG_PRINTF("\nProduct: MIFARE Classic \n");

                        bUidSize = sDiscLoop.sTypeATargetInfo.aTypeA_I3P3[0].bUidSize;
                        memcpy(bUid, sDiscLoop.sTypeATargetInfo.aTypeA_I3P3[0].aUid, bUidSize);

                        /* Authenticate with the Key
                         * We can authenticate at any block of a sector and we will get the access to all blocks of the same sector
                         * For example authenticating at block 5, we will get the access to blocks 4, 5, 6 and 7.
                         */
                        /* Send authentication for block 6 */
                        //status = phalMfc_Authenticate(&salMFC, 6, PHHAL_HW_MFC_KEYA, 1, 0, bUid, bUidSize); // original
                        status = phalMfc_Authenticate(&salMFC, 6, PHHAL_HW_MFC_KEYA, SECTOR, 0, bUid, bUidSize); // !!!

                        /* Check for Status */
                        if ((status & PH_ERR_MASK) != PH_ERR_SUCCESS)
                        {
                            /* Print Error info */
                            DEBUG_PRINTF("\nAuthentication Failed!!!");
                            DEBUG_PRINTF("\nPlease correct the used key");
                            DEBUG_PRINTF("\nExecution aborted!!!\n");
                            break;
                        }

                        DEBUG_PRINTF("\nAuthentication Successful");

                        /* Empty the bDataBuffer */
                        memset(bDataBuffer, '\0', DATA_BUFFER_LEN);

                        DEBUG_PRINTF("\nRead data from Block 4");

                        /* Read data from block 4 */
                        status = phalMfc_Read(&salMFC, 4, bDataBuffer);

                        /* Check for Status */
                        if (status != PH_ERR_SUCCESS)
                        {
                            /* Print Error info */
                            DEBUG_PRINTF("\nRead operation failed!!!\n");
                            DEBUG_PRINTF("\nExecution aborted!!!\n\n");
                            break; /* Break from the loop*/
                        }

                        DEBUG_PRINTF("\nRead Success");
                        DEBUG_PRINTF("\nThe content of Block 4 is:\n");

                        phApp_Print_Buff(&bDataBuffer[0], MFC_BLOCK_DATA_SIZE);
                        DEBUG_PRINTF("\n\n --- End of Read Operation --- \n");

                        DEBUG_PRINTF("\nWrite data to Block 4");

                        /* Write data to block 4 */
                        status = phalMfc_Write(&salMFC, 4, bDataBuffer);

                        /* Check for Status */
                        if (status != PH_ERR_SUCCESS)
                        {
                            /* Print Error info */
                            DEBUG_PRINTF("\nWrite operation failed!!!\n");
                            DEBUG_PRINTF("\nExecution aborted!!!\n");
                            break; /* Break from the loop*/
                        }

                        DEBUG_PRINTF("\nWrite Success");
                        DEBUG_PRINTF("\n\n --- End of Write Operation --- ");

                        /* End of example */
                        DEBUG_PRINTF("\n\n --- End of Example --- \n\n");

                    }while(0);

                    DEBUG_PRINTF("\nPlease Remove the Card\n\n");

                    /* Field RESET */
                    status = phhalHw_FieldReset(pHal);
                    CHECK_STATUS(status);

                    /* Make sure that example application is not detecting the same card continuously */
                    do
                    {
                        /* Send WakeUpA */
                        status = phpalI14443p3a_WakeUpA(sDiscLoop.pPal1443p3aDataParams,
                                                        sDiscLoop.sTypeATargetInfo.aTypeA_I3P3[0].aAtqa);

                        /* Check for Status */
                        if (status != PH_ERR_SUCCESS)
                        {
                            break; /* Card Removed, break from the loop */
                        }

                        /* Send HaltA */
                        status = phpalI14443p3a_HaltA(sDiscLoop.pPal1443p3aDataParams);
                        CHECK_STATUS(status);

                        /* Delay - 5 milli seconds*/
                        status = phhalHw_Wait(sDiscLoop.pHalDataParams, PHHAL_HW_TIME_MILLISECONDS, 5);
                        CHECK_STATUS(status);

                    }while(1);
                }
            }
        }
    }
}

/***********************************************************************************************
 * \brief   Initializes the discovery loop and keystore components required by Example-4
 * \param   none
 * \return  status  Returns the function status
 **********************************************************************************************/
static phStatus_t Ex4_NfcRdLibInit(void)
{
    phStatus_t status;

    /* Device limit for Type A */
    status = phacDiscLoop_SetConfig(&sDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEA_DEVICE_LIMIT, 1);
    CHECK_STATUS(status);

    /* Bailout on Type A detect */
    status = phacDiscLoop_SetConfig(&sDiscLoop, PHAC_DISCLOOP_CONFIG_BAIL_OUT, PHAC_DISCLOOP_POS_BIT_MASK_A);
    CHECK_STATUS(status);

    /* Initialize the keystore component */
    status = phKeyStore_Sw_Init(
        &sPlatform.sKeyStore,
        sizeof(phKeyStore_Sw_DataParams_t),
        &sKeyEntries[0],
        NUMBER_OF_KEYENTRIES,
        &sKeyVersionPairs[0],
        NUMBER_OF_KEYVERSIONPAIRS,
        &sKUCEntries[0],
        NUMBER_OF_KUCENTRIES
        );
    CHECK_STATUS(status);

    /* load a Key to the Store */
    /* Note: If You use Key number 0x00, be aware that in SAM
      this Key is the 'Host authentication key' !!! */
    //status = phKeyStore_FormatKeyEntry(&sPlatform.sKeyStore, 1, PH_KEYSTORE_KEY_TYPE_MIFARE);    // original
    status = phKeyStore_FormatKeyEntry(&sPlatform.sKeyStore, SECTOR, PH_KEYSTORE_KEY_TYPE_MIFARE); // !!!
    CHECK_STATUS(status);

    /* Set Key Store */
    //status = phKeyStore_SetKey(&sPlatform.sKeyStore, 1, 0, PH_KEYSTORE_KEY_TYPE_MIFARE, &Key[0], 0); // original
    status = phKeyStore_SetKey(&sPlatform.sKeyStore, SECTOR, 0, PH_KEYSTORE_KEY_TYPE_MIFARE, &Key_8A[0], 0); // !!!
    CHECK_STATUS(status);

    /* Read the version of the reader IC */
#if defined NXPBUILD__PHHAL_HW_RC523
    status = phhalHw_Rc523_ReadRegister(&sPlatform.sHal, PHHAL_HW_RC523_REG_VERSION, &bDataBuffer[0]);
    CHECK_STATUS(status);
    DEBUG_PRINTF("\nReader chip PN512: 0x%02x\n", bDataBuffer[0]);
#endif
#if defined NXPBUILD__PHHAL_HW_RC663
    status = phhalHw_Rc663_ReadRegister(&sPlatform.sHal, PHHAL_HW_RC663_REG_VERSION, &bDataBuffer[0]);
    CHECK_STATUS(status);
    DEBUG_PRINTF("\nReader chip RC663: 0x%02x\n", bDataBuffer[0]);
#endif

    /* Return Success */
    return PH_ERR_SUCCESS;
}

/* Stubs, in case the phApp_Init.c expects these implementations */
#ifdef NXPBUILD__PHPAL_I14443P4MC_SW
/*
 * WTX Callback called from WTX timer of 14443p3mC PAL.
 */
void pWtoxCallBck(uint8_t bTimerId)
{
  /* Dummy */
}

uint8_t aAppHCEBuf[32];
uint16_t wAppHCEBuffSize = sizeof(aAppHCEBuf);
#endif /* NXPBUILD__PHPAL_I14443P4MC_SW */

#ifdef NXPBUILD__PHPAL_I18092MT_SW
void pRtoxCallBck(uint8_t bTimerId)
{
  /* Dummy */
}
#endif /* NXPBUILD__PHPAL_I18092MT_SW */

#ifdef NXPBUILD__PHHAL_HW_TARGET
/* Stubbed definitions in case TARGET is enabled */
uint8_t  sens_res[2]     = {0x04, 0x00};
uint8_t  nfc_id1[3]      = {0xA1, 0xA2, 0xA3};
uint8_t  sel_res         = 0x40;
uint8_t  nfc_id3         = 0xFA;
uint8_t  poll_res[18]    = {0x01, 0xFE, 0xB2, 0xB3, 0xB4, 0xB5,
                                   0xB6, 0xB7, 0xC0, 0xC1, 0xC2, 0xC3,
                                   0xC4, 0xC5, 0xC6, 0xC7, 0x23, 0x45 };
#endif /* NXPBUILD__PHHAL_HW_TARGET */

/***********************************************************************************************
 *                            End Of File
 **********************************************************************************************/

Labels (1)
0 Kudos
1 Reply

2,886 Views
IvanRuiz
NXP Employee
NXP Employee

Hello T L,

In order to work with sector 8 it is needed to authenticate in one of the blocks within sector 8.

Mifare's sectors structure

Mifare classic 1K: EEPROM memory is organized in 16 sectors of 4 blocks.

Mifare classic 4K: EEPROM memory is organized in 32 sectors of 4 blocks and 8 sectors of 16 blocks.

Sector 8 corresponds to Block 32 (Sector 8 * 4 blocks = Block 32). The authentication must be made within this sector, starting from block 32 to block 35.

 

Code section:

#define NUMBER_OF_KEYENTRIES        2

#define NUMBER_OF_KEYVERSIONPAIRS   2

#define NUMBER_OF_KUCENTRIES        1

 

/* Set the key for the MIFARE (R) Classic cards. */

uint8_t Key[6] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};

 

/* Don't change the following line */

uint8_t Original_Key[6] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};

 

/* Send authentication for block 32 (sector 8) */

status = phalMfc_Authenticate(&salMFC, 32, PHHAL_HW_MFC_KEYA, 1, 0, bUid, bUidSize);

 

Once you’ve already authenticated in this sector, you’ll be able to get access to all blocks of sector 8.

 

Debug section:

pastedImage_3.png

Best regards,

Ivan.

0 Kudos