From 35018431590240ea5dc50772a06cc72c8d8f4f02 Mon Sep 17 00:00:00 2001 From: Jan-Christopher Pien <101@janchristopherpien.de> Date: Wed, 12 Oct 2016 00:17:16 +0200 Subject: [PATCH] Let ACardEmulator provide installed AIDs --- .../SmartcardProviderService.java | 54 ++++++++++++++----- .../emulators/EmulatorSingleton.java | 38 +++++++++++++ TCardEmulator/inc/sap_app.h | 1 + TCardEmulator/inc/tcardemulator.h | 3 +- TCardEmulator/src/sap.c | 47 ++++++++-------- TCardEmulator/src/tcardemulator.c | 20 ++++--- 6 files changed, 118 insertions(+), 45 deletions(-) diff --git a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SmartcardProviderService.java b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SmartcardProviderService.java index 0e6df62..64e4917 100644 --- a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SmartcardProviderService.java +++ b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SmartcardProviderService.java @@ -23,12 +23,6 @@ package com.vsmartcard.acardemulator; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import javax.security.cert.CertificateException; -import javax.security.cert.X509Certificate; -import java.util.Arrays; - import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; @@ -37,13 +31,25 @@ import android.content.pm.Signature; import android.os.Binder; import android.os.Handler; import android.os.IBinder; -import android.widget.Toast; +import android.text.TextUtils; import android.util.Log; +import android.widget.Toast; import com.samsung.android.sdk.SsdkUnsupportedException; -import com.samsung.android.sdk.accessory.*; +import com.samsung.android.sdk.accessory.SA; +import com.samsung.android.sdk.accessory.SAAgent; +import com.samsung.android.sdk.accessory.SAAuthenticationToken; +import com.samsung.android.sdk.accessory.SAPeerAgent; +import com.samsung.android.sdk.accessory.SASocket; import com.vsmartcard.acardemulator.emulators.EmulatorSingleton; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Arrays; + +import javax.security.cert.CertificateException; +import javax.security.cert.X509Certificate; + public class SmartcardProviderService extends SAAgent { private static final String TAG = "ACardEmulator"; private static final int ACCESSORY_CHANNEL_ID = 104; @@ -199,14 +205,34 @@ public class SmartcardProviderService extends SAAgent { if (mConnectionHandler == null) { return; } - final byte[] response = EmulatorSingleton.process(getApplicationContext(), data); + final byte[] sendResponse; + if (data[0] == 'd') { + // APDU is sent + byte[] newData = new byte[data.length - 1]; + System.arraycopy(data, 1, newData, 0, data.length - 1); + byte[] response = EmulatorSingleton.process(getApplicationContext(), newData); + sendResponse = new byte[response.length + 1]; + sendResponse[0] = 'd'; + System.arraycopy(response, 0, sendResponse, 1, response.length); + } else if (data[0] == 'a') { + // request for aids + String[] aidList = EmulatorSingleton.getRegisteredAids(getApplicationContext()); + String aidListJoined = TextUtils.join(",", aidList); + sendResponse = new byte[aidListJoined.length() + 1]; + sendResponse[0] = 'a'; + byte[] aids = aidListJoined.getBytes(); + System.arraycopy(aids, 0, sendResponse, 1, aids.length); + } else { + Log.e(TAG, "unknown message from consumer: " + new String(data)); + return; + } new Thread(new Runnable() { public void run() { - try { - mConnectionHandler.secureSend(ACCESSORY_CHANNEL_ID, response); - } catch (IOException e) { - e.printStackTrace(); - } + try { + mConnectionHandler.secureSend(ACCESSORY_CHANNEL_ID, sendResponse); + } catch (IOException e) { + e.printStackTrace(); + } } }).start(); } diff --git a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/EmulatorSingleton.java b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/EmulatorSingleton.java index b8b725f..d0fcdbd 100644 --- a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/EmulatorSingleton.java +++ b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/EmulatorSingleton.java @@ -22,13 +22,25 @@ package com.vsmartcard.acardemulator.emulators; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.nfc.NfcAdapter; +import android.nfc.cardemulation.CardEmulation; import android.preference.PreferenceManager; +import android.support.annotation.XmlRes; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import com.vsmartcard.acardemulator.R; import com.vsmartcard.acardemulator.Util; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + public class EmulatorSingleton { public static final String TAG = "com.vsmartcard.acardemulator.EmulatorService"; public static final String EXTRA_CAPDU = "MSG_CAPDU"; @@ -90,6 +102,32 @@ public class EmulatorSingleton { return rapdu; } + public static String[] getRegisteredAids(Context context) { + List aidList = new ArrayList<>(); + XmlResourceParser aidXmlParser = context.getResources().getXml(R.xml.aid_list); + + try { + while (aidXmlParser.getEventType() != XmlPullParser.END_DOCUMENT) { + if (aidXmlParser.getEventType() == XmlPullParser.START_TAG) { + if (aidXmlParser.getName().equals("aid-filter")) { + int aid = aidXmlParser.getAttributeResourceValue(0, -1); + if (aid != -1) { + aidList.add(context.getResources().getString(aid)); + } + } + } + + aidXmlParser.next(); + } + + aidXmlParser.close(); + } catch (XmlPullParserException | IOException e) { + Log.e(TAG.substring(0, 23), "Couldn't parse aid xml list."); + } + + return aidList.toArray(new String[0]); + } + public static void deactivate() { emulator.deactivate(); } diff --git a/TCardEmulator/inc/sap_app.h b/TCardEmulator/inc/sap_app.h index 5a9815f..38e8a75 100644 --- a/TCardEmulator/inc/sap_app.h +++ b/TCardEmulator/inc/sap_app.h @@ -4,6 +4,7 @@ #include void send_apdu_response(nfc_se_h handle, unsigned char *resp, unsigned int resp_len); +void install_aids(void *buffer, unsigned int buffer_size); extern gboolean agent_connected; diff --git a/TCardEmulator/inc/tcardemulator.h b/TCardEmulator/inc/tcardemulator.h index f8f1797..ca74f0d 100644 --- a/TCardEmulator/inc/tcardemulator.h +++ b/TCardEmulator/inc/tcardemulator.h @@ -16,7 +16,6 @@ void initialize_sap(); gboolean find_peers(); gboolean request_service_connection(void); gboolean terminate_service_connection(void); -gboolean send_data(nfc_se_h nfc_handle, void *message, unsigned int message_len); -GSList* request_installed_aids(); +gboolean send_data(nfc_se_h nfc_handle, char* prefix, unsigned int prefix_len, void *message, unsigned int message_len); #endif /* __tcardemulator_H__ */ diff --git a/TCardEmulator/src/sap.c b/TCardEmulator/src/sap.c index b29eaf3..763e78b 100644 --- a/TCardEmulator/src/sap.c +++ b/TCardEmulator/src/sap.c @@ -25,8 +25,7 @@ static priv_s priv_data = { 0 }; void on_peer_agent_updated(sap_peer_agent_h peer_agent, sap_peer_agent_status_e peer_status, sap_peer_agent_found_result_e result, - void *user_data) -{ + void *user_data) { switch (result) { case SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED: dlog_print(DLOG_INFO, LOG_TAG, "device is not connected"); @@ -61,8 +60,7 @@ void on_peer_agent_updated(sap_peer_agent_h peer_agent, static void on_service_connection_terminated(sap_peer_agent_h peer_agent, sap_socket_h socket, sap_service_connection_terminated_reason_e result, - void *user_data) -{ + void *user_data) { switch (result) { case SAP_CONNECTION_TERMINATED_REASON_PEER_DISCONNECTED: dlog_print(DLOG_INFO, LOG_TAG, "disconnected because peer lost"); @@ -92,26 +90,41 @@ static void on_data_recieved(sap_socket_h socket, void *user_data) { dlog_print(DLOG_INFO, LOG_TAG, "received data: %p, len:%d", buffer, payload_length); - send_apdu_response(priv_data.nfc_handle, buffer, payload_length); + char* string_buffer = (char*) buffer; + if (string_buffer[0] == 'a') { + install_aids(buffer + sizeof(char), payload_length - 1); + } else if (string_buffer[0] == 'd') { + send_apdu_response(priv_data.nfc_handle, buffer + sizeof(char), payload_length - 1); + } } -gboolean send_data(nfc_se_h nfc_handle, void *message, unsigned int message_len) { +gboolean send_data(nfc_se_h nfc_handle, char* prefix, unsigned int prefix_len, void *message, unsigned int message_len) { gboolean result; - priv_data.nfc_handle = nfc_handle; + if (nfc_handle != NULL) { + priv_data.nfc_handle = nfc_handle; + } + void *final_message = malloc(prefix_len + message_len); + memcpy(final_message, prefix, prefix_len); + memcpy(final_message + prefix_len * sizeof(char), message, message_len); result = sap_socket_send_secure_data(priv_data.socket, - ACCESSORY_CHANNELID, message_len, message); + ACCESSORY_CHANNELID, prefix_len + message_len, final_message); if (result != SAP_RESULT_SUCCESS) { dlog_print(DLOG_INFO, LOG_TAG, "couldn't send sap message: %d", result); } + + free(final_message); return result; } +gboolean request_installed_aids() { + return send_data(NULL, "a", 1, "", 0); +} + static void on_service_connection_created(sap_peer_agent_h peer_agent, sap_socket_h socket, sap_service_connection_result_e result, - void *user_data) -{ + void *user_data) { switch (result) { case SAP_CONNECTION_SUCCESS: dlog_print(DLOG_INFO, LOG_TAG, "peer agent connection is successful, pa :%u", peer_agent); @@ -122,6 +135,8 @@ static void on_service_connection_created(sap_peer_agent_h peer_agent, sap_socket_set_data_received_cb(socket, on_data_recieved, peer_agent); priv_data.socket = socket; agent_connected = TRUE; + + request_installed_aids(); break; case SAP_CONNECTION_IN_PROGRESS: @@ -239,18 +254,6 @@ gboolean find_peers() return TRUE; } -GSList* request_installed_aids() { - GSList* aid_list = g_slist_append(NULL, "A000000397425446590201"); - aid_list = g_slist_append(aid_list, "A0000003974254465902"); - aid_list = g_slist_append(aid_list, "A00000039742544659"); - aid_list = g_slist_append(aid_list, "F276A288BCFBA69D34F31001"); - aid_list = g_slist_append(aid_list, "F000000001"); - aid_list = g_slist_append(aid_list, "D27600012401"); - aid_list = g_slist_append(aid_list, "D2760001240102000000000000010000"); - aid_list = g_slist_append(aid_list, "A000000527210101"); - return aid_list; -} - static void on_agent_initialized(sap_agent_h agent, sap_agent_initialized_result_e result, void *user_data) diff --git a/TCardEmulator/src/tcardemulator.c b/TCardEmulator/src/tcardemulator.c index c8cd0be..530092e 100644 --- a/TCardEmulator/src/tcardemulator.c +++ b/TCardEmulator/src/tcardemulator.c @@ -27,7 +27,7 @@ static void hce_event_cb(nfc_se_h handle, nfc_hce_event_type_e event, unsigned c case NFC_HCE_EVENT_APDU_RECEIVED: dlog_print(DLOG_DEBUG, LOG_TAG, "received NFC_HCE_EVENT_APDU_RECEIVED event on NFC handle %d", handle); if (agent_connected) { - send_data(handle, apdu, apdu_len); + send_data(handle, "d", 1, apdu, apdu_len); } else { dlog_print(DLOG_INFO, LOG_TAG, "couldn't send message on SAP channel because agent is not connected"); } @@ -39,7 +39,7 @@ static void hce_event_cb(nfc_se_h handle, nfc_hce_event_type_e event, unsigned c } } -void register_aid(gpointer data, gpointer user_data) { +void register_aid(gpointer data) { int result = nfc_se_register_aid(NFC_SE_TYPE_HCE, NFC_CARD_EMULATION_CATEGORY_OTHER, data); if (result != NFC_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "nfc_se_register_aid for aid %s failed: %d", data, result); @@ -48,9 +48,17 @@ void register_aid(gpointer data, gpointer user_data) { } } -void install_aids() { - GSList* aid_list = request_installed_aids(); - g_slist_foreach(aid_list, register_aid, NULL); +void install_aids(void *buffer, unsigned int buffer_size) { + gchar aid_string[buffer_size + 1]; + g_strlcpy(aid_string, (gchar *)buffer, buffer_size + 1); + + gchar **aid_buffer = g_strsplit(aid_string, ",", 0); + int i; + int aid_len = g_strv_length(aid_buffer); + for (i = 0; i < aid_len; i++) { + register_aid((gpointer)aid_buffer[i]); + } + g_strfreev(aid_buffer); } void send_apdu_response(nfc_se_h handle, unsigned char *resp, unsigned int resp_len) { @@ -98,8 +106,6 @@ bool service_app_create(void *data) { find_peers(); - install_aids(); - r = true; err: