From 283289fbc6b1531caf899ad6f793c9045a8ad2cf Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 26 Apr 2022 18:04:25 +0200 Subject: [PATCH] Moving retries to PW STATUS. Signed-off-by: Pol Henarejos --- src/openpgp/files.c | 32 ++++++++--------- src/openpgp/files.h | 4 +-- src/openpgp/openpgp.c | 84 +++++++++++++++++-------------------------- 3 files changed, 49 insertions(+), 71 deletions(-) diff --git a/src/openpgp/files.c b/src/openpgp/files.c index 80902eb..310bd53 100644 --- a/src/openpgp/files.c +++ b/src/openpgp/files.c @@ -54,15 +54,15 @@ uint8_t historical_bytes[] = { uint8_t extended_capabilities[] = { 10, 0, - 0x74, /* + 0x76, /* * No Secure Messaging supported * GET CHALLENGE supported * Key import supported * PW status byte can be put * No private_use_DO * Algorithm attrs are changable - * No DEC with AES - * KDF-DO available + * ENC/DEC with AES + * No KDF-DO available */ 0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */ 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 }, /* 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 }, - /* 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 }, - /* 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 }, - /* 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 }, - /* 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 }, - /* 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 }, - /* 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 }, - /* 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 }, - /* 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 }, - /* 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 }, - /* 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 }, - /* 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 }, + /* 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_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_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_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_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_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_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_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_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_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 }, - /* 54 */ { .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 + /* 52 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, + /* 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]; diff --git a/src/openpgp/files.h b/src/openpgp/files.h index 63aa4c2..a844bcd 100644 --- a/src/openpgp/files.h +++ b/src/openpgp/files.h @@ -24,12 +24,10 @@ #define EF_PW1 0x1081 #define EF_RC 0x1082 #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_PRIV2 0x10c2 #define EF_ALGO_PRIV3 0x10c3 +#define EF_PW_PRIV 0x10c4 #define EF_PK_SIG 0x10d1 #define EF_PK_DEC 0x10d2 #define EF_PK_AUT 0x10d3 diff --git a/src/openpgp/openpgp.c b/src/openpgp/openpgp.c index 3d15c9b..729ba57 100644 --- a/src/openpgp/openpgp.c +++ b/src/openpgp/openpgp.c @@ -148,12 +148,6 @@ void scan_files() { dhash[0] = sizeof(def); double_hash_pin(def, sizeof(def), dhash+1); 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))) { @@ -165,12 +159,6 @@ void scan_files() { dhash[0] = sizeof(def); double_hash_pin(def, sizeof(def), dhash+1); 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))) { @@ -182,12 +170,6 @@ void scan_files() { dhash[0] = sizeof(def); double_hash_pin(def, sizeof(def), dhash+1); 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))) { @@ -197,6 +179,13 @@ void scan_files() { 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(); } @@ -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++] = 7; } - res_APDU[res_APDU_size++] = 0x1; - 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); + ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY); if (ef && ef->data) { - res_APDU[res_APDU_size++] = file_read_uint8(ef->data+2); - } - 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); + memcpy(res_APDU+res_APDU_size, file_read(ef->data+2), 7); + res_APDU_size += 7; } 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) { if (!pin) return CCID_ERR_NULL_PARAM; - const file_t *act = search_by_fid(pin->fid+3, NULL, SPECIFY_EF); - if (!act) + file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF); + if (!pw_status) 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 return CCID_ERR_BLOCKED; - retries = 3; - int r = flash_write_data_to_file((file_t *)act, &retries, sizeof(retries)); + p[3+(pin->fid&0x3)] = 3; + int r = flash_write_data_to_file(pw_status, p, file_read_uint16(pw_status->data)); low_flash_available(); return r; } @@ -673,19 +653,20 @@ int pin_reset_retries(const file_t *pin, bool force) { int pin_wrong_retry(const file_t *pin) { if (!pin) return CCID_ERR_NULL_PARAM; - const file_t *act = search_by_fid(pin->fid+3, NULL, SPECIFY_EF); - if (!act) + file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF); + if (!pw_status) return CCID_ERR_FILE_NOT_FOUND; - uint8_t retries = file_read_uint8(act->data+2); - if (retries > 0) { - retries -= 1; - int r = flash_write_data_to_file((file_t *)act, &retries, sizeof(retries)); + uint8_t p[7]; + memcpy(p, file_read(pw_status->data+2), 7); + if (p[3+(pin->fid&0x3)] > 0) { + 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) return r; low_flash_available(); - if (retries == 0) + if (p[3+(pin->fid&0x3)] == 0) return CCID_ERR_BLOCKED; - return retries; + return p[3+(pin->fid&0x3)]; } return CCID_ERR_BLOCKED; } @@ -750,19 +731,20 @@ static int cmd_verify() { uint16_t fid = 0x1000 | p2; if (fid == EF_RC && apdu.cmd_apdu_data_len > 0) fid = EF_PW1; - file_t *pw, *retries; + file_t *pw, *pw_status; if (!(pw = search_by_fid(fid, NULL, SPECIFY_EF))) 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(); if (file_read_uint8(pw->data+2) == 0) //not initialized return SW_REFERENCE_NOT_FOUND(); if (apdu.cmd_apdu_data_len > 0) { 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 set_res_sw(0x63, 0xc0 | file_read_uint8(retries->data+2)); + return set_res_sw(0x63, 0xc0 | retries); } static int cmd_put_data() { @@ -1282,9 +1264,9 @@ static int cmd_terminate_df() { if (P1(apdu) != 0x0 && P2(apdu) != 0x0) return SW_INCORRECT_P1P2(); 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(); - 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(); if (apdu.cmd_apdu_data_len != 0) return SW_WRONG_LENGTH();