samedi 30 juillet 2016

Premier programme avec mon InfinityUSB Unlimited

Ca y est ! J'ai reçu mon programmateur de cartes à puce InfinityUSB Unlimited. Finalement, il n'aura mis que 2 semaines pour venir de Chine.

J'avais un peu peur qu'il ne soit pas fonctionnel car il est censé être le même que le modèle vendu en France 90€ alors qu'Ali Baba le vend 20€.

La boite est identique à l'original : elle comprend l'appareil, son câble USB et le mini-CDROM contenant le driver Windows et le soft. Eh oui, bad news pour moi mais je le savais déjà, c'est sous Windows que la programmation de ma Silvercard va se passer.

L'appareil en lui-même est vraiment rikiki : environ 3cm sur 7cm, poids vraiment plume. A se demander s'il y a vraiment de l'électronique là-dedans.

J'ai installé d'abord le pilote et le logiciel, et ensuite branché l'appareil. Sa led s'est mise à clignoter rouge pendant un moment, puis elle est devenue définitivement bleue (les branchements suivants donnent du bleu directement).


Le logiciel est des plus simples : on choisit la carte à programmer (Silvercard pour moi), le fichier hex à envoyer dans le PIC, éventuellement le fichier hex à envoyer dans l'EEPROM externe au PIC et on clique sur "Write". La programmation dure environ 5 secondes, la led clignotant verte à ce seul moment. Dans le cas où un fichier hex est à envoyer dans l'EEPROM externe, le logiciel commence par charger dans le PIC un loader maison, s'adresse à lui comme intermédiaire pour écrire dans l'EEPROM, et ensuite seulement écrit le PIC avec le fichier hex du PIC.

Inutile de dire que j'avais un fichier hex réfléchi tout prêt à injecter dans le PIC. C'est là que les ennuis ont commencé. L'injection s'est très bien passé, par contre gscriptor sous Linux voyait ma carte comme "non alimentée" (donc quasi morte pour lui). Aucune communication ne s'établissait avec la carte.

J'ai donc carrément injecté dans la Silvercard le fichier hex brut de fonderie original duquel j'avais tiré les routines SEND et RECEIVE en ISO7816. C'était un fichier d'un vieux programme de piratage des cartes SECA MEDIAGUARD du début des années 2000. Après tout, c'est peut-être moi qui avait mal extrait les routines. Même topo avec ce fichier, carte non alimentée.

Là j'ai commencé à me dire que j'étais mal, parce qu'il faut absolument que je parte d'un programme dans lequel les routines SEND et RECEIVE fonctionnent, car c'est de l'horlogerie, quasi impossible à écrire soit-même. Me voilà donc condamné à chercher sur le net un programme pour Silvercard dans lequel les routines SEND et RECEIVE au format ISO7816 fonctionnent bien. Difficile à trouver car maintenant tout le monde utilise des MIFARE ou autres cartes NFC.

Eh bien j'ai trouvé un vieux programme de déplombage de la chaine de TV italienne RAI qui date de 2004 et qui, une fois injecté dans ma Silvercard a envoyé un ATR à gscriptor, et avec lequel je pouvais envoyer des APDU. Certes il répondait à chaque fois que l'APDU correspondait à une classe non implémentée, mais la communication se faisait. Pour la première fois je communiquais avec ma Silvercard!

Je reprennais espoir car, quand on a un programme qui marche tout est différent. On a un angle d'attaque. Problème tout de même : mon programme RAI fait 13 Ko compilé. Chercher les routines SEND et RECEIVE là-dedans revient à chercher une aiguille dans une meule de foin.

Bon, j'exagère un peu car, par définition, SEND et RECEIVE manipulent le bit 7 du registre PORTB (car c'est sur ce bit que se fait la communication extérieure). En faisant une recherche sur ce critère, j'ai assez vite isolé les 2 routines et je les ai extraites.

Je les ai reprises dans un programme simple de mon cru, une espèce de "hello world" pour les cartes à puce : ce programme envoie le même ATR que la carte RAI puis passe dans une boucle infinie qui lit 5 octets (ie 1 APDU : CLA INS P1 P2 Le) et renvoie systématiquement 90 00, quel que soit l'APDU reçu. On ne peut pas faire plus simple comme programme.

Pour être franc, j'étais sûr que cela ne marcherait pas, ou du moins pas du premier coup. Sauf que BINGO !!! mon programme marche parfaitement bien. Voici un petit échange entre mon programme et gscriptor.

Voici donc mon programme. C'est du brut de fonderie, le premier programme qui marche. A partir de lui, je vais petit à petit monter une vraie application carte à puce.

    LIST    P=16F876, F=INHX8M
        include "P16F876.INC"
   
    __CONFIG    _BODEN_OFF & _CP_OFF & _WRT_ENABLE_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC & _DEBUG_OFF & _CPD_OFF & _LVP_OFF

    ORG     0x60
IODATA        RES    1
BIT_COUNT    RES    1
PARITY        RES    1
TEMPO        RES    1

    ORG    0x0000
    GOTO    INIT

    ORG    0x0004
    RETFIE

SEND    MOVWF    IODATA
    MOVLW    0x32
    CALL    WAIT2   
    BCF    0x6,7
    MOVLW    0x7f
    BSF        STATUS,RP0
     MOVWF   TRISB 
     BCF        STATUS,RP0   
    CLRF    PARITY   
    MOVLW    0x8
    MOVWF    BIT_COUNT
BOUCLE_SEND
    CALL    WAIT1   
    RRF    IODATA,F   
    RRF    IODATA,W
    ANDLW    0x80
    XORWF    PARITY,F   
    XORWF    0x6,W
    XORWF    0x6,F
    DECFSZ    BIT_COUNT,F
    GOTO    BOUCLE_SEND   
    CALL    WAIT1   
    MOVF    PARITY,W
    XORWF    0x6,W
    XORWF    0x6,F   
    CALL    WAIT1   
    MOVLW    0xff
    BSF        STATUS,RP0
     MOVWF   TRISB 
     BCF        STATUS,RP0   
    MOVLW    0x3e
    GOTO    WAIT2   

RECEIVE    BTFSC    0x6,7   
    GOTO    RECEIVE   
    MOVLW    0x2d   
    CALL    WAIT2
    MOVLW    0x9
    MOVWF    BIT_COUNT   
BOUCLE_RECEIVE
    BCF    0x3,0   
    BTFSC    0x6,7
    BSF    0x3,0
    RRF    IODATA,F
    CALL    WAIT1   
    NOP   
    NOP   
    DECFSZ    BIT_COUNT,F
    GOTO    BOUCLE_RECEIVE   
    RLF    IODATA,F
    MOVLW    0x1d
    CALL    WAIT2   
    MOVF    IODATA,W
    RETURN   

