Protect PW status limits from PUT DATA

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2026-08-14 18:44:38 +02:00
parent f82c97e604
commit aba80f964c
2 changed files with 24 additions and 5 deletions
+2 -5
View File
@@ -61,13 +61,10 @@ int cmd_put_data(void) {
return SW_WRONG_P1P2();
}
if (fid == EF_PW_STATUS) {
if (apdu.nc > 4) {
if (apdu.nc != 1 || apdu.data[0] > 1) {
return SW_WRONG_DATA();
}
fid = EF_PW_PRIV;
if (apdu.nc == 0) {
return SW_WRONG_LENGTH();
}
if (!(ef = file_search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
@@ -94,7 +91,7 @@ int cmd_put_data(void) {
uint16_t status_len = MIN(file_get_size(ef), sizeof(pw_status));
memcpy(pw_status, file_get_data(ef), status_len);
}
memcpy(pw_status, apdu.data, MIN(apdu.nc, 4u));
pw_status[0] = apdu.data[0];
r = file_put_data(ef, CONST_BYTE_ARRAY(pw_status, sizeof(pw_status)));
}
else if (fid == EF_RC) {
+22
View File
@@ -219,6 +219,27 @@ static bool reset_code_is_public_default(const file_t *rc) {
return pin_record_matches_value(rc, default_reset_code, sizeof(default_reset_code) - 1);
}
static void restore_pw_status_limits(void) {
file_t *pw_status = file_search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF);
if (!pw_status || !file_has_data(pw_status) || file_get_size(pw_status) > 64) {
return;
}
uint16_t status_len = file_get_size(pw_status);
uint8_t status[64];
bool changed = false;
memcpy(status, file_get_data(pw_status), status_len);
for (uint8_t i = 1; i < 4 && i < status_len; i++) {
if (status[i] != 127) {
status[i] = 127;
changed = true;
}
}
if (changed) {
file_put_data(pw_status, CONST_BYTE_ARRAY(status, status_len));
}
}
static int set_reset_code_retries(uint8_t retries) {
file_t *pw_status = file_search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF);
if (!pw_status || !file_has_data(pw_status)) {
@@ -437,6 +458,7 @@ void scan_files_openpgp(void) {
}
#endif
}
restore_pw_status_limits();
file_t *rc = file_search_by_fid(EF_RC, NULL, SPECIFY_EF);
if (!rc || !file_has_data(rc) || reset_dek || reset_code_is_public_default(rc)) {
openpgp_reset_code_deactivate();