diff --git a/src/Common/EMVCard.cpp b/src/Common/EMVCard.cpp index 70725003..bc7c764b 100644 --- a/src/Common/EMVCard.cpp +++ b/src/Common/EMVCard.cpp @@ -252,13 +252,21 @@ namespace VeraCrypt { sfi = sfiNode->Value->at(0); - uint8 rec = 1; - do + // Record numbers 0 and 255 are reserved. Use a wider counter + // so a full directory cannot wrap back to the first record. + const unsigned int maxDirectoryRecords = 254; + // Also bound the total data retained across all short records. + size_t remainingDirectoryBytes = maxDirectoryRecords * SCardReader::shortAPDUMaxTransSize; + for (unsigned int rec = 1; rec <= maxDirectoryRecords; ++rec) { - command = CommandAPDU(CLA_ISO7816, INS_READ_RECORD, rec++, (sfi << 3) | 4, SCardReader::shortAPDUMaxTransSize); + command = CommandAPDU(CLA_ISO7816, INS_READ_RECORD, rec, (sfi << 3) | 4, SCardReader::shortAPDUMaxTransSize); m_reader->ApduProcessData(command, response); if (response.getSW() == SW_NO_ERROR && response.getData().size() > 0) { + if (response.getData().size() > remainingDirectoryBytes) + throw PCSCException(SCARD_E_UNEXPECTED); + remainingDirectoryBytes -= response.getData().size(); + try { templateNode = TLVParser::TLV_Parse(response.getData().data(), response.getData().size()); @@ -278,7 +286,11 @@ namespace VeraCrypt continue; } } - } while (response.getData().size() > 0); + else + { + break; + } + } } } } diff --git a/src/Common/SCardReader.cpp b/src/Common/SCardReader.cpp index 67bf31e5..a8bdfba7 100644 --- a/src/Common/SCardReader.cpp +++ b/src/Common/SCardReader.cpp @@ -590,8 +590,18 @@ namespace VeraCrypt // Send get response to get the rest as long as we receive SW == 0x61XX // In case of PACE, this is never the case + // A GET RESPONSE returns at most 256 bytes and no response exceeds 65536 bytes, + // so stop a card that keeps answering 0x61XX instead of looping without end + uint32 getResponseCount = 0; while ((lRet == SCARD_S_SUCCESS) && ((BYTE)(SW >> 8) == (BYTE)(SW_BYTES_REMAINING_00 >> 8))) // 0x61 { + if (++getResponseCount > extendedAPDUMaxTransSize / shortAPDUMaxTransSize) + { + responseAPDU.clear(); + lRet = SCARD_E_UNEXPECTED; + break; + } + // GET RESPONSE APDU pbSendBuffer[0] = commandAPDU.getCLA(); pbSendBuffer[1] = INS_GET_RESPONSE;