Implement deactivation of Applets

Actually implements and fixes what was intended with
f401923005
This commit is contained in:
Frank Morgner
2016-04-12 22:01:50 -04:00
parent 0aeb8a1859
commit 65cbac22c5
10 changed files with 148 additions and 253 deletions

View File

@@ -74,8 +74,13 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/debug" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/animated-vector-drawable/23.2.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.2.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/23.2.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.2.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.2.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-vector-drawable/23.2.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.journeyapps/zxing-android-embedded/3.2.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
@@ -88,10 +93,15 @@
</content>
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" />
<orderEntry type="library" exported="" name="animated-vector-drawable-23.2.1" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.2.1" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-23.2.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.2.1" level="project" />
<orderEntry type="library" exported="" name="support-vector-drawable-23.2.1" level="project" />
<orderEntry type="library" exported="" name="zxing-android-embedded-3.2.0" level="project" />
<orderEntry type="library" exported="" name="design-23.2.1" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-23.2.1" level="project" />
<orderEntry type="library" exported="" name="core-1.51.0.0" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
<orderEntry type="library" exported="" name="jcardsim-3.0.4-SNAPSHOT-android" level="project" />
</component>
</module>

View File

@@ -31,5 +31,8 @@ dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
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'
compile 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
compile group: 'com.madgag.spongycastle', name: 'core', version: '1.51.0.0'
}

View File

@@ -22,6 +22,12 @@
</intent-filter>
</activity>
<activity
android:name="com.vsmartcard.acardemulator.SettingsActivity"
android:label="@string/action_settings" >
>
</activity>
<service android:name=".SimulatorService"
android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">

View File

@@ -1,4 +1,4 @@
package com.vsmartcard.remotesmartcardreader.app;
package com.vsmartcard.acardemulator;
import android.content.res.Configuration;
import android.os.Bundle;

View File

