Autor Tema: ATR de una smartcard con pic en CCS  (Leído 2375 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado sistemasorp

  • PIC10
  • *
  • Mensajes: 28
ATR de una smartcard con pic en CCS
« en: 26 de Agosto de 2009, 14:28:09 »
Hola.

Recientemente adquirí unas tarjetas goldcard (smartcard con PIC 16f84a) y quería de momento simular un ATR (answer to reset), pero con el lector de tarjetas que tengo siempre me da error, por lo que creo que el código esta mal, pero no se donde:


Código: [Seleccionar]
#include <16F84A.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading

#use delay(clock=3571200)
#use fast_io(b)

void envia_byte(char caracter);

void main()
{
   unsigned char atr[] = {0x3B,7,1,2,3,4,5,6,7};
   int indice;
   
   //setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);

   SET_TRIS_B(0);
   OUTPUT_HIGH(PIN_B7);
   for(indice = 0; indice < sizeof(atr); indice++)
   {
      envia_byte(atr[indice]);
   }
   OUTPUT_HIGH(PIN_B7);
   for(;;);
}

void envia_byte(unsigned char caracter)
{
   int contador;
   int valor = 0x80;
   int paridad = 0;

   OUTPUT_LOW(PIN_B7);
   delay_us(104);
   for(contador = 0; contador < 8; contador++)
   {
      if(caracter & valor > 0)
      {
         OUTPUT_HIGH(PIN_B7);
         paridad++;
      }
      else
      {
         OUTPUT_LOW(PIN_B7);
      }
      valor >>= 1;
      delay_us(104);
   }
   
   // paridad
   if(paridad % 2 == 0)
   {
      OUTPUT_LOW(PIN_B7);
   }
   else
   {
      OUTPUT_HIGH(PIN_B7);
   }
   delay_us(104);
   //stop
   OUTPUT_HIGH(PIN_B7);
   delay_us(208);
}

Parto de la base de que los lectores de tarjetas, según el estandar ISO 7816 otorgan al PIC una frecuencia de 3,57 Mhz. Que después de un reset la tarjeta se comunica a 9600 bps, 8 bits de datos, paridad par y 2 bits de stop. La espera entre bit y bit es de 104 us cuando se trata de una velocidad de 9600 bps. El ATR es muy sencillo, sólo envía el TS, un T0 indicando 7 bytes históricos y 7 bytes (del 1 al 7).

Desconectado sistemasorp

  • PIC10
  • *
  • Mensajes: 28
Re: ATR de una smartcard con pic en CCS
« Respuesta #1 en: 27 de Agosto de 2009, 19:51:38 »
Me respondo a mi mismo (por si a alguien le sirve) con un código que además de devolver el ATR, devuelve el CLA INS P1 P2 y LEN de cualquier orden que se le envíe. Probado con una goldcard y un lector smartcard ltc31.

Código: [Seleccionar]
#include <16F84A.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading

#use delay(clock=3571200)
#use fast_io(b)

#byte W = 0x0000
#byte F = 0x0001
#byte PORTB = 0x06
#byte STATUS = 0x03

byte CONST C = 0x0000;

void sendByte(int iSendData);
int receiveByte();

void main()
{
   unsigned char atr[] = {0x3B,0x09,0,0xFF,0x80,0xAA,'o','s','c','a','r'};
   unsigned char envia[5];
   int indice;
   
   SET_TRIS_B(0x7F);
   OUTPUT_HIGH(PIN_B7);
   //delay_us(RETARDO * 3);
   
   for(indice = 0; indice < sizeof(atr); indice++)
   {
      sendByte(atr[indice]);
   }
   for(;;)
   {
      for(indice = 0; indice < 5; indice++)
      {
         envia[indice] = receiveByte();
         //WRITE_EEPROM(indice, envia[indice]);
      }
      sendByte(envia[1]);
      for(indice = 0; indice < 5; indice++)
      {
         sendByte(envia[indice]);
      }
      sendByte(0x90);
      sendByte(0);

   }
}

void sendByte(int iSendData)
{

int iParity;
int iCtr;
int iPauseCtr;

#asm

movlw 0x32 ; Pause for 170 ?s
call Pause ; call Pause
bcf PORTB,7 ; Send start bit in RB7

movlw 0x7F
tris PORTB ; TRIS PORB with 01111111 (0x7F)

clrf iParity ; Initialize Parity to 0

movlw 0x08
movwf iCtr ; Initialize 8 to counter to send 8 data bits

send_loop:

call Std_pause ; Pause for 93 ?s (at 9600 bps)

rrf iSendData,f
rrf iSendData,W
andlw 0x80

xorwf iParity,f ; Calculate Parity

xorwf PORTB,W
xorwf PORTB,f

decfsz iCtr,f ; Decrement Data Bit counter

goto send_loop ; Loop

call Std_pause ; Pause

movf iParity,W ; Send Parity

xorwf PORTB,W
xorwf PORTB,f

call Std_pause

movlw 0xFF
tris PORTB

movlw 0x3E
goto Pause ; Pause 0x3E

Std_pause:
movlw 0x1A ; Standard Pause Value

Pause:
movwf iPauseCtr ; Initialize iPauseCounter with value of W Register

Pause_loop:
decfsz iPauseCtr,f ; Decrement Pause Counter
goto Pause_loop
retlw 0x00 ; Return after setting W Register to 0

#endasm
}

int receiveByte()
{

int iCtr;
int iPauseCtr;
int iReceiveData;

#asm
Receive:

btfsc PORTB,7
goto Receive
movlw 0x2D
call Pause

movlw 0x09
movwf iCtr

ReceiveLoop:

bcf STATUS,C
btfsc PORTB,7
bsf STATUS,C

rrf iReceiveData,f
call Std_pause
nop
nop

decfsz iCtr,f
goto ReceiveLoop


rlf iReceiveData,f
movlw 0x1D
call Pause

movf iReceiveData,W

#endasm

return iReceiveData;

#asm
Std_pause:

movlw 0x1A

Pause:
movwf iPauseCtr

Pause_loop:

decfsz iPauseCtr,f

goto Pause_loop

retlw 0x00

#endasm
}