mirror of
https://github.com/polhenarejos/pico-fido
synced 2026-06-04 11:59:06 +02:00
Compare commits
12 Commits
v7.6
...
nightly-ma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ffcfb4beb | ||
|
|
3ccd6e827f | ||
|
|
a2044d697d | ||
|
|
659c04c837 | ||
|
|
a0437dbfb2 | ||
|
|
604e7868e2 | ||
|
|
0e3d0d9a7d | ||
|
|
1f4be2a051 | ||
|
|
dc6007d1b4 | ||
|
|
6aa986ca06 | ||
|
|
98145a0ef4 | ||
|
|
342ae90df8 |
@@ -88,10 +88,10 @@ else()
|
||||
endif()
|
||||
|
||||
set(USB_ITF_HID 1)
|
||||
include(pico-keys-sdk/pico_keys_sdk_import.cmake)
|
||||
include(pico-keys-sdk/picokeys_sdk_import.cmake)
|
||||
|
||||
if(NOT ESP_PLATFORM)
|
||||
set(SOURCES ${PICO_KEYS_SOURCES})
|
||||
set(SOURCES ${PICOKEYS_SOURCES})
|
||||
endif()
|
||||
|
||||
list(APPEND SOURCES
|
||||
@@ -147,7 +147,7 @@ if(NOT ESP_PLATFORM)
|
||||
)
|
||||
target_compile_options(pico_fido PRIVATE ${COMMON_COMPILE_OPTIONS})
|
||||
|
||||
pico_keys_apply_strict_flags(
|
||||
picokeys_apply_strict_flags(
|
||||
SOURCES ${SOURCES}
|
||||
FILTER_REGEX "/src/fido/|/pico-keys-sdk/src/|/pico-keys-sdk/config/"
|
||||
)
|
||||
@@ -193,12 +193,12 @@ if(NOT ESP_PLATFORM)
|
||||
target_link_options(pico_fido PRIVATE ${EMULATION_NON_APPLE_LINK_OPTIONS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(pico_fido PRIVATE pico_keys_sdk mbedtls pthread m)
|
||||
target_link_libraries(pico_fido PRIVATE picokeys_sdk mbedtls pthread m)
|
||||
else()
|
||||
target_link_libraries(
|
||||
pico_fido
|
||||
PRIVATE
|
||||
pico_keys_sdk
|
||||
picokeys_sdk
|
||||
pico_stdlib
|
||||
pico_multicore
|
||||
hardware_flash
|
||||
|
||||
Submodule pico-keys-sdk updated: 44ee025416...13d2e84595
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#if defined(PICO_PLATFORM)
|
||||
#include "pico/stdlib.h"
|
||||
#endif
|
||||
@@ -34,9 +34,9 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next);
|
||||
|
||||
const uint8_t aaguid[16] = { 0x89, 0xFB, 0x94, 0xB7, 0x06, 0xC9, 0x36, 0x73, 0x9B, 0x7E, 0x30, 0x52, 0x6D, 0x96, 0x81, 0x45 }; // First 16 bytes of SHA256("Pico FIDO2")
|
||||
|
||||
const uint8_t *cbor_data = NULL;
|
||||
size_t cbor_len = 0;
|
||||
uint8_t cbor_cmd = 0;
|
||||
static const uint8_t *volatile cbor_data = NULL;
|
||||
static volatile size_t cbor_len = 0;
|
||||
static volatile uint8_t cbor_cmd = 0;
|
||||
|
||||
int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
if (len == 0 && cmd == CTAPHID_CBOR) {
|
||||
@@ -108,7 +108,10 @@ void *cbor_thread(void *arg) {
|
||||
if (m == EV_EXIT) {
|
||||
break;
|
||||
}
|
||||
apdu.sw = (uint16_t)cbor_parse(cbor_cmd, cbor_data, cbor_len);
|
||||
const uint8_t *data = (const uint8_t *)cbor_data;
|
||||
size_t len = cbor_len;
|
||||
uint8_t cmd = cbor_cmd;
|
||||
apdu.sw = (uint16_t)cbor_parse(cmd, data, len);
|
||||
if (apdu.sw == 0) {
|
||||
DEBUG_DATA(res_APDU, res_APDU_size);
|
||||
}
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/ecdh.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "mbedtls/hkdf.h"
|
||||
#include "mbedtls/constant_time.h"
|
||||
#include "cbor.h"
|
||||
#include "ctap.h"
|
||||
#include "ctap2_cbor.h"
|
||||
@@ -99,7 +100,7 @@ static int regenerate(void) {
|
||||
mbedtls_ecdh_init(&hkey);
|
||||
hkey_init = true;
|
||||
mbedtls_ecdh_setup(&hkey, MBEDTLS_ECP_DP_SECP256R1);
|
||||
int ret = mbedtls_ecdh_gen_public(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.d, &hkey.ctx.mbed_ecdh.Q, random_gen, NULL);
|
||||
int ret = mbedtls_ecdh_gen_public(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.d, &hkey.ctx.mbed_ecdh.Q, random_fill_iterator, NULL);
|
||||
mbedtls_mpi_lset(&hkey.ctx.mbed_ecdh.Qp.Z, 1);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
@@ -131,7 +132,7 @@ static int kdf(uint8_t protocol, const mbedtls_mpi *z, uint8_t *sharedSecret) {
|
||||
int ecdh(uint8_t protocol, const mbedtls_ecp_point *Q, uint8_t *sharedSecret) {
|
||||
mbedtls_mpi z;
|
||||
mbedtls_mpi_init(&z);
|
||||
int ret = mbedtls_ecdh_compute_shared(&hkey.ctx.mbed_ecdh.grp, &z, Q, &hkey.ctx.mbed_ecdh.d, random_gen, NULL);
|
||||
int ret = mbedtls_ecdh_compute_shared(&hkey.ctx.mbed_ecdh.grp, &z, Q, &hkey.ctx.mbed_ecdh.d, random_fill_iterator, NULL);
|
||||
ret = kdf(protocol, &z, sharedSecret);
|
||||
mbedtls_mpi_free(&z);
|
||||
return ret;
|
||||
@@ -142,11 +143,11 @@ static void resetAuthToken(bool persistent) {
|
||||
if (persistent) {
|
||||
fid = EF_PAUTHTOKEN;
|
||||
}
|
||||
file_t *ef = search_by_fid(fid, NULL, SPECIFY_EF);
|
||||
file_t *ef = file_search_by_fid(fid, NULL, SPECIFY_EF);
|
||||
uint8_t t[32];
|
||||
random_gen(NULL, t, sizeof(t));
|
||||
random_fill_buffer(t, sizeof(t));
|
||||
file_put_data(ef, t, sizeof(t));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
|
||||
int resetPinUvAuthToken(void) {
|
||||
@@ -159,7 +160,7 @@ int resetPinUvAuthToken(void) {
|
||||
|
||||
int resetPersistentPinUvAuthToken(void) {
|
||||
resetAuthToken(true);
|
||||
file_t *ef_pauthtoken = search_by_fid(EF_PAUTHTOKEN, NULL, SPECIFY_EF);
|
||||
file_t *ef_pauthtoken = file_search_by_fid(EF_PAUTHTOKEN, NULL, SPECIFY_EF);
|
||||
ppaut.permissions = 0;
|
||||
ppaut.data = file_get_data(ef_pauthtoken);
|
||||
ppaut.len = file_get_size(ef_pauthtoken);
|
||||
@@ -169,12 +170,12 @@ int resetPersistentPinUvAuthToken(void) {
|
||||
int encrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, uint16_t in_len, uint8_t *out) {
|
||||
if (protocol == 1) {
|
||||
memcpy(out, in, in_len);
|
||||
return aes_encrypt(key, NULL, 32 * 8, PICO_KEYS_AES_MODE_CBC, out, in_len);
|
||||
return aes_encrypt(key, NULL, 32 * 8, PICOKEYS_AES_MODE_CBC, out, in_len);
|
||||
}
|
||||
else if (protocol == 2) {
|
||||
random_gen(NULL, out, IV_SIZE);
|
||||
random_fill_buffer(out, IV_SIZE);
|
||||
memcpy(out + IV_SIZE, in, in_len);
|
||||
return aes_encrypt(key + 32, out, 32 * 8, PICO_KEYS_AES_MODE_CBC, out + IV_SIZE, in_len);
|
||||
return aes_encrypt(key + 32, out, 32 * 8, PICOKEYS_AES_MODE_CBC, out + IV_SIZE, in_len);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -183,11 +184,11 @@ int encrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, uint16_t in
|
||||
int decrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, uint16_t in_len, uint8_t *out) {
|
||||
if (protocol == 1) {
|
||||
memcpy(out, in, in_len);
|
||||
return aes_decrypt(key, NULL, 32 * 8, PICO_KEYS_AES_MODE_CBC, out, in_len);
|
||||
return aes_decrypt(key, NULL, 32 * 8, PICOKEYS_AES_MODE_CBC, out, in_len);
|
||||
}
|
||||
else if (protocol == 2) {
|
||||
memcpy(out, in + IV_SIZE, in_len - IV_SIZE);
|
||||
return aes_decrypt(key + 32, in, 32 * 8, PICO_KEYS_AES_MODE_CBC, out, in_len - IV_SIZE);
|
||||
return aes_decrypt(key + 32, in, 32 * 8, PICOKEYS_AES_MODE_CBC, out, in_len - IV_SIZE);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -221,10 +222,10 @@ int verify(uint8_t protocol, const uint8_t *key, const uint8_t *data, uint16_t l
|
||||
return ret;
|
||||
}
|
||||
if (protocol == 1) {
|
||||
return ct_memcmp(sign, hmac, 16);
|
||||
return mbedtls_ct_memcmp(sign, hmac, 16);
|
||||
}
|
||||
else if (protocol == 2) {
|
||||
return ct_memcmp(sign, hmac, 32);
|
||||
return mbedtls_ct_memcmp(sign, hmac, 32);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -266,9 +267,9 @@ static int check_keydev_encrypted(const uint8_t pin_token[32]) {
|
||||
encrypt_with_aad(pin_token, file_get_data(ef_keydev) + 1, 32, 2, tmp_keydev + 1);
|
||||
file_put_data(ef_keydev, tmp_keydev, sizeof(tmp_keydev));
|
||||
mbedtls_platform_zeroize(tmp_keydev, sizeof(tmp_keydev));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
|
||||
uint8_t new_pin_mismatches = 0;
|
||||
@@ -400,7 +401,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
pin_len++;
|
||||
}
|
||||
uint8_t minPin = 4;
|
||||
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
file_t *ef_minpin = file_search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef_minpin)) {
|
||||
minPin = *file_get_data(ef_minpin);
|
||||
}
|
||||
@@ -415,11 +416,11 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
mbedtls_platform_zeroize(paddedNewPin, sizeof(paddedNewPin));
|
||||
pin_derive_verifier(dhash, 16, hsh + 3);
|
||||
file_put_data(ef_pin, hsh, sizeof(hsh));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
|
||||
pin_derive_session(dhash, 16, session_pin);
|
||||
ret = check_keydev_encrypted(session_pin);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
CBOR_ERROR(ret);
|
||||
}
|
||||
mbedtls_platform_zeroize(hsh, sizeof(hsh));
|
||||
@@ -474,7 +475,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
memcpy(pin_data, file_get_data(ef_pin), file_get_size(ef_pin));
|
||||
pin_data[0] -= 1;
|
||||
file_put_data(ef_pin, pin_data, file_get_size(ef_pin));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
uint8_t retries = pin_data[0];
|
||||
uint8_t paddedNewPin[64];
|
||||
ret = decrypt((uint8_t)pinUvAuthProtocol, sharedSecret, pinHashEnc.data, (uint16_t)pinHashEnc.len, paddedNewPin);
|
||||
@@ -491,7 +492,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
pin_derive_verifier(paddedNewPin, 16, dhash);
|
||||
}
|
||||
|
||||
if (ct_memcmp(dhash, file_get_data(ef_pin) + off, 32) != 0) {
|
||||
if (mbedtls_ct_memcmp(dhash, file_get_data(ef_pin) + off, 32) != 0) {
|
||||
regenerate();
|
||||
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
||||
if (retries == 0) {
|
||||
@@ -512,7 +513,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
|
||||
hash_multi(paddedNewPin, 16, session_pin);
|
||||
ret = load_keydev(keydev);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
CBOR_ERROR(CTAP2_ERR_PIN_INVALID);
|
||||
}
|
||||
encrypt_keydev_f1(keydev);
|
||||
@@ -520,10 +521,10 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
pin_derive_session(paddedNewPin, 16, session_pin);
|
||||
pin_data[0] = MAX_PIN_RETRIES;
|
||||
file_put_data(ef_pin, pin_data, sizeof(pin_data));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
|
||||
ret = check_keydev_encrypted(session_pin);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
CBOR_ERROR(ret);
|
||||
}
|
||||
|
||||
@@ -541,7 +542,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
pin_len++;
|
||||
}
|
||||
uint8_t minPin = 4;
|
||||
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
file_t *ef_minpin = file_search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef_minpin)) {
|
||||
minPin = *file_get_data(ef_minpin);
|
||||
}
|
||||
@@ -551,7 +552,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
|
||||
// New PIN is valid and verified
|
||||
ret = load_keydev(keydev);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
CBOR_ERROR(CTAP2_ERR_PIN_INVALID);
|
||||
}
|
||||
encrypt_keydev_f1(keydev);
|
||||
@@ -559,17 +560,17 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), paddedNewPin, pin_len, dhash);
|
||||
pin_derive_session(dhash, 16, session_pin);
|
||||
ret = check_keydev_encrypted(session_pin);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
CBOR_ERROR(ret);
|
||||
}
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
|
||||
pin_data[0] = MAX_PIN_RETRIES;
|
||||
pin_data[1] = pin_len;
|
||||
pin_data[2] = 1; // New format indicator
|
||||
pin_derive_verifier(dhash, 16, pin_data + 3);
|
||||
|
||||
if (file_has_data(ef_minpin) && file_get_data(ef_minpin)[1] == 1 && ct_memcmp(pin_data + 3, file_get_data(ef_pin) + 3, 32) == 0) {
|
||||
if (file_has_data(ef_minpin) && file_get_data(ef_minpin)[1] == 1 && mbedtls_ct_memcmp(pin_data + 3, file_get_data(ef_pin) + 3, 32) == 0) {
|
||||
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||
}
|
||||
file_put_data(ef_pin, pin_data, sizeof(pin_data));
|
||||
@@ -583,7 +584,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
file_put_data(ef_minpin, tmpf, file_get_size(ef_minpin));
|
||||
free(tmpf);
|
||||
}
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
resetPinUvAuthToken();
|
||||
resetPersistentPinUvAuthToken();
|
||||
needs_power_cycle = false;
|
||||
@@ -636,7 +637,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
memcpy(pin_data, file_get_data(ef_pin), file_get_size(ef_pin));
|
||||
pin_data[0] -= 1;
|
||||
file_put_data(ef_pin, pin_data, file_get_size(ef_pin));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
uint8_t retries = pin_data[0];
|
||||
uint8_t paddedNewPin[64], poff = ((uint8_t)pinUvAuthProtocol - 1) * IV_SIZE;
|
||||
ret = decrypt((uint8_t)pinUvAuthProtocol, sharedSecret, pinHashEnc.data, (uint16_t)pinHashEnc.len, paddedNewPin);
|
||||
@@ -652,7 +653,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
else {
|
||||
pin_derive_verifier(paddedNewPin, 16, dhash);
|
||||
}
|
||||
if (ct_memcmp(dhash, file_get_data(ef_pin) + off, 32) != 0) {
|
||||
if (mbedtls_ct_memcmp(dhash, file_get_data(ef_pin) + off, 32) != 0) {
|
||||
regenerate();
|
||||
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
||||
mbedtls_platform_zeroize(dhash, sizeof(dhash));
|
||||
@@ -675,7 +676,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
pin_derive_verifier(paddedNewPin, 16, pin_data + 3);
|
||||
hash_multi(paddedNewPin, 16, session_pin);
|
||||
ret = load_keydev(keydev);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
CBOR_ERROR(CTAP2_ERR_PIN_INVALID);
|
||||
}
|
||||
encrypt_keydev_f1(keydev);
|
||||
@@ -683,7 +684,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
|
||||
pin_derive_session(paddedNewPin, 16, session_pin);
|
||||
ret = check_keydev_encrypted(session_pin);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
CBOR_ERROR(ret);
|
||||
}
|
||||
|
||||
@@ -693,8 +694,8 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
||||
file_put_data(ef_pin, pin_data, sizeof(pin_data));
|
||||
mbedtls_platform_zeroize(pin_data, sizeof(pin_data));
|
||||
|
||||
low_flash_available();
|
||||
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
flash_commit();
|
||||
file_t *ef_minpin = file_search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef_minpin) && file_get_data(ef_minpin)[1] == 1) {
|
||||
CBOR_ERROR(CTAP2_ERR_PIN_INVALID);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "ctap2_cbor.h"
|
||||
#include "fido.h"
|
||||
#include "ctap.h"
|
||||
@@ -151,7 +151,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
file_put_data(ef_keydev, keydev_dec, sizeof(keydev_dec));
|
||||
mbedtls_platform_zeroize(keydev_dec, sizeof(keydev_dec));
|
||||
file_put_data(ef_keydev_enc, NULL, 0); // Set ef to 0 bytes
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
else if (vendorCommandId == CTAP_CONFIG_AUT_ENABLE) {
|
||||
if (!file_has_data(ef_keydev)) {
|
||||
@@ -168,7 +168,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
}
|
||||
|
||||
uint8_t key_dev_enc[12 + 32 + 16];
|
||||
random_gen(NULL, key_dev_enc, 12);
|
||||
random_fill_buffer(key_dev_enc, 12);
|
||||
mbedtls_chachapoly_init(&chatx);
|
||||
mbedtls_chachapoly_setkey(&chatx, vendorParamByteString.data);
|
||||
ret = mbedtls_chachapoly_encrypt_and_tag(&chatx, file_get_size(ef_keydev), key_dev_enc, NULL, 0, file_get_data(ef_keydev), key_dev_enc + 12, key_dev_enc + 12 + file_get_size(ef_keydev));
|
||||
@@ -181,17 +181,17 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
mbedtls_platform_zeroize(key_dev_enc, sizeof(key_dev_enc));
|
||||
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();
|
||||
flash_commit();
|
||||
}
|
||||
else if (vendorCommandId == CTAP_CONFIG_EA_UPLOAD) {
|
||||
if (vendorParamByteString.present == false) {
|
||||
CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER);
|
||||
}
|
||||
file_t *ef_ee_ea = search_by_fid(EF_EE_DEV_EA, NULL, SPECIFY_EF);
|
||||
file_t *ef_ee_ea = file_search_by_fid(EF_EE_DEV_EA, NULL, SPECIFY_EF);
|
||||
if (ef_ee_ea) {
|
||||
file_put_data(ef_ee_ea, vendorParamByteString.data, (uint16_t)vendorParamByteString.len);
|
||||
}
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
else if (vendorCommandId == CTAP_CONFIG_PIN_POLICY) {
|
||||
file_t *ef_pin_policy = file_new(EF_PIN_COMPLEXITY_POLICY);
|
||||
@@ -206,7 +206,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
free(val);
|
||||
}
|
||||
}
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
else {
|
||||
CBOR_ERROR(CTAP2_ERR_INVALID_SUBCOMMAND);
|
||||
@@ -215,7 +215,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
}
|
||||
else if (subcommand == 0x03) {
|
||||
uint8_t currentMinPinLen = 4;
|
||||
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
file_t *ef_minpin = file_search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef_minpin)) {
|
||||
currentMinPinLen = *file_get_data(ef_minpin);
|
||||
}
|
||||
@@ -242,7 +242,7 @@ int cbor_config(const uint8_t *data, size_t len) {
|
||||
mbedtls_sha256((uint8_t *) minPinLengthRPIDs[m].data, minPinLengthRPIDs[m].len, dataf + 2 + m * 32, 0);
|
||||
}
|
||||
file_put_data(ef_minpin, dataf, (uint16_t)(2 + minPinLengthRPIDs_len * 32));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
free(dataf);
|
||||
goto err; //No return
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "fido.h"
|
||||
#include "ctap.h"
|
||||
#include "hid/ctap_hid.h"
|
||||
@@ -137,7 +137,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
|
||||
}
|
||||
uint8_t existing = 0;
|
||||
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) {
|
||||
if (file_has_data(search_dynamic_file((uint16_t)(EF_CRED + i)))) {
|
||||
if (file_has_data(file_search((uint16_t)(EF_CRED + i)))) {
|
||||
existing++;
|
||||
}
|
||||
}
|
||||
@@ -173,7 +173,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
|
||||
}
|
||||
uint8_t skip = 0;
|
||||
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) {
|
||||
file_t *tef = search_dynamic_file((uint16_t)(EF_RP + i));
|
||||
file_t *tef = file_search((uint16_t)(EF_RP + i));
|
||||
if (file_has_data(tef) && *file_get_data(tef) > 0) {
|
||||
if (++skip == rp_counter) {
|
||||
if (rp_ef == NULL) {
|
||||
@@ -239,7 +239,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
|
||||
file_t *cred_ef = NULL;
|
||||
uint8_t skip = 0;
|
||||
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) {
|
||||
file_t *tef = search_dynamic_file((uint16_t)(EF_CRED + i));
|
||||
file_t *tef = file_search((uint16_t)(EF_CRED + i));
|
||||
if (file_has_data(tef) && memcmp(file_get_data(tef), rpIdHash.data, 32) == 0) {
|
||||
if (++skip == cred_counter) {
|
||||
if (cred_ef == NULL) {
|
||||
@@ -373,20 +373,20 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
|
||||
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
||||
}
|
||||
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_CRED + i));
|
||||
file_t *ef = file_search((uint16_t)(EF_CRED + i));
|
||||
if (file_has_data(ef) && memcmp(file_get_data(ef) + 32, credentialId.id.data, CRED_RESIDENT_LEN) == 0) {
|
||||
uint8_t *rp_id_hash = file_get_data(ef);
|
||||
if (delete_file(ef) != 0) {
|
||||
if (file_delete(ef) != 0) {
|
||||
CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED);
|
||||
}
|
||||
for (int j = 0; j < MAX_RESIDENT_CREDENTIALS; j++) {
|
||||
file_t *rp_ef = search_dynamic_file((uint16_t)(EF_RP + j));
|
||||
file_t *rp_ef = file_search((uint16_t)(EF_RP + j));
|
||||
if (file_has_data(rp_ef) && memcmp(file_get_data(rp_ef) + 1, rp_id_hash, 32) == 0) {
|
||||
uint8_t *rp_data = (uint8_t *) calloc(1, file_get_size(rp_ef));
|
||||
memcpy(rp_data, file_get_data(rp_ef), file_get_size(rp_ef));
|
||||
rp_data[0] -= 1;
|
||||
if (rp_data[0] == 0) {
|
||||
delete_file(rp_ef);
|
||||
file_delete(rp_ef);
|
||||
}
|
||||
else {
|
||||
file_put_data(rp_ef, rp_data, file_get_size(rp_ef));
|
||||
@@ -395,7 +395,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
goto err; //no error
|
||||
}
|
||||
}
|
||||
@@ -415,7 +415,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
|
||||
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
||||
}
|
||||
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_CRED + i));
|
||||
file_t *ef = file_search((uint16_t)(EF_CRED + i));
|
||||
if (file_has_data(ef) && memcmp(file_get_data(ef) + 32, credentialId.id.data, CRED_RESIDENT_LEN) == 0) {
|
||||
Credential cred = { 0 };
|
||||
uint8_t *rp_id_hash = file_get_data(ef);
|
||||
@@ -439,7 +439,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
|
||||
if (credential_store(newcred, newcred_len, rp_id_hash) != 0) {
|
||||
CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED);
|
||||
}
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
goto err; //no error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "cbor.h"
|
||||
#include "ctap.h"
|
||||
#if defined(PICO_PLATFORM)
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "random.h"
|
||||
|
||||
int cbor_get_assertion(const uint8_t *data, size_t len, bool next);
|
||||
extern char *rp_id, *user_name, *display_name;
|
||||
|
||||
bool residentx = false;
|
||||
Credential credsx[MAX_CREDENTIAL_COUNT_IN_LIST] = { 0 };
|
||||
@@ -205,6 +206,9 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
|
||||
if (rpId.present == false || clientDataHash.present == false) {
|
||||
CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER);
|
||||
}
|
||||
rp_id = rpId.data;
|
||||
user_name = NULL;
|
||||
display_name = NULL;
|
||||
|
||||
uint8_t flags = 0;
|
||||
uint8_t rp_id_hash[32] = {0};
|
||||
@@ -301,7 +305,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
|
||||
}
|
||||
if (credential_is_resident(allowList[e].id.data, allowList[e].id.len)) {
|
||||
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS && creds_len < MAX_CREDENTIAL_COUNT_IN_LIST; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_CRED + i));
|
||||
file_t *ef = file_search((uint16_t)(EF_CRED + i));
|
||||
if (!file_has_data(ef) || memcmp(file_get_data(ef), rp_id_hash, 32) != 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -328,7 +332,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
|
||||
// Even we provide allowList, we need to check if the credential is resident
|
||||
if (!resident) {
|
||||
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS && creds_len < MAX_CREDENTIAL_COUNT_IN_LIST; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_CRED + i));
|
||||
file_t *ef = file_search((uint16_t)(EF_CRED + i));
|
||||
if (!file_has_data(ef) || memcmp(file_get_data(ef), rp_id_hash, 32) != 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -347,7 +351,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS && creds_len < MAX_CREDENTIAL_COUNT_IN_LIST; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_CRED + i));
|
||||
file_t *ef = file_search((uint16_t)(EF_CRED + i));
|
||||
if (!file_has_data(ef) || memcmp(file_get_data(ef), rp_id_hash, 32) != 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -401,7 +405,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
|
||||
}
|
||||
if (credential_is_resident(allowList[e].id.data, allowList[e].id.len)) {
|
||||
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS && creds_len < MAX_CREDENTIAL_COUNT_IN_LIST; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_CRED + i));
|
||||
file_t *ef = file_search((uint16_t)(EF_CRED + i));
|
||||
if (!file_has_data(ef) || memcmp(file_get_data(ef), rp_id_hash, 32) != 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -611,7 +615,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
|
||||
uint8_t *pa = aut_data;
|
||||
memcpy(pa, rp_id_hash, 32); pa += 32;
|
||||
*pa++ = flags;
|
||||
pa += put_uint32_t_be(ctr, pa);
|
||||
pa += put_uint32_be(ctr, pa);
|
||||
memcpy(pa, ext, ext_len); pa += ext_len;
|
||||
if ((size_t)(pa - aut_data) != aut_data_len) {
|
||||
CBOR_ERROR(CTAP1_ERR_OTHER);
|
||||
@@ -644,11 +648,11 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
|
||||
#endif
|
||||
if (md != NULL) {
|
||||
ret = mbedtls_md(md, aut_data, aut_data_len + clientDataHash.len, hash);
|
||||
ret = mbedtls_ecdsa_write_signature(&ekey, mbedtls_md_get_type(md), hash, mbedtls_md_get_size(md), sig, sizeof(sig), &olen, random_gen, NULL);
|
||||
ret = mbedtls_ecdsa_write_signature(&ekey, mbedtls_md_get_type(md), hash, mbedtls_md_get_size(md), sig, sizeof(sig), &olen, random_fill_iterator, NULL);
|
||||
}
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
else {
|
||||
ret = mbedtls_eddsa_write_signature(&ekey, aut_data, aut_data_len + clientDataHash.len, sig, sizeof(sig), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL);
|
||||
ret = mbedtls_eddsa_write_signature(&ekey, aut_data, aut_data_len + clientDataHash.len, sig, sizeof(sig), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_fill_iterator, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -739,7 +743,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
|
||||
resp_size = cbor_encoder_get_buffer_size(&encoder, ctap_resp->init.data + 1);
|
||||
ctr++;
|
||||
file_put_data(ef_counter, (uint8_t *) &ctr, sizeof(ctr));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
err:
|
||||
CBOR_FREE_BYTE_STRING(clientDataHash);
|
||||
CBOR_FREE_BYTE_STRING(pinUvAuthParam);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "ctap2_cbor.h"
|
||||
#include "hid/ctap_hid.h"
|
||||
#include "fido.h"
|
||||
@@ -36,7 +36,7 @@ int cbor_get_info(void) {
|
||||
#else
|
||||
lfields++;
|
||||
#endif
|
||||
file_t *ef_pin_policy = search_by_fid(EF_PIN_COMPLEXITY_POLICY, NULL, SPECIFY_EF);
|
||||
file_t *ef_pin_policy = file_search_by_fid(EF_PIN_COMPLEXITY_POLICY, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef_pin_policy)) {
|
||||
lfields += 2;
|
||||
}
|
||||
@@ -144,7 +144,7 @@ int cbor_get_info(void) {
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0B));
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, MAX_LARGE_BLOB_SIZE)); // maxSerializedLargeBlobArray
|
||||
|
||||
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
file_t *ef_minpin = file_search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0C));
|
||||
if (file_has_data(ef_minpin) && file_get_data(ef_minpin)[1] == 1) {
|
||||
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, true));
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "ctap2_cbor.h"
|
||||
#include "fido.h"
|
||||
#include "ctap.h"
|
||||
@@ -129,7 +129,7 @@ int cbor_large_blobs(const uint8_t *data, size_t len) {
|
||||
uint8_t verify_data[70] = { 0 };
|
||||
memset(verify_data, 0xff, 32);
|
||||
verify_data[32] = 0x0C;
|
||||
put_uint32_t_le((uint32_t)offset, verify_data + 34);
|
||||
put_uint32_le((uint32_t)offset, verify_data + 34);
|
||||
mbedtls_sha256(set.data, set.len, verify_data + 38, 0);
|
||||
if (verify((uint8_t)pinUvAuthProtocol, paut.data, verify_data, (uint16_t)sizeof(verify_data), pinUvAuthParam.data) != 0) {
|
||||
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
||||
@@ -152,7 +152,7 @@ int cbor_large_blobs(const uint8_t *data, size_t len) {
|
||||
CBOR_ERROR(CTAP2_ERR_INTEGRITY_FAILURE);
|
||||
}
|
||||
file_put_data(ef_largeblob, temp_lba, (uint16_t)expectedLength);
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "cbor_make_credential.h"
|
||||
#include "ctap2_cbor.h"
|
||||
#include "hid/ctap_hid.h"
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "random.h"
|
||||
#include "crypto_utils.h"
|
||||
|
||||
char *rp_id = NULL, *user_name = NULL, *display_name = NULL;
|
||||
|
||||
int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
CborParser parser;
|
||||
CborValue map;
|
||||
@@ -192,6 +194,9 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
}
|
||||
}
|
||||
CBOR_PARSE_MAP_END(map, 1);
|
||||
rp_id = rp.id.data;
|
||||
user_name = user.parent.name.data;
|
||||
display_name = user.displayName.data;
|
||||
|
||||
uint8_t flags = FIDO2_AUT_FLAG_AT;
|
||||
uint8_t rp_id_hash[32] = {0};
|
||||
@@ -352,7 +357,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
Credential ecred = {0};
|
||||
if (credential_is_resident(excludeList[e].id.data, excludeList[e].id.len)) {
|
||||
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) {
|
||||
file_t *ef_cred = search_dynamic_file((uint16_t)(EF_CRED + i));
|
||||
file_t *ef_cred = file_search((uint16_t)(EF_CRED + i));
|
||||
if (!file_has_data(ef_cred) || memcmp(file_get_data(ef_cred), rp_id_hash, 32) != 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -423,7 +428,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
l++;
|
||||
}
|
||||
if (extensions.minPinLength == ptrue) {
|
||||
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
file_t *ef_minpin = file_search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef_minpin)) {
|
||||
uint8_t *minpin_data = file_get_data(ef_minpin);
|
||||
for (int o = 2; o < file_get_size(ef_minpin); o += 32) {
|
||||
@@ -517,7 +522,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
}
|
||||
if (pin_complexity_policy == ptrue) {
|
||||
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "pinComplexityPolicy"));
|
||||
file_t *ef_pin_complexity_policy = search_by_fid(EF_PIN_COMPLEXITY_POLICY, NULL, SPECIFY_EF);
|
||||
file_t *ef_pin_complexity_policy = file_search_by_fid(EF_PIN_COMPLEXITY_POLICY, NULL, SPECIFY_EF);
|
||||
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, file_has_data(ef_pin_complexity_policy)));
|
||||
}
|
||||
|
||||
@@ -550,16 +555,16 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
uint8_t *pa = aut_data;
|
||||
memcpy(pa, rp_id_hash, 32); pa += 32;
|
||||
*pa++ = flags;
|
||||
pa += put_uint32_t_be(ctr, pa);
|
||||
pa += put_uint32_be(ctr, pa);
|
||||
memcpy(pa, aaguid, 16); pa += 16;
|
||||
if (options.rk == ptrue) {
|
||||
uint8_t cred_idr[CRED_RESIDENT_LEN] = {0};
|
||||
pa += put_uint16_t_be(sizeof(cred_idr), pa);
|
||||
pa += put_uint16_be(sizeof(cred_idr), pa);
|
||||
credential_derive_resident(cred_id, cred_id_len, cred_idr);
|
||||
memcpy(pa, cred_idr, sizeof(cred_idr)); pa += sizeof(cred_idr);
|
||||
}
|
||||
else {
|
||||
pa += put_uint16_t_be(cred_id_len, pa);
|
||||
pa += put_uint16_be(cred_id_len, pa);
|
||||
memcpy(pa, cred_id, cred_id_len); pa += (uint16_t)cred_id_len;
|
||||
}
|
||||
memcpy(pa, cbor_buf, rs); pa += (uint16_t)rs;
|
||||
@@ -601,11 +606,11 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
self_attestation = false;
|
||||
}
|
||||
if (md != NULL) {
|
||||
ret = mbedtls_ecdsa_write_signature(&ekey, mbedtls_md_get_type(md), hash, mbedtls_md_get_size(md), sig, sizeof(sig), &olen, random_gen, NULL);
|
||||
ret = mbedtls_ecdsa_write_signature(&ekey, mbedtls_md_get_type(md), hash, mbedtls_md_get_size(md), sig, sizeof(sig), &olen, random_fill_iterator, NULL);
|
||||
}
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
else {
|
||||
ret = mbedtls_eddsa_write_signature(&ekey, aut_data, aut_data_len + clientDataHash.len, sig, sizeof(sig), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL);
|
||||
ret = mbedtls_eddsa_write_signature(&ekey, aut_data, aut_data_len + clientDataHash.len, sig, sizeof(sig), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_fill_iterator, NULL);
|
||||
}
|
||||
#endif
|
||||
mbedtls_ecp_keypair_free(&ekey);
|
||||
@@ -646,7 +651,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
CborEncoder arrEncoder;
|
||||
file_t *ef_cert = NULL;
|
||||
if (enterpriseAttestation == 2) {
|
||||
ef_cert = search_by_fid(EF_EE_DEV_EA, NULL, SPECIFY_EF);
|
||||
ef_cert = file_search_by_fid(EF_EE_DEV_EA, NULL, SPECIFY_EF);
|
||||
}
|
||||
if (!file_has_data(ef_cert)) {
|
||||
ef_cert = ef_certdev;
|
||||
@@ -678,7 +683,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
|
||||
}
|
||||
ctr++;
|
||||
file_put_data(ef_counter, (uint8_t *) &ctr, sizeof(ctr));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
err:
|
||||
CBOR_FREE_BYTE_STRING(clientDataHash);
|
||||
CBOR_FREE_BYTE_STRING(pinUvAuthParam);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "file.h"
|
||||
#include "fido.h"
|
||||
#include "ctap2_cbor.h"
|
||||
@@ -35,11 +35,11 @@ int cbor_reset(void) {
|
||||
return CTAP2_ERR_NOT_ALLOWED;
|
||||
}
|
||||
#endif
|
||||
if (wait_button_pressed() == true) {
|
||||
if (wait_button_pressed() > 0) {
|
||||
return CTAP2_ERR_USER_ACTION_TIMEOUT;
|
||||
}
|
||||
#endif
|
||||
initialize_flash(true);
|
||||
file_initialize_flash(true);
|
||||
init_fido();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -15,14 +15,21 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "fido.h"
|
||||
#include "ctap2_cbor.h"
|
||||
#include "ctap.h"
|
||||
|
||||
extern char *rp_id, *user_name, *display_name;
|
||||
|
||||
int cbor_selection(void) {
|
||||
if (wait_button_pressed() == true) {
|
||||
rp_id = user_name = display_name = NULL;
|
||||
int ret = wait_button_pressed() ;
|
||||
if (ret == 1) {
|
||||
return CTAP2_ERR_USER_ACTION_TIMEOUT;
|
||||
}
|
||||
else if (ret == 2) {
|
||||
return CTAP2_ERR_OPERATION_DENIED;
|
||||
}
|
||||
return CTAP2_OK;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "serial.h"
|
||||
#include "ctap2_cbor.h"
|
||||
#include "fido.h"
|
||||
#include "ctap.h"
|
||||
@@ -116,7 +117,7 @@ static int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
file_put_data(ef_keydev_enc, vendorParam.data, (uint16_t)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();
|
||||
flash_commit();
|
||||
goto err;
|
||||
}
|
||||
else {
|
||||
@@ -132,7 +133,7 @@ static int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
mbedtls_ecdh_context hkey;
|
||||
mbedtls_ecdh_init(&hkey);
|
||||
mbedtls_ecdh_setup(&hkey, MBEDTLS_ECP_DP_SECP256R1);
|
||||
int ret = mbedtls_ecdh_gen_public(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.d, &hkey.ctx.mbed_ecdh.Q, random_gen, NULL);
|
||||
int ret = mbedtls_ecdh_gen_public(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.d, &hkey.ctx.mbed_ecdh.Q, random_fill_iterator, NULL);
|
||||
mbedtls_mpi_lset(&hkey.ctx.mbed_ecdh.Qp.Z, 1);
|
||||
if (ret != 0) {
|
||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||
@@ -154,7 +155,7 @@ static int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
ret = mbedtls_ecdh_calc_secret(&hkey, &olen, buf, MBEDTLS_ECP_MAX_BYTES, random_gen, NULL);
|
||||
ret = mbedtls_ecdh_calc_secret(&hkey, &olen, buf, MBEDTLS_ECP_MAX_BYTES, random_fill_iterator, NULL);
|
||||
if (ret != 0) {
|
||||
mbedtls_ecdh_free(&hkey);
|
||||
mbedtls_platform_zeroize(buf, sizeof(buf));
|
||||
@@ -216,7 +217,7 @@ static int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
mbedtls_ecdsa_free(&ekey);
|
||||
CBOR_ERROR(CTAP2_ERR_PROCESSING);
|
||||
}
|
||||
ret = mbedtls_ecp_mul(&ekey.grp, &ekey.Q, &ekey.d, &ekey.grp.G, random_gen, NULL);
|
||||
ret = mbedtls_ecp_keypair_calc_public(&ekey, random_fill_iterator, NULL);
|
||||
if (ret != 0) {
|
||||
mbedtls_ecdsa_free(&ekey);
|
||||
CBOR_ERROR(CTAP2_ERR_PROCESSING);
|
||||
@@ -232,7 +233,7 @@ static int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
mbedtls_x509write_csr_set_key(&ctx, &key);
|
||||
mbedtls_x509write_csr_set_md_alg(&ctx, MBEDTLS_MD_SHA256);
|
||||
mbedtls_x509write_csr_set_extension(&ctx, "\x2B\x06\x01\x04\x01\x82\xE5\x1C\x01\x01\x04", 0xB, 0, aaguid, sizeof(aaguid));
|
||||
ret = mbedtls_x509write_csr_der(&ctx, buffer, sizeof(buffer), random_gen, NULL);
|
||||
ret = mbedtls_x509write_csr_der(&ctx, buffer, sizeof(buffer), random_fill_iterator, NULL);
|
||||
mbedtls_ecdsa_free(&ekey);
|
||||
if (ret <= 0) {
|
||||
mbedtls_x509write_csr_free(&ctx);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "fido.h"
|
||||
#include "apdu.h"
|
||||
#include "ctap.h"
|
||||
@@ -26,7 +26,7 @@
|
||||
int cmd_authenticate(void) {
|
||||
CTAP_AUTHENTICATE_REQ *req = (CTAP_AUTHENTICATE_REQ *) apdu.data;
|
||||
CTAP_AUTHENTICATE_RESP *resp = (CTAP_AUTHENTICATE_RESP *) res_APDU;
|
||||
//if (scan_files_fido(true) != PICOKEY_OK)
|
||||
//if (scan_files_fido(true) != PICOKEYS_OK)
|
||||
// return SW_EXEC_ERROR();
|
||||
if (apdu.nc < CTAP_CHAL_SIZE + CTAP_APPID_SIZE + 1 + 1) {
|
||||
return SW_WRONG_DATA();
|
||||
@@ -34,7 +34,7 @@ int cmd_authenticate(void) {
|
||||
if (req->keyHandleLen < KEY_HANDLE_LEN) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
if (P1(apdu) == CTAP_AUTH_ENFORCE && wait_button_pressed() == true) {
|
||||
if (P1(apdu) == CTAP_AUTH_ENFORCE && wait_button_pressed() > 0) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ int cmd_authenticate(void) {
|
||||
}
|
||||
}
|
||||
free(tmp_kh);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
mbedtls_ecp_keypair_free(&key);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
@@ -66,7 +66,7 @@ int cmd_authenticate(void) {
|
||||
resp->flags = 0;
|
||||
resp->flags |= P1(apdu) == CTAP_AUTH_ENFORCE ? CTAP_AUTH_FLAG_TUP : 0x0;
|
||||
uint32_t ctr = get_sign_counter();
|
||||
put_uint32_t_be(ctr, resp->ctr);
|
||||
put_uint32_be(ctr, resp->ctr);
|
||||
uint8_t hash[32], sig_base[CTAP_APPID_SIZE + 1 + 4 + CTAP_CHAL_SIZE];
|
||||
memcpy(sig_base, req->appId, CTAP_APPID_SIZE);
|
||||
memcpy(sig_base + CTAP_APPID_SIZE, &resp->flags, sizeof(uint8_t));
|
||||
@@ -78,7 +78,7 @@ int cmd_authenticate(void) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
size_t olen = 0;
|
||||
ret = mbedtls_ecdsa_write_signature(&key, MBEDTLS_MD_SHA256, hash, 32, (uint8_t *) resp->sig, CTAP_MAX_EC_SIG_SIZE, &olen, random_gen, NULL);
|
||||
ret = mbedtls_ecdsa_write_signature(&key, MBEDTLS_MD_SHA256, hash, 32, (uint8_t *) resp->sig, CTAP_MAX_EC_SIG_SIZE, &olen, random_fill_iterator, NULL);
|
||||
mbedtls_ecp_keypair_free(&key);
|
||||
if (ret != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
@@ -87,6 +87,6 @@ int cmd_authenticate(void) {
|
||||
|
||||
ctr++;
|
||||
file_put_data(ef_counter, (uint8_t *) &ctr, sizeof(ctr));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "fido.h"
|
||||
#include "apdu.h"
|
||||
#include "ctap.h"
|
||||
@@ -37,9 +37,9 @@ static int u2f_select(app_t *a, uint8_t force) {
|
||||
if (cap_supported(CAP_U2F)) {
|
||||
a->process_apdu = u2f_process_apdu;
|
||||
a->unload = u2f_unload;
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
INITIALIZER ( u2f_ctor ) {
|
||||
@@ -47,7 +47,7 @@ INITIALIZER ( u2f_ctor ) {
|
||||
}
|
||||
|
||||
int u2f_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
|
||||
const uint8_t *bogus_firefox = (const uint8_t *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
@@ -58,12 +58,12 @@ int cmd_register(void) {
|
||||
CTAP_REGISTER_RESP *resp = (CTAP_REGISTER_RESP *) res_APDU;
|
||||
resp->registerId = CTAP_REGISTER_ID;
|
||||
resp->keyHandleLen = KEY_HANDLE_LEN;
|
||||
//if (scan_files_fido(true) != PICOKEY_OK)
|
||||
//if (scan_files_fido(true) != PICOKEYS_OK)
|
||||
// return SW_EXEC_ERROR();
|
||||
if (apdu.nc != CTAP_APPID_SIZE + CTAP_CHAL_SIZE) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
if (wait_button_pressed() == true) {
|
||||
if (wait_button_pressed() > 0) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
if (memcmp(req->appId, bogus_firefox,
|
||||
@@ -72,7 +72,7 @@ int cmd_register(void) {
|
||||
mbedtls_ecdsa_context key;
|
||||
mbedtls_ecdsa_init(&key);
|
||||
int ret = derive_key(req->appId, true, resp->keyHandleCertSig, MBEDTLS_ECP_DP_SECP256R1, &key);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
mbedtls_ecdsa_free(&key);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
@@ -97,16 +97,16 @@ int cmd_register(void) {
|
||||
mbedtls_ecdsa_init(&key);
|
||||
uint8_t key_dev[32] = {0};
|
||||
ret = load_keydev(key_dev);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1, &key, key_dev, 32);
|
||||
mbedtls_platform_zeroize(key_dev, sizeof(key_dev));
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
mbedtls_ecdsa_free(&key);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
ret = mbedtls_ecdsa_write_signature(&key,MBEDTLS_MD_SHA256, hash, 32, (uint8_t *) resp->keyHandleCertSig + KEY_HANDLE_LEN + ef_certdev_size, CTAP_MAX_EC_SIG_SIZE, &olen, random_gen, NULL);
|
||||
ret = mbedtls_ecdsa_write_signature(&key,MBEDTLS_MD_SHA256, hash, 32, (uint8_t *) resp->keyHandleCertSig + KEY_HANDLE_LEN + ef_certdev_size, CTAP_MAX_EC_SIG_SIZE, &olen, random_fill_iterator, NULL);
|
||||
mbedtls_ecdsa_free(&key);
|
||||
if (ret != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "apdu.h"
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "fido.h"
|
||||
|
||||
int cmd_version(void) {
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "serial.h"
|
||||
#include "pico_time.h"
|
||||
#include "mbedtls/chachapoly.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "credential.h"
|
||||
@@ -158,7 +160,7 @@ int credential_create(CborCharString *rpId,
|
||||
uint8_t key[32] = {0};
|
||||
credential_derive_chacha_key(key, (const uint8_t *)CRED_PROTO);
|
||||
uint8_t iv[CRED_IV_LEN] = {0};
|
||||
random_gen(NULL, iv, sizeof(iv));
|
||||
random_fill_buffer(iv, sizeof(iv));
|
||||
mbedtls_chachapoly_context chatx;
|
||||
mbedtls_chachapoly_init(&chatx);
|
||||
mbedtls_chachapoly_setkey(&chatx, key);
|
||||
@@ -310,7 +312,7 @@ int credential_store(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *
|
||||
return ret;
|
||||
}
|
||||
for (uint16_t i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) {
|
||||
file_t *ef = search_dynamic_file(EF_CRED + i);
|
||||
file_t *ef = file_search(EF_CRED + i);
|
||||
Credential rcred = { 0 };
|
||||
if (!file_has_data(ef)) {
|
||||
if (sloti == -1) {
|
||||
@@ -350,7 +352,7 @@ int credential_store(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *
|
||||
if (new_record == true) { //increase rps
|
||||
sloti = -1;
|
||||
for (uint16_t i = 0; i < MAX_RESIDENT_CREDENTIALS; i++) {
|
||||
ef = search_dynamic_file(EF_RP + i);
|
||||
ef = file_search(EF_RP + i);
|
||||
if (!file_has_data(ef)) {
|
||||
if (sloti == -1) {
|
||||
sloti = i;
|
||||
@@ -365,7 +367,7 @@ int credential_store(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *
|
||||
if (sloti == -1) {
|
||||
return -1;
|
||||
}
|
||||
ef = search_dynamic_file((uint16_t)(EF_RP + sloti));
|
||||
ef = file_search((uint16_t)(EF_RP + sloti));
|
||||
if (file_has_data(ef)) {
|
||||
data = (uint8_t *) calloc(1, file_get_size(ef));
|
||||
memcpy(data, file_get_data(ef), file_get_size(ef));
|
||||
@@ -384,7 +386,7 @@ int credential_store(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *
|
||||
}
|
||||
}
|
||||
credential_free(&cred);
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "fido.h"
|
||||
#include "version.h"
|
||||
|
||||
|
||||
113
src/fido/fido.c
113
src/fido/fido.c
@@ -15,8 +15,9 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "fido.h"
|
||||
#include "serial.h"
|
||||
#include "apdu.h"
|
||||
#include "ctap.h"
|
||||
#include "files.h"
|
||||
@@ -75,9 +76,9 @@ static int fido_select(app_t *a, uint8_t force) {
|
||||
if (cap_supported(CAP_FIDO2)) {
|
||||
a->process_apdu = fido_process_apdu;
|
||||
a->unload = fido_unload;
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
extern uint8_t (*get_version_major)(void);
|
||||
@@ -94,7 +95,7 @@ INITIALIZER ( fido_ctor ) {
|
||||
}
|
||||
|
||||
static int fido_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
|
||||
mbedtls_ecp_group_id fido_curve_to_mbedtls(int curve) {
|
||||
@@ -191,7 +192,7 @@ static int x509_create_cert(mbedtls_ecdsa_context *ecdsa, uint8_t *buffer, size_
|
||||
mbedtls_x509write_crt_set_issuer_name(&ctx, "C=ES,O=Pico HSM,CN=Pico FIDO");
|
||||
mbedtls_x509write_crt_set_subject_name(&ctx, "C=ES,O=Pico HSM,CN=Pico FIDO");
|
||||
uint8_t serial[16];
|
||||
random_gen(NULL, serial, sizeof(serial));
|
||||
random_fill_buffer(serial, sizeof(serial));
|
||||
mbedtls_x509write_crt_set_serial_raw(&ctx, serial, sizeof(serial));
|
||||
mbedtls_pk_context key;
|
||||
mbedtls_pk_init(&key);
|
||||
@@ -206,7 +207,7 @@ static int x509_create_cert(mbedtls_ecdsa_context *ecdsa, uint8_t *buffer, size_
|
||||
mbedtls_x509write_crt_set_key_usage(&ctx,
|
||||
MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
|
||||
MBEDTLS_X509_KU_KEY_CERT_SIGN);
|
||||
int ret = mbedtls_x509write_crt_der(&ctx, buffer, buffer_size, random_gen, NULL);
|
||||
int ret = mbedtls_x509write_crt_der(&ctx, buffer, buffer_size, random_fill_iterator, NULL);
|
||||
mbedtls_x509write_crt_free(&ctx);
|
||||
/* pk cannot be freed, as it is freed later */
|
||||
//mbedtls_pk_free(&key);
|
||||
@@ -215,7 +216,7 @@ static int x509_create_cert(mbedtls_ecdsa_context *ecdsa, uint8_t *buffer, size_
|
||||
|
||||
int load_keydev(uint8_t key[32]) {
|
||||
if (has_keydev_dec == false && !file_has_data(ef_keydev)) {
|
||||
return PICOKEY_ERR_MEMORY_FATAL;
|
||||
return PICOKEYS_ERR_MEMORY_FATAL;
|
||||
}
|
||||
|
||||
if (has_keydev_dec == true) {
|
||||
@@ -225,8 +226,8 @@ int load_keydev(uint8_t key[32]) {
|
||||
uint16_t fid_size = file_get_size(ef_keydev);
|
||||
if (fid_size == 32) {
|
||||
memcpy(key, file_get_data(ef_keydev), 32);
|
||||
if (otp_key_1 && aes_decrypt(otp_key_1, NULL, 32 * 8, PICO_KEYS_AES_MODE_CBC, key, 32) != PICOKEY_OK) {
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
if (otp_key_1 && aes_decrypt(otp_key_1, NULL, 32 * 8, PICOKEYS_AES_MODE_CBC, key, 32) != PICOKEYS_OK) {
|
||||
return PICOKEYS_EXEC_ERROR;
|
||||
}
|
||||
}
|
||||
else if (fid_size == 33 || fid_size == 61) {
|
||||
@@ -236,18 +237,18 @@ int load_keydev(uint8_t key[32]) {
|
||||
uint8_t tmp_key[61], version = format == 0x03 ? 2 : 1;
|
||||
memcpy(tmp_key, file_get_data(ef_keydev), sizeof(tmp_key));
|
||||
int ret = decrypt_with_aad(session_pin, tmp_key + 1, 60, version, key);
|
||||
if (ret != PICOKEY_OK) {
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
if (ret != PICOKEYS_OK) {
|
||||
return PICOKEYS_EXEC_ERROR;
|
||||
}
|
||||
if (format == 0x02) {
|
||||
tmp_key[0] = 0x03;
|
||||
ret = encrypt_with_aad(session_pin, key, 32, 2, tmp_key + 1);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
mbedtls_platform_zeroize(tmp_key, sizeof(tmp_key));
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
return PICOKEYS_EXEC_ERROR;
|
||||
}
|
||||
file_put_data(ef_keydev, tmp_key, sizeof(tmp_key));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
mbedtls_platform_zeroize(tmp_key, sizeof(tmp_key));
|
||||
}
|
||||
@@ -256,17 +257,17 @@ int load_keydev(uint8_t key[32]) {
|
||||
}
|
||||
uint8_t kbase[32];
|
||||
derive_kbase(kbase);
|
||||
int ret = aes_decrypt(kbase, pico_serial_hash, 32 * 8, PICO_KEYS_AES_MODE_CBC, key, 32);
|
||||
if (ret != PICOKEY_OK) {
|
||||
int ret = aes_decrypt(kbase, pico_serial_hash, 32 * 8, PICOKEYS_AES_MODE_CBC, key, 32);
|
||||
if (ret != PICOKEYS_OK) {
|
||||
mbedtls_platform_zeroize(kbase, sizeof(kbase));
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
return PICOKEYS_EXEC_ERROR;
|
||||
}
|
||||
mbedtls_platform_zeroize(kbase, sizeof(kbase));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
|
||||
int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecp_keypair *key) {
|
||||
@@ -307,7 +308,7 @@ int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int cur
|
||||
uint8_t outk[67] = { 0 }; //SECP521R1 key is 66 bytes length
|
||||
int r = 0;
|
||||
memset(outk, 0, sizeof(outk));
|
||||
if ((r = load_keydev(outk)) != PICOKEY_OK) {
|
||||
if ((r = load_keydev(outk)) != PICOKEYS_OK) {
|
||||
printf("Error loading keydev: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
@@ -315,7 +316,7 @@ int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int cur
|
||||
for (size_t i = 0; i < KEY_PATH_ENTRIES; i++) {
|
||||
if (new_key == true) {
|
||||
uint32_t val = 0;
|
||||
random_gen(NULL, (uint8_t *) &val, sizeof(val));
|
||||
random_fill_buffer((uint8_t *) &val, sizeof(val));
|
||||
val |= 0x80000000;
|
||||
memcpy(&key_handle[i * sizeof(uint32_t)], &val, sizeof(uint32_t));
|
||||
}
|
||||
@@ -348,12 +349,7 @@ int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int cur
|
||||
if (r != 0) {
|
||||
return r;
|
||||
}
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
if (curve == MBEDTLS_ECP_DP_ED25519) {
|
||||
return mbedtls_ecp_point_edwards(&key->grp, &key->Q, &key->d, random_gen, NULL);
|
||||
}
|
||||
#endif
|
||||
return mbedtls_ecp_mul(&key->grp, &key->Q, &key->d, &key->grp.G, random_gen, NULL);
|
||||
return mbedtls_ecp_keypair_calc_public(key, random_fill_iterator, NULL);
|
||||
}
|
||||
mbedtls_platform_zeroize(outk, sizeof(outk));
|
||||
return r;
|
||||
@@ -365,27 +361,26 @@ int encrypt_keydev_f1(const uint8_t keydev[32]) {
|
||||
memcpy(kdata + 1, keydev, 32);
|
||||
uint8_t kbase[32];
|
||||
derive_kbase(kbase);
|
||||
int ret = aes_encrypt(kbase, pico_serial_hash, 32 * 8, PICO_KEYS_AES_MODE_CBC, kdata + 1, 32);
|
||||
int ret = aes_encrypt(kbase, pico_serial_hash, 32 * 8, PICOKEYS_AES_MODE_CBC, kdata + 1, 32);
|
||||
mbedtls_platform_zeroize(kbase, sizeof(kbase));
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
return ret;
|
||||
}
|
||||
ret = file_put_data(ef_keydev, kdata, 33);
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int scan_files_fido(void) {
|
||||
ef_keydev = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF);
|
||||
ef_keydev_enc = search_by_fid(EF_KEY_DEV_ENC, NULL, SPECIFY_EF);
|
||||
ef_keydev = file_search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF);
|
||||
ef_keydev_enc = file_search_by_fid(EF_KEY_DEV_ENC, NULL, SPECIFY_EF);
|
||||
if (ef_keydev) {
|
||||
if (!file_has_data(ef_keydev) && !file_has_data(ef_keydev_enc)) {
|
||||
printf("KEY DEVICE is empty. Generating SECP256R1 curve...");
|
||||
mbedtls_ecdsa_context ecdsa;
|
||||
mbedtls_ecdsa_init(&ecdsa);
|
||||
uint8_t index = 0;
|
||||
int ret = mbedtls_ecdsa_genkey(&ecdsa, MBEDTLS_ECP_DP_SECP256R1, random_gen, &index);
|
||||
int ret = mbedtls_ecdsa_genkey(&ecdsa, MBEDTLS_ECP_DP_SECP256R1, random_fill_iterator, NULL);
|
||||
if (ret != 0) {
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
return ret;
|
||||
@@ -396,12 +391,12 @@ int scan_files_fido(void) {
|
||||
if (ret != 0 || key_size != 32) {
|
||||
mbedtls_platform_zeroize(keydev, sizeof(keydev));
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
return ret != 0 ? ret : PICOKEY_EXEC_ERROR;
|
||||
return ret != 0 ? ret : PICOKEYS_EXEC_ERROR;
|
||||
}
|
||||
encrypt_keydev_f1(keydev);
|
||||
mbedtls_platform_zeroize(keydev, sizeof(keydev));
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
return ret;
|
||||
}
|
||||
printf(" done!\n");
|
||||
@@ -410,7 +405,7 @@ int scan_files_fido(void) {
|
||||
else {
|
||||
printf("FATAL ERROR: KEY DEV not found in memory!\r\n");
|
||||
}
|
||||
ef_certdev = search_by_fid(EF_EE_DEV, NULL, SPECIFY_EF);
|
||||
ef_certdev = file_search_by_fid(EF_EE_DEV, NULL, SPECIFY_EF);
|
||||
if (ef_certdev) {
|
||||
if (!file_has_data(ef_certdev)) {
|
||||
uint8_t cert[2048], outk[32];
|
||||
@@ -426,7 +421,7 @@ int scan_files_fido(void) {
|
||||
mbedtls_ecdsa_free(&key);
|
||||
return ret;
|
||||
}
|
||||
ret = mbedtls_ecp_mul(&key.grp, &key.Q, &key.d, &key.grp.G, random_gen, NULL);
|
||||
ret = mbedtls_ecp_keypair_calc_public(&key, random_fill_iterator, NULL);
|
||||
if (ret != 0) {
|
||||
mbedtls_ecdsa_free(&key);
|
||||
return ret;
|
||||
@@ -442,7 +437,7 @@ int scan_files_fido(void) {
|
||||
else {
|
||||
printf("FATAL ERROR: CERT DEV not found in memory!\r\n");
|
||||
}
|
||||
ef_counter = search_by_fid(EF_COUNTER, NULL, SPECIFY_EF);
|
||||
ef_counter = file_search_by_fid(EF_COUNTER, NULL, SPECIFY_EF);
|
||||
if (ef_counter) {
|
||||
if (!file_has_data(ef_counter)) {
|
||||
uint32_t v = 0;
|
||||
@@ -452,13 +447,13 @@ int scan_files_fido(void) {
|
||||
else {
|
||||
printf("FATAL ERROR: Global counter not found in memory!\r\n");
|
||||
}
|
||||
ef_pin = search_by_fid(EF_PIN, NULL, SPECIFY_EF);
|
||||
ef_pin_admin = search_by_fid(EF_PIN_ADMIN, NULL, SPECIFY_EF);
|
||||
ef_authtoken = search_by_fid(EF_AUTHTOKEN, NULL, SPECIFY_EF);
|
||||
ef_pin = file_search_by_fid(EF_PIN, NULL, SPECIFY_EF);
|
||||
ef_pin_admin = file_search_by_fid(EF_PIN_ADMIN, NULL, SPECIFY_EF);
|
||||
ef_authtoken = file_search_by_fid(EF_AUTHTOKEN, NULL, SPECIFY_EF);
|
||||
if (ef_authtoken) {
|
||||
if (!file_has_data(ef_authtoken)) {
|
||||
uint8_t t[32];
|
||||
random_gen(NULL, t, sizeof(t));
|
||||
random_fill_buffer(t, sizeof(t));
|
||||
file_put_data(ef_authtoken, t, sizeof(t));
|
||||
}
|
||||
paut.data = file_get_data(ef_authtoken);
|
||||
@@ -467,11 +462,11 @@ int scan_files_fido(void) {
|
||||
else {
|
||||
printf("FATAL ERROR: Auth Token not found in memory!\r\n");
|
||||
}
|
||||
file_t *ef_pauthtoken = search_by_fid(EF_PAUTHTOKEN, NULL, SPECIFY_EF);
|
||||
file_t *ef_pauthtoken = file_search_by_fid(EF_PAUTHTOKEN, NULL, SPECIFY_EF);
|
||||
if (ef_pauthtoken) {
|
||||
if (!file_has_data(ef_pauthtoken)) {
|
||||
uint8_t t[32];
|
||||
random_gen(NULL, t, sizeof(t));
|
||||
random_fill_buffer(t, sizeof(t));
|
||||
file_put_data(ef_pauthtoken, t, sizeof(t));
|
||||
}
|
||||
ppaut.data = file_get_data(ef_pauthtoken);
|
||||
@@ -480,17 +475,17 @@ int scan_files_fido(void) {
|
||||
else {
|
||||
printf("FATAL ERROR: Persistent Auth Token not found in memory!\r\n");
|
||||
}
|
||||
ef_largeblob = search_by_fid(EF_LARGEBLOB, NULL, SPECIFY_EF);
|
||||
ef_largeblob = file_search_by_fid(EF_LARGEBLOB, NULL, SPECIFY_EF);
|
||||
if (!file_has_data(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);
|
||||
}
|
||||
|
||||
low_flash_available();
|
||||
return PICOKEY_OK;
|
||||
flash_commit();
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
|
||||
void scan_all(void) {
|
||||
scan_flash();
|
||||
file_scan_flash();
|
||||
scan_files_fido();
|
||||
}
|
||||
|
||||
@@ -503,22 +498,28 @@ void init_fido(void) {
|
||||
needs_power_cycle = false;
|
||||
}
|
||||
|
||||
bool wait_button_pressed(void) {
|
||||
int wait_button_pressed(void) {
|
||||
uint32_t val = EV_PRESS_BUTTON;
|
||||
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
|
||||
queue_try_add(&card_to_usb_q, &val);
|
||||
do {
|
||||
queue_remove_blocking(&usb_to_card_q, &val);
|
||||
} while (val != EV_BUTTON_PRESSED && val != EV_BUTTON_TIMEOUT);
|
||||
} while (val != EV_BUTTON_PRESSED && val != EV_BUTTON_TIMEOUT && val != EV_BUTTON_CANCELLED);
|
||||
#endif
|
||||
return val == EV_BUTTON_TIMEOUT;
|
||||
if (val == EV_BUTTON_TIMEOUT) {
|
||||
return 1;
|
||||
}
|
||||
else if (val == EV_BUTTON_CANCELLED) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t user_present_time_limit = 0;
|
||||
|
||||
bool check_user_presence(void) {
|
||||
if (user_present_time_limit == 0 || user_present_time_limit + TRANSPORT_TIME_LIMIT < board_millis()) {
|
||||
if (wait_button_pressed() == true) { //timeout
|
||||
if (wait_button_pressed() > 0) { //timeout
|
||||
return false;
|
||||
}
|
||||
//user_present_time_limit = board_millis();
|
||||
@@ -528,11 +529,11 @@ bool check_user_presence(void) {
|
||||
|
||||
uint32_t get_sign_counter(void) {
|
||||
uint8_t *caddr = file_get_data(ef_counter);
|
||||
return get_uint32_t_le(caddr);
|
||||
return get_uint32_le(caddr);
|
||||
}
|
||||
|
||||
uint8_t get_opts(void) {
|
||||
file_t *ef = search_by_fid(EF_OPTS, NULL, SPECIFY_EF);
|
||||
file_t *ef = file_search_by_fid(EF_OPTS, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef)) {
|
||||
return *file_get_data(ef);
|
||||
}
|
||||
@@ -540,9 +541,9 @@ uint8_t get_opts(void) {
|
||||
}
|
||||
|
||||
void set_opts(uint8_t opts) {
|
||||
file_t *ef = search_by_fid(EF_OPTS, NULL, SPECIFY_EF);
|
||||
file_t *ef = file_search_by_fid(EF_OPTS, NULL, SPECIFY_EF);
|
||||
file_put_data(ef, &opts, sizeof(uint8_t));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
|
||||
#define CTAP_CBOR 0x10
|
||||
|
||||
@@ -41,7 +41,7 @@ extern int derive_key(const uint8_t *app_id,
|
||||
int,
|
||||
mbedtls_ecp_keypair *key);
|
||||
extern int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecp_keypair *);
|
||||
extern bool wait_button_pressed(void);
|
||||
extern int wait_button_pressed(void);
|
||||
extern void init_fido(void);
|
||||
extern void init_otp(void);
|
||||
extern void scan_all(void);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "fido.h"
|
||||
#include "ctap2_cbor.h"
|
||||
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include <stdio.h>
|
||||
#include "picokeys.h"
|
||||
#include "serial.h"
|
||||
#include "fido.h"
|
||||
#include "apdu.h"
|
||||
#include "version.h"
|
||||
#include "files.h"
|
||||
#include "asn1.h"
|
||||
#include "tlv.h"
|
||||
#include "management.h"
|
||||
|
||||
bool is_gpg = true;
|
||||
@@ -45,7 +47,7 @@ static int man_select(app_t *a, uint8_t force) {
|
||||
#endif
|
||||
}
|
||||
is_gpg = false;
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
|
||||
INITIALIZER ( man_ctor ) {
|
||||
@@ -53,22 +55,22 @@ INITIALIZER ( man_ctor ) {
|
||||
}
|
||||
|
||||
static int man_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
|
||||
bool cap_supported(uint16_t cap) {
|
||||
file_t *ef = search_dynamic_file(EF_DEV_CONF);
|
||||
file_t *ef = file_search(EF_DEV_CONF);
|
||||
if (file_has_data(ef)) {
|
||||
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)) {
|
||||
tlv_ctx_t ctxi;
|
||||
tlv_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
|
||||
while (tlv_walk(&ctxi, &p, &tag, &tag_len, &tag_data)) {
|
||||
if (tag == TAG_USB_ENABLED) {
|
||||
uint16_t ecaps = tag_data[0];
|
||||
if (tag_len == 2) {
|
||||
ecaps = get_uint16_t_be(tag_data);
|
||||
ecaps = get_uint16_be(tag_data);
|
||||
}
|
||||
return ecaps & cap;
|
||||
}
|
||||
@@ -87,7 +89,7 @@ static uint8_t _piv_aid[] = {
|
||||
};
|
||||
|
||||
int man_get_config(void) {
|
||||
file_t *ef = search_dynamic_file(EF_DEV_CONF);
|
||||
file_t *ef = file_search(EF_DEV_CONF);
|
||||
res_APDU_size = 0;
|
||||
res_APDU[res_APDU_size++] = 0; // Overall length. Filled later
|
||||
res_APDU[res_APDU_size++] = TAG_USB_SUPPORTED;
|
||||
@@ -164,7 +166,7 @@ static int cmd_write_config(void) {
|
||||
}
|
||||
file_t *ef = file_new(EF_DEV_CONF);
|
||||
file_put_data(ef, apdu.data + 1, (uint16_t)(apdu.nc - 1));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
#ifndef ENABLE_EMULATION
|
||||
if (cap_supported(CAP_OTP)) {
|
||||
phy_data.enabled_usb_itf |= PHY_USB_ITF_KB;
|
||||
|
||||
245
src/fido/oath.c
245
src/fido/oath.c
@@ -15,13 +15,14 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "picokeys.h"
|
||||
#include "serial.h"
|
||||
#include "fido.h"
|
||||
#include "apdu.h"
|
||||
#include "files.h"
|
||||
#include "random.h"
|
||||
#include "version.h"
|
||||
#include "asn1.h"
|
||||
#include "tlv.h"
|
||||
#include "crypto_utils.h"
|
||||
#include "management.h"
|
||||
|
||||
@@ -87,8 +88,8 @@ static int oath_select(app_t *a, uint8_t force) {
|
||||
res_APDU[res_APDU_size++] = TAG_NAME;
|
||||
res_APDU[res_APDU_size++] = 8;
|
||||
memcpy(res_APDU + res_APDU_size, pico_serial_str, 8); res_APDU_size += 8;
|
||||
if (file_has_data(search_dynamic_file(EF_OATH_CODE)) == true) {
|
||||
random_gen(NULL, challenge, sizeof(challenge));
|
||||
if (file_has_data(file_search(EF_OATH_CODE)) == true) {
|
||||
random_fill_buffer(challenge, sizeof(challenge));
|
||||
res_APDU[res_APDU_size++] = TAG_CHALLENGE;
|
||||
res_APDU[res_APDU_size++] = sizeof(challenge);
|
||||
memcpy(res_APDU + res_APDU_size, challenge, sizeof(challenge));
|
||||
@@ -102,7 +103,7 @@ static int oath_select(app_t *a, uint8_t force) {
|
||||
res_APDU[res_APDU_size++] = 8;
|
||||
memcpy(res_APDU + res_APDU_size, pico_serial_str, 8);
|
||||
res_APDU_size += 8;
|
||||
file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
file_t *ef_otp_pin = file_search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef_otp_pin)) {
|
||||
const uint8_t *pin_data = file_get_data(ef_otp_pin);
|
||||
res_APDU[res_APDU_size++] = TAG_PIN_COUNTER;
|
||||
@@ -111,9 +112,9 @@ static int oath_select(app_t *a, uint8_t force) {
|
||||
}
|
||||
}
|
||||
apdu.ne = res_APDU_size;
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
INITIALIZER ( oath_ctor ) {
|
||||
@@ -121,15 +122,15 @@ INITIALIZER ( oath_ctor ) {
|
||||
}
|
||||
|
||||
static int oath_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
|
||||
static file_t *find_oath_cred(const uint8_t *name, size_t name_len) {
|
||||
for (int i = 0; i < MAX_OATH_CRED; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_OATH_CRED + i));
|
||||
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) {
|
||||
file_t *ef = file_search((uint16_t)(EF_OATH_CRED + i));
|
||||
tlv_ctx_t ctxi, ef_tag = { 0 };
|
||||
tlv_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
|
||||
if (file_has_data(ef) && tlv_find_tag(&ctxi, TAG_NAME, &ef_tag) == true && ef_tag.len == name_len && memcmp(ef_tag.data, name, name_len) == 0) {
|
||||
return ef;
|
||||
}
|
||||
}
|
||||
@@ -140,16 +141,16 @@ static int cmd_put(void) {
|
||||
if (validated == false) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
asn1_ctx_t ctxi, key = { 0 }, name = { 0 }, imf = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_KEY, &key) == false) {
|
||||
tlv_ctx_t ctxi, key = { 0 }, name = { 0 }, imf = { 0 };
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_KEY, &key) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
if (tlv_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
if ((key.data[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) {
|
||||
if (asn1_find_tag(&ctxi, TAG_IMF, &imf) == false) {
|
||||
if (tlv_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;
|
||||
}
|
||||
@@ -166,15 +167,15 @@ static int cmd_put(void) {
|
||||
file_t *ef = find_oath_cred(name.data, name.len);
|
||||
if (file_has_data(ef)) {
|
||||
file_put_data(ef, apdu.data, (uint16_t)apdu.nc);
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < MAX_OATH_CRED; i++) {
|
||||
file_t *tef = search_dynamic_file((uint16_t)(EF_OATH_CRED + i));
|
||||
file_t *tef = file_search((uint16_t)(EF_OATH_CRED + i));
|
||||
if (!file_has_data(tef)) {
|
||||
tef = file_new((uint16_t)(EF_OATH_CRED + i));
|
||||
file_put_data(tef, apdu.data, (uint16_t)apdu.nc);
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
return SW_OK();
|
||||
}
|
||||
}
|
||||
@@ -188,12 +189,12 @@ static int cmd_delete(void) {
|
||||
if (validated == false) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
asn1_ctx_t ctxi, ctxo = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_NAME, &ctxo) == true) {
|
||||
tlv_ctx_t ctxi, ctxo = { 0 };
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_NAME, &ctxo) == true) {
|
||||
file_t *ef = find_oath_cred(ctxo.data, ctxo.len);
|
||||
if (ef) {
|
||||
delete_file(ef);
|
||||
file_delete(ef);
|
||||
return SW_OK();
|
||||
}
|
||||
return SW_DATA_INVALID();
|
||||
@@ -219,24 +220,24 @@ static int cmd_set_code(void) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (apdu.nc == 0) {
|
||||
delete_file(search_dynamic_file(EF_OATH_CODE));
|
||||
file_delete(file_search(EF_OATH_CODE));
|
||||
validated = true;
|
||||
return SW_OK();
|
||||
}
|
||||
asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, resp = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_KEY, &key) == false) {
|
||||
tlv_ctx_t ctxi, key = { 0 }, chal = { 0 }, resp = { 0 };
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_KEY, &key) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
if (key.len == 0) {
|
||||
delete_file(search_dynamic_file(EF_OATH_CODE));
|
||||
file_delete(file_search(EF_OATH_CODE));
|
||||
validated = true;
|
||||
return SW_OK();
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) {
|
||||
if (tlv_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_RESPONSE, &resp) == false) {
|
||||
if (tlv_find_tag(&ctxi, TAG_RESPONSE, &resp) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
|
||||
@@ -252,10 +253,10 @@ static int cmd_set_code(void) {
|
||||
if (memcmp(hmac, resp.data, resp.len) != 0) {
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
random_gen(NULL, challenge, sizeof(challenge));
|
||||
random_fill_buffer(challenge, sizeof(challenge));
|
||||
file_t *ef = file_new(EF_OATH_CODE);
|
||||
file_put_data(ef, key.data, key.len);
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
validated = false;
|
||||
return SW_OK();
|
||||
}
|
||||
@@ -265,14 +266,14 @@ static int cmd_reset(void) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
for (int i = 0; i < MAX_OATH_CRED; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_OATH_CRED + i));
|
||||
file_t *ef = file_search((uint16_t)(EF_OATH_CRED + i));
|
||||
if (file_has_data(ef)) {
|
||||
delete_file(ef);
|
||||
file_delete(ef);
|
||||
}
|
||||
}
|
||||
delete_file(search_dynamic_file(EF_OATH_CODE));
|
||||
flash_clear_file(search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF));
|
||||
low_flash_available();
|
||||
file_delete(file_search(EF_OATH_CODE));
|
||||
flash_clear_file(file_search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF));
|
||||
flash_commit();
|
||||
validated = true;
|
||||
return SW_OK();
|
||||
}
|
||||
@@ -283,21 +284,21 @@ static int cmd_list(void) {
|
||||
}
|
||||
bool ext = (apdu.nc == 1 && apdu.data[0] == 0x01);
|
||||
for (int i = 0; i < MAX_OATH_CRED; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_OATH_CRED + i));
|
||||
file_t *ef = file_search((uint16_t)(EF_OATH_CRED + i));
|
||||
if (file_has_data(ef)) {
|
||||
asn1_ctx_t ctxi, key = { 0 }, name = { 0 }, pws = { 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) {
|
||||
tlv_ctx_t ctxi, key = { 0 }, name = { 0 }, pws = { 0 };
|
||||
tlv_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_NAME, &name) == true && tlv_find_tag(&ctxi, TAG_KEY, &key) == true) {
|
||||
res_APDU[res_APDU_size++] = TAG_NAME_LIST;
|
||||
res_APDU[res_APDU_size++] = (uint8_t)(name.len + 1 + (ext ? 1 : 0));
|
||||
res_APDU[res_APDU_size++] = key.data[0];
|
||||
memcpy(res_APDU + res_APDU_size, name.data, name.len); res_APDU_size += name.len;
|
||||
if (ext) {
|
||||
uint8_t props = 0x0;
|
||||
if (asn1_find_tag(&ctxi, TAG_PWS_LOGIN, &pws) == true || asn1_find_tag(&ctxi, TAG_PWS_PASSWORD, &pws) == true || asn1_find_tag(&ctxi, TAG_PWS_METADATA, &pws) == true) {
|
||||
if (tlv_find_tag(&ctxi, TAG_PWS_LOGIN, &pws) == true || tlv_find_tag(&ctxi, TAG_PWS_PASSWORD, &pws) == true || tlv_find_tag(&ctxi, TAG_PWS_METADATA, &pws) == true) {
|
||||
props |= 0x4;
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_PROPERTY, &pws) == true && (pws.data[0] & PROP_TOUCH)) {
|
||||
if (tlv_find_tag(&ctxi, TAG_PROPERTY, &pws) == true && (pws.data[0] & PROP_TOUCH)) {
|
||||
props |= 0x1;
|
||||
}
|
||||
res_APDU[res_APDU_size++] = props;
|
||||
@@ -310,15 +311,15 @@ static int cmd_list(void) {
|
||||
}
|
||||
|
||||
static int cmd_validate(void) {
|
||||
asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, resp = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) {
|
||||
tlv_ctx_t ctxi, key = { 0 }, chal = { 0 }, resp = { 0 };
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_RESPONSE, &resp) == false) {
|
||||
if (tlv_find_tag(&ctxi, TAG_RESPONSE, &resp) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
file_t *ef = search_dynamic_file(EF_OATH_CODE);
|
||||
file_t *ef = file_search(EF_OATH_CODE);
|
||||
if (file_has_data(ef) == false) {
|
||||
validated = true;
|
||||
return SW_DATA_INVALID();
|
||||
@@ -359,7 +360,7 @@ int calculate_oath(uint8_t truncate, const uint8_t *key, size_t key_len, const u
|
||||
int r = mbedtls_md_hmac(md_info, key + 2, key_len - 2, chal, chal_len, hmac);
|
||||
size_t hmac_size = mbedtls_md_get_size(md_info);
|
||||
if (r != 0) {
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
return PICOKEYS_EXEC_ERROR;
|
||||
}
|
||||
if (truncate == 0x01) {
|
||||
res_APDU[res_APDU_size++] = 4 + 1;
|
||||
@@ -376,7 +377,7 @@ int calculate_oath(uint8_t truncate, const uint8_t *key, size_t key_len, const u
|
||||
memcpy(res_APDU + res_APDU_size, hmac, hmac_size); res_APDU_size += (uint16_t)hmac_size;
|
||||
}
|
||||
apdu.ne = res_APDU_size;
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
|
||||
static int cmd_calculate(void) {
|
||||
@@ -386,26 +387,26 @@ static int cmd_calculate(void) {
|
||||
if (validated == false) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) {
|
||||
tlv_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 };
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
if (tlv_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
file_t *ef = find_oath_cred(name.data, name.len);
|
||||
if (file_has_data(ef) == false) {
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
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) {
|
||||
tlv_ctx_t ctxe;
|
||||
tlv_ctx_init(file_get_data(ef), file_get_size(ef), &ctxe);
|
||||
if (tlv_find_tag(&ctxe, TAG_KEY, &key) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
|
||||
if ((key.data[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) {
|
||||
if (asn1_find_tag(&ctxe, TAG_IMF, &chal) == false) {
|
||||
if (tlv_find_tag(&ctxe, TAG_IMF, &chal) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
}
|
||||
@@ -413,21 +414,21 @@ static int cmd_calculate(void) {
|
||||
res_APDU[res_APDU_size++] = TAG_RESPONSE + P2(apdu);
|
||||
|
||||
int ret = calculate_oath(P2(apdu), key.data, key.len, chal.data, chal.len);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
if ((key.data[0] & OATH_TYPE_MASK) == OATH_TYPE_HOTP) {
|
||||
uint64_t v = get_uint64_t_be(chal.data);
|
||||
uint64_t v = get_uint64_be(chal.data);
|
||||
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_ctx_t ctxt;
|
||||
asn1_ctx_init(tmp, (uint16_t)ef_size, &ctxt);
|
||||
asn1_find_tag(&ctxt, TAG_IMF, &chal);
|
||||
put_uint64_t_be(v, chal.data);
|
||||
tlv_ctx_t ctxt;
|
||||
tlv_ctx_init(tmp, (uint16_t)ef_size, &ctxt);
|
||||
tlv_find_tag(&ctxt, TAG_IMF, &chal);
|
||||
put_uint64_be(v, chal.data);
|
||||
file_put_data(ef, tmp, (uint16_t)ef_size);
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
free(tmp);
|
||||
}
|
||||
apdu.ne = res_APDU_size;
|
||||
@@ -435,26 +436,26 @@ static int cmd_calculate(void) {
|
||||
}
|
||||
|
||||
static int cmd_calculate_all(void) {
|
||||
asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 }, prop = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
tlv_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 }, prop = { 0 };
|
||||
tlv_ctx_init(apdu.data, (uint16_t)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(&ctxi, TAG_CHALLENGE, &chal) == false) {
|
||||
if (tlv_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
res_APDU_size = 0;
|
||||
for (int i = 0; i < MAX_OATH_CRED; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_OATH_CRED + i));
|
||||
file_t *ef = file_search((uint16_t)(EF_OATH_CRED + i));
|
||||
if (file_has_data(ef)) {
|
||||
const uint8_t *ef_data = file_get_data(ef);
|
||||
size_t ef_len = file_get_size(ef);
|
||||
asn1_ctx_t ctxe;
|
||||
asn1_ctx_init((uint8_t *)ef_data, (uint16_t)ef_len, &ctxe);
|
||||
if (asn1_find_tag(&ctxe, TAG_NAME, &name) == false || asn1_find_tag(&ctxe, TAG_KEY, &key) == false) {
|
||||
tlv_ctx_t ctxe;
|
||||
tlv_ctx_init((uint8_t *)ef_data, (uint16_t)ef_len, &ctxe);
|
||||
if (tlv_find_tag(&ctxe, TAG_NAME, &name) == false || tlv_find_tag(&ctxe, TAG_KEY, &key) == false) {
|
||||
continue;
|
||||
}
|
||||
res_APDU[res_APDU_size++] = TAG_NAME;
|
||||
@@ -465,7 +466,7 @@ static int cmd_calculate_all(void) {
|
||||
res_APDU[res_APDU_size++] = 1;
|
||||
res_APDU[res_APDU_size++] = key.data[1];
|
||||
}
|
||||
else if (asn1_find_tag(&ctxe, TAG_PROPERTY, &prop) == true && (prop.data[0] & PROP_TOUCH)) {
|
||||
else if (tlv_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.data[1];
|
||||
@@ -473,7 +474,7 @@ static int cmd_calculate_all(void) {
|
||||
else {
|
||||
res_APDU[res_APDU_size++] = TAG_RESPONSE + P2(apdu);
|
||||
int ret = calculate_oath(P2(apdu), key.data, key.len, chal.data, chal.len);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
res_APDU[res_APDU_size++] = 1;
|
||||
res_APDU[res_APDU_size++] = key.data[1];
|
||||
}
|
||||
@@ -490,56 +491,56 @@ static int cmd_send_remaining(void) {
|
||||
|
||||
static int cmd_set_otp_pin(void) {
|
||||
uint8_t hsh[33] = { 0 };
|
||||
file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
file_t *ef_otp_pin = file_search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef_otp_pin)) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
asn1_ctx_t ctxi, pw = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_PASSWORD, &pw) == false) {
|
||||
tlv_ctx_t ctxi, pw = { 0 };
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_PASSWORD, &pw) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
hsh[0] = MAX_OTP_COUNTER;
|
||||
double_hash_pin(pw.data, pw.len, hsh + 1);
|
||||
file_put_data(ef_otp_pin, hsh, sizeof(hsh));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_change_otp_pin(void) {
|
||||
uint8_t hsh[33] = { 0 };
|
||||
file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
file_t *ef_otp_pin = file_search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
if (!file_has_data(ef_otp_pin)) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
asn1_ctx_t ctxi, pw = { 0 }, new_pw = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_PASSWORD, &pw) == false) {
|
||||
tlv_ctx_t ctxi, pw = { 0 }, new_pw = { 0 };
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_PASSWORD, &pw) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
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(&ctxi, TAG_NEW_PASSWORD, &new_pw) == false) {
|
||||
if (tlv_find_tag(&ctxi, TAG_NEW_PASSWORD, &new_pw) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
hsh[0] = MAX_OTP_COUNTER;
|
||||
double_hash_pin(new_pw.data, new_pw.len, hsh + 1);
|
||||
file_put_data(ef_otp_pin, hsh, sizeof(hsh));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_verify_otp_pin(void) {
|
||||
uint8_t hsh[33] = { 0 }, data_hsh[33];
|
||||
file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
file_t *ef_otp_pin = file_search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
if (!file_has_data(ef_otp_pin)) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
asn1_ctx_t ctxi, pw = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_PASSWORD, &pw) == false) {
|
||||
tlv_ctx_t ctxi, pw = { 0 };
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_PASSWORD, &pw) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
double_hash_pin(pw.data, pw.len, hsh + 1);
|
||||
@@ -549,49 +550,49 @@ static int cmd_verify_otp_pin(void) {
|
||||
data_hsh[0] -= 1;
|
||||
}
|
||||
file_put_data(ef_otp_pin, data_hsh, sizeof(data_hsh));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
validated = false;
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
data_hsh[0] = MAX_OTP_COUNTER;
|
||||
file_put_data(ef_otp_pin, data_hsh, sizeof(data_hsh));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
validated = true;
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_verify_hotp(void) {
|
||||
asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 }, code = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
tlv_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 }, code = { 0 };
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
uint32_t code_int = 0;
|
||||
if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
if (tlv_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
file_t *ef = find_oath_cred(name.data, name.len);
|
||||
file_t *ef = file_search_by_fid(EF_OATH_CRED, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef) == false) {
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
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) {
|
||||
tlv_ctx_t ctxe;
|
||||
tlv_ctx_init(file_get_data(ef), file_get_size(ef), &ctxe);
|
||||
if (tlv_find_tag(&ctxe, TAG_KEY, &key) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
|
||||
if ((key.data[0] & OATH_TYPE_MASK) != OATH_TYPE_HOTP) {
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
if (asn1_find_tag(&ctxe, TAG_IMF, &chal) == false) {
|
||||
if (tlv_find_tag(&ctxe, TAG_IMF, &chal) == false) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_RESPONSE, &code) == true) {
|
||||
code_int = get_uint32_t_be(code.data);
|
||||
if (tlv_find_tag(&ctxi, TAG_RESPONSE, &code) == true) {
|
||||
code_int = get_uint32_be(code.data);
|
||||
}
|
||||
|
||||
int ret = calculate_oath(0x01, key.data, key.len, chal.data, chal.len);
|
||||
if (ret != PICOKEY_OK) {
|
||||
if (ret != PICOKEYS_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
uint32_t res_int = get_uint32_t_be(res_APDU + 2);
|
||||
uint32_t res_int = get_uint32_be(res_APDU + 2);
|
||||
if (res_APDU[1] == 6) {
|
||||
res_int %= (uint32_t) 1e6;
|
||||
}
|
||||
@@ -607,7 +608,7 @@ static int cmd_verify_hotp(void) {
|
||||
}
|
||||
|
||||
static int cmd_rename(void) {
|
||||
asn1_ctx_t ctxi, name = { 0 }, new_name = { 0 };
|
||||
tlv_ctx_t ctxi, name = { 0 }, new_name = { 0 };
|
||||
|
||||
if (validated == false) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
@@ -615,13 +616,13 @@ static int cmd_rename(void) {
|
||||
if (apdu.data[0] != TAG_NAME) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
|
||||
asn1_ctx_init(name.data + name.len, (uint16_t)(apdu.nc - (name.data + name.len - apdu.data)), &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_NAME, &new_name) == false) {
|
||||
tlv_ctx_init(name.data + name.len, (uint16_t)(apdu.nc - (name.data + name.len - apdu.data)), &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_NAME, &new_name) == false) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (name.len == new_name.len && memcmp(name.data, new_name.data, name.len) == 0) {
|
||||
@@ -633,8 +634,8 @@ static int cmd_rename(void) {
|
||||
}
|
||||
uint8_t *fdata = file_get_data(ef);
|
||||
uint16_t fsize = file_get_size(ef);
|
||||
asn1_ctx_init(fdata, fsize, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
tlv_ctx_init(fdata, fsize, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
uint8_t *new_data = (uint8_t *) calloc(fsize + new_name.len - name.len, sizeof(uint8_t));
|
||||
@@ -643,50 +644,50 @@ static int cmd_rename(void) {
|
||||
memcpy(new_data + (name.data - fdata), new_name.data, new_name.len);
|
||||
memcpy(new_data + (name.data - fdata) + new_name.len, name.data + name.len, fsize - (name.data + name.len - fdata));
|
||||
file_put_data(ef, new_data, fsize + new_name.len - name.len);
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
free(new_data);
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_get_credential(void) {
|
||||
asn1_ctx_t ctxi, name = { 0 };
|
||||
tlv_ctx_t ctxi, name = { 0 };
|
||||
if (apdu.nc < 3) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
if (apdu.data[0] != TAG_NAME) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
tlv_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_NAME, &name) == false) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
file_t *ef = find_oath_cred(name.data, name.len);
|
||||
if (file_has_data(ef) == false) {
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
asn1_ctx_t login = { 0 }, pw = { 0 }, meta = { 0 }, prop = { 0 };
|
||||
asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_NAME, &name) == true) {
|
||||
tlv_ctx_t login = { 0 }, pw = { 0 }, meta = { 0 }, prop = { 0 };
|
||||
tlv_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
|
||||
if (tlv_find_tag(&ctxi, TAG_NAME, &name) == true) {
|
||||
res_APDU[res_APDU_size++] = TAG_NAME;
|
||||
res_APDU[res_APDU_size++] = (uint8_t)(name.len);
|
||||
memcpy(res_APDU + res_APDU_size, name.data, name.len); res_APDU_size += name.len;
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_PWS_LOGIN, &login) == true) {
|
||||
if (tlv_find_tag(&ctxi, TAG_PWS_LOGIN, &login) == true) {
|
||||
res_APDU[res_APDU_size++] = TAG_PWS_LOGIN;
|
||||
res_APDU[res_APDU_size++] = (uint8_t)(login.len);
|
||||
memcpy(res_APDU + res_APDU_size, login.data, login.len); res_APDU_size += login.len;
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_PWS_PASSWORD, &pw) == true) {
|
||||
if (tlv_find_tag(&ctxi, TAG_PWS_PASSWORD, &pw) == true) {
|
||||
res_APDU[res_APDU_size++] = TAG_PWS_PASSWORD;
|
||||
res_APDU[res_APDU_size++] = (uint8_t)(pw.len);
|
||||
memcpy(res_APDU + res_APDU_size, pw.data, pw.len); res_APDU_size += pw.len;
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_PWS_METADATA, &meta) == true) {
|
||||
if (tlv_find_tag(&ctxi, TAG_PWS_METADATA, &meta) == true) {
|
||||
res_APDU[res_APDU_size++] = TAG_PWS_METADATA;
|
||||
res_APDU[res_APDU_size++] = (uint8_t)(meta.len);
|
||||
memcpy(res_APDU + res_APDU_size, meta.data, meta.len); res_APDU_size += meta.len;
|
||||
}
|
||||
if (asn1_find_tag(&ctxi, TAG_PROPERTY, &prop) == true) {
|
||||
if (tlv_find_tag(&ctxi, TAG_PROPERTY, &prop) == true) {
|
||||
res_APDU[res_APDU_size++] = TAG_PROPERTY;
|
||||
res_APDU[res_APDU_size++] = (uint8_t)(prop.len);
|
||||
memcpy(res_APDU + res_APDU_size, prop.data, prop.len); res_APDU_size += prop.len;
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include <stdio.h>
|
||||
#include "picokeys.h"
|
||||
#include "serial.h"
|
||||
#include "button.h"
|
||||
#include "fido.h"
|
||||
#include "apdu.h"
|
||||
#include "files.h"
|
||||
#include "random.h"
|
||||
#include "version.h"
|
||||
#include "asn1.h"
|
||||
#include "hid/ctap_hid.h"
|
||||
#include "usb.h"
|
||||
#if defined(PICO_PLATFORM)
|
||||
@@ -145,17 +147,16 @@ static int otp_select(app_t *a, uint8_t force) {
|
||||
if (cap_supported(CAP_OTP)) {
|
||||
a->process_apdu = otp_process_apdu;
|
||||
a->unload = otp_unload;
|
||||
if (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) ||
|
||||
file_has_data(search_dynamic_file(EF_OTP_SLOT2))) {
|
||||
if (file_has_data(file_search(EF_OTP_SLOT1)) || file_has_data(file_search(EF_OTP_SLOT2))) {
|
||||
config_seq = 1;
|
||||
}
|
||||
else {
|
||||
config_seq = 0;
|
||||
}
|
||||
otp_status(false);
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
uint8_t modhex_tab[] =
|
||||
@@ -172,22 +173,22 @@ void init_otp(void) {
|
||||
if (scanned == false) {
|
||||
scan_all();
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
file_t *ef = search_dynamic_file(EF_OTP_SLOT1 + i);
|
||||
file_t *ef = file_search(EF_OTP_SLOT1 + i);
|
||||
uint8_t *data = file_get_data(ef);
|
||||
otp_config_t *otp_config = (otp_config_t *) data;
|
||||
if (file_has_data(ef) && !(otp_config->tkt_flags & OATH_HOTP) &&
|
||||
!(otp_config->cfg_flags & SHORT_TICKET || otp_config->cfg_flags & STATIC_TICKET)) {
|
||||
uint16_t counter = get_uint16_t_be(data + otp_config_size);
|
||||
uint16_t counter = get_uint16_be(data + otp_config_size);
|
||||
if (++counter <= 0x7fff) {
|
||||
uint8_t new_data[otp_config_size + 8];
|
||||
memcpy(new_data, data, sizeof(new_data));
|
||||
put_uint16_t_be(counter, new_data + otp_config_size);
|
||||
put_uint16_be(counter, new_data + otp_config_size);
|
||||
file_put_data(ef, new_data, sizeof(new_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
scanned = true;
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
}
|
||||
static uint16_t calculate_crc(const uint8_t *data, size_t data_len) {
|
||||
@@ -212,7 +213,7 @@ static int otp_button_pressed(uint8_t slot) {
|
||||
return 3;
|
||||
}
|
||||
uint16_t slot_ef = EF_OTP_SLOT1 + slot - 1;
|
||||
file_t *ef = search_dynamic_file(slot_ef);
|
||||
file_t *ef = file_search(slot_ef);
|
||||
const uint8_t *data = file_get_data(ef);
|
||||
otp_config_t *otp_config = (otp_config_t *) data;
|
||||
if (file_has_data(ef) == false) {
|
||||
@@ -228,18 +229,18 @@ static int otp_button_pressed(uint8_t slot) {
|
||||
memcpy(tmp_key + 2, otp_config->aes_key, KEY_SIZE);
|
||||
uint64_t imf = 0;
|
||||
const uint8_t *p = data + otp_config_size;
|
||||
imf = get_uint64_t_be(p);
|
||||
imf = get_uint64_be(p);
|
||||
p += 8;
|
||||
if (imf == 0) {
|
||||
imf = get_uint16_t_be(otp_config->uid + 4);
|
||||
imf = get_uint16_be(otp_config->uid + 4);
|
||||
}
|
||||
uint8_t chal[8];
|
||||
put_uint64_t_be(imf, chal);
|
||||
put_uint64_be(imf, chal);
|
||||
res_APDU_size = 0;
|
||||
int ret = calculate_oath(1, tmp_key, sizeof(tmp_key), chal, sizeof(chal));
|
||||
if (ret == PICOKEY_OK) {
|
||||
if (ret == PICOKEYS_OK) {
|
||||
uint32_t base = otp_config->cfg_flags & OATH_HOTP8 ? 1e8 : 1e6;
|
||||
uint32_t number = get_uint16_t_be(res_APDU + 2);
|
||||
uint32_t number = get_uint16_be(res_APDU + 2);
|
||||
number %= base;
|
||||
char number_str[9];
|
||||
if (otp_config->cfg_flags & OATH_HOTP8) {
|
||||
@@ -252,12 +253,12 @@ static int otp_button_pressed(uint8_t slot) {
|
||||
}
|
||||
imf++;
|
||||
uint8_t new_chal[8];
|
||||
put_uint64_t_be(imf, new_chal);
|
||||
put_uint64_be(imf, new_chal);
|
||||
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));
|
||||
file_put_data(ef, new_otp_config, sizeof(new_otp_config));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
if (otp_config->tkt_flags & APPEND_CR) {
|
||||
append_keyboard_buffer((const uint8_t *) "\r", 1);
|
||||
@@ -277,7 +278,7 @@ static int otp_button_pressed(uint8_t slot) {
|
||||
else {
|
||||
uint8_t otpk[22], *po = otpk;
|
||||
bool update_counter = false;
|
||||
uint16_t counter = get_uint16_t_be(data + otp_config_size), crc = 0;
|
||||
uint16_t counter = get_uint16_be(data + otp_config_size), crc = 0;
|
||||
uint32_t ts = board_millis() / 1000;
|
||||
if (counter == 0) {
|
||||
update_counter = true;
|
||||
@@ -287,16 +288,16 @@ static int otp_button_pressed(uint8_t slot) {
|
||||
po += 6;
|
||||
memcpy(po, otp_config->uid, UID_SIZE);
|
||||
po += UID_SIZE;
|
||||
po += put_uint16_t_le(counter, po);
|
||||
po += put_uint16_le(counter, po);
|
||||
ts >>= 1;
|
||||
*po++ = ts & 0xff;
|
||||
*po++ = ts >> 8;
|
||||
*po++ = ts >> 16;
|
||||
*po++ = session_counter[slot - 1];
|
||||
random_gen(NULL, po, 2);
|
||||
random_fill_buffer(po, 2);
|
||||
po += 2;
|
||||
crc = calculate_crc(otpk + 6, 14);
|
||||
po += put_uint16_t_le(~crc, po);
|
||||
po += put_uint16_le(~crc, po);
|
||||
mbedtls_aes_context ctx;
|
||||
mbedtls_aes_init(&ctx);
|
||||
mbedtls_aes_setkey_enc(&ctx, otp_config->aes_key, 128);
|
||||
@@ -317,9 +318,9 @@ static int otp_button_pressed(uint8_t slot) {
|
||||
if (update_counter == true) {
|
||||
uint8_t new_data[otp_config_size + 8];
|
||||
memcpy(new_data, data, sizeof(new_data));
|
||||
put_uint16_t_be(counter, new_data + otp_config_size);
|
||||
put_uint16_be(counter, new_data + otp_config_size);
|
||||
file_put_data(ef, new_data, sizeof(new_data));
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,13 +335,13 @@ INITIALIZER( otp_ctor ) {
|
||||
}
|
||||
|
||||
static int otp_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
return PICOKEYS_OK;
|
||||
}
|
||||
|
||||
uint8_t status_byte = 0x0;
|
||||
static uint16_t otp_status_ext(void) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
file_t *ef = search_dynamic_file(EF_OTP_SLOT1 + i);
|
||||
file_t *ef = file_search(EF_OTP_SLOT1 + i);
|
||||
if (file_has_data(ef)) {
|
||||
res_APDU[res_APDU_size++] = 0xB0 + i;
|
||||
res_APDU[res_APDU_size++] = 0; // Filled later
|
||||
@@ -385,7 +386,7 @@ static uint16_t otp_status(bool is_otp) {
|
||||
res_APDU[res_APDU_size++] = 0;
|
||||
res_APDU[res_APDU_size++] = config_seq;
|
||||
uint8_t opts = 0;
|
||||
file_t *ef = search_dynamic_file(EF_OTP_SLOT1);
|
||||
file_t *ef = file_search(EF_OTP_SLOT1);
|
||||
if (file_has_data(ef)) {
|
||||
opts |= CONFIG1_VALID;
|
||||
otp_config_t *otp_config = (otp_config_t *) file_get_data(ef);
|
||||
@@ -393,7 +394,7 @@ static uint16_t otp_status(bool is_otp) {
|
||||
opts |= CONFIG1_TOUCH;
|
||||
}
|
||||
}
|
||||
ef = search_dynamic_file(EF_OTP_SLOT2);
|
||||
ef = file_search(EF_OTP_SLOT2);
|
||||
if (file_has_data(ef)) {
|
||||
opts |= CONFIG2_VALID;
|
||||
otp_config_t *otp_config = (otp_config_t *) file_get_data(ef);
|
||||
@@ -442,13 +443,13 @@ static int cmd_otp(void) {
|
||||
}
|
||||
memset(apdu.data + otp_config_size, 0, 8); // Add 8 bytes extra
|
||||
file_put_data(ef, apdu.data, otp_config_size + 8);
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
config_seq++;
|
||||
return otp_status(_is_otp);
|
||||
}
|
||||
}
|
||||
// Delete slot
|
||||
delete_file(ef);
|
||||
file_delete(ef);
|
||||
config_seq++;
|
||||
return otp_status(_is_otp);
|
||||
}
|
||||
@@ -461,7 +462,7 @@ static int cmd_otp(void) {
|
||||
if (odata->rfu[0] != 0 || odata->rfu[1] != 0 || check_crc(odata) == false) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
file_t *ef = search_dynamic_file(slot);
|
||||
file_t *ef = file_search(slot);
|
||||
if (file_has_data(ef)) {
|
||||
otp_config_t *otpc = (otp_config_t *) file_get_data(ef);
|
||||
if (memcmp(otpc->acc_code, apdu.data + otp_config_size, ACC_CODE_SIZE) != 0) {
|
||||
@@ -481,7 +482,7 @@ static int cmd_otp(void) {
|
||||
odata->cfg_flags = otpc->cfg_flags;
|
||||
}
|
||||
file_put_data(ef, apdu.data, otp_config_size);
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
config_seq++;
|
||||
}
|
||||
return otp_status(_is_otp);
|
||||
@@ -507,7 +508,7 @@ static int cmd_otp(void) {
|
||||
file_put_data(ef1, file_get_data(ef2), file_get_size(ef2));
|
||||
}
|
||||
else {
|
||||
delete_file(ef1);
|
||||
file_delete(ef1);
|
||||
// When a dynamic file is deleted, existing referenes are invalidated
|
||||
ef2 = file_new(slot2);
|
||||
}
|
||||
@@ -515,9 +516,9 @@ static int cmd_otp(void) {
|
||||
file_put_data(ef2, tmp, sizeof(tmp));
|
||||
}
|
||||
else {
|
||||
delete_file(ef2);
|
||||
file_delete(ef2);
|
||||
}
|
||||
low_flash_available();
|
||||
flash_commit();
|
||||
config_seq++;
|
||||
return otp_status(_is_otp);
|
||||
}
|
||||
@@ -537,7 +538,7 @@ static int cmd_otp(void) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
uint16_t slot = (p1 == 0x30 || p1 == 0x20 ? EF_OTP_SLOT1 : EF_OTP_SLOT2) + p2;
|
||||
file_t *ef = search_dynamic_file(slot);
|
||||
file_t *ef = file_search(slot);
|
||||
if (file_has_data(ef)) {
|
||||
otp_config_t *otp_config = (otp_config_t *) file_get_data(ef);
|
||||
if (!(otp_config->tkt_flags & CHAL_RESP)) {
|
||||
@@ -549,7 +550,7 @@ static int cmd_otp(void) {
|
||||
status_byte = 0x20;
|
||||
otp_status(_is_otp);
|
||||
#ifndef ENABLE_EMULATION
|
||||
if (wait_button() == true) {
|
||||
if (button_wait()) {
|
||||
status_byte = 0x00;
|
||||
otp_status(_is_otp);
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
@@ -629,7 +630,7 @@ uint8_t otp_header[4] = {0};
|
||||
|
||||
static int otp_send_frame(uint8_t *frame, size_t frame_len) {
|
||||
uint16_t crc = calculate_crc(frame, frame_len);
|
||||
frame_len += put_uint16_t_le(~crc, frame + frame_len);
|
||||
frame_len += put_uint16_le(~crc, frame + frame_len);
|
||||
*get_send_buffer_size(ITF_KEYBOARD) = frame_len;
|
||||
otp_exp_seq = (frame_len / 7);
|
||||
if (frame_len % 7) {
|
||||
@@ -660,7 +661,7 @@ static int otp_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type
|
||||
if (rseq == 9) {
|
||||
DEBUG_DATA(otp_frame_rx, sizeof(otp_frame_rx));
|
||||
DEBUG_PAYLOAD(otp_frame_rx, sizeof(otp_frame_rx));
|
||||
uint16_t residual_crc = calculate_crc(otp_frame_rx, 64), rcrc = get_uint16_t_le(otp_frame_rx + 65);
|
||||
uint16_t residual_crc = calculate_crc(otp_frame_rx, 64), rcrc = get_uint16_le(otp_frame_rx + 65);
|
||||
uint8_t slot_id = otp_frame_rx[64];
|
||||
if (residual_crc == rcrc) {
|
||||
uint8_t hdr[5];
|
||||
|
||||
@@ -22,6 +22,9 @@ RUN apt install -y libccid \
|
||||
cmake \
|
||||
libfuse-dev \
|
||||
python3-pyscard \
|
||||
libtss2-dev \
|
||||
tpm2-tools \
|
||||
swtpm \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
RUN pip3 install pytest pycvc cryptography inputimeout fido2==2.0.0 --break-system-packages
|
||||
WORKDIR /
|
||||
|
||||
@@ -49,6 +49,7 @@ cd build
|
||||
esptool.py --chip ESP32-S2 merge_bin -o ../release/pico_fido_esp32-s2.bin @flash_args
|
||||
cd ..
|
||||
else
|
||||
sudo apt install -y libtss2-dev tpm2-tools swtpm cmake
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DENABLE_EMULATION=1 ..
|
||||
|
||||
Reference in New Issue
Block a user