mirror of
https://salsa.debian.org/gnuk-team/gnuk/gnuk.git
synced 2024-09-20 10:50:09 +00:00
works now.
This commit is contained in:
parent
a68663cb5b
commit
c4f1bc576b
@ -82,7 +82,7 @@ CSRC = $(PORTSRC) \
|
||||
|
||||
# List ASM source files here
|
||||
ASMSRC = $(PORTASM) \
|
||||
$(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s
|
||||
$(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s gpg-data.s
|
||||
|
||||
INCDIR = $(STMUSBINCDIR) $(USBCDCDIR) \
|
||||
$(PORTINC) $(KERNINC) $(TESTINC) \
|
||||
|
22
src/gnuk.h
22
src/gnuk.h
@ -1,9 +1,25 @@
|
||||
extern Thread *blinker_thread;
|
||||
|
||||
extern void put_byte (uint8_t b);
|
||||
|
||||
extern void _write (const char *, int);
|
||||
|
||||
extern size_t strlen(const char *s);
|
||||
extern void *memcpy(void *dest, const void *src, size_t n);
|
||||
|
||||
/*
|
||||
* Interface between ICC<-->GPG
|
||||
*/
|
||||
extern Thread *icc_thread;
|
||||
extern Thread *gpg_thread;
|
||||
|
||||
#define USB_BUF_SIZE 64
|
||||
|
||||
#define EV_EXEC_FINISHED (eventmask_t)2 /* GPG Execution finished */
|
||||
|
||||
#define put_string(STR)
|
||||
|
||||
extern void _write (char *, int);
|
||||
#define MAX_CMD_APDU_SIZE (256) /* XXX: Check OpenPGPcard protocol */
|
||||
#define MAX_RES_APDU_SIZE (256+2) /* Data + status */
|
||||
extern uint8_t cmd_APDU[MAX_CMD_APDU_SIZE];
|
||||
extern uint8_t res_APDU[MAX_RES_APDU_SIZE];
|
||||
extern int cmd_APDU_size;
|
||||
extern int res_APDU_size;
|
||||
|
221
src/gpg-data.c
Normal file
221
src/gpg-data.c
Normal file
@ -0,0 +1,221 @@
|
||||
const char const select_file_TOP_result[] __attribute__ ((aligned (1))) =
|
||||
{ 0x00, 0x00, 0x0b, 0x10, 0x3f, 0x00, 0x38, 0xff, 0xff, 0x44,
|
||||
0x44, 0x01, 0x05, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
const char const get_data_64_result[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const char const get_data_5e_result[] __attribute__ ((aligned (1))) =
|
||||
{ /* Login Data */
|
||||
'g', 'n', 'i', 'i', 'b', 'e'
|
||||
};
|
||||
|
||||
/***** do_6e is compound object of { do_47, do_4f, do_c0,..,c6,cd }*/
|
||||
const char const do_6e_head[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0x6e, 0x81, 2*10+3+16+1+1+1+1+7+60+60+12 /* (> 128) */
|
||||
};
|
||||
|
||||
const char const do_47[] __attribute__ ((aligned (1))) = /* Card Capabilities */
|
||||
{
|
||||
0x47, 3,
|
||||
0x00 /*???*/, 0x00 /*???*/, 0x00 /*???*/
|
||||
/* XXX: See ISO 7816-4 for first byte and second byte */
|
||||
};
|
||||
|
||||
const char const do_4f[] __attribute__ ((aligned (1))) = /* AID */
|
||||
{
|
||||
0x4f, 16,
|
||||
0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
|
||||
0x01, 0x01, /* Version 1.1 */
|
||||
0xF5, 0x17, /* Manufacturer (FSIJ) */
|
||||
0x00, 0x00, 0x00, 0x02, /* Serial */
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
const char const do_c0[] __attribute__ ((aligned (1))) =
|
||||
{ /* Extended capability */
|
||||
0xc0, 1,
|
||||
0x00
|
||||
};
|
||||
|
||||
const char const do_c1[] __attribute__ ((aligned (1))) =
|
||||
{ /* Algorithm Attributes Signature ??? */
|
||||
0xc1, 1,
|
||||
0x01, /* RSA */ /*??? should have length modulus, length exponent ??? */
|
||||
};
|
||||
|
||||
const char const do_c2[] __attribute__ ((aligned (1))) =
|
||||
{ /* Algorithm Attributes Decryption ??? */
|
||||
0xc2, 1,
|
||||
0x00
|
||||
};
|
||||
|
||||
const char const do_c3[] __attribute__ ((aligned (1))) =
|
||||
{ /* Algorithm Attributes Authentication ??? */
|
||||
0xc3, 1,
|
||||
0x00
|
||||
};
|
||||
|
||||
const char const do_c4[] __attribute__ ((aligned (1))) =
|
||||
{ /* CHV status bytes */
|
||||
0xc4, 7,
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01
|
||||
};
|
||||
|
||||
const char const do_c5[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0xc5, 60,
|
||||
/* sign */
|
||||
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
|
||||
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
|
||||
0xe5, 0x02, 0xbf, 0xcd,
|
||||
/* enc */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
/* auth */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const char const do_c6[] __attribute__ ((aligned (1))) = /* CA Fingerprints */
|
||||
{
|
||||
0xc6, 60,
|
||||
/* c6 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
/* c7 */
|
||||
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
|
||||
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
|
||||
0xe5, 0x02, 0xbf, 0xcd,
|
||||
/* c8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const char const do_cd[] __attribute__ ((aligned (1))) =
|
||||
{ /* Generation time */
|
||||
0xcd, 12,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x49, 0x8a, 0x50, 0x7a, /* 0xce */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
/*************************/
|
||||
|
||||
/***** do_65 is compound object of { do_5b, do_5f2d, do_5f35 }*/
|
||||
const char const do_65_head[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0x65, 2*1+3*2+12+2+1
|
||||
};
|
||||
|
||||
const char const do_5b[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0x5b, 12,
|
||||
'N', 'I', 'I', 'B', 'E', ' ', 'Y', 'u', 't', 'a', 'k', 'a'
|
||||
};
|
||||
|
||||
const char const do_5f2d[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0x5f, 0x2d, 2,
|
||||
'j', 'a'
|
||||
};
|
||||
|
||||
const char const do_5f35[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0x5f, 0x35, 1,
|
||||
'1'
|
||||
};
|
||||
/****************************/
|
||||
|
||||
/* do_7a is compound object of { do_93 } */
|
||||
const char const do_7a_head[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0x7a, 2+3
|
||||
};
|
||||
|
||||
/* Digital Signature Counter (3-bytes) */
|
||||
const char const do_93[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0x93, 3,
|
||||
0, 0, 0
|
||||
};
|
||||
/****************************/
|
||||
|
||||
|
||||
const char const do_5f50[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0x5f, 0x50, 20,
|
||||
'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w',
|
||||
'.', 'f', 's', 'i', 'j', '.', 'o', 'r', 'g', '/'
|
||||
};
|
||||
|
||||
/* Historycal bytes */
|
||||
const char const do_5f52[] __attribute__ ((aligned (1))) =
|
||||
{
|
||||
0x5f, 0x52, 10,
|
||||
0x00,
|
||||
0x31, 0xc0, /* full DF name, partial DF name supported */
|
||||
0x73,
|
||||
0xc0, 0x01, 0x00, /* full DF name, partial DF name supported */
|
||||
/* 1-byte */
|
||||
/* no command chaining, no ext lc_le */
|
||||
0x00, 0x90, 0x00 /* Status info */
|
||||
};
|
||||
|
||||
const char const get_data_rb_result[] __attribute__ ((aligned (1))) = {
|
||||
0x5a, 0x4, 0x01, 0x02, 0x03, 0x04
|
||||
};
|
||||
|
||||
const char const get_data_sigkey_result[] __attribute__ ((aligned (1))) = {
|
||||
0x7f, 0x49, 0x81, 0x88,
|
||||
0x81, 0x81, 0x80,
|
||||
/* 128-byte data */
|
||||
/* modulus */
|
||||
0xdb, 0xca, 0x58, 0x74, 0x44, 0x8e, 0x1a, 0x2c,
|
||||
0xa0, 0x91, 0xac, 0xc4, 0xe2, 0x77, 0x2b, 0x90,
|
||||
0xcf, 0x3c, 0x7e, 0x81, 0xdc, 0x8d, 0xb0, 0xe2,
|
||||
0xf1, 0xfe, 0x56, 0x7e, 0x54, 0x57, 0xf0, 0xd8,
|
||||
0xb1, 0xb1, 0xaa, 0x9d, 0x8f, 0xb0, 0x56, 0x01,
|
||||
0xaa, 0x6b, 0xa7, 0x2e, 0xce, 0x01, 0x20, 0xd2,
|
||||
0xf8, 0xf5, 0x85, 0x3a, 0xc2, 0x73, 0xf9, 0x66,
|
||||
0x30, 0x28, 0x65, 0x5e, 0x3f, 0x91, 0xaf, 0x3f,
|
||||
0xf6, 0x1c, 0x31, 0x2f, 0xa2, 0x91, 0xbb, 0x41,
|
||||
0x91, 0x41, 0x08, 0x0a, 0xc5, 0x3e, 0x39, 0xda,
|
||||
0x2f, 0x6f, 0x58, 0x51, 0xe2, 0xd2, 0xe9, 0x42,
|
||||
0x8a, 0x7b, 0x72, 0x7b, 0x15, 0xf6, 0xf6, 0x6a,
|
||||
0x12, 0x6e, 0x0c, 0x15, 0x24, 0x13, 0x16, 0x55,
|
||||
0x3a, 0xf1, 0xa7, 0x16, 0x3e, 0xe9, 0xc8, 0x3d,
|
||||
0x2c, 0x3d, 0xae, 0x51, 0x2d, 0x7f, 0xef, 0x92,
|
||||
0x25, 0x6a, 0xbb, 0x02, 0x03, 0x70, 0x45, 0x3d,
|
||||
/* public exponent */
|
||||
0x82, 3, 0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
const char const get_data_enckey_result[] __attribute__ ((aligned (1))) = {
|
||||
0x7f, 0x49, 0x81, 0x88,
|
||||
0x81, 0x81, 0x80,
|
||||
/* 128-byte data */
|
||||
0xB2, 0x19, 0x91, 0x42, 0x27, 0xC7, 0x97, 0xFE,
|
||||
0x92, 0x64, 0x42, 0xCA, 0xE3, 0x66, 0x4D, 0xD0,
|
||||
0x31, 0xE4, 0x10, 0x31, 0x0F, 0xC7, 0x07, 0x4A,
|
||||
0xAA, 0x6D, 0x31, 0xA2, 0x88, 0x68, 0xAF, 0x45,
|
||||
0x8E, 0x42, 0x12, 0xFF, 0xB6, 0xEF, 0x6E, 0x54,
|
||||
0x7E, 0x51, 0x8E, 0xBC, 0xE8, 0x18, 0x79, 0xA7,
|
||||
0xBC, 0xA8, 0x14, 0x8B, 0xE7, 0x91, 0x57, 0x38,
|
||||
0xCE, 0x4F, 0x6E, 0x16, 0x48, 0xCB, 0xD6, 0x0B,
|
||||
0x3A, 0x53, 0x70, 0xF3, 0xFC, 0xFA, 0xC3, 0x58,
|
||||
0x3D, 0xE7, 0x2A, 0x5E, 0xDD, 0xE1, 0x38, 0x82,
|
||||
0x57, 0x87, 0x3A, 0xDC, 0x34, 0xDE, 0xCD, 0x5D,
|
||||
0x33, 0x1C, 0xAB, 0xB0, 0x1B, 0xEE, 0x82, 0x43,
|
||||
0x7B, 0xAC, 0xF8, 0xF0, 0xB2, 0x62, 0xB2, 0x6D,
|
||||
0x09, 0xED, 0x2E, 0xD1, 0xBA, 0xB8, 0xC6, 0x96,
|
||||
0xFA, 0x3E, 0xB4, 0xE3, 0xFE, 0x68, 0xF9, 0x51,
|
||||
0x9A, 0x8C, 0x8B, 0x20, 0x93, 0xD0, 0x2E, 0x0F,
|
||||
0x82, 3, 0x01, 0x00, 0x01
|
||||
};
|
1284
src/gpg-data.s
Normal file
1284
src/gpg-data.s
Normal file
File diff suppressed because it is too large
Load Diff
548
src/gpg.c
548
src/gpg.c
@ -25,7 +25,35 @@
|
||||
#include "hal.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
#define RSA_SIGNATURE_LENGTH 256 /* 256 byte == 2048-bit */
|
||||
static void
|
||||
put_hex (uint8_t nibble)
|
||||
{
|
||||
uint8_t c;
|
||||
|
||||
if (nibble < 0x0a)
|
||||
c = '0' + nibble;
|
||||
else
|
||||
c = 'a' + nibble - 0x0a;
|
||||
|
||||
_write (&c, 1);
|
||||
}
|
||||
|
||||
void
|
||||
put_byte (uint8_t b)
|
||||
{
|
||||
put_hex (b >> 4);
|
||||
put_hex (b &0x0f);
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
|
||||
static void
|
||||
put_string (const char *s)
|
||||
{
|
||||
_write (s, strlen (s));
|
||||
}
|
||||
|
||||
|
||||
#define RSA_SIGNATURE_LENGTH 128 /* 256 byte == 2048-bit */
|
||||
extern unsigned char *rsa_sign (unsigned char *);
|
||||
|
||||
#define INS_PUT_DATA 0xDA
|
||||
@ -37,162 +65,31 @@ extern unsigned char *rsa_sign (unsigned char *);
|
||||
#define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR 0x47
|
||||
#define INS_PSO 0x2A
|
||||
|
||||
static const char const select_file_TOP_result[] =
|
||||
{ 0x00, 0x00, 0x0b, 0x10, 0x3f, 0x00, 0x38, 0xff, 0xff, 0x44,
|
||||
0x44, 0x01, 0x05, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
static const char const get_data_64_result[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const char const get_data_5e_result[] =
|
||||
{ /* Login Data */
|
||||
'g', 'n', 'i', 'i', 'b', 'e'
|
||||
};
|
||||
|
||||
/***** do_65 is compound object of { do_47, do_4f, do_c0,..,c6,cd }*/
|
||||
const unsigned char const do_6e_head[] =
|
||||
{
|
||||
0x6e, 0x81, 2*10+3+16+1+1+1+1+7+60+60+12 /* (> 128) */
|
||||
};
|
||||
|
||||
const char const do_47[] = /* Card Capabilities */
|
||||
{
|
||||
0x47, 3,
|
||||
0x00 /*???*/, 0x00 /*???*/, 0x00 /*???*/
|
||||
/* XXX: See ISO 7816-4 for first byte and second byte */
|
||||
};
|
||||
|
||||
const char const do_4f[] = /* AID */
|
||||
{
|
||||
0x4f, 16,
|
||||
0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
|
||||
0x01, 0x01, /* Version 1.1 */
|
||||
0xF5, 0x17, /* Manufacturer (FSIJ) */
|
||||
0x00, 0x00, 0x00, 0x02, /* Serial */
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
const char const do_c0[] =
|
||||
{ /* Extended capability */
|
||||
0xc0, 1,
|
||||
0x00
|
||||
};
|
||||
|
||||
const char const do_c1[] =
|
||||
{ /* Algorithm Attributes Signature ??? */
|
||||
0xc1, 1,
|
||||
0x01, /* RSA */ /*??? should have length modulus, length exponent ??? */
|
||||
};
|
||||
|
||||
const char const do_c2[] =
|
||||
{ /* Algorithm Attributes Decryption ??? */
|
||||
0xc2, 1,
|
||||
0x00
|
||||
};
|
||||
|
||||
const char const do_c3[] =
|
||||
{ /* Algorithm Attributes Authentication ??? */
|
||||
0xc3, 1,
|
||||
0x00
|
||||
};
|
||||
|
||||
const char const do_c4[] =
|
||||
{ /* CHV status bytes */
|
||||
0xc4, 7,
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01
|
||||
};
|
||||
|
||||
const char const do_c5[] =
|
||||
{
|
||||
0xc5, 60,
|
||||
/* sign */
|
||||
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
|
||||
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
|
||||
0xe5, 0x02, 0xbf, 0xcd,
|
||||
/* enc */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
/* auth */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const char const do_c6[] = /* CA Fingerprints */
|
||||
{
|
||||
0xc6, 60,
|
||||
/* c6 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
/* c7 */
|
||||
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
|
||||
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
|
||||
0xe5, 0x02, 0xbf, 0xcd,
|
||||
/* c8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const char const do_cd[] =
|
||||
{ /* Generation time */
|
||||
0xcd, 12,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x49, 0x8a, 0x50, 0x7a, /* 0xce */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
/*************************/
|
||||
|
||||
/***** do_65 is compound object of { do_5b, do_5f2d, do_5f35 }*/
|
||||
const char const do_65_head[] =
|
||||
{
|
||||
0x65, 2*1+3*2+12+2+1
|
||||
};
|
||||
|
||||
const char const do_5b[] =
|
||||
{
|
||||
0x5b, 12,
|
||||
'N', 'I', 'I', 'B', 'E', ' ', 'Y', 'u', 't', 'a', 'k', 'a'
|
||||
};
|
||||
|
||||
const char const do_5f2d[] =
|
||||
{
|
||||
0x5f, 0x2d, 2,
|
||||
'j', 'a'
|
||||
};
|
||||
|
||||
const char const do_5f35[] =
|
||||
{
|
||||
0x5f, 0x35, 1,
|
||||
'1'
|
||||
};
|
||||
/****************************/
|
||||
|
||||
/* do_7a is compound object of { do_93 } */
|
||||
const char const do_7a_head[] =
|
||||
{
|
||||
0x7a, 2+3
|
||||
};
|
||||
|
||||
/* Digital Signature Counter (3-bytes) */
|
||||
const char const do_93[] =
|
||||
{
|
||||
0x93, 3,
|
||||
0, 0, 0
|
||||
};
|
||||
/****************************/
|
||||
|
||||
|
||||
const char const do_5f50[] =
|
||||
{
|
||||
0x5f, 0x50, 20,
|
||||
'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w',
|
||||
'.', 'f', 's', 'i', 'j', '.', 'o', 'r', 'g', '/'
|
||||
};
|
||||
extern const char const select_file_TOP_result[20];
|
||||
extern const char const get_data_64_result[7];
|
||||
extern const char const get_data_5e_result[6];
|
||||
extern const char const do_6e_head[3];
|
||||
extern const char const do_47[2+3];
|
||||
extern const char const do_4f[2+16];
|
||||
extern const char const do_c0[2+1];
|
||||
extern const char const do_c1[2+1];
|
||||
extern const char const do_c2[2+1];
|
||||
extern const char const do_c3[2+1];
|
||||
extern const char const do_c4[2+7];
|
||||
extern const char const do_c5[2+60];
|
||||
extern const char const do_c6[2+60];
|
||||
extern const char const do_cd[2+12];
|
||||
extern const char const do_65_head[2];
|
||||
extern const char const do_5b[2+12];
|
||||
extern const char const do_5f2d[3+2];
|
||||
extern const char const do_5f35[3+1];
|
||||
extern const char const do_7a_head[2];
|
||||
extern const char const do_93[2+3];
|
||||
extern const char const do_5f50[3+20];
|
||||
extern const char const do_5f52[3+10];
|
||||
extern const char const get_data_rb_result[6];
|
||||
extern const char const get_data_sigkey_result[7+128];
|
||||
extern const char const get_data_enckey_result[7+128];
|
||||
|
||||
|
||||
/*
|
||||
@ -211,26 +108,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)
|
||||
static void
|
||||
write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
|
||||
{
|
||||
if (icc_read_buf[1] == INS_GET_RESPONSE)
|
||||
{
|
||||
put_string (" - GET Response\r\n");
|
||||
|
||||
if ((icc_result_flag & ICC_RESULT_BUF))
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
put_string ("Wrong GET Response\r\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
icc_result_flag = 0;
|
||||
res_APDU_size = 2 + len;
|
||||
if (len)
|
||||
memcpy (res_APDU, p, len);
|
||||
res_APDU[len] = sw1;
|
||||
res_APDU[len+1] = sw2;
|
||||
}
|
||||
|
||||
static int
|
||||
process_command_apdu (void)
|
||||
{
|
||||
/*
|
||||
INS_VERIFY
|
||||
|
||||
@ -242,20 +133,18 @@ INS_VERIFY
|
||||
CHV3
|
||||
*/
|
||||
|
||||
if (icc_read_buf[1] == INS_PUT_DATA)
|
||||
if (cmd_APDU[1] == INS_PUT_DATA)
|
||||
{
|
||||
put_string (" - PUT DATA\r\n");
|
||||
icc_result_value = 0x9000; /* 6a88: No record */
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00); /* 0x6a, 0x88: No record */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (icc_read_buf[1] == INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR)
|
||||
if (cmd_APDU[1] == INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR)
|
||||
{
|
||||
put_string (" - Generate Asymmetric Key Pair\r\n");
|
||||
|
||||
if (icc_read_buf[2] == 0x81)
|
||||
if (cmd_APDU[2] == 0x81)
|
||||
{
|
||||
/*
|
||||
* tag: 0x7f49 public key data
|
||||
@ -272,107 +161,44 @@ INS_VERIFY
|
||||
* 0x81 0x80
|
||||
*/
|
||||
|
||||
if (icc_read_buf[6] == 0x00 && icc_read_buf[5] == 0xb6)
|
||||
if (cmd_APDU[6] == 0x00 && cmd_APDU[5] == 0xb6)
|
||||
{ /* Key for Sign */
|
||||
static const char const get_data_sigkey_result[] =
|
||||
{
|
||||
0x7f, 0x49, 0x81, 0x88,
|
||||
0x81, 0x81, 0x80,
|
||||
/* 128-byte data */
|
||||
/* modulus */
|
||||
0xdb, 0xca, 0x58, 0x74, 0x44, 0x8e, 0x1a, 0x2c,
|
||||
0xa0, 0x91, 0xac, 0xc4, 0xe2, 0x77, 0x2b, 0x90,
|
||||
0xcf, 0x3c, 0x7e, 0x81, 0xdc, 0x8d, 0xb0, 0xe2,
|
||||
0xf1, 0xfe, 0x56, 0x7e, 0x54, 0x57, 0xf0, 0xd8,
|
||||
0xb1, 0xb1, 0xaa, 0x9d, 0x8f, 0xb0, 0x56, 0x01,
|
||||
0xaa, 0x6b, 0xa7, 0x2e, 0xce, 0x01, 0x20, 0xd2,
|
||||
0xf8, 0xf5, 0x85, 0x3a, 0xc2, 0x73, 0xf9, 0x66,
|
||||
0x30, 0x28, 0x65, 0x5e, 0x3f, 0x91, 0xaf, 0x3f,
|
||||
0xf6, 0x1c, 0x31, 0x2f, 0xa2, 0x91, 0xbb, 0x41,
|
||||
0x91, 0x41, 0x08, 0x0a, 0xc5, 0x3e, 0x39, 0xda,
|
||||
0x2f, 0x6f, 0x58, 0x51, 0xe2, 0xd2, 0xe9, 0x42,
|
||||
0x8a, 0x7b, 0x72, 0x7b, 0x15, 0xf6, 0xf6, 0x6a,
|
||||
0x12, 0x6e, 0x0c, 0x15, 0x24, 0x13, 0x16, 0x55,
|
||||
0x3a, 0xf1, 0xa7, 0x16, 0x3e, 0xe9, 0xc8, 0x3d,
|
||||
0x2c, 0x3d, 0xae, 0x51, 0x2d, 0x7f, 0xef, 0x92,
|
||||
0x25, 0x6a, 0xbb, 0x02, 0x03, 0x70, 0x45, 0x3d,
|
||||
/* public exponent */
|
||||
0x82, 3, 0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
icc_result_value = get_data_sigkey_result;
|
||||
icc_result_len = sizeof (get_data_sigkey_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
write_res_apdu (get_data_sigkey_result,
|
||||
sizeof (get_data_sigkey_result), 0x90, 0x00);
|
||||
}
|
||||
else if (icc_read_buf[6] == 0x00 && icc_read_buf[5] == 0xb8)
|
||||
else if (cmd_APDU[6] == 0x00 && cmd_APDU[5] == 0xb8)
|
||||
{ /* Key for Encryption */
|
||||
static const char const get_data_enckey_result[] =
|
||||
{
|
||||
0x7f, 0x49, 0x81, 0x88,
|
||||
0x81, 0x81, 0x80,
|
||||
/* 128-byte data */
|
||||
0xB2, 0x19, 0x91, 0x42, 0x27, 0xC7, 0x97, 0xFE,
|
||||
0x92, 0x64, 0x42, 0xCA, 0xE3, 0x66, 0x4D, 0xD0,
|
||||
0x31, 0xE4, 0x10, 0x31, 0x0F, 0xC7, 0x07, 0x4A,
|
||||
0xAA, 0x6D, 0x31, 0xA2, 0x88, 0x68, 0xAF, 0x45,
|
||||
0x8E, 0x42, 0x12, 0xFF, 0xB6, 0xEF, 0x6E, 0x54,
|
||||
0x7E, 0x51, 0x8E, 0xBC, 0xE8, 0x18, 0x79, 0xA7,
|
||||
0xBC, 0xA8, 0x14, 0x8B, 0xE7, 0x91, 0x57, 0x38,
|
||||
0xCE, 0x4F, 0x6E, 0x16, 0x48, 0xCB, 0xD6, 0x0B,
|
||||
0x3A, 0x53, 0x70, 0xF3, 0xFC, 0xFA, 0xC3, 0x58,
|
||||
0x3D, 0xE7, 0x2A, 0x5E, 0xDD, 0xE1, 0x38, 0x82,
|
||||
0x57, 0x87, 0x3A, 0xDC, 0x34, 0xDE, 0xCD, 0x5D,
|
||||
0x33, 0x1C, 0xAB, 0xB0, 0x1B, 0xEE, 0x82, 0x43,
|
||||
0x7B, 0xAC, 0xF8, 0xF0, 0xB2, 0x62, 0xB2, 0x6D,
|
||||
0x09, 0xED, 0x2E, 0xD1, 0xBA, 0xB8, 0xC6, 0x96,
|
||||
0xFA, 0x3E, 0xB4, 0xE3, 0xFE, 0x68, 0xF9, 0x51,
|
||||
0x9A, 0x8C, 0x8B, 0x20, 0x93, 0xD0, 0x2E, 0x0F,
|
||||
0x82, 3, 0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
icc_result_value = get_data_enckey_result;
|
||||
icc_result_len = sizeof (get_data_enckey_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
write_res_apdu (get_data_enckey_result,
|
||||
sizeof (get_data_enckey_result), 0x90, 0x00);
|
||||
}
|
||||
/* icc_read_buf[5] == 0xa4 */
|
||||
/* cmd_APDU[5] == 0xa4 */
|
||||
else
|
||||
{
|
||||
icc_result_value = 0x6a88; /* No record */
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_result_value = 0x6a88; /* No record */
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
|
||||
}
|
||||
}
|
||||
else if (icc_read_buf[1] == INS_READ_BINARY)
|
||||
else if (cmd_APDU[1] == INS_READ_BINARY)
|
||||
{ /* it must be for DF 0x2f02 */
|
||||
put_string (" - Read binary\r\n");
|
||||
|
||||
if (icc_read_buf[3] >= 6)
|
||||
if (cmd_APDU[3] >= 6)
|
||||
{
|
||||
icc_result_value = 0x6b00; /* BAD_P0_P1 */
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
write_res_apdu (NULL, 0, 0x6b, 0x00); /* BAD_P0_P1 */
|
||||
}
|
||||
else
|
||||
{ /* Tag 5a, serial number */
|
||||
static const char const get_data_rb_result[] = { 0x5a, 0x4, 0x01, 0x02, 0x03, 0x04 };
|
||||
|
||||
icc_result_value = (word)get_data_rb_result;
|
||||
icc_result_len = sizeof (get_data_rb_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
|
||||
/* XXX: Next get response returns 6282??? eof_reached ??? */
|
||||
write_res_apdu (get_data_rb_result,
|
||||
sizeof (get_data_rb_result), 0x90, 0x00);
|
||||
}
|
||||
}
|
||||
else if (icc_read_buf[1] == INS_SELECT_FILE)
|
||||
else if (cmd_APDU[1] == INS_SELECT_FILE)
|
||||
{
|
||||
if (icc_read_buf[2] == 4) /* Selection by DF name */
|
||||
if (cmd_APDU[2] == 4) /* Selection by DF name */
|
||||
{
|
||||
put_string (" - select DF by name\r\n");
|
||||
/*
|
||||
@ -381,176 +207,210 @@ INS_VERIFY
|
||||
|
||||
if (1)
|
||||
{
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
}
|
||||
}
|
||||
else if (icc_read_buf[4] == 2
|
||||
&& icc_read_buf[5] == 0x2f
|
||||
&& icc_read_buf[6] == 02)
|
||||
else if (cmd_APDU[4] == 2
|
||||
&& cmd_APDU[5] == 0x2f
|
||||
&& cmd_APDU[6] == 02)
|
||||
{
|
||||
put_string (" - select 0x2f02 EF\r\n");
|
||||
/*
|
||||
* MF.EF-GDO -- Serial number of the card and name of the owner
|
||||
*/
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
}
|
||||
else
|
||||
if (icc_read_buf[4] == 2
|
||||
&& icc_read_buf[5] == 0x3f
|
||||
&& icc_read_buf[6] == 0)
|
||||
if (cmd_APDU[4] == 2
|
||||
&& cmd_APDU[5] == 0x3f
|
||||
&& cmd_APDU[6] == 0)
|
||||
{
|
||||
put_string (" - select ROOT MF\r\n");
|
||||
if (icc_read_buf[3] == 0x0c)
|
||||
if (cmd_APDU[3] == 0x0c)
|
||||
{
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_result_value = select_file_TOP_result;
|
||||
icc_result_len = sizeof (select_file_TOP_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
write_res_apdu (select_file_TOP_result,
|
||||
sizeof (select_file_TOP_result), 0x90, 0x00);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
put_string (" - select ?? \r\n");
|
||||
|
||||
icc_result_value = 0x6a82; /* File missing */
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x82); /* File missing */
|
||||
}
|
||||
}
|
||||
else if (icc_read_buf[1] == INS_GET_DATA)
|
||||
else if (cmd_APDU[1] == INS_GET_DATA)
|
||||
{
|
||||
put_string (" - Get Data\r\n");
|
||||
|
||||
switch (((icc_read_buf[2]<<8) | icc_read_buf[3]))
|
||||
switch (((cmd_APDU[2]<<8) | cmd_APDU[3]))
|
||||
{
|
||||
case 0x4f: /* AID */
|
||||
{
|
||||
icc_result_value = (word)&do_4f[2];
|
||||
icc_result_len = sizeof (do_4f) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" AID\r\n");
|
||||
write_res_apdu (&do_4f[2],
|
||||
sizeof (do_4f) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x5e: /* Login data */
|
||||
{
|
||||
icc_result_value = (word)get_data_5e_result;
|
||||
icc_result_len = sizeof (get_data_5e_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" Login data\r\n");
|
||||
write_res_apdu (get_data_5e_result,
|
||||
sizeof (get_data_5e_result), 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x64:
|
||||
{
|
||||
icc_result_value = (word)get_data_64_result;
|
||||
icc_result_len = sizeof (get_data_64_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" 64\r\n");
|
||||
write_res_apdu (get_data_64_result,
|
||||
sizeof (get_data_64_result), 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0xc0:
|
||||
{
|
||||
icc_result_value = (word)&do_c0[2];
|
||||
icc_result_len = sizeof (do_c0) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" c0\r\n");
|
||||
write_res_apdu (&do_c0[2],
|
||||
sizeof (do_c0) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0xc1:
|
||||
{
|
||||
put_string (" c1\r\n");
|
||||
write_res_apdu (&do_c1[2],
|
||||
sizeof (do_c1) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0xc2:
|
||||
{
|
||||
put_string (" c2\r\n");
|
||||
write_res_apdu (&do_c2[2],
|
||||
sizeof (do_c2) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0xc3:
|
||||
{
|
||||
put_string (" c3\r\n");
|
||||
write_res_apdu (&do_c3[2],
|
||||
sizeof (do_c3) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0xc4:
|
||||
{
|
||||
icc_result_value = (word)&do_c4[2];
|
||||
icc_result_len = sizeof (do_c4) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" c4\r\n");
|
||||
write_res_apdu (&do_c4[2],
|
||||
sizeof (do_c4) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x5b: /* Name */
|
||||
{
|
||||
icc_result_value = (word)&do_5b[2];
|
||||
icc_result_len = sizeof (do_5b) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" 5b\r\n");
|
||||
write_res_apdu (&do_5b[2],
|
||||
sizeof (do_5b) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x93: /* Digital Signature Counter (3-bytes) */
|
||||
{
|
||||
icc_result_value = (word)&do_93[2];
|
||||
icc_result_len = sizeof (do_93) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" 93\r\n");
|
||||
write_res_apdu (&do_93[2],
|
||||
sizeof (do_93) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0xc5: /* Fingerprints */
|
||||
{
|
||||
icc_result_value = &do_c5[2];
|
||||
icc_result_len = sizeof (do_c5) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" c5\r\n");
|
||||
write_res_apdu (&do_c5[2],
|
||||
sizeof (do_c5) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x5f2d: /* Language preference */
|
||||
{
|
||||
icc_result_value = (word)&do_5f2d[3];
|
||||
icc_result_len = sizeof (do_5f2d) - 3;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" 5f2d\r\n");
|
||||
write_res_apdu (&do_5f2d[3],
|
||||
sizeof (do_5f2d) - 3, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x5f35: /* Sex */
|
||||
{
|
||||
icc_result_value = (word)&do_5f35[3];
|
||||
icc_result_len = sizeof (do_5f35) - 3;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" 5f35\r\n");
|
||||
write_res_apdu (&do_5f35[3],
|
||||
sizeof (do_5f35) - 3, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x5f50: /* URL */
|
||||
{
|
||||
icc_result_value = (word)&do_5f50[3];
|
||||
icc_result_len = sizeof (do_5f50) - 3;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" 5f50\r\n");
|
||||
write_res_apdu (&do_5f50[3],
|
||||
sizeof (do_5f50) - 3, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x5f52: /* Historycal bytes */
|
||||
{
|
||||
put_string (" 5f52\r\n");
|
||||
write_res_apdu (&do_5f52[3],
|
||||
sizeof (do_5f52) - 3, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x65: /* Card Holder Related Data (Tag) */
|
||||
{
|
||||
icc_result_value = (word)do_65_head;
|
||||
icc_result_len = do_65_head[1] + 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" 65\r\n");
|
||||
write_res_apdu (do_65_head,
|
||||
do_65_head[1] + 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x6e: /* Application Related Data (Tag) */
|
||||
{
|
||||
icc_result_value = (word)do_6e_head;
|
||||
icc_result_len = do_6e_head[2] + 3;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" 6e\r\n");
|
||||
write_res_apdu (do_6e_head,
|
||||
do_6e_head[2] + 3, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0x7a: /* Security Support Template (Tag) */
|
||||
{
|
||||
icc_result_value = (word)do_7a_head;
|
||||
icc_result_len = do_7a_head[1] + 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
put_string (" 7a\r\n");
|
||||
write_res_apdu (do_7a_head,
|
||||
do_7a_head[1] + 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0xc6: /* List of CA fingerprints */
|
||||
{
|
||||
put_string (" c6\r\n");
|
||||
write_res_apdu (&do_c6[2],
|
||||
sizeof (do_c6) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
case 0xcd: /* List of generation dates/times public-key pairs */
|
||||
{
|
||||
put_string (" cd\r\n");
|
||||
write_res_apdu (&do_cd[2],
|
||||
sizeof (do_cd) - 2, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
put_string (" ?");
|
||||
put_byte (((cmd_APDU[2]<<8) | cmd_APDU[3]));
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (icc_read_buf[1] == INS_PSO)
|
||||
else if (cmd_APDU[1] == INS_PSO)
|
||||
{
|
||||
put_string (" - PSO\r\n");
|
||||
|
||||
if (icc_read_buf[2] == 0x9E && icc_read_buf[3] == 0x9A)
|
||||
if (cmd_APDU[2] == 0x9E && cmd_APDU[3] == 0x9A)
|
||||
{
|
||||
if (icc_read_len != 5 + 35 && icc_read_len != 5 + 35 + 1)
|
||||
if (cmd_APDU_size != 5 + 35 && cmd_APDU_size != 5 + 35 + 1)
|
||||
put_string (" wrong length\r\n");
|
||||
else
|
||||
{
|
||||
icc_result_value = rsa_sign (&icc_read_buf[5]);
|
||||
icc_result_len = RSA_SIGNATURE_LENGTH;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_RAM;
|
||||
#if 0
|
||||
r = rsa_sign (&cmd_APDU[5]);
|
||||
write_res_apdu (NULL, RSA_SIGNATURE_LENGTH, 0x90, 0x00);
|
||||
#endif
|
||||
write_res_apdu (NULL, 0, 0x64, 0x00);
|
||||
}
|
||||
|
||||
put_string ("done.\r\n");
|
||||
@ -558,22 +418,17 @@ INS_VERIFY
|
||||
else
|
||||
{
|
||||
put_string (" - ???\r\n");
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
put_string (" - ???\r\n");
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
Thread *gpg_thread;
|
||||
|
||||
@ -592,15 +447,8 @@ GPGthread (void *arg)
|
||||
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
|
||||
|
||||
process_command_apdu ();
|
||||
|
||||
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
|
||||
}
|
||||
|
886
src/icc.c
886
src/icc.c
@ -1,886 +0,0 @@
|
||||
/*
|
||||
* icc.c --
|
||||
*
|
||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
*
|
||||
* Gnuk is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
enum icc_state {
|
||||
ICC_STATE_INITIAL,
|
||||
ICC_STATE_WAITING_ADPU,
|
||||
ICC_STATE_BUSY1,
|
||||
ICC_STATE_BUSY2,
|
||||
ICC_STATE_BUSY3,
|
||||
ICC_STATE_BUSY4,
|
||||
ICC_STATE_BUSY5,
|
||||
ICC_STATE_ADPU_RECEIVED_PARTIALLY,
|
||||
ICC_STATE_ADPU_SENT_PARTIALLY,
|
||||
};
|
||||
|
||||
#define RSA_SIGNATURE_LENGTH 128 /* 128 byte == 1024-bit */
|
||||
extern unsigned char *rsa_sign (unsigned char *);
|
||||
|
||||
/* Three callbacks */
|
||||
|
||||
static byte icc_cycle;
|
||||
byte icc_status;
|
||||
|
||||
/* GET_ICC_STATUS */
|
||||
byte
|
||||
icc_get_status (void)
|
||||
{
|
||||
#if 0
|
||||
if (icc_status == ICC_STATUS_BUSY)
|
||||
return ((icc_cycle++) & 0x0f) | ICC_STATUS_BUSY;
|
||||
#endif
|
||||
|
||||
return icc_status;
|
||||
}
|
||||
|
||||
/* XXX: need to be fixed... *//* T=0 */
|
||||
const char *ATR = "\x3B\x02\xbe\xef";
|
||||
|
||||
task_t icc_wait_task;
|
||||
byte icc_wait_result;
|
||||
|
||||
|
||||
/* ICC_POWER_ON */
|
||||
const byte *
|
||||
icc_power_on (void)
|
||||
{
|
||||
task_t t = icc_wait_task;
|
||||
|
||||
if (t != 0)
|
||||
{
|
||||
icc_wait_task = 0;
|
||||
need_resched = 1;
|
||||
icc_wait_result = 1;
|
||||
stx_wakeup (t);
|
||||
}
|
||||
|
||||
return ATR;
|
||||
}
|
||||
|
||||
word icc_initial_sp;
|
||||
void icc_main (void);
|
||||
extern word task[];
|
||||
|
||||
extern byte icc_write_buf[2];
|
||||
byte icc_read_buf[143];
|
||||
extern int icc_write_len;
|
||||
extern int icc_read_len;
|
||||
|
||||
extern task_t icc_write_task;
|
||||
extern task_t icc_read_task;
|
||||
|
||||
/* ICC_POWER_OFF */
|
||||
void
|
||||
icc_power_off (void)
|
||||
{
|
||||
#if 0
|
||||
if (icc_read_task)
|
||||
{
|
||||
icc_read_task = 0;
|
||||
icc_read_len = 0xff;
|
||||
}
|
||||
|
||||
if (icc_write_task)
|
||||
{
|
||||
icc_write_task = 0;
|
||||
icc_write_len = 0xff;
|
||||
}
|
||||
|
||||
if (icc_wait_task)
|
||||
{
|
||||
icc_wait_task = 0;
|
||||
icc_wait_result = 0;
|
||||
}
|
||||
|
||||
icc_status = ICC_STATUS_BUSY;
|
||||
stx_wakeup (ICC_TASK);
|
||||
#endif
|
||||
#if 1
|
||||
extern stx_cancel_write (byte);
|
||||
word sp = icc_initial_sp;
|
||||
|
||||
if (sp)
|
||||
{
|
||||
icc_status = ICC_STATUS_BUSY;
|
||||
|
||||
stx_cancel_write (ICC_TASK);
|
||||
|
||||
/* Push PC */
|
||||
*(byte *)(sp - 1) = ((word)icc_main >> 8);
|
||||
*(byte *)sp = ((word)icc_main & 0xff);
|
||||
sp -= 32 + 1 + 2; /* Registers 0-31, SREG and PC */
|
||||
|
||||
need_resched = 1;
|
||||
task[ICC_TASK] = sp;
|
||||
stx_wakeup (ICC_TASK);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define INS_PUT_DATA 0xDA
|
||||
#define INS_VERIFY 0x20
|
||||
#define INS_GET_DATA 0xCA
|
||||
#define INS_GET_RESPONSE 0xC0
|
||||
#define INS_SELECT_FILE 0xA4
|
||||
#define INS_READ_BINARY 0xB0
|
||||
#define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR 0x47
|
||||
#define INS_PSO 0x2A
|
||||
|
||||
extern byte *icc_read_p;
|
||||
|
||||
word icc_result_value; /* Buffer pointer or status word */
|
||||
byte icc_result_flag;
|
||||
byte icc_result_len;
|
||||
|
||||
#define ICC_RESULT_BUF 0x80
|
||||
#define ICC_RESULT_BUF_MASK 0x7f
|
||||
#define ICC_RESULT_BUF_ROM 0
|
||||
#define ICC_RESULT_BUF_EEPROM 1
|
||||
#define ICC_RESULT_BUF_RAM 2
|
||||
/************************ 3 */
|
||||
|
||||
static void
|
||||
icc_success (void)
|
||||
{
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
|
||||
byte
|
||||
stx_icc_read (void)
|
||||
{
|
||||
asm volatile ("cli");
|
||||
icc_read_p = icc_read_buf;
|
||||
icc_read_len = 0;
|
||||
icc_read_task = current;
|
||||
task_wait_bits |= taskset_current ();
|
||||
icc_status = ICC_STATUS_READY;
|
||||
stx_yield ();
|
||||
|
||||
if (icc_read_len == 5
|
||||
&& (icc_read_buf[1] == INS_SELECT_FILE
|
||||
|| icc_read_buf[1] == INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR
|
||||
|| icc_read_buf[1] == INS_PUT_DATA
|
||||
|| icc_read_buf[1] == INS_VERIFY
|
||||
|| icc_read_buf[1] == INS_PSO))
|
||||
{ /* Recieve a packet again */
|
||||
asm volatile ("cli");
|
||||
icc_read_task = current;
|
||||
task_wait_bits |= taskset_current ();
|
||||
icc_status = ICC_STATUS_DATA;
|
||||
stx_yield ();
|
||||
}
|
||||
|
||||
return icc_read_len;
|
||||
}
|
||||
|
||||
static byte
|
||||
receive_command_adpu (void)
|
||||
{
|
||||
byte r;
|
||||
char s[11];
|
||||
|
||||
if ((r = stx_icc_read ()) != 0xff)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < icc_read_len; i++)
|
||||
{
|
||||
sprintf (s, " %02x", icc_read_buf[i]);
|
||||
stx_put_string (s);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const char const select_file_TOP_result[] =
|
||||
{ 0x00, 0x00, 0x0b, 0x10, 0x3f, 0x00, 0x38, 0xff, 0xff, 0x44,
|
||||
0x44, 0x01, 0x05, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
static const char const get_data_64_result[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const char const get_data_5e_result[] =
|
||||
{ /* Login Data */
|
||||
'g', 'n', 'i', 'i', 'b', 'e'
|
||||
};
|
||||
|
||||
/***** do_65 is compound object of { do_47, do_4f, do_c0,..,c6,cd }*/
|
||||
const unsigned char const do_6e_head[] =
|
||||
{
|
||||
0x6e, 0x81, 2*10+3+16+1+1+1+1+7+60+60+12 /* (> 128) */
|
||||
};
|
||||
|
||||
const char const do_47[] = /* Card Capabilities */
|
||||
{
|
||||
0x47, 3,
|
||||
0x00 /*???*/, 0x00 /*???*/, 0x00 /*???*/
|
||||
/* XXX: See ISO 7816-4 for first byte and second byte */
|
||||
};
|
||||
|
||||
const char const do_4f[] = /* AID */
|
||||
{
|
||||
0x4f, 16,
|
||||
0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
|
||||
0x01, 0x01, /* Version 1.1 */
|
||||
0xF5, 0x17, /* Manufacturer (FSIJ) */
|
||||
0x00, 0x00, 0x00, 0x02, /* Serial */
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
const char const do_c0[] =
|
||||
{ /* Extended capability */
|
||||
0xc0, 1,
|
||||
0x00
|
||||
};
|
||||
|
||||
const char const do_c1[] =
|
||||
{ /* Algorithm Attributes Signature ??? */
|
||||
0xc1, 1,
|
||||
0x01, /* RSA */ /*??? should have length modulus, length exponent ??? */
|
||||
};
|
||||
|
||||
const char const do_c2[] =
|
||||
{ /* Algorithm Attributes Decryption ??? */
|
||||
0xc2, 1,
|
||||
0x00
|
||||
};
|
||||
|
||||
const char const do_c3[] =
|
||||
{ /* Algorithm Attributes Authentication ??? */
|
||||
0xc3, 1,
|
||||
0x00
|
||||
};
|
||||
|
||||
const char const do_c4[] =
|
||||
{ /* CHV status bytes */
|
||||
0xc4, 7,
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01
|
||||
};
|
||||
|
||||
const char const do_c5[] =
|
||||
{
|
||||
0xc5, 60,
|
||||
/* sign */
|
||||
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
|
||||
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
|
||||
0xe5, 0x02, 0xbf, 0xcd,
|
||||
/* enc */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
/* auth */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const char const do_c6[] = /* CA Fingerprints */
|
||||
{
|
||||
0xc6, 60,
|
||||
/* c6 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
/* c7 */
|
||||
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
|
||||
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
|
||||
0xe5, 0x02, 0xbf, 0xcd,
|
||||
/* c8 */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const char const do_cd[] =
|
||||
{ /* Generation time */
|
||||
0xcd, 12,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x49, 0x8a, 0x50, 0x7a, /* 0xce */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
/*************************/
|
||||
|
||||
/***** do_65 is compound object of { do_5b, do_5f2d, do_5f35 }*/
|
||||
const char const do_65_head[] =
|
||||
{
|
||||
0x65, 2*1+3*2+12+2+1
|
||||
};
|
||||
|
||||
const char const do_5b[] =
|
||||
{
|
||||
0x5b, 12,
|
||||
'N', 'I', 'I', 'B', 'E', ' ', 'Y', 'u', 't', 'a', 'k', 'a'
|
||||
};
|
||||
|
||||
const char const do_5f2d[] =
|
||||
{
|
||||
0x5f, 0x2d, 2,
|
||||
'j', 'a'
|
||||
};
|
||||
|
||||
const char const do_5f35[] =
|
||||
{
|
||||
0x5f, 0x35, 1,
|
||||
'1'
|
||||
};
|
||||
/****************************/
|
||||
|
||||
/* do_7a is compound object of { do_93 } */
|
||||
const char const do_7a_head[] =
|
||||
{
|
||||
0x7a, 2+3
|
||||
};
|
||||
|
||||
/* Digital Signature Counter (3-bytes) */
|
||||
const char const do_93[] =
|
||||
{
|
||||
0x93, 3,
|
||||
0, 0, 0
|
||||
};
|
||||
/****************************/
|
||||
|
||||
|
||||
const char const do_5f50[] =
|
||||
{
|
||||
0x5f, 0x50, 20,
|
||||
'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w',
|
||||
'.', 'f', 's', 'i', 'j', '.', 'o', 'r', 'g', '/'
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 73
|
||||
* 101
|
||||
* 102
|
||||
* 103
|
||||
* 104
|
||||
*
|
||||
* 65 - 5b, 5f2d, 5f35
|
||||
* 6e - 47, 4f, c0, c1, c2, c3, c4, c5, c6, cd
|
||||
* 7a - 93
|
||||
*
|
||||
*
|
||||
* 65 L-65 [5b L-5b .... ] [5f2d 2 'j' 'a'] [5f35 1 '1']
|
||||
* 6e L-6e [47 3 x x x ] [4f L-4f ...] [c0 L-c0 ...] ...
|
||||
* 7a L-7a [93 L-93 ... ]
|
||||
*/
|
||||
|
||||
static byte
|
||||
process_command_adpu (void)
|
||||
{
|
||||
if (icc_read_buf[1] == INS_GET_RESPONSE)
|
||||
{
|
||||
stx_put_string (" - GET Response\r\n");
|
||||
|
||||
if ((icc_result_flag & ICC_RESULT_BUF))
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
stx_put_string ("Wrong GET Response\r\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
icc_result_flag = 0;
|
||||
|
||||
/*
|
||||
INS_VERIFY
|
||||
|
||||
00 20 00 81 06 - ???
|
||||
CHV1
|
||||
00 20 00 82 06 - ???
|
||||
CHV2
|
||||
00 20 00 83 08 - ???
|
||||
CHV3
|
||||
*/
|
||||
|
||||
if (icc_read_buf[1] == INS_PUT_DATA)
|
||||
{
|
||||
stx_put_string (" - PUT DATA\r\n");
|
||||
icc_result_value = 0x9000; /* 6a88: No record */
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (icc_read_buf[1] == INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR)
|
||||
{
|
||||
stx_put_string (" - Generate Asymmetric Key Pair\r\n");
|
||||
|
||||
if (icc_read_buf[2] == 0x81)
|
||||
{
|
||||
/*
|
||||
* tag: 0x7f49 public key data
|
||||
* tag: 0x0081 RSA modulus
|
||||
* tag: 0x0082 RSA exponent
|
||||
*
|
||||
* TAG
|
||||
* [0x7f 0x49][LEN][DATA]
|
||||
* _______/ \_________________
|
||||
* / \
|
||||
* [0x81][128][DATA][0x82][3][DATA]
|
||||
* __/ \__ 0x01, 0x00, 0x01
|
||||
* / \
|
||||
* 0x81 0x80
|
||||
*/
|
||||
|
||||
if (icc_read_buf[6] == 0x00 && icc_read_buf[5] == 0xb6)
|
||||
{ /* Key for Sign */
|
||||
static const char const get_data_sigkey_result[] =
|
||||
{
|
||||
0x7f, 0x49, 0x81, 0x88,
|
||||
0x81, 0x81, 0x80,
|
||||
/* 128-byte data */
|
||||
/* modulus */
|
||||
0xdb, 0xca, 0x58, 0x74, 0x44, 0x8e, 0x1a, 0x2c,
|
||||
0xa0, 0x91, 0xac, 0xc4, 0xe2, 0x77, 0x2b, 0x90,
|
||||
0xcf, 0x3c, 0x7e, 0x81, 0xdc, 0x8d, 0xb0, 0xe2,
|
||||
0xf1, 0xfe, 0x56, 0x7e, 0x54, 0x57, 0xf0, 0xd8,
|
||||
0xb1, 0xb1, 0xaa, 0x9d, 0x8f, 0xb0, 0x56, 0x01,
|
||||
0xaa, 0x6b, 0xa7, 0x2e, 0xce, 0x01, 0x20, 0xd2,
|
||||
0xf8, 0xf5, 0x85, 0x3a, 0xc2, 0x73, 0xf9, 0x66,
|
||||
0x30, 0x28, 0x65, 0x5e, 0x3f, 0x91, 0xaf, 0x3f,
|
||||
0xf6, 0x1c, 0x31, 0x2f, 0xa2, 0x91, 0xbb, 0x41,
|
||||
0x91, 0x41, 0x08, 0x0a, 0xc5, 0x3e, 0x39, 0xda,
|
||||
0x2f, 0x6f, 0x58, 0x51, 0xe2, 0xd2, 0xe9, 0x42,
|
||||
0x8a, 0x7b, 0x72, 0x7b, 0x15, 0xf6, 0xf6, 0x6a,
|
||||
0x12, 0x6e, 0x0c, 0x15, 0x24, 0x13, 0x16, 0x55,
|
||||
0x3a, 0xf1, 0xa7, 0x16, 0x3e, 0xe9, 0xc8, 0x3d,
|
||||
0x2c, 0x3d, 0xae, 0x51, 0x2d, 0x7f, 0xef, 0x92,
|
||||
0x25, 0x6a, 0xbb, 0x02, 0x03, 0x70, 0x45, 0x3d,
|
||||
/* public exponent */
|
||||
0x82, 3, 0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
icc_result_value = get_data_sigkey_result;
|
||||
icc_result_len = sizeof (get_data_sigkey_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
}
|
||||
#if 0
|
||||
else if (icc_read_buf[6] == 0x00 && icc_read_buf[5] == 0xb8)
|
||||
{ /* Key for Encryption */
|
||||
static const char const get_data_enckey_result[] =
|
||||
{
|
||||
0x7f, 0x49, 0x81, 0x88,
|
||||
0x81, 0x81, 0x80,
|
||||
/* 128-byte data */
|
||||
0xB2, 0x19, 0x91, 0x42, 0x27, 0xC7, 0x97, 0xFE,
|
||||
0x92, 0x64, 0x42, 0xCA, 0xE3, 0x66, 0x4D, 0xD0,
|
||||
0x31, 0xE4, 0x10, 0x31, 0x0F, 0xC7, 0x07, 0x4A,
|
||||
0xAA, 0x6D, 0x31, 0xA2, 0x88, 0x68, 0xAF, 0x45,
|
||||
0x8E, 0x42, 0x12, 0xFF, 0xB6, 0xEF, 0x6E, 0x54,
|
||||
0x7E, 0x51, 0x8E, 0xBC, 0xE8, 0x18, 0x79, 0xA7,
|
||||
0xBC, 0xA8, 0x14, 0x8B, 0xE7, 0x91, 0x57, 0x38,
|
||||
0xCE, 0x4F, 0x6E, 0x16, 0x48, 0xCB, 0xD6, 0x0B,
|
||||
0x3A, 0x53, 0x70, 0xF3, 0xFC, 0xFA, 0xC3, 0x58,
|
||||
0x3D, 0xE7, 0x2A, 0x5E, 0xDD, 0xE1, 0x38, 0x82,
|
||||
0x57, 0x87, 0x3A, 0xDC, 0x34, 0xDE, 0xCD, 0x5D,
|
||||
0x33, 0x1C, 0xAB, 0xB0, 0x1B, 0xEE, 0x82, 0x43,
|
||||
0x7B, 0xAC, 0xF8, 0xF0, 0xB2, 0x62, 0xB2, 0x6D,
|
||||
0x09, 0xED, 0x2E, 0xD1, 0xBA, 0xB8, 0xC6, 0x96,
|
||||
0xFA, 0x3E, 0xB4, 0xE3, 0xFE, 0x68, 0xF9, 0x51,
|
||||
0x9A, 0x8C, 0x8B, 0x20, 0x93, 0xD0, 0x2E, 0x0F,
|
||||
0x82, 3, 0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
icc_result_value = get_data_enckey_result;
|
||||
icc_result_len = sizeof (get_data_enckey_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
}
|
||||
#endif
|
||||
/* icc_read_buf[5] == 0xa4 */
|
||||
else
|
||||
{
|
||||
icc_result_value = 0x6a88; /* No record */
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_result_value = 0x6a88; /* No record */
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
}
|
||||
else if (icc_read_buf[1] == INS_READ_BINARY)
|
||||
{ /* it must be for DF 0x2f02 */
|
||||
stx_put_string (" - Read binary\r\n");
|
||||
|
||||
if (icc_read_buf[3] >= 6)
|
||||
{
|
||||
icc_result_value = 0x6b00; /* BAD_P0_P1 */
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
else
|
||||
{ /* Tag 5a, serial number */
|
||||
static const char const get_data_rb_result[] = { 0x5a, 0x4, 0x01, 0x02, 0x03, 0x04 };
|
||||
|
||||
icc_result_value = (word)get_data_rb_result;
|
||||
icc_result_len = sizeof (get_data_rb_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
|
||||
/* XXX: Next get response returns 6282??? eof_reached ??? */
|
||||
}
|
||||
}
|
||||
else if (icc_read_buf[1] == INS_SELECT_FILE)
|
||||
{
|
||||
if (icc_read_buf[2] == 4) /* Selection by DF name */
|
||||
{
|
||||
stx_put_string (" - select DF by name\r\n");
|
||||
/*
|
||||
* XXX: Should return contents.
|
||||
*/
|
||||
|
||||
if (1)
|
||||
{
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
}
|
||||
else if (icc_read_buf[4] == 2
|
||||
&& icc_read_buf[5] == 0x2f
|
||||
&& icc_read_buf[6] == 02)
|
||||
{
|
||||
stx_put_string (" - select 0x2f02 EF\r\n");
|
||||
/*
|
||||
* MF.EF-GDO -- Serial number of the card and name of the owner
|
||||
*/
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
else
|
||||
if (icc_read_buf[4] == 2
|
||||
&& icc_read_buf[5] == 0x3f
|
||||
&& icc_read_buf[6] == 0)
|
||||
{
|
||||
stx_put_string (" - select ROOT MF\r\n");
|
||||
if (icc_read_buf[3] == 0x0c)
|
||||
{
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_result_value = select_file_TOP_result;
|
||||
icc_result_len = sizeof (select_file_TOP_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stx_put_string (" - select ?? \r\n");
|
||||
|
||||
icc_result_value = 0x6a82; /* File missing */
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
}
|
||||
else if (icc_read_buf[1] == INS_GET_DATA)
|
||||
{
|
||||
stx_put_string (" - Get Data\r\n");
|
||||
|
||||
switch (((icc_read_buf[2]<<8) | icc_read_buf[3]))
|
||||
{
|
||||
case 0x4f: /* AID */
|
||||
{
|
||||
icc_result_value = (word)&do_4f[2];
|
||||
icc_result_len = sizeof (do_4f) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0x5e: /* Login data */
|
||||
{
|
||||
icc_result_value = (word)get_data_5e_result;
|
||||
icc_result_len = sizeof (get_data_5e_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0x64:
|
||||
{
|
||||
icc_result_value = (word)get_data_64_result;
|
||||
icc_result_len = sizeof (get_data_64_result);
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0xc0:
|
||||
{
|
||||
icc_result_value = (word)&do_c0[2];
|
||||
icc_result_len = sizeof (do_c0) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0xc4:
|
||||
{
|
||||
icc_result_value = (word)&do_c4[2];
|
||||
icc_result_len = sizeof (do_c4) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0x5b: /* Name */
|
||||
{
|
||||
icc_result_value = (word)&do_5b[2];
|
||||
icc_result_len = sizeof (do_5b) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0x93: /* Digital Signature Counter (3-bytes) */
|
||||
{
|
||||
icc_result_value = (word)&do_93[2];
|
||||
icc_result_len = sizeof (do_93) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0xc5: /* Fingerprints */
|
||||
{
|
||||
icc_result_value = &do_c5[2];
|
||||
icc_result_len = sizeof (do_c5) - 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0x5f2d: /* Language preference */
|
||||
{
|
||||
icc_result_value = (word)&do_5f2d[3];
|
||||
icc_result_len = sizeof (do_5f2d) - 3;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0x5f35: /* Sex */
|
||||
{
|
||||
icc_result_value = (word)&do_5f35[3];
|
||||
icc_result_len = sizeof (do_5f35) - 3;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0x5f50: /* URL */
|
||||
{
|
||||
icc_result_value = (word)&do_5f50[3];
|
||||
icc_result_len = sizeof (do_5f50) - 3;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0x65: /* Card Holder Related Data (Tag) */
|
||||
{
|
||||
icc_result_value = (word)do_65_head;
|
||||
icc_result_len = do_65_head[1] + 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0x6e: /* Application Related Data (Tag) */
|
||||
{
|
||||
icc_result_value = (word)do_6e_head;
|
||||
icc_result_len = do_6e_head[2] + 3;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0x7a: /* Security Support Template (Tag) */
|
||||
{
|
||||
icc_result_value = (word)do_7a_head;
|
||||
icc_result_len = do_7a_head[1] + 2;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
|
||||
break;
|
||||
}
|
||||
case 0xc6: /* List of CA fingerprints */
|
||||
case 0xcd: /* List of generation dates/times public-key pairs */
|
||||
default:
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
}
|
||||
else if (icc_read_buf[1] == INS_PSO)
|
||||
{
|
||||
stx_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");
|
||||
else
|
||||
{
|
||||
icc_result_value = rsa_sign (&icc_read_buf[5]);
|
||||
icc_result_len = RSA_SIGNATURE_LENGTH;
|
||||
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_RAM;
|
||||
}
|
||||
|
||||
stx_put_string ("done.\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
stx_put_string (" - ???\r\n");
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stx_put_string (" - ???\r\n");
|
||||
icc_result_value = 0x9000;
|
||||
icc_result_len = 0;
|
||||
icc_result_flag = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ICC_RESULT_MAX_LEN 32
|
||||
|
||||
static byte
|
||||
send_result_adpu (void)
|
||||
{
|
||||
byte r = 0;
|
||||
|
||||
if ((icc_result_flag & ICC_RESULT_BUF))
|
||||
{
|
||||
if ((icc_result_flag & ICC_RESULT_BUF_MASK) == ICC_RESULT_BUF_ROM
|
||||
|| (icc_result_flag & ICC_RESULT_BUF_MASK) == ICC_RESULT_BUF_RAM)
|
||||
{
|
||||
byte r;
|
||||
|
||||
asm volatile ("cli");
|
||||
icc_status = ICC_STATUS_DATA;
|
||||
icc_write_task = current;
|
||||
task_wait_bits |= taskset_current ();
|
||||
r = stx_yield ();
|
||||
|
||||
if (r == 0)
|
||||
{
|
||||
if (icc_result_len <= ICC_RESULT_MAX_LEN)
|
||||
{
|
||||
icc_write_buf[0] = 0x90;
|
||||
icc_write_buf[1] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_result_len -= ICC_RESULT_MAX_LEN;
|
||||
icc_result_value += ICC_RESULT_MAX_LEN;
|
||||
icc_write_buf[0] = 0x61;
|
||||
icc_write_buf[1] = icc_result_len;
|
||||
}
|
||||
|
||||
icc_write_len = 2;
|
||||
asm volatile ("cli");
|
||||
icc_status = ICC_STATUS_SW;
|
||||
icc_write_task = current;
|
||||
task_wait_bits |= taskset_current ();
|
||||
stx_yield ();
|
||||
}
|
||||
}
|
||||
else
|
||||
;
|
||||
}
|
||||
else /* Status word */
|
||||
{
|
||||
icc_write_buf[0] = (icc_result_value >> 8);
|
||||
icc_write_buf[1] = (icc_result_value & 0xff);
|
||||
icc_write_len = 2;
|
||||
|
||||
asm volatile ("cli");
|
||||
icc_status = ICC_STATUS_SW;
|
||||
icc_write_task = current;
|
||||
task_wait_bits |= taskset_current ();
|
||||
stx_yield ();
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
byte
|
||||
stx_icc_wait_power_on (void)
|
||||
{
|
||||
stx_put_string ("W\r\n");
|
||||
asm volatile ("cli");
|
||||
icc_status = ICC_STATUS_DATA; /* Ready to send ATR */
|
||||
icc_wait_task = current;
|
||||
task_wait_bits |= taskset_current ();
|
||||
stx_yield ();
|
||||
|
||||
stx_put_string ("w\r\n");
|
||||
if (icc_wait_result)
|
||||
{
|
||||
char s[10];
|
||||
sprintf(s,"On %d\r\n", icc_wait_task);
|
||||
stx_put_string (s);
|
||||
}
|
||||
else
|
||||
stx_put_string ("Off?\r\n");
|
||||
return icc_wait_result;
|
||||
}
|
||||
|
||||
void
|
||||
icc_main (void)
|
||||
{
|
||||
#if 1
|
||||
word old_sp = icc_initial_sp;
|
||||
|
||||
icc_status = ICC_STATUS_BUSY;
|
||||
icc_wait_task = 0;
|
||||
icc_write_task = 0;
|
||||
icc_read_task = 0;
|
||||
|
||||
icc_initial_sp = task[ICC_TASK] + 32 + 1 + 2;
|
||||
|
||||
if (old_sp != icc_initial_sp)
|
||||
stx_put_string ("Start\r\n");
|
||||
else
|
||||
stx_put_string ("RESET\r\n");
|
||||
#else
|
||||
char s[12];
|
||||
sprintf(s, "Start %d\r\n", current);
|
||||
stx_put_string (s);
|
||||
#endif
|
||||
|
||||
again:
|
||||
if (stx_icc_wait_power_on ())
|
||||
while (1)
|
||||
{
|
||||
byte r;
|
||||
r = receive_command_adpu ();
|
||||
|
||||
if (r == 0xff) /* wait for XFR_BLOCK */
|
||||
break;
|
||||
|
||||
if (r == 0)
|
||||
{
|
||||
stx_put_string ("zero size command packet\r\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (process_command_adpu ())
|
||||
continue;
|
||||
|
||||
if (send_result_adpu () == 0xff)
|
||||
break;
|
||||
}
|
||||
|
||||
stx_put_string ("Reset\r\n");
|
||||
goto again;
|
||||
}
|
@ -207,9 +207,9 @@ int main(int argc, char **argv)
|
||||
|
||||
chThdSleepMilliseconds (100);
|
||||
|
||||
if (bDeviceState == CONFIGURED && (count % 30) == 0)
|
||||
if (bDeviceState == CONFIGURED && (count % 300) == 0)
|
||||
{
|
||||
_write ("0123456789"+((count / 30)%10), 1);
|
||||
_write ("0123456789"+((count / 300)%10), 1);
|
||||
_write ("\r\nThis is ChibiOS 2.0.2 on Olimex STM32-H103.\r\n"
|
||||
"Testing USB driver.\n\n"
|
||||
"Hello world\r\n\r\n", 47+21+15);
|
||||
|
529
src/usb-icc.c
529
src/usb-icc.c
@ -32,11 +32,59 @@
|
||||
#include "hw_config.h"
|
||||
#include "usb_istr.h"
|
||||
|
||||
static uint8_t icc_buffer_out[64];
|
||||
static uint8_t icc_buffer_in[64];
|
||||
#define ICC_POWER_ON 0x62
|
||||
#define ICC_POWER_OFF 0x63
|
||||
#define ICC_SLOT_STATUS 0x65
|
||||
#define ICC_XFR_BLOCK 0x6F
|
||||
#define ICC_DATA_BLOCK_RET 0x80
|
||||
#define ICC_SLOT_STATUS_RET 0x81
|
||||
|
||||
static __IO uint32_t icc_count_out = 0;
|
||||
static uint32_t icc_count_in = 0;
|
||||
#define ICC_MSG_SEQ_OFFSET 6
|
||||
#define ICC_MSG_STATUS_OFFSET 7
|
||||
#define ICC_MSG_ERROR_OFFSET 8
|
||||
#define ICC_MSG_CHAIN_OFFSET 9
|
||||
#define ICC_MSG_DATA_OFFSET 10
|
||||
#define ICC_MSG_HEADER_SIZE ICC_MSG_DATA_OFFSET
|
||||
#define ICC_MAX_MSG_DATA_SIZE (USB_BUF_SIZE - ICC_MSG_HEADER_SIZE)
|
||||
|
||||
#define ICC_STATUS_RUN 0x00
|
||||
#define ICC_STATUS_PRESENT 0x01
|
||||
#define ICC_STATUS_NOTPRESENT 0x02
|
||||
#define ICC_CMD_STATUS_OK 0x00
|
||||
#define ICC_CMD_STATUS_ERROR 0x40
|
||||
#define ICC_CMD_STATUS_TIMEEXT 0x80
|
||||
|
||||
#define ICC_ERROR_XFR_OVERRUN 0xFC
|
||||
|
||||
|
||||
struct icc_header {
|
||||
uint8_t msg_type;
|
||||
int32_t data_len;
|
||||
uint8_t slot;
|
||||
uint8_t seq;
|
||||
uint8_t rsvd;
|
||||
uint16_t param;
|
||||
} __attribute__((packed));
|
||||
|
||||
static struct icc_header *icc_header;
|
||||
static uint8_t icc_seq;
|
||||
|
||||
static uint8_t *icc_data;
|
||||
static int icc_data_size;
|
||||
|
||||
static uint8_t icc_rcv_data[USB_BUF_SIZE];
|
||||
static uint8_t icc_tx_data[USB_BUF_SIZE];
|
||||
|
||||
static int icc_tx_size;
|
||||
|
||||
static int
|
||||
icc_tx_ready (void)
|
||||
{
|
||||
if (icc_tx_size == -1)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Thread *icc_thread;
|
||||
|
||||
@ -48,332 +96,330 @@ Thread *icc_thread;
|
||||
void
|
||||
EP4_IN_Callback (void)
|
||||
{
|
||||
icc_count_in = 0;
|
||||
if (icc_tx_size == USB_BUF_SIZE)
|
||||
{
|
||||
icc_tx_size = 0;
|
||||
USB_SIL_Write (EP4_IN, icc_tx_data, icc_tx_size);
|
||||
SetEPTxValid (ENDP4);
|
||||
}
|
||||
else
|
||||
icc_tx_size = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rx data
|
||||
* Upon arrival of Bulk-OUT packet,
|
||||
* we setup the variables (icc_header, icc_data, and icc_data_size, icc_seq)
|
||||
* and notify icc_thread
|
||||
* (modify header's byte order to host order if needed)
|
||||
*/
|
||||
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);
|
||||
}
|
||||
int len;
|
||||
|
||||
#define ICC_POWER_ON 0x62
|
||||
#define ICC_POWER_OFF 0x63
|
||||
#define ICC_SLOT_STATUS 0x65
|
||||
#define XFR_BLOCK 0x6F
|
||||
|
||||
#define ICC_MSG_SEQ_OFFSET 6
|
||||
#define ICC_MSG_STATUS_OFFSET 7
|
||||
#define ICC_MSG_ERROR_OFFSET 8
|
||||
|
||||
#if 0
|
||||
0 bMessageType 0x62
|
||||
1 dwLength 0x00000000
|
||||
5 bSlot 0x00 FIXED
|
||||
6 bSeq 0x00-FF
|
||||
7 bReserved 0x01 FIXED
|
||||
8 abRFU 0x0000
|
||||
-->
|
||||
0 bMessageType 0x80 Indicates RDR_to_PC_DataBlock
|
||||
1 dwLength Size of bytes for the ATR
|
||||
5 bSlot 0x00 FIXED
|
||||
6 bSeq Sequence number for the corresponding command.
|
||||
7 bStatus USB-ICC Status register as defined in Table 6.1-8
|
||||
8 bError USB-ICC Error register as defined in Table 6.1-9
|
||||
9 bChainParameter 0x00 Indicates that this message contains the complete ATR.
|
||||
10 abData ATR
|
||||
|
||||
|
||||
0 bMessageType 0x63
|
||||
1 dwLength 0x00000000 Message-specific data length
|
||||
5 bSlot 0x00 FIXED
|
||||
6 bSeq 0x00-FF Sequence number for command.
|
||||
7 abRFU 0x000000
|
||||
-->
|
||||
0 bMessageType 81h Indicates RDR_to_PC_SlotStatus
|
||||
1 dwLength 0x00000000 Message-specific data length
|
||||
5 bSlot 0x00 FIXED
|
||||
6 bSeq Sequence number for the corresponding command.
|
||||
7 bStatus USB-ICC Status register as defined in Table 6.1-8
|
||||
8 bError USB-ICC Error register as defined in Table 6.1-9
|
||||
9 bReserved 0x00 FIXED
|
||||
|
||||
|
||||
0 bMessageType 0x6F Indicates PC_to_RDR_XfrBlock
|
||||
1 dwLength Size of abData field of this message
|
||||
5 bSlot 0x00 FIXED
|
||||
6 bSeq 0x00-FF Sequence number for command.
|
||||
7 bReserved 0x00 FIXED
|
||||
8 wLevelParameter
|
||||
0x0000
|
||||
the command APDU begins and ends with this command
|
||||
|
||||
0x0001
|
||||
the command APDU begins with this command, and
|
||||
continue in the next PC_to_RDR_XfrBlock
|
||||
|
||||
0x0002
|
||||
this abData field continues a command APDU and
|
||||
ends the command APDU
|
||||
|
||||
0x0003
|
||||
the abData field continues a command APDU and
|
||||
another block is to follow
|
||||
|
||||
0x0010
|
||||
empty abData field, continuation of response APDU
|
||||
is expected in the next RDR_to_PC_DataBlock.
|
||||
|
||||
10 abData Data block sent to the USB-ICC
|
||||
-->
|
||||
0 bMessageType 0x80 Indicates RDR_to_PC_DataBlock
|
||||
1 dwLength Size of abData field of this message
|
||||
5 bSlot 0x00 FIXED
|
||||
6 bSeq Sequence number for the corresponding command.
|
||||
|
||||
7 bStatus USB-ICC Status register as defined in Table 6.1-8
|
||||
8 bError USB-ICC Error register as defined in Table 6.1-9
|
||||
9 bChainParameter
|
||||
Indicates if the response is complete, to be
|
||||
continued or if the command APDU can continue
|
||||
0x00: The response APDU begins and ends in this command
|
||||
0x01: The response APDU begins with this command and is to continue
|
||||
0x02: This abData field continues the response
|
||||
APDU and ends the response APDU
|
||||
0x03: This abData field continues the response
|
||||
APDU and another block is to follow
|
||||
0x10: Empty abData field, continuation of the
|
||||
command APDU is expected in next PC_to_RDR_XfrBlock command
|
||||
10 abData
|
||||
|
||||
|
||||
/* status code and error code */
|
||||
0 bmIccStatus 1 0, 1, 2 0= The USB-ICC is present and activated.
|
||||
(2 bits) 1= The USB-ICC is present but not activated
|
||||
(2 bits) 2= The USB-ICC is virtually not present
|
||||
3= RFU
|
||||
(4 bits) RFU
|
||||
(6 bits) bmCommandStatus (2 bits) 0, 1, 2 0= Processed without error.
|
||||
1= Failed, error condition given by bError.
|
||||
2= Time extension is requested
|
||||
3= RFU
|
||||
1 bError 1 Error codes
|
||||
|
||||
|
||||
/* error code */
|
||||
ICC_MUTE 0xFE The applications of the USB-ICC did not respond
|
||||
or the ATR could not be sent by the USB-ICC.
|
||||
XFR_OVERRUN 0xFC The USB-ICC detected a buffer overflow when
|
||||
receiving a data block.
|
||||
HW_ERROR 0xFB The USB-ICC detected a hardware error.
|
||||
|
||||
(0xC0 to 0x81) User defined
|
||||
|
||||
0xE0, 0xEF, 0xF0, These values shall not be used by the USB-ICC
|
||||
0xF2..0xF8, 0xFD
|
||||
|
||||
all others Reserved for future use
|
||||
(0x80 and those filling the gaps)
|
||||
#ifdef HOST_BIG_ENDIAN
|
||||
#error "Here, you need to write code to correct byte order."
|
||||
#else
|
||||
/* nothing to do */
|
||||
#endif
|
||||
|
||||
len = USB_SIL_Read (EP5_OUT, icc_rcv_data);
|
||||
|
||||
icc_header = (struct icc_header *)icc_rcv_data;
|
||||
icc_data = &icc_rcv_data[ICC_MSG_DATA_OFFSET];
|
||||
icc_data_size = len - ICC_MSG_HEADER_SIZE;
|
||||
icc_seq = icc_header->seq;
|
||||
|
||||
if (icc_data_size < 0 || icc_data_size != icc_header->data_len)
|
||||
/* just ignore short invalid packet, enable Rx again */
|
||||
SetEPRxValid (ENDP5);
|
||||
else
|
||||
/* Notify icc_thread */
|
||||
chEvtSignalI (icc_thread, EV_RX_DATA_READY);
|
||||
}
|
||||
|
||||
enum icc_state
|
||||
{
|
||||
ICC_STATE_START, /* Initial */
|
||||
ICC_STATE_WAIT, /* Waiting ADPU */
|
||||
ICC_STATE_WAIT, /* Waiting APDU */
|
||||
/* Busy1, Busy2, Busy3, Busy5 */
|
||||
ICC_STATE_EXECUTE, /* Busy4 */
|
||||
ICC_STATE_RECEIVE, /* ADPU Received Partially */
|
||||
ICC_STATE_SEND /* ADPU Sent Partially */
|
||||
ICC_STATE_RECEIVE, /* APDU Received Partially */
|
||||
ICC_STATE_SEND, /* APDU Sent Partially */
|
||||
};
|
||||
|
||||
static enum icc_state icc_state;
|
||||
|
||||
/* Direct conversion, T=1, "FSIJ" */
|
||||
static const char ATR[] = { '\x3B', '\x84', '\x01', 'F', 'S', 'I', 'J' };
|
||||
static const char ATR[] = { '\x3B', '\x84', '\x01', 'F', 'S', 'I', 'J',
|
||||
('\x84'^'F'^'S'^'I'^'J') };
|
||||
|
||||
/* Send back ATR (Answer To Reset) */
|
||||
enum icc_state
|
||||
icc_power_on (char *buf, int len)
|
||||
icc_power_on (void)
|
||||
{
|
||||
int i, size_atr;
|
||||
int size_atr;
|
||||
|
||||
size_atr = sizeof (ATR);
|
||||
|
||||
icc_buffer_in[0] = 0x80;
|
||||
icc_buffer_in[1] = size_atr;
|
||||
/* not including '\0' at the end */
|
||||
icc_buffer_in[2] = 0x00;
|
||||
icc_buffer_in[3] = 0x00;
|
||||
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;
|
||||
icc_buffer_in[ICC_MSG_ERROR_OFFSET] = 0x00;
|
||||
icc_buffer_in[9] = 0x00;
|
||||
for (i = 0; i < size_atr; i++)
|
||||
icc_buffer_in[i+10] = ATR[i];
|
||||
icc_tx_data[0] = ICC_DATA_BLOCK_RET;
|
||||
icc_tx_data[1] = size_atr;
|
||||
icc_tx_data[2] = 0x00;
|
||||
icc_tx_data[3] = 0x00;
|
||||
icc_tx_data[4] = 0x00;
|
||||
icc_tx_data[5] = 0x00; /* Slot */
|
||||
icc_tx_data[ICC_MSG_SEQ_OFFSET] = icc_seq;
|
||||
icc_tx_data[ICC_MSG_STATUS_OFFSET] = 0x00;
|
||||
icc_tx_data[ICC_MSG_ERROR_OFFSET] = 0x00;
|
||||
icc_tx_data[ICC_MSG_CHAIN_OFFSET] = 0x00;
|
||||
memcpy (&icc_tx_data[ICC_MSG_DATA_OFFSET], ATR, size_atr);
|
||||
|
||||
icc_count_in = 10 + size_atr;
|
||||
if (!icc_tx_ready ())
|
||||
{
|
||||
_write ("ERR0B\r\n", 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_tx_size = ICC_MSG_DATA_OFFSET + size_atr;
|
||||
USB_SIL_Write (EP4_IN, icc_tx_data, icc_tx_size);
|
||||
SetEPTxValid (ENDP4);
|
||||
_write ("ON\r\n", 4);
|
||||
}
|
||||
|
||||
USB_SIL_Write (EP4_IN, icc_buffer_in, icc_count_in);
|
||||
SetEPTxValid (ENDP4);
|
||||
|
||||
_write ("ON\r\n", 4);
|
||||
return ICC_STATE_WAIT;
|
||||
}
|
||||
|
||||
static void
|
||||
icc_send_status (char *buf, int len)
|
||||
icc_send_status (void)
|
||||
{
|
||||
icc_buffer_in[0] = 0x81;
|
||||
icc_buffer_in[1] = 0x00;
|
||||
icc_buffer_in[2] = 0x00;
|
||||
icc_buffer_in[3] = 0x00;
|
||||
icc_buffer_in[4] = 0x00;
|
||||
icc_buffer_in[5] = 0x00; /* Slot */
|
||||
icc_buffer_in[ICC_MSG_SEQ_OFFSET] = buf[ICC_MSG_SEQ_OFFSET];
|
||||
icc_tx_data[0] = ICC_SLOT_STATUS_RET;
|
||||
icc_tx_data[1] = 0x00;
|
||||
icc_tx_data[2] = 0x00;
|
||||
icc_tx_data[3] = 0x00;
|
||||
icc_tx_data[4] = 0x00;
|
||||
icc_tx_data[5] = 0x00; /* Slot */
|
||||
icc_tx_data[ICC_MSG_SEQ_OFFSET] = icc_seq;
|
||||
if (icc_state == ICC_STATE_START)
|
||||
icc_buffer_in[ICC_MSG_STATUS_OFFSET] = 2; /* No ICC present */
|
||||
/* 1: ICC present but not activated 2: No ICC present */
|
||||
icc_tx_data[ICC_MSG_STATUS_OFFSET] = 1;
|
||||
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;
|
||||
/* An ICC is present and active */
|
||||
icc_tx_data[ICC_MSG_STATUS_OFFSET] = 0;
|
||||
icc_tx_data[ICC_MSG_ERROR_OFFSET] = 0x00;
|
||||
icc_tx_data[ICC_MSG_CHAIN_OFFSET] = 0x00;
|
||||
|
||||
icc_count_in = 10;
|
||||
USB_SIL_Write (EP4_IN, icc_buffer_in, icc_count_in);
|
||||
SetEPTxValid (ENDP4);
|
||||
if (!icc_tx_ready ())
|
||||
{
|
||||
_write ("ERR0C\r\n", 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_tx_size = ICC_MSG_DATA_OFFSET;
|
||||
USB_SIL_Write (EP4_IN, icc_tx_data, icc_tx_size);
|
||||
SetEPTxValid (ENDP4);
|
||||
}
|
||||
_write ("St\r\n", 4);
|
||||
}
|
||||
|
||||
enum icc_state
|
||||
icc_power_off (char *buf, int len)
|
||||
icc_power_off (void)
|
||||
{
|
||||
|
||||
icc_send_status (buf, len);
|
||||
icc_send_status ();
|
||||
_write ("OFF\r\n", 5);
|
||||
return ICC_STATE_START;
|
||||
}
|
||||
|
||||
uint8_t cmd_APDU[MAX_CMD_APDU_SIZE];
|
||||
uint8_t res_APDU[MAX_RES_APDU_SIZE];
|
||||
int cmd_APDU_size;
|
||||
int res_APDU_size;
|
||||
|
||||
static uint8_t *p_cmd;
|
||||
static uint8_t *p_res;
|
||||
|
||||
static void
|
||||
icc_send_data_block (uint8_t status, uint8_t error, uint8_t chain,
|
||||
uint8_t *data, int len)
|
||||
{
|
||||
icc_tx_data[0] = ICC_DATA_BLOCK_RET;
|
||||
icc_tx_data[1] = len & 0xFF;
|
||||
icc_tx_data[2] = (len >> 8)& 0xFF;
|
||||
icc_tx_data[3] = (len >> 16)& 0xFF;
|
||||
icc_tx_data[4] = (len >> 24)& 0xFF;
|
||||
icc_tx_data[5] = 0x00; /* Slot */
|
||||
icc_tx_data[ICC_MSG_SEQ_OFFSET] = icc_seq;
|
||||
icc_tx_data[ICC_MSG_STATUS_OFFSET] = status;
|
||||
icc_tx_data[ICC_MSG_ERROR_OFFSET] = error;
|
||||
icc_tx_data[ICC_MSG_CHAIN_OFFSET] = chain;
|
||||
if (len)
|
||||
memcpy (&icc_tx_data[ICC_MSG_DATA_OFFSET], data, len);
|
||||
|
||||
if (!icc_tx_ready ())
|
||||
{ /* not ready to send */
|
||||
_write ("ERR09\r\n", 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_tx_size = ICC_MSG_DATA_OFFSET + len;
|
||||
USB_SIL_Write (EP4_IN, icc_tx_data, icc_tx_size);
|
||||
SetEPTxValid (ENDP4);
|
||||
_write ("DATA\r\n", 6);
|
||||
}
|
||||
}
|
||||
|
||||
static enum icc_state
|
||||
icc_handle_data (void)
|
||||
{
|
||||
enum icc_state next_state = icc_state;
|
||||
|
||||
#if 1
|
||||
char b[3];
|
||||
|
||||
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)
|
||||
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);
|
||||
if (icc_header->msg_type == ICC_POWER_ON)
|
||||
next_state = icc_power_on ();
|
||||
else if (icc_header->msg_type == ICC_POWER_OFF)
|
||||
next_state = icc_power_off ();
|
||||
else if (icc_header->msg_type == ICC_SLOT_STATUS)
|
||||
icc_send_status ();
|
||||
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)
|
||||
if (icc_header->msg_type == ICC_POWER_ON)
|
||||
/* Not in the spec., but GPG 2 */
|
||||
next_state = icc_power_on ();
|
||||
else if (icc_header->msg_type == ICC_POWER_OFF)
|
||||
next_state = icc_power_off ();
|
||||
else if (icc_header->msg_type == ICC_SLOT_STATUS)
|
||||
icc_send_status ();
|
||||
else if (icc_header->msg_type == ICC_XFR_BLOCK)
|
||||
{
|
||||
if (icc_buffer_out[8] == 0 && icc_buffer_out[9] == 0)
|
||||
{
|
||||
/* Give this message to GPG thread */
|
||||
next_state = ICC_STATE_EXECUTE;
|
||||
if (icc_header->param == 0)
|
||||
{ /* Give this message to GPG thread */
|
||||
p_cmd = cmd_APDU;
|
||||
memcpy (p_cmd, icc_data, icc_data_size);
|
||||
cmd_APDU_size = icc_data_size;
|
||||
chEvtSignal (gpg_thread, (eventmask_t)1);
|
||||
next_state = ICC_STATE_EXECUTE;
|
||||
}
|
||||
else if (icc_buffer_out[8] == 1 && icc_buffer_out[9] == 0)
|
||||
else if (icc_header->param == 1)
|
||||
{
|
||||
/* XXX: return back RDR_to_PC_DataBlock */
|
||||
/* bChainParameter = 0x10, abData=empty */
|
||||
p_cmd = cmd_APDU;
|
||||
memcpy (p_cmd, icc_data, icc_data_size);
|
||||
p_cmd += icc_data_size;
|
||||
cmd_APDU_size = icc_data_size;
|
||||
icc_send_data_block (0, 0, 0x10, NULL, 0);
|
||||
next_state = ICC_STATE_RECEIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX: error */;
|
||||
{ /* XXX: error */;
|
||||
_write ("ERR02\r\n", 7);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR03\r\n", 7);
|
||||
put_byte (icc_header->msg_type);
|
||||
next_state = ICC_STATE_START;
|
||||
}
|
||||
break;
|
||||
case ICC_STATE_EXECUTE:
|
||||
if (icc_buffer_out[0] == ICC_POWER_OFF)
|
||||
if (icc_header->msg_type == ICC_POWER_OFF)
|
||||
{
|
||||
/* XXX: Kill GPG thread */
|
||||
next_state = icc_power_off (icc_buffer_out, icc_count_out);
|
||||
next_state = icc_power_off ();
|
||||
}
|
||||
else if (icc_buffer_out[0] == ICC_SLOT_STATUS)
|
||||
icc_send_status (icc_buffer_out, icc_count_out);
|
||||
else if (icc_header->msg_type == ICC_SLOT_STATUS)
|
||||
icc_send_status ();
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR04\r\n", 7);
|
||||
put_byte (icc_header->msg_type);
|
||||
next_state = ICC_STATE_START;
|
||||
}
|
||||
break;
|
||||
case ICC_STATE_RECEIVE:
|
||||
if (icc_buffer_out[0] == ICC_POWER_OFF)
|
||||
if (icc_header->msg_type == ICC_POWER_OFF)
|
||||
next_state = icc_power_off ();
|
||||
else if (icc_header->msg_type == ICC_SLOT_STATUS)
|
||||
icc_send_status ();
|
||||
else if (icc_header->msg_type == ICC_XFR_BLOCK)
|
||||
{
|
||||
/* 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 */
|
||||
if (cmd_APDU_size + icc_data_size <= MAX_CMD_APDU_SIZE)
|
||||
{
|
||||
/* Give this message to GPG thread */
|
||||
next_state = ICC_STATE_EXECUTE;
|
||||
chEvtSignal (gpg_thread, (eventmask_t)1);
|
||||
memcpy (p_cmd, icc_data, icc_data_size);
|
||||
p_cmd += icc_data_size;
|
||||
cmd_APDU_size += icc_data_size;
|
||||
|
||||
if (icc_header->param == 2) /* Got final block */
|
||||
{ /* Give this message to GPG thread */
|
||||
next_state = ICC_STATE_EXECUTE;
|
||||
cmd_APDU_size = p_cmd - cmd_APDU;
|
||||
chEvtSignal (gpg_thread, (eventmask_t)1);
|
||||
}
|
||||
else if (icc_header->param == 3)
|
||||
icc_send_data_block (0, 0, 0x10, NULL, 0);
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR08\r\n", 7);
|
||||
}
|
||||
}
|
||||
else /* Overrun */
|
||||
{
|
||||
icc_send_data_block (ICC_CMD_STATUS_ERROR, ICC_ERROR_XFR_OVERRUN,
|
||||
0, NULL, 0);
|
||||
next_state = ICC_STATE_WAIT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR05\r\n", 7);
|
||||
put_byte (icc_header->msg_type);
|
||||
next_state = ICC_STATE_START;
|
||||
}
|
||||
break;
|
||||
case ICC_STATE_SEND:
|
||||
if (icc_buffer_out[0] == ICC_POWER_OFF)
|
||||
if (icc_header->msg_type == ICC_POWER_OFF)
|
||||
next_state = icc_power_off ();
|
||||
else if (icc_header->msg_type == ICC_SLOT_STATUS)
|
||||
icc_send_status ();
|
||||
else if (icc_header->msg_type == ICC_XFR_BLOCK)
|
||||
{
|
||||
/* 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;
|
||||
if (icc_header->param == 0x10)
|
||||
{
|
||||
if (res_APDU_size <= ICC_MAX_MSG_DATA_SIZE)
|
||||
{
|
||||
icc_send_data_block (0, 0, 0x02, p_res, res_APDU_size);
|
||||
next_state = ICC_STATE_WAIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_send_data_block (0, 0, 0x03,
|
||||
p_res, ICC_MAX_MSG_DATA_SIZE);
|
||||
p_res += ICC_MAX_MSG_DATA_SIZE;
|
||||
res_APDU_size -= ICC_MAX_MSG_DATA_SIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR0A\r\n", 7);
|
||||
put_byte (icc_header->param >> 8);
|
||||
put_byte (icc_header->param & 0xff);
|
||||
next_state = ICC_STATE_WAIT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR06\r\n", 7);
|
||||
put_byte (icc_header->msg_type);
|
||||
next_state = ICC_STATE_START;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
icc_count_out = 0;
|
||||
SetEPRxValid (ENDP5);
|
||||
return next_state;
|
||||
}
|
||||
@ -383,18 +429,16 @@ 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
|
||||
switch (icc_state)
|
||||
{
|
||||
next_state = ICC_STATE_WAIT;
|
||||
case ICC_STATE_EXECUTE:
|
||||
icc_send_data_block (ICC_CMD_STATUS_TIMEEXT, 0, 0, NULL, 0);
|
||||
break;
|
||||
case ICC_STATE_RECEIVE:
|
||||
case ICC_STATE_SEND:
|
||||
case ICC_STATE_START:
|
||||
case ICC_STATE_WAIT:
|
||||
break;
|
||||
}
|
||||
|
||||
chEvtSignal (blinker_thread, (eventmask_t)1);
|
||||
@ -412,6 +456,7 @@ USBthread (void *arg)
|
||||
chEvtClear (ALL_EVENTS);
|
||||
|
||||
icc_state = ICC_STATE_START;
|
||||
icc_tx_size = -1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@ -425,14 +470,18 @@ USBthread (void *arg)
|
||||
{
|
||||
if (icc_state == ICC_STATE_EXECUTE)
|
||||
{
|
||||
if (1/* message is short enough*/)
|
||||
if (res_APDU_size <= ICC_MAX_MSG_DATA_SIZE)
|
||||
{
|
||||
/* XXX: send back result */;
|
||||
icc_send_data_block (0, 0, 0, res_APDU, res_APDU_size);
|
||||
icc_state = ICC_STATE_WAIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX: send back part of result */;
|
||||
p_res = res_APDU;
|
||||
icc_send_data_block (0, 0, 0x01,
|
||||
p_res, ICC_MAX_MSG_DATA_SIZE);
|
||||
p_res += ICC_MAX_MSG_DATA_SIZE;
|
||||
res_APDU_size -= ICC_MAX_MSG_DATA_SIZE;
|
||||
icc_state = ICC_STATE_SEND;
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ static const uint8_t gnukStringProduct[VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT] = {
|
||||
static uint8_t gnukStringSerial[] = {
|
||||
8, /* bLength */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
'2', 0, '.', 0, '0', 0
|
||||
'2', 0, '0', 0, '0', 0
|
||||
};
|
||||
|
||||
ONE_DESCRIPTOR Device_Descriptor = {
|
||||
|
Loading…
Reference in New Issue
Block a user