WAIT1    MOVLW    0x1a   
WAIT2    MOVWF    TEMPO
BWAIT    DECFSZ    TEMPO,F
    GOTO    BWAIT
    RETLW    0x0   


INIT   
    BSF        STATUS,RP0 ; select bank1     
    BCF    OPTION_REG,7    ; enable pull-ups
    BCF        STATUS,RP0
    CALL    WAIT1
    MOVLW    0x3B         ; ATR 3B F7 11 00 01 40 96 54 30 04 0E 6C B6 D6
        CALL       SEND   
    MOVLW    0xF7
        CALL       SEND   
    MOVLW    0x11
        CALL       SEND   
    MOVLW    0x00
        CALL       SEND   
    MOVLW    0x01
        CALL       SEND   
    MOVLW    0x40
        CALL       SEND   
    MOVLW    0x96
        CALL       SEND   
    MOVLW    0x54
        CALL       SEND   
    MOVLW    0x30
        CALL       SEND   
    MOVLW    0x04
    CALL    SEND
    MOVLW    0x0E
    CALL    SEND
    MOVLW    0x6C
    CALL    SEND
    MOVLW    0xB6
    CALL    SEND
    MOVLW    0xD6
    CALL    SEND
BOUCLE    CALL    RECEIVE
    CALL    RECEIVE
    CALL    RECEIVE
    CALL    RECEIVE
    CALL    RECEIVE
    MOVLW    0x90
    CALL    SEND
    MOVLW    0x00
    CALL    SEND
    END

jeudi 28 juillet 2016

Codes source d'algorithmes de chiffrement symétriques

Lorsqu'on réalise des développements à base de carte à puce, c'est souvent parce qu'il y a un impératif de sécurité.

Si c'est le cas, on est rapidement confronté à la mise en oeuvre d'un ou plusieurs  chiffrement/déchiffrement. Et donc se pose la question de savoir quel code source (fiable par rapport à l'algorithme, si possible) utiliser.

Voici un site qui propose gratuitement des codes source concernant les algorithmes symétriques les plus populaires et les plus costauds (clés de 256 bits pour des traitements par blocs de 128 bits).

Dommage qu'il n'y ait pas de sources d'algos asymétriques, comme RSA par exemple qui est beaucoup utilisé dans les cartes à puce.

L'algorithme star, AES, est bien sûr présent avec un code source montrant sa mise en oeuvre avec une clé de 256 bits (rappelons que l'AES peut fonctionner avec des clés de 128, 192 ou 256 bits). Cet algorithme est actuellement considéré, officiellement, comme inviolable.

Je dois dire qu'à titre personnel je me tâte encore de savoir si je vais utiliser AES dans mes développements futurs ou si je vais utiliser TEA. AES a pour lui la robustesse supposée, mais a l'inconvénient d'être probablement l'algo le plus étudié au monde et rien ne dit qu'il soit sûr officieusement. Par ailleurs le code source n'est pas simple. TEA a pour lui la simplicité du code source (quelques lignes) et est probablement un des algo les moins étudiés (donc sûr quelque part), il est par contre sur le papier moins sûr qu'AES.

A noter qu'une implémentation gratuite et opensource d'AES est disponible sur le net, que ce soit pour Windows, Mac ou Linux, en 64 bits comme en 32 bits, en ligne de commande comme en version graphique : il s'agit de l'excellent AEScrypt. A découvrir.

Publié le 28 juillet par Alan Cartman (cartesapuce@gmail.com)

mercredi 27 juillet 2016

Silvercard, le jeu d'instructions du PIC16F876

Le PIC16F876, caché au cœur d’une Silvercard, ne comporte que 35 instructions, que nous allons voir.

