mirror of
https://salsa.debian.org/gnuk-team/gnuk/gnuk.git
synced 2024-09-20 10:50:09 +00:00
implement downloading program
This commit is contained in:
parent
e2e2e1a045
commit
ce338a9727
22
ChangeLog
22
ChangeLog
@ -1,8 +1,25 @@
|
||||
2012-05-17 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tool/gnuk_upgrade.py: New tool.
|
||||
|
||||
* src/gnuk.h (ICC_STATE_EXITED, ICC_STATE_EXEC_REQUESTED): New.
|
||||
|
||||
* src/openpgp.c (INS_EXTERNAL_AUTHENTICATE)
|
||||
(cmd_external_authenticate): New.
|
||||
(INS_GET_CHALLENGE, cmd_get_challenge): New.
|
||||
|
||||
* src/usb-icc.c (USBthread): Finish the thread with
|
||||
ICC_STATE_EXITED, after EXTERNAL_AUTHENTICATE.
|
||||
|
||||
* src/usb_prop.c (gnuk_setup_endpoints_for_interface): Add STOP
|
||||
argument.
|
||||
(gnuk_usb_event): Disable all endpoints when configure(0).
|
||||
(vcom_port_data_setup): Check direction and support
|
||||
USB_CDC_REQ_SET_LINE_CODING.
|
||||
(vcom_port_setup_with_nodata): Check direction.
|
||||
(gnuk_setup_with_data): Check direction and add FSIJ_GNUK device
|
||||
requests.
|
||||
(gnuk_setup_with_nodata): Likewise.
|
||||
|
||||
* src/usb_lld.c (LAST_OUT_DATA): Remove.
|
||||
(handle_datastage_out): Cleanup and call st103_ep_set_rxtx_status.
|
||||
@ -10,6 +27,11 @@
|
||||
st103_ep_set_tx_status.
|
||||
(handle_setup0): Likewise.
|
||||
(handle_out0): Remove LAST_OUT_DATA.
|
||||
(std_none, std_get_status, std_clear_feature, std_set_feature)
|
||||
(std_set_address, std_get_descriptor, std_get_configuration)
|
||||
(std_set_configuration, std_get_interface, std_set_interface):
|
||||
Check direction.
|
||||
(handle_setup0): Add length for setup_with_data
|
||||
|
||||
2012-05-16 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
|
@ -76,6 +76,9 @@ enum icc_state
|
||||
ICC_STATE_EXECUTE, /* Busy4 */
|
||||
ICC_STATE_RECEIVE, /* APDU Received Partially */
|
||||
ICC_STATE_SEND, /* APDU Sent Partially */
|
||||
|
||||
ICC_STATE_EXITED, /* ICC Thread Terminated */
|
||||
ICC_STATE_EXEC_REQUESTED, /* Exec requested */
|
||||
};
|
||||
|
||||
extern enum icc_state *icc_state_p;
|
||||
@ -385,3 +388,5 @@ extern uint8_t pin_input_len;
|
||||
extern int pinpad_getline (int msg_code, systime_t timeout);
|
||||
|
||||
#endif
|
||||
|
||||
extern uint8_t __heap_base__, __heap_end__;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* openpgp.c -- OpenPGP card protocol support
|
||||
*
|
||||
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@ -39,6 +39,8 @@
|
||||
#define INS_PSO 0x2a
|
||||
#define INS_RESET_RETRY_COUNTER 0x2c
|
||||
#define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR 0x47
|
||||
#define INS_EXTERNAL_AUTHENTICATE 0x82
|
||||
#define INS_GET_CHALLENGE 0x84
|
||||
#define INS_INTERNAL_AUTHENTICATE 0x88
|
||||
#define INS_SELECT_FILE 0xa4
|
||||
#define INS_READ_BINARY 0xb0
|
||||
@ -821,6 +823,43 @@ cmd_write_binary (void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_external_authenticate (void)
|
||||
{
|
||||
DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
{
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
chThdTerminate (chThdSelf ());
|
||||
set_res_sw (0xff, 0xff);
|
||||
DEBUG_INFO ("EXTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_get_challenge (void)
|
||||
{
|
||||
const uint8_t *rand;
|
||||
int i;
|
||||
|
||||
DEBUG_INFO (" - GET CHALLENGE\r\n");
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
rand = random_bytes_get ();
|
||||
memcpy (res_APDU + i * 16, rand, 16);
|
||||
random_bytes_free (rand);
|
||||
}
|
||||
|
||||
res_APDU_size = 96;
|
||||
GPG_SUCCESS ();
|
||||
DEBUG_INFO ("GET CHALLENGE done.\r\n");
|
||||
}
|
||||
|
||||
|
||||
struct command
|
||||
{
|
||||
uint8_t command;
|
||||
@ -833,11 +872,14 @@ const struct command cmds[] = {
|
||||
{ INS_PSO, cmd_pso },
|
||||
{ INS_RESET_RETRY_COUNTER, cmd_reset_user_password },
|
||||
{ INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR, cmd_pgp_gakp },
|
||||
{ INS_EXTERNAL_AUTHENTICATE, /* Not in OpenPGP card protocol */
|
||||
cmd_external_authenticate },
|
||||
{ INS_GET_CHALLENGE, cmd_get_challenge }, /* Not in OpenPGP card protocol */
|
||||
{ INS_INTERNAL_AUTHENTICATE, cmd_internal_authenticate },
|
||||
{ INS_SELECT_FILE, cmd_select_file },
|
||||
{ INS_READ_BINARY, cmd_read_binary },
|
||||
{ INS_GET_DATA, cmd_get_data },
|
||||
{ INS_WRITE_BINARY, cmd_write_binary}, /* Not in OpenPGP card protocol */
|
||||
{ INS_WRITE_BINARY, cmd_write_binary}, /* Not in OpenPGP card protocol */
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
{ INS_UPDATE_BINARY, cmd_update_binary }, /* Not in OpenPGP card protocol */
|
||||
#endif
|
||||
|
@ -1273,6 +1273,7 @@ icc_handle_timeout (struct ccid *c)
|
||||
|
||||
static struct ccid ccid;
|
||||
|
||||
#define GPG_THREAD_TERMINATED 0xffff
|
||||
|
||||
msg_t
|
||||
USBthread (void *arg)
|
||||
@ -1303,6 +1304,16 @@ USBthread (void *arg)
|
||||
else if (m == EV_EXEC_FINISHED)
|
||||
if (c->icc_state == ICC_STATE_EXECUTE)
|
||||
{
|
||||
if (c->a->sw == GPG_THREAD_TERMINATED)
|
||||
{
|
||||
c->sw1sw2[0] = 0x90;
|
||||
c->sw1sw2[1] = 0x00;
|
||||
c->state = APDU_STATE_RESULT;
|
||||
icc_send_data_block (c, 0);
|
||||
c->icc_state = ICC_STATE_EXITED;
|
||||
break;
|
||||
}
|
||||
|
||||
c->a->cmd_apdu_data_len = 0;
|
||||
c->sw1sw2[0] = c->a->sw >> 8;
|
||||
c->sw1sw2[1] = c->a->sw & 0xff;
|
||||
|
104
src/usb_lld.c
104
src/usb_lld.c
@ -4,8 +4,6 @@
|
||||
|
||||
#define USB_MAX_PACKET_SIZE 64 /* For FS device */
|
||||
|
||||
#define RECIPIENT 0x1F /* Mask to get recipient */
|
||||
|
||||
enum STANDARD_REQUESTS
|
||||
{
|
||||
GET_STATUS = 0,
|
||||
@ -450,25 +448,27 @@ static void handle_datastage_in (void)
|
||||
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
|
||||
}
|
||||
|
||||
typedef int (*HANDLER) (uint8_t rcp,
|
||||
typedef int (*HANDLER) (uint8_t req,
|
||||
uint16_t value, uint16_t index, uint16_t length);
|
||||
|
||||
static int std_none (uint8_t rcp,
|
||||
static int std_none (uint8_t req,
|
||||
uint16_t value, uint16_t index, uint16_t length)
|
||||
{
|
||||
(void)rcp; (void)value; (void)index; (void)length;
|
||||
(void)req; (void)value; (void)index; (void)length;
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
static int std_get_status (uint8_t rcp,
|
||||
static int std_get_status (uint8_t req,
|
||||
uint16_t value, uint16_t index, uint16_t length)
|
||||
{
|
||||
static uint16_t status_info;
|
||||
uint8_t rcp = req & RECIPIENT;
|
||||
|
||||
status_info = 0; /* Reset Status Information */
|
||||
data_p->addr = (uint8_t *)&status_info;
|
||||
|
||||
if (value != 0 || length != 2 || (index >> 8) != 0)
|
||||
if (value != 0 || length != 2 || (index >> 8) != 0
|
||||
|| (req & REQUEST_DIR) == 0)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
if (rcp == DEVICE_RECIPIENT)
|
||||
@ -540,9 +540,14 @@ static int std_get_status (uint8_t rcp,
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
static int std_clear_feature (uint8_t rcp, uint16_t value,
|
||||
static int std_clear_feature (uint8_t req, uint16_t value,
|
||||
uint16_t index, uint16_t length)
|
||||
{
|
||||
uint8_t rcp = req & RECIPIENT;
|
||||
|
||||
if ((req & REQUEST_DIR) == 1)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
if (rcp == DEVICE_RECIPIENT)
|
||||
{
|
||||
if (length != 0 || index != 0)
|
||||
@ -598,9 +603,14 @@ static int std_clear_feature (uint8_t rcp, uint16_t value,
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
static int std_set_feature (uint8_t rcp, uint16_t value,
|
||||
static int std_set_feature (uint8_t req, uint16_t value,
|
||||
uint16_t index, uint16_t length)
|
||||
{
|
||||
uint8_t rcp = req & RECIPIENT;
|
||||
|
||||
if ((req & REQUEST_DIR) == 1)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
if (rcp == DEVICE_RECIPIENT)
|
||||
{
|
||||
if (length != 0 || index != 0)
|
||||
@ -646,9 +656,14 @@ static int std_set_feature (uint8_t rcp, uint16_t value,
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
static int std_set_address (uint8_t rcp, uint16_t value,
|
||||
static int std_set_address (uint8_t req, uint16_t value,
|
||||
uint16_t index, uint16_t length)
|
||||
{
|
||||
uint8_t rcp = req & RECIPIENT;
|
||||
|
||||
if ((req & REQUEST_DIR) == 1)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
if (rcp == DEVICE_RECIPIENT)
|
||||
{
|
||||
if (length == 0 && value <= 127 && index == 0
|
||||
@ -659,9 +674,14 @@ static int std_set_address (uint8_t rcp, uint16_t value,
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
static int std_get_descriptor (uint8_t rcp, uint16_t value,
|
||||
static int std_get_descriptor (uint8_t req, uint16_t value,
|
||||
uint16_t index, uint16_t length)
|
||||
{
|
||||
uint8_t rcp = req & RECIPIENT;
|
||||
|
||||
if ((req & REQUEST_DIR) == 0)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
(void)length;
|
||||
if (rcp == DEVICE_RECIPIENT)
|
||||
return (*method_p->get_descriptor) ((value >> 8), index, value);
|
||||
@ -669,9 +689,14 @@ static int std_get_descriptor (uint8_t rcp, uint16_t value,
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
static int std_get_configuration (uint8_t rcp, uint16_t value,
|
||||
static int std_get_configuration (uint8_t req, uint16_t value,
|
||||
uint16_t index, uint16_t length)
|
||||
{
|
||||
uint8_t rcp = req & RECIPIENT;
|
||||
|
||||
if ((req & REQUEST_DIR) == 0)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
(void)value; (void)index; (void)length;
|
||||
if (rcp == DEVICE_RECIPIENT)
|
||||
{
|
||||
@ -683,9 +708,14 @@ static int std_get_configuration (uint8_t rcp, uint16_t value,
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
static int std_set_configuration (uint8_t rcp, uint16_t value,
|
||||
static int std_set_configuration (uint8_t req, uint16_t value,
|
||||
uint16_t index, uint16_t length)
|
||||
{
|
||||
uint8_t rcp = req & RECIPIENT;
|
||||
|
||||
if ((req & REQUEST_DIR) == 1)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
if (rcp == DEVICE_RECIPIENT && index == 0 && length == 0)
|
||||
{
|
||||
int r;
|
||||
@ -698,9 +728,14 @@ static int std_set_configuration (uint8_t rcp, uint16_t value,
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
static int std_get_interface (uint8_t rcp, uint16_t value,
|
||||
static int std_get_interface (uint8_t req, uint16_t value,
|
||||
uint16_t index, uint16_t length)
|
||||
{
|
||||
uint8_t rcp = req & RECIPIENT;
|
||||
|
||||
if ((req & REQUEST_DIR) == 0)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
if (rcp == INTERFACE_RECIPIENT)
|
||||
{
|
||||
if (value != 0 || (index >> 8) != 0 || length != 1)
|
||||
@ -715,9 +750,14 @@ static int std_get_interface (uint8_t rcp, uint16_t value,
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
static int std_set_interface (uint8_t rcp, uint16_t value,
|
||||
static int std_set_interface (uint8_t req, uint16_t value,
|
||||
uint16_t index, uint16_t length)
|
||||
{
|
||||
uint8_t rcp = req & RECIPIENT;
|
||||
|
||||
if ((req & REQUEST_DIR) == 1)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
if (rcp == INTERFACE_RECIPIENT)
|
||||
{
|
||||
int r;
|
||||
@ -759,7 +799,6 @@ static void handle_setup0 (void)
|
||||
uint8_t req;
|
||||
int r = USB_UNSUPPORT;
|
||||
HANDLER handler;
|
||||
uint8_t type_rcp;
|
||||
|
||||
pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2));
|
||||
w = *pw++;
|
||||
@ -776,34 +815,35 @@ static void handle_setup0 (void)
|
||||
data_p->len = 0;
|
||||
data_p->offset = 0;
|
||||
|
||||
type_rcp = (ctrl_p->bmRequestType & (REQUEST_TYPE | RECIPIENT));
|
||||
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) /* Interface */
|
||||
|| (ctrl_p->bmRequestType & REQUEST_TYPE) == VENDOR_REQUEST)
|
||||
{
|
||||
if (ctrl_p->wLength == 0)
|
||||
r = (*method_p->setup_with_nodata) (type_rcp, req, ctrl_p->wIndex);
|
||||
else
|
||||
{
|
||||
(*method_p->setup_with_data) (type_rcp, req, ctrl_p->wIndex);
|
||||
if (data_p->len != 0)
|
||||
r = USB_SUCCESS;
|
||||
}
|
||||
}
|
||||
else if ((ctrl_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST)
|
||||
if ((ctrl_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST)
|
||||
{
|
||||
if (req < TOTAL_REQUEST)
|
||||
{
|
||||
handler = std_request_handler[req];
|
||||
r = (*handler) (ctrl_p->bmRequestType & RECIPIENT,
|
||||
r = (*handler) (ctrl_p->bmRequestType,
|
||||
ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctrl_p->wLength == 0)
|
||||
r = (*method_p->setup_with_nodata) (ctrl_p->bmRequestType,
|
||||
req, ctrl_p->wIndex);
|
||||
else
|
||||
{
|
||||
(*method_p->setup_with_data) (ctrl_p->bmRequestType, req,
|
||||
ctrl_p->wIndex, ctrl_p->wLength);
|
||||
if (data_p->len != 0)
|
||||
r = USB_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (r != USB_SUCCESS)
|
||||
dev_p->state = STALLED;
|
||||
else
|
||||
{
|
||||
if (ctrl_p->bmRequestType & 0x80)
|
||||
if (ctrl_p->bmRequestType & REQUEST_DIR)
|
||||
{
|
||||
uint32_t len = ctrl_p->wLength;
|
||||
|
||||
|
@ -39,10 +39,12 @@ enum DESCRIPTOR_TYPE
|
||||
ENDPOINT_DESCRIPTOR
|
||||
};
|
||||
|
||||
#define REQUEST_DIR 0x80 /* Mask to get request dir */
|
||||
#define REQUEST_TYPE 0x60 /* Mask to get request type */
|
||||
#define STANDARD_REQUEST 0x00 /* Standard request */
|
||||
#define CLASS_REQUEST 0x20 /* Class request */
|
||||
#define VENDOR_REQUEST 0x40 /* Vendor request */
|
||||
#define RECIPIENT 0x1F /* Mask to get recipient */
|
||||
|
||||
struct Descriptor
|
||||
{
|
||||
@ -60,7 +62,8 @@ struct usb_device_method
|
||||
{
|
||||
void (*init) (void);
|
||||
void (*reset) (void);
|
||||
void (*setup_with_data) (uint8_t rcp, uint8_t req_no, uint16_t index);
|
||||
void (*setup_with_data) (uint8_t rcp, uint8_t req_no, uint16_t index,
|
||||
uint16_t len);
|
||||
int (*setup_with_nodata) (uint8_t rcp, uint8_t req_no, uint16_t index);
|
||||
int (*get_descriptor) (uint8_t desc_type, uint16_t index, uint16_t value);
|
||||
int (*event) (uint8_t event_type, uint16_t value);
|
||||
@ -141,3 +144,8 @@ extern uint8_t usb_lld_current_configuration (void);
|
||||
extern void usb_lld_set_feature (uint8_t feature);
|
||||
|
||||
extern void usb_lld_set_data_to_send (const void *p, size_t len);
|
||||
|
||||
extern inline void usb_lld_set_data_to_recv (void *p, size_t len)
|
||||
{
|
||||
usb_lld_set_data_to_send ((const void *)p, len);
|
||||
}
|
||||
|
100
src/usb_prop.c
100
src/usb_prop.c
@ -28,6 +28,7 @@
|
||||
#include "ch.h"
|
||||
#include "usb_lld.h"
|
||||
#include "usb_conf.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
#include "usb-cdc.h"
|
||||
@ -40,7 +41,7 @@ struct line_coding
|
||||
uint8_t datatype;
|
||||
};
|
||||
|
||||
static const struct line_coding line_coding = {
|
||||
static struct line_coding line_coding = {
|
||||
115200, /* baud rate: 115200 */
|
||||
0x00, /* stop bits: 1 */
|
||||
0x00, /* parity: none */
|
||||
@ -48,20 +49,19 @@ static const struct line_coding line_coding = {
|
||||
};
|
||||
|
||||
static void
|
||||
vcom_port_data_setup (uint8_t RequestNo)
|
||||
vcom_port_data_setup (uint8_t req, uint8_t req_no)
|
||||
{
|
||||
if (RequestNo != USB_CDC_REQ_GET_LINE_CODING)
|
||||
return;
|
||||
if ((req & REQUEST_DIR) == 1 && req_no == USB_CDC_REQ_GET_LINE_CODING)
|
||||
usb_lld_set_data_to_send (&line_coding, sizeof(line_coding));
|
||||
|
||||
/* RequestNo == USB_CDC_REQ_SET_LINE_CODING is not supported */
|
||||
|
||||
usb_lld_set_data_to_send (&line_coding, sizeof(line_coding));
|
||||
if ((req & REQUEST_DIR) == 0 && req_no == USB_CDC_REQ_SET_LINE_CODING)
|
||||
usb_lld_set_data_to_recv (&line_coding, sizeof(line_coding));
|
||||
}
|
||||
|
||||
static int
|
||||
vcom_port_setup_with_nodata (uint8_t RequestNo)
|
||||
vcom_port_setup_with_nodata (uint8_t req, uint8_t req_no)
|
||||
{
|
||||
if (RequestNo == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
||||
if ((req & REQUEST_DIR) == 0 && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
||||
/* Do nothing and success */
|
||||
return USB_SUCCESS;
|
||||
|
||||
@ -183,26 +183,54 @@ static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */
|
||||
static const uint8_t lun_table[] = { 0, 0, 0, 0, };
|
||||
#endif
|
||||
|
||||
static const uint8_t *mem_info[] = { &__heap_base__, &__heap_end__, };
|
||||
|
||||
#define USB_FSIJ_GNUK_MEMINFO 0
|
||||
#define USB_FSIJ_GNUK_DOWNLOAD 1
|
||||
#define USB_FSIJ_GNUK_EXEC 2
|
||||
|
||||
static void
|
||||
gnuk_setup_with_data (uint8_t recipient, uint8_t RequestNo, uint16_t index)
|
||||
gnuk_setup_with_data (uint8_t req, uint8_t req_no, uint16_t index,
|
||||
uint16_t len)
|
||||
{
|
||||
if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */
|
||||
uint8_t recipient = req & RECIPIENT;
|
||||
|
||||
if (recipient == (VENDOR_REQUEST | DEVICE_RECIPIENT))
|
||||
{
|
||||
if ((req & REQUEST_DIR) == 1 && req_no == USB_FSIJ_GNUK_MEMINFO)
|
||||
usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
|
||||
else if ((req & REQUEST_DIR) == 0 && req_no == USB_FSIJ_GNUK_DOWNLOAD)
|
||||
{
|
||||
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
|
||||
return;
|
||||
|
||||
if ((uint32_t)(index * 0x100) < (uint32_t)&__heap_base__
|
||||
|| (uint32_t)((index * 0x100) + len) > (uint32_t)&__heap_end__)
|
||||
return;
|
||||
|
||||
usb_lld_set_data_to_recv ((void *)0x20000000 + index*0x100, len);
|
||||
}
|
||||
}
|
||||
else if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
if (RequestNo == USB_CCID_REQ_GET_CLOCK_FREQUENCIES)
|
||||
if ((req & REQUEST_DIR) == 1
|
||||
&& req_no == USB_CCID_REQ_GET_CLOCK_FREQUENCIES)
|
||||
usb_lld_set_data_to_send (freq_table, sizeof (freq_table));
|
||||
else if (RequestNo == USB_CCID_REQ_GET_DATA_RATES)
|
||||
usb_lld_set_data_to_send (data_rate_table, sizeof (data_rate_table));
|
||||
else if ((req & REQUEST_DIR) == 1
|
||||
&& req_no == USB_CCID_REQ_GET_DATA_RATES)
|
||||
usb_lld_set_data_to_send (data_rate_table,
|
||||
sizeof (data_rate_table));
|
||||
}
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
else if (index == 1)
|
||||
vcom_port_data_setup (RequestNo);
|
||||
vcom_port_data_setup (req, req_no);
|
||||
#endif
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
else if (index == MSC_INTERFACE_NO)
|
||||
{
|
||||
if (RequestNo == MSC_GET_MAX_LUN_COMMAND)
|
||||
if ((req & REQUEST_DIR) == 1 && req_no == MSC_GET_MAX_LUN_COMMAND)
|
||||
usb_lld_set_data_to_send (lun_table, sizeof (lun_table));
|
||||
}
|
||||
#endif
|
||||
@ -211,12 +239,28 @@ gnuk_setup_with_data (uint8_t recipient, uint8_t RequestNo, uint16_t index)
|
||||
|
||||
|
||||
static int
|
||||
gnuk_setup_with_nodata (uint8_t recipient, uint8_t RequestNo, uint16_t index)
|
||||
gnuk_setup_with_nodata (uint8_t req, uint8_t req_no, uint16_t index)
|
||||
{
|
||||
if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */
|
||||
uint8_t recipient = req & RECIPIENT;
|
||||
|
||||
if ((req & REQUEST_DIR) == 1)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
if (recipient == (VENDOR_REQUEST | DEVICE_RECIPIENT))
|
||||
{
|
||||
if (req_no == USB_FSIJ_GNUK_EXEC)
|
||||
{
|
||||
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
*icc_state_p = ICC_STATE_EXEC_REQUESTED;
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
}
|
||||
else if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
if (index == 0)
|
||||
{
|
||||
if (RequestNo == USB_CCID_REQ_ABORT)
|
||||
if (req_no == USB_CCID_REQ_ABORT)
|
||||
/* wValue: bSeq, bSlot */
|
||||
/* Abortion is not supported in Gnuk */
|
||||
return USB_UNSUPPORT;
|
||||
@ -225,24 +269,20 @@ gnuk_setup_with_nodata (uint8_t recipient, uint8_t RequestNo, uint16_t index)
|
||||
}
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
else if (index == 1)
|
||||
return vcom_port_setup_with_nodata (RequestNo);
|
||||
return vcom_port_setup_with_nodata (req, req_no);
|
||||
#endif
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
else if (index == MSC_INTERFACE_NO)
|
||||
{
|
||||
if (RequestNo == MSC_MASS_STORAGE_RESET_COMMAND)
|
||||
if (req_no == MSC_MASS_STORAGE_RESET_COMMAND)
|
||||
{
|
||||
/* Should call resetting MSC thread, something like msc_reset() */
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
else
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return USB_UNSUPPORT;
|
||||
else
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -278,6 +318,8 @@ gnuk_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
|
||||
|
||||
static int gnuk_usb_event (uint8_t event_type, uint16_t value)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (event_type)
|
||||
{
|
||||
case USB_EVENT_RESET:
|
||||
@ -288,10 +330,6 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value)
|
||||
case USB_EVENT_CONFIG:
|
||||
if (usb_lld_current_configuration () == 0)
|
||||
{
|
||||
int i;
|
||||
extern void *main_thread;
|
||||
#define LED_STATUS_MODE (8)
|
||||
|
||||
if (value != 1)
|
||||
return USB_UNSUPPORT;
|
||||
|
||||
|
239
tool/gnuk_upgrade.py
Executable file
239
tool/gnuk_upgrade.py
Executable file
@ -0,0 +1,239 @@
|
||||
#! /usr/bin/python
|
||||
|
||||
"""
|
||||
gnuk_upgrade.py - a tool to upgrade firmware of Gnuk Token
|
||||
|
||||
Copyright (C) 2012 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/>.
|
||||
"""
|
||||
|
||||
from intel_hex import *
|
||||
from struct import *
|
||||
import sys, time, os, binascii, string
|
||||
|
||||
# INPUT: binary file
|
||||
|
||||
# Assume only single CCID device is attached to computer, and it's Gnuk Token
|
||||
|
||||
import usb
|
||||
|
||||
# USB class, subclass, protocol
|
||||
CCID_CLASS = 0x0B
|
||||
CCID_SUBCLASS = 0x00
|
||||
CCID_PROTOCOL_0 = 0x00
|
||||
|
||||
def icc_compose(msg_type, data_len, slot, seq, param, data):
|
||||
return pack('<BiBBBH', msg_type, data_len, slot, seq, 0, param) + data
|
||||
|
||||
def iso7816_compose(ins, p1, p2, data):
|
||||
cls = 0x00
|
||||
data_len = len(data)
|
||||
if data_len == 0:
|
||||
return pack('>BBBB', cls, ins, p1, p2)
|
||||
else:
|
||||
return pack('>BBBBBh', cls, ins, p1, p2, 0, data_len) + data
|
||||
|
||||
# This class only supports Gnuk (for now)
|
||||
class gnuk_token:
|
||||
def __init__(self, device, configuration, interface):
|
||||
"""
|
||||
__init__(device, configuration, interface) -> None
|
||||
Initialize the device.
|
||||
device: usb.Device object.
|
||||
configuration: configuration number.
|
||||
interface: usb.Interface object representing the interface and altenate setting.
|
||||
"""
|
||||
if interface.interfaceClass != CCID_CLASS:
|
||||
raise ValueError, "Wrong interface class"
|
||||
if interface.interfaceSubClass != CCID_SUBCLASS:
|
||||
raise ValueError, "Wrong interface sub class"
|
||||
self.__devhandle = device.open()
|
||||
try:
|
||||
self.__devhandle.setConfiguration(configuration)
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(interface)
|
||||
self.__devhandle.setAltInterface(interface)
|
||||
|
||||
self.__intf = interface.interfaceNumber
|
||||
self.__alt = interface.alternateSetting
|
||||
self.__conf = configuration
|
||||
|
||||
self.__bulkout = 2
|
||||
self.__bulkin = 0x81
|
||||
|
||||
self.__timeout = 10000
|
||||
self.__seq = 0
|
||||
|
||||
def icc_get_result(self):
|
||||
msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout)
|
||||
if len(msg) < 10:
|
||||
print msg
|
||||
raise ValueError, "icc_get_result"
|
||||
msg_type = msg[0]
|
||||
data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24)
|
||||
slot = msg[5]
|
||||
seq = msg[6]
|
||||
status = msg[7]
|
||||
error = msg[8]
|
||||
chain = msg[9]
|
||||
data = msg[10:]
|
||||
# XXX: check msg_type, data_len, slot, seq, error
|
||||
return (status, chain, data)
|
||||
|
||||
def icc_get_status(self):
|
||||
msg = icc_compose(0x65, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def icc_power_on(self):
|
||||
msg = icc_compose(0x62, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check status, chain
|
||||
return data # ATR
|
||||
|
||||
def icc_power_off(self):
|
||||
msg = icc_compose(0x63, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def icc_send_data_block(self, data):
|
||||
msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data)
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
return self.icc_get_result()
|
||||
|
||||
def icc_send_cmd(self, data):
|
||||
status, chain, data_rcv = self.icc_send_data_block(data)
|
||||
if chain == 0:
|
||||
return data_rcv
|
||||
elif chain == 1:
|
||||
d = data_rcv
|
||||
while True:
|
||||
msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data_rcv = self.icc_get_result()
|
||||
# XXX: check status
|
||||
d += data_rcv
|
||||
if chain == 2:
|
||||
break
|
||||
elif chain == 3:
|
||||
continue
|
||||
else:
|
||||
raise ValueError, "icc_send_cmd chain"
|
||||
return d
|
||||
else:
|
||||
raise ValueError, "icc_send_cmd"
|
||||
|
||||
def cmd_get_response(self, expected_len):
|
||||
cmd_data = iso7816_compose(0xc0, 0x00, 0x00, [expected_len])
|
||||
response = self.icc_send_cmd(cmd_data)
|
||||
return response
|
||||
|
||||
def cmd_verify(self, who, passwd):
|
||||
cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd)
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_verify"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, "cmd_verify"
|
||||
|
||||
def cmd_select_openpgp(self):
|
||||
cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01")
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_select_openpgp"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
|
||||
|
||||
def cmd_external_authenticate(self, who, signed):
|
||||
cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed)
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_external_authenticate"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, "cmd_external_authenticate"
|
||||
|
||||
def compare(data_original, data_in_device):
|
||||
i = 0
|
||||
for d in data_original:
|
||||
if ord(d) != data_in_device[i]:
|
||||
raise ValueError, "verify failed at %08x" % i
|
||||
i += 1
|
||||
|
||||
def get_device():
|
||||
busses = usb.busses()
|
||||
for bus in busses:
|
||||
devices = bus.devices
|
||||
for dev in devices:
|
||||
for config in dev.configurations:
|
||||
for intf in config.interfaces:
|
||||
for alt in intf:
|
||||
if alt.interfaceClass == CCID_CLASS and \
|
||||
alt.interfaceSubClass == CCID_SUBCLASS and \
|
||||
alt.interfaceProtocol == CCID_PROTOCOL_0:
|
||||
return dev, config, alt
|
||||
raise ValueError, "Device not found"
|
||||
|
||||
def main(passwd, data):
|
||||
dev, config, intf = get_device()
|
||||
print "Device: ", dev.filename
|
||||
print "Configuration: ", config.value
|
||||
print "Interface: ", intf.interfaceNumber
|
||||
icc = gnuk_token(dev, config, intf)
|
||||
if icc.icc_get_status() == 2:
|
||||
raise ValueError, "No ICC present"
|
||||
elif icc.icc_get_status() == 1:
|
||||
icc.icc_power_on()
|
||||
icc.cmd_verify(3, passwd)
|
||||
icc.cmd_select_openpgp()
|
||||
challenge = icc.cmd_get_challenge()
|
||||
signed = challenge
|
||||
icc.cmd_external_authenticate(signed)
|
||||
# set_configure(0) to disable all interfaces but control pipe
|
||||
# check mem_info
|
||||
# download flash install program
|
||||
# exec
|
||||
# ...
|
||||
# Then, send upgrade program...
|
||||
return 0
|
||||
|
||||
DEFAULT_PW3 = "12345678"
|
||||
|
||||
if __name__ == '__main__':
|
||||
passwd = DEFAULT_PW3
|
||||
if sys.argv[1] == '-p':
|
||||
from getpass import getpass
|
||||
passwd = getpass("Admin password: ")
|
||||
sys.argv.pop(1)
|
||||
filename = sys.argv[1]
|
||||
f = open(filename)
|
||||
data = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename, len(data))
|
||||
print "Downloading flash upgrade program"
|
||||
main(passwd, data)
|
Loading…
Reference in New Issue
Block a user