JavaCard

JavaCard est un canevas d’exécution d'application pour carte à puce développé en Java.

Les APIs

 * Python http://pyscard.sourceforge.net/
 * Java Javax.smartcardio
 * Ada http://www.nongnu.org/pcscada/
 * C#
 * C/C++

Les outils

 * GPShell
 * OpenSC
 * MUSCLE

Global Platform
Global Platform est un standard permettant l'installation de cardapplets.

Carte étudiante (ancienne génération)
Présentation de la carte

Script GPShell pour lister les card applets
mode_211 gemXpressoPro enable_trace establish_context card_connect select -AID a000000018434d open_sc -security 3 -keyind 0 -keyver 0 -key 47454d5850524553534f53414d504c45 // Open secure channel get_status -element 20 card_disconnect release_context

Script GPShell pour lister les card applets sélectionnables
mode_211 gemXpressoPro enable_trace establish_context card_connect select -AID a000000018434d open_sc -security 3 -keyind 0 -keyver 0 -key 47454d5850524553534f53414d504c45 // Open secure channel get_status -element 40 card_disconnect release_context

Code LUA pour CardPeek
require('lib.tlv')

AID_UJF  = "#556E69762E554A46" function ui_parse_cstring(node,data) ui.tree_set_value(node,data) if #data>1 then ui.tree_set_alt_value(node,bytes.format("%P",bytes.sub(data,0,#data))) end end function raw_get_data(id) return card.send(bytes.new(8,card.CLA,0xCA,id,00,01,01,00)) end

if card.connect then CARD = card.tree_startup("UJF")

sw,resp = card.select(AID_UJF) if sw==0x9000 then APP = ui.tree_add_node(CARD,"application","Univ.UJF", AID_UJF)