Ces instructions, pour beaucoup d’entre elles, sont des opérations mettant en jeu l’accumulateur (registre W) et un registre f en RAM. Dans les exemples ci-dessous, je prendrai comme adresse 0xAA pour illustrer par l’exemple ce qu’il faut écrire pour manipuler un registre en RAM (registre à l’adresse 0xAA donc) et 0xBB pour illustrer par l’exemple ce qu’il faut écrire lorsqu’on manipule des nombres littéraux. Evidemment, en programmation réelle, il faudra utiliser les bons registres/littéraux.
Les instructions sont les suivantes :
ADDWF 0xAA, F ; ajoute W et le registre 0xAA, met le résultat en 0xAA
ADDWF 0xAA,W ; ajoute W et le registre 0xAA, met le résultat en W
ANDWF 0xAA, F ; ET logique entre W et le registre 0xAA, met le résultat en 0xAA
ANDWF 0xAA,W ; ET logique entre W et le registre 0xAA, met le résultat en W
CLRF 0xAA ; met les 8 bits du registre à 0
CLRW ; met les 8 bits de W à 0
COMF 0xAA, F ; complément à 2 du registre 0xAA, met le résultat en 0xAA
COMF 0xAA,W ; complément à 2 du registre 0xAA, met le résultat en W
DECF 0xAA, F ; décrémente le registre 0xAA, met le résultat en 0xAA
DECF 0xAA,W ; décrémente le registre 0xAA, met le résultat en W
DECFSZ 0xAA, F ; décrémente le registre 0xAA, met le résultat en 0xAA et saute l’instruction suivante si ce résultat vaut 0
DECFSZ 0xAA,W ; décrémente le registre 0xAA, met le résultat en W et saute l’instruction suivante si ce résultat vaut 0
INCF 0xAA, F ; incrémente le registre 0xAA, met le résultat en 0xAA
INCF 0xAA,W ; incrémente le registre 0xAA, met le résultat en W
INCFSZ 0xAA, F ; incrémente le registre 0xAA, met le résultat en 0xAA et saute l’instruction suivante si ce résultat vaut 0
INCFSZ 0xAA,W ; incrémente le registre 0xAA, met le résultat en W et saute l’instruction suivante si ce résultat vaut 0
IORWF 0xAA, F ; OU logique entre W et le registre 0xAA, met le résultat en 0xAA
IORWF 0xAA,W ; OU logique entre W et le registre 0xAA, met le résultat en W
MOVF 0xAA, F ; copie le contenu du registre 0xAA vers lui-même. Permet de tester si ce contenu est égal à 0
MOVF 0xAA,W ; copie le contenu du registre 0xAA vers W
NOP ; pas d’opération
RLF 0xAA, F ; décale le contenu du registre 0xAA d’un bit vers la gauche (multiplication par 2), le bit sortant va dans le carry, et le bit du carry rentre dans le registre comme bit de poids faible. Le résultat de cette opération est mis dans le registre 0xAA
RLF 0xAA,W ; décale le contenu du registre 0xAA d’un bit vers la gauche (multiplication par 2), le bit sortant va dans le carry, et le bit du carry rentre dans le registre comme bit de poids faible. Le résultat de cette opération est mis dans le registre W (le registre 0xAA garde donc sa valeur initiale)
RRF 0xAA, F ; décale le contenu du registre 0xAA d’un bit vers la droite (division par 2), le bit sortant va dans le carry, et le bit du carry rentre dans le registre comme bit de poids faible. Le résultat de cette opération est mis dans le registre 0xAA
RRF 0xAA,W ; décale le contenu du registre 0xAA d’un bit vers la droite (multiplication par 2), le bit sortant va dans le carry, et le bit du carry rentre dans le registre comme bit de poids faible. Le résultat de cette opération est mis dans le registre W (le registre 0xAA garde donc sa valeur initiale)
SUBWF 0xAA, F ; Soustrait le contenu du registre W du contenu du registre 0xAA, met le résultat en 0xAA
SUBWF 0xAA,W ; Soustrait le contenu du registre W du contenu du registre 0xAA, met le résultat en W
SWAPF 0xAA, F ; intervertit les 4 bits de poids fort et les 4 bits de poids faible du registre 0xAA, met le résultat en 0xAA
SWAPF 0xAA,W ; intervertit les 4 bits de poids fort et les 4 bits de poids faible du registre 0xAA, met le résultat en W
XORWF 0xAA, F ; OU exclusif logique entre W et le registre 0xAA, met le résultat en 0xAA
XORWF 0xAA,W ; OU exclusif logique entre W et le registre 0xAA, met le résultat en W
BCF 0xAA,3 ; met à 0 le bit 3 du registre 0xAA
BSF 0xAA,3 ; met à 1 le bit 3 du registre 0xAA
BTFSC 0xAA,3 ; teste le bit 3 du registre 0xAA. S’il est à 0, l’instruction suivante n’est pas exécutée
BTFSS 0xAA,3 ; teste le bit 3 du registre 0xAA. S’il est à 1, l’instruction suivante n’est pas exécutée
ADDLW 0xBB ; ajoute 0xBB à W et met le résultat dans W
ANDLW 0xBB ; ET logique entre W et 0xBB, met le résultat dans W
CALL adresse ; appel à une sous-routine
CLRWDT ; Met à 0 le watchdog timer
GOTO adresse ; aller à l’adresse
IORLW 0xBB ; OU logique entre W et 0xBB, met le résultat dans W
MOVLW 0xBB ; met la valeur 0xBB dans W
RETFIE ; retour d’un programme d’interruption
RETLW 0xBB ; retour d’une sous-routine en mettant au passage la valeur 0xBB dans W
RETURN ; retour d’une sous-routine
SLEEP ; mise en sommeil du micro-contrôleur
SUBLW 0xBB ; Soustrait la valeur 0xBB à W et met le résultat dans W
XORLW 0xBB ; Ou exclusif logique entre la valeur 0xBB et W, le résultat est mis dans W
 
Le tableau ci-dessus montre comment l’instruction sur 14 bits est codée et surtout quels sont les bits Z et C qui sont affectés par l’opération.
Publié par Alan Cartman le 27 juillet 2016

OpenPGP card, la carte à puce pour sécuriser les emails

OpenPGP card est un concept intéressant pour sécuriser les échanges par email. L’idée est de stocker dans une carte à puce les clés privées GnuPG, de sorte que d’une part elles ne soient pas sur le PC (donc moins vulnérables, même si les clés privées GnuPG sont stockées sur le PC chiffrées via une passphrase), que d’autre part elles ne soient jamais communiquées à l’extérieur de la puce, et enfin qu’elles soient protégées par un code PIN à 3 essais qui ensuite bloque la carte (déblocage possible via un code PIN administrateur).
GnuPG peut être paramétré pour utiliser cette carte à puce, que l’on insèrera dans un lecteur PCSC, au lieu du traditionnel fichier clé privée protégé par passphrase. Ainsi paramétré, GnuPG demandera à l’utilisateur son code PIN plutôt que sa passphrase.
La puce réalise des opérations cryptographiques, c’est un passage obligé si l’on veut qu’elle ne communique rien de secret à l’extérieur, mais elle en fait le minimum vu sa faible puissance de calcul. Dans une opération de déchiffrement, par exemple, elle ne fait que calculer (et communiquer au PC) la clé de session symétrique à utiliser ; c’est ensuite le PC qui déchiffre le message à l’aide de cette clé de session.
Cette initiative rejoint mon idée initiale de chiffrer des communications à l’aide d’une carte à puce, système pour lequel j’ai déjà réfléchi à des spécifications et que je compte implémenter sur une Silvercard. A deux bémols près.
Premier bémol, OpenPGP card n’est qu’une spécification que tout un chacun peut implémenter sur la carte à puce de son choix. Quelques implémentations sur des cartes à puce réelles ont été faites, comme sur la BasicCard, mais ces cartes ne semblent pas si faciles à dégoter. La piste la plus simple semble être de devenir Fellow de la FSF (Free Software Foundation) et ainsi avoir la possibilité d’obtenir cette Fellowship Smartcard. Après, il faut se cogner tout le paramétrage de GnuPG, sans se tromper car sinon on est vite fait de générer une faille de sécurité. Bref, c’est pas gagné.
Deuxième bémol, non seulement la spécification montre que les concepteurs de la carte à puce ont succombé aux sirènes des cartes modernes à base de fichiers plus compliqués les uns que les autres (le concept de fichiers étant complètement inutile à mon avis, les cartes de la génération d’avant fonctionnaient très bien sans le moindre fichier), mais ils ont aussi fait de leur concept un fourre-tout qui dépasse du cadre initial de la simple protection hard des clés privées. Du coup, l’implémentation de la spécification sur une carte comme la Silvercard, par exemple, est impossible. Seules les cartes « bêtes de course » sont éligibles.
Le concept est intéressant (la preuve, j’ai la même idée), mais la simplicité n’est pas au rendez-vous :
  • Cartes pré-programmées difficiles à trouver
  • Spécification trop compliquée, donc implémentation difficile
  • Paramétrage et utilisation pour informaticiens
Il y a moyen de faire beaucoup plus simple.
Update : j’ai trouvé un revendeur US qui propose la carte à 15$. A voir.

