Skip to content
Snippets Groups Projects
Commit 6b3f347b authored by da1l6's avatar da1l6
Browse files

Add Portal Manager to repo

parent ee6a4c1f
No related branches found
No related tags found
No related merge requests found
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="create_run_jar" name="Create Runnable Jar for Project PortalManager">
<!--this file was created by Eclipse Runnable JAR Export Wizard-->
<!--ANT 1.7 is required -->
<target name="create_run_jar">
<jar destfile="/home/philipp/workspace/PortalManager/PortalManager.jar" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="Main"/>
<attribute name="Class-Path" value="."/>
</manifest>
<fileset dir="/home/philipp/workspace/PortalManager/bin"/>
<fileset dir="/home/philipp/workspace/gpj/bin"/>
<zipfileset excludes="META-INF/*.SF" src="/usr/lib/jline/jline.jar"/>
<zipfileset excludes="META-INF/*.SF" src="/usr/share/java/rxtx/RXTXcomm.jar"/>
</jar>
</target>
</project>
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CardTerminals;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;
import net.sourceforge.gpj.cardservices.AID;
import net.sourceforge.gpj.cardservices.AIDRegistry;
import net.sourceforge.gpj.cardservices.AIDRegistryEntry;
import net.sourceforge.gpj.cardservices.CapFile;
import net.sourceforge.gpj.cardservices.GPUtil;
import net.sourceforge.gpj.cardservices.GlobalPlatformService;
import net.sourceforge.gpj.cardservices.exceptions.GPMakeSelectableException;
@SuppressWarnings("restriction")
public class JavaCardProgrammer {
AID securityDomainAID = new AID(new byte[]{(byte)0xA0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00});
byte[][] keys = {GlobalPlatformService.defaultEncKey,
GlobalPlatformService.defaultMacKey,
GlobalPlatformService.defaultKekKey};
private int keySet = 0;
private byte[] appletID = new byte[]{0x23, 0x23, 0x00, 0x42, 0x42};
private CardChannel channel;
private GlobalPlatformService service;
private static final byte CARD_KEY_LENGTH = 64;
public JavaCardProgrammer() throws NoSuchAlgorithmException, CardException{
try{
this.channel = getCardChannel();
this.service = new GlobalPlatformService(securityDomainAID, this.channel);
this.service.addAPDUListener(this.service);
this.service.open();
this.service.setKeys(keySet, keys[0], keys[1], keys[2], GlobalPlatformService.DIVER_NONE);
this.service.openSecureChannel(keySet, 0, GlobalPlatformService.SCP_ANY, GlobalPlatformService.APDU_CLR);
} catch (CardException e) {
if (e.getCause().getMessage().equalsIgnoreCase("SCARD_E_NO_READERS_AVAILABLE")){
System.out.println("No smart card readers found");
}
throw e;
} catch (NoSuchAlgorithmException e) {
if (e.getCause().getMessage().equalsIgnoreCase("SCARD_E_NO_SERVICE")){
System.out.println("No smart card readers found (PC/SC service not running)");
}
throw e;
}
}
private static CardChannel getCardChannel() throws NoSuchAlgorithmException, CardException{
TerminalFactory tf = TerminalFactory.getInstance("PC/SC", null);
CardTerminals terminals = tf.terminals();
System.out.println("Found terminals: " + terminals.list());
for (CardTerminal terminal : terminals.list(CardTerminals.State.ALL)) {
Card c = null;
try {
c = terminal.connect("*");
} catch (CardException e) {
if (e.getCause().getMessage().equalsIgnoreCase("SCARD_E_NO_SMARTCARD")) {
System.err.println("No card in reader " + terminal.getName());
continue;
} else
e.printStackTrace();
}
System.out.println("Found card in terminal: " + terminal.getName());
System.out.println("ATR: " + GPUtil.byteArrayToString(c.getATR().getBytes()));
CardChannel channel = c.getBasicChannel();
return channel;
}
return null;
}
private void uploadCapFile(File capFile) throws GPMakeSelectableException, CardException, IOException{
CapFile cap = null;
try{
cap = new CapFile(new FileInputStream(capFile));
} catch (IOException ex){
System.out.format("Failed to open CAP file '%s': %s", capFile, ex.toString());
throw ex;
}
int loadSize = GlobalPlatformService.defaultLoadSize;
service.loadCapFile(cap, true, false, loadSize, false, false);
AID p = cap.getPackageAID();
for (AID a : cap.getAppletAIDs()) {
service.installAndMakeSelecatable(p, a, null, (byte)0, null, null);
}
}
public void initializeCardApplet(File capFile) throws CardException, IOException{
AID packageAID = new AID(new byte[]{(byte)0xCA, (byte)0xFF, (byte)0xEE, (byte)0xC0, (byte)0x1A});
try{
service.deleteAID(packageAID, true);
} catch (CardException ce) {
System.out.println("Could not delete AID: " + packageAID + ", ignoring.");
// This is when the applet is not there, ignore
}
uploadCapFile(capFile);
}
public List<AID> readAppletList() throws CardException{
List<AID> result = new ArrayList<AID>();
AIDRegistry registry = service.getStatus();
for (AIDRegistryEntry e : registry){
if (e.isApplet()){
result.add(e.getAID());
}
}
return result;
}
public void dumpAppletList() throws CardException{
//List applets
AIDRegistry registry = service.getStatus();
for (AIDRegistryEntry e : registry) {
AID aid = e.getAID();
int numSpaces = (15 - aid.getLength());
String spaces = "";
String spaces2 = "";
for (int i = 0; i < numSpaces; i++) {
spaces = spaces + " ";
spaces2 = spaces2 + " ";
}
System.out.print("AID: "
+ GPUtil.byteArrayToString(aid.getBytes())
+ spaces
+ " "
+ GPUtil.byteArrayToReadableString(aid
.getBytes()) + spaces2);
System.out.format(" %s LC: %d PR: 0x%02X\n", e
.getKind().toShortString(), e
.getLifeCycleState(), e.getPrivileges());
for (AID a : e.getExecutableAIDs()) {
numSpaces = (15 - a.getLength()) * 3;
spaces = "";
for (int i = 0; i < numSpaces; i++)
spaces = spaces + " ";
System.out
.println(" "
+ GPUtil.byteArrayToString(a
.getBytes())
+ spaces
+ " "
+ GPUtil
.byteArrayToReadableString(a
.getBytes()));
}
System.out.println();
}
}
public boolean selectApplet(byte[] aid){
ByteArrayOutputStream bo = new ByteArrayOutputStream();
try {
bo.write(aid);
} catch (IOException e) {
e.printStackTrace();
return false;
}
CommandAPDU delete = new CommandAPDU(0x00, 0xA4, 0x04, 0x00, bo.toByteArray());
ResponseAPDU response;
try {
response = service.transmit(delete);
} catch (IllegalStateException e) {
e.printStackTrace();
return false;
} catch (CardException e) {
e.printStackTrace();
return false;
}
service.notifyExchangedAPDU(delete, response);
short sw = (short) response.getSW();
if (sw != GlobalPlatformService.SW_NO_ERROR) {
System.err.println("Select Applet failed, SW: " + GPUtil.swToString(sw));
return false;
}
return true;
}
public byte[] setCardKey(byte[] key){
if (! selectApplet(appletID)) return null;
ByteArrayOutputStream bo = new ByteArrayOutputStream();
try {
bo.write(key); //BODY
} catch (IOException e) {
e.printStackTrace();
return null;
}
CommandAPDU delete = new CommandAPDU(0x00, 0x01, 0x00, 0x00, bo.toByteArray(), CARD_KEY_LENGTH);
ResponseAPDU response;
try {
response = service.transmit(delete);
} catch (IllegalStateException e) {
e.printStackTrace();
return null;
} catch (CardException e) {
e.printStackTrace();
return null;
}
service.notifyExchangedAPDU(delete, response);
short sw = (short) response.getSW();
if (sw != GlobalPlatformService.SW_NO_ERROR) {
System.err.println("Key set failed, SW: " + GPUtil.swToString(sw));
return null;
}
return response.getData();
}
public byte[] readCardKey(byte[] readKey){
if (! selectApplet(appletID)) return null;
ByteArrayOutputStream bo = new ByteArrayOutputStream();
try {
bo.write(readKey); //BODY
} catch (IOException e) {
e.printStackTrace();
return null;
}
CommandAPDU delete = new CommandAPDU(0x00, 0x04, 0x00, 0x00, bo.toByteArray(), CARD_KEY_LENGTH);
ResponseAPDU response;
try {
response = service.transmit(delete);
} catch (IllegalStateException e) {
e.printStackTrace();
return null;
} catch (CardException e) {
e.printStackTrace();
return null;
}
service.notifyExchangedAPDU(delete, response);
short sw = (short) response.getSW();
if (sw != GlobalPlatformService.SW_NO_ERROR) {
System.err.println("Key read failed, SW: " + GPUtil.swToString(sw));
return null;
}
return response.getData();
}
public boolean clearCardKey(){
if (! selectApplet(appletID)) return false;
CommandAPDU delete = new CommandAPDU(0x00, 0xFF, 0x00, 0x00);
ResponseAPDU response;
try {
response = service.transmit(delete);
} catch (IllegalStateException e) {
e.printStackTrace();
return false;
} catch (CardException e) {
e.printStackTrace();
return false;
}
service.notifyExchangedAPDU(delete, response);
short sw = (short) response.getSW();
if (sw != GlobalPlatformService.SW_NO_ERROR) {
System.err.println("Key clear failed, SW: " + GPUtil.swToString(sw));
return false;
}
return true;
}
public void close() throws CardException{
channel.close();
}
}
import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import javax.smartcardio.CardException;
import net.sourceforge.gpj.cardservices.AID;
import net.sourceforge.gpj.cardservices.GPUtil;
@SuppressWarnings("restriction")
public class Main {
public static void main(String args[]) throws NoSuchAlgorithmException, CardException, IOException{
int i = 0;
JavaCardProgrammer card = null;
//JavaCardProgrammer card = new JavaCardProgrammer();
//writeAppletList(card.readAppletList());
while(i < args.length){
if (args[i].equals("--help")){
help();
} else if (args[i].equals("--setupcard")){
if (card == null) card = new JavaCardProgrammer();
card.initializeCardApplet(new File("./applet.cap"));
writeAppletList(card.readAppletList());
} else if (args[i].equals("--updatecard")){
i++;
if (args.length < i-1) {help(); System.exit(1);}
if (args[i].length() != 128 && args[i].length() != 255) {help(); System.exit(1);}
byte[] readkey = GPUtil.stringToByteArray(args[1]);
if (card == null) card = new JavaCardProgrammer();
//Backup card key
byte[] currentKey = card.readCardKey(readkey);
if (currentKey == null) return;
//Reset card
card.close();
card = new JavaCardProgrammer();
//Update Applet
card.initializeCardApplet(new File("./applet.cap"));
byte[] readKey = card.setCardKey(currentKey);
if (readKey != null){
System.out.println("Applet updated successfully!");
System.out.println("To read the (current) card key or update the card use the read key:");
System.out.println(GPUtil.byteArrayToString(readKey).replace(" ", ""));
System.out.println("");
}
} else if (args[i].equals("--clearkey")){
if (card == null) card = new JavaCardProgrammer();
if (card.clearCardKey()){
System.out.println("Card key cleared successfully!");
System.out.println("");
}
} else if (args[i].equals("--setkey")){
if (card == null) card = new JavaCardProgrammer();
i++;
if (args.length < i-1) {help(); System.exit(1);}
if (args[i].length() != 128) {help(); System.exit(1);}
byte[] key = GPUtil.stringToByteArray(args[1]);
byte[] readKey = card.setCardKey(key);
if (readKey != null){
System.out.println("Initial key written successfully!");
System.out.println("To read the (current) card key or update the card use the read key:");
System.out.println(GPUtil.byteArrayToString(readKey).replace(" ", ""));
System.out.println("");
}
} else if (args[i].equals("--readkey")){
if (card == null) card = new JavaCardProgrammer();
i++;
if (args.length < i-1) {help(); System.exit(1);}
if (args[i].length() != 128 && args[i].length() != 255) {help(); System.exit(1);}
byte[] readkey = GPUtil.stringToByteArray(args[1]);
byte[] currentKey = card.readCardKey(readkey);
if (currentKey != null){
System.out.println("Current Key read successfully!");
System.out.println(GPUtil.byteArrayToString(currentKey).replace(" ", ""));
System.out.println("");
}
} else if (args[i].equals("--console")){
Integer keyslot = 0;
if (args.length >= i && !args[i].startsWith("--")){
keyslot = Integer.parseInt(args[i]);
i++;
}
try {
PortalControlInterface portal = new PortalControlInterface();
portal.shell();
portal.close();
} catch (PortalControlInterface.PortalControlNotFoundException ex){
System.out.println("Portal Control not found");
}
} else {
help();
System.exit(1);
}
i++;
}
System.out.println("Bye.");
}
private static void writeAppletList(List<AID> list){
System.out.println(list.size() + " applet(s) installed on card:");
for (AID a : list){
System.out.println("Applet ID: " + a.toString());
}
}
private static void help(){
System.out.println("Usage: ");
System.out.println("--setupcard : Install the Portal Applet on a Javacard. Any auth key on the card will be cleared.");
System.out.println("--setkey <key> : Set the Portal auth key on the card (can only be used once). The key is given as 128 hex digits (64 bytes)");
System.out.println("--updatecard <rkey> : Update the Portal Applet on a Javacard. The auth key on the card will be backed up. You need to supply the read key that --setkey returned.");
System.out.println("--readkey <rkey> : Read the auth key on the card. You need to supply the read key that --setkey returned.");
System.out.println("--clearkey : Delete the Portal auth key from the card (only works on cards with debug commands enabled).");
}
}
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;
import jline.*;
@SuppressWarnings("restriction")
public class PortalControlInterface {
private final Charset CHARSET = Charset.forName("UTF-8");
private final String PORTAL_PROBE_COMMAND = "\n";
private final String PORTAL_PROBE_IDENTIFIER = "Mezu Login:";
private final long PROBE_TIMEOUT = 300;
private final String PORTAL_PROMPT = "> ";
private boolean login = false;
private SerialPort port;
public PortalControlInterface() throws PortalControlNotFoundException{
java.util.Enumeration<CommPortIdentifier> portEnum = CommPortIdentifier.getPortIdentifiers();
while (portEnum.hasMoreElements()){
CommPortIdentifier portIdentifier = portEnum.nextElement();
if (portIdentifier.getPortType() == CommPortIdentifier.PORT_SERIAL){
System.out.print("Found Serial Port: " + portIdentifier.getName());
try{
port = openPort(portIdentifier);
try {
System.out.print(" Probing...");
if (probePort(port)){
System.out.println(" PortalControl found!");
break;
} else {
System.out.println(" negative.");
port.close();
port = null;
}
} catch (IOException ex) {
System.out.println(" Read failed: " + ex.toString());
}
} catch (IOException ex) {
System.out.println(" IO Error: " + ex.toString());
} catch (UnsupportedCommOperationException ex){
System.out.println(" Failed to configure: " + ex.toString());
} catch (PortInUseException ex){
System.out.println(" In use, skipping");
}
}
}
if (port == null) throw new PortalControlNotFoundException();
}
private SerialPort openPort(CommPortIdentifier portIdentifier) throws PortInUseException, UnsupportedCommOperationException, IOException{
SerialPort port = (SerialPort)portIdentifier.open(this.getClass().getName(), 2000);
try {
port.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException ex){
port.close();
throw ex;
}
return port;
}
private boolean probePort(SerialPort port) throws IOException{
while (port.getInputStream().available() != 0) port.getInputStream().read(); //trash buffer
port.getOutputStream().write(PORTAL_PROBE_COMMAND.getBytes(CHARSET));
Integer status = waitString(new String[]{PORTAL_PROBE_IDENTIFIER , PORTAL_PROMPT}, PROBE_TIMEOUT);
this.login = (status != null && 1 == status);
return status != null;
}
private void writeLine(String line) throws IOException{
port.getOutputStream().write(line.getBytes(CHARSET));
port.getOutputStream().write('\n');
}
/* private String readLine() throws IOException{
StringWriter writer = new StringWriter();
int c = 0;
while ((c = this.reader.read()) != '\n'){
writer.write(c);
}
return writer.toString();
}*/
/**
* Waits for any of the given strings to appear in the input from the
* serial port.
* @param strings
* @param timeout
* @return index of the string found, null on timeout
* @throws IOException
*/
private Integer waitString(String[] strings, long timeout) throws IOException{
InputStreamReader reader = new InputStreamReader(port.getInputStream());
StringWriter writer = new StringWriter();
char[] buffer = new char[1024];
long tStart = System.currentTimeMillis();
while ((System.currentTimeMillis() - tStart) < timeout){
if (!reader.ready()){
try { Thread.sleep(10); } catch (InterruptedException e) {}
} else {
int count = reader.read(buffer);
writer.write(buffer, 0, count);
for (int i = 0; i < strings.length; i++){
if (writer.toString().contains(strings[i])){
return i;
}
}
}
}
return null;
}
public void shell() throws IOException{
final ConsoleReader console = new ConsoleReader();
final Pattern newKeyPattern = Pattern.compile("New key: ([0-9A-F]{128})", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
Matcher m = newKeyPattern.matcher("fdsfdf\nNew key: 6F7AE2ED44007E0C25015FC5BFD4B598F2AD06BF817227A21CFACBC054927C6EA2AF3BBE12704CA575FA27035B413AB1D2F59C46E9320E5505FE83C0E011084D\nfdsfds");
m.matches();
Thread readThread = new Thread(){
public void run(){
InputStreamReader input;
char[] buffer = new char[512];
StringBuffer sb = new StringBuffer(1024);
try {
input = new InputStreamReader(port.getInputStream());
while (true){
int len = input.read(buffer);
sb.append(buffer, 0, len);
int lineend = sb.indexOf("\n");
if (lineend != -1) sb.replace(0, lineend+1, "");
if (sb.lastIndexOf("logout\n") != -1) break;
Matcher m = newKeyPattern.matcher(sb.toString());
if (m.matches()){
System.out.print("k:" + m.group(1));
sb = new StringBuffer(1024);
}
System.out.print(new String(buffer,0,len));
System.out.flush();
}
System.out.println("Exited");
} catch (IOException e) {
e.printStackTrace();
System.exit(2);
}
}
};
readThread.start();
writeLine("");
while(readThread.isAlive()){
int c = console.readVirtualKey();
port.getOutputStream().write(c);
}
System.out.println("Shell Exited");
}
public void close(){
if (login){
try {
writeLine("logout");
} catch (IOException e) {
e.printStackTrace();
}
}
port.close();
port = null;
}
@SuppressWarnings("serial")
static class PortalControlNotFoundException extends Exception{
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment