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
No known key found for this signature in database
GPG Key ID: C0095B7870A4CCD3
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_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)

View File

@ -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;
}

View File

@ -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);

View File

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

View File

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

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_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;

View File

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