Using NXP Card Test Framework with SpringCard PC/SC Couplers

Card Test Framework is a GUI software provided by NXP to help the developers explore the features of their contactless cards (Mifare, Desfire, NTAG and ICode) and learn how-to use them from a real application.

This software is available to customers under NDA (non-disclosure agreement) with NXP, through the DocStore document delivery platform (ref. SW5434).

This article shows how-to get started with this Card Test Framework, in the aim of using it together with SpringCard devices.

Disclaimers

SpringCard is not affiliated, endorsed by, or sponsored by NXP. SpringCard provides this article "as is" at the date of writing in the hope that it will be useful - no updates nor support will be provided. In case you don't already have access the software depicted in this article, please contact your NXP representative.

Installing Card Test Framework and getting started with the software

Once approved by NXP, download the software from DocStore. Extract the setup (that is provided as an attachement inside a PDF file for security reasons), and run the setup.

You may then launch the software:

The main form looks like this:

To select the contactless reader, click Configuration in the top-level menu, and then Equipment.

This popup form shows the PC/SC readers that are actually connected to your computer (here we have a Prox'N'Roll and a Puck Base) as well as NXP test boards and reference PCDs (CLEV6630B, Pegoda) even if you don't have them.

Double-click the PC/SC reader you want to use (here the Puck's contactless slot) to add it into the list of selected equipements.

On the right part of the form, leave the default parameters:

  • No additional delay (0ms),
  • Protocol is Auto,
  • Communication Mode is Normal Mode.

Click OK to go back to the main form.

Creating your first test script

Card Test Framework uses scripts to send commands to a card (and manage its responses). We'll start with a very basic script to read the protocol-level ID of a contactless card (equal to its serial number in most situations).

1. Select the Scripts tab

2. In the Scripts tab, do a right-click in the left panel

3. In the popup menu, click New, then Full to create a complete script (not a subroutine).

4. Change the script's properties as follow:

  • Enter the name of your script in the Name edit box,
  • Un-check the Command Database Logging checkbox,
  • Un-check the Repetition Database Logging checkbox,
  • Un-check the Shmoo Database Logging checkbox.

5. Click the Commands label, located at the bottom left, to open the list of commands

6. Select the commands one after the other, and drag-and-drop them to the Test execution tab.

  • Communication / ISO14443 / Type A / Activate layer 4
  • APDU
  • Framework / MessageBox

7. Select the 'APDU' line in the Test execution tab and define its properties as follow:

  • Name: GET UID (this is informative only, the script does not use this data),
  • Command: FFCA000000 (this is the GET DATA - UID instruction of the device's embedded APDU interpreter),
  • Expected SW: 9000 (ISO 7816-4 "correct execution"),
  • Save to Shared Variable checkbox is checked.

8. Select the 'MessageBox' line in the Test execution tab and define its properties as follow:

  • Message: UID (+9000) = $Response$

9. Now place a card over the selected contactless reader, and click the run button located at the top left:

The software runs the script and terminates showing the UID (followed by the status word 9000).

The only purpose of this very basic sample is to show how-to send an APDU to the smart card (well, to the PC/SC reader itself in case of the CLAss of the APDU is FF, which is reserved for the internal APDU interpreter). This makes use the Card Test Framework software an alternative to SpringCard's PcscScriptor (a software from the PC/SC SDK) to test and validate a card transaction before writing any line of code.

Sample scripts for Desfire cards

Card Test Framework comes with two sample scripts that are interesting to discover the Desfire EV1 implementation. You'll need a (blank) NXP Desfire EV1 card to use these scripts (will work with EV2 and EV3 too, provided that the card has not been formatted yet).

To import a scripts, in the Scripts tab, do a right-click in the left panel, then click Import. Navigate to the Scripts\ExampleScripts sub-directory in the software's installation directory (namely C:\LocalData\Applications\NXP\CardTestFramework\2.4.7621.23695\Scripts\ExampleScripts), select the script file (.XML extension) and click Open.

The Desfire EV1 AES perso script

The goal of this first script is to format the card, with the directory structure (application and files) that will be used by the next script to store data (i.e. to write and read the files). This is a good introduction on how-to format or pre-personalize the Desfire card.

Aside terminology clarification: in many smart card standards and reference implementations, personalizing a card means writing the user's personal data in it. This step comes after the pre-personalization step where the card is formatted with the system's directory structure and authentication keys (and possibly non-user related data, such as meta-data to identify the issuer and document the version of the structure). NXP uses the word "perso" for the formatting script; this is a little confusing since this script does not write any data in the card.

Don't forget to un-check the 3 Command Database Loggin, Repetition Database Logging and Shmoo Database Logging on the right panel.

Before running the script, make sure to check both the Message Logging checkbox in the Output / Normal tab and the APDU Logging checkbox in the Output / Apdu tab.

Now place a (blank) Desfire EV1 on the SpringCard Contactless PC/SC reader and run the script.

Examining (and understanding) the execution log

The Output / Normal box shows the execution log (the bold emphasis are ours):

2021.09.30 09:32:17 : Message : Test set start. '1' test(s).
2021.09.30 09:32:17 : Message : Test start. TestSet: Default, Test: MIFARE DESFireEV1 AES Perso, Script: MIFARE DESFireEV1 AES Perso, Mode: Debug.
2021.09.30 09:32:18 : Message : Step 1: Hf-Pause: _1 Status: Pass
2021.09.30 09:32:18 : Message : Step 2: Activate Layer 4 Status: Pass
2021.09.30 09:32:18 : Message : Step 3: MfDfEv1Initialize Status: Pass
2021.09.30 09:32:18 : Message :       Parameter(s): wOption = 0, wKeyNo = 6, wKeyVer = 0, bKeyNoCard = 00, pDivInput =  
2021.09.30 09:32:18 : Message : Step 4: alMfdf.Sw: Authenticate DES Key 6 Status: Pass
2021.09.30 09:32:18 : Message :       Parameter(s): pMemInfo = 00, 1f, 00
2021.09.30 09:32:18 : Message : Step 5: alMfdf.Sw: FreeMem Status: Pass
2021.09.30 09:32:18 : Message : Step 6: alMfdf.Sw: FormatPICC Status: Pass
2021.09.30 09:32:18 : Message :       Parameter(s): bOption = 00, pAid = 00, 00, 01, bKeySettings1 = ef, bKeySettings2 = 83, pISOFileId =  , pISODFName =  
2021.09.30 09:32:18 : Message : Step 7: alMfdf.Sw: CreateApplication Status: Pass
2021.09.30 09:32:18 : Message :       Parameter(s): pAppId = 00, 00, 01
2021.09.30 09:32:18 : Message : Step 8: alMfdf.Sw: SelectApplication Status: Pass
2021.09.30 09:32:18 : Message :       Parameter(s): wOption = 0, wKeyNo = 0, wKeyVer = 0, bKeyNoCard = 00, pDivInput =  
2021.09.30 09:32:18 : Message : Step 9: alMfdf.Sw: AuthenticateAES128 Key 0 Status: Pass
2021.09.30 09:32:18 : Message :       Parameter(s): bOption = 00, bFileNo = 01, pISOFileId =  , bCommSett = 30, pAccessRights = 00, e2, pFileSize = 14, 00, 00
2021.09.30 09:32:18 : Message : Step 10: alMfdf.Sw: CreateStdDataFile 1 Status: Pass
2021.09.30 09:32:18 : Message :       Parameter(s): bOption = 00, bFileNo = 02, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = 1a, 00, 00
2021.09.30 09:32:18 : Message : Step 11: alMfdf.Sw: CreateStdDataFile 2 Status: Pass
2021.09.30 09:32:18 : Message :       Parameter(s): bOption = 00, bFileNo = 03, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = 30, 00, 00
2021.09.30 09:32:18 : Message : Step 12: alMfdf.Sw: CreateStdDataFile 3 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 04, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = d0, 02, 00
2021.09.30 09:32:19 : Message : Step 13: alMfdf.Sw: CreateStdDataFile 4 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 05, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = 16, 00, 00
2021.09.30 09:32:19 : Message : Step 14: alMfdf.Sw: CreateStdDataFile 5 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 06, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = 18, 00, 00
2021.09.30 09:32:19 : Message : Step 15: alMfdf.Sw: CreateStdDataFile 6 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 07, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = 40, 00, 00
2021.09.30 09:32:19 : Message : Step 16: alMfdf.Sw: CreateStdDataFile 7 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 08, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = 4a, 00, 00
2021.09.30 09:32:19 : Message : Step 17: alMfdf.Sw: CreateStdDataFile 8 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 09, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = 69, 00, 00
2021.09.30 09:32:19 : Message : Step 18: alMfdf.Sw: CreateStdDataFile 9 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 0a, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = 81, 01, 00
2021.09.30 09:32:19 : Message : Step 19: alMfdf.Sw: CreateStdDataFile 10 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 0b, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = ea, 01, 00
2021.09.30 09:32:19 : Message : Step 20: alMfdf.Sw: CreateStdDataFile 11 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 0c, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = c3, 00, 00
2021.09.30 09:32:19 : Message : Step 21: alMfdf.Sw: CreateStdDataFile 12 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 0d, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = 90, 00, 00
2021.09.30 09:32:19 : Message : Step 22: alMfdf.Sw: CreateStdDataFile 13 Status: Pass
2021.09.30 09:32:19 : Message :       Parameter(s): bOption = 00, bFileNo = 00, pISOFileId =  , bCommSett = 30, pAccessRights = 00, 12, pFileSize = 20, 00, 00
2021.09.30 09:32:19 : Message : Step 23: alMfdf.Sw: CreateBackupDataFile Status: Pass
2021.09.30 09:32:19 : Message : Test set completed.

Let's have a look on what this script does to the card:

  • Get authenticated with the card's master key - since the card is blank, this is still a DES key, hence the Authenticate DES line.

The value of the key (0000000000000000) is taken by the script from its own key-set, in key slot number 6.

To examine the key-set, select the script (not one of its commands) and click the icon that looks like a pin-pad after the Store Mifare keys with script checkbox in the script's Parameters panel:

This opens a new form showing all the keys (people who are already familiar with the NXP SAM AV1, SAM AV2 or SAM AV3 will recognize the SAM's key entry structure). Key slot number 6 actually contains a basic (EV0) Desfire key with all bytes equal to 00.

  • After the authentication, the script formats (blanks again) the card (FormatPICC command)
  • The script then creates a directory (CreateApplication command). The identifier of the directory (AID) is 000001. The two Key Settings bytes (see Desfire EV1 datasheet for details) specify the number of keys and the fact that the keys will be AES.
  • The script now enters the directory (SelectApplication command with AID = 000001).
  • The script gets authenticated with the newly-created application's master key (key number 00 within the application, still having its default value 00000000000000000000000000000000). For the key is AES128, the corresponding command (AuthenticateAES128) is used. Again, use the key-set form to retrieve this value (key slot number 00 in the key-set).
  • Once the authenticated, the script is able to create a few files inside the application's directory.

Digging into the APDU exchanged between the software and the card

What may be the most interesting from a software developer point-of-view is the APDU log, because it details the commands to send through SCardTransmit to perform the same transaction with the card.

The Output / Apdu box shows this alternate view of the execution log (again, the bold emphasis are ours):

2021.09.30 09:32:18 : Message : Test start. TestSet: Default, Test: MIFARE DESFireEV1 AES Perso, Script: MIFARE DESFireEV1 AES Perso, Mode: Debug.
2021.09.30 09:32:18 : Message : Name: 4 alMfdf.Sw: Authenticate DES Key 6
2021.09.30 09:32:18 : Message :      Transmitted: 
2021.09.30 09:32:18 : Message :      Response:     
2021.09.30 09:32:18 : Message : Name: 5 alMfdf.Sw: FreeMem
2021.09.30 09:32:18 : Message :      Transmitted: 6E
2021.09.30 09:32:18 : Message :      Response:     00001F00
2021.09.30 09:32:18 : Message : Name: 6 alMfdf.Sw: FormatPICC
2021.09.30 09:32:18 : Message :      Transmitted: FC
2021.09.30 09:32:18 : Message :      Response:     00
2021.09.30 09:32:18 : Message : Name: 7 alMfdf.Sw: CreateApplication
2021.09.30 09:32:18 : Message :      Transmitted: CA000001EF83
2021.09.30 09:32:18 : Message :      Response:     00
2021.09.30 09:32:18 : Message : Name: 8 alMfdf.Sw: SelectApplication
2021.09.30 09:32:18 : Message :      Transmitted: 5A000001
2021.09.30 09:32:18 : Message :      Response:     00
2021.09.30 09:32:18 : Message : Name: 9 alMfdf.Sw: AuthenticateAES128 Key 0
2021.09.30 09:32:18 : Message :      Transmitted: AA00
2021.09.30 09:32:18 : Message :      Response:     AFAE50D410DCDEFE05B1D163595187EBC1
2021.09.30 09:32:18 : Message :      Transmitted: AF12F28CBAB0FAF9E0D9370DF9B038F788414735A2400C1F314BDDA417D5978003
2021.09.30 09:32:18 : Message :      Response:     00E81B4D4716DECA688061F197F4FC2347
2021.09.30 09:32:18 : Message : Name: 10 alMfdf.Sw: CreateStdDataFile 1
2021.09.30 09:32:18 : Message :      Transmitted: CD010300E2140000
2021.09.30 09:32:18 : Message :      Response:     000EDF1B36BC4F842B
2021.09.30 09:32:18 : Message : Name: 11 alMfdf.Sw: CreateStdDataFile 2
2021.09.30 09:32:18 : Message :      Transmitted: CD020300121A0000
2021.09.30 09:32:18 : Message :      Response:     00CE30507B5CCB47DB
2021.09.30 09:32:18 : Message : Name: 12 alMfdf.Sw: CreateStdDataFile 3
2021.09.30 09:32:18 : Message :      Transmitted: CD03030012300000
2021.09.30 09:32:18 : Message :      Response:     0084FDFAA452103FE9
2021.09.30 09:32:19 : Message : Name: 13 alMfdf.Sw: CreateStdDataFile 4
2021.09.30 09:32:19 : Message :      Transmitted: CD04030012D00200
2021.09.30 09:32:19 : Message :      Response:     00D88DA8AF65653E05
2021.09.30 09:32:19 : Message : Name: 14 alMfdf.Sw: CreateStdDataFile 5
2021.09.30 09:32:19 : Message :      Transmitted: CD05030012160000
2021.09.30 09:32:19 : Message :      Response:     005DDE9162BE7AA56D
2021.09.30 09:32:19 : Message : Name: 15 alMfdf.Sw: CreateStdDataFile 6
2021.09.30 09:32:19 : Message :      Transmitted: CD06030012180000
2021.09.30 09:32:19 : Message :      Response:     00385416E1A98A2C8D
2021.09.30 09:32:19 : Message : Name: 16 alMfdf.Sw: CreateStdDataFile 7
2021.09.30 09:32:19 : Message :      Transmitted: CD07030012400000
2021.09.30 09:32:19 : Message :      Response:     00032276A94CE5A929
2021.09.30 09:32:19 : Message : Name: 17 alMfdf.Sw: CreateStdDataFile 8
2021.09.30 09:32:19 : Message :      Transmitted: CD080300124A0000
2021.09.30 09:32:19 : Message :      Response:     001E143774D6030E2E
2021.09.30 09:32:19 : Message : Name: 18 alMfdf.Sw: CreateStdDataFile 9
2021.09.30 09:32:19 : Message :      Transmitted: CD09030012690000
2021.09.30 09:32:19 : Message :      Response:     0072ED1982E15603F5
2021.09.30 09:32:19 : Message : Name: 19 alMfdf.Sw: CreateStdDataFile 10
2021.09.30 09:32:19 : Message :      Transmitted: CD0A030012810100
2021.09.30 09:32:19 : Message :      Response:     00DE447B31F5B52CFA
2021.09.30 09:32:19 : Message : Name: 20 alMfdf.Sw: CreateStdDataFile 11
2021.09.30 09:32:19 : Message :      Transmitted: CD0B030012EA0100
2021.09.30 09:32:19 : Message :      Response:     008A2DDAEBD2C885C2
2021.09.30 09:32:19 : Message : Name: 21 alMfdf.Sw: CreateStdDataFile 12
2021.09.30 09:32:19 : Message :      Transmitted: CD0C030012C30000
2021.09.30 09:32:19 : Message :      Response:     0005DD6B1399C4F4A6
2021.09.30 09:32:19 : Message : Name: 22 alMfdf.Sw: CreateStdDataFile 13
2021.09.30 09:32:19 : Message :      Transmitted: CD0D030012900000
2021.09.30 09:32:19 : Message :      Response:     00A0D5D7CDC522CEC5
2021.09.30 09:32:19 : Message : Name: 23 alMfdf.Sw: CreateBackupDataFile
2021.09.30 09:32:19 : Message :      Transmitted: CB00030012200000
2021.09.30 09:32:19 : Message :      Response:     00ECB3E1B72DFE352A

Things worth noticing:

  • The initial Authenticate command (with the DES key) does not trace its APDU - too bad. Looking with a PC/SC spy would show that the script sends 0A00 (EV0 authentication, key number 00),
  • The AuthenticateAES128 command shows all its detail. Random numbers are exchanged between the software and the card to perform the mutual authentication and establish a (disposable) session key. This is the trickiest part when you have to write your own Desfire implementation (hopefully, the SpringCard PC/SC SDK features 2 libraries, one in C and the other in C#, that already do the job).
  • All commands and responses are transmitted 'as is', without ISO/IEC 7816-4 encapsulation. This is normally not allowed by PC/SC for, according to the standard, all smart cards must use the APDU format (CLA, INS, P1, P2 ...) but is possible because the SpringCard's driver and firmware are tolerant to transmitting raw Desfire frames. A standard-compliant implementation would either use the card-side 7816-4 encapsulation (wrapping of Desfire native commands in APDUs with CLA=90, the unwrapping being done by the card itself) or the reader-side 7816-4 encapsulation (wrapping of Desfire native commands in APDUs with CLA=FF and INS=FE, the unwrapping being done by the reader's embedded APDU interpreter).

The Desfire EV1 Read/Write script

After the card has been pre-personalized with the previous script, use the read/write script to populate one its files.

Here's the execution log:

2021.09.30 11:16:04 : Message : Test set start. '1' test(s).
2021.09.30 11:16:05 : Message : Test start. TestSet: Default, Test: MIFARE DESFireEV1 ReadWrite, Script: MIFARE DESFireEV1 ReadWrite, Mode: Debug.
2021.09.30 11:16:06 : Message : Step 1: Hf-Pause Status: Pass
2021.09.30 11:16:06 : Message : Step 2: Activate Layer 4 Status: Pass
2021.09.30 11:16:06 : Message : Step 3: MfDfEv1Initialize Status: Pass
2021.09.30 11:16:06 : Message :       Parameter(s): pAidBuff = 00, 00, 01
2021.09.30 11:16:06 : Message : Step 4: alMfdf.Sw: GetApplicationIDs Status: Pass
2021.09.30 11:16:06 : Message :       Parameter(s): pAppId = 00, 00, 01
2021.09.30 11:16:06 : Message : Step 5: alMfdf.Sw: SelectApplication Status: Pass
2021.09.30 11:16:06 : Message :       Parameter(s): wOption = 0, wKeyNo = 0, wKeyVer = 0, bKeyNoCard = 00, pDivInput =  
2021.09.30 11:16:06 : Message : Step 6: alMfdf.Sw: AuthenticateAES128 key 0 Status: Pass
2021.09.30 11:16:06 : Message :       Parameter(s): pFid = 01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 00
2021.09.30 11:16:06 : Message : Step 7: alMfdf.Sw: GetFileIDs Status: Pass
2021.09.30 11:16:07 : Message :       Parameter(s): wOption = 30, bFileNo = 00, pOffset = 00, 00, 00, pLength = 20, 00, 00, pRxdata = 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
2021.09.30 11:16:07 : Message : Step 8: alMfdf.Sw: ReadData Status: Pass
2021.09.30 11:16:07 : Message :       Parameter(s): wOption = 30, bFileNo = 00, pOffset = 00, 00, 00, pTxData = e3, b5, 20, c9, 70, 98, 85, 90, 91, 98, c2, 0d, 8a, 7f, 0d, 6a, fc, 09, 74, 9f, 10, 3e, 01, f8, 8b, 81, d9, 8e, b0, 68, b2, d2, pTxDataLen = 20, 00, 00
2021.09.30 11:16:07 : Message : Step 9: alMfdf.Sw: WriteData Status: Pass
2021.09.30 11:16:07 : Message : Step 10: alMfdf.Sw: CommitTransaction Status: Pass
2021.09.30 11:16:07 : Message : Test set completed.

And the APDU log:

2021.09.30 11:16:05 : Message : Test start. TestSet: Default, Test: MIFARE DESFireEV1 ReadWrite, Script: MIFARE DESFireEV1 ReadWrite, Mode: Debug.
2021.09.30 11:16:06 : Message : Name: 4 alMfdf.Sw: GetApplicationIDs
2021.09.30 11:16:06 : Message :      Transmitted: 6A
2021.09.30 11:16:06 : Message :      Response:     00000001
2021.09.30 11:16:06 : Message : Name: 5 alMfdf.Sw: SelectApplication
2021.09.30 11:16:06 : Message :      Transmitted: 5A000001
2021.09.30 11:16:06 : Message :      Response:     00
2021.09.30 11:16:06 : Message : Name: 6 alMfdf.Sw: AuthenticateAES128 key 0
2021.09.30 11:16:06 : Message :      Transmitted: AA00
2021.09.30 11:16:06 : Message :      Response:     AFA377686291124362BF6D29B2B99B7A63
2021.09.30 11:16:06 : Message :      Transmitted: AFD67BE53BC3FBA73F3F684B982156FFF82F8CEF0256BB96BEC3CE5C41351FF347
2021.09.30 11:16:06 : Message :      Response:     00A7D1FCFF6616BD461FB1D7175A94DEC3
2021.09.30 11:16:06 : Message : Name: 7 alMfdf.Sw: GetFileIDs
2021.09.30 11:16:06 : Message :      Transmitted: 6F
2021.09.30 11:16:06 : Message :      Response:     000102030405060708090A0B0C0D00B93F4F764867408A
2021.09.30 11:16:07 : Message : Name: 8 alMfdf.Sw: ReadData
2021.09.30 11:16:07 : Message :      Transmitted: BD00000000200000
2021.09.30 11:16:07 : Message :      Response:     00C065B27A9F213B82272481B4DE183D1162B9962984EBC0BAA75EDA32AF29E41C5BEC6A871EF68E8E9ADFB0FB582476F8
2021.09.30 11:16:07 : Message : Name: 9 alMfdf.Sw: WriteData
2021.09.30 11:16:07 : Message :      Transmitted: 3D00000000200000E3B520C9709885909198C20D8A7F0D6AFC09749F103E01F88B81D98EB068B2D21B25723242E399AA7A8C1DAA94790C09
2021.09.30 11:16:07 : Message :      Response:     0020B1ECBFE51F3D5A
2021.09.30 11:16:07 : Message : Name: 10 alMfdf.Sw: CommitTransaction
2021.09.30 11:16:07 : Message :      Transmitted: C7
2021.09.30 11:16:07 : Message :      Response:     00E88ABC42A731336F

Note that the script writes AA00000000000000000000000000000000000000000000000000000000000000, but this value does not appear anywhere in the execution. This is because of the ciphering.

Again, a developer could use this script as the reference to implement a Desfire transaction in his own application, but the authentication and cipher part may be tricky unless a Desfire library is used (such as the ones in SpringCard PC/SC SDK).

Conclusion

The Card Test Framework by NXP is an interesting tool to get familiar with the low-level implementation of their cards and tags (not only Desfire EV1 but also Desfire EV2, EV3 and Light, Mifare Plus EV0 and EV1, Mifare UltraLight EV0, EV1 and C, and of course the still popular Mifare Classic).

Even the integrators and developers who don't have to dig deeply into all implementation details will undoubtedly find useful to use this training tool for learning and understanding the logic of the cards before building their own application.

Since the software works well with SprinCard PC/SC couplers, such as Prox'N'Roll, Puck, and more, there's no need to buy a dedicated test reader to get a training.