From b505c5f4d8e7823c3a2c474e63e375412ec57505 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 22 Dec 2020 05:01:42 +0300 Subject: [PATCH] emrtd: Read file hash data from EF_SOD --- client/src/cmdhfemrtd.c | 76 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index d0b3527af..4e3bfc575 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -203,9 +203,9 @@ static char emrtd_calculate_check_digit(char *data) { } static int emrtd_get_asn1_data_length(uint8_t *datain, int datainlen, int offset) { - PrintAndLogEx(DEBUG, "asn1datalength, datain: %s", sprint_hex_inrow(datain, datainlen)); + PrintAndLogEx(DEBUG, "asn1 datalength, datain: %s", sprint_hex_inrow(datain, datainlen)); int lenfield = (int) * (datain + offset); - PrintAndLogEx(DEBUG, "asn1datalength, lenfield: %i", lenfield); + PrintAndLogEx(DEBUG, "asn1 datalength, lenfield: %02X", lenfield); if (lenfield <= 0x7f) { return lenfield; } else if (lenfield == 0x81) { @@ -221,7 +221,7 @@ static int emrtd_get_asn1_data_length(uint8_t *datain, int datainlen, int offset static int emrtd_get_asn1_field_length(uint8_t *datain, int datainlen, int offset) { PrintAndLogEx(DEBUG, "asn1 fieldlength, datain: %s", sprint_hex_inrow(datain, datainlen)); int lenfield = (int) * (datain + offset); - PrintAndLogEx(DEBUG, "asn1 fieldlength, thing: %i", lenfield); + PrintAndLogEx(DEBUG, "asn1 fieldlength, lenfield: %02X", lenfield); if (lenfield <= 0x7F) { return 1; } else if (lenfield == 0x81) { @@ -629,10 +629,10 @@ static int emrtd_lds_determine_tag_length(uint8_t tag) { return 1; } -static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *dataout, int *dataoutlen, int tag1, int tag2, bool twobytetag, bool skiptoptag) { +static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *dataout, int *dataoutlen, int tag1, int tag2, bool twobytetag, bool entertoptag) { int offset = 0; - if (skiptoptag) { + if (entertoptag) { offset += emrtd_lds_determine_tag_length(*datain); offset += emrtd_get_asn1_field_length(datain, datainlen, offset); } @@ -651,6 +651,8 @@ static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *d // Get the length of the element's length e_fieldlen = emrtd_get_asn1_field_length(datain + offset, datainlen - offset, e_idlen); + PrintAndLogEx(DEBUG, "emrtd_lds_get_data_by_tag, e_idlen: %02X, e_datalen: %02X, e_fieldlen: %02X", e_idlen, e_datalen, e_fieldlen); + // If the element is what we're looking for, get the data and return true if (*(datain + offset) == tag1 && (!twobytetag || *(datain + offset + 1) == tag2)) { if (datainlen > e_datalen) { @@ -1477,10 +1479,68 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { return PM3_SUCCESS; } +static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_t *dataout, size_t *dataoutlen) { + // very very very very cursed code. + uint8_t top[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t signeddata[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t emrtdsigcontainer[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t emrtdsigtext[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + size_t toplen, signeddatalen, emrtdsigcontainerlen, emrtdsiglen, emrtdsigtextlen = 0; + + if (!emrtd_lds_get_data_by_tag(data, (int) datalen, top, (int *) &toplen, 0x30, 0x00, false, true)) { + PrintAndLogEx(ERR, "Failed to read top from EF_SOD."); + return false; + } + + PrintAndLogEx(DEBUG, "top: %s.", sprint_hex_inrow(top, toplen)); + + if (!emrtd_lds_get_data_by_tag(top, (int) toplen, signeddata, (int *) &signeddatalen, 0xA0, 0x00, false, false)) { + PrintAndLogEx(ERR, "Failed to read signedData from EF_SOD."); + return false; + } + + PrintAndLogEx(DEBUG, "signeddata: %s.", sprint_hex_inrow(signeddata, signeddatalen)); + + // Do true on reading into the tag as it's a "sequence" + if (!emrtd_lds_get_data_by_tag(signeddata, (int) signeddatalen, emrtdsigcontainer, (int *) &emrtdsigcontainerlen, 0x30, 0x00, false, true)) { + PrintAndLogEx(ERR, "Failed to read eMRTDSignature container from EF_SOD."); + return false; + } + + PrintAndLogEx(DEBUG, "emrtdsigcontainer: %s.", sprint_hex_inrow(emrtdsigcontainer, emrtdsigcontainerlen)); + + if (!emrtd_lds_get_data_by_tag(emrtdsigcontainer, (int) emrtdsigcontainerlen, emrtdsig, (int *) &emrtdsiglen, 0xA0, 0x00, false, false)) { + PrintAndLogEx(ERR, "Failed to read eMRTDSignature from EF_SOD."); + return false; + } + + PrintAndLogEx(DEBUG, "emrtdsig: %s.", sprint_hex_inrow(emrtdsig, emrtdsiglen)); + + // TODO: Not doing memcpy here, it didn't work, fix it somehow + if (!emrtd_lds_get_data_by_tag(emrtdsig, (int) emrtdsiglen, emrtdsigtext, (int *) &emrtdsigtextlen, 0x04, 0x00, false, false)) { + PrintAndLogEx(ERR, "Failed to read eMRTDSignature (text) from EF_SOD."); + return false; + } + memcpy(dataout, emrtdsigtext, emrtdsigtextlen); + *dataoutlen = emrtdsigtextlen; + return PM3_SUCCESS; +} + static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen) { -// PrintAndLogEx(NORMAL, ""); -// PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); -// PrintAndLogEx(WARNING, "TODO"); + uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + // size_t emrtdsiglen, e_datalen, e_fieldlen = 0; + size_t emrtdsiglen = 0; + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); + + if (emrtd_ef_sod_extract_signatures(data, datalen, emrtdsig, &emrtdsiglen) != PM3_SUCCESS) { + return false; + } + // TODO: parse this + PrintAndLogEx(INFO, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); + return PM3_SUCCESS; }