mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-13 08:40:26 +01:00
Merge pull request #18663 from Ollrogge/fido2_follow_up2
sys/fido2: follow up continued
This commit is contained in:
commit
737f675442
@ -10,7 +10,9 @@ endif
|
||||
|
||||
ifneq (,$(filter fido2_ctap,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += periph_flashpage
|
||||
ifeq (,$(filter native,$(CPU)))
|
||||
FEATURES_REQUIRED += periph_flashpage_in_address_space
|
||||
endif
|
||||
FEATURES_REQUIRED += periph_gpio_irq
|
||||
|
||||
USEPKG += tiny-asn1
|
||||
@ -26,4 +28,5 @@ ifneq (,$(filter fido2_ctap,$(USEMODULE)))
|
||||
USEMODULE += crypto_aes_256
|
||||
USEMODULE += hashes
|
||||
USEMODULE += fido2
|
||||
USEMODULE += fmt
|
||||
endif
|
||||
|
@ -248,26 +248,26 @@ static uint8_t _pin_token[CTAP_PIN_TOKEN_SZ];
|
||||
*/
|
||||
static int _rem_pin_att_boot = CTAP_PIN_MAX_ATTS_BOOT;
|
||||
|
||||
int fido2_ctap_init(void)
|
||||
ctap_status_code_t fido2_ctap_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = fido2_ctap_mem_init();
|
||||
|
||||
if (ret != CTAP2_OK) {
|
||||
return -EPROTO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fido2_ctap_mem_read_state_from_flash(&_state);
|
||||
if (ret != CTAP2_OK) {
|
||||
return -EPROTO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* first startup of the device */
|
||||
if (_state.initialized_marker != CTAP_INITIALIZED_MARKER) {
|
||||
ret = _reset();
|
||||
if (ret != CTAP2_OK) {
|
||||
return -EPROTO;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,29 +275,29 @@ int fido2_ctap_init(void)
|
||||
ret = fido2_ctap_utils_init_gpio_pin(CTAP_UP_BUTTON, CTAP_UP_BUTTON_MODE,
|
||||
CTAP_UP_BUTTON_FLANK);
|
||||
if (ret != CTAP2_OK) {
|
||||
return -EPROTO;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = fido2_ctap_crypto_init();
|
||||
|
||||
if (ret != CTAP2_OK) {
|
||||
return -EPROTO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initialize pin_token */
|
||||
ret = fido2_ctap_crypto_prng(_pin_token, sizeof(_pin_token));
|
||||
|
||||
if (ret != CTAP2_OK) {
|
||||
return -EPROTO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEBUG("fido2_ctap: initialization successful \n");
|
||||
|
||||
return 0;
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
size_t fido2_ctap_handle_request(ctap_req_t *req, ctap_resp_t *resp)
|
||||
ctap_status_code_t fido2_ctap_handle_request(ctap_req_t *req, ctap_resp_t *resp)
|
||||
{
|
||||
assert(req);
|
||||
assert(resp);
|
||||
@ -305,35 +305,38 @@ size_t fido2_ctap_handle_request(ctap_req_t *req, ctap_resp_t *resp)
|
||||
switch (req->method) {
|
||||
case CTAP_GET_INFO:
|
||||
DEBUG("fido2_ctap: get_info req \n");
|
||||
return fido2_ctap_get_info(resp);
|
||||
fido2_ctap_get_info(resp);
|
||||
break;
|
||||
case CTAP_MAKE_CREDENTIAL:
|
||||
DEBUG("fido2_ctap: make_credential req \n");
|
||||
return fido2_ctap_make_credential(req, resp);
|
||||
fido2_ctap_make_credential(req, resp);
|
||||
break;
|
||||
case CTAP_GET_ASSERTION:
|
||||
DEBUG("fido2_ctap: get_assertion req \n");
|
||||
return fido2_ctap_get_assertion(req, resp);
|
||||
fido2_ctap_get_assertion(req, resp);
|
||||
break;
|
||||
case CTAP_GET_NEXT_ASSERTION:
|
||||
DEBUG("fido2_ctap: get_next_assertion req \n");
|
||||
return fido2_ctap_get_next_assertion(resp);
|
||||
fido2_ctap_get_next_assertion(resp);
|
||||
break;
|
||||
case CTAP_CLIENT_PIN:
|
||||
DEBUG("fido2_ctap: client_pin req \n");
|
||||
return fido2_ctap_client_pin(req, resp);
|
||||
fido2_ctap_client_pin(req, resp);
|
||||
break;
|
||||
case CTAP_RESET:
|
||||
DEBUG("fido2_ctap: reset req \n");
|
||||
return fido2_ctap_reset(resp);
|
||||
fido2_ctap_reset(resp);
|
||||
break;
|
||||
default:
|
||||
DEBUG("fido2_ctap: unknown req: %u \n", req->method);
|
||||
resp->status = CTAP1_ERR_INVALID_COMMAND;
|
||||
resp->len = 0x0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
DEBUG("Resp status %d \n", resp->status);
|
||||
|
||||
return resp->status;
|
||||
}
|
||||
|
||||
ctap_state_t *fido2_ctap_get_state(void)
|
||||
@ -341,18 +344,19 @@ ctap_state_t *fido2_ctap_get_state(void)
|
||||
return &_state;
|
||||
}
|
||||
|
||||
size_t fido2_ctap_get_info(ctap_resp_t *resp)
|
||||
ctap_status_code_t fido2_ctap_get_info(ctap_resp_t *resp)
|
||||
{
|
||||
assert(resp);
|
||||
|
||||
fido2_ctap_cbor_init_encoder(resp->data, sizeof(resp->data));
|
||||
|
||||
resp->status = _get_info();
|
||||
resp->len = fido2_ctap_cbor_get_buffer_size(resp->data);
|
||||
|
||||
return fido2_ctap_cbor_get_buffer_size(resp->data);
|
||||
return resp->status;
|
||||
}
|
||||
|
||||
size_t fido2_ctap_make_credential(ctap_req_t *req, ctap_resp_t *resp)
|
||||
ctap_status_code_t fido2_ctap_make_credential(ctap_req_t *req, ctap_resp_t *resp)
|
||||
{
|
||||
assert(req);
|
||||
assert(resp);
|
||||
@ -360,11 +364,12 @@ size_t fido2_ctap_make_credential(ctap_req_t *req, ctap_resp_t *resp)
|
||||
fido2_ctap_cbor_init_encoder(resp->data, sizeof(resp->data));
|
||||
|
||||
resp->status = _make_credential(req);
|
||||
resp->len = fido2_ctap_cbor_get_buffer_size(resp->data);
|
||||
|
||||
return fido2_ctap_cbor_get_buffer_size(resp->data);
|
||||
return resp->status;
|
||||
}
|
||||
|
||||
size_t fido2_ctap_get_assertion(ctap_req_t *req, ctap_resp_t *resp)
|
||||
ctap_status_code_t fido2_ctap_get_assertion(ctap_req_t *req, ctap_resp_t *resp)
|
||||
{
|
||||
assert(req);
|
||||
assert(resp);
|
||||
@ -372,22 +377,24 @@ size_t fido2_ctap_get_assertion(ctap_req_t *req, ctap_resp_t *resp)
|
||||
fido2_ctap_cbor_init_encoder(resp->data, sizeof(resp->data));
|
||||
|
||||
resp->status = _get_assertion(req);
|
||||
resp->len = fido2_ctap_cbor_get_buffer_size(resp->data);
|
||||
|
||||
return fido2_ctap_cbor_get_buffer_size(resp->data);
|
||||
return resp->status;
|
||||
}
|
||||
|
||||
size_t fido2_ctap_get_next_assertion(ctap_resp_t *resp)
|
||||
ctap_status_code_t fido2_ctap_get_next_assertion(ctap_resp_t *resp)
|
||||
{
|
||||
assert(resp);
|
||||
|
||||
fido2_ctap_cbor_init_encoder(resp->data, sizeof(resp->data));
|
||||
|
||||
resp->status = _get_next_assertion();
|
||||
resp->len = fido2_ctap_cbor_get_buffer_size(resp->data);
|
||||
|
||||
return fido2_ctap_cbor_get_buffer_size(resp->data);
|
||||
return resp->status;
|
||||
}
|
||||
|
||||
size_t fido2_ctap_client_pin(ctap_req_t *req, ctap_resp_t *resp)
|
||||
ctap_status_code_t fido2_ctap_client_pin(ctap_req_t *req, ctap_resp_t *resp)
|
||||
{
|
||||
assert(req);
|
||||
assert(resp);
|
||||
@ -395,15 +402,19 @@ size_t fido2_ctap_client_pin(ctap_req_t *req, ctap_resp_t *resp)
|
||||
fido2_ctap_cbor_init_encoder(resp->data, sizeof(resp->data));
|
||||
|
||||
resp->status = _client_pin(req);
|
||||
resp->len = fido2_ctap_cbor_get_buffer_size(resp->data);
|
||||
|
||||
return fido2_ctap_cbor_get_buffer_size(resp->data);
|
||||
return resp->status;
|
||||
}
|
||||
|
||||
size_t fido2_ctap_reset(ctap_resp_t *resp)
|
||||
ctap_status_code_t fido2_ctap_reset(ctap_resp_t *resp)
|
||||
{
|
||||
resp->status = _reset();
|
||||
assert(resp);
|
||||
|
||||
return 0;
|
||||
resp->status = _reset();
|
||||
resp->len = 0x0;
|
||||
|
||||
return resp->status;
|
||||
}
|
||||
|
||||
static uint32_t get_id(void)
|
||||
@ -413,7 +424,11 @@ static uint32_t get_id(void)
|
||||
|
||||
static int _reset(void)
|
||||
{
|
||||
fido2_ctap_mem_erase_flash();
|
||||
int ret = fido2_ctap_mem_erase_flash();
|
||||
|
||||
if (ret != CTAP2_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
_state.initialized_marker = CTAP_INITIALIZED_MARKER;
|
||||
_state.rem_pin_att = CTAP_PIN_MAX_ATTS;
|
||||
@ -540,12 +555,12 @@ static int _make_credential(ctap_req_t *req_raw)
|
||||
}
|
||||
|
||||
/* last moment where transaction can be cancelled */
|
||||
if (IS_USED(MODULE_FIDO2_CTAP_TRANSPORT_HID)) {
|
||||
if (fido2_ctap_transport_hid_should_cancel()) {
|
||||
ret = CTAP2_ERR_KEEPALIVE_CANCEL;
|
||||
goto done;
|
||||
}
|
||||
#if IS_USED(MODULE_FIDO2_CTAP_TRANSPORT_HID)
|
||||
if (fido2_ctap_transport_hid_should_cancel()) {
|
||||
ret = CTAP2_ERR_KEEPALIVE_CANCEL;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* user presence test to create a new credential */
|
||||
if (IS_ACTIVE(CONFIG_FIDO2_CTAP_DISABLE_UP)) {
|
||||
@ -697,10 +712,12 @@ static int _get_assertion(ctap_req_t *req_raw)
|
||||
rk = &_assert_state.rks[_assert_state.cred_counter++];
|
||||
|
||||
/* last moment where transaction can be cancelled */
|
||||
#if IS_USED(MODULE_FIDO2_CTAP_TRANSPORT_HID)
|
||||
if (fido2_ctap_transport_hid_should_cancel()) {
|
||||
ret = CTAP2_ERR_KEEPALIVE_CANCEL;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = _make_auth_data_assert(req.rp_id, req.rp_id_len, &auth_data, uv,
|
||||
up,
|
||||
@ -855,7 +872,7 @@ static int _client_pin(ctap_req_t *req_raw)
|
||||
}
|
||||
|
||||
/* common error handling */
|
||||
if (req.sub_command != CTAP_CP_REQ_SUB_COMMAND_GET_RETRIES) {
|
||||
if (req.sub_command != CTAP_PIN_GET_RETRIES) {
|
||||
if (_is_locked()) {
|
||||
return CTAP2_ERR_PIN_BLOCKED;
|
||||
}
|
||||
@ -870,19 +887,19 @@ static int _client_pin(ctap_req_t *req_raw)
|
||||
}
|
||||
|
||||
switch (req.sub_command) {
|
||||
case CTAP_CP_REQ_SUB_COMMAND_GET_RETRIES:
|
||||
case CTAP_PIN_GET_RETRIES:
|
||||
ret = _get_retries();
|
||||
break;
|
||||
case CTAP_CP_REQ_SUB_COMMAND_GET_KEY_AGREEMENT:
|
||||
case CTAP_PIN_GET_KEY_AGREEMENT:
|
||||
ret = _get_key_agreement();
|
||||
break;
|
||||
case CTAP_CP_REQ_SUB_COMMAND_SET_PIN:
|
||||
case CTAP_PIN_SET_PIN:
|
||||
ret = _set_pin(&req);
|
||||
break;
|
||||
case CTAP_CP_REQ_SUB_COMMAND_CHANGE_PIN:
|
||||
case CTAP_PIN_CHANGE_PIN:
|
||||
ret = _change_pin(&req);
|
||||
break;
|
||||
case CTAP_CP_REQ_SUB_COMMAND_GET_PIN_TOKEN:
|
||||
case CTAP_PIN_GET_PIN_TOKEN:
|
||||
ret = _get_pin_token(&req);
|
||||
break;
|
||||
default:
|
||||
@ -904,7 +921,6 @@ static int _get_key_agreement(void)
|
||||
int ret;
|
||||
ctap_public_key_cose_t key = { 0 };
|
||||
|
||||
|
||||
/* generate key agreement key */
|
||||
ret =
|
||||
fido2_ctap_crypto_gen_keypair(&_state.ag_key.pub, _state.ag_key.priv,
|
||||
@ -989,12 +1005,12 @@ static int _set_pin(ctap_client_pin_req_t *req)
|
||||
}
|
||||
|
||||
/* last moment where transaction can be cancelled */
|
||||
if (IS_USED(MODULE_FIDO2_CTAP_TRANSPORT_HID)) {
|
||||
if (fido2_ctap_transport_hid_should_cancel()) {
|
||||
ret = CTAP2_ERR_KEEPALIVE_CANCEL;
|
||||
goto done;
|
||||
}
|
||||
#if IS_USED(MODULE_FIDO2_CTAP_TRANSPORT_HID)
|
||||
if (fido2_ctap_transport_hid_should_cancel()) {
|
||||
ret = CTAP2_ERR_KEEPALIVE_CANCEL;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
sz = fmt_strnlen((char *)new_pin_dec, CTAP_PIN_MAX_SIZE + 1);
|
||||
if (sz < CTAP_PIN_MIN_SIZE || sz > CTAP_PIN_MAX_SIZE) {
|
||||
@ -1100,13 +1116,12 @@ static int _change_pin(ctap_client_pin_req_t *req)
|
||||
}
|
||||
|
||||
/* last moment where transaction can be cancelled */
|
||||
if (IS_USED(MODULE_FIDO2_CTAP_TRANSPORT_HID)) {
|
||||
if (fido2_ctap_transport_hid_should_cancel()) {
|
||||
ret = CTAP2_ERR_KEEPALIVE_CANCEL;
|
||||
goto done;
|
||||
}
|
||||
#if IS_USED(MODULE_FIDO2_CTAP_TRANSPORT_HID)
|
||||
if (fido2_ctap_transport_hid_should_cancel()) {
|
||||
ret = CTAP2_ERR_KEEPALIVE_CANCEL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* verify decrypted pinHash against LEFT(SHA-256(curPin), 16) */
|
||||
if (memcmp(pin_hash_dec, _state.pin_hash, CTAP_PIN_TOKEN_SZ) != 0) {
|
||||
DEBUG("fido2_ctap: _get_pin_token - invalid pin \n");
|
||||
@ -1198,13 +1213,12 @@ static int _get_pin_token(ctap_client_pin_req_t *req)
|
||||
}
|
||||
|
||||
/* last moment where transaction can be cancelled */
|
||||
if (IS_USED(MODULE_FIDO2_CTAP_TRANSPORT_HID)) {
|
||||
if (fido2_ctap_transport_hid_should_cancel()) {
|
||||
ret = CTAP2_ERR_KEEPALIVE_CANCEL;
|
||||
goto done;
|
||||
}
|
||||
#if IS_USED(MODULE_FIDO2_CTAP_TRANSPORT_HID)
|
||||
if (fido2_ctap_transport_hid_should_cancel()) {
|
||||
ret = CTAP2_ERR_KEEPALIVE_CANCEL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* sha256 of shared secret ((abG).x) to obtain shared key */
|
||||
ret = fido2_ctap_crypto_sha256(shared_secret, sizeof(shared_secret), shared_key);
|
||||
|
||||
|
@ -33,99 +33,101 @@ typedef enum {
|
||||
* data structure into @ref ctap_rp_ent_t or @ref ctap_user_ent_t struct
|
||||
* respectively.
|
||||
*/
|
||||
static int _parse_entity(CborValue *it, void *entity, entity_type_t type);
|
||||
static ctap_status_code_t _parse_entity(CborValue *it, void *entity, entity_type_t type);
|
||||
|
||||
/**
|
||||
* @brief Parse CBOR encoded sequence of PublicKeyCredentialDescriptors into
|
||||
* @ref ctap_cred_desc_alt_t struct
|
||||
*/
|
||||
static int _parse_exclude_list(CborValue *it, ctap_cred_desc_alt_t *exclude_list,
|
||||
static ctap_status_code_t _parse_exclude_list(CborValue *it, ctap_cred_desc_alt_t *exclude_list,
|
||||
size_t *exclude_list_len);
|
||||
|
||||
/**
|
||||
* @brief Parse CBOR encoded sequence of PublicKeyCredentialDescriptors into
|
||||
* @ref ctap_cred_desc_alt_t struct
|
||||
*/
|
||||
static int _parse_allow_list(CborValue *it, ctap_cred_desc_alt_t *allow_list,
|
||||
static ctap_status_code_t _parse_allow_list(CborValue *it, ctap_cred_desc_alt_t *allow_list,
|
||||
uint8_t *allow_list_len);
|
||||
|
||||
/**
|
||||
* @brief Parse CBOR encoded sequence of PublicKeyCredentialType and cryptographic
|
||||
* algorithm type pairs and check if the combination is supported
|
||||
*/
|
||||
static int _parse_pub_key_cred_params(CborValue *it,
|
||||
static ctap_status_code_t _parse_pub_key_cred_params(CborValue *it,
|
||||
ctap_make_credential_req_t *req);
|
||||
|
||||
/**
|
||||
* @brief Parse CBOR encoded PublicKeyCredentialType and cryptographic
|
||||
* algorithm type
|
||||
*/
|
||||
static int _parse_pub_key_cred_param(CborValue *it, uint8_t *cred_type,
|
||||
static ctap_status_code_t _parse_pub_key_cred_param(CborValue *it, uint8_t *cred_type,
|
||||
int32_t *alg_type);
|
||||
|
||||
/**
|
||||
* @brief Parse CBOR encoded map of authenticator options into @ref ctap_options_t
|
||||
* struct
|
||||
*/
|
||||
static int _parse_options(CborValue *it, ctap_options_t *options);
|
||||
static ctap_status_code_t _parse_options(CborValue *it, ctap_options_t *options);
|
||||
|
||||
/**
|
||||
* @brief Parse public key in COSE_KEY format into ctap_public_key_cose_t struct
|
||||
*/
|
||||
static int _parse_public_key_cose(CborValue *it, ctap_public_key_cose_t *cose_key);
|
||||
static ctap_status_code_t _parse_public_key_cose(CborValue *it, ctap_public_key_cose_t *cose_key);
|
||||
|
||||
/**
|
||||
* @brief Parse CBOR encoded fixed length array into dst
|
||||
*/
|
||||
static int _parse_fixed_len_byte_array(CborValue *map, uint8_t *dst,
|
||||
static ctap_status_code_t _parse_fixed_len_byte_array(CborValue *map, uint8_t *dst,
|
||||
size_t *len);
|
||||
|
||||
/**
|
||||
* @brief Parse CBOR encoded unknown length array into dst
|
||||
*/
|
||||
static int _parse_byte_array(CborValue *it, uint8_t *dst, size_t *len);
|
||||
static ctap_status_code_t _parse_byte_array(CborValue *it, uint8_t *dst, size_t *len);
|
||||
|
||||
/**
|
||||
* @brief Parse CBOR encoded unknown length array into dst
|
||||
*/
|
||||
static int _parse_byte_array_u8len(CborValue *it, uint8_t *dst, uint8_t *len);
|
||||
static ctap_status_code_t _parse_byte_array_u8len(CborValue *it, uint8_t *dst, uint8_t *len);
|
||||
|
||||
/**
|
||||
* @brief Parse CBOR encoded string into dst
|
||||
*/
|
||||
static int _parse_text_string(CborValue *it, char *dst, size_t *len);
|
||||
static ctap_status_code_t _parse_text_string(CborValue *it, char *dst, size_t *len);
|
||||
/**
|
||||
* @brief Parse CBOR encoded string into dst
|
||||
*/
|
||||
static int _parse_text_string_u8len(CborValue *it, char *dst, uint8_t *len);
|
||||
static ctap_status_code_t _parse_text_string_u8len(CborValue *it, char *dst, uint8_t *len);
|
||||
|
||||
/**
|
||||
* @brief Parse CBOR encoded int into num
|
||||
*/
|
||||
static int _parse_int(CborValue *it, int *num);
|
||||
static ctap_status_code_t _parse_int(CborValue *it, int *num);
|
||||
|
||||
/**
|
||||
* @brief Parse credential description
|
||||
*/
|
||||
static int _fido2_ctap_cbor_parse_cred_desc(CborValue *arr, ctap_cred_desc_alt_t *cred);
|
||||
static ctap_status_code_t _fido2_ctap_cbor_parse_cred_desc(CborValue *arr,
|
||||
ctap_cred_desc_alt_t *cred);
|
||||
|
||||
/**
|
||||
* @brief Encode public key into COSE_KEY format
|
||||
*
|
||||
* See https://tools.ietf.org/html/rfc8152#page-34 Section 13.1.1 for details.
|
||||
*/
|
||||
static int _encode_public_key_cose(CborEncoder *cose_key, const ctap_public_key_cose_t *key);
|
||||
static ctap_status_code_t _encode_public_key_cose(CborEncoder *cose_key,
|
||||
const ctap_public_key_cose_t *key);
|
||||
|
||||
/**
|
||||
* @brief Encode PublicKeyCredentialDescriptor into CBOR format
|
||||
*/
|
||||
static int _encode_credential(CborEncoder *encoder, const void *cred_ptr,
|
||||
static ctap_status_code_t _encode_credential(CborEncoder *encoder, const void *cred_ptr,
|
||||
bool rk);
|
||||
|
||||
/**
|
||||
* @brief Encode PublicKeyCredentialUserEntity into CBOR format
|
||||
*/
|
||||
static int _encode_user_entity(CborEncoder *it, const ctap_resident_key_t *rk);
|
||||
static ctap_status_code_t _encode_user_entity(CborEncoder *it, const ctap_resident_key_t *rk);
|
||||
|
||||
/**
|
||||
* @brief CBOR encoder
|
||||
@ -142,7 +144,7 @@ void fido2_ctap_cbor_init_encoder(uint8_t *buf, size_t len)
|
||||
cbor_encoder_init(&_encoder, buf, len, 0);
|
||||
}
|
||||
|
||||
int fido2_ctap_cbor_encode_info(const ctap_info_t *info)
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_info(const ctap_info_t *info)
|
||||
{
|
||||
int ret;
|
||||
size_t sz = 0;
|
||||
@ -339,7 +341,7 @@ int fido2_ctap_cbor_encode_info(const ctap_info_t *info)
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_cbor_encode_assertion_object(const ctap_auth_data_header_t *auth_data,
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_assertion_object(const ctap_auth_data_header_t *auth_data,
|
||||
const uint8_t *client_data_hash,
|
||||
ctap_resident_key_t *rk,
|
||||
uint8_t valid_cred_count)
|
||||
@ -457,7 +459,7 @@ int fido2_ctap_cbor_encode_assertion_object(const ctap_auth_data_header_t *auth_
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_cbor_encode_attestation_object(const ctap_auth_data_t *auth_data,
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_attestation_object(const ctap_auth_data_t *auth_data,
|
||||
const uint8_t *client_data_hash,
|
||||
ctap_resident_key_t *rk)
|
||||
{
|
||||
@ -580,7 +582,7 @@ int fido2_ctap_cbor_encode_attestation_object(const ctap_auth_data_t *auth_data,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _encode_credential(CborEncoder *encoder, const void *cred_ptr,
|
||||
static ctap_status_code_t _encode_credential(CborEncoder *encoder, const void *cred_ptr,
|
||||
bool rk)
|
||||
{
|
||||
CborEncoder desc;
|
||||
@ -630,7 +632,7 @@ static int _encode_credential(CborEncoder *encoder, const void *cred_ptr,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_cbor_encode_key_agreement(const ctap_public_key_cose_t *key)
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_key_agreement(const ctap_public_key_cose_t *key)
|
||||
{
|
||||
int ret;
|
||||
CborEncoder map;
|
||||
@ -659,7 +661,7 @@ int fido2_ctap_cbor_encode_key_agreement(const ctap_public_key_cose_t *key)
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_cbor_encode_retries(uint8_t tries_left)
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_retries(uint8_t tries_left)
|
||||
{
|
||||
int ret;
|
||||
CborEncoder map;
|
||||
@ -687,7 +689,7 @@ int fido2_ctap_cbor_encode_retries(uint8_t tries_left)
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_cbor_encode_pin_token(uint8_t *token, size_t len)
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_pin_token(uint8_t *token, size_t len)
|
||||
{
|
||||
int ret;
|
||||
CborEncoder map;
|
||||
@ -715,7 +717,7 @@ int fido2_ctap_cbor_encode_pin_token(uint8_t *token, size_t len)
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _encode_user_entity(CborEncoder *encoder,
|
||||
static ctap_status_code_t _encode_user_entity(CborEncoder *encoder,
|
||||
const ctap_resident_key_t *rk)
|
||||
{
|
||||
int ret;
|
||||
@ -743,7 +745,8 @@ static int _encode_user_entity(CborEncoder *encoder,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _encode_public_key_cose(CborEncoder *cose_key, const ctap_public_key_cose_t *key)
|
||||
static ctap_status_code_t _encode_public_key_cose(CborEncoder *cose_key,
|
||||
const ctap_public_key_cose_t *key)
|
||||
{
|
||||
int ret;
|
||||
CborEncoder map;
|
||||
@ -806,7 +809,7 @@ static int _encode_public_key_cose(CborEncoder *cose_key, const ctap_public_key_
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_cbor_parse_get_assertion_req(ctap_get_assertion_req_t *req,
|
||||
ctap_status_code_t fido2_ctap_cbor_parse_get_assertion_req(ctap_get_assertion_req_t *req,
|
||||
const uint8_t *req_raw, size_t len)
|
||||
{
|
||||
uint8_t required_parsed = 0;
|
||||
@ -928,7 +931,7 @@ int fido2_ctap_cbor_parse_get_assertion_req(ctap_get_assertion_req_t *req,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_cbor_parse_client_pin_req(ctap_client_pin_req_t *req,
|
||||
ctap_status_code_t fido2_ctap_cbor_parse_client_pin_req(ctap_client_pin_req_t *req,
|
||||
const uint8_t *req_raw, size_t len)
|
||||
{
|
||||
uint8_t required_parsed = 0;
|
||||
@ -1041,7 +1044,7 @@ int fido2_ctap_cbor_parse_client_pin_req(ctap_client_pin_req_t *req,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_cbor_parse_make_credential_req(ctap_make_credential_req_t *req,
|
||||
ctap_status_code_t fido2_ctap_cbor_parse_make_credential_req(ctap_make_credential_req_t *req,
|
||||
const uint8_t *buf,
|
||||
size_t size)
|
||||
{
|
||||
@ -1172,7 +1175,7 @@ int fido2_ctap_cbor_parse_make_credential_req(ctap_make_credential_req_t *req,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _parse_public_key_cose(CborValue *it, ctap_public_key_cose_t *cose_key)
|
||||
static ctap_status_code_t _parse_public_key_cose(CborValue *it, ctap_public_key_cose_t *cose_key)
|
||||
{
|
||||
int ret;
|
||||
int type;
|
||||
@ -1256,7 +1259,7 @@ static int _parse_public_key_cose(CborValue *it, ctap_public_key_cose_t *cose_ke
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _parse_entity(CborValue *it, void *entity, entity_type_t type)
|
||||
static ctap_status_code_t _parse_entity(CborValue *it, void *entity, entity_type_t type)
|
||||
{
|
||||
int ret;
|
||||
int cbor_type;
|
||||
@ -1386,7 +1389,7 @@ static int _parse_entity(CborValue *it, void *entity, entity_type_t type)
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _parse_pub_key_cred_params(CborValue *it,
|
||||
static ctap_status_code_t _parse_pub_key_cred_params(CborValue *it,
|
||||
ctap_make_credential_req_t *req)
|
||||
{
|
||||
int type;
|
||||
@ -1434,7 +1437,7 @@ static int _parse_pub_key_cred_params(CborValue *it,
|
||||
return CTAP2_ERR_UNSUPPORTED_ALGORITHM;
|
||||
}
|
||||
|
||||
static int _parse_pub_key_cred_param(CborValue *it, uint8_t *cred_type,
|
||||
static ctap_status_code_t _parse_pub_key_cred_param(CborValue *it, uint8_t *cred_type,
|
||||
int32_t *alg_type)
|
||||
{
|
||||
int ret;
|
||||
@ -1490,7 +1493,7 @@ static int _parse_pub_key_cred_param(CborValue *it, uint8_t *cred_type,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _parse_options(CborValue *it, ctap_options_t *options)
|
||||
static ctap_status_code_t _parse_options(CborValue *it, ctap_options_t *options)
|
||||
{
|
||||
int ret;
|
||||
int cbor_type;
|
||||
@ -1569,7 +1572,7 @@ static int _parse_options(CborValue *it, ctap_options_t *options)
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _parse_allow_list(CborValue *it, ctap_cred_desc_alt_t *allow_list,
|
||||
static ctap_status_code_t _parse_allow_list(CborValue *it, ctap_cred_desc_alt_t *allow_list,
|
||||
uint8_t *allow_list_len)
|
||||
{
|
||||
size_t len2 = *allow_list_len;
|
||||
@ -1579,7 +1582,7 @@ static int _parse_allow_list(CborValue *it, ctap_cred_desc_alt_t *allow_list,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int _parse_exclude_list(CborValue *it, ctap_cred_desc_alt_t *exclude_list,
|
||||
static ctap_status_code_t _parse_exclude_list(CborValue *it, ctap_cred_desc_alt_t *exclude_list,
|
||||
size_t *exclude_list_len)
|
||||
{
|
||||
int ret;
|
||||
@ -1620,7 +1623,8 @@ static int _parse_exclude_list(CborValue *it, ctap_cred_desc_alt_t *exclude_list
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _fido2_ctap_cbor_parse_cred_desc(CborValue *arr, ctap_cred_desc_alt_t *cred)
|
||||
static ctap_status_code_t _fido2_ctap_cbor_parse_cred_desc(CborValue *arr,
|
||||
ctap_cred_desc_alt_t *cred)
|
||||
{
|
||||
int ret;
|
||||
int type;
|
||||
@ -1685,7 +1689,7 @@ static int _fido2_ctap_cbor_parse_cred_desc(CborValue *arr, ctap_cred_desc_alt_t
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _parse_fixed_len_byte_array(CborValue *it, uint8_t *dst, size_t *len)
|
||||
static ctap_status_code_t _parse_fixed_len_byte_array(CborValue *it, uint8_t *dst, size_t *len)
|
||||
{
|
||||
int ret;
|
||||
int type;
|
||||
@ -1708,7 +1712,7 @@ static int _parse_fixed_len_byte_array(CborValue *it, uint8_t *dst, size_t *len)
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _parse_byte_array(CborValue *it, uint8_t *dst, size_t *len)
|
||||
static ctap_status_code_t _parse_byte_array(CborValue *it, uint8_t *dst, size_t *len)
|
||||
{
|
||||
int type;
|
||||
int ret;
|
||||
@ -1726,7 +1730,7 @@ static int _parse_byte_array(CborValue *it, uint8_t *dst, size_t *len)
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _parse_byte_array_u8len(CborValue *it, uint8_t *dst, uint8_t *len)
|
||||
static ctap_status_code_t _parse_byte_array_u8len(CborValue *it, uint8_t *dst, uint8_t *len)
|
||||
{
|
||||
size_t len2 = *len;
|
||||
int retval = _parse_byte_array(it, dst, &len2);
|
||||
@ -1735,7 +1739,7 @@ static int _parse_byte_array_u8len(CborValue *it, uint8_t *dst, uint8_t *len)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int _parse_text_string(CborValue *it, char *dst, size_t *len)
|
||||
static ctap_status_code_t _parse_text_string(CborValue *it, char *dst, size_t *len)
|
||||
{
|
||||
int type;
|
||||
int ret;
|
||||
@ -1755,7 +1759,7 @@ static int _parse_text_string(CborValue *it, char *dst, size_t *len)
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _parse_text_string_u8len(CborValue *it, char *dst, uint8_t *len)
|
||||
static ctap_status_code_t _parse_text_string_u8len(CborValue *it, char *dst, uint8_t *len)
|
||||
{
|
||||
size_t len2 = *len;
|
||||
int retval = _parse_text_string(it, dst, &len2);
|
||||
@ -1764,7 +1768,7 @@ static int _parse_text_string_u8len(CborValue *it, char *dst, uint8_t *len)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int _parse_int(CborValue *it, int *num)
|
||||
static ctap_status_code_t _parse_int(CborValue *it, int *num)
|
||||
{
|
||||
int type;
|
||||
int ret;
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "tiny-asn1.h"
|
||||
|
||||
#include "fido2/ctap/ctap_crypto.h"
|
||||
#include "fido2/ctap.h"
|
||||
#include "fido2/ctap/ctap_utils.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
@ -37,7 +36,7 @@
|
||||
/**
|
||||
* @brief Parse signature into ASN.1 DER format
|
||||
*/
|
||||
static int _sig_to_der_format(uint8_t *r, uint8_t *s, uint8_t *sig,
|
||||
static ctap_status_code_t _sig_to_der_format(uint8_t *r, uint8_t *s, uint8_t *sig,
|
||||
size_t *sig_len);
|
||||
|
||||
/**
|
||||
@ -45,72 +44,72 @@ static int _sig_to_der_format(uint8_t *r, uint8_t *s, uint8_t *sig,
|
||||
*
|
||||
* wrapper for @ref fido2_ctap_crypto_prng
|
||||
*/
|
||||
static int _RNG(uint8_t *dest, unsigned size);
|
||||
|
||||
int fido2_ctap_crypto_init(void)
|
||||
{
|
||||
uECC_set_rng(&_RNG);
|
||||
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _RNG(uint8_t *dest, unsigned size)
|
||||
{
|
||||
fido2_ctap_crypto_prng(dest, (size_t)size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_prng(uint8_t *buf, size_t len)
|
||||
ctap_status_code_t fido2_ctap_crypto_init(void)
|
||||
{
|
||||
uECC_set_rng(&_RNG);
|
||||
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
ctap_status_code_t fido2_ctap_crypto_prng(uint8_t *buf, size_t len)
|
||||
{
|
||||
random_bytes(buf, len);
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_sha256_init(sha256_context_t *ctx)
|
||||
ctap_status_code_t fido2_ctap_crypto_sha256_init(sha256_context_t *ctx)
|
||||
{
|
||||
sha256_init(ctx);
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_sha256_update(sha256_context_t *ctx, const void *data, size_t len)
|
||||
ctap_status_code_t fido2_ctap_crypto_sha256_update(sha256_context_t *ctx,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
sha256_update(ctx, data, len);
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_sha256_final(sha256_context_t *ctx, void *digest)
|
||||
ctap_status_code_t fido2_ctap_crypto_sha256_final(sha256_context_t *ctx, void *digest)
|
||||
{
|
||||
sha256_final(ctx, digest);
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_sha256(const void *data, size_t len,
|
||||
ctap_status_code_t fido2_ctap_crypto_sha256(const void *data, size_t len,
|
||||
void *digest)
|
||||
{
|
||||
sha256(data, len, digest);
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_hmac_sha256_init(hmac_context_t *ctx, const void *key,
|
||||
ctap_status_code_t fido2_ctap_crypto_hmac_sha256_init(hmac_context_t *ctx, const void *key,
|
||||
size_t key_length)
|
||||
{
|
||||
hmac_sha256_init(ctx, key, key_length);
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_hmac_sha256_update(hmac_context_t *ctx, const void *data, size_t len)
|
||||
ctap_status_code_t fido2_ctap_crypto_hmac_sha256_update(hmac_context_t *ctx,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
hmac_sha256_update(ctx, data, len);
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_hmac_sha256_final(hmac_context_t *ctx, void *digest)
|
||||
ctap_status_code_t fido2_ctap_crypto_hmac_sha256_final(hmac_context_t *ctx, void *digest)
|
||||
{
|
||||
hmac_sha256_final(ctx, digest);
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_hmac_sha256(const void *key,
|
||||
ctap_status_code_t fido2_ctap_crypto_hmac_sha256(const void *key,
|
||||
size_t key_length, const void *data, size_t len,
|
||||
void *digest)
|
||||
{
|
||||
@ -118,7 +117,7 @@ int fido2_ctap_crypto_hmac_sha256(const void *key,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_ecdh(uint8_t *out, size_t len,
|
||||
ctap_status_code_t fido2_ctap_crypto_ecdh(uint8_t *out, size_t len,
|
||||
ctap_crypto_pub_key_t *pub_key, uint8_t *priv_key, size_t key_len)
|
||||
{
|
||||
assert(len == CTAP_CRYPTO_KEY_SIZE);
|
||||
@ -136,7 +135,7 @@ int fido2_ctap_crypto_ecdh(uint8_t *out, size_t len,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_aes_enc(uint8_t *out, size_t *out_len, uint8_t *in,
|
||||
ctap_status_code_t fido2_ctap_crypto_aes_enc(uint8_t *out, size_t *out_len, uint8_t *in,
|
||||
size_t in_len, const uint8_t *key,
|
||||
size_t key_len)
|
||||
{
|
||||
@ -160,7 +159,7 @@ int fido2_ctap_crypto_aes_enc(uint8_t *out, size_t *out_len, uint8_t *in,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_aes_dec(uint8_t *out, size_t *out_len, uint8_t *in,
|
||||
ctap_status_code_t fido2_ctap_crypto_aes_dec(uint8_t *out, size_t *out_len, uint8_t *in,
|
||||
size_t in_len, const uint8_t *key,
|
||||
size_t key_len)
|
||||
{
|
||||
@ -184,7 +183,7 @@ int fido2_ctap_crypto_aes_dec(uint8_t *out, size_t *out_len, uint8_t *in,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_aes_ccm_enc(uint8_t *out, size_t out_len,
|
||||
ctap_status_code_t fido2_ctap_crypto_aes_ccm_enc(uint8_t *out, size_t out_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
uint8_t *auth_data, size_t auth_data_len,
|
||||
uint8_t mac_len, uint8_t length_encoding,
|
||||
@ -213,7 +212,7 @@ int fido2_ctap_crypto_aes_ccm_enc(uint8_t *out, size_t out_len,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_aes_ccm_dec(uint8_t *out, size_t out_len,
|
||||
ctap_status_code_t fido2_ctap_crypto_aes_ccm_dec(uint8_t *out, size_t out_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
uint8_t *auth_data, size_t auth_data_len,
|
||||
uint8_t mac_len, uint8_t length_encoding,
|
||||
@ -242,7 +241,7 @@ int fido2_ctap_crypto_aes_ccm_dec(uint8_t *out, size_t out_len,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_gen_keypair(ctap_crypto_pub_key_t *pub_key,
|
||||
ctap_status_code_t fido2_ctap_crypto_gen_keypair(ctap_crypto_pub_key_t *pub_key,
|
||||
uint8_t *priv_key, size_t len)
|
||||
{
|
||||
assert(len == CTAP_CRYPTO_KEY_SIZE);
|
||||
@ -258,7 +257,7 @@ int fido2_ctap_crypto_gen_keypair(ctap_crypto_pub_key_t *pub_key,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_crypto_get_sig(uint8_t *hash, size_t hash_len, uint8_t *sig,
|
||||
ctap_status_code_t fido2_ctap_crypto_get_sig(uint8_t *hash, size_t hash_len, uint8_t *sig,
|
||||
size_t *sig_len, const uint8_t *key,
|
||||
size_t key_len)
|
||||
{
|
||||
@ -293,7 +292,7 @@ int fido2_ctap_crypto_get_sig(uint8_t *hash, size_t hash_len, uint8_t *sig,
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _sig_to_der_format(uint8_t *r, uint8_t *s, uint8_t *sig,
|
||||
static ctap_status_code_t _sig_to_der_format(uint8_t *r, uint8_t *s, uint8_t *sig,
|
||||
size_t *sig_len)
|
||||
{
|
||||
asn1_tree t;
|
||||
|
@ -28,16 +28,22 @@
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef BOARD_NATIVE
|
||||
#include "mtd_default.h"
|
||||
/* native mtd is file backed => Start address of flash is 0. */
|
||||
char *_backing_memory = NULL;
|
||||
static mtd_dev_t *_mtd_dev = NULL;
|
||||
#else
|
||||
/**
|
||||
* @brief Reserve flash memory to store CTAP data
|
||||
*/
|
||||
FLASH_WRITABLE_INIT(_backing_memory, CONFIG_FIDO2_CTAP_NUM_FLASHPAGES);
|
||||
|
||||
/**
|
||||
* @brief MTD device descriptor initialized with flash-page driver
|
||||
*/
|
||||
static mtd_flashpage_t _mtd_flash_dev = MTD_FLASHPAGE_INIT_VAL(CTAP_FLASH_PAGES_PER_SECTOR);
|
||||
static mtd_dev_t *_mtd_dev = &_mtd_flash_dev.base;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Check if flash region is erased
|
||||
@ -52,15 +58,14 @@ static unsigned _amount_flashpages_rk(void);
|
||||
/**
|
||||
* @brief Write to flash memory
|
||||
*/
|
||||
static int _flash_write(const void *buf, uint32_t addr, size_t len);
|
||||
static ctap_status_code_t _flash_write(const void *buf, uint32_t addr, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Get start address of reserved flash memory region
|
||||
*/
|
||||
static unsigned _flash_start(void);
|
||||
|
||||
int fido2_ctap_mem_init(void)
|
||||
ctap_status_code_t fido2_ctap_mem_init(void)
|
||||
{
|
||||
#ifdef BOARD_NATIVE
|
||||
_mtd_dev = mtd_default_get_dev(0);
|
||||
#endif
|
||||
|
||||
int ret = mtd_init(_mtd_dev);
|
||||
|
||||
if (ret < 0) {
|
||||
@ -75,10 +80,9 @@ static unsigned _amount_flashpages_rk(void)
|
||||
return _mtd_dev->sector_count * _mtd_dev->pages_per_sector;
|
||||
}
|
||||
|
||||
int fido2_ctap_mem_read(void *buf, uint32_t page, uint32_t offset, uint32_t len)
|
||||
ctap_status_code_t fido2_ctap_mem_read(void *buf, uint32_t page, uint32_t offset, uint32_t len)
|
||||
{
|
||||
assert(buf);
|
||||
|
||||
int ret;
|
||||
|
||||
ret = mtd_read_page(_mtd_dev, buf, page, offset, len);
|
||||
@ -90,7 +94,7 @@ int fido2_ctap_mem_read(void *buf, uint32_t page, uint32_t offset, uint32_t len)
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
static int _flash_write(const void *buf, uint32_t addr, size_t len)
|
||||
static ctap_status_code_t _flash_write(const void *buf, uint32_t addr, size_t len)
|
||||
{
|
||||
assert(buf);
|
||||
int ret;
|
||||
@ -119,6 +123,9 @@ static int _flash_write(const void *buf, uint32_t addr, size_t len)
|
||||
|
||||
static bool _flash_is_erased(uint32_t addr, size_t len)
|
||||
{
|
||||
#ifdef BOARD_NATIVE
|
||||
return true;
|
||||
#else
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (*(uint32_t *)(addr + i) != FLASHPAGE_ERASE_STATE) {
|
||||
return false;
|
||||
@ -126,34 +133,35 @@ static bool _flash_is_erased(uint32_t addr, size_t len)
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned _flash_start(void)
|
||||
static uint32_t _flash_start_addr(void)
|
||||
{
|
||||
return flashpage_page((void *)_backing_memory);
|
||||
return (uint32_t)_backing_memory;
|
||||
}
|
||||
|
||||
int fido2_ctap_mem_erase_flash(void)
|
||||
ctap_status_code_t fido2_ctap_mem_erase_flash(void)
|
||||
{
|
||||
unsigned start = _flash_start();
|
||||
unsigned end = start + CONFIG_FIDO2_CTAP_NUM_FLASHPAGES;
|
||||
unsigned addr = _flash_start_addr();
|
||||
unsigned sector_size = _mtd_dev->pages_per_sector * _mtd_dev->page_size;
|
||||
|
||||
for (unsigned page = start; page < end; page++) {
|
||||
flashpage_erase(page);
|
||||
}
|
||||
int ret = mtd_erase(_mtd_dev, addr, sector_size * CONFIG_FIDO2_CTAP_NUM_FLASHPAGES);
|
||||
|
||||
return CTAP2_OK;
|
||||
return ret == 0 ? CTAP2_OK : CTAP1_ERR_OTHER;
|
||||
}
|
||||
|
||||
/**
|
||||
* CTAP state information is stored at flashpage 0 of the memory area
|
||||
* dedicated for storing CTAP data
|
||||
*/
|
||||
int fido2_ctap_mem_read_state_from_flash(ctap_state_t *state)
|
||||
ctap_status_code_t fido2_ctap_mem_read_state_from_flash(ctap_state_t *state)
|
||||
{
|
||||
uint32_t addr = (uint32_t)flashpage_addr(_flash_start());
|
||||
uint32_t addr = _flash_start_addr();
|
||||
|
||||
return mtd_read(_mtd_dev, state, addr, sizeof(ctap_state_t));
|
||||
int ret = mtd_read(_mtd_dev, state, addr, sizeof(ctap_state_t));
|
||||
|
||||
return ret == 0 ? CTAP2_OK : CTAP1_ERR_OTHER;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,10 +171,10 @@ int fido2_ctap_mem_read_state_from_flash(ctap_state_t *state)
|
||||
* so rk's can't be deleted, only overwritten => we can be sure that there are
|
||||
* no holes when reading keys from flash memory
|
||||
*/
|
||||
int fido2_ctap_mem_write_rk_to_flash(ctap_resident_key_t *rk)
|
||||
ctap_status_code_t fido2_ctap_mem_write_rk_to_flash(ctap_resident_key_t *rk)
|
||||
{
|
||||
int ret;
|
||||
uint32_t addr = (uint32_t)flashpage_addr(_flash_start() + CTAP_FLASH_RK_OFF);
|
||||
uint32_t addr = _flash_start_addr() + FLASHPAGE_SIZE;
|
||||
uint16_t amt_stored = fido2_ctap_get_state()->rk_amount_stored;
|
||||
ctap_resident_key_t tmp = { 0 };
|
||||
bool equal = false;
|
||||
@ -205,24 +213,23 @@ int fido2_ctap_mem_write_rk_to_flash(ctap_resident_key_t *rk)
|
||||
return _flash_write(rk, addr, CTAP_FLASH_RK_SZ);
|
||||
}
|
||||
|
||||
int fido2_ctap_mem_write_state_to_flash(ctap_state_t *state)
|
||||
ctap_status_code_t fido2_ctap_mem_write_state_to_flash(ctap_state_t *state)
|
||||
{
|
||||
uint32_t addr = (uint32_t)flashpage_addr(_flash_start());
|
||||
|
||||
return _flash_write(state, addr, CTAP_FLASH_STATE_SZ);
|
||||
return _flash_write(state, _flash_start_addr(), CTAP_FLASH_STATE_SZ);
|
||||
}
|
||||
|
||||
int fido2_ctap_mem_read_rk_from_flash(ctap_resident_key_t *key, uint8_t *rp_id_hash, uint32_t *addr)
|
||||
ctap_status_code_t fido2_ctap_mem_read_rk_from_flash(ctap_resident_key_t *key, uint8_t *rp_id_hash,
|
||||
uint32_t *addr)
|
||||
{
|
||||
uint16_t end;
|
||||
uint16_t amt_stored = fido2_ctap_get_state()->rk_amount_stored;
|
||||
|
||||
if (*addr == 0x0) {
|
||||
end = amt_stored;
|
||||
*addr = (uint32_t)flashpage_addr(_flash_start() + CTAP_FLASH_RK_OFF);
|
||||
*addr = _flash_start_addr() + FLASHPAGE_SIZE;
|
||||
}
|
||||
else {
|
||||
uint32_t start_addr = (uint32_t)flashpage_addr(_flash_start() + CTAP_FLASH_RK_OFF);
|
||||
uint32_t start_addr = _flash_start_addr() + FLASHPAGE_SIZE;
|
||||
uint16_t rks_read = (*addr - start_addr) / CTAP_FLASH_RK_SZ;
|
||||
|
||||
if (rks_read > amt_stored) {
|
||||
|
@ -44,7 +44,7 @@ static gpio_t _pin;
|
||||
*/
|
||||
static void _gpio_cb(void *arg);
|
||||
|
||||
int fido2_ctap_utils_init_gpio_pin(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank)
|
||||
ctap_status_code_t fido2_ctap_utils_init_gpio_pin(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank)
|
||||
{
|
||||
if (gpio_init_int(pin, mode, flank, _gpio_cb, NULL) < 0) {
|
||||
return CTAP1_ERR_OTHER;
|
||||
@ -55,7 +55,7 @@ int fido2_ctap_utils_init_gpio_pin(gpio_t pin, gpio_mode_t mode, gpio_flank_t fl
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
int fido2_ctap_utils_user_presence_test(void)
|
||||
ctap_status_code_t fido2_ctap_utils_user_presence_test(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "ztimer.h"
|
||||
#include "ztimer64.h"
|
||||
#include "usb/usbus.h"
|
||||
#include "usb/usbus/hid.h"
|
||||
#include "usb/usbus/hid_io.h"
|
||||
@ -478,9 +477,8 @@ static uint32_t _handle_init_packet(uint32_t cid, uint16_t bcnt,
|
||||
|
||||
static void _handle_cbor_packet(uint8_t cmd, uint32_t cid, uint8_t *buf, uint16_t bcnt)
|
||||
{
|
||||
ctap_resp_t resp;
|
||||
ctap_resp_t resp = {0x0};
|
||||
uint8_t err;
|
||||
size_t size;
|
||||
|
||||
if (bcnt == 0) {
|
||||
err = CTAP_HID_ERR_INVALID_LEN;
|
||||
@ -489,26 +487,24 @@ static void _handle_cbor_packet(uint8_t cmd, uint32_t cid, uint8_t *buf, uint16_
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&resp, 0, sizeof(ctap_resp_t));
|
||||
ctap_req_t req = {
|
||||
.method = *buf,
|
||||
.buf = buf + 1,
|
||||
.len = bcnt - 1
|
||||
};
|
||||
|
||||
ctap_req_t req;
|
||||
|
||||
req.method = *buf;
|
||||
req.buf = buf + 1;
|
||||
req.len = bcnt - 1;
|
||||
|
||||
size = fido2_ctap_handle_request(&req, &resp);
|
||||
ctap_status_code_t status = fido2_ctap_handle_request(&req, &resp);
|
||||
|
||||
/* transaction done, clear should_cancel flag */
|
||||
_state.should_cancel = false;
|
||||
|
||||
if (resp.status == CTAP2_OK && size > 0) {
|
||||
if (status == CTAP2_OK && resp.len > 0) {
|
||||
/* status + data */
|
||||
_ctap_hid_write(cmd, cid, &resp, size + sizeof(resp.status));
|
||||
_ctap_hid_write(cmd, cid, &resp, resp.len + sizeof(resp.status));
|
||||
}
|
||||
else {
|
||||
/* status only */
|
||||
_ctap_hid_write(cmd, cid, &resp.status, sizeof(resp.status));
|
||||
_ctap_hid_write(cmd, cid, &resp.status, sizeof(status));
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,7 +525,7 @@ bool fido2_ctap_transport_hid_should_cancel(void)
|
||||
|
||||
void fido2_ctap_transport_hid_check_timeouts(void)
|
||||
{
|
||||
uint64_t now = ztimer64_now(ZTIMER64_MSEC);
|
||||
uint32_t now = ztimer_now(ZTIMER_MSEC);
|
||||
|
||||
for (uint8_t i = 0; i < CTAP_HID_CIDS_MAX; i++) {
|
||||
/* transaction timed out because cont packets didn't arrive in time */
|
||||
@ -548,14 +544,14 @@ void fido2_ctap_transport_hid_check_timeouts(void)
|
||||
|
||||
static int8_t _add_cid(uint32_t cid)
|
||||
{
|
||||
uint64_t oldest = ztimer64_now(ZTIMER64_MSEC);
|
||||
uint32_t oldest = ztimer_now(ZTIMER_MSEC);
|
||||
int8_t index_oldest = -1;
|
||||
|
||||
for (int i = 0; i < CTAP_HID_CIDS_MAX; i++) {
|
||||
if (!g_cids[i].taken) {
|
||||
g_cids[i].taken = true;
|
||||
g_cids[i].cid = cid;
|
||||
g_cids[i].last_used = ztimer64_now(ZTIMER64_MSEC);
|
||||
g_cids[i].last_used = ztimer_now(ZTIMER_MSEC);
|
||||
|
||||
return CTAP_HID_OK;
|
||||
}
|
||||
@ -570,7 +566,7 @@ static int8_t _add_cid(uint32_t cid)
|
||||
if (index_oldest > -1) {
|
||||
g_cids[index_oldest].taken = true;
|
||||
g_cids[index_oldest].cid = cid;
|
||||
g_cids[index_oldest].last_used = ztimer64_now(ZTIMER64_MSEC);
|
||||
g_cids[index_oldest].last_used = ztimer_now(ZTIMER_MSEC);
|
||||
return CTAP_HID_OK;
|
||||
}
|
||||
|
||||
@ -581,7 +577,7 @@ static int8_t _refresh_cid(uint32_t cid)
|
||||
{
|
||||
for (int i = 0; i < CTAP_HID_CIDS_MAX; i++) {
|
||||
if (g_cids[i].cid == cid) {
|
||||
g_cids[i].last_used = ztimer64_now(ZTIMER64_MSEC);
|
||||
g_cids[i].last_used = ztimer_now(ZTIMER_MSEC);
|
||||
return CTAP_HID_OK;
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,22 @@ typedef enum {
|
||||
CTAP2_ERR_EXTENSION_LAST = 0xEF,
|
||||
CTAP2_ERR_VENDOR_FIRST = 0xF0,
|
||||
CTAP2_ERR_VENDOR_LAST = 0xFF
|
||||
} ctap_status_codes_t;
|
||||
} ctap_status_code_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief CTAP methods
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
typedef enum {
|
||||
CTAP_MAKE_CREDENTIAL = 0x01,
|
||||
CTAP_GET_ASSERTION = 0x02,
|
||||
CTAP_GET_INFO = 0x04,
|
||||
CTAP_CLIENT_PIN = 0x06,
|
||||
CTAP_RESET = 0x07,
|
||||
CTAP_GET_NEXT_ASSERTION = 0x08
|
||||
} ctap_method_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -118,17 +133,17 @@ typedef struct {
|
||||
* CTAP specification (version 20190130) section 6.2
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t status; /**< response status */
|
||||
ctap_status_code_t status; /**< response status */
|
||||
uint8_t data[CTAP_MAX_MSG_SIZE]; /**< response data */
|
||||
size_t len; /**< length of response data */
|
||||
} ctap_resp_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize ctap
|
||||
*
|
||||
* @return 0 for success
|
||||
* @return negative error code otherwise
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_init(void);
|
||||
ctap_status_code_t fido2_ctap_init(void);
|
||||
|
||||
/**
|
||||
* @brief Handle CBOR encoded ctap request.
|
||||
@ -139,9 +154,9 @@ int fido2_ctap_init(void);
|
||||
* @param[in] req request struct
|
||||
* @param[in] resp response struct
|
||||
*
|
||||
* @return Length of @p resp->data
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
size_t fido2_ctap_handle_request(ctap_req_t *req, ctap_resp_t *resp);
|
||||
ctap_status_code_t fido2_ctap_handle_request(ctap_req_t *req, ctap_resp_t *resp);
|
||||
|
||||
/**
|
||||
* @brief MakeCredential method
|
||||
@ -151,9 +166,9 @@ size_t fido2_ctap_handle_request(ctap_req_t *req, ctap_resp_t *resp);
|
||||
* @param[in] req CTAP request
|
||||
* @param[in, out] resp CTAP response
|
||||
*
|
||||
* @return Length of @p resp->data
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
size_t fido2_ctap_make_credential(ctap_req_t *req, ctap_resp_t *resp);
|
||||
ctap_status_code_t fido2_ctap_make_credential(ctap_req_t *req, ctap_resp_t *resp);
|
||||
|
||||
/**
|
||||
* @brief GetAssertion method
|
||||
@ -163,9 +178,9 @@ size_t fido2_ctap_make_credential(ctap_req_t *req, ctap_resp_t *resp);
|
||||
* @param[in] req CTAP request
|
||||
* @param[in, out] resp CTAP response
|
||||
*
|
||||
* @return Length of @p resp->data
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
size_t fido2_ctap_get_assertion(ctap_req_t *req, ctap_resp_t *resp);
|
||||
ctap_status_code_t fido2_ctap_get_assertion(ctap_req_t *req, ctap_resp_t *resp);
|
||||
|
||||
/**
|
||||
* @brief GetNextAssertion method
|
||||
@ -174,9 +189,9 @@ size_t fido2_ctap_get_assertion(ctap_req_t *req, ctap_resp_t *resp);
|
||||
*
|
||||
* @param[in, out] resp CTAP response
|
||||
*
|
||||
* @return Length of @p resp->data
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
size_t fido2_ctap_get_next_assertion(ctap_resp_t *resp);
|
||||
ctap_status_code_t fido2_ctap_get_next_assertion(ctap_resp_t *resp);
|
||||
|
||||
/**
|
||||
* @brief GetInfo method
|
||||
@ -185,9 +200,9 @@ size_t fido2_ctap_get_next_assertion(ctap_resp_t *resp);
|
||||
*
|
||||
* @param[in, out] resp CTAP response
|
||||
*
|
||||
* @return Length of @p resp->data
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
size_t fido2_ctap_get_info(ctap_resp_t *resp);
|
||||
ctap_status_code_t fido2_ctap_get_info(ctap_resp_t *resp);
|
||||
|
||||
/**
|
||||
* @brief ClientPIN method
|
||||
@ -197,9 +212,9 @@ size_t fido2_ctap_get_info(ctap_resp_t *resp);
|
||||
* @param[in] req CTAP request
|
||||
* @param[in, out] resp CTAP response
|
||||
*
|
||||
* @return Length of @p resp->data
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
size_t fido2_ctap_client_pin(ctap_req_t *req, ctap_resp_t *resp);
|
||||
ctap_status_code_t fido2_ctap_client_pin(ctap_req_t *req, ctap_resp_t *resp);
|
||||
|
||||
/**
|
||||
* @brief Reset method
|
||||
@ -208,9 +223,9 @@ size_t fido2_ctap_client_pin(ctap_req_t *req, ctap_resp_t *resp);
|
||||
*
|
||||
* @param[in, out] resp CTAP response
|
||||
*
|
||||
* @return Length of @p resp->data
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
size_t fido2_ctap_reset(ctap_resp_t *resp);
|
||||
ctap_status_code_t fido2_ctap_reset(ctap_resp_t *resp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -50,19 +50,6 @@ extern "C" {
|
||||
*/
|
||||
#define CTAP_PIN_AUTH_SZ 16
|
||||
|
||||
/**
|
||||
* @name CTAP methods
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#define CTAP_MAKE_CREDENTIAL 0x01 /**< authenticatorMakeCredential method */
|
||||
#define CTAP_GET_ASSERTION 0x02 /**< authenticatorGetAssertion method */
|
||||
#define CTAP_GET_INFO 0x04 /**< authenticatorGetInfo method */
|
||||
#define CTAP_CLIENT_PIN 0x06 /**< authenticatorClientPIN method */
|
||||
#define CTAP_RESET 0x07 /**< authenticatorReset method */
|
||||
#define CTAP_GET_NEXT_ASSERTION 0x08 /**< authenticatorGetNextAssertion method */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name CTAP authenticator data option flags
|
||||
*
|
||||
@ -111,15 +98,17 @@ extern "C" {
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name CTAP Client PIN request subCommand CBOR key values
|
||||
* @brief CTAP Client PIN request subCommand CBOR key values
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#define CTAP_CP_REQ_SUB_COMMAND_GET_RETRIES 0x01 /**< getRetries subCommand */
|
||||
#define CTAP_CP_REQ_SUB_COMMAND_GET_KEY_AGREEMENT 0x02 /**< getKeyAgreement subCommand */
|
||||
#define CTAP_CP_REQ_SUB_COMMAND_SET_PIN 0x03 /**< setPIN subCommand */
|
||||
#define CTAP_CP_REQ_SUB_COMMAND_CHANGE_PIN 0x04 /**< changePIN subCommand */
|
||||
#define CTAP_CP_REQ_SUB_COMMAND_GET_PIN_TOKEN 0x05 /**< getPinToken subCommand */
|
||||
typedef enum {
|
||||
CTAP_PIN_GET_RETRIES = 0x01, /**< getRetries subCommand */
|
||||
CTAP_PIN_GET_KEY_AGREEMENT = 0x02, /**< getKeyAgreement subCommand */
|
||||
CTAP_PIN_SET_PIN = 0x03, /**< setPIN subCommand */
|
||||
CTAP_PIN_CHANGE_PIN = 0x04, /**< changePIN subCommand */
|
||||
CTAP_PIN_GET_PIN_TOKEN = 0x05 /**< getPinToken subCommand */
|
||||
} ctap_pin_subcommand_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -572,7 +561,7 @@ typedef struct {
|
||||
uint8_t pin_auth[CTAP_PIN_AUTH_SZ]; /**< first 16 bytes of HMAC-SHA-256 of encrypted contents */
|
||||
uint8_t new_pin_enc[CTAP_PIN_ENC_MAX_SIZE]; /**< Encrypted new PIN using sharedSecret. */
|
||||
uint8_t pin_hash_enc[SHA256_DIGEST_LENGTH / 2]; /**< Encrypted first 16 bytes of SHA-256 of PIN using sharedSecret. */
|
||||
uint8_t sub_command; /**< authenticator Client PIN sub command */
|
||||
ctap_pin_subcommand_t sub_command; /**< ClientPIN sub command */
|
||||
uint8_t pin_protocol; /**< PIN protocol version chosen by the client */
|
||||
bool pin_hash_enc_present; /**< indicate pin_hash_enc is present */
|
||||
bool pin_auth_present; /**< indicate if pin_auth present */
|
||||
@ -642,7 +631,7 @@ typedef struct {
|
||||
* @param[in] sig signature buffer
|
||||
* @param[in] sig_len length of @p sig
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_get_sig(const uint8_t *auth_data, size_t auth_data_len,
|
||||
const uint8_t *client_data_hash,
|
||||
@ -668,7 +657,7 @@ bool fido2_ctap_cred_params_supported(uint8_t cred_type, int32_t alg_type);
|
||||
* @param[in] nonce_len length of @p nonce
|
||||
* @param[in] id credential id struct storing encrypted resident key
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_encrypt_rk(ctap_resident_key_t *rk, uint8_t *nonce,
|
||||
size_t nonce_len, ctap_cred_id_t *id);
|
||||
|
@ -212,9 +212,9 @@ extern "C" {
|
||||
* @param[in] req_raw raw request
|
||||
* @param[in] len length of @p req_raw
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_cbor_parse_make_credential_req(ctap_make_credential_req_t *req,
|
||||
ctap_status_code_t fido2_ctap_cbor_parse_make_credential_req(ctap_make_credential_req_t *req,
|
||||
const uint8_t *req_raw, size_t len);
|
||||
|
||||
/**
|
||||
@ -226,9 +226,9 @@ int fido2_ctap_cbor_parse_make_credential_req(ctap_make_credential_req_t *req,
|
||||
* @param[in] req_raw raw request
|
||||
* @param[in] len length of @p req_raw
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_cbor_parse_get_assertion_req(ctap_get_assertion_req_t *req,
|
||||
ctap_status_code_t fido2_ctap_cbor_parse_get_assertion_req(ctap_get_assertion_req_t *req,
|
||||
const uint8_t *req_raw, size_t len);
|
||||
|
||||
/**
|
||||
@ -238,10 +238,10 @@ int fido2_ctap_cbor_parse_get_assertion_req(ctap_get_assertion_req_t *req,
|
||||
*
|
||||
* @param[in] info information about capabilities
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
|
||||
int fido2_ctap_cbor_encode_info(const ctap_info_t *info);
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_info(const ctap_info_t *info);
|
||||
/**
|
||||
* @brief Parse ClientPIN method
|
||||
*
|
||||
@ -251,9 +251,9 @@ int fido2_ctap_cbor_encode_info(const ctap_info_t *info);
|
||||
* @param[in] req_raw raw request
|
||||
* @param[in] len length of @p req_raw
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_cbor_parse_client_pin_req(ctap_client_pin_req_t *req,
|
||||
ctap_status_code_t fido2_ctap_cbor_parse_client_pin_req(ctap_client_pin_req_t *req,
|
||||
const uint8_t *req_raw, size_t len);
|
||||
/**
|
||||
* @brief Encode attestation object
|
||||
@ -264,9 +264,9 @@ int fido2_ctap_cbor_parse_client_pin_req(ctap_client_pin_req_t *req,
|
||||
* @param[in] client_data_hash SHA-256 hash of JSON serialized client data
|
||||
* @param[in] rk resident key
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_cbor_encode_attestation_object(const ctap_auth_data_t *auth_data,
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_attestation_object(const ctap_auth_data_t *auth_data,
|
||||
const uint8_t *client_data_hash,
|
||||
ctap_resident_key_t *rk);
|
||||
|
||||
@ -280,9 +280,9 @@ int fido2_ctap_cbor_encode_attestation_object(const ctap_auth_data_t *auth_data,
|
||||
* @param[in] rk resident key
|
||||
* @param[in] valid_cred_count amount of valid credentials found in allow list
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_cbor_encode_assertion_object(const ctap_auth_data_header_t *auth_data,
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_assertion_object(const ctap_auth_data_header_t *auth_data,
|
||||
const uint8_t *client_data_hash,
|
||||
ctap_resident_key_t *rk,
|
||||
uint8_t valid_cred_count);
|
||||
@ -291,9 +291,9 @@ int fido2_ctap_cbor_encode_assertion_object(const ctap_auth_data_header_t *auth_
|
||||
*
|
||||
* @param[in] key Public key in COSE format
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_cbor_encode_key_agreement(const ctap_public_key_cose_t *key);
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_key_agreement(const ctap_public_key_cose_t *key);
|
||||
|
||||
/**
|
||||
* @brief Encode encrypted pin token
|
||||
@ -301,18 +301,18 @@ int fido2_ctap_cbor_encode_key_agreement(const ctap_public_key_cose_t *key);
|
||||
* @param[in] token encrypted pin token
|
||||
* @param[in] len length of @p token
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_cbor_encode_pin_token(uint8_t *token, size_t len);
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_pin_token(uint8_t *token, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Encode PIN tries left
|
||||
*
|
||||
* @param[in] tries_left amount of tries left
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_cbor_encode_retries(uint8_t tries_left);
|
||||
ctap_status_code_t fido2_ctap_cbor_encode_retries(uint8_t tries_left);
|
||||
|
||||
/**
|
||||
* @brief Get size of CBOR encoded data
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hashes/sha256.h"
|
||||
#include "fido2/ctap.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -64,9 +65,9 @@ typedef struct {
|
||||
*
|
||||
* Initializes crypto libs and creates key_agreement key pair
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_init(void);
|
||||
ctap_status_code_t fido2_ctap_crypto_init(void);
|
||||
|
||||
/**
|
||||
* @brief Wrapper function for @ref random_bytes
|
||||
@ -74,18 +75,18 @@ int fido2_ctap_crypto_init(void);
|
||||
* @param[in] buf buffer to hold random bytes
|
||||
* @param[in] len length of @p buf
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_prng(uint8_t *buf, size_t len);
|
||||
ctap_status_code_t fido2_ctap_crypto_prng(uint8_t *buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Wrapper function for @ref sha256_init
|
||||
*
|
||||
* @param ctx sha256_context_t handle to init
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_sha256_init(sha256_context_t *ctx);
|
||||
ctap_status_code_t fido2_ctap_crypto_sha256_init(sha256_context_t *ctx);
|
||||
|
||||
/**
|
||||
* @brief Wrapper function for @ref sha256_update
|
||||
@ -94,9 +95,9 @@ int fido2_ctap_crypto_sha256_init(sha256_context_t *ctx);
|
||||
* @param[in] data Input data
|
||||
* @param[in] len Length of @p data
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_sha256_update(sha256_context_t *ctx, const void *data, size_t len);
|
||||
ctap_status_code_t fido2_ctap_crypto_sha256_update(sha256_context_t *ctx, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Wrapper for @ref sha256_final
|
||||
@ -104,9 +105,9 @@ int fido2_ctap_crypto_sha256_update(sha256_context_t *ctx, const void *data, siz
|
||||
* @param ctx sha256_context_t handle to use
|
||||
* @param digest resulting digest, this is the hash of all the bytes
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_sha256_final(sha256_context_t *ctx, void *digest);
|
||||
ctap_status_code_t fido2_ctap_crypto_sha256_final(sha256_context_t *ctx, void *digest);
|
||||
|
||||
/**
|
||||
* @brief Wrapper function for @ref sha256
|
||||
@ -118,9 +119,9 @@ int fido2_ctap_crypto_sha256_final(sha256_context_t *ctx, void *digest);
|
||||
*
|
||||
* @note discards the pointer returned by @ref sha256
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_sha256(const void *data, size_t len,
|
||||
ctap_status_code_t fido2_ctap_crypto_sha256(const void *data, size_t len,
|
||||
void *digest);
|
||||
|
||||
/**
|
||||
@ -130,9 +131,9 @@ int fido2_ctap_crypto_sha256(const void *data, size_t len,
|
||||
* @param[in] key key used in the hmac-sha256 computation
|
||||
* @param[in] key_length length of @p key
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_hmac_sha256_init(hmac_context_t *ctx, const void *key,
|
||||
ctap_status_code_t fido2_ctap_crypto_hmac_sha256_init(hmac_context_t *ctx, const void *key,
|
||||
size_t key_length);
|
||||
|
||||
/**
|
||||
@ -142,9 +143,9 @@ int fido2_ctap_crypto_hmac_sha256_init(hmac_context_t *ctx, const void *key,
|
||||
* @param[in] data pointer to the buffer to generate hash from
|
||||
* @param[in] len length of @p data
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_hmac_sha256_update(hmac_context_t *ctx, const void *data, size_t len);
|
||||
ctap_status_code_t fido2_ctap_crypto_hmac_sha256_update(hmac_context_t *ctx, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Wrapper function for @ref hmac_sha256_final
|
||||
@ -153,9 +154,9 @@ int fido2_ctap_crypto_hmac_sha256_update(hmac_context_t *ctx, const void *data,
|
||||
* @param[out] digest the computed hmac-sha256,
|
||||
* length MUST be SHA256_DIGEST_LENGTH
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_hmac_sha256_final(hmac_context_t *ctx, void *digest);
|
||||
ctap_status_code_t fido2_ctap_crypto_hmac_sha256_final(hmac_context_t *ctx, void *digest);
|
||||
|
||||
/**
|
||||
* @brief Wrapper function for @ref hmac_sha256
|
||||
@ -169,9 +170,9 @@ int fido2_ctap_crypto_hmac_sha256_final(hmac_context_t *ctx, void *digest);
|
||||
*
|
||||
* @note discards the pointer returned by @ref hmac_sha256
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_hmac_sha256(const void *key,
|
||||
ctap_status_code_t fido2_ctap_crypto_hmac_sha256(const void *key,
|
||||
size_t key_length, const void *data, size_t len,
|
||||
void *digest);
|
||||
|
||||
@ -182,9 +183,9 @@ int fido2_ctap_crypto_hmac_sha256(const void *key,
|
||||
* @param[in] priv_key private key buffer
|
||||
* @param[in] len length of @p priv_key
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_gen_keypair(ctap_crypto_pub_key_t *pub_key, uint8_t *priv_key, size_t len);
|
||||
ctap_status_code_t fido2_ctap_crypto_gen_keypair(ctap_crypto_pub_key_t *pub_key, uint8_t *priv_key, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Elliptic-curve Diffie-Hellmann
|
||||
@ -195,9 +196,9 @@ int fido2_ctap_crypto_gen_keypair(ctap_crypto_pub_key_t *pub_key, uint8_t *priv_
|
||||
* @param[in] priv_key private key
|
||||
* @param[in] key_len length of @p priv_key
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_ecdh(uint8_t *out, size_t len,
|
||||
ctap_status_code_t fido2_ctap_crypto_ecdh(uint8_t *out, size_t len,
|
||||
ctap_crypto_pub_key_t *pub_key, uint8_t *priv_key, size_t key_len);
|
||||
|
||||
/**
|
||||
@ -210,9 +211,9 @@ int fido2_ctap_crypto_ecdh(uint8_t *out, size_t len,
|
||||
* @param[in] key private key to use for signature
|
||||
* @param[in] key_len length of @p key
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_get_sig(uint8_t *hash, size_t hash_len, uint8_t *sig,
|
||||
ctap_status_code_t fido2_ctap_crypto_get_sig(uint8_t *hash, size_t hash_len, uint8_t *sig,
|
||||
size_t *sig_len, const uint8_t *key, size_t key_len);
|
||||
|
||||
/**
|
||||
@ -225,9 +226,9 @@ int fido2_ctap_crypto_get_sig(uint8_t *hash, size_t hash_len, uint8_t *sig,
|
||||
* @param[in] key symmetric key to use for encryption
|
||||
* @param[in] key_len length of @p key
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_aes_enc(uint8_t * out, size_t *out_len, uint8_t * in,
|
||||
ctap_status_code_t fido2_ctap_crypto_aes_enc(uint8_t * out, size_t *out_len, uint8_t * in,
|
||||
size_t in_len, const uint8_t * key, size_t key_len);
|
||||
|
||||
/**
|
||||
@ -240,9 +241,9 @@ int fido2_ctap_crypto_aes_enc(uint8_t * out, size_t *out_len, uint8_t * in,
|
||||
* @param[in] key symmetric key to use for decryption
|
||||
* @param[in] key_len length of @p key
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_aes_dec(uint8_t * out, size_t *out_len, uint8_t * in,
|
||||
ctap_status_code_t fido2_ctap_crypto_aes_dec(uint8_t * out, size_t *out_len, uint8_t * in,
|
||||
size_t in_len, const uint8_t * key, size_t key_len);
|
||||
|
||||
/**
|
||||
@ -261,9 +262,9 @@ int fido2_ctap_crypto_aes_dec(uint8_t * out, size_t *out_len, uint8_t * in,
|
||||
* @param[in] key symmetric key to use for encryption
|
||||
* @param[in] key_len length of @p key
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_aes_ccm_enc(uint8_t *out, size_t out_len,
|
||||
ctap_status_code_t fido2_ctap_crypto_aes_ccm_enc(uint8_t *out, size_t out_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
uint8_t *auth_data, size_t auth_data_len,
|
||||
uint8_t mac_len, uint8_t length_encoding,
|
||||
@ -286,9 +287,9 @@ int fido2_ctap_crypto_aes_ccm_enc(uint8_t *out, size_t out_len,
|
||||
* @param[in] key symmetric key to use for encryption
|
||||
* @param[in] key_len length of @p key
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_crypto_aes_ccm_dec(uint8_t *out, size_t out_len,
|
||||
ctap_status_code_t fido2_ctap_crypto_aes_ccm_dec(uint8_t *out, size_t out_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
uint8_t *auth_data, size_t auth_data_len,
|
||||
uint8_t mac_len, uint8_t length_encoding,
|
||||
|
@ -100,9 +100,9 @@ extern "C" {
|
||||
/**
|
||||
* @brief Initialize memory helper
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_mem_init(void);
|
||||
ctap_status_code_t fido2_ctap_mem_init(void);
|
||||
|
||||
/**
|
||||
* @brief Read from flash memory
|
||||
@ -112,34 +112,34 @@ int fido2_ctap_mem_init(void);
|
||||
* @param[in] offset offset from the start of the page (in bytes)
|
||||
* @param[in] len number of bytes to write
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_mem_read(void *buf, uint32_t page, uint32_t offset, uint32_t len);
|
||||
ctap_status_code_t fido2_ctap_mem_read(void *buf, uint32_t page, uint32_t offset, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief Erase all flashpages containing CTAP data
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_mem_erase_flash(void);
|
||||
ctap_status_code_t fido2_ctap_mem_erase_flash(void);
|
||||
|
||||
/**
|
||||
* @brief Read authenticator state from flash
|
||||
*
|
||||
* @param[in] state pointer to authenticator state
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_mem_read_state_from_flash(ctap_state_t *state);
|
||||
ctap_status_code_t fido2_ctap_mem_read_state_from_flash(ctap_state_t *state);
|
||||
|
||||
/**
|
||||
* @brief Write authenticator state to flash
|
||||
*
|
||||
* @param[in] state pointer to authenticator state
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_mem_write_state_to_flash(ctap_state_t *state);
|
||||
ctap_status_code_t fido2_ctap_mem_write_state_to_flash(ctap_state_t *state);
|
||||
|
||||
/**
|
||||
* @brief Find resident credential for @p rp_id_hash in flash
|
||||
@ -153,19 +153,19 @@ int fido2_ctap_mem_write_state_to_flash(ctap_state_t *state);
|
||||
* @param[in] rp_id_hash pointer to hash of rp domain string
|
||||
* @param[in] addr pointer to address where to read from
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_mem_read_rk_from_flash(ctap_resident_key_t *key, uint8_t *rp_id_hash,
|
||||
uint32_t *addr);
|
||||
ctap_status_code_t fido2_ctap_mem_read_rk_from_flash(ctap_resident_key_t *key, uint8_t *rp_id_hash,
|
||||
uint32_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Write resident credential to flash
|
||||
*
|
||||
* @param[in] rk pointer to resident credential
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_mem_write_rk_to_flash(ctap_resident_key_t *rk);
|
||||
ctap_status_code_t fido2_ctap_mem_write_rk_to_flash(ctap_resident_key_t *rk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -38,18 +38,18 @@ void fido2_ctap_utils_led_animation(void);
|
||||
/**
|
||||
* @brief Initialize button to be used for user presence test
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_utils_init_gpio_pin(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank);
|
||||
ctap_status_code_t fido2_ctap_utils_init_gpio_pin(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank);
|
||||
|
||||
/**
|
||||
* @brief Test user presence
|
||||
*
|
||||
* Successful if user clicks button in less than @ref CTAP_UP_TIMEOUT
|
||||
*
|
||||
* @return @ref ctap_status_codes_t
|
||||
* @return @ref ctap_status_code_t
|
||||
*/
|
||||
int fido2_ctap_utils_user_presence_test(void);
|
||||
ctap_status_code_t fido2_ctap_utils_user_presence_test(void);
|
||||
|
||||
/**
|
||||
* @brief Compare fido2 credentials based on id to find more recent one
|
||||
|
@ -208,7 +208,7 @@ typedef struct __attribute__((packed)){
|
||||
typedef struct {
|
||||
bool taken; /**< is cid taken? */
|
||||
uint32_t cid; /**< channel identifier */
|
||||
uint64_t last_used; /**< timestamp of last usage */
|
||||
uint32_t last_used; /**< timestamp of last usage */
|
||||
} ctap_hid_cid_t;
|
||||
|
||||
/**
|
||||
|
@ -1,39 +1,24 @@
|
||||
BOARD ?= nrf52840dk
|
||||
#BOARD ?= nrf52840dongle
|
||||
BOARD ?= native
|
||||
|
||||
include ../Makefile.sys_common
|
||||
|
||||
USEMODULE += fido2_ctap_transport_hid
|
||||
USEMODULE += usbus
|
||||
USEMODULE += ztimer_sec
|
||||
USEPKG += fido2_tests
|
||||
BOARD_WHITELIST = \
|
||||
native \
|
||||
nrf52840dk \
|
||||
nrf52840dongle
|
||||
|
||||
USB_VID ?= $(USB_VID_TESTING)
|
||||
USB_PID ?= $(USB_PID_TESTING)
|
||||
# same as CTAP_STACKSIZE
|
||||
CFLAGS += -DTHREAD_STACKSIZE_MAIN=15000
|
||||
|
||||
# Add unittest framework
|
||||
USEMODULE += embunit
|
||||
|
||||
USEMODULE += fido2_ctap
|
||||
|
||||
# Disable user presence tests
|
||||
# Should be used when running fido2-test to make them run quicker
|
||||
#CFLAGS += -DCONFIG_FIDO2_CTAP_DISABLE_UP=1
|
||||
CFLAGS += -DCONFIG_FIDO2_CTAP_DISABLE_UP=1
|
||||
|
||||
# Disable user LED animation
|
||||
#CFLAGS += -DCONFIG_FIDO2_CTAP_DISABLE_LED=1
|
||||
|
||||
# FIDO2 tests except for the ones requiring user presence
|
||||
#
|
||||
# Use env -i because fido2-test has a depedency (pyscard) that needs to be
|
||||
# compiled natively (x86-64). Therefore we need to clear the flags set by e.g.
|
||||
# BOARD = nrf52840dk
|
||||
fido2-test:
|
||||
env -i PATH=$(PATH) $(MAKE) -C $(PKGDIRBASE)/fido2_tests
|
||||
|
||||
# FIDO2 user presence tests.
|
||||
#
|
||||
# Make sure to enable user presence tests by uncommenting CFLAGS += -DCONFIG_FIDO2_CTAP_DISABLE_UP=1
|
||||
#
|
||||
# Use env -i because fido2-test has a depedency (pyscard) that needs to be
|
||||
# compiled natively (x86-64). Therefore we need to clear the flags set by e.g.
|
||||
# BOARD = nrf52840dk
|
||||
fido2-test-up:
|
||||
env -i PATH=$(PATH) $(MAKE) -C $(PKGDIRBASE)/fido2_tests up-tests
|
||||
CFLAGS += -DCONFIG_FIDO2_CTAP_DISABLE_LED=1
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
@ -1,59 +1,16 @@
|
||||
# Test Application for FIDO2 CTAP
|
||||
# Overview
|
||||
|
||||
This test aims to test the FIDO2 CTAP implementation by creating a FIDO2
|
||||
authenticator which uses CTAPHID as communication protocol.
|
||||
This test application tests FIDO2 CTAP2 functionality without a transport layer being used.
|
||||
|
||||
Note:
|
||||
* This test application has only been tested on an nrf52840 DK.
|
||||
To execute the test run e.g.
|
||||
|
||||
The test application requires at least 16536 bytes of stack memory which are
|
||||
divided as follows:
|
||||
* 512 bytes isr_stack
|
||||
* 1024 usbus
|
||||
* 15000 bytes FIDO2 CTAP
|
||||
```
|
||||
BOARD = nrf52840dk make flash test
|
||||
```
|
||||
|
||||
## Usage
|
||||
The FIDO2 authenticator can be tested in two ways:
|
||||
To generate a new test case array run:
|
||||
* Note: This requires the [python-fido lib](https://github.com/Yubico/python-fido2)
|
||||
|
||||
### Functional testing
|
||||
1. Flash the device with `make flash`.
|
||||
2. Test the authenticator on a website like [Webauthn.io](https://webauthn.io/).
|
||||
|
||||
Note:
|
||||
* Due to limited support of FIDO2 CTAP in browsers as of now, make sure to use the
|
||||
Chromium or Google Chrome browser when testing on [Webauthn.io](https://webauthn.io/).
|
||||
* When registering and authenticating on [Webauthn.io](https://webauthn.io/) you
|
||||
will need to push button 1 on your device in order to show user presence.
|
||||
|
||||
**Resetting the authenticator**
|
||||
* To reset the authenticator, meaning that all credentials and state information
|
||||
will be deleted, execute the `reset.py` file located in this directory.
|
||||
* This requires you to install the python fido2 package. To install run:
|
||||
`pip install fido2==0.8.1`.
|
||||
|
||||
### Unit testing
|
||||
Unit testing is based on the `fido2_tests` package.
|
||||
|
||||
There are two test targets (fido2-test, fido2-test-up). The former requires no user
|
||||
interaction the latter does.
|
||||
|
||||
Note:
|
||||
* The tests require python 3.6+.
|
||||
* The tests require [swig](http://www.swig.org/) to be installed on your host computer.
|
||||
* Running the tests for the first time will setup a virtual python environment (venv) and install python dependencies of the tests. To check the dependencies please refer to the `requirements.txt` of the [fido2-tests repository](https://github.com/solokeys/fido2-tests).
|
||||
* The unit tests will require you to reboot the authenticator multiple times. Be patient before continuing as it takes a few seconds for the connection between OS and authenticator to be re-established.
|
||||
* If you keep getting errors while trying to run the tests try changing to another git branch and back e.g. `git checkout branch1 && git checkout -` in order to remove build artifacts. Then re-flash the device with `make flash term` and try to run the tests again with `make fido2-test` or `make fido2-test-up`.
|
||||
|
||||
fido2-test
|
||||
|
||||
1. To make benchmarking faster disable user presence tests by enabling the CFLAG
|
||||
`CONFIG_FIDO2_CTAP_DISABLE_UP` in the Makefile or through KConfig.
|
||||
2. Flash the device with `make flash`.
|
||||
3. Run the unit tests by running `make fido2-test`.
|
||||
|
||||
fido2-test-up
|
||||
|
||||
1. Make sure that the CFLAG `CONFIG_FIDO2_CTAP_DISABLE_UP` is disabled as this test target
|
||||
requires user interaction.
|
||||
2. Flash the device with `make flash`.
|
||||
3. Run the unit tests by running `make fido2-test-up` and follow the instructions. E.g. when `.ACTIVATE UP ONCE` is displayed, press the configured UP button (default button 1) once.
|
||||
```
|
||||
python3 gen_test_case.py
|
||||
```
|
92
tests/sys/fido2_ctap/gen_test_case.py
Normal file
92
tests/sys/fido2_ctap/gen_test_case.py
Normal file
@ -0,0 +1,92 @@
|
||||
from fido2.ctap2 import CTAP2
|
||||
from fido2 import cbor
|
||||
from fido2.client import Fido2Client
|
||||
from fido2.server import Fido2Server
|
||||
from unittest import mock
|
||||
|
||||
|
||||
def mock_device():
|
||||
device = mock.MagicMock()
|
||||
return CTAP2(device)
|
||||
|
||||
|
||||
def get_cbor(data):
|
||||
request = b""
|
||||
if data is not None:
|
||||
request += cbor.encode(data)
|
||||
|
||||
return request
|
||||
|
||||
|
||||
def args(*params):
|
||||
"""Constructs a dict from a list of arguments for sending a CBOR command.
|
||||
None elements will be omitted.
|
||||
"""
|
||||
return dict((i, v) for i, v in enumerate(params, 1) if v is not None)
|
||||
|
||||
|
||||
def print_req(req, prefix):
|
||||
print(f"static uint8_t {prefix}_data[] = {{", end='')
|
||||
print("".join(f"{hex(x)}, " for x in req), end='')
|
||||
print("};")
|
||||
|
||||
|
||||
def gen_mc_req():
|
||||
dev = mock_device()
|
||||
dev.capabilities = 0
|
||||
user = {"id": b"user_id", "name": "A. User"}
|
||||
client = Fido2Client(dev, "https://example.com")
|
||||
server = Fido2Server({"id": "example.com", "name": "Example RP"}, attestation="direct")
|
||||
|
||||
create_options, _ = server.register_begin(user)
|
||||
create_options = create_options['publicKey']
|
||||
client_data = client._build_client_data("webauthn.create", create_options['challenge'])
|
||||
|
||||
options = {}
|
||||
options["rk"] = True
|
||||
|
||||
return get_cbor(
|
||||
args(
|
||||
client_data.hash,
|
||||
create_options["rp"],
|
||||
create_options["user"],
|
||||
create_options["pubKeyCredParams"],
|
||||
None, # exclude list
|
||||
None, # extensions
|
||||
options,
|
||||
None, # pin_auth
|
||||
None, # pin protocol version
|
||||
))
|
||||
|
||||
|
||||
def gen_ga_req():
|
||||
dev = mock_device()
|
||||
dev.capabilities = 0
|
||||
# user = {"id": b"user_id", "name": "A. User"}
|
||||
client = Fido2Client(dev, "https://example.com")
|
||||
server = Fido2Server({"id": "example.com", "name": "Example RP"}, attestation="direct")
|
||||
|
||||
request_options, _ = server.authenticate_begin()
|
||||
request_options = request_options['publicKey']
|
||||
client_data = client._build_client_data("webauthn.get", request_options['challenge'])
|
||||
|
||||
return get_cbor(
|
||||
args(
|
||||
request_options["rpId"],
|
||||
client_data.hash,
|
||||
None, # allow list
|
||||
None, # extensions
|
||||
None, # options
|
||||
None, # pin_uv_param
|
||||
None # pin_uv_protocol
|
||||
))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
req = gen_mc_req()
|
||||
print_req(req, "mc")
|
||||
|
||||
print("")
|
||||
|
||||
req = gen_ga_req()
|
||||
print_req(req, "ga")
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Freie Universität Berlin
|
||||
* Copyright (C) 2022 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -10,27 +10,91 @@
|
||||
* @ingroup tests
|
||||
* @{
|
||||
* @file
|
||||
* @brief FIDO2 CTAP test application that creates an authenticator
|
||||
* which uses CTAPHID as underlying communication protocol
|
||||
* @brief FIDO2 CTAP test application that tests CTAP functionality
|
||||
* without transport layer.
|
||||
*
|
||||
* @author Nils Ollrogge <nils-ollrogge@outlook.de>
|
||||
* @author Nils Ollrogge <nils.ollrogge@mailbox.tu-dresden.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#include "ztimer.h"
|
||||
#include "embUnit.h"
|
||||
|
||||
#include "fido2/ctap.h"
|
||||
#include "fido2/ctap/transport/ctap_transport.h"
|
||||
|
||||
/**
|
||||
* To generate a new arrays simply run the gen_test_case.py script
|
||||
*/
|
||||
static uint8_t mc_data[] =
|
||||
{ 0xa5, 0x1, 0x58, 0x20, 0xe0, 0xa1, 0xec, 0x5a, 0xa, 0x12, 0xa1, 0x4, 0xc8, 0xcb, 0x93, 0x54, 0x31,
|
||||
0xbf, 0x5c, 0x39, 0x7a, 0xee, 0x1b, 0x9f, 0xd0, 0x97, 0x97, 0x7d, 0x7b, 0xfb, 0x1, 0xa1, 0x20,
|
||||
0x2a, 0xad, 0x5c, 0x2, 0xa2, 0x62, 0x69, 0x64, 0x6b, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x6a, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c,
|
||||
0x65, 0x20, 0x52, 0x50, 0x3, 0xa2, 0x62, 0x69, 0x64, 0x47, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69,
|
||||
0x64, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x67, 0x41, 0x2e, 0x20, 0x55, 0x73, 0x65, 0x72, 0x4, 0x84,
|
||||
0xa2, 0x63, 0x61, 0x6c, 0x67, 0x26, 0x64, 0x74, 0x79, 0x70, 0x65, 0x6a, 0x70, 0x75, 0x62, 0x6c,
|
||||
0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0xa2, 0x63, 0x61, 0x6c, 0x67, 0x27, 0x64, 0x74, 0x79, 0x70,
|
||||
0x65, 0x6a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0xa2, 0x63, 0x61, 0x6c,
|
||||
0x67, 0x38, 0x24, 0x64, 0x74, 0x79, 0x70, 0x65, 0x6a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2d,
|
||||
0x6b, 0x65, 0x79, 0xa2, 0x63, 0x61, 0x6c, 0x67, 0x39, 0x1, 0x0, 0x64, 0x74, 0x79, 0x70, 0x65,
|
||||
0x6a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x7, 0xa1, 0x62, 0x72, 0x6b,
|
||||
0xf5, };
|
||||
|
||||
static uint8_t ga_data[] =
|
||||
{ 0xa2, 0x1, 0x6b, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2, 0x58,
|
||||
0x20, 0x7d, 0xf3, 0x9a, 0x49, 0xa9, 0x8c, 0xa2, 0xd8, 0x3e, 0x50, 0x36, 0x42, 0xd9, 0xc6, 0xfa,
|
||||
0x39, 0xf5, 0xa7, 0xe9, 0x35, 0x41, 0xb0, 0x1c, 0x59, 0xfa, 0xc2, 0x35, 0x3a, 0xb0, 0xbc, 0xcc,
|
||||
0x70, };
|
||||
|
||||
static void test_ctap(void)
|
||||
{
|
||||
fido2_ctap_init();
|
||||
ctap_req_t req = { 0 };
|
||||
ctap_resp_t resp = { 0 };
|
||||
|
||||
/* reset authenticator */
|
||||
req.method = CTAP_RESET;
|
||||
req.buf = NULL;
|
||||
req.len = 0x0;
|
||||
fido2_ctap_handle_request(&req, &resp);
|
||||
|
||||
TEST_ASSERT(resp.status == CTAP2_OK);
|
||||
|
||||
/* create new credential */
|
||||
req.method = CTAP_MAKE_CREDENTIAL;
|
||||
req.buf = mc_data;
|
||||
req.len = sizeof(mc_data);
|
||||
fido2_ctap_handle_request(&req, &resp);
|
||||
|
||||
TEST_ASSERT(resp.status == CTAP2_OK);
|
||||
|
||||
/* create assertion using credential */
|
||||
req.method = CTAP_GET_ASSERTION;
|
||||
req.buf = ga_data;
|
||||
req.len = sizeof(ga_data);
|
||||
fido2_ctap_handle_request(&req, &resp);
|
||||
|
||||
TEST_ASSERT(resp.status == CTAP2_OK);
|
||||
}
|
||||
|
||||
Test *ctap_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_ctap),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(ctap_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test *)&ctap_tests;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* sleep in order to see early DEBUG outputs */
|
||||
ztimer_sleep(ZTIMER_SEC, 3);
|
||||
fido2_ctap_transport_init();
|
||||
TESTS_START();
|
||||
TESTS_RUN(ctap_tests());
|
||||
TESTS_END();
|
||||
|
||||
return 0;
|
||||
}
|
||||
/** @} */
|
||||
|
14
tests/sys/fido2_ctap/tests/01-run.py
Executable file
14
tests/sys/fido2_ctap/tests/01-run.py
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2022 Freie Universität Berlin
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU Lesser
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
import sys
|
||||
from testrunner import run_check_unittests
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run_check_unittests())
|
41
tests/sys/fido2_ctap_hid/Makefile
Normal file
41
tests/sys/fido2_ctap_hid/Makefile
Normal file
@ -0,0 +1,41 @@
|
||||
BOARD ?= nrf52840dk
|
||||
#BOARD ?= nrf52840dongle
|
||||
|
||||
include ../Makefile.sys_common
|
||||
|
||||
BOARD_WHITELIST = \
|
||||
nrf52840dk \
|
||||
nrf52840dongle
|
||||
|
||||
USEMODULE += fido2_ctap_transport_hid
|
||||
USEPKG += fido2_tests
|
||||
|
||||
USB_VID ?= $(USB_VID_TESTING)
|
||||
USB_PID ?= $(USB_PID_TESTING)
|
||||
|
||||
# Disable user presence tests
|
||||
# Should be used when running fido2-test to make them run quicker
|
||||
CFLAGS += -DCONFIG_FIDO2_CTAP_DISABLE_UP=1
|
||||
|
||||
# Disable user LED animation
|
||||
CFLAGS += -DCONFIG_FIDO2_CTAP_DISABLE_LED=1
|
||||
|
||||
# FIDO2 tests except for the ones requiring user presence
|
||||
#
|
||||
# Use env -i because fido2-test has a depedency (pyscard) that needs to be
|
||||
# compiled natively (x86-64). Therefore we need to clear the flags set by e.g.
|
||||
# BOARD = nrf52840dk
|
||||
fido2-test:
|
||||
env -i PATH=$(PATH) $(MAKE) -C $(RIOTBASE)/build/pkg/fido2_tests
|
||||
|
||||
# FIDO2 user presence tests.
|
||||
#
|
||||
# Make sure to enable user presence tests by uncommenting CFLAGS += -DCONFIG_FIDO2_CTAP_DISABLE_UP=1
|
||||
#
|
||||
# Use env -i because fido2-test has a depedency (pyscard) that needs to be
|
||||
# compiled natively (x86-64). Therefore we need to clear the flags set by e.g.
|
||||
# BOARD = nrf52840dk
|
||||
fido2-test-up:
|
||||
env -i PATH=$(PATH) $(MAKE) -C $(RIOTBASE)/build/pkg/fido2_tests up-tests
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
59
tests/sys/fido2_ctap_hid/README.md
Normal file
59
tests/sys/fido2_ctap_hid/README.md
Normal file
@ -0,0 +1,59 @@
|
||||
# Test Application for FIDO2 CTAP using USB HID transport binding
|
||||
|
||||
This test aims to test the FIDO2 CTAP implementation by creating a FIDO2
|
||||
authenticator which uses CTAPHID as communication protocol.
|
||||
|
||||
Note:
|
||||
* This test application has only been tested on an nrf52840 DK.
|
||||
|
||||
The test application requires at least 16536 bytes of stack memory which are
|
||||
divided as follows:
|
||||
* 512 bytes isr_stack
|
||||
* 1024 usbus
|
||||
* 15000 bytes FIDO2 CTAP
|
||||
|
||||
## Usage
|
||||
The FIDO2 authenticator can be tested in two ways:
|
||||
|
||||
### Functional testing
|
||||
1. Flash the device with `make flash`.
|
||||
2. Test the authenticator on a website like [Webauthn.io](https://webauthn.io/).
|
||||
|
||||
Note:
|
||||
* Due to limited support of FIDO2 CTAP in browsers as of now, make sure to use the
|
||||
Chromium or Google Chrome browser when testing on [Webauthn.io](https://webauthn.io/).
|
||||
* When registering and authenticating on [Webauthn.io](https://webauthn.io/) you
|
||||
will need to push button 1 on your device in order to show user presence.
|
||||
|
||||
**Resetting the authenticator**
|
||||
* To reset the authenticator, meaning that all credentials and state information
|
||||
will be deleted, execute the `reset.py` file located in this directory.
|
||||
* This requires you to install the python fido2 package. To install run:
|
||||
`pip install fido2==0.8.1`.
|
||||
|
||||
### Unit testing
|
||||
Unit testing is based on the `fido2_tests` package.
|
||||
|
||||
There are two test targets (fido2-test, fido2-test-up). The former requires no user
|
||||
interaction the latter does.
|
||||
|
||||
Note:
|
||||
* The tests require python 3.6+.
|
||||
* The tests require [swig](http://www.swig.org/) to be installed on your host computer.
|
||||
* Running the tests for the first time will setup a virtual python environment (venv) and install python dependencies of the tests. To check the dependencies please refer to the `requirements.txt` of the [fido2-tests repository](https://github.com/solokeys/fido2-tests).
|
||||
* The unit tests will require you to reboot the authenticator multiple times. Be patient before continuing as it takes a few seconds for the connection between OS and authenticator to be re-established.
|
||||
* If you keep getting errors while trying to run the tests try changing to another git branch and back e.g. `git checkout branch1 && git checkout -` in order to remove build artifacts. Then re-flash the device with `make flash term` and try to run the tests again with `make fido2-test` or `make fido2-test-up`.
|
||||
|
||||
fido2-test
|
||||
|
||||
1. To make benchmarking faster disable user presence tests by enabling the CFLAG
|
||||
`CONFIG_FIDO2_CTAP_DISABLE_UP` in the Makefile or through KConfig.
|
||||
2. Flash the device with `make flash`.
|
||||
3. Run the unit tests by running `make fido2-test`.
|
||||
|
||||
fido2-test-up
|
||||
|
||||
1. Make sure that the CFLAG `CONFIG_FIDO2_CTAP_DISABLE_UP` is disabled as this test target
|
||||
requires user interaction.
|
||||
2. Flash the device with `make flash`.
|
||||
3. Run the unit tests by running `make fido2-test-up` and follow the instructions. E.g. when `.ACTIVATE UP ONCE` is displayed, press the configured UP button (default button 1) once.
|
8
tests/sys/fido2_ctap_hid/app.config.test
Normal file
8
tests/sys/fido2_ctap_hid/app.config.test
Normal file
@ -0,0 +1,8 @@
|
||||
CONFIG_MODULE_AUTO_INIT_USBUS=n
|
||||
CONFIG_MODULE_USBUS=y
|
||||
CONFIG_MODULE_FIDO2=y
|
||||
CONFIG_MODULE_FIDO2_CTAP=y
|
||||
CONFIG_MODULE_FIDO2_CTAP_TRANSPORT=y
|
||||
CONFIG_MODULE_FIDO2_CTAP_TRANSPORT_HID=y
|
||||
|
||||
CONFIG_PACKAGE_FIDO2_TESTS=y
|
31
tests/sys/fido2_ctap_hid/main.c
Normal file
31
tests/sys/fido2_ctap_hid/main.c
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
* @file
|
||||
* @brief FIDO2 CTAP test application that creates an authenticator
|
||||
* which uses CTAPHID as underlying communication protocol
|
||||
*
|
||||
* @author Nils Ollrogge <nils.ollrogge@mailbox.tu-dresden.de>
|
||||
* @}
|
||||
*/
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#include "ztimer.h"
|
||||
|
||||
#include "fido2/ctap/transport/ctap_transport.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* sleep in order to see early DEBUG outputs */
|
||||
ztimer_sleep(ZTIMER_MSEC, 3000);
|
||||
fido2_ctap_transport_init();
|
||||
}
|
Loading…
Reference in New Issue
Block a user