no ext lc and le but short APDU only

This commit is contained in:
NIIBE Yutaka
2012-01-20 18:18:23 +09:00
parent f92ee76db5
commit 21debc0567
13 changed files with 1064 additions and 626 deletions

View File

@@ -15,6 +15,9 @@
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "usb_lib.h" #include "usb_lib.h"
extern void usb_lld_to_pmabuf (const void *src, uint16_t addr, uint32_t n);
extern void usb_lld_from_pmabuf (void *dst, uint16_t addr, uint32_t n);
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
#define ValBit(VAR,Place) (VAR & (1 << Place)) #define ValBit(VAR,Place) (VAR & (1 << Place))
@@ -460,7 +463,7 @@ void DataStageOut(void)
#ifdef STM32F10X_CL #ifdef STM32F10X_CL
OTGD_FS_PCD_EP_Read(ENDP0, Buffer, Length); OTGD_FS_PCD_EP_Read(ENDP0, Buffer, Length);
#else #else
PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length); usb_lld_from_pmabuf (Buffer, GetEPRxAddr(ENDP0), Length);
#endif /* STM32F10X_CL */ #endif /* STM32F10X_CL */
} }
@@ -544,7 +547,7 @@ void DataStageIn(void)
#ifdef STM32F10X_CL #ifdef STM32F10X_CL
OTGD_FS_PCD_EP_Write (ENDP0, DataBuffer, Length); OTGD_FS_PCD_EP_Write (ENDP0, DataBuffer, Length);
#else #else
UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length); usb_lld_to_pmabuf (DataBuffer, GetEPTxAddr(ENDP0), Length);
#endif /* STM32F10X_CL */ #endif /* STM32F10X_CL */
SetEPTxCount(ENDP0, Length); SetEPTxCount(ENDP0, Length);

View File

