dimanche 7 août 2016

Edito du 7 août 2016

Bonjour à tous. 

Peu d'activité sur mon blog actuellement car je prends 10 jours de vacances du côté de La Baule. Ce qui ne veut pas dire que je n'ai pas amené mon matériel avec moi en vacance, mais comme je suis en famille, je ne pianote que peu et le soir. 

Mes travaux avancent donc au ralenti mais avancent. J'ai terminé ma carte à puce de chiffrement des communications, et j'en suis à programmer le logiciel de chiffrement Linux qui interroge la puce pour en extraire la clé. Ca avance pas mal, d'autant que je prévois deux versions du soft : une première, simple et rapide à programmer, ne sera qu'un front-end à AEScrypt, tandis que la seconde, plus sécurisée car j'en maitriserai le code de A à Z, embarquera en son sein ses propres routines de chiffrement / déchiffrement AES 256 bits. 

Je fourmille d'idées pour la suite, d'autres projets à base de carte à puce programmable Silvercard. Les deux les plus importants sont les suivants : 

- Développer un système de tickets sur carte à puce, utilisable dans par exemple un cinema ou un moyen de transport. Ce projet introduira un aspect nouveau non abordé dans mon projet de carte de chiffrement actuel, à savoir qu'il faudra que la carte authentifie le lecteur, mais aussi que le lecteur officiel de la compagnie exploitante authentifie la carte. Il faudra donc embarquer de l'algorithme de crypto dans la carte, ce qui sera une nouveauté. Par rapport aux capacités de la Silvercard, le seul algo envisageable sera le Tiny Encryption Algotithm. De belles heures de debuggage en perspective. 

- Développer une carte santé, non sécurisée elle, à savoir une carte que chacun peut porter sur lui et qui contient toutes les informations relatives à la santé que l'individu veut bien y mettre : civilité, coordonnées de la personne à contacter en cas d'urgence, groupe sanguin, allergies, souhait de don d'organe ou non, hopital préféré pour une hospitalisation, souhait vis à vis de l'arrêt des soins éventuel en fin de vie, etc. Cette carte serait librement modifiable par le porteur, et librement lisible par les services de soin. Techniquement, cette carte va introduire une nouveauté pour moi : la lecture et l'écriture dans l'EEPROM externe contenue dans la Silvercard. Bref, un programme scientifique chargé pour la rentrée. D'ici fin août je ne posterai probablement plus rien. Je vais profiter de la piscine et des miens. 

@+

mardi 2 août 2016

PCSCLite, c'est quand même un peu de la daube

De retour sur le blog après plusieurs jours passés à expérimenter.

La joie qui m'a animé suite à mon premier programme m'a vite quitté. En effet, j'ai été confronté à une série de problèmes plus hardus à résoudre les uns que les autres.

Tout d'abord je me suis rendu compte que la boucle retour de mon programme faisait planter ma carte à puce. Ce que j'appelle la boucle retour c'est le retour à l'attente de l'APDU suivant lorsqu'on a traité le précédent. Gscriptor ne m'affichait la réponse de la carte que lorsque la boucle retour était oubliée. Aussi incroyable que cela puisse paraitre, mon programme ne marchait qu'à partir du moment où le code partait dans le décor ! Pas coton de trouver d'où ça venait.

Autre problème : je me suis rendu compte que ma carte rebootait entre 2 APDU. Pour une carte censée mémoriser entre 2 APDU qu'un code PIN a été entré, c'est moyen.

J'ai fini par trouver que tous mes problèmes venaient de la routine RECEIVE pompée sur la carte de déplombage de la RAI : elle n'avait pas les bonnes tempo. J'ai réussi à trouver les bonnes en analysant les tempos de la routine SEND. A ce demander si ce programme a bien permis de regarder la RAI un jour.

Bref, me voilà remis en selle puisque la correction de cette routine a non seulement fait marcher ma boucle retour, mais a aussi fait en sorte que la puce ne rebootait plus entre 2 APDU.

