mirror of
https://github.com/polhenarejos/pico-fido.git
synced 2025-12-19 02:48:04 +08:00
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:
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
Reference in New Issue
Block a user