2 liens intéressants pour approfondir le sujet :
http://connect.ed-diamond.com/GNU-Linux-Magazine/GLMF-123/Utilisation-de-smartcards-GnuPG-V2-au-quotidien-Partie-1

Publié le 27 juillet 2016 par Alan Cartman


lundi 25 juillet 2016

Fonctionnement des cartes à puce hybrides à NFC

Nous avons vu dans un précédent article comment fonctionne une carte à puce standard. C’est très intéressant de le savoir, sauf que beaucoup de cartes récentes sont hybrides : on voit la présence d’une puce, mais elles fonctionnent aussi en sans contact.
C’est le cas notamment des pass navigo, des cartes bancaires sans contact, de la carte MOBIB (équivalent du NAVIGO à Bruxelles), des cartes SNCF des militaires, etc.

Ces cartes sont équipées d’une puce qui sait fonctionner dans les 2 environnements : avec contact et sans contact.
Avec contact, on a vu que c’est le lecteur qui apporte l’alimentation, l’horloge et le reset à chaud. La communication se fait elle sur une patte précise, le lecteur initiant chaque échange et la carte à puce ne faisant que répondre (pour éviter les collisions).

En mode sans contact, cela fonctionne quasiment de la même manière. A partir du moment où la carte est approchée du lecteur, elle baigne dans un champ électromagnétique sous forme d’une porteuse à 13.56 Mhz accompagnée de 2 sous-porteuses.
La carte NFC comporte une antenne accordée sur la fréquence de 13.56 Mhz. Cette fréquence a été choisie car elle permet de se contenter d’une antenne de taille très réduite (2 à 3 tours de cuivre associés à un petit condensateur de quelques pico-farads), donc facilement noyable dans le plastique d’une carte à puce, et surtout car elle permet un débit de communication en bauds qui est … plus élevé que le débit obtenu avec un lecteur de carte à puce !
La porteuse à 13.56 Mhz du lecteur passe dans un redresseur limiteur de tension et alimente la puce en énergie électrique.
Cette même porteuse passe dans un circuit récupérateur d’horloge, qui génère un signal d’horloge pour la puce (à partir de la fréquence de la porteuse).
Un circuit modulateur/démodulateur est capable de décoder les deux sous-porteuses modulées (ou de moduler les 2 sous-porteuses si c’est la puce qui parle). Ces circuits peuvent gérer de la modulation d’amplitude, de fréquence ou de phase.
Ainsi équipée, la puce se croirait presque dans son environnement « à contact » habituel, la vitesse en plus (dans le domaine des transports, comme NAVIGO, il n’est pas rare d’observer un échange de 6 APDU en moins de 140 ms).
Presque, car il y a quelques petites différences. Citons notamment le fait que la carte n’envoie pas un ATR dès qu’elle reçoit l’alimentation électrique : elle attend que le lecteur envoie un WUPA ou WUPB (Wake Up Type A ou type B. Cf norme ISO 14443), et à ce moment-là seulement elle répond par un ATQA ou ATQB (Answer to ReQuest de type A ou B), équivalent d’un ATR.
Citons également le fait que, contrairement au mode contact dans lequel une seule carte peut rentrer à la fois dans le lecteur, en mode sans contact plusieurs cartes peuvent se retrouver dans le champ électromagnétique du lecteur. Le protocole doit donc savoir gérer les collisions.
Bien sûr, les cartes hybrides ont un logiciel adapté à leur côté dual. Les cartes bancaires, par exemple, ne disposent que du fichier 1PAY.SYS.DDF01 si elles sont uniquement avec contact, alors qu’elles disposent en plus du fichier 2PAY.SYS.DDF01 lorsqu’elles gèrent également le sans contact.
Autre différence entre le sans et avec contact : en "sans contact" on ne peut pas taper son code PIN (c’est le but du sans contact). Donc la sécurité est forcément amoindrie, comme on peut le voir dans cette vidéo, qui montre que le sans contact appliqué à la carte bancaire est une hérésie (c’est un avis perso).
Publié par Alan Cartman le 25 juillet 2016

dimanche 24 juillet 2016

Edito du 24 juillet 2016

On est dimanche, un dimanche passé en famille. Je lève le pieds sur les cartes à puce.

Cette semaine j'ai passé pas mal de temps sur le blog, au détriment de mes travaux personnels sur les cartes à puce.

Les statistiques du site ne sont pas encourageantes, même si le blog est en ligne depuis 8 jours seulement.

Elles montrent clairement que plus les articles deviennent techniques, moins ils intéressent les gens. On verra si cette tendance se confirme à l'usage. Si c'est le cas, je continuerai mes travaux dans mon coin, sans perdre de l’énergie à les partager.

Comme je ne peux pas programmer ma Silvercard, vu que mon programmateur est quelque part en transit entre la Chine et la France, je pense de plus en plus à me programmer un analyseur de cartes bancaires EMV donnant, dans une belle interface graphique Linux, le pedigree des cartes. J'étais hésitant car les quelques articles que j'avais lu sur le sujet avaient l'air d'indiquer que lire la zone de transactions d'une carte EMV ne pouvait se faire qu'en envoyant une commande GET PROCESSING OPTIONS à la carte, ce qui avait la fâcheuse conséquence d'incrémenter le compteur de transactions qu'il y a dans la carte (et quand on atteint la valeur max, la carte se désactive définitivement). Cela ne donnait donc pas envie de se lancer.

Cependant, je suis tombé sur un article de Patrick GUEULE qui présente une méthode pour extraire ces infos d'une carte EMV sans envoyer cette commande. Son programme en BASIC (langage que je ne maitrise pas, mais qui n'est pas difficile à lire) va être une source d'info très intéressante dans cette direction.

Voilou, voilou. Bon week-end à tous.

Publié par Alan Cartman le 24 juillet 2016

samedi 23 juillet 2016

Silvercard : le PIC16F876


Nous avons vu qu'une Silvercard est composée d'un PIC16F876 (ou PIC16F877 selon les sources) et d'une EEPROM 24LC64. Etre capable de programmer une Silvercard, c'est être capable de programmer un PIC16F876, donc allons faire le tour des fonctionnalités intéressantes de la bête dans cet article.

Tout ce qui y à savoir sur un PIC16F876 est écrit dans sa datasheet. Néanmoins il n'est nul besoin d'étudier les 218 pages du document pour apprendre à le programmer dans le cadre d'une silvercard. En effet, dans une silvercard, le PIC est câblé de manière particulière (peu de pattes connectées) de sorte que seules peu de fonctionnalités nous intéressent.

Rappelons le câblage interne d'une Silvercard :

