Detecting and powering the card up...
One will need a routine to exchange messages with the card reader, something like :
Now, one can see if a card is present by requesting the reader's ACR_STAT. The last byte ([19]) of the answer is 0 if there is no card, 1 if there is a card in the reader and 3 if it is powered.
Once we detect a card, we power it up as in the file ./bel-eid-fr-linux/Etape_1/ACR38_LINUX_100706_P/src/driver/AdmHndlr.c.
and power it off...
So, the main code becomes
The 'sleep(10)' is there to see if the LED (steady) shines as documented.
What is interesting is that we get the Answer-To-Reset (ATR) of the inserted card...
For example :
Googling these byte sequences, one finds a smardcard_list.txt (from Ludovic Rousseau) and other informations to explore.
Is there a standard way to extract data from a card? a 'READ BINARY' APDU?
/*
** ACR_xchange(udp, *outp, out_len, *inp, in_len)
** send a command to the reader and get the answer
** returns 0 if all goes well; -1 if not
*/
int ACR_xchange(struct usb_dev_handle* udp, u_char *outp, int out_len, u_char *inp, int in_len)
{
if (usb_bulk_write(udp, EP_OUT, (char *)outp, out_len, TIMEOUT) < 0)
{
perror("usb_bulk_write");
return(-1);
}
if (usb_bulk_read(udp, EP_IN, (char *)inp, in_len, TIMEOUT) < 0)
{
perror("usb_bulk_read");
return(-1);
}
if (inp[1])
return(-1); /* bad status -- should set errno */
return(0);
}
Now, one can see if a card is present by requesting the reader's ACR_STAT. The last byte ([19]) of the answer is 0 if there is no card, 1 if there is a card in the reader and 3 if it is powered.
/*
** ACR_card_present(udp)
** returns 1 if a card is present, 0 otherwise
** -1 if something goes wrong
*/
int ACR_card_present(struct usb_dev_handle* udp)
{
u_char buf_out[] = { 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }; /* GET_ACR_STAT */
u_char buf_in[64];
if (ACR_xchange(udp, buf_out, 6, buf_in, 64) < 0)
{
perror("ACR_xchange");
return(-1);
}
return(buf_in[19] & 1); /* card present */
}
Once we detect a card, we power it up as in the file ./bel-eid-fr-linux/Etape_1/ACR38_LINUX_100706_P/src/driver/AdmHndlr.c.
/*
** MCU_powerup(udp)
*/
int MCU_powerup(struct usb_dev_handle *udp)
{
u_char MCU_EMV[] = { 0x01, 0x07, 0x00, 0x01, 0x00}; /* [No EMV + No Mem Card] */
u_char MCU_TYPE[] = { 0x01, 0x02, 0x00, 0x01, 0x00}; /* auto select */
u_char MCU_POWER[] = { 0x01, 0x80, 0x00, 0x00};
u_char buf_in[64];
/*
** EMV OPTIONS : no EMV no Mem (?!)
*/
if (ACR_xchange(udp, MCU_EMV, 5, buf_in, sizeof(buf_in)) < 0)
{
perror("MCU_EMV");
return(-1);
}
/*
** card type auto select
*/
if (ACR_xchange(udp, MCU_TYPE, 5, buf_in, sizeof(buf_in)) < 0)
{
perror("MCU_TYPE");
return(-1);
}
/*
** Power up the card
*/
if (ACR_xchange(udp, MCU_POWER, 4, buf_in, sizeof(buf_in)) < 0)
{
perror("MCU_POWER");
return(-1);
}
xdump("----- ATR:", &buf_in[4], buf_in[3]);
return(0);
}
and power it off...
/*
** MCU_powerdown(udp)
*/
int MCU_powerdown(struct usb_dev_handle *udp)
{
u_char MCU_POWER_DOWN[] = { 0x01, 0x81, 0x00, 0x00};
u_char buf_in[64];
if (ACR_xchange(udp, MCU_POWER_DOWN, 4, buf_in, sizeof(buf_in)) < 0)
{
perror("MCU_POWER_DOWN");
return(-1);
}
return(0);
}
So, the main code becomes
main()
{
...
if ((udp = usb_open(dev)) == NULL)
{
perror("usb_open");
exit(-1);
}
while (ACR_card_present(udp) != 1)
sleep(1); /* wait for card insertion */
MCU_powerup(udp);
sleep(10);
MCU_powerdown(udp);
if (usb_close(udp) < 0)
{
perror("usb_close");
exit(-1);
}
exit(0);
}
The 'sleep(10)' is there to see if the LED (steady) shines as documented.
What is interesting is that we get the Answer-To-Reset (ATR) of the inserted card...
For example :
Dexia bank card (Belgium)
----- ATR: : 3b 67 00 00 2d 20 36 00 78 90 00
VISA Dexia (Belgium)
----- ATR: : 3b 67 00 00 00 00 00 00 00 90 00
FNAC Finaref (Belgium; exp. 2006)
----- ATR: : 3b 6d 00 00 00 31 c0 71 d6 64 34 c7 02 00 84 90 00
Googling these byte sequences, one finds a smardcard_list.txt (from Ludovic Rousseau) and other informations to explore.
Is there a standard way to extract data from a card? a 'READ BINARY' APDU?
0 Comments:
Enregistrer un commentaire
<< Home