* nfc: refactor nfc_worker_read_mifare_desfire to use furi_hal_nfc_tx_rx Renames furi_hal_nfc_exchange_full to furi_hal_nfc_tx_rx_full, and rewrites it to use furi_hal_nfc_tx_rx. This eliminates the final remaining use of furi_hal_nfc_exchange, so remove that. * nfc: write debug.pcap when debug mode enabled Limited to NFC protocols that use furi_hal_nfc_tx_rx to communicate. * switch to Doxygen style comment Co-authored-by: Kevin Wallace <git+flipperzero@kevin.wallace.seattle.wa.us> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									d5df4027d7
								
							
						
					
					
						commit
						9c9f66a30f
					
				
							
								
								
									
										99
									
								
								applications/nfc/helpers/nfc_debug_pcap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								applications/nfc/helpers/nfc_debug_pcap.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | |||||||
|  | #include "nfc_debug_pcap.h" | ||||||
|  | 
 | ||||||
|  | #include <furi_hal_rtc.h> | ||||||
|  | 
 | ||||||
|  | #define TAG "NfcDebugPcap" | ||||||
|  | 
 | ||||||
|  | #define PCAP_MAGIC 0xa1b2c3d4 | ||||||
|  | #define PCAP_MAJOR 2 | ||||||
|  | #define PCAP_MINOR 4 | ||||||
|  | #define DLT_ISO_14443 264 | ||||||
|  | 
 | ||||||
|  | #define DATA_PICC_TO_PCD 0xFF | ||||||
|  | #define DATA_PCD_TO_PICC 0xFE | ||||||
|  | #define DATA_PICC_TO_PCD_CRC_DROPPED 0xFB | ||||||
|  | #define DATA_PCD_TO_PICC_CRC_DROPPED 0xFA | ||||||
|  | 
 | ||||||
