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

Aucun commentaire: