@@ -2568,91 +2568,190 @@ int CmdHF14BNdefRead(const char *Cmd) {
25682568 // --------------- Select NDEF Tag application ----------------
25692569 uint8_t aSELECT_AID [80 ];
25702570 int aSELECT_AID_n = 0 ;
2571- param_gethex_to_eol ("00a4040007d276000085010100" , 0 , aSELECT_AID , sizeof (aSELECT_AID ), & aSELECT_AID_n );
2571+ // It's likely safe to ignore the backwards compatibility select that's present in the 14443A part of this code.
2572+ // Full-fledged 14443B is rare, after all. And if not.. your eMRTD passport doesn't have NDEF for a fact.
2573+ param_gethex_to_eol ("00a4040007d276000085010100" , 0 , aSELECT_AID , sizeof (aSELECT_AID ), & aSELECT_AID_n ); // Select NDEF application D2760000850101
25722574 int res = exchange_14b_apdu (aSELECT_AID , aSELECT_AID_n , activate_field , keep_field_on , response , sizeof (response ), & resplen , -1 );
25732575 if (res ) {
2574- goto out ;
2576+ switch_off_field_14b ();
2577+ return res ;
25752578 }
25762579
25772580 if (resplen < 2 ) {
25782581 res = PM3_ESOFT ;
2579- goto out ;
2582+ switch_off_field_14b ();
2583+ return res ;
25802584 }
25812585
25822586 uint16_t sw = get_sw (response , resplen );
25832587 if (sw != ISO7816_OK ) {
2584- PrintAndLogEx (ERR , "Selecting NDEF aid failed (%04x - %s)." , sw , GetAPDUCodeDescription (sw >> 8 , sw & 0xff ));
2588+ PrintAndLogEx (ERR , "Selecting NDEF AID failed (%04x - %s)." , sw , GetAPDUCodeDescription (sw >> 8 , sw & 0xff ));
25852589 res = PM3_ESOFT ;
2586- goto out ;
2590+ switch_off_field_14b ();
2591+ return res ;
25872592 }
25882593
25892594 activate_field = false;
25902595 keep_field_on = true;
2591- // --------------- Send CC select ----------------
2592- // --------------- Read binary ----------------
25932596
2594- // --------------- NDEF file reading ----------------
2595- uint8_t aSELECT_FILE_NDEF [30 ];
2596- int aSELECT_FILE_NDEF_n = 0 ;
2597- param_gethex_to_eol ("00a4000c020001" , 0 , aSELECT_FILE_NDEF , sizeof (aSELECT_FILE_NDEF ), & aSELECT_FILE_NDEF_n );
2598- res = exchange_14b_apdu (aSELECT_FILE_NDEF , aSELECT_FILE_NDEF_n , activate_field , keep_field_on , response , sizeof (response ), & resplen , -1 );
2599- if (res )
2600- goto out ;
2597+ // --------------- CC file reading ----------------
2598+ uint8_t aSELECT_FILE_CC [30 ];
2599+ int aSELECT_FILE_CC_n = 0 ;
2600+ param_gethex_to_eol ("00a4000c02e103" , 0 , aSELECT_FILE_CC , sizeof (aSELECT_FILE_CC ), & aSELECT_FILE_CC_n ); // Select E103 file with payload information
2601+ res = exchange_14b_apdu (aSELECT_FILE_CC , aSELECT_FILE_CC_n , activate_field , keep_field_on , response , sizeof (response ), & resplen , -1 );
2602+ if (res ) {
2603+ switch_off_field_14b ();
2604+ return res ;
2605+ }
26012606
26022607 sw = get_sw (response , resplen );
26032608 if (sw != ISO7816_OK ) {
2604- PrintAndLogEx (ERR , "Selecting NDEF file failed (%04x - %s)." , sw , GetAPDUCodeDescription (sw >> 8 , sw & 0xff ));
2609+ PrintAndLogEx (ERR , "Selecting CC file failed (%04x - %s)." , sw , GetAPDUCodeDescription (sw >> 8 , sw & 0xff ));
26052610 res = PM3_ESOFT ;
2606- goto out ;
2611+ switch_off_field_14b ();
2612+ return res ;
26072613 }
26082614
26092615 // --------------- Read binary ----------------
2610- uint8_t aREAD_NDEF [30 ];
2611- int aREAD_NDEF_n = 0 ;
2612- param_gethex_to_eol ("00b0000002 " , 0 , aREAD_NDEF , sizeof (aREAD_NDEF ), & aREAD_NDEF_n );
2613- res = exchange_14b_apdu (aREAD_NDEF , aREAD_NDEF_n , activate_field , keep_field_on , response , sizeof (response ), & resplen , -1 );
2616+ uint8_t aREAD_CC [30 ];
2617+ int aREAD_CC_n = 0 ;
2618+ param_gethex_to_eol ("00b000000f " , 0 , aREAD_CC , sizeof (aREAD_CC ), & aREAD_CC_n );
2619+ res = exchange_14b_apdu (aREAD_CC , aREAD_CC_n , activate_field , keep_field_on , response , sizeof (response ), & resplen , -1 );
26142620 if (res ) {
2615- goto out ;
2621+ switch_off_field_14b ();
2622+ return res ;
26162623 }
26172624
26182625 sw = get_sw (response , resplen );
26192626 if (sw != ISO7816_OK ) {
2620- PrintAndLogEx (ERR , "reading NDEF file failed (%04x - %s)." , sw , GetAPDUCodeDescription (sw >> 8 , sw & 0xff ));
2627+ PrintAndLogEx (ERR , "reading CC file failed (%04x - %s)." , sw , GetAPDUCodeDescription (sw >> 8 , sw & 0xff ));
26212628 res = PM3_ESOFT ;
2622- goto out ;
2629+ switch_off_field_14b ();
2630+ return res ;
26232631 }
26242632 // take offset from response
26252633 uint8_t offset = response [1 ];
2626-
2627- // --------------- Read binary w offset ----------------
2628- keep_field_on = false;
2634+
2635+ // Parse CC data
2636+ uint8_t cc_data [resplen - 2 ];
2637+ memcpy (cc_data , response , sizeof (cc_data ));
2638+ uint8_t file_id [2 ] = {cc_data [9 ], cc_data [10 ]};
2639+
2640+
2641+ uint16_t max_rapdu_size = (cc_data [3 ] << 8 | cc_data [4 ]) - 2 ;
2642+
2643+ max_rapdu_size = max_rapdu_size < sizeof (response ) - 2 ? max_rapdu_size : sizeof (response ) - 2 ;
2644+ // --------------- NDEF file reading ----------------
2645+ uint8_t aSELECT_FILE_NDEF [30 ];
2646+ int aSELECT_FILE_NDEF_n = 0 ;
2647+ param_gethex_to_eol ("00a4000c02" , 0 , aSELECT_FILE_NDEF , sizeof (aSELECT_FILE_NDEF ), & aSELECT_FILE_NDEF_n );
2648+ memcpy (aSELECT_FILE_NDEF + aSELECT_FILE_NDEF_n , file_id , sizeof (file_id ));
2649+ res = exchange_14b_apdu (aSELECT_FILE_NDEF , aSELECT_FILE_NDEF_n + sizeof (file_id ), activate_field , keep_field_on , response , sizeof (response ), & resplen , -1 );
2650+ if (res != PM3_SUCCESS ) {
2651+ switch_off_field_14b ();
2652+ return res ;
2653+ }
2654+ sw = get_sw (response , resplen );
2655+ if (sw != ISO7816_OK ) {
2656+ PrintAndLogEx (ERR , "Selecting NDEF file failed (%04x - %s)." , sw , GetAPDUCodeDescription (sw >> 8 , sw & 0xff ));
2657+ switch_off_field_14b ();
2658+ return PM3_ESOFT ;
2659+ }
2660+ // --------------- Read binary size ----------------
2661+ uint8_t aREAD_NDEF [30 ];
2662+ int aREAD_NDEF_n = 0 ;
26292663 aREAD_NDEF_n = 0 ;
2630- param_gethex_to_eol ("00b00002" , 0 , aREAD_NDEF , sizeof (aREAD_NDEF ), & aREAD_NDEF_n );
2631- aREAD_NDEF [4 ] = offset ;
2664+ param_gethex_to_eol ("00b0000002" , 0 , aREAD_NDEF , sizeof (aREAD_NDEF ), & aREAD_NDEF_n );
26322665 res = exchange_14b_apdu (aREAD_NDEF , aREAD_NDEF_n , activate_field , keep_field_on , response , sizeof (response ), & resplen , -1 );
26332666 if (res ) {
2634- goto out ;
2667+ switch_off_field_14b ();
2668+ return res ;
26352669 }
26362670
26372671 sw = get_sw (response , resplen );
26382672 if (sw != ISO7816_OK ) {
26392673 PrintAndLogEx (ERR , "reading NDEF file failed (%04x - %s)." , sw , GetAPDUCodeDescription (sw >> 8 , sw & 0xff ));
26402674 res = PM3_ESOFT ;
2641- goto out ;
2675+ switch_off_field_14b ();
2676+ return res ;
2677+ }
2678+
2679+ uint16_t ndef_size = (response [0 ] << 8 ) + response [1 ];
2680+ offset = 2 ;
2681+
2682+ uint8_t * ndef_file = calloc (ndef_size , sizeof (uint8_t ));
2683+ if (ndef_file == NULL ) {
2684+ PrintAndLogEx (WARNING , "Failed to allocate memory" );
2685+ switch_off_field_14b ();
2686+ return PM3_EMALLOC ;
2687+ }
2688+
2689+ if (ndef_size + offset > 0xFFFF ) {
2690+ PrintAndLogEx (ERR , "NDEF size abnormally large in CmdHF14BNdefRead(). Aborting...\n" );
2691+ free (ndef_file );
2692+ switch_off_field_14b ();
2693+ return PM3_EOVFLOW ;
2694+ }
2695+ for (size_t i = offset ; i < ndef_size + offset ; i += max_rapdu_size ) {
2696+ size_t segment_size = max_rapdu_size < ndef_size + offset - i ? max_rapdu_size : ndef_size + offset - i ;
2697+
2698+ keep_field_on = i < ndef_size + offset - max_rapdu_size ;
2699+ aREAD_NDEF_n = 0 ;
2700+ param_gethex_to_eol ("00b00000" , 0 , aREAD_NDEF , sizeof (aREAD_NDEF ), & aREAD_NDEF_n );
2701+ aREAD_NDEF [2 ] = i >> 8 ;
2702+ aREAD_NDEF [3 ] = i & 0xFF ;
2703+
2704+ // Segment_size is stuffed into a single-byte field below ... so error out if overflows
2705+ if (segment_size > 0xFFu ) {
2706+ PrintAndLogEx (ERR , "Segment size too large (0x%zx > 0xFF)" , segment_size );
2707+ switch_off_field_14b ();
2708+ free (ndef_file );
2709+ return PM3_EOVFLOW ;
2710+ }
2711+ aREAD_NDEF [4 ] = segment_size ;
2712+
2713+ res = exchange_14b_apdu (aREAD_NDEF , aREAD_NDEF_n + 1 , activate_field , keep_field_on , response , sizeof (response ), & resplen , -1 );
2714+ if (res != PM3_SUCCESS ) {
2715+ switch_off_field_14b ();
2716+ free (ndef_file );
2717+ return res ;
2718+ }
2719+
2720+ sw = get_sw (response , resplen );
2721+ if (sw != ISO7816_OK ) {
2722+ PrintAndLogEx (ERR , "reading NDEF file failed (%04x - %s)." , sw , GetAPDUCodeDescription (sw >> 8 , sw & 0xff ));
2723+ switch_off_field_14b ();
2724+ free (ndef_file );
2725+ return PM3_ESOFT ;
2726+ }
2727+
2728+ if (resplen != segment_size + 2 ) {
2729+ PrintAndLogEx (ERR , "reading NDEF file failed, expected %zu bytes, got %i bytes." , segment_size , resplen - 2 );
2730+ switch_off_field_14b ();
2731+ free (ndef_file );
2732+ return PM3_ESOFT ;
2733+ }
2734+
2735+ memcpy (ndef_file + (i - offset ), response , segment_size );
26422736 }
26432737
2738+ if (verbose == false) {
2739+ PrintAndLogEx (HINT , "Hint: Try " _YELLOW_ ("`hf 14b ndefread -v`" ) " for more details" ); // So far this prints absolutely nothing
2740+ }
2741+
2742+
26442743 // get total NDEF length before save. If fails, we save it all
26452744 size_t n = 0 ;
26462745 if (NDEFGetTotalLength (response + 2 , resplen - 4 , & n ) != PM3_SUCCESS )
26472746 n = resplen - 4 ;
26482747
26492748 pm3_save_dump (filename , response + 2 , n , jsfNDEF );
26502749
2651- res = NDEFRecordsDecodeAndPrint (response + 2 , resplen - 4 , verbose );
2652-
2653- out :
2750+ NDEFRecordsDecodeAndPrint (ndef_file , ndef_size , verbose );
2751+ free ( ndef_file );
2752+ PrintAndLogEx ( NORMAL , "" );
26542753 switch_off_field_14b ();
2655- return res ;
2754+ return PM3_SUCCESS ;
26562755}
26572756
26582757static int CmdHF14BView (const char * Cmd ) {
0 commit comments