Le développement de nouveaux composants plus puissants va permettre l'installation de plusieurs applications sur une même carte à puce. Elles pourront contenir des données aussi disparates que de la monnaie électronique, des crédits téléphoniques ou des informations médicales utiles en cas d'accident. L'apparition d'un nouveau langage de haut niveau adapté aux standards 7816 de la carte à puce, Java Card (sous-ensemble de Java), offre de nouvelles possibilités en matière de portabilité et de sécurité. Nous étudions la sémantique du langage Java Card afin de construire un environnement de développement et de vérification de programmes Java Card.
Mots-clés: Java Card, applets, carte à puce intelligente, sémantique, environnement graphique
Sommaire
1. Introduction *
2. Etat de l'art *
2.1 Les Sémantiques Formelles de Java
*2.2 Le checker Java Card
*2.3 Les outils commerciaux adaptésà Java Card
*3. Construction d'un environnement Java Card *
4. Discussion et travaux futurs *
5. Conclusion *
Remerciements
Je tiens à remercier Isabelle Attali et Denis Caromel pour m'avoir accueillie pour ce stage. Leurs conseils, encouragements, aide, patience me furent d'une grande utilité durant ces quatre mois.
Je voudrais aussi remercier toutes les personnes du projet CROAP pour m'avoir si rapidement adoptée et pour m'avoir aidée à "vaincre Centaur ".
Je tiens à remercier plus particulièrement :
Je tiens à remercier aussi Claire Loiseaux et Dominique Bolignano de Dyade (GIE Bull/INRIA) pour avoir répondu si gentiment à mes questions sur Java Card.
L'informatique a pris une place prépondérante dans notre vie de tous les jours durant ces vingt dernières années. Elle est utilisée partout : pour la gestion des capteurs dans nos voitures, pour aider les chirurgiens à opérer, pour les télécommunications, pour retirer de l'argent d'un guichet automatique avec une carte à puce, etc. Cette formidable évolution fut possible grâce au développement des technologies (aux progrès fulgurants de l'électronique) qui a permis, en autre, la réduction de la taille des éléments de stockage d'information (les transistors) dans les composants. Cette miniaturisation a permis d'augmenter la taille de la mémoire d'un composant et donc de passer d'une programmation proche de la machine (assembleur) à une programmation haut niveau avec, par exemple, des langages à objet (Java, C++, etc.).
Ce phénomène est en train d'apparaître dans le domaine très fermé des cartes à puces intelligentes (les smart cards) très populaires en Europe et au Japon mais encore peu développées aux Etats-Unis où on préfère utiliser les cartes magnétiques. Mais tout cela est en train de changer grâce à l'apparition de nouvelles puces plus puissantes permettant d'installer plusieurs applications sur le même composant. Par exemple, elles pourront contenir des données aussi disparates que de la monnaie électronique, des crédits téléphoniques, des informations médicales utiles en cas d'accident, etc. Il y a un intérêt grandissant pour les cartes à puce (la demande augmente de 40% par an [DRE98]). En effet, ces possibilités d'authentification et de stockage d'information permettent des accès sécurisés à l'Internet. Gemplus (un fabriquant de cartes à puce) estime qu'il y en aurait environ 3 000 millions à la fin de 2001.
Présentation des cartes à puce
Il y a deux sortes de cartes à puce : la carte à mémoire servant seulement au stockage d'information utilisant la logique pour accéder à l'information (ex : une carte de téléphone avec 50 crédits) et la carte à puce intelligente (celle qui nous intéresse dans ce rapport) qui est un mini-ordinateur. Elle contient un micro-contrôleur 8 bits (les plus connus étant les composants 6805 de Motorola et le 8051 d'Intel) qui a des propriétés de sécurité. Sa mémoire est composée de RAM où sont stockées les données temporaires (i.e. ces données sont perdues lors de la perte de courant), d'EEPROM où sont stockées les données sur le possesseur de la carte (ex : le numéro de compte bancaire, la clé privée d'encryption, etc.) et de la ROM où résident les programmes de la carte.
Le protocole ISO 7816 définit un ensemble de standards internationaux pour les cartes à circuit intégré avec contacts que doivent suivre les programmeurs d'application pour que les opérations soient possibles sur n'importe quel terminal (le lecteur de carte ou CAD : Card Acceptance Device) dans le monde entier qui fournit le pouvoir électrique à la carte. La structure de communication utilisée entre le CAD et la carte est un format standardisé de donnée : une APDU (Application Protocol Data Unit) qui est un message de commande du CAD vers la carte ou un message de réponse de la carte vers le CAD (cf. Figure 1 ).
Figure 1
Format des APDUsCla indique la classe de la commande, ins le code de l'instruction à faire, p1 et p2 sont les paramètres de la commande, lc est la longueur en octet des données, le est le nombre maximum des octets attendus pour la donnés de l'APDU de réponse. Sw1 et sw2 indiquent comment s'est passée la commande (le mot d'état).
En mars 1996, un petit groupe d'ingénieurs de Schumberger au Texas ont souhaité simplifier la programmation des cartes à puces tout en préservant la sécurité des données [GUT98]. Presque immédiatement, ils ont analysé que ce problème avait déjà été posé par le chargement de code sur le World Wide Web. La solution avait été Java. Malheureusement vu la taille de la mémoire disponible sur une carte à puce seulement un sous-ensemble de Java pouvait être utilisé (la taille de la JVM (Java Virtual Machine) et du système de runtime ne devant pas dépasser 12 kø). C'est ainsi qu'est né Java Card, le premier langage à objets adapté aux cartes à puces. Schlumberger et Gemplus sont les co-fondateurs du JavaCard Forum qui recommande des spécifications à JavaSoft (la division de Sun à qui appartient Java Card) en vue d'obtenir un standardisation du langage et il s'occupe aussi de la promotion des APIs (Application Programming Interface) Java Card pour qu'il devienne la plate-forme standard de développement des applications pour les smart cards
Java présente trois avantages majeurs pour la programmation des cartes à puce :
Présentation de Java Card
C'est un sous-ensemble de Java adapté aux cartes à puce. Sa syntaxe est légèrement moins riche à cause de la faible capacité mémoire d'une puce. C'est pourquoi, les utilisations de tableaux multidimensionnels, des types float, double ou long ou des modifiers transient et volatile ne sont pas autorisées [SUN1] ainsi que les threads. Ses APIs sont basées sur les standards 7816 et ont été adoptées par 95% des constructeurs de cartes à puce. Les applications Java Card sont appelées des applets [SUN2], identifiées uniquement par leur AID (Application IDentifier) isolées entre elles par des applets firewall. Elles possèdent 5 méthodes : la méthode install() qui permet de créer l'applet, la methode register() qui permet d'enregistrer l'applet au JCRE (Java Card Runtime Environment), les méthodes select() et deselect() qui permettent la sélection ou la desélection d'une applet et la méthode process() qui traite les APDUs de commande. Plusieurs applets pourront cohabiter sur une carte même si elles appartiennent à des fabriquants différents. Les applets d'une carte sont gérées par le JCRE. Les minima requis pour faire tourner un programme Java Card sont 16kø de ROM, 8kø d'EEPROM et 256ø de RAM [CHE98].
Java Card, bien qu'il soit un sous-ensemble de Java, possède des mécanismes spéciaux liés aux spécificités des cartes à puce. Ainsi il a 2 types d'objets : les objets transients (i.e. stockés en RAM qui perdront leurs valeurs lors du retrait de la carte, d'une coupure de courant, de la desélection de l'applet ou après chaque transaction) et les objets persistents stockés en EEPROM. Java Card permet de garantir l'atomicité des transactions. Il permet aussi de partager des objets entre applets sous certaines conditions. Les lignes de sécurité sont implémentées par la machine virtuelle.
Le gros avantage de Java Card est la possibilité de charger dynamiquement, n'importe quand, une nouvelle applet sur la carte. Cela signifie que le code des applets pourra être remis à jour.
Présentation du problème
L'usage de Java Card au lieu des assembleurs propriétaires utilisés actuellement pour coder des applications pour les cartes à puce permettra de réduire énormément le temps de réalisation. De plus il est possible d'utiliser les environnements de développement existants pour Java (par exemple Symantec Visual Café, Microsoft Visual J++, etc.) pour Java Card.
Malheureusement les erreurs de programmation ne sont pas exclues même avec un langage de haut niveau. C'est pourquoi les développeurs ont besoin d'outils pour les aider à vérifier le comportement de leurs applets Java Card avant leur mise en mémoire dans une carte à puce.
L'idéal serait de pouvoir vérifier le fonctionnement des applets sur une station de travail. Lors de cette simulation, on pourrait visualiser les objets, les attributs contenus par la carte, les APDUs transmises. Le but de notre étude est donc de construire un environnement basé sur la sémantique pour tester le fonctionnement d'applications Java Card.
Nous nous appuyons sur deux applets Java Card : PurseFr et FrequentFlyer qui permettent d'ajouter et retirer respectivement des francs et des miles.
La section 2 présente un état de l'art sur la sémantique et les outils existants. La section 3 explique la construction de notre environnement de simulation d'application. La section 4 présente les travaux futurs.
Il existe de nombreux travaux liés à la sémantique et à la sécurité de Java et plus récemment de Java Card. C'est pourquoi cette étude commence par une présentation des sémantiques formelles de Java (dont celle utilisée pour notre travail). De plus, il est nécessaire pour juger de la pertinence de notre travail de connaître les outils existants adaptés à Java Card i.e. le vérificateur statique (appelé checker) fourni par Sun et les outils commerciaux Odyssey-Lab de Bull, GemXpresso RAD de Gemplus et Cyberflex de Schlumberger.
Un important domaine de recherche est la preuve de la sûreté des types en Java. Drossopoulou, Einsenbach [DRO98] et Syme [SYM97] spécifient la sémantique de différents sous-ensembles Java séquentiels (incluants les types primitifs, les classes, l'héritage, les variables et méthodes d'instances, les interfaces, la surcharge des variables d'instance, la création d'objet Java, les tableaux et les exceptions) pour prouver que l'exécution d'un programme préserve les types. En rapport avec leurs travaux, Nipkow et Oheimb [NIP98] définissent et prouvent des propriétés sur leur sous-ensemble Java Light avec le prouveur de théorème Isabelle/HOL.
Börger et Schulte [BOR98a], pour leur part, définissent une sémantique dynamique par empilement de différents sous-ensembles Java.
Une autre approche pour prouver la sûreté des types est de travailler au niveau du byte code de la JVM. Qian [QIA98] a défini une sémantique pour un sous-ensemble d'instructions de la JVM. Les comportements de ces instructions dans la mémoire lors du runtime sont décrites comme des transitions d'états. Son but comme Börger et Schulte [BOR98b] est de prouver le bon fonctionnement du byte code lors de son exécution.
Joachim Posegga et Harald Vogt [POS98] définissent, pour leur part, un système à état fini pour la vérification de byte code pour Java Card. Eva Rose [ROS97] a elle aussi spécifiée un sous ensemble Java, JavaOb, assez restreint pour modéliser Java Card. Puis elle a définit une traduction de JavaOb vers un sous-ensemble de la JVM, JVMOb dont la sémantique statique correspond au vérificateur Java de byte code. Ainsi elle a obtenu une formalisation de son sous-ensemble et peut proposer une procédure de vérification de la sûreté du byte code.
Cette sémantique [RUS97], [ATT97] (spécifiée par Marjorie Russo, doctorante du projet CROAP) est celle sur laquelle notre sémantique Java Card est basée (en modifiant le moins possible sa syntaxe et sa sémantique pour les adapter à Java Card).
Pour cette description formelle du langage, une sémantique big-step est adoptée pour l'héritage et les caractéristiques objets alors que le multithreading est spécifié par une sémantique small-step (ou opérationnelle). L'ensemble de cette spécification représente environ 400 règles Typol.
Cette sémantique naturelle spécifie un large sous-ensemble Java et est exécutable dans le système Centaur.
Le système Centaur est un outil de génération d'environnements de langages de programmation développé par le projet CROAP. Il permet de spécifier formellement des langages aussi différents qu'Eiffel, Esterel ou ASN1.
Pour spécifier un langage avec cet outil, il faut tout d'abord définir sa syntaxe concrète et sa syntaxe abstraite à l'aide du langage Metal. Cette première étape permet de générer un analyseur syntaxique (parseur). Son rôle est d'analyser syntaxiquement un programme et de créer son arbre de syntaxe abstraite. La deuxième étape est la spécification de règles d'affichage en Ppml pour générer un pretty-printer. Enfin la dernière étape est la spécification de la sémantique du langage à l'aide de règles Typol. De cette sémantique, on pourra constituer des outils d'aide à la programmation (comme par exemple un interprète ou vérificateur de type). La Figure 2 permet d'avoir une vue simplifiée du système.
Figure 2
Environnement de programmation construit avec CentaurLa Syntaxe
Le langage Metal permet de spécifier la grammaire de langages de programmation. Il se décompose en 2 parties :
Quand un fichier (contenant un programme du langage décrit) est lu sous Centaur, le parseur associé au langage utilisé dans le fichier construit l'arbre de syntaxe abstraite (cf. Figure 3 ) représentant le programme. Cet arbre sert de base pour faire de l'édition structurée, de la sémantique statique ou dynamique. En cas d'erreur syntaxique, l'arbre n'est pas généré et un message d'erreur apparaît. Le Tableau 1 présente des exemples de spécification de syntaxe concrète et abstraite écrits en Metal.
Exemple de syntaxe concrète en Metal: <VariableDeclaratorId>::=<Identifier> ; <Identifier> <VariableDeclaratorId>::=<Identifier>"[""]"; array(<Identifier>) (1) <Identifier> : := %ID ; identifier-atom(%ID) ;
Exemple de syntaxe abstraite en Metal: VariableDeclaratorId ::= array Identifier ; Identifier ::= identifier class ; Identifier -> implemented as IDENTIFIER ; Array -> Identifier ; (2) Class -> implemented as SINGLETON ; |
Explications Le non terminal VariableDeclaratorId est utilisé lors de la déclaration d'une variable. Il décrit les variables de type tableau. Int varT[] ; Dans ce cas varT est analysé par la règle (1) de VariableDeclaratorId. L'arbre construit aura pour l'opérateur array et pour feuille un identifier i.e. dans ce cas varT En effet, comme cette règle s'applique, la fonction de construction d'arbre array(<Identifier>) est appelée. Elle correspond à un opérateur de syntaxe abstraite (2). |
Tableau 1 Exemples de spécification de syntaxe écrits en Metal
Il faut spécifier un pretty-printer en langage Ppml pour qu'un arbre de syntaxe abstraite du langage soit visible dans une représentation textuelle (cf. Figure 4).
i
Figure 3 Arbre de syntaxe abstraite du célèbre programme HelloWorld.java (présentation arborescente)
i
Figure 4 Arbre de syntaxe abstraite du célèbre programme HelloWorld.java (présentation textuelle Java)
La Sémantique
Les sémantiques statiques et dynamiques doivent être spécifiées en Typol, qui est un langage dédié à la sémantique naturelle. C'est un langage déclaratif, logique, typé, manipulant la syntaxe abstraite du langage. Il fournit des mécanismes de filtrage, d'unification et de retour arrière.
Les règles peuvent être regroupées dans des sets
Le Tableau 2 présente un exemple de règle écrite en Typol.
A partir des spécifications décrites en Typol, Centaur permet de générer des outils sémantiques comme un vérificateur de type ou un interprète pour le langage. Le résultat d'un vérificateur de type sur un programme donné est une liste d'erreurs avec une référence de l'emplacement de chaque erreur dans l'arbre de syntaxe abstraite (ainsi l'erreur pourra être mise en exergue dans le programme). Au cours de l'interprétation d'un programme des structures sémantiques (contenant des informations utiles sur le comportement du programme comme par exemple la liste des objets créés par le programme ou bien la liste des variables statiques) sont construites. Donc un résultat possible de l'interprète pourrait être une de ces structures sémantiques (ex : la liste des objets et leurs attributs à la fin de l'interprétation). Ces résultats sont montrés dans des fenêtres spécifiques (textuelles ou graphiques). De plus, Centaur permet d'animer l'exécution d'un programme en utilisant des mises à jour incrémentales des fenêtres contenant les résultats.
Exemple de règle en Typol : Jugdement Object_L, O_Id |- Object ;
find_Apdu_attribute(identifier "commandApdu" |- ObjL1, AttrL1 -> AttrL2) -------------------------------------------------------------------------- ObjL1, OthId1 |- object(_, identifier "CAD", AttrL1, _, _, _, _); Do Update_apduL(APDU(OthId1, AttrL2) -> ApduL) & emit_tree("APDU", ApduL) ; |
Explications Cette règle d'inférence ne s'applique que si l'objet a comme nom de classe CAD (mécanisme utilisé : le filtrage) et si la prémisse find_Apdu_attribute n'échoue pas. Cette prémisse recherche la référence de l'objet APDU, contenu par l'objet de type CAD donné, dans la liste d'attributs (AttrL1). Puis elle recherche cet objet dans la liste des objets du programme (ObjL1) pour en extraire la liste d'attributs pour une APDU de commande (AttrL2). Donc si la règle réussit, une mise à jour de la liste des APDUs est faite (update_apduL), suivie par son affichage dans la fenêtre APDU (cf. Figure 10). |
Tableau 2 Exemple d'une règle Typol
Pour compiler des programmes Java Card (cf Figure 5), il faut utiliser le compilateur de Java, javac, en précisant dans le classpath les librairies spécifiques à Java Card (i.e. throwable.jar, jc20api.jar, jcre.jar et jcsimulation.jar). Tout emploi de méthodes, exceptions ou classes n'appartenant pas à Java Card est détecté lors de cette phase de compilation.
Le compilateur javac, qui a un analyseur syntaxique adapté à Java et non à Java Card, ne peut garantir que le programme compilé est bien écrit en Java Card car certaines erreurs syntaxiques ne pourront pas être détectées.
Pour cette raison, Sun fournit en plus des librairies Java Card un utilitaire appelé checker qui permet de vérifier si les packages/applets sont écrits en Java Card et non en Java. Son rôle est de détecter l'usage de types ou de modifiers non supportés, d'opérations arithmétiques non autorisées et de classes, méthodes ou exceptions n'appartenant pas à Java Card. Cet outil travaille sur le byte code du programme (c'est pourquoi il lui est impossible de donner le numéro de ligne où se situe l'erreur).
Figure 5
La compilation d'un programme Java CardCet outil peut être utilisé de deux manières :
C'est un environnement de développement fournissant les outils nécessaires pour optimiser et charger les applets (compilées avec un compilateur quelconque). Odyssey I (nom de la carte) est conforme aux spécifications Java Card API 2.0 et sa JVM est l'une des plus performantes du marché selon Bull. Son composant, développé par ST (auparavant SGS Thomson), a été conçu pour les besoins des plates-formes ouvertes et pour être adapté à de nouveaux mécanismes de sécurité (accès sécurisé aux secteurs partitionnés de la mémoire permettant une séparation étanche des applications, authentification ; intégrité et confidentialité assurées lors du chargement des applets ; cryptographie). La carte Odyssey offre en standard l'application de crédit/débit CCPS de Visa et 8 kø d'EEPROM pour des applications propriétaires (ex : programmes de fidélité, porte-monnaie électronique,...).
Cyberflex est une carte intelligente Java (appelée J-Card) 8 bits développée par Schlumberger qui peut exécuter des applications Java Card (les Cardlets). Elle est conforme aux spécifications de Java Card 2.0. Le kit vendu pour PC comprend à peu près les mêmes éléments que celui de Gemplus mais apparemment n'a pas d'environnement de développement car il serait très facile de l'intégrer dans un environnement de développement Java existant (comme par exemple Microsoft Visual J++).
Cet outil posséderait lui aussi un simulateur qui vérifierait le code d'une cardlet après la phase de compilation et d'édition de lien faite dans un environnement de développement Java quelconque. Pour l'utiliser, il suffirait juste de le lancer en cliquant dans le menu Tool de l'environnement utilisé, puis d'exécuter la cardlet. Il suffirait ensuite d'interagir avec la carte par l'interface graphique du simulateur. Il détecterait les erreurs fonctionnelles possibles du code avant que celui ne soit chargé sur la carte. Après cette simulation le byte code de la cardlet est modifié par MakeSolo (un outil du kit qui teste l'absence de caractéristiques non supportées et qui groupe les fichiers .class en un seul fichier) puis peut être chargé sur la carte Schlumberger par l'utilitaire LoadSolo.
Ces trois outils ne sont pas spécifiques à Java Card car ils permettent la mise au point de programme Java. Leur spécificité Java Card intervient au niveau du byte code (généré dynamiquement) avec une phase de vérification puis de chargement.
Tout d'abord, on indiquera les modifications apportées aux spécifications syntaxiques Java pour les adapter à Java Card. Puis on décrira un outil de vérification statique spécifié pour détecter la présence de tableaux multidimensionnels. Puis enfin notre simulateur d'application Java Card sera présenté.
Tout le travail sur la syntaxe de Java Card repose sur le document Java Card 2.0 language subset and virtual machine specification [SUN1] écrit par Sun Microsystems. Notre rôle était de modifier ou de supprimer les types et les opérateurs adéquats de la spécification syntaxique de Java qui contenait 130 types et 209 opérateurs.
Notre première action fut donc d'enlever les types de base non supportés en Java Card (i.e. char, long, double et float).
Puis comme les threads ne sont pas supportés, le modifier synchronized (utilisé pour synchroniser l'accès à une donnée ou à une méthode lors de l'exécution multi-threadée d'un programme) fut enlevé.
Comme aucune gestion de la mémoire (garbage collector) n'est spécifiée en Java Card, les modifiers volatile (permettant d'indiquer que cette variable est une copie d'une donnée partagée par deux threads ayant comme avantage d'être remise à jour à chaque accès) et transient (permettant d'indiquer que la valeur d'un attribut d'un objet n'est pas persistante) ont été enlevés.
Java Card, contrairement à Java, ne possède que des tableaux unidimensionnels. C'est pourquoi des modifications ont dû être faites pour éviter la déclaration et l'usage de tableau à plus d'une dimension. Pour cela, il a fallu restreindre la spécification des types utilisables pour la déclaration d'un attribut, d'une variable locale, du type de retour d'une méthode, ou d'un cast. Malgré ces modifications, il est encore possible de faire une analyse syntaxiquement correcte d'un programme illégal en Java Card (i.e. contenant un tableau à 2 dimensions). En effet, Java lors de la déclaration d'une variable, d'un attribut ou du type de retour d'une méthode, laisse la possibilité au développeur de positionner les crochets indiquant un tableau soit à droite du nom du type, soit à droite du nom de la variable, de l'attribut ou de la méthode (après ses paramètres). C'est pourquoi, ces 3 déclarations int[] i , int i[] et int[] i[] sont syntaxiquement correctes en Java Card mais le dernier exemple n'a aucun sens pour un programme Java Card car le tableau déclaré a 2 dimensions. Ce type de vérification est donc à effectuer pendant la phase d'analyse statique (cf. partie 3.2 pour avoir plus de détails).
Lors de cette analyse fine de la syntaxe de Java et de Java Card, nous avons détecté des erreurs dans la description syntaxique de Java qui était trop permissive par rapport à la grammaire LALR définie par Gosling [GOS96].
Lors de notre spécification sémantique, nous avons eu besoin de définir une structure de résultat qui définit les APDUs transmises entre la carte et le lecteur. Cette structure, qui est une liste d'APDUs, a été rajoutée à la syntaxe abstraite. En voici sa spécification :
APDU_L ::= apdu_l ;
apdu_l -> APDU *... ;
APDU ::= apdu ;
apdu -> O_Id Pair_L ;
Une APDU contient la référence de l'objet (O_Id) l'ayant transmis et une liste de paires (Pair_L). Chaque paire contient le nom de l'attribut et sa valeur (comme par exemple (" cla ", 0)). Les types O_Id et Pair_L étaient déjà définis dans la syntaxe abstraite de Java.
Pour débuter avec le langage Typol, nous avons décidé de spécifier un outil de sémantique statique testant que les tableaux n'ont qu'une dimension (cf. partie 3.1 pour une description de la problématique). Cette spécification permettait de se familiariser au parcours de l'arbre de syntaxe abstraite d'un programme Java Card et à la syntaxe des règles Typol.
Le but était donc d'analyser un programme et de vérifier sa légalité en Javacard. En cas d'erreur, un message est affiché (cf. Figure 6).
Les emplacements possibles d'erreur
Nous avons ainsi pu identifier les nuds de l'arbre abstrait à analyser i.e. fieldVariableDeclaration, methodDeclaration, localVariableDeclaration.
Algorithme utilisé
Début : noeud typeDeclarations de compilationUnit Pour chaque noeud fieldVariableDeclaration si son fils type est arrayof(TypeName) Pour chaque variableDeclarator si c'est un array ou un initializedVariable avec un VariableDeclaratorId qui est un array msg d'erreur Pour chaque noeud methodDeclaration si ResultType est un array(TypeName) et si MethodDeclarator est un arrayMethodDeclarator msg d'erreur Pour chaque parameter Si Type = arrayof(TypeName) et VariableDeclaratorId = array msg d'erreur Pour chaque noeud constructorDeclaration Pour chaque parameter Si Type = arrayof(TypeName) et VariableDeclaratorId = array msg d'erreur Pour chaque noeud localVariableDeclaration si Type = arrayOf(TypeName) Pour chaque variableDeclarator si c'est un array ou un initializedVariable avec un VariableDeclaratorId qui est un array msg d'erreur
Ci-dessous (cf. Tableau 3) sont écrites les règles Typol nécessaires pour tester que les paramètres d'un constructeur sont corrects (i.e. ne sont pas des tableaux à plusieurs dimensions).
program javacardCheckCompilationUnit is use javacard ; import message(string, string, string, string, path, string) from message ; import diff(_,_) from prolog ; ...
set javacardCheckCompilationUnit is judgement (CompilationUnit -> Bool); checkTypeDeclaration_l(TypeDec -> Bool) ---------------- (compilationUnit(_, _, TypeDec) -> Bool) ; // on ne teste que le noeud typeDeclarationsend javacardCheckCompilationUnit;
set checkTypeDeclaration_l is judgement (TypeDeclarations -> Bool); MainRule: // on teste recursivement tous les types déclarationsCheckTypeDeclaration(TypeDec -> Bool1) & CheckTypeDeclaration_l(TypeDecL -> Bool2) & and(|- Bool1, Bool2 -> Bool3) ---------------- (typeDeclarations[TypeDec.TypeDecL] -> Bool3) ;
(typeDeclarations[] -> true()) ; end checkTypeDeclaration_l;
set checkTypeDeclaration is judgement (TypeDeclaration -> Bool); ClassRule: // si le typeDeclaration est une classDeclaration, on teste sa liste de FieldDeclarationCheckClassField_l(FieldDecL -> Bool) ---------------- (classDeclaration(_, _, _, _, FieldDecL) -> Bool) ; InterfaceRule: // si le typeDeclaration est une interfaceDeclaration,//on teste sa liste de InterfaceFieldDeclaration CheckInterfaceFieldDec_l(InterFieldDecL -> Bool) ---------------- (interfaceDeclaration(_, _, _, InterFieldDecL) -> Bool) ; end checkTypeDeclaration;
set checkClassField_l is judgement (FieldDeclarations -> Bool); MainRule: // on teste recursivement tous les FieldDeclarationCheckClassField(FieldDec -> Bool1) & CheckClassField_l(FieldDecL -> Bool2) & and(|- Bool1, Bool2 -> Bool3) ---------------- (fieldDeclarations[FieldDec.FieldDecL] -> Bool3) ;
(fieldDeclarations[] -> true()) ; end checkClassField_l;
set checkClassField is judgement (javacard -> Bool); ConstructorRule: //si le fieldDeclaration est un constructorDeclaration //on teste sa liste de paramètres et son corps. checkParam_l(ParamL -> Bool1) & checkConstBody(ConstBody -> Bool2) & and(|- Bool1, Bool2 -> Bool3) ---------------- (constructorDeclaration(_, constructor(_, ParamL), _, ConstBody) -> Bool3) ; ... end checkClassField;
set checkParam_l is judgement (javacard -> Bool); ItParamRule: // on teste recursivement chaque paramètrecheckParam(|- Param -> Bool1) & checkParam_l(|- ParamL -> Bool2) & and(|- Bool1, Bool2 -> Bool3) ---------------- (parameters[Param.ParamL] -> Bool3) ;
ItParamEmptyRule: (parameters[] -> true()) ; end checkParam_l;
set checkParam is judgement |- javacard -> Bool; ArrayArrayParamRule: //erreur car le type du paramètre est un tableau à 2 dimensions|- parameter(_, arrayof(TName), array(Param)) -> false() ; do message("javacard", "checker", "errorDimArray", "Error", subject, ""); ArrayParamRule: //Le type du paramètre est un tableau à 1 dimension|- parameter(_, arrayof(TName), Param) -> false() ; provided diff(Param, array(_)); SimpleParamRule: //parametre |- parameter(_, TypParam, _) -> true() ; provided diff(TypParam, arrayof(_)); end checkParam; ... |
Tableau 3 Spécifications de l'outil de vérification
Figure 6
Fenêtre contenant les erreurs du programme testéSes acteurs
Les principaux acteurs lors d'une transaction entre une carte à puce et un CAD sont :
Nous avons décidé de simuler l'ensemble de ces acteurs pour pouvoir tester des applets Java Card sur une station de travail. Pour cela, nous avons codé en Java le comportement de chaque acteur.
Son architecture
Pour simplifier notre modèle dans une première approche, nous avons décidé de simuler seulement les événements synchrones i.e. les actions de l'utilisateur sur le lecteur de carte. Donc tous les événements asynchrones comme une coupure de courant ou un retrait de carte ne sont pas encore gérés par notre modèle. Mais nous en avons tenu compte lors de la phase de conception afin de faciliter leur intégration future lors de l'évolution de notre modèle.
Chaque acteur (User, CAD, JCRE) est modélisé par un Thread Java (cf. Figure 7).
Figure 7
Schéma du modèle adoptéNous avons aussi choisi de représenter les applets de la carte par des threads. En effet, il est envisagé dans le futur d'introduire du multithreading sur une carte à puce. De plus, cela nous permettait de séparer les contextes d'exécution des objets contenus sur la carte et donc d'avoir une meilleure visualisation de ce qui se passe sur la carte.
Le JCRE doit être le plus générique possible pour pouvoir référencer n'importe quel type d'applet contenue par la carte.
Son fonctionnement
Nous avons choisi un mode de fonctionnement maître/esclave permettant d'avoir un déroulement séquentiel. C'est pourquoi un seul Thread est actif à un instant donné comme nous le montre la Figure 8.
Figure 8
Description des différentes phases
Tous les threads (User, CAD, JCRE) sont créés, démarrés, puis suspendus (méthode invoquée : suspend()) en attente d'être réveillés (méthode resume()).
Son Implémentation
Le programme se compose de 10 classes :
Vue la longueur de notre programme (environ 500 lignes), seulement les parties les plus intéressantes des classes User (Tableau 4), CAD (Tableau 5), JCRE (Tableau 6), Applet (Tableau 7) et PurseFr (Tableau 8) sont présentées et commentées. L'annexe A contient l'ensemble du programme.
class User extends Thread {... Public void run() { Cad.installAppli(PurseFr.AID, 1000); cad.sendAction(PurseFr.AID, PurseFr.PURSE_FR_WITHDRAW, 100); cad.installAppli(FrequentFlyer.AID, 0); cad.sendAction(FrequentFlyer.AID, FrequentFlyer.GAIN_MILES, 5000);}...} |
Commentaires Cette classe simule l'utilisateur. Sa première action est de faire installer par sa banque l'application PurseFr avec comme montant initial 1000 francs sur sa carte. Puis il se sert de sa carte pour payer son essence (retrait de 100 francs). Il décide ensuite de faire installer l'application Frequent Flyer par sa compagnie aérienne car il souhaite pouvoir conserver les miles de son voyage en Suède offerts (gain de 5000 miles). Ainsi il pourra, un jour, avoir un voyage gratuit Chaque appel à la fonction sendAction envoie au CAD l'AID de l'applet sur laquelle l'opération indiquée doit être faite et attend sa réponse. La fonction installAppli permet de simuler le chargement dynamique du code d'une applet sur une carte déjà en service. |
Tableau 4 Une partie de la classe User
Class CAD extends Thread {... Public void run() { While (true) { sendActionToCard(); if (action == SELECT) { if (apdu.sw1 == JCRE.OK) { currentAID = AID; apdu.setCommandApdu(JCRE.PROCESS_CLA, ins, NOTHING, commandData); sendActionToCard(); } else currentAID = JCRE.NO_SELECTED_APPLET; } user.resume(); suspend();}...} |
Commentaires Cette classe simule le lecteur de carte qui traduit l'action demandée en APDU de commande standardisée en fonction des informations données lors de l'appel de la méthode sendAction(). |
Tableau 5 Une partie de la classe CAD
Class JCRE extends Thread {... Public void run() { while (true) { /*// Select APDU*/ if (apdu.cla == SELECT_CLA && apdu.ins == SELECT_INS) { if (selectedAppliAID != NO_SELECTED_APPLET) { sendCommandToAppletAndWaitResponse(DESELECT, selectedAppliAID); selectedAppliAID = NO_SELECTED_APPLET; } sendCommandToAppletAndWaitResponse(SELECT, apdu.p1); if (apdu.sw1 == OK) selectedAppliAID = apdu.p1; } else { /*// Process APDU*/ if (selectedAppliAID != NO_SELECTED_APPLET) sendCommandToAppletAndWaitResponse(PROCESS, selectedAppliAID); else apdu.sw1 = IMPOSSIBLE; } cad.apdu.copyResponseApdu(apdu); cad.resume(); suspend(); /*Wait a CAD action*/ }...} |
Commentaires Cette classe simule le runtime de la carte. Son rôle est d'attendre une commande du CAD pour sélectionner, desélectionner les applets de la carte ou leur envoyer les commandes de l'utilisateur contenues dans les APDUs. |
Tableau 6 Une partie de la classe JCRE
class Applet extends Thread {.../*//Java Card Applet*/ public void run() { byte commandCode; boolean selectOk; while (true) { commandCode = JCRE.self.commandCode; if (commandCode == JCRE.SELECT) { selectOk = select(); if (selectOk == true) JCRE.self.apdu.sw1 = JCRE.OK; Else JCRE.self.apdu.sw1 = JCRE.IMPOSSIBLE; } else if (commandCode == JCRE.DESELECT) deselect(); else if (commandCode == JCRE.PROCESS) process(JCRE.self.apdu); JCRE.self.resume(); Suspend(); }...}...} |
Commentaires Cette classe décrit les Applets Java Card de notre modèle où chaque applet est un Thread. Donc chaque fois que l'on fait un resume() (pour réveiller le thread) sur une de nos applets, on exécute ce run() générique qui appelle la méthode appropriée de l'applet (i.e. soit process(), deselect() ou select()) et qui s'occupe de la gestion des Threads. |
Tableau 7 Une partie de la classe Applet
class PurseFr extends Applet { protected final static byte AID = 126; /*//Possible Instructions*/ protected final static byte PURSE_FR_DEPOSIT = 1; protected final static byte PURSE_FR_WITHDRAW = 2; protected final static byte PURSE_FR_BALANCE_CHECK = 3; ... public static PurseFr install(APDU apdu) { return new PurseFr(apdu);}
public void process(APDU apdu) { if (apdu.ins == PURSE_FR_DEPOSIT) purseDeposit(apdu); else if (apdu.ins == PURSE_FR_WITHDRAW) purseWithdraw(apdu); else if (apdu.ins == PURSE_FR_BALANCE_CHECK) purseBalanceCheck(apdu);}... |
Commentaires Voici l'exemple d'une applet Java Card avec ses méthodes process() et install() ainsi que sa liste d'actions possibles (PURSE_FR_DEPOSIT, ...). Chaque fois d'un développeur d'applet voudra tester une applet, il n'aura qu'à insérer son code Java Card, sans le modifier, dans le programme de notre modèle comme pour cette applet PurseFr. Puis il devra modifier légèrement la méthode run() de User pour installer son applet sur la carte et pour exécuter des actions. Il n'aura pas à s'occuper de la gestion des threads. |
Tableau 8 Une partie de la classe PurseFr
Nous avons modifié la sémantique Java, en particulier, sur l'entrelacement des threads. En effet, une sémantique small-step classique, après chaque pas d'instruction élémentaire, recherche un autre thread à exécuter (simulation de la concurrence). Le modèle décrit permet d'avancer dans l'exécution d'un thread jusqu'à sa mort ou sa suspension comme nous le montre la spécification dans le set exec_activity du Tableau 9 (les modifications ont été mises en gras dans ce set. Le set treat_next_inst_if_not_suspended a été créé spécialement pour la sémantique Java Card ainsi que le set send_apdu qui sert à communiquer avec l'environnement.
set exec_activity is --C : Deals with the execution of the thread activity. --C : The first reference 'OThId1' is the current "executing" thread --C : identifier. The second one 'ObjId1' is the current object identifier. judgement Object_L, C_Var_L, O_Id, O_Id |- Activity -> Object_L, C_Var_L; judgement Object_L, C_Var_L, O_Id, O_Id |- Clr :> Object_L, C_Var_L, T_Status; judgement Object_L, C_Var_L, O_Id, O_Id, Clr |- Inst -> Object_L, C_Var_L, Env, Clr, Comp_Exp, T_Status; ... Dead_thread: send_object_struct(ObjL1, ClVarL1) & update_thread_status(ObjL1, ClVarL1, OThId1, dead() -> ObjL1_1) & update_activity_in_object_l(ObjL1_1, OThId1, clr(OThId1, Mode, MethName, env(pair_l[], locs[]), inst_l[]), ClVarL1 -> ObjL1_2) ---------------- ObjL1, ClVarL1, OThId1, ObjId1 |- clr(OThId1, Mode, MethName, env(ParL, LocL), inst_l[]) :> ObjL1_2, ClVarL1, dead() ; Do send_dead(ObjL1_2, OThId1) & delete_a_given_thread_from_stack(OThId1);
General_rule: delete_a_given_thread_from_stack(OThId1) & ObjL1, ClVarL1, OThId1, ObjId1, clr(OThId1, Mode, MethName, Env1, inst_l[Inst.InstL])|- Inst -> ObjL1_1, ClVarL1_1, Env1_1, Clr2, Val, ThStatus1 & Update_activity_in_object_l(ObjL1_1, OThId1, Clr2, ClVarL1_1 -> ObjL1_2) & update_thread_status(ObjL1_2, ClVarL1_1, OThId1, ThStatus1 -> ObjL1_3) & send_object_struct(ObjL1_3, ClVarL1_1) & treat_next_inst_if_not_suspended(ObjL1_3, ClVarL1_1, OthId1, ObjId1 |- ThStatus1, Clr2 -> ObjL1_4, ClVarL1_2, ThStatus2) ---------------- ObjL1, ClVarL1, OThId1, ObjId1 |- clr(OThId1, Mode, MethName, Env1, inst_l[Inst.InstL]) :> ObjL1_4,ClVarL1_2, ThStatus2 ; ... end exec_activity;
set treat_next_inst_if_not_suspended is judgement Object_L, C_Var_L, O_Id, O_Id |- T_Status, Clr -> Object_L, C_Var_L, T_Status;
Not_suspended_thread: send_current(ObjL1, OThId1) & exec_activity(ObjL1, ClVarL1, OThId1, ObjId1 |- Clr :> ObjL1_1, ClVarL1_1, ThStatus1_1) ---------------- ObjL1, ClVarL1, OThId1, ObjId1 |- ThStatus1, Clr -> ObjL1_1, ClVarL1_1, ThStatus1_1 ; provided not_eq(ThStatus1, suspended(_));
Suspended_thread: send_apdu(ObjL, OThId, Clr) ---------------- ObjL, ClVarL, OThId, ObjId |- suspended(ThStatus), Clr -> ObjL, ClVarL, suspended(ThStatus) ; end treat_next_inst_if_not_suspended; |
Tableau 9 Spécification sémantique des threads de notre modèle
Lors du déroulement de l'interprétation de notre programme, certaines structures sémantiques sont affichées incrémentalement pour faciliter la mise au point des applets Java Card.
Fenêtres communes Java/ Java Card
L'environnement Java offre quatre fenêtres de résultats dont une (cf. Figure 9) qui montre l'évolution des états (suspended, runnable, etc.) des Threads par l'utilisation de couleurs, les dépendances des objets créés par le programme, les variables locales et les attributs des objets (cf. l'objet PurseFr).
Figure 9 Fenêtre graphique contenant tous les objets de notre modèle
Fenêtres spécifiques Java Card
Pour mettre au point une application Java Card, il est utile de visualiser les APDUs transmises entre le CAD et la carte (cf. Figure 10). Ainsi on peut espionner la ligne de communication entre ces deux entités et afficher les informations transitant sur cette ligne (i.e. les APDUs de commande du CAD vers le JCRE et des APDUs de réponse entre le JCRE et le CAD). Cette même information est affichée " décodée " dans une autre fenêtre (cf. Figure 11). simulant l'écran LCD (Liquid Cristal Display) du CAD pour être comprise. De cette manière, notre outil permet aux développeurs d'applets de mettre au point des applets Java Card ainsi que l'interface du CAD.
Il a fallu spécifier comment notre structure d'APDUs devait être construite dans la sémantique de notre interprète et à quels moments ces informations devaient être affichées dans les fenêtres de résultat
Pour pouvoir afficher cette même structure de deux manières différentes (i.e. selon si c'est l'écran LCD du CAD ou bien l'espion réseau), il fallait écrire deux pretty-printers différents.
Figure 10 L'espion réseau montrant les APDUs échangées entre la carte et le lecteur de carte
Figure 11 Ecran LCD du CAD (APDUs décodées pour l'utilisateur)
Notre modèle n'inclut pas toutes les possibilités de Java Card. Pour le rendre plus réaliste, il faudrait que les applets puissent utiliser des tableaux de bytes, les nombres hexadécimaux beaucoup employés pour la programmation des cartes et plus tard les APIs (Application Programming Interface) de Java Card 2.0.
Il faudrait aussi que modèle gère l'authentification grâce au PIN (Personal Identifier Number) en début de communication entre le lecteur et la carte pour s'assurer de l'identité de la personne employant la carte.
Les retraits de carte ou coupures de courant devront également être simulés avec sauvegarde du contexte. Ces deux événements asynchrones auront comme conséquence de cesser toute activité sur la carte. Lors de la remise du courant, toutes les opérations atomiques interrompues seront annulées.
Le JCRE devrait stocker, pour chaque applet contenue sur la carte, l'état en plus de l'AID et de la référence. Les différents états possibles sont : none, loaded, registred, selectable.
Actuellement la sémantique de Java n'est pas encore totalement spécifiée. Le mécanisme d'exception est en cours de spécification par Marjorie Russo. Il faudra juste l'adapter à Java Card (i.e. enlever les exceptions n'appartenant pas à Java Card et rajouter celles propres à Java Card).
De plus, les nombres hexadécimaux ainsi que certaines opérations binaires comme le décalage droit (>>), gauche (<<), droit non signé (>>>), le modulo (%), le xor bit à bit (^), le et bit à bit (&) ou le ou bit à bit (|) n'ont pas été spécifiées. La plupart de ces opérations sont nécessaires pour travailler avec des nombres en hexadécimal (ex. pour faire des masques) utilisés intensément par les développeurs d'applications en assembleur pour les cartes.
Il faudra aussi faire migrer la sémantique Java de JDK 1.0 vers JDK 1.1 pour pouvoir traiter les inner classes et interfaces.
De plus, il faudra aussi être capable de spécifier le mécanisme de package qui permet à une application d'être modulaire multi-fichiers.
La première chose à faire serait de spécifier les comportements du JCRE, CAD et de la classe Applet en Typol. Cela permettrait de réduire la taille de notre programme à quelques lignes seulement et donc d'améliorer les performances de l'interprétation. Ainsi la gestion des threads serait complètement cachée.
Il faudrait pouvoir spécifier toutes les classes et les méthodes de Java Card. Cette solution paraît acceptable au vue du faible nombre de classes en Java Card (51 classes dont 18 classes d'exception pour 5 packages).
Dans un sens Java Card peut être vu comme un sous-ensemble de Java, mais pourtant il possède des mécanismes qui lui sont propres et qui sont liés aux spécificités des cartes à puce.
Par exemple, notre sémantique devra tenir compte des objets transients. Pour cela, il faudra définir une nouvelle structure : une liste d'objets transients contenant également le moment où la remise aux valeurs par défaut doit être faite. Cette liste sera consultée et mise à jour après chaque transaction, desélection, simulation de coupure de courant ou de retrait de carte.
Notre sémantique doit pouvoir intégrer le mécanisme de transactions atomiques. La solution serait de faire lors de la rencontre de l'appel système beginTransaction() (méthode indiquant le début d'une transaction atomique) une copie de la liste des objets persistents. Ainsi on pourrait restaurer les valeurs modifiées en cas de simulation de retrait de carte ou de coupure de courant dans une transaction atomique ou en cas d'appel de la méthode abortTransaction() (pour annuler la transaction).
La sémantique devrait enfin définir le partage d'objets entre applets (caractéristique absente des outils commerciaux).
L'interprétation de notre programme (environ 500 lignes) grâce à la sémantique modifiée de Java montre que des programmes assez gros peuvent être traités sur station de travail. Pour donner un ordre d'idée de la vitesse de notre interprète nous pouvons dire que l'interprétation se fait en 7 mn sous un DEC PWS 500 à 500 MegaHertz, avec 256 Mø de mémoire vive et 600 Mø de swap sur disque dur. Ces performances sont acceptables en présence de l'animation de l'exécution. En effet le développeur doit pouvoir suivre le déroulement de l'exécution.
Actuellement le comportement du l'utilisateur est décrit dans le programme et est donc figé. En offrant une fenêtre d'entrée au CAD, nous permettrons à l'utilisateur de choisir l'applet et l'opération à exécuter. De cette manière, l'utilisateur ne sera plus simulé. Cette fenêtre aura l'apparence d'un vrai lecteur de carte avec des boutons et un écran LCD. Le problème sera bien sûr d'avoir un CAD générique i.e. indépendant des applications de la carte. Pour cela, il faudra une phase d'initialisation entre le CAD et la carte pour donner les AIDs et les opérations possibles des applets contenues par la carte. Actuellement les fabricants de carte et de terminaux sont en train de réfléchir à ce problème. En effet, jusqu'à présent comme nos cartes étaient mono-applications, les CADs connaissaient les opérations qui pouvaient être réalisées sur cette application. Mais maintenant avec l'arrivée des cartes multi-applications, les CADs devront devenir " intelligents ".
D'autres fenêtres d'interfaces pourraient être créées pour visualiser le fonctionnement du JCRE et objets de type File (très couramment utilisés dans la programmation des cartes à puces).
Nous avons présenté nos travaux sur le langage Java Card: nous avons tout d'abord étudié le langage, les standards liés aux cartes à puces, puis modélisé les applications Java Card en y incluant tous les acteurs, et pas seulement ce qui se passait effectivement sur la carte.
Nous avons modifié une sémantique formelle de Java existante afin de prendre en compte ce modèle, en particulier le fait qu'un seul thread est actif à un instant donné. Enfin, cette modélisation ainsi que la sémantique ainsi décrite permettent de comprendre le comportement des applications Java Card. L'environnement de développement construit pour Java Card facilite la mise au point des applets Java Card grâce à la visualisation des acteurs du modèle et des transactions entre terminal et carte.
Notre objectif est, dans un premier temps, de compléter la description formelle du langage (et du modèle), puis de proposer d'autres outils pour permettre la mise au point. Enfin, nous souhaitons étudier et formaliser des propriétés liées à la sécurité qui, une fois vérifiées, pourront garantir le bon fonctionnement d'une application Java Card.
A terme, nous pourrons ainsi disposer d'un environnement complet de développement et vérification d'applications Java Card.
Références
[ATT97] |
Isabelle Attali, Denis Caromel, Marjorie Russo Vers une sémantique Formelle de Java Journées du GDR Programmation 12, 13, 14 novembre 1997 Rennes |
[BOR98a] |
E. Börger and W. Schulte A programmer friendly modular definition of the semantics of Java Formal syntax et semantics of Java. LNCS. Springer-Verlag, 1998. A paraître |
[BOR98b] |
E. Börger and W. Schulte Defining the Java Virtual Machine as platform for Provably correct Java compilation 23rd International Symp. On Mathematical foundations of computer sciences LNCS. Springer-Verlag, 1998. A paraître |
[BUL98] |
Bull CP8 Odyssey I: Your passport to the Java world March 1998
http://www.bull.gr/bull/www.cp8.bull.net/news/021798a.htm |
[CHE98] |
Zhiqun Chen (with special contribution by Rinaldo Di Giorgio) Understanding Java Card 2.0 (learn the inner workings of the Java Card architecture, API, and runtime environment) JavaWorld March 1998 http://www.javaworld.com/javaworld/jw-03-1998/jw-03-javadev.html |
[DRE98] |
Henry Dreifus, J. Thomas Monk Smart Cards (Chapitres 1, 2, 3, 10) John Wiley & Sons 1998 ISBN 0-471-15748-1 |
[DRO98] |
S. Drossopoulou, S. Eisenbach Towards an operationnal semantics and proof of type soundness for Java Formals Syntax and Semantics of Java, LNCS. Springer-Verlag, 1998 A paraître |
[GEM98] |
Gemplus Gemplus ships GemXpresso RAD, a Java-Based Development Plateform for smart cards Gemplus presse 23/03/98 |
[GOS96] |
James Gosling, Bill Joy and Guy Steele The Java Language Specification (Chapitre 19 LALR Grammar) Addison-Wesley 1996 http://java.sun.com/docs/books/jls/htlm/19.doc.html#52996 |
[GUT97] |
Scott B. Guthery (Schumberger Electronic Transactions) Java Card : Internet Computing on a Smart Card IEEE Internet Computing Volume 1 Jan. Feb. 1997 |
[NIP98] |
T. Nipkow and D. Von Oheimb Java Light is Type Safe- Definitely 25th ACM Symp. Principles of Programming Languages, 1998 |
[QIA98] |
Z Qian A formal specification of the Java Virtual Machine Instructions for objets, methods and subroutines Formal syntax et semantics of Java. LNCS. Springer-Verlag, 1998. A paraître |
[ROS97] |
Eva Rose Towards a Secure Bytecode Verification on a Java Card Workshop on security and languages, Palo Alto. Oct 97 |
[SYM97] |
D. Syme Proving Java type soundness Technical report 427, University of Cambridge Computer laboratory. 1997 |
[RUS97] |
Marjorie Russo Une sémantique formelle de Java Mémoire de DEA de Mathématiques Discrètes de Fondements de l'Informatique de Marseille Juin 1997 |
[POS98] |
Joachim Posegga, Harald Vogt Byte Code Verification for Java Smart Cards Based on Model Checking 5th European Symposium on Research in Computer Security (ESORICS) 1998 Springer LNCS 1998 |
[SLG97] |
Schlumberger Presenting ... the butterfly effect ? 1997-1998 http://www.cyberflex.austin.et.slb.com/cyberflex Simulation Tool Aids Development of Cyberflex Cardlets ™ for smart card http://www.cyberflex.austin.et.slb.com/cyberflex/top/news/032398-m8ksim.html |
[SUN1] |
Sun Microsystems Java Card 2.0 Language Subset and Virtual Machine Specification Révision finale 1.0 du 13 octobre 1997 http://java.sun.com/products/javacard |
[SUN2] |
Sun Microsystems Java Card 2.0 Programming Concepts Révision finale 1.0 du 15 octobre 1997 http://javaworld.com/javaworld/jw-04-1998/iButtons/JC20-Concepts.pdf |
[SUN3] |
Sun Microsystems Java Card Checker User's Guide Révision finale 1.5 du 20 Février 1998 |
[SUN4] |
Sun Microsystems Java Card Application Programming Interface (package javacard.framework) Révision finale 1.0 du 13 Octobre 1997 http://javaworld.com/javaworld/jw-04-1998/iButtons/JC20API-prtrat.pdf |