Adding support for clientPIN.

It does not pass the tests yet.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2022-09-19 17:20:52 +02:00
parent 199091e2b9
commit ee8f3a0965
7 changed files with 70 additions and 9 deletions

View File

@@ -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_get_info.c
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_make_credential.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/known_apps.c
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_client_pin.c
) )
set(HSM_DRIVER "hid") set(HSM_DRIVER "hid")
include(pico-hsm-sdk/pico_hsm_sdk_import.cmake) include(pico-hsm-sdk/pico_hsm_sdk_import.cmake)

View File

@@ -39,5 +39,7 @@ int cbor_process(const uint8_t *data, size_t len) {
return cbor_get_info(); return cbor_get_info();
else if (data[0] == CTAP_RESET) else if (data[0] == CTAP_RESET)
return cbor_reset(); return cbor_reset();
else if (data[0] == CTAP_CLIENT_PIN)
return cbor_client_pin(data+1, len-1);
return -CTAP2_ERR_INVALID_CBOR; return -CTAP2_ERR_INVALID_CBOR;
} }

View File

@@ -43,7 +43,7 @@ bool credential_verify(CborByteString *cred_id, const uint8_t *rp_id_hash) {
return false; return false;
} }
int verify(CborByteString *clientDataHash, CborByteString *pinUvAuthParam) { int verify_user(CborByteString *clientDataHash, CborByteString *pinUvAuthParam) {
return CborNoError; return CborNoError;
} }
@@ -225,7 +225,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
//Unfinished. See 6.1.2.9 //Unfinished. See 6.1.2.9
} }
if (pinUvAuthParam.present == true) { //11.1 if (pinUvAuthParam.present == true) { //11.1
int ret = verify(&clientDataHash, &pinUvAuthParam); int ret = verify_user(&clientDataHash, &pinUvAuthParam);
if (ret != CborNoError) if (ret != CborNoError)
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
//Check pinUvAuthToken permissions. See 6.1.2.11 //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]; uint8_t key[32];
memset(key, 0, sizeof(key)); memset(key, 0, sizeof(key));
uint8_t iv[12]; 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_context chatx;
mbedtls_chachapoly_init(&chatx); mbedtls_chachapoly_init(&chatx);
mbedtls_chachapoly_setkey(&chatx, key); mbedtls_chachapoly_setkey(&chatx, key);

View File

@@ -24,6 +24,7 @@
#include "file.h" #include "file.h"
#include "usb.h" #include "usb.h"
#include "random.h" #include "random.h"
#include "bsp/board.h"
#include "mbedtls/ecdsa.h" #include "mbedtls/ecdsa.h"
#include "mbedtls/x509_crt.h" #include "mbedtls/x509_crt.h"
#include "mbedtls/hkdf.h" #include "mbedtls/hkdf.h"
@@ -36,6 +37,8 @@ void init_fido();
int fido_process_apdu(); int fido_process_apdu();
int fido_unload(); int fido_unload();
pinUvAuthToken_t paut = {0};
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
@@ -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_subject_key_identifier(&ctx);
mbedtls_x509write_crt_set_authority_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); 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; 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++) for (int i = 0; i < KEY_PATH_ENTRIES; i++)
{ {
if (new_key == true) { 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)); 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)); 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() { int scan_files() {
ef_keydev = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF); ef_keydev = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF);
if (ef_keydev) { if (ef_keydev) {
if (!ef_keydev->data) { if (!file_has_data(ef_keydev)) {
printf("KEY DEVICE is empty. Generating SECP256R1 curve..."); printf("KEY DEVICE is empty. Generating SECP256R1 curve...");
mbedtls_ecdsa_context ecdsa; mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init(&ecdsa); mbedtls_ecdsa_init(&ecdsa);
@@ -168,7 +173,7 @@ int scan_files() {
} }
ef_certdev = search_by_fid(EF_EE_DEV, NULL, SPECIFY_EF); ef_certdev = search_by_fid(EF_EE_DEV, NULL, SPECIFY_EF);
if (ef_certdev) { if (ef_certdev) {
if (file_get_size(ef_certdev) == 0 || !ef_certdev->data) { if (!file_has_data(ef_certdev)) {
uint8_t cert[4096]; uint8_t cert[4096];
mbedtls_ecdsa_context key; mbedtls_ecdsa_context key;
mbedtls_ecdsa_init(&key); mbedtls_ecdsa_init(&key);
@@ -188,7 +193,7 @@ int scan_files() {
} }
ef_counter = search_by_fid(EF_COUNTER, NULL, SPECIFY_EF); ef_counter = search_by_fid(EF_COUNTER, NULL, SPECIFY_EF);
if (ef_counter) { if (ef_counter) {
if (file_get_size(ef_counter) == 0 || !ef_counter->data) { if (!file_has_data(ef_counter)) {
uint32_t v = 0; uint32_t v = 0;
flash_write_data_to_file(ef_counter, (uint8_t *)&v, sizeof(v)); 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"); printf("FATAL ERROR: Global counter not found in memory!\r\n");
} }
ef_pin = search_by_fid(EF_PIN, NULL, SPECIFY_EF); 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(); low_flash_available();
return CCID_OK; return CCID_OK;
} }
@@ -218,6 +236,17 @@ bool wait_button_pressed() {
return (val == EV_BUTTON_TIMEOUT); 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 typedef struct cmd
{ {
uint8_t ins; uint8_t ins;

View File

@@ -54,6 +54,15 @@ extern CTAPHID_FRAME *ctap_req, *ctap_resp;
#define FIDO2_AUT_FLAG_AT 0x40 #define FIDO2_AUT_FLAG_AT 0x40
#define FIDO2_AUT_FLAG_ED 0x80 #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 { typedef struct known_app {
const uint8_t *rp_id_hash; const uint8_t *rp_id_hash;
const char *label; 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); 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 #endif //_FIDO_H

View File

@@ -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_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_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_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 { .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_certdev = NULL;
file_t *ef_counter = NULL; file_t *ef_counter = NULL;
file_t *ef_pin = NULL; file_t *ef_pin = NULL;
file_t *ef_authtoken = NULL;

View File

@@ -24,10 +24,12 @@
#define EF_EE_DEV 0xCE00 #define EF_EE_DEV 0xCE00
#define EF_COUNTER 0xC000 #define EF_COUNTER 0xC000
#define EF_PIN 0x1080 #define EF_PIN 0x1080
#define EF_AUTHTOKEN 0x1090
extern file_t *ef_keydev; extern file_t *ef_keydev;
extern file_t *ef_certdev; extern file_t *ef_certdev;
extern file_t *ef_counter; extern file_t *ef_counter;
extern file_t *ef_pin; extern file_t *ef_pin;
extern file_t *ef_authtoken;
#endif //_FILES_H_ #endif //_FILES_H_