From 879a4bd273d00f9b132d7a11b6f1b94fafcb4f9f Mon Sep 17 00:00:00 2001 From: Sparky <191017067+actuallysparky@users.noreply.github.com> Date: Sun, 30 Aug 2026 10:48:29 -0700 Subject: [PATCH] fix(eMRTD): avoid EF_SOD parser stack overflow Allocate EF_SOD parsing scratch buffers on the heap so macOS worker threads do not exceed their stack while reading protected travel documents. Co-Authored-By: Codex --- client/src/cmdhfemrtd.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 5d0182d56..edd06dfe0 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1738,15 +1738,22 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { } static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_t *dataout, size_t *dataoutlen) { - 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 }; + uint8_t *buffers = calloc(5, EMRTD_MAX_FILE_SIZE); + if (buffers == NULL) { + PrintAndLogEx(ERR, "Failed to allocate EF_SOD parser buffers."); + return PM3_EMALLOC; + } + + uint8_t *top = buffers; + uint8_t *signeddata = top + EMRTD_MAX_FILE_SIZE; + uint8_t *emrtdsigcontainer = signeddata + EMRTD_MAX_FILE_SIZE; + uint8_t *emrtdsig = emrtdsigcontainer + EMRTD_MAX_FILE_SIZE; + uint8_t *emrtdsigtext = emrtdsig + EMRTD_MAX_FILE_SIZE; size_t toplen, signeddatalen, emrtdsigcontainerlen, emrtdsiglen, emrtdsigtextlen = 0; if (emrtd_lds_get_data_by_tag(data, datalen, top, &toplen, 0x30, 0x00, false, true, 0) == false) { PrintAndLogEx(ERR, "Failed to read top from EF_SOD."); + free(buffers); return false; } @@ -1754,6 +1761,7 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ if (emrtd_lds_get_data_by_tag(top, toplen, signeddata, &signeddatalen, 0xA0, 0x00, false, false, 0) == false) { PrintAndLogEx(ERR, "Failed to read signedData from EF_SOD."); + free(buffers); return false; } @@ -1762,6 +1770,7 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ // Do true on reading into the tag as it's a "sequence" if (emrtd_lds_get_data_by_tag(signeddata, signeddatalen, emrtdsigcontainer, &emrtdsigcontainerlen, 0x30, 0x00, false, true, 0) == false) { PrintAndLogEx(ERR, "Failed to read eMRTDSignature container from EF_SOD."); + free(buffers); return false; } @@ -1769,6 +1778,7 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ if (emrtd_lds_get_data_by_tag(emrtdsigcontainer, emrtdsigcontainerlen, emrtdsig, &emrtdsiglen, 0xA0, 0x00, false, false, 0) == false) { PrintAndLogEx(ERR, "Failed to read eMRTDSignature from EF_SOD."); + free(buffers); return false; } @@ -1777,10 +1787,12 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ // TODO: Not doing memcpy here, it didn't work, fix it somehow if (emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, emrtdsigtext, &emrtdsigtextlen, 0x04, 0x00, false, false, 0) == false) { PrintAndLogEx(ERR, "Failed to read eMRTDSignature (text) from EF_SOD."); + free(buffers); return false; } memcpy(dataout, emrtdsigtext, emrtdsigtextlen); *dataoutlen = emrtdsigtextlen; + free(buffers); return PM3_SUCCESS; } @@ -1823,8 +1835,14 @@ static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hash } static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *hashes, int *hashalgo) { - uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; - uint8_t hashlist[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t *buffers = calloc(2, EMRTD_MAX_FILE_SIZE); + if (buffers == NULL) { + PrintAndLogEx(ERR, "Failed to allocate EF_SOD hash buffers."); + return PM3_EMALLOC; + } + + uint8_t *emrtdsig = buffers; + uint8_t *hashlist = emrtdsig + EMRTD_MAX_FILE_SIZE; uint8_t hash[64] = { 0x00 }; size_t hashlen = 0; @@ -1836,6 +1854,7 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has size_t offset = 0; if (emrtd_ef_sod_extract_signatures(data, datalen, emrtdsig, &emrtdsiglen) != PM3_SUCCESS) { + free(buffers); return false; } @@ -1845,6 +1864,7 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has if (emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, hashlist, &hashlistlen, 0x30, 0x00, false, true, 1) == false) { PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD"); + free(buffers); return false; } @@ -1876,6 +1896,7 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has offset += 1 + e_datalen + e_fieldlen; } + free(buffers); return PM3_SUCCESS; }