Le PIC16F876 comporte :
Une zone pour le programme de 8 Ko
De la RAM pour stocker des valeurs volatiles de 368 octets
Une zone EEPROM interne de 256 octets

Prenons chacun des ces éléments dans l'ordre.

La zone pour le programme


La figure ci-dessus montre la zone pour le programme. On y voit en bas les 0x2000 adresses (soit 8K) numérotées de 0x0000 à 0x1FFF. On notera que pour pouvoir adresser toute cette plage d'adresses il faut 13 bits (0x1FFF est codé sur 13 bits).

Chaque adresse peut comporter une instruction de 14 bits de large. On regardera le jeu d'instruction dans un autre article.

Revenons à l'adressage car il comporte une astuce qu'il convient de bien comprendre. En effet, comme dans un micro-processeur normal, dans un micro-contrôleur il y a des registres.

Le premier, celui qui nous intéresse dans le cadre de l'adressage, s'appelle PC (Program Counter). C'est le registre qui contient l'adresse de l'instruction que le micro-contrôleur est en train d'exécuter. Vous voyez tout de suite le problème : comment parcourir un espace d'adressage sur 13 bits avec un registre qui ne contient que 8 bits ? C'est impossible. C'est pourquoi apparaît cette notion de page que l'on voit sur le schéma.


Comme on peut le voir ci-dessus un registre en RAM appelé PCLATH intervient dans la construction de l'adresse complète de 13 bits : [les 5 bits de poids faible de PCLATH][les 8 bits de PC] ce qui au final fait bien une adresse sur 13 bits.

La conséquence de ce point est qu'il faut normalement faire attention quand on fait un GOTO ou un CALL à ce que la destination soit bien dans la même page. Si ce n'est pas le cas, il faut faire attention à ce que les bits 4 et 3 de PCLATH contiennent bien le numéro de la page dans laquelle se situe la destination du GOTO ou du CALL.


Normalement c'est le genre de détail qui doit être pris en compte par le compilateur, sauf que je ne sais pas encore à ce stade si gpasm le fait. En fait, on n'est pas confronté au problème tant que notre code n'a pas atteint la taille minimale de 2K. Je ne sais pas encore si mon programme atteindra cette taille ; il faut juste avoir en tête que si cela se produit, il faudra vérifier que cette subtilité est bien gérée par le compilo. Si ce n'est pas le cas, il faudra faire attention, selon un exemple donné dans le datasheet :

 

Il faut faire attention au fait que l'adresse 0x0000 et l'adresse 0x0004 contiennent deux « vecteurs », l'un pour le reset du PIC, l'autre pour l'interruption. Je mets « vecteur » entre guillemets car c'est un abus de langage. En effet, traditionnellement un vecteur contient une adresse à laquelle se brancher. Ici, ces cases comportent bien une instruction qui sera exécutée.

En clair, au boot, le PIC commence par exécuter l'instruction présente à l'adresse 0, et lors d'une interruption il se branche à l'adresse 4. Autant dire qu'il est quasiment impératif de commencer son programme par un GOTO sinon on exécute le programme d'interruption dès l'adresse 4.

L'interruption sera un mécanisme du PIC non utilisé dans le cadre de la Silvercard car … la patte correspondante n'est branchée à rien.

A noter que le PIC comporte aussi une zone de pile de 8 emplacements mémoire. Cette pile est située dans une zone particulière du PIC qui n'empiète pas sur l'espace d'adressage du programme. Cette zone de pile contient les adresses de retour lors des CALL. En effet, lorsqu'on fait un CALL on se branche ailleurs dans le programme, et on exécute jusqu'à ce qu'on rencontre l'instruction RETURN. A ce moment-là, on est censé revenir à l'instruction qui suivait immédiatement le CALL (ce qu'on appelle l'adresse de retour). Il faut donc avoir mémorisé cette adresse. C'est dans la pile que le micro-contrôleur mémorise l'adresse de retour.

La gestion de la pile est indépendante du programmeur. Quand on fait des CALL on empile, quand on fait des RETURN on dépile. C'est aussi simple que cela. Sauf que, comme il n'y a que 8 emplacements de pile, il faut faire attention de ne pas faire plus de 8 CALL imbriqués dans ses programmes. Le risque c'est que, si on fait des CALL vers des routines qui elles-mêmes font des CALL vers d'autres routines qui font des CALL, etc. on va vite avoir plus de 8 niveaux de CALL imbriqués. Et comme la pile est cyclique, l'adresse de retour du 9ème CALL vient écraser l'adresse de retour du 1er CALL et ainsi de suite. Donc si l'on dépasse 8 CALL imbriqués, le programme part assurément en cacahuète.

Bon bien, voilà, on a fait le tour de tout ce qu'il y a à savoir sur la zone de programme. Après, il faut pratiquer.

La zone de RAM de 368 octets


La figure ci-dessus montre l'organisation des 368 octets de RAM dans le PIC. On voit que la RAM est organisée en 4 banques de 128 octets chacune. On pourrait croire à tort que toute cette RAM est à disposition du programmeur. C'est faux car toutes les cases qui ont un nom sont des registres, et chaque bit de ces registres a un rôle bien particulier qui est documenté dans le datasheet. Les cases grises correspondent à des cases inaccessibles donc inutilisables. Reste à la disposition du programmeur seulement les « general purpose registers ».

Dieu merci, il n'y a pas besoin de bosser la signification de tous les bits de tous les registres pour utiliser notre PIC dans sa carte à puce.

Un des registres les plus important est le registre STATUS (accessible aux adresses RAM 0x03, 0x83, 0x103 ou 0x183). Ce registre contient le bit Z qui se met à 1 quand une opération a généré un résultat égal à 0, et le bit C (Carry) qui se met à un quand un calcul a donné lieu à un débordement. Les bits 5 (RP0) et 6 (RP1) du registre STATUS permettent de choisir dans laquelle des 4 banques on travaille selon le tableau suivant :


Les deux autres registres importants pour nous sont PORTB et TRISB. En effet, notre PIC a sa plusieurs ports d'entrées/sorties, dont l'un, le PORT B de 8 bits, a sa patte 7 connectée à la patte I/O de la puce de la carte à puce.

Le bit 7 du port B permet donc lorsqu'on y écrit, d'envoyer des données de la carte à puce vers le monde extérieur, et lorsqu'on y lit, de recevoir des données (APDU) du monde extérieur.

Le registre TRISB permet lui de paramétrer en entrée ou en sortie chaque bit du port B. Si l'on met le bit 7 du registre TRISB à 1 alors le bit 7 du port B est en entrée. A 0 le bit 7 du port B sera en sortie.