sw,resp = raw_get_data(0x01) if sw==0x9000 then ID = ui.tree_add_node(APP,"id","ID", "01", #resp) ui_parse_cstring(ID,resp) end

sw,resp = raw_get_data(0x02) if sw==0x9000 then VERSION = ui.tree_add_node(APP,"version","VERSION", "02", #resp) ui_parse_cstring(VERSION,resp) end

sw,resp = raw_get_data(0x03) if sw==0x9000 then HOLDER = ui.tree_add_node(APP,"holder","HOLDER", "03", #resp) if resp[0] == 0x30 then ui.tree_set_alt_value(HOLDER, "Student") elseif resp[0] == 0x31 then ui.tree_set_alt_value(HOLDER, "Employee") else ui.tree_set_alt_value(HOLDER, "Unknown") end ui.tree_set_value(HOLDER, resp) end

sw,resp = raw_get_data(0x04) if sw==0x9000 then INE = ui.tree_add_node(APP,"ine","INE", "04", #resp) ui_parse_cstring(INE,resp) end

sw,resp = raw_get_data(0x05) if sw==0x9000 then VS = ui.tree_add_node(APP,"validity start","VALIDITY_START", "05", #resp) ui_parse_cstring(VS,resp) end

sw,resp = raw_get_data(0x06) if sw==0x9000 then VE = ui.tree_add_node(APP,"validity end","VALIDITY_END", "06", #resp) ui_parse_cstring(VE,resp) end --sw,resp = raw_get_data(0x21) --if sw==0x9000 then --	TEST = ui.tree_add_node(APP,"test","TEST", "21", #resp) --	ui_parse_cstring(TEST,resp) --end end

card.disconnect

else ui.question("No card detected",{"OK"}) end

Application Java pour lister quelques informations de la carte
package fr.imag.javacard;

import javax.smartcardio.*; import java.util.*;

public class Main { static class Util { static final String HEXES = "0123456789ABCDEF";

public static String getHex(byte[] raw) { if (raw == null) { return null; }           final StringBuilder hex = new StringBuilder(2 * raw.length); for (final byte b : raw) { hex.append(HEXES.charAt((b & 0xF0) >> 4)) .append(HEXES.charAt((b & 0x0F))); }           return hex.toString; }   }

private static byte[] appletAID = {0x55, 0x6E, 0x69, 0x76, 0x2E, 0x55, 0x4A, 0x46}; private final static byte INS_SELECT = (byte) 0xA4; private final static byte INS_GETDATA = (byte) 0xCA;

static class Command { String description;

Command(String description) { this.description = description; }   }

private static final Map COMMAND_MAP = Collections.unmodifiableMap(new HashMap );

public static CardTerminal selectCardTerminal throws Exception { Scanner in = new Scanner(System.in); TerminalFactory tf = TerminalFactory.getDefault; List ctlist = null; ctlist = tf.terminals.list; if (ctlist.size == 0) { throw new Exception("No reader present"); }       if (ctlist.size == 1) { return ctlist.get(0); }

int index = 0; do {

System.out.println("Readers:"); System.out.println("============================================"); for (CardTerminal ct : ctlist) { System.out.println(index++ + ": " + ct.getName); }           System.out.print("Select a reader:"); index = in.nextInt; } while (index < 0 || index >= ctlist.size);

return ctlist.get(index); }

public static void selectApplication(CardChannel cc) throws Exception { System.out.println("Selecting \"Univ.UJF\" application");

CommandAPDU apdu = new CommandAPDU(               0x00, INS_SELECT,                0x4, 0x0,                appletAID);

ResponseAPDU rapdu = cc.transmit(apdu); if (rapdu.getSW != 0x9000) { throw new Exception("Can't select \"Univ.UJF\" application: "                   + Integer.toHexString(rapdu.getSW)); }

}

public static void main(String[] args) { try { CardTerminal ct = selectCardTerminal; Card c = ct.connect("T=0"); ATR atr = c.getATR; System.out.println("ATR : " + Util.getHex(atr.getBytes)); CardChannel cc = c.getBasicChannel;

selectApplication(cc);

for (int id : COMMAND_MAP.keySet) { Command cmd = COMMAND_MAP.get(id); CommandAPDU apdu = new CommandAPDU(                       0x00, INS_GETDATA,                        (byte) id, 0x00, new byte[]{0x01});

ResponseAPDU rapdu = cc.transmit(apdu); if (rapdu.getSW != 0x9000) { throw new Exception("Can't get data (" + id + "): "                           + Integer.toHexString(rapdu.getSW)); }               System.out.println(cmd.description + ":"                        + new String(rapdu.getData)); }       } catch (Exception e) {

e.printStackTrace; }   } }

MuscleCard pour la carte étudiante
''MuscleCard is an open source project hosted at the M.U.S.C.L.E website. It aims to develop a JavaCard applet and supporting middleware to perform cryptographic operations like signing and encryption in a smart card.'' http://www.openscdp.org/scripts/musclecard/index.html

Compilation
(De préference sous Linux) svn co svn://svn.debian.org/muscleplugins/trunk/MCardApplet Index: common.xml
 * Télécharger les sources de Muscle
 * Télécharger Java Card 2.1.2 Development Kit: lien
 * Changer common.xml en modifiant:

=
====================================================== --- common.xml (revision 297) +++ common.xml (working copy) @@ -62,8 +62,8 @@               executable="${JAVA_BUILD_HOME}/bin/javac" srcdir="${APPLET_SRC}" destdir="${OUTPUT_DIR}" -               target="${VM_TARGET_VERSION}" -               source="${VM_SOURCE_VERSION}"> +               target="1.1" +               source="1.2">  CARD_NAME=JCOP JAVA_BUILD_HOME=PATH_VERS_JDK JC_HOME=PATH_VERS JC212 API_JAR=${JC_HOME}/lib/api21.jar API_EXPORT_FILES=${JC_HOME}/api21_export_files
 * Modifier le fichier JCOP.properties

Installation
Deplacer le fichier CardEdge.cap dans le dossier de GPShell et lancer le script suivant mode_211 gemXpressoPro enable_trace establish_context card_connect select -AID a000000018434d open_sc -security 3 -keyind 0 -keyver 0 -key 47454d5850524553534f53414d504c45 // Open secure channel install -file CardEdge.cap -sdAID A000000018434D00 -nvCodeLimit 4000 card_disconnect release_context

Initialisation de l'applet
Comme spécifié ici, l'applet à besoin d'être initialisé (par exemple avec opensc):

Attention : les version > 0.11.3 de opensc ne fonctionne pas avec cette carte

opensc-tool -s 00:A4:04:00:06:A0:00:00:00:01:01 \ -s B0:2A:00:00:38:08:4D:75:73:63:6C:65:30:30:04:01:08:30:30:30:30:30:30:30:30:08:30:30:30:30:30:30:30:30:05:02:08:30:30:30:30:30:30:30:30:08:30:30:30:30:30:30:30:30:00:00:17:70:00:02:01

Initialisation de PKCS15
pkcs15-init -C --so-pin 00000000 --so-puk 00000000 --pin 00000000 --puk 00000000

Changer le code PIN
pkcs15-tool --change-pin

Générer clés RSA/2048bits
pkcs15-init --generate-key rsa/2048 --auth-id ff

Générer certificat auto-signé
Récupérer le slot du lecteur pkcs11-tool --list-slots Générer avec openssl: openssl engine -t dynamic -pre SO_PATH:/usr/lib/engines/engine_pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:opensc-pkcs11.so req -engine pkcs11 -new -key slot_8-id_45 -keyform engine -x509 -out cert.pem -text Ajouter le certificat dans la carte pkcs15-init --store-certificate cert.pem --auth-id ff --id 45 --format pem