1 Commits
v5.8 ... v5.6

Author SHA1 Message Date
Pol Henarejos
900e7f2eb2 Merge branch 'development' 2023-09-18 09:00:39 +02:00
26 changed files with 91 additions and 321 deletions

6
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "pico-keys-sdk"] [submodule "pico-hsm-sdk"]
path = pico-keys-sdk path = pico-hsm-sdk
url = https://github.com/polhenarejos/pico-keys-sdk url = ../pico-hsm-sdk

View File

@@ -109,7 +109,7 @@ set(SOURCES ${SOURCES}
endif() endif()
set(USB_ITF_HID 1) set(USB_ITF_HID 1)
include(pico-keys-sdk/pico_keys_sdk_import.cmake) include(pico-hsm-sdk/pico_hsm_sdk_import.cmake)
set(INCLUDES ${INCLUDES} set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/src/fido ${CMAKE_CURRENT_LIST_DIR}/src/fido
@@ -147,5 +147,5 @@ target_compile_options(pico_fido PUBLIC
endif (APPLE) endif (APPLE)
else() else()
pico_add_extra_outputs(pico_fido) pico_add_extra_outputs(pico_fido)
target_link_libraries(pico_fido PRIVATE pico_keys_sdk pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc tinyusb_device tinyusb_board) 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() endif()

View File

@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
VERSION_MAJOR="5" VERSION_MAJOR="5"
VERSION_MINOR="8" VERSION_MINOR="6"
rm -rf release/* rm -rf release/*
cd build_release cd build_release

View File

@@ -87,7 +87,7 @@ fi
LITTLE_VID="\x${VID:2:2}\x${VID:0:2}" LITTLE_VID="\x${VID:2:2}\x${VID:0:2}"
LITTLE_PID="\x${PID:2:2}\x${PID:0:2}" LITTLE_PID="\x${PID:2:2}\x${PID:0:2}"
perl -pi -e "s/[\x00-\xff]{4}\x$VERSION_MINOR\x$VERSION_MAJOR\x01\x02\x03\x01\x00\x00/$LITTLE_VID$LITTLE_PID\x$VERSION_MINOR\x$VERSION_MAJOR\x01\x02\x03\x01\x00\x00/" $UF2_FILE_OF perl -pi -e "s/\xfe\xca\x31\x42\x$VERSION_MINOR\x$VERSION_MAJOR\x01\x02\x03\x01/$LITTLE_VID$LITTLE_PID\x$VERSION_MINOR\x$VERSION_MAJOR\x01\x02\x03\x01/" $UF2_FILE_OF
echo "Done!" echo "Done!"
echo "" echo ""

1
pico-hsm-sdk Submodule

Submodule pico-hsm-sdk added at a36a89cc95

Submodule pico-keys-sdk deleted from f0687c1ef3

View File

@@ -25,7 +25,6 @@
#include "apdu.h" #include "apdu.h"
#include "management.h" #include "management.h"
#include "ctap2_cbor.h" #include "ctap2_cbor.h"
#include "version.h"
const bool _btrue = true, _bfalse = false; const bool _btrue = true, _bfalse = false;
@@ -41,8 +40,6 @@ int cbor_config(const uint8_t *data, size_t len);
int cbor_vendor(const uint8_t *data, size_t len); int cbor_vendor(const uint8_t *data, size_t len);
int cbor_large_blobs(const uint8_t *data, size_t len); int cbor_large_blobs(const uint8_t *data, size_t len);
extern int cmd_read_config();
const uint8_t aaguid[16] = const uint8_t aaguid[16] =
{ 0x89, 0xFB, 0x94, 0xB7, 0x06, 0xC9, 0x36, 0x73, 0x9B, 0x7E, 0x30, 0x52, 0x6D, 0x96, 0x81, 0x45 }; // First 16 bytes of SHA256("Pico FIDO2") { 0x89, 0xFB, 0x94, 0xB7, 0x06, 0xC9, 0x36, 0x73, 0x9B, 0x7E, 0x30, 0x52, 0x6D, 0x96, 0x81, 0x45 }; // First 16 bytes of SHA256("Pico FIDO2")
@@ -94,12 +91,6 @@ int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) {
else if (cmd == CTAP_VENDOR_CBOR) { else if (cmd == CTAP_VENDOR_CBOR) {
return cbor_vendor(data, len); return cbor_vendor(data, len);
} }
else if (cmd == 0xC2) {
if (cmd_read_config() == 0x9000) {
res_APDU_size -= 1;
return 0;
}
}
} }
return CTAP1_ERR_INVALID_CMD; return CTAP1_ERR_INVALID_CMD;
} }

View File

@@ -31,7 +31,7 @@
#include "files.h" #include "files.h"
#include "random.h" #include "random.h"
#include "crypto_utils.h" #include "crypto_utils.h"
#include "pico_keys.h" #include "hsm.h"
#include "apdu.h" #include "apdu.h"
uint32_t usage_timer = 0, initial_usage_time_limit = 0; uint32_t usage_timer = 0, initial_usage_time_limit = 0;
@@ -181,12 +181,12 @@ int resetPinUvAuthToken() {
int encrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, size_t in_len, uint8_t *out) { int encrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, size_t in_len, uint8_t *out) {
if (protocol == 1) { if (protocol == 1) {
memcpy(out, in, in_len); memcpy(out, in, in_len);
return aes_encrypt(key, NULL, 32 * 8, PICO_KEYS_AES_MODE_CBC, out, in_len); return aes_encrypt(key, NULL, 32 * 8, HSM_AES_MODE_CBC, out, in_len);
} }
else if (protocol == 2) { else if (protocol == 2) {
random_gen(NULL, out, IV_SIZE); random_gen(NULL, out, IV_SIZE);
memcpy(out + IV_SIZE, in, in_len); memcpy(out + IV_SIZE, in, in_len);
return aes_encrypt(key + 32, out, 32 * 8, PICO_KEYS_AES_MODE_CBC, out + IV_SIZE, in_len); return aes_encrypt(key + 32, out, 32 * 8, HSM_AES_MODE_CBC, out + IV_SIZE, in_len);
} }
return -1; return -1;
@@ -195,11 +195,11 @@ int encrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, size_t in_l
int decrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, size_t in_len, uint8_t *out) { int decrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, size_t in_len, uint8_t *out) {
if (protocol == 1) { if (protocol == 1) {
memcpy(out, in, in_len); memcpy(out, in, in_len);
return aes_decrypt(key, NULL, 32 * 8, PICO_KEYS_AES_MODE_CBC, out, in_len); return aes_decrypt(key, NULL, 32 * 8, HSM_AES_MODE_CBC, out, in_len);
} }
else if (protocol == 2) { else if (protocol == 2) {
memcpy(out, in + IV_SIZE, in_len); memcpy(out, in + IV_SIZE, in_len);
return aes_decrypt(key + 32, in, 32 * 8, PICO_KEYS_AES_MODE_CBC, out, in_len - IV_SIZE); return aes_decrypt(key + 32, in, 32 * 8, HSM_AES_MODE_CBC, out, in_len - IV_SIZE);
} }
return -1; return -1;

View File

@@ -22,7 +22,7 @@
#include "files.h" #include "files.h"
#include "apdu.h" #include "apdu.h"
#include "credential.h" #include "credential.h"
#include "pico_keys.h" #include "hsm.h"
#include "random.h" #include "random.h"
#include "mbedtls/ecdh.h" #include "mbedtls/ecdh.h"
#include "mbedtls/chachapoly.h" #include "mbedtls/chachapoly.h"
@@ -64,7 +64,7 @@ int cbor_config(const uint8_t *data, size_t len) {
raw_subpara = (uint8_t *) cbor_value_get_next_byte(&_f1); raw_subpara = (uint8_t *) cbor_value_get_next_byte(&_f1);
CBOR_PARSE_MAP_START(_f1, 2) CBOR_PARSE_MAP_START(_f1, 2)
{ {
if (subcommand == 0x7f) { if (subcommand == 0xff) {
CBOR_FIELD_GET_UINT(subpara, 2); CBOR_FIELD_GET_UINT(subpara, 2);
if (subpara == 0x01) { if (subpara == 0x01) {
CBOR_FIELD_GET_UINT(vendorCommandId, 2); CBOR_FIELD_GET_UINT(vendorCommandId, 2);
@@ -134,7 +134,7 @@ int cbor_config(const uint8_t *data, size_t len) {
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
} }
if (subcommand == 0x7f) { if (subcommand == 0xff) {
if (vendorCommandId == CTAP_CONFIG_AUT_DISABLE) { if (vendorCommandId == CTAP_CONFIG_AUT_DISABLE) {
if (!file_has_data(ef_keydev_enc)) { if (!file_has_data(ef_keydev_enc)) {
CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED); CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED);

View File

@@ -22,7 +22,7 @@
#include "files.h" #include "files.h"
#include "apdu.h" #include "apdu.h"
#include "credential.h" #include "credential.h"
#include "pico_keys.h" #include "hsm.h"
uint8_t rp_counter = 1; uint8_t rp_counter = 1;
uint8_t rp_total = 0; uint8_t rp_total = 0;

View File

@@ -24,7 +24,7 @@
#include "fido.h" #include "fido.h"
#include "files.h" #include "files.h"
#include "crypto_utils.h" #include "crypto_utils.h"
#include "pico_keys.h" #include "hsm.h"
#include "apdu.h" #include "apdu.h"
#include "cbor_make_credential.h" #include "cbor_make_credential.h"
#include "credential.h" #include "credential.h"

View File

@@ -21,7 +21,7 @@
#include "hid/ctap_hid.h" #include "hid/ctap_hid.h"
#include "files.h" #include "files.h"
#include "apdu.h" #include "apdu.h"
#include "pico_keys.h" #include "hsm.h"
#include "mbedtls/sha256.h" #include "mbedtls/sha256.h"
static uint64_t expectedLength = 0, expectedNextOffset = 0; static uint64_t expectedLength = 0, expectedNextOffset = 0;

View File

@@ -25,7 +25,7 @@
#include "credential.h" #include "credential.h"
#include "mbedtls/sha256.h" #include "mbedtls/sha256.h"
#include "random.h" #include "random.h"
#include "pico_keys.h" #include "hsm.h"
int cbor_make_credential(const uint8_t *data, size_t len) { int cbor_make_credential(const uint8_t *data, size_t len) {
CborParser parser; CborParser parser;

View File

@@ -21,7 +21,7 @@
#include "hid/ctap_hid.h" #include "hid/ctap_hid.h"
#include "files.h" #include "files.h"
#include "apdu.h" #include "apdu.h"
#include "pico_keys.h" #include "hsm.h"
#include "random.h" #include "random.h"
#include "mbedtls/ecdh.h" #include "mbedtls/ecdh.h"
#include "mbedtls/chachapoly.h" #include "mbedtls/chachapoly.h"

View File

@@ -16,7 +16,7 @@
*/ */
#include "fido.h" #include "fido.h"
#include "pico_keys.h" #include "hsm.h"
#include "apdu.h" #include "apdu.h"
#include "ctap.h" #include "ctap.h"
#include "random.h" #include "random.h"

View File

@@ -16,7 +16,7 @@
*/ */
#include "fido.h" #include "fido.h"
#include "pico_keys.h" #include "hsm.h"
#include "apdu.h" #include "apdu.h"
#include "ctap.h" #include "ctap.h"
#include "random.h" #include "random.h"
@@ -32,17 +32,18 @@ const uint8_t u2f_aid[] = {
int u2f_unload(); int u2f_unload();
int u2f_process_apdu(); int u2f_process_apdu();
int u2f_select(app_t *a) { app_t *u2f_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
if (cap_supported(CAP_U2F)) { if (!memcmp(aid, u2f_aid + 1, MIN(aid_len, u2f_aid[0])) && cap_supported(CAP_U2F)) {
a->aid = u2f_aid;
a->process_apdu = u2f_process_apdu; a->process_apdu = u2f_process_apdu;
a->unload = u2f_unload; a->unload = u2f_unload;
return CCID_OK; return a;
} }
return CCID_ERR_FILE_NOT_FOUND; return NULL;
} }
void __attribute__((constructor)) u2f_ctor() { void __attribute__((constructor)) u2f_ctor() {
register_app(u2f_select, u2f_aid); register_app(u2f_select);
} }
int u2f_unload() { int u2f_unload() {

View File

@@ -16,7 +16,7 @@
*/ */
#include "apdu.h" #include "apdu.h"
#include "pico_keys.h" #include "hsm.h"
int cmd_version() { int cmd_version() {
memcpy(res_APDU, "U2F_V2", strlen("U2F_V2")); memcpy(res_APDU, "U2F_V2", strlen("U2F_V2"));

View File

@@ -26,7 +26,7 @@
#include "ctap.h" #include "ctap.h"
#include "random.h" #include "random.h"
#include "files.h" #include "files.h"
#include "pico_keys.h" #include "hsm.h"
int credential_derive_chacha_key(uint8_t *outk); int credential_derive_chacha_key(uint8_t *outk);

View File

@@ -16,7 +16,7 @@
*/ */
#include "fido.h" #include "fido.h"
#include "pico_keys.h" #include "hsm.h"
#include "apdu.h" #include "apdu.h"
#include "ctap.h" #include "ctap.h"
#include "files.h" #include "files.h"
@@ -33,7 +33,6 @@
#include <math.h> #include <math.h>
#include "management.h" #include "management.h"
#include "ctap_hid.h" #include "ctap_hid.h"
#include "version.h"
int fido_process_apdu(); int fido_process_apdu();
int fido_unload(); int fido_unload();
@@ -43,7 +42,7 @@ pinUvAuthToken_t paut = { 0 };
uint8_t keydev_dec[32]; uint8_t keydev_dec[32];
bool has_keydev_dec = false; bool has_keydev_dec = false;
const uint8_t _fido_aid[] = { const uint8_t fido_aid[] = {
8, 8,
0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01 0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01
}; };
@@ -54,44 +53,21 @@ const uint8_t atr_fido[] = {
0x75, 0x62, 0x69, 0x4b, 0x65, 0x79, 0x40 0x75, 0x62, 0x69, 0x4b, 0x65, 0x79, 0x40
}; };
uint8_t fido_get_version_major() { app_t *fido_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
return PICO_FIDO_VERSION_MAJOR; if (!memcmp(aid, fido_aid + 1, MIN(aid_len, fido_aid[0])) && cap_supported(CAP_FIDO2)) {
} a->aid = fido_aid;
uint8_t fido_get_version_minor() {
return PICO_FIDO_VERSION_MINOR;
}
int fido_select(app_t *a) {
if (cap_supported(CAP_FIDO2)) {
a->process_apdu = fido_process_apdu; a->process_apdu = fido_process_apdu;
a->unload = fido_unload; a->unload = fido_unload;
return CCID_OK; return a;
} }
return CCID_ERR_FILE_NOT_FOUND; return NULL;
} }
extern uint8_t (*get_version_major)();
extern uint8_t (*get_version_minor)();
extern const uint8_t *fido_aid;
extern void (*init_fido_cb)();
extern void (*cbor_thread_func)();
extern int (*cbor_process_cb)(uint8_t, const uint8_t *, size_t);
extern void cbor_thread();
extern int cbor_process(uint8_t last_cmd, const uint8_t *data, size_t len);
void __attribute__((constructor)) fido_ctor() { void __attribute__((constructor)) fido_ctor() {
#if defined(USB_ITF_CCID) || defined(ENABLE_EMULATION) #if defined(USB_ITF_CCID) || defined(ENABLE_EMULATION)
ccid_atr = atr_fido; ccid_atr = atr_fido;
#endif #endif
get_version_major = fido_get_version_major; register_app(fido_select);
get_version_minor = fido_get_version_minor;
fido_aid = _fido_aid;
init_fido_cb = init_fido;
#ifndef ENABLE_EMULATION
cbor_thread_func = cbor_thread;
#endif
cbor_process_cb = cbor_process;
register_app(fido_select, fido_aid);
} }
int fido_unload() { int fido_unload() {
@@ -398,10 +374,8 @@ void scan_all() {
scan_files(); scan_files();
} }
extern void init_otp();
void init_fido() { void init_fido() {
scan_all(); scan_all();
init_otp();
} }
bool wait_button_pressed() { bool wait_button_pressed() {

View File

@@ -16,7 +16,7 @@
*/ */
#include "fido.h" #include "fido.h"
#include "pico_keys.h" #include "hsm.h"
#include "apdu.h" #include "apdu.h"
#include "version.h" #include "version.h"
#include "files.h" #include "files.h"
@@ -31,20 +31,22 @@ const uint8_t man_aid[] = {
0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17 0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
}; };
extern void scan_all(); extern void scan_all();
extern void init_otp(); app_t *man_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
int man_select(app_t *a) { if (!memcmp(aid, man_aid + 1, MIN(aid_len, man_aid[0]))) {
a->process_apdu = man_process_apdu; a->aid = man_aid;
a->unload = man_unload; a->process_apdu = man_process_apdu;
sprintf((char *) res_APDU, "%d.%d.0", PICO_FIDO_VERSION_MAJOR, PICO_FIDO_VERSION_MINOR); a->unload = man_unload;
res_APDU_size = strlen((char *) res_APDU); sprintf((char *) res_APDU, "%d.%d.0", PICO_FIDO_VERSION_MAJOR, PICO_FIDO_VERSION_MINOR);
apdu.ne = res_APDU_size; res_APDU_size = strlen((char *) res_APDU);
scan_all(); apdu.ne = res_APDU_size;
init_otp(); scan_all();
return CCID_OK; return a;
}
return NULL;
} }
void __attribute__((constructor)) man_ctor() { void __attribute__((constructor)) man_ctor() {
register_app(man_select, man_aid); register_app(man_select);
} }
int man_unload() { int man_unload() {

View File

@@ -16,7 +16,7 @@
*/ */
#include "fido.h" #include "fido.h"
#include "pico_keys.h" #include "hsm.h"
#include "apdu.h" #include "apdu.h"
#include "files.h" #include "files.h"
#include "random.h" #include "random.h"
@@ -68,8 +68,9 @@ const uint8_t oath_aid[] = {
0xa0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x01 0xa0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x01
}; };
int oath_select(app_t *a) { app_t *oath_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
if (cap_supported(CAP_OATH)) { if (!memcmp(aid, oath_aid + 1, MIN(aid_len, oath_aid[0])) && cap_supported(CAP_OATH)) {
a->aid = oath_aid;
a->process_apdu = oath_process_apdu; a->process_apdu = oath_process_apdu;
a->unload = oath_unload; a->unload = oath_unload;
res_APDU_size = 0; res_APDU_size = 0;
@@ -81,10 +82,10 @@ int oath_select(app_t *a) {
res_APDU[res_APDU_size++] = TAG_NAME; res_APDU[res_APDU_size++] = TAG_NAME;
res_APDU[res_APDU_size++] = 8; res_APDU[res_APDU_size++] = 8;
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
pico_get_unique_board_id((pico_unique_board_id_t *) (res_APDU + res_APDU_size)); pico_get_unique_board_id((pico_unique_board_id_t *) (res_APDU + res_APDU_size));
res_APDU_size += 8; res_APDU_size += 8;
#else #else
memset(res_APDU + res_APDU_size, 0, 8); res_APDU_size += 8; memset(res_APDU + res_APDU_size, 0, 8); res_APDU_size += 8;
#endif #endif
if (file_has_data(search_dynamic_file(EF_OATH_CODE)) == true) { if (file_has_data(search_dynamic_file(EF_OATH_CODE)) == true) {
random_gen(NULL, challenge, sizeof(challenge)); random_gen(NULL, challenge, sizeof(challenge));
@@ -104,13 +105,13 @@ int oath_select(app_t *a) {
res_APDU[res_APDU_size++] = 1; res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = ALG_HMAC_SHA1; res_APDU[res_APDU_size++] = ALG_HMAC_SHA1;
apdu.ne = res_APDU_size; apdu.ne = res_APDU_size;
return CCID_OK; return a;
} }
return CCID_ERR_FILE_NOT_FOUND; return NULL;
} }
void __attribute__((constructor)) oath_ctor() { void __attribute__((constructor)) oath_ctor() {
register_app(oath_select, oath_aid); register_app(oath_select);
} }
int oath_unload() { int oath_unload() {
@@ -454,7 +455,6 @@ int cmd_calculate_all() {
if (asn1_find_tag(apdu.data, apdu.nc, TAG_CHALLENGE, &chal_len, &chal) == false) { if (asn1_find_tag(apdu.data, apdu.nc, TAG_CHALLENGE, &chal_len, &chal) == false) {
return SW_INCORRECT_PARAMS(); return SW_INCORRECT_PARAMS();
} }
res_APDU_size = 0;
for (int i = 0; i < MAX_OATH_CRED; i++) { for (int i = 0; i < MAX_OATH_CRED; i++) {
file_t *ef = search_dynamic_file(EF_OATH_CRED + i); file_t *ef = search_dynamic_file(EF_OATH_CRED + i);
if (file_has_data(ef)) { if (file_has_data(ef)) {

View File

@@ -16,7 +16,7 @@
*/ */
#include "fido.h" #include "fido.h"
#include "pico_keys.h" #include "hsm.h"
#include "apdu.h" #include "apdu.h"
#include "files.h" #include "files.h"
#include "random.h" #include "random.h"
@@ -111,20 +111,14 @@ uint16_t otp_status();
int otp_process_apdu(); int otp_process_apdu();
int otp_unload(); int otp_unload();
#ifndef ENABLE_EMULATION
extern int (*hid_set_report_cb)(uint8_t, uint8_t, hid_report_type_t, uint8_t const *, uint16_t);
extern uint16_t (*hid_get_report_cb)(uint8_t, uint8_t, hid_report_type_t, uint8_t *, uint16_t);
int otp_hid_set_report_cb(uint8_t, uint8_t, hid_report_type_t, uint8_t const *, uint16_t);
uint16_t otp_hid_get_report_cb(uint8_t, uint8_t, hid_report_type_t, uint8_t *, uint16_t);
#endif
const uint8_t otp_aid[] = { const uint8_t otp_aid[] = {
7, 7,
0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01 0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01
}; };
int otp_select(app_t *a) { app_t *otp_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
if (cap_supported(CAP_OTP)) { if (!memcmp(aid, otp_aid + 1, MIN(aid_len, otp_aid[0])) && cap_supported(CAP_OTP)) {
a->aid = otp_aid;
a->process_apdu = otp_process_apdu; a->process_apdu = otp_process_apdu;
a->unload = otp_unload; a->unload = otp_unload;
if (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) || if (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) ||
@@ -138,9 +132,9 @@ int otp_select(app_t *a) {
memmove(res_APDU, res_APDU + 1, 6); memmove(res_APDU, res_APDU + 1, 6);
res_APDU_size = 6; res_APDU_size = 6;
apdu.ne = res_APDU_size; apdu.ne = res_APDU_size;
return CCID_OK; return a;
} }
return CCID_ERR_FILE_NOT_FOUND; return NULL;
} }
uint8_t modhex_tab[] = uint8_t modhex_tab[] =
@@ -182,22 +176,6 @@ extern int calculate_oath(uint8_t truncate,
size_t key_len, size_t key_len,
const uint8_t *chal, const uint8_t *chal,
size_t chal_len); size_t chal_len);
uint16_t calculate_crc(const uint8_t *data, size_t data_len) {
uint16_t crc = 0xFFFF;
for (size_t idx = 0; idx < data_len; idx++) {
crc ^= data[idx];
for (uint8_t i = 0; i < 8; i++) {
uint16_t j = crc & 0x1;
crc >>= 1;
if (j == 1) {
crc ^= 0x8408;
}
}
}
return crc & 0xFFFF;
}
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
static uint8_t session_counter[2] = { 0 }; static uint8_t session_counter[2] = { 0 };
#endif #endif
@@ -266,11 +244,10 @@ int otp_button_pressed(uint8_t slot) {
} }
} }
else if (otp_config->cfg_flags & SHORT_TICKET || otp_config->cfg_flags & STATIC_TICKET) { else if (otp_config->cfg_flags & SHORT_TICKET || otp_config->cfg_flags & STATIC_TICKET) {
uint8_t fixed_size = FIXED_SIZE + UID_SIZE + KEY_SIZE; if (otp_config->cfg_flags & SHORT_TICKET) {
if (otp_config->cfg_flags & SHORT_TICKET) { // Not clear which is the purpose of SHORT_TICKET otp_config->fixed_size /= 2;
//fixed_size /= 2;
} }
add_keyboard_buffer(otp_config->fixed_data, fixed_size, false); add_keyboard_buffer(otp_config->fixed_data, otp_config->fixed_size, false);
if (otp_config->tkt_flags & APPEND_CR) { if (otp_config->tkt_flags & APPEND_CR) {
append_keyboard_buffer((const uint8_t *) "\x28", 1); append_keyboard_buffer((const uint8_t *) "\x28", 1);
} }
@@ -331,12 +308,8 @@ int otp_button_pressed(uint8_t slot) {
} }
void __attribute__((constructor)) otp_ctor() { void __attribute__((constructor)) otp_ctor() {
register_app(otp_select, otp_aid); register_app(otp_select);
button_pressed_cb = otp_button_pressed; button_pressed_cb = otp_button_pressed;
#ifndef ENABLE_EMULATION
hid_set_report_cb = otp_hid_set_report_cb;
hid_get_report_cb = otp_hid_get_report_cb;
#endif
} }
int otp_unload() { int otp_unload() {
@@ -516,110 +489,3 @@ int otp_process_apdu() {
} }
return SW_INS_NOT_SUPPORTED(); return SW_INS_NOT_SUPPORTED();
} }
#ifndef ENABLE_EMULATION
uint8_t otp_frame_rx[70] = {0};
uint8_t otp_frame_tx[70] = {0};
uint8_t otp_exp_seq = 0, otp_curr_seq = 0;
uint8_t otp_header[4] = {0};
extern uint16_t *get_send_buffer_size(uint8_t itf);
int otp_send_frame(uint8_t *frame, size_t frame_len) {
uint16_t crc = calculate_crc(frame, frame_len);
frame[frame_len] = ~crc & 0xff;
frame[frame_len + 1] = ~crc >> 8;
frame_len += 2;
*get_send_buffer_size(ITF_KEYBOARD) = frame_len;
otp_exp_seq = (frame_len / 7);
if (frame_len % 7) {
otp_exp_seq++;
}
otp_curr_seq = 0;
return 0;
}
int otp_hid_set_report_cb(uint8_t itf,
uint8_t report_id,
hid_report_type_t report_type,
uint8_t const *buffer,
uint16_t bufsize)
{
if (report_type == 3) {
DEBUG_PAYLOAD(buffer, bufsize);
if (itf == ITF_KEYBOARD && buffer[7] == 0xFF) { // reset
*get_send_buffer_size(ITF_KEYBOARD) = 0;
otp_curr_seq = otp_exp_seq = 0;
memset(otp_frame_tx, 0, sizeof(otp_frame_tx));
}
else if (buffer[7] & 0x80) { // a frame
uint8_t rseq = buffer[7] & 0x1F;
if (rseq < 10) {
if (rseq == 0) {
memset(otp_frame_rx, 0, sizeof(otp_frame_rx));
}
memcpy(otp_frame_rx + rseq * 7, buffer, 7);
if (rseq == 9) {
DEBUG_DATA(otp_frame_rx, sizeof(otp_frame_rx));
uint16_t residual_crc = calculate_crc(otp_frame_rx, 64), rcrc = (otp_frame_rx[66] << 8 | otp_frame_rx[65]);
uint8_t slot_id = otp_frame_rx[64];
if (residual_crc == rcrc) {
apdu.data = otp_frame_rx;
apdu.nc = 64;
apdu.rdata = otp_frame_tx;
apdu.header[0] = 0;
apdu.header[1] = 0x01;
apdu.header[2] = slot_id;
apdu.header[3] = 0;
int ret = otp_process_apdu();
if (ret == 0x9000 && res_APDU_size > 0) {
otp_send_frame(apdu.rdata, apdu.rlen);
}
}
else {
printf("[OTP] Bad CRC!\n");
}
}
}
}
return 1;
}
return 0;
}
uint16_t otp_hid_get_report_cb(uint8_t itf,
uint8_t report_id,
hid_report_type_t report_type,
uint8_t *buffer,
uint16_t reqlen) {
// TODO not Implemented
(void) itf;
(void) report_id;
(void) report_type;
(void) buffer;
(void) reqlen;
uint16_t send_buffer_size = *get_send_buffer_size(ITF_KEYBOARD);
if (send_buffer_size > 0) {
uint8_t seq = otp_curr_seq++;
memset(buffer, 0, 8);
memcpy(buffer, otp_frame_tx + 7 * seq, MIN(7, send_buffer_size));
buffer[7] = 0x40 | seq;
DEBUG_DATA(buffer, 8);
*get_send_buffer_size(ITF_KEYBOARD) -= MIN(7, send_buffer_size);
}
else if (otp_curr_seq == otp_exp_seq && otp_exp_seq > 0) {
memset(buffer, 0, 7);
buffer[7] = 0x40;
DEBUG_DATA(buffer,8);
otp_curr_seq = otp_exp_seq = 0;
}
else {
otp_status();
memcpy(buffer, res_APDU, 7);
}
return reqlen;
}
#endif

View File

@@ -18,7 +18,7 @@
#ifndef __VERSION_H_ #ifndef __VERSION_H_
#define __VERSION_H_ #define __VERSION_H_
#define PICO_FIDO_VERSION 0x0508 #define PICO_FIDO_VERSION 0x0506
#define PICO_FIDO_VERSION_MAJOR ((PICO_FIDO_VERSION >> 8) & 0xff) #define PICO_FIDO_VERSION_MAJOR ((PICO_FIDO_VERSION >> 8) & 0xff)
#define PICO_FIDO_VERSION_MINOR (PICO_FIDO_VERSION & 0xff) #define PICO_FIDO_VERSION_MINOR (PICO_FIDO_VERSION & 0xff)

View File

@@ -23,6 +23,7 @@ import sys
import argparse import argparse
import platform import platform
from binascii import hexlify from binascii import hexlify
from words import words
from threading import Event from threading import Event
from typing import Mapping, Any, Optional, Callable from typing import Mapping, Any, Optional, Callable
import struct import struct
@@ -32,7 +33,7 @@ from enum import IntEnum, unique
try: try:
from fido2.ctap2.config import Config from fido2.ctap2.config import Config
from fido2.ctap2 import Ctap2, ClientPin, PinProtocolV2 from fido2.ctap2 import Ctap2
from fido2.hid import CtapHidDevice, CTAPHID from fido2.hid import CtapHidDevice, CTAPHID
from fido2.utils import bytes2int, int2bytes from fido2.utils import bytes2int, int2bytes
from fido2 import cbor from fido2 import cbor
@@ -57,6 +58,14 @@ except:
from enum import IntEnum from enum import IntEnum
from binascii import hexlify from binascii import hexlify
if (platform.system() == 'Windows' or platform.system() == 'Linux'):
from secure_key import windows as skey
elif (platform.system() == 'Darwin'):
from secure_key import macos as skey
else:
print('ERROR: platform not supported')
sys.exit(-1)
def get_pki_data(url, data=None, method='GET'): def get_pki_data(url, data=None, method='GET'):
user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; ' user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; '
'rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7' 'rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7'
@@ -81,7 +90,6 @@ class VendorConfig(Config):
class CMD(IntEnum): class CMD(IntEnum):
CONFIG_AUT_ENABLE = 0x03e43f56b34285e2 CONFIG_AUT_ENABLE = 0x03e43f56b34285e2
CONFIG_AUT_DISABLE = 0x1831a40f04a25ed9 CONFIG_AUT_DISABLE = 0x1831a40f04a25ed9
CONFIG_VENDOR_PROTOTYPE = 0x7f
class RESP(IntEnum): class RESP(IntEnum):
KEY_AGREEMENT = 0x01 KEY_AGREEMENT = 0x01
@@ -91,7 +99,7 @@ class VendorConfig(Config):
def enable_device_aut(self, ct): def enable_device_aut(self, ct):
self._call( self._call(
VendorConfig.CMD.CONFIG_VENDOR_PROTOTYPE, Config.CMD.VENDOR_PROTOTYPE,
{ {
VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_AUT_ENABLE, VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_AUT_ENABLE,
VendorConfig.PARAM.VENDOR_AUT_CT: ct VendorConfig.PARAM.VENDOR_AUT_CT: ct
@@ -100,7 +108,7 @@ class VendorConfig(Config):
def disable_device_aut(self): def disable_device_aut(self):
self._call( self._call(
VendorConfig.CMD.CONFIG_VENDOR_PROTOTYPE, Config.CMD.VENDOR_PROTOTYPE,
{ {
VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_AUT_DISABLE VendorConfig.PARAM.VENDOR_COMMAND_ID: VendorConfig.CMD.CONFIG_AUT_DISABLE
}, },
@@ -222,7 +230,7 @@ class Vendor:
self.__key_enc = None self.__key_enc = None
self.__iv = None self.__iv = None
self.vcfg = VendorConfig(ctap, pin_uv_protocol=pin_uv_protocol, pin_uv_token=pin_uv_token) self.vcfg = VendorConfig(ctap)
def _call(self, cmd, sub_cmd, params=None): def _call(self, cmd, sub_cmd, params=None):
if params: if params:
@@ -244,14 +252,6 @@ class Vendor:
return self.ctap.vendor(cmd, sub_cmd, params, pin_uv_protocol, pin_uv_param) return self.ctap.vendor(cmd, sub_cmd, params, pin_uv_protocol, pin_uv_param)
def backup_save(self, filename): def backup_save(self, filename):
if (platform.system() == 'Windows' or platform.system() == 'Linux'):
from secure_key import windows as skey
elif (platform.system() == 'Darwin'):
from secure_key import macos as skey
else:
print('ERROR: platform not supported')
sys.exit(-1)
from words import words
ret = self._call( ret = self._call(
Vendor.CMD.VENDOR_BACKUP, Vendor.CMD.VENDOR_BACKUP,
Vendor.SUBCMD.ENABLE, Vendor.SUBCMD.ENABLE,
@@ -270,14 +270,6 @@ class Vendor:
print(f'{(c+1):02d} - {words[coef]}') print(f'{(c+1):02d} - {words[coef]}')
def backup_load(self, filename): def backup_load(self, filename):
if (platform.system() == 'Windows' or platform.system() == 'Linux'):
from secure_key import windows as skey
elif (platform.system() == 'Darwin'):
from secure_key import macos as skey
else:
print('ERROR: platform not supported')
sys.exit(-1)
from words import words
d = 0 d = 0
if (d == 0): if (d == 0):
for c in range(24): for c in range(24):
@@ -357,13 +349,6 @@ class Vendor:
) )
def _get_key_device(self): def _get_key_device(self):
if (platform.system() == 'Windows' or platform.system() == 'Linux'):
from secure_key import windows as skey
elif (platform.system() == 'Darwin'):
from secure_key import macos as skey
else:
print('ERROR: platform not supported')
sys.exit(-1)
return skey.get_secure_key() return skey.get_secure_key()
def get_skey(self): def get_skey(self):
@@ -396,7 +381,6 @@ class Vendor:
def parse_args(): def parse_args():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
subparser = parser.add_subparsers(title="commands", dest="command") subparser = parser.add_subparsers(title="commands", dest="command")
parser.add_argument('-p','--pin', help='Specify the PIN of the device.', required=True)
parser_secure = subparser.add_parser('secure', help='Manages security of Pico Fido.') parser_secure = subparser.add_parser('secure', help='Manages security of Pico Fido.')
parser_secure.add_argument('subcommand', choices=['enable', 'disable', 'unlock'], help='Enables, disables or unlocks the security.') parser_secure.add_argument('subcommand', choices=['enable', 'disable', 'unlock'], help='Enables, disables or unlocks the security.')
@@ -442,17 +426,15 @@ def attestation(vdr, args):
vdr.upload_ea(cert.public_bytes(Encoding.DER)) vdr.upload_ea(cert.public_bytes(Encoding.DER))
def main(args): def main(args):
print('Pico Fido Tool v1.6') print('Pico Fido Tool v1.4')
print('Author: Pol Henarejos') print('Author: Pol Henarejos')
print('Report bugs to https://github.com/polhenarejos/pico-fido/issues') print('Report bugs to https://github.com/polhenarejos/pico-fido/issues')
print('') print('')
print('') print('')
dev = next(CtapHidDevice.list_devices(), None) dev = next(CtapHidDevice.list_devices(), None)
ctap = Ctap2Vendor(dev)
client_pin = ClientPin(ctap) vdr = Vendor(Ctap2Vendor(dev))
token = client_pin.get_pin_token(args.pin, permissions=ClientPin.PERMISSION.AUTHENTICATOR_CFG)
vdr = Vendor(ctap, pin_uv_protocol=PinProtocolV2(), pin_uv_token=token)
if (args.command == 'secure'): if (args.command == 'secure'):
secure(vdr, args) secure(vdr, args)

View File

@@ -51,9 +51,7 @@ def get_secure_key():
try: try:
backend = get_backend(False) backend = get_backend(False)
key = backend.get_password(DOMAIN, USERNAME)[0] key = backend.get_password(DOMAIN, USERNAME)[0]
if (key is None): except keyring.errors.KeyringError:
raise TypeError
except (keyring.errors.KeyringError, TypeError):
try: try:
key = generate_secure_key(False)[0] # It should be True, but secure enclave causes python segfault key = generate_secure_key(False)[0] # It should be True, but secure enclave causes python segfault
except keyring.errors.PasswordSetError: except keyring.errors.PasswordSetError:

View File

@@ -1,44 +0,0 @@
import sys
DOMAIN = "PicoKeys.com"
USERNAME = "Pico-Fido"
try:
import keyring
except:
print('ERROR: keyring module not found! Install keyring package.\nTry with `pip install keyring`')
sys.exit(-1)
try:
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption, load_pem_private_key
from cryptography.hazmat.primitives.asymmetric import ec
except:
print('ERROR: cryptography module not found! Install cryptography package.\nTry with `pip install cryptography`')
sys.exit(-1)
def generate_secure_key():
pkey = ec.generate_private_key(ec.SECP256R1())
set_secure_key(pkey)
return keyring.get_password(DOMAIN, USERNAME)
def get_d(key):
return load_pem_private_key(key, password=None).private_numbers().private_value.to_bytes(32, 'big')
def set_secure_key(pk):
try:
keyring.delete_password(DOMAIN, USERNAME)
except:
pass
keyring.set_password(DOMAIN, USERNAME, pk.private_bytes(Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()).decode())
def get_secure_key():
key = None
try:
key = keyring.get_password(DOMAIN, USERNAME)
if (key is None):
raise TypeError
except (keyring.errors.KeyringError, TypeError):
key = generate_secure_key()
return get_d(key.encode())