Skip to content

Commit

Permalink
PluginTerminal samle: seperation of code for terminal and mock card
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] committed May 29, 2012
1 parent 8adb024 commit b8013f2
Showing 1 changed file with 75 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -1,34 +1,67 @@
package org.simalliance.openmobileapi.service.terminals.SamplePluginTerminal;

import java.util.Arrays;
import java.util.NoSuchElementException;

import android.content.Context;
import android.util.Log;

import java.util.MissingResourceException;
import java.util.NoSuchElementException;

public class DummyTerminal {

private static final String LOG_TAG = "SamplePluginTerminal";

static final byte[] AID_ACA = {(byte)0xd2, (byte)0x76, (byte)0x00, (byte)0x01, (byte)0x18, (byte)0xaa, (byte)0xff, (byte)0xff, (byte)0x49, (byte)0x10, (byte)0x48, (byte)0x89, (byte)0x01};

private int channelNr = 0x00;


private static String bytesToString(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for (byte b : bytes) {
sb.append(String.format("%02x ", b & 0xFF));
}
return sb.toString();
}
private static final String LOG_TAG = DummyTerminal.class.getSimpleName();

/**
* constructs byte array for C-APDU "MANAGE_CHANNEL (open)"
* @return C-APDU
*/
static byte[] commandManageChannel_open() {
return new byte[]{(byte)0x00, (byte)0x70, (byte)0x00, (byte)0x00, (byte)0x01};
}

/**
* constructs byte array for C-APDU "MANNAGE_CHANNEL (close)"
* @param iChannel
* @return C-APDU
*/
static byte[] commandManageChannel_close(int iChannel) {
byte cla = (byte)((iChannel < 4) ? iChannel : 0x40 | (iChannel - 4));
return new byte[]{cla, (byte)0x70, (byte)0x80, (byte)iChannel, (byte)0x00};
}

/**
* constructs byte array for C-APDU "SELECT"
* @param iChannel
* @param aid
* @return C-APDU
*/
static byte[] commandSelect(int iChannel, byte[] aid) {
byte cla = (byte)((iChannel < 4) ? iChannel : 0x40 | (iChannel - 4));
byte[] command = new byte[5 + aid.length];
System.arraycopy(new byte[]{cla, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)aid.length}, 0, command, 0, 5);
System.arraycopy(aid, 0, command, 5, aid.length);
return command;
}

MockCard mockCard;

/**
* @param context
*/
public DummyTerminal(Context context) {
// DummyTerminal contains a MockCard, that simulates a smart card:
mockCard = new MockCard();
// MockCard contains following applet:
mockCard.installApplet(new byte[]{(byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x00},
new Applet(){
@Override
public byte[] process(byte[] command) throws Throwable {
// all this applet does is answer any C-APDU with this R-APDU:
return new byte[] { (byte)0xDE, (byte)0xAD, (byte)0xC0, (byte)0xDE, (byte)(command[0] & 0x03)};
}
});
}

public byte[] getAtr() {
return new byte[] { 0x3B, 0x00 };
return mockCard.getATR();
}

public String getName() {
Expand All @@ -47,30 +80,43 @@ public void internalDisconnect() {
Log.v(LOG_TAG, "internalDisconnect");
}

byte[] selectResponse;

public byte[] getSelectResponse() {
return new byte[] { 0x01, 0x03, 0x03, 0x07 };
return selectResponse;
}

public byte[] internalTransmit(byte[] command) {
Log.v(LOG_TAG, "internalTransmit: " + bytesToString(command));
return new byte[] { (byte)0xDE, (byte)0xAD, (byte)0xC0, (byte)0xDE, (byte)(command[0] & 0x03), (byte)0x90, (byte)0x00 };
Log.v(LOG_TAG, "internalTransmit: " + MockCard.bytesToHexString(command));
return mockCard.process(command);
}

public int internalOpenLogicalChannel() {
Log.v(LOG_TAG, "internalOpenLogicalChannel: default applet");
return ++channelNr;
byte[] response = mockCard.process(commandManageChannel_open());
if (response.length != 3 || response[1] != (byte)0x90 || response[2] != (byte)0x00) {
throw new MissingResourceException("Failed to open channel", "", "");
}
return response[0];
}

public int internalOpenLogicalChannel(byte[] aid) {
Log.v(LOG_TAG, "internalOpenLogicalChannel: " + bytesToString(aid));
if (Arrays.equals(aid, AID_ACA))
throw new NoSuchElementException("ACA not available");
return ++channelNr;
Log.v(LOG_TAG, "internalOpenLogicalChannel: AID = " + MockCard.bytesToHexString(aid));
int iChannel;
iChannel = internalOpenLogicalChannel();
byte[] response = mockCard.process(commandSelect(iChannel, aid));
selectResponse = response;
if (response.length < 2 || response[response.length - 2] != (byte)0x90 || response[response.length - 1] != (byte)0x00) {
mockCard.process(commandManageChannel_close(iChannel));
throw new NoSuchElementException("Failed to select AID");
}
return iChannel;
}

public void internalCloseLogicalChannel(int iChannel) {
Log.v(LOG_TAG, "internalCloseLogicalChannel: " + iChannel);
if (iChannel > 0)
--channelNr;
if (iChannel < 0) return;
mockCard.process(commandManageChannel_close(iChannel));
}

}

0 comments on commit b8013f2

Please sign in to comment.