Moving retries to PW STATUS.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2022-04-26 18:04:25 +02:00
parent dc988e2a88
commit 283289fbc6
3 changed files with 49 additions and 71 deletions

View File

@@ -54,15 +54,15 @@ uint8_t historical_bytes[] = {
uint8_t extended_capabilities[] = { uint8_t extended_capabilities[] = {
10, 0, 10, 0,
0x74, /* 0x76, /*
* No Secure Messaging supported * No Secure Messaging supported
* GET CHALLENGE supported * GET CHALLENGE supported
* Key import supported * Key import supported
* PW status byte can be put * PW status byte can be put
* No private_use_DO * No private_use_DO
* Algorithm attrs are changable * Algorithm attrs are changable
* No DEC with AES * ENC/DEC with AES
* KDF-DO available * No KDF-DO available
*/ */
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */ 0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
0x00, 128, /* Max size of GET CHALLENGE */ 0x00, 128, /* Max size of GET CHALLENGE */
@@ -126,21 +126,19 @@ file_t file_entries[] = {
/* 39 */ { .fid = EF_PW1, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 39 */ { .fid = EF_PW1, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 40 */ { .fid = EF_RC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 40 */ { .fid = EF_RC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 41 */ { .fid = EF_PW3, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 41 */ { .fid = EF_PW3, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 42 */ { .fid = EF_PW1_RETRIES, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 42 */ { .fid = EF_ALGO_PRIV1, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 43 */ { .fid = EF_RC_RETRIES, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 43 */ { .fid = EF_ALGO_PRIV2, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 44 */ { .fid = EF_PW3_RETRIES, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 44 */ { .fid = EF_ALGO_PRIV3, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 45 */ { .fid = EF_ALGO_PRIV1, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 45 */ { .fid = EF_PK_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 46 */ { .fid = EF_ALGO_PRIV2, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 46 */ { .fid = EF_PK_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 47 */ { .fid = EF_ALGO_PRIV3, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 47 */ { .fid = EF_PK_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 48 */ { .fid = EF_PK_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 48 */ { .fid = EF_PB_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 49 */ { .fid = EF_PK_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 49 */ { .fid = EF_PB_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 50 */ { .fid = EF_PK_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 50 */ { .fid = EF_PB_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 51 */ { .fid = EF_PB_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 51 */ { .fid = EF_PW_PRIV, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 52 */ { .fid = EF_PB_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 53 */ { .fid = EF_PB_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 54 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, /* 52 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 55 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = ACL_NONE } //end /* 53 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = ACL_NONE } //end
}; };
const file_t *MF = &file_entries[0]; const file_t *MF = &file_entries[0];

View File

@@ -24,12 +24,10 @@
#define EF_PW1 0x1081 #define EF_PW1 0x1081
#define EF_RC 0x1082 #define EF_RC 0x1082
#define EF_PW3 0x1083 #define EF_PW3 0x1083
#define EF_PW1_RETRIES 0x1084
#define EF_RC_RETRIES 0x1085
#define EF_PW3_RETRIES 0x1086
#define EF_ALGO_PRIV1 0x10c1 #define EF_ALGO_PRIV1 0x10c1
#define EF_ALGO_PRIV2 0x10c2 #define EF_ALGO_PRIV2 0x10c2
#define EF_ALGO_PRIV3 0x10c3 #define EF_ALGO_PRIV3 0x10c3
#define EF_PW_PRIV 0x10c4
#define EF_PK_SIG 0x10d1 #define EF_PK_SIG 0x10d1
#define EF_PK_DEC 0x10d2 #define EF_PK_DEC 0x10d2
#define EF_PK_AUT 0x10d3 #define EF_PK_AUT 0x10d3

View File

@@ -148,12 +148,6 @@ void scan_files() {
dhash[0] = sizeof(def); dhash[0] = sizeof(def);
double_hash_pin(def, sizeof(def), dhash+1); double_hash_pin(def, sizeof(def), dhash+1);
flash_write_data_to_file(ef, dhash, sizeof(dhash)); flash_write_data_to_file(ef, dhash, sizeof(dhash));
ef = search_by_fid(EF_PW1_RETRIES, NULL, SPECIFY_ANY);
if (ef && !ef->data) {
const uint8_t retries = 3;
flash_write_data_to_file(ef, &retries, sizeof(retries));
}
} }
} }
if ((ef = search_by_fid(EF_RC, NULL, SPECIFY_ANY))) { if ((ef = search_by_fid(EF_RC, NULL, SPECIFY_ANY))) {
@@ -165,12 +159,6 @@ void scan_files() {
dhash[0] = sizeof(def); dhash[0] = sizeof(def);
double_hash_pin(def, sizeof(def), dhash+1); double_hash_pin(def, sizeof(def), dhash+1);
flash_write_data_to_file(ef, dhash, sizeof(dhash)); flash_write_data_to_file(ef, dhash, sizeof(dhash));
ef = search_by_fid(EF_RC_RETRIES, NULL, SPECIFY_ANY);
if (ef && !ef->data) {
const uint8_t retries = 3;
flash_write_data_to_file(ef, &retries, sizeof(retries));
}
} }
} }
if ((ef = search_by_fid(EF_PW3, NULL, SPECIFY_ANY))) { if ((ef = search_by_fid(EF_PW3, NULL, SPECIFY_ANY))) {
@@ -182,12 +170,6 @@ void scan_files() {
dhash[0] = sizeof(def); dhash[0] = sizeof(def);
double_hash_pin(def, sizeof(def), dhash+1); double_hash_pin(def, sizeof(def), dhash+1);
flash_write_data_to_file(ef, dhash, sizeof(dhash)); flash_write_data_to_file(ef, dhash, sizeof(dhash));
ef = search_by_fid(EF_PW3_RETRIES, NULL, SPECIFY_ANY);
if (ef && !ef->data) {
const uint8_t retries = 3;
flash_write_data_to_file(ef, &retries, sizeof(retries));
}
} }
} }
if ((ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY))) { if ((ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY))) {
@@ -197,6 +179,13 @@ void scan_files() {
flash_write_data_to_file(ef, def, sizeof(def)); flash_write_data_to_file(ef, def, sizeof(def));
} }
} }
if ((ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY))) {
if (!ef->data) {
TU_LOG1("PW status is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x1, 127, 127, 127, 3, 3, 3 };
flash_write_data_to_file(ef, def, sizeof(def));
}
}
low_flash_available(); low_flash_available();
} }
@@ -395,21 +384,10 @@ int parse_pw_status(const file_t *f, int mode) {
res_APDU[res_APDU_size++] = EF_PW_STATUS & 0xff; res_APDU[res_APDU_size++] = EF_PW_STATUS & 0xff;
res_APDU[res_APDU_size++] = 7; res_APDU[res_APDU_size++] = 7;
} }
res_APDU[res_APDU_size++] = 0x1; ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY);
res_APDU[res_APDU_size++] = 127;
res_APDU[res_APDU_size++] = 127;
res_APDU[res_APDU_size++] = 127;
ef = search_by_fid(EF_PW1_RETRIES, NULL, SPECIFY_ANY);
if (ef && ef->data) { if (ef && ef->data) {
res_APDU[res_APDU_size++] = file_read_uint8(ef->data+2); memcpy(res_APDU+res_APDU_size, file_read(ef->data+2), 7);
} res_APDU_size += 7;
ef = search_by_fid(EF_RC_RETRIES, NULL, SPECIFY_ANY);
if (ef && ef->data) {
res_APDU[res_APDU_size++] = file_read_uint8(ef->data+2);
}
ef = search_by_fid(EF_PW3_RETRIES, NULL, SPECIFY_ANY);
if (ef && ef->data) {
res_APDU[res_APDU_size++] = file_read_uint8(ef->data+2);
} }
return res_APDU_size-init_len; return res_APDU_size-init_len;
} }
@@ -658,14 +636,16 @@ static int cmd_get_data() {
int pin_reset_retries(const file_t *pin, bool force) { int pin_reset_retries(const file_t *pin, bool force) {
if (!pin) if (!pin)
return CCID_ERR_NULL_PARAM; return CCID_ERR_NULL_PARAM;
const file_t *act = search_by_fid(pin->fid+3, NULL, SPECIFY_EF); file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF);
if (!act) if (!pw_status)
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
uint8_t retries = file_read_uint8(act->data+2); uint8_t p[7];
memcpy(p, file_read(pw_status->data+2), 7);
uint8_t retries = p[3+(pin->fid&0x3)];
if (retries == 0 && force == false) //blocked if (retries == 0 && force == false) //blocked
return CCID_ERR_BLOCKED; return CCID_ERR_BLOCKED;
retries = 3; p[3+(pin->fid&0x3)] = 3;
int r = flash_write_data_to_file((file_t *)act, &retries, sizeof(retries)); int r = flash_write_data_to_file(pw_status, p, file_read_uint16(pw_status->data));
low_flash_available(); low_flash_available();
return r; return r;
} }
@@ -673,19 +653,20 @@ int pin_reset_retries(const file_t *pin, bool force) {
int pin_wrong_retry(const file_t *pin) { int pin_wrong_retry(const file_t *pin) {
if (!pin) if (!pin)
return CCID_ERR_NULL_PARAM; return CCID_ERR_NULL_PARAM;
const file_t *act = search_by_fid(pin->fid+3, NULL, SPECIFY_EF); file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF);
if (!act) if (!pw_status)
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
uint8_t retries = file_read_uint8(act->data+2); uint8_t p[7];
if (retries > 0) { memcpy(p, file_read(pw_status->data+2), 7);
retries -= 1; if (p[3+(pin->fid&0x3)] > 0) {
int r = flash_write_data_to_file((file_t *)act, &retries, sizeof(retries)); p[3+(pin->fid&0x3)] -= 1;
int r = flash_write_data_to_file(pw_status, p, file_read_uint16(pw_status->data));
if (r != CCID_OK) if (r != CCID_OK)
return r; return r;
low_flash_available(); low_flash_available();
if (retries == 0) if (p[3+(pin->fid&0x3)] == 0)
return CCID_ERR_BLOCKED; return CCID_ERR_BLOCKED;
return retries; return p[3+(pin->fid&0x3)];
} }
return CCID_ERR_BLOCKED; return CCID_ERR_BLOCKED;
} }
@@ -750,19 +731,20 @@ static int cmd_verify() {
uint16_t fid = 0x1000 | p2; uint16_t fid = 0x1000 | p2;
if (fid == EF_RC && apdu.cmd_apdu_data_len > 0) if (fid == EF_RC && apdu.cmd_apdu_data_len > 0)
fid = EF_PW1; fid = EF_PW1;
file_t *pw, *retries; file_t *pw, *pw_status;
if (!(pw = search_by_fid(fid, NULL, SPECIFY_EF))) if (!(pw = search_by_fid(fid, NULL, SPECIFY_EF)))
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
if (!(retries = search_by_fid(fid+3, NULL, SPECIFY_EF))) if (!(pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF)))
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
if (file_read_uint8(pw->data+2) == 0) //not initialized if (file_read_uint8(pw->data+2) == 0) //not initialized
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
if (apdu.cmd_apdu_data_len > 0) { if (apdu.cmd_apdu_data_len > 0) {
return check_pin(pw, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); return check_pin(pw, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
} }
if (file_read_uint8(retries->data+2) == 0) uint8_t retries = file_read_uint8(pw_status->data+2+3+(fid&0x3));
if (retries == 0)
return SW_PIN_BLOCKED(); return SW_PIN_BLOCKED();
return set_res_sw(0x63, 0xc0 | file_read_uint8(retries->data+2)); return set_res_sw(0x63, 0xc0 | retries);
} }
static int cmd_put_data() { static int cmd_put_data() {
@@ -1282,9 +1264,9 @@ static int cmd_terminate_df() {
if (P1(apdu) != 0x0 && P2(apdu) != 0x0) if (P1(apdu) != 0x0 && P2(apdu) != 0x0)
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
file_t *retries; file_t *retries;
if (!(retries = search_by_fid(EF_PW3_RETRIES, NULL, SPECIFY_EF))) if (!(retries = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF)))
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
if (!has_pw3 && file_read_uint8(retries->data+2) > 0) if (!has_pw3 && file_read_uint8(retries->data+2+6) > 0)
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
if (apdu.cmd_apdu_data_len != 0) if (apdu.cmd_apdu_data_len != 0)
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();