C'est à ce moment là qu'a surgit un problème aussi pénible : je me suis rendu compte que la couche PCSCLite filtrait à mort les réponses de ma carte à puce. En fait, on pourrait croire que PCSC n'est qu'une couche permettant d'accéder aux cartes à puce sans se soucier de la gestion de l'USB. Que nenni. PCSCLite se croit investi de la mission de vérifier que les échanges entre le PC et la carte à puce se font bien selon les standards internationaux en vigueur. Et il n'hésite pas à enlever des octets réponses s'ils ne lui plaisent pas, voire à rajouter dans la réponse de la carte un octet à lui !

En fait, on n'est même pas libre d'employer le protocole de communication que l'on veut avec sa propre carte !

J'ai vite compris que cette daube allait me poser un très gros problème. D'autant qu'il ne parait pas possible de bypasser ce comportement pénible. Je ne voyais que 2 solutions : soit bûcher les standards de communication internationaux (ce que je ne souhaitais pas faire initialement), soit se contenter d'échanges avec 2 octets de réponse de la carte par APDU seulement. En effet, PCSCLite semble laisser passer les octets SW1 et SW2 des réponses des cartes, mais commence à filtrer dès que ces octets sont accompagnés de data. ET quand je dis filtrer je suis gentil : les 3/4 du temps la couche PCSCLite informe le programme utilisateur que, de son point de vue, il y a une erreur de transmission et lui transmet ... rien (mais de quoi je me mêle ?).

Le fait de tenter de coller aux standards internationaux n'a rien donné de bon : malgré mes efforts, PCSCLite ne semblait jamais assez satisfait et continuait à filtrer.

Pour s'en sortir, restait donc la solution de ne communiquer les réponses que sur les 2 octets SW1 et SW2. Le principe est d'au lieu d'envoyer un APDU qui entraine une réponse dans laquelle il y a 32 octets, on envoie 32 APDU qui entrainent chacun un octet de réponse. On a ainsi quand même les 32 octets réponse qu'on cherche, c'est un peu plus long, mais au moins on met un gros à cette daube de PCSCLite. C'est donc la solution que j'ai choisie et mis en oeuvre.

Même en faisant comme ça, il fallait tout de même faire attention. Si SW1 vaut 0x60, par exemple, PCSCLite filtrait SW1 et SW2 ! Quelle chienlit. J'ai fini par trouver des couples SW1/SW2 qui passait sans problème la couche PCSCLite, et j'ai pu bâtir un protocole de communication avec ça.

Que d'énergie perdue et d'énergie dépensée à cause de PCSCLite. Mais bon, on final, ça marche.

Je me suis ensuite heurté au fait que, si la lecture de l'EEPROM interne du PIC ne me posait pas de problème, impossible de réussir à y écrire. Là aussi, des heures et des heures à chercher d'où le problème pouvait venir, pour finir par enfin découvrir que le problème venait d'une variable temporaire commune entre les routines EEPROM_WRITE et SEND. La séparation des variables a miraculeusement permis l'écriture dans l'EEPROM.

J'avais absolument besoin d'une routine EEPROM_WRITE qui marche pour stocker le nombre d'essais restant pour le code PIN et pour la mise à jour de la clé en EEPROM via un APDU.

Une fois tous ces problèmes résolus, j'ai pu écrire un programme gérant complètement 3 codes PIN (1 code PIN utilisateur, 1 code PIN administrateur, 1 code PIN de compromission). Ce programme, dont je ne suis pas peu fier car il m'a fallu des heures et des heures pour le debugger, est fourni ci-dessous.

J'ai pu également tester la protection du PIC activée directement dans l'injecteur InfinityUSB unlimited. Ca marche nickel. Cela se paramètre au moment de l'injection du programme dans le PIC et cela entraine le fait que la lecture du PIC ainsi verrouillé ne ramène que des 00 (pour le code du programme et pour la zone EEPROM). La clé contenue dans la puce est donc bien à l'abri avec ce mécanisme.

