Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

sys/fido2: follow up continued #18663

Merged
merged 5 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions sys/fido2/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -26,4 +28,5 @@ ifneq (,$(filter fido2_ctap,$(USEMODULE)))
USEMODULE += crypto_aes_256
USEMODULE += hashes
USEMODULE += fido2
USEMODULE += fmt
endif
130 changes: 72 additions & 58 deletions sys/fido2/ctap/ctap.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@
ctap_resident_key_t rks[CTAP_MAX_EXCLUDE_LIST_SIZE]; /**< eligible resident keys found */
uint8_t count; /**< number of rks found */
uint8_t cred_counter; /**< amount of creds sent to host */
uint32_t timer; /**< time gap between get_next_assertion calls in milliseconds */

Check warning on line 48 in sys/fido2/ctap/ctap.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
bool uv; /**< indicate if user verified */
bool up; /**< indicate if user present */
uint8_t client_data_hash[SHA256_DIGEST_LENGTH]; /**< SHA-256 hash of JSON serialized client data */

Check warning on line 51 in sys/fido2/ctap/ctap.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
} ctap_get_assertion_state_t;

/*** CTAP methods ***/
Expand Down Expand Up @@ -248,162 +248,173 @@
*/
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;
}
}

if (!IS_ACTIVE(CONFIG_FIDO2_CTAP_DISABLE_UP)) {
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);

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

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

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

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)
{
assert(resp);

resp->status = _reset();
resp->len = 0x0;

return 0;
return resp->status;
}

static uint32_t get_id(void)
Expand All @@ -413,7 +424,11 @@

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;
Expand Down Expand Up @@ -540,12 +555,12 @@
}

/* 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)) {
Expand Down Expand Up @@ -697,10 +712,12 @@
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,
Expand Down Expand Up @@ -855,7 +872,7 @@
}

/* 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;
}
Expand All @@ -870,19 +887,19 @@
}

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:
Expand All @@ -904,7 +921,6 @@
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,
Expand Down Expand Up @@ -989,12 +1005,12 @@
}

/* 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) {
Expand Down Expand Up @@ -1100,13 +1116,12 @@
}

/* 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");
Expand Down Expand Up @@ -1198,13 +1213,12 @@
}

/* 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);

Expand Down
Loading
Loading