Let ACardEmulator provide installed AIDs
This commit is contained in:
committed by
Frank Morgner
parent
dae5622992
commit
3501843159
@@ -23,12 +23,6 @@
|
|||||||
|
|
||||||
package com.vsmartcard.acardemulator;
|
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.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
@@ -37,13 +31,25 @@ import android.content.pm.Signature;
|
|||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.widget.Toast;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.samsung.android.sdk.SsdkUnsupportedException;
|
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 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 {
|
public class SmartcardProviderService extends SAAgent {
|
||||||
private static final String TAG = "ACardEmulator";
|
private static final String TAG = "ACardEmulator";
|
||||||
private static final int ACCESSORY_CHANNEL_ID = 104;
|
private static final int ACCESSORY_CHANNEL_ID = 104;
|
||||||
@@ -199,14 +205,34 @@ public class SmartcardProviderService extends SAAgent {
|
|||||||
if (mConnectionHandler == null) {
|
if (mConnectionHandler == null) {
|
||||||
return;
|
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() {
|
new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
mConnectionHandler.secureSend(ACCESSORY_CHANNEL_ID, response);
|
mConnectionHandler.secureSend(ACCESSORY_CHANNEL_ID, sendResponse);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,25 @@ package com.vsmartcard.acardemulator.emulators;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
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.preference.PreferenceManager;
|
||||||
|
import android.support.annotation.XmlRes;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.vsmartcard.acardemulator.R;
|
import com.vsmartcard.acardemulator.R;
|
||||||
import com.vsmartcard.acardemulator.Util;
|
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 class EmulatorSingleton {
|
||||||
public static final String TAG = "com.vsmartcard.acardemulator.EmulatorService";
|
public static final String TAG = "com.vsmartcard.acardemulator.EmulatorService";
|
||||||
public static final String EXTRA_CAPDU = "MSG_CAPDU";
|
public static final String EXTRA_CAPDU = "MSG_CAPDU";
|
||||||
@@ -90,6 +102,32 @@ public class EmulatorSingleton {
|
|||||||
return rapdu;
|
return rapdu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String[] getRegisteredAids(Context context) {
|
||||||
|
List<String> 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() {
|
public static void deactivate() {
|
||||||
emulator.deactivate();
|
emulator.deactivate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <nfc.h>
|
#include <nfc.h>
|
||||||
|
|
||||||
void send_apdu_response(nfc_se_h handle, unsigned char *resp, unsigned int resp_len);
|
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;
|
extern gboolean agent_connected;
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ void initialize_sap();
|
|||||||
gboolean find_peers();
|
gboolean find_peers();
|
||||||
gboolean request_service_connection(void);
|
gboolean request_service_connection(void);
|
||||||
gboolean terminate_service_connection(void);
|
gboolean terminate_service_connection(void);
|
||||||
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);
|
||||||
GSList* request_installed_aids();
|
|
||||||
|
|
||||||
#endif /* __tcardemulator_H__ */
|
#endif /* __tcardemulator_H__ */
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ static priv_s priv_data = { 0 };
|
|||||||
void on_peer_agent_updated(sap_peer_agent_h peer_agent,
|
void on_peer_agent_updated(sap_peer_agent_h peer_agent,
|
||||||
sap_peer_agent_status_e peer_status,
|
sap_peer_agent_status_e peer_status,
|
||||||
sap_peer_agent_found_result_e result,
|
sap_peer_agent_found_result_e result,
|
||||||
void *user_data)
|
void *user_data) {
|
||||||
{
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED:
|
case SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED:
|
||||||
dlog_print(DLOG_INFO, LOG_TAG, "device is 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,
|
static void on_service_connection_terminated(sap_peer_agent_h peer_agent,
|
||||||
sap_socket_h socket,
|
sap_socket_h socket,
|
||||||
sap_service_connection_terminated_reason_e result,
|
sap_service_connection_terminated_reason_e result,
|
||||||
void *user_data)
|
void *user_data) {
|
||||||
{
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case SAP_CONNECTION_TERMINATED_REASON_PEER_DISCONNECTED:
|
case SAP_CONNECTION_TERMINATED_REASON_PEER_DISCONNECTED:
|
||||||
dlog_print(DLOG_INFO, LOG_TAG, "disconnected because peer lost");
|
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) {
|
void *user_data) {
|
||||||
dlog_print(DLOG_INFO, LOG_TAG, "received data: %p, len:%d", buffer, payload_length);
|
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;
|
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,
|
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) {
|
if (result != SAP_RESULT_SUCCESS) {
|
||||||
dlog_print(DLOG_INFO, LOG_TAG, "couldn't send sap message: %d", result);
|
dlog_print(DLOG_INFO, LOG_TAG, "couldn't send sap message: %d", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(final_message);
|
||||||
return result;
|
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,
|
static void on_service_connection_created(sap_peer_agent_h peer_agent,
|
||||||
sap_socket_h socket,
|
sap_socket_h socket,
|
||||||
sap_service_connection_result_e result,
|
sap_service_connection_result_e result,
|
||||||
void *user_data)
|
void *user_data) {
|
||||||
{
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case SAP_CONNECTION_SUCCESS:
|
case SAP_CONNECTION_SUCCESS:
|
||||||
dlog_print(DLOG_INFO, LOG_TAG, "peer agent connection is successful, pa :%u", peer_agent);
|
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);
|
sap_socket_set_data_received_cb(socket, on_data_recieved, peer_agent);
|
||||||
priv_data.socket = socket;
|
priv_data.socket = socket;
|
||||||
agent_connected = TRUE;
|
agent_connected = TRUE;
|
||||||
|
|
||||||
|
request_installed_aids();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SAP_CONNECTION_IN_PROGRESS:
|
case SAP_CONNECTION_IN_PROGRESS:
|
||||||
@@ -239,18 +254,6 @@ gboolean find_peers()
|
|||||||
return TRUE;
|
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,
|
static void on_agent_initialized(sap_agent_h agent,
|
||||||
sap_agent_initialized_result_e result,
|
sap_agent_initialized_result_e result,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
|
|||||||
@@ -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:
|
case NFC_HCE_EVENT_APDU_RECEIVED:
|
||||||
dlog_print(DLOG_DEBUG, LOG_TAG, "received NFC_HCE_EVENT_APDU_RECEIVED event on NFC handle %d", handle);
|
dlog_print(DLOG_DEBUG, LOG_TAG, "received NFC_HCE_EVENT_APDU_RECEIVED event on NFC handle %d", handle);
|
||||||
if (agent_connected) {
|
if (agent_connected) {
|
||||||
send_data(handle, apdu, apdu_len);
|
send_data(handle, "d", 1, apdu, apdu_len);
|
||||||
} else {
|
} else {
|
||||||
dlog_print(DLOG_INFO, LOG_TAG, "couldn't send message on SAP channel because agent is not connected");
|
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);
|
int result = nfc_se_register_aid(NFC_SE_TYPE_HCE, NFC_CARD_EMULATION_CATEGORY_OTHER, data);
|
||||||
if (result != NFC_ERROR_NONE) {
|
if (result != NFC_ERROR_NONE) {
|
||||||
dlog_print(DLOG_ERROR, LOG_TAG, "nfc_se_register_aid for aid %s failed: %d", data, result);
|
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() {
|
void install_aids(void *buffer, unsigned int buffer_size) {
|
||||||
GSList* aid_list = request_installed_aids();
|
gchar aid_string[buffer_size + 1];
|
||||||
g_slist_foreach(aid_list, register_aid, NULL);
|
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) {
|
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();
|
find_peers();
|
||||||
|
|
||||||
install_aids();
|
|
||||||
|
|
||||||
r = true;
|
r = true;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
|||||||
Reference in New Issue
Block a user