En fait, je suis allé bien plus loin que tout cela puisque j'ai quasiment finalisé le code la puce, qui contient maintenant beaucoup plus que le programme de gestion des 3 codes PIN présenté ci-dessous. Je développerai le produit fini dans un prochain article, probablement fin août après mes vacances.


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


;----------------------Zone de RAM --------------------------
ORG 0x60
IODATA RES 1
BIT_COUNT RES 1
PARITY RES 1
TEMPO RES 1
TEMP RES 1
CLA RES 1
INS RES 1
P1 RES 1
P2 RES 1
LE RES 1
RANDOM RES 1
PIN1GIVEN RES 1
PIN2GIVEN RES 1

ORG 0x160
EEADRW RES 1

;------------------------Zone de programme ----------------
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
CALL WAIT1
CALL WAIT1
MOVF IODATA,W
RETURN

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

EEPROM_READ ; mettre au préalable l'adresse à lire dans W
BSF STATUS,RP1
BCF STATUS,RP0
MOVWF EEADR
BSF STATUS,RP0
BCF EECON1,EEPGD
BSF EECON1,RD
BCF STATUS,RP0
MOVF EEDATA,W
BCF STATUS,RP1
RETURN
EEPROM_WRITE
BSF STATUS,RP1 ; banque 3
BSF STATUS,RP0
BTFSC EECON1,WR
GOTO $-1
BCF STATUS,RP0 ; banque 2
MOVWF EEDATA
MOVF EEADRW,W
MOVWF EEADR
BSF STATUS,RP0 ; banque 3
BCF INTCON,GIE
BSF EECON1,WREN
MOVLW 0x55
MOVWF EECON2
MOVLW 0xAA
MOVWF EECON2
BSF EECON1,WR
;BSF INTCON,GIE
BCF EECON1,WREN
BCF STATUS,RP0 ; banque 0
BCF STATUS,RP1
GOTO BOUCLE

SET_PIN_3
BSF STATUS,RP1 ; banque 2
MOVLW PINC
MOVWF EEADRW
MOVLW 0x3
CALL EEPROM_WRITE
GOTO BOUCLE
SET_PIN_2
BSF STATUS,RP1 ; banque 2
MOVLW PINC
MOVWF EEADRW
MOVLW 0x2
CALL EEPROM_WRITE
GOTO BOUCLE
SET_PIN_1
BSF STATUS,RP1 ; banque 2
MOVLW PINC
MOVWF EEADRW
MOVLW 0x1
CALL EEPROM_WRITE
GOTO BOUCLE
LOCK_CARD
BSF STATUS,RP1 ; banque 2
MOVLW LOCK
MOVWF EEADRW
MOVLW 0x1
CALL EEPROM_WRITE
GOTO BOUCLE

BAD_CLASS
MOVLW 0x6E
CALL SEND
MOVLW 0x00
CALL SEND
GOTO BOUCLE

TESTE_PIN
; Test par rapport au PIN3
MOVLW PIN30
CALL EEPROM_READ
SUBWF P1,W
BTFSC STATUS,Z
GOTO TEST_PIN3_2
; Test par rapport au PIN2
TEST_PIN2
MOVLW PIN20
CALL EEPROM_READ
SUBWF P1,W
BTFSC STATUS,Z
GOTO TEST_PIN2_2
; Test par rapport au PIN1
TEST_PIN1
MOVLW PIN10
CALL EEPROM_READ
SUBWF P1,W
BTFSC STATUS,Z
GOTO TEST_PIN1_2
BAD_PIN
MOVLW 0x63
CALL SEND
MOVLW PINC
CALL EEPROM_READ
MOVWF TEMP
DECF TEMP,F
MOVLW 0xC0
ADDWF TEMP,W
CALL SEND
MOVLW 0x2
SUBWF TEMP,W
BTFSC STATUS,Z
GOTO SET_PIN_2
MOVLW 0x1
SUBWF TEMP,W
BTFSC STATUS,Z
GOTO SET_PIN_1
GOTO LOCK_CARD

