diff --git a/ACardEmulator/app/.gitignore b/ACardEmulator/app/.gitignore index 796b96d..42afabf 100644 --- a/ACardEmulator/app/.gitignore +++ b/ACardEmulator/app/.gitignore @@ -1 +1 @@ -/build +/build \ No newline at end of file diff --git a/ACardEmulator/app/app.iml b/ACardEmulator/app/app.iml index 70b0fb8..55409a1 100644 --- a/ACardEmulator/app/app.iml +++ b/ACardEmulator/app/app.iml @@ -71,14 +71,6 @@ - - - - - - - - @@ -87,6 +79,14 @@ + + + + + + + + @@ -108,6 +108,7 @@ + diff --git a/ACardEmulator/app/build.gradle b/ACardEmulator/app/build.gradle index 380911f..8e86e46 100644 --- a/ACardEmulator/app/build.gradle +++ b/ACardEmulator/app/build.gradle @@ -1,9 +1,20 @@ apply plugin: 'com.android.application' +def keystorePropertiesFile = rootProject.file("keystore.properties") +def keystoreProperties = new Properties() +keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + android { + signingConfigs { + config { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] + storePassword keystoreProperties['storePassword'] + } + } compileSdkVersion 23 buildToolsVersion "23.0.1" - defaultConfig { applicationId "com.vsmartcard.acardemulator" minSdkVersion 19 @@ -15,6 +26,10 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.config + } + debug { + signingConfig signingConfigs.config } } sourceSets { @@ -49,7 +64,7 @@ android.applicationVariants.all { variant -> } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + compile fileTree(include: ['*.jar'], dir: 'libs') compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.android.support:support-v4:23.0.1' compile 'com.android.support:design:23.2.1' 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 17ea8f6..0e6df62 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,17 @@ package com.vsmartcard.acardemulator; +import java.io.ByteArrayInputStream; import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.GregorianCalendar; +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; +import android.content.pm.PackageManager; +import android.content.pm.Signature; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -40,8 +45,8 @@ import com.samsung.android.sdk.accessory.*; import com.vsmartcard.acardemulator.emulators.EmulatorSingleton; public class SmartcardProviderService extends SAAgent { - private static final String TAG = "HelloAccessory(P)"; - private static final int HELLOACCESSORY_CHANNEL_ID = 104; + private static final String TAG = "ACardEmulator"; + private static final int ACCESSORY_CHANNEL_ID = 104; private static final Class SASOCKET_CLASS = ServiceConnection.class; private final IBinder mBinder = new LocalBinder(); private ServiceConnection mConnectionHandler = null; @@ -99,8 +104,7 @@ public class SmartcardProviderService extends SAAgent { @Override protected void onServiceConnectionRequested(SAPeerAgent peerAgent) { if (peerAgent != null) { - //TODO: Check for keys and everything - acceptServiceConnectionRequest(peerAgent); + authenticatePeerAgent(peerAgent); } } @@ -116,12 +120,36 @@ public class SmartcardProviderService extends SAAgent { } } + private static byte[] getApplicationCertificate(Context context) { + byte[] cert = new byte[0]; + String packageName = context.getPackageName(); + try { + PackageInfo pkgInfo = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES); + if (pkgInfo != null) { + Signature[] sigs = pkgInfo.signatures; + if (sigs != null) { + ByteArrayInputStream stream = new ByteArrayInputStream(sigs[0].toByteArray()); + X509Certificate x509cert = X509Certificate.getInstance(stream); + cert = x509cert.getPublicKey().getEncoded(); + } + } + } catch (PackageManager.NameNotFoundException | CertificateException e) { + Log.e(TAG, e.getMessage()); + } + return cert; + } + @Override protected void onAuthenticationResponse(SAPeerAgent peerAgent, SAAuthenticationToken authToken, int error) { - /* - * The authenticatePeerAgent(peerAgent) API may not be working properly depending on the firmware - * version of accessory device. Please refer to another sample application for Security. - */ + if (authToken.getAuthenticationType() == SAAuthenticationToken.AUTHENTICATION_TYPE_CERTIFICATE_X509) { + byte[] myAppKey = getApplicationCertificate(getApplicationContext()); + if (authToken.getKey().length == myAppKey.length) { + if (Arrays.equals(authToken.getKey(), myAppKey)) { + acceptServiceConnectionRequest(peerAgent); + } + } + } + rejectServiceConnectionRequest(peerAgent); } @Override @@ -175,7 +203,7 @@ public class SmartcardProviderService extends SAAgent { new Thread(new Runnable() { public void run() { try { - mConnectionHandler.send(HELLOACCESSORY_CHANNEL_ID, response); + mConnectionHandler.secureSend(ACCESSORY_CHANNEL_ID, response); } catch (IOException e) { e.printStackTrace(); } diff --git a/ACardEmulator/app/src/main/res/xml/accessoryservices.xml b/ACardEmulator/app/src/main/res/xml/accessoryservices.xml index f6b7f02..1a5c7cf 100644 --- a/ACardEmulator/app/src/main/res/xml/accessoryservices.xml +++ b/ACardEmulator/app/src/main/res/xml/accessoryservices.xml @@ -43,7 +43,7 @@ diff --git a/TCardEmulator/inc/sap_app.h b/TCardEmulator/inc/sap_app.h index 2475765..5a9815f 100644 --- a/TCardEmulator/inc/sap_app.h +++ b/TCardEmulator/inc/sap_app.h @@ -5,4 +5,6 @@ void send_apdu_response(nfc_se_h handle, unsigned char *resp, unsigned int resp_len); +extern gboolean agent_connected; + #endif /* __tcardemulator_H__ */ diff --git a/TCardEmulator/inc/tcardemulator.h b/TCardEmulator/inc/tcardemulator.h index 62c9665..f8f1797 100644 --- a/TCardEmulator/inc/tcardemulator.h +++ b/TCardEmulator/inc/tcardemulator.h @@ -12,13 +12,6 @@ #include #include -//extern unsigned char *rapdu; -//extern size_t rapdu_length; -//extern gboolean rapdu_received; - -#define HELLO_ACC_ASPID "/com/vsmcartcard" -#define HELLO_ACC_CHANNELID 104 - void initialize_sap(); gboolean find_peers(); gboolean request_service_connection(void); diff --git a/TCardEmulator/res/accessoryservices.xml b/TCardEmulator/res/accessoryservices.xml index 57095a1..e2265f1 100644 --- a/TCardEmulator/res/accessoryservices.xml +++ b/TCardEmulator/res/accessoryservices.xml @@ -7,7 +7,7 @@ - diff --git a/TCardEmulator/src/sap.c b/TCardEmulator/src/sap.c index 82aec7e..b29eaf3 100644 --- a/TCardEmulator/src/sap.c +++ b/TCardEmulator/src/sap.c @@ -7,8 +7,8 @@ #include #include -#define HELLO_ACCESSORY_PROFILE_ID "/com/vsmcartcard" -#define HELLO_ACCESSORY_CHANNELID 104 +#define ACCESSORY_PROFILE_ID "/com/vsmcartcard" +#define ACCESSORY_CHANNELID 104 typedef struct priv { sap_agent_h agent; @@ -17,17 +17,10 @@ typedef struct priv { nfc_se_h nfc_handle; } priv_s; -typedef struct message_queue { - void *message; - unsigned int message_len; - struct message_queue *next; -} message_queue_s; - -static gboolean agent_created = FALSE; -static gboolean agent_connected = FALSE; +gboolean agent_created = FALSE; +gboolean agent_connected = FALSE; static priv_s priv_data = { 0 }; -static message_queue_s *m_queue = NULL; void on_peer_agent_updated(sap_peer_agent_h peer_agent, sap_peer_agent_status_e peer_status, @@ -42,7 +35,7 @@ void on_peer_agent_updated(sap_peer_agent_h peer_agent, case SAP_PEER_AGENT_FOUND_RESULT_FOUND: if (peer_status == SAP_PEER_AGENT_STATUS_AVAILABLE) { priv_data.peer_agent = peer_agent; - dlog_print(DLOG_INFO, LOG_TAG, "Find Peer Success!!"); + dlog_print(DLOG_INFO, LOG_TAG, "requesting service connection"); request_service_connection(); } else { dlog_print(DLOG_INFO, LOG_TAG, "peer agent removed"); @@ -96,77 +89,20 @@ static void on_data_recieved(sap_socket_h socket, unsigned short int channel_id, unsigned int payload_length, void *buffer, - void *user_data) -{ + void *user_data) { dlog_print(DLOG_INFO, LOG_TAG, "received data: %p, len:%d", buffer, payload_length); - //unsigned char *p = realloc(rapdu, payload_length); -// if (p) { -// rapdu = p; -// rapdu_length = payload_length; -// } else { -// dlog_print(DLOG_ERROR, LOG_TAG, "not enough for storing data"); -// if (rapdu && rapdu_length >= 2) { -// dlog_print(DLOG_ERROR, LOG_TAG, -// "not enough memory, returning 0x6D00 as R-APDU"); -// rapdu[0] = 0x6D; -// rapdu[1] = 0x00; -// rapdu_length = 2; -// } else { -// dlog_print(DLOG_ERROR, LOG_TAG, -// "not enough memory, setting R-APDU to nothing"); -// rapdu_length = 0; -// } -// } - -// rapdu_received = TRUE; send_apdu_response(priv_data.nfc_handle, buffer, payload_length); } -message_queue_s *read_message() { - if (m_queue != NULL) { - message_queue_s *message = m_queue; - m_queue = message->next; - return message; - } - return NULL; -} - - -gboolean add_message(void *message, unsigned int message_len) { - message_queue_s *message_pointer = m_queue; - message_queue_s *prev = message_pointer; - while (message_pointer != NULL) { - prev = message_pointer; - message_pointer = message_pointer->next; - } - message_pointer = malloc(sizeof (message_queue_s)); - if (message_pointer != NULL) { - if (m_queue == NULL) { - m_queue = message_pointer; - } else { - prev->next = message_pointer; - } - message_pointer->message = message; - message_pointer->message_len = message_len; - message_pointer->next = NULL; - return TRUE; - } - return FALSE; -} - gboolean send_data(nfc_se_h nfc_handle, void *message, unsigned int message_len) { gboolean result; - if (agent_connected) { - priv_data.nfc_handle = nfc_handle; - result = sap_socket_send_data(priv_data.socket, - HELLO_ACCESSORY_CHANNELID, message_len, message); + priv_data.nfc_handle = nfc_handle; + result = sap_socket_send_secure_data(priv_data.socket, + ACCESSORY_CHANNELID, message_len, message); - if (result != SAP_RESULT_SUCCESS) { - - } - } else { - result = add_message(message, message_len); + if (result != SAP_RESULT_SUCCESS) { + dlog_print(DLOG_INFO, LOG_TAG, "couldn't send sap message: %d", result); } return result; } @@ -186,17 +122,16 @@ 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; - // read messages in queue and send them - message_queue_s *message_queue = read_message(); - while (message_queue != NULL) { - send_data(priv_data.nfc_handle, message_queue->message, message_queue->message_len); - message_queue = read_message(); - } + break; + + case SAP_CONNECTION_IN_PROGRESS: + dlog_print(DLOG_INFO, LOG_TAG, "connection is already in progress"); break; case SAP_CONNECTION_ALREADY_EXIST: - dlog_print(DLOG_INFO, LOG_TAG, "connection is already exist"); + dlog_print(DLOG_INFO, LOG_TAG, "connection already exists"); priv_data.socket = socket; + agent_connected = TRUE; break; case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE: @@ -225,8 +160,7 @@ static void on_service_connection_created(sap_peer_agent_h peer_agent, } } -static gboolean _create_service_connection(gpointer user_data) -{ +static gboolean _create_service_connection(gpointer user_data) { struct priv *priv = NULL; sap_result_e result = SAP_RESULT_FAILURE; @@ -245,16 +179,12 @@ static gboolean _create_service_connection(gpointer user_data) return FALSE; } -gboolean request_service_connection(void) -{ +gboolean request_service_connection(void) { g_idle_add(_create_service_connection, &priv_data); - - dlog_print(DLOG_DEBUG, LOG_TAG, "request_service_connection call over"); return TRUE; } -static gboolean _terminate_service_connection(gpointer user_data) -{ +static gboolean _terminate_service_connection(gpointer user_data) { struct priv *priv = NULL; sap_result_e result = SAP_RESULT_FAILURE; @@ -281,7 +211,6 @@ static gboolean _terminate_service_connection(gpointer user_data) gboolean terminate_service_connection(void) { g_idle_add(_terminate_service_connection, &priv_data); - return TRUE; } @@ -312,6 +241,13 @@ gboolean find_peers() 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; } @@ -382,6 +318,7 @@ static void on_device_status_changed(sap_device_status_e status, sap_transport_t priv_data.socket = NULL; sap_peer_agent_destroy(priv_data.peer_agent); priv_data.peer_agent = NULL; + agent_connected = FALSE; } break; @@ -408,7 +345,7 @@ gboolean agent_initialize() break; } result = sap_agent_initialize(priv_data.agent, - HELLO_ACCESSORY_PROFILE_ID, SAP_AGENT_ROLE_CONSUMER, + ACCESSORY_PROFILE_ID, SAP_AGENT_ROLE_CONSUMER, on_agent_initialized, NULL); dlog_print(DLOG_DEBUG, LOG_TAG, "sap_agent_initialize >>> %d", result); i++; diff --git a/TCardEmulator/src/tcardemulator.c b/TCardEmulator/src/tcardemulator.c index cce0a7f..c8cd0be 100644 --- a/TCardEmulator/src/tcardemulator.c +++ b/TCardEmulator/src/tcardemulator.c @@ -1,4 +1,5 @@ #include "tcardemulator.h" +#include "sap_app.h" #include #include #include @@ -10,45 +11,30 @@ typedef struct appdata { } appdata_s; -//unsigned char *rapdu = NULL; -//size_t rapdu_length = 0; -//gboolean rapdu_received = FALSE; - - static void -hce_event_cb(nfc_se_h handle, nfc_hce_event_type_e event, - unsigned char *apdu, unsigned int apdu_len, void *user_data) -{ +static void hce_event_cb(nfc_se_h handle, nfc_hce_event_type_e event, unsigned char *apdu, unsigned int apdu_len, void *user_data) { switch (event) { case NFC_HCE_EVENT_DEACTIVATED: - // Do something when NFC_HCE_EVENT_DEACTIVATED event arrives - // When the event arrives, apdu and apdu len is NULL and 0 dlog_print(DLOG_DEBUG, LOG_TAG, "received NFC_HCE_EVENT_DEACTIVATED event on NFC handle %d", handle); - //terminate_service_connection(); break; case NFC_HCE_EVENT_ACTIVATED: - // Do something when NFC_HCE_EVENT_ACTIVATED event arrives - // When the event arrives, apdu and apdu len is NULL and 0 dlog_print(DLOG_DEBUG, LOG_TAG, "received NFC_HCE_EVENT_ACTIVATED event on NFC handle %d", handle); - //find_peers(); + if (!agent_connected) { + find_peers(); + } break; case NFC_HCE_EVENT_APDU_RECEIVED: -// rapdu_received = FALSE; dlog_print(DLOG_DEBUG, LOG_TAG, "received NFC_HCE_EVENT_APDU_RECEIVED event on NFC handle %d", handle); - send_data(handle, apdu, apdu_len); -// size_t count_apdu = 0; -// while (!rapdu_received && count_apdu < 10) { -// dlog_print(DLOG_INFO, LOG_TAG, "waiting for response"); -// usleep(100); -// count_apdu++; -// } -// nfc_hce_send_apdu_response(handle, rapdu, rapdu_length); -// rapdu_received = FALSE; + if (agent_connected) { + send_data(handle, apdu, apdu_len); + } else { + dlog_print(DLOG_INFO, LOG_TAG, "couldn't send message on SAP channel because agent is not connected"); + } break; default: - // Error handling + dlog_print(DLOG_DEBUG, LOG_TAG, "received unknown event on NFC handle %d", handle); break; } } @@ -75,9 +61,7 @@ void send_apdu_response(nfc_se_h handle, unsigned char *resp, unsigned int resp_ } } - bool -service_app_create(void *data) -{ +bool service_app_create(void *data) { int ret = NFC_ERROR_NONE; bool r = false; nfc_se_card_emulation_mode_type_e ce_type; @@ -122,9 +106,7 @@ err: return r; } - void -service_app_terminate(void *data) -{ +void service_app_terminate(void *data) { int ret = NFC_ERROR_NONE; nfc_manager_unset_hce_event_cb(); @@ -137,43 +119,26 @@ service_app_terminate(void *data) terminate_service_connection(); -// free(rapdu); -// rapdu = NULL; -// rapdu_length = 0; -// rapdu_received = FALSE; - return; } - void -service_app_control(app_control_h app_control, void *data) -{ - // Todo: add your code here - +void service_app_control(app_control_h app_control, void *data) { return; } - void -service_app_low_memory(void *data) -{ - // Todo: add your code here +void service_app_low_memory(void *data) { service_app_terminate(&data); return; } - void -service_app_low_battery(void *data) -{ - // Todo: add your code here +void service_app_low_battery(void *data) { service_app_terminate(&data); return; } - int -main(int argc, char* argv[]) -{ +int main(int argc, char* argv[]) { appdata_s ad = {}; service_app_event_callback_s event_callback; @@ -184,20 +149,5 @@ main(int argc, char* argv[]) event_callback.low_memory = service_app_low_memory; event_callback.low_battery = service_app_low_battery; - -//#if 1 -// initialize_sap(); -// find_peers(); -// rapdu_received = FALSE; -// unsigned char apdu[] = {0x00, 0xa4, 0x00, 0x00}; -// send_data(apdu, sizeof apdu); -// size_t count = 0; -// while (!rapdu_received && count < 10) { -// dlog_print(DLOG_INFO, LOG_TAG, "waiting for response"); -// usleep(100); -// count++; -// } -//#endif - return svc_app_main(argc, argv, &event_callback, &ad); }