diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7a5ae58..46af1c9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,14 +17,20 @@
cmake_minimum_required(VERSION 3.13)
+if(ENABLE_EMULATION)
+else()
include(pico_sdk_import.cmake)
+endif()
project(pico_fido C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
+if(ENABLE_EMULATION)
+else()
pico_sdk_init()
+endif()
add_executable(pico_fido)
@@ -70,7 +76,7 @@ else()
set(USB_ITF_CCID 0)
endif()
-target_sources(pico_fido PUBLIC
+set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/fido/fido.c
${CMAKE_CURRENT_LIST_DIR}/src/fido/files.c
${CMAKE_CURRENT_LIST_DIR}/src/fido/cmd_register.c
@@ -91,12 +97,12 @@ target_sources(pico_fido PUBLIC
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_large_blobs.c
)
if (${ENABLE_OATH_APP})
-target_sources(pico_fido PUBLIC
+set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/fido/oath.c
)
endif()
if (${ENABLE_OTP_APP})
-target_sources(pico_fido PUBLIC
+set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/fido/otp.c
)
endif()
@@ -104,10 +110,13 @@ endif()
set(USB_ITF_HID 1)
include(pico-hsm-sdk/pico_hsm_sdk_import.cmake)
-target_include_directories(pico_fido PUBLIC
+set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/src/fido
)
+target_sources(pico_fido PUBLIC ${SOURCES})
+target_include_directories(pico_fido PUBLIC ${INCLUDES})
+
target_compile_options(pico_fido PUBLIC
-Wall
-Werror
@@ -119,6 +128,16 @@ if (${COMPILER_COLON} GREATER_EQUAL 0)
)
endif()
-pico_add_extra_outputs(pico_fido)
+if(ENABLE_EMULATION)
+target_compile_options(pico_fido PUBLIC
+ -fdata-sections
+ -ffunction-sections
+ )
+ target_link_options(pico_fido PUBLIC
+ -Wl,-dead_strip
+ )
+else()
+pico_add_extra_outputs(pico_fido)
target_link_libraries(pico_fido PRIVATE pico_hsm_sdk pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc tinyusb_device tinyusb_board)
+endif()
diff --git a/pico-hsm-sdk b/pico-hsm-sdk
index 88b2978..4919eb9 160000
--- a/pico-hsm-sdk
+++ b/pico-hsm-sdk
@@ -1 +1 @@
-Subproject commit 88b2978ae5cf3f1de95ebaec0aec0acd3a24878e
+Subproject commit 4919eb980f22652aeb5ad91fbdeaeb510ffb7ca3
diff --git a/src/fido/cbor.c b/src/fido/cbor.c
index aebc662..717d0cf 100644
--- a/src/fido/cbor.c
+++ b/src/fido/cbor.c
@@ -15,7 +15,10 @@
* along with this program. If not, see .
*/
+#ifndef ENABLE_EMULATION
#include "pico/stdlib.h"
+#endif
+#include "hid/ctap_hid.h"
#include "ctap.h"
#include "fido.h"
#include "usb.h"
@@ -45,7 +48,9 @@ int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) {
if (len == 0)
return CTAP1_ERR_INVALID_LEN;
DEBUG_DATA(data+1,len-1);
+#ifndef ENABLE_EMULATION
driver_prepare_response_hid();
+#endif
if (cmd == CTAPHID_CBOR) {
if (data[0] == CTAP_MAKE_CREDENTIAL)
return cbor_make_credential(data + 1, len - 1);
@@ -74,6 +79,7 @@ int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) {
return CTAP2_ERR_INVALID_CBOR;
}
+#ifndef ENABLE_EMULATION
void cbor_thread() {
card_init_core1();
@@ -90,10 +96,12 @@ void cbor_thread() {
DEBUG_DATA(res_APDU + 1, res_APDU_size);
finished_data_size = res_APDU_size+1;
+
uint32_t flag = EV_EXEC_FINISHED;
queue_add_blocking(&card_to_usb_q, &flag);
}
}
+#endif
int cbor_process(uint8_t last_cmd, const uint8_t *data, size_t len) {
cbor_data = data;
diff --git a/src/fido/cbor_client_pin.c b/src/fido/cbor_client_pin.c
index 5b4dadc..0765e1b 100644
--- a/src/fido/cbor_client_pin.c
+++ b/src/fido/cbor_client_pin.c
@@ -23,7 +23,10 @@
#include "cbor.h"
#include "ctap.h"
#include "ctap2_cbor.h"
+#ifndef ENABLE_EMULATION
#include "bsp/board.h"
+#endif
+#include "hid/ctap_hid.h"
#include "fido.h"
#include "files.h"
#include "random.h"
diff --git a/src/fido/cbor_config.c b/src/fido/cbor_config.c
index 2029748..dff4014 100644
--- a/src/fido/cbor_config.c
+++ b/src/fido/cbor_config.c
@@ -18,6 +18,7 @@
#include "ctap2_cbor.h"
#include "fido.h"
#include "ctap.h"
+#include "hid/ctap_hid.h"
#include "files.h"
#include "apdu.h"
#include "credential.h"
diff --git a/src/fido/cbor_cred_mgmt.c b/src/fido/cbor_cred_mgmt.c
index e43a749..c4994d1 100644
--- a/src/fido/cbor_cred_mgmt.c
+++ b/src/fido/cbor_cred_mgmt.c
@@ -17,6 +17,7 @@
#include "fido.h"
#include "ctap.h"
+#include "hid/ctap_hid.h"
#include "cbor_make_credential.h"
#include "files.h"
#include "apdu.h"
diff --git a/src/fido/cbor_get_assertion.c b/src/fido/cbor_get_assertion.c
index b7b589a..2ed9b14 100644
--- a/src/fido/cbor_get_assertion.c
+++ b/src/fido/cbor_get_assertion.c
@@ -17,7 +17,10 @@
#include "cbor.h"
#include "ctap.h"
+#ifndef ENABLE_EMULATION
#include "bsp/board.h"
+#endif
+#include "hid/ctap_hid.h"
#include "fido.h"
#include "files.h"
#include "crypto_utils.h"
diff --git a/src/fido/cbor_get_info.c b/src/fido/cbor_get_info.c
index 689ddca..15cfcc1 100644
--- a/src/fido/cbor_get_info.c
+++ b/src/fido/cbor_get_info.c
@@ -16,6 +16,7 @@
*/
#include "ctap2_cbor.h"
+#include "hid/ctap_hid.h"
#include "fido.h"
#include "ctap.h"
#include "files.h"
diff --git a/src/fido/cbor_large_blobs.c b/src/fido/cbor_large_blobs.c
index 24b685b..2f7876e 100644
--- a/src/fido/cbor_large_blobs.c
+++ b/src/fido/cbor_large_blobs.c
@@ -18,6 +18,7 @@
#include "ctap2_cbor.h"
#include "fido.h"
#include "ctap.h"
+#include "hid/ctap_hid.h"
#include "files.h"
#include "apdu.h"
#include "hsm.h"
diff --git a/src/fido/cbor_make_credential.c b/src/fido/cbor_make_credential.c
index d2ffa40..80da1f0 100644
--- a/src/fido/cbor_make_credential.c
+++ b/src/fido/cbor_make_credential.c
@@ -17,6 +17,7 @@
#include "cbor_make_credential.h"
#include "ctap2_cbor.h"
+#include "hid/ctap_hid.h"
#include "fido.h"
#include "ctap.h"
#include "files.h"
diff --git a/src/fido/cbor_reset.c b/src/fido/cbor_reset.c
index 586d0a8..47b5486 100644
--- a/src/fido/cbor_reset.c
+++ b/src/fido/cbor_reset.c
@@ -19,17 +19,21 @@
#include "file.h"
#include "fido.h"
#include "ctap.h"
+#ifndef ENABLE_EMULATION
#include "bsp/board.h"
+#endif
extern void scan_all();
int cbor_reset() {
+#ifndef ENABLE_EMULATION
#if defined(ENABLE_POWER_ON_RESET) && ENABLE_POWER_ON_RESET==1
if (board_millis() > 10000)
return CTAP2_ERR_NOT_ALLOWED;
#endif
if (wait_button_pressed() == true)
return CTAP2_ERR_USER_ACTION_TIMEOUT;
+#endif
initialize_flash(true);
init_fido();
return 0;
diff --git a/src/fido/cbor_vendor.c b/src/fido/cbor_vendor.c
index 5039caf..8e65252 100644
--- a/src/fido/cbor_vendor.c
+++ b/src/fido/cbor_vendor.c
@@ -18,6 +18,7 @@
#include "ctap2_cbor.h"
#include "fido.h"
#include "ctap.h"
+#include "hid/ctap_hid.h"
#include "files.h"
#include "apdu.h"
#include "hsm.h"
@@ -241,8 +242,14 @@ int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) {
mbedtls_ecdsa_free(&ekey);
CBOR_ERROR(CTAP2_ERR_PROCESSING);
}
+#ifndef ENABLE_EMULATION
pico_unique_board_id_t rpiid;
pico_get_unique_board_id(&rpiid);
+#else
+ struct {
+ uint8_t id[8];
+ } rpiid = {0};
+#endif
mbedtls_x509write_csr ctx;
mbedtls_x509write_csr_init(&ctx);
snprintf((char *)buffer, sizeof(buffer), "C=ES,O=Pico Keys,OU=Authenticator Attestation,CN=Pico Fido EE Serial %llu", ((uint64_t)rpiid.id[0] << 56) | ((uint64_t)rpiid.id[1] << 48) | ((uint64_t)rpiid.id[2] << 40) | ((uint64_t)rpiid.id[3] << 32) | (rpiid.id[4] << 24) | (rpiid.id[5] << 16) | (rpiid.id[6] << 8) | rpiid.id[7]);
diff --git a/src/fido/cmd_register.c b/src/fido/cmd_register.c
index 432132c..4890135 100644
--- a/src/fido/cmd_register.c
+++ b/src/fido/cmd_register.c
@@ -21,6 +21,7 @@
#include "ctap.h"
#include "random.h"
#include "files.h"
+#include "hid/ctap_hid.h"
const uint8_t *bogus_firefox = (const uint8_t *)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
const uint8_t *bogus_chrome = (const uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
@@ -38,7 +39,11 @@ int cmd_register() {
if (wait_button_pressed() == true)
return SW_CONDITIONS_NOT_SATISFIED();
if (memcmp(req->appId, bogus_firefox, CTAP_APPID_SIZE) == 0 || memcmp(req->appId, bogus_chrome, CTAP_APPID_SIZE) == 0)
+#ifndef ENABLE_EMULATION
return ctap_error(CTAP1_ERR_CHANNEL_BUSY);
+#else
+ return SW_DATA_INVALID();
+#endif
mbedtls_ecdsa_context key;
mbedtls_ecdsa_init(&key);
int ret = derive_key(req->appId, true, resp->keyHandleCertSig, MBEDTLS_ECP_DP_SECP256R1, &key);
diff --git a/src/fido/credential.c b/src/fido/credential.c
index bfe7a30..c6a928b 100644
--- a/src/fido/credential.c
+++ b/src/fido/credential.c
@@ -18,7 +18,10 @@
#include "mbedtls/chachapoly.h"
#include "mbedtls/sha256.h"
#include "credential.h"
+#ifndef ENABLE_EMULATION
#include "bsp/board.h"
+#endif
+#include "hid/ctap_hid.h"
#include "fido.h"
#include "ctap.h"
#include "random.h"
diff --git a/src/fido/ctap.h b/src/fido/ctap.h
index ad012f9..a82c608 100644
--- a/src/fido/ctap.h
+++ b/src/fido/ctap.h
@@ -24,7 +24,9 @@ typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
#else
+#include
#include
+#include
#endif
#ifdef __cplusplus
diff --git a/src/fido/fido.c b/src/fido/fido.c
index c9e42f5..a1295fb 100644
--- a/src/fido/fido.c
+++ b/src/fido/fido.c
@@ -24,8 +24,11 @@
#include "random.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/hkdf.h"
-#ifdef USB_ITF_CCID
-#include "ccid.h"
+#if defined(USB_ITF_CCID) || defined(ENABLE_EMULATION)
+#include "ccid/ccid.h"
+#endif
+#ifndef ENABLE_EMULATION
+#include "bsp/board.h"
#endif
#include
@@ -58,7 +61,7 @@ app_t *fido_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
}
void __attribute__ ((constructor)) fido_ctor() {
-#ifdef USB_ITF_CCID
+#if defined(USB_ITF_CCID) || defined(ENABLE_EMULATION)
ccid_atr = atr_fido;
#endif
register_app(fido_select);
@@ -308,11 +311,13 @@ void init_fido() {
bool wait_button_pressed() {
uint32_t val = EV_PRESS_BUTTON;
+#ifndef ENABLE_EMULATION
#if defined(ENABLE_UP_BUTTON) && ENABLE_UP_BUTTON==1
queue_try_add(&card_to_usb_q, &val);
do {
queue_remove_blocking(&usb_to_card_q, &val);
} while (val != EV_BUTTON_PRESSED && val != EV_BUTTON_TIMEOUT);
+#endif
#endif
return (val == EV_BUTTON_TIMEOUT);
}
diff --git a/src/fido/fido.h b/src/fido/fido.h
index 8230cb9..72f363a 100644
--- a/src/fido/fido.h
+++ b/src/fido/fido.h
@@ -18,10 +18,16 @@
#ifndef _FIDO_H_
#define _FIDO_H_
+#ifndef ENABLE_EMULATION
#include "pico/stdlib.h"
+#endif
#include "common.h"
#include "mbedtls/ecdsa.h"
+#ifndef ENABLE_EMULATION
#include "ctap_hid.h"
+#else
+#include
+#endif
#define CTAP_PUBKEY_LEN (65)
#define KEY_PATH_LEN (32)
@@ -33,7 +39,6 @@ extern int scan_files();
extern int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int, mbedtls_ecdsa_context *key);
extern int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecdsa_context *);
extern bool wait_button_pressed();
-extern CTAPHID_FRAME *ctap_req, *ctap_resp;
extern void init_fido();
extern mbedtls_ecp_group_id fido_curve_to_mbedtls(int curve);
extern int fido_load_key(int curve, const uint8_t *cred_id, mbedtls_ecdsa_context *key);
diff --git a/src/fido/oath.c b/src/fido/oath.c
index 67ea75e..812b3b5 100644
--- a/src/fido/oath.c
+++ b/src/fido/oath.c
@@ -75,12 +75,17 @@ app_t *oath_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
res_APDU[res_APDU_size++] = 0;
res_APDU[res_APDU_size++] = TAG_NAME;
res_APDU[res_APDU_size++] = 8;
+#ifndef ENABLE_EMULATION
pico_get_unique_board_id((pico_unique_board_id_t *)(res_APDU+res_APDU_size)); res_APDU_size += 8;
+#else
+ memset(res_APDU+res_APDU_size,0,8); res_APDU_size += 8;
+#endif
if (file_has_data(search_dynamic_file(EF_OATH_CODE)) == true) {
res_APDU[res_APDU_size++] = TAG_CHALLENGE;
res_APDU[res_APDU_size++] = sizeof(challenge);
memcpy(res_APDU+res_APDU_size, challenge, sizeof(challenge)); res_APDU_size += sizeof(challenge);
}
+ apdu.ne = res_APDU_size;
return a;
}
return NULL;
@@ -248,6 +253,7 @@ int cmd_list() {
}
}
}
+ apdu.ne = res_APDU_size;
return SW_OK();
}
@@ -281,6 +287,7 @@ int cmd_validate() {
res_APDU[res_APDU_size++] = TAG_RESPONSE;
res_APDU[res_APDU_size++] = mbedtls_md_get_size(md_info);
memcpy(res_APDU+res_APDU_size, hmac, mbedtls_md_get_size(md_info)); res_APDU_size += mbedtls_md_get_size(md_info);
+ apdu.ne = res_APDU_size;
return SW_OK();
}
@@ -307,6 +314,7 @@ int calculate_oath(uint8_t truncate, const uint8_t *key, size_t key_len, const u
res_APDU[res_APDU_size++] = key[1];
memcpy(res_APDU+res_APDU_size, hmac, hmac_size); res_APDU_size += hmac_size;
}
+ apdu.ne = res_APDU_size;
return CCID_OK;
}
@@ -357,6 +365,7 @@ int cmd_calculate() {
low_flash_available();
free(tmp);
}
+ apdu.ne = res_APDU_size;
return SW_OK();
}
@@ -399,6 +408,11 @@ int cmd_calculate_all() {
}
}
}
+ apdu.ne = res_APDU_size;
+ return SW_OK();
+}
+
+int cmd_send_remaining() {
return SW_OK();
}
@@ -421,6 +435,7 @@ static const cmd_t cmds[] = {
{ INS_VALIDATE, cmd_validate },
{ INS_CALCULATE, cmd_calculate },
{ INS_CALC_ALL, cmd_calculate_all },
+ { INS_SEND_REMAINING, cmd_send_remaining },
{ 0x00, 0x0}
};
diff --git a/src/fido/otp.c b/src/fido/otp.c
index 1cf6c21..7e41258 100644
--- a/src/fido/otp.c
+++ b/src/fido/otp.c
@@ -36,7 +36,7 @@
#define CONFIG_LED_INV 0x10
#define CONFIG_STATUS_MASK 0x1f
-static uint8_t config_seq[2] = {1};
+static uint8_t config_seq = {1};
typedef struct otp_config {
uint8_t fixed_data[FIXED_SIZE];
@@ -52,13 +52,14 @@ typedef struct otp_config {
} __attribute__((packed)) otp_config_t;
static const size_t otp_config_size = sizeof(otp_config_t);
+uint16_t otp_status();
int otp_process_apdu();
int otp_unload();
const uint8_t otp_aid[] = {
7,
- 0xa0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x01
+ 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01
};
app_t *otp_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
@@ -66,6 +67,12 @@ app_t *otp_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
a->aid = otp_aid;
a->process_apdu = otp_process_apdu;
a->unload = otp_unload;
+ if (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) || file_has_data(search_dynamic_file(EF_OTP_SLOT2)))
+ config_seq = 1;
+ else
+ config_seq = 0;
+ otp_status();
+ apdu.ne = res_APDU_size;
return a;
}
return NULL;
@@ -79,13 +86,13 @@ int otp_unload() {
return CCID_OK;
}
-uint16_t otp_status(uint8_t slot) {
+uint16_t otp_status() {
res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MAJOR;
res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MINOR;
res_APDU[res_APDU_size++] = 0;
- res_APDU[res_APDU_size++] = config_seq[slot];
+ res_APDU[res_APDU_size++] = config_seq;
res_APDU[res_APDU_size++] = 0;
- res_APDU[res_APDU_size++] = (CONFIG2_TOUCH | CONFIG1_TOUCH) | (config_seq[0] > 0 ? CONFIG1_VALID : 0x00) | (config_seq[1] > 0 ? CONFIG2_VALID : 0x00);
+ res_APDU[res_APDU_size++] = (CONFIG2_TOUCH | CONFIG1_TOUCH) | (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) ? CONFIG1_VALID : 0x00) | (file_has_data(search_dynamic_file(EF_OTP_SLOT2)) ? CONFIG2_VALID : 0x00);
return SW_OK();
}
@@ -99,7 +106,6 @@ int cmd_otp() {
return SW_WRONG_LENGTH();
if (apdu.data[48] != 0 || apdu.data[49] != 0)
return SW_WRONG_DATA();
- uint8_t slot = p1 == 0x01 ? 0 : 1;
file_t *ef = file_new(p1 == 0x01 ? EF_OTP_SLOT1 : EF_OTP_SLOT2);
if (file_has_data(ef)) {
otp_config_t *otpc = (otp_config_t *)file_get_data(ef);
@@ -110,14 +116,21 @@ int cmd_otp() {
if (apdu.data[c] != 0) {
flash_write_data_to_file(ef, apdu.data, otp_config_size);
low_flash_available();
- config_seq[slot]++;
- return otp_status(slot);
+ config_seq++;
+ return otp_status();
}
}
// Delete slot
delete_file(ef);
- config_seq[slot] = 0;
- return otp_status(slot);
+ if (!file_has_data(search_dynamic_file(EF_OTP_SLOT1)) && !file_has_data(search_dynamic_file(EF_OTP_SLOT2)))
+ config_seq = 0;
+ return otp_status();
+ }
+ else if (p1 == 0x10) {
+#ifndef ENABLE_EMULATION
+ pico_get_unique_board_id_string((char *)res_APDU, 4);
+#endif
+ res_APDU_size = 4;
}
return SW_OK();
}