From 034b64f4153550cbe5849bcbfc27e187377cc512 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Thu, 29 Jun 2023 00:06:20 +0200 Subject: [PATCH] EMV keyfile support: Overall code improvements and bug fixes --- src/Common/CommandAPDU.cpp | 366 +++++++++ src/Common/CommandAPDU.h | 93 +++ src/Common/Dlgcode.c | 14 +- src/Common/Dlgcode.h | 2 +- src/Common/EMVCard.cpp | 523 ++++++++++++ src/Common/EMVCard.h | 69 ++ src/Common/EMVToken.cpp | 178 +++- src/Common/EMVToken.h | 28 +- src/Common/IccDataExtractor.cpp | 777 ------------------ src/Common/IccDataExtractor.h | 231 ------ src/Common/Keyfiles.c | 2 +- src/Common/Language.xml | 20 +- src/Common/PCSCException.cpp | 199 +++++ src/Common/PCSCException.h | 136 +++ src/Common/ResponseAPDU.cpp | 111 +++ src/Common/ResponseAPDU.h | 44 + src/Common/SCard.cpp | 62 ++ src/Common/SCard.h | 27 + src/Common/SCardLoader.cpp | 402 +++++++++ src/Common/SCardLoader.h | 125 +++ src/Common/SCardManager.cpp | 109 +++ src/Common/SCardManager.h | 21 + src/Common/SCardReader.cpp | 681 +++++++++++++++ src/Common/SCardReader.h | 200 +++++ src/Common/SecurityToken.h | 4 + src/Common/TLVParser.cpp | 324 ++++---- src/Common/TLVParser.h | 146 ++-- src/Common/Token.cpp | 74 +- src/Common/Token.h | 38 +- src/Common/reader.h | 271 ++++++ src/Core/Core.h | 22 +- src/Core/CoreBase.cpp | 18 +- src/Core/CoreBase.h | 8 +- src/Core/MountOptions.h | 2 +- src/Core/Unix/CoreServiceProxy.h | 6 +- src/Core/Unix/CoreUnix.cpp | 2 +- src/Core/VolumeCreator.cpp | 2 +- src/Core/VolumeCreator.h | 2 +- src/Driver/veracrypt_vs2019.vcxproj | 135 +++ src/Driver/veracrypt_vs2019.vcxproj.filters | 9 + src/ExpandVolume/ExpandVolume.vcxproj | 26 +- src/ExpandVolume/ExpandVolume.vcxproj.filters | 50 +- src/ExpandVolume/ExpandVolume_vs2019.vcxproj | 22 + .../ExpandVolume_vs2019.vcxproj.filters | 66 ++ src/ExpandVolume/WinMain.cpp | 2 +- src/Format/Format.vcxproj | 26 +- src/Format/Format.vcxproj.filters | 50 +- src/Format/Format_vs2019.vcxproj | 22 + src/Format/Tcformat.c | 2 +- src/Main/CommandLineInterface.cpp | 10 +- src/Main/CommandLineInterface.h | 4 +- src/Main/Forms/ChangePasswordDialog.cpp | 2 +- src/Main/Forms/Forms.cpp | 10 +- src/Main/Forms/Forms.h | 2 +- src/Main/Forms/MainFrame.cpp | 4 +- src/Main/Forms/MountOptionsDialog.cpp | 2 +- src/Main/Forms/PreferencesDialog.cpp | 2 +- .../Forms/SecurityTokenKeyfilesDialog.cpp | 52 +- src/Main/Forms/VolumeCreationWizard.cpp | 8 +- src/Main/Forms/WaitDialog.cpp | 20 +- src/Main/GraphicUserInterface.cpp | 18 +- src/Main/GraphicUserInterface.h | 4 +- src/Main/TextUserInterface.cpp | 36 +- src/Main/TextUserInterface.h | 4 +- src/Main/UserInterface.cpp | 48 +- src/Main/UserInterface.h | 4 +- src/Main/UserPreferences.cpp | 4 +- src/Main/UserPreferences.h | 4 +- src/Makefile | 15 +- src/Mount/Mount.c | 8 +- src/Mount/Mount.rc | 2 +- src/Mount/Mount.vcxproj | 26 +- src/Mount/Mount.vcxproj.filters | 50 +- src/Mount/Mount_vs2019.vcxproj | 22 + src/Mount/Resource.h | 2 +- src/VeraCrypt_vs2019.sln | 8 +- src/Volume/Keyfile.cpp | 81 +- src/Volume/Keyfile.h | 4 +- src/Volume/Volume.cpp | 10 +- src/Volume/Volume.h | 4 +- src/Volume/Volume.make | 9 +- 81 files changed, 4654 insertions(+), 1574 deletions(-) create mode 100644 src/Common/CommandAPDU.cpp create mode 100644 src/Common/CommandAPDU.h create mode 100644 src/Common/EMVCard.cpp create mode 100644 src/Common/EMVCard.h create mode 100644 src/Common/PCSCException.cpp create mode 100644 src/Common/PCSCException.h create mode 100644 src/Common/ResponseAPDU.cpp create mode 100644 src/Common/ResponseAPDU.h create mode 100644 src/Common/SCard.cpp create mode 100644 src/Common/SCard.h create mode 100644 src/Common/SCardLoader.cpp create mode 100644 src/Common/SCardLoader.h create mode 100644 src/Common/SCardManager.cpp create mode 100644 src/Common/SCardManager.h create mode 100644 src/Common/SCardReader.cpp create mode 100644 src/Common/SCardReader.h create mode 100644 src/Common/reader.h diff --git a/src/Common/CommandAPDU.cpp b/src/Common/CommandAPDU.cpp new file mode 100644 index 00000000..b202cb13 --- /dev/null +++ b/src/Common/CommandAPDU.cpp @@ -0,0 +1,366 @@ +#include "CommandAPDU.h" +#include + +using namespace std; + +namespace VeraCrypt +{ + CommandAPDU::CommandAPDU() + : m_nc(0), m_ne(0), m_dataOffset(0), m_isExtendedAPDU(false), m_parsingErrorStr(""), m_parsedSuccessfully(false) + { + } + + void CommandAPDU::parse() + { + uint32 l1 = 0; + uint32 l2 = 0; + size_t leOfs = 0; + uint32 l3 = 0; + m_parsingErrorStr = ""; + m_parsedSuccessfully = false; + + if (m_apdu.size() < 4) + { + m_parsingErrorStr = vformat("APDU must be at least 4 bytes long - Length = %zu", m_apdu.size()); + goto failure; + } + + if (m_apdu.size() == 4) + { + // case 1 + goto success; + } + + /*** SHORT APDUs ***/ + l1 = m_apdu[4] & 0xff; + if (m_apdu.size() == 5) + { + // case 2s + m_ne = (l1 == 0) ? 256 : l1; + goto success; + } + if (l1 != 0) + { + if (m_apdu.size() == 4 + 1 + l1) + { + // case 3s + m_nc = l1; + m_dataOffset = 5; + goto success; + } + else if (m_apdu.size() == 4 + 2 + l1) + { + // case 4s + m_nc = l1; + m_dataOffset = 5; + l2 = m_apdu[m_apdu.size() - 1] & 0xff; + m_ne = (l2 == 0) ? 256 : l2; + goto success; + } + else + { + m_parsingErrorStr = vformat("Invalid APDU : b1 = %u, expected length to be %u or %u, got %zu", l1, 4 + 1 + l1, 4 + 2 + l1, m_apdu.size()); + goto failure; + } + } + + if (m_apdu.size() < 7) + { + m_parsingErrorStr = vformat("Invalid APDU : b1 = %u, expected length to be >= 7 , got %zu", l1, m_apdu.size()); + goto failure; + } + + /*** EXTENDED APDUs ***/ + l2 = ((m_apdu[5] & 0xff) << 8) | (m_apdu[6] & 0xff); + if (m_apdu.size() == 7) + { + // case 2e + m_ne = (l2 == 0) ? 65536 : l2; + m_isExtendedAPDU = true; + goto success; + } + if (l2 == 0) + { + m_parsingErrorStr = vformat("Invalid APDU: b1 = %u, b2||b3 = %u, length = %zu", l1, l2, m_apdu.size()); + goto failure; + } + if (m_apdu.size() == 4 + 3 + l2) + { + // case 3e + m_nc = l2; + m_dataOffset = 7; + m_isExtendedAPDU = true; + goto success; + } + if (m_apdu.size() == 4 + 5 + l2) + { + // case 4e + m_nc = l2; + m_dataOffset = 7; + leOfs = m_apdu.size() - 2; + l3 = ((m_apdu[leOfs] & 0xff) << 8) | (m_apdu[leOfs + 1] & 0xff); + m_ne = (l3 == 0) ? 65536 : l3; + m_isExtendedAPDU = true; + goto success; + } + else + { + m_parsingErrorStr = vformat("Invalid APDU : b1 = %u, b2||b3 = %u, expected length to be %u or %u, got %zu", l1, l2, 4 + 3 + l2, 4 + 5 + l2, m_apdu.size()); + goto failure; + } + + success: + m_parsedSuccessfully = true; + + failure: + clear(); + } + + void CommandAPDU::init(byte cla, byte ins, byte p1, byte p2, const byte* data, uint32 dataOffset, uint32 dataLength, uint32 ne) + { + m_nc = 0; + m_ne = 0; + m_dataOffset = 0; + m_isExtendedAPDU = false; + m_parsingErrorStr = ""; + m_parsedSuccessfully = false; + + if (dataLength > 65535) + { + m_parsingErrorStr = vformat("dataLength is too large (> 65535) - dataLength = %u", dataLength); + clear(); + return; + } + if (ne > 65536) + { + m_parsingErrorStr = vformat("ne is too large (> 65536) - ne = %u", ne); + clear(); + return; + } + + m_ne = ne; + m_nc = dataLength; + + if (dataLength == 0) + { + if (m_ne == 0) + { + // case 1 + m_apdu.resize(4, 0); + setHeader(cla, ins, p1, p2); + } + else + { + // case 2s or 2e + if (ne <= 256) + { + // case 2s + // 256 is encoded as 0x00 + byte len = (m_ne != 256) ? (byte)m_ne : 0; + m_apdu.resize(5, 0); + setHeader(cla, ins, p1, p2); + m_apdu[4] = len; + } + else + { + // case 2e + byte l1, l2; + // 65536 is encoded as 0x00 0x00 + if (m_ne == 65536) + { + l1 = 0; + l2 = 0; + } + else + { + l1 = (byte)(m_ne >> 8); + l2 = (byte)m_ne; + } + m_apdu.resize(7, 0); + setHeader(cla, ins, p1, p2); + m_apdu[5] = l1; + m_apdu[6] = l2; + m_isExtendedAPDU = true; + } + } + } + else + { + if (m_ne == 0) + { + // case 3s or 3e + if (dataLength <= 255) + { + // case 3s + m_apdu.resize(4 + 1 + dataLength, 0); + setHeader(cla, ins, p1, p2); + m_apdu[4] = (byte)dataLength; + m_dataOffset = 5; + memcpy(m_apdu.data() + 5, data + dataOffset, dataLength); + } + else + { + // case 3e + m_apdu.resize(4 + 3 + dataLength, 0); + setHeader(cla, ins, p1, p2); + m_apdu[4] = 0; + m_apdu[5] = (byte)(dataLength >> 8); + m_apdu[6] = (byte)dataLength; + m_dataOffset = 7; + memcpy(m_apdu.data() + 7, data + dataOffset, dataLength); + m_isExtendedAPDU = true; + } + } + else + { + // case 4s or 4e + if ((dataLength <= 255) && (m_ne <= 256)) + { + // case 4s + m_apdu.resize(4 + 2 + dataLength, 0); + setHeader(cla, ins, p1, p2); + m_apdu[4] = (byte)dataLength; + m_dataOffset = 5; + memcpy(m_apdu.data() + 5, data + dataOffset, dataLength); + m_apdu[m_apdu.size() - 1] = (m_ne != 256) ? (byte)m_ne : 0; + } + else + { + // case 4e + m_apdu.resize(4 + 5 + dataLength, 0); + setHeader(cla, ins, p1, p2); + m_apdu[4] = 0; + m_apdu[5] = (byte)(dataLength >> 8); + m_apdu[6] = (byte)dataLength; + m_dataOffset = 7; + memcpy(m_apdu.data() + 7, data + dataOffset, dataLength); + if (ne != 65536) + { + size_t leOfs = m_apdu.size() - 2; + m_apdu[leOfs] = (byte)(m_ne >> 8); + m_apdu[leOfs + 1] = (byte)m_ne; + } // else le == 65536: no need to fill in, encoded as 0 + m_isExtendedAPDU = true; + } + } + } + + m_parsedSuccessfully = true; + } + + void CommandAPDU::setHeader(byte cla, byte ins, byte p1, byte p2) + { + m_apdu[0] = (byte)cla; + m_apdu[1] = (byte)ins; + m_apdu[2] = (byte)p1; + m_apdu[3] = (byte)p2; + } + + void CommandAPDU::clear() + { + m_apdu.clear(); + m_nc = 0; + m_ne = 0; + m_dataOffset = 0; + } + + CommandAPDU::CommandAPDU(byte cla, byte ins, byte p1, byte p2, const byte* data, uint32 dataOffset, uint32 dataLength, uint32 ne) + { + init(cla, ins, p1, p2, data, dataOffset, dataLength, ne); + } + + CommandAPDU::CommandAPDU(byte cla, byte ins, byte p1, byte p2) + { + init(cla, ins, p1, p2, NULL, 0, 0, 0); + } + + CommandAPDU::CommandAPDU(byte cla, byte ins, byte p1, byte p2, uint32 ne) + { + init(cla, ins, p1, p2, NULL, 0, 0, ne); + } + + CommandAPDU::CommandAPDU(byte cla, byte ins, byte p1, byte p2, const vector& data) + { + init(cla, ins, p1, p2, data.data(), 0, (uint32)data.size(), 0); + } + + CommandAPDU::CommandAPDU(byte cla, byte ins, byte p1, byte p2, const byte* data, uint32 dataOffset, uint32 dataLength) + { + init(cla, ins, p1, p2, data, dataOffset, dataLength, 0); + } + + CommandAPDU::CommandAPDU(byte cla, byte ins, byte p1, byte p2, const vector& data, uint32 ne) + { + init(cla, ins, p1, p2, data.data(), 0, (uint32)data.size(), ne); + } + + CommandAPDU::CommandAPDU(const vector& apdu) : m_nc(0), m_ne(0), m_dataOffset(0), m_isExtendedAPDU(false) + { + m_apdu = apdu; + parse(); + } + + byte CommandAPDU::getCLA() + { + return m_apdu[0] & 0xff; + } + + byte CommandAPDU::getINS() + { + return m_apdu[1] & 0xff; + } + + byte CommandAPDU::getP1() + { + return m_apdu[2] & 0xff; + } + + byte CommandAPDU::getP2() + { + return m_apdu[3] & 0xff; + } + + uint32 CommandAPDU::getNc() + { + return m_nc; + } + + const vector CommandAPDU::getData() + { + vector data; + + if (m_nc > 0) + { + data.resize(m_nc, 0); + memcpy(data.data(), m_apdu.data() + m_dataOffset, data.size()); + } + + return data; + } + + uint32 CommandAPDU::getNe() + { + return m_ne; + } + + const vector CommandAPDU::getAPDU() + { + return m_apdu; + } + + bool CommandAPDU::isExtended() + { + return m_isExtendedAPDU; + } + + bool CommandAPDU::isValid() + { + return m_parsedSuccessfully; + } + + std::string CommandAPDU::getErrorStr() + { + return m_parsingErrorStr; + } +} + diff --git a/src/Common/CommandAPDU.h b/src/Common/CommandAPDU.h new file mode 100644 index 00000000..98825faa --- /dev/null +++ b/src/Common/CommandAPDU.h @@ -0,0 +1,93 @@ +#ifndef TC_HEADER_Common_CommandAPDU +#define TC_HEADER_Common_CommandAPDU + +#include "Platform/PlatformBase.h" +#include + +namespace VeraCrypt +{ + inline const std::string vformat(const char* zcFormat, ...) + { + if (zcFormat) + { + va_list vaArgs; + va_start(vaArgs, zcFormat); + + const int iLen = vsnprintf(NULL, 0, zcFormat, vaArgs); + va_end(vaArgs); + + if (iLen) + { + std::vector zc((size_t)iLen + 1); + va_start(vaArgs, zcFormat); + vsnprintf(zc.data(), zc.size(), zcFormat, vaArgs); + va_end(vaArgs); + + return std::string(zc.data(), iLen); + } + } + + return ""; + } + + class CommandAPDU + { + protected: + + vector m_apdu; + uint32 m_nc; + uint32 m_ne; + uint32 m_dataOffset; + bool m_isExtendedAPDU; + std::string m_parsingErrorStr; + bool m_parsedSuccessfully; + + void parse(); + void init(byte cla, byte ins, byte p1, byte p2, const byte* data, uint32 dataOffset, uint32 dataLength, uint32 ne); + void setHeader(byte cla, byte ins, byte p1, byte p2); + + public: + + void clear(); + + CommandAPDU(); + + CommandAPDU(byte cla, byte ins, byte p1, byte p2, const byte* data, uint32 dataOffset, uint32 dataLength, uint32 ne); + + CommandAPDU(byte cla, byte ins, byte p1, byte p2); + + CommandAPDU(byte cla, byte ins, byte p1, byte p2, uint32 ne); + + CommandAPDU(byte cla, byte ins, byte p1, byte p2, const vector& data); + + CommandAPDU(byte cla, byte ins, byte p1, byte p2, const byte* data, uint32 dataOffset, uint32 dataLength); + + CommandAPDU(byte cla, byte ins, byte p1, byte p2, const vector& data, uint32 ne); + + CommandAPDU(const vector& apdu); + + byte getCLA(); + + byte getINS(); + + byte getP1(); + + byte getP2(); + + uint32 getNc(); + + const vector getData(); + + uint32 getNe(); + + const vector getAPDU(); + + bool isValid(); + + std::string getErrorStr(); + + bool isExtended(); + }; +}; + +#endif // TC_HEADER_Common_CommandAPDU \ No newline at end of file diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index dfcc3d03..6933eb71 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -207,7 +207,7 @@ BOOL LastMountedVolumeDirty; BOOL MountVolumesAsSystemFavorite = FALSE; BOOL FavoriteMountOnArrivalInProgress = FALSE; BOOL MultipleMountOperationInProgress = FALSE; -BOOL ActivateEMVOption = FALSE; +BOOL EMVSupportEnabled = FALSE; volatile BOOL NeedPeriodicDeviceListUpdate = FALSE; BOOL DisablePeriodicDeviceListUpdate = FALSE; @@ -12373,7 +12373,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam WaitCursor(); finally_do ({ NormalCursor(); }); - keyfiles = Token::GetAvailableKeyfiles(ActivateEMVOption); + keyfiles = Token::GetAvailableKeyfiles(EMVSupportEnabled); } catch (UserAbort&) { @@ -12415,10 +12415,14 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam { BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); BOOL deletable = selected; + // Multiple key files can be selected. + // Therefore, if one of them is not deletable, it means the delete button must be disabled for all. foreach (const shared_ptr &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) { - if( ! keyfile->Token->isEditable()){ + if (!keyfile->Token->isEditable()) + { deletable = false; + break; } } EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); @@ -12469,7 +12473,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam SecurityToken::CreateKeyfile (newParams.SlotId, keyfileDataVector, newParams.Name); - keyfiles = Token::GetAvailableKeyfiles(ActivateEMVOption); + keyfiles = Token::GetAvailableKeyfiles(EMVSupportEnabled); SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); } catch (Exception &e) @@ -12551,7 +12555,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam SecurityToken::DeleteKeyfile (dynamic_cast(*keyfile.get())); } - keyfiles = Token::GetAvailableKeyfiles(ActivateEMVOption); + keyfiles = Token::GetAvailableKeyfiles(EMVSupportEnabled); SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); } catch (Exception &e) diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h index 2004eb2a..7f7efb0f 100644 --- a/src/Common/Dlgcode.h +++ b/src/Common/Dlgcode.h @@ -166,7 +166,7 @@ extern BOOL LastMountedVolumeDirty; extern BOOL MountVolumesAsSystemFavorite; extern BOOL FavoriteMountOnArrivalInProgress; extern BOOL MultipleMountOperationInProgress; -extern BOOL ActivateEMVOption; +extern BOOL EMVSupportEnabled; extern volatile BOOL NeedPeriodicDeviceListUpdate; extern BOOL DisablePeriodicDeviceListUpdate; diff --git a/src/Common/EMVCard.cpp b/src/Common/EMVCard.cpp new file mode 100644 index 00000000..72c0952b --- /dev/null +++ b/src/Common/EMVCard.cpp @@ -0,0 +1,523 @@ +#include "EMVCard.h" +#include "TLVParser.h" +#include "SCardReader.h" +#include "PCSCException.h" + +#include "Platform/Finally.h" +#include "Platform/ForEach.h" +#include +#include +#include + +#if !defined(TC_WINDOWS) || defined(TC_PROTOTYPE) +#include "Platform/SerializerFactory.h" +#include "Platform/StringConverter.h" +#include "Platform/SystemException.h" +#else +#include "Dictionary.h" +#include "Language.h" +#endif + +using namespace std; + +namespace VeraCrypt +{ +#ifndef TC_WINDOWS + wstring ArrayToHexWideString(const unsigned char * pbData, size_t cbData) + { + static wchar_t* hexChar = L"0123456789ABCDEF"; + wstring result; + if (pbData) + { + for (int i = 0; i < cbData; i++) + { + result += hexChar[pbData[i] >> 4]; + result += hexChar[pbData[i] & 0x0F]; + } + } + + return result; + } +#endif + + map> InitializeSupportedAIDs() + { + map> supportedAIDs; + supportedAIDs.insert(std::make_pair(EMVCardType::AMEX, vector(EMVCard::AMEX_AID, EMVCard::AMEX_AID + (std::end(EMVCard::AMEX_AID) - std::begin(EMVCard::AMEX_AID))))); + supportedAIDs.insert(std::make_pair(EMVCardType::MASTERCARD, vector(EMVCard::MASTERCARD_AID, EMVCard::MASTERCARD_AID + (std::end(EMVCard::MASTERCARD_AID) - std::begin(EMVCard::MASTERCARD_AID))))); + supportedAIDs.insert(std::make_pair(EMVCardType::VISA, vector(EMVCard::VISA_AID, EMVCard::VISA_AID + (std::end(EMVCard::VISA_AID) - std::begin(EMVCard::VISA_AID))))); + return supportedAIDs; + } + + const byte EMVCard::AMEX_AID[7] = {0xA0, 0x00, 0x00, 0x00, 0x00, 0x25, 0x10}; + const byte EMVCard::MASTERCARD_AID[7] = {0xA0, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10}; + const byte EMVCard::VISA_AID[7] = {0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10}; + const map> EMVCard::SUPPORTED_AIDS = InitializeSupportedAIDs(); + + EMVCard::EMVCard() : SCard(), m_lastPANDigits(L"") + { + } + + EMVCard::EMVCard(size_t slotId) : SCard(slotId), m_lastPANDigits(L"") + { + } + + EMVCard::~EMVCard() + { + Clear(); + } + + EMVCard::EMVCard(const EMVCard& other) : + SCard(other), + m_aid(other.m_aid), + m_supportedAids(other.m_supportedAids), + m_iccCert(other.m_iccCert), + m_issuerCert(other.m_issuerCert), + m_cplcData(other.m_cplcData), + m_lastPANDigits(other.m_lastPANDigits) + { + } + + EMVCard::EMVCard(EMVCard&& other) : + SCard(other), + m_aid(std::move(other.m_aid)), + m_supportedAids(std::move(other.m_supportedAids)), + m_iccCert(std::move(other.m_iccCert)), + m_issuerCert(std::move(other.m_issuerCert)), + m_cplcData(std::move(other.m_cplcData)), + m_lastPANDigits(std::move(other.m_lastPANDigits)) + { + } + + EMVCard& EMVCard::operator = (const EMVCard& other) + { + if (this != &other) + { + SCard::operator=(other); + m_aid = other.m_aid; + m_supportedAids = other.m_supportedAids; + m_iccCert = other.m_iccCert; + m_issuerCert = other.m_issuerCert; + m_cplcData = other.m_cplcData; + m_lastPANDigits = other.m_lastPANDigits; + } + return *this; + } + + EMVCard& EMVCard::operator = (EMVCard&& other) + { + if (this != &other) + { + SCard::operator=(other); + m_reader = std::move(other.m_reader); + m_aid = std::move(other.m_aid); + m_supportedAids = std::move(other.m_supportedAids); + m_iccCert = std::move(other.m_iccCert); + m_issuerCert = std::move(other.m_issuerCert); + m_cplcData = std::move(other.m_cplcData); + m_lastPANDigits = std::move(other.m_lastPANDigits); + } + return *this; + } + + void EMVCard::Clear(void) + { + m_aid.clear(); + m_supportedAids.clear(); + m_iccCert.clear(); + m_issuerCert.clear(); + m_cplcData.clear(); + m_lastPANDigits.clear(); + } + + vector EMVCard::GetCardAID(bool forceContactless) + { + vector> supportedAIDs; + vector supportedAIDsPriorities; + vector>> supportedAIDsSorted; + bool hasBeenReset = false; + CommandAPDU command; + ResponseAPDU response; + vector responseData; + shared_ptr rootNode; + shared_ptr fciNode; + shared_ptr dfNameNode; + shared_ptr sfiNode; + shared_ptr fciIssuerNode; + shared_ptr fciIssuerDiscretionaryDataNode; + shared_ptr templateNode; + vector> pseDirectoryNodes; + unsigned char sfi; + bool usingContactless = false; + vector tokenAID; + + if (m_aid.size()) + return m_aid; + + if (m_reader) + { + if (m_reader->IsCardPresent()) + { + m_reader->Connect(SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, hasBeenReset, true); + m_reader->BeginTransaction(); + finally_do_arg (shared_ptr, m_reader, { finally_arg->EndTransaction(); }); + + try + { + for (auto it = EMVCard::SUPPORTED_AIDS.begin(); it != EMVCard::SUPPORTED_AIDS.end(); it++) + { + command = CommandAPDU(CLA_ISO7816, INS_SELECT_FILE, 0x04, 0x00, it->second, SCardReader::shortAPDUMaxTransSize); + m_reader->ApduProcessData(command, response); + if (response.getSW() == SW_NO_ERROR) + { + tokenAID = it->second; + break; + } + } + + if (tokenAID.size()) + { + m_supportedAids.push_back(tokenAID); + m_aid = tokenAID; + } + else + { + // The following code retrieves the supported AIDs from the card using PSE. + // If the card supports more than one AID, the returned list is sorted using the AIDs priorities, + // the first AID being the one with more priority. + if (forceContactless) + { + usingContactless = true; + command = CommandAPDU(CLA_ISO7816, INS_SELECT_FILE, 0x04, 0x00, EMV_PSE2, 0, sizeof(EMV_PSE2), SCardReader::shortAPDUMaxTransSize); + m_reader->ApduProcessData(command, response); + } + else + { + command = CommandAPDU(CLA_ISO7816, INS_SELECT_FILE, 0x04, 0x00, EMV_PSE1, 0, sizeof(EMV_PSE1), SCardReader::shortAPDUMaxTransSize); + m_reader->ApduProcessData(command, response); + if (response.getSW() != SW_NO_ERROR) + { + // EMV_PSE2 not found, try EMV_PSE1 + usingContactless = true; + command = CommandAPDU(CLA_ISO7816, INS_SELECT_FILE, 0x04, 0x00, EMV_PSE2, 0, sizeof(EMV_PSE2), SCardReader::shortAPDUMaxTransSize); + m_reader->ApduProcessData(command, response); + } + } + if (response.getSW() == SW_NO_ERROR && response.getData().size() > 0) + { + responseData = response.getData(); + rootNode = TLVParser::TLV_Parse(responseData.data(), responseData.size()); + fciNode = TLVParser::TLV_Find(rootNode, EMV_FCI_TAG); + if (fciNode && fciNode->Subs->size() >= 2) + { + if (usingContactless) + { + fciIssuerNode = TLVParser::TLV_Find(fciNode, EMV_FCI_ISSUER_TAG); + if (fciIssuerNode && fciIssuerNode->Subs->size() >= 1) + { + fciIssuerDiscretionaryDataNode = TLVParser::TLV_Find(fciIssuerNode, EMV_FCI_ISSUER_DISCRETIONARY_DATA_TAG); + if (fciIssuerDiscretionaryDataNode && fciIssuerDiscretionaryDataNode->Subs->size() >= 1) + { + for (size_t i = 0; i < fciIssuerDiscretionaryDataNode->Subs->size(); i++) + { + if (fciIssuerDiscretionaryDataNode->Subs->at(i)->Tag == EMV_DIRECTORY_ENTRY_TAG) + { + pseDirectoryNodes.push_back(fciIssuerDiscretionaryDataNode->Subs->at(i)); + } + } + } + } + } + else + { + dfNameNode = TLVParser::TLV_Find(fciNode, EMV_DFNAME_TAG); + if (dfNameNode) + { + fciIssuerNode = TLVParser::TLV_Find(fciNode, EMV_FCI_ISSUER_TAG); + if (fciIssuerNode) + { + sfiNode = TLVParser::TLV_Find(fciIssuerNode, EMV_SFI_TAG); + if (sfiNode && sfiNode->Value->size() == 1) + { + sfi = sfiNode->Value->at(0); + + byte rec = 1; + do + { + 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) + { + responseData = response.getData(); + + try + { + templateNode = TLVParser::TLV_Parse(responseData.data(), responseData.size()); + if (templateNode && templateNode->Tag == EMV_TEMPLATE_TAG && templateNode->Subs->size() >= 1) + { + for (size_t i = 0; i < templateNode->Subs->size(); i++) + { + if (templateNode->Subs->at(i)->Tag == EMV_DIRECTORY_ENTRY_TAG) + { + pseDirectoryNodes.push_back(templateNode->Subs->at(i)); + } + } + } + } + catch(TLVException) + { + continue; + } + } + } while (response.getData().size() > 0); + } + } + } + } + } + } + + for (size_t i = 0; i < pseDirectoryNodes.size(); i++) + { + shared_ptr aidNode; + shared_ptr aidPriorityNode; + aidNode = TLVParser::TLV_Find(pseDirectoryNodes[i], EMV_AID_TAG); + aidPriorityNode = TLVParser::TLV_Find(pseDirectoryNodes[i], EMV_PRIORITY_TAG); + if (aidNode && aidNode->Value->size() > 0 && aidPriorityNode && aidPriorityNode->Value->size() == 1) + { + supportedAIDs.push_back(*aidNode->Value.get()); + supportedAIDsPriorities.push_back(aidNode->Value->at(0)); + } + } + for(size_t i = 0; i < supportedAIDs.size(); i++) + { + supportedAIDsSorted.push_back(make_pair(supportedAIDsPriorities[i], supportedAIDs[i])); + } + std::sort(supportedAIDsSorted.begin(), supportedAIDsSorted.end()); + for(size_t i = 0; i < supportedAIDs.size(); i++) + { + supportedAIDs[i] = supportedAIDsSorted[i].second; + } + + if (supportedAIDs.size()) + { + m_supportedAids = supportedAIDs; + tokenAID = supportedAIDs[0]; + m_aid = tokenAID; + } + } + } + catch (...) + { + } + } + } + + return tokenAID; + } + + void EMVCard::GetCardContent(vector& iccCert, vector& issuerCert, vector& cplcData) + { + bool hasBeenReset = false; + bool aidSelected = false; + bool iccFound = false; + bool issuerFound = false; + bool cplcFound = false; + vector emvCardAid; + shared_ptr rootNode; + shared_ptr iccPublicKeyCertNode; + shared_ptr issuerPublicKeyCertNode; + CommandAPDU command; + ResponseAPDU response; + vector responseData; + + iccCert.clear(); + issuerCert.clear(); + cplcData.clear(); + + if (m_iccCert.size() && m_issuerCert.size() && m_cplcData.size()) + { + iccCert = m_iccCert; + issuerCert = m_issuerCert; + cplcData = m_cplcData; + return; + } + + emvCardAid = GetCardAID(); + if (emvCardAid.size() == 0) + { + throw EMVUnknownCardType(); + } + + if (m_reader) + { + if (m_reader->IsCardPresent()) + { + m_reader->Connect(SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, hasBeenReset, true); + m_reader->BeginTransaction(); + finally_do_arg (shared_ptr, m_reader, { finally_arg->EndTransaction(); }); + + // First get CPLC before selecting the AID of the card. + command = CommandAPDU(0x80, INS_GET_DATA, (EMV_CPLC_TAG >> 8) & 0xFF, EMV_CPLC_TAG & 0xFF, SCardReader::shortAPDUMaxTransSize); + m_reader->ApduProcessData(command, response); + if (response.getSW() == SW_NO_ERROR && response.getData().size() > 0) + { + cplcFound = true; + cplcData = response.getData(); + + // Then get the certs. + command = CommandAPDU(CLA_ISO7816, INS_SELECT_FILE, 0x04, 0x00, emvCardAid, SCardReader::shortAPDUMaxTransSize); + m_reader->ApduProcessData(command, response); + if (response.getSW() == SW_NO_ERROR) + { + aidSelected = true; + + // TODO: Send GET PROCESSING OPTIONS to get the AIL and AFL, + // which will then be used to get the actual start and end of sfi and rec. + for (byte sfi = 1; sfi < 32 && (!iccFound || !issuerFound); sfi++) + { + for (byte rec = 1; rec < 17 && (!iccFound || !issuerFound); rec++) + { + 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) + { + responseData = response.getData(); + + try + { + rootNode = TLVParser::TLV_Parse(responseData.data(), responseData.size()); + } + catch(TLVException) + { + continue; + } + + iccPublicKeyCertNode = TLVParser::TLV_Find(rootNode, EMV_ICC_PK_CERT_TAG); + if (iccPublicKeyCertNode && iccPublicKeyCertNode->Value->size() > 0) + { + iccFound = true; + iccCert = *iccPublicKeyCertNode->Value.get(); + } + + issuerPublicKeyCertNode = TLVParser::TLV_Find(rootNode, EMV_ISS_PK_CERT_TAG); + if (issuerPublicKeyCertNode && issuerPublicKeyCertNode->Value->size() > 0) + { + issuerFound = true; + issuerCert = *issuerPublicKeyCertNode->Value.get(); + } + } + } + } + } + } + } + } + + if (!cplcFound) + throw EMVCPLCNotFound(); + + if (!aidSelected) + throw EMVSelectAIDFailed(); + + if (!iccFound) + throw EMVIccCertNotFound(); + + if (!issuerFound) + throw EMVIssuerCertNotFound(); + + m_iccCert = iccCert; + m_issuerCert = issuerCert; + m_cplcData = cplcData; + } + + void EMVCard::GetCardPAN(wstring& lastPANDigits) + { + bool hasBeenReset = false; + bool panFound = false; + bool aidSelected = false; + vector EMVCardAid; + vector panData; + shared_ptr rootNode; + shared_ptr panNode; + CommandAPDU command; + ResponseAPDU response; + vector responseData; + + lastPANDigits = L""; + + if (m_lastPANDigits != L"") + { + lastPANDigits = m_lastPANDigits; + return; + } + + EMVCardAid = GetCardAID(); + if (EMVCardAid.size() == 0) + { + throw EMVUnknownCardType(); + } + + if (m_reader) + { + if (m_reader->IsCardPresent()) + { + m_reader->Connect(SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, hasBeenReset, true); + m_reader->BeginTransaction(); + finally_do_arg (shared_ptr, m_reader, { finally_arg->EndTransaction(); }); + + command = CommandAPDU(CLA_ISO7816, INS_SELECT_FILE, 0x04, 0x00, EMVCardAid, SCardReader::shortAPDUMaxTransSize); + m_reader->ApduProcessData(command, response); + if (response.getSW() == SW_NO_ERROR) + { + aidSelected = true; + + // TODO: Send GET PROCESSING OPTIONS to get the AIL and AFL, + // which will then be used to get the actual start and end of sfi and rec. + for (byte sfi = 1; sfi < 32 && !panFound; sfi++) + { + for (byte rec = 1; rec < 17 && !panFound; rec++) + { + 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) + { + responseData = response.getData(); + + try + { + rootNode = TLVParser::TLV_Parse(responseData.data(), responseData.size()); + } + catch(TLVException) + { + continue; + } + + panNode = TLVParser::TLV_Find(rootNode, EMV_PAN_TAG); + if (panNode && panNode->Value->size() >= 8) + { + panFound = true; + panData = *panNode->Value.get(); + panData = vector(panData.rbegin(), panData.rbegin() + 2); // only interested in last digits + std::swap(panData[0], panData[1]); + lastPANDigits = ArrayToHexWideString(panData.data(), panData.size()); + } + } + } + } + } + } + } + + if (panData.size()) + burn(panData.data(), panData.size()); + + if (!aidSelected) + throw EMVSelectAIDFailed(); + + if (!panFound) + throw EMVPANNotFound(); + + m_lastPANDigits = lastPANDigits; + } +} diff --git a/src/Common/EMVCard.h b/src/Common/EMVCard.h new file mode 100644 index 00000000..116de705 --- /dev/null +++ b/src/Common/EMVCard.h @@ -0,0 +1,69 @@ +#ifndef TC_HEADER_Common_EMVCard +#define TC_HEADER_Common_EMVCard + +#include "Platform/PlatformBase.h" +#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) +# include "Exception.h" +#else +# include "Platform/Exception.h" +#endif + +#include "Token.h" +#include "SCard.h" + +namespace VeraCrypt +{ + typedef enum EMVCardType + { + NONE = 0, + AMEX, + MASTERCARD, + VISA + } EMVCardType; + + class EMVCard : public SCard + { + protected: + + // The following fields will only be empty if the card has not been read yet. + // After the card has been read, and if some or all fields cannot be read, the EMVCard + // object will be considered invalid and will not be included in the list of available cards + // of EMVToken. + vector m_aid; + vector> m_supportedAids; + vector m_iccCert; + vector m_issuerCert; + vector m_cplcData; + wstring m_lastPANDigits; + + public: + + // Add other AIDS + // https://gist.github.com/pvieito/6224eed92c99b069f6401996c548d0e4 + // https://ambimat.com/developer-resources/list-of-application-identifiers-aid/ + const static byte AMEX_AID[7]; + const static byte MASTERCARD_AID[7]; + const static byte VISA_AID[7]; + const static map> SUPPORTED_AIDS; + + EMVCard(); + EMVCard(size_t slotId); + EMVCard(const EMVCard& other); + EMVCard(EMVCard&& other); + EMVCard& operator = (const EMVCard& other); + EMVCard& operator = (EMVCard&& other); + virtual ~EMVCard(); + + void Clear(void); + + // Retrieves the card's AID. + // It first checks the card against a list of supported AIDs. + // If that fails, it tries getting the AID from the card using PSE + vector GetCardAID(bool forceContactless = false); + + void GetCardContent(vector& iccCert, vector& issuerCert, vector& cplcData); + void GetCardPAN(wstring& lastPANDigits); + }; +} + +#endif // TC_HEADER_Common_EMVCard diff --git a/src/Common/EMVToken.cpp b/src/Common/EMVToken.cpp index aac59a6a..0fe3dc1f 100644 --- a/src/Common/EMVToken.cpp +++ b/src/Common/EMVToken.cpp @@ -1,11 +1,13 @@ #include "EMVToken.h" +#include "TLVParser.h" +#include "SCardReader.h" +#include "PCSCException.h" #include "Platform/Finally.h" #include "Platform/ForEach.h" #include #include - - +#include #if !defined(TC_WINDOWS) || defined(TC_PROTOTYPE) #include "Platform/SerializerFactory.h" @@ -16,29 +18,52 @@ #include "Language.h" #endif - using namespace std; namespace VeraCrypt { + void AppendData(vector& buffer, const unsigned char* pbData, size_t cbData, size_t from, size_t length, bool bEncodeLength = false) + { + if (cbData > 0 && from <= cbData - 2 && length > 0 && length <= cbData - from) + { + size_t offset = (bEncodeLength ? 4 : 0); + size_t orgSize = buffer.size(); + buffer.resize(orgSize + length + offset); + if (bEncodeLength) + { + unsigned int dwLength = (unsigned int)(length); + memcpy(buffer.data() + orgSize, &dwLength, 4); + } + memcpy(buffer.data() + orgSize + offset, pbData + from, length); + } + } - IccDataExtractor EMVToken::extractor; + /* ****************************************************************************************************************************************** */ + + map > EMVToken::EMVCards; EMVTokenInfo::~EMVTokenInfo() { - burn(&Label,Label.size()); + if (Label.size() > 0) + burn(&Label[0], Label.size() * sizeof(wchar_t)); + } + + EMVTokenKeyfile::EMVTokenKeyfile() + { + Id = EMV_CARDS_LABEL; + Token = shared_ptr(new EMVTokenInfo()); } EMVTokenKeyfile::EMVTokenKeyfile(const TokenKeyfilePath& path) { - Id = EMV_CARDS_LABEL; - Token = shared_ptr(new EMVTokenInfo()); wstring pathStr = path; unsigned long slotId; if (swscanf(pathStr.c_str(), TC_EMV_TOKEN_KEYFILE_URL_PREFIX TC_EMV_TOKEN_KEYFILE_URL_SLOT L"/%lu", &slotId) != 1) throw InvalidEMVPath(); + Id = EMV_CARDS_LABEL; + Token = shared_ptr(new EMVTokenInfo()); Token->SlotId = slotId; } @@ -51,12 +76,46 @@ namespace VeraCrypt void EMVTokenKeyfile::GetKeyfileData(vector & keyfileData) const { - #ifdef TC_WINDOWS - EMVToken::extractor.InitLibrary(); - #endif + map >::iterator emvCardsIt; + shared_ptr card; + vector iccCert; + vector issuerCert; + vector cplcData; + bool addNewCard = true; - EMVToken::extractor.GetReaders(); - EMVToken::extractor.GettingAllCerts(Token->SlotId, keyfileData); + keyfileData.clear(); + + emvCardsIt = EMVToken::EMVCards.find(Token->SlotId); + if (emvCardsIt != EMVToken::EMVCards.end()) + { + // An EMVCard object has already been created for this slotId. + // We check that it's SCard handle is still valid. + // If it is, we use the existing EMVCard to get the card's content. + // If it is not, we remove the EMVCard from EMVCards and create a new one. + + if (emvCardsIt->second->IsCardHandleValid()) + { + emvCardsIt->second->GetCardContent(iccCert, issuerCert, cplcData); + addNewCard = false; + } + else + { + EMVToken::EMVCards.erase(emvCardsIt); + } + } + + if (addNewCard) + { + // An EMVCard object does not exist for this slotId, or exists but its handle is not valid anymore. + // We create a new one and then add it to EMVCards. + card = make_shared(Token->SlotId); + card->GetCardContent(iccCert, issuerCert, cplcData); + EMVToken::EMVCards.insert(make_pair(Token->SlotId, card)); + } + + AppendData(keyfileData, iccCert.data(), iccCert.size(), 0, iccCert.size()); + AppendData(keyfileData, issuerCert.data(), issuerCert.size(), 0, issuerCert.size()); + AppendData(keyfileData, cplcData.data(), cplcData.size(), 0, cplcData.size()); } bool EMVToken::IsKeyfilePathValid(const wstring& emvTokenKeyfilePath) @@ -64,36 +123,52 @@ namespace VeraCrypt return emvTokenKeyfilePath.find(TC_EMV_TOKEN_KEYFILE_URL_PREFIX) == 0; } - vector EMVToken::GetAvailableKeyfiles(unsigned long int* slotIdFilter, const wstring keyfileIdFilter) { - #ifdef TC_WINDOWS - EMVToken::extractor.InitLibrary(); - #endif - + vector EMVToken::GetAvailableKeyfiles(unsigned long int* slotIdFilter, const wstring& keyfileIdFilter) + { vector keyfiles; - unsigned long int nb = 0; + vector readers; - nb = EMVToken::extractor.GetReaders(); - - - for(unsigned long int slotId = 0; slotIdSlotId = slotId; keyfile.Token = shared_ptr(new EMVTokenInfo(token)); + keyfile.Token->SlotId = slotId; + + // keyfileIdFilter is of no use for EMV tokens as the Id is always set to EMV_CARDS_LABEL. + // Nonetheless, we keep the following code that is also used in SecurityToken::GetAvailableKeyfiles. + if (keyfile.Id.empty() || (!keyfileIdFilter.empty() && keyfileIdFilter != keyfile.Id)) + continue; keyfiles.push_back(keyfile); @@ -102,20 +177,49 @@ namespace VeraCrypt } return keyfiles; - } - - EMVTokenInfo EMVToken::GetTokenInfo(unsigned long int slotId) { + EMVTokenInfo EMVToken::GetTokenInfo(unsigned long int slotId) + { EMVTokenInfo token; + wstring lastPANDigits; + map >::iterator emvCardsIt; + shared_ptr card; + bool addNewCard = true; + + emvCardsIt = EMVCards.find(slotId); + if (emvCardsIt != EMVCards.end()) + { + // An EMVCard object has already been created for this slotId. + // We check that it's SCard handle is still valid. + // If it is, we use the existing EMVCard to get the card's PAN. + // If it is not, we remove the EMVCard from EMVCards and create a new one. + + if (emvCardsIt->second->IsCardHandleValid()) + { + emvCardsIt->second->GetCardPAN(lastPANDigits); + addNewCard = false; + } + else + { + EMVCards.erase(emvCardsIt); + } + } + + if (addNewCard) + { + // An EMVCard object does not exist for this slotId, or exists but its handle is not valid anymore. + // We create a new one and then add it to EMVCards. + card = make_shared(slotId); + card->GetCardPAN(lastPANDigits); + EMVCards.insert(make_pair(slotId, card)); + } + token.SlotId = slotId; - //card numbers extraction - std::string pan; - EMVToken::extractor.GettingPAN(slotId, pan); token.Label = L"EMV card **** "; - token.Label += wstring (pan.begin(), pan.end()); - burn(&pan[0],pan.size()); + token.Label += lastPANDigits; + burn(&lastPANDigits[0], lastPANDigits.size() * sizeof(wchar_t)); + return token; } - } diff --git a/src/Common/EMVToken.h b/src/Common/EMVToken.h index 1d84ec28..a1c0a2e1 100644 --- a/src/Common/EMVToken.h +++ b/src/Common/EMVToken.h @@ -6,44 +6,36 @@ #define EMV_CARDS_LABEL L"EMV Certificates" -#include "Platform/PlatformBase.h" -#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) -# include "Exception.h" -#else -# include "Platform/Exception.h" -#endif - -#include "Token.h" -#include "IccDataExtractor.h" - -namespace VeraCrypt { +#include "EMVCard.h" +namespace VeraCrypt +{ struct EMVTokenInfo: TokenInfo { virtual ~EMVTokenInfo(); - virtual BOOL isEditable() const {return false;} + virtual BOOL isEditable() const { return false; } }; struct EMVTokenKeyfile: TokenKeyfile { - EMVTokenKeyfile(){Id = EMV_CARDS_LABEL; Token = shared_ptr(new EMVTokenInfo());}; + EMVTokenKeyfile(); EMVTokenKeyfile(const TokenKeyfilePath& path); + virtual ~EMVTokenKeyfile() {}; virtual operator TokenKeyfilePath () const; virtual void GetKeyfileData(vector & keyfileData) const; - }; - class EMVToken { - private: - static IccDataExtractor extractor; + class EMVToken + { public: static bool IsKeyfilePathValid(const wstring& emvTokenKeyfilePath); - static vector GetAvailableKeyfiles(unsigned long int* slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring()); + static vector GetAvailableKeyfiles(unsigned long int* slotIdFilter = nullptr, const wstring& keyfileIdFilter = wstring()); static EMVTokenInfo GetTokenInfo(unsigned long int slotId); friend void EMVTokenKeyfile::GetKeyfileData(vector & keyfileData) const; + static map > EMVCards; }; } diff --git a/src/Common/IccDataExtractor.cpp b/src/Common/IccDataExtractor.cpp index d98bc360..e69de29b 100644 --- a/src/Common/IccDataExtractor.cpp +++ b/src/Common/IccDataExtractor.cpp @@ -1,777 +0,0 @@ -// -// Created by bshp on 1/14/23. -// - -#include "IccDataExtractor.h" - -#if !defined (TC_WINDOWS) || defined (TC_PROTOTYPE) -# include "Platform/SerializerFactory.h" -# include "Platform/StringConverter.h" -# include "Platform/SystemException.h" -#else -# include "Dictionary.h" -# include "Language.h" -#endif - -#include "Tcdefs.h" - -namespace VeraCrypt -{ - - - #ifdef TC_WINDOWS - bool VeraCrypt::IccDataExtractor::Initialized; - #endif - //using namespace std; - const BYTE IccDataExtractor::SELECT_MASTERCARD[] = {00, 0xA4, 0x04, 00, 0x07, 0xA0, 00, 00, 00, 0x04, 0x10, 0x10}; - const BYTE IccDataExtractor::SELECT_VISA[] = {00, 0xA4, 0x04, 00, 0x07, 0xA0, 00, 00, 00, 0x03, 0x10, 0x10}; - const BYTE IccDataExtractor::SELECT_AMEX[] = {00, 0xA4, 0x04, 00, 0x07, 0xA0, 00, 00, 00, 00, 0x25, 0x10}; - const BYTE * IccDataExtractor::SELECT_TYPES[]={SELECT_MASTERCARD, SELECT_VISA, SELECT_AMEX}; - - IccDataExtractor::IccDataExtractor(){} - - IccDataExtractor::~IccDataExtractor(){ - /* Disconnect card if connected */ - if(hCard){ - #ifdef TC_WINDOWS - WSCardDisconnect(hContext,hCard); - #else - SCardDisconnect(hContext,hCard); - #endif - } - /* Release memory that has been returned from the resource manager using the SCARD_AUTOALLOCATE length - * designator*/ - if (mszReaders){ - #ifdef TC_WINDOWS - WSCardFreeMemory(hContext, mszReaders); - #else - SCardFreeMemory(hContext, mszReaders); - #endif - } - - /* Closing the established resource manager context freeing any resources allocated under that context - * including SCARDHANDLE objects and memory allocated using the SCARD_AUTOALLOCATE length designator*/ - if(hContext){ - #ifdef TC_WINDOWS - WSCardReleaseContext(hContext); - #else - SCardReleaseContext(hContext); - #endif - } - - /* Freeing winscard library */ - #ifdef TC_WINDOWS - FreeLibrary(WinscardLibraryHandle); - #endif - } - - #ifdef TC_WINDOWS - void IccDataExtractor::InitLibrary(){ - - if(Initialized) return; - - /* Getting the System32 directory */ - char sysDir[MAX_PATH-20]; - GetSystemDirectoryA(sysDir, MAX_PATH); - - /* Getting the winscard dll path directory */ - char winscardPath[MAX_PATH]; - sprintf_s(winscardPath, "%s\\Winscard.dll", sysDir); - - /* Loading the winscard dll from System32 */ - WinscardLibraryHandle = LoadLibraryA(winscardPath); - throw_sys_if(!WinscardLibraryHandle); - - /* Fetching the functions pointers from the dll */ - WSCardEstablishContext = (SCardEstablishContextPtr) GetProcAddress(WinscardLibraryHandle,"SCardEstablishContext"); - if(!WSCardEstablishContext) throw WinscardLibraryNotInitialized(); - - WSCardReleaseContext= (SCardReleaseContextPtr) GetProcAddress(WinscardLibraryHandle,"SCardReleaseContext"); - if(!WSCardReleaseContext) throw WinscardLibraryNotInitialized(); - - WSCardConnectA = (SCardConnectAPtr) GetProcAddress(WinscardLibraryHandle,"SCardConnectA"); - if(!WSCardConnectA) throw WinscardLibraryNotInitialized(); - - WSCardDisconnect = (SCardDisconnectPtr) GetProcAddress(WinscardLibraryHandle,"SCardDisconnect"); - if(!WSCardDisconnect) throw WinscardLibraryNotInitialized(); - - WSCardFreeMemory = ( SCardFreeMemoryPtr) GetProcAddress(WinscardLibraryHandle,"SCardFreeMemory"); - if(!WSCardFreeMemory) throw WinscardLibraryNotInitialized(); - - WSCardListReadersA = (SCardListReadersAPtr) GetProcAddress(WinscardLibraryHandle,"SCardListReadersA"); - if(!WSCardListReadersA) throw WinscardLibraryNotInitialized(); - - WSCardTransmit = ( SCardTransmitPtr) GetProcAddress(WinscardLibraryHandle,"SCardTransmit"); - if(!WSCardTransmit) throw WinscardLibraryNotInitialized(); - - Initialized = true; - - } - #endif - - /* Establishing the resource manager context (the scope) within which database operations are performed. - * The module of the smart card subsystem that manages access to multiple readers and smart cards. The - * resource manager identifies and tracks resources, allocates readers and resources across multiple - * applications,and supports transaction primitives for accessing services available on a given card.*/ - int IccDataExtractor::EstablishRSContext(){ - - #ifdef TC_WINDOWS - LONG returnValue = WSCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); - #else - LONG returnValue = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); - #endif - - /* Check if the establishment of the context was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - return EXIT_SUCCESS; - } - - /* Detecting available readers and filling the reader table */ - unsigned long IccDataExtractor::GetReaders(){ - - #ifdef TC_WINDOWS - if(!Initialized) - throw WinscardLibraryNotInitialized(); - #endif - - EstablishRSContext(); - - /* Length of the mszReaders buffer in characters. If the buffer length is specified as - * SCARD_AUTOALLOCATE, then mszReaders is converted to a pointer to a byte pointer, and - * receives the address of a block of memory containing the multi-string structure */ - DWORD dwReaders = SCARD_AUTOALLOCATE; - - /* Retrieving the available readers list and putting it in mszReaders*/ // Use LPSTR on linux - #ifdef TC_WINDOWS - LONG returnValue = WSCardListReadersA(hContext, NULL, (LPSTR)&mszReaders, &dwReaders); - #else - LONG returnValue = SCardListReaders(hContext, NULL, (LPTSTR)&mszReaders, &dwReaders); - #endif - - /* If the is no readers, return */ - if(returnValue == SCARD_E_NO_READERS_AVAILABLE) return 0; - - /* Check if the listing of the connected readers was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - nbReaders = 0; - LPSTR ReaderPtr = mszReaders; - - /* Getting the total number of readers */ - while (*ReaderPtr != '\0') - { - readers.push_back(ReaderPtr); - ReaderPtr += strlen((char*)ReaderPtr) + 1; - nbReaders++; - } - - return nbReaders; - } - - /* Connecting to the card in the given reader*/ - int IccDataExtractor::ConnectCard(unsigned long int reader_nb){ - - /* Check if the given reader slot number is possible */ - if (reader_nb < 0 || reader_nb >= nbReaders) - throw InvalidEMVPath(); - - dwActiveProtocol = SCARD_PROTOCOL_UNDEFINED; - - #ifdef TC_WINDOWS - LONG returnValue = WSCardConnectA(hContext, readers[reader_nb], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); - #else - LONG returnValue = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); - #endif - - /* Check is the card connection was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - return EXIT_SUCCESS; - } - - /* Disconnect the card currently connected*/ - int IccDataExtractor::DisconnectCard(){ - #ifdef TC_WINDOWS - LONG returnValue = WSCardDisconnect(hCard, SCARD_UNPOWER_CARD); - #else - LONG returnValue = SCardDisconnect(hCard, SCARD_UNPOWER_CARD); - #endif - - /* Check is the card deconnection was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - return EXIT_SUCCESS; - } - - /* Testing if the card contains the application of the given EMV type (0:Mastercard, 1:Visa, 2:Amex) */ - bool IccDataExtractor::TestingCardType(const int SELECT_TYPE_NUMBER){ - - const BYTE * SELECTED_TYPE = SELECT_TYPES[SELECT_TYPE_NUMBER]; - - BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */ - - DWORD dwSendLength = SELECT_TYPE_SIZE; /* Set the size of the send buffer */ - DWORD dwRecvLength = sizeof(pbRecvBuffer); /* Set the size of the reception buffer */ - - /* Set up the io request */ - SCARD_IO_REQUEST ioRequest; - ioRequest.dwProtocol = dwActiveProtocol; - ioRequest.cbPciLength = sizeof(ioRequest); - - #ifdef TC_WINDOWS - LONG returnValue = WSCardTransmit(hCard, &ioRequest, SELECTED_TYPE, dwSendLength, NULL, pbRecvBuffer, &dwRecvLength); - #else - LONG returnValue = SCardTransmit(hCard, &ioRequest, SELECTED_TYPE, dwSendLength, NULL, pbRecvBuffer, &dwRecvLength); - #endif - - /* Check if the transmission was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - /* It received a response. Check if it didn't get a recognisable response */ - if (dwRecvLength < 2) - return false; - - /* Check if the command successfully executed (the card is the type passed in the parameter) */ - if (pbRecvBuffer[0] == 0x61) - return true; - - return false; - } - - /* Getting the ICC Public Key Certificates and the Issuer Public Key Certificates by parsing the application - * (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/ - void IccDataExtractor::GetCerts(vector &CERTS){ - - CERTS.clear(); - - bool iccFound= false; - bool issuerFound= false; - - shared_ptr node; - shared_ptr ICC_Public_Key_Certificate; - shared_ptr Issuer_PK_Certificate; - - BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */ - BYTE pbRecvBufferFat[256]; /* Bigger buffer to receive the card response */ - - DWORD dwSendLength; /* Size of the send buffer */ - DWORD dwRecvLength; /* Size of the reception buffer */ - - /* Set up the io request */ - SCARD_IO_REQUEST ioRequest; - ioRequest.dwProtocol = dwActiveProtocol; - ioRequest.cbPciLength = sizeof(ioRequest); - - LONG returnValue; - - /* Parsing root folders */ - for (int sfi = 0; sfi < 32; sfi++) - { - /* Parsing sub folders */ - for (int rec = 0; rec < 17; rec++) - { - BYTE SELECT_APDU_FILE[] = {00, 0xB2, static_cast(rec), static_cast((sfi << 3) | 4), 0x00}; - - dwSendLength = sizeof(SELECT_APDU_FILE); - dwRecvLength = sizeof(pbRecvBuffer); - - /* Check if there is data in the folder */ - #ifdef TC_WINDOWS - returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength); - #else - returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength); - #endif - - /* Check if the transmission was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - /* There is no data in the folder */ - if (pbRecvBuffer[0] != 0x6C) - continue; - - /* It set the proper expected length of the data in the APDU */ - SELECT_APDU_FILE[4] = pbRecvBuffer[1]; - - dwRecvLength = sizeof(pbRecvBufferFat); - - /* Get the data from the folder */ - #ifdef TC_WINDOWS - returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength, NULL, pbRecvBufferFat, &dwRecvLength); - #else - returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength, NULL, pbRecvBufferFat, &dwRecvLength); - #endif - - /* Check if the transmission was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - /* It received a response. Check if it didn't get a recognisable response */ - if (dwRecvLength < 2) - continue; - - /* Parsing the TLV */ - try{ - node = TLVParser::TLV_Parse(pbRecvBufferFat,sizeof(pbRecvBufferFat)); - }catch(TLVException){ - continue; - } - - /* Finding the ICC_Public_Key_Certificate */ - try{ - ICC_Public_Key_Certificate = TLVParser::TLV_Find(node, 0x9F46); - }catch(TLVException){ - continue; - } - if(ICC_Public_Key_Certificate) { - iccFound=true; - for (int i = 0; i < ICC_Public_Key_Certificate->Length;i++) { - CERTS.push_back(static_cast(ICC_Public_Key_Certificate->Value[i])); - } - } - - /* Finding the Issuer_Public_Key_Certificate */ - try{ - Issuer_PK_Certificate = TLVParser::TLV_Find(node, 0x90); - }catch(TLVException){ - continue; - } - - if(Issuer_PK_Certificate) { - issuerFound=true; - for (int i = 0; i < Issuer_PK_Certificate->Length;i++) { - CERTS.push_back(static_cast(Issuer_PK_Certificate->Value[i])); - } - } - - /* Limiting the search to at least one occurrence of both PKs to speed up the process. - * There might be more certificates tho */ - if(iccFound && issuerFound){ - burn(pbRecvBuffer, sizeof(pbRecvBuffer)); - burn(pbRecvBufferFat, sizeof(pbRecvBufferFat)); - return; - } - } - } - burn(pbRecvBuffer, sizeof(pbRecvBuffer)); - burn(pbRecvBufferFat, sizeof(pbRecvBufferFat)); - throw EMVKeyfileDataNotFound(); - } - - /* Getting CPCL data from the card*/ - void IccDataExtractor::GetCPCL(vector &v){ - - BYTE SELECT_APDU_CPCL[] = {0x80,0xCA, 0x9F, 0x7F, 0x00}; - - BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */ - BYTE pbRecvBufferFat[256]; /* Bigger buffer to receive the card response */ - - DWORD dwSendLength = sizeof (SELECT_APDU_CPCL); /* Set the size of the send buffer */ - DWORD dwRecvLength = sizeof(pbRecvBuffer); /* Set the size of the reception buffer */ - - /* Set up the io request */ - SCARD_IO_REQUEST ioRequest; - ioRequest.dwProtocol = dwActiveProtocol; - ioRequest.cbPciLength = sizeof(ioRequest); - - /* Check if there is the TAG for CPCL Data in the card */ - #ifdef TC_WINDOWS - LONG returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength, NULL, pbRecvBuffer, &dwRecvLength); - #else - LONG returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength, NULL, pbRecvBuffer, &dwRecvLength); - #endif - - /* Check if the transmission was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - /* Not the correct APDU response code */ - if (pbRecvBuffer[0] != 0x6C) - throw EMVKeyfileDataNotFound(); - - /* It set the proper expected length of the data in the APDU */ - SELECT_APDU_CPCL[4] = pbRecvBuffer[1]; - - dwRecvLength = sizeof(pbRecvBufferFat); - - /* Get the CPCL data */ - #ifdef TC_WINDOWS - returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength); - #else - returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength); - #endif - - /* Check if the transmission was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - /* It received a response. Check if it didn't get a recognisable response */ - if (dwRecvLength < 2) - throw EMVKeyfileDataNotFound(); - - /* We add CPCL data and crop the TAG and the data length at the start and the trailer at the end */ - for (unsigned long i = 3; i < dwRecvLength-2; i++) { - v.push_back(static_cast(pbRecvBufferFat[i])); - } - burn(pbRecvBuffer, sizeof(pbRecvBuffer)); - burn(pbRecvBufferFat, sizeof(pbRecvBufferFat)); - - } - - /* Getting an ICC Public Key Certificates and an Issuer Public Key Certificates for the first application with the cpcl - * data present on the card and finally merge it into one byte array */ - void IccDataExtractor::GettingAllCerts(int readerNumber, vector &v){ - - #ifdef TC_WINDOWS - if(!Initialized) - throw WinscardLibraryNotInitialized(); - #endif - - bool isEMV= false; - - ConnectCard(readerNumber); - - /* Test all the type of applications and get the certificates from the first one found */ - for(int i=0;i &v) { - - bool PANFound= false; - shared_ptr node; - shared_ptr PAN; - - BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */ - BYTE pbRecvBufferFat[256]; /* Bigger buffer to receive the card response */ - - DWORD dwSendLength; /* Size of the send buffer */ - DWORD dwRecvLength; /* Size of the reception buffer */ - - /* Set up the io request */ - SCARD_IO_REQUEST ioRequest; - ioRequest.dwProtocol = dwActiveProtocol; - ioRequest.cbPciLength = sizeof(ioRequest); - - LONG returnValue; - - /* Parsing root folders */ - for (int sfi = 0; sfi < 32; sfi++) - { - /* Parsing sub folders */ - for (int rec = 0; rec < 17; rec++) - { - BYTE SELECT_APDU_FILE[] = {00, 0xB2, static_cast(rec), static_cast((sfi << 3) | 4), 0x00}; - - dwSendLength = sizeof(SELECT_APDU_FILE); - dwRecvLength = sizeof(pbRecvBuffer); - - /* Check if there is data in the folder */ - #ifdef TC_WINDOWS - returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength); - #else - returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength); - #endif - - /* Check if the transmission was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - /* There is no data in the folder */ - if (pbRecvBuffer[0] != 0x6C) - continue; - - /* It set the proper expected length of the data in the APDU */ - SELECT_APDU_FILE[4] = pbRecvBuffer[1]; - - dwRecvLength = sizeof(pbRecvBufferFat); - - /* Get the data from the folder */ - #ifdef TC_WINDOWS - returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength); - #else - returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength); - #endif - - /* Check if the transmission was unsuccessful */ - if (returnValue != SCARD_S_SUCCESS) - throw PCSCException(returnValue); - - /* It received a response. Check if it didn't get a recognisable response */ - if (dwRecvLength < 2) - continue; - - /* Parsing the TLV */ - try{ - node = TLVParser::TLV_Parse(pbRecvBufferFat,sizeof(pbRecvBufferFat)); - }catch(TLVException){ - continue; - } - - /* Finding the PAN */ - try{ - PAN = TLVParser::TLV_Find(node, 0x5A); - }catch(TLVException){ - continue; - } - if(PAN) { - PANFound=true; - if (PAN->Length >= 8){ - for (int i = 6; i < 8;i++) { - v.push_back(static_cast(PAN->Value[i])); - } - } - } - - if(PANFound){ - burn(pbRecvBuffer, sizeof(pbRecvBuffer)); - burn(pbRecvBufferFat, sizeof(pbRecvBufferFat)); - return ; - } - } - } - burn(pbRecvBuffer, sizeof(pbRecvBuffer)); - burn(pbRecvBufferFat, sizeof(pbRecvBufferFat)); - throw EMVPANNotFound(); - } - - /* Helper function to transform the PAN received (vector of byte) to a string */ - template - void IccDataExtractor::make_hex_string(TInputIter first, TInputIter last, string& returnValue, bool use_uppercase, bool insert_spaces) { - ostringstream ss; - ss << hex << std::setfill('0'); - if (use_uppercase) - ss << uppercase; - while (first != last) - { - ss << setw(2) << static_cast(*first++); - if (insert_spaces && first != last) - ss << " "; - } - - returnValue = ss.str(); - } - - /* Wrapper function to get the PAN of the card*/ - void IccDataExtractor::GettingPAN(int readerNumber, string& panString) { - - #ifdef TC_WINDOWS - if(!Initialized) - throw WinscardLibraryNotInitialized(); - #endif - - vector PAN; - - bool isEMV= false; - - ConnectCard(readerNumber); - - /* Test all the type of applications and get the PAN from the first one found */ - for(int i=0;i stream) - { - Exception::Deserialize(stream); - Serializer sr(stream); - uint64 code; - sr.Deserialize("ErrorCode", code); - sr.Deserialize("SubjectErrorCodeValid", SubjectErrorCodeValid); - sr.Deserialize("SubjectErrorCode", SubjectErrorCode); - ErrorCode = (LONG)code; - } - - void PCSCException::Serialize(shared_ptr stream) const - { - Exception::Serialize(stream); - Serializer sr(stream); - sr.Serialize("ErrorCode", (uint64)ErrorCode); - sr.Serialize("SubjectErrorCodeValid", SubjectErrorCodeValid); - sr.Serialize("SubjectErrorCode", SubjectErrorCode); - } - -# define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) -# undef TC_EXCEPTION_NODECL -# define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) - - TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET(PCSCTokenException); - -#endif - -} \ No newline at end of file diff --git a/src/Common/IccDataExtractor.h b/src/Common/IccDataExtractor.h index 777a3555..e69de29b 100644 --- a/src/Common/IccDataExtractor.h +++ b/src/Common/IccDataExtractor.h @@ -1,231 +0,0 @@ -// -// Created by bshp on 1/14/23. -// - -#ifndef NEWEMV_ICCDATAEXTRACTOR_H -#define NEWEMV_ICCDATAEXTRACTOR_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include "Platform/PlatformBase.h" -#include "TLVParser.h" - -#ifdef __linux__ -#include -#endif - -#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) -# include "Exception.h" -#else -# include "Platform/Exception.h" -#endif - -#ifdef TC_WINDOWS -#include -#include -#endif -#ifdef TC_UNIX -#undef BOOL -#include -using VeraCrypt::byte; -#define BOOL int -//#include //Works without on windows -#endif - -#ifdef _WIN32 -#include -#endif - -#ifdef _WIN64 -#define ssize_t __int64 -#else -#define ssize_t long -#endif - -#define SELECT_TYPE_SIZE 12 /* Size of the SELECT_TYPE APDU */ - -/* Winscard function pointers definitions for windows import */ -#ifdef TC_WINDOWS -typedef LONG (WINAPI *SCardEstablishContextPtr)(DWORD dwScope,LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext); -typedef LONG (WINAPI *SCardReleaseContextPtr)(SCARDCONTEXT hContext); -typedef LONG (WINAPI *SCardConnectAPtr)(SCARDCONTEXT hContext,LPCSTR szReader,DWORD dwShareMode,DWORD dwPreferredProtocols,LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol); -typedef LONG (WINAPI *SCardDisconnectPtr)(SCARDHANDLE hCard, DWORD dwDisposition); -typedef LONG (WINAPI *SCardTransmitPtr)(SCARDHANDLE hCard,LPCSCARD_IO_REQUEST pioSendPci,const BYTE* pbSendBuffer, DWORD cbSendLength,LPSCARD_IO_REQUEST pioRecvPci,BYTE* pbRecvBuffer, LPDWORD pcbRecvLength); -typedef LONG (WINAPI *SCardListReadersAPtr)(SCARDCONTEXT hContext,LPCSTR mszGroups,LPSTR mszReaders, LPDWORD pcchReaders); -typedef LONG (WINAPI *SCardFreeMemoryPtr)(SCARDCONTEXT hContext,LPCVOID pvMem); -#endif - -namespace VeraCrypt -{ - class IccDataExtractor { - private: - - /* Used for loading winscard on windows */ - #ifdef TC_WINDOWS - /* Winscard Library Handle */ - HMODULE WinscardLibraryHandle; - - /* Winscard function pointers */ - SCardEstablishContextPtr WSCardEstablishContext; - SCardReleaseContextPtr WSCardReleaseContext; - SCardConnectAPtr WSCardConnectA; - SCardDisconnectPtr WSCardDisconnect; - SCardFreeMemoryPtr WSCardFreeMemory; - SCardListReadersAPtr WSCardListReadersA; - SCardTransmitPtr WSCardTransmit; - - /* Is the winscard library loaded */ - static bool Initialized; - #endif - - /* SELECT_TYPES FOR DIFFERENT AIDs*/ - const static BYTE SELECT_MASTERCARD[SELECT_TYPE_SIZE]; - const static BYTE SELECT_VISA[SELECT_TYPE_SIZE]; - const static BYTE SELECT_AMEX[SELECT_TYPE_SIZE]; - const static BYTE * SELECT_TYPES[3]; - - - SCARDCONTEXT hContext; /* Handle that identifies the resource manager context.*/ - - SCARDHANDLE hCard; /* A handle that identifies the connection to the smart card in the designated reader*/ - - std::vector readers; /* Card reader list */ - - unsigned long int nbReaders; /* Number of connected (available) readers */ - - LPSTR mszReaders; /* Names of the reader groups defined to the system, as a multi-string. Use a NULL value to - * list all readers in the system */ - - DWORD dwActiveProtocol; /* A flag that indicates the established active protocol. - * SCARD_PROTOCOL_T0: An asynchronous, character-oriented half-duplex transmission protocol. - * SCARD_PROTOCOL_T1: An asynchronous, block-oriented half-duplex transmission protocol.*/ - - - /* Establishing the resource manager context (the scope) within which database operations are performed. - * The module of the smart card subsystem that manages access to multiple readers and smart cards. The - * resource manager identifies and tracks resources, allocates readers and resources across multiple - * applications,and supports transaction primitives for accessing services available on a given card.*/ - int EstablishRSContext(); - - /* Connecting to the card in the given reader*/ - int ConnectCard(unsigned long int reader_nb); - - /* Disconnect the card currently connected*/ - int DisconnectCard(); - - /* Testing if the card contains the application of the given EMV type */ - bool TestingCardType(const int SELECT_TYPE_NUMBER); - - /* Getting the ICC Public Key Certificates and the Issuer Public Key Certificates by parsing the application - * (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/ - void GetCerts(vector &CERTS); - - /* Getting CPCL data from the card and put it into a reference*/ - void GetCPCL(vector &v); - - /* Getting the PAN by parsing the application - * (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/ - void GetPAN(vector &v); - - /* Helper function to make a string from plain arrays and various standard containers of bytes */ - template - void make_hex_string(TInputIter first, TInputIter last, std::string& panString, bool use_uppercase = true, bool insert_spaces = false); - - public: - IccDataExtractor(); - - ~IccDataExtractor(); - - /* Used to initialize the winscard library on windows to make sure the dll is in System32 */ - #ifdef TC_WINDOWS - void IccDataExtractor::InitLibrary(); - #endif - - /* Detecting available readers and filling the reader table. Returns - * the number of available readers */ - unsigned long GetReaders(); - - - /* Getting an ICC Public Key Certificates, an Issuer Public Key Certificates and the CPCL data - * from the card designated by the reader number. Appending them into a byte vector */ - void GettingAllCerts(int readerNumber, vector &v); - - /* Getting the PAN from the card designated by the reader number */ - void GettingPAN(int readerNumber, string& panString); - }; - - struct PCSCException: public Exception - { - PCSCException(LONG errorCode = (LONG) -1): ErrorCode(errorCode), SubjectErrorCodeValid(false), SubjectErrorCode((uint64)-1){} - PCSCException(LONG errorCode, uint64 subjectErrorCode): ErrorCode(errorCode), SubjectErrorCodeValid(true), SubjectErrorCode(subjectErrorCode){} - - #ifdef TC_HEADER_Platform_Exception - virtual ~PCSCException() throw () { } - TC_SERIALIZABLE_EXCEPTION(PCSCException); - #else - - void Show(HWND parent) const; - #endif - - operator string () const; - LONG GetErrorCode() const { return ErrorCode; } - - protected: - LONG ErrorCode; - bool SubjectErrorCodeValid; - uint64 SubjectErrorCode; - }; - - #ifdef TC_HEADER_Platform_Exception - - #define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception) - - #undef TC_EXCEPTION_SET - #define TC_EXCEPTION_SET \ - TC_EXCEPTION_NODECL (PCSCException); \ - TC_EXCEPTION (WinscardLibraryNotInitialized); \ - TC_EXCEPTION (InvalidEMVPath); \ - TC_EXCEPTION (EMVKeyfileDataNotFound); \ - TC_EXCEPTION (EMVPANNotFound); \ - TC_EXCEPTION (EMVUnknownCardType); - TC_EXCEPTION_SET; - - #undef TC_EXCEPTION - - #else // !TC_HEADER_Platform_Exception - - struct WinscardLibraryNotInitialized: public Exception - { - void Show(HWND parent) const { Error("WINSCARD_MODULE_INIT_FAILED", parent); } - }; - - struct InvalidEMVPath: public Exception - { - void Show(HWND parent) const { Error("INVALID_EMV_PATH", parent); } - }; - - struct EMVKeyfileDataNotFound: public Exception - { - void Show(HWND parent) const { Error("EMV_KEYFILE_DATA_NOT_FOUND", parent); } - }; - - struct EMVPANNotFound: public Exception - { - void Show(HWND parent) const { Error("EMV_PAN_NOT_FOUND", parent); } - }; - - struct EMVUnknownCardType: public Exception - { - void Show(HWND parent) const { Error("EMV_UNKNOWN_CARD_TYPE", parent); } - }; - - #endif // !TC_HEADER_Platform_Exception -} - -#endif //NEWEMV_ICCDATAEXTRACTOR_H diff --git a/src/Common/Keyfiles.c b/src/Common/Keyfiles.c index d2207f5f..d5a2d5c2 100644 --- a/src/Common/Keyfiles.c +++ b/src/Common/Keyfiles.c @@ -250,7 +250,7 @@ BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFile, con // Determine whether it's a security token path try { - if (Token::IsKeyfilePathValid (kf->FileName, ActivateEMVOption)) + if (Token::IsKeyfilePathValid (kf->FileName, EMVSupportEnabled)) { // Apply security token keyfile vector keyfileData; diff --git a/src/Common/Language.xml b/src/Common/Language.xml index cd996bce..a34187a5 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -113,7 +113,6 @@ Cache passwords and keyfil&es in memory Exit when there are no mounted volumes &Close token session (log out) after a volume is successfully mounted - Activate EMV Option Include VeraCrypt Volume Expander Include VeraCrypt Volume Creation Wizard Create @@ -1280,12 +1279,6 @@ Password for security token is incorrect. The security token does not have enough memory/space to perform the requested operation.\n\nIf you are attempting to import a keyfile, you should select a smaller file or use a keyfile generated by VeraCrypt (select 'Tools' > 'Keyfile Generator'). All open security token sessions have been closed. - Error when loading the winscard library.\n\nPlease make sure the WinSCard.dll is present in your System32 folder. - EMV path is invalid. - Unable to build a keyfile from the EMV card's data.\n\nOne of the following is missing:\n- ICC Public Key Certificate.\n- Issuer Public Key Certificate.\n- CPCL data. - No Primary Account Number (PAN) found in the EMV card. - The card in the reader is not a supported EMV card. - No card in the reader.\n\nPlease make sure the card is correctly slotted. Select Security Token Keyfiles Slot Token name @@ -1616,6 +1609,19 @@ Full Format Fast Create WARNING: You should use Fast Create only in the following cases:\n\n1) The device contains no sensitive data and you do not need plausible deniability.\n2) The device has already been securely and fully encrypted.\n\nAre you sure you want to use Fast Create? + Enable EMV Support + The APDU command sent to the card is not valid. + Extended APDU commands cannot be used with the current token. + Error when loading the WinSCard / PCSC library. + The card in the reader is not a supported EMV card. + The AID of the card in the reader could not be selected. + ICC Public Key Certificate was not found in the card. + Issuer Public Key Certificate was not found in the card. + CLPC was not found in the EMV card. + No Primary Account Number (PAN) found in the EMV card. + EMV path is invalid. + Unable to build a keyfile from the EMV card's data.\n\nOne of the following is missing:\n- ICC Public Key Certificate.\n- Issuer Public Key Certificate.\n- CPCL data. + No card in the reader.\n\nPlease make sure the card is correctly slotted. diff --git a/src/Common/PCSCException.cpp b/src/Common/PCSCException.cpp new file mode 100644 index 00000000..93fff181 --- /dev/null +++ b/src/Common/PCSCException.cpp @@ -0,0 +1,199 @@ +#include "PCSCException.h" + +#if !defined(TC_WINDOWS) || defined(TC_PROTOTYPE) +#include "Platform/SerializerFactory.h" +#include "Platform/StringConverter.h" +#include "Platform/SystemException.h" +#else +#include "Dictionary.h" +#include "Language.h" +#endif + +namespace VeraCrypt +{ + PCSCException::operator string() const + { + if (ErrorCode == SCARD_S_SUCCESS) + return string(); + + static const struct{ + LONG_PCSC ErrorCode; + const char* ErrorString; + } ErrorStrings[] = { +#define SC_ERR(CODE) { CODE, #CODE }, +#ifdef TC_WINDOWS + SC_ERR(ERROR_BROKEN_PIPE) + SC_ERR(SCARD_E_NO_PIN_CACHE) + SC_ERR(SCARD_E_PIN_CACHE_EXPIRED) + SC_ERR(SCARD_E_READ_ONLY_CARD) + SC_ERR(SCARD_W_CACHE_ITEM_NOT_FOUND) + SC_ERR(SCARD_W_CACHE_ITEM_STALE) + SC_ERR(SCARD_W_CACHE_ITEM_TOO_BIG) +#endif + SC_ERR(SCARD_E_BAD_SEEK) + SC_ERR(SCARD_E_CANCELLED) + SC_ERR(SCARD_E_CANT_DISPOSE) + SC_ERR(SCARD_E_CARD_UNSUPPORTED) + SC_ERR(SCARD_E_CERTIFICATE_UNAVAILABLE) + SC_ERR(SCARD_E_COMM_DATA_LOST) + SC_ERR(SCARD_E_COMM_DATA_LOST) + SC_ERR(SCARD_E_DIR_NOT_FOUND) + SC_ERR(SCARD_E_DUPLICATE_READER) + SC_ERR(SCARD_E_FILE_NOT_FOUND) + SC_ERR(SCARD_E_ICC_CREATEORDER) + SC_ERR(SCARD_E_ICC_INSTALLATION) + SC_ERR(SCARD_E_INSUFFICIENT_BUFFER) + SC_ERR(SCARD_E_INVALID_ATR) + SC_ERR(SCARD_E_INVALID_CHV) + SC_ERR(SCARD_E_INVALID_HANDLE) + SC_ERR(SCARD_E_INVALID_PARAMETER) + SC_ERR(SCARD_E_INVALID_TARGET) + SC_ERR(SCARD_E_INVALID_VALUE) + SC_ERR(SCARD_E_NO_ACCESS) + SC_ERR(SCARD_E_NO_DIR) + SC_ERR(SCARD_E_NO_FILE) + SC_ERR(SCARD_E_NO_KEY_CONTAINER) + SC_ERR(SCARD_E_NO_MEMORY) + SC_ERR(SCARD_E_NO_READERS_AVAILABLE) + SC_ERR(SCARD_E_NO_SERVICE) + SC_ERR(SCARD_E_NO_SMARTCARD) + SC_ERR(SCARD_E_NO_SUCH_CERTIFICATE) + SC_ERR(SCARD_E_NOT_READY) + SC_ERR(SCARD_E_NOT_TRANSACTED) + SC_ERR(SCARD_E_PCI_TOO_SMALL) + SC_ERR(SCARD_E_PROTO_MISMATCH) + SC_ERR(SCARD_E_READER_UNAVAILABLE) + SC_ERR(SCARD_E_READER_UNSUPPORTED) + SC_ERR(SCARD_E_SERVER_TOO_BUSY) + SC_ERR(SCARD_E_SERVICE_STOPPED) + SC_ERR(SCARD_E_SHARING_VIOLATION) + SC_ERR(SCARD_E_SYSTEM_CANCELLED) + SC_ERR(SCARD_E_TIMEOUT) + SC_ERR(SCARD_E_UNEXPECTED) + SC_ERR(SCARD_E_UNKNOWN_CARD) + SC_ERR(SCARD_E_UNKNOWN_READER) + SC_ERR(SCARD_E_UNKNOWN_RES_MNG) + SC_ERR(SCARD_E_UNSUPPORTED_FEATURE) + SC_ERR(SCARD_E_WRITE_TOO_MANY) + SC_ERR(SCARD_F_COMM_ERROR) + SC_ERR(SCARD_F_INTERNAL_ERROR) + SC_ERR(SCARD_F_UNKNOWN_ERROR) + SC_ERR(SCARD_W_CANCELLED_BY_USER) + SC_ERR(SCARD_W_CARD_NOT_AUTHENTICATED) + SC_ERR(SCARD_W_CHV_BLOCKED) + SC_ERR(SCARD_W_EOF) + SC_ERR(SCARD_W_REMOVED_CARD) + SC_ERR(SCARD_W_RESET_CARD) + SC_ERR(SCARD_W_SECURITY_VIOLATION) + SC_ERR(SCARD_W_UNPOWERED_CARD) + SC_ERR(SCARD_W_UNRESPONSIVE_CARD) + SC_ERR(SCARD_W_UNSUPPORTED_CARD) + SC_ERR(SCARD_W_WRONG_CHV) +#undef SC_ERR + }; + + for (size_t i = 0; i < array_capacity(ErrorStrings); ++i) + { + if (ErrorStrings[i].ErrorCode == ErrorCode) + return ErrorStrings[i].ErrorString; + } + + stringstream s; + s << "0x" << ErrorCode; + return s.str(); + } + +#ifdef TC_HEADER_Common_Exception + void PCSCException::Show(HWND parent) const + { + string errorString = string(*this); + + if (!errorString.empty()) + { + if (!GetDictionaryValue(errorString.c_str())) + { + if (errorString.find("SCARD_E_") == 0 || errorString.find("SCARD_F_") == 0 || errorString.find("SCARD_W_") == 0) + { + errorString = errorString.substr(8); + for (size_t i = 0; i < errorString.size(); ++i) + { + if (errorString[i] == '_') + errorString[i] = ' '; + } + } + wchar_t err[8192]; + StringCbPrintfW(err, sizeof(err), L"%s:\n\n%hs%s", GetString("PCSC_ERROR"), errorString.c_str()); + ErrorDirect(err, parent); + } + else + { + wstring err = GetString(errorString.c_str()); + ErrorDirect(err.c_str(), parent); + } + } + } +#endif // TC_HEADER_Common_Exception + +#ifdef TC_HEADER_Platform_Exception + + void PCSCException::Deserialize(shared_ptr stream) + { + Exception::Deserialize(stream); + Serializer sr(stream); + sr.Deserialize("ErrorCode", ErrorCode); + } + + void PCSCException::Serialize(shared_ptr stream) const + { + Exception::Serialize(stream); + Serializer sr(stream); + sr.Serialize("ErrorCode", ErrorCode); + } + +# define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +# undef TC_EXCEPTION_NODECL +# define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET(PCSCException); + +#endif + + CommandAPDUNotValid::operator string() const + { + return string(ErrorStr); + } + +#ifdef TC_HEADER_Common_Exception + void CommandAPDUNotValid::Show(HWND parent) const + { + string msgBody = "Command APDU invalid.\n\n\n(If you report a bug in connection with this, please include the following technical information in the bug report:\n" + SrcPos + "\nLast Error = " + ErrorStr + ")"; + MessageBoxA (parent, msgBody.c_str(), "VeraCrypt", MB_ICONERROR | MB_SETFOREGROUND); + } +#endif // TC_HEADER_Common_Exception + +#ifdef TC_HEADER_Platform_Exception + + void CommandAPDUNotValid::Deserialize(shared_ptr stream) + { + Exception::Deserialize(stream); + Serializer sr(stream); + sr.Deserialize("SrcPos", SrcPos); + sr.Deserialize("ErrorStr", ErrorStr); + } + + void CommandAPDUNotValid::Serialize(shared_ptr stream) const + { + Exception::Serialize(stream); + Serializer sr(stream); + sr.Serialize("SrcPos", SrcPos); + sr.Serialize("ErrorStr", ErrorStr); + } + +# define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +# undef TC_EXCEPTION_NODECL +# define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET(CommandAPDUNotValid); + +#endif +} \ No newline at end of file diff --git a/src/Common/PCSCException.h b/src/Common/PCSCException.h new file mode 100644 index 00000000..6c7766b5 --- /dev/null +++ b/src/Common/PCSCException.h @@ -0,0 +1,136 @@ +#ifndef TC_HEADER_Common_PCSCException +#define TC_HEADER_Common_PCSCException + +#include "Platform/PlatformBase.h" +#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) +# include "Exception.h" +#else +# include "Platform/Exception.h" +#endif + +#include "SCardLoader.h" + +#ifdef TC_MACOSX +#define LONG_PCSC uint32_t +#else +#define LONG_PCSC LONG +#endif + +namespace VeraCrypt +{ + struct PCSCException: public Exception + { + PCSCException(LONG_PCSC errorCode = (LONG_PCSC)-1): ErrorCode(errorCode){} + +#ifdef TC_HEADER_Platform_Exception + virtual ~PCSCException() throw () { } + TC_SERIALIZABLE_EXCEPTION(PCSCException); +#else + void Show(HWND parent) const; +#endif + + operator string () const; + LONG_PCSC GetErrorCode() const { return ErrorCode; } + + protected: + LONG_PCSC ErrorCode; + }; + + struct CommandAPDUNotValid: public Exception + { + CommandAPDUNotValid() : SrcPos (""), ErrorStr ("") { } + CommandAPDUNotValid(const string& srcPos, const string& errorStr) : SrcPos (srcPos), ErrorStr(errorStr) { } + +#ifdef TC_HEADER_Platform_Exception + virtual ~CommandAPDUNotValid() throw () { } + TC_SERIALIZABLE_EXCEPTION(CommandAPDUNotValid); +#else + void Show(HWND parent) const; +#endif + + operator string () const; + + protected: + string SrcPos; + string ErrorStr; + }; + +#ifdef TC_HEADER_Platform_Exception + + #define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception) + + #undef TC_EXCEPTION_SET + #define TC_EXCEPTION_SET \ + TC_EXCEPTION_NODECL (PCSCException); \ + TC_EXCEPTION_NODECL (CommandAPDUNotValid); \ + TC_EXCEPTION (ExtendedAPDUNotSupported); \ + TC_EXCEPTION (ScardLibraryInitializationFailed); \ + TC_EXCEPTION (EMVUnknownCardType); \ + TC_EXCEPTION (EMVSelectAIDFailed); \ + TC_EXCEPTION (EMVIccCertNotFound); \ + TC_EXCEPTION (EMVIssuerCertNotFound); \ + TC_EXCEPTION (EMVCPLCNotFound); \ + TC_EXCEPTION (InvalidEMVPath); \ + TC_EXCEPTION (EMVKeyfileDataNotFound); \ + TC_EXCEPTION (EMVPANNotFound); \ + + TC_EXCEPTION_SET; + + #undef TC_EXCEPTION + +#else // !TC_HEADER_Platform_Exception + + struct ExtendedAPDUNotSupported: public Exception + { + void Show(HWND parent) const { Error("EXTENDED_APDU_UNSUPPORTED", parent); } + }; + + struct ScardLibraryInitializationFailed: public Exception + { + void Show(HWND parent) const { Error("SCARD_MODULE_INIT_FAILED", parent); } + }; + + struct EMVUnknownCardType: public Exception + { + void Show(HWND parent) const { Error("EMV_UNKNOWN_CARD_TYPE", parent); } + }; + + struct EMVSelectAIDFailed: public Exception + { + void Show(HWND parent) const { Error("EMV_SELECT_AID_FAILED", parent); } + }; + + struct EMVIccCertNotFound: public Exception + { + void Show(HWND parent) const { Error("EMV_ICC_CERT_NOTFOUND", parent); } + }; + + struct EMVIssuerCertNotFound: public Exception + { + void Show(HWND parent) const { Error("EMV_ISSUER_CERT_NOTFOUND", parent); } + }; + + struct EMVCPLCNotFound: public Exception + { + void Show(HWND parent) const { Error("EMV_CPLC_NOTFOUND", parent); } + }; + + struct EMVPANNotFound: public Exception + { + void Show(HWND parent) const { Error("EMV_PAN_NOTFOUND", parent); } + }; + + struct InvalidEMVPath: public Exception + { + void Show(HWND parent) const { Error("INVALID_EMV_PATH", parent); } + }; + + struct EMVKeyfileDataNotFound: public Exception + { + void Show(HWND parent) const { Error("EMV_KEYFILE_DATA_NOTFOUND", parent); } + }; + +#endif // !TC_HEADER_Platform_Exception +} + +#endif // TC_HEADER_Common_PCSCException \ No newline at end of file diff --git a/src/Common/ResponseAPDU.cpp b/src/Common/ResponseAPDU.cpp new file mode 100644 index 00000000..8a7f069c --- /dev/null +++ b/src/Common/ResponseAPDU.cpp @@ -0,0 +1,111 @@ +#include "ResponseAPDU.h" +#include + +using namespace std; + +namespace VeraCrypt +{ + uint16 BytesToUInt16(const vector& buff) + { + uint16 value = 0; + for (uint16 i = 0; i < buff.size(); i++) + { + value <<= 8; + value |= (uint16)buff.at(i); + } + + return value; + } + + void AppendData (vector& buffer, const byte* pbData, size_t cbData) + { + size_t orgSize = buffer.size (); + buffer.resize (orgSize + cbData); + memcpy (buffer.data () + orgSize, pbData, cbData); + } + + /*********************************************************************************/ + + void ResponseAPDU::clear() + { + m_data.clear(); + m_SW = 0; + } + + ResponseAPDU::ResponseAPDU() : m_SW(0) + { + } + + ResponseAPDU::ResponseAPDU(const vector& data, uint16 SW) + { + m_data = data; + m_SW = SW; + } + + uint32 ResponseAPDU::getNr() + { + return (uint32)m_data.size(); + } + + const vector ResponseAPDU::getData() + { + return m_data; + } + + byte ResponseAPDU::getSW1() + { + return (byte)((0xFF00 & m_SW) >> 8); + } + + byte ResponseAPDU::getSW2() + { + return (byte)(0x00FF & m_SW); + } + + uint16 ResponseAPDU::getSW() + { + return m_SW; + } + + const vector ResponseAPDU::getBytes() + { + vector apdu; + + AppendData(apdu, m_data.data(), m_data.size()); + apdu.push_back((byte)getSW1()); + apdu.push_back((byte)getSW2()); + + return apdu; + } + + void ResponseAPDU::appendData(const vector& data) + { + appendData(data.data(), data.size()); + } + + void ResponseAPDU::appendData(const byte* data, size_t dataLen) + { + AppendData(m_data, data, dataLen); + } + + void ResponseAPDU::setSW(uint16 SW) + { + m_SW = SW; + } + + void ResponseAPDU::setBytes(const vector& bytes) + { + clear(); + if (bytes.size() >= 2) + { + vector SWBytes; + m_data.resize(bytes.size() - 2); + SWBytes.resize(2); + + memcpy(m_data.data(), bytes.data(), bytes.size() - 2); + memcpy(SWBytes.data(), bytes.data() + bytes.size() - 2, 2); + m_SW = BytesToUInt16(SWBytes); + } + } +} + diff --git a/src/Common/ResponseAPDU.h b/src/Common/ResponseAPDU.h new file mode 100644 index 00000000..b9aa4adc --- /dev/null +++ b/src/Common/ResponseAPDU.h @@ -0,0 +1,44 @@ +#ifndef TC_HEADER_Common_ResponseAPDU +#define TC_HEADER_Common_ResponseAPDU + +#include "Platform/PlatformBase.h" + +namespace VeraCrypt +{ + class ResponseAPDU + { + protected: + + vector m_data; + + uint16 m_SW; + + public: + + void clear(); + + ResponseAPDU(); + + ResponseAPDU(const vector& data, uint16 SW); + + uint32 getNr(); + + const vector getData(); + + byte getSW1(); + + byte getSW2(); + + uint16 getSW(); + + const vector getBytes(); + + void setSW(uint16 SW); + void setBytes(const vector& bytes); + + void appendData(const vector& data); + void appendData(const byte* data, size_t dataLen); + }; +}; + +#endif // TC_HEADER_Common_ResponseAPDU \ No newline at end of file diff --git a/src/Common/SCard.cpp b/src/Common/SCard.cpp new file mode 100644 index 00000000..9f8d1145 --- /dev/null +++ b/src/Common/SCard.cpp @@ -0,0 +1,62 @@ +#include "SCard.h" + +using namespace std; + +namespace VeraCrypt +{ + SCardManager SCard::manager; + + SCard::SCard() : m_reader(NULL) + { + } + + SCard::SCard(size_t slotId) + { + m_reader = SCard::manager.GetReader(slotId); + } + + SCard::~SCard() + { + if (m_reader) + { + m_reader->Disconnect(); + } + } + + SCard::SCard(const SCard& other) : m_reader(other.m_reader) + { + } + + SCard::SCard(SCard&& other) : m_reader(std::move(other.m_reader)) + { + } + + SCard& SCard::operator = (const SCard& other) + { + if (this != &other) + { + m_reader = other.m_reader; + } + return *this; + } + + SCard& SCard::operator = (SCard&& other) + { + if (this != &other) + { + m_reader = std::move(other.m_reader); + } + return *this; + } + + bool SCard::IsCardHandleValid() const + { + bool isValid = false; + if (m_reader) + { + isValid = m_reader->CardHandleStatus() == SCARD_S_SUCCESS; + } + + return isValid; + } +} diff --git a/src/Common/SCard.h b/src/Common/SCard.h new file mode 100644 index 00000000..b02f14f0 --- /dev/null +++ b/src/Common/SCard.h @@ -0,0 +1,27 @@ +#ifndef TC_HEADER_Common_SCard +#define TC_HEADER_Common_SCard + +#include "Platform/PlatformBase.h" + +#include "SCardManager.h" + +namespace VeraCrypt +{ + class SCard + { + protected: + shared_ptr m_reader; + public: + static SCardManager manager; + SCard(); + SCard(size_t slotId); + SCard(const SCard& other); + SCard(SCard&& other); + SCard& operator = (const SCard& other); + SCard& operator = (SCard&& other); + virtual ~SCard(); + bool IsCardHandleValid() const; + }; +} + +#endif // TC_HEADER_Common_SCard diff --git a/src/Common/SCardLoader.cpp b/src/Common/SCardLoader.cpp new file mode 100644 index 00000000..ff3c9100 --- /dev/null +++ b/src/Common/SCardLoader.cpp @@ -0,0 +1,402 @@ +#include "SCardLoader.h" +#include "PCSCException.h" + +#ifndef TC_WINDOWS +#include +#define LoadLibrary(x) dlopen(x, RTLD_NOW | RTLD_LOCAL) +#define FreeLibrary(x) dlclose(x) +#define GetProcAddress(x, y) dlsym(x, y) +typedef void* HMODULE; +#ifdef TC_MACOSX +#if !defined(USE_SCARD_CONTROL_112) +#define SCardControlName "SCardControl132" +#else +#define SCardControlName "SCardControl" +#endif +#else +#define SCardControlName "SCardControl" +#endif +#define SCardConnectName "SCardConnect" +#define SCardStatusName "SCardStatus" +#define SCardGetStatusChangeName "SCardGetStatusChange" +#define SCardListReaderGroupsName "SCardListReaderGroups" +#define SCardListReadersName "SCardListReaders" +#else +#define SCardControlName "SCardControl" +#define SCardConnectName "SCardConnectW" +#define SCardStatusName "SCardStatusW" +#define SCardGetStatusChangeName "SCardGetStatusChangeW" +#define SCardListReaderGroupsName "SCardListReaderGroupsW" +#define SCardListReadersName "SCardListReadersW" +#endif + +using namespace std; + +namespace VeraCrypt +{ + HMODULE SCardLoader::hScardModule = NULL; + SCARDCONTEXT SCardLoader::hScardContext = 0; + SCardEstablishContextPtr SCardLoader::scardEstablishContext = NULL; + SCardReleaseContextPtr SCardLoader::scardReleaseContext = NULL; + SCardIsValidContextPtr SCardLoader::scardIsValidContext = NULL; +#ifndef TC_MACOSX + SCardFreeMemoryPtr SCardLoader::scardFreeMemory = NULL; +#endif + SCardConnectPtr SCardLoader::scardConnect = NULL; + SCardReconnectPtr SCardLoader::scardReconnect = NULL; + SCardDisconnectPtr SCardLoader::scardDisconnect = NULL; + SCardBeginTransactionPtr SCardLoader::scardBeginTransaction = NULL; + SCardEndTransactionPtr SCardLoader::scardEndTransaction = NULL; + SCardStatusPtr SCardLoader::scardStatus = NULL; + SCardGetStatusChangePtr SCardLoader::scardGetStatusChange = NULL; + SCardControlPtr SCardLoader::scardControl = NULL; + SCardTransmitPtr SCardLoader::scardTransmit = NULL; + SCardListReaderGroupsPtr SCardLoader::scardListReaderGroups = NULL; + SCardListReadersPtr SCardLoader::scardListReaders = NULL; + SCardCancelPtr SCardLoader::scardCancel = NULL; + SCardGetAttribPtr SCardLoader::scardGetAttrib = NULL; + SCardSetAttribPtr SCardLoader::scardSetAttrib = NULL; + SCARD_IO_REQUEST* SCardLoader::scardT0Pci = NULL; + SCARD_IO_REQUEST* SCardLoader::scardT1Pci = NULL; + SCARD_IO_REQUEST* SCardLoader::scardRawPci = NULL; + bool SCardLoader::bInitialized = false; + +#ifdef TC_WINDOWS + wstring SCardLoader::GetSCardPath() +#else + string SCardLoader::GetSCardPath() +#endif + { +#ifdef TC_WINDOWS + wchar_t winscardPath[TC_MAX_PATH]; + if (GetSystemDirectory(winscardPath, TC_MAX_PATH)) + { + StringCbCat(winscardPath, sizeof(winscardPath), L"\\Winscard.dll"); + } + else + StringCbCopy(winscardPath, sizeof(winscardPath), L"C:\\Windows\\System32\\Winscard.dll"); + return winscardPath; +#elif TC_MACOSX + return "/System/Library/Frameworks/PCSC.framework/PCSC"; +#else + string pcscPath = ""; + FILE* pipe = +#ifdef TC_LINUX + popen("ldconfig -p", "r"); +#else + popen("ldconfig -r", "r"); // FreeBSD +#endif + if (pipe) + { + char buffer[128]; + while (!feof(pipe)) + { + if (fgets(buffer, 128, pipe) != NULL) + { + string line(buffer); + if (line.find("libpcsclite.so") != string::npos) + { + size_t pos = line.find("=>"); + if (pos != string::npos) + { + pcscPath = line.substr(pos + 3); + pos = pcscPath.find_first_of(" \t\r\n"); + if (pos != string::npos) + pcscPath = pcscPath.substr(0, pos); + break; + } + } + } + } + pclose(pipe); + } + + if (pcscPath == "") + { + pcscPath = "libpcsclite.so"; + } + + return pcscPath; +#endif + } + + void SCardLoader::Initialize() + { + if (bInitialized) + return; + + hScardModule = LoadLibrary(GetSCardPath().c_str()); + if (hScardModule) + { + scardEstablishContext = (SCardEstablishContextPtr)GetProcAddress(hScardModule, "SCardEstablishContext"); + scardReleaseContext = (SCardReleaseContextPtr)GetProcAddress(hScardModule, "SCardReleaseContext"); + scardIsValidContext = (SCardIsValidContextPtr)GetProcAddress(hScardModule, "SCardIsValidContext"); +#ifndef TC_MACOSX + scardFreeMemory = (SCardFreeMemoryPtr)GetProcAddress(hScardModule, "SCardFreeMemory"); +#endif + scardConnect = (SCardConnectPtr)GetProcAddress(hScardModule, SCardConnectName); + scardReconnect = (SCardReconnectPtr)GetProcAddress(hScardModule, "SCardReconnect"); + scardDisconnect = (SCardDisconnectPtr)GetProcAddress(hScardModule, "SCardDisconnect"); + scardBeginTransaction = (SCardBeginTransactionPtr)GetProcAddress(hScardModule, "SCardBeginTransaction"); + scardEndTransaction = (SCardEndTransactionPtr)GetProcAddress(hScardModule, "SCardEndTransaction"); + scardStatus = (SCardStatusPtr)GetProcAddress(hScardModule, SCardStatusName); + scardGetStatusChange = (SCardGetStatusChangePtr)GetProcAddress(hScardModule, SCardGetStatusChangeName); + scardControl = (SCardControlPtr)GetProcAddress(hScardModule, SCardControlName); + scardTransmit = (SCardTransmitPtr)GetProcAddress(hScardModule, "SCardTransmit"); + scardListReaderGroups = (SCardListReaderGroupsPtr)GetProcAddress(hScardModule, SCardListReaderGroupsName); + scardListReaders = (SCardListReadersPtr)GetProcAddress(hScardModule, SCardListReadersName); + scardCancel = (SCardCancelPtr)GetProcAddress(hScardModule, "SCardCancel"); + scardGetAttrib = (SCardGetAttribPtr)GetProcAddress(hScardModule, "SCardGetAttrib"); + scardSetAttrib = (SCardSetAttribPtr)GetProcAddress(hScardModule, "SCardSetAttrib"); + scardT0Pci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardT0Pci"); + scardT1Pci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardT1Pci"); + scardRawPci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardRawPci"); + if ( +#ifndef TC_MACOSX + scardFreeMemory && +#endif + scardEstablishContext && scardReleaseContext && scardIsValidContext && scardConnect && scardReconnect && scardDisconnect && + scardBeginTransaction && scardEndTransaction && scardStatus && scardGetStatusChange && scardControl && scardTransmit && + scardListReaderGroups && scardListReaders && scardCancel && scardGetAttrib && scardSetAttrib && scardT0Pci && scardT1Pci && scardRawPci) + { + if (SCARD_S_SUCCESS == scardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hScardContext)) + { + bInitialized = true; + } + } + } + + if (!bInitialized) + { + Finalize(); + } + } + + void SCardLoader::Finalize() + { + if (hScardContext) + { + scardReleaseContext(hScardContext); + hScardContext = 0; + } + + if (hScardModule) + { + FreeLibrary(hScardModule); + hScardModule = NULL; + } + + scardEstablishContext = NULL; + scardReleaseContext = NULL; + scardIsValidContext = NULL; +#ifndef TC_MACOSX + scardFreeMemory = NULL; +#endif + scardConnect = NULL; + scardReconnect = NULL; + scardDisconnect = NULL; + scardBeginTransaction = NULL; + scardEndTransaction = NULL; + scardStatus = NULL; + scardGetStatusChange = NULL; + scardControl = NULL; + scardTransmit = NULL; + scardListReaderGroups = NULL; + scardListReaders = NULL; + scardCancel = NULL; + scardGetAttrib = NULL; + scardSetAttrib = NULL; + scardT0Pci = NULL; + scardT1Pci = NULL; + scardRawPci = NULL; + + bInitialized = false; + } + + SCARDCONTEXT SCardLoader::GetSCardContext() + { + return hScardContext; + } + + LONG SCardLoader::SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext); + } + + LONG SCardLoader::SCardReleaseContext(SCARDCONTEXT hContext) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardReleaseContext(hContext); + } + + LONG SCardLoader::SCardIsValidContext(SCARDCONTEXT hContext) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardIsValidContext(hContext); + } + +#ifndef TC_MACOSX + LONG SCardLoader::SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardFreeMemory(hContext, pvMem); + } +#endif + + LONG SCardLoader::SCardConnect(SCARDCONTEXT hContext, LPCTSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardConnect(hContext, szReader, dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol); + } + + LONG SCardLoader::SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardReconnect(hCard, dwShareMode, dwPreferredProtocols, dwInitialization, pdwActiveProtocol); + } + + LONG SCardLoader::SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardDisconnect(hCard, dwDisposition); + } + + LONG SCardLoader::SCardBeginTransaction(SCARDHANDLE hCard) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardBeginTransaction(hCard); + } + + LONG SCardLoader::SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardEndTransaction(hCard, dwDisposition); + } + + LONG SCardLoader::SCardStatus(SCARDHANDLE hCard, LPTSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, BYTE* pbAtr, LPDWORD pcbAtrLen) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardStatus(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen); + } + + LONG SCardLoader::SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardGetStatusChange(hContext, dwTimeout, rgReaderStates, cReaders); + } + + LONG SCardLoader::SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned); + } + + LONG SCardLoader::SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, const BYTE* pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, BYTE* pbRecvBuffer, LPDWORD pcbRecvLength) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength, pioRecvPci, pbRecvBuffer, pcbRecvLength); + } + + LONG SCardLoader::SCardListReaderGroups(SCARDCONTEXT hContext, LPTSTR mszGroups, LPDWORD pcchGroups) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardListReaderGroups(hContext, mszGroups, pcchGroups); + } + + LONG SCardLoader::SCardListReaders(SCARDCONTEXT hContext, LPCTSTR mszGroups, LPTSTR mszReaders, LPDWORD pcchReaders) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardListReaders(hContext, mszGroups, mszReaders, pcchReaders); + } + + LONG SCardLoader::SCardCancel(SCARDCONTEXT hContext) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardCancel(hContext); + } + + LONG SCardLoader::SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, BYTE* pbAttr, LPDWORD pcbAttrLen) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen); + } + + LONG SCardLoader::SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, const BYTE* pbAttr, DWORD cbAttrLen) + { + Initialize(); + + if (!bInitialized) + throw ScardLibraryInitializationFailed(); + + return scardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen); + } +} \ No newline at end of file diff --git a/src/Common/SCardLoader.h b/src/Common/SCardLoader.h new file mode 100644 index 00000000..b1ab114b --- /dev/null +++ b/src/Common/SCardLoader.h @@ -0,0 +1,125 @@ +#ifndef TC_HEADER_Common_SCardLoader +#define TC_HEADER_Common_SCardLoader + +#include "Platform/PlatformBase.h" + +#ifdef TC_WINDOWS +#include +#include +#else +#ifdef TC_MACOSX +#undef BOOL +#include +#include +#include +#include "reader.h" +typedef LPSCARD_READERSTATE_A LPSCARD_READERSTATE; +using VeraCrypt::byte; +#define BOOL int +#else +#undef BOOL +#include "pcsclite.h" +#include +#include +#include +using VeraCrypt::byte; +#define BOOL int +#endif +#endif + +#ifndef TC_WINDOWS +typedef void* HMODULE; +#define SCARD_CALL_SPEC +#else +#define SCARD_CALL_SPEC WINAPI +#endif + +namespace VeraCrypt +{ + typedef LONG (SCARD_CALL_SPEC *SCardEstablishContextPtr)(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext); + typedef LONG (SCARD_CALL_SPEC *SCardReleaseContextPtr)(SCARDCONTEXT hContext); + typedef LONG (SCARD_CALL_SPEC *SCardIsValidContextPtr)(SCARDCONTEXT hContext); +#ifndef TC_MACOSX + typedef LONG (SCARD_CALL_SPEC *SCardFreeMemoryPtr)(SCARDCONTEXT hContext, LPCVOID pvMem); +#endif + typedef LONG (SCARD_CALL_SPEC *SCardConnectPtr)(SCARDCONTEXT hContext, LPCTSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol); + typedef LONG (SCARD_CALL_SPEC *SCardReconnectPtr)(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol); + typedef LONG (SCARD_CALL_SPEC *SCardDisconnectPtr)(SCARDHANDLE hCard, DWORD dwDisposition); + typedef LONG (SCARD_CALL_SPEC *SCardBeginTransactionPtr)(SCARDHANDLE hCard); + typedef LONG (SCARD_CALL_SPEC *SCardEndTransactionPtr)(SCARDHANDLE hCard, DWORD dwDisposition); + typedef LONG (SCARD_CALL_SPEC *SCardStatusPtr)(SCARDHANDLE hCard, LPTSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, BYTE* pbAtr, LPDWORD pcbAtrLen); + typedef LONG (SCARD_CALL_SPEC *SCardGetStatusChangePtr)(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders); + typedef LONG (SCARD_CALL_SPEC *SCardControlPtr)(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned); + typedef LONG (SCARD_CALL_SPEC *SCardTransmitPtr)(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, const BYTE* pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, BYTE* pbRecvBuffer, LPDWORD pcbRecvLength); + typedef LONG (SCARD_CALL_SPEC *SCardListReaderGroupsPtr)(SCARDCONTEXT hContext, LPTSTR mszGroups, LPDWORD pcchGroups); + typedef LONG (SCARD_CALL_SPEC *SCardListReadersPtr)(SCARDCONTEXT hContext, LPCTSTR mszGroups, LPTSTR mszReaders, LPDWORD pcchReaders); + typedef LONG (SCARD_CALL_SPEC *SCardCancelPtr)(SCARDCONTEXT hContext); + typedef LONG (SCARD_CALL_SPEC *SCardGetAttribPtr)(SCARDHANDLE hCard, DWORD dwAttrId, BYTE* pbAttr, LPDWORD pcbAttrLen); + typedef LONG (SCARD_CALL_SPEC *SCardSetAttribPtr)(SCARDHANDLE hCard, DWORD dwAttrId, const BYTE* pbAttr, DWORD cbAttrLen); + + class SCardLoader + { + protected: + static HMODULE hScardModule; + static SCARDCONTEXT hScardContext; + static SCardEstablishContextPtr scardEstablishContext; + static SCardReleaseContextPtr scardReleaseContext; + static SCardIsValidContextPtr scardIsValidContext; +#ifndef TC_MACOSX + static SCardFreeMemoryPtr scardFreeMemory; +#endif + static SCardConnectPtr scardConnect; + static SCardReconnectPtr scardReconnect; + static SCardDisconnectPtr scardDisconnect; + static SCardBeginTransactionPtr scardBeginTransaction; + static SCardEndTransactionPtr scardEndTransaction; + static SCardStatusPtr scardStatus; + static SCardGetStatusChangePtr scardGetStatusChange; + static SCardControlPtr scardControl; + static SCardTransmitPtr scardTransmit; + static SCardListReaderGroupsPtr scardListReaderGroups; + static SCardListReadersPtr scardListReaders; + static SCardCancelPtr scardCancel; + static SCardGetAttribPtr scardGetAttrib; + static SCardSetAttribPtr scardSetAttrib; + static bool bInitialized; + + public: + static SCARD_IO_REQUEST* scardT0Pci; + static SCARD_IO_REQUEST* scardT1Pci; + static SCARD_IO_REQUEST* scardRawPci; + + SCardLoader() { }; + static void Initialize(); + static void Finalize(); +#ifdef TC_WINDOWS + static wstring GetSCardPath(); +#else + static string GetSCardPath(); +#endif + static SCARDCONTEXT GetSCardContext(); + + static LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext); + static LONG SCardReleaseContext(SCARDCONTEXT hContext); + static LONG SCardIsValidContext(SCARDCONTEXT hContext); +#ifndef TC_MACOSX + static LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem); +#endif + static LONG SCardConnect(SCARDCONTEXT hContext, LPCTSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol); + static LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol); + static LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition); + static LONG SCardBeginTransaction(SCARDHANDLE hCard); + static LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition); + static LONG SCardStatus(SCARDHANDLE hCard, LPTSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, BYTE* pbAtr, LPDWORD pcbAtrLen); + static LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders); + static LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned); + static LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, const BYTE* pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, BYTE* pbRecvBuffer, LPDWORD pcbRecvLength); + static LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPTSTR mszGroups, LPDWORD pcchGroups); + static LONG SCardListReaders(SCARDCONTEXT hContext, LPCTSTR mszGroups, LPTSTR mszReaders, LPDWORD pcchReaders); + static LONG SCardCancel(SCARDCONTEXT hContext); + static LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, BYTE* pbAttr, LPDWORD pcbAttrLen); + static LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, const BYTE* pbAttr, DWORD cbAttrLen); + }; +}; + +#endif // TC_HEADER_Common_SCardLoader \ No newline at end of file diff --git a/src/Common/SCardManager.cpp b/src/Common/SCardManager.cpp new file mode 100644 index 00000000..40578d39 --- /dev/null +++ b/src/Common/SCardManager.cpp @@ -0,0 +1,109 @@ +#include "SCardManager.h" +#include "PCSCException.h" + +namespace VeraCrypt +{ + shared_ptr SCardManager::loader = make_shared(); + + SCardManager::SCardManager() + { + loader->Initialize(); + } + + SCardManager::~SCardManager() + { + loader->Finalize(); + } + + vector SCardManager::GetReaders() + { + vector readers; + LPTSTR mszReaders = NULL; + LPTSTR ptr = NULL; + DWORD dwReaders = 0; + SCARDCONTEXT hScardContext = 0; + LONG lRet = SCARD_S_SUCCESS; + + hScardContext = loader->GetSCardContext(); + lRet = loader->SCardIsValidContext(hScardContext); + if (SCARD_S_SUCCESS != lRet) + { + loader->SCardReleaseContext(hScardContext); + lRet = loader->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hScardContext); + if (lRet != SCARD_S_SUCCESS) + throw PCSCException(lRet); + } + +#ifdef SCARD_AUTOALLOCATE + dwReaders = SCARD_AUTOALLOCATE; + lRet = loader->SCardListReaders(hScardContext, NULL, (LPTSTR)&mszReaders, &dwReaders); +#else + lRet = loader->SCardListReaders(hScardContext, NULL, NULL, &dwReaders); + if (lRet == SCARD_S_SUCCESS) + { + mszReaders = (LPTSTR)calloc(dwReaders, sizeof(char)); + lRet = loader->SCardListReaders(hScardContext, NULL, mszReaders, &dwReaders); + } +#endif + + if (lRet == SCARD_S_SUCCESS && !mszReaders) + { + lRet = SCARD_E_NO_READERS_AVAILABLE; + } + if (lRet == SCARD_E_NO_READERS_AVAILABLE) + { + readers.clear(); + lRet = SCARD_S_SUCCESS; + } + + if (lRet == SCARD_S_SUCCESS && mszReaders) + { + ptr = mszReaders; + while (*ptr) + { +#ifdef TC_WINDOWS + readers.push_back(ptr); +#else + readers.push_back(StringConverter::ToWide(ptr)); +#endif + ptr += +#ifdef TC_WINDOWS + wcslen(ptr) + 1; +#else + strlen(ptr) + 1; +#endif + } + +#ifdef SCARD_AUTOALLOCATE + loader->SCardFreeMemory(hScardContext, mszReaders); +#else + free(mszReaders); +#endif + } + + if (lRet != SCARD_S_SUCCESS) + throw PCSCException(lRet); + + return readers; + } + + shared_ptr SCardManager::GetReader(size_t readerNumber) + { + vector readers; + shared_ptr smartCardReader; + + loader->Initialize(); + + readers = GetReaders(); + if (readerNumber < readers.size()) + { + smartCardReader = make_shared(readers[readerNumber], loader); + if (smartCardReader) + { + return smartCardReader; + } + } + + throw InvalidEMVPath(); + } +} \ No newline at end of file diff --git a/src/Common/SCardManager.h b/src/Common/SCardManager.h new file mode 100644 index 00000000..94a58cb7 --- /dev/null +++ b/src/Common/SCardManager.h @@ -0,0 +1,21 @@ +#ifndef TC_HEADER_Common_SCardManager +#define TC_HEADER_Common_SCardManager + +#include "Platform/PlatformBase.h" +#include "SCardReader.h" + +namespace VeraCrypt +{ + class SCardManager + { + protected: + static shared_ptr loader; + public: + SCardManager(); + virtual ~SCardManager(); + static vector GetReaders(); + static shared_ptr GetReader(size_t readerNumber); + }; +}; + +#endif // TC_HEADER_Common_SCardManager \ No newline at end of file diff --git a/src/Common/SCardReader.cpp b/src/Common/SCardReader.cpp new file mode 100644 index 00000000..3a762415 --- /dev/null +++ b/src/Common/SCardReader.cpp @@ -0,0 +1,681 @@ +#include "SCardReader.h" +#include "PCSCException.h" + +#include + +using namespace std; + +namespace VeraCrypt +{ + void SCardReader::Init(const wstring& szSCReaderName, const shared_ptr scardLoader, const SCARDHANDLE& hCard, const DWORD& dwProtocol, LPCSCARD_IO_REQUEST pIO_Protocol) + { + m_szSCReaderName = szSCReaderName; + if (scardLoader) + { + m_scardLoader = scardLoader; + m_hSCReaderContext = m_scardLoader->GetSCardContext(); + } + else + { + m_scardLoader = NULL; + m_hSCReaderContext = 0; + } + m_hCard = hCard; + m_dwProtocol = dwProtocol; + m_pIO_Protocol = pIO_Protocol; + } + + SCardReader::SCardReader(const wstring &szName, const shared_ptr scardLoader) + { + Init(szName, scardLoader, 0, 0, NULL); + } + + SCardReader::SCardReader(const SCardReader& other) + : m_szSCReaderName(other.m_szSCReaderName), + m_scardLoader(other.m_scardLoader), + m_hSCReaderContext(other.m_hSCReaderContext), + m_hCard(other.m_hCard), + m_dwProtocol(other.m_dwProtocol), + m_pIO_Protocol(other.m_pIO_Protocol) + { + } + + SCardReader::SCardReader(SCardReader&& other) + : m_szSCReaderName(other.m_szSCReaderName), + m_scardLoader(other.m_scardLoader), + m_hSCReaderContext(other.m_hSCReaderContext), + m_hCard(other.m_hCard), + m_dwProtocol(other.m_dwProtocol), + m_pIO_Protocol(other.m_pIO_Protocol) + { + other.Clear(); + } + + SCardReader& SCardReader::operator=(const SCardReader& other) + { + if (this != &other) + { + m_szSCReaderName = other.m_szSCReaderName; + m_scardLoader = other.m_scardLoader; + m_hSCReaderContext = other.m_hSCReaderContext; + m_hCard = other.m_hCard; + m_dwProtocol = other.m_dwProtocol; + m_pIO_Protocol = other.m_pIO_Protocol; + } + return *this; + } + + SCardReader& SCardReader::operator=(SCardReader&& other) + { + if (this != &other) + { + m_szSCReaderName = other.m_szSCReaderName; + m_scardLoader = other.m_scardLoader; + m_hSCReaderContext = other.m_hSCReaderContext; + m_hCard = other.m_hCard; + m_dwProtocol = other.m_dwProtocol; + m_pIO_Protocol = other.m_pIO_Protocol; + + other.Clear(); + } + return *this; + } + + void SCardReader::Clear(void) + { + m_szSCReaderName = L""; + m_scardLoader = NULL; + m_hSCReaderContext = 0; + m_hCard = 0; + m_dwProtocol = 0; + m_pIO_Protocol = NULL; + } + + SCardReader::~SCardReader() + { + Clear(); + } + + const wstring SCardReader::GetNameWide() const + { + return m_szSCReaderName; + } + + const string SCardReader::GetName() const + { + string name = ""; + size_t size = wcstombs(NULL, m_szSCReaderName.c_str(), 0) + 1; + if (size) + { + name.resize(size); + size = wcstombs(&name[0], m_szSCReaderName.c_str(), size); + if (size) + { + name.resize(size); + } + } + return name; + } + + bool SCardReader::IsCardPresent(vector& cardAtr) + { + LONG lRet = SCARD_S_SUCCESS; + SCARD_READERSTATE state; + bool bIsCardPresent = false; +#ifdef TC_WINDOWS + wstring readerName = GetNameWide(); +#else + string readerName = GetName(); +#endif + + if (!m_scardLoader) + throw ScardLibraryInitializationFailed(); + + cardAtr.clear(); + burn(&state, sizeof(SCARD_READERSTATE)); + state.szReader = readerName.c_str(); + + lRet = m_scardLoader->SCardIsValidContext(m_hSCReaderContext); + if (SCARD_S_SUCCESS != lRet) + { + m_scardLoader->SCardReleaseContext(m_hSCReaderContext); + lRet = m_scardLoader->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &m_hSCReaderContext); + if (lRet != SCARD_S_SUCCESS) + throw PCSCException(lRet); + } + + lRet = m_scardLoader->SCardGetStatusChange(m_hSCReaderContext, 0, &state, 1); + if (lRet == SCARD_S_SUCCESS) + { + if ((state.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT && (state.dwEventState & SCARD_STATE_MUTE) == 0) + { + cardAtr.resize(state.cbAtr, 0); + memcpy(cardAtr.data(), state.rgbAtr, state.cbAtr); + bIsCardPresent = true; + burn(&state, sizeof(SCARD_READERSTATE)); + } + } + else + { + throw PCSCException(lRet); + } + + return bIsCardPresent; + } + + bool SCardReader::IsCardPresent() + { + vector dummy; + return IsCardPresent(dummy); + } + + LONG SCardReader::CardHandleStatus() + { + LONG lRet = SCARD_E_INVALID_HANDLE; + + if (!m_scardLoader) + throw ScardLibraryInitializationFailed(); + + if (m_hCard != 0) + { +#ifdef TC_WINDOWS + wchar_t +#else + char +#endif + szName[TC_MAX_PATH] = {}; + BYTE pbAtr[36] = {}; + DWORD dwState, dwProtocol, dwNameLen = TC_MAX_PATH, dwAtrLen = 36; + lRet = m_scardLoader->SCardStatus(m_hCard, szName, &dwNameLen, &dwState, &dwProtocol, pbAtr, &dwAtrLen); + } + + return lRet; + } + + void SCardReader::Connect(DWORD dwProtocolToUse, bool& bHasBeenReset, bool resetAfterConnect) + { + LONG lRet = SCARD_S_SUCCESS; + bHasBeenReset = false; +#ifdef TC_WINDOWS + wstring readerName = GetNameWide(); +#else + string readerName = GetName(); +#endif + + if (!m_scardLoader) + throw ScardLibraryInitializationFailed(); + + lRet = m_scardLoader->SCardIsValidContext(m_hSCReaderContext); + if (SCARD_S_SUCCESS != lRet) + { + m_scardLoader->SCardReleaseContext(m_hSCReaderContext); + lRet = m_scardLoader->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &m_hSCReaderContext); + if (lRet != SCARD_S_SUCCESS) + throw PCSCException(lRet); + } + + if (m_hCard != 0) + { + lRet = CardHandleStatus(); + if (lRet == SCARD_W_RESET_CARD) + { + bHasBeenReset = true; + lRet = m_scardLoader->SCardReconnect( + m_hCard, + SCARD_SHARE_SHARED, + dwProtocolToUse, + SCARD_LEAVE_CARD, + &m_dwProtocol); + if (lRet != SCARD_S_SUCCESS) + { + throw PCSCException(lRet); + } + } + else if (lRet != SCARD_S_SUCCESS) + { + // Card handle is invalid, disconnect and reconnect. + Disconnect(); + } + } + + if (m_hCard == 0) + { + lRet = m_scardLoader->SCardConnect( + m_hSCReaderContext, + readerName.c_str(), + SCARD_SHARE_SHARED, + dwProtocolToUse, + &m_hCard, + &m_dwProtocol); + if (lRet != SCARD_S_SUCCESS) + { + throw PCSCException(lRet); + } + } + + if (m_pIO_Protocol == NULL) + { + if (m_dwProtocol == SCARD_PROTOCOL_T0) + { + m_pIO_Protocol = m_scardLoader->scardT0Pci; + } + else if (m_dwProtocol == SCARD_PROTOCOL_T1) + { + m_pIO_Protocol = m_scardLoader->scardT1Pci; + } + else if (m_dwProtocol == SCARD_PROTOCOL_RAW) + { + m_pIO_Protocol = m_scardLoader->scardRawPci; + } + else + { + lRet = SCARD_E_INVALID_PARAMETER; + Disconnect(); + throw PCSCException(lRet); + } + } + + if (resetAfterConnect) + { + lRet = m_scardLoader->SCardReconnect( + m_hCard, + SCARD_SHARE_SHARED, + m_dwProtocol, + SCARD_RESET_CARD, + &m_dwProtocol); + + if (lRet != SCARD_S_SUCCESS) + { + Disconnect(); + throw PCSCException(lRet); + } + } + } + + bool SCardReader::IsConnected() + { + return m_hCard != 0; + } + + void SCardReader::Disconnect() const + { + if (!m_scardLoader) + throw ScardLibraryInitializationFailed(); + + if (m_hCard != 0) + { + m_scardLoader->SCardDisconnect(m_hCard, SCARD_LEAVE_CARD); + m_dwProtocol = 0; + m_hCard = 0; + m_pIO_Protocol = NULL; + } + } + + LONG SCardReader::SendAPDU(LPCBYTE pbSendBuffer, DWORD cbSendLength, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength, uint16& SW) const + { + if (!m_scardLoader) + throw ScardLibraryInitializationFailed(); + + LONG lRet = m_scardLoader->SCardTransmit(m_hCard, m_pIO_Protocol, pbSendBuffer, cbSendLength, NULL, pbRecvBuffer, pcbRecvLength); + + if (SCARD_S_SUCCESS == lRet) + { + if (*pcbRecvLength < 2) // must be at least = 2 (SW) + { + lRet = SCARD_E_UNEXPECTED; + } + else + { + SW = (pbRecvBuffer[*pcbRecvLength - 2] << 8) | pbRecvBuffer[*pcbRecvLength - 1]; + *pcbRecvLength -= 2; + } + } + + return lRet; + } + + void SCardReader::BeginTransaction() + { + LONG lRet = 0; + + if (!m_scardLoader) + throw ScardLibraryInitializationFailed(); + + if (m_hCard != 0) + { +#ifndef _DEBUG + lRet = m_scardLoader->SCardBeginTransaction(m_hCard); + if (lRet != SCARD_S_SUCCESS) + { + throw PCSCException(lRet); + } +#else + lRet = SCARD_S_SUCCESS; +#endif + } + else + { + lRet = SCARD_E_INVALID_HANDLE; + throw PCSCException(lRet); + } + } + + void SCardReader::EndTransaction() + { + LONG lRet = 0; + + if (!m_scardLoader) + throw ScardLibraryInitializationFailed(); + + if (m_hCard != 0) + { +#ifndef _DEBUG + lRet = m_scardLoader->SCardEndTransaction(m_hCard, SCARD_LEAVE_CARD); + if (lRet != SCARD_S_SUCCESS) + { + throw PCSCException(lRet); + } +#endif + lRet = SCARD_S_SUCCESS; + } + else + { + lRet = SCARD_E_INVALID_HANDLE; + throw PCSCException(lRet); + } + } + + void SCardReader::ApduProcessData(CommandAPDU commandAPDU, ResponseAPDU& responseAPDU) const + { + LONG lRet = 0; + uint16 SW = 0; + + uint32 nc = 0, ne = 0; + + bool expectingResponse = false; + bool useExtendedAPDU = false; + + size_t indexOfLe = 0; + size_t indexOfLcData = 0; + + vector pbSendBuffer; + vector pbRecvBuffer; + DWORD cbSendLength = 0; + DWORD cbRecvLength = 0; + + responseAPDU.clear(); + + if (!commandAPDU.isValid()) + { + throw CommandAPDUNotValid(SRC_POS, commandAPDU.getErrorStr()); + } + + // See whether the CommandAPDU is extended or not + useExtendedAPDU = commandAPDU.isExtended(); + + // If T != 1, cannot use Extended-APDU + if (m_dwProtocol != SCARD_PROTOCOL_T1 && useExtendedAPDU) + { + throw ExtendedAPDUNotSupported(); + } + + // Set some needed vars + nc = commandAPDU.getNc(); + ne = commandAPDU.getNe(); + pbSendBuffer.resize(useExtendedAPDU ? extendedAPDUMaxSendSize : shortAPDUMaxSendSize, 0); + pbRecvBuffer.resize(useExtendedAPDU ? extendedAPDUMaxRecvSize : shortAPDUMaxRecvSize, 0); + cbRecvLength = (DWORD)pbRecvBuffer.size(); + + if (nc > (useExtendedAPDU ? extendedAPDUMaxTransSize : shortAPDUMaxTransSize) - 1) // Max = 255 or 65535 + { + std::string errStr = vformat("Nc > %d", (useExtendedAPDU ? extendedAPDUMaxTransSize : shortAPDUMaxTransSize) - 1); + throw CommandAPDUNotValid(SRC_POS, commandAPDU.getErrorStr()); + } + if (ne > (useExtendedAPDU ? extendedAPDUMaxTransSize : shortAPDUMaxTransSize)) // Max = 256 or 65536 + { + std::string errStr = vformat("Ne > %d", (useExtendedAPDU ? extendedAPDUMaxTransSize : shortAPDUMaxTransSize) - 1); + throw CommandAPDUNotValid(SRC_POS, commandAPDU.getErrorStr()); + } + + // Create and populate buffer to send to card + pbSendBuffer[0] = commandAPDU.getCLA(); + pbSendBuffer[1] = commandAPDU.getINS(); + pbSendBuffer[2] = commandAPDU.getP1(); + pbSendBuffer[3] = commandAPDU.getP2(); + if (nc == 0) + { + if (ne == 0) + { + // case 1 + cbSendLength = 4; + } + else + { + expectingResponse = true; + + // case 2s or 2e + if (ne <= 256) + { + // case 2s + // 256 is encoded as 0x00 + pbSendBuffer[4] = (BYTE)ne; + indexOfLe = 4; + cbSendLength = 4 + 1; // header || Le (1 byte) + } + else + { + // case 2e + // 65536 is encoded as 0x00 0x00 0x00 + BYTE l1, l2; + if (ne == 65536) + { + l1 = 0; + l2 = 0; + } + else + { + l1 = (BYTE)(ne >> 8); + l2 = (BYTE)ne; + } + pbSendBuffer[4] = 0x00; + pbSendBuffer[5] = l1; + pbSendBuffer[6] = l2; + cbSendLength = 4 + 3; // header || Le (3 bytes) + } + } + } + else + { + if (ne == 0) + { + // case 3s or 3e + if (nc <= 255) + { + // case 3s + pbSendBuffer[4] = (BYTE)nc; + indexOfLcData = 5; + cbSendLength = 4 + 1 + nc; // header || Lc (1 byte) || Data + memcpy(&pbSendBuffer[indexOfLcData], commandAPDU.getData().data(), nc); + } + else + { + // case 3e + pbSendBuffer[4] = 0; + pbSendBuffer[5] = (BYTE)(nc >> 8); + pbSendBuffer[6] = (BYTE)nc; + indexOfLcData = 7; + cbSendLength = 4 + 3 + nc; // header || Lc (3 bytes) || Data + memcpy(&pbSendBuffer[indexOfLcData], commandAPDU.getData().data(), nc); + } + } + else + { + expectingResponse = true; + + // case 4s or 4e + if ((nc <= 255) && (ne <= 256)) + { + // case 4s + pbSendBuffer[4] = (BYTE)nc; + indexOfLcData = 5; + cbSendLength = 4 + 1 + nc + 1; // header || Lc (1 byte) || Data || Le (1 byte) + memcpy(&pbSendBuffer[indexOfLcData], commandAPDU.getData().data(), nc); + pbSendBuffer[indexOfLcData + nc] = (ne != 256) ? (BYTE)ne : 0; + indexOfLe = indexOfLcData + nc; + } + else + { + // case 4e + pbSendBuffer[4] = 0; + pbSendBuffer[5] = (BYTE)(nc >> 8); + pbSendBuffer[6] = (BYTE)nc; + indexOfLcData = 7; + cbSendLength = 4 + 3 + nc + 2; // header || Lc (3 bytes) || Data || Le (2 bytes) + memcpy(&pbSendBuffer[indexOfLcData], commandAPDU.getData().data(), nc); + if (ne != 65536) + { + size_t leOfs = cbSendLength - 2; + pbSendBuffer[leOfs] = (BYTE)(ne >> 8); + pbSendBuffer[leOfs + 1] = (BYTE)ne; + }// 65536 is 0x00 0x00 and the buffer has already been initialized with 0s + } + } + } + cbRecvLength = (DWORD)pbRecvBuffer.size(); + lRet = SendAPDU(pbSendBuffer.data(), cbSendLength, pbRecvBuffer.data(), &cbRecvLength, SW); + if (lRet != SCARD_S_SUCCESS) + { + responseAPDU.setSW(SW); + goto end; + } + + // If Expecting Response + if (expectingResponse) + { + // If Short-APDU + if (!useExtendedAPDU) + { + // If SW != 0x9000 + if (SW != SW_NO_ERROR) + { + // If SW == 0x6CXX => Le larger than actual available data on ICC, SW2 contains the appropriate value + if ((BYTE)(SW >> 8) == (BYTE)(SW_CORRECT_LENGTH_00 >> 8)) // 0x6C + { + pbSendBuffer[indexOfLe] = (BYTE)(SW & 0x00FF); + cbRecvLength = (DWORD)pbRecvBuffer.size(); + lRet = SendAPDU(pbSendBuffer.data(), cbSendLength, pbRecvBuffer.data(), &cbRecvLength, SW); + + if (lRet != SCARD_S_SUCCESS) + { + responseAPDU.setSW(SW); + goto end; + } + } + + // If SW != 0x61XX (GET RESPONSE REMAINING BYTES) => there was an unexpected error + if (SW != SW_NO_ERROR && ((BYTE)(SW >> 8) != (BYTE)(SW_BYTES_REMAINING_00 >> 8))) // 0x61 + { + responseAPDU.setSW(SW); + goto end; + } + } + + // Get response data from APDU Response + // Response might be complete (1 APDU, <= 256 bytes : SW = 0x9000) or needs a Get Response to get the rest (1st APDU, == 256 bytes, SW = 0x61XX) + if (cbRecvLength) + responseAPDU.appendData(pbRecvBuffer.data(), cbRecvLength); + + // Send get response to get the rest as long as we receive SW == 0x61XX + // In case of PACE, this is never the case + while ((lRet == SCARD_S_SUCCESS) && ((BYTE)(SW >> 8) == (BYTE)(SW_BYTES_REMAINING_00 >> 8))) // 0x61 + { + // GET RESPONSE APDU + pbSendBuffer[0] = commandAPDU.getCLA(); + pbSendBuffer[1] = INS_GET_RESPONSE; + pbSendBuffer[2] = 0x00; + pbSendBuffer[3] = 0x00; + pbSendBuffer[4] = (BYTE)(SW & 0x00FF); + cbSendLength = 5; + + cbRecvLength = (DWORD)pbRecvBuffer.size(); + lRet = SendAPDU(pbSendBuffer.data(), cbSendLength, pbRecvBuffer.data(), &cbRecvLength, SW); + + if (lRet == SCARD_S_SUCCESS) + { + if ((SW != SW_NO_ERROR) && ((SW >> 8) != (BYTE)(SW_BYTES_REMAINING_00 >> 8))) // 0x61 + { + responseAPDU.clear(); + responseAPDU.setSW(SW); + } + else + responseAPDU.appendData(pbRecvBuffer.data(), cbRecvLength); + } + } + } + // If Extended-APDU (SW = 0x6CXX and SW = 0x61XX are handled by the low-level driver + smart card reader) + else + { + // If SW != 0x9000 => there was an unexpected error + if (SW != SW_NO_ERROR) + { + responseAPDU.setSW(SW); + goto end; + } + + // Response is complete in 1 ResponseAPDU + if (cbRecvLength) + responseAPDU.appendData(pbRecvBuffer.data(), cbRecvLength); + } + + if (lRet == SCARD_S_SUCCESS) + { + responseAPDU.setSW(SW); + } + } + else + { + responseAPDU.setSW(SW); + } + + end: + + burn(pbSendBuffer.data(), pbSendBuffer.size()); + burn(pbRecvBuffer.data(), pbRecvBuffer.size()); + + if (lRet != SCARD_S_SUCCESS) + throw PCSCException(lRet); + } + + void SCardReader::GetATRFromHandle(vector& atrValue) + { + vector pbATR; + DWORD cByte = 0; + LONG lRet = 0; + + atrValue.clear(); + + if (!m_scardLoader) + throw ScardLibraryInitializationFailed(); + + lRet = m_scardLoader->SCardGetAttrib(m_hCard, SCARD_ATTR_ATR_STRING, NULL, &cByte); + if (lRet == SCARD_S_SUCCESS) + { + pbATR.resize(cByte, 0); + lRet = m_scardLoader->SCardGetAttrib(m_hCard, SCARD_ATTR_ATR_STRING, pbATR.data(), &cByte); + + if (lRet == SCARD_S_SUCCESS) + { + atrValue = pbATR; + } + else + { + throw PCSCException(lRet); + } + } + else + { + throw PCSCException(lRet); + } + } +} + diff --git a/src/Common/SCardReader.h b/src/Common/SCardReader.h new file mode 100644 index 00000000..95586963 --- /dev/null +++ b/src/Common/SCardReader.h @@ -0,0 +1,200 @@ +#ifndef TC_HEADER_Common_SCardReader +#define TC_HEADER_Common_SCardReader + +#include "Platform/PlatformBase.h" +#include "CommandAPDU.h" +#include "ResponseAPDU.h" +#include "SCardLoader.h" + +namespace VeraCrypt +{ + /* ================================================================================================ */ + /* SW values */ + /* ================================================================================================ */ + const uint16 SW_BYTES_REMAINING_00 = (uint16)0x6100; + const uint16 SW_STATE_NON_VOLATILE_MEMORY_UNCHANGED_NO_INFORMATION_GIVEN = (uint16)0x6200; + const uint16 SW_END_OF_FILE = (uint16)0x6282; + const uint16 SW_LESS_DATA_RESPONDED_THAN_REQUESTED = (uint16)0x6287; + const uint16 SW_NON_VOLATILE_MEMORY_CHANGED_NO_INFORMATION_GIVEN = (uint16)0x6300; + const uint16 SW_NON_VOLATILE_MEMORY_CHANGED_FILE_FILLED_UP_BY_LAST_WRITE = (uint16)0x6381; + const uint16 SW_NON_VOLATILE_MEMORY_CHANGED_COUNTER_0 = (uint16)0x63C0; + const uint16 SW_WRONG_LENGTH = (uint16)0x6700; + const uint16 SW_LOGICAL_CHANNEL_NOT_SUPPORTED = (uint16)0x6881; + const uint16 SW_SECURE_MESSAGING_NOT_SUPPORTED = (uint16)0x6882; + const uint16 SW_LAST_COMMAND_EXPECTED = (uint16)0x6883; + const uint16 SW_SECURITY_STATUS_NOT_SATISFIED = (uint16)0x6982; + const uint16 SW_FILE_INVALID = (uint16)0x6983; + const uint16 SW_DATA_INVALID = (uint16)0x6984; + const uint16 SW_CONDITIONS_NOT_SATISFIED = (uint16)0x6985; + const uint16 SW_COMMAND_NOT_ALLOWED = (uint16)0x6986; + const uint16 SW_EXPECTED_SM_DATA_OBJECTS_MISSING = (uint16)0x6987; + const uint16 SW_SM_DATA_OBJECTS_INCORRECT = (uint16)0x6988; + const uint16 SW_APPLET_SELECT_FAILED = (uint16)0x6999; + const uint16 SW_KEY_USAGE_ERROR = (uint16)0x69C1; + const uint16 SW_WRONG_DATA = (uint16)0x6A80; + const uint16 SW_FILEHEADER_INCONSISTENT = (uint16)0x6A80; + const uint16 SW_FUNC_NOT_SUPPORTED = (uint16)0x6A81; + const uint16 SW_FILE_NOT_FOUND = (uint16)0x6A82; + const uint16 SW_RECORD_NOT_FOUND = (uint16)0x6A83; + const uint16 SW_FILE_FULL = (uint16)0x6A84; + const uint16 SW_OUT_OF_MEMORY = (uint16)0x6A84; + const uint16 SW_INCORRECT_P1P2 = (uint16)0x6A86; + const uint16 SW_KEY_NOT_FOUND = (uint16)0x6A88; + const uint16 SW_WRONG_P1P2 = (uint16)0x6B00; + const uint16 SW_CORRECT_LENGTH_00 = (uint16)0x6C00; + const uint16 SW_INS_NOT_SUPPORTED = (uint16)0x6D00; + const uint16 SW_CLA_NOT_SUPPORTED = (uint16)0x6E00; + const uint16 SW_UNKNOWN = (uint16)0x6F00; + const uint16 SW_CARD_TERMINATED = (uint16)0x6FFF; + const uint16 SW_NO_ERROR = (uint16)0x9000; + + /* ================================================================================================ */ + /* CLA values */ + /* ================================================================================================ */ + const byte CLA_ISO7816 = (byte)0x00; + const byte CLA_COMMAND_CHAINING = (byte)0x10; + + /* ================================================================================================ */ + /* INS values */ + /* ================================================================================================ */ + const byte INS_ERASE_BINARY = 0x0E; + const byte INS_VERIFY = 0x20; + const byte INS_CHANGE_CHV = 0x24; + const byte INS_UNBLOCK_CHV = 0x2C; + const byte INS_DECREASE = 0x30; + const byte INS_INCREASE = 0x32; + const byte INS_DECREASE_STAMPED = 0x34; + const byte INS_REHABILITATE_CHV = 0x44; + const byte INS_MANAGE_CHANNEL = 0x70; + const byte INS_EXTERNAL_AUTHENTICATE = (byte)0x82; + const byte INS_MUTUAL_AUTHENTICATE = (byte)0x82; + const byte INS_GET_CHALLENGE = (byte)0x84; + const byte INS_ASK_RANDOM = (byte)0x84; + const byte INS_GIVE_RANDOM = (byte)0x86; + const byte INS_INTERNAL_AUTHENTICATE = (byte)0x88; + const byte INS_SEEK = (byte)0xA2; + const byte INS_SELECT = (byte)0xA4; + const byte INS_SELECT_FILE = (byte)0xA4; + const byte INS_CLOSE_APPLICATION = (byte)0xAC; + const byte INS_READ_BINARY = (byte)0xB0; + const byte INS_READ_BINARY2 = (byte)0xB1; + const byte INS_READ_RECORD = (byte)0xB2; + const byte INS_READ_RECORD2 = (byte)0xB3; + const byte INS_READ_RECORDS = (byte)0xB2; + const byte INS_READ_BINARY_STAMPED = (byte)0xB4; + const byte INS_READ_RECORD_STAMPED = (byte)0xB6; + const byte INS_GET_RESPONSE = (byte)0xC0; + const byte INS_ENVELOPE = (byte)0xC2; + const byte INS_GET_DATA = (byte)0xCA; + const byte INS_WRITE_BINARY = (byte)0xD0; + const byte INS_WRITE_RECORD = (byte)0xD2; + const byte INS_UPDATE_BINARY = (byte)0xD6; + const byte INS_LOAD_KEY_FILE = (byte)0xD8; + const byte INS_PUT_DATA = (byte)0xDA; + const byte INS_UPDATE_RECORD = (byte)0xDC; + const byte INS_CREATE_FILE = (byte)0xE0; + const byte INS_APPEND_RECORD = (byte)0xE2; + const byte INS_DELETE_FILE = (byte)0xE4; + const byte INS_PSO = (byte)0x2A; + const byte INS_MSE = (byte)0x22; + + /* ================================================================================================ */ + /* EMV values */ + /* ================================================================================================ */ + const uint16 EMV_CPLC_TAG = (uint16)0x9F7F; + const uint16 EMV_ICC_PK_CERT_TAG = (uint16)0x9F46; + const uint16 EMV_FCI_ISSUER_DISCRETIONARY_DATA_TAG = (uint16)0xBF0C; + const byte EMV_ISS_PK_CERT_TAG = (byte)0x90; + const byte EMV_PAN_TAG = (byte)0x5A; + const byte EMV_FCI_TAG = (byte)0x6F; + const byte EMV_DFNAME_TAG = (byte)0x84; + const byte EMV_FCI_ISSUER_TAG = (byte)0xA5; + const byte EMV_DIRECTORY_ENTRY_TAG = (byte)0x61; + const byte EMV_SFI_TAG = (byte)0x88; + const byte EMV_TEMPLATE_TAG = (byte)0x70; + const byte EMV_AID_TAG = (byte)0x4F; + const byte EMV_LABEL_TAG = (byte)0x50; + const byte EMV_PRIORITY_TAG = (byte)0x87; + const byte EMV_PSE1[] = { 0x31, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31 }; // "1PAY.SYS.DDF01" (contact) + const byte EMV_PSE2[] = { 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31 }; // "2PAY.SYS.DDF01" (contactless) + + /* ================================================================================================ */ + + class SCardReader + { + protected: + + wstring m_szSCReaderName; + + shared_ptr m_scardLoader; + mutable SCARDCONTEXT m_hSCReaderContext; + mutable SCARDHANDLE m_hCard; + mutable DWORD m_dwProtocol; + mutable LPCSCARD_IO_REQUEST m_pIO_Protocol; + + void Init(const wstring& szSCReaderName, const shared_ptr scardLoader, const SCARDHANDLE& hCard, const DWORD& dwProtocol, LPCSCARD_IO_REQUEST pIO_Protocol); + + public: + + /* Card variables */ + // Max Command APDU total size ; Typically either 261 (short) or 65544 (extended) + // Max Response APDU total size ; Typically either 258 (short) or 65538 (extended) + // Max Response APDU data size ; Ne ; Typically either 256 (short : 0x00) of 65536 (extended : 0x0000) + const static uint32 shortAPDUMaxSendSize = 261; + const static uint32 shortAPDUMaxRecvSize = 258; + const static uint32 shortAPDUMaxTransSize = 256; + const static uint32 extendedAPDUMaxSendSize = 65544; + const static uint32 extendedAPDUMaxRecvSize = 65538; + const static uint32 extendedAPDUMaxTransSize = 65536; + + // ------------------------------------------------------------------------------------------------------------------------------------- // + // Ctors, dtors + // ------------------------------------------------------------------------------------------------------------------------------------- // + + SCardReader(const wstring &szName, const shared_ptr scardLoader); + + SCardReader(const SCardReader& other); + SCardReader(SCardReader&& other); + SCardReader& operator = (const SCardReader& other); + SCardReader& operator = (SCardReader&& other); + + void Clear(void); + + ~SCardReader(); + + // ------------------------------------------------------------------------------------------------------------------------------------- // + // Getters & Setters + // ------------------------------------------------------------------------------------------------------------------------------------- // + + const wstring GetNameWide() const; + const string GetName() const; + + // ------------------------------------------------------------------------------------------------------------------------------------- // + // Card Connection management methods + // ------------------------------------------------------------------------------------------------------------------------------------- // + + bool IsCardPresent(vector& cardAtr); + bool IsCardPresent(); + + LONG CardHandleStatus(); + + void Connect(DWORD dwProtocolToUse, bool& bHasBeenReset, bool resetAfterConnect = false); + bool IsConnected(); + void Disconnect() const; + + LONG SendAPDU(LPCBYTE pbSendBuffer, + DWORD cbSendLength, + LPBYTE pbRecvBuffer, + LPDWORD pcbRecvLength, + uint16& SW) const; + + void BeginTransaction(); + void EndTransaction(); + + void ApduProcessData(CommandAPDU commandAPDU, ResponseAPDU& responseAPDU) const; + + void GetATRFromHandle(vector& atrValue); + }; +}; + +#endif // TC_HEADER_Common_SCardReader \ No newline at end of file diff --git a/src/Common/SecurityToken.h b/src/Common/SecurityToken.h index 0d671dcc..4dff42fa 100644 --- a/src/Common/SecurityToken.h +++ b/src/Common/SecurityToken.h @@ -59,6 +59,7 @@ namespace VeraCrypt { struct SecurityTokenInfo: TokenInfo { + virtual ~SecurityTokenInfo() {}; virtual BOOL isEditable() const {return true;} CK_FLAGS Flags; @@ -71,10 +72,13 @@ namespace VeraCrypt SecurityTokenKeyfile(const TokenKeyfilePath& path); + virtual ~SecurityTokenKeyfile() {} + operator TokenKeyfilePath () const; void GetKeyfileData(vector& keyfileData) const; + string IdUtf8; CK_OBJECT_HANDLE Handle; }; diff --git a/src/Common/TLVParser.cpp b/src/Common/TLVParser.cpp index bda9dec0..9a177007 100644 --- a/src/Common/TLVParser.cpp +++ b/src/Common/TLVParser.cpp @@ -3,177 +3,185 @@ using namespace std; -/* TLV node structure creation */ -shared_ptr TLVParser::TLV_CreateNode() +namespace VeraCrypt { - shared_ptr node= shared_ptr(new TLVNode); - memset(node.get(),0,sizeof(*node)); - return node; -} - -/* Check if the bit is correct */ -uint16_t TLVParser::CheckBit(unsigned char value, int bit){ - unsigned char bitvalue[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; - - if((bit >= 1)&&(bit <= 8)){ - if(value & bitvalue[bit-1]) { - return (1); - } - else { - return (0); - } - } - else{ - throw TLVException("FILE:"+string(__FILE__)+"LINE: "+to_string(static_cast((__LINE__)))+" fonction parameter incorrect! bit=["+to_string(static_cast(bit))); - return(2); - } -} - -/* Parsing one TLV node */ -shared_ptr TLVParser::TLV_Parse_One(unsigned char* buf,int size){ - int index = 0; - int i; - unsigned char tag1,tag2,tagsize; - unsigned char len,lensize; - unsigned char* value; - shared_ptr node = TLV_CreateNode(); - - tag1 = tag2 = 0; - tagsize = 1; - tag1 = buf[index++]; - if((tag1 & 0x1f) == 0x1f){ - tagsize++; - tag2 = buf[index++]; - //tag2 b8 must be 0! - } - if(tagsize == 1) { - node->Tag = tag1; - } - else { - node->Tag = (tag1 << 8) + tag2; - } - node->TagSize = tagsize; - - //SubFlag - node->SubFlag = CheckBit(tag1,6); - - //L zone - len = 0; - lensize = 1; - len = buf[index++]; - if(CheckBit(len,8) == 0){ - node->Length = len; - } - else{ - lensize = len & 0x7f; - len = 0; - for(i=0;iLength = len; - node->LengthSize = lensize; - - //V zone - value = new unsigned char[len]; - std::copy(buf+index,buf+index+len,value); - node->Value = value; - index += len; - - if(index < size){ - node->MoreFlag = 1; - } - else if(index == size){ - node->MoreFlag = 0; - } - else{ - throw TLVException("Parse Error! index="+to_string(static_cast(index))+"size="+to_string(static_cast(size))); - } - - return node; -} - -/* Parsing all sub-nodes (in width not in depth) of a given parent node */ -int TLVParser::TLV_Parse_SubNodes(shared_ptr parent){ - int sublen = 0; - int i; - - //No sub-nodes - if(parent->SubFlag == 0) - return 0; - - for(i=0;iSubCount;i++) + /* TLV node structure creation */ + shared_ptr TLVParser::TLV_CreateNode() { - sublen += (parent->Sub[i]->TagSize + parent->Sub[i]->Length + parent->Sub[i]->LengthSize); + shared_ptr node = shared_ptr(new TLVNode()); + return node; } - if(sublen < parent->Length) + /* Check if the bit is correct */ + uint16 TLVParser::CheckBit(byte value, int bit) { - shared_ptr subnode = TLV_Parse_One(parent->Value+sublen,parent->Length-sublen); - parent->Sub[parent->SubCount++] = subnode; - return subnode->MoreFlag; - } - else - { - return 0; - } -} + unsigned char bitvalue[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; -/* Recursive function to parse all nodes starting from a root parent node */ -void TLVParser::TLV_Parse_Sub(shared_ptr parent) -{ - int i; - if(parent->SubFlag != 0) - { - //Parse all sub nodes. - while(TLV_Parse_SubNodes(parent) != 0); - - for(i=0;iSubCount;i++) + if ((bit >= 1) && (bit <= 8)) { - if(parent->Sub[i]->SubFlag != 0) + if (value & bitvalue[bit-1]) { - TLV_Parse_Sub(parent->Sub[i]); + return (1); + } + else + { + return (0); + } + } + else + { + throw TLVException("FILE:"+string(__FILE__)+"LINE: "+to_string(static_cast((__LINE__)))+" fonction parameter incorrect! bit=["+to_string(static_cast(bit))); + //return(2); + } + } + + /* Parsing one TLV node */ + shared_ptr TLVParser::TLV_Parse_One(byte* buf, size_t size) + { + size_t index = 0; + size_t i = 0; + byte tag1, tag2, tagsize; + byte len, lensize; + shared_ptr> value = make_shared>(); + shared_ptr node = TLV_CreateNode(); + + tag1 = tag2 = 0; + tagsize = 1; + tag1 = buf[index++]; + if ((tag1 & 0x1f) == 0x1f) + { + tagsize++; + tag2 = buf[index++]; + //tag2 b8 must be 0! + } + if (tagsize == 1) + { + node->Tag = tag1; + } + else + { + node->Tag = (tag1 << 8) + tag2; + } + node->TagSize = tagsize; + + //SubFlag + node->SubFlag = CheckBit(tag1,6); + + //L zone + len = 0; + lensize = 1; + len = buf[index++]; + if (CheckBit(len,8) == 0) + { + node->Length = len; + } + else + { + lensize = len & 0x7f; + len = 0; + for (i = 0; i < lensize; i++) + { + len += (uint16)buf[index++] << (i*8); + } + lensize++; + } + node->Length = len; + node->LengthSize = lensize; + + //V zone + value->resize(len); + memcpy(value->data(), buf + index, len); + node->Value = value; + index += len; + + if (index < size) + { + node->MoreFlag = 1; + } + else if(index == size) + { + node->MoreFlag = 0; + } + else + { + throw TLVException("Parse Error! index="+to_string(static_cast(index))+"size="+to_string(static_cast(size))); + } + + return node; + } + + /* Parsing all sub-nodes (in width not in depth) of a given parent node */ + int TLVParser::TLV_Parse_SubNodes(shared_ptr parent) + { + uint16 sublen = 0; + size_t i; + + //No sub-nodes + if (parent->SubFlag == 0) + return 0; + + for (i = 0; i < parent->Subs->size(); i++) + { + sublen += (parent->Subs->at(i)->TagSize + parent->Subs->at(i)->Length + parent->Subs->at(i)->LengthSize); + } + + if (sublen < parent->Value->size()) + { + shared_ptr subnode = TLV_Parse_One(parent->Value->data() + sublen, parent->Value->size() - sublen); + parent->Subs->push_back(subnode); + return subnode->MoreFlag; + } + else + { + return 0; + } + } + + /* Recursive function to parse all nodes starting from a root parent node */ + void TLVParser::TLV_Parse_Sub(shared_ptr parent) + { + size_t i; + if (parent->SubFlag != 0) + { + // Parse all sub nodes. + while (TLV_Parse_SubNodes(parent) != 0); + + for (i = 0; i < parent->Subs->size(); i++) + { + if (parent->Subs->at(i)->SubFlag != 0) + { + TLV_Parse_Sub(parent->Subs->at(i)); + } } } } - return; -} -/* Parsing TLV from a buffer and constructing TLV structure */ -shared_ptr TLVParser::TLV_Parse(unsigned char* buf,int size) -{ - shared_ptr node = TLV_Parse_One(buf,size); - TLV_Parse_Sub(node); - - return node; -} - -/* Finding a TLV node with a particular tag */ -shared_ptr TLVParser::TLV_Find(shared_ptr node,uint16_t tag){ - int i; - shared_ptr tmpnode; - if(node->Tag == tag) + /* Parsing TLV from a buffer and constructing TLV structure */ + shared_ptr TLVParser::TLV_Parse(byte* buf, size_t size) { + shared_ptr node = TLV_Parse_One(buf, size); + TLV_Parse_Sub(node); + return node; } - for(i=0;iSubCount;i++) - { - tmpnode = NULL; - tmpnode = TLV_Find(node->Sub[i],tag); - if(tmpnode != NULL){ - return tmpnode; - } - } - if(node->Next) - { - tmpnode = NULL; - tmpnode = TLV_Find(node->Next,tag); - if(tmpnode != NULL){ - return tmpnode; - } - } - - return nullptr; -} + /* Finding a TLV node with a particular tag */ + shared_ptr TLVParser::TLV_Find(shared_ptr node, uint16 tag) + { + size_t i = 0; + shared_ptr tmpnode = NULL; + if (node->Tag == tag) + { + return node; + } + for (i = 0; i < node->Subs->size(); i++) + { + tmpnode = TLV_Find(node->Subs->at(i),tag); + if (tmpnode != NULL) + { + return tmpnode; + } + } + return NULL; + } +} \ No newline at end of file diff --git a/src/Common/TLVParser.h b/src/Common/TLVParser.h index e25e429f..b989ca41 100644 --- a/src/Common/TLVParser.h +++ b/src/Common/TLVParser.h @@ -1,80 +1,80 @@ -// -// Created by bshp on 1/20/23. -// +#ifndef TC_HEADER_Common_TLVPARSER +#define TC_HEADER_Common_TLVPARSER -#ifndef ICC_EXTRACTOR_TLVPARSER_H -#define ICC_EXTRACTOR_TLVPARSER_H -#include -#include -#include -#include -#include -#include -#include "iostream" +#include "Platform/PlatformBase.h" #include "Tcdefs.h" -using namespace std; -struct TLVNode{ - uint16_t Tag; /* T */ - uint16_t Length; /* L */ - unsigned char* Value; /* V */ - unsigned char TagSize; - unsigned char LengthSize; - uint16_t MoreFlag; /* Used In Sub */ - uint16_t SubFlag; /* Does it have sub-nodes? */ - uint16_t SubCount; - shared_ptr Sub[256]; - shared_ptr Next; - ~TLVNode() { - burn(Value, Length); - delete Value; - } -}; - -class TLVParser{ -private : - - /* TLV node structure creation */ - static shared_ptr TLV_CreateNode(); - - /* Check if the bit is correct */ - static uint16_t CheckBit(unsigned char value, int bit); - - /* Parsing one TLV node */ - static shared_ptr TLV_Parse_One(unsigned char* buf,int size); - - /* Parsing all TLV nodes */ - static int TLV_Parse_SubNodes(shared_ptr parent); - - /* Parsing all sub-nodes (in width not in depth) of a given parent node */ - static int TLV_Parse_All(shared_ptr parent); - - /* Recursive function to parse all nodes starting from a root parent node */ - static void TLV_Parse_Sub(shared_ptr parent); - -public: - - /* Parsing TLV from a buffer and constructing TLV structure */ - static shared_ptr TLV_Parse(unsigned char* buf,int size); - - /* Finding a TLV node with a particular tag */ - static shared_ptr TLV_Find(shared_ptr node,uint16_t tag); -}; - -/* The definition of the exception class related to the TLV parsing */ -class TLVException +namespace VeraCrypt { -public: - TLVException(std::string errormessage): m_errormessage(errormessage){} - - /* Get the error message */ - inline std::string ErrorMessage() const + struct TLVNode { - return m_errormessage; - } + uint16 Tag; /* T */ + uint16 Length; /* L */ + shared_ptr> Value; /* V */ + byte TagSize; + byte LengthSize; + uint16 MoreFlag; /* Used In Sub */ + uint16 SubFlag; /* Does it have sub-nodes? */ + shared_ptr>> Subs; -protected: - std::string m_errormessage; -}; + TLVNode() : Tag(0), Length(0), TagSize(0), LengthSize(0), MoreFlag(0), SubFlag(0) + { + Value = make_shared>(); + Subs = make_shared>>(); + } -#endif //ICC_EXTRACTOR_TLVPARSER_H + ~TLVNode() + { + burn(Value->data(), Value->size()); + } + }; + + class TLVParser + { + private : + + /* TLV node structure creation */ + static shared_ptr TLV_CreateNode(); + + /* Check if the bit is correct */ + static uint16 CheckBit(byte value, int bit); + + /* Parsing one TLV node */ + static shared_ptr TLV_Parse_One(byte* buf, size_t size); + + /* Parsing all TLV nodes */ + static int TLV_Parse_SubNodes(shared_ptr parent); + + /* Parsing all sub-nodes (in width not in depth) of a given parent node */ + static int TLV_Parse_All(shared_ptr parent); + + /* Recursive function to parse all nodes starting from a root parent node */ + static void TLV_Parse_Sub(shared_ptr parent); + + public: + + /* Parsing TLV from a buffer and constructing TLV structure */ + static shared_ptr TLV_Parse(byte* buf, size_t size); + + /* Finding a TLV node with a particular tag */ + static shared_ptr TLV_Find(shared_ptr node, uint16 tag); + }; + + /* The definition of the exception class related to the TLV parsing */ + class TLVException + { + public: + TLVException(std::string errormessage): m_errormessage(errormessage){} + + /* Get the error message */ + inline std::string ErrorMessage() const + { + return m_errormessage; + } + + protected: + std::string m_errormessage; + }; +} + +#endif //TC_HEADER_Common_TLVPARSER diff --git a/src/Common/Token.cpp b/src/Common/Token.cpp index 5da677de..17fce78b 100644 --- a/src/Common/Token.cpp +++ b/src/Common/Token.cpp @@ -17,62 +17,94 @@ #include "SecurityToken.h" #include "EMVToken.h" +#include "PCSCException.h" #include "iostream" using namespace std; namespace VeraCrypt { - vector> Token::GetAvailableKeyfiles(bool EMVOption) { + vector> Token::GetAvailableKeyfiles(bool isEMVSupportEnabled) + { vector> availableKeyfiles; bool securityTokenLibraryInitialized = true; + bool scardLibraryInitialized = true; - try{ - foreach (SecurityTokenKeyfile k, SecurityToken::GetAvailableKeyfiles()) { + try + { + foreach (SecurityTokenKeyfile k, SecurityToken::GetAvailableKeyfiles()) + { availableKeyfiles.push_back(shared_ptr(new SecurityTokenKeyfile(k))); } - } catch (SecurityTokenLibraryNotInitialized){ + } + catch (SecurityTokenLibraryNotInitialized&) + { securityTokenLibraryInitialized = false; } + + if (isEMVSupportEnabled) + { + try + { + foreach (EMVTokenKeyfile k, EMVToken::GetAvailableKeyfiles()) + { + availableKeyfiles.push_back(shared_ptr(new EMVTokenKeyfile(k))); + } + } + catch (ScardLibraryInitializationFailed&) + { + scardLibraryInitialized = false; + } + } - if(EMVOption){ - foreach (EMVTokenKeyfile k, EMVToken::GetAvailableKeyfiles()) { - availableKeyfiles.push_back(shared_ptr(new EMVTokenKeyfile(k))); - } - } - - if(availableKeyfiles.size() == 0 && ! securityTokenLibraryInitialized){ - throw SecurityTokenLibraryNotInitialized(); + if (availableKeyfiles.size() == 0) + { + if (!securityTokenLibraryInitialized) + { + throw SecurityTokenLibraryNotInitialized(); + } + else if (!scardLibraryInitialized) + { + throw ScardLibraryInitializationFailed(); + } } return availableKeyfiles; } - bool Token::IsKeyfilePathValid(const wstring& tokenKeyfilePath, bool EMVOption) + bool Token::IsKeyfilePathValid(const wstring& tokenKeyfilePath, bool isEMVSupportEnabled) { - if(EMVOption){ - return SecurityToken::IsKeyfilePathValid(tokenKeyfilePath) || EMVToken::IsKeyfilePathValid(tokenKeyfilePath); - } + if (isEMVSupportEnabled) + { + return SecurityToken::IsKeyfilePathValid(tokenKeyfilePath) || EMVToken::IsKeyfilePathValid(tokenKeyfilePath); + } return SecurityToken::IsKeyfilePathValid(tokenKeyfilePath); } list > Token::GetAvailableTokens() { list > availableTokens; - foreach(SecurityTokenInfo securityToken, SecurityToken::GetAvailableTokens()){ + + foreach(SecurityTokenInfo securityToken, SecurityToken::GetAvailableTokens()) + { availableTokens.push_back(shared_ptr(new SecurityTokenInfo(std::move(securityToken)))); } return availableTokens ; } - shared_ptr Token::getTokenKeyfile(const TokenKeyfilePath path){ + shared_ptr Token::getTokenKeyfile(const TokenKeyfilePath& path) + { shared_ptr tokenKeyfile; - if(SecurityToken::IsKeyfilePathValid(path)){ + if (SecurityToken::IsKeyfilePathValid(path)) + { tokenKeyfile = shared_ptr(new SecurityTokenKeyfile(path)); - } else { - if(EMVToken::IsKeyfilePathValid(path)){ + } + else + { + if (EMVToken::IsKeyfilePathValid(path)) + { tokenKeyfile = shared_ptr(new EMVTokenKeyfile(path)); } } diff --git a/src/Common/Token.h b/src/Common/Token.h index 28c6a489..c1dd8ac4 100644 --- a/src/Common/Token.h +++ b/src/Common/Token.h @@ -15,42 +15,46 @@ #define UNAVAILABLE_SLOT ~0UL -namespace VeraCrypt { - - struct TokenKeyfilePath { +namespace VeraCrypt +{ + struct TokenKeyfilePath + { + virtual ~TokenKeyfilePath() {}; TokenKeyfilePath(const wstring& path): Path(path) { } operator wstring () const { return Path; } - wstring Path; //Complete path - + wstring Path; // Complete path }; - struct TokenInfo { - TokenInfo() {} + + struct TokenInfo + { + TokenInfo(): SlotId(0), Label(L"") {} virtual ~TokenInfo() {} - virtual BOOL isEditable() const=0; + virtual BOOL isEditable() const = 0; unsigned long int SlotId; - wstring Label; //Card name + wstring Label; // Card name }; - struct TokenKeyfile { + struct TokenKeyfile + { + virtual ~TokenKeyfile() {} virtual operator TokenKeyfilePath () const = 0; virtual void GetKeyfileData(vector & keyfileData) const = 0; - string IdUtf8; // Was used in SecurityToken to compare with the file name from a PKCS11 card, remove from token ? shared_ptr Token; wstring Id; }; - class Token { + class Token + { public: - static vector> GetAvailableKeyfiles(bool EMVOption); - static bool IsKeyfilePathValid(const wstring& tokenKeyfilePath, bool EMVOption); - static list > GetAvailableTokens(); // List available token to write - static shared_ptr getTokenKeyfile(const TokenKeyfilePath path); + static vector> GetAvailableKeyfiles(bool isEMVSupportEnabled); + static bool IsKeyfilePathValid(const wstring& tokenKeyfilePath, bool isEMVSupportEnabled); + static list > GetAvailableTokens(); + static shared_ptr getTokenKeyfile(const TokenKeyfilePath& path); }; - }; diff --git a/src/Common/reader.h b/src/Common/reader.h new file mode 100644 index 00000000..19fbba87 --- /dev/null +++ b/src/Common/reader.h @@ -0,0 +1,271 @@ +/* + * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ ) + * + * Copyright (C) 1999-2005 + * David Corcoran + * Copyright (C) 2005-2009 + * Ludovic Rousseau + * +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief This keeps a list of defines shared between the driver and the application + */ + +#ifndef __reader_h__ +#define __reader_h__ + +/* + * Tags for requesting card and reader attributes + */ + +#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) + +#define SCARD_CLASS_VENDOR_INFO 1 /**< Vendor information definitions */ +#define SCARD_CLASS_COMMUNICATIONS 2 /**< Communication definitions */ +#define SCARD_CLASS_PROTOCOL 3 /**< Protocol definitions */ +#define SCARD_CLASS_POWER_MGMT 4 /**< Power Management definitions */ +#define SCARD_CLASS_SECURITY 5 /**< Security Assurance definitions */ +#define SCARD_CLASS_MECHANICAL 6 /**< Mechanical characteristic definitions */ +#define SCARD_CLASS_VENDOR_DEFINED 7 /**< Vendor specific definitions */ +#define SCARD_CLASS_IFD_PROTOCOL 8 /**< Interface Device Protocol options */ +#define SCARD_CLASS_ICC_STATE 9 /**< ICC State specific definitions */ +#define SCARD_CLASS_SYSTEM 0x7fff /**< System-specific definitions */ + +#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100) /**< Vendor name. */ +#define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101) /**< Vendor-supplied interface device type (model designation of reader). */ +#define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102) /**< Vendor-supplied interface device version (DWORD in the form 0xMMmmbbbb where MM = major version, mm = minor version, and bbbb = build number). */ +#define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103) /**< Vendor-supplied interface device serial number. */ +#define SCARD_ATTR_CHANNEL_ID SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0110) /**< DWORD encoded as 0xDDDDCCCC, where DDDD = data channel type and CCCC = channel number */ +#define SCARD_ATTR_ASYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0120) /**< FIXME */ +#define SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0121) /**< Default clock rate, in kHz. */ +#define SCARD_ATTR_MAX_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0122) /**< Maximum clock rate, in kHz. */ +#define SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0123) /**< Default data rate, in bps. */ +#define SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0124) /**< Maximum data rate, in bps. */ +#define SCARD_ATTR_MAX_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0125) /**< Maximum bytes for information file size device. */ +#define SCARD_ATTR_SYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0126) /**< FIXME */ +#define SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_VALUE(SCARD_CLASS_POWER_MGMT, 0x0131) /**< Zero if device does not support power down while smart card is inserted. Nonzero otherwise. */ +#define SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0140) /**< FIXME */ +#define SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0142) /**< FIXME */ +#define SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_VALUE(SCARD_CLASS_MECHANICAL, 0x0150) /**< DWORD indicating which mechanical characteristics are supported. If zero, no special characteristics are supported. Note that multiple bits can be set */ + +#define SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0201) /**< FIXME */ +#define SCARD_ATTR_CURRENT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0202) /**< Current clock rate, in kHz. */ +#define SCARD_ATTR_CURRENT_F SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0203) /**< Clock conversion factor. */ +#define SCARD_ATTR_CURRENT_D SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0204) /**< Bit rate conversion factor. */ +#define SCARD_ATTR_CURRENT_N SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0205) /**< Current guard time. */ +#define SCARD_ATTR_CURRENT_W SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0206) /**< Current work waiting time. */ +#define SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0207) /**< Current byte size for information field size card. */ +#define SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0208) /**< Current byte size for information field size device. */ +#define SCARD_ATTR_CURRENT_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0209) /**< Current block waiting time. */ +#define SCARD_ATTR_CURRENT_CWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020a) /**< Current character waiting time. */ +#define SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020b) /**< Current error block control encoding. */ +#define SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020c) /**< FIXME */ + +#define SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0300) /**< Single byte indicating smart card presence */ +#define SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0301) /**< Single byte. Zero if smart card electrical contact is not active; nonzero if contact is active. */ +#define SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0302) /**< FIXME */ +#define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303) /**< Answer to reset (ATR) string. */ +#define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304) /**< Single byte indicating smart card type */ + +#define SCARD_ATTR_ESC_RESET SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA000) /**< FIXME */ +#define SCARD_ATTR_ESC_CANCEL SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA003) /**< FIXME */ +#define SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA005) /**< FIXME */ +#define SCARD_ATTR_MAXINPUT SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA007) /**< FIXME */ + +#define SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0001) /**< Instance of this vendor's reader attached to the computer. The first instance will be device unit 0, the next will be unit 1 (if it is the same brand of reader) and so on. Two different brands of readers will both have zero for this value. */ +#define SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0002) /**< Reserved for future use. */ +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003) +#define SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0004) +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005) +#define SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0006) +#define SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0007) /**< FIXME */ + +#ifdef UNICODE +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W /**< Reader's display name. */ +#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W /**< Reader's system name. */ +#else +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A /**< Reader's display name. */ +#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A /**< Reader's system name. */ +#endif + +/** + * Provide source compatibility on different platforms + */ +#define SCARD_CTL_CODE(code) (0x42000000 + (code)) + +/** + * PC/SC part 10 v2.02.07 March 2010 reader tags + */ +#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) + +#define FEATURE_VERIFY_PIN_START 0x01 +#define FEATURE_VERIFY_PIN_FINISH 0x02 +#define FEATURE_MODIFY_PIN_START 0x03 +#define FEATURE_MODIFY_PIN_FINISH 0x04 +#define FEATURE_GET_KEY_PRESSED 0x05 +#define FEATURE_VERIFY_PIN_DIRECT 0x06 /**< Verify PIN */ +#define FEATURE_MODIFY_PIN_DIRECT 0x07 /**< Modify PIN */ +#define FEATURE_MCT_READER_DIRECT 0x08 +#define FEATURE_MCT_UNIVERSAL 0x09 +#define FEATURE_IFD_PIN_PROPERTIES 0x0A /**< retrieve properties of the IFD regarding PIN handling */ +#define FEATURE_ABORT 0x0B +#define FEATURE_SET_SPE_MESSAGE 0x0C +#define FEATURE_VERIFY_PIN_DIRECT_APP_ID 0x0D +#define FEATURE_MODIFY_PIN_DIRECT_APP_ID 0x0E +#define FEATURE_WRITE_DISPLAY 0x0F +#define FEATURE_GET_KEY 0x10 +#define FEATURE_IFD_DISPLAY_PROPERTIES 0x11 +#define FEATURE_GET_TLV_PROPERTIES 0x12 +#define FEATURE_CCID_ESC_COMMAND 0x13 +#define FEATURE_EXECUTE_PACE 0x20 + +/* structures used (but not defined) in PC/SC Part 10: + * "IFDs with Secure Pin Entry Capabilities" */ + +#include + +/* Set structure elements alignment on bytes + * http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */ +#if defined(__APPLE__) || defined(sun) || defined(__NetBSD__) +#pragma pack(1) +#else +#pragma pack(push, 1) +#endif + +/** the structure must be 6-bytes long */ +typedef struct +{ + uint8_t tag; + uint8_t length; + uint32_t value; /**< This value is always in BIG ENDIAN format as documented in PCSC v2 part 10 ch 2.2 page 2. You can use ntohl() for example */ +} PCSC_TLV_STRUCTURE; + +/** Since CCID 1.4.1 (revision 5252) the byte order is no more important + * These macros are now deprecated and should be removed in the future */ +#define HOST_TO_CCID_16(x) (x) +#define HOST_TO_CCID_32(x) (x) + +/** structure used with \ref FEATURE_VERIFY_PIN_DIRECT */ +typedef struct +{ + uint8_t bTimerOut; /**< timeout is seconds (00 means use default timeout) */ + uint8_t bTimerOut2; /**< timeout in seconds after first key stroke */ + uint8_t bmFormatString; /**< formatting options */ + uint8_t bmPINBlockString; /**< bits 7-4 bit size of PIN length in APDU, + * bits 3-0 PIN block size in bytes after + * justification and formatting */ + uint8_t bmPINLengthFormat; /**< bits 7-5 RFU, + * bit 4 set if system units are bytes, clear if + * system units are bits, + * bits 3-0 PIN length position in system units */ + uint16_t wPINMaxExtraDigit; /**< 0xXXYY where XX is minimum PIN size in digits, + and YY is maximum PIN size in digits */ + uint8_t bEntryValidationCondition; /**< Conditions under which PIN entry should + * be considered complete */ + uint8_t bNumberMessage; /**< Number of messages to display for PIN verification */ + uint16_t wLangId; /**< Language for messages. https://docs.microsoft.com/en-us/windows/win32/intl/language-identifier-constants-and-strings */ + uint8_t bMsgIndex; /**< Message index (should be 00) */ + uint8_t bTeoPrologue[3]; /**< T=1 block prologue field to use (fill with 00) */ + uint32_t ulDataLength; /**< length of Data to be sent to the ICC */ + uint8_t abData +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + [] /* valid C99 code */ +#else + [0] /* non-standard, but usually working code */ +#endif + ; /**< Data to send to the ICC */ +} PIN_VERIFY_STRUCTURE; + +/** structure used with \ref FEATURE_MODIFY_PIN_DIRECT */ +typedef struct +{ + uint8_t bTimerOut; /**< timeout is seconds (00 means use default timeout) */ + uint8_t bTimerOut2; /**< timeout in seconds after first key stroke */ + uint8_t bmFormatString; /**< formatting options */ + uint8_t bmPINBlockString; /**< bits 7-4 bit size of PIN length in APDU, + * bits 3-0 PIN block size in bytes after + * justification and formatting */ + uint8_t bmPINLengthFormat; /**< bits 7-5 RFU, + * bit 4 set if system units are bytes, clear if + * system units are bits, + * bits 3-0 PIN length position in system units */ + uint8_t bInsertionOffsetOld; /**< Insertion position offset in bytes for + the current PIN */ + uint8_t bInsertionOffsetNew; /**< Insertion position offset in bytes for + the new PIN */ + uint16_t wPINMaxExtraDigit; + /**< 0xXXYY where XX is minimum PIN size in digits, + and YY is maximum PIN size in digits */ + uint8_t bConfirmPIN; /**< Flags governing need for confirmation of new PIN */ + uint8_t bEntryValidationCondition; /**< Conditions under which PIN entry should + * be considered complete */ + uint8_t bNumberMessage; /**< Number of messages to display for PIN verification*/ + uint16_t wLangId; /**< Language for messages. https://docs.microsoft.com/en-us/windows/win32/intl/language-identifier-constants-and-strings */ + uint8_t bMsgIndex1; /**< index of 1st prompting message */ + uint8_t bMsgIndex2; /**< index of 2d prompting message */ + uint8_t bMsgIndex3; /**< index of 3d prompting message */ + uint8_t bTeoPrologue[3]; /**< T=1 block prologue field to use (fill with 00) */ + uint32_t ulDataLength; /**< length of Data to be sent to the ICC */ + uint8_t abData +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + [] /* valid C99 code */ +#else + [0] /* non-standard, but usually working code */ +#endif + ; /**< Data to send to the ICC */ +} PIN_MODIFY_STRUCTURE; + +/** structure used with \ref FEATURE_IFD_PIN_PROPERTIES */ +typedef struct { + uint16_t wLcdLayout; /**< display characteristics */ + uint8_t bEntryValidationCondition; + uint8_t bTimeOut2; +} PIN_PROPERTIES_STRUCTURE; + +/* restore default structure elements alignment */ +#if defined(__APPLE__) || defined(sun) || defined(__NetBSD__) +#pragma pack() +#else +#pragma pack(pop) +#endif + +/* properties returned by FEATURE_GET_TLV_PROPERTIES */ +#define PCSCv2_PART10_PROPERTY_wLcdLayout 1 +#define PCSCv2_PART10_PROPERTY_bEntryValidationCondition 2 +#define PCSCv2_PART10_PROPERTY_bTimeOut2 3 +#define PCSCv2_PART10_PROPERTY_wLcdMaxCharacters 4 +#define PCSCv2_PART10_PROPERTY_wLcdMaxLines 5 +#define PCSCv2_PART10_PROPERTY_bMinPINSize 6 +#define PCSCv2_PART10_PROPERTY_bMaxPINSize 7 +#define PCSCv2_PART10_PROPERTY_sFirmwareID 8 +#define PCSCv2_PART10_PROPERTY_bPPDUSupport 9 +#define PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize 10 +#define PCSCv2_PART10_PROPERTY_wIdVendor 11 +#define PCSCv2_PART10_PROPERTY_wIdProduct 12 + +#endif + diff --git a/src/Core/Core.h b/src/Core/Core.h index d2a4c593..78b2bf3d 100644 --- a/src/Core/Core.h +++ b/src/Core/Core.h @@ -82,10 +82,10 @@ namespace VeraCrypt shared_ptr m_newKeyfiles; shared_ptr m_newPkcs5Kdf; int m_wipeCount; - bool m_emvoption; - ChangePasswordThreadRoutine(shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf, int wipeCount, bool EMVOption) : m_volumePath(volumePath), m_preserveTimestamps(preserveTimestamps), m_password(password), m_pim(pim), m_kdf(kdf), m_truecryptMode(truecryptMode), m_keyfiles(keyfiles), m_newPassword(newPassword), m_newPim(newPim), m_newKeyfiles(newKeyfiles), m_newPkcs5Kdf(newPkcs5Kdf), m_wipeCount(wipeCount), m_emvoption(EMVOption) {} + bool m_emvSupportEnabled; + ChangePasswordThreadRoutine(shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf, int wipeCount, bool emvSupportEnabled) : m_volumePath(volumePath), m_preserveTimestamps(preserveTimestamps), m_password(password), m_pim(pim), m_kdf(kdf), m_truecryptMode(truecryptMode), m_keyfiles(keyfiles), m_newPassword(newPassword), m_newPim(newPim), m_newKeyfiles(newKeyfiles), m_newPkcs5Kdf(newPkcs5Kdf), m_wipeCount(wipeCount), m_emvSupportEnabled(emvSupportEnabled) {} virtual ~ChangePasswordThreadRoutine() { } - virtual void ExecutionCode(void) { Core->ChangePassword(m_volumePath, m_preserveTimestamps, m_password, m_pim, m_kdf, m_truecryptMode, m_keyfiles, m_newPassword, m_newPim, m_newKeyfiles, m_emvoption, m_newPkcs5Kdf, m_wipeCount); } + virtual void ExecutionCode(void) { Core->ChangePassword(m_volumePath, m_preserveTimestamps, m_password, m_pim, m_kdf, m_truecryptMode, m_keyfiles, m_newPassword, m_newPim, m_newKeyfiles, m_emvSupportEnabled, m_newPkcs5Kdf, m_wipeCount); } }; class OpenVolumeThreadRoutine : public WaitThreadRoutine @@ -108,16 +108,16 @@ namespace VeraCrypt bool m_useBackupHeaders; bool m_partitionInSystemEncryptionScope; shared_ptr m_pVolume; - bool m_emvoption; + bool m_emvSupportEnabled; - OpenVolumeThreadRoutine(shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr Kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false): + OpenVolumeThreadRoutine(shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr Kdf, bool truecryptMode, shared_ptr keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false): m_volumePath(volumePath), m_preserveTimestamps(preserveTimestamps), m_password(password), m_pim(pim), m_Kdf(Kdf), m_truecryptMode(truecryptMode), m_keyfiles(keyfiles), m_protection(protection), m_protectionPassword(protectionPassword), m_protectionPim(protectionPim), m_protectionKdf(protectionKdf), m_protectionKeyfiles(protectionKeyfiles), m_sharedAccessAllowed(sharedAccessAllowed), m_volumeType(volumeType),m_useBackupHeaders(useBackupHeaders), - m_partitionInSystemEncryptionScope(partitionInSystemEncryptionScope), m_emvoption(EMVOption) {} + m_partitionInSystemEncryptionScope(partitionInSystemEncryptionScope), m_emvSupportEnabled(emvSupportEnabled) {} ~OpenVolumeThreadRoutine() {} - virtual void ExecutionCode(void) { m_pVolume = Core->OpenVolume(m_volumePath,m_preserveTimestamps,m_password,m_pim,m_Kdf,m_truecryptMode,m_keyfiles, m_emvoption, m_protection,m_protectionPassword,m_protectionPim,m_protectionKdf, m_protectionKeyfiles,m_sharedAccessAllowed,m_volumeType,m_useBackupHeaders, m_partitionInSystemEncryptionScope); } + virtual void ExecutionCode(void) { m_pVolume = Core->OpenVolume(m_volumePath,m_preserveTimestamps,m_password,m_pim,m_Kdf,m_truecryptMode,m_keyfiles, m_emvSupportEnabled, m_protection,m_protectionPassword,m_protectionPim,m_protectionKdf, m_protectionKeyfiles,m_sharedAccessAllowed,m_volumeType,m_useBackupHeaders, m_partitionInSystemEncryptionScope); } }; @@ -129,11 +129,11 @@ namespace VeraCrypt shared_ptr m_password; int m_pim; shared_ptr m_keyfiles; - bool m_emvoption; - ReEncryptHeaderThreadRoutine(const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles, bool EMVOption) - : m_newHeaderBuffer(newHeaderBuffer), m_header(header), m_password(password), m_pim(pim), m_keyfiles(keyfiles), m_emvoption(EMVOption) {} + bool m_emvSupportEnabled; + ReEncryptHeaderThreadRoutine(const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles, bool emvSupportEnabled) + : m_newHeaderBuffer(newHeaderBuffer), m_header(header), m_password(password), m_pim(pim), m_keyfiles(keyfiles), m_emvSupportEnabled(emvSupportEnabled) {} virtual ~ReEncryptHeaderThreadRoutine() { } - virtual void ExecutionCode(void) { Core->ReEncryptVolumeHeaderWithNewSalt (m_newHeaderBuffer, m_header, m_password, m_pim, m_keyfiles, m_emvoption); } + virtual void ExecutionCode(void) { Core->ReEncryptVolumeHeaderWithNewSalt (m_newHeaderBuffer, m_header, m_password, m_pim, m_keyfiles, m_emvSupportEnabled); } }; class DecryptThreadRoutine : public WaitThreadRoutine diff --git a/src/Core/CoreBase.cpp b/src/Core/CoreBase.cpp index ce6e0c20..d31c9689 100644 --- a/src/Core/CoreBase.cpp +++ b/src/Core/CoreBase.cpp @@ -30,7 +30,7 @@ namespace VeraCrypt { } - void CoreBase::ChangePassword (shared_ptr openVolume, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool EMVOption, shared_ptr newPkcs5Kdf, int wipeCount) const + void CoreBase::ChangePassword (shared_ptr openVolume, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool emvSupportEnabled, shared_ptr newPkcs5Kdf, int wipeCount) const { if ((!newPassword || newPassword->Size() < 1) && (!newKeyfiles || newKeyfiles->empty())) throw PasswordEmpty (SRC_POS); @@ -58,7 +58,7 @@ namespace VeraCrypt SecureBuffer newSalt (openVolume->GetSaltSize()); SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize()); - shared_ptr password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword, EMVOption)); + shared_ptr password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword, emvSupportEnabled)); bool backupHeader = false; while (true) @@ -83,10 +83,10 @@ namespace VeraCrypt } } - void CoreBase::ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool EMVOption, shared_ptr newPkcs5Kdf, int wipeCount) const + void CoreBase::ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool emvSupportEnabled, shared_ptr newPkcs5Kdf, int wipeCount) const { - shared_ptr volume = OpenVolume (volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, EMVOption); - ChangePassword (volume, newPassword, newPim, newKeyfiles, EMVOption, newPkcs5Kdf, wipeCount); + shared_ptr volume = OpenVolume (volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, emvSupportEnabled); + ChangePassword (volume, newPassword, newPim, newKeyfiles, emvSupportEnabled, newPkcs5Kdf, wipeCount); } void CoreBase::CoalesceSlotNumberAndMountPoint (MountOptions &options) const @@ -261,10 +261,10 @@ namespace VeraCrypt return false; } - shared_ptr CoreBase::OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) const + shared_ptr CoreBase::OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) const { make_shared_auto (Volume, volume); - volume->Open (*volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, EMVOption, protection, protectionPassword, protectionPim, protectionKdf, protectionKeyfiles, sharedAccessAllowed, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); + volume->Open (*volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, emvSupportEnabled, protection, protectionPassword, protectionPim, protectionKdf, protectionKeyfiles, sharedAccessAllowed, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); return volume; } @@ -279,7 +279,7 @@ namespace VeraCrypt encryptionAlgorithm->GetMode()->SetKey (modeKey); } - void CoreBase::ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles, bool EMVOption) const + void CoreBase::ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles, bool emvSupportEnabled) const { shared_ptr pkcs5Kdf = header->GetPkcs5Kdf(); @@ -288,7 +288,7 @@ namespace VeraCrypt SecureBuffer newSalt (header->GetSaltSize()); SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize()); - shared_ptr passwordKey (Keyfile::ApplyListToPassword (keyfiles, password, EMVOption)); + shared_ptr passwordKey (Keyfile::ApplyListToPassword (keyfiles, password, emvSupportEnabled)); RandomNumberGenerator::GetData (newSalt); pkcs5Kdf->DeriveKey (newHeaderKey, *passwordKey, pim, newSalt); diff --git a/src/Core/CoreBase.h b/src/Core/CoreBase.h index 8df644c3..bd37ecb9 100644 --- a/src/Core/CoreBase.h +++ b/src/Core/CoreBase.h @@ -33,8 +33,8 @@ namespace VeraCrypt public: virtual ~CoreBase (); - virtual void ChangePassword (shared_ptr openVolume, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool EMVOption, shared_ptr newPkcs5Kdf = shared_ptr (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const; - virtual void ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool EMVOption, shared_ptr newPkcs5Kdf = shared_ptr (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const; + virtual void ChangePassword (shared_ptr openVolume, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool emvSupportEnabled, shared_ptr newPkcs5Kdf = shared_ptr (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const; + virtual void ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool emvSupportEnabled, shared_ptr newPkcs5Kdf = shared_ptr (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const; virtual void CheckFilesystem (shared_ptr mountedVolume, bool repair = false) const = 0; virtual void CoalesceSlotNumberAndMountPoint (MountOptions &options) const; virtual void CreateKeyfile (const FilePath &keyfilePath) const; @@ -69,9 +69,9 @@ namespace VeraCrypt virtual bool IsVolumeMounted (const VolumePath &volumePath) const; virtual VolumeSlotNumber MountPointToSlotNumber (const DirectoryPath &mountPoint) const = 0; virtual shared_ptr MountVolume (MountOptions &options) = 0; - virtual shared_ptr OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr Kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false) const; + virtual shared_ptr OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr Kdf, bool truecryptMode, shared_ptr keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false) const; virtual void RandomizeEncryptionAlgorithmKey (shared_ptr encryptionAlgorithm) const; - virtual void ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles, bool EMVOption) const; + virtual void ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles, bool emvSupportEnabled) const; virtual void SetAdminPasswordCallback (shared_ptr functor) { } virtual void SetApplicationExecutablePath (const FilePath &path) { ApplicationExecutablePath = path; } virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const = 0; diff --git a/src/Core/MountOptions.h b/src/Core/MountOptions.h index 6daecadd..02762806 100644 --- a/src/Core/MountOptions.h +++ b/src/Core/MountOptions.h @@ -73,7 +73,7 @@ namespace VeraCrypt VolumeSlotNumber SlotNumber; bool UseBackupHeaders; bool TrueCryptMode; - bool EMVOption; + bool EMVSupportEnabled; protected: void CopyFrom (const MountOptions &other); diff --git a/src/Core/Unix/CoreServiceProxy.h b/src/Core/Unix/CoreServiceProxy.h index 63b208a8..d57d8163 100644 --- a/src/Core/Unix/CoreServiceProxy.h +++ b/src/Core/Unix/CoreServiceProxy.h @@ -98,11 +98,11 @@ namespace VeraCrypt { MountOptions newOptions = options; - newOptions.Password = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVOption); + newOptions.Password = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVSupportEnabled); if (newOptions.Keyfiles) newOptions.Keyfiles->clear(); - newOptions.ProtectionPassword = Keyfile::ApplyListToPassword (options.ProtectionKeyfiles, options.ProtectionPassword, options.EMVOption); + newOptions.ProtectionPassword = Keyfile::ApplyListToPassword (options.ProtectionKeyfiles, options.ProtectionPassword, options.EMVSupportEnabled); if (newOptions.ProtectionKeyfiles) newOptions.ProtectionKeyfiles->clear(); @@ -126,7 +126,7 @@ namespace VeraCrypt if (options.CachePassword && ((options.Password && !options.Password->IsEmpty()) || (options.Keyfiles && !options.Keyfiles->empty()))) { - VolumePasswordCache::Store (*Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVOption)); + VolumePasswordCache::Store (*Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVSupportEnabled)); } } diff --git a/src/Core/Unix/CoreUnix.cpp b/src/Core/Unix/CoreUnix.cpp index 3b495e5f..bbc60e3c 100644 --- a/src/Core/Unix/CoreUnix.cpp +++ b/src/Core/Unix/CoreUnix.cpp @@ -548,7 +548,7 @@ namespace VeraCrypt options.Kdf, options.TrueCryptMode, options.Keyfiles, - options.EMVOption, + options.EMVSupportEnabled, options.Protection, options.ProtectionPassword, options.ProtectionPim, diff --git a/src/Core/VolumeCreator.cpp b/src/Core/VolumeCreator.cpp index 8a4baeed..d5caa846 100644 --- a/src/Core/VolumeCreator.cpp +++ b/src/Core/VolumeCreator.cpp @@ -307,7 +307,7 @@ namespace VeraCrypt // Header key HeaderKey.Allocate (VolumeHeader::GetLargestSerializedKeySize()); - PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password, options->EMVOption); + PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password, options->EMVSupportEnabled); options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, options->Pim, salt); headerOptions.HeaderKey = HeaderKey; diff --git a/src/Core/VolumeCreator.h b/src/Core/VolumeCreator.h index dc742911..781354b9 100644 --- a/src/Core/VolumeCreator.h +++ b/src/Core/VolumeCreator.h @@ -38,7 +38,7 @@ namespace VeraCrypt shared_ptr VolumeHeaderKdf; shared_ptr EA; bool Quick; - bool EMVOption; + bool EMVSupportEnabled; struct FilesystemType { diff --git a/src/Driver/veracrypt_vs2019.vcxproj b/src/Driver/veracrypt_vs2019.vcxproj index f06f8974..e956bcb0 100644 --- a/src/Driver/veracrypt_vs2019.vcxproj +++ b/src/Driver/veracrypt_vs2019.vcxproj @@ -5,6 +5,10 @@ Debug ARM64 + + Debug + Win32 + Debug x64 @@ -13,6 +17,10 @@ Release ARM64 + + Release + Win32 + Release x64 @@ -34,6 +42,9 @@ + + + @@ -44,21 +55,27 @@ true true + true true true + true true true + true true true + true true true + true true true + true @@ -106,6 +123,16 @@ <_NT_TARGET_VERSION>0x0A00 false + + Windows10 + true + WindowsKernelModeDriver10.0 + Driver + WDM + Universal + <_NT_TARGET_VERSION>0x0A00 + false + Windows10 false @@ -124,6 +151,15 @@ <_NT_TARGET_VERSION>0x0A00 false + + Windows10 + false + WindowsKernelModeDriver10.0 + Driver + WDM + <_NT_TARGET_VERSION>0x0A00 + false + @@ -141,6 +177,10 @@ veracrypt DbgengKernelDebugger + + veracrypt + DbgengKernelDebugger + DbgengKernelDebugger $(ProjectDir)$(Platform)\$(ConfigurationName)\ @@ -150,6 +190,10 @@ veracrypt DbgengKernelDebugger + + veracrypt + DbgengKernelDebugger + fltmgr.lib;%(AdditionalDependencies) @@ -184,6 +228,23 @@ false + + + fltmgr.lib;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + + + $(SolutionDir)Common;$(SolutionDir)Crypto;$(SolutionDir);%(AdditionalIncludeDirectories) + TC_WINDOWS_DRIVER;_WIN32;_NO_CRT_STDIO_INLINE;DEBUG;_DEBUG;%(PreprocessorDefinitions) + 4064;4627;4627;4366;4100;4057;4457;4456;4152;4213;4244;4127;4706;%(DisableSpecificWarnings) + + + copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-arm64.sys" + + + false + + fltmgr.lib;%(AdditionalDependencies) @@ -220,6 +281,24 @@ false + + + fltmgr.lib;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + + + $(SolutionDir)Common;$(SolutionDir)Crypto;$(SolutionDir);%(AdditionalIncludeDirectories) + TC_WINDOWS_DRIVER;_WIN32;_NO_CRT_STDIO_INLINE;%(PreprocessorDefinitions) + 4064;4627;4627;4366;4100;4057;4457;4456;4152;4213;4244;4127;4706;%(DisableSpecificWarnings) + + + copy $(TargetPath) "..\Release\Setup Files\VeraCrypt-arm64.sys" + + + true + false + + @@ -265,27 +344,37 @@ echo %(Filename)%(Extension) & nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" echo %(Filename)%(Extension) & nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" + + echo %(Filename)%(Extension) & nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" echo %(Filename)%(Extension) & nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" echo %(Filename)%(Extension) & nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" + + echo %(Filename)%(Extension) & nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) true true + true true true + true true true + true true true + true @@ -293,19 +382,27 @@ echo %(Filename)%(Extension) & nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" echo %(Filename)%(Extension) & nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" + + echo %(Filename)%(Extension) & nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" echo %(Filename)%(Extension) & nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" echo %(Filename)%(Extension) & nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" + + echo %(Filename)%(Extension) & nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)" $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) true true + true true true + true @@ -313,8 +410,10 @@ Document true true + true true true + true @@ -322,8 +421,10 @@ Document true true + true true true + true @@ -331,8 +432,10 @@ Document true true + true true true + true @@ -345,8 +448,10 @@ Document true true + true true true + true @@ -354,8 +459,10 @@ Document true true + true true true + true @@ -363,8 +470,10 @@ Document true true + true true true + true @@ -372,8 +481,10 @@ Document true true + false true true + false @@ -381,8 +492,10 @@ Document true true + true true true + true @@ -390,8 +503,10 @@ Document true true + true true true + true @@ -399,8 +514,10 @@ Document true true + true true true + true @@ -408,8 +525,10 @@ Document true true + true true true + true @@ -418,19 +537,27 @@ echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" + + echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" + + echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) true true + true true true + true @@ -439,19 +566,27 @@ echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" + + echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" + + echo %(Filename)%(Extension) & ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)" $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) $(TargetDir)\%(Filename).obj;%(Outputs) + $(TargetDir)\%(Filename).obj;%(Outputs) true true + true true true + true diff --git a/src/Driver/veracrypt_vs2019.vcxproj.filters b/src/Driver/veracrypt_vs2019.vcxproj.filters index 2940815c..f0c7d0e3 100644 --- a/src/Driver/veracrypt_vs2019.vcxproj.filters +++ b/src/Driver/veracrypt_vs2019.vcxproj.filters @@ -148,6 +148,15 @@ Crypto\Source Files + + Crypto\Source Files + + + Crypto\Source Files + + + Crypto\Source Files + diff --git a/src/ExpandVolume/ExpandVolume.vcxproj b/src/ExpandVolume/ExpandVolume.vcxproj index c182afe5..ce87f4fb 100644 --- a/src/ExpandVolume/ExpandVolume.vcxproj +++ b/src/ExpandVolume/ExpandVolume.vcxproj @@ -245,7 +245,7 @@ copy Debug\VeraCryptExpander.exe "..\Debug\Setup Files" >NUL: 4311;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCryptExpander.exe false mpr.dll;%(DelayLoadDLLs) @@ -336,7 +336,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" >NUL: 4311;4131;%(DisableSpecificWarnings) - ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCryptExpander.exe false mpr.dll;%(DelayLoadDLLs) @@ -428,7 +428,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" >NUL: 4311;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCryptExpander.exe false mpr.dll;%(DelayLoadDLLs) @@ -476,7 +476,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" >NUL: 4311;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCryptExpander.exe false mpr.dll;%(DelayLoadDLLs) @@ -575,8 +575,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" >NUL: + + - + + + + + + @@ -659,8 +666,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" >NUL: + + - + + + + + + diff --git a/src/ExpandVolume/ExpandVolume.vcxproj.filters b/src/ExpandVolume/ExpandVolume.vcxproj.filters index 3997d07f..c168cfc2 100644 --- a/src/ExpandVolume/ExpandVolume.vcxproj.filters +++ b/src/ExpandVolume/ExpandVolume.vcxproj.filters @@ -132,10 +132,31 @@ Source Files\Common - + Source Files\Common - + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + Source Files\Common @@ -248,10 +269,31 @@ Header Files - + Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + Header Files diff --git a/src/ExpandVolume/ExpandVolume_vs2019.vcxproj b/src/ExpandVolume/ExpandVolume_vs2019.vcxproj index 835a4d3b..555c6d8f 100644 --- a/src/ExpandVolume/ExpandVolume_vs2019.vcxproj +++ b/src/ExpandVolume/ExpandVolume_vs2019.vcxproj @@ -641,6 +641,17 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-arm64.exe" >NUL: + + + + + + + + + + + @@ -726,6 +737,17 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-arm64.exe" >NUL: + + + + + + + + + + + diff --git a/src/ExpandVolume/ExpandVolume_vs2019.vcxproj.filters b/src/ExpandVolume/ExpandVolume_vs2019.vcxproj.filters index 007757ff..17ed8515 100644 --- a/src/ExpandVolume/ExpandVolume_vs2019.vcxproj.filters +++ b/src/ExpandVolume/ExpandVolume_vs2019.vcxproj.filters @@ -126,6 +126,39 @@ Source Files\Setup + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + @@ -230,6 +263,39 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/src/ExpandVolume/WinMain.cpp b/src/ExpandVolume/WinMain.cpp index 57e58b4f..69f4c23b 100644 --- a/src/ExpandVolume/WinMain.cpp +++ b/src/ExpandVolume/WinMain.cpp @@ -321,7 +321,7 @@ void LoadSettings (HWND hwndDlg) mountOptions = defaultMountOptions; CloseSecurityTokenSessionsAfterMount = ConfigReadInt ("CloseSecurityTokenSessionsAfterMount", 0); - ActivateEMVOption = ConfigReadInt ("ActivateEMVOption", 0); + EMVSupportEnabled = ConfigReadInt ("EMVSupportEnabled", 0); { char szTmp[TC_MAX_PATH] = {0}; diff --git a/src/Format/Format.vcxproj b/src/Format/Format.vcxproj index 9f5abbc0..06e3dca7 100644 --- a/src/Format/Format.vcxproj +++ b/src/Format/Format.vcxproj @@ -218,7 +218,7 @@ copy Debug\VeraCryptFormat.exe "..\Debug\Setup Files\VeraCrypt Format.exe" >N 4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCryptFormat.exe false mpr.dll;%(DelayLoadDLLs) @@ -301,7 +301,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: 4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCryptFormat.exe false mpr.dll;%(DelayLoadDLLs) @@ -385,7 +385,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: 4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCryptFormat.exe false mpr.dll;%(DelayLoadDLLs) @@ -429,7 +429,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: 4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCryptFormat.exe false mpr.dll;%(DelayLoadDLLs) @@ -497,8 +497,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: + + - + + + + + + @@ -581,18 +588,25 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: + + - + + + + + + diff --git a/src/Format/Format.vcxproj.filters b/src/Format/Format.vcxproj.filters index e6615982..dbba0b57 100644 --- a/src/Format/Format.vcxproj.filters +++ b/src/Format/Format.vcxproj.filters @@ -114,10 +114,31 @@ Source Files\Common - + Source Files\Common - + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + Source Files\Common @@ -226,10 +247,31 @@ Header Files - + Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + Header Files diff --git a/src/Format/Format_vs2019.vcxproj b/src/Format/Format_vs2019.vcxproj index e6fe017f..819724f2 100644 --- a/src/Format/Format_vs2019.vcxproj +++ b/src/Format/Format_vs2019.vcxproj @@ -557,6 +557,17 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-arm64.exe" >NUL: + + + + + + + + + + + CompileAsCpp @@ -642,16 +653,27 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-arm64.exe" >NUL: + + + + + + + + + + + diff --git a/src/Format/Tcformat.c b/src/Format/Tcformat.c index 1e605c4d..a2eb828d 100644 --- a/src/Format/Tcformat.c +++ b/src/Format/Tcformat.c @@ -802,7 +802,7 @@ static void LoadSettingsAndCheckModified (HWND hwndDlg, BOOL bOnlyCheckModified, ConfigReadCompareInt ("UseLegacyMaxPasswordLength", FALSE, &bUseLegacyMaxPasswordLength, bOnlyCheckModified, pbSettingsModified); - ConfigReadCompareInt ("ActivateEMVOption", 0, &ActivateEMVOption, bOnlyCheckModified, pbSettingsModified); + ConfigReadCompareInt ("EMVSupportEnabled", 0, &EMVSupportEnabled, bOnlyCheckModified, pbSettingsModified); { char szTmp[MAX_PATH] = {0}; diff --git a/src/Main/CommandLineInterface.cpp b/src/Main/CommandLineInterface.cpp index dabfcad6..a7189652 100644 --- a/src/Main/CommandLineInterface.cpp +++ b/src/Main/CommandLineInterface.cpp @@ -56,7 +56,7 @@ namespace VeraCrypt parser.AddSwitch (L"", L"display-password", _("Display password while typing")); parser.AddOption (L"", L"encryption", _("Encryption algorithm")); parser.AddSwitch (L"", L"explore", _("Open explorer window for mounted volume")); - parser.AddSwitch (L"", L"export-token-keyfile",_("Export keyfile from security token")); + parser.AddSwitch (L"", L"export-token-keyfile",_("Export keyfile from token")); parser.AddOption (L"", L"filesystem", _("Filesystem type")); parser.AddSwitch (L"f", L"force", _("Force mount/dismount/overwrite")); #if !defined(TC_WINDOWS) && !defined(TC_MACOSX) @@ -67,9 +67,9 @@ namespace VeraCrypt parser.AddSwitch (L"", L"import-token-keyfiles", _("Import keyfiles to security token")); parser.AddOption (L"k", L"keyfiles", _("Keyfiles")); parser.AddSwitch (L"l", L"list", _("List mounted volumes")); - parser.AddSwitch (L"", L"list-token-keyfiles", _("List token keyfiles")); + parser.AddSwitch (L"", L"list-token-keyfiles", _("List token keyfiles")); parser.AddSwitch (L"", L"list-securitytoken-keyfiles", _("List security token keyfiles")); - parser.AddSwitch (L"", L"list-emvtoken-keyfiles", _("List emv token keyfiles")); + parser.AddSwitch (L"", L"list-emvtoken-keyfiles", _("List EMV token keyfiles")); parser.AddSwitch (L"", L"load-preferences", _("Load user preferences")); parser.AddSwitch (L"", L"mount", _("Mount volume interactively")); parser.AddOption (L"m", L"mount-options", _("VeraCrypt volume mount options")); @@ -221,13 +221,13 @@ namespace VeraCrypt if (parser.Found (L"export-token-keyfile")) { CheckCommandSingle(); - ArgCommand = CommandId::ExportSecurityTokenKeyfile; + ArgCommand = CommandId::ExportTokenKeyfile; } if (parser.Found (L"import-token-keyfiles")) { CheckCommandSingle(); - ArgCommand = CommandId::ImportSecurityTokenKeyfiles; + ArgCommand = CommandId::ImportTokenKeyfiles; } if (parser.Found (L"list")) diff --git a/src/Main/CommandLineInterface.h b/src/Main/CommandLineInterface.h index 21fb5c89..6a31932e 100644 --- a/src/Main/CommandLineInterface.h +++ b/src/Main/CommandLineInterface.h @@ -39,9 +39,9 @@ namespace VeraCrypt DismountVolumes, DisplayVersion, DisplayVolumeProperties, - ExportSecurityTokenKeyfile, + ExportTokenKeyfile, Help, - ImportSecurityTokenKeyfiles, + ImportTokenKeyfiles, ListTokenKeyfiles, ListSecurityTokenKeyfiles, ListEMVTokenKeyfiles, diff --git a/src/Main/Forms/ChangePasswordDialog.cpp b/src/Main/Forms/ChangePasswordDialog.cpp index 0992cf3b..0b54fefc 100644 --- a/src/Main/Forms/ChangePasswordDialog.cpp +++ b/src/Main/Forms/ChangePasswordDialog.cpp @@ -204,7 +204,7 @@ namespace VeraCrypt wxBusyCursor busy; ChangePasswordThreadRoutine routine(Path, Gui->GetPreferences().DefaultMountOptions.PreserveTimestamps, CurrentPasswordPanel->GetPassword(), CurrentPasswordPanel->GetVolumePim(), CurrentPasswordPanel->GetPkcs5Kdf(bUnsupportedKdf), CurrentPasswordPanel->GetTrueCryptMode(),CurrentPasswordPanel->GetKeyfiles(), - newPassword, newPim, newKeyfiles, NewPasswordPanel->GetPkcs5Kdf(bUnsupportedKdf), NewPasswordPanel->GetHeaderWipeCount(), Gui->GetPreferences().ActivateEMVOption); + newPassword, newPim, newKeyfiles, NewPasswordPanel->GetPkcs5Kdf(bUnsupportedKdf), NewPasswordPanel->GetHeaderWipeCount(), Gui->GetPreferences().EMVSupportEnabled); Gui->ExecuteWaitThreadRoutine (this, &routine); } diff --git a/src/Main/Forms/Forms.cpp b/src/Main/Forms/Forms.cpp index 8667a741..e92b970e 100644 --- a/src/Main/Forms/Forms.cpp +++ b/src/Main/Forms/Forms.cpp @@ -2208,13 +2208,13 @@ PreferencesDialogBase::PreferencesDialogBase( wxWindow* parent, wxWindowID id, c bSizer128->Add( sbSizer37, 0, wxEXPAND|wxALL, 5 ); - wxStaticBoxSizer* sbSizer38; - sbSizer38 = new wxStaticBoxSizer( new wxStaticBox( SecurityTokensPage, wxID_ANY, _("IDT_EMV_OPTIONS") ), wxVERTICAL ); + wxStaticBoxSizer* sbSizer38; + sbSizer38 = new wxStaticBoxSizer( new wxStaticBox( SecurityTokensPage, wxID_ANY, _("IDT_EMV_OPTIONS") ), wxVERTICAL ); - ActivateEMVOptionCheckBox = new wxCheckBox( sbSizer38->GetStaticBox(), wxID_ANY, _("IDC_ACTIVATE_EMV_OPTION"), wxDefaultPosition, wxDefaultSize, 0 ); - sbSizer38->Add( ActivateEMVOptionCheckBox, 0, wxALL, 5 ); + EMVSupportEnabledCheckBox = new wxCheckBox( sbSizer38->GetStaticBox(), wxID_ANY, _("IDC_ENABLE_EMV_SUPPORT"), wxDefaultPosition, wxDefaultSize, 0 ); + sbSizer38->Add( EMVSupportEnabledCheckBox, 0, wxALL, 5 ); - bSizer128->Add( sbSizer38, 0, wxEXPAND|wxALL, 5 ); + bSizer128->Add( sbSizer38, 0, wxEXPAND|wxALL, 5 ); bSizer127->Add( bSizer128, 1, wxEXPAND|wxALL, 5 ); diff --git a/src/Main/Forms/Forms.h b/src/Main/Forms/Forms.h index 904e96dd..60937550 100644 --- a/src/Main/Forms/Forms.h +++ b/src/Main/Forms/Forms.h @@ -593,7 +593,7 @@ namespace VeraCrypt wxTextCtrl* Pkcs11ModulePathTextCtrl; wxButton* SelectPkcs11ModuleButton; wxCheckBox* CloseSecurityTokenSessionsAfterMountCheckBox; - wxCheckBox* ActivateEMVOptionCheckBox; + wxCheckBox* EMVSupportEnabledCheckBox; wxListCtrl* HotkeyListCtrl; wxTextCtrl* HotkeyTextCtrl; wxButton* AssignHotkeyButton; diff --git a/src/Main/Forms/MainFrame.cpp b/src/Main/Forms/MainFrame.cpp index b52682ce..4b9b9bf1 100644 --- a/src/Main/Forms/MainFrame.cpp +++ b/src/Main/Forms/MainFrame.cpp @@ -683,7 +683,7 @@ namespace VeraCrypt { mountOptions.Pim = CmdLine->ArgPim; } - mountOptions.EMVOption = GetPreferences().ActivateEMVOption; + mountOptions.EMVSupportEnabled = GetPreferences().EMVSupportEnabled; Gui->MountAllFavoriteVolumes (mountOptions); } catch (exception &e) @@ -718,7 +718,7 @@ namespace VeraCrypt { mountOptions.Pim = CmdLine->ArgPim; } - mountOptions.EMVOption = GetPreferences().ActivateEMVOption; + mountOptions.EMVSupportEnabled = GetPreferences().EMVSupportEnabled; try { diff --git a/src/Main/Forms/MountOptionsDialog.cpp b/src/Main/Forms/MountOptionsDialog.cpp index 28a9919c..4b8f7ce5 100644 --- a/src/Main/Forms/MountOptionsDialog.cpp +++ b/src/Main/Forms/MountOptionsDialog.cpp @@ -193,7 +193,7 @@ namespace VeraCrypt Options.MountPoint = make_shared (mountPoint); Options.FilesystemOptions = FilesystemOptionsTextCtrl->GetValue(); - Options.EMVOption = Gui->GetPreferences().ActivateEMVOption; + Options.EMVSupportEnabled = Gui->GetPreferences().EMVSupportEnabled; EndModal (wxID_OK); } diff --git a/src/Main/Forms/PreferencesDialog.cpp b/src/Main/Forms/PreferencesDialog.cpp index 6caae325..abf1d505 100644 --- a/src/Main/Forms/PreferencesDialog.cpp +++ b/src/Main/Forms/PreferencesDialog.cpp @@ -96,7 +96,7 @@ namespace VeraCrypt // Security tokens Pkcs11ModulePathTextCtrl->SetValue (wstring (Preferences.SecurityTokenModule)); TC_CHECK_BOX_VALIDATOR (CloseSecurityTokenSessionsAfterMount); - TC_CHECK_BOX_VALIDATOR (ActivateEMVOption); + TC_CHECK_BOX_VALIDATOR (EMVSupportEnabled); // System integration TC_CHECK_BOX_VALIDATOR (StartOnLogon); diff --git a/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp b/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp index 2c5896a7..d78e22fd 100644 --- a/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp +++ b/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp @@ -53,7 +53,7 @@ namespace VeraCrypt wxBusyCursor busy; SecurityTokenKeyfileListCtrl->DeleteAllItems(); - SecurityTokenKeyfileList = Token::GetAvailableKeyfiles(Gui->GetPreferences().ActivateEMVOption); + SecurityTokenKeyfileList = Token::GetAvailableKeyfiles(Gui->GetPreferences().EMVSupportEnabled); size_t i = 0; foreach (const shared_ptr key, SecurityTokenKeyfileList) @@ -177,34 +177,38 @@ namespace VeraCrypt } } - void SecurityTokenKeyfilesDialog::OnListItemSelected(wxListEvent &event) { - if (event.GetItem().GetData() != (wxUIntPtr) nullptr) { - BOOL deletable = true; - foreach(long - item, Gui->GetListCtrlSelectedItems(SecurityTokenKeyfileListCtrl)) - { - TokenKeyfile *keyfile = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData( - item)); - if (!keyfile->Token->isEditable()) { - deletable = false; - } - } - if (deletable) { - DeleteButton->Enable(); - } - ExportButton->Enable(); - OKButton->Enable(); - } - } + void SecurityTokenKeyfilesDialog::OnListItemSelected(wxListEvent &event) + { + if (event.GetItem().GetData() != (wxUIntPtr) nullptr) + { + BOOL deletable = true; + foreach(long + item, Gui->GetListCtrlSelectedItems(SecurityTokenKeyfileListCtrl)) + { + TokenKeyfile *keyfile = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData(item)); + if (!keyfile->Token->isEditable()) + { + deletable = false; + break; + } + } + if (deletable) + { + DeleteButton->Enable(); + } + ExportButton->Enable(); + OKButton->Enable(); + } + } void SecurityTokenKeyfilesDialog::OnOKButtonClick () { foreach (long item, Gui->GetListCtrlSelectedItems (SecurityTokenKeyfileListCtrl)) - { - TokenKeyfile *key = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData(item)); + { + TokenKeyfile *key = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData(item)); - SelectedSecurityTokenKeyfilePaths.push_back(*key); - } + SelectedSecurityTokenKeyfilePaths.push_back(*key); + } EndModal (wxID_OK); } } diff --git a/src/Main/Forms/VolumeCreationWizard.cpp b/src/Main/Forms/VolumeCreationWizard.cpp index 0487455f..5939fc1b 100644 --- a/src/Main/Forms/VolumeCreationWizard.cpp +++ b/src/Main/Forms/VolumeCreationWizard.cpp @@ -795,7 +795,7 @@ namespace VeraCrypt shared_ptr hiddenPassword; try { - hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().ActivateEMVOption); + hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().EMVSupportEnabled); } catch (...) { @@ -846,7 +846,7 @@ namespace VeraCrypt shared_ptr hiddenPassword; try { - hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().ActivateEMVOption); + hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().EMVSupportEnabled); } catch (...) { @@ -1032,7 +1032,7 @@ namespace VeraCrypt options->Size = VolumeSize; options->Type = OuterVolume ? VolumeType::Normal : SelectedVolumeType; options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*SelectedHash, false); - options->EMVOption = Gui->GetPreferences().ActivateEMVOption; + options->EMVSupportEnabled = Gui->GetPreferences().EMVSupportEnabled; Creator.reset (new VolumeCreator); @@ -1162,7 +1162,7 @@ namespace VeraCrypt // remember Outer password and keyfiles in order to be able to compare it with those of Hidden volume try { - OuterPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().ActivateEMVOption); + OuterPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().EMVSupportEnabled); } catch (...) { diff --git a/src/Main/Forms/WaitDialog.cpp b/src/Main/Forms/WaitDialog.cpp index c2e0be96..720c2bdc 100644 --- a/src/Main/Forms/WaitDialog.cpp +++ b/src/Main/Forms/WaitDialog.cpp @@ -9,8 +9,8 @@ #include "System.h" #include "Volume/EncryptionModeXTS.h" #include "Main/GraphicUserInterface.h" +#include "Common/PCSCException.h" #include "Common/SecurityToken.h" -#include "Common/IccDataExtractor.h" #include "WaitDialog.h" namespace VeraCrypt @@ -103,12 +103,18 @@ namespace VeraCrypt VC_CONVERT_EXCEPTION (VolumeException); VC_CONVERT_EXCEPTION (PasswordException); - VC_CONVERT_EXCEPTION (PCSCException); - VC_CONVERT_EXCEPTION (WinscardLibraryNotInitialized); - VC_CONVERT_EXCEPTION (InvalidEMVPath); - VC_CONVERT_EXCEPTION (EMVKeyfileDataNotFound); - VC_CONVERT_EXCEPTION (EMVPANNotFound); - VC_CONVERT_EXCEPTION (EMVUnknownCardType); + VC_CONVERT_EXCEPTION (PCSCException); + VC_CONVERT_EXCEPTION (CommandAPDUNotValid); + VC_CONVERT_EXCEPTION (ExtendedAPDUNotSupported); + VC_CONVERT_EXCEPTION (ScardLibraryInitializationFailed); + VC_CONVERT_EXCEPTION (EMVUnknownCardType); + VC_CONVERT_EXCEPTION (EMVSelectAIDFailed); + VC_CONVERT_EXCEPTION (EMVIccCertNotFound); + VC_CONVERT_EXCEPTION (EMVIssuerCertNotFound); + VC_CONVERT_EXCEPTION (EMVCPLCNotFound); + VC_CONVERT_EXCEPTION (InvalidEMVPath); + VC_CONVERT_EXCEPTION (EMVKeyfileDataNotFound); + VC_CONVERT_EXCEPTION (EMVPANNotFound); throw *ex; } diff --git a/src/Main/GraphicUserInterface.cpp b/src/Main/GraphicUserInterface.cpp index c76f1886..6786e9a8 100644 --- a/src/Main/GraphicUserInterface.cpp +++ b/src/Main/GraphicUserInterface.cpp @@ -193,7 +193,7 @@ namespace VeraCrypt options->Kdf, false, options->Keyfiles, - options->EMVOption, + options->EMVSupportEnabled, options->Protection, options->ProtectionPassword, options->ProtectionPim, @@ -222,7 +222,7 @@ namespace VeraCrypt options->Kdf, false, options->Keyfiles, - options->EMVOption, + options->EMVSupportEnabled, options->Protection, options->ProtectionPassword, options->ProtectionPim, @@ -317,7 +317,7 @@ namespace VeraCrypt // Re-encrypt volume header SecureBuffer newHeaderBuffer (normalVolume->GetLayout()->GetHeaderSize()); - ReEncryptHeaderThreadRoutine routine(newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Pim, normalVolumeMountOptions.Keyfiles, normalVolumeMountOptions.EMVOption); + ReEncryptHeaderThreadRoutine routine(newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Pim, normalVolumeMountOptions.Keyfiles, normalVolumeMountOptions.EMVSupportEnabled); ExecuteWaitThreadRoutine (parent, &routine); @@ -326,7 +326,7 @@ namespace VeraCrypt if (hiddenVolume) { // Re-encrypt hidden volume header - ReEncryptHeaderThreadRoutine hiddenRoutine(newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Pim, hiddenVolumeMountOptions.Keyfiles, hiddenVolumeMountOptions.EMVOption); + ReEncryptHeaderThreadRoutine hiddenRoutine(newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Pim, hiddenVolumeMountOptions.Keyfiles, hiddenVolumeMountOptions.EMVSupportEnabled); ExecuteWaitThreadRoutine (parent, &hiddenRoutine); } @@ -1468,7 +1468,7 @@ namespace VeraCrypt options.Kdf, options.TrueCryptMode, options.Keyfiles, - options.EMVOption, + options.EMVSupportEnabled, options.Protection, options.ProtectionPassword, options.ProtectionPim, @@ -1501,7 +1501,7 @@ namespace VeraCrypt // Re-encrypt volume header wxBusyCursor busy; SecureBuffer newHeaderBuffer (volume->GetLayout()->GetHeaderSize()); - ReEncryptHeaderThreadRoutine routine(newHeaderBuffer, volume->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVOption); + ReEncryptHeaderThreadRoutine routine(newHeaderBuffer, volume->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVSupportEnabled); ExecuteWaitThreadRoutine (parent, &routine); @@ -1582,7 +1582,7 @@ namespace VeraCrypt backupFile.ReadAt (headerBuffer, layout->GetType() == VolumeType::Hidden ? layout->GetHeaderSize() : 0); // Decrypt header - shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVOption); + shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVSupportEnabled); Pkcs5KdfList keyDerivationFunctions = layout->GetSupportedKeyDerivationFunctions(options.TrueCryptMode); EncryptionAlgorithmList encryptionAlgorithms = layout->GetSupportedEncryptionAlgorithms(); EncryptionModeList encryptionModes = layout->GetSupportedEncryptionModes(); @@ -1616,7 +1616,7 @@ namespace VeraCrypt // Re-encrypt volume header wxBusyCursor busy; SecureBuffer newHeaderBuffer (decryptedLayout->GetHeaderSize()); - ReEncryptHeaderThreadRoutine routine(newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVOption); + ReEncryptHeaderThreadRoutine routine(newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVSupportEnabled); ExecuteWaitThreadRoutine (parent, &routine); @@ -1632,7 +1632,7 @@ namespace VeraCrypt if (decryptedLayout->HasBackupHeader()) { // Re-encrypt backup volume header - ReEncryptHeaderThreadRoutine backupRoutine(newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVOption); + ReEncryptHeaderThreadRoutine backupRoutine(newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVSupportEnabled); ExecuteWaitThreadRoutine (parent, &backupRoutine); diff --git a/src/Main/GraphicUserInterface.h b/src/Main/GraphicUserInterface.h index e50c6386..820a4831 100644 --- a/src/Main/GraphicUserInterface.h +++ b/src/Main/GraphicUserInterface.h @@ -46,7 +46,7 @@ namespace VeraCrypt virtual void DoShowWarning (const wxString &message) const; virtual void EndBusyState () const { wxEndBusyCursor(); } virtual void EndInteractiveBusyState (wxWindow *window) const; - virtual void ExportSecurityTokenKeyfile () const { ThrowTextModeRequired(); } + virtual void ExportTokenKeyfile () const { ThrowTextModeRequired(); } virtual wxTopLevelWindow *GetActiveWindow () const; virtual shared_ptr GetAdminPasswordRequestHandler (); virtual int GetCharHeight (wxWindow *window) const; @@ -58,7 +58,7 @@ namespace VeraCrypt virtual int GetScrollbarWidth (wxWindow *window, bool noScrollBar = false) const; virtual list GetListCtrlSelectedItems (wxListCtrl *listCtrl) const; virtual wxString GetListCtrlSubItemText (wxListCtrl *listCtrl, long itemIndex, int columnIndex) const; - virtual void ImportSecurityTokenKeyfiles () const { ThrowTextModeRequired(); } + virtual void ImportTokenKeyfiles () const { ThrowTextModeRequired(); } virtual void InitSecurityTokenLibrary () const; virtual void InsertToListCtrl (wxListCtrl *listCtrl, long itemIndex, const vector &itemFields, int imageIndex = -1, void *itemDataPtr = nullptr) const; virtual bool IsInBackgroundMode () const { return BackgroundMode; } diff --git a/src/Main/TextUserInterface.cpp b/src/Main/TextUserInterface.cpp index f4f73d7f..22df8e1f 100644 --- a/src/Main/TextUserInterface.cpp +++ b/src/Main/TextUserInterface.cpp @@ -289,6 +289,9 @@ namespace VeraCrypt normalVolumeMountOptions.Path = volumePath; hiddenVolumeMountOptions.Path = volumePath; + normalVolumeMountOptions.EMVSupportEnabled = true; + hiddenVolumeMountOptions.EMVSupportEnabled = true; + VolumeType::Enum volumeType = VolumeType::Normal; // Open both types of volumes @@ -314,7 +317,7 @@ namespace VeraCrypt kdf, false, options->Keyfiles, - true, + options->EMVSupportEnabled, options->Protection, options->ProtectionPassword, options->ProtectionPim, @@ -340,7 +343,7 @@ namespace VeraCrypt kdf, false, options->Keyfiles, - true, + options->EMVSupportEnabled, options->Protection, options->ProtectionPassword, options->ProtectionPim, @@ -411,14 +414,14 @@ namespace VeraCrypt // Re-encrypt volume header SecureBuffer newHeaderBuffer (normalVolume->GetLayout()->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Pim, normalVolumeMountOptions.Keyfiles, true); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Pim, normalVolumeMountOptions.Keyfiles, normalVolumeMountOptions.EMVSupportEnabled); backupFile.Write (newHeaderBuffer); if (hiddenVolume) { // Re-encrypt hidden volume header - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Pim, hiddenVolumeMountOptions.Keyfiles, true); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Pim, hiddenVolumeMountOptions.Keyfiles, hiddenVolumeMountOptions.EMVSupportEnabled); } else { @@ -915,7 +918,7 @@ namespace VeraCrypt wxLongLong startTime = wxGetLocalTimeMillis(); VolumeCreator creator; - options->EMVOption = true; + options->EMVSupportEnabled = true; creator.CreateVolume (options); bool volumeCreated = false; @@ -957,6 +960,7 @@ namespace VeraCrypt mountOptions.Password = options->Password; mountOptions.Pim = options->Pim; mountOptions.Keyfiles = options->Keyfiles; + mountOptions.EMVSupportEnabled = true; shared_ptr volume = Core->MountVolume (mountOptions); finally_do_arg (shared_ptr , volume, { Core->DismountVolume (finally_arg, true); }); @@ -1053,9 +1057,9 @@ namespace VeraCrypt wcerr << L"Warning: " << static_cast (message) << endl; } - void TextUserInterface::ExportSecurityTokenKeyfile () const + void TextUserInterface::ExportTokenKeyfile () const { - wstring keyfilePath = AskString (_("Enter security token keyfile path: ")); + wstring keyfilePath = AskString (_("Enter token keyfile path: ")); if (keyfilePath.empty()) throw UserAbort (SRC_POS); @@ -1103,7 +1107,7 @@ namespace VeraCrypt return shared_ptr (new AdminPasswordRequestHandler (this)); } - void TextUserInterface::ImportSecurityTokenKeyfiles () const + void TextUserInterface::ImportTokenKeyfiles () const { list > tokens = Token::GetAvailableTokens(); @@ -1268,6 +1272,8 @@ namespace VeraCrypt if (!options.Keyfiles) options.Keyfiles = AskKeyfiles(); + options.EMVSupportEnabled = true; + VolumeInfoList mountedVolumes = UserInterface::MountAllDeviceHostedVolumes (options); if (!mountedVolumes.empty()) @@ -1306,6 +1312,8 @@ namespace VeraCrypt VolumePassword password; KeyfileList keyfiles; + options.EMVSupportEnabled = true; + if ((!options.Password || options.Password->IsEmpty()) && (!options.Keyfiles || options.Keyfiles->empty()) && !Core->IsPasswordCacheEmpty()) @@ -1526,6 +1534,7 @@ namespace VeraCrypt shared_ptr volume; MountOptions options; options.Path = volumePath; + options.EMVSupportEnabled = true; while (!volume) { @@ -1544,7 +1553,7 @@ namespace VeraCrypt kdf, false, options.Keyfiles, - true, + options.EMVSupportEnabled, options.Protection, options.ProtectionPassword, options.ProtectionPim, @@ -1572,7 +1581,7 @@ namespace VeraCrypt // Re-encrypt volume header SecureBuffer newHeaderBuffer (volume->GetLayout()->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, volume->GetHeader(), options.Password, options.Pim, options.Keyfiles, true); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, volume->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVSupportEnabled); // Write volume header int headerOffset = volume->GetLayout()->GetHeaderOffset(); @@ -1622,6 +1631,7 @@ namespace VeraCrypt // Open the volume header stored in the backup file MountOptions options; + options.EMVSupportEnabled = true; shared_ptr decryptedLayout; @@ -1649,7 +1659,7 @@ namespace VeraCrypt backupFile.ReadAt (headerBuffer, layout->GetType() == VolumeType::Hidden ? layout->GetHeaderSize() : 0); // Decrypt header - shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, true); + shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVSupportEnabled); if (layout->GetHeader()->Decrypt (headerBuffer, *passwordKey, options.Pim, kdf, false, layout->GetSupportedKeyDerivationFunctions(false), layout->GetSupportedEncryptionAlgorithms(), layout->GetSupportedEncryptionModes())) { decryptedLayout = layout; @@ -1674,7 +1684,7 @@ namespace VeraCrypt // Re-encrypt volume header SecureBuffer newHeaderBuffer (decryptedLayout->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, true); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVSupportEnabled); // Write volume header int headerOffset = decryptedLayout->GetHeaderOffset(); @@ -1688,7 +1698,7 @@ namespace VeraCrypt if (decryptedLayout->HasBackupHeader()) { // Re-encrypt backup volume header - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, true); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVSupportEnabled); // Write backup volume header headerOffset = decryptedLayout->GetBackupHeaderOffset(); diff --git a/src/Main/TextUserInterface.h b/src/Main/TextUserInterface.h index 5e64aac7..dc16fe97 100644 --- a/src/Main/TextUserInterface.h +++ b/src/Main/TextUserInterface.h @@ -44,9 +44,9 @@ namespace VeraCrypt virtual void DoShowString (const wxString &str) const; virtual void DoShowWarning (const wxString &message) const; virtual void EndBusyState () const { } - virtual void ExportSecurityTokenKeyfile () const; + virtual void ExportTokenKeyfile () const; virtual shared_ptr GetAdminPasswordRequestHandler (); - virtual void ImportSecurityTokenKeyfiles () const; + virtual void ImportTokenKeyfiles () const; #ifndef TC_NO_GUI virtual bool Initialize (int &argc, wxChar **argv) { return wxAppBase::Initialize(argc, argv); } #endif diff --git a/src/Main/UserInterface.cpp b/src/Main/UserInterface.cpp index 132ad0e0..c2e95f7e 100644 --- a/src/Main/UserInterface.cpp +++ b/src/Main/UserInterface.cpp @@ -17,6 +17,7 @@ #include #include "Crypto/cpu.h" #include "Platform/PlatformTest.h" +#include "Common/PCSCException.h" #ifdef TC_UNIX #include #include "Platform/Unix/Process.h" @@ -24,7 +25,6 @@ #include "Platform/SystemInfo.h" #include "Platform/SystemException.h" #include "Common/SecurityToken.h" -#include "Common/IccDataExtractor.h" #include "Volume/EncryptionTest.h" #include "Application.h" #include "FavoriteVolume.h" @@ -501,12 +501,18 @@ namespace VeraCrypt EX2MSG (StringFormatterException, LangString["LINUX_EX2MSG_STRINGFORMATTEREXCEPTION"]); EX2MSG (TemporaryDirectoryFailure, LangString["LINUX_EX2MSG_TEMPORARYDIRECTORYFAILURE"]); EX2MSG (UnportablePassword, LangString["UNSUPPORTED_CHARS_IN_PWD"]); - - EX2MSG (WinscardLibraryNotInitialized, LangString["WINSCARD_MODULE_INIT_FAILED"]); - EX2MSG (InvalidEMVPath, LangString["INVALID_EMV_PATH"]); - EX2MSG (EMVKeyfileDataNotFound, LangString["EMV_KEYFILE_DATA_NOT_FOUND"]); - EX2MSG (EMVPANNotFound, LangString["EMV_PAN_NOT_FOUND"]); - EX2MSG (EMVUnknownCardType, LangString["EMV_UNKNOWN_CARD_TYPE"]); + + EX2MSG (CommandAPDUNotValid, LangString["COMMAND_APDU_INVALID"]); + EX2MSG (ExtendedAPDUNotSupported, LangString["EXTENDED_APDU_UNSUPPORTED"]); + EX2MSG (ScardLibraryInitializationFailed, LangString["SCARD_MODULE_INIT_FAILED"]); + EX2MSG (EMVUnknownCardType, LangString["EMV_UNKNOWN_CARD_TYPE"]); + EX2MSG (EMVSelectAIDFailed, LangString["EMV_SELECT_AID_FAILED"]); + EX2MSG (EMVIccCertNotFound, LangString["EMV_ICC_CERT_NOTFOUND"]); + EX2MSG (EMVIssuerCertNotFound, LangString["EMV_ISSUER_CERT_NOTFOUND"]); + EX2MSG (EMVCPLCNotFound, LangString["EMV_CPLC_NOTFOUND"]); + EX2MSG (InvalidEMVPath, LangString["EMV_PAN_NOTFOUND"]); + EX2MSG (EMVKeyfileDataNotFound, LangString["INVALID_EMV_PATH"]); + EX2MSG (EMVPANNotFound, LangString["EMV_KEYFILE_DATA_NOTFOUND"]); #if defined (TC_LINUX) EX2MSG (TerminalNotFound, LangString["LINUX_EX2MSG_TERMINALNOTFOUND"]); @@ -1150,7 +1156,7 @@ namespace VeraCrypt " Delete keyfiles from security tokens. See also command --list-token-keyfiles.\n" "\n" "--export-token-keyfile\n" - " Export a keyfile from a token keyfile. See also command --list-token-keyfiles.\n" + " Export a keyfile from a token. See also command --list-token-keyfiles.\n" "\n" "--import-token-keyfiles\n" " Import keyfiles to a security token. See also option --token-lib.\n" @@ -1393,12 +1399,12 @@ namespace VeraCrypt } return true; - case CommandId::ExportSecurityTokenKeyfile: - ExportSecurityTokenKeyfile(); + case CommandId::ExportTokenKeyfile: + ExportTokenKeyfile(); return true; - case CommandId::ImportSecurityTokenKeyfiles: - ImportSecurityTokenKeyfiles(); + case CommandId::ImportTokenKeyfiles: + ImportTokenKeyfiles(); return true; case CommandId::ListTokenKeyfiles: @@ -1694,12 +1700,18 @@ namespace VeraCrypt VC_CONVERT_EXCEPTION (VolumeException); VC_CONVERT_EXCEPTION (PasswordException); - VC_CONVERT_EXCEPTION (PCSCException); - VC_CONVERT_EXCEPTION (WinscardLibraryNotInitialized); - VC_CONVERT_EXCEPTION (InvalidEMVPath); - VC_CONVERT_EXCEPTION (EMVKeyfileDataNotFound); - VC_CONVERT_EXCEPTION (EMVPANNotFound); - VC_CONVERT_EXCEPTION (EMVUnknownCardType); + VC_CONVERT_EXCEPTION (PCSCException); + VC_CONVERT_EXCEPTION (CommandAPDUNotValid); + VC_CONVERT_EXCEPTION (ExtendedAPDUNotSupported); + VC_CONVERT_EXCEPTION (ScardLibraryInitializationFailed); + VC_CONVERT_EXCEPTION (EMVUnknownCardType); + VC_CONVERT_EXCEPTION (EMVSelectAIDFailed); + VC_CONVERT_EXCEPTION (EMVIccCertNotFound); + VC_CONVERT_EXCEPTION (EMVIssuerCertNotFound); + VC_CONVERT_EXCEPTION (EMVCPLCNotFound); + VC_CONVERT_EXCEPTION (InvalidEMVPath); + VC_CONVERT_EXCEPTION (EMVKeyfileDataNotFound); + VC_CONVERT_EXCEPTION (EMVPANNotFound); throw *ex; } diff --git a/src/Main/UserInterface.h b/src/Main/UserInterface.h index 4b628235..39c2be61 100644 --- a/src/Main/UserInterface.h +++ b/src/Main/UserInterface.h @@ -49,10 +49,10 @@ namespace VeraCrypt virtual void DoShowWarning (const wxString &message) const = 0; virtual void EndBusyState () const = 0; static wxString ExceptionToMessage (const exception &ex); - virtual void ExportSecurityTokenKeyfile () const = 0; + virtual void ExportTokenKeyfile () const = 0; virtual shared_ptr GetAdminPasswordRequestHandler () = 0; virtual const UserPreferences &GetPreferences () const { return Preferences; } - virtual void ImportSecurityTokenKeyfiles () const = 0; + virtual void ImportTokenKeyfiles () const = 0; virtual void Init (); virtual void InitSecurityTokenLibrary () const = 0; virtual void ListMountedVolumes (const VolumeInfoList &volumes) const; diff --git a/src/Main/UserPreferences.cpp b/src/Main/UserPreferences.cpp index d5b37bab..ef14b2c8 100644 --- a/src/Main/UserPreferences.cpp +++ b/src/Main/UserPreferences.cpp @@ -79,7 +79,7 @@ namespace VeraCrypt TC_CONFIG_SET (CloseBackgroundTaskOnNoVolumes); TC_CONFIG_SET (CloseExplorerWindowsOnDismount); TC_CONFIG_SET (CloseSecurityTokenSessionsAfterMount); - TC_CONFIG_SET (ActivateEMVOption); + TC_CONFIG_SET (EMVSupportEnabled); TC_CONFIG_SET (DisableKernelEncryptionModeWarning); TC_CONFIG_SET (DismountOnInactivity); TC_CONFIG_SET (DismountOnLogOff); @@ -198,7 +198,7 @@ namespace VeraCrypt TC_CONFIG_ADD (CloseBackgroundTaskOnNoVolumes); TC_CONFIG_ADD (CloseExplorerWindowsOnDismount); TC_CONFIG_ADD (CloseSecurityTokenSessionsAfterMount); - TC_CONFIG_ADD (ActivateEMVOption); + TC_CONFIG_ADD (EMVSupportEnabled); TC_CONFIG_ADD (DisableKernelEncryptionModeWarning); TC_CONFIG_ADD (DismountOnInactivity); TC_CONFIG_ADD (DismountOnLogOff); diff --git a/src/Main/UserPreferences.h b/src/Main/UserPreferences.h index bc9cc0c7..6d53fb5f 100644 --- a/src/Main/UserPreferences.h +++ b/src/Main/UserPreferences.h @@ -31,7 +31,7 @@ namespace VeraCrypt CloseBackgroundTaskOnNoVolumes (true), CloseExplorerWindowsOnDismount (true), CloseSecurityTokenSessionsAfterMount (false), - ActivateEMVOption (false), + EMVSupportEnabled (false), DisableKernelEncryptionModeWarning (false), DismountOnInactivity (false), DismountOnLogOff (true), @@ -73,7 +73,7 @@ namespace VeraCrypt bool CloseBackgroundTaskOnNoVolumes; bool CloseExplorerWindowsOnDismount; bool CloseSecurityTokenSessionsAfterMount; - bool ActivateEMVOption; + bool EMVSupportEnabled; bool DisableKernelEncryptionModeWarning; bool DismountOnInactivity; bool DismountOnLogOff; diff --git a/src/Makefile b/src/Makefile index 53e460b6..f6ec5041 100644 --- a/src/Makefile +++ b/src/Makefile @@ -190,9 +190,9 @@ ifeq "$(shell uname -s)" "Linux" PLATFORM := Linux C_CXX_FLAGS += -DTC_UNIX -DTC_LINUX - # TODO: Prpoper implementation in the makefile - C_CXX_FLAGS += -I/usr/include/PCSC/ -lpcsclite - LFLAGS += -I/usr/include/PCSC/ -lpcsclite + + # PCSC + C_CXX_FLAGS += $(shell pkg-config --cflags libpcsclite) # GNU GCC version 11 and higher compile with -std=gnu++17 by default @@ -367,6 +367,9 @@ ifeq "$(shell uname -s)" "FreeBSD" PLATFORM := FreeBSD PLATFORM_UNSUPPORTED := 1 C_CXX_FLAGS += -DTC_UNIX -DTC_BSD -DTC_FREEBSD + + # PCSC + C_CXX_FLAGS += $(shell pkg-config --cflags libpcsclite) CC := cc CXX := c++ @@ -424,6 +427,9 @@ ifeq "$(shell uname -s)" "OpenBSD" PLATFORM_UNSUPPORTED := 1 C_CXX_FLAGS += -DTC_UNIX -DTC_BSD -DTC_OPENBSD + # PCSC + C_CXX_FLAGS += $(shell pkg-config --cflags libpcsclite) + CC := cc CXX := c++ @@ -446,6 +452,9 @@ ifeq "$(shell uname -s)" "SunOS" C_CXX_FLAGS += -DTC_UNIX -DTC_SOLARIS WX_CONFIGURE_FLAGS += --with-gtk + # PCSC + C_CXX_FLAGS += $(shell pkg-config --cflags libpcsclite) + endif diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index a7552411..713b239d 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -954,7 +954,7 @@ void LoadSettingsAndCheckModified (HWND hwndDlg, BOOL bOnlyCheckModified, BOOL* } ConfigReadCompareInt ("CloseSecurityTokenSessionsAfterMount", 0, &CloseSecurityTokenSessionsAfterMount, bOnlyCheckModified, pbSettingsModified); - ConfigReadCompareInt ("ActivateEMVOption", 0, &ActivateEMVOption, bOnlyCheckModified, pbSettingsModified); + ConfigReadCompareInt ("EMVSupportEnabled", 0, &EMVSupportEnabled, bOnlyCheckModified, pbSettingsModified); if (IsHiddenOSRunning()) ConfigReadCompareInt ("HiddenSystemLeakProtNotifStatus", TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE, &HiddenSysLeakProtectionNotificationStatus, bOnlyCheckModified, pbSettingsModified); @@ -1127,7 +1127,7 @@ void SaveSettings (HWND hwndDlg) } ConfigWriteInt ("CloseSecurityTokenSessionsAfterMount", CloseSecurityTokenSessionsAfterMount); - ConfigWriteInt ("ActivateEMVOption", ActivateEMVOption); + ConfigWriteInt ("EMVSupportEnabled", EMVSupportEnabled); // Hotkeys ConfigWriteInt ("HotkeyModAutoMountDevices", Hotkeys[HK_AUTOMOUNT_DEVICES].vKeyModifiers); @@ -11881,7 +11881,7 @@ static BOOL CALLBACK SecurityTokenPreferencesDlgProc (HWND hwndDlg, UINT msg, WP LocalizeDialog (hwndDlg, "IDD_TOKEN_PREFERENCES"); SetDlgItemText (hwndDlg, IDC_PKCS11_MODULE, SecurityTokenLibraryPath); CheckDlgButton (hwndDlg, IDC_CLOSE_TOKEN_SESSION_AFTER_MOUNT, CloseSecurityTokenSessionsAfterMount ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton (hwndDlg, IDC_ACTIVATE_EMV_OPTION, ActivateEMVOption ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton (hwndDlg, IDC_ENABLE_EMV_SUPPORT, EMVSupportEnabled ? BST_CHECKED : BST_UNCHECKED); SetWindowTextW (GetDlgItem (hwndDlg, IDT_PKCS11_LIB_HELP), GetString("PKCS11_LIB_LOCATION_HELP")); @@ -11924,7 +11924,7 @@ static BOOL CALLBACK SecurityTokenPreferencesDlgProc (HWND hwndDlg, UINT msg, WP } CloseSecurityTokenSessionsAfterMount = (IsDlgButtonChecked (hwndDlg, IDC_CLOSE_TOKEN_SESSION_AFTER_MOUNT) == BST_CHECKED); - ActivateEMVOption = (IsDlgButtonChecked (hwndDlg, IDC_ACTIVATE_EMV_OPTION) == BST_CHECKED); + EMVSupportEnabled = (IsDlgButtonChecked (hwndDlg, IDC_ENABLE_EMV_SUPPORT) == BST_CHECKED); WaitCursor (); SaveSettings (hwndDlg); NormalCursor (); diff --git a/src/Mount/Mount.rc b/src/Mount/Mount.rc index d6d766c5..8d248f7b 100644 --- a/src/Mount/Mount.rc +++ b/src/Mount/Mount.rc @@ -280,7 +280,7 @@ BEGIN PUSHBUTTON "Auto-&Detect Library",IDC_AUTO_DETECT_PKCS11_MODULE,16,41,112,14 CONTROL "&Close token session (log out) after a volume is successfully mounted",IDC_CLOSE_TOKEN_SESSION_AFTER_MOUNT, "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,16,154,284,9 - CONTROL "&Activate EMV Option",IDC_ACTIVATE_EMV_OPTION,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,16,185,284,9 + CONTROL "&Enable EMV Support",IDC_ENABLE_EMV_SUPPORT,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,16,185,284,9 DEFPUSHBUTTON "OK",IDOK,205,208,50,14 PUSHBUTTON "Cancel",IDCANCEL,259,208,50,14 GROUPBOX "PKCS #11 Library Path",IDT_PKCS11_LIB_PATH,7,7,302,129 diff --git a/src/Mount/Mount.vcxproj b/src/Mount/Mount.vcxproj index 5aeb6722..480ef694 100644 --- a/src/Mount/Mount.vcxproj +++ b/src/Mount/Mount.vcxproj @@ -236,7 +236,7 @@ copy Debug\VeraCrypt.exe "..\Debug\Setup Files" >NUL: 4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCrypt.exe false mpr.dll;%(DelayLoadDLLs) @@ -325,7 +325,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" >NUL: 4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCrypt.exe false mpr.dll;%(DelayLoadDLLs) @@ -415,7 +415,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" >NUL: 4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCrypt.exe false mpr.dll;%(DelayLoadDLLs) @@ -462,7 +462,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" >NUL: 4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) $(OutDir)VeraCrypt.exe false mpr.dll;%(DelayLoadDLLs) @@ -533,8 +533,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" >NUL: + + - + + + + + + @@ -606,8 +613,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" >NUL: + + - + + + + + + diff --git a/src/Mount/Mount.vcxproj.filters b/src/Mount/Mount.vcxproj.filters index 033a76ff..d5014051 100644 --- a/src/Mount/Mount.vcxproj.filters +++ b/src/Mount/Mount.vcxproj.filters @@ -114,10 +114,31 @@ Source Files\Common - + Source Files\Common - + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + Source Files\Common @@ -229,10 +250,31 @@ Header Files - + Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + Header Files diff --git a/src/Mount/Mount_vs2019.vcxproj b/src/Mount/Mount_vs2019.vcxproj index 13aef3ca..b75121e4 100644 --- a/src/Mount/Mount_vs2019.vcxproj +++ b/src/Mount/Mount_vs2019.vcxproj @@ -602,6 +602,17 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-arm64.exe" >NUL: + + + + + + + + + + + @@ -675,6 +686,17 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-arm64.exe" >NUL: + + + + + + + + + + + diff --git a/src/Mount/Resource.h b/src/Mount/Resource.h index 69f99080..0687b9ae 100644 --- a/src/Mount/Resource.h +++ b/src/Mount/Resource.h @@ -199,7 +199,7 @@ #define IDC_FORCE_NEXT_BOOT_VERACRYPT 1176 #define IDC_FORCE_VERACRYPT_BOOT_ENTRY 1177 #define IDC_FORCE_VERACRYPT_FIRST_BOOT_ENTRY 1178 -#define IDC_ACTIVATE_EMV_OPTION 1179 +#define IDC_ENABLE_EMV_SUPPORT 1179 #define IDT_EMV_OPTIONS 1180 #define IDM_HELP 40001 #define IDM_ABOUT 40002 diff --git a/src/VeraCrypt_vs2019.sln b/src/VeraCrypt_vs2019.sln index 43b2f41e..5c440480 100644 --- a/src/VeraCrypt_vs2019.sln +++ b/src/VeraCrypt_vs2019.sln @@ -684,11 +684,11 @@ Global {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All CustomEFI|x64.ActiveCfg = Debug|ARM64 {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All Debug|ARM64.ActiveCfg = Debug|ARM64 {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All Debug|ARM64.Build.0 = Debug|ARM64 - {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All Debug|Win32.ActiveCfg = Debug|ARM64 - {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All Debug|x64.ActiveCfg = Debug|ARM64 + {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All Debug|Win32.ActiveCfg = Debug|Win32 + {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All Debug|x64.ActiveCfg = Debug|x64 {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All|ARM64.ActiveCfg = Release|ARM64 - {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All|Win32.ActiveCfg = Debug|ARM64 - {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All|x64.ActiveCfg = Debug|ARM64 + {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All|Win32.ActiveCfg = Release|Win32 + {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.All|x64.ActiveCfg = Release|x64 {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.Boot Loader|ARM64.ActiveCfg = Debug|ARM64 {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.Boot Loader|ARM64.Build.0 = Debug|ARM64 {4B41C7B5-75C6-40A2-AF4D-55BC1E012BCD}.Boot Loader|ARM64.Deploy.0 = Debug|ARM64 diff --git a/src/Volume/Keyfile.cpp b/src/Volume/Keyfile.cpp index 9527fd11..24b40709 100644 --- a/src/Volume/Keyfile.cpp +++ b/src/Volume/Keyfile.cpp @@ -18,7 +18,7 @@ #include "VolumeException.h" namespace VeraCrypt { - void Keyfile::Apply (const BufferPtr &pool, bool EMVOption) const + void Keyfile::Apply (const BufferPtr &pool, bool emvSupportEnabled) const { if (Path.IsDirectory()) throw ParameterIncorrect (SRC_POS); @@ -32,57 +32,60 @@ namespace VeraCrypt SecureBuffer keyfileBuf (File::GetOptimalReadSize()); - std::wcout << wstring (Path) << std::endl; - if (Token::IsKeyfilePathValid (Path, EMVOption)) { - // Apply keyfile generated by a security token - vector keyfileData; - Token::getTokenKeyfile(wstring(Path))->GetKeyfileData(keyfileData); + if (Token::IsKeyfilePathValid (Path, emvSupportEnabled)) + { + // Apply keyfile generated by a security token + vector keyfileData; + Token::getTokenKeyfile(wstring(Path))->GetKeyfileData(keyfileData); - if (keyfileData.size() < MinProcessedLength) - throw InsufficientData(SRC_POS, Path); + if (keyfileData.size() < MinProcessedLength) + throw InsufficientData(SRC_POS, Path); - for (size_t i = 0; i < keyfileData.size(); i++) { - uint32 crc = crc32.Process(keyfileData[i]); + for (size_t i = 0; i < keyfileData.size(); i++) + { + uint32 crc = crc32.Process(keyfileData[i]); - pool[poolPos++] += (byte)(crc >> 24); - pool[poolPos++] += (byte)(crc >> 16); - pool[poolPos++] += (byte)(crc >> 8); - pool[poolPos++] += (byte) crc; + pool[poolPos++] += (byte)(crc >> 24); + pool[poolPos++] += (byte)(crc >> 16); + pool[poolPos++] += (byte)(crc >> 8); + pool[poolPos++] += (byte) crc; - if (poolPos >= pool.Size()) - poolPos = 0; + if (poolPos >= pool.Size()) + poolPos = 0; - if (++totalLength >= MaxProcessedLength) - break; - } + if (++totalLength >= MaxProcessedLength) + break; + } - burn(&keyfileData.front(), keyfileData.size()); - goto done; - } + burn(&keyfileData.front(), keyfileData.size()); + goto done; + } - file.Open (Path, File::OpenRead, File::ShareRead); + file.Open (Path, File::OpenRead, File::ShareRead); - while ((readLength = file.Read (keyfileBuf)) > 0) { - for (size_t i = 0; i < readLength; i++) { - uint32 crc = crc32.Process(keyfileBuf[i]); - pool[poolPos++] += (byte)(crc >> 24); - pool[poolPos++] += (byte)(crc >> 16); - pool[poolPos++] += (byte)(crc >> 8); - pool[poolPos++] += (byte) crc; - if (poolPos >= pool.Size()) - poolPos = 0; - if (++totalLength >= MaxProcessedLength) - goto done; - } - } - done: + while ((readLength = file.Read (keyfileBuf)) > 0) + { + for (size_t i = 0; i < readLength; i++) + { + uint32 crc = crc32.Process(keyfileBuf[i]); + pool[poolPos++] += (byte)(crc >> 24); + pool[poolPos++] += (byte)(crc >> 16); + pool[poolPos++] += (byte)(crc >> 8); + pool[poolPos++] += (byte) crc; + if (poolPos >= pool.Size()) + poolPos = 0; + if (++totalLength >= MaxProcessedLength) + goto done; + } + } + done: if (totalLength < MinProcessedLength) throw InsufficientData (SRC_POS, Path); } - shared_ptr Keyfile::ApplyListToPassword (shared_ptr keyfiles, shared_ptr password, bool EMVOption) + shared_ptr Keyfile::ApplyListToPassword (shared_ptr keyfiles, shared_ptr password, bool emvSupportEnabled) { if (!password) password.reset (new VolumePassword); @@ -139,7 +142,7 @@ namespace VeraCrypt // Apply all keyfiles foreach_ref (const Keyfile &k, keyfilesExp) { - k.Apply (keyfilePool, EMVOption); + k.Apply (keyfilePool, emvSupportEnabled); } newPassword->Set (keyfilePool); diff --git a/src/Volume/Keyfile.h b/src/Volume/Keyfile.h index bf0a524b..1d87a983 100644 --- a/src/Volume/Keyfile.h +++ b/src/Volume/Keyfile.h @@ -29,7 +29,7 @@ namespace VeraCrypt virtual ~Keyfile () { }; operator FilesystemPath () const { return Path; } - static shared_ptr ApplyListToPassword (shared_ptr keyfiles, shared_ptr password, bool EMVOption = false); + static shared_ptr ApplyListToPassword (shared_ptr keyfiles, shared_ptr password, bool emvSupportEnabled = false); static shared_ptr DeserializeList (shared_ptr stream, const string &name); static void SerializeList (shared_ptr stream, const string &name, shared_ptr keyfiles); static bool WasHiddenFilePresentInKeyfilePath() { bool r = HiddenFileWasPresentInKeyfilePath; HiddenFileWasPresentInKeyfilePath = false; return r; } @@ -38,7 +38,7 @@ namespace VeraCrypt static const size_t MaxProcessedLength = 1024 * 1024; protected: - void Apply (const BufferPtr &pool, bool EMVOption) const; + void Apply (const BufferPtr &pool, bool emvSupportEnabled) const; static bool HiddenFileWasPresentInKeyfilePath; diff --git a/src/Volume/Volume.cpp b/src/Volume/Volume.cpp index 6fb906b6..57707726 100644 --- a/src/Volume/Volume.cpp +++ b/src/Volume/Volume.cpp @@ -71,7 +71,7 @@ namespace VeraCrypt return EA->GetMode(); } - void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) + void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) { make_shared_auto (File, file); @@ -102,10 +102,10 @@ namespace VeraCrypt throw; } - return Open (file, password, pim, kdf, truecryptMode, keyfiles, EMVOption, protection, protectionPassword, protectionPim, protectionKdf,protectionKeyfiles, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); + return Open (file, password, pim, kdf, truecryptMode, keyfiles, emvSupportEnabled, protection, protectionPassword, protectionPim, protectionKdf,protectionKeyfiles, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); } - void Volume::Open (shared_ptr volumeFile, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf,shared_ptr protectionKeyfiles, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) + void Volume::Open (shared_ptr volumeFile, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf,shared_ptr protectionKeyfiles, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) { if (!volumeFile) throw ParameterIncorrect (SRC_POS); @@ -121,7 +121,7 @@ namespace VeraCrypt try { VolumeHostSize = VolumeFile->Length(); - shared_ptr passwordKey = Keyfile::ApplyListToPassword (keyfiles, password, EMVOption); + shared_ptr passwordKey = Keyfile::ApplyListToPassword (keyfiles, password, emvSupportEnabled); bool skipLayoutV1Normal = false; @@ -249,7 +249,7 @@ namespace VeraCrypt protectedVolume.Open (VolumeFile, protectionPassword, protectionPim, protectionKdf, truecryptMode, protectionKeyfiles, - EMVOption, + emvSupportEnabled, VolumeProtection::ReadOnly, shared_ptr (), 0, shared_ptr (),shared_ptr (), VolumeType::Hidden, diff --git a/src/Volume/Volume.h b/src/Volume/Volume.h index 85fdbe41..e50dd0e7 100644 --- a/src/Volume/Volume.h +++ b/src/Volume/Volume.h @@ -123,8 +123,8 @@ namespace VeraCrypt uint64 GetVolumeCreationTime () const { return Header->GetVolumeCreationTime(); } bool IsHiddenVolumeProtectionTriggered () const { return HiddenVolumeProtectionTriggered; } bool IsInSystemEncryptionScope () const { return SystemEncryption; } - void Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (),shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); - void Open (shared_ptr volumeFile, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); + void Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (),shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); + void Open (shared_ptr volumeFile, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); void ReadSectors (const BufferPtr &buffer, uint64 byteOffset); void ReEncryptHeader (bool backupHeader, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf); void WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset); diff --git a/src/Volume/Volume.make b/src/Volume/Volume.make index 03e06eaa..d69ec135 100644 --- a/src/Volume/Volume.make +++ b/src/Volume/Volume.make @@ -96,15 +96,22 @@ OBJS += ../Crypto/kuznyechik_simd.o OBJSNOOPT += ../Crypto/jitterentropy-base.o0 +OBJS += ../Common/CommandAPDU.o +OBJS += ../Common/PCSCException.o +OBJS += ../Common/ResponseAPDU.o +OBJS += ../Common/SCard.o +OBJS += ../Common/SCardLoader.o +OBJS += ../Common/SCardManager.o +OBJS += ../Common/SCardReader.o OBJS += ../Common/Token.o OBJS += ../Common/Crc.o OBJS += ../Common/TLVParser.o +OBJS += ../Common/EMVCard.o OBJS += ../Common/EMVToken.o OBJS += ../Common/Endian.o OBJS += ../Common/GfMul.o OBJS += ../Common/Pkcs5.o OBJS += ../Common/SecurityToken.o -OBJS += ../Common/IccDataExtractor.o VolumeLibrary: Volume.a