From ee8f3a0965a9a3504e4c672603a5489974c1f95e Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 19 Sep 2022 17:20:52 +0200 Subject: [PATCH] Adding support for clientPIN. It does not pass the tests yet. Signed-off-by: Pol Henarejos --- CMakeLists.txt | 1 + src/fido/cbor.c | 2 ++ src/fido/cbor_make_credential.c | 6 ++--- src/fido/fido.c | 39 ++++++++++++++++++++++++++++----- src/fido/fido.h | 25 +++++++++++++++++++++ src/fido/files.c | 4 +++- src/fido/files.h | 2 ++ 7 files changed, 70 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9526881..ab1e93e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ target_sources(pico_fido PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_get_info.c ${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_make_credential.c ${CMAKE_CURRENT_LIST_DIR}/src/fido/known_apps.c + ${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_client_pin.c ) set(HSM_DRIVER "hid") include(pico-hsm-sdk/pico_hsm_sdk_import.cmake) diff --git a/src/fido/cbor.c b/src/fido/cbor.c index cdebc88..8ac6380 100644 --- a/src/fido/cbor.c +++ b/src/fido/cbor.c @@ -39,5 +39,7 @@ int cbor_process(const uint8_t *data, size_t len) { return cbor_get_info(); else if (data[0] == CTAP_RESET) return cbor_reset(); + else if (data[0] == CTAP_CLIENT_PIN) + return cbor_client_pin(data+1, len-1); return -CTAP2_ERR_INVALID_CBOR; } diff --git a/src/fido/cbor_make_credential.c b/src/fido/cbor_make_credential.c index 5205366..8b774ed 100644 --- a/src/fido/cbor_make_credential.c +++ b/src/fido/cbor_make_credential.c @@ -43,7 +43,7 @@ bool credential_verify(CborByteString *cred_id, const uint8_t *rp_id_hash) { return false; } -int verify(CborByteString *clientDataHash, CborByteString *pinUvAuthParam) { +int verify_user(CborByteString *clientDataHash, CborByteString *pinUvAuthParam) { return CborNoError; } @@ -225,7 +225,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) { //Unfinished. See 6.1.2.9 } if (pinUvAuthParam.present == true) { //11.1 - int ret = verify(&clientDataHash, &pinUvAuthParam); + int ret = verify_user(&clientDataHash, &pinUvAuthParam); if (ret != CborNoError) CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); //Check pinUvAuthToken permissions. See 6.1.2.11 @@ -272,7 +272,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) { uint8_t key[32]; memset(key, 0, sizeof(key)); uint8_t iv[12]; - memcpy(iv, random_bytes_get(sizeof(iv)), sizeof(iv)); + random_gen_core0(NULL, iv, sizeof(12)); mbedtls_chachapoly_context chatx; mbedtls_chachapoly_init(&chatx); mbedtls_chachapoly_setkey(&chatx, key); diff --git a/src/fido/fido.c b/src/fido/fido.c index 58df475..9d275f9 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -24,6 +24,7 @@ #include "file.h" #include "usb.h" #include "random.h" +#include "bsp/board.h" #include "mbedtls/ecdsa.h" #include "mbedtls/x509_crt.h" #include "mbedtls/hkdf.h" @@ -36,6 +37,8 @@ void init_fido(); int fido_process_apdu(); int fido_unload(); +pinUvAuthToken_t paut = {0}; + const uint8_t fido_aid[] = { 8, 0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01 @@ -81,7 +84,7 @@ int x509_create_cert(mbedtls_ecdsa_context *ecdsa, uint8_t *buffer, size_t buffe mbedtls_x509write_crt_set_subject_key_identifier(&ctx); mbedtls_x509write_crt_set_authority_key_identifier(&ctx); mbedtls_x509write_crt_set_key_usage(&ctx, MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN); - int ret = mbedtls_x509write_crt_der(&ctx, buffer, buffer_size, random_gen, NULL); + int ret = mbedtls_x509write_crt_der(&ctx, buffer, buffer_size, random_gen_core0, NULL); return ret; } @@ -103,7 +106,9 @@ int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int cur for (int i = 0; i < KEY_PATH_ENTRIES; i++) { if (new_key == true) { - uint32_t val = 0x80000000 | *((uint32_t *)random_bytes_get(sizeof(uint32_t))); + uint32_t val = 0; + random_gen_core0(NULL, (uint8_t *) &val, sizeof(val)); + val |= 0x80000000; memcpy(&key_handle[i*sizeof(uint32_t)], &val, sizeof(uint32_t)); } r = mbedtls_hkdf(md_info, &key_handle[i * sizeof(uint32_t)], sizeof(uint32_t), outk, 32, outk + 32, 32, outk, sizeof(outk)); @@ -141,7 +146,7 @@ int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int cur int scan_files() { ef_keydev = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF); if (ef_keydev) { - if (!ef_keydev->data) { + if (!file_has_data(ef_keydev)) { printf("KEY DEVICE is empty. Generating SECP256R1 curve..."); mbedtls_ecdsa_context ecdsa; mbedtls_ecdsa_init(&ecdsa); @@ -168,7 +173,7 @@ int scan_files() { } ef_certdev = search_by_fid(EF_EE_DEV, NULL, SPECIFY_EF); if (ef_certdev) { - if (file_get_size(ef_certdev) == 0 || !ef_certdev->data) { + if (!file_has_data(ef_certdev)) { uint8_t cert[4096]; mbedtls_ecdsa_context key; mbedtls_ecdsa_init(&key); @@ -188,7 +193,7 @@ int scan_files() { } ef_counter = search_by_fid(EF_COUNTER, NULL, SPECIFY_EF); if (ef_counter) { - if (file_get_size(ef_counter) == 0 || !ef_counter->data) { + if (!file_has_data(ef_counter)) { uint32_t v = 0; flash_write_data_to_file(ef_counter, (uint8_t *)&v, sizeof(v)); } @@ -197,6 +202,19 @@ int scan_files() { printf("FATAL ERROR: Global counter not found in memory!\r\n"); } ef_pin = search_by_fid(EF_PIN, NULL, SPECIFY_EF); + ef_authtoken = search_by_fid(EF_AUTHTOKEN, NULL, SPECIFY_EF); + if (ef_authtoken) { + if (!file_has_data(ef_authtoken)) { + uint8_t t[32]; + random_gen_core0(NULL, t, sizeof(t)); + flash_write_data_to_file(ef_authtoken, t, sizeof(t)); + } + paut.data = file_get_data(ef_authtoken); + paut.len = file_get_size(ef_authtoken); + } + else { + printf("FATAL ERROR: Auth Token not found in memory!\r\n"); + } low_flash_available(); return CCID_OK; } @@ -218,6 +236,17 @@ bool wait_button_pressed() { return (val == EV_BUTTON_TIMEOUT); } +uint32_t user_present_time_limit = 0; + +bool check_user_presence() { + if (user_present_time_limit == 0 || user_present_time_limit+TRANSPORT_TIME_LIMIT < board_millis()) { + if (wait_button() == true) //timeout + return false; + user_present_time_limit = board_millis(); + } + return true; +} + typedef struct cmd { uint8_t ins; diff --git a/src/fido/fido.h b/src/fido/fido.h index e085838..1a9ba83 100644 --- a/src/fido/fido.h +++ b/src/fido/fido.h @@ -54,6 +54,15 @@ extern CTAPHID_FRAME *ctap_req, *ctap_resp; #define FIDO2_AUT_FLAG_AT 0x40 #define FIDO2_AUT_FLAG_ED 0x80 +#define FIDO2_PERMISSION_MC 0x1 +#define FIDO2_PERMISSION_GA 0x2 +#define FIDO2_PERMISSION_CM 0x4 +#define FIDO2_PERMISSION_BE 0x8 +#define FIDO2_PERMISSION_LBW 0x10 +#define FIDO2_PERMISSION_ACFG 0x20 + +#define MAX_PIN_RETRIES 3 + typedef struct known_app { const uint8_t *rp_id_hash; const char *label; @@ -63,4 +72,20 @@ typedef struct known_app { extern const known_app_t *find_app_by_rp_id_hash(const uint8_t *rp_id_hash); +#define TRANSPORT_TIME_LIMIT (30*1000) //USB + +bool check_user_presence(); + +typedef struct pinUvAuthToken { + uint8_t *data; + size_t len; + bool in_use; + uint8_t permissions; + uint8_t rp_id_hash[32]; +} pinUvAuthToken_t; + +extern uint32_t user_present_time_limit; + +extern pinUvAuthToken_t paut; + #endif //_FIDO_H diff --git a/src/fido/files.c b/src/fido/files.c index df9ded8..c8948de 100644 --- a/src/fido/files.c +++ b/src/fido/files.c @@ -23,7 +23,8 @@ file_t file_entries[] = { {.fid = EF_KEY_DEV, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // Device Key {.fid = EF_EE_DEV, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // End Entity Certificate Device {.fid = EF_COUNTER, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // Global counter - {.fid = EF_PIN, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // Global counter + {.fid = EF_PIN, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // PIN + {.fid = EF_AUTHTOKEN, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff}}, // AUTH TOKEN { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = {0} } //end }; @@ -33,3 +34,4 @@ file_t *ef_keydev = NULL; file_t *ef_certdev = NULL; file_t *ef_counter = NULL; file_t *ef_pin = NULL; +file_t *ef_authtoken = NULL; diff --git a/src/fido/files.h b/src/fido/files.h index 3d7e69e..c8a35a4 100644 --- a/src/fido/files.h +++ b/src/fido/files.h @@ -24,10 +24,12 @@ #define EF_EE_DEV 0xCE00 #define EF_COUNTER 0xC000 #define EF_PIN 0x1080 +#define EF_AUTHTOKEN 0x1090 extern file_t *ef_keydev; extern file_t *ef_certdev; extern file_t *ef_counter; extern file_t *ef_pin; +extern file_t *ef_authtoken; #endif //_FILES_H_