From 9c758ffda06e2faaf6b2260fd983f0f054d3c854 Mon Sep 17 00:00:00 2001
From: Jan-Christopher Pien <101@janchristopherpien.de>
Date: Tue, 11 Oct 2016 21:54:29 +0200
Subject: [PATCH] Authentication for ACardEmulator/TCardEmulator
secure sending and with high priority
---
ACardEmulator/app/.gitignore | 2 +-
ACardEmulator/app/app.iml | 17 +--
ACardEmulator/app/build.gradle | 19 ++-
.../SmartcardProviderService.java | 52 ++++++--
.../src/main/res/xml/accessoryservices.xml | 2 +-
TCardEmulator/inc/sap_app.h | 2 +
TCardEmulator/inc/tcardemulator.h | 7 -
TCardEmulator/res/accessoryservices.xml | 2 +-
TCardEmulator/src/sap.c | 121 +++++-------------
TCardEmulator/src/tcardemulator.c | 84 +++---------
10 files changed, 117 insertions(+), 191 deletions(-)
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);
}