TEST_PIN3_2
MOVLW PIN31
CALL EEPROM_READ
SUBWF P2,W
BTFSS STATUS,Z
GOTO TEST_PIN2
MOVLW 0x90
CALL SEND
MOVLW 0x02
CALL SEND
GOTO LOCK_CARD
TEST_PIN2_2
MOVLW PIN21
CALL EEPROM_READ
SUBWF P2,W
BTFSS STATUS,Z
GOTO TEST_PIN1
MOVLW 0x90
CALL SEND
MOVLW 0x01
CALL SEND
MOVLW 0x01
MOVWF PIN2GIVEN
GOTO SET_PIN_3
TEST_PIN1_2
MOVLW PIN11
CALL EEPROM_READ
SUBWF P2,W
BTFSS STATUS,Z
GOTO BAD_PIN
MOVLW 0x90
CALL SEND
MOVLW 0x00
CALL SEND
MOVLW 0x01
MOVWF PIN1GIVEN
GOTO SET_PIN_3

CARD_LOCKED
MOVLW 0x6A
CALL SEND
MOVLW 0x81
CALL SEND
GOTO BOUCLE

; début du programme
INIT
BSF STATUS,RP0 ; select bank1
BCF OPTION_REG,7 ; enable pull-ups
BCF STATUS,RP0
MOVLW 0x00
MOVWF PIN1GIVEN
MOVWF PIN2GIVEN
CALL WAIT1
;Envoi de l'ATR
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
MOVWF CLA
CALL RECEIVE
MOVWF INS
CALL RECEIVE
MOVWF P1
CALL RECEIVE
MOVWF P2
CALL RECEIVE
MOVWF LE
; Verification que la classe est bien AA
MOVLW 0xAA
SUBWF CLA,W
BTFSS STATUS,Z
GOTO BAD_CLASS
; Verification si la carte est bloquée
MOVLW LOCK
CALL EEPROM_READ
MOVWF TEMPO
MOVLW 0x1
SUBWF TEMPO,W
BTFSC STATUS,Z
GOTO CARD_LOCKED
; Traitement de INS=7 (Présentation du code PIN)
MOVLW 0x7
SUBWF INS,W
BTFSC STATUS,Z
GOTO TESTE_PIN

; Instruction non reconnue
MOVLW 0x68
CALL SEND
MOVLW 0x00
CALL SEND
GOTO BOUCLE
;-----------------------Fin du programme --------------------------

;EEPROM interne
ORG 0x2100
K0 DATA 0xA5 ; key
K1 DATA 0xA4
K2 DATA 0xA4
K3 DATA 0xA4
K4 DATA 0xA4
K5 DATA 0xA4
K6 DATA 0xA4
K7 DATA 0xA4
K8 DATA 0xA4
K9 DATA 0xA4
K10 DATA 0xA4
K11 DATA 0xA4
K12 DATA 0xA4
K13 DATA 0xA4
K14 DATA 0xA4
K15 DATA 0xA5
K16 DATA 0xA4
K17 DATA 0xA4
K18 DATA 0xA4
K19 DATA 0xA4
K20 DATA 0xA4
K21 DATA 0xA4
K22 DATA 0xA4
K23 DATA 0xA4
K24 DATA 0xA4
K25 DATA 0xA4
K26 DATA 0xA4
K27 DATA 0xA4
K28 DATA 0xA4
K29 DATA 0xA4
K30 DATA 0xA4
K31 DATA 0xA4
PIN10 DATA 0x40 ; valeur du PIN1
PIN11 DATA 0x56
PINC DATA 0x3 ; nombre d'essais restants pour PIN
PIN20 DATA 0x23 ; valeur du PIN2
PIN21 DATA 0x76
PIN30 DATA 0x6 ; valeur de PIN3
PIN31 DATA 0x66
LOCK DATA 0x0 ; 0 carte non verrouillée, 1 carte verrouillée
RANDSTART
DATA 0x47
SOFTVERSION
DATA 0x01
END

Publié par Alan Cartman le 2 août 2016

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