more impl.

This commit is contained in:
NIIBE Yutaka
2010-08-19 17:09:59 +09:00
parent 4a7dfc5cd3
commit a68663cb5b
6 changed files with 308 additions and 86 deletions

View File

@@ -78,7 +78,7 @@ CSRC = $(PORTSRC) \
$(CHIBIOS)/os/various/syscalls.c \
$(STMUSBSRC) \
$(USBCDCSRC) \
main.c hw_config.c usb_lld.c usb_desc.c usb_prop.c usb.c
main.c hw_config.c usb_lld.c usb_desc.c usb_prop.c usb-icc.c gpg.c
# List ASM source files here
ASMSRC = $(PORTASM) \

9
src/gnuk.h Normal file
View File

@@ -0,0 +1,9 @@
extern Thread *blinker_thread;
extern Thread *icc_thread;
extern Thread *gpg_thread;
#define EV_EXEC_FINISHED (eventmask_t)2 /* GPG Execution finished */
#define put_string(STR)
extern void _write (char *, int);

View File

@@ -1,5 +1,5 @@
/*
* gpg.c --
* gpg.c -- OpenPGP card protocol support
*
* Copyright (C) 2010 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
@@ -21,7 +21,11 @@
*
*/
#define RSA_SIGNATURE_LENGTH 128 /* 128 byte == 1024-bit */
#include "ch.h"
#include "hal.h"
#include "gnuk.h"
#define RSA_SIGNATURE_LENGTH 256 /* 256 byte == 2048-bit */
extern unsigned char *rsa_sign (unsigned char *);
#define INS_PUT_DATA 0xDA
@@ -207,19 +211,20 @@ const char const do_5f50[] =
* 6e L-6e [47 3 x x x ] [4f L-4f ...] [c0 L-c0 ...] ...
* 7a L-7a [93 L-93 ... ]
*/
#if 0
static byte
process_command_adpu (void)
{
if (icc_read_buf[1] == INS_GET_RESPONSE)
{
stx_put_string (" - GET Response\r\n");
put_string (" - GET Response\r\n");
if ((icc_result_flag & ICC_RESULT_BUF))
return 0;
else
{
stx_put_string ("Wrong GET Response\r\n");
put_string ("Wrong GET Response\r\n");
return 1;
}
}
@@ -239,7 +244,7 @@ INS_VERIFY
if (icc_read_buf[1] == INS_PUT_DATA)
{
stx_put_string (" - PUT DATA\r\n");
put_string (" - PUT DATA\r\n");
icc_result_value = 0x9000; /* 6a88: No record */
icc_result_len = 0;
icc_result_flag = 0;
@@ -248,7 +253,7 @@ INS_VERIFY
if (icc_read_buf[1] == INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR)
{
stx_put_string (" - Generate Asymmetric Key Pair\r\n");
put_string (" - Generate Asymmetric Key Pair\r\n");
if (icc_read_buf[2] == 0x81)
{
@@ -346,7 +351,7 @@ INS_VERIFY
}
else if (icc_read_buf[1] == INS_READ_BINARY)
{ /* it must be for DF 0x2f02 */
stx_put_string (" - Read binary\r\n");
put_string (" - Read binary\r\n");
if (icc_read_buf[3] >= 6)
{
@@ -369,7 +374,7 @@ INS_VERIFY
{
if (icc_read_buf[2] == 4) /* Selection by DF name */
{
stx_put_string (" - select DF by name\r\n");
put_string (" - select DF by name\r\n");
/*
* XXX: Should return contents.
*/
@@ -385,7 +390,7 @@ INS_VERIFY
&& icc_read_buf[5] == 0x2f
&& icc_read_buf[6] == 02)
{
stx_put_string (" - select 0x2f02 EF\r\n");
put_string (" - select 0x2f02 EF\r\n");
/*
* MF.EF-GDO -- Serial number of the card and name of the owner
*/
@@ -398,7 +403,7 @@ INS_VERIFY
&& icc_read_buf[5] == 0x3f
&& icc_read_buf[6] == 0)
{
stx_put_string (" - select ROOT MF\r\n");
put_string (" - select ROOT MF\r\n");
if (icc_read_buf[3] == 0x0c)
{
icc_result_value = 0x9000;
@@ -414,7 +419,7 @@ INS_VERIFY
}
else
{
stx_put_string (" - select ?? \r\n");
put_string (" - select ?? \r\n");
icc_result_value = 0x6a82; /* File missing */
icc_result_len = 0;
@@ -423,7 +428,7 @@ INS_VERIFY
}
else if (icc_read_buf[1] == INS_GET_DATA)
{
stx_put_string (" - Get Data\r\n");
put_string (" - Get Data\r\n");
switch (((icc_read_buf[2]<<8) | icc_read_buf[3]))
{
@@ -535,12 +540,12 @@ INS_VERIFY
}
else if (icc_read_buf[1] == INS_PSO)
{
stx_put_string (" - PSO\r\n");
put_string (" - PSO\r\n");
if (icc_read_buf[2] == 0x9E && icc_read_buf[3] == 0x9A)
{
if (icc_read_len != 5 + 35 && icc_read_len != 5 + 35 + 1)
stx_put_string (" wrong length\r\n");
put_string (" wrong length\r\n");
else
{
icc_result_value = rsa_sign (&icc_read_buf[5]);
@@ -548,11 +553,11 @@ INS_VERIFY
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_RAM;
}
stx_put_string ("done.\r\n");
put_string ("done.\r\n");
}
else
{
stx_put_string (" - ???\r\n");
put_string (" - ???\r\n");
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
@@ -560,7 +565,7 @@ INS_VERIFY
}
else
{
stx_put_string (" - ???\r\n");
put_string (" - ???\r\n");
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
@@ -568,3 +573,37 @@ INS_VERIFY
return 0;
}
#endif
Thread *gpg_thread;
msg_t
GPGthread (void *arg)
{
(void)arg;
gpg_thread = chThdSelf ();
chEvtClear (ALL_EVENTS);
while (1)
{
eventmask_t m;
m = chEvtWaitOne (ALL_EVENTS);
_write ("GPG!\r\n", 6);
#if 0
receive_command_adpu ();
#endif
#if 0
process_command_adpu ();
#endif
#if 0
send_result_adpu ();
#endif
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
}
return 0;
}

View File

@@ -35,18 +35,22 @@
#include "hw_config.h"
#include "usb_pwr.h"
Thread *blinker_thread;
/*
* Red LEDs blinker thread, times are in milliseconds.
*/
static WORKING_AREA(waThread1, 128);
static msg_t Thread1(void *arg) {
static msg_t
Thread1 (void *arg)
{
(void)arg;
while (TRUE) {
blinker_thread = chThdSelf ();
while (1)
{
palClearPad (IOPORT3, GPIOC_LED);
chThdSleepMilliseconds (1000);
chEvtWaitOne (ALL_EVENTS);
palSetPad (IOPORT3, GPIOC_LED);
chThdSleepMilliseconds (1000);
chEvtWaitOne (ALL_EVENTS);
}
return 0;
}
@@ -160,8 +164,11 @@ static msg_t Thread2 (void *arg)
return 0;
}
static WORKING_AREA(waUSBThread, 128*2);
extern msg_t USBThread (void *arg);
static WORKING_AREA(waUSBthread, 128*2);
extern msg_t USBthread (void *arg);
static WORKING_AREA(waGPGthread, 128*4);
extern msg_t GPGthread (void *arg);
/*
* Entry point, note, the main() function is already a thread in the system
@@ -188,7 +195,8 @@ int main(int argc, char **argv)
*/
chThdCreateStatic (waThread2, sizeof(waThread2), NORMALPRIO, Thread2, NULL);
chThdCreateStatic (waUSBThread, sizeof(waUSBThread), NORMALPRIO, USBThread, NULL);
chThdCreateStatic (waUSBthread, sizeof(waUSBthread), NORMALPRIO, USBthread, NULL);
chThdCreateStatic (waGPGthread, sizeof(waGPGthread), NORMALPRIO, GPGthread, NULL);
while (1)
{

View File

@@ -1,5 +1,5 @@
/*
* usb.c --
* usb-icc.c -- USB CCID/ICCD protocol handling
*
* Copyright (C) 2010 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
@@ -24,31 +24,42 @@
#include "ch.h"
#include "hal.h"
#include "gnuk.h"
#include "usb_lib.h"
#include "usb_desc.h"
#include "usb_mem.h"
#include "hw_config.h"
#include "usb_istr.h"
Mutex icc_in_mutex;
static uint8_t icc_buffer_out[64];
static uint8_t icc_buffer_in[64];
static __IO uint32_t icc_count_out = 0;
static uint32_t icc_count_in = 0;
Thread *icc_thread;
#define EV_RX_DATA_READY (eventmask_t)1 /* USB Rx data available */
/*
* Tx done
*/
void
EP4_IN_Callback (void)
{
icc_count_in = 0;
}
/*
* Rx data
*/
void
EP5_OUT_Callback (void)
{
/* Get the received data buffer and update the counter */
icc_count_out = USB_SIL_Read (EP5_OUT, icc_buffer_out);
chEvtSignalI (icc_thread, EV_RX_DATA_READY);
}
#define ICC_POWER_ON 0x62
@@ -168,32 +179,31 @@ HW_ERROR 0xFB The USB-ICC detected a hardware error.
all others Reserved for future use
(0x80 and those filling the gaps)
extern const uchar *icc_power_on (void);
extern byte icc_get_status (void);
PC_to_RDR_IccPowerOff
RDR_to_PC_SlotStatus
PC_to_RDR_IccPowerOn
RDR_to_PC_DataBlock
PC_to_RDR_XfrBlock
RDR_to_PC_DataBlock
#endif
enum icc_state
{
ICC_STATE_START, /* Initial */
ICC_STATE_WAIT, /* Waiting ADPU */
/* Busy1, Busy2, Busy3, Busy5 */
ICC_STATE_EXECUTE, /* Busy4 */
ICC_STATE_RECEIVE, /* ADPU Received Partially */
ICC_STATE_SEND /* ADPU Sent Partially */
};
static enum icc_state icc_state;
/* Direct conversion, T=1, "FSIJ" */
static const char ATR[] = { '\x3B', '\x84', '\x01', 'F', 'S', 'I', 'J' };
void
/* Send back ATR (Answer To Reset) */
enum icc_state
icc_power_on (char *buf, int len)
{
int i, size_atr;
size_atr = sizeof (ATR);
chMtxLock (&icc_in_mutex);
icc_buffer_in[0] = 0x80;
icc_buffer_in[1] = size_atr;
/* not including '\0' at the end */
@@ -212,16 +222,14 @@ icc_power_on (char *buf, int len)
USB_SIL_Write (EP4_IN, icc_buffer_in, icc_count_in);
SetEPTxValid (ENDP4);
chMtxUnlock ();
_write ("ON\r\n", 4);
return ICC_STATE_WAIT;
}
void
icc_power_off (char *buf, int len)
static void
icc_send_status (char *buf, int len)
{
chMtxLock (&icc_in_mutex);
icc_buffer_in[0] = 0x81;
icc_buffer_in[1] = 0x00;
icc_buffer_in[2] = 0x00;
@@ -229,56 +237,212 @@ icc_power_off (char *buf, int len)
icc_buffer_in[4] = 0x00;
icc_buffer_in[5] = 0x00; /* Slot */
icc_buffer_in[ICC_MSG_SEQ_OFFSET] = buf[ICC_MSG_SEQ_OFFSET];
icc_buffer_in[ICC_MSG_STATUS_OFFSET] = 0x00;
if (icc_state == ICC_STATE_START)
icc_buffer_in[ICC_MSG_STATUS_OFFSET] = 2; /* No ICC present */
else
icc_buffer_in[ICC_MSG_STATUS_OFFSET] = 0; /* An ICC is present and active */
icc_buffer_in[ICC_MSG_ERROR_OFFSET] = 0x00;
icc_buffer_in[9] = 0x00;
icc_count_in = 10;
USB_SIL_Write (EP4_IN, icc_buffer_in, icc_count_in);
SetEPTxValid (ENDP4);
chMtxUnlock ();
_write ("OFF\r\n", 5);
}
msg_t
USBThread (void *arg)
enum icc_state
icc_power_off (char *buf, int len)
{
icc_send_status (buf, len);
_write ("OFF\r\n", 5);
return ICC_STATE_START;
}
static enum icc_state
icc_handle_data (void)
{
enum icc_state next_state = icc_state;
#if 1
char b[3];
chMtxInit (&icc_in_mutex);
while (TRUE)
{
while (icc_count_out == 0)
chThdSleepMilliseconds (1);
b[0] = icc_buffer_out[0];
b[1] = '\r';
b[2] = '\n';
_write (b, 3);
#endif
switch (icc_state)
{
case ICC_STATE_START:
if (icc_buffer_out[0] == ICC_POWER_ON)
{
/* Send back ATR (Answer To Reset) */
icc_power_on (icc_buffer_out, icc_count_out);
}
else if (icc_buffer_out[0] == ICC_POWER_OFF
|| icc_buffer_out[0] == ICC_SLOT_STATUS)
{
/* Kill ICC thread(s) and send back slot status */
icc_power_off (icc_buffer_out, icc_count_out);
next_state = icc_power_on (icc_buffer_out, icc_count_out);
else if (icc_buffer_out[0] == ICC_POWER_OFF)
next_state = icc_power_off (icc_buffer_out, icc_count_out);
else if (icc_buffer_out[0] == ICC_SLOT_STATUS)
icc_send_status (icc_buffer_out, icc_count_out);
else
{ /* XXX: error */
_write ("ERR01\r\n", 7);
}
break;
case ICC_STATE_WAIT:
if (icc_buffer_out[0] == ICC_POWER_OFF)
next_state = icc_power_off (icc_buffer_out, icc_count_out);
else if (icc_buffer_out[0] == ICC_SLOT_STATUS)
icc_send_status (icc_buffer_out, icc_count_out);
else if (icc_buffer_out[0] == XFR_BLOCK)
{
/* Give this message to ICC thread */
if (icc_buffer_out[8] == 0 && icc_buffer_out[9] == 0)
{
/* Give this message to GPG thread */
next_state = ICC_STATE_EXECUTE;
chEvtSignal (gpg_thread, (eventmask_t)1);
}
else if (icc_buffer_out[8] == 1 && icc_buffer_out[9] == 0)
{
/* XXX: return back RDR_to_PC_DataBlock */
/* bChainParameter = 0x10, abData=empty */
next_state = ICC_STATE_RECEIVE;
}
else
{
/* XXX: error */;
_write ("ERR02\r\n", 7);
}
}
else
{ /* XXX: error */
_write ("ERR03\r\n", 7);
}
break;
case ICC_STATE_EXECUTE:
if (icc_buffer_out[0] == ICC_POWER_OFF)
{
/* XXX: Kill GPG thread */
next_state = icc_power_off (icc_buffer_out, icc_count_out);
}
else if (icc_buffer_out[0] == ICC_SLOT_STATUS)
icc_send_status (icc_buffer_out, icc_count_out);
else
{ /* XXX: error */
_write ("ERR04\r\n", 7);
}
break;
case ICC_STATE_RECEIVE:
if (icc_buffer_out[0] == ICC_POWER_OFF)
{
/* XXX: release partial ADPU received */
next_state = icc_power_off (icc_buffer_out, icc_count_out);
}
else if (icc_buffer_out[0] == ICC_SLOT_STATUS)
icc_send_status (icc_buffer_out, icc_count_out);
else if (icc_buffer_out[0] == XFR_BLOCK)
{
if (1 /* XXX */) /* Got final block */
{
/* Give this message to GPG thread */
next_state = ICC_STATE_EXECUTE;
chEvtSignal (gpg_thread, (eventmask_t)1);
}
}
else
{ /* XXX: error */
_write ("ERR05\r\n", 7);
}
break;
case ICC_STATE_SEND:
if (icc_buffer_out[0] == ICC_POWER_OFF)
{
/* XXX: release partial ADPU sending */
next_state = icc_power_off (icc_buffer_out, icc_count_out);
}
else if (icc_buffer_out[0] == ICC_SLOT_STATUS)
icc_send_status (icc_buffer_out, icc_count_out);
else if (icc_buffer_out[0] == XFR_BLOCK)
{
/* XXX: send back to data */
/* finished?, then go ICC_STATE_WAIT */
next_state = ICC_STATE_WAIT;
}
else
{ /* XXX: error */
_write ("ERR06\r\n", 7);
}
break;
}
icc_count_out = 0;
SetEPRxValid (ENDP5);
return next_state;
}
static enum icc_state
icc_handle_timeout (void)
{
enum icc_state next_state = icc_state;
/*
*
* XXX: ICC_STATE_EXECUTE -> kill
* XXX: ICC_STATE_RECEIVE -> cancel
* XXX: ICC_STATE_SEND -> cancel
*/
if (icc_state == ICC_STATE_START
|| icc_state == ICC_STATE_WAIT)
;
else
{
next_state = ICC_STATE_WAIT;
}
chEvtSignal (blinker_thread, (eventmask_t)1);
return next_state;
}
#define USB_ICC_TIMEOUT MS2ST(1000)
msg_t
USBthread (void *arg)
{
(void)arg;
icc_thread = chThdSelf ();
chEvtClear (ALL_EVENTS);
icc_state = ICC_STATE_START;
while (1)
{
eventmask_t m;
m = chEvtWaitOneTimeout (ALL_EVENTS, USB_ICC_TIMEOUT);
if (m == EV_RX_DATA_READY)
icc_state = icc_handle_data ();
else if (m == EV_EXEC_FINISHED)
{
if (icc_state == ICC_STATE_EXECUTE)
{
if (1/* message is short enough*/)
{
/* XXX: send back result */;
icc_state = ICC_STATE_WAIT;
}
else
{
/* XXX: send back part of result */;
icc_state = ICC_STATE_SEND;
}
}
else
{ /* XXX: error */
_write ("ERR07\r\n", 7);
}
}
else /* Timeout */
icc_state = icc_handle_timeout ();
}
return 0;

View File

@@ -6,9 +6,11 @@ extern void USB_Istr (void);
CH_IRQ_HANDLER (Vector90) {
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
USB_Istr();
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
@@ -17,9 +19,9 @@ void usb_lld_init (void) {
NVICEnableVector (USB_LP_CAN1_RX0_IRQn,
CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY));
/*
* Note that we also have other IRQs:
* USB_HP_CAN1_TX_IRQn
* USBWakeUp_IRQn
* Note that we also have other IRQ(s):
* USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous)
* USBWakeUp_IRQn (suspend/resume)
*/
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
RCC->APB1RSTR = 0;