add installApplet()

This commit is contained in:
Dmitry Novotochinov 2018-11-28 14:54:31 +03:00
parent 989ffc140d
commit 97b95a3a6f
No known key found for this signature in database
GPG Key ID: 43D1DAF5AD39C927
6 changed files with 139 additions and 1 deletions

View File

@ -39,5 +39,5 @@ repositories {
dependencies {
implementation 'com.facebook.react:react-native:+'
implementation 'com.github.status-im:hardwallet-lite-android:145fe4b'
implementation 'com.github.status-im:hardwallet-lite-android:735ccd8'
}

Binary file not shown.

View File

@ -0,0 +1,29 @@
package im.status.ethereum.keycard;
public class HexUtils {
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len/2];
for(int i = 0; i < len; i+=2){
data[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
}
return data;
}
final protected static char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
public static String byteArrayToHexString(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
int v;
for(int j=0; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v>>>4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}

View File

@ -0,0 +1,92 @@
package im.status.ethereum.keycard;
import android.content.res.AssetManager;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import im.status.hardwallet_lite_android.globalplatform.Load;
import im.status.hardwallet_lite_android.io.APDUException;
import im.status.hardwallet_lite_android.io.APDUResponse;
import im.status.hardwallet_lite_android.io.CardChannel;
import im.status.hardwallet_lite_android.globalplatform.ApplicationID;
import im.status.hardwallet_lite_android.globalplatform.GlobalPlatformCommandSet;
public class Installer {
private CardChannel plainChannel;
private AssetManager assets;
private String capPath;
private static final String TAG = "SmartCardInstaller";
static final byte[] PACKAGE_AID = HexUtils.hexStringToByteArray("53746174757357616C6C6574");
static final byte[] WALLET_AID = HexUtils.hexStringToByteArray("53746174757357616C6C6574417070");
static final byte[] NDEF_APPLET_AID = HexUtils.hexStringToByteArray("53746174757357616C6C65744E4643");
static final byte[] NDEF_INSTANCE_AID = HexUtils.hexStringToByteArray("D2760000850101");
private GlobalPlatformCommandSet cmdSet;
public Installer(CardChannel channel, AssetManager assets, String capPath) {
this.plainChannel = channel;
this.assets = assets;
this.capPath = capPath;
}
public void start() throws IOException, APDUException, NoSuchAlgorithmException, InvalidKeySpecException {
Log.i(TAG, "installation started...");
long startTime = System.currentTimeMillis();
Log.i(TAG, "auto select sdaid...");
cmdSet = new GlobalPlatformCommandSet(this.plainChannel);
ApplicationID sdaid = new ApplicationID(cmdSet.select().checkOK().getData());
SecureRandom random = new SecureRandom();
byte hostChallenge[] = new byte[8];
random.nextBytes(hostChallenge);
Log.i(TAG, "initialize update...");
cmdSet.initializeUpdate(hostChallenge).checkOK();
Log.i(TAG, "external authenticate...");
cmdSet.externalAuthenticate(hostChallenge).checkOK();
Log.i(TAG, "delete NDEF instance AID...");
cmdSet.delete(NDEF_INSTANCE_AID).checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND);
Log.i(TAG, "delete wallet AID...");
cmdSet.delete(WALLET_AID).checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND);
Log.i(TAG, "delete package AID...");
cmdSet.delete(PACKAGE_AID).checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND);
Log.i(TAG, "install for load...");
cmdSet.installForLoad(PACKAGE_AID, sdaid.getAID()).checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND);
InputStream in = this.assets.open(this.capPath);
Load load = new Load(in);
java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\\A");
Log.i(TAG, "cap file " + s.toString().length());
byte[] block;
int steps = load.blocksCount();
while((block = load.nextDataBlock()) != null) {
int count = load.getCount() - 1;
Log.i(TAG, String.format("load %d/%d...", count + 1, steps));
cmdSet.load(block, count, load.hasMore()).checkOK();
}
Log.i(TAG, "install for install ndef...");
byte[] params = HexUtils.hexStringToByteArray("0024d40f12616e64726f69642e636f6d3a706b67696d2e7374617475732e657468657265756d");
cmdSet.installForInstall(PACKAGE_AID, NDEF_APPLET_AID, NDEF_INSTANCE_AID, params).checkOK();
Log.i(TAG, "install for install wallet...");
cmdSet.installForInstall(PACKAGE_AID, WALLET_AID, WALLET_AID, new byte[0]).checkOK();
long duration = System.currentTimeMillis() - startTime;
Log.i(TAG, String.format("\n\ninstallation completed in %d seconds", duration / 1000));
}
}

View File

@ -180,4 +180,15 @@ public class RNStatusKeycardModule extends ReactContextBaseJavaModule implements
}
}
@ReactMethod
public void installApplet(Promise promise) {
try {
smartCard.installApplet(this.reactContext.getAssets(), "wallet.cap");
promise.resolve(true);
} catch (IOException | APDUException | NoSuchAlgorithmException | InvalidKeySpecException e) {
Log.d(TAG, e.getMessage());
promise.reject(e);
}
}
}

View File

@ -1,6 +1,7 @@
package im.status.ethereum.keycard;
import android.app.Activity;
import android.content.res.AssetManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -343,4 +344,9 @@ public class SmartCard extends BroadcastReceiver implements CardListener {
return data;
}
public void installApplet(AssetManager assets, String capPath) throws IOException, APDUException, NoSuchAlgorithmException, InvalidKeySpecException {
Installer installer = new Installer(this.cardChannel, assets, capPath);
installer.start();
}
}