Dans le cadre de l'utilisation du PIC dans la Silvercard, on veillera à ce que le bit 7 de TRISB soit à 1 en permanence, sauf les rares fois où l'on a quelque chose à émettre.

Tous les registres dont le noms commencent par EE sont impliqués dans la lecture ou l'écriture des données dans la zone d'EEPROM interne au PIC.

Un autre registre qui peut être intéressant est celui de l'adressage indirect (adresse 0, 0x80, 0x100 et 0x180). En fait, la lecture ou l'écriture dans cette case de RAM se fait en réalité dans la case de RAM dont l'adresse a été mise dans le registre FSR.

Voilà pratiquement tout ce qu'il y a à savoir sur la RAM pour utiliser le PIC dans le cadre d'une Silvercard.

La zone d'EEPROM interne de 256 octets

Le PIC comporte une zone de mémoire interne de 256 octets. C'est bien peu par rapport aux 8 Ko contenus dans l'EEPROM externe 24LC64. Il faut voir cependant qu'une donnée est beaucoup plus en sécurité dans l'EEPROM à l'intérieur du PIC (qui est protégeable en lecture) que dans l'EEPROM à l'extérieur du PIC (qui n'est pas protégeable en lecture). Une donnée sensible, comme une clé de cryptographie par exemple doit être mise en EEPROM interne.

Accéder en lecture ou en écriture dans la zone d'EEPROM interne est assez compliqué. En tout cas assez compliqué pour que la datasheet du PIC donne carrément les deux routines pour le faire proprement. Les voici :

Lecture :


On met dans ADDR (adresse qu'on choisit où l'on veut en RAM) l'adresse de la case d'EEPROM interne à lire (entre 0 et 255) et on appelle la routine ci-dessus. On récupère la donnée lue dans le registre W.

Tiens, c'est la première fois qu'on parle du registre W. Ne le cherchez pas en RAM, il n'y est pas. C'est d'ailleurs le seul registre qui n'est pas en RAM. Son petit nom dans tous les micro-processeurs du monde c'est « l'accumulateur ». L'accumulateur du PIC s'appelle W.

Bref, on voit qu'avec la routine ci-dessus, c'est facile d'aller lire une case d'EEPROM interne.

Ecriture :


On voit que l'écriture en EEPROM est plus compliquée que la lecture. On met dans ADDR et VALUE (2 adresses de RAM qu'on choisit arbitrairement) l'adresse de la case d'EEPROM dans laquelle on souhaite écrire, et la valeur (octet) à y écrire, puis on appelle la routine ci-dessus qui réalise l'écriture.

Même si la routine est compliquée, comme elle est donnée directement par le constructeur son utilisation est simple.

Au final, avec les deux routines données par le constructeur, lire ou écrire dans l'EEPROM interne est très facile.

Eh bien, mine de rien, on vient de voir comment ça se passe pour la zone de programme, la zone de RAM et la zone d'EEPROM.

Il ne reste plus qu'à voir le jeu d'instructions du PIC et on en aura déjà fait le tour, au moins en ce qui concerne son utilisation dans le cadre d'une Silvercard.

Jeu d'instruction du PIC est le suivant.


Le tableau ci-dessus montre les 35 instructions du PIC, avec la manière dont l'instruction sur 14 bits sera construite, et aussi les bits de statut qui sont impactés par l'instruction.

Il s'agit d'instructions très basiques, que nous verrons dans un prochain article.

Publié par Alan Cartman le 23 juillet 2016


















Pour ceux qui croient encore que le sans-contact de leur carte bleue est inoffensif

Parfois une démo est mieux qu'un long discours. Sachez que vous pouvez demander à votre banque de désactiver cette saloperie, idéalement avant que la banque vous livre la carte.


jeudi 21 juillet 2016

Discuter avec une carte à puce en langage C

Dans un article précédent nous avons utilisé gscriptor pour envoyer un APDU à une carte à puce. Voyons donc maintenant comment faire exactement la même chose mais en langage C.

En effet, gscriptor c'est bien beau, mais si l'on veut créer une application à nous à base de cartes à puce, on aura très certainement besoin que notre application puisse discuter avec la carte.

Le lecteur de carte à puce est branché sur le port USB, et le port USB c'est coton à programmer en direct. La bonne nouvelle c'est qu'on va utiliser l'API PCSC qui va nous simplifier la vie puisqu'elle nous cache toute cette gestion de l'USB.

La mauvaise nouvelle c'est que, comme à chaque fois avec ce genre d'API, le code à écrire est absolument imbitable ! Désolé mais il n'y a pas d'autre mot :)

En fait, c'est peu important. L'important c'est de chopper une routine qui marche bien et de la reprendre dans son programme quand on en a besoin. Et la routine qui marche, la voici. Je peux vous dire que j'ai eu du mal à la faire marcher mais au final elle marche tip top.

Enregistrez ça dans un fichier discut.c

#include <stdio.h>
#include <stdlib.h>
#include <PCSC/winscard.h>

#define CHECK(f, rv) \
 if (SCARD_S_SUCCESS != rv) \
 { \
  printf(f ": %s\n", pcsc_stringify_error(rv)); \
  return -1; \
 }

int main()
{
int i;
LONG rv;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol,dwRecvLength,dwReaders;
LPTSTR mszReaders;
SCARD_IO_REQUEST pioSendPci;
BYTE pbRecvBuffer[258];
DWORD dwState, dwProtocol, dwAtrLen, dwReaderLen;
BYTE *pbAtr = NULL;
char *pcReader = NULL;
BYTE cmd1[] = {00,0x84,00,00,0x08};

rv=SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
CHECK("SCardEstablishContext", rv)
rv=SCardListReaders(hContext, NULL, NULL, &dwReaders);
CHECK("SCardListReaders", rv)
mszReaders=calloc(dwReaders, sizeof(char));
rv=SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
printf("Reader name: %s\n", mszReaders);
rv = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED,SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
CHECK("SCardConnect", rv)
dwReaderLen = SCARD_AUTOALLOCATE;
dwAtrLen = SCARD_AUTOALLOCATE;
rv = SCardStatus(hCard, (LPSTR)&pcReader, &dwReaderLen, &dwState,    &dwProtocol, (LPBYTE)&pbAtr, &dwAtrLen);
CHECK("SCardStatus", rv)
printf("ATR : ");
for(i=0;i<dwAtrLen;i++) printf("%x ",pbAtr[i]);
printf("\n");
pioSendPci = *SCARD_PCI_T0;
dwRecvLength = sizeof(pbRecvBuffer);
rv = SCardTransmit(hCard, &pioSendPci, cmd1, sizeof(cmd1), NULL, pbRecvBuffer, &dwRecvLength);
CHECK("SCardTransmit", rv)
printf("response: ");
for(i=0; i<dwRecvLength; i++)
printf("%02X ", pbRecvBuffer[i]);
printf("\n");
}
Et compilez le sous Linux en tapant la commande :
gcc discut.c -o discut -I /usr/include/PCSC -lpcsclite

