diff --git a/pico-keys-sdk b/pico-keys-sdk index f0687c1..f4ad8e1 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit f0687c1ef392c2bcb293ea554f1dd8b784484922 +Subproject commit f4ad8e1af2e2657f3900f1e01db031d7d73d623b diff --git a/src/fido/cbor_client_pin.c b/src/fido/cbor_client_pin.c index c7c13d8..0e3d6e9 100644 --- a/src/fido/cbor_client_pin.c +++ b/src/fido/cbor_client_pin.c @@ -169,7 +169,7 @@ int ecdh(uint8_t protocol, const mbedtls_ecp_point *Q, uint8_t *sharedSecret) { int resetPinUvAuthToken() { uint8_t t[32]; random_gen(NULL, t, sizeof(t)); - flash_write_data_to_file(ef_authtoken, t, sizeof(t)); + file_put_data(ef_authtoken, t, sizeof(t)); paut.permissions = 0; paut.data = file_get_data(ef_authtoken); paut.len = file_get_size(ef_authtoken); @@ -417,7 +417,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) { hsh[0] = MAX_PIN_RETRIES; hsh[1] = pin_len; mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), paddedNewPin, pin_len, hsh + 2); - flash_write_data_to_file(ef_pin, hsh, 2 + 16); + file_put_data(ef_pin, hsh, 2 + 16); low_flash_available(); goto err; //No return } @@ -464,7 +464,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) { uint8_t pin_data[18]; memcpy(pin_data, file_get_data(ef_pin), 18); pin_data[0] -= 1; - flash_write_data_to_file(ef_pin, pin_data, sizeof(pin_data)); + file_put_data(ef_pin, pin_data, sizeof(pin_data)); low_flash_available(); uint8_t retries = pin_data[0]; uint8_t paddedNewPin[64]; @@ -489,7 +489,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) { } } pin_data[0] = MAX_PIN_RETRIES; - flash_write_data_to_file(ef_pin, pin_data, sizeof(pin_data)); + file_put_data(ef_pin, pin_data, sizeof(pin_data)); low_flash_available(); new_pin_mismatches = 0; ret = decrypt(pinUvAuthProtocol, sharedSecret, newPinEnc.data, newPinEnc.len, paddedNewPin); @@ -520,12 +520,12 @@ int cbor_client_pin(const uint8_t *data, size_t len) { memcmp(hsh + 2, file_get_data(ef_pin) + 2, 16) == 0) { CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION); } - flash_write_data_to_file(ef_pin, hsh, 2 + 16); + file_put_data(ef_pin, hsh, 2 + 16); if (file_has_data(ef_minpin) && file_get_data(ef_minpin)[1] == 1) { uint8_t *tmp = (uint8_t *) calloc(1, file_get_size(ef_minpin)); memcpy(tmp, file_get_data(ef_minpin), file_get_size(ef_minpin)); tmp[1] = 0; - flash_write_data_to_file(ef_minpin, tmp, file_get_size(ef_minpin)); + file_put_data(ef_minpin, tmp, file_get_size(ef_minpin)); free(tmp); } low_flash_available(); @@ -573,7 +573,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) { uint8_t pin_data[18]; memcpy(pin_data, file_get_data(ef_pin), 18); pin_data[0] -= 1; - flash_write_data_to_file(ef_pin, pin_data, sizeof(pin_data)); + file_put_data(ef_pin, pin_data, sizeof(pin_data)); low_flash_available(); uint8_t retries = pin_data[0]; uint8_t paddedNewPin[64], poff = (pinUvAuthProtocol - 1) * IV_SIZE; @@ -599,7 +599,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) { } pin_data[0] = MAX_PIN_RETRIES; new_pin_mismatches = 0; - flash_write_data_to_file(ef_pin, pin_data, sizeof(pin_data)); + file_put_data(ef_pin, pin_data, sizeof(pin_data)); low_flash_available(); file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF); if (file_has_data(ef_minpin) && file_get_data(ef_minpin)[1] == 1) { diff --git a/src/fido/cbor_config.c b/src/fido/cbor_config.c index 4026cc7..b8cb73f 100644 --- a/src/fido/cbor_config.c +++ b/src/fido/cbor_config.c @@ -142,9 +142,9 @@ int cbor_config(const uint8_t *data, size_t len) { if (has_keydev_dec == false) { CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID); } - flash_write_data_to_file(ef_keydev, keydev_dec, sizeof(keydev_dec)); + file_put_data(ef_keydev, keydev_dec, sizeof(keydev_dec)); mbedtls_platform_zeroize(keydev_dec, sizeof(keydev_dec)); - flash_write_data_to_file(ef_keydev_enc, NULL, 0); // Set ef to 0 bytes + file_put_data(ef_keydev_enc, NULL, 0); // Set ef to 0 bytes low_flash_available(); } else if (vendorCommandId == CTAP_CONFIG_AUT_ENABLE) { @@ -178,10 +178,10 @@ int cbor_config(const uint8_t *data, size_t len) { CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER); } - flash_write_data_to_file(ef_keydev_enc, key_dev_enc, sizeof(key_dev_enc)); + file_put_data(ef_keydev_enc, key_dev_enc, sizeof(key_dev_enc)); mbedtls_platform_zeroize(key_dev_enc, sizeof(key_dev_enc)); - flash_write_data_to_file(ef_keydev, key_dev_enc, file_get_size(ef_keydev)); // Overwrite ef with 0 - flash_write_data_to_file(ef_keydev, NULL, 0); // Set ef to 0 bytes + file_put_data(ef_keydev, key_dev_enc, file_get_size(ef_keydev)); // Overwrite ef with 0 + file_put_data(ef_keydev, NULL, 0); // Set ef to 0 bytes low_flash_available(); } else { @@ -216,7 +216,7 @@ int cbor_config(const uint8_t *data, size_t len) { data + 2 + m * 32, 0); } - flash_write_data_to_file(ef_minpin, data, 2 + minPinLengthRPIDs_len * 32); + file_put_data(ef_minpin, data, 2 + minPinLengthRPIDs_len * 32); low_flash_available(); goto err; //No return } diff --git a/src/fido/cbor_cred_mgmt.c b/src/fido/cbor_cred_mgmt.c index 68e95a8..f5b9fdd 100644 --- a/src/fido/cbor_cred_mgmt.c +++ b/src/fido/cbor_cred_mgmt.c @@ -380,7 +380,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) { delete_file(rp_ef); } else { - flash_write_data_to_file(rp_ef, rp_data, file_get_size(rp_ef)); + file_put_data(rp_ef, rp_data, file_get_size(rp_ef)); } free(rp_data); break; diff --git a/src/fido/cbor_get_assertion.c b/src/fido/cbor_get_assertion.c index f3a2516..87c6363 100644 --- a/src/fido/cbor_get_assertion.c +++ b/src/fido/cbor_get_assertion.c @@ -640,7 +640,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) { CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder)); resp_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1); ctr++; - flash_write_data_to_file(ef_counter, (uint8_t *) &ctr, sizeof(ctr)); + file_put_data(ef_counter, (uint8_t *) &ctr, sizeof(ctr)); low_flash_available(); err: CBOR_FREE_BYTE_STRING(clientDataHash); diff --git a/src/fido/cbor_large_blobs.c b/src/fido/cbor_large_blobs.c index c3ebd70..432464d 100644 --- a/src/fido/cbor_large_blobs.c +++ b/src/fido/cbor_large_blobs.c @@ -155,7 +155,7 @@ int cbor_large_blobs(const uint8_t *data, size_t len) { if (expectedLength > 17 && memcmp(sha, temp_lba + expectedLength - 16, 16) != 0) { CBOR_ERROR(CTAP2_ERR_INTEGRITY_FAILURE); } - flash_write_data_to_file(ef_largeblob, temp_lba, expectedLength); + file_put_data(ef_largeblob, temp_lba, expectedLength); low_flash_available(); } goto err; diff --git a/src/fido/cbor_make_credential.c b/src/fido/cbor_make_credential.c index 44a488f..33ccc98 100644 --- a/src/fido/cbor_make_credential.c +++ b/src/fido/cbor_make_credential.c @@ -225,9 +225,9 @@ int cbor_make_credential(const uint8_t *data, size_t len) { else if (pubKeyCredParams[i].alg <= FIDO2_ALG_RS256 && pubKeyCredParams[i].alg >= FIDO2_ALG_RS512) { // pass } - else { - CBOR_ERROR(CTAP2_ERR_CBOR_UNEXPECTED_TYPE); - } + //else { + // CBOR_ERROR(CTAP2_ERR_CBOR_UNEXPECTED_TYPE); + //} if (curve > 0 && alg == 0) { alg = pubKeyCredParams[i].alg; } @@ -313,9 +313,11 @@ int cbor_make_credential(const uint8_t *data, size_t len) { } } flags |= FIDO2_AUT_FLAG_UP; - clearUserPresentFlag(); - clearUserVerifiedFlag(); - clearPinUvAuthTokenPermissionsExceptLbw(); + if (options.up == ptrue) { + clearUserPresentFlag(); + clearUserVerifiedFlag(); + clearPinUvAuthTokenPermissionsExceptLbw(); + } } const known_app_t *ka = find_app_by_rp_id_hash(rp_id_hash); @@ -518,7 +520,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) { } } ctr++; - flash_write_data_to_file(ef_counter, (uint8_t *) &ctr, sizeof(ctr)); + file_put_data(ef_counter, (uint8_t *) &ctr, sizeof(ctr)); low_flash_available(); err: CBOR_FREE_BYTE_STRING(clientDataHash); diff --git a/src/fido/cbor_vendor.c b/src/fido/cbor_vendor.c index afe939b..d1b6f54 100644 --- a/src/fido/cbor_vendor.c +++ b/src/fido/cbor_vendor.c @@ -121,9 +121,9 @@ int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) { } uint8_t zeros[32]; memset(zeros, 0, sizeof(zeros)); - flash_write_data_to_file(ef_keydev_enc, vendorParam.data, vendorParam.len); - flash_write_data_to_file(ef_keydev, zeros, file_get_size(ef_keydev)); // Overwrite ef with 0 - flash_write_data_to_file(ef_keydev, NULL, 0); // Set ef to 0 bytes + file_put_data(ef_keydev_enc, vendorParam.data, vendorParam.len); + file_put_data(ef_keydev, zeros, file_get_size(ef_keydev)); // Overwrite ef with 0 + file_put_data(ef_keydev, NULL, 0); // Set ef to 0 bytes low_flash_available(); goto err; } @@ -306,7 +306,7 @@ int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) { } file_t *ef_ee_ea = search_by_fid(EF_EE_DEV_EA, NULL, SPECIFY_EF); if (ef_ee_ea) { - flash_write_data_to_file(ef_ee_ea, vendorParam.data, vendorParam.len); + file_put_data(ef_ee_ea, vendorParam.data, vendorParam.len); } low_flash_available(); goto err; diff --git a/src/fido/cmd_authenticate.c b/src/fido/cmd_authenticate.c index 6f458d6..b3c7f9d 100644 --- a/src/fido/cmd_authenticate.c +++ b/src/fido/cmd_authenticate.c @@ -97,7 +97,7 @@ int cmd_authenticate() { res_APDU_size = 1 + 4 + olen; ctr++; - flash_write_data_to_file(ef_counter, (uint8_t *) &ctr, sizeof(ctr)); + file_put_data(ef_counter, (uint8_t *) &ctr, sizeof(ctr)); low_flash_available(); return SW_OK(); } diff --git a/src/fido/credential.c b/src/fido/credential.c index b43388b..ea44ebb 100644 --- a/src/fido/credential.c +++ b/src/fido/credential.c @@ -306,7 +306,7 @@ int credential_store(const uint8_t *cred_id, size_t cred_id_len, const uint8_t * memcpy(data, rp_id_hash, 32); memcpy(data + 32, cred_id, cred_id_len); file_t *ef = file_new(EF_CRED + sloti); - flash_write_data_to_file(ef, data, cred_id_len + 32); + file_put_data(ef, data, cred_id_len + 32); free(data); if (new_record == true) { //increase rps @@ -332,7 +332,7 @@ int credential_store(const uint8_t *cred_id, size_t cred_id_len, const uint8_t * data = (uint8_t *) calloc(1, file_get_size(ef)); memcpy(data, file_get_data(ef), file_get_size(ef)); data[0] += 1; - flash_write_data_to_file(ef, data, file_get_size(ef)); + file_put_data(ef, data, file_get_size(ef)); free(data); } else { @@ -341,7 +341,7 @@ int credential_store(const uint8_t *cred_id, size_t cred_id_len, const uint8_t * data[0] = 1; memcpy(data + 1, rp_id_hash, 32); memcpy(data + 1 + 32, cred.rpId.data, cred.rpId.len); - flash_write_data_to_file(ef, data, 1 + 32 + cred.rpId.len); + file_put_data(ef, data, 1 + 32 + cred.rpId.len); free(data); } } diff --git a/src/fido/fido.c b/src/fido/fido.c index 79a935d..1adf712 100644 --- a/src/fido/fido.c +++ b/src/fido/fido.c @@ -215,7 +215,8 @@ int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecdsa_con } } uint8_t hmac[32], d[32]; - int ret = mbedtls_ecp_write_key(key, d, sizeof(d)); + size_t olen = 0; + int ret = mbedtls_ecp_write_key_ext(key, &olen, d, sizeof(d)); if (key == NULL) { mbedtls_ecdsa_free(&ctx); } @@ -317,7 +318,7 @@ int scan_files() { uint8_t kdata[32]; int key_size = mbedtls_mpi_size(&ecdsa.d); mbedtls_mpi_write_binary(&ecdsa.d, kdata, key_size); - ret = flash_write_data_to_file(ef_keydev, kdata, key_size); + ret = file_put_data(ef_keydev, kdata, key_size); mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_ecdsa_free(&ecdsa); if (ret != CCID_OK) { @@ -353,7 +354,7 @@ int scan_files() { if (ret <= 0) { return ret; } - flash_write_data_to_file(ef_certdev, cert + sizeof(cert) - ret, ret); + file_put_data(ef_certdev, cert + sizeof(cert) - ret, ret); } } else { @@ -363,7 +364,7 @@ int scan_files() { if (ef_counter) { if (!file_has_data(ef_counter)) { uint32_t v = 0; - flash_write_data_to_file(ef_counter, (uint8_t *) &v, sizeof(v)); + file_put_data(ef_counter, (uint8_t *) &v, sizeof(v)); } } else { @@ -375,7 +376,7 @@ int scan_files() { if (!file_has_data(ef_authtoken)) { uint8_t t[32]; random_gen(NULL, t, sizeof(t)); - flash_write_data_to_file(ef_authtoken, t, sizeof(t)); + file_put_data(ef_authtoken, t, sizeof(t)); } paut.data = file_get_data(ef_authtoken); paut.len = file_get_size(ef_authtoken); @@ -385,7 +386,7 @@ int scan_files() { } ef_largeblob = search_by_fid(EF_LARGEBLOB, NULL, SPECIFY_EF); if (!file_has_data(ef_largeblob)) { - flash_write_data_to_file(ef_largeblob, + file_put_data(ef_largeblob, (const uint8_t *) "\x80\x76\xbe\x8b\x52\x8d\x00\x75\xf7\xaa\xe9\x8d\x6f\xa5\x7a\x6d\x3c", 17); } @@ -447,7 +448,7 @@ uint8_t get_opts() { void set_opts(uint8_t opts) { file_t *ef = search_by_fid(EF_OPTS, NULL, SPECIFY_EF); - flash_write_data_to_file(ef, &opts, sizeof(uint8_t)); + file_put_data(ef, &opts, sizeof(uint8_t)); low_flash_available(); } diff --git a/src/fido/files.c b/src/fido/files.c index 121f76d..11573c5 100644 --- a/src/fido/files.c +++ b/src/fido/files.c @@ -49,7 +49,7 @@ file_t file_entries[] = { { .fid = EF_OTP_PIN, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, - { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, + { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL, .ef_structure = 0, .acl = { 0 } } //end }; diff --git a/src/fido/management.c b/src/fido/management.c index 83cbd43..f7590d0 100644 --- a/src/fido/management.c +++ b/src/fido/management.c @@ -54,10 +54,12 @@ int man_unload() { bool cap_supported(uint16_t cap) { file_t *ef = search_dynamic_file(EF_DEV_CONF); if (file_has_data(ef)) { - uint16_t tag = 0x0, data_len = file_get_size(ef); - uint8_t *tag_data = NULL, *p = NULL, *data = file_get_data(ef); - size_t tag_len = 0; - while (walk_tlv(data, data_len, &p, &tag, &tag_len, &tag_data)) { + uint16_t tag = 0x0; + uint8_t *tag_data = NULL, *p = NULL; + uint16_t tag_len = 0; + asn1_ctx_t ctxi; + asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi); + while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) { if (tag == TAG_USB_ENABLED) { uint16_t ecaps = tag_data[0]; if (tag_len == 2) { @@ -128,7 +130,7 @@ int cmd_write_config() { return SW_WRONG_DATA(); } file_t *ef = file_new(EF_DEV_CONF); - flash_write_data_to_file(ef, apdu.data + 1, apdu.nc - 1); + file_put_data(ef, apdu.data + 1, apdu.nc - 1); low_flash_available(); return SW_OK(); } diff --git a/src/fido/oath.c b/src/fido/oath.c index cfeb390..03ee790 100644 --- a/src/fido/oath.c +++ b/src/fido/oath.c @@ -118,14 +118,11 @@ int oath_unload() { } file_t *find_oath_cred(const uint8_t *name, size_t name_len) { - size_t ef_tag_len = 0; - uint8_t *ef_tag_data = NULL; for (int i = 0; i < MAX_OATH_CRED; i++) { file_t *ef = search_dynamic_file(EF_OATH_CRED + i); - if (file_has_data(ef) && - asn1_find_tag(file_get_data(ef), file_get_size(ef), TAG_NAME, &ef_tag_len, - &ef_tag_data) == true && ef_tag_len == name_len && - memcmp(ef_tag_data, name, name_len) == 0) { + asn1_ctx_t ctxi, ef_tag = { 0 }; + asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi); + if (file_has_data(ef) && asn1_find_tag(&ctxi, TAG_NAME, &ef_tag) == true && ef_tag.len == name_len && memcmp(ef_tag.data, name, name_len) == 0) { return ef; } } @@ -136,32 +133,32 @@ int cmd_put() { if (validated == false) { return SW_SECURITY_STATUS_NOT_SATISFIED(); } - size_t key_len = 0, imf_len = 0, name_len = 0; - uint8_t *key = NULL, *imf = NULL, *name = NULL; - if (asn1_find_tag(apdu.data, apdu.nc, TAG_KEY, &key_len, &key) == false) { + asn1_ctx_t ctxi, key = { 0 }, name = { 0 }, imf = { 0 }; + asn1_ctx_init(apdu.data, apdu.nc, &ctxi); + if (asn1_find_tag(&ctxi, TAG_KEY, &key) == false) { return SW_INCORRECT_PARAMS(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_NAME, &name_len, &name) == false) { + if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) { return SW_INCORRECT_PARAMS(); } - if ((key[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) { - if (asn1_find_tag(apdu.data, apdu.nc, TAG_IMF, &imf_len, &imf) == false) { + if ((key.data[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) { + if (asn1_find_tag(&ctxi, TAG_IMF, &imf) == false) { memcpy(apdu.data + apdu.nc, "\x7a\x08\x00\x00\x00\x00\x00\x00\x00\x00", 10); apdu.nc += 10; } else { //prepend zero-valued bytes - if (imf_len < 8) { - memmove(imf + (8 - imf_len), imf, imf_len); - memset(imf, 0, 8 - imf_len); - *(imf - 1) = 8; - apdu.nc += (8 - imf_len); + if (imf.len < 8) { + memmove(imf.data + (8 - imf.len), imf.data, imf.len); + memset(imf.data, 0, 8 - imf.len); + *(imf.data - 1) = 8; + apdu.nc += (8 - imf.len); } } } - file_t *ef = find_oath_cred(name, name_len); + file_t *ef = find_oath_cred(name.data, name.len); if (file_has_data(ef)) { - flash_write_data_to_file(ef, apdu.data, apdu.nc); + file_put_data(ef, apdu.data, apdu.nc); low_flash_available(); } else { @@ -169,7 +166,7 @@ int cmd_put() { file_t *ef = search_dynamic_file(EF_OATH_CRED + i); if (!file_has_data(ef)) { ef = file_new(EF_OATH_CRED + i); - flash_write_data_to_file(ef, apdu.data, apdu.nc); + file_put_data(ef, apdu.data, apdu.nc); low_flash_available(); return SW_OK(); } @@ -181,13 +178,13 @@ int cmd_put() { int cmd_delete() { - size_t tag_len = 0; - uint8_t *tag_data = NULL; if (validated == false) { return SW_SECURITY_STATUS_NOT_SATISFIED(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_NAME, &tag_len, &tag_data) == true) { - file_t *ef = find_oath_cred(tag_data, tag_len); + asn1_ctx_t ctxi, ctxo = { 0 }; + asn1_ctx_init(apdu.data, apdu.nc, &ctxi); + if (asn1_find_tag(&ctxi, TAG_NAME, &ctxo) == true) { + file_t *ef = find_oath_cred(ctxo.data, ctxo.len); if (ef) { delete_file(ef); return SW_OK(); @@ -219,38 +216,38 @@ int cmd_set_code() { validated = true; return SW_OK(); } - size_t key_len = 0, chal_len = 0, resp_len = 0; - uint8_t *key = NULL, *chal = NULL, *resp = NULL; - if (asn1_find_tag(apdu.data, apdu.nc, TAG_KEY, &key_len, &key) == false) { + asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, resp = { 0 }; + asn1_ctx_init(apdu.data, apdu.nc, &ctxi); + if (asn1_find_tag(&ctxi, TAG_KEY, &key) == false) { return SW_INCORRECT_PARAMS(); } - if (key_len == 0) { + if (key.len == 0) { delete_file(search_dynamic_file(EF_OATH_CODE)); validated = true; return SW_OK(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_CHALLENGE, &chal_len, &chal) == false) { + if (asn1_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) { return SW_INCORRECT_PARAMS(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_RESPONSE, &resp_len, &resp) == false) { + if (asn1_find_tag(&ctxi, TAG_RESPONSE, &resp) == false) { return SW_INCORRECT_PARAMS(); } - const mbedtls_md_info_t *md_info = get_oath_md_info(key[0]); + const mbedtls_md_info_t *md_info = get_oath_md_info(key.data[0]); if (md_info == NULL) { return SW_INCORRECT_PARAMS(); } uint8_t hmac[64]; - int r = mbedtls_md_hmac(md_info, key + 1, key_len - 1, chal, chal_len, hmac); + int r = mbedtls_md_hmac(md_info, key.data + 1, key.len - 1, chal.data, chal.len, hmac); if (r != 0) { return SW_EXEC_ERROR(); } - if (memcmp(hmac, resp, resp_len) != 0) { + if (memcmp(hmac, resp.data, resp.len) != 0) { return SW_DATA_INVALID(); } random_gen(NULL, challenge, sizeof(challenge)); file_t *ef = file_new(EF_OATH_CODE); - flash_write_data_to_file(ef, key, key_len); + file_put_data(ef, key.data, key.len); low_flash_available(); validated = false; return SW_OK(); @@ -274,23 +271,19 @@ int cmd_reset() { } int cmd_list() { - size_t name_len = 0, key_len = 0; - uint8_t *name = NULL, *key = NULL; if (validated == false) { return SW_SECURITY_STATUS_NOT_SATISFIED(); } for (int i = 0; i < MAX_OATH_CRED; i++) { file_t *ef = search_dynamic_file(EF_OATH_CRED + i); if (file_has_data(ef)) { - uint8_t *data = file_get_data(ef); - size_t data_len = file_get_size(ef); - if (asn1_find_tag(data, data_len, TAG_NAME, &name_len, - &name) == true && - asn1_find_tag(data, data_len, TAG_KEY, &key_len, &key) == true) { + asn1_ctx_t ctxi, key = { 0 }, name = { 0 }; + asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi); + if (asn1_find_tag(&ctxi, TAG_NAME, &name) == true && asn1_find_tag(&ctxi, TAG_KEY, &key) == true) { res_APDU[res_APDU_size++] = TAG_NAME_LIST; - res_APDU[res_APDU_size++] = name_len + 1; - res_APDU[res_APDU_size++] = key[0]; - memcpy(res_APDU + res_APDU_size, name, name_len); res_APDU_size += name_len; + res_APDU[res_APDU_size++] = name.len + 1; + res_APDU[res_APDU_size++] = key.data[0]; + memcpy(res_APDU + res_APDU_size, name.data, name.len); res_APDU_size += name.len; } } } @@ -299,12 +292,12 @@ int cmd_list() { } int cmd_validate() { - size_t chal_len = 0, resp_len = 0, key_len = 0; - uint8_t *chal = NULL, *resp = NULL, *key = NULL; - if (asn1_find_tag(apdu.data, apdu.nc, TAG_CHALLENGE, &chal_len, &chal) == false) { + asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, resp = { 0 }; + asn1_ctx_init(apdu.data, apdu.nc, &ctxi); + if (asn1_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) { return SW_INCORRECT_PARAMS(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_RESPONSE, &resp_len, &resp) == false) { + if (asn1_find_tag(&ctxi, TAG_RESPONSE, &resp) == false) { return SW_INCORRECT_PARAMS(); } file_t *ef = search_dynamic_file(EF_OATH_CODE); @@ -312,21 +305,21 @@ int cmd_validate() { validated = true; return SW_DATA_INVALID(); } - key = file_get_data(ef); - key_len = file_get_size(ef); - const mbedtls_md_info_t *md_info = get_oath_md_info(key[0]); + key.data = file_get_data(ef); + key.len = file_get_size(ef); + const mbedtls_md_info_t *md_info = get_oath_md_info(key.data[0]); if (md_info == NULL) { return SW_INCORRECT_PARAMS(); } uint8_t hmac[64]; - int ret = mbedtls_md_hmac(md_info, key + 1, key_len - 1, challenge, sizeof(challenge), hmac); + int ret = mbedtls_md_hmac(md_info, key.data + 1, key.len - 1, challenge, sizeof(challenge), hmac); if (ret != 0) { return SW_EXEC_ERROR(); } - if (memcmp(hmac, resp, resp_len) != 0) { + if (memcmp(hmac, resp.data, resp.len) != 0) { return SW_DATA_INVALID(); } - ret = mbedtls_md_hmac(md_info, key + 1, key_len - 1, chal, chal_len, hmac); + ret = mbedtls_md_hmac(md_info, key.data + 1, key.len - 1, chal.data, chal.len, hmac); if (ret != 0) { return SW_EXEC_ERROR(); } @@ -373,68 +366,70 @@ int calculate_oath(uint8_t truncate, } int cmd_calculate() { - size_t chal_len = 0, name_len = 0, key_len = 0; - uint8_t *chal = NULL, *name = NULL, *key = NULL; if (P2(apdu) != 0x0 && P2(apdu) != 0x1) { return SW_INCORRECT_P1P2(); } if (validated == false) { return SW_SECURITY_STATUS_NOT_SATISFIED(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_CHALLENGE, &chal_len, &chal) == false) { + asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 }; + asn1_ctx_init(apdu.data, apdu.nc, &ctxi); + if (asn1_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) { return SW_INCORRECT_PARAMS(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_NAME, &name_len, &name) == false) { + if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) { return SW_INCORRECT_PARAMS(); } - file_t *ef = find_oath_cred(name, name_len); + file_t *ef = find_oath_cred(name.data, name.len); if (file_has_data(ef) == false) { return SW_DATA_INVALID(); } - - if (asn1_find_tag(file_get_data(ef), file_get_size(ef), TAG_KEY, &key_len, &key) == false) { + asn1_ctx_t ctxe; + asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxe); + if (asn1_find_tag(&ctxe, TAG_KEY, &key) == false) { return SW_INCORRECT_PARAMS(); } - if ((key[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) { - if (asn1_find_tag(file_get_data(ef), file_get_size(ef), TAG_IMF, &chal_len, - &chal) == false) { + if ((key.data[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) { + if (asn1_find_tag(&ctxe, TAG_IMF, &chal) == false) { return SW_INCORRECT_PARAMS(); } } res_APDU[res_APDU_size++] = TAG_RESPONSE + P2(apdu); - int ret = calculate_oath(P2(apdu), key, key_len, chal, chal_len); + int ret = calculate_oath(P2(apdu), key.data, key.len, chal.data, chal.len); if (ret != CCID_OK) { return SW_EXEC_ERROR(); } - if ((key[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) { + if ((key.data[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) { uint64_t v = - ((uint64_t) chal[0] << + ((uint64_t) chal.data[0] << 56) | - ((uint64_t) chal[1] << + ((uint64_t) chal.data[1] << 48) | - ((uint64_t) chal[2] << + ((uint64_t) chal.data[2] << 40) | - ((uint64_t) chal[3] << + ((uint64_t) chal.data[3] << 32) | - ((uint64_t) chal[4] << - 24) | ((uint64_t) chal[5] << 16) | ((uint64_t) chal[6] << 8) | (uint64_t) chal[7]; + ((uint64_t) chal.data[4] << + 24) | ((uint64_t) chal.data[5] << 16) | ((uint64_t) chal.data[6] << 8) | (uint64_t) chal.data[7]; size_t ef_size = file_get_size(ef); v++; uint8_t *tmp = (uint8_t *) calloc(1, ef_size); memcpy(tmp, file_get_data(ef), ef_size); - asn1_find_tag(tmp, ef_size, TAG_IMF, &chal_len, &chal); - chal[0] = v >> 56; - chal[1] = v >> 48; - chal[2] = v >> 40; - chal[3] = v >> 32; - chal[4] = v >> 24; - chal[5] = v >> 16; - chal[6] = v >> 8; - chal[7] = v & 0xff; - flash_write_data_to_file(ef, tmp, ef_size); + asn1_ctx_t ctxt; + asn1_ctx_init(tmp, ef_size, &ctxt); + asn1_find_tag(&ctxt, TAG_IMF, &chal); + chal.data[0] = v >> 56; + chal.data[1] = v >> 48; + chal.data[2] = v >> 40; + chal.data[3] = v >> 32; + chal.data[4] = v >> 24; + chal.data[5] = v >> 16; + chal.data[6] = v >> 8; + chal.data[7] = v & 0xff; + file_put_data(ef, tmp, ef_size); low_flash_available(); free(tmp); } @@ -443,15 +438,15 @@ int cmd_calculate() { } int cmd_calculate_all() { - size_t chal_len = 0, name_len = 0, key_len = 0, prop_len = 0; - uint8_t *chal = NULL, *name = NULL, *key = NULL, *prop = NULL; + asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 }, prop = { 0 }; + asn1_ctx_init(apdu.data, apdu.nc, &ctxi); if (P2(apdu) != 0x0 && P2(apdu) != 0x1) { return SW_INCORRECT_P1P2(); } if (validated == false) { return SW_SECURITY_STATUS_NOT_SATISFIED(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_CHALLENGE, &chal_len, &chal) == false) { + if (asn1_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) { return SW_INCORRECT_PARAMS(); } res_APDU_size = 0; @@ -460,31 +455,30 @@ int cmd_calculate_all() { if (file_has_data(ef)) { const uint8_t *ef_data = file_get_data(ef); size_t ef_len = file_get_size(ef); - if (asn1_find_tag(ef_data, ef_len, TAG_NAME, &name_len, - &name) == false || - asn1_find_tag(ef_data, ef_len, TAG_KEY, &key_len, &key) == false) { + asn1_ctx_t ctxe; + asn1_ctx_init((uint8_t *)ef_data, ef_len, &ctxe); + if (asn1_find_tag(&ctxe, TAG_NAME, &name) == false || asn1_find_tag(&ctxe, TAG_KEY, &key) == false) { continue; } res_APDU[res_APDU_size++] = TAG_NAME; - res_APDU[res_APDU_size++] = name_len; - memcpy(res_APDU + res_APDU_size, name, name_len); res_APDU_size += name_len; - if ((key[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) { + res_APDU[res_APDU_size++] = name.len; + memcpy(res_APDU + res_APDU_size, name.data, name.len); res_APDU_size += name.len; + if ((key.data[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) { res_APDU[res_APDU_size++] = TAG_NO_RESPONSE; res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = key[1]; + res_APDU[res_APDU_size++] = key.data[1]; } - else if (asn1_find_tag(ef_data, ef_len, TAG_PROPERTY, &prop_len, - &prop) == true && (prop[0] & PROP_TOUCH)) { + else if (asn1_find_tag(&ctxe, TAG_PROPERTY, &prop) == true && (prop.data[0] & PROP_TOUCH)) { res_APDU[res_APDU_size++] = TAG_TOUCH_RESPONSE; res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = key[1]; + res_APDU[res_APDU_size++] = key.data[1]; } else { res_APDU[res_APDU_size++] = TAG_RESPONSE + P2(apdu); - int ret = calculate_oath(P2(apdu), key, key_len, chal, chal_len); + int ret = calculate_oath(P2(apdu), key.data, key.len, chal.data, chal.len); if (ret != CCID_OK) { res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = key[1]; + res_APDU[res_APDU_size++] = key.data[1]; } } } @@ -498,101 +492,105 @@ int cmd_send_remaining() { } int cmd_set_otp_pin() { - size_t pw_len = 0; - uint8_t *pw = NULL, hsh[33] = { 0 }; + uint8_t hsh[33] = { 0 }; file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF); if (file_has_data(ef_otp_pin)) { return SW_CONDITIONS_NOT_SATISFIED(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_PASSWORD, &pw_len, &pw) == false) { + asn1_ctx_t ctxi, pw = { 0 }; + asn1_ctx_init(apdu.data, apdu.nc, &ctxi); + if (asn1_find_tag(&ctxi, TAG_PASSWORD, &pw) == false) { return SW_INCORRECT_PARAMS(); } hsh[0] = MAX_OTP_COUNTER; - double_hash_pin(pw, pw_len, hsh + 1); - flash_write_data_to_file(ef_otp_pin, hsh, sizeof(hsh)); + double_hash_pin(pw.data, pw.len, hsh + 1); + file_put_data(ef_otp_pin, hsh, sizeof(hsh)); low_flash_available(); return SW_OK(); } int cmd_change_otp_pin() { - size_t pw_len = 0, new_pw_len = 0; - uint8_t *pw = NULL, *new_pw = NULL, hsh[33] = { 0 }; + uint8_t hsh[33] = { 0 }; file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF); if (!file_has_data(ef_otp_pin)) { return SW_CONDITIONS_NOT_SATISFIED(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_PASSWORD, &pw_len, &pw) == false) { + asn1_ctx_t ctxi, pw = { 0 }, new_pw = { 0 }; + asn1_ctx_init(apdu.data, apdu.nc, &ctxi); + if (asn1_find_tag(&ctxi, TAG_PASSWORD, &pw) == false) { return SW_INCORRECT_PARAMS(); } - double_hash_pin(pw, pw_len, hsh + 1); + double_hash_pin(pw.data, pw.len, hsh + 1); if (memcmp(file_get_data(ef_otp_pin) + 1, hsh + 1, 32) != 0) { return SW_SECURITY_STATUS_NOT_SATISFIED(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_NEW_PASSWORD, &new_pw_len, &new_pw) == false) { + if (asn1_find_tag(&ctxi, TAG_NEW_PASSWORD, &new_pw) == false) { return SW_INCORRECT_PARAMS(); } hsh[0] = MAX_OTP_COUNTER; - double_hash_pin(new_pw, new_pw_len, hsh + 1); - flash_write_data_to_file(ef_otp_pin, hsh, sizeof(hsh)); + double_hash_pin(new_pw.data, new_pw.len, hsh + 1); + file_put_data(ef_otp_pin, hsh, sizeof(hsh)); low_flash_available(); return SW_OK(); } int cmd_verify_otp_pin() { - size_t pw_len = 0; - uint8_t *pw = NULL, hsh[33] = { 0 }, data_hsh[33]; + uint8_t hsh[33] = { 0 }, data_hsh[33]; file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF); if (!file_has_data(ef_otp_pin)) { return SW_CONDITIONS_NOT_SATISFIED(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_PASSWORD, &pw_len, &pw) == false) { + asn1_ctx_t ctxi, pw = { 0 }; + asn1_ctx_init(apdu.data, apdu.nc, &ctxi); + if (asn1_find_tag(&ctxi, TAG_PASSWORD, &pw) == false) { return SW_INCORRECT_PARAMS(); } - double_hash_pin(pw, pw_len, hsh + 1); + double_hash_pin(pw.data, pw.len, hsh + 1); memcpy(data_hsh, file_get_data(ef_otp_pin), sizeof(data_hsh)); if (data_hsh[0] == 0 || memcmp(data_hsh + 1, hsh + 1, 32) != 0) { if (data_hsh[0] > 0) { data_hsh[0] -= 1; } - flash_write_data_to_file(ef_otp_pin, data_hsh, sizeof(data_hsh)); + file_put_data(ef_otp_pin, data_hsh, sizeof(data_hsh)); low_flash_available(); validated = false; return SW_SECURITY_STATUS_NOT_SATISFIED(); } data_hsh[0] = MAX_OTP_COUNTER; - flash_write_data_to_file(ef_otp_pin, data_hsh, sizeof(data_hsh)); + file_put_data(ef_otp_pin, data_hsh, sizeof(data_hsh)); low_flash_available(); validated = true; return SW_OK(); } int cmd_verify_hotp() { - size_t key_len = 0, chal_len = 0, name_len = 0, code_len = 0; - uint8_t *key = NULL, *chal = NULL, *name = NULL, *code = NULL; + asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 }, code = { 0 }; + asn1_ctx_init(apdu.data, apdu.nc, &ctxi); uint32_t code_int = 0; - if (asn1_find_tag(apdu.data, apdu.nc, TAG_NAME, &name_len, &name) == false) { + if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) { return SW_INCORRECT_PARAMS(); } - file_t *ef = find_oath_cred(name, name_len); + file_t *ef = find_oath_cred(name.data, name.len); if (file_has_data(ef) == false) { return SW_DATA_INVALID(); } - if (asn1_find_tag(file_get_data(ef), file_get_size(ef), TAG_KEY, &key_len, &key) == false) { + asn1_ctx_t ctxe; + asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxe); + if (asn1_find_tag(&ctxe, TAG_KEY, &key) == false) { return SW_INCORRECT_PARAMS(); } - if ((key[0] & OATH_TYPE_MASK) != OATH_TYPE_HOTP) { + if ((key.data[0] & OATH_TYPE_MASK) != OATH_TYPE_HOTP) { return SW_DATA_INVALID(); } - if (asn1_find_tag(file_get_data(ef), file_get_size(ef), TAG_IMF, &chal_len, - &chal) == false) { + if (asn1_find_tag(&ctxe, TAG_IMF, &chal) == false) { return SW_INCORRECT_PARAMS(); } - if (asn1_find_tag(apdu.data, apdu.nc, TAG_RESPONSE, &code_len, &code) == true) { - code_int = (code[0] << 24) | (code[1] << 16) | (code[2] << 8) | code[3]; + if (asn1_find_tag(&ctxi, TAG_RESPONSE, &code) == true) { + code_int = (code.data[0] << 24) | (code.data[1] << 16) | (code.data[2] << 8) | code.data[3]; } - int ret = calculate_oath(0x01, key, key_len, chal, chal_len); + int ret = calculate_oath(0x01, key.data, key.len, chal.data, chal.len); if (ret != CCID_OK) { return SW_EXEC_ERROR(); } diff --git a/src/fido/otp.c b/src/fido/otp.c index e37e779..daee316 100644 --- a/src/fido/otp.c +++ b/src/fido/otp.c @@ -23,6 +23,7 @@ #include "version.h" #include "asn1.h" #include "hid/ctap_hid.h" +#include "usb.h" #ifndef ENABLE_EMULATION #include "bsp/board.h" #endif @@ -169,7 +170,7 @@ void init_otp() { memcpy(new_data, data, sizeof(new_data)); new_data[otp_config_size] = counter >> 8; new_data[otp_config_size + 1] = counter & 0xff; - flash_write_data_to_file(ef, new_data, sizeof(new_data)); + file_put_data(ef, new_data, sizeof(new_data)); } } } @@ -258,7 +259,7 @@ int otp_button_pressed(uint8_t slot) { uint8_t new_otp_config[otp_config_size + sizeof(new_chal)]; memcpy(new_otp_config, otp_config, otp_config_size); memcpy(new_otp_config + otp_config_size, new_chal, sizeof(new_chal)); - flash_write_data_to_file(ef, new_otp_config, sizeof(new_otp_config)); + file_put_data(ef, new_otp_config, sizeof(new_otp_config)); low_flash_available(); } if (otp_config->tkt_flags & APPEND_CR) { @@ -322,7 +323,7 @@ int otp_button_pressed(uint8_t slot) { memcpy(new_data, data, sizeof(new_data)); new_data[otp_config_size] = counter >> 8; new_data[otp_config_size + 1] = counter & 0xff; - flash_write_data_to_file(ef, new_data, sizeof(new_data)); + file_put_data(ef, new_data, sizeof(new_data)); low_flash_available(); } } @@ -387,7 +388,7 @@ int cmd_otp() { return SW_WRONG_DATA(); } memset(apdu.data + otp_config_size, 0, 8); // Add 8 bytes extra - flash_write_data_to_file(ef, apdu.data, otp_config_size + 8); + file_put_data(ef, apdu.data, otp_config_size + 8); low_flash_available(); config_seq++; return otp_status(); @@ -420,7 +421,7 @@ int cmd_otp() { (odata->tkt_flags & TKTFLAG_UPDATE_MASK); odata->cfg_flags = (otpc->cfg_flags & ~CFGFLAG_UPDATE_MASK) | (odata->cfg_flags & CFGFLAG_UPDATE_MASK); - flash_write_data_to_file(ef, apdu.data, otp_config_size); + file_put_data(ef, apdu.data, otp_config_size); low_flash_available(); } } @@ -434,13 +435,13 @@ int cmd_otp() { ef1_data = true; } if (file_has_data(ef2)) { - flash_write_data_to_file(ef1, file_get_data(ef2), file_get_size(ef2)); + file_put_data(ef1, file_get_data(ef2), file_get_size(ef2)); } else { delete_file(ef1); } if (ef1_data) { - flash_write_data_to_file(ef2, tmp, sizeof(tmp)); + file_put_data(ef2, tmp, sizeof(tmp)); } else { delete_file(ef2); diff --git a/tests/pico-fido/test_020_register.py b/tests/pico-fido/test_020_register.py index 378a13e..bbb2dd1 100644 --- a/tests/pico-fido/test_020_register.py +++ b/tests/pico-fido/test_020_register.py @@ -147,11 +147,13 @@ def test_bad_type_pubKeyCredParams_alg(device): with pytest.raises(CtapError) as e: device.doMC(key_params=[{"alg": "7", "type": "public-key"}]) + assert e.value.code == CtapError.ERR.CBOR_UNEXPECTED_TYPE + def test_unsupported_algorithm(device): with pytest.raises(CtapError) as e: device.doMC(key_params=[{"alg": 1337, "type": "public-key"}]) - assert e.value.code == CtapError.ERR.CBOR_UNEXPECTED_TYPE + assert e.value.code == CtapError.ERR.UNSUPPORTED_ALGORITHM def test_exclude_list(resetdevice): resetdevice.doMC(exclude_list=[{"id": b"1234", "type": "rot13"}])