From 0f1ba33b6931d051a987c2b47c399aa89c0414e5 Mon Sep 17 00:00:00 2001 From: Ave Date: Sun, 21 Feb 2021 01:43:59 +0300 Subject: [PATCH] emrtd: Add PACE algo detection --- client/src/cmdhfemrtd.c | 99 ++++++++++++++++++++++++++++++++--------- client/src/cmdhfemrtd.h | 6 +++ 2 files changed, 84 insertions(+), 21 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 882d43bae..4621a3b39 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -58,6 +58,7 @@ static int emrtd_print_ef_com_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg1_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen); +static int emrtd_print_ef_cardaccess_info(uint8_t *data, size_t datalen); typedef enum { // list must match dg_table EF_COM = 0, @@ -83,27 +84,27 @@ typedef enum { // list must match dg_table } emrtd_dg_enum; static emrtd_dg_t dg_table[] = { -// tag dg# fileid filename desc pace eac req fast parser dumper - {0x60, 0, "011E", "EF_COM", "Header and Data Group Presence Information", false, false, true, true, emrtd_print_ef_com_info, NULL}, - {0x61, 1, "0101", "EF_DG1", "Details recorded in MRZ", false, false, true, true, emrtd_print_ef_dg1_info, NULL}, - {0x75, 2, "0102", "EF_DG2", "Encoded Face", false, false, true, false, NULL, emrtd_dump_ef_dg2}, - {0x63, 3, "0103", "EF_DG3", "Encoded Finger(s)", false, true, false, false, NULL, NULL}, - {0x76, 4, "0104", "EF_DG4", "Encoded Eye(s)", false, true, false, false, NULL, NULL}, - {0x65, 5, "0105", "EF_DG5", "Displayed Portrait", false, false, false, false, NULL, emrtd_dump_ef_dg5}, - {0x66, 6, "0106", "EF_DG6", "Reserved for Future Use", false, false, false, false, NULL, NULL}, - {0x67, 7, "0107", "EF_DG7", "Displayed Signature or Usual Mark", false, false, false, false, NULL, emrtd_dump_ef_dg7}, - {0x68, 8, "0108", "EF_DG8", "Data Feature(s)", false, false, false, true, NULL, NULL}, - {0x69, 9, "0109", "EF_DG9", "Structure Feature(s)", false, false, false, true, NULL, NULL}, - {0x6a, 10, "010A", "EF_DG10", "Substance Feature(s)", false, false, false, true, NULL, NULL}, - {0x6b, 11, "010B", "EF_DG11", "Additional Personal Detail(s)", false, false, false, true, emrtd_print_ef_dg11_info, NULL}, - {0x6c, 12, "010C", "EF_DG12", "Additional Document Detail(s)", false, false, false, true, emrtd_print_ef_dg12_info, NULL}, - {0x6d, 13, "010D", "EF_DG13", "Optional Detail(s)", false, false, false, true, NULL, NULL}, - {0x6e, 14, "010E", "EF_DG14", "Security Options", false, false, false, true, NULL, NULL}, - {0x6f, 15, "010F", "EF_DG15", "Active Authentication Public Key Info", false, false, false, true, NULL, NULL}, - {0x70, 16, "0110", "EF_DG16", "Person(s) to Notify", false, false, false, true, NULL, NULL}, - {0x77, 0, "011D", "EF_SOD", "Document Security Object", false, false, false, false, NULL, emrtd_dump_ef_sod}, - {0xff, 0, "011C", "EF_CardAccess", "PACE SecurityInfos", true, false, true, true, NULL, NULL}, - {0xff, 0, "011D", "EF_CardSecurity", "PACE SecurityInfos for Chip Authentication Mapping", true, false, false, true, NULL, NULL}, +// tag dg# fileid filename desc pace eac req fast parser dumper + {0x60, 0, "011E", "EF_COM", "Header and Data Group Presence Information", false, false, true, true, emrtd_print_ef_com_info, NULL}, + {0x61, 1, "0101", "EF_DG1", "Details recorded in MRZ", false, false, true, true, emrtd_print_ef_dg1_info, NULL}, + {0x75, 2, "0102", "EF_DG2", "Encoded Face", false, false, true, false, NULL, emrtd_dump_ef_dg2}, + {0x63, 3, "0103", "EF_DG3", "Encoded Finger(s)", false, true, false, false, NULL, NULL}, + {0x76, 4, "0104", "EF_DG4", "Encoded Eye(s)", false, true, false, false, NULL, NULL}, + {0x65, 5, "0105", "EF_DG5", "Displayed Portrait", false, false, false, false, NULL, emrtd_dump_ef_dg5}, + {0x66, 6, "0106", "EF_DG6", "Reserved for Future Use", false, false, false, false, NULL, NULL}, + {0x67, 7, "0107", "EF_DG7", "Displayed Signature or Usual Mark", false, false, false, false, NULL, emrtd_dump_ef_dg7}, + {0x68, 8, "0108", "EF_DG8", "Data Feature(s)", false, false, false, true, NULL, NULL}, + {0x69, 9, "0109", "EF_DG9", "Structure Feature(s)", false, false, false, true, NULL, NULL}, + {0x6a, 10, "010A", "EF_DG10", "Substance Feature(s)", false, false, false, true, NULL, NULL}, + {0x6b, 11, "010B", "EF_DG11", "Additional Personal Detail(s)", false, false, false, true, emrtd_print_ef_dg11_info, NULL}, + {0x6c, 12, "010C", "EF_DG12", "Additional Document Detail(s)", false, false, false, true, emrtd_print_ef_dg12_info, NULL}, + {0x6d, 13, "010D", "EF_DG13", "Optional Detail(s)", false, false, false, true, NULL, NULL}, + {0x6e, 14, "010E", "EF_DG14", "Security Options", false, false, false, true, NULL, NULL}, + {0x6f, 15, "010F", "EF_DG15", "Active Authentication Public Key Info", false, false, false, true, NULL, NULL}, + {0x70, 16, "0110", "EF_DG16", "Person(s) to Notify", false, false, false, true, NULL, NULL}, + {0x77, 0, "011D", "EF_SOD", "Document Security Object", false, false, false, false, NULL, emrtd_dump_ef_sod}, + {0xff, 0, "011C", "EF_CardAccess", "PACE SecurityInfos", true, false, true, true, emrtd_print_ef_cardaccess_info, NULL}, + {0xff, 0, "011D", "EF_CardSecurity", "PACE SecurityInfos for Chip Authentication Mapping", true, false, false, true, NULL, NULL}, {0x00, 0, NULL, NULL, NULL, false, false, false, false, NULL, NULL} }; @@ -117,6 +118,27 @@ static emrtd_hashalg_t hashalg_table[] = { {NULL, NULL, 0, 0, {}} }; +static emrtd_pacealg_t pacealg_table[] = { +// name keygen descriptor + {"DH, Generic Mapping, 3DES-CBC-CBC", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x01, 0x01}}, + {"DH, Generic Mapping, AES-CMAC-128", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x01, 0x02}}, + {"DH, Generic Mapping, AES-CMAC-192", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x01, 0x03}}, + {"DH, Generic Mapping, AES-CMAC-256", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x01, 0x04}}, + {"ECDH, Generic Mapping, 3DES-CBC-CBC", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x01}}, + {"ECDH, Generic Mapping, AES-CMAC-128", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x02}}, + {"ECDH, Generic Mapping, AES-CMAC-192", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x03}}, + {"ECDH, Generic Mapping, AES-CMAC-256", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x04}}, + {"DH, Integrated Mapping, 3DES-CBC-CBC", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x03, 0x01}}, + {"DH, Integrated Mapping, AES-CMAC-128", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x03, 0x02}}, + {"DH, Integrated Mapping, AES-CMAC-192", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x03, 0x03}}, + {"DH, Integrated Mapping, AES-CMAC-256", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x03, 0x04}}, + {"ECDH, Integrated Mapping, 3DES-CBC-CBC", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x04, 0x01}}, + {"ECDH, Integrated Mapping, AES-CMAC-128", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x04, 0x02}}, + {"ECDH, Integrated Mapping, AES-CMAC-192", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x04, 0x03}}, + {"ECDH, Integrated Mapping, AES-CMAC-256", NULL, {0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x04, 0x04}}, + {NULL, NULL, {}} +}; + static emrtd_dg_t *emrtd_tag_to_dg(uint8_t tag) { for (int dgi = 0; dg_table[dgi].filename != NULL; dgi++) { if (dg_table[dgi].tag == tag) { @@ -1726,6 +1748,37 @@ static int emrtd_print_ef_sod_info(uint8_t *dg_hashes_calc, uint8_t *dg_hashes_s return PM3_SUCCESS; } +static int emrtd_print_ef_cardaccess_info(uint8_t *data, size_t datalen) { + uint8_t dataset[100] = { 0x00 }; + size_t datasetlen = 0; + uint8_t pacealgorithm[100] = { 0x00 }; + size_t pacealgorithmlen = 0; + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "----------------- " _CYAN_("EF_CardAccess") " ----------------"); + + if (!emrtd_lds_get_data_by_tag(data, datalen, dataset, &datasetlen, 0x30, 0x00, false, true, 0)) { + PrintAndLogEx(ERR, "Failed to read set from EF_CardAccess."); + return PM3_ESOFT; + } + + if (!emrtd_lds_get_data_by_tag(dataset, datasetlen, pacealgorithm, &pacealgorithmlen, 0x06, 0x00, false, false, 0)) { + PrintAndLogEx(ERR, "Failed to read PACE algorithm from EF_CardAccess."); + return PM3_ESOFT; + } + + for (int pacei = 0; pacealg_table[pacei].name != NULL; pacei++) { + PrintAndLogEx(DEBUG, "Trying: %s", hashalg_table[pacei].name); + + if (memcmp(pacealg_table[pacei].descriptor, pacealgorithm, pacealgorithmlen) == 0) { + PrintAndLogEx(SUCCESS, "PACE algorithm........: " _YELLOW_("%s"), pacealg_table[pacei].name); + return PM3_SUCCESS; + } + } + + return PM3_SUCCESS; +} + int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available) { uint8_t response[EMRTD_MAX_FILE_SIZE] = { 0x00 }; int resplen = 0; @@ -1758,6 +1811,10 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab PrintAndLogEx(SUCCESS, "PACE..................: %s", PACE_available ? _GREEN_("Available") : _YELLOW_("Not available")); PrintAndLogEx(SUCCESS, "Authentication result.: %s", auth_result ? _GREEN_("Successful") : _RED_("Failed")); + if (PACE_available) { + emrtd_print_ef_cardaccess_info(response, resplen); + } + if (!auth_result) { DropField(); return PM3_ESOFT; diff --git a/client/src/cmdhfemrtd.h b/client/src/cmdhfemrtd.h index bb32fb53d..afa814f0a 100644 --- a/client/src/cmdhfemrtd.h +++ b/client/src/cmdhfemrtd.h @@ -35,6 +35,12 @@ typedef struct emrtd_hashalg_s { const uint8_t descriptor[15]; } emrtd_hashalg_t; +typedef struct emrtd_pacealg_s { + const char *name; + int (*keygenerator)(uint8_t *datain, int datainlen, uint8_t *dataout); + const uint8_t descriptor[10]; +} emrtd_pacealg_t; + int CmdHFeMRTD(const char *Cmd); int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available, const char *path);