@@ -167,7 +167,7 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
#endif #endif
r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len, r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len,
input, output, MAX_RES_APDU_SIZE - 2); input, output, MAX_RES_APDU_DATA_SIZE);
rsa_free (&rsa_ctx); rsa_free (&rsa_ctx);
if (r < 0) if (r < 0)
{ {

View File

@@ -36,7 +36,7 @@ struct apdu {
uint8_t *cmd_apdu_head; /* CLS INS P1 P2 [ internal Lc ] */ uint8_t *cmd_apdu_head; /* CLS INS P1 P2 [ internal Lc ] */
uint8_t *cmd_apdu_data; uint8_t *cmd_apdu_data;
uint16_t cmd_apdu_data_len; /* Nc, calculated by Lc field */ uint16_t cmd_apdu_data_len; /* Nc, calculated by Lc field */
uint32_t expected_res_size; /* Ne, calculated by Le field */ uint16_t expected_res_size; /* Ne, calculated by Le field */
/* response APDU */ /* response APDU */
uint16_t sw; uint16_t sw;
@@ -55,10 +55,10 @@ extern struct apdu apdu;
#define EV_VERIFY_CMD_AVAILABLE ((eventmask_t)8) #define EV_VERIFY_CMD_AVAILABLE ((eventmask_t)8)
#define EV_MODIFY_CMD_AVAILABLE ((eventmask_t)16) #define EV_MODIFY_CMD_AVAILABLE ((eventmask_t)16)
/* maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */ /* Maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */
#define MAX_CMD_APDU_SIZE (7+282) /* header + data */ #define MAX_CMD_APDU_DATA_SIZE (22+4+128+128) /* without header */
/* maximum res apdu data is public key 5+9+256+2 (gpg_do_public_key) */ /* Maximum res apdu data is public key 5+9+256 (gpg_do_public_key) */
#define MAX_RES_APDU_SIZE ((5+9+256)+2) /* Data + status */ #define MAX_RES_APDU_DATA_SIZE (5+9+256) /* without trailer */
#define ICC_MSG_HEADER_SIZE 10 #define ICC_MSG_HEADER_SIZE 10
@@ -68,13 +68,6 @@ extern struct apdu apdu;
/* USB buffer size of LL (Low-level): size of single Bulk transaction */ /* USB buffer size of LL (Low-level): size of single Bulk transaction */
#define USB_LL_BUF_SIZE 64 #define USB_LL_BUF_SIZE 64
/*
* USB buffer size of USB-ICC driver
* (Changing this, dwMaxCCIDMessageLength too !!)
*/
#define USB_BUF_SIZE ((10 + 10 + MAX_CMD_APDU_SIZE + USB_LL_BUF_SIZE - 1) \
/ USB_LL_BUF_SIZE * USB_LL_BUF_SIZE)
enum icc_state enum icc_state
{ {
ICC_STATE_START, /* Initial */ ICC_STATE_START, /* Initial */
@@ -85,7 +78,7 @@ enum icc_state
ICC_STATE_SEND, /* APDU Sent Partially */ ICC_STATE_SEND, /* APDU Sent Partially */
}; };
extern volatile enum icc_state icc_state; extern enum icc_state *icc_state_p;
extern volatile uint8_t auth_status; extern volatile uint8_t auth_status;
#define AC_NONE_AUTHORIZED 0x00 #define AC_NONE_AUTHORIZED 0x00
@@ -116,7 +109,7 @@ extern void ac_reset_admin (void);
extern void ac_fini (void); extern void ac_fini (void);
extern void set_res_apdu (uint8_t sw1, uint8_t sw2); extern void set_res_sw (uint8_t sw1, uint8_t sw2);
extern uint16_t data_objects_number_of_bytes; extern uint16_t data_objects_number_of_bytes;
extern void gpg_data_scan (const uint8_t *p); extern void gpg_data_scan (const uint8_t *p);

View File

@@ -287,6 +287,13 @@ static void display_fatal_code (void)
static void display_status_code (void) static void display_status_code (void)
{ {
enum icc_state icc_state;
if (icc_state_p == NULL)
icc_state = ICC_STATE_START;
else
icc_state = *icc_state_p;
if (icc_state == ICC_STATE_START) if (icc_state == ICC_STATE_START)
{ {
set_led (1); set_led (1);

View File

@@ -77,12 +77,11 @@ uint16_t data_objects_number_of_bytes;
static const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = { static const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = {
10, 10,
0x00, 0x00,
0x31, 0x80, /* Full DF name */ 0x31, 0x84, /* Full DF name, GET DATA, MF */
0x73, 0x73,
0x80, 0x01, 0x40, /* Full DF name */ 0x80, 0x01, 0x80, /* Full DF name */
/* 1-byte */ /* 1-byte */
/* No command chaining */ /* Command chaining, No extended Lc and Le */
/* Extended Lc and Le */
0x00, 0x90, 0x00 /* Status info (no life cycle management) */ 0x00, 0x90, 0x00 /* Status info (no life cycle management) */
}; };
@@ -90,27 +89,24 @@ static const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = {
static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = { static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
10, 10,
0x30, /* 0x30, /*
* No SM, No get challenge, * No SM,
* No get challenge,
* Key import supported, * Key import supported,
* PW status byte can be put, * PW status byte can be put,
* No private_use_DO, * No private_use_DO,
* No algo change allowed * No algo change allowed
*/ */
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */ 0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
0x00, 0x00, /* Max get challenge */ 0x00, 0x00, /* Max get challenge (0: Get challenge not supported) */
#ifdef CERTDO_SUPPORT #ifdef CERTDO_SUPPORT
0x07, 0xfe, /* max. length of cardholder certificate (2KB - 2)*/ 0x08, 0x00, /* max. length of cardholder certificate (2KiB) */
#else #else
0x00, 0x00, 0x00, 0x00,
#endif #endif
/* Max. length of command data */ /* Max. length of command APDU */
(MAX_CMD_APDU_SIZE>>8), (MAX_CMD_APDU_SIZE&0xff), 0x00, 0xff,
/* Max. length of response data */ /* Max. length of response data */
#ifdef CERTDO_SUPPORT 0x00, 0xff,
0x08, 0x00, /* the case of cardholder ceritificate */
#else
(MAX_RES_APDU_SIZE>>8), (MAX_RES_APDU_SIZE&0xff),
#endif
}; };
/* Algorithm Attributes */ /* Algorithm Attributes */

View File

@@ -67,7 +67,7 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = {
}; };
void void
set_res_apdu (uint8_t sw1, uint8_t sw2) set_res_sw (uint8_t sw1, uint8_t sw2)
{ {
apdu.sw = (sw1 << 8) | sw2; apdu.sw = (sw1 << 8) | sw2;
} }
@@ -510,7 +510,7 @@ cmd_select_file (void)
if (apdu.cmd_apdu_data_len != 6 if (apdu.cmd_apdu_data_len != 6
|| memcmp (openpgpcard_aid, apdu.cmd_apdu_data, 6) != 0) || memcmp (openpgpcard_aid, apdu.cmd_apdu_data, 6) != 0)
{ {
DEBUG_WORD (apdu.cmd_apdu_data_len); DEBUG_SHORT (apdu.cmd_apdu_data_len);
DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
GPG_NO_FILE (); GPG_NO_FILE ();
@@ -528,6 +528,7 @@ cmd_select_file (void)
res_APDU[1] = 0x12; res_APDU[1] = 0x12;
res_APDU[2] = 0x84; /* overwrite: DF name */ res_APDU[2] = 0x84; /* overwrite: DF name */
res_APDU_size += 2; res_APDU_size += 2;
GPG_SUCCESS ();
} }
} }
else if (apdu.cmd_apdu_data_len == 2 else if (apdu.cmd_apdu_data_len == 2

View File

@@ -1,12 +1,12 @@
#define GPG_MEMORY_FAILURE() set_res_apdu (0x65, 0x81) #define GPG_MEMORY_FAILURE() set_res_sw (0x65, 0x81)
#define GPG_SECURITY_FAILURE() set_res_apdu (0x69, 0x82) #define GPG_SECURITY_FAILURE() set_res_sw (0x69, 0x82)
#define GPG_SECURITY_AUTH_BLOCKED() set_res_apdu (0x69, 0x83) #define GPG_SECURITY_AUTH_BLOCKED() set_res_sw (0x69, 0x83)
#define GPG_CONDITION_NOT_SATISFIED() set_res_apdu (0x69, 0x85) #define GPG_CONDITION_NOT_SATISFIED() set_res_sw (0x69, 0x85)
#define GPG_COMMAND_NOT_ALLOWED() set_res_apdu (0x69, 0x86) #define GPG_COMMAND_NOT_ALLOWED() set_res_sw (0x69, 0x86)
#define GPG_FUNCTION_NOT_SUPPORTED() set_res_apdu (0x6a, 0x81) #define GPG_FUNCTION_NOT_SUPPORTED() set_res_sw (0x6a, 0x81)
#define GPG_NO_FILE() set_res_apdu (0x6a, 0x82) #define GPG_NO_FILE() set_res_sw (0x6a, 0x82)
#define GPG_NO_RECORD() set_res_apdu (0x6a, 0x88) #define GPG_NO_RECORD() set_res_sw (0x6a, 0x88)
#define GPG_BAD_P0_P1() set_res_apdu (0x6b, 0x00) #define GPG_BAD_P0_P1() set_res_sw (0x6b, 0x00)
#define GPG_NO_INS() set_res_apdu (0x6d, 0x00) #define GPG_NO_INS() set_res_sw (0x6d, 0x00)
#define GPG_ERROR() set_res_apdu (0x6f, 0x00) #define GPG_ERROR() set_res_sw (0x6f, 0x00)
#define GPG_SUCCESS() set_res_apdu (0x90, 0x00) #define GPG_SUCCESS() set_res_sw (0x90, 0x00)

View File

@@ -3,5 +3,5 @@ STMUSBSRCDIR = $(STMUSBDIR)/src
STMUSBINCDIR = $(STMUSBDIR)/inc STMUSBINCDIR = $(STMUSBDIR)/inc
STMUSBSRC= \ STMUSBSRC= \
$(STMUSBSRCDIR)/usb_init.c $(STMUSBSRCDIR)/usb_int.c \ $(STMUSBSRCDIR)/usb_init.c $(STMUSBSRCDIR)/usb_int.c \
$(STMUSBSRCDIR)/usb_mem.c $(STMUSBSRCDIR)/usb_core.c \ $(STMUSBSRCDIR)/usb_core.c \
$(STMUSBSRCDIR)/usb_regs.c $(STMUSBSRCDIR)/usb_regs.c

File diff suppressed because it is too large Load Diff

View File

@@ -102,7 +102,7 @@ static const uint8_t gnukConfigDescriptor[] = {
* ccid-driver. * ccid-driver.
*/ */
0x42, 0x08, 0x04, 0x00, /* dwFeatures (not ICCD): 0x42, 0x08, 0x04, 0x00, /* dwFeatures (not ICCD):
* Short and extended APDU level: 0x40000 * * Short APDU level : 0x20000 *
* (what? means ICCD?) : 0x00800 * * (what? means ICCD?) : 0x00800 *
* Automatic IFSD : 0x00400 * Automatic IFSD : 0x00400
* NAD value other than 0x00 : 0x00200 * NAD value other than 0x00 : 0x00200
@@ -115,7 +115,7 @@ static const uint8_t gnukConfigDescriptor[] = {
* Auto activaction of ICC : 0x00004 * Auto activaction of ICC : 0x00004
* Automatic conf. based on ATR : 0x00002 g * Automatic conf. based on ATR : 0x00002 g
*/ */
0x40, 0x01, 0, 0, /* dwMaxCCIDMessageLength */ 0x0f, 0x01, 0, 0, /* dwMaxCCIDMessageLength: 271 */
0xff, /* bClassGetResponse: */ 0xff, /* bClassGetResponse: */
0xff, /* bClassEnvelope: */ 0xff, /* bClassEnvelope: */
0, 0, /* wLCDLayout: FIXED VALUE */ 0, 0, /* wLCDLayout: FIXED VALUE */

View File

@@ -27,3 +27,76 @@ void usb_lld_init (void) {
RCC->APB1RSTR = RCC_APB1RSTR_USBRST; RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
RCC->APB1RSTR = 0; RCC->APB1RSTR = 0;
} }
void usb_lld_to_pmabuf (const void *src, uint16_t wPMABufAddr, size_t n)
{
const uint8_t *s = (const uint8_t *)src;
uint16_t *p;
uint16_t w;
if (n == 0)
return;
if ((wPMABufAddr & 1))
{
p = (uint16_t *)(PMAAddr + (wPMABufAddr - 1) * 2);
w = *p;
w = (w & 0xff) | (*s++) << 8;
*p = w;
p += 2;
n--;
}
else
p = (uint16_t *)(PMAAddr + wPMABufAddr * 2);
while (n >= 2)
{
w = *s++;
w |= (*s++) << 8;
*p = w;
p += 2;
n -= 2;
}
if (n > 0)
{
w = *s;
*p = w;
}
}
void usb_lld_from_pmabuf (void *dst, uint16_t wPMABufAddr, size_t n)
{
uint8_t *d = (uint8_t *)dst;
uint16_t *p;
uint16_t w;
if (n == 0)
return;
if ((wPMABufAddr & 1))
{
p = (uint16_t *)(PMAAddr + (wPMABufAddr - 1) * 2);
w = *p;
*d++ = (w >> 8);
p += 2;
n--;
}
else
p = (uint16_t *)(PMAAddr + wPMABufAddr * 2);
while (n >= 2)
{
w = *p;
*d++ = (w & 0xff);
*d++ = (w >> 8);
p += 2;
n -= 2;
}
if (n > 0)
{
w = *p;
*d = (w & 0xff);
}
}

View File

@@ -1,6 +1,9 @@
#define STM32_USB_IRQ_PRIORITY 11 #define STM32_USB_IRQ_PRIORITY 11
void usb_lld_init (void); void usb_lld_init (void);
extern void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n);
extern void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n);
extern inline void usb_lld_stall_tx (int ep_num) extern inline void usb_lld_stall_tx (int ep_num)
{ {
SetEPTxStatus (ep_num, EP_TX_STALL); SetEPTxStatus (ep_num, EP_TX_STALL);
@@ -16,10 +19,10 @@ extern inline int usb_lld_tx_data_len (int ep_num)
return GetEPTxCount (ep_num); return GetEPTxCount (ep_num);
} }
extern inline void usb_lld_txcpy (const uint8_t *src, extern inline void usb_lld_txcpy (const void *src,
int ep_num, int offset, size_t len) int ep_num, int offset, size_t len)
{ {
UserToPMABufferCopy ((uint8_t *)src, GetEPTxAddr (ep_num) + offset, len); usb_lld_to_pmabuf (src, GetEPTxAddr (ep_num) + offset, len);
} }
extern inline void usb_lld_tx_enable (int ep_num, size_t len) extern inline void usb_lld_tx_enable (int ep_num, size_t len)
@@ -28,9 +31,9 @@ extern inline void usb_lld_tx_enable (int ep_num, size_t len)
SetEPTxValid (ep_num); SetEPTxValid (ep_num);
} }
extern inline void usb_lld_write (uint8_t ep_num, void *buf, size_t len) extern inline void usb_lld_write (uint8_t ep_num, const void *buf, size_t len)
{ {
UserToPMABufferCopy (buf, GetEPTxAddr (ep_num), len); usb_lld_to_pmabuf (buf, GetEPTxAddr (ep_num), len);
SetEPTxCount (ep_num, len); SetEPTxCount (ep_num, len);
SetEPTxValid (ep_num); SetEPTxValid (ep_num);
} }
@@ -48,5 +51,5 @@ extern inline int usb_lld_rx_data_len (int ep_num)
extern inline void usb_lld_rxcpy (uint8_t *dst, extern inline void usb_lld_rxcpy (uint8_t *dst,
int ep_num, int offset, size_t len) int ep_num, int offset, size_t len)
{ {
PMAToUserBufferCopy (dst, GetEPRxAddr (ep_num) + offset, len); usb_lld_from_pmabuf (dst, GetEPRxAddr (ep_num) + offset, len);
} }

View File

@@ -44,7 +44,7 @@ class GnukToken(object):
self.connection = cardservice.connection self.connection = cardservice.connection
def cmd_verify(self, who, passwd): def cmd_verify(self, who, passwd):
apdu = [0x00, 0x20, 0x00, 0x80+who, 0, 0, len(passwd)] + s2l(passwd) apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd)
response, sw1, sw2 = self.connection.transmit(apdu) response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00): if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2)) raise ValueError, ("%02x%02x" % (sw1, sw2))
@@ -59,10 +59,20 @@ class GnukToken(object):
while count*256 < data_len: while count*256 < data_len:
if count == 0: if count == 0:
d = data[:256] d = data[:256]
apdu = [0x00, ins, 0x80+fileid, 0x00, 0, len(d)>>8, len(d)&0xff] + s2l(d) if len(d) <= 255:
apdu = [0x00, ins, 0x80+fileid, 0x00, len(d) ] + s2l(d)
else:
apdu0 = [0x10, ins, 0x80+fileid, 0x00, 255 ] + s2l(d[:255])
response, sw1, sw2 = self.connection.transmit(apdu0)
apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:])
else: else:
d = data[256*count:256*(count+1)] d = data[256*count:256*(count+1)]
apdu = [0x00, ins, count, 0x00, 0, len(d)>>8, len(d)&0xff] + s2l(d) if len(d) <= 255:
apdu = [0x00, ins, count, 0x00, len(d) ] + s2l(d)
else:
apdu0 = [0x10, ins, count, 0x00, 255 ] + s2l(d[:255])
response, sw1, sw2 = self.connection.transmit(apdu0)
apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:])
response, sw1, sw2 = self.connection.transmit(apdu) response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00): if not (sw1 == 0x90 and sw2 == 0x00):
if is_update: if is_update:
@@ -72,13 +82,13 @@ class GnukToken(object):
count += 1 count += 1
def cmd_select_openpgp(self): def cmd_select_openpgp(self):
apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ]
response, sw1, sw2 = self.connection.transmit(apdu) response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00): if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2)) raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_get_data(self, tagh, tagl): def cmd_get_data(self, tagh, tagl):
apdu = [0x00, 0xca, tagh, tagl] apdu = [0x00, 0xca, tagh, tagl ]
response, sw1, sw2 = self.connection.transmit(apdu) response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00): if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2)) raise ValueError, ("%02x%02x" % (sw1, sw2))
@@ -146,18 +156,6 @@ if __name__ == '__main__':
exit(1) exit(1)
print "Writing serial number" print "Writing serial number"
data = binascii.unhexlify(serial_data_hex) data = binascii.unhexlify(serial_data_hex)
elif sys.argv[1] == '-r':
fileid = 1 # Random number bits
if len(sys.argv) == 3:
filename = sys.argv[2]
f = open(filename)
else:
filename = stdin
f = sys.stdin
data = f.read()
f.close()
print "%s: %d" % (filename, len(data))
print "Updating random bits"
else: else:
fileid = 0 # Card holder certificate fileid = 0 # Card holder certificate
filename = sys.argv[1] filename = sys.argv[1]