mirror of
https://github.com/polhenarejos/pico-keys-sdk
synced 2026-05-31 18:41:22 +02:00
Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
657913d29a | ||
|
|
18fa1d7f37 | ||
|
|
f123108c3e | ||
|
|
f8590ba8c7 | ||
|
|
4d7101b802 | ||
|
|
7fded7234b | ||
|
|
988d4e23c2 | ||
|
|
c23f17107a | ||
|
|
91e2b7f643 | ||
|
|
3092da23ed | ||
|
|
e29521fcf6 | ||
|
|
d2e54b04db | ||
|
|
4ab68cc822 | ||
|
|
e1914556ec | ||
|
|
287be74921 | ||
|
|
5a4aff7008 | ||
|
|
8b97791d8f | ||
|
|
847005d94f | ||
|
|
68f43f3cb2 | ||
|
|
4c49e59edc | ||
|
|
633593aae3 | ||
|
|
42f3c67c61 | ||
|
|
493a88538a | ||
|
|
607f7c50d4 | ||
|
|
2cb59d57d2 | ||
|
|
a8e1fe5842 | ||
|
|
d1530733a2 | ||
|
|
4538d6ef14 | ||
|
|
4a1bddb3d5 | ||
|
|
c6a129b6ad | ||
|
|
abd52c34ba | ||
|
|
7aeac46eef | ||
|
|
867d4637ee | ||
|
|
7491021102 | ||
|
|
9b137f6f08 | ||
|
|
3f492b9272 | ||
|
|
799733203b | ||
|
|
0be497e713 | ||
|
|
e23dead31d | ||
|
|
4d9faccedb | ||
|
|
f47df94dfb | ||
|
|
c0123aa669 | ||
|
|
43dfb0cde5 | ||
|
|
f14e029094 | ||
|
|
f14cc8dba5 | ||
|
|
16a1981dc3 | ||
|
|
9ccd10fcea | ||
|
|
a6506e6c95 | ||
|
|
3e73d6569b | ||
|
|
214ec2b9ae |
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
|||||||
[submodule "mbedtls"]
|
[submodule "mbedtls"]
|
||||||
path = mbedtls
|
path = mbedtls
|
||||||
url = https://github.com/ARMmbed/mbedtls
|
url = https://github.com/ARMmbed/mbedtls
|
||||||
|
[submodule "tinycbor"]
|
||||||
|
path = tinycbor
|
||||||
|
url = https://github.com/intel/tinycbor.git
|
||||||
|
|||||||
@@ -1004,7 +1004,7 @@
|
|||||||
*
|
*
|
||||||
* Enable functions that use the filesystem.
|
* Enable functions that use the filesystem.
|
||||||
*/
|
*/
|
||||||
#define MBEDTLS_FS_IO
|
//#define MBEDTLS_FS_IO
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
|
* \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
|
||||||
@@ -2112,7 +2112,7 @@
|
|||||||
*
|
*
|
||||||
* Module: library/chacha20.c
|
* Module: library/chacha20.c
|
||||||
*/
|
*/
|
||||||
//#define MBEDTLS_CHACHA20_C
|
#define MBEDTLS_CHACHA20_C
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \def MBEDTLS_CHACHAPOLY_C
|
* \def MBEDTLS_CHACHAPOLY_C
|
||||||
@@ -2123,7 +2123,7 @@
|
|||||||
*
|
*
|
||||||
* This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C
|
* This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C
|
||||||
*/
|
*/
|
||||||
//#define MBEDTLS_CHACHAPOLY_C
|
#define MBEDTLS_CHACHAPOLY_C
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \def MBEDTLS_CIPHER_C
|
* \def MBEDTLS_CIPHER_C
|
||||||
@@ -2657,7 +2657,7 @@
|
|||||||
* either MBEDTLS_PSA_ITS_FILE_C or a native implementation of
|
* either MBEDTLS_PSA_ITS_FILE_C or a native implementation of
|
||||||
* the PSA ITS interface
|
* the PSA ITS interface
|
||||||
*/
|
*/
|
||||||
#define MBEDTLS_PSA_CRYPTO_STORAGE_C
|
//#define MBEDTLS_PSA_CRYPTO_STORAGE_C
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \def MBEDTLS_PSA_ITS_FILE_C
|
* \def MBEDTLS_PSA_ITS_FILE_C
|
||||||
@@ -2669,7 +2669,7 @@
|
|||||||
*
|
*
|
||||||
* Requires: MBEDTLS_FS_IO
|
* Requires: MBEDTLS_FS_IO
|
||||||
*/
|
*/
|
||||||
#define MBEDTLS_PSA_ITS_FILE_C
|
//#define MBEDTLS_PSA_ITS_FILE_C
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \def MBEDTLS_RIPEMD160_C
|
* \def MBEDTLS_RIPEMD160_C
|
||||||
|
|||||||
@@ -91,9 +91,22 @@ if (NOT TARGET pico_hsm_sdk)
|
|||||||
target_sources(pico_hsm_sdk INTERFACE
|
target_sources(pico_hsm_sdk INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/usb/hid/hid.c
|
${CMAKE_CURRENT_LIST_DIR}/src/usb/hid/hid.c
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/usb/hid/usb_descriptors.c
|
${CMAKE_CURRENT_LIST_DIR}/src/usb/hid/usb_descriptors.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/tinycbor/src/cborencoder.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/tinycbor/src/cborparser.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/tinycbor/src/cborparser_dup_string.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/x509write_crt.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/x509_create.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/pk.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/pk_wrap.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/pkwrite.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/pkwrite.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/chachapoly.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/chacha20.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/poly1305.c
|
||||||
)
|
)
|
||||||
target_include_directories(pico_hsm_sdk INTERFACE
|
target_include_directories(pico_hsm_sdk INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/usb/hid
|
${CMAKE_CURRENT_LIST_DIR}/src/usb/hid
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/tinycbor/src
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
35
src/apdu.c
35
src/apdu.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
|
* This file is part of the Pico HSM SDK distribution (https://github.com/polhenarejos/pico-hsm-sdk).
|
||||||
* Copyright (c) 2022 Pol Henarejos.
|
* Copyright (c) 2022 Pol Henarejos.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@@ -125,6 +125,39 @@ uint16_t set_res_sw(uint8_t sw1, uint8_t sw2) {
|
|||||||
return make_uint16_t(sw1, sw2);
|
return make_uint16_t(sw1, sw2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void apdu_thread() {
|
||||||
|
|
||||||
|
card_init_core1();
|
||||||
|
while (1) {
|
||||||
|
uint32_t m;
|
||||||
|
queue_remove_blocking(&usb_to_card_q, &m);
|
||||||
|
|
||||||
|
if (m == EV_VERIFY_CMD_AVAILABLE || m == EV_MODIFY_CMD_AVAILABLE)
|
||||||
|
{
|
||||||
|
set_res_sw (0x6f, 0x00);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else if (m == EV_EXIT) {
|
||||||
|
if (current_app && current_app->unload) {
|
||||||
|
current_app->unload();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
process_apdu();
|
||||||
|
|
||||||
|
done:;
|
||||||
|
|
||||||
|
apdu_finish();
|
||||||
|
finished_data_size = apdu_next();
|
||||||
|
uint32_t flag = EV_EXEC_FINISHED;
|
||||||
|
queue_add_blocking(&card_to_usb_q, &flag);
|
||||||
|
}
|
||||||
|
//printf("EXIT !!!!!!\r\n");
|
||||||
|
if (current_app && current_app->unload)
|
||||||
|
current_app->unload();
|
||||||
|
}
|
||||||
|
|
||||||
void apdu_finish() {
|
void apdu_finish() {
|
||||||
apdu.rdata[apdu.rlen] = apdu.sw >> 8;
|
apdu.rdata[apdu.rlen] = apdu.sw >> 8;
|
||||||
apdu.rdata[apdu.rlen+1] = apdu.sw & 0xff;
|
apdu.rdata[apdu.rlen+1] = apdu.sw & 0xff;
|
||||||
|
|||||||
15
src/apdu.h
15
src/apdu.h
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
|
* This file is part of the Pico HSM SDK distribution (https://github.com/polhenarejos/pico-hsm-sdk).
|
||||||
* Copyright (c) 2022 Pol Henarejos.
|
* Copyright (c) 2022 Pol Henarejos.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef struct app {
|
typedef struct app {
|
||||||
const uint8_t *aid;
|
const uint8_t *aid;
|
||||||
@@ -47,8 +48,19 @@ extern int register_app(app_t * (*)());
|
|||||||
printf("\r\n");\
|
printf("\r\n");\
|
||||||
} printf("\r\n"); \
|
} printf("\r\n"); \
|
||||||
}
|
}
|
||||||
|
#define DEBUG_DATA(_p, _s) \
|
||||||
|
{ \
|
||||||
|
printf("Data %s (%d bytes):\r\n", #_p, _s); \
|
||||||
|
for (int _i = 0; _i < _s; _i++) \
|
||||||
|
{ \
|
||||||
|
printf("%02X", (_p)[_i]); \
|
||||||
|
} \
|
||||||
|
printf("\n"); \
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define DEBUG_PAYLOAD(_p,_s)
|
#define DEBUG_PAYLOAD(_p,_s)
|
||||||
|
#define DEBUG_DATA(_p,_s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern uint8_t num_apps;
|
extern uint8_t num_apps;
|
||||||
@@ -80,5 +92,6 @@ extern int process_apdu();
|
|||||||
extern size_t apdu_process(const uint8_t *buffer, size_t buffer_size);
|
extern size_t apdu_process(const uint8_t *buffer, size_t buffer_size);
|
||||||
extern void apdu_finish();
|
extern void apdu_finish();
|
||||||
extern size_t apdu_next();
|
extern size_t apdu_next();
|
||||||
|
extern void apdu_thread();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -235,10 +235,10 @@ void scan_region(bool persistent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void wait_flash_finish();
|
||||||
void scan_flash() {
|
void scan_flash() {
|
||||||
initialize_flash(false); //soft initialization
|
initialize_flash(false); //soft initialization
|
||||||
if (*(uintptr_t *)end_data_pool == 0xffffffff && *(uintptr_t *)(end_data_pool+sizeof(uintptr_t)) == 0xffffffff)
|
if (*(uintptr_t *)flash_read(end_rom_pool) == 0xffffffff && *(uintptr_t *)flash_read(end_rom_pool+sizeof(uintptr_t)) == 0xffffffff)
|
||||||
{
|
{
|
||||||
printf("First initialization (or corrupted!)\r\n");
|
printf("First initialization (or corrupted!)\r\n");
|
||||||
uint8_t empty[sizeof(uintptr_t)*2+sizeof(uint32_t)];
|
uint8_t empty[sizeof(uintptr_t)*2+sizeof(uint32_t)];
|
||||||
@@ -427,3 +427,6 @@ int meta_add(uint16_t fid, const uint8_t *data, uint16_t len) {
|
|||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool file_has_data(file_t *f) {
|
||||||
|
return (f != NULL && f->data != NULL && file_get_size(f) > 0);
|
||||||
|
}
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ typedef struct file
|
|||||||
const uint8_t acl[7];
|
const uint8_t acl[7];
|
||||||
} __attribute__((packed)) file_t;
|
} __attribute__((packed)) file_t;
|
||||||
|
|
||||||
|
extern bool file_has_data(file_t *);
|
||||||
|
|
||||||
extern file_t *currentEF;
|
extern file_t *currentEF;
|
||||||
extern file_t *currentDF;
|
extern file_t *currentDF;
|
||||||
extern const file_t *selected_applet;
|
extern const file_t *selected_applet;
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ enum {
|
|||||||
};
|
};
|
||||||
extern void led_set_blink(uint32_t mode);
|
extern void led_set_blink(uint32_t mode);
|
||||||
|
|
||||||
|
extern bool is_req_button_pending();
|
||||||
|
extern uint32_t button_timeout;
|
||||||
|
|
||||||
#define SW_BYTES_REMAINING_00() set_res_sw (0x61, 0x00)
|
#define SW_BYTES_REMAINING_00() set_res_sw (0x61, 0x00)
|
||||||
#define SW_WARNING_STATE_UNCHANGED() set_res_sw (0x62, 0x00)
|
#define SW_WARNING_STATE_UNCHANGED() set_res_sw (0x62, 0x00)
|
||||||
#define SW_WARNING_CORRUPTED() set_res_sw (0x62, 0x81)
|
#define SW_WARNING_CORRUPTED() set_res_sw (0x62, 0x81)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef __VERSION_H_
|
#ifndef __VERSION_H_
|
||||||
#define __VERSION_H_
|
#define __VERSION_H_
|
||||||
|
|
||||||
#define HSM_SDK_VERSION 0x0300
|
#define HSM_SDK_VERSION 0x0304
|
||||||
|
|
||||||
#define HSM_SDK_VERSION_MAJOR ((HSM_SDK_VERSION >> 8) & 0xff)
|
#define HSM_SDK_VERSION_MAJOR ((HSM_SDK_VERSION >> 8) & 0xff)
|
||||||
#define HSM_SDK_VERSION_MINOR (HSM_SDK_VERSION & 0xff)
|
#define HSM_SDK_VERSION_MINOR (HSM_SDK_VERSION & 0xff)
|
||||||
|
|||||||
21
src/main.c
21
src/main.c
@@ -67,21 +67,31 @@ void led_set_blink(uint32_t mode) {
|
|||||||
|
|
||||||
void execute_tasks();
|
void execute_tasks();
|
||||||
|
|
||||||
|
static bool req_button_pending = false;
|
||||||
|
|
||||||
|
bool is_req_button_pending() {
|
||||||
|
return req_button_pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t button_timeout = 15000;
|
||||||
|
bool cancel_button = false;
|
||||||
|
|
||||||
bool wait_button() {
|
bool wait_button() {
|
||||||
uint32_t start_button = board_millis();
|
uint32_t start_button = board_millis();
|
||||||
bool timeout = false;
|
bool timeout = false;
|
||||||
|
cancel_button = false;
|
||||||
led_set_blink((1000 << 16) | 100);
|
led_set_blink((1000 << 16) | 100);
|
||||||
|
req_button_pending = true;
|
||||||
while (board_button_read() == false) {
|
while (board_button_read() == false && cancel_button == false) {
|
||||||
execute_tasks();
|
execute_tasks();
|
||||||
//sleep_ms(10);
|
//sleep_ms(10);
|
||||||
if (start_button + 15000 < board_millis()) { /* timeout */
|
if (start_button + button_timeout < board_millis()) { /* timeout */
|
||||||
timeout = true;
|
timeout = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!timeout) {
|
if (!timeout) {
|
||||||
while (board_button_read() == true) {
|
while (board_button_read() == true && cancel_button == false) {
|
||||||
execute_tasks();
|
execute_tasks();
|
||||||
//sleep_ms(10);
|
//sleep_ms(10);
|
||||||
if (start_button + 15000 < board_millis()) { /* timeout */
|
if (start_button + 15000 < board_millis()) { /* timeout */
|
||||||
@@ -91,7 +101,8 @@ bool wait_button() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
led_set_blink(BLINK_PROCESSING);
|
led_set_blink(BLINK_PROCESSING);
|
||||||
return timeout;
|
req_button_pending = false;
|
||||||
|
return timeout || cancel_button;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct apdu apdu;
|
struct apdu apdu;
|
||||||
|
|||||||
@@ -176,6 +176,17 @@ void neug_wait_full(void) { //should be called only on core1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void neug_wait_full_ext(bool blocking) {
|
||||||
|
struct rng_rb *rb = &the_ring_buffer;
|
||||||
|
|
||||||
|
while (!rb->full) {
|
||||||
|
if (blocking == true)
|
||||||
|
sleep_ms(1);
|
||||||
|
else
|
||||||
|
neug_task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void neug_fini(void) {
|
void neug_fini(void) {
|
||||||
neug_get();
|
neug_get();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,14 @@
|
|||||||
|
|
||||||
#define NEUG_PRE_LOOP 32
|
#define NEUG_PRE_LOOP 32
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
void neug_init(uint32_t *buf, uint8_t size);
|
void neug_init(uint32_t *buf, uint8_t size);
|
||||||
uint32_t neug_get();
|
uint32_t neug_get();
|
||||||
void neug_flush(void);
|
void neug_flush(void);
|
||||||
void neug_wait_full(void);
|
void neug_wait_full(void);
|
||||||
|
void neug_wait_full_ext(bool);
|
||||||
void neug_fini(void);
|
void neug_fini(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -79,13 +79,13 @@ void random_get_salt(uint8_t *p) {
|
|||||||
/*
|
/*
|
||||||
* Random byte iterator
|
* Random byte iterator
|
||||||
*/
|
*/
|
||||||
int random_gen(void *arg, unsigned char *out, size_t out_len) {
|
int random_gen_ext(void *arg, unsigned char *out, size_t out_len, bool blocking) {
|
||||||
uint8_t *index_p = (uint8_t *)arg;
|
uint8_t *index_p = (uint8_t *)arg;
|
||||||
uint8_t index = index_p ? *index_p : 0;
|
uint8_t index = index_p ? *index_p : 0;
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
while (out_len) {
|
while (out_len) {
|
||||||
neug_wait_full();
|
neug_wait_full_ext(blocking);
|
||||||
|
|
||||||
n = RANDOM_BYTES_LENGTH - index;
|
n = RANDOM_BYTES_LENGTH - index;
|
||||||
if (n > out_len)
|
if (n > out_len)
|
||||||
@@ -107,3 +107,11 @@ int random_gen(void *arg, unsigned char *out, size_t out_len) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int random_gen(void *arg, unsigned char *out, size_t out_len) {
|
||||||
|
return random_gen_ext(arg, out, out_len, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int random_gen_core0(void *arg, unsigned char *out, size_t out_len) {
|
||||||
|
return random_gen_ext(arg, out, out_len, false);
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,5 +34,6 @@ void random_get_salt (uint8_t *p);
|
|||||||
|
|
||||||
/* iterator returning a byta at a time */
|
/* iterator returning a byta at a time */
|
||||||
extern int random_gen (void *arg, unsigned char *output, size_t output_len);
|
extern int random_gen (void *arg, unsigned char *output, size_t output_len);
|
||||||
|
extern int random_gen_core0(void *arg, unsigned char *out, size_t out_len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -124,6 +124,8 @@ int driver_init() {
|
|||||||
ccid_response = (struct ccid_header *)usb_get_tx();
|
ccid_response = (struct ccid_header *)usb_get_tx();
|
||||||
apdu.rdata = &ccid_response->apdu;
|
apdu.rdata = &ccid_response->apdu;
|
||||||
|
|
||||||
|
usb_set_timeout_counter(1500);
|
||||||
|
|
||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +176,7 @@ int driver_process_usb_packet(uint16_t rx_read) {
|
|||||||
ccid_response->abRFU1 = 0;
|
ccid_response->abRFU1 = 0;
|
||||||
//printf("1 %x %x %x || %x %x %x\r\n",ccid_response->apdu,apdu.rdata,ccid_response,ccid_header,ccid_header->apdu,apdu.data);
|
//printf("1 %x %x %x || %x %x %x\r\n",ccid_response->apdu,apdu.rdata,ccid_response,ccid_header,ccid_header->apdu,apdu.data);
|
||||||
memcpy(apdu.rdata, ccid_atr+1, size_atr);
|
memcpy(apdu.rdata, ccid_atr+1, size_atr);
|
||||||
card_start();
|
card_start(apdu_thread);
|
||||||
ccid_status = 0;
|
ccid_status = 0;
|
||||||
ccid_write(size_atr);
|
ccid_write(size_atr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ char const* string_desc_arr [] =
|
|||||||
{
|
{
|
||||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||||
"Pol Henarejos", // 1: Manufacturer
|
"Pol Henarejos", // 1: Manufacturer
|
||||||
"Pico HSM", // 2: Product
|
"Pico HSM CCID", // 2: Product
|
||||||
"11223344", // 3: Serials, should use chip ID
|
"11223344", // 3: Serials, should use chip ID
|
||||||
"Pico HSM Config", // 4: Vendor Interface
|
"Pico HSM Config", // 4: Vendor Interface
|
||||||
"Pico HSM Interface"
|
"Pico HSM Interface"
|
||||||
|
|||||||
159
src/usb/hid/ctap_hid.h
Normal file
159
src/usb/hid/ctap_hid.h
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Pico HSM SDK distribution (https://github.com/polhenarejos/pico-hsm-sdk).
|
||||||
|
* Copyright (c) 2022 Pol Henarejos.
|
||||||
|
*
|
||||||
|
* This program 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, version 3.
|
||||||
|
*
|
||||||
|
* This program 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CTAP_HID_H_
|
||||||
|
#define _CTAP_HID_H_
|
||||||
|
|
||||||
|
#ifdef _MSC_VER // Windows
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef unsigned long int uint64_t;
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Size of HID reports
|
||||||
|
|
||||||
|
#define HID_RPT_SIZE 64 // Default size of raw HID report
|
||||||
|
|
||||||
|
// Frame layout - command- and continuation frames
|
||||||
|
|
||||||
|
#define CID_BROADCAST 0xffffffff // Broadcast channel id
|
||||||
|
|
||||||
|
#define TYPE_MASK 0x80 // Frame type mask
|
||||||
|
#define TYPE_INIT 0x80 // Initial frame identifier
|
||||||
|
#define TYPE_CONT 0x00 // Continuation frame identifier
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t cid; // Channel identifier
|
||||||
|
union {
|
||||||
|
uint8_t type; // Frame type - b7 defines type
|
||||||
|
struct {
|
||||||
|
uint8_t cmd; // Command - b7 set
|
||||||
|
uint8_t bcnth; // Message byte count - high part
|
||||||
|
uint8_t bcntl; // Message byte count - low part
|
||||||
|
uint8_t data[HID_RPT_SIZE - 7]; // Data payload
|
||||||
|
} init;
|
||||||
|
struct {
|
||||||
|
uint8_t seq; // Sequence number - b7 cleared
|
||||||
|
uint8_t data[HID_RPT_SIZE - 5]; // Data payload
|
||||||
|
} cont;
|
||||||
|
};
|
||||||
|
}__packed CTAPHID_FRAME;
|
||||||
|
|
||||||
|
#define FRAME_TYPE(f) ((f)->type & TYPE_MASK)
|
||||||
|
#define FRAME_CMD(f) ((f)->init.cmd & ~TYPE_MASK)
|
||||||
|
#define MSG_LEN(f) ((f)->init.bcnth*256 + (f)->init.bcntl)
|
||||||
|
#define FRAME_SEQ(f) ((f)->cont.seq & ~TYPE_MASK)
|
||||||
|
|
||||||
|
// HID usage- and usage-page definitions
|
||||||
|
|
||||||
|
#define FIDO_USAGE_PAGE 0xf1d0 // FIDO alliance HID usage page
|
||||||
|
#define FIDO_USAGE_CTAPHID 0x01 // CTAPHID usage for top-level collection
|
||||||
|
#define FIDO_USAGE_DATA_IN 0x20 // Raw IN data report
|
||||||
|
#define FIDO_USAGE_DATA_OUT 0x21 // Raw OUT data report
|
||||||
|
|
||||||
|
// General constants
|
||||||
|
|
||||||
|
#define CTAPHID_IF_VERSION 2 // Current interface implementation version
|
||||||
|
#define CTAPHID_TRANS_TIMEOUT 3000 // Default message timeout in ms
|
||||||
|
|
||||||
|
// CTAPHID native commands
|
||||||
|
|
||||||
|
#define CTAPHID_PING (TYPE_INIT | 0x01) // Echo data through local processor only
|
||||||
|
#define CTAPHID_MSG (TYPE_INIT | 0x03) // Send CTAP message frame
|
||||||
|
#define CTAPHID_LOCK (TYPE_INIT | 0x04) // Send lock channel command
|
||||||
|
#define CTAPHID_INIT (TYPE_INIT | 0x06) // Channel initialization
|
||||||
|
#define CTAPHID_WINK (TYPE_INIT | 0x08) // Send device identification wink
|
||||||
|
#define CTAPHID_CBOR (TYPE_INIT | 0x10) // CBOR
|
||||||
|
#define CTAPHID_CANCEL (TYPE_INIT | 0x11) // Cancel any request
|
||||||
|
#define CTAPHID_KEEPALIVE (TYPE_INIT | 0x3B) // Keepalive command
|
||||||
|
#define CTAPHID_SYNC (TYPE_INIT | 0x3C) // Protocol resync command
|
||||||
|
#define CTAPHID_ERROR (TYPE_INIT | 0x3F) // Error response
|
||||||
|
|
||||||
|
#define CTAPHID_VENDOR_FIRST (TYPE_INIT | 0x40) // First vendor defined command
|
||||||
|
#define CTAPHID_VENDOR_LAST (TYPE_INIT | 0x7F) // Last vendor defined command
|
||||||
|
|
||||||
|
// CTAP CBOR commands
|
||||||
|
|
||||||
|
#define CTAP_MAKE_CREDENTIAL 0x01
|
||||||
|
#define CTAP_GET_ASSERTION 0x02
|
||||||
|
#define CTAP_GET_INFO 0x04
|
||||||
|
#define CTAP_CLIENT_PIN 0x06
|
||||||
|
#define CTAP_RESET 0x07
|
||||||
|
#define CTAP_GET_NEXT_ASSERTION 0x08
|
||||||
|
|
||||||
|
// CTAP_KEEPALIVE command defines
|
||||||
|
|
||||||
|
#define KEEPALIVE_STATUS_PROCESSING 0x1
|
||||||
|
#define KEEPALIVE_STATUS_UPNEEDED 0x2
|
||||||
|
|
||||||
|
// CTAPHID_INIT command defines
|
||||||
|
|
||||||
|
#define INIT_NONCE_SIZE 8 // Size of channel initialization challenge
|
||||||
|
#define CAPFLAG_WINK 0x01 // Device supports WINK command
|
||||||
|
#define CAPFLAG_CBOR 0x04 // Device supports CBOR command
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t nonce[INIT_NONCE_SIZE]; // Client application nonce
|
||||||
|
}__packed CTAPHID_INIT_REQ;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t nonce[INIT_NONCE_SIZE]; // Client application nonce
|
||||||
|
uint32_t cid; // Channel identifier
|
||||||
|
uint8_t versionInterface; // Interface version
|
||||||
|
uint8_t versionMajor; // Major version number
|
||||||
|
uint8_t versionMinor; // Minor version number
|
||||||
|
uint8_t versionBuild; // Build version number
|
||||||
|
uint8_t capFlags; // Capabilities flags
|
||||||
|
}__packed CTAPHID_INIT_RESP;
|
||||||
|
|
||||||
|
// CTAPHID_SYNC command defines
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t nonce; // Client application nonce
|
||||||
|
} CTAPHID_SYNC_REQ;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t nonce; // Client application nonce
|
||||||
|
} CTAPHID_SYNC_RESP;
|
||||||
|
|
||||||
|
// Low-level error codes. Return as negatives.
|
||||||
|
|
||||||
|
#define CTAP_MAX_PACKET_SIZE (64 - 7 + 128 * (64 - 5))
|
||||||
|
|
||||||
|
#define CTAP1_ERR_NONE 0x00 // No error
|
||||||
|
#define CTAP1_ERR_INVALID_CMD 0x01 // Invalid command
|
||||||
|
#define CTAP1_ERR_INVALID_PARAMETER 0x02 // Invalid parameter
|
||||||
|
#define CTAP1_ERR_INVALID_LEN 0x03 // Invalid message length
|
||||||
|
#define CTAP1_ERR_INVALID_SEQ 0x04 // Invalid message sequencing
|
||||||
|
#define CTAP1_ERR_MSG_TIMEOUT 0x05 // Message has timed out
|
||||||
|
#define CTAP1_ERR_CHANNEL_BUSY 0x06 // Channel busy
|
||||||
|
#define CTAP1_ERR_LOCK_REQUIRED 0x0a // Command requires channel lock
|
||||||
|
#define CTAP1_ERR_INVALID_CHANNEL 0x0b // CID not valid
|
||||||
|
#define CTAP1_ERR_OTHER 0x7f // Other unspecified error
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _CTAP_HID_H_
|
||||||
@@ -16,13 +16,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#include "u2f_hid.h"
|
#include "ctap_hid.h"
|
||||||
#include "hsm.h"
|
#include "hsm.h"
|
||||||
#include "hsm_version.h"
|
#include "hsm_version.h"
|
||||||
#include "apdu.h"
|
#include "apdu.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
#include "bsp/board.h"
|
||||||
|
|
||||||
static bool mounted = false;
|
static bool mounted = false;
|
||||||
|
extern int cbor_process(const uint8_t *, size_t);
|
||||||
|
extern void init_fido(bool);
|
||||||
|
|
||||||
|
typedef struct msg_packet {
|
||||||
|
uint16_t len;
|
||||||
|
uint16_t current_len;
|
||||||
|
uint8_t data[CTAP_MAX_PACKET_SIZE];
|
||||||
|
} __packed msg_packet_t;
|
||||||
|
|
||||||
|
msg_packet_t msg_packet = { 0 };
|
||||||
|
|
||||||
void tud_mount_cb()
|
void tud_mount_cb()
|
||||||
{
|
{
|
||||||
@@ -33,15 +44,17 @@ bool driver_mounted() {
|
|||||||
return mounted;
|
return mounted;
|
||||||
}
|
}
|
||||||
|
|
||||||
U2FHID_FRAME *u2f_req, *u2f_resp;
|
CTAPHID_FRAME *ctap_req = NULL, *ctap_resp = NULL;
|
||||||
|
|
||||||
int driver_init() {
|
int driver_init() {
|
||||||
tud_init(BOARD_TUD_RHPORT);
|
tud_init(BOARD_TUD_RHPORT);
|
||||||
u2f_req = (U2FHID_FRAME *)usb_get_rx();
|
ctap_req = (CTAPHID_FRAME *)usb_get_rx();
|
||||||
apdu.header = u2f_req->init.data;
|
apdu.header = ctap_req->init.data;
|
||||||
|
|
||||||
u2f_resp = (U2FHID_FRAME *)usb_get_tx();
|
ctap_resp = (CTAPHID_FRAME *)usb_get_tx();
|
||||||
apdu.rdata = u2f_resp->init.data;
|
apdu.rdata = ctap_resp->init.data;
|
||||||
|
|
||||||
|
usb_set_timeout_counter(200);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -69,8 +82,32 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hid_write_offset(uint16_t size, uint16_t offset) {
|
||||||
|
if (*usb_get_tx() != 0x81)
|
||||||
|
DEBUG_PAYLOAD(usb_get_tx()+offset, size);
|
||||||
|
usb_write_offset(size, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hid_write(uint16_t size) {
|
||||||
|
hid_write_offset(size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t send_buffer_size = 0;
|
||||||
|
|
||||||
|
void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, /*uint16_t*/ uint8_t len) {
|
||||||
|
uint8_t seq = report[4] & TYPE_MASK ? 0 : report[4]+1;
|
||||||
|
if (send_buffer_size > 0) {
|
||||||
|
ctap_resp->cid = ctap_req->cid;
|
||||||
|
ctap_resp->cont.seq = seq;
|
||||||
|
hid_write_offset(64, (uint8_t *)ctap_resp - (usb_get_tx()));
|
||||||
|
send_buffer_size -= MIN(64 - 5, send_buffer_size);
|
||||||
|
ctap_resp = (CTAPHID_FRAME *)((uint8_t *)ctap_resp + 64 - 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int driver_write(const uint8_t *buffer, size_t buffer_size) {
|
int driver_write(const uint8_t *buffer, size_t buffer_size) {
|
||||||
return tud_hid_report(0, buffer, buffer_size);
|
int ret = tud_hid_report(0, buffer, buffer_size);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t driver_read(uint8_t *buffer, size_t buffer_size) {
|
size_t driver_read(uint8_t *buffer, size_t buffer_size) {
|
||||||
@@ -85,57 +122,239 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t rep
|
|||||||
(void) itf;
|
(void) itf;
|
||||||
(void) report_id;
|
(void) report_id;
|
||||||
(void) report_type;
|
(void) report_type;
|
||||||
printf("set report\n");
|
|
||||||
usb_rx(buffer, bufsize);
|
usb_rx(buffer, bufsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hid_write_offset(uint16_t size, uint16_t offset) {
|
uint32_t last_cmd_time = 0, last_packet_time = 0;
|
||||||
if (*usb_get_tx() != 0x81)
|
int ctap_error(uint8_t error) {
|
||||||
DEBUG_PAYLOAD(usb_get_tx()+offset,size+10);
|
ctap_resp = (CTAPHID_FRAME *)usb_get_tx();
|
||||||
usb_write_offset(size, offset);
|
memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
|
||||||
}
|
ctap_resp->cid = ctap_req->cid;
|
||||||
|
ctap_resp->init.cmd = CTAPHID_ERROR;
|
||||||
void hid_write(uint16_t size) {
|
ctap_resp->init.bcntl = 1;
|
||||||
hid_write_offset(size, 0);
|
ctap_resp->init.data[0] = error;
|
||||||
}
|
|
||||||
|
|
||||||
int driver_process_usb_packet(uint16_t read) {
|
|
||||||
if (read >= 10)
|
|
||||||
{
|
|
||||||
if (FRAME_TYPE(u2f_req) == TYPE_INIT) {
|
|
||||||
printf("command %x\n", FRAME_CMD(u2f_req));
|
|
||||||
printf("len %d\n", MSG_LEN(u2f_req));
|
|
||||||
DEBUG_PAYLOAD(u2f_req->init.data, MSG_LEN(u2f_req));
|
|
||||||
}
|
|
||||||
if (u2f_req->init.cmd == U2FHID_INIT) {
|
|
||||||
U2FHID_INIT_REQ *req = (U2FHID_INIT_REQ *)u2f_req->init.data;
|
|
||||||
U2FHID_INIT_RESP *resp = (U2FHID_INIT_RESP *)u2f_resp->init.data;
|
|
||||||
memcpy(resp->nonce, req->nonce, sizeof(resp->nonce));
|
|
||||||
resp->cid = 0x01000000;
|
|
||||||
resp->versionInterface = U2FHID_IF_VERSION;
|
|
||||||
resp->versionMajor = HSM_SDK_VERSION_MAJOR;
|
|
||||||
resp->versionMinor = HSM_SDK_VERSION_MINOR;
|
|
||||||
resp->capFlags = CAPFLAG_WINK;
|
|
||||||
|
|
||||||
u2f_resp->cid = CID_BROADCAST;
|
|
||||||
u2f_resp->init.cmd = U2FHID_INIT;
|
|
||||||
u2f_resp->init.bcntl = 17;
|
|
||||||
u2f_resp->init.bcnth = 0;
|
|
||||||
hid_write(64);
|
hid_write(64);
|
||||||
DEBUG_PAYLOAD((uint8_t *)u2f_resp, u2f_resp->init.bcntl+7);
|
|
||||||
}
|
|
||||||
// echo back anything we received from host
|
|
||||||
//tud_hid_report(0, buffer, bufsize);
|
|
||||||
printf("END\n");
|
|
||||||
usb_clear_rx();
|
usb_clear_rx();
|
||||||
|
last_packet_time = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t last_cmd = 0;
|
||||||
|
uint8_t last_seq = 0;
|
||||||
|
CTAPHID_FRAME last_req = { 0 };
|
||||||
|
uint32_t lock = 0;
|
||||||
|
|
||||||
|
uint8_t thread_type = 0; //1 is APDU, 2 is CBOR
|
||||||
|
extern void cbor_thread();
|
||||||
|
extern bool cancel_button;
|
||||||
|
|
||||||
|
int driver_process_usb_nopacket() {
|
||||||
|
if (last_packet_time > 0 && last_packet_time+500 < board_millis()) {
|
||||||
|
ctap_error(CTAP1_ERR_MSG_TIMEOUT);
|
||||||
|
last_packet_time = 0;
|
||||||
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void driver_exec_timeout() {
|
int driver_process_usb_packet(uint16_t read) {
|
||||||
|
int apdu_sent = 0;
|
||||||
|
if (read >= 5)
|
||||||
|
{
|
||||||
|
last_packet_time = board_millis();
|
||||||
|
DEBUG_PAYLOAD(usb_get_rx(),64);
|
||||||
|
memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
|
||||||
|
if (ctap_req->cid == 0x0 || (ctap_req->cid == CID_BROADCAST && ctap_req->init.cmd != CTAPHID_INIT))
|
||||||
|
return ctap_error(CTAP1_ERR_INVALID_CHANNEL);
|
||||||
|
if (board_millis() < lock && ctap_req->cid != last_req.cid && last_cmd_time+100 > board_millis())
|
||||||
|
return ctap_error(CTAP1_ERR_CHANNEL_BUSY);
|
||||||
|
if (FRAME_TYPE(ctap_req) == TYPE_INIT)
|
||||||
|
{
|
||||||
|
if (MSG_LEN(ctap_req) > CTAP_MAX_PACKET_SIZE)
|
||||||
|
return ctap_error(CTAP1_ERR_INVALID_LEN);
|
||||||
|
if (msg_packet.len > 0 && last_cmd_time+100 > board_millis() && ctap_req->init.cmd != CTAPHID_INIT) {
|
||||||
|
if (last_req.cid != ctap_req->cid) //We are in a transaction
|
||||||
|
return ctap_error(CTAP1_ERR_CHANNEL_BUSY);
|
||||||
|
else
|
||||||
|
return ctap_error(CTAP1_ERR_INVALID_SEQ);
|
||||||
|
}
|
||||||
|
printf("command %x\n", FRAME_CMD(ctap_req));
|
||||||
|
printf("len %d\n", MSG_LEN(ctap_req));
|
||||||
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
|
if (MSG_LEN(ctap_req) > 64 - 7)
|
||||||
|
{
|
||||||
|
msg_packet.len = MSG_LEN(ctap_req);
|
||||||
|
memcpy(msg_packet.data + msg_packet.current_len, ctap_req->init.data, 64-7);
|
||||||
|
msg_packet.current_len += 64 - 7;
|
||||||
|
}
|
||||||
|
memcpy(&last_req, ctap_req, sizeof(CTAPHID_FRAME));
|
||||||
|
last_cmd = ctap_req->init.cmd;
|
||||||
|
last_seq = 0;
|
||||||
|
last_cmd_time = board_millis();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (msg_packet.len == 0) //Received a cont with a prior init pkt
|
||||||
|
return 0;
|
||||||
|
if (last_seq != ctap_req->cont.seq)
|
||||||
|
return ctap_error(CTAP1_ERR_INVALID_SEQ);
|
||||||
|
if (last_req.cid == ctap_req->cid) {
|
||||||
|
memcpy(msg_packet.data + msg_packet.current_len, ctap_req->cont.data, MIN(64 - 5, msg_packet.len - msg_packet.current_len));
|
||||||
|
msg_packet.current_len += MIN(64 - 5, msg_packet.len - msg_packet.current_len);
|
||||||
|
memcpy(&last_req, ctap_req, sizeof(CTAPHID_FRAME));
|
||||||
|
last_seq++;
|
||||||
|
}
|
||||||
|
else if (last_cmd_time+100 > board_millis())
|
||||||
|
return ctap_error(CTAP1_ERR_CHANNEL_BUSY);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctap_req->init.cmd == CTAPHID_INIT) {
|
||||||
|
init_fido(false);
|
||||||
|
ctap_resp = (CTAPHID_FRAME *)usb_get_tx();
|
||||||
|
memset(ctap_resp, 0, 64);
|
||||||
|
CTAPHID_INIT_REQ *req = (CTAPHID_INIT_REQ *)ctap_req->init.data;
|
||||||
|
CTAPHID_INIT_RESP *resp = (CTAPHID_INIT_RESP *)ctap_resp->init.data;
|
||||||
|
memcpy(resp->nonce, req->nonce, sizeof(resp->nonce));
|
||||||
|
resp->cid = 0x01000000;
|
||||||
|
resp->versionInterface = CTAPHID_IF_VERSION;
|
||||||
|
resp->versionMajor = HSM_SDK_VERSION_MAJOR;
|
||||||
|
resp->versionMinor = HSM_SDK_VERSION_MINOR;
|
||||||
|
resp->capFlags = CAPFLAG_WINK | CAPFLAG_CBOR;
|
||||||
|
|
||||||
|
ctap_resp->cid = CID_BROADCAST;
|
||||||
|
ctap_resp->init.cmd = CTAPHID_INIT;
|
||||||
|
ctap_resp->init.bcntl = 17;
|
||||||
|
ctap_resp->init.bcnth = 0;
|
||||||
|
driver_exec_finished(17);
|
||||||
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
|
last_packet_time = 0;
|
||||||
|
}
|
||||||
|
else if (ctap_req->init.cmd == CTAPHID_WINK) {
|
||||||
|
if (MSG_LEN(ctap_req) != 0) {
|
||||||
|
return ctap_error(CTAP1_ERR_INVALID_LEN);
|
||||||
|
}
|
||||||
|
ctap_resp = (CTAPHID_FRAME *)usb_get_tx();
|
||||||
|
memcpy(ctap_resp, ctap_req, sizeof(CTAPHID_FRAME));
|
||||||
|
sleep_ms(1000); //For blinking the device during 1 seg
|
||||||
|
hid_write(64);
|
||||||
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
|
last_packet_time = 0;
|
||||||
|
}
|
||||||
|
else if ((last_cmd == CTAPHID_PING || last_cmd == CTAPHID_SYNC) && (msg_packet.len == 0 || (msg_packet.len == msg_packet.current_len && msg_packet.len > 0))) {
|
||||||
|
ctap_resp = (CTAPHID_FRAME *)usb_get_tx();
|
||||||
|
if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) {
|
||||||
|
memcpy(ctap_resp->init.data, msg_packet.data, msg_packet.len);
|
||||||
|
driver_exec_finished(msg_packet.len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memcpy(ctap_resp->init.data, ctap_req->init.data, MSG_LEN(ctap_req));
|
||||||
|
driver_exec_finished(MSG_LEN(ctap_req));
|
||||||
|
}
|
||||||
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
|
last_packet_time = 0;
|
||||||
|
}
|
||||||
|
else if (ctap_req->init.cmd == CTAPHID_LOCK) {
|
||||||
|
if (MSG_LEN(ctap_req) != 1)
|
||||||
|
return ctap_error(CTAP1_ERR_INVALID_LEN);
|
||||||
|
if (ctap_req->init.data[0] > 10)
|
||||||
|
return ctap_error(CTAP1_ERR_INVALID_PARAMETER);
|
||||||
|
lock = board_millis() + ctap_req->init.data[0] * 1000;
|
||||||
|
ctap_resp = (CTAPHID_FRAME *)usb_get_tx();
|
||||||
|
memset(ctap_resp, 0, 64);
|
||||||
|
ctap_resp->cid = ctap_req->cid;
|
||||||
|
ctap_resp->init.cmd = ctap_req->init.cmd;
|
||||||
|
hid_write(64);
|
||||||
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
|
last_packet_time = 0;
|
||||||
|
}
|
||||||
|
else if (last_cmd == CTAPHID_MSG && (msg_packet.len == 0 || (msg_packet.len == msg_packet.current_len && msg_packet.len > 0))) {
|
||||||
|
|
||||||
|
current_app = apps[0].select_aid(&apps[0]);
|
||||||
|
if (thread_type != 1)
|
||||||
|
card_start(apdu_thread);
|
||||||
|
thread_type = 1;
|
||||||
|
|
||||||
|
if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0)
|
||||||
|
apdu_sent = apdu_process(msg_packet.data, msg_packet.len);
|
||||||
|
else
|
||||||
|
apdu_sent = apdu_process(ctap_req->init.data, MSG_LEN(ctap_req));
|
||||||
|
DEBUG_PAYLOAD(apdu.data, (int)apdu.nc);
|
||||||
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
|
last_packet_time = 0;
|
||||||
|
}
|
||||||
|
else if (last_cmd == CTAPHID_CBOR && (msg_packet.len == 0 || (msg_packet.len == msg_packet.current_len && msg_packet.len > 0))) {
|
||||||
|
|
||||||
|
if (thread_type != 2)
|
||||||
|
card_start(cbor_thread);
|
||||||
|
thread_type = 2;
|
||||||
|
if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0)
|
||||||
|
apdu_sent = cbor_process(msg_packet.data, msg_packet.len);
|
||||||
|
else
|
||||||
|
apdu_sent = cbor_process(ctap_req->init.data, MSG_LEN(ctap_req));
|
||||||
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
|
last_packet_time = 0;
|
||||||
|
if (apdu_sent < 0)
|
||||||
|
return ctap_error(-apdu_sent);
|
||||||
|
}
|
||||||
|
else if (ctap_req->init.cmd == CTAPHID_CANCEL) {
|
||||||
|
ctap_error(0x2D);
|
||||||
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
|
last_packet_time = 0;
|
||||||
|
cancel_button = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (msg_packet.len == 0)
|
||||||
|
return ctap_error(CTAP1_ERR_INVALID_CMD);
|
||||||
|
}
|
||||||
|
// echo back anything we received from host
|
||||||
|
//tud_hid_report(0, buffer, bufsize);
|
||||||
|
//printf("END\n");
|
||||||
|
usb_clear_rx();
|
||||||
|
}
|
||||||
|
return apdu_sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_keepalive() {
|
||||||
|
CTAPHID_FRAME *resp = (CTAPHID_FRAME *)(usb_get_tx() + 4096);
|
||||||
|
//memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
|
||||||
|
resp->cid = ctap_req->cid;
|
||||||
|
resp->init.cmd = CTAPHID_KEEPALIVE;
|
||||||
|
resp->init.bcntl = 1;
|
||||||
|
resp->init.data[0] = is_req_button_pending() ? 2 : 1;
|
||||||
|
send_buffer_size = 0;
|
||||||
|
hid_write_offset(64, 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver_exec_timeout() {
|
||||||
|
send_keepalive();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *driver_prepare_response() {
|
||||||
|
ctap_resp = (CTAPHID_FRAME *)usb_get_tx();
|
||||||
|
apdu.rdata = ctap_resp->init.data;
|
||||||
|
send_buffer_size = 0;
|
||||||
|
memset(usb_get_tx(), 0, 4096);
|
||||||
|
return ctap_resp->init.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void driver_exec_finished(size_t size_next) {
|
void driver_exec_finished(size_t size_next) {
|
||||||
|
if (thread_type == 2 && apdu.sw != 0)
|
||||||
|
ctap_error(apdu.sw & 0xff);
|
||||||
|
else
|
||||||
|
driver_exec_finished_cont(size_next, 7);
|
||||||
|
apdu.sw = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver_exec_finished_cont(size_t size_next, size_t offset) {
|
||||||
|
offset -= 7;
|
||||||
|
ctap_resp = (CTAPHID_FRAME *)(usb_get_tx() + offset);
|
||||||
|
ctap_resp->cid = ctap_req->cid;
|
||||||
|
ctap_resp->init.cmd = last_cmd;
|
||||||
|
ctap_resp->init.bcnth = size_next >> 8;
|
||||||
|
ctap_resp->init.bcntl = size_next & 0xff;
|
||||||
|
hid_write_offset(64, offset);
|
||||||
|
ctap_resp = (CTAPHID_FRAME *)((uint8_t *)ctap_resp + 64 - 5);
|
||||||
|
|
||||||
|
send_buffer_size = size_next;
|
||||||
|
send_buffer_size -= MIN(64-7, send_buffer_size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
// Common U2F raw message format header - Review Draft
|
|
||||||
// 2014-10-08
|
|
||||||
// Editor: Jakob Ehrensvard, Yubico, jakob@yubico.com
|
|
||||||
|
|
||||||
#ifndef __U2F_H_INCLUDED__
|
|
||||||
#define __U2F_H_INCLUDED__
|
|
||||||
|
|
||||||
#ifdef _MSC_VER // Windows
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef unsigned short uint16_t;
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
typedef unsigned long int uint64_t;
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// General constants
|
|
||||||
|
|
||||||
#define U2F_EC_KEY_SIZE 32 // EC key size in bytes
|
|
||||||
#define U2F_EC_POINT_SIZE ((U2F_EC_KEY_SIZE * 2) + 1) // Size of EC point
|
|
||||||
#define U2F_MAX_KH_SIZE 128 // Max size of key handle
|
|
||||||
#define U2F_MAX_ATT_CERT_SIZE 2048 // Max size of attestation certificate
|
|
||||||
#define U2F_MAX_EC_SIG_SIZE 72 // Max size of DER coded EC signature
|
|
||||||
#define U2F_CTR_SIZE 4 // Size of counter field
|
|
||||||
#define U2F_APPID_SIZE 32 // Size of application id
|
|
||||||
#define U2F_CHAL_SIZE 32 // Size of challenge
|
|
||||||
|
|
||||||
#define ENC_SIZE(x) ((x + 7) & 0xfff8)
|
|
||||||
|
|
||||||
// EC (uncompressed) point
|
|
||||||
|
|
||||||
#define U2F_POINT_UNCOMPRESSED 0x04 // Uncompressed point format
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t pointFormat; // Point type
|
|
||||||
uint8_t x[U2F_EC_KEY_SIZE]; // X-value
|
|
||||||
uint8_t y[U2F_EC_KEY_SIZE]; // Y-value
|
|
||||||
} U2F_EC_POINT;
|
|
||||||
|
|
||||||
// U2F native commands
|
|
||||||
|
|
||||||
#define U2F_REGISTER 0x01 // Registration command
|
|
||||||
#define U2F_AUTHENTICATE 0x02 // Authenticate/sign command
|
|
||||||
#define U2F_VERSION 0x03 // Read version string command
|
|
||||||
|
|
||||||
#define U2F_VENDOR_FIRST 0x40 // First vendor defined command
|
|
||||||
#define U2F_VENDOR_LAST 0xbf // Last vendor defined command
|
|
||||||
|
|
||||||
// U2F_CMD_REGISTER command defines
|
|
||||||
|
|
||||||
#define U2F_REGISTER_ID 0x05 // Version 2 registration identifier
|
|
||||||
#define U2F_REGISTER_HASH_ID 0x00 // Version 2 hash identintifier
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t chal[U2F_CHAL_SIZE]; // Challenge
|
|
||||||
uint8_t appId[U2F_APPID_SIZE]; // Application id
|
|
||||||
} U2F_REGISTER_REQ;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t registerId; // Registration identifier (U2F_REGISTER_ID_V2)
|
|
||||||
U2F_EC_POINT pubKey; // Generated public key
|
|
||||||
uint8_t keyHandleLen; // Length of key handle
|
|
||||||
uint8_t keyHandleCertSig[
|
|
||||||
U2F_MAX_KH_SIZE + // Key handle
|
|
||||||
U2F_MAX_ATT_CERT_SIZE + // Attestation certificate
|
|
||||||
U2F_MAX_EC_SIG_SIZE]; // Registration signature
|
|
||||||
} U2F_REGISTER_RESP;
|
|
||||||
|
|
||||||
// U2F_CMD_AUTHENTICATE command defines
|
|
||||||
|
|
||||||
// Authentication control byte
|
|
||||||
|
|
||||||
#define U2F_AUTH_ENFORCE 0x03 // Enforce user presence and sign
|
|
||||||
#define U2F_AUTH_CHECK_ONLY 0x07 // Check only
|
|
||||||
#define U2F_AUTH_FLAG_TUP 0x01 // Test of user presence set
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t chal[U2F_CHAL_SIZE]; // Challenge
|
|
||||||
uint8_t appId[U2F_APPID_SIZE]; // Application id
|
|
||||||
uint8_t keyHandleLen; // Length of key handle
|
|
||||||
uint8_t keyHandle[U2F_MAX_KH_SIZE]; // Key handle
|
|
||||||
} U2F_AUTHENTICATE_REQ;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t flags; // U2F_AUTH_FLAG_ values
|
|
||||||
uint8_t ctr[U2F_CTR_SIZE]; // Counter field (big-endian)
|
|
||||||
uint8_t sig[U2F_MAX_EC_SIG_SIZE]; // Signature
|
|
||||||
} U2F_AUTHENTICATE_RESP;
|
|
||||||
|
|
||||||
// Command status responses
|
|
||||||
|
|
||||||
#define U2F_SW_NO_ERROR 0x9000 // SW_NO_ERROR
|
|
||||||
#define U2F_SW_WRONG_DATA 0x6A80 // SW_WRONG_DATA
|
|
||||||
#define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985 // SW_CONDITIONS_NOT_SATISFIED
|
|
||||||
#define U2F_SW_COMMAND_NOT_ALLOWED 0x6986 // SW_COMMAND_NOT_ALLOWED
|
|
||||||
#define U2F_SW_INS_NOT_SUPPORTED 0x6D00 // SW_INS_NOT_SUPPORTED
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __U2F_H_INCLUDED__
|
|
||||||
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
// Common U2F HID transport header - Review Draft
|
|
||||||
// 2014-10-08
|
|
||||||
// Editor: Jakob Ehrensvard, Yubico, jakob@yubico.com
|
|
||||||
|
|
||||||
#ifndef __U2FHID_H_INCLUDED__
|
|
||||||
#define __U2FHID_H_INCLUDED__
|
|
||||||
|
|
||||||
#ifdef _MSC_VER // Windows
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef unsigned short uint16_t;
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
typedef unsigned long int uint64_t;
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Size of HID reports
|
|
||||||
|
|
||||||
#define HID_RPT_SIZE 64 // Default size of raw HID report
|
|
||||||
|
|
||||||
// Frame layout - command- and continuation frames
|
|
||||||
|
|
||||||
#define CID_BROADCAST 0xffffffff // Broadcast channel id
|
|
||||||
|
|
||||||
#define TYPE_MASK 0x80 // Frame type mask
|
|
||||||
#define TYPE_INIT 0x80 // Initial frame identifier
|
|
||||||
#define TYPE_CONT 0x00 // Continuation frame identifier
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t cid; // Channel identifier
|
|
||||||
union {
|
|
||||||
uint8_t type; // Frame type - b7 defines type
|
|
||||||
struct {
|
|
||||||
uint8_t cmd; // Command - b7 set
|
|
||||||
uint8_t bcnth; // Message byte count - high part
|
|
||||||
uint8_t bcntl; // Message byte count - low part
|
|
||||||
uint8_t data[HID_RPT_SIZE - 7]; // Data payload
|
|
||||||
} init;
|
|
||||||
struct {
|
|
||||||
uint8_t seq; // Sequence number - b7 cleared
|
|
||||||
uint8_t data[HID_RPT_SIZE - 5]; // Data payload
|
|
||||||
} cont;
|
|
||||||
};
|
|
||||||
}__packed U2FHID_FRAME;
|
|
||||||
|
|
||||||
#define FRAME_TYPE(f) ((f)->type & TYPE_MASK)
|
|
||||||
#define FRAME_CMD(f) ((f)->init.cmd & ~TYPE_MASK)
|
|
||||||
#define MSG_LEN(f) ((f)->init.bcnth*256 + (f)->init.bcntl)
|
|
||||||
#define FRAME_SEQ(f) ((f)->cont.seq & ~TYPE_MASK)
|
|
||||||
|
|
||||||
// HID usage- and usage-page definitions
|
|
||||||
|
|
||||||
#define FIDO_USAGE_PAGE 0xf1d0 // FIDO alliance HID usage page
|
|
||||||
#define FIDO_USAGE_U2FHID 0x01 // U2FHID usage for top-level collection
|
|
||||||
#define FIDO_USAGE_DATA_IN 0x20 // Raw IN data report
|
|
||||||
#define FIDO_USAGE_DATA_OUT 0x21 // Raw OUT data report
|
|
||||||
|
|
||||||
// General constants
|
|
||||||
|
|
||||||
#define U2FHID_IF_VERSION 2 // Current interface implementation version
|
|
||||||
#define U2FHID_TRANS_TIMEOUT 3000 // Default message timeout in ms
|
|
||||||
|
|
||||||
// U2FHID native commands
|
|
||||||
|
|
||||||
#define U2FHID_PING (TYPE_INIT | 0x01) // Echo data through local processor only
|
|
||||||
#define U2FHID_MSG (TYPE_INIT | 0x03) // Send U2F message frame
|
|
||||||
#define U2FHID_LOCK (TYPE_INIT | 0x04) // Send lock channel command
|
|
||||||
#define U2FHID_INIT (TYPE_INIT | 0x06) // Channel initialization
|
|
||||||
#define U2FHID_WINK (TYPE_INIT | 0x08) // Send device identification wink
|
|
||||||
#define U2FHID_SYNC (TYPE_INIT | 0x3c) // Protocol resync command
|
|
||||||
#define U2FHID_ERROR (TYPE_INIT | 0x3f) // Error response
|
|
||||||
|
|
||||||
#define U2FHID_VENDOR_FIRST (TYPE_INIT | 0x40) // First vendor defined command
|
|
||||||
#define U2FHID_VENDOR_LAST (TYPE_INIT | 0x7f) // Last vendor defined command
|
|
||||||
|
|
||||||
// U2FHID_INIT command defines
|
|
||||||
|
|
||||||
#define INIT_NONCE_SIZE 8 // Size of channel initialization challenge
|
|
||||||
#define CAPFLAG_WINK 0x01 // Device supports WINK command
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t nonce[INIT_NONCE_SIZE]; // Client application nonce
|
|
||||||
}__packed U2FHID_INIT_REQ;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t nonce[INIT_NONCE_SIZE]; // Client application nonce
|
|
||||||
uint32_t cid; // Channel identifier
|
|
||||||
uint8_t versionInterface; // Interface version
|
|
||||||
uint8_t versionMajor; // Major version number
|
|
||||||
uint8_t versionMinor; // Minor version number
|
|
||||||
uint8_t versionBuild; // Build version number
|
|
||||||
uint8_t capFlags; // Capabilities flags
|
|
||||||
}__packed U2FHID_INIT_RESP;
|
|
||||||
|
|
||||||
// U2FHID_SYNC command defines
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t nonce; // Client application nonce
|
|
||||||
} U2FHID_SYNC_REQ;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t nonce; // Client application nonce
|
|
||||||
} U2FHID_SYNC_RESP;
|
|
||||||
|
|
||||||
// Low-level error codes. Return as negatives.
|
|
||||||
|
|
||||||
#define ERR_NONE 0x00 // No error
|
|
||||||
#define ERR_INVALID_CMD 0x01 // Invalid command
|
|
||||||
#define ERR_INVALID_PAR 0x02 // Invalid parameter
|
|
||||||
#define ERR_INVALID_LEN 0x03 // Invalid message length
|
|
||||||
#define ERR_INVALID_SEQ 0x04 // Invalid message sequencing
|
|
||||||
#define ERR_MSG_TIMEOUT 0x05 // Message has timed out
|
|
||||||
#define ERR_CHANNEL_BUSY 0x06 // Channel busy
|
|
||||||
#define ERR_LOCK_REQUIRED 0x0a // Command requires channel lock
|
|
||||||
#define ERR_SYNC_FAIL 0x0b // SYNC command failed
|
|
||||||
#define ERR_OTHER 0x7f // Other unspecified error
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __U2FHID_H_INCLUDED__
|
|
||||||
|
|
||||||
@@ -24,7 +24,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#include "u2f_hid.h"
|
#include "ctap_hid.h"
|
||||||
|
#include "pico/unique_id.h"
|
||||||
|
#include "hsm_version.h"
|
||||||
|
|
||||||
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
||||||
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
||||||
@@ -49,7 +51,7 @@ tusb_desc_device_t const desc_device =
|
|||||||
|
|
||||||
.idVendor = 0xCafe,
|
.idVendor = 0xCafe,
|
||||||
.idProduct = 0x4231,
|
.idProduct = 0x4231,
|
||||||
.bcdDevice = 0x0100,
|
.bcdDevice = HSM_SDK_VERSION,
|
||||||
|
|
||||||
.iManufacturer = 0x01,
|
.iManufacturer = 0x01,
|
||||||
.iProduct = 0x02,
|
.iProduct = 0x02,
|
||||||
@@ -69,9 +71,9 @@ uint8_t const * tud_descriptor_device_cb(void)
|
|||||||
// HID Report Descriptor
|
// HID Report Descriptor
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
#define TUD_HID_REPORT_DESC_U2F(report_size, ...) \
|
#define TUD_HID_REPORT_DESC_CTAP(report_size, ...) \
|
||||||
HID_USAGE_PAGE_N ( FIDO_USAGE_PAGE, 2 ),\
|
HID_USAGE_PAGE_N ( FIDO_USAGE_PAGE, 2 ),\
|
||||||
HID_USAGE ( FIDO_USAGE_U2FHID ),\
|
HID_USAGE ( FIDO_USAGE_CTAPHID ),\
|
||||||
HID_COLLECTION ( HID_COLLECTION_APPLICATION ),\
|
HID_COLLECTION ( HID_COLLECTION_APPLICATION ),\
|
||||||
/* Report ID if any */\
|
/* Report ID if any */\
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
@@ -93,7 +95,7 @@ uint8_t const * tud_descriptor_device_cb(void)
|
|||||||
|
|
||||||
uint8_t const desc_hid_report[] =
|
uint8_t const desc_hid_report[] =
|
||||||
{
|
{
|
||||||
TUD_HID_REPORT_DESC_U2F(CFG_TUD_HID_EP_BUFSIZE)
|
TUD_HID_REPORT_DESC_CTAP(CFG_TUD_HID_EP_BUFSIZE)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Invoked when received GET HID REPORT DESCRIPTOR
|
// Invoked when received GET HID REPORT DESCRIPTOR
|
||||||
@@ -145,8 +147,8 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
|||||||
char const* string_desc_arr [] =
|
char const* string_desc_arr [] =
|
||||||
{
|
{
|
||||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||||
"TinyUSB", // 1: Manufacturer
|
"Pol Henarejos", // 1: Manufacturer
|
||||||
"TinyUSB Device", // 2: Product
|
"Pico HSM HID", // 2: Product
|
||||||
"123456", // 3: Serials, should use chip ID
|
"123456", // 3: Serials, should use chip ID
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -160,33 +162,37 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
|||||||
|
|
||||||
uint8_t chr_count;
|
uint8_t chr_count;
|
||||||
|
|
||||||
if ( index == 0)
|
if (index == 0) {
|
||||||
{
|
|
||||||
memcpy(&_desc_str[1], string_desc_arr[0], 2);
|
memcpy(&_desc_str[1], string_desc_arr[0], 2);
|
||||||
chr_count = 1;
|
chr_count = 1;
|
||||||
}else
|
}
|
||||||
{
|
else {
|
||||||
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
|
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
|
||||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
|
||||||
|
|
||||||
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
|
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
const char* str = string_desc_arr[index];
|
const char* str = string_desc_arr[index];
|
||||||
|
char unique_id_str[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1];
|
||||||
|
if (index == 3) {
|
||||||
|
pico_unique_board_id_t unique_id;
|
||||||
|
pico_get_unique_board_id(&unique_id);
|
||||||
|
pico_get_unique_board_id_string(unique_id_str, 2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1);
|
||||||
|
str = unique_id_str;
|
||||||
|
}
|
||||||
|
|
||||||
// Cap at max char
|
chr_count = strlen(str);
|
||||||
chr_count = (uint8_t) strlen(str);
|
if ( chr_count > 31 )
|
||||||
if ( chr_count > 31 ) chr_count = 31;
|
chr_count = 31;
|
||||||
|
|
||||||
// Convert ASCII string into UTF-16
|
// Convert ASCII string into UTF-16
|
||||||
for(uint8_t i=0; i<chr_count; i++)
|
for(uint8_t i=0; i<chr_count; i++) {
|
||||||
{
|
|
||||||
_desc_str[1+i] = str[i];
|
_desc_str[1+i] = str[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// first byte is length (including header), second byte is string type
|
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
|
||||||
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8 ) | (2*chr_count + 2));
|
|
||||||
|
|
||||||
return _desc_str;
|
return _desc_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,14 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
// Device specific functions
|
// Device specific functions
|
||||||
static uint8_t rx_buffer[4096], tx_buffer[4096];
|
static uint8_t rx_buffer[4096], tx_buffer[4096+64];
|
||||||
static uint16_t w_offset = 0, r_offset = 0;
|
static uint16_t w_offset = 0, r_offset = 0;
|
||||||
static uint16_t w_len = 0, tx_r_offset = 0;
|
static uint16_t w_len = 0, tx_r_offset = 0;
|
||||||
|
static uint32_t timeout_counter = 0;
|
||||||
|
|
||||||
|
void usb_set_timeout_counter(uint32_t v) {
|
||||||
|
timeout_counter = v;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t usb_write_offset(uint16_t len, uint16_t offset) {
|
uint32_t usb_write_offset(uint16_t len, uint16_t offset) {
|
||||||
uint8_t pkt_max = 64;
|
uint8_t pkt_max = 64;
|
||||||
@@ -129,6 +134,8 @@ void usb_init() {
|
|||||||
driver_init();
|
driver_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int driver_process_usb_nopacket();
|
||||||
|
|
||||||
static int usb_event_handle() {
|
static int usb_event_handle() {
|
||||||
uint16_t rx_read = usb_read_available();
|
uint16_t rx_read = usb_read_available();
|
||||||
if (driver_process_usb_packet(rx_read) > 0) {
|
if (driver_process_usb_packet(rx_read) > 0) {
|
||||||
@@ -136,50 +143,22 @@ static int usb_event_handle() {
|
|||||||
queue_add_blocking(&usb_to_card_q, &flag);
|
queue_add_blocking(&usb_to_card_q, &flag);
|
||||||
timeout_start();
|
timeout_start();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
driver_process_usb_nopacket();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void card_init_core1(void) {
|
extern void low_flash_init();
|
||||||
//gpg_data_scan (flash_do_start, flash_do_end);
|
void card_init_core1() {
|
||||||
low_flash_init_core1();
|
low_flash_init_core1();
|
||||||
}
|
}
|
||||||
|
|
||||||
void card_thread() {
|
size_t finished_data_size = 0;
|
||||||
card_init_core1();
|
|
||||||
|
|
||||||
while (1) {
|
void card_start(void (*func)(void)) {
|
||||||
uint32_t m;
|
|
||||||
queue_remove_blocking(&usb_to_card_q, &m);
|
|
||||||
|
|
||||||
if (m == EV_VERIFY_CMD_AVAILABLE || m == EV_MODIFY_CMD_AVAILABLE)
|
|
||||||
{
|
|
||||||
set_res_sw (0x6f, 0x00);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else if (m == EV_EXIT) {
|
|
||||||
if (current_app && current_app->unload) {
|
|
||||||
current_app->unload();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
process_apdu();
|
|
||||||
|
|
||||||
done:;
|
|
||||||
uint32_t flag = EV_EXEC_FINISHED;
|
|
||||||
queue_add_blocking(&card_to_usb_q, &flag);
|
|
||||||
}
|
|
||||||
//printf("EXIT !!!!!!\r\n");
|
|
||||||
if (current_app && current_app->unload)
|
|
||||||
current_app->unload();
|
|
||||||
}
|
|
||||||
|
|
||||||
void card_thread();
|
|
||||||
void card_start()
|
|
||||||
{
|
|
||||||
multicore_reset_core1();
|
multicore_reset_core1();
|
||||||
multicore_launch_core1(card_thread);
|
multicore_launch_core1(func);
|
||||||
led_set_blink(BLINK_MOUNTED);
|
led_set_blink(BLINK_MOUNTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,10 +180,9 @@ void usb_task() {
|
|||||||
// printf("\r\n ------ M = %lu\r\n",m);
|
// printf("\r\n ------ M = %lu\r\n",m);
|
||||||
if (has_m) {
|
if (has_m) {
|
||||||
if (m == EV_EXEC_FINISHED) {
|
if (m == EV_EXEC_FINISHED) {
|
||||||
apdu_finish();
|
driver_exec_finished(finished_data_size);
|
||||||
size_t size_next = apdu_next();
|
|
||||||
driver_exec_finished(size_next);
|
|
||||||
led_set_blink(BLINK_MOUNTED);
|
led_set_blink(BLINK_MOUNTED);
|
||||||
|
timeout_stop();
|
||||||
}
|
}
|
||||||
else if (m == EV_PRESS_BUTTON) {
|
else if (m == EV_PRESS_BUTTON) {
|
||||||
uint32_t flag = wait_button() ? EV_BUTTON_TIMEOUT : EV_BUTTON_PRESSED;
|
uint32_t flag = wait_button() ? EV_BUTTON_TIMEOUT : EV_BUTTON_PRESSED;
|
||||||
@@ -262,7 +240,7 @@ void usb_task() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (timeout > 0) {
|
if (timeout > 0) {
|
||||||
if (timeout + 1500 < board_millis()) {
|
if (timeout + timeout_counter < board_millis()) {
|
||||||
driver_exec_timeout();
|
driver_exec_timeout();
|
||||||
timeout = board_millis();
|
timeout = board_millis();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ extern void driver_exec_timeout();
|
|||||||
extern bool driver_mounted();
|
extern bool driver_mounted();
|
||||||
extern uint8_t *driver_prepare_response();
|
extern uint8_t *driver_prepare_response();
|
||||||
|
|
||||||
extern void card_start();
|
extern void card_start(void (*func)(void));
|
||||||
extern void card_exit();
|
extern void card_exit();
|
||||||
extern void usb_init();
|
extern void usb_init();
|
||||||
extern uint8_t *usb_prepare_response();
|
extern uint8_t *usb_prepare_response();
|
||||||
@@ -56,4 +56,8 @@ extern uint8_t *usb_get_rx();
|
|||||||
extern uint8_t *usb_get_tx();
|
extern uint8_t *usb_get_tx();
|
||||||
extern uint32_t usb_write_offset(uint16_t len, uint16_t offset);
|
extern uint32_t usb_write_offset(uint16_t len, uint16_t offset);
|
||||||
extern void usb_clear_rx();
|
extern void usb_clear_rx();
|
||||||
|
extern size_t finished_data_size;
|
||||||
|
extern void usb_set_timeout_counter(uint32_t v);
|
||||||
|
extern void card_init_core1();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
1
tinycbor
Submodule
1
tinycbor
Submodule
Submodule tinycbor added at e27261ed5e
Reference in New Issue
Block a user