Cela crée l'exécutable discut qui fait exactement ce qu'on a fait avec gscriptor, à savoir envoyer à la carte l'ADPU 00 84 00 00 08 et affiche en retour les 8 octets aléatoires renvoyés par la carte (+ le 90 00 final).

Voyons ce que cela donne à l'exécution :

D'abord, je lance le programme sans qu'aucun lecteur ne soit connecté au port USB :
./discut
SCardListReaders: Cannot find a smart card reader.

Ensuite, je relance le programme, avec un lecteur de carte connecté mais aucune carte dans le lecteur :
./discut
Reader name: Gemalto PC Twin Reader (73131FC4) 00 00
SCardConnect: No smart card inserted.


Et pour finir, je relance le programme en ayant au préalable branché le lecteur sur le port USB avec ma carte bancaire EMV dedans :
./discut
Reader name: Gemalto PC Twin Reader (73131FC4) 00 00
ATR : 3b 65 0 0 20 63 cb 6a 0
response: E4 5E 36 A7 9D B9 B8 DF 90 00


./discut
Reader name: Gemalto PC Twin Reader (73131FC4) 00 00
ATR : 3b 65 0 0 20 63 cb 6a 0
response: 23 31 9F 6D AE BD 1C 55 90 00


Conclusion : le programme est parfaitement fonctionnel, et réutilisable dans une application. On constate également que l'ATR lu est bien le bon.

Nous voyons, pour faire simple et sans rentrer dans les détails, qu'il faut successivement appeler les fonctions :

SCardEstablishContext =>pour initialiser le contexte
SCardListReaders => pour lire la liste des lecteurs de cartes détectés par la couche PCSC
SCardConnect => pour se connecter à la carte
SCardStatus => pour lire le statut de la carte (et entre autres son ATR)
SCardTransmit => pour envoyer dans la carte un APDU et lire la réponse à l'APDU

Et à chaque fois avec un passage de paramètres pas piqué des vers. Pourquoi faire simple quand on peut faire compliqué.