|  | File* nfc_debug_pcap_open(Storage* storage) { | ||||||
|  |     File* file = storage_file_alloc(storage); | ||||||
|  |     if(!storage_file_open(file, "/ext/nfc/debug.pcap", FSAM_WRITE, FSOM_OPEN_APPEND)) { | ||||||
|  |         storage_file_free(file); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |     if(!storage_file_tell(file)) { | ||||||
|  |         struct { | ||||||
|  |             uint32_t magic; | ||||||
|  |             uint16_t major, minor; | ||||||
|  |             uint32_t reserved[2]; | ||||||
|  |             uint32_t snaplen; | ||||||
|  |             uint32_t link_type; | ||||||
|  |         } __attribute__((__packed__)) pcap_hdr = { | ||||||
|  |             .magic = PCAP_MAGIC, | ||||||
|  |             .major = PCAP_MAJOR, | ||||||
|  |             .minor = PCAP_MINOR, | ||||||
|  |             .snaplen = FURI_HAL_NFC_DATA_BUFF_SIZE, | ||||||
|  |             .link_type = DLT_ISO_14443, | ||||||
|  |         }; | ||||||
|  |         if(storage_file_write(file, &pcap_hdr, sizeof(pcap_hdr)) != sizeof(pcap_hdr)) { | ||||||
|  |             FURI_LOG_E(TAG, "Failed to write pcap header"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return file; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_debug_pcap_write(Storage* storage, uint8_t event, uint8_t* data, uint16_t len) { | ||||||
|  |     File* file = nfc_debug_pcap_open(storage); | ||||||
|  |     if(!file) return; | ||||||
|  | 
 | ||||||
|  |     FuriHalRtcDateTime datetime; | ||||||
|  |     furi_hal_rtc_get_datetime(&datetime); | ||||||
|  | 
 | ||||||
|  |     struct { | ||||||
|  |         // https://wiki.wireshark.org/Development/LibpcapFileFormat#record-packet-header
 | ||||||
|  |         uint32_t ts_sec; | ||||||
|  |         uint32_t ts_usec; | ||||||
|  |         uint32_t incl_len; | ||||||
|  |         uint32_t orig_len; | ||||||
|  |         // https://www.kaiser.cx/posts/pcap-iso14443/#_packet_data
 | ||||||
|  |         uint8_t version; | ||||||
|  |         uint8_t event; | ||||||
|  |         uint16_t len; | ||||||
|  |     } __attribute__((__packed__)) pkt_hdr = { | ||||||
|  |         .ts_sec = furi_hal_rtc_datetime_to_timestamp(&datetime), | ||||||
|  |         .ts_usec = 0, | ||||||
|  |         .incl_len = len + 4, | ||||||
|  |         .orig_len = len + 4, | ||||||
|  |         .version = 0, | ||||||
|  |         .event = event, | ||||||
|  |         .len = len << 8 | len >> 8, | ||||||
|  |     }; | ||||||
|  |     if(storage_file_write(file, &pkt_hdr, sizeof(pkt_hdr)) != sizeof(pkt_hdr)) { | ||||||
|  |         FURI_LOG_E(TAG, "Failed to write pcap packet header"); | ||||||
|  |     } else if(storage_file_write(file, data, len) != len) { | ||||||
|  |         FURI_LOG_E(TAG, "Failed to write pcap packet data"); | ||||||
|  |     } | ||||||
|  |     storage_file_free(file); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_debug_pcap_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { | ||||||
|  |     uint8_t event = crc_dropped ? DATA_PCD_TO_PICC_CRC_DROPPED : DATA_PCD_TO_PICC; | ||||||
|  |     nfc_debug_pcap_write(context, event, data, bits / 8); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_debug_pcap_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { | ||||||
|  |     uint8_t event = crc_dropped ? DATA_PICC_TO_PCD_CRC_DROPPED : DATA_PICC_TO_PCD; | ||||||
|  |     nfc_debug_pcap_write(context, event, data, bits / 8); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_debug_pcap_prepare_tx_rx(FuriHalNfcTxRxContext* tx_rx, Storage* storage, bool is_picc) { | ||||||
|  |     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { | ||||||
|  |         if(is_picc) { | ||||||
|  |             tx_rx->sniff_tx = nfc_debug_pcap_write_rx; | ||||||
|  |             tx_rx->sniff_rx = nfc_debug_pcap_write_tx; | ||||||
|  |         } else { | ||||||
|  |             tx_rx->sniff_tx = nfc_debug_pcap_write_tx; | ||||||
|  |             tx_rx->sniff_rx = nfc_debug_pcap_write_rx; | ||||||
|  |         } | ||||||
|  |         tx_rx->sniff_context = storage; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								applications/nfc/helpers/nfc_debug_pcap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								applications/nfc/helpers/nfc_debug_pcap.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <furi_hal_nfc.h> | ||||||
|  | #include <storage/storage.h> | ||||||
|  | 
 | ||||||
|  | /** Prepare tx/rx context for debug pcap logging, if enabled.
 | ||||||
|  |  * | ||||||
|  |  * @param      tx_rx   TX/RX context to log | ||||||
|  |  * @param      storage Storage to log to | ||||||
|  |  * @param      is_picc if true, record Flipper as PICC, else PCD. | ||||||
|  |  */ | ||||||
|  | void nfc_debug_pcap_prepare_tx_rx(FuriHalNfcTxRxContext* tx_rx, Storage* storage, bool is_picc); | ||||||
| @ -10,6 +10,7 @@ | |||||||
| #include <lib/nfc_protocols/nfca.h> | #include <lib/nfc_protocols/nfca.h> | ||||||
| 
 | 
 | ||||||
| #include "helpers/nfc_mf_classic_dict.h" | #include "helpers/nfc_mf_classic_dict.h" | ||||||
|  | #include "helpers/nfc_debug_pcap.h" | ||||||
| 
 | 
 | ||||||
| #define TAG "NfcWorker" | #define TAG "NfcWorker" | ||||||
| 
 | 
 | ||||||
| @ -153,6 +154,7 @@ void nfc_worker_detect(NfcWorker* nfc_worker) { | |||||||
| 
 | 
 | ||||||
| void nfc_worker_emulate(NfcWorker* nfc_worker) { | void nfc_worker_emulate(NfcWorker* nfc_worker) { | ||||||
|     FuriHalNfcTxRxContext tx_rx = {}; |     FuriHalNfcTxRxContext tx_rx = {}; | ||||||
|  |     nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, true); | ||||||
|     FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data; |     FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data; | ||||||
|     NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data; |     NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data; | ||||||
| 
 | 
 | ||||||
| @ -175,6 +177,7 @@ void nfc_worker_emulate(NfcWorker* nfc_worker) { | |||||||
| 
 | 
 | ||||||
| void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { | void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { | ||||||
|     FuriHalNfcTxRxContext tx_rx = {}; |     FuriHalNfcTxRxContext tx_rx = {}; | ||||||
|  |     nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); | ||||||
|     EmvApplication emv_app = {}; |     EmvApplication emv_app = {}; | ||||||
|     NfcDeviceData* result = nfc_worker->dev_data; |     NfcDeviceData* result = nfc_worker->dev_data; | ||||||
|     FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; |     FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; | ||||||
| @ -206,6 +209,7 @@ void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { | |||||||
| 
 | 
 | ||||||
| void nfc_worker_read_emv(NfcWorker* nfc_worker) { | void nfc_worker_read_emv(NfcWorker* nfc_worker) { | ||||||
|     FuriHalNfcTxRxContext tx_rx = {}; |     FuriHalNfcTxRxContext tx_rx = {}; | ||||||
|  |     nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); | ||||||
|     EmvApplication emv_app = {}; |     EmvApplication emv_app = {}; | ||||||
|     NfcDeviceData* result = nfc_worker->dev_data; |     NfcDeviceData* result = nfc_worker->dev_data; | ||||||
|     FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; |     FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; | ||||||
| @ -254,6 +258,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) { | |||||||
| 
 | 
 | ||||||
| void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { | void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { | ||||||
|     FuriHalNfcTxRxContext tx_rx = {}; |     FuriHalNfcTxRxContext tx_rx = {}; | ||||||
|  |     nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, true); | ||||||
|     FuriHalNfcDevData params = { |     FuriHalNfcDevData params = { | ||||||
|         .uid = {0xCF, 0x72, 0xd4, 0x40}, |         .uid = {0xCF, 0x72, 0xd4, 0x40}, | ||||||
|         .uid_len = 4, |         .uid_len = 4, | ||||||
| @ -278,6 +283,7 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { | |||||||
| 
 | 
 | ||||||
| void nfc_worker_read_mifare_ultralight(NfcWorker* nfc_worker) { | void nfc_worker_read_mifare_ultralight(NfcWorker* nfc_worker) { | ||||||
|     FuriHalNfcTxRxContext tx_rx = {}; |     FuriHalNfcTxRxContext tx_rx = {}; | ||||||
|  |     nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); | ||||||
|     MfUltralightReader reader = {}; |     MfUltralightReader reader = {}; | ||||||
|     MfUltralightData data = {}; |     MfUltralightData data = {}; | ||||||
|     NfcDeviceData* result = nfc_worker->dev_data; |     NfcDeviceData* result = nfc_worker->dev_data; | ||||||
| @ -342,6 +348,7 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) { | |||||||
| void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { | void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { | ||||||
|     furi_assert(nfc_worker->callback); |     furi_assert(nfc_worker->callback); | ||||||
|     FuriHalNfcTxRxContext tx_rx_ctx = {}; |     FuriHalNfcTxRxContext tx_rx_ctx = {}; | ||||||
|  |     nfc_debug_pcap_prepare_tx_rx(&tx_rx_ctx, nfc_worker->storage, false); | ||||||
|     MfClassicAuthContext auth_ctx = {}; |     MfClassicAuthContext auth_ctx = {}; | ||||||
|     MfClassicReader reader = {}; |     MfClassicReader reader = {}; | ||||||
|     uint64_t curr_key = 0; |     uint64_t curr_key = 0; | ||||||
| @ -483,7 +490,8 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker) { | void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker) { | ||||||
|     FuriHalNfcTxRxContext tx_rx; |     FuriHalNfcTxRxContext tx_rx = {}; | ||||||
|  |     nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, true); | ||||||
|     FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; |     FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; | ||||||
|     MfClassicEmulator emulator = { |     MfClassicEmulator emulator = { | ||||||
|         .cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4), |         .cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4), | ||||||
| @ -511,11 +519,8 @@ void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { | void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { | ||||||
|     ReturnCode err; |     FuriHalNfcTxRxContext tx_rx = {}; | ||||||
|     uint8_t tx_buff[64] = {}; |     nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); | ||||||
|     uint16_t tx_len = 0; |  | ||||||
|     uint8_t rx_buff[512] = {}; |  | ||||||
|     uint16_t rx_len; |  | ||||||
|     NfcDeviceData* result = nfc_worker->dev_data; |     NfcDeviceData* result = nfc_worker->dev_data; | ||||||
|     nfc_device_data_clear(result); |     nfc_device_data_clear(result); | ||||||
|     MifareDesfireData* data = &result->mf_df_data; |     MifareDesfireData* data = &result->mf_df_data; | ||||||
| @ -540,37 +545,36 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { | |||||||
|         result->protocol = NfcDeviceProtocolMifareDesfire; |         result->protocol = NfcDeviceProtocolMifareDesfire; | ||||||
| 
 | 
 | ||||||
|         // Get DESFire version
 |         // Get DESFire version
 | ||||||
|         tx_len = mf_df_prepare_get_version(tx_buff); |         tx_rx.tx_bits = 8 * mf_df_prepare_get_version(tx_rx.tx_data); | ||||||
|         err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |         if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { | ||||||
|         if(err != ERR_NONE) { |             FURI_LOG_W(TAG, "Bad exchange getting version"); | ||||||
|             FURI_LOG_W(TAG, "Bad exchange getting version, err: %d", err); |  | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|         if(!mf_df_parse_get_version_response(rx_buff, rx_len, &data->version)) { |         if(!mf_df_parse_get_version_response(tx_rx.rx_data, tx_rx.rx_bits / 8, &data->version)) { | ||||||
|             FURI_LOG_W(TAG, "Bad DESFire GET_VERSION response"); |             FURI_LOG_W(TAG, "Bad DESFire GET_VERSION response"); | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         tx_len = mf_df_prepare_get_free_memory(tx_buff); |         tx_rx.tx_bits = 8 * mf_df_prepare_get_free_memory(tx_rx.tx_data); | ||||||
|         err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |         if(furi_hal_nfc_tx_rx_full(&tx_rx)) { | ||||||
|         if(err == ERR_NONE) { |  | ||||||
|             data->free_memory = malloc(sizeof(MifareDesfireFreeMemory)); |             data->free_memory = malloc(sizeof(MifareDesfireFreeMemory)); | ||||||
|             memset(data->free_memory, 0, sizeof(MifareDesfireFreeMemory)); |             memset(data->free_memory, 0, sizeof(MifareDesfireFreeMemory)); | ||||||
|             if(!mf_df_parse_get_free_memory_response(rx_buff, rx_len, data->free_memory)) { |             if(!mf_df_parse_get_free_memory_response( | ||||||
|  |                    tx_rx.rx_data, tx_rx.rx_bits / 8, data->free_memory)) { | ||||||
|                 FURI_LOG_D(TAG, "Bad DESFire GET_FREE_MEMORY response (normal for pre-EV1 cards)"); |                 FURI_LOG_D(TAG, "Bad DESFire GET_FREE_MEMORY response (normal for pre-EV1 cards)"); | ||||||
|                 free(data->free_memory); |                 free(data->free_memory); | ||||||
|                 data->free_memory = NULL; |                 data->free_memory = NULL; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         tx_len = mf_df_prepare_get_key_settings(tx_buff); |         tx_rx.tx_bits = 8 * mf_df_prepare_get_key_settings(tx_rx.tx_data); | ||||||
|         err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |         if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { | ||||||
|         if(err != ERR_NONE) { |             FURI_LOG_D(TAG, "Bad exchange getting key settings"); | ||||||
|             FURI_LOG_D(TAG, "Bad exchange getting key settings, err: %d", err); |  | ||||||
|         } else { |         } else { | ||||||
|             data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings)); |             data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings)); | ||||||
|             memset(data->master_key_settings, 0, sizeof(MifareDesfireKeySettings)); |             memset(data->master_key_settings, 0, sizeof(MifareDesfireKeySettings)); | ||||||
|             if(!mf_df_parse_get_key_settings_response(rx_buff, rx_len, data->master_key_settings)) { |             if(!mf_df_parse_get_key_settings_response( | ||||||
|  |                    tx_rx.rx_data, tx_rx.rx_bits / 8, data->master_key_settings)) { | ||||||
|                 FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response"); |                 FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response"); | ||||||
|                 free(data->master_key_settings); |                 free(data->master_key_settings); | ||||||
|                 data->master_key_settings = NULL; |                 data->master_key_settings = NULL; | ||||||
| @ -580,17 +584,16 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { | |||||||
|             MifareDesfireKeyVersion** key_version_head = |             MifareDesfireKeyVersion** key_version_head = | ||||||
|                 &data->master_key_settings->key_version_head; |                 &data->master_key_settings->key_version_head; | ||||||
|             for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) { |             for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) { | ||||||
|                 tx_len = mf_df_prepare_get_key_version(tx_buff, key_id); |                 tx_rx.tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx.tx_data, key_id); | ||||||
|                 err = |                 if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { | ||||||
|                     furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |                     FURI_LOG_W(TAG, "Bad exchange getting key version"); | ||||||
|                 if(err != ERR_NONE) { |  | ||||||
|                     FURI_LOG_W(TAG, "Bad exchange getting key version, err: %d", err); |  | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|                 MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion)); |                 MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion)); | ||||||
|                 memset(key_version, 0, sizeof(MifareDesfireKeyVersion)); |                 memset(key_version, 0, sizeof(MifareDesfireKeyVersion)); | ||||||
|                 key_version->id = key_id; |                 key_version->id = key_id; | ||||||
|                 if(!mf_df_parse_get_key_version_response(rx_buff, rx_len, key_version)) { |                 if(!mf_df_parse_get_key_version_response( | ||||||
|  |                        tx_rx.rx_data, tx_rx.rx_bits / 8, key_version)) { | ||||||
|                     FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response"); |                     FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response"); | ||||||
|                     free(key_version); |                     free(key_version); | ||||||
|                     continue; |                     continue; | ||||||
| @ -600,31 +603,31 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         tx_len = mf_df_prepare_get_application_ids(tx_buff); |         tx_rx.tx_bits = 8 * mf_df_prepare_get_application_ids(tx_rx.tx_data); | ||||||
|         err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |         if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { | ||||||
|         if(err != ERR_NONE) { |             FURI_LOG_W(TAG, "Bad exchange getting application IDs"); | ||||||
|             FURI_LOG_W(TAG, "Bad exchange getting application IDs, err: %d", err); |  | ||||||
|         } else { |         } else { | ||||||
|             if(!mf_df_parse_get_application_ids_response(rx_buff, rx_len, &data->app_head)) { |             if(!mf_df_parse_get_application_ids_response( | ||||||
|  |                    tx_rx.rx_data, tx_rx.rx_bits / 8, &data->app_head)) { | ||||||
|                 FURI_LOG_W(TAG, "Bad DESFire GET_APPLICATION_IDS response"); |                 FURI_LOG_W(TAG, "Bad DESFire GET_APPLICATION_IDS response"); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { |         for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { | ||||||
|             tx_len = mf_df_prepare_select_application(tx_buff, app->id); |             tx_rx.tx_bits = 8 * mf_df_prepare_select_application(tx_rx.tx_data, app->id); | ||||||
|             err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |             if(!furi_hal_nfc_tx_rx_full(&tx_rx) || | ||||||
|             if(!mf_df_parse_select_application_response(rx_buff, rx_len)) { |                !mf_df_parse_select_application_response(tx_rx.rx_data, tx_rx.rx_bits / 8)) { | ||||||
|                 FURI_LOG_W(TAG, "Bad exchange selecting application, err: %d", err); |                 FURI_LOG_W(TAG, "Bad exchange selecting application"); | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             tx_len = mf_df_prepare_get_key_settings(tx_buff); |             tx_rx.tx_bits = 8 * mf_df_prepare_get_key_settings(tx_rx.tx_data); | ||||||
|             err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |             if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { | ||||||
|             if(err != ERR_NONE) { |                 FURI_LOG_W(TAG, "Bad exchange getting key settings"); | ||||||
|                 FURI_LOG_W(TAG, "Bad exchange getting key settings, err: %d", err); |  | ||||||
|             } else { |             } else { | ||||||
|                 app->key_settings = malloc(sizeof(MifareDesfireKeySettings)); |                 app->key_settings = malloc(sizeof(MifareDesfireKeySettings)); | ||||||
|                 memset(app->key_settings, 0, sizeof(MifareDesfireKeySettings)); |                 memset(app->key_settings, 0, sizeof(MifareDesfireKeySettings)); | ||||||
|                 if(!mf_df_parse_get_key_settings_response(rx_buff, rx_len, app->key_settings)) { |                 if(!mf_df_parse_get_key_settings_response( | ||||||
|  |                        tx_rx.rx_data, tx_rx.rx_bits / 8, app->key_settings)) { | ||||||
|                     FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response"); |                     FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response"); | ||||||
|                     free(app->key_settings); |                     free(app->key_settings); | ||||||
|                     app->key_settings = NULL; |                     app->key_settings = NULL; | ||||||
| @ -633,17 +636,16 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { | |||||||
| 
 | 
 | ||||||
|                 MifareDesfireKeyVersion** key_version_head = &app->key_settings->key_version_head; |                 MifareDesfireKeyVersion** key_version_head = &app->key_settings->key_version_head; | ||||||
|                 for(uint8_t key_id = 0; key_id < app->key_settings->max_keys; key_id++) { |                 for(uint8_t key_id = 0; key_id < app->key_settings->max_keys; key_id++) { | ||||||
|                     tx_len = mf_df_prepare_get_key_version(tx_buff, key_id); |                     tx_rx.tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx.tx_data, key_id); | ||||||
|                     err = furi_hal_nfc_exchange_full( |                     if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { | ||||||
|                         tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |                         FURI_LOG_W(TAG, "Bad exchange getting key version"); | ||||||
|                     if(err != ERR_NONE) { |  | ||||||
|                         FURI_LOG_W(TAG, "Bad exchange getting key version, err: %d", err); |  | ||||||
|                         continue; |                         continue; | ||||||
|                     } |                     } | ||||||
|                     MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion)); |                     MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion)); | ||||||
|                     memset(key_version, 0, sizeof(MifareDesfireKeyVersion)); |                     memset(key_version, 0, sizeof(MifareDesfireKeyVersion)); | ||||||
|                     key_version->id = key_id; |                     key_version->id = key_id; | ||||||
|                     if(!mf_df_parse_get_key_version_response(rx_buff, rx_len, key_version)) { |                     if(!mf_df_parse_get_key_version_response( | ||||||
|  |                            tx_rx.rx_data, tx_rx.rx_bits / 8, key_version)) { | ||||||
|                         FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response"); |                         FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response"); | ||||||
|                         free(key_version); |                         free(key_version); | ||||||
|                         continue; |                         continue; | ||||||
| @ -653,48 +655,45 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             tx_len = mf_df_prepare_get_file_ids(tx_buff); |             tx_rx.tx_bits = 8 * mf_df_prepare_get_file_ids(tx_rx.tx_data); | ||||||
|             err = furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |             if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { | ||||||
|             if(err != ERR_NONE) { |                 FURI_LOG_W(TAG, "Bad exchange getting file IDs"); | ||||||
|                 FURI_LOG_W(TAG, "Bad exchange getting file IDs, err: %d", err); |  | ||||||
|             } else { |             } else { | ||||||
|                 if(!mf_df_parse_get_file_ids_response(rx_buff, rx_len, &app->file_head)) { |                 if(!mf_df_parse_get_file_ids_response( | ||||||
|  |                        tx_rx.rx_data, tx_rx.rx_bits / 8, &app->file_head)) { | ||||||
|                     FURI_LOG_W(TAG, "Bad DESFire GET_FILE_IDS response"); |                     FURI_LOG_W(TAG, "Bad DESFire GET_FILE_IDS response"); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             for(MifareDesfireFile* file = app->file_head; file; file = file->next) { |             for(MifareDesfireFile* file = app->file_head; file; file = file->next) { | ||||||
|                 tx_len = mf_df_prepare_get_file_settings(tx_buff, file->id); |                 tx_rx.tx_bits = 8 * mf_df_prepare_get_file_settings(tx_rx.tx_data, file->id); | ||||||
|                 err = |                 if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { | ||||||
|                     furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |                     FURI_LOG_W(TAG, "Bad exchange getting file settings"); | ||||||
|                 if(err != ERR_NONE) { |  | ||||||
|                     FURI_LOG_W(TAG, "Bad exchange getting file settings, err: %d", err); |  | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|                 if(!mf_df_parse_get_file_settings_response(rx_buff, rx_len, file)) { |                 if(!mf_df_parse_get_file_settings_response( | ||||||
|  |                        tx_rx.rx_data, tx_rx.rx_bits / 8, file)) { | ||||||
|                     FURI_LOG_W(TAG, "Bad DESFire GET_FILE_SETTINGS response"); |                     FURI_LOG_W(TAG, "Bad DESFire GET_FILE_SETTINGS response"); | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|                 switch(file->type) { |                 switch(file->type) { | ||||||
|                 case MifareDesfireFileTypeStandard: |                 case MifareDesfireFileTypeStandard: | ||||||
|                 case MifareDesfireFileTypeBackup: |                 case MifareDesfireFileTypeBackup: | ||||||
|                     tx_len = mf_df_prepare_read_data(tx_buff, file->id, 0, 0); |                     tx_rx.tx_bits = 8 * mf_df_prepare_read_data(tx_rx.tx_data, file->id, 0, 0); | ||||||
|                     break; |                     break; | ||||||
|                 case MifareDesfireFileTypeValue: |                 case MifareDesfireFileTypeValue: | ||||||
|                     tx_len = mf_df_prepare_get_value(tx_buff, file->id); |                     tx_rx.tx_bits = 8 * mf_df_prepare_get_value(tx_rx.tx_data, file->id); | ||||||
|                     break; |                     break; | ||||||
|                 case MifareDesfireFileTypeLinearRecord: |                 case MifareDesfireFileTypeLinearRecord: | ||||||
|                 case MifareDesfireFileTypeCyclicRecord: |                 case MifareDesfireFileTypeCyclicRecord: | ||||||
|                     tx_len = mf_df_prepare_read_records(tx_buff, file->id, 0, 0); |                     tx_rx.tx_bits = 8 * mf_df_prepare_read_records(tx_rx.tx_data, file->id, 0, 0); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 err = |                 if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { | ||||||
|                     furi_hal_nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len); |                     FURI_LOG_W(TAG, "Bad exchange reading file %d", file->id); | ||||||
|                 if(err != ERR_NONE) { |  | ||||||
|                     FURI_LOG_W(TAG, "Bad exchange reading file %d, err: %d", file->id, err); |  | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|                 if(!mf_df_parse_read_data_response(rx_buff, rx_len, file)) { |                 if(!mf_df_parse_read_data_response(tx_rx.rx_data, tx_rx.rx_bits / 8, file)) { | ||||||
|                     FURI_LOG_W(TAG, "Bad response reading file %d", file->id); |                     FURI_LOG_W(TAG, "Bad response reading file %d", file->id); | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|  | |||||||
| @ -366,44 +366,6 @@ bool furi_hal_nfc_emulate_nfca( | |||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ReturnCode furi_hal_nfc_data_exchange( |  | ||||||
|     uint8_t* tx_buff, |  | ||||||
|     uint16_t tx_len, |  | ||||||
|     uint8_t** rx_buff, |  | ||||||
|     uint16_t** rx_len, |  | ||||||
|     bool deactivate) { |  | ||||||
|     furi_assert(rx_buff); |  | ||||||
|     furi_assert(rx_len); |  | ||||||
| 
 |  | ||||||
|     ReturnCode ret; |  | ||||||
|     rfalNfcState state = RFAL_NFC_STATE_ACTIVATED; |  | ||||||
|     ret = rfalNfcDataExchangeStart(tx_buff, tx_len, rx_buff, rx_len, 0, RFAL_TXRX_FLAGS_DEFAULT); |  | ||||||
|     if(ret != ERR_NONE) { |  | ||||||
|         return ret; |  | ||||||
|     } |  | ||||||
|     uint32_t start = DWT->CYCCNT; |  | ||||||
|     while(state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) { |  | ||||||
|         rfalNfcWorker(); |  | ||||||
|         state = rfalNfcGetState(); |  | ||||||
|         ret = rfalNfcDataExchangeGetStatus(); |  | ||||||
|         if(ret == ERR_BUSY) { |  | ||||||
|             if(DWT->CYCCNT - start > 1000 * clocks_in_ms) { |  | ||||||
|                 ret = ERR_TIMEOUT; |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|             continue; |  | ||||||
|         } else { |  | ||||||
|             start = DWT->CYCCNT; |  | ||||||
|         } |  | ||||||
|         taskYIELD(); |  | ||||||
|     } |  | ||||||
|     if(deactivate) { |  | ||||||
|         rfalNfcDeactivate(false); |  | ||||||
|         rfalLowPowerModeStart(); |  | ||||||
|     } |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { | static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { | ||||||
|     furi_assert(tx_rx->nfca_signal); |     furi_assert(tx_rx->nfca_signal); | ||||||
| 
 | 
 | ||||||
| @ -576,6 +538,12 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { | |||||||
|         FURI_LOG_E(TAG, "Failed to start data exchange"); |         FURI_LOG_E(TAG, "Failed to start data exchange"); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     if(tx_rx->sniff_tx) { | ||||||
|  |         bool crc_dropped = !(flags & RFAL_TXRX_FLAGS_CRC_TX_MANUAL); | ||||||
|  |         tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, crc_dropped, tx_rx->sniff_context); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     uint32_t start = DWT->CYCCNT; |     uint32_t start = DWT->CYCCNT; | ||||||
|     while(state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) { |     while(state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) { | ||||||
|         rfalNfcWorker(); |         rfalNfcWorker(); | ||||||
| @ -602,42 +570,42 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { | |||||||
|         tx_rx->rx_bits = *temp_rx_bits; |         tx_rx->rx_bits = *temp_rx_bits; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if(tx_rx->sniff_rx) { | ||||||
|  |         bool crc_dropped = !(flags & RFAL_TXRX_FLAGS_CRC_RX_KEEP); | ||||||
|  |         tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, crc_dropped, tx_rx->sniff_context); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ReturnCode furi_hal_nfc_exchange_full( | bool furi_hal_nfc_tx_rx_full(FuriHalNfcTxRxContext* tx_rx) { | ||||||
|     uint8_t* tx_buff, |  | ||||||
|     uint16_t tx_len, |  | ||||||
|     uint8_t* rx_buff, |  | ||||||
|     uint16_t rx_cap, |  | ||||||
|     uint16_t* rx_len) { |  | ||||||
|     ReturnCode err; |  | ||||||
|     uint8_t* part_buff; |  | ||||||
|     uint16_t* part_len_bits; |  | ||||||
|     uint16_t part_len_bytes; |     uint16_t part_len_bytes; | ||||||
| 
 | 
 | ||||||
|     err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &part_buff, &part_len_bits, false); |     if(!furi_hal_nfc_tx_rx(tx_rx, 1000)) { | ||||||
|     part_len_bytes = *part_len_bits / 8; |         return false; | ||||||
|     if(part_len_bytes > rx_cap) { |  | ||||||
|         return ERR_OVERRUN; |  | ||||||
|     } |     } | ||||||
|     memcpy(rx_buff, part_buff, part_len_bytes); |     while(tx_rx->rx_bits && tx_rx->rx_data[0] == 0xAF) { | ||||||
|     *rx_len = part_len_bytes; |         FuriHalNfcTxRxContext tmp = *tx_rx; | ||||||
|     while(err == ERR_NONE && rx_buff[0] == 0xAF) { |         tmp.tx_data[0] = 0xAF; | ||||||
|         err = furi_hal_nfc_data_exchange(rx_buff, 1, &part_buff, &part_len_bits, false); |         tmp.tx_bits = 8; | ||||||
|         part_len_bytes = *part_len_bits / 8; |         if(!furi_hal_nfc_tx_rx(&tmp, 1000)) { | ||||||
|         if(part_len_bytes > rx_cap - *rx_len) { |             return false; | ||||||
|             return ERR_OVERRUN; |         } | ||||||
|  |         part_len_bytes = tmp.rx_bits / 8; | ||||||
|  |         if(part_len_bytes > FURI_HAL_NFC_DATA_BUFF_SIZE - tx_rx->rx_bits / 8) { | ||||||
|  |             FURI_LOG_W(TAG, "Overrun rx buf"); | ||||||
|  |             return false; | ||||||
|         } |         } | ||||||
|         if(part_len_bytes == 0) { |         if(part_len_bytes == 0) { | ||||||
|             return ERR_PROTO; |             FURI_LOG_W(TAG, "Empty 0xAF response"); | ||||||
|  |             return false; | ||||||
|         } |         } | ||||||
|         memcpy(rx_buff + *rx_len, part_buff + 1, part_len_bytes - 1); |         memcpy(tx_rx->rx_data + tx_rx->rx_bits / 8, tmp.rx_data + 1, part_len_bytes - 1); | ||||||
|         *rx_buff = *part_buff; |         tx_rx->rx_data[0] = tmp.rx_data[0]; | ||||||
|         *rx_len += part_len_bytes - 1; |         tx_rx->rx_bits += 8 * (part_len_bytes - 1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return err; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_nfc_sleep() { | void furi_hal_nfc_sleep() { | ||||||
|  | |||||||
							
								
								
									
										41
									
								
								firmware/targets/furi_hal_include/furi_hal_nfc.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										41
									
								
								firmware/targets/furi_hal_include/furi_hal_nfc.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -17,7 +17,7 @@ extern "C" { | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #define FURI_HAL_NFC_UID_MAX_LEN 10 | #define FURI_HAL_NFC_UID_MAX_LEN 10 | ||||||
| #define FURI_HAL_NFC_DATA_BUFF_SIZE (256) | #define FURI_HAL_NFC_DATA_BUFF_SIZE (512) | ||||||
| #define FURI_HAL_NFC_PARITY_BUFF_SIZE (FURI_HAL_NFC_DATA_BUFF_SIZE / 8) | #define FURI_HAL_NFC_PARITY_BUFF_SIZE (FURI_HAL_NFC_DATA_BUFF_SIZE / 8) | ||||||
| 
 | 
 | ||||||
| #define FURI_HAL_NFC_TXRX_DEFAULT                                                    \ | #define FURI_HAL_NFC_TXRX_DEFAULT                                                    \ | ||||||
| @ -80,6 +80,9 @@ typedef struct { | |||||||
|     uint8_t sak; |     uint8_t sak; | ||||||
| } FuriHalNfcDevData; | } FuriHalNfcDevData; | ||||||
| 
 | 
 | ||||||
|  | typedef void ( | ||||||
|  |     *FuriHalNfcTxRxSniffCallback)(uint8_t* data, uint16_t bits, bool crc_dropped, void* context); | ||||||
|  | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     uint8_t tx_data[FURI_HAL_NFC_DATA_BUFF_SIZE]; |     uint8_t tx_data[FURI_HAL_NFC_DATA_BUFF_SIZE]; | ||||||
|     uint8_t tx_parity[FURI_HAL_NFC_PARITY_BUFF_SIZE]; |     uint8_t tx_parity[FURI_HAL_NFC_PARITY_BUFF_SIZE]; | ||||||
| @ -89,6 +92,10 @@ typedef struct { | |||||||
|     uint16_t rx_bits; |     uint16_t rx_bits; | ||||||
|     FuriHalNfcTxRxType tx_rx_type; |     FuriHalNfcTxRxType tx_rx_type; | ||||||
|     NfcaSignal* nfca_signal; |     NfcaSignal* nfca_signal; | ||||||
|  | 
 | ||||||
|  |     FuriHalNfcTxRxSniffCallback sniff_tx; | ||||||
|  |     FuriHalNfcTxRxSniffCallback sniff_rx; | ||||||
|  |     void* sniff_context; | ||||||
| } FuriHalNfcTxRxContext; | } FuriHalNfcTxRxContext; | ||||||
| 
 | 
 | ||||||
| /** Init nfc
 | /** Init nfc
 | ||||||
| @ -165,23 +172,6 @@ bool furi_hal_nfc_emulate_nfca( | |||||||
|     void* context, |     void* context, | ||||||
|     uint32_t timeout); |     uint32_t timeout); | ||||||
| 
 | 
 | ||||||
| /** NFC data exchange
 |  | ||||||
|  * |  | ||||||
|  * @param      tx_buff     transmit buffer |  | ||||||
|  * @param      tx_len      transmit buffer length |  | ||||||
|  * @param      rx_buff     receive buffer |  | ||||||
|  * @param      rx_len      receive buffer length |  | ||||||
|  * @param      deactivate  deactivate flag |  | ||||||
|  * |  | ||||||
|  * @return     ST ReturnCode |  | ||||||
|  */ |  | ||||||
| ReturnCode furi_hal_nfc_data_exchange( |  | ||||||
|     uint8_t* tx_buff, |  | ||||||
|     uint16_t tx_len, |  | ||||||
|     uint8_t** rx_buff, |  | ||||||
|     uint16_t** rx_len, |  | ||||||
|     bool deactivate); |  | ||||||
| 
 |  | ||||||
| /** NFC data exchange
 | /** NFC data exchange
 | ||||||
|  * |  * | ||||||
|  * @param       tx_rx_ctx   FuriHalNfcTxRxContext instance |  * @param       tx_rx_ctx   FuriHalNfcTxRxContext instance | ||||||
| @ -192,20 +182,11 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms); | |||||||
| 
 | 
 | ||||||
| /** NFC data full exhange
 | /** NFC data full exhange
 | ||||||
|  * |  * | ||||||
|  * @param      tx_buff     transmit buffer |  * @param       tx_rx_ctx   FuriHalNfcTxRxContext instance | ||||||
|  * @param      tx_len      transmit buffer length |  | ||||||
|  * @param      rx_buff     receive buffer |  | ||||||
|  * @param      rx_cap      receive buffer capacity |  | ||||||
|  * @param      rx_len      receive buffer length |  | ||||||
|  * |  * | ||||||
|  * @return     ST ReturnCode |  * @return      true on success | ||||||
|  */ |  */ | ||||||
| ReturnCode furi_hal_nfc_exchange_full( | bool furi_hal_nfc_tx_rx_full(FuriHalNfcTxRxContext* tx_rx); | ||||||
|     uint8_t* tx_buff, |  | ||||||
|     uint16_t tx_len, |  | ||||||
|     uint8_t* rx_buff, |  | ||||||
|     uint16_t rx_cap, |  | ||||||
|     uint16_t* rx_len); |  | ||||||
| 
 | 
 | ||||||
| /** NFC deactivate and start sleep
 | /** NFC deactivate and start sleep
 | ||||||
|  */ |  */ | ||||||
|  | |||||||
| @ -397,7 +397,8 @@ bool emv_read_bank_card(FuriHalNfcTxRxContext* tx_rx, EmvApplication* emv_app) { | |||||||
| bool emv_card_emulation(FuriHalNfcTxRxContext* tx_rx) { | bool emv_card_emulation(FuriHalNfcTxRxContext* tx_rx) { | ||||||
|     furi_assert(tx_rx); |     furi_assert(tx_rx); | ||||||
|     bool emulation_complete = false; |     bool emulation_complete = false; | ||||||
|     memset(tx_rx, 0, sizeof(FuriHalNfcTxRxContext)); |     tx_rx->tx_bits = 0; | ||||||
|  |     tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; | ||||||
| 
 | 
 | ||||||
|     do { |     do { | ||||||
|         FURI_LOG_D(TAG, "Read select PPSE command"); |         FURI_LOG_D(TAG, "Read select PPSE command"); | ||||||
|  | |||||||
| @ -270,7 +270,9 @@ static bool mf_classic_auth( | |||||||
|     MfClassicKey key_type, |     MfClassicKey key_type, | ||||||
|     Crypto1* crypto) { |     Crypto1* crypto) { | ||||||
|     bool auth_success = false; |     bool auth_success = false; | ||||||
|     memset(tx_rx, 0, sizeof(FuriHalNfcTxRxContext)); |     memset(tx_rx->tx_data, 0, sizeof(tx_rx->tx_data)); | ||||||
|  |     memset(tx_rx->tx_parity, 0, sizeof(tx_rx->tx_parity)); | ||||||
|  |     tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; | ||||||
| 
 | 
 | ||||||
|     do { |     do { | ||||||
|         if(key_type == MfClassicKeyA) { |         if(key_type == MfClassicKeyA) { | ||||||
| @ -372,7 +374,8 @@ bool mf_classic_read_block( | |||||||
|     bool read_block_success = false; |     bool read_block_success = false; | ||||||
|     uint8_t plain_cmd[4] = {MF_CLASSIC_READ_SECT_CMD, block_num, 0x00, 0x00}; |     uint8_t plain_cmd[4] = {MF_CLASSIC_READ_SECT_CMD, block_num, 0x00, 0x00}; | ||||||
|     nfca_append_crc16(plain_cmd, 2); |     nfca_append_crc16(plain_cmd, 2); | ||||||
|     memset(tx_rx, 0, sizeof(FuriHalNfcTxRxContext)); |     memset(tx_rx->tx_data, 0, sizeof(tx_rx->tx_data)); | ||||||
|  |     memset(tx_rx->tx_parity, 0, sizeof(tx_rx->tx_parity)); | ||||||
| 
 | 
 | ||||||
|     for(uint8_t i = 0; i < 4; i++) { |     for(uint8_t i = 0; i < 4; i++) { | ||||||
|         tx_rx->tx_data[i] = crypto1_byte(crypto, 0x00, 0) ^ plain_cmd[i]; |         tx_rx->tx_data[i] = crypto1_byte(crypto, 0x00, 0) ^ plain_cmd[i]; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Kevin Wallace
						Kevin Wallace