@@ -128,6 +128,9 @@ public class MainActivity extends ActionBarActivity {
case R.id.action_help:
showStartupMessage();
return true;
case R.id.action_settings:
startActivity(new Intent(this, SettingsActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}

View File

@@ -1,108 +0,0 @@
/*
* Copyright (C) 2014 Frank Morgner
*
* This file is part of RemoteSmartCardReader.
*
* RemoteSmartCardReader is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* RemoteSmartCardReader is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* RemoteSmartCardReader. If not, see <http://www.gnu.org/licenses/>.
*/
package com.vsmartcard.acardemulator;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import com.licel.jcardsim.base.Simulator;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Settings {
private final Context context;
private static final String simulatorFilename = "simulator";
public Settings (Context activity) {
context = activity;
}
public void witeObjectToFile(String filename, Object object) {
ObjectOutputStream objectOut = null;
try {
FileOutputStream fileOut = context.openFileOutput(filename, Activity.MODE_PRIVATE);
objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(object);
fileOut.getFD().sync();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (objectOut != null) {
try {
objectOut.close();
} catch (IOException e) {
// do nowt
}
}
}
}
public Object readObjectFromFile(String filename) {
ObjectInputStream objectIn = null;
Object object = null;
try {
FileInputStream fileIn = context.getApplicationContext().openFileInput(filename);
objectIn = new ObjectInputStream(fileIn);
object = objectIn.readObject();
} catch (java.io.FileNotFoundException e) {
// Do nothing
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (objectIn != null) {
try {
objectIn.close();
} catch (IOException e) {
// do nowt
}
}
}
return object;
}
public void setSimulator(Simulator simulator) {
witeObjectToFile(simulatorFilename, simulator);
}
public Simulator getSimulator() {
Object object = readObjectFromFile(simulatorFilename);
if (object == null) {
// TODO
return new Simulator();
} else {
return (Simulator) object;
}
}
}

View File

@@ -17,28 +17,23 @@
* RemoteSmartCardReader. If not, see <http://www.gnu.org/licenses/>.
*/
package com.vsmartcard.remotesmartcardreader.app;
package com.vsmartcard.acardemulator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.provider.Settings;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.SwitchPreference;
import android.support.v7.app.ActionBar;
import android.view.MenuItem;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
@@ -59,7 +54,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
// Display the fragment as the main content.
getFragmentManager().beginTransaction().replace(android.R.id.content,
new VPCDPreferenceFragment()).commit();
new VICCPreferenceFragment()).commit();
}
/**
@@ -119,6 +114,14 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
index >= 0
? listPreference.getEntries()[index]
: null);
} else if (preference instanceof SwitchPreference) {
SwitchPreference switchPreference = (SwitchPreference) preference;
if (stringValue == "true") {
CharSequence aid = switchPreference.getSwitchTextOn();
preference.setSummary("Selectable with AID " + aid);
} else {
preference.setSummary("Deactivated");
}
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
@@ -143,10 +146,17 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
// Trigger the listener immediately with the settings's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
if (preference instanceof SwitchPreference) {
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getBoolean(preference.getKey(), false));
} else {
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
}
/**
@@ -154,7 +164,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class VPCDPreferenceFragment extends PreferenceFragment {
public static class VICCPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -165,26 +175,11 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("hostname"));
bindPreferenceSummaryToValue(findPreference("port"));
bindPreferenceSummaryToValue(findPreference("delay"));
Preference nfcSettings = findPreference("nfcSettings");
nfcSettings.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
Intent viewIntent = new Intent(Settings.ACTION_NFC_SETTINGS);
startActivity(viewIntent);
return true;
}
});
Preference scan = findPreference("scan");
scan.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
new IntentIntegrator(getActivity()).initiateScan();
return true;
}
});
bindPreferenceSummaryToValue(findPreference("activate_helloworld"));
bindPreferenceSummaryToValue(findPreference("activate_openpgp"));
bindPreferenceSummaryToValue(findPreference("activate_oath"));
bindPreferenceSummaryToValue(findPreference("activate_isoapplet"));
bindPreferenceSummaryToValue(findPreference("activate_gidsapplet"));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
@@ -197,51 +192,4 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
}
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
switch(requestCode) {
case IntentIntegrator.REQUEST_CODE:
if (resultCode != RESULT_CANCELED) {
handleScannedURI(Uri.parse(scanResult.getContents()));
}
break;
}
}
private void handleScannedURI(Uri uri) {
try {
String h, p;
h = uri.getHost();
int _p = uri.getPort();
if (_p < 0) {
_p = VPCDWorker.DEFAULT_PORT;
}
p = Integer.toString(_p);
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(this);
SP.edit().putString("hostname", h).apply();
SP.edit().putString("port", p).apply();
} catch (Exception e) {
Snackbar.make(this.getCurrentFocus(), "Could not import configuration", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
}
@Override
public void onResume() {
super.onResume();
Intent intent = getIntent();
// Check to see that the Activity started due to a configuration URI
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri uri = intent.getData();
handleScannedURI(uri);
super.onNewIntent(intent);
}
}
@Override
public void onNewIntent(Intent intent) {
// onResume gets called after this to handle the intent
setIntent(intent);
}
}

View File

@@ -20,9 +20,11 @@
package com.vsmartcard.acardemulator;
import android.content.Intent;
import android.content.SharedPreferences;
import android.nfc.cardemulation.HostApduService;
import android.os.Bundle;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
@@ -64,64 +66,75 @@ public class SimulatorService extends HostApduService {
private void createSimulator() {
String aid, name, extra_install = "", extra_error = "";
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(this);
simulator = new Simulator(new SimulatorRuntime());
name = getResources().getString(R.string.applet_helloworld);
aid = getResources().getString(R.string.aid_helloworld);
try {
simulator.installApplet(AIDUtil.create(aid), HelloWorldApplet.class);
extra_install += "\n" + name + " (AID: " + aid + ")";
} catch (Exception e) {
e.printStackTrace();
extra_error += "\n" + "Could not install " + name + " (AID: " + aid + ")";
if (SP.getBoolean("activate_helloworld", false)) {
name = getResources().getString(R.string.applet_helloworld);
aid = getResources().getString(R.string.aid_helloworld);
try {
simulator.installApplet(AIDUtil.create(aid), HelloWorldApplet.class);
extra_install += "\n" + name + " (AID: " + aid + ")";
} catch (Exception e) {
e.printStackTrace();
extra_error += "\n" + "Could not install " + name + " (AID: " + aid + ")";
}
}
name = getResources().getString(R.string.applet_openpgp);
aid = getResources().getString(R.string.aid_openpgp);
try {
byte[] aid_bytes = Util.hexStringToByteArray(aid);
byte[] inst_params = new byte[aid.length()+1];
inst_params[0] = (byte) aid_bytes.length;
System.arraycopy(aid_bytes, 0, inst_params, 1, aid_bytes.length);
simulator.installApplet(AIDUtil.create(aid), OpenPGPApplet.class, inst_params, (short) 0, (byte) inst_params.length);
extra_install += "\n" + name + " (AID: " + aid + ")";
} catch (Exception e) {
e.printStackTrace();
extra_error += "\n" + "Could not install " + name + " (AID: " + aid + ")";
if (SP.getBoolean("activate_openpgp", false)) {
name = getResources().getString(R.string.applet_openpgp);
aid = getResources().getString(R.string.aid_openpgp);
try {
byte[] aid_bytes = Util.hexStringToByteArray(aid);
byte[] inst_params = new byte[aid.length() + 1];
inst_params[0] = (byte) aid_bytes.length;
System.arraycopy(aid_bytes, 0, inst_params, 1, aid_bytes.length);
simulator.installApplet(AIDUtil.create(aid), OpenPGPApplet.class, inst_params, (short) 0, (byte) inst_params.length);
extra_install += "\n" + name + " (AID: " + aid + ")";
} catch (Exception e) {
e.printStackTrace();
extra_error += "\n" + "Could not install " + name + " (AID: " + aid + ")";
}
}
name = getResources().getString(R.string.applet_oath);
aid = getResources().getString(R.string.aid_oath);
try {
byte[] aid_bytes = Util.hexStringToByteArray(aid);
byte[] inst_params = new byte[aid.length()+1];
inst_params[0] = (byte) aid_bytes.length;
System.arraycopy(aid_bytes, 0, inst_params, 1, aid_bytes.length);
simulator.installApplet(AIDUtil.create(aid), YkneoOath.class, inst_params, (short) 0, (byte) inst_params.length);
extra_install += "\n" + name + " (AID: " + aid + ")";
} catch (Exception e) {
e.printStackTrace();
extra_error += "\n" + "Could not install " + name + " (AID: " + aid + ")";
if (SP.getBoolean("activate_oath", false)) {
name = getResources().getString(R.string.applet_oath);
aid = getResources().getString(R.string.aid_oath);
try {
byte[] aid_bytes = Util.hexStringToByteArray(aid);
byte[] inst_params = new byte[aid.length() + 1];
inst_params[0] = (byte) aid_bytes.length;
System.arraycopy(aid_bytes, 0, inst_params, 1, aid_bytes.length);
simulator.installApplet(AIDUtil.create(aid), YkneoOath.class, inst_params, (short) 0, (byte) inst_params.length);
extra_install += "\n" + name + " (AID: " + aid + ")";
} catch (Exception e) {
e.printStackTrace();
extra_error += "\n" + "Could not install " + name + " (AID: " + aid + ")";
}
}
name = getResources().getString(R.string.applet_isoapplet);
aid = getResources().getString(R.string.aid_isoapplet);
try {
simulator.installApplet(AIDUtil.create(aid), IsoApplet.class);
extra_install += "\n" + name + " (AID: " + aid + ")";
} catch (Exception e) {
e.printStackTrace();
extra_error += "\n" + "Could not install " + name + " (AID: " + aid + ")";
if (SP.getBoolean("activate_isoapplet", false)) {
name = getResources().getString(R.string.applet_isoapplet);
aid = getResources().getString(R.string.aid_isoapplet);
try {
simulator.installApplet(AIDUtil.create(aid), IsoApplet.class);
extra_install += "\n" + name + " (AID: " + aid + ")";
} catch (Exception e) {
e.printStackTrace();
extra_error += "\n" + "Could not install " + name + " (AID: " + aid + ")";
}
}
name = getResources().getString(R.string.applet_gidsapplet);
aid = getResources().getString(R.string.aid_gidsapplet);
try {
simulator.installApplet(AIDUtil.create(aid), GidsApplet.class);
extra_install += "\n" + name + " (AID: " + aid + ")";
} catch (Exception e) {
e.printStackTrace();
extra_error += "\n" + "Could not install " + name + " (AID: " + aid + ")";
if (SP.getBoolean("activate_gidsapplet", false)) {
name = getResources().getString(R.string.applet_gidsapplet);
aid = getResources().getString(R.string.aid_gidsapplet);
try {
simulator.installApplet(AIDUtil.create(aid), GidsApplet.class);
extra_install += "\n" + name + " (AID: " + aid + ")";
} catch (Exception e) {
e.printStackTrace();
extra_error += "\n" + "Could not install " + name + " (AID: " + aid + ")";
}
}
Intent i = new Intent(TAG);

View File

@@ -13,11 +13,6 @@
android:icon="@drawable/ic_action_delete"
app:showAsAction="withText" />
<item android:id="@+id/action_delete"
android:title="@string/action_delete"
android:icon="@drawable/ic_action_delete"
app:showAsAction="withText" />
<item
android:id="@+id/action_settings"
android:orderInCategory="100"

View File

@@ -4,11 +4,36 @@
<PreferenceCategory
android:title="Java Card Emulator">
<Preference
android:title="NFC System Settings"
android:summary="NFC needs to be enabled for emulating a contactless smart card"
android:key="nfcSettings">
</Preference>
<SwitchPreference
android:title="@string/applet_helloworld"
android:switchTextOn="@string/aid_helloworld"
android:key="activate_helloworld"
android:defaultValue="false"
/>
<SwitchPreference
android:title="@string/applet_openpgp"
android:switchTextOn="@string/aid_openpgp"
android:key="activate_openpgp"
android:defaultValue="true"
/>
<SwitchPreference
android:title="@string/applet_oath"
android:switchTextOn="@string/aid_oath"
android:key="activate_oath"
android:defaultValue="true"
/>
<SwitchPreference
android:title="@string/applet_isoapplet"
android:switchTextOn="@string/aid_isoapplet"
android:key="activate_isoapplet"
android:defaultValue="true"
/>
<SwitchPreference
android:title="@string/applet_gidsapplet"
android:switchTextOn="@string/aid_gidsapplet"
android:key="activate_gidsapplet"
android:defaultValue="true"
/>
</PreferenceCategory>