Bon, la bonne nouvelle, c'est qu'au final, en quelques lignes de C, on a quasiment ré-écrit gscriptor (à l'interface graphique près).

Publié le 21 juillet 2016 par Alan Cartman

Silvercard et autres cartes à puce à base de PIC

Il y a 3 types de cartes à puce. Tout d’abord, et ce sont les plus répandues, les cartes émises par les fondeurs de cartes. C’est le cas de toutes les cartes bancaires, navigo, et autres. Ces cartes ont ce qu’on appelle dans le jargon un « masque », c’est-à-dire un logiciel intégré en dur sur la base d’un système d’exploitation maison dédié. Ces cartes sont programmées une fois pour toutes en usine.

Ensuite il y a les cartes programmables de haut niveau, comme les java cards ou les basic cards. Il s’agit de cartes comportant un système d’exploitation capable de faire tourner des applications écrites dans un langage de haut niveau (java, basic) et qui surtout fournit aux programmeurs de la carte des fonctions de haut niveau déjà écrites (briques logicielles) permettant l’utilisation directe de composants logiciels déjà programmés et réutilisables, sur la gestion des entrées/sorties par exemple ou pour l’utilisation de fonctions cryptographiques.

Enfin, il y a les cartes programmables de bas niveau. Ce sont celles qui m’intéressent et qui font l’objet de cet article. Dans cette catégorie, on retrouve les cartes wafer gold, silvercard ou greencard. Ici pas de brique logicielle ni de composant logiciel réutilisable. La carte est programmable mais est fournie nue, sans rien de logiciel dedans. Le langage de prédilection pour les programmer est l’assembleur, voire le C dans le meilleur des cas (mais pas de java ni de basic).
Dit comme cela, ces cartes semblent moins intéressantes que les cartes programmables de haut niveau. Elles ont pourtant un intérêt, cela dépend de ce que l’on veut faire. Si l’on veut développer une application qui ne nécessite pas trop de mémoire, elles sont faciles à programmer et l’investissement initial est minime (un simple programmateur de cartes à quelques dizaines d’euros).
En tout cas, pour le projet que j’ai en tête, une silvercard est largement suffisante. Présentons donc cette famille de cartes à puce dans le détail.
Des puces à micro-contrôleur
Si les années 60-70 ont vu l’explosion de l’utilisation des micro-processeurs, les années 80-90 ont-elles été le théâtre de l’explosion de l’utilisation des micro-contrôleurs. Un micro-contrôleur c’est un micro-processeur simple, mais avec de la RAM, de la PROM (ou mieux de l’EEPROM) et des entrées/sorties dedans. En fait, dans un micro-contrôleur on a pratiquement un ordinateur complet dans une seule puce à quelques euros.
Bien sûr les micro-contrôleurs ne sont pas destinés à équiper des ordinateurs, mais plutôt des lave-vaisselle, des robots industriels, ou des lave-linge. Dans ce cadre sont apparus sur le marché plusieurs marques de micro-contrôleurs.
Dans les années 90, l’explosion de l’utilisation des cartes à puce a amené certains fabricants à avoir l’idée d’intégrer des micro-contrôleurs standards dans des cartes à puce. C’est ainsi que sont apparues ces cartes programmables de bas niveau. Deux fabricants de micro-contrôleurs en particulier ont bénéficié de cette dynamique : Microchip qui fabrique les micro-contrôleurs PIC, et Atmel qui fabrique les micro-contrôleurs du même nom.
Ainsi on retrouve des cartes programmables de bas niveau à base de micro-contrôleurs PIC comme les wafer gold cards, les silvercards, ou les greencards. D’autres cartes comme la Funcard ou la Jupiter embarquent un micro-contrôleur Atmel.
La différence entre ces cartes tient en la référence exacte du micro-contrôleur embarqué ainsi que la quantité de mémoire EEPROM l’accompagnant. En effet, la quantité de mémoire nécessaire au développement d’applications sérieuses n’étant généralement pas compatible avec le peu de mémoire embarquée dans le micro-contrôleur, les cartes embarquent une mémoire EEPROM en plus du micro-contrôleur.
Les cartes à puce à base de PIC
Nous voilà donc au cœur du sujet. L’architecture interne de ces cartes est toujours la même : les pattes externes de la carte à puce sont reliées en interne aux pattes équivalentes du micro-contrôleur (la patte horloge externe par exemple est reliée en interne à la patte horloge du micro-contrôleur, idem pour l’alimentation, etc.), y compris la patte input/ouput qui elle est reliée à l’une des pattes d’un des ports de communication du micro-contrôleur. La mémoire EEPROM est elle aussi reliée à des pattes internes du micro-contrôleur (ce qui permet au PIC de lire ou d’écrire dedans), mais n’est pas accessible depuis l’extérieur de la carte à puce.
Cette mémoire EEPROM interne, non accessible depuis l’extérieur de la puce, pose problème quant à son remplissage initial puisque justement … elle n’est pas accessible depuis l’extérieur de la puce. On est donc obligé de passer par un programme spécial, appelé « loader », à charger dans le PIC et dont le but est de prendre les données qu’on lui envoie et c’est le PIC qui transfère ces données vers l’EEPROM. Une fois que l’EEPROM est remplie, on efface le loader du PIC et on y met le programme final.
D’un point de vue de la sécurité le PIC est protégé, car il dispose d’un bit de sécurité qu’on peut positionner à 1 et qui empêche de pouvoir le lire pour y analyser le programme qu’il contient. Ce n’est pas le cas de l’EEPROM. Il faut donc faire attention à mettre les données sensibles dans le PIC et non dans l’EEPROM quand on design un système. En effet, si votre PIC est protégé en lecture, un assaillant peut toujours écraser votre programme par un programme à lui qui communique à l’extérieur le contenu de l’EEPROM.
La carte wafer gold est une carte à puce de couleur or renfermant un PIC16F84 et une mémoire EEPROM 24LC16B (de 2 Ko) câblée selon le schéma ci-dessous.

Il est à noter qu’il est tout à fait possible de recréer ces cartes en mettant sur un bout d’epoxy le PIC, l’EEPROM et en les reliant comme sur le schéma, en reliant le tout à des connexions de carte à puce.
La silvercard est une carte à puce de couleur argent refermant un PIC16F876 (ou 16F877) et une EEPROM 24LC64 (8 Ko) câblée selon le schéma ci-dessous.

On trouve aussi des greencards  (PIC16F876 + 24C128), des greencards 2 (PIC16F876 + 24C256), des bluecards, des emeraldcards, des canarycards.
Programmation de ces cartes
Hormis le fait qu’il faut disposer d’un programmateur physique, c’est-à-dire un dispositif à même d’injecter dans le PIC qui est dans la carte le programme qu’on a écrit pour lui (un simple lecteur de carte à puce en est incapable), encore faut-il savoir écrire un programme pour un PIC.
Et là il faut trois choses :
  • Un : maitriser un langage de programmation supporté
  • Deux : être capable de compiler le programme qu’on a écrit
  • Trois : connaitre parfaitement le fonctionnement du PIC
Concernant le point 3, il n’y a pas 36 manières de faire : il faut récupérer et bûcher le datasheet du PIC sur le site de Microchip.
Concernant le point 1, en gros, il y a le choix entre 2 langages : le C ou l’assembleur. Le problème du C, c’est qu’on ne maitrise pas aussi bien la bête qu’en assembleur, et surtout les compilateurs C pour PIC sont payants à ma connaissance.
Concernant le point 2, il faut un compilateur. Soit on achète un compilateur C, soit on installe un compilateur assembleur gratuit, son on programme son propre compilateur. Cela parait bizarre de suggérer de programmer son propre compilateur, mais en réalité c’est assez facile, le PIC ne connaissant que 35 instructions assembleur. Je l’ai fait plus jeune pour le PIC16F84, le compilateur ne faisait que quelques centaines de lignes de C. J’ai aussi fait dernièrement un désassembleur de PIC16F876 en C, que je présenterai dans un prochain article. Sous Linux, il suffit d’installer le compilateur ASM PIC du GNU, gpasm (sudo apt-get install gputils).
Les compilateurs produisent des fichiers textes au format hex intel.
Il va de soi que, quel que soit le projet qu’on envisage de faire avec une PIC card, il y a des routines assembleur incontournables qui seront nécessairement à mettre dans le programme. On peut citer :
  • Une routine capable d’émettre un octet pour un APDU en convention directe ( !)
  • Une routine capable d’émettre un octet pour un APDU en convention inverse ( !)
  • Une routine capable de recevoir un octet APDU en convention directe ( !)
  • Une routine capable de recevoir un octet APDU en convention inverse ( !)
  • Une routine capable de lire dans l’EEPROM interne du PIC (*)
  • Une routine capable d’écrire dans l’EEPROM interne du PIC (*)
  • Une routine capable de lire dans l’EEPROM externe ( !)
  • Une routine capable d’écrire dans l’EEPROM externe ( !)
  • Des routines de cryptographie
Il faut donc avoir ces routines dans sa boite à outil. Il se trouve que les routines (*) sont données dans la datasheet des PIC, et les routines ( !) sont aisément retrouvables dans les programmes « loaders » (vu au-dessus) qui pullulent sur Internet.
Pour un programme personnel, il n’y a pas besoin de routines en convention directe et en convention inverse. On en choisit une. En ce qui me concerne, j’ai récupéré une routine SEND et une routine RECEIVE en convention inverse.
Concernant les routines de cryptographie, elles sont normalement indispensables. En effet, généralement si l’on utilise une application à base de carte à puce, c’est qu’il y a un processus à sécuriser. Or, dans notre époque moderne, la sécurité c’est la cryptographie.
Microchip met à disposition de la doc et une librairie pour faire de la crypto avec les PIC. En ce qui me concerne j’ai l’intention d’utiliser l’algorithme TEA pour sécuriser les communications. Ce sera l’objet d’un prochain article.

Piratage

Bien sûr, ce genre de carte peut servir, et a servi dans le passé, pour faire du piratage. Cependant, pour faire une bonne carte à puce de contrefaçon, il faut à la fois simuler un fonctionnement correct de la puce et reproduire le look de la partie plastique de la carte à puce.

D'aucuns seraient tentés, pour simplifier le problème du look de la partie plastique de la puce, de desceller la puce d'une vraie carte pour la remplacer par la puce d'une PIC card correctement programmée. Comme cela, ni vu ni connu je t'embrouille.

Sauf que non. Les concepteurs des PIC cards ont pensé à cette éventualité et l'ont contré en personnalisant la puce des PIC cards : elles contiennent toutes un dessin du symbole "alpha" ce qui rend les fausses puces collées très vite décelables.

Symbole alpha présent sur la puce d'une Silvercard
Publié le 21 juillet 2016 par Alan Cartman