50 Commits
v3.0 ... v3.4

Author SHA1 Message Date
Pol Henarejos
657913d29a Upgrading version
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-25 18:14:18 +02:00
Pol Henarejos
18fa1d7f37 Reseting previous command if new arrives.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-25 18:09:37 +02:00
Pol Henarejos
f123108c3e Added variable to cancel button press.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-23 18:07:38 +02:00
Pol Henarejos
f8590ba8c7 Added CTAPHID_CANCEL support.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-23 18:07:27 +02:00
Pol Henarejos
4d7101b802 Fix send_keepalive with auxiliary buffer.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 23:53:55 +02:00
Pol Henarejos
7fded7234b Adding extra buffer to tx.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 22:52:56 +02:00
Pol Henarejos
988d4e23c2 Fix combining APDU MSG and keepalive.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 22:52:41 +02:00
Pol Henarejos
c23f17107a Random functions shall be called for each core, otherwise it will hung.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 20:18:05 +02:00
Pol Henarejos
91e2b7f643 Fix reading corrupted memory.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 19:24:17 +02:00
Pol Henarejos
3092da23ed card_init_core1() shall be called from every thread launched on core1.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 19:24:07 +02:00
Pol Henarejos
e29521fcf6 Multiple bug fixes to pass HID tests.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 19:23:39 +02:00
Pol Henarejos
d2e54b04db Adding variable button timeout.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 19:22:44 +02:00
Pol Henarejos
4ab68cc822 HID fixes.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 14:05:39 +02:00
Pol Henarejos
e1914556ec Fix debug_data
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 09:59:02 +02:00
Pol Henarejos
287be74921 Adding macro for easy debug.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-22 09:29:43 +02:00
Pol Henarejos
5a4aff7008 Adding KEEP_ALIVE response.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-20 15:31:34 +02:00
Pol Henarejos
8b97791d8f Reorganizing core0/core1 split.
Now CBOR and APDU (i.e., intensive processing) areas are executed on core1, while core0 is dedicated for hardware tasks (usb, button, led, etc.).
2022-09-20 14:39:59 +02:00
Pol Henarejos
847005d94f Adding support for clientPIN.
It does not pass the tests yet.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-19 17:20:52 +02:00
Pol Henarejos
68f43f3cb2 Adding functions for calling random in core0.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-16 00:49:10 +02:00
Pol Henarejos
4c49e59edc Major CTAP refactoring.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-15 14:16:40 +02:00
Pol Henarejos
633593aae3 Adding chacha sources.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-15 14:16:30 +02:00
Pol Henarejos
42f3c67c61 Adding Credentials structure.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-14 17:27:00 +02:00
Pol Henarejos
493a88538a Adding support for ChaCha20 with Poly1305.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-14 17:26:45 +02:00
Pol Henarejos
607f7c50d4 Adding some macros for CBOR parsing.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-14 00:08:05 +02:00
Pol Henarejos
2cb59d57d2 Adding first attempt of adding make_credential.
It requires lot of efforts to parse CBOR incoming data.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-13 20:37:15 +02:00
Pol Henarejos
a8e1fe5842 Adding CBOR parser routines.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-13 20:36:27 +02:00
Pol Henarejos
d1530733a2 Lots of fixes with CBOR encoding cbor_get_info().
- Numeric fields shall be encoded with uint and NOT with simple, despite are < 24.
- maxCredentialCountInList and maxCredentialIdLength only accept uint values.
- up shall not be present (assumed True always).
- Also added cbor_reset(). It does nothing but ok.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-12 00:50:38 +02:00
Pol Henarejos
4538d6ef14 Add TinyCBOR library compile.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-09 20:43:18 +02:00
Pol Henarejos
4a1bddb3d5 Adding cbor_get_info().
This is the first funciont that uses TinyCBOR to encode the cbor message.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-09 20:35:11 +02:00
Pol Henarejos
c6a129b6ad Add TinyCBOR for CBOR encoding/decoding.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-09 20:33:42 +02:00
Pol Henarejos
abd52c34ba Added CBOR processing.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 20:37:21 +02:00
Pol Henarejos
7aeac46eef Adding CTAP2 commands.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 17:49:56 +02:00
Pol Henarejos
867d4637ee Moving from U2F to CTAP1.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 17:35:40 +02:00
Pol Henarejos
7491021102 Fix initializing variables.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 16:38:13 +02:00
Pol Henarejos
9b137f6f08 Moved to FIDO.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 13:50:28 +02:00
Pol Henarejos
3f492b9272 Upgrade version to v3.2.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 13:45:30 +02:00
Pol Henarejos
799733203b Added SYNC command.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 13:24:03 +02:00
Pol Henarejos
0be497e713 Added LOCK command.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 13:12:17 +02:00
Pol Henarejos
e23dead31d Add PING command.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 12:56:32 +02:00
Pol Henarejos
4d9faccedb Added some sanity checks.
Also fix u2f_error report.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 12:13:34 +02:00
Pol Henarejos
f47df94dfb Added some string descriptors.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-08 10:45:25 +02:00
Pol Henarejos
c0123aa669 Adding blink in 1 second on WINK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-06 16:09:02 +02:00
Pol Henarejos
43dfb0cde5 Fix APDU processing for small packets.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-05 17:30:05 +02:00
Pol Henarejos
f14e029094 Adding x509 routines.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-05 17:05:51 +02:00
Pol Henarejos
f14cc8dba5 Clearing tx buffer for every transmission.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-05 16:47:07 +02:00
Pol Henarejos
16a1981dc3 When a packet > 57 bytes is sent, it must be chunked.
Once the packet is sent, a callback is triggered to send the next chunk.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-05 11:29:04 +02:00
Pol Henarejos
9ccd10fcea Adding x509 functions.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-02 19:08:45 +02:00
Pol Henarejos
a6506e6c95 Adding missing headers.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-09-02 19:08:33 +02:00
Pol Henarejos
3e73d6569b Disabling MbedTLS with FS. 2022-09-02 19:08:25 +02:00
Pol Henarejos
214ec2b9ae Adding support for U2F_MSG 2022-09-02 18:02:31 +02:00
24 changed files with 615 additions and 375 deletions

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "mbedtls"]
path = mbedtls
url = https://github.com/ARMmbed/mbedtls
[submodule "tinycbor"]
path = tinycbor
url = https://github.com/intel/tinycbor.git

