Fix OTP command issues in Linux.

Fixes #96.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2025-01-31 12:01:29 +01:00
parent cdd2f486aa
commit 353d782970

View File

@@ -111,7 +111,7 @@ typedef struct otp_config {
}) otp_config_t; }) otp_config_t;
#define otp_config_size sizeof(otp_config_t) #define otp_config_size sizeof(otp_config_t)
uint16_t otp_status(); uint16_t otp_status(bool is_otp);
int otp_process_apdu(); int otp_process_apdu();
int otp_unload(); int otp_unload();
@@ -140,10 +140,7 @@ int otp_select(app_t *a, uint8_t force) {
else { else {
config_seq = 0; config_seq = 0;
} }
otp_status(); otp_status(false);
memmove(res_APDU, res_APDU + 1, 6);
res_APDU_size = 6;
apdu.ne = res_APDU_size;
return PICOKEY_OK; return PICOKEY_OK;
} }
return PICOKEY_ERR_FILE_NOT_FOUND; return PICOKEY_ERR_FILE_NOT_FOUND;
@@ -339,22 +336,32 @@ int otp_unload() {
return PICOKEY_OK; return PICOKEY_OK;
} }
uint16_t otp_status() { uint16_t otp_status(bool is_otp) {
if (scanned == false) { if (scanned == false) {
scan_all(); scan_all();
scanned = true; scanned = true;
} }
res_APDU_size = 0; res_APDU_size = 0;
res_APDU[1] = PICO_FIDO_VERSION_MAJOR; if (is_otp) {
res_APDU[2] = PICO_FIDO_VERSION_MINOR; res_APDU_size++;
res_APDU[3] = 0; }
res_APDU[4] = config_seq; res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MAJOR;
res_APDU[5] = (CONFIG2_TOUCH | CONFIG1_TOUCH) | res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MINOR;
res_APDU[res_APDU_size++] = 0;
res_APDU[res_APDU_size++] = config_seq;
res_APDU[res_APDU_size++] = (CONFIG2_TOUCH | CONFIG1_TOUCH) |
(file_has_data(search_dynamic_file(EF_OTP_SLOT1)) ? CONFIG1_VALID : (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) ? CONFIG1_VALID :
0x00) | 0x00) |
(file_has_data(search_dynamic_file(EF_OTP_SLOT2)) ? CONFIG2_VALID : (file_has_data(search_dynamic_file(EF_OTP_SLOT2)) ? CONFIG2_VALID :
0x00); 0x00);
res_APDU[6] = 0; res_APDU[res_APDU_size++] = 0;
if (is_otp) {
res_APDU_size = 0;
}
else {
apdu.ne = res_APDU_size;
}
return SW_OK(); return SW_OK();
} }
@@ -363,6 +370,7 @@ bool check_crc(const otp_config_t *data) {
return crc == 0xF0B8; return crc == 0xF0B8;
} }
bool _is_otp = false;
int cmd_otp() { int cmd_otp() {
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
if (p2 != 0x00) { if (p2 != 0x00) {
@@ -386,13 +394,13 @@ int cmd_otp() {
file_put_data(ef, apdu.data, otp_config_size + 8); file_put_data(ef, apdu.data, otp_config_size + 8);
low_flash_available(); low_flash_available();
config_seq++; config_seq++;
return otp_status(); return otp_status(_is_otp);
} }
} }
// Delete slot // Delete slot
delete_file(ef); delete_file(ef);
config_seq++; config_seq++;
return otp_status(); return otp_status(_is_otp);
} }
else if (p1 == 0x04 || p1 == 0x05) { else if (p1 == 0x04 || p1 == 0x05) {
otp_config_t *odata = (otp_config_t *) apdu.data; otp_config_t *odata = (otp_config_t *) apdu.data;
@@ -416,6 +424,7 @@ int cmd_otp() {
file_put_data(ef, apdu.data, otp_config_size); file_put_data(ef, apdu.data, otp_config_size);
low_flash_available(); low_flash_available();
} }
return otp_status(_is_otp);
} }
else if (p1 == 0x06) { else if (p1 == 0x06) {
uint8_t tmp[otp_config_size + 8]; uint8_t tmp[otp_config_size + 8];
@@ -439,6 +448,7 @@ int cmd_otp() {
delete_file(ef2); delete_file(ef2);
} }
low_flash_available(); low_flash_available();
return otp_status(_is_otp);
} }
else if (p1 == 0x10) { else if (p1 == 0x10) {
memcpy(res_APDU, pico_serial.id, 4); memcpy(res_APDU, pico_serial.id, 4);
@@ -456,12 +466,7 @@ int cmd_otp() {
} }
int ret = 0; int ret = 0;
if (p1 == 0x30 || p1 == 0x38) { if (p1 == 0x30 || p1 == 0x38) {
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), otp_config->aes_key, KEY_SIZE, apdu.data, 8, res_APDU);
otp_config->aes_key,
KEY_SIZE,
apdu.data,
8,
res_APDU);
if (ret == 0) { if (ret == 0) {
res_APDU_size = 20; res_APDU_size = 20;
} }
@@ -562,10 +567,12 @@ int otp_hid_set_report_cb(uint8_t itf,
apdu.header[1] = 0x01; apdu.header[1] = 0x01;
apdu.header[2] = slot_id; apdu.header[2] = slot_id;
apdu.header[3] = 0; apdu.header[3] = 0;
_is_otp = true;
int ret = otp_process_apdu(); int ret = otp_process_apdu();
if (ret == 0x9000 && res_APDU_size > 0) { if (ret == 0x9000 && res_APDU_size > 0) {
otp_send_frame(apdu.rdata, apdu.rlen); otp_send_frame(apdu.rdata, apdu.rlen);
} }
_is_otp = false;
} }
else { else {
printf("[OTP] Bad CRC!\n"); printf("[OTP] Bad CRC!\n");
@@ -607,7 +614,7 @@ uint16_t otp_hid_get_report_cb(uint8_t itf,
} }
else { else {
res_APDU = buffer; res_APDU = buffer;
otp_status(); otp_status(true);
} }
return reqlen; return reqlen;