|
1 | 1 |
|
2 | 2 | #include "sam_api.h"
|
3 | 3 | #include <toolbox/path.h>
|
| 4 | +#include <bit_lib/bit_lib.h> |
4 | 5 |
|
5 | 6 | #define TAG "SAMAPI"
|
6 | 7 |
|
@@ -728,6 +729,161 @@ void seader_iso14443a_transmit(
|
728 | 729 | bit_buffer_free(rx_buffer);
|
729 | 730 | }
|
730 | 731 |
|
| 732 | +/* Assumes this is called in the context of the NFC API callback */ |
| 733 | +#define MF_CLASSIC_FWT_FC (60000) |
| 734 | +void seader_mfc_transmit( |
| 735 | + Seader* seader, |
| 736 | + MfClassicPoller* mfc_poller, |
| 737 | + uint8_t* buffer, |
| 738 | + size_t len, |
| 739 | + uint16_t timeout, |
| 740 | + uint8_t format[3]) { |
| 741 | + UNUSED(timeout); |
| 742 | + |
| 743 | + furi_assert(seader); |
| 744 | + furi_assert(buffer); |
| 745 | + furi_assert(mfc_poller); |
| 746 | + SeaderWorker* seader_worker = seader->worker; |
| 747 | + SeaderUartBridge* seader_uart = seader_worker->uart; |
| 748 | + |
| 749 | + BitBuffer* tx_buffer = bit_buffer_alloc(len); |
| 750 | + BitBuffer* rx_buffer = bit_buffer_alloc(SEADER_POLLER_MAX_BUFFER_SIZE); |
| 751 | + |
| 752 | + do { |
| 753 | + if(format[0] == 0x00 && format[1] == 0xC0 && format[2] == 0x00) { |
| 754 | + bit_buffer_append_bytes(tx_buffer, buffer, len); |
| 755 | + MfClassicError error = |
| 756 | + mf_classic_poller_send_frame(mfc_poller, tx_buffer, rx_buffer, MF_CLASSIC_FWT_FC); |
| 757 | + if(error != MfClassicErrorNone) { |
| 758 | + FURI_LOG_W(TAG, "mf_classic_poller_send_frame error %d", error); |
| 759 | + seader_worker->stage = SeaderPollerEventTypeFail; |
| 760 | + break; |
| 761 | + } |
| 762 | + } else if( |
| 763 | + (format[0] == 0x00 && format[1] == 0x00 && format[2] == 0x40) || |
| 764 | + (format[0] == 0x00 && format[1] == 0x00 && format[2] == 0x24) || |
| 765 | + (format[0] == 0x00 && format[1] == 0x00 && format[2] == 0x44)) { |
| 766 | + memset(display, 0, sizeof(display)); |
| 767 | + for(uint8_t i = 0; i < len; i++) { |
| 768 | + snprintf(display + (i * 2), sizeof(display), "%02x", buffer[i]); |
| 769 | + } |
| 770 | + FURI_LOG_D(TAG, "NFC Send with parity %d: %s", len, display); |
| 771 | + |
| 772 | + // Only handles message up to 8 data bytes |
| 773 | + uint8_t tx_parity = 0; |
| 774 | + uint8_t len_without_parity = len - 1; |
| 775 | + |
| 776 | + // Don't forget to swap the bits of buffer[8] |
| 777 | + for(size_t i = 0; i < len; i++) { |
| 778 | + bit_lib_reverse_bits(buffer + i, 0, 8); |
| 779 | + } |
| 780 | + |
| 781 | + // Pull out parity bits |
| 782 | + for(size_t i = 0; i < len_without_parity; i++) { |
| 783 | + bool val = bit_lib_get_bit(buffer + i + 1, i); |
| 784 | + bit_lib_set_bit(&tx_parity, i, val); |
| 785 | + } |
| 786 | + |
| 787 | + for(size_t i = 0; i < len_without_parity; i++) { |
| 788 | + buffer[i] = (buffer[i] << i) | (buffer[i + 1] >> (8 - i)); |
| 789 | + } |
| 790 | + bit_buffer_append_bytes(tx_buffer, buffer, len_without_parity); |
| 791 | + |
| 792 | + for(size_t i = 0; i < len_without_parity; i++) { |
| 793 | + bit_lib_reverse_bits(buffer + i, 0, 8); |
| 794 | + bit_buffer_set_byte_with_parity( |
| 795 | + tx_buffer, i, buffer[i], bit_lib_get_bit(&tx_parity, i)); |
| 796 | + } |
| 797 | + |
| 798 | + memset(display, 0, sizeof(display)); |
| 799 | + for(uint8_t i = 0; i < bit_buffer_get_size_bytes(tx_buffer); i++) { |
| 800 | + snprintf( |
| 801 | + display + (i * 2), sizeof(display), "%02x", bit_buffer_get_byte(tx_buffer, i)); |
| 802 | + } |
| 803 | + FURI_LOG_D( |
| 804 | + TAG, |
| 805 | + "NFC Send without parity %d: %s [%02x]", |
| 806 | + bit_buffer_get_size_bytes(tx_buffer), |
| 807 | + display, |
| 808 | + tx_parity); |
| 809 | + |
| 810 | + MfClassicError error = mf_classic_poller_send_custom_parity_frame( |
| 811 | + mfc_poller, tx_buffer, rx_buffer, MF_CLASSIC_FWT_FC); |
| 812 | + if(error != MfClassicErrorNone) { |
| 813 | + FURI_LOG_W(TAG, "mf_classic_poller_send_encrypted_frame error %d", error); |
| 814 | + seader_worker->stage = SeaderPollerEventTypeFail; |
| 815 | + break; |
| 816 | + } |
| 817 | + |
| 818 | + size_t length = bit_buffer_get_size_bytes(rx_buffer); |
| 819 | + const uint8_t* rx_parity = bit_buffer_get_parity(rx_buffer); |
| 820 | + |
| 821 | + memset(display, 0, sizeof(display)); |
| 822 | + for(uint8_t i = 0; i < length; i++) { |
| 823 | + snprintf( |
| 824 | + display + (i * 2), sizeof(display), "%02x", bit_buffer_get_byte(rx_buffer, i)); |
| 825 | + } |
| 826 | + FURI_LOG_D( |
| 827 | + TAG, "NFC Response without parity %d: %s [%02x]", length, display, rx_parity[0]); |
| 828 | + |
| 829 | + uint8_t with_parity[SEADER_POLLER_MAX_BUFFER_SIZE]; |
| 830 | + memset(with_parity, 0, sizeof(with_parity)); |
| 831 | + |
| 832 | + for(size_t i = 0; i < length; i++) { |
| 833 | + uint8_t b = bit_buffer_get_byte(rx_buffer, i); |
| 834 | + bit_lib_reverse_bits(&b, 0, 8); |
| 835 | + bit_buffer_set_byte(rx_buffer, i, b); |
| 836 | + } |
| 837 | + |
| 838 | + length = length + (length / 8) + 1; |
| 839 | + |
| 840 | + uint8_t parts = 1 + length / 9; |
| 841 | + for(size_t p = 0; p < parts; p++) { |
| 842 | + uint8_t doffset = p * 9; |
| 843 | + uint8_t soffset = p * 8; |
| 844 | + |
| 845 | + for(size_t i = 0; i < 9; i++) { |
| 846 | + with_parity[i + doffset] = bit_buffer_get_byte(rx_buffer, i + soffset) >> i; |
| 847 | + if(i > 0) { |
| 848 | + with_parity[i + doffset] |= bit_buffer_get_byte(rx_buffer, i + soffset - 1) |
| 849 | + << (9 - i); |
| 850 | + } |
| 851 | + |
| 852 | + if(i > 0) { |
| 853 | + bool val = bit_lib_get_bit(rx_parity, i - 1); |
| 854 | + bit_lib_set_bit(with_parity + i, i - 1, val); |
| 855 | + } |
| 856 | + } |
| 857 | + } |
| 858 | + |
| 859 | + for(size_t i = 0; i < length; i++) { |
| 860 | + bit_lib_reverse_bits(with_parity + i, 0, 8); |
| 861 | + } |
| 862 | + |
| 863 | + bit_buffer_copy_bytes(rx_buffer, with_parity, length); |
| 864 | + |
| 865 | + memset(display, 0, sizeof(display)); |
| 866 | + for(uint8_t i = 0; i < length; i++) { |
| 867 | + snprintf( |
| 868 | + display + (i * 2), sizeof(display), "%02x", bit_buffer_get_byte(rx_buffer, i)); |
| 869 | + } |
| 870 | + FURI_LOG_D( |
| 871 | + TAG, "NFC Response with parity %d: %s [%02x]", length, display, rx_parity[0]); |
| 872 | + |
| 873 | + } else { |
| 874 | + FURI_LOG_W(TAG, "UNHANDLED FORMAT"); |
| 875 | + } |
| 876 | + |
| 877 | + seader_send_nfc_rx( |
| 878 | + seader_uart, |
| 879 | + (uint8_t*)bit_buffer_get_data(rx_buffer), |
| 880 | + bit_buffer_get_size_bytes(rx_buffer)); |
| 881 | + |
| 882 | + } while(false); |
| 883 | + bit_buffer_free(tx_buffer); |
| 884 | + bit_buffer_free(rx_buffer); |
| 885 | +} |
| 886 | + |
731 | 887 | void seader_parse_nfc_command_transmit(
|
732 | 888 | Seader* seader,
|
733 | 889 | NFCSend_t* nfcSend,
|
@@ -757,13 +913,23 @@ void seader_parse_nfc_command_transmit(
|
757 | 913 | seader_iso15693_transmit(
|
758 | 914 | seader, spc->picopass_poller, nfcSend->data.buf, nfcSend->data.size);
|
759 | 915 | } else if(frameProtocol == FrameProtocol_nfc) {
|
760 |
| - seader_iso14443a_transmit( |
761 |
| - seader, |
762 |
| - spc->iso14443_4a_poller, |
763 |
| - nfcSend->data.buf, |
764 |
| - nfcSend->data.size, |
765 |
| - (uint16_t)timeOut, |
766 |
| - nfcSend->format->buf); |
| 916 | + if(spc->iso14443_4a_poller) { |
| 917 | + seader_iso14443a_transmit( |
| 918 | + seader, |
| 919 | + spc->iso14443_4a_poller, |
| 920 | + nfcSend->data.buf, |
| 921 | + nfcSend->data.size, |
| 922 | + (uint16_t)timeOut, |
| 923 | + nfcSend->format->buf); |
| 924 | + } else if(spc->mfc_poller) { |
| 925 | + seader_mfc_transmit( |
| 926 | + seader, |
| 927 | + spc->mfc_poller, |
| 928 | + nfcSend->data.buf, |
| 929 | + nfcSend->data.size, |
| 930 | + (uint16_t)timeOut, |
| 931 | + nfcSend->format->buf); |
| 932 | + } |
767 | 933 | } else {
|
768 | 934 | FURI_LOG_W(TAG, "unknown frame protocol %lx", frameProtocol);
|
769 | 935 | }
|
@@ -911,18 +1077,22 @@ NfcCommand seader_worker_card_detect(
|
911 | 1077 | OCTET_STRING_t atqa_string = {.buf = atqa, .size = 2};
|
912 | 1078 | uint8_t protocol_bytes[] = {0x00, 0x00};
|
913 | 1079 |
|
914 |
| - if(sak == 0 && atqa == NULL) { |
| 1080 | + if(sak == 0 && atqa == NULL) { // picopass |
915 | 1081 | protocol_bytes[1] = FrameProtocol_iclass;
|
916 | 1082 | OCTET_STRING_fromBuf(
|
917 | 1083 | &cardDetails->protocol, (const char*)protocol_bytes, sizeof(protocol_bytes));
|
918 | 1084 | memcpy(credential->diversifier, uid, uid_len);
|
919 | 1085 | credential->diversifier_len = uid_len;
|
920 | 1086 | credential->isDesfire = false;
|
921 |
| - } else { |
| 1087 | + } else if(atqa == 0) { // MFC |
| 1088 | + protocol_bytes[1] = FrameProtocol_nfc; |
| 1089 | + OCTET_STRING_fromBuf( |
| 1090 | + &cardDetails->protocol, (const char*)protocol_bytes, sizeof(protocol_bytes)); |
| 1091 | + cardDetails->sak = &sak_string; |
| 1092 | + } else { // type 4 |
922 | 1093 | protocol_bytes[1] = FrameProtocol_nfc;
|
923 | 1094 | OCTET_STRING_fromBuf(
|
924 | 1095 | &cardDetails->protocol, (const char*)protocol_bytes, sizeof(protocol_bytes));
|
925 |
| - |
926 | 1096 | cardDetails->sak = &sak_string;
|
927 | 1097 | cardDetails->atqa = &atqa_string;
|
928 | 1098 | credential->isDesfire = seader_mf_df_check_card_type(atqa[0], atqa[1], sak);
|
|
0 commit comments