View File

@@ -1004,7 +1004,7 @@
*
* Enable functions that use the filesystem.
*/
#define MBEDTLS_FS_IO
//#define MBEDTLS_FS_IO
/**
* \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
@@ -2112,7 +2112,7 @@
*
* Module: library/chacha20.c
*/
//#define MBEDTLS_CHACHA20_C
#define MBEDTLS_CHACHA20_C
/**
* \def MBEDTLS_CHACHAPOLY_C
@@ -2123,7 +2123,7 @@
*
* This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C
*/
//#define MBEDTLS_CHACHAPOLY_C
#define MBEDTLS_CHACHAPOLY_C
/**
* \def MBEDTLS_CIPHER_C
@@ -2657,7 +2657,7 @@
* either MBEDTLS_PSA_ITS_FILE_C or a native implementation of
* the PSA ITS interface
*/
#define MBEDTLS_PSA_CRYPTO_STORAGE_C
//#define MBEDTLS_PSA_CRYPTO_STORAGE_C
/**
* \def MBEDTLS_PSA_ITS_FILE_C
@@ -2669,7 +2669,7 @@
*
* Requires: MBEDTLS_FS_IO
*/
#define MBEDTLS_PSA_ITS_FILE_C
//#define MBEDTLS_PSA_ITS_FILE_C
/**
* \def MBEDTLS_RIPEMD160_C

View File

@@ -91,9 +91,22 @@ if (NOT TARGET pico_hsm_sdk)
target_sources(pico_hsm_sdk INTERFACE
${CMAKE_CURRENT_LIST_DIR}/src/usb/hid/hid.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
${CMAKE_CURRENT_LIST_DIR}/src/usb/hid
${CMAKE_CURRENT_LIST_DIR}/tinycbor/src
)
endif()

View File

@@ -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.
*
* 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);
}
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() {
apdu.rdata[apdu.rlen] = apdu.sw >> 8;
apdu.rdata[apdu.rlen+1] = apdu.sw & 0xff;

View File

@@ -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.
*
* This program is free software: you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include "pico/stdlib.h"
#include <stdio.h>
typedef struct app {
const uint8_t *aid;
@@ -47,8 +48,19 @@ extern int register_app(app_t * (*)());
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
#define DEBUG_PAYLOAD(_p,_s)
#define DEBUG_DATA(_p,_s)
#endif
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 void apdu_finish();
extern size_t apdu_next();
extern void apdu_thread();
#endif

View File

@@ -235,10 +235,10 @@ void scan_region(bool persistent) {
}
}
}
void wait_flash_finish();
void scan_flash() {
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");
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;
}
bool file_has_data(file_t *f) {
return (f != NULL && f->data != NULL && file_get_size(f) > 0);
}

View File

@@ -74,6 +74,8 @@ typedef struct file
const uint8_t acl[7];
} __attribute__((packed)) file_t;
extern bool file_has_data(file_t *);
extern file_t *currentEF;
extern file_t *currentDF;
extern const file_t *selected_applet;

View File

@@ -61,6 +61,9 @@ enum {
};
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_WARNING_STATE_UNCHANGED() set_res_sw (0x62, 0x00)
#define SW_WARNING_CORRUPTED() set_res_sw (0x62, 0x81)

View File

@@ -18,7 +18,7 @@
#ifndef __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_MINOR (HSM_SDK_VERSION & 0xff)

View File

@@ -67,21 +67,31 @@ void led_set_blink(uint32_t mode) {
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() {
uint32_t start_button = board_millis();
bool timeout = false;
cancel_button = false;
led_set_blink((1000 << 16) | 100);
while (board_button_read() == false) {
req_button_pending = true;
while (board_button_read() == false && cancel_button == false) {
execute_tasks();
//sleep_ms(10);
if (start_button + 15000 < board_millis()) { /* timeout */
if (start_button + button_timeout < board_millis()) { /* timeout */
timeout = true;
break;
}
}
if (!timeout) {
while (board_button_read() == true) {
while (board_button_read() == true && cancel_button == false) {
execute_tasks();
//sleep_ms(10);
if (start_button + 15000 < board_millis()) { /* timeout */
@@ -91,7 +101,8 @@ bool wait_button() {
}
}
led_set_blink(BLINK_PROCESSING);
return timeout;
req_button_pending = false;
return timeout || cancel_button;
}
struct apdu apdu;

View File

@@ -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) {
neug_get();
}

View File

@@ -20,10 +20,14 @@
#define NEUG_PRE_LOOP 32
#include <stdlib.h>
#include "pico/stdlib.h"
void neug_init(uint32_t *buf, uint8_t size);
uint32_t neug_get();
void neug_flush(void);
void neug_wait_full(void);
void neug_wait_full_ext(bool);
void neug_fini(void);
#endif

View File

@@ -79,13 +79,13 @@ void random_get_salt(uint8_t *p) {
/*
* 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 = index_p ? *index_p : 0;
size_t n;
while (out_len) {
neug_wait_full();
neug_wait_full_ext(blocking);
n = RANDOM_BYTES_LENGTH - index;
if (n > out_len)
@@ -107,3 +107,11 @@ int random_gen(void *arg, unsigned char *out, size_t out_len) {
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);
}

View File

@@ -34,5 +34,6 @@ void random_get_salt (uint8_t *p);
/* iterator returning a byta at a time */
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

View File

@@ -124,6 +124,8 @@ int driver_init() {
ccid_response = (struct ccid_header *)usb_get_tx();
apdu.rdata = &ccid_response->apdu;
usb_set_timeout_counter(1500);
return CCID_OK;
}
@@ -174,7 +176,7 @@ int driver_process_usb_packet(uint16_t rx_read) {
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);
memcpy(apdu.rdata, ccid_atr+1, size_atr);
card_start();
card_start(apdu_thread);
ccid_status = 0;
ccid_write(size_atr);
}

View File

@@ -183,7 +183,7 @@ char const* string_desc_arr [] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"Pol Henarejos", // 1: Manufacturer
"Pico HSM", // 2: Product
"Pico HSM CCID", // 2: Product
"11223344", // 3: Serials, should use chip ID
"Pico HSM Config", // 4: Vendor Interface
"Pico HSM Interface"

159
src/usb/hid/ctap_hid.h Normal file
View 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_

View File

@@ -16,13 +16,24 @@
*/
#include "tusb.h"
#include "u2f_hid.h"
#include "ctap_hid.h"
#include "hsm.h"
#include "hsm_version.h"
#include "apdu.h"
#include "usb.h"
#include "bsp/board.h"
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()
{
@@ -33,15 +44,17 @@ bool driver_mounted() {
return mounted;
}
U2FHID_FRAME *u2f_req, *u2f_resp;
CTAPHID_FRAME *ctap_req = NULL, *ctap_resp = NULL;
int driver_init() {
tud_init(BOARD_TUD_RHPORT);
u2f_req = (U2FHID_FRAME *)usb_get_rx();
apdu.header = u2f_req->init.data;
ctap_req = (CTAPHID_FRAME *)usb_get_rx();
apdu.header = ctap_req->init.data;
u2f_resp = (U2FHID_FRAME *)usb_get_tx();
apdu.rdata = u2f_resp->init.data;
ctap_resp = (CTAPHID_FRAME *)usb_get_tx();
apdu.rdata = ctap_resp->init.data;
usb_set_timeout_counter(200);
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;
}
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) {
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) {
@@ -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) report_id;
(void) report_type;
printf("set report\n");
usb_rx(buffer, bufsize);
}
void hid_write_offset(uint16_t size, uint16_t offset) {
if (*usb_get_tx() != 0x81)
DEBUG_PAYLOAD(usb_get_tx()+offset,size+10);
usb_write_offset(size, offset);
}
void hid_write(uint16_t size) {
hid_write_offset(size, 0);
}
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;
uint32_t last_cmd_time = 0, last_packet_time = 0;
int ctap_error(uint8_t error) {
ctap_resp = (CTAPHID_FRAME *)usb_get_tx();
memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
ctap_resp->cid = ctap_req->cid;
ctap_resp->init.cmd = CTAPHID_ERROR;
ctap_resp->init.bcntl = 1;
ctap_resp->init.data[0] = error;
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();
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;
}
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) {
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);
}

View File

@@ -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__

View File

@@ -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__

View File

@@ -24,7 +24,9 @@
*/
#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.
* 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,
.idProduct = 0x4231,
.bcdDevice = 0x0100,
.bcdDevice = HSM_SDK_VERSION,
.iManufacturer = 0x01,
.iProduct = 0x02,
@@ -69,9 +71,9 @@ uint8_t const * tud_descriptor_device_cb(void)
// 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 ( FIDO_USAGE_U2FHID ),\
HID_USAGE ( FIDO_USAGE_CTAPHID ),\
HID_COLLECTION ( HID_COLLECTION_APPLICATION ),\
/* Report ID if any */\
__VA_ARGS__ \
@@ -93,7 +95,7 @@ uint8_t const * tud_descriptor_device_cb(void)
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
@@ -145,8 +147,8 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
char const* string_desc_arr [] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
"Pol Henarejos", // 1: Manufacturer
"Pico HSM HID", // 2: Product
"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;
if ( index == 0)
{
if (index == 0) {
memcpy(&_desc_str[1], string_desc_arr[0], 2);
chr_count = 1;
}else
{
}
else {
// 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
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];
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 = (uint8_t) strlen(str);
if ( chr_count > 31 ) chr_count = 31;
chr_count = strlen(str);
if ( chr_count > 31 )
chr_count = 31;
// 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];
}
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8 ) | (2*chr_count + 2));
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
return _desc_str;
}

View File

@@ -35,9 +35,14 @@
#include <stdlib.h>
// 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_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) {
uint8_t pkt_max = 64;
@@ -129,6 +134,8 @@ void usb_init() {
driver_init();
}
extern int driver_process_usb_nopacket();
static int usb_event_handle() {
uint16_t rx_read = usb_read_available();
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);
timeout_start();
}
else
driver_process_usb_nopacket();
return 0;
}
static void card_init_core1(void) {
//gpg_data_scan (flash_do_start, flash_do_end);
extern void low_flash_init();
void card_init_core1() {
low_flash_init_core1();
}
void card_thread() {
card_init_core1();
size_t finished_data_size = 0;
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:;
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()
{
void card_start(void (*func)(void)) {
multicore_reset_core1();
multicore_launch_core1(card_thread);
multicore_launch_core1(func);
led_set_blink(BLINK_MOUNTED);
}
@@ -201,10 +180,9 @@ void usb_task() {
// printf("\r\n ------ M = %lu\r\n",m);
if (has_m) {
if (m == EV_EXEC_FINISHED) {
apdu_finish();
size_t size_next = apdu_next();
driver_exec_finished(size_next);
driver_exec_finished(finished_data_size);
led_set_blink(BLINK_MOUNTED);
timeout_stop();
}
else if (m == EV_PRESS_BUTTON) {
uint32_t flag = wait_button() ? EV_BUTTON_TIMEOUT : EV_BUTTON_PRESSED;
@@ -262,7 +240,7 @@ void usb_task() {
}
else {
if (timeout > 0) {
if (timeout + 1500 < board_millis()) {
if (timeout + timeout_counter < board_millis()) {
driver_exec_timeout();
timeout = board_millis();
}

View File

@@ -46,7 +46,7 @@ extern void driver_exec_timeout();
extern bool driver_mounted();
extern uint8_t *driver_prepare_response();
extern void card_start();
extern void card_start(void (*func)(void));
extern void card_exit();
extern void usb_init();
extern uint8_t *usb_prepare_response();
@@ -56,4 +56,8 @@ extern uint8_t *usb_get_rx();
extern uint8_t *usb_get_tx();
extern uint32_t usb_write_offset(uint16_t len, uint16_t offset);
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

1
tinycbor Submodule

Submodule tinycbor added at e27261ed5e