mirror of
https://github.com/polhenarejos/pico-keys-sdk
synced 2026-06-11 04:48:15 +02:00
More and more fixes.
This commit is contained in:
1276
src/ccid/ccid2040.c
1276
src/ccid/ccid2040.c
File diff suppressed because it is too large
Load Diff
@@ -59,20 +59,16 @@ extern const uint8_t historical_bytes[];
|
|||||||
} printf("\r\n"); \
|
} printf("\r\n"); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct apdu {
|
struct apdu {
|
||||||
uint8_t seq;
|
uint8_t *header;
|
||||||
|
uint32_t nc;
|
||||||
/* command APDU */
|
uint32_t ne;
|
||||||
uint8_t *cmd_apdu_head; /* CLS INS P1 P2 [ internal Lc ] */
|
uint8_t *data;
|
||||||
uint8_t *cmd_apdu_data;
|
|
||||||
size_t cmd_apdu_data_len; /* Nc, calculated by Lc field */
|
|
||||||
size_t expected_res_size; /* Ne, calculated by Le field */
|
|
||||||
|
|
||||||
/* response APDU */
|
|
||||||
uint16_t sw;
|
uint16_t sw;
|
||||||
uint16_t res_apdu_data_len;
|
uint8_t *rdata;
|
||||||
uint8_t *res_apdu_data;
|
uint16_t rlen;
|
||||||
};
|
} __packed;
|
||||||
|
|
||||||
#define MAX_CMD_APDU_DATA_SIZE (24+4+512*4)
|
#define MAX_CMD_APDU_DATA_SIZE (24+4+512*4)
|
||||||
#define MAX_RES_APDU_DATA_SIZE (5+9+512*4)
|
#define MAX_RES_APDU_DATA_SIZE (5+9+512*4)
|
||||||
@@ -95,10 +91,6 @@ struct apdu {
|
|||||||
#define EV_BUTTON_TIMEOUT 16
|
#define EV_BUTTON_TIMEOUT 16
|
||||||
#define EV_BUTTON_PRESSED 32
|
#define EV_BUTTON_PRESSED 32
|
||||||
|
|
||||||
//Variables set by core1
|
|
||||||
extern queue_t *ccid_comm;
|
|
||||||
extern queue_t *card_comm;
|
|
||||||
|
|
||||||
enum ccid_state {
|
enum ccid_state {
|
||||||
CCID_STATE_NOCARD, /* No card available */
|
CCID_STATE_NOCARD, /* No card available */
|
||||||
CCID_STATE_START, /* Initial */
|
CCID_STATE_START, /* Initial */
|
||||||
@@ -112,13 +104,13 @@ enum ccid_state {
|
|||||||
CCID_STATE_EXEC_REQUESTED, /* Exec requested */
|
CCID_STATE_EXEC_REQUESTED, /* Exec requested */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLA(a) a.cmd_apdu_head[0]
|
#define CLA(a) a.header[0]
|
||||||
#define INS(a) a.cmd_apdu_head[1]
|
#define INS(a) a.header[1]
|
||||||
#define P1(a) a.cmd_apdu_head[2]
|
#define P1(a) a.header[2]
|
||||||
#define P2(a) a.cmd_apdu_head[3]
|
#define P2(a) a.header[3]
|
||||||
|
|
||||||
#define res_APDU apdu.res_apdu_data
|
#define res_APDU apdu.rdata
|
||||||
#define res_APDU_size apdu.res_apdu_data_len
|
#define res_APDU_size apdu.rlen
|
||||||
|
|
||||||
extern struct apdu apdu;
|
extern struct apdu apdu;
|
||||||
|
|
||||||
@@ -138,6 +130,9 @@ static inline const void put_uint16_t(uint16_t n, uint8_t *b) {
|
|||||||
|
|
||||||
extern const uint8_t *ccid_atr;
|
extern const uint8_t *ccid_atr;
|
||||||
|
|
||||||
|
extern queue_t ccid_to_card_q;
|
||||||
|
extern queue_t card_to_ccid_q;
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void stdout_init (void);
|
void stdout_init (void);
|
||||||
|
|||||||
@@ -88,13 +88,13 @@ int sm_unwrap() {
|
|||||||
return r;
|
return r;
|
||||||
int le = sm_get_le();
|
int le = sm_get_le();
|
||||||
if (le >= 0)
|
if (le >= 0)
|
||||||
apdu.expected_res_size = le;
|
apdu.ne = le;
|
||||||
uint8_t *body = NULL;
|
uint8_t *body = NULL;
|
||||||
size_t body_size = 0;
|
size_t body_size = 0;
|
||||||
bool is87 = false;
|
bool is87 = false;
|
||||||
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL;
|
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL;
|
||||||
size_t tag_len = 0;
|
size_t tag_len = 0;
|
||||||
while (walk_tlv(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, &p, &tag, &tag_len, &tag_data)) {
|
while (walk_tlv(apdu.data, apdu.nc, &p, &tag, &tag_len, &tag_data)) {
|
||||||
if (tag == 0x87 || tag == 0x85) {
|
if (tag == 0x87 || tag == 0x85) {
|
||||||
body = tag_data;
|
body = tag_data;
|
||||||
body_size = tag_len;
|
body_size = tag_len;
|
||||||
@@ -111,9 +111,9 @@ int sm_unwrap() {
|
|||||||
}
|
}
|
||||||
sm_update_iv();
|
sm_update_iv();
|
||||||
aes_decrypt(sm_kenc, sm_iv, 128, HSM_AES_MODE_CBC, body, body_size);
|
aes_decrypt(sm_kenc, sm_iv, 128, HSM_AES_MODE_CBC, body, body_size);
|
||||||
memmove(apdu.cmd_apdu_data, body, body_size);
|
memmove(apdu.data, body, body_size);
|
||||||
apdu.cmd_apdu_data_len = sm_remove_padding(apdu.cmd_apdu_data, body_size);
|
apdu.nc = sm_remove_padding(apdu.data, body_size);
|
||||||
DEBUG_PAYLOAD(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
|
DEBUG_PAYLOAD(apdu.data, apdu.nc);
|
||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,15 +173,15 @@ int sm_wrap() {
|
|||||||
res_APDU[res_APDU_size++] = 0x8E;
|
res_APDU[res_APDU_size++] = 0x8E;
|
||||||
res_APDU[res_APDU_size++] = 8;
|
res_APDU[res_APDU_size++] = 8;
|
||||||
res_APDU_size += 8;
|
res_APDU_size += 8;
|
||||||
if (apdu.expected_res_size > 0)
|
if (apdu.ne > 0)
|
||||||
apdu.expected_res_size = res_APDU_size;
|
apdu.ne = res_APDU_size;
|
||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sm_get_le() {
|
int sm_get_le() {
|
||||||
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL;
|
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL;
|
||||||
size_t tag_len = 0;
|
size_t tag_len = 0;
|
||||||
while (walk_tlv(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, &p, &tag, &tag_len, &tag_data)) {
|
while (walk_tlv(apdu.data, apdu.nc, &p, &tag, &tag_len, &tag_data)) {
|
||||||
if (tag == 0x97) {
|
if (tag == 0x97) {
|
||||||
uint32_t le = 0;
|
uint32_t le = 0;
|
||||||
for (int t = 1; t <= tag_len; t++)
|
for (int t = 1; t <= tag_len; t++)
|
||||||
@@ -205,7 +205,7 @@ int sm_verify() {
|
|||||||
memset(input, 0, sizeof(input));
|
memset(input, 0, sizeof(input));
|
||||||
int input_len = 0, r = 0;
|
int input_len = 0, r = 0;
|
||||||
bool add_header = (CLA(apdu) & 0xC) == 0xC;
|
bool add_header = (CLA(apdu) & 0xC) == 0xC;
|
||||||
int data_len = (int)(apdu.cmd_apdu_data_len/sm_blocksize)*sm_blocksize;
|
int data_len = (int)(apdu.nc/sm_blocksize)*sm_blocksize;
|
||||||
if (data_len % sm_blocksize)
|
if (data_len % sm_blocksize)
|
||||||
data_len += sm_blocksize;
|
data_len += sm_blocksize;
|
||||||
if (data_len+(add_header ? sm_blocksize : 0) > 1024)
|
if (data_len+(add_header ? sm_blocksize : 0) > 1024)
|
||||||
@@ -232,7 +232,7 @@ int sm_verify() {
|
|||||||
size_t mac_len = 0;
|
size_t mac_len = 0;
|
||||||
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL;
|
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL;
|
||||||
size_t tag_len = 0;
|
size_t tag_len = 0;
|
||||||
while (walk_tlv(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, &p, &tag, &tag_len, &tag_data)) {
|
while (walk_tlv(apdu.data, apdu.nc, &p, &tag, &tag_len, &tag_data)) {
|
||||||
if (tag & 0x1) {
|
if (tag & 0x1) {
|
||||||
input[input_len++] = tag;
|
input[input_len++] = tag;
|
||||||
int tlen = format_tlv_len(tag_len, input+input_len);
|
int tlen = format_tlv_len(tag_len, input+input_len);
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ file_t *get_parent(file_t *f) {
|
|||||||
|
|
||||||
file_t *search_by_name(uint8_t *name, uint16_t namelen) {
|
file_t *search_by_name(uint8_t *name, uint16_t namelen) {
|
||||||
for (file_t *p = file_entries; p != file_last; p++) {
|
for (file_t *p = file_entries; p != file_last; p++) {
|
||||||
if (p->name && *p->name == apdu.cmd_apdu_data_len && memcmp(p->name+1, name, namelen) == 0) {
|
if (p->name && *p->name == apdu.nc && memcmp(p->name+1, name, namelen) == 0) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ static inline uint32_t usb_buffer_offset(volatile uint8_t *buf) {
|
|||||||
* @param ep
|
* @param ep
|
||||||
*/
|
*/
|
||||||
void usb_setup_endpoint(const struct usb_endpoint_configuration *ep) {
|
void usb_setup_endpoint(const struct usb_endpoint_configuration *ep) {
|
||||||
printf("Set up endpoint 0x%x with buffer address 0x%p\n", ep->descriptor->bEndpointAddress, ep->data_buffer);
|
//printf("Set up endpoint 0x%x with buffer address 0x%p\n", ep->descriptor->bEndpointAddress, ep->data_buffer);
|
||||||
|
|
||||||
// EP0 doesn't have one so return if that is the case
|
// EP0 doesn't have one so return if that is the case
|
||||||
if (!ep->endpoint_control) {
|
if (!ep->endpoint_control) {
|
||||||
@@ -243,7 +243,7 @@ void usb_start_transfer(struct usb_endpoint_configuration *ep, uint8_t *buf, uin
|
|||||||
// For multi packet transfers see the tinyusb port.
|
// For multi packet transfers see the tinyusb port.
|
||||||
assert(len <= 64);
|
assert(len <= 64);
|
||||||
|
|
||||||
printf("Start transfer of len %d on ep addr 0x%x\n", len, ep->descriptor->bEndpointAddress);
|
//printf("Start transfer of len %d on ep addr 0x%x\n", len, ep->descriptor->bEndpointAddress);
|
||||||
|
|
||||||
// Prepare buffer control register value
|
// Prepare buffer control register value
|
||||||
uint32_t val = len | USB_BUF_CTRL_AVAIL;
|
uint32_t val = len | USB_BUF_CTRL_AVAIL;
|
||||||
@@ -331,12 +331,6 @@ bool usb_is_configured(void) {
|
|||||||
return configured;
|
return configured;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t usb_write(uint8_t *buffer, size_t buffer_size) {
|
|
||||||
struct usb_endpoint_configuration *ep = usb_get_endpoint_configuration(EP2_IN_ADDR);
|
|
||||||
usb_start_transfer(ep, buffer, MIN(buffer_size, 64));
|
|
||||||
return MIN(buffer_size, 64);
|
|
||||||
}
|
|
||||||
|
|
||||||
void usb_init() {
|
void usb_init() {
|
||||||
usb_device_init();
|
usb_device_init();
|
||||||
|
|
||||||
@@ -491,7 +485,7 @@ static void usb_handle_ep_buff_done(struct usb_endpoint_configuration *ep) {
|
|||||||
*/
|
*/
|
||||||
static void usb_handle_buff_done(uint ep_num, bool in) {
|
static void usb_handle_buff_done(uint ep_num, bool in) {
|
||||||
uint8_t ep_addr = ep_num | (in ? USB_DIR_IN : 0);
|
uint8_t ep_addr = ep_num | (in ? USB_DIR_IN : 0);
|
||||||
printf("EP %d (in = %d) done\n", ep_num, in);
|
//printf("EP %d (in = %d) done\n", ep_num, in);
|
||||||
for (uint i = 0; i < USB_NUM_ENDPOINTS; i++) {
|
for (uint i = 0; i < USB_NUM_ENDPOINTS; i++) {
|
||||||
struct usb_endpoint_configuration *ep = &dev_config.endpoints[i];
|
struct usb_endpoint_configuration *ep = &dev_config.endpoints[i];
|
||||||
if (ep->descriptor && ep->handler) {
|
if (ep->descriptor && ep->handler) {
|
||||||
@@ -551,7 +545,7 @@ void isr_usbctrl(void) {
|
|||||||
|
|
||||||
// Bus is reset
|
// Bus is reset
|
||||||
if (status & USB_INTS_BUS_RESET_BITS) {
|
if (status & USB_INTS_BUS_RESET_BITS) {
|
||||||
printf("BUS RESET\n");
|
//printf("BUS RESET\n");
|
||||||
handled |= USB_INTS_BUS_RESET_BITS;
|
handled |= USB_INTS_BUS_RESET_BITS;
|
||||||
usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS;
|
usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS;
|
||||||
usb_bus_reset();
|
usb_bus_reset();
|
||||||
@@ -585,37 +579,72 @@ void ep0_out_handler(uint8_t *buf, uint16_t len) {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DEBUG_PAYLOAD(p,s) { \
|
||||||
|
printf("Payload %s (%d bytes):\r\n", #p,s);\
|
||||||
|
for (int i = 0; i < s; i += 16) {\
|
||||||
|
printf("%07Xh : ",i+p);\
|
||||||
|
for (int j = 0; j < 16; j++) {\
|
||||||
|
if (j < s-i) printf("%02X ",(p)[i+j]);\
|
||||||
|
else printf(" ");\
|
||||||
|
if (j == 7) printf(" ");\
|
||||||
|
} printf(": "); \
|
||||||
|
for (int j = 0; j < MIN(16,s-i); j++) {\
|
||||||
|
printf("%c",(p)[i+j] == 0x0a || (p)[i+j] == 0x0d ? '\\' : (p)[i+j]);\
|
||||||
|
if (j == 7) printf(" ");\
|
||||||
|
}\
|
||||||
|
printf("\r\n");\
|
||||||
|
} printf("\r\n"); \
|
||||||
|
}
|
||||||
|
|
||||||
// Device specific functions
|
// Device specific functions
|
||||||
static uint8_t rx_buffer[4096];
|
static uint8_t rx_buffer[4096], tx_buffer[4096];
|
||||||
static uint16_t w_offset = 0, r_offset = 0;
|
static uint16_t w_offset = 0, r_offset = 0;
|
||||||
|
|
||||||
void ep1_out_handler(uint8_t *buf, uint16_t len) {
|
void ep1_out_handler(uint8_t *buf, uint16_t len) {
|
||||||
printf("RX %d bytes from host\n", len);
|
printf("RX %d bytes from host\n", len);
|
||||||
|
DEBUG_PAYLOAD(buf,len);
|
||||||
// Send data back to host
|
// Send data back to host
|
||||||
uint16_t size = MIN(sizeof(rx_buffer)-w_offset,len);
|
uint16_t size = MIN(sizeof(rx_buffer)-w_offset,len);
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
memcpy(rx_buffer+w_offset, buf, size);
|
memcpy(rx_buffer+w_offset, buf, size);
|
||||||
w_offset += size;
|
w_offset += size;
|
||||||
}
|
}
|
||||||
/*
|
//printf("rx_w_offset %d, rx_r_offset %d\r\n",w_offset, r_offset);
|
||||||
do {
|
|
||||||
uint16_t size = MIN(sizeof(rx_buffer)-w_offset,len);
|
|
||||||
memcpy(rx_buffer+w_offset, buf, size);
|
|
||||||
len -= size;
|
|
||||||
w_offset += size;
|
|
||||||
if (w_offset == sizeof(rx_buffer))
|
|
||||||
w_offset = 0;
|
|
||||||
buf += size;
|
|
||||||
} while (len > 0);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t usb_write(uint16_t size) {
|
||||||
|
return usb_write_offset(size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t usb_write_offset(uint16_t size, uint16_t roffset) {
|
||||||
|
if (size > sizeof(tx_buffer))
|
||||||
|
size = sizeof(tx_buffer);
|
||||||
|
struct usb_endpoint_configuration *ep = usb_get_endpoint_configuration(EP2_IN_ADDR);
|
||||||
|
for (uint16_t offset = roffset; offset-roffset < size; offset += 64) {
|
||||||
|
usb_start_transfer(ep, tx_buffer+offset, MIN(size-offset, 64));
|
||||||
|
}
|
||||||
|
usb_start_transfer(usb_get_endpoint_configuration(EP1_OUT_ADDR), NULL, 64);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
uint16_t usb_read_available() {
|
uint16_t usb_read_available() {
|
||||||
return w_offset - r_offset;
|
return w_offset - r_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t *usb_get_rx() {
|
||||||
|
return rx_buffer;
|
||||||
|
}
|
||||||
|
uint8_t *usb_get_tx() {
|
||||||
|
return tx_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_clear_rx() {
|
||||||
|
w_offset = r_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t usb_read(uint8_t *buffer, size_t buffer_size) {
|
uint16_t usb_read(uint8_t *buffer, size_t buffer_size) {
|
||||||
if (w_offset-r_offset > 0) {
|
|
||||||
uint16_t size = MIN(buffer_size, w_offset-r_offset);
|
uint16_t size = MIN(buffer_size, w_offset-r_offset);
|
||||||
|
if (size > 0) {
|
||||||
memcpy(buffer, rx_buffer+r_offset, size);
|
memcpy(buffer, rx_buffer+r_offset, size);
|
||||||
r_offset += size;
|
r_offset += size;
|
||||||
if (r_offset == w_offset) {
|
if (r_offset == w_offset) {
|
||||||
@@ -627,9 +656,9 @@ uint16_t usb_read(uint8_t *buffer, size_t buffer_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ep2_in_handler(uint8_t *buf, uint16_t len) {
|
void ep2_in_handler(uint8_t *buf, uint16_t len) {
|
||||||
printf("Sent %d bytes to host\n", len);
|
//printf("Sent %d bytes to host\n", len);
|
||||||
// Get ready to rx again from host
|
// Get ready to rx again from host
|
||||||
usb_start_transfer(usb_get_endpoint_configuration(EP1_OUT_ADDR), NULL, 64);
|
//usb_start_transfer(usb_get_endpoint_configuration(EP1_OUT_ADDR), NULL, 64);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|||||||
@@ -317,9 +317,14 @@ static const unsigned char *descriptor_strings[] = {
|
|||||||
|
|
||||||
extern uint16_t usb_read(uint8_t *buffer, size_t buffer_size);
|
extern uint16_t usb_read(uint8_t *buffer, size_t buffer_size);
|
||||||
extern uint16_t usb_read_available();
|
extern uint16_t usb_read_available();
|
||||||
extern uint32_t usb_write(uint8_t *buffer, size_t buffer_size);
|
extern uint32_t usb_write_offset(uint16_t size, uint16_t offset);
|
||||||
|
extern uint32_t usb_write(uint16_t size);
|
||||||
extern bool usb_is_configured();
|
extern bool usb_is_configured();
|
||||||
extern void usb_init();
|
extern void usb_init();
|
||||||
|
extern uint8_t *usb_get_rx();
|
||||||
|
extern uint32_t usb_send_tx_buffer();
|
||||||
|
extern uint8_t *usb_get_tx();
|
||||||
|
extern void usb_clear_rx();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user