EMV keyfile support: Overall code improvements and bug fixes

This commit is contained in:
Mounir IDRASSI 2023-06-29 00:06:20 +02:00
parent 502ab9112a
commit 034b64f415
No known key found for this signature in database
GPG Key ID: 02C30AE90FAE4A6F
81 changed files with 4654 additions and 1574 deletions

366
src/Common/CommandAPDU.cpp Normal file
View File

@ -0,0 +1,366 @@
#include "CommandAPDU.h"
#include <string.h>
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<byte>& 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<byte>& data, uint32 ne)
{
init(cla, ins, p1, p2, data.data(), 0, (uint32)data.size(), ne);
}
CommandAPDU::CommandAPDU(const vector<byte>& 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<byte> CommandAPDU::getData()
{
vector<byte> 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<byte> CommandAPDU::getAPDU()
{
return m_apdu;
}
bool CommandAPDU::isExtended()
{
return m_isExtendedAPDU;
}
bool CommandAPDU::isValid()
{
return m_parsedSuccessfully;
}
std::string CommandAPDU::getErrorStr()
{
return m_parsingErrorStr;
}
}

93
src/Common/CommandAPDU.h Normal file
View File

@ -0,0 +1,93 @@
#ifndef TC_HEADER_Common_CommandAPDU
#define TC_HEADER_Common_CommandAPDU
#include "Platform/PlatformBase.h"
#include <stdarg.h>
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<char> 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<byte> 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<byte>& 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<byte>& data, uint32 ne);
CommandAPDU(const vector<byte>& apdu);
byte getCLA();
byte getINS();
byte getP1();
byte getP2();
uint32 getNc();
const vector<byte> getData();
uint32 getNe();
const vector<byte> getAPDU();
bool isValid();
std::string getErrorStr();
bool isExtended();
};
};
#endif // TC_HEADER_Common_CommandAPDU

View File

@ -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<TokenKeyfile> &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<SecurityTokenKeyfile&>(*keyfile.get()));
}
keyfiles = Token::GetAvailableKeyfiles(ActivateEMVOption);
keyfiles = Token::GetAvailableKeyfiles(EMVSupportEnabled);
SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles);
}
catch (Exception &e)

View File

@ -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;

523
src/Common/EMVCard.cpp Normal file
View File

@ -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 <vector>
#include <iostream>
#include <algorithm>
#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<EMVCardType, vector<byte>> InitializeSupportedAIDs()
{
map<EMVCardType, vector<byte>> supportedAIDs;
supportedAIDs.insert(std::make_pair(EMVCardType::AMEX, vector<byte>(EMVCard::AMEX_AID, EMVCard::AMEX_AID + (std::end(EMVCard::AMEX_AID) - std::begin(EMVCard::AMEX_AID)))));
supportedAIDs.insert(std::make_pair(EMVCardType::MASTERCARD, vector<byte>(EMVCard::MASTERCARD_AID, EMVCard::MASTERCARD_AID + (std::end(EMVCard::MASTERCARD_AID) - std::begin(EMVCard::MASTERCARD_AID)))));
supportedAIDs.insert(std::make_pair(EMVCardType::VISA, vector<byte>(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<EMVCardType, vector<byte>> 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<byte> EMVCard::GetCardAID(bool forceContactless)
{
vector<vector<byte>> supportedAIDs;
vector<byte> supportedAIDsPriorities;
vector<pair<byte, vector<byte>>> supportedAIDsSorted;
bool hasBeenReset = false;
CommandAPDU command;
ResponseAPDU response;
vector<byte> responseData;
shared_ptr<TLVNode> rootNode;
shared_ptr<TLVNode> fciNode;
shared_ptr<TLVNode> dfNameNode;
shared_ptr<TLVNode> sfiNode;
shared_ptr<TLVNode> fciIssuerNode;
shared_ptr<TLVNode> fciIssuerDiscretionaryDataNode;
shared_ptr<TLVNode> templateNode;
vector<shared_ptr<TLVNode>> pseDirectoryNodes;
unsigned char sfi;
bool usingContactless = false;
vector<byte> 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<SCardReader>, 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<TLVNode> aidNode;
shared_ptr<TLVNode> 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<byte>& iccCert, vector<byte>& issuerCert, vector<byte>& cplcData)
{
bool hasBeenReset = false;
bool aidSelected = false;
bool iccFound = false;
bool issuerFound = false;
bool cplcFound = false;
vector<byte> emvCardAid;
shared_ptr<TLVNode> rootNode;
shared_ptr<TLVNode> iccPublicKeyCertNode;
shared_ptr<TLVNode> issuerPublicKeyCertNode;
CommandAPDU command;
ResponseAPDU response;
vector<byte> 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<SCardReader>, 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<byte> EMVCardAid;
vector<byte> panData;
shared_ptr<TLVNode> rootNode;
shared_ptr<TLVNode> panNode;
CommandAPDU command;
ResponseAPDU response;
vector<byte> 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<SCardReader>, 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<byte>(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;
}
}

69
src/Common/EMVCard.h Normal file
View File

@ -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<byte> m_aid;
vector<vector<byte>> m_supportedAids;
vector<byte> m_iccCert;
vector<byte> m_issuerCert;
vector<byte> 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<EMVCardType, vector<byte>> 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<byte> GetCardAID(bool forceContactless = false);
void GetCardContent(vector<byte>& iccCert, vector<byte>& issuerCert, vector<byte>& cplcData);
void GetCardPAN(wstring& lastPANDigits);
};
}
#endif // TC_HEADER_Common_EMVCard

View File

@ -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 <vector>
#include <iostream>
#include <algorithm>
#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<byte>& 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 <unsigned long int, shared_ptr<EMVCard>> 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<EMVTokenInfo>(new EMVTokenInfo());
}
EMVTokenKeyfile::EMVTokenKeyfile(const TokenKeyfilePath& path)
{
Id = EMV_CARDS_LABEL;
Token = shared_ptr<EMVTokenInfo>(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<EMVTokenInfo>(new EMVTokenInfo());
Token->SlotId = slotId;
}
@ -51,12 +76,46 @@ namespace VeraCrypt
void EMVTokenKeyfile::GetKeyfileData(vector <byte>& keyfileData) const
{
#ifdef TC_WINDOWS
EMVToken::extractor.InitLibrary();
#endif
map <unsigned long int, shared_ptr<EMVCard>>::iterator emvCardsIt;
shared_ptr<EMVCard> card;
vector<byte> iccCert;
vector<byte> issuerCert;
vector<byte> 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<EMVCard>(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<EMVTokenKeyfile> EMVToken::GetAvailableKeyfiles(unsigned long int* slotIdFilter, const wstring keyfileIdFilter) {
#ifdef TC_WINDOWS
EMVToken::extractor.InitLibrary();
#endif
vector<EMVTokenKeyfile> EMVToken::GetAvailableKeyfiles(unsigned long int* slotIdFilter, const wstring& keyfileIdFilter)
{
vector <EMVTokenKeyfile> keyfiles;
unsigned long int nb = 0;
vector<wstring> readers;
nb = EMVToken::extractor.GetReaders();
for(unsigned long int slotId = 0; slotId<nb; slotId++)
readers = EMVCard::manager.GetReaders();
for (unsigned long int slotId = 0; slotId < readers.size(); slotId++)
{
EMVTokenInfo token;
if (slotIdFilter && *slotIdFilter != slotId)
continue;
try{
try
{
token = GetTokenInfo(slotId);
} catch(EMVUnknownCardType) {
}
catch(ParameterIncorrect&)
{
continue;
}
catch(EMVUnknownCardType&)
{
continue;
}
catch(EMVSelectAIDFailed&)
{
continue;
}
catch(EMVPANNotFound&)
{
continue;
}
catch(PCSCException&)
{
continue;
}catch(PCSCException){
continue;
}
EMVTokenKeyfile keyfile;
keyfile.Token->SlotId = slotId;
keyfile.Token = shared_ptr<TokenInfo>(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 <unsigned long int, shared_ptr<EMVCard>>::iterator emvCardsIt;
shared_ptr<EMVCard> 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<EMVCard>(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;
}
}

View File

@ -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<EMVTokenInfo>(new EMVTokenInfo());};
EMVTokenKeyfile();
EMVTokenKeyfile(const TokenKeyfilePath& path);
virtual ~EMVTokenKeyfile() {};
virtual operator TokenKeyfilePath () const;
virtual void GetKeyfileData(vector <byte>& keyfileData) const;
};
class EMVToken {
private:
static IccDataExtractor extractor;
class EMVToken
{
public:
static bool IsKeyfilePathValid(const wstring& emvTokenKeyfilePath);
static vector<EMVTokenKeyfile> GetAvailableKeyfiles(unsigned long int* slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring());
static vector<EMVTokenKeyfile> GetAvailableKeyfiles(unsigned long int* slotIdFilter = nullptr, const wstring& keyfileIdFilter = wstring());
static EMVTokenInfo GetTokenInfo(unsigned long int slotId);
friend void EMVTokenKeyfile::GetKeyfileData(vector <byte>& keyfileData) const;
static map <unsigned long int, shared_ptr<EMVCard>> EMVCards;
};
}

View File

@ -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<byte> &CERTS){
CERTS.clear();
bool iccFound= false;
bool issuerFound= false;
shared_ptr<TLVNode> node;
shared_ptr<TLVNode> ICC_Public_Key_Certificate;
shared_ptr<TLVNode> 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<unsigned char>(rec), static_cast<unsigned char>((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<byte>(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<byte>(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<byte> &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<byte>(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<byte> &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<sizeof(SELECT_TYPES)/sizeof(SELECT_TYPES[0]); i++){
/* The card does not contain this application (0:Mastercard, 1:Visa, 2:Amex) */
if(!TestingCardType(i)) continue;
isEMV= true;
GetCerts(v);
break;
}
/* Need to disconnect reconnect the card to access CPLC data (not located in any application) */
DisconnectCard();
/* Check if the card is not an EMV one */
if(!isEMV)
throw EMVUnknownCardType();
ConnectCard(readerNumber);
GetCPCL(v);
DisconnectCard();
}
/* Getting the PAN by parsing the application
* (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/
void IccDataExtractor::GetPAN(vector<byte> &v) {
bool PANFound= false;
shared_ptr<TLVNode> node;
shared_ptr<TLVNode> 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<unsigned char>(rec), static_cast<unsigned char>((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<byte>(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<typename TInputIter>
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<int>(*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<byte> 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<sizeof(SELECT_TYPES)/sizeof(SELECT_TYPES[0]); i++){
/* The card does not contain this application (0:Mastercard, 1:Visa, 2:Amex) */
if(!TestingCardType(i)) continue;
isEMV=true;
GetPAN(PAN);
break;
}
DisconnectCard();
/* Check if the card is not an EMV one */
if(!isEMV)
throw EMVUnknownCardType();
make_hex_string(PAN.begin(),PAN.end(),panString);
burn(&PAN.front(),PAN.size());
}
PCSCException::operator string() const{
if (ErrorCode == SCARD_S_SUCCESS)
return string();
static const struct{
LONG 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())
{
wstringstream subjectErrorCode;
if (SubjectErrorCodeValid)
subjectErrorCode << L": " << SubjectErrorCode;
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(), subjectErrorCode.str().c_str());
ErrorDirect(err, parent);
}
else
{
wstring err = GetString(errorString.c_str());
if (SubjectErrorCodeValid)
err += L"\n\nError code" + subjectErrorCode.str();
ErrorDirect(err.c_str(), parent);
}
}
}
#endif // TC_HEADER_Common_Exception
#ifdef TC_HEADER_Platform_Exception
void PCSCException::Deserialize(shared_ptr <Stream> 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> 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
}

View File

@ -1,231 +0,0 @@
//
// Created by bshp on 1/14/23.
//
#ifndef NEWEMV_ICCDATAEXTRACTOR_H
#define NEWEMV_ICCDATAEXTRACTOR_H
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sstream>
#include <vector>
#include <iomanip>
#include <memory>
#include "Platform/PlatformBase.h"
#include "TLVParser.h"
#ifdef __linux__
#include <unistd.h>
#endif
#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE)
# include "Exception.h"
#else
# include "Platform/Exception.h"
#endif
#ifdef TC_WINDOWS
#include <winscard.h>
#include <windows.h>
#endif
#ifdef TC_UNIX
#undef BOOL
#include <PCSC/winscard.h>
using VeraCrypt::byte;
#define BOOL int
//#include <unistd.h> //Works without on windows
#endif
#ifdef _WIN32
#include <windows.h>
#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<char*> 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<byte> &CERTS);
/* Getting CPCL data from the card and put it into a reference*/
void GetCPCL(vector<byte> &v);
/* Getting the PAN by parsing the application
* (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/
void GetPAN(vector<byte> &v);
/* Helper function to make a string from plain arrays and various standard containers of bytes */
template<typename TInputIter>
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<byte> &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

View File

@ -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 <byte> keyfileData;

View File

@ -113,7 +113,6 @@
<entry lang="en" key="IDC_CACHE">Cache passwords and keyfil&amp;es in memory</entry>
<entry lang="en" key="IDC_CLOSE_BKG_TASK_WHEN_NOVOL">Exit when there are no mounted volumes</entry>
<entry lang="en" key="IDC_CLOSE_TOKEN_SESSION_AFTER_MOUNT">&amp;Close token session (log out) after a volume is successfully mounted</entry>
<entry lang="en" key="IDC_ACTIVATE_EMV_OPTION">Activate EMV Option</entry>
<entry lang="en" key="IDC_COPY_EXPANDER">Include VeraCrypt Volume Expander</entry>
<entry lang="en" key="IDC_COPY_WIZARD">Include VeraCrypt Volume Creation Wizard</entry>
<entry lang="en" key="IDC_CREATE">Create</entry>
@ -1280,12 +1279,6 @@
<entry lang="en" key="CKR_PIN_INCORRECT">Password for security token is incorrect.</entry>
<entry lang="en" key="CKR_DEVICE_MEMORY">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').</entry>
<entry lang="en" key="ALL_TOKEN_SESSIONS_CLOSED">All open security token sessions have been closed.</entry>
<entry lang="en" key="WINSCARD_MODULE_INIT_FAILED">Error when loading the winscard library.\n\nPlease make sure the WinSCard.dll is present in your System32 folder.</entry>
<entry lang="en" key="INVALID_EMV_PATH">EMV path is invalid.</entry>
<entry lang="en" key="EMV_KEYFILE_DATA_NOT_FOUND">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.</entry>
<entry lang="en" key="EMV_PAN_NOT_FOUND">No Primary Account Number (PAN) found in the EMV card.</entry>
<entry lang="en" key="EMV_UNKNOWN_CARD_TYPE">The card in the reader is not a supported EMV card.</entry>
<entry lang="en" key="SCARD_W_REMOVED_CARD">No card in the reader.\n\nPlease make sure the card is correctly slotted.</entry>
<entry lang="en" key="SELECT_TOKEN_KEYFILES">Select Security Token Keyfiles</entry>
<entry lang="en" key="TOKEN_SLOT_ID">Slot</entry>
<entry lang="en" key="TOKEN_NAME">Token name</entry>
@ -1616,6 +1609,19 @@
<entry lang="en" key="FULL_FORMAT">Full Format</entry>
<entry lang="en" key="FAST_CREATE">Fast Create</entry>
<entry lang="en" key="WARN_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?</entry>
<entry lang="en" key="IDC_ENABLE_EMV_SUPPORT">Enable EMV Support</entry>
<entry lang="en" key="COMMAND_APDU_INVALID">The APDU command sent to the card is not valid.</entry>
<entry lang="en" key="EXTENDED_APDU_UNSUPPORTED">Extended APDU commands cannot be used with the current token.</entry>
<entry lang="en" key="SCARD_MODULE_INIT_FAILED">Error when loading the WinSCard / PCSC library.</entry>
<entry lang="en" key="EMV_UNKNOWN_CARD_TYPE">The card in the reader is not a supported EMV card.</entry>
<entry lang="en" key="EMV_SELECT_AID_FAILED">The AID of the card in the reader could not be selected.</entry>
<entry lang="en" key="EMV_ICC_CERT_NOTFOUND">ICC Public Key Certificate was not found in the card.</entry>
<entry lang="en" key="EMV_ISSUER_CERT_NOTFOUND">Issuer Public Key Certificate was not found in the card.</entry>
<entry lang="en" key="EMV_CPLC_NOTFOUND">CLPC was not found in the EMV card.</entry>
<entry lang="en" key="EMV_PAN_NOTFOUND">No Primary Account Number (PAN) found in the EMV card.</entry>
<entry lang="en" key="INVALID_EMV_PATH">EMV path is invalid.</entry>
<entry lang="en" key="EMV_KEYFILE_DATA_NOTFOUND">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.</entry>
<entry lang="en" key="SCARD_W_REMOVED_CARD">No card in the reader.\n\nPlease make sure the card is correctly slotted.</entry>
</localization>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="VeraCrypt">

View File

@ -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> stream)
{
Exception::Deserialize(stream);
Serializer sr(stream);
sr.Deserialize("ErrorCode", ErrorCode);
}
void PCSCException::Serialize(shared_ptr <Stream> 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> stream)
{
Exception::Deserialize(stream);
Serializer sr(stream);
sr.Deserialize("SrcPos", SrcPos);
sr.Deserialize("ErrorStr", ErrorStr);
}
void CommandAPDUNotValid::Serialize(shared_ptr <Stream> 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
}

136
src/Common/PCSCException.h Normal file
View File

@ -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

111
src/Common/ResponseAPDU.cpp Normal file
View File

@ -0,0 +1,111 @@
#include "ResponseAPDU.h"
#include <string.h>
using namespace std;
namespace VeraCrypt
{
uint16 BytesToUInt16(const vector<byte>& buff)
{
uint16 value = 0;
for (uint16 i = 0; i < buff.size(); i++)
{
value <<= 8;
value |= (uint16)buff.at(i);
}
return value;
}
void AppendData (vector<byte>& 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<byte>& data, uint16 SW)
{
m_data = data;
m_SW = SW;
}
uint32 ResponseAPDU::getNr()
{
return (uint32)m_data.size();
}
const vector<byte> 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<byte> ResponseAPDU::getBytes()
{
vector<byte> 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<byte>& 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<byte>& bytes)
{
clear();
if (bytes.size() >= 2)
{
vector<byte> 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);
}
}
}

44
src/Common/ResponseAPDU.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef TC_HEADER_Common_ResponseAPDU
#define TC_HEADER_Common_ResponseAPDU
#include "Platform/PlatformBase.h"
namespace VeraCrypt
{
class ResponseAPDU
{
protected:
vector<byte> m_data;
uint16 m_SW;
public:
void clear();
ResponseAPDU();
ResponseAPDU(const vector<byte>& data, uint16 SW);
uint32 getNr();
const vector<byte> getData();
byte getSW1();
byte getSW2();
uint16 getSW();
const vector<byte> getBytes();
void setSW(uint16 SW);
void setBytes(const vector<byte>& bytes);
void appendData(const vector<byte>& data);
void appendData(const byte* data, size_t dataLen);
};
};
#endif // TC_HEADER_Common_ResponseAPDU

62
src/Common/SCard.cpp Normal file
View File

@ -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;
}
}

27
src/Common/SCard.h Normal file
View File

@ -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<SCardReader> 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

402
src/Common/SCardLoader.cpp Normal file
View File

@ -0,0 +1,402 @@
#include "SCardLoader.h"
#include "PCSCException.h"
#ifndef TC_WINDOWS
#include <dlfcn.h>
#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);
}
}

125
src/Common/SCardLoader.h Normal file
View File

@ -0,0 +1,125 @@
#ifndef TC_HEADER_Common_SCardLoader
#define TC_HEADER_Common_SCardLoader
#include "Platform/PlatformBase.h"
#ifdef TC_WINDOWS
#include <winscard.h>
#include <windows.h>
#else
#ifdef TC_MACOSX
#undef BOOL
#include <PCSC/pcsclite.h>
#include <PCSC/winscard.h>
#include <PCSC/wintypes.h>
#include "reader.h"
typedef LPSCARD_READERSTATE_A LPSCARD_READERSTATE;
using VeraCrypt::byte;
#define BOOL int
#else
#undef BOOL
#include "pcsclite.h"
#include <winscard.h>
#include <wintypes.h>
#include <reader.h>
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

109
src/Common/SCardManager.cpp Normal file
View File

@ -0,0 +1,109 @@
#include "SCardManager.h"
#include "PCSCException.h"
namespace VeraCrypt
{
shared_ptr<SCardLoader> SCardManager::loader = make_shared<SCardLoader>();
SCardManager::SCardManager()
{
loader->Initialize();
}
SCardManager::~SCardManager()
{
loader->Finalize();
}
vector<wstring> SCardManager::GetReaders()
{
vector<wstring> 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<SCardReader> SCardManager::GetReader(size_t readerNumber)
{
vector<wstring> readers;
shared_ptr<SCardReader> smartCardReader;
loader->Initialize();
readers = GetReaders();
if (readerNumber < readers.size())
{
smartCardReader = make_shared<SCardReader>(readers[readerNumber], loader);
if (smartCardReader)
{
return smartCardReader;
}
}
throw InvalidEMVPath();
}
}

21
src/Common/SCardManager.h Normal file
View File

@ -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<SCardLoader> loader;
public:
SCardManager();
virtual ~SCardManager();
static vector<wstring> GetReaders();
static shared_ptr<SCardReader> GetReader(size_t readerNumber);
};
};
#endif // TC_HEADER_Common_SCardManager

681
src/Common/SCardReader.cpp Normal file
View File

@ -0,0 +1,681 @@
#include "SCardReader.h"
#include "PCSCException.h"
#include <locale>
using namespace std;
namespace VeraCrypt
{
void SCardReader::Init(const wstring& szSCReaderName, const shared_ptr<SCardLoader> 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> 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<byte>& 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<byte> 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<byte> pbSendBuffer;
vector<byte> 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<byte>& atrValue)
{
vector<byte> 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);
}
}
}

200
src/Common/SCardReader.h Normal file
View File

@ -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<SCardLoader> 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> 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> 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<byte>& 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<byte>& atrValue);
};
};
#endif // TC_HEADER_Common_SCardReader

View File

@ -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<byte>& keyfileData) const;
string IdUtf8;
CK_OBJECT_HANDLE Handle;
};

View File

@ -3,177 +3,185 @@
using namespace std;
/* TLV node structure creation */
shared_ptr<TLVNode> TLVParser::TLV_CreateNode()
namespace VeraCrypt
{
shared_ptr<TLVNode> node= shared_ptr<TLVNode>(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<long long>((__LINE__)))+" fonction parameter incorrect! bit=["+to_string(static_cast<long long>(bit)));
return(2);
}
}
/* Parsing one TLV node */
shared_ptr<TLVNode> 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<TLVNode> 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_t)buf[index++] << (i*8);
}
lensize++;
}
node->Length = 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<long long>(index))+"size="+to_string(static_cast<long long>(size)));
}
return node;
}
/* Parsing all sub-nodes (in width not in depth) of a given parent node */
int TLVParser::TLV_Parse_SubNodes(shared_ptr<TLVNode> parent){
int sublen = 0;
int i;
//No sub-nodes
if(parent->SubFlag == 0)
return 0;
for(i=0;i<parent->SubCount;i++)
/* TLV node structure creation */
shared_ptr<TLVNode> TLVParser::TLV_CreateNode()
{
sublen += (parent->Sub[i]->TagSize + parent->Sub[i]->Length + parent->Sub[i]->LengthSize);
shared_ptr<TLVNode> node = shared_ptr<TLVNode>(new TLVNode());
return node;
}
if(sublen < parent->Length)
/* Check if the bit is correct */
uint16 TLVParser::CheckBit(byte value, int bit)
{
shared_ptr<TLVNode> 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<TLVNode> parent)
{
int i;
if(parent->SubFlag != 0)
{
//Parse all sub nodes.
while(TLV_Parse_SubNodes(parent) != 0);
for(i=0;i<parent->SubCount;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<long long>((__LINE__)))+" fonction parameter incorrect! bit=["+to_string(static_cast<long long>(bit)));
//return(2);
}
}
/* Parsing one TLV node */
shared_ptr<TLVNode> 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<vector<byte>> value = make_shared<vector<byte>>();
shared_ptr<TLVNode> 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<long long>(index))+"size="+to_string(static_cast<long long>(size)));
}
return node;
}
/* Parsing all sub-nodes (in width not in depth) of a given parent node */
int TLVParser::TLV_Parse_SubNodes(shared_ptr<TLVNode> 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<TLVNode> 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<TLVNode> 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<TLVNode> TLVParser::TLV_Parse(unsigned char* buf,int size)
{
shared_ptr<TLVNode> node = TLV_Parse_One(buf,size);
TLV_Parse_Sub(node);
return node;
}
/* Finding a TLV node with a particular tag */
shared_ptr<TLVNode> TLVParser::TLV_Find(shared_ptr<TLVNode> node,uint16_t tag){
int i;
shared_ptr<TLVNode> tmpnode;
if(node->Tag == tag)
/* Parsing TLV from a buffer and constructing TLV structure */
shared_ptr<TLVNode> TLVParser::TLV_Parse(byte* buf, size_t size)
{
shared_ptr<TLVNode> node = TLV_Parse_One(buf, size);
TLV_Parse_Sub(node);
return node;
}
for(i=0;i<node->SubCount;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<TLVNode> TLVParser::TLV_Find(shared_ptr<TLVNode> node, uint16 tag)
{
size_t i = 0;
shared_ptr<TLVNode> 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;
}
}

View File

@ -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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string>
#include <memory>
#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<TLVNode> Sub[256];
shared_ptr<TLVNode> Next;
~TLVNode() {
burn(Value, Length);
delete Value;
}
};
class TLVParser{
private :
/* TLV node structure creation */
static shared_ptr<TLVNode> TLV_CreateNode();
/* Check if the bit is correct */
static uint16_t CheckBit(unsigned char value, int bit);
/* Parsing one TLV node */
static shared_ptr<TLVNode> TLV_Parse_One(unsigned char* buf,int size);
/* Parsing all TLV nodes */
static int TLV_Parse_SubNodes(shared_ptr<TLVNode> parent);
/* Parsing all sub-nodes (in width not in depth) of a given parent node */
static int TLV_Parse_All(shared_ptr<TLVNode> parent);
/* Recursive function to parse all nodes starting from a root parent node */
static void TLV_Parse_Sub(shared_ptr<TLVNode> parent);
public:
/* Parsing TLV from a buffer and constructing TLV structure */
static shared_ptr<TLVNode> TLV_Parse(unsigned char* buf,int size);
/* Finding a TLV node with a particular tag */
static shared_ptr<TLVNode> TLV_Find(shared_ptr<TLVNode> 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<vector<byte>> Value; /* V */
byte TagSize;
byte LengthSize;
uint16 MoreFlag; /* Used In Sub */
uint16 SubFlag; /* Does it have sub-nodes? */
shared_ptr<vector<shared_ptr<TLVNode>>> Subs;
protected:
std::string m_errormessage;
};
TLVNode() : Tag(0), Length(0), TagSize(0), LengthSize(0), MoreFlag(0), SubFlag(0)
{
Value = make_shared<vector<byte>>();
Subs = make_shared<vector<shared_ptr<TLVNode>>>();
}
#endif //ICC_EXTRACTOR_TLVPARSER_H
~TLVNode()
{
burn(Value->data(), Value->size());
}
};
class TLVParser
{
private :
/* TLV node structure creation */
static shared_ptr<TLVNode> TLV_CreateNode();
/* Check if the bit is correct */
static uint16 CheckBit(byte value, int bit);
/* Parsing one TLV node */
static shared_ptr<TLVNode> TLV_Parse_One(byte* buf, size_t size);
/* Parsing all TLV nodes */
static int TLV_Parse_SubNodes(shared_ptr<TLVNode> parent);
/* Parsing all sub-nodes (in width not in depth) of a given parent node */
static int TLV_Parse_All(shared_ptr<TLVNode> parent);
/* Recursive function to parse all nodes starting from a root parent node */
static void TLV_Parse_Sub(shared_ptr<TLVNode> parent);
public:
/* Parsing TLV from a buffer and constructing TLV structure */
static shared_ptr<TLVNode> TLV_Parse(byte* buf, size_t size);
/* Finding a TLV node with a particular tag */
static shared_ptr<TLVNode> TLV_Find(shared_ptr<TLVNode> 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

View File

@ -17,62 +17,94 @@
#include "SecurityToken.h"
#include "EMVToken.h"
#include "PCSCException.h"
#include "iostream"
using namespace std;
namespace VeraCrypt
{
vector<shared_ptr<TokenKeyfile>> Token::GetAvailableKeyfiles(bool EMVOption) {
vector<shared_ptr<TokenKeyfile>> Token::GetAvailableKeyfiles(bool isEMVSupportEnabled)
{
vector<shared_ptr<TokenKeyfile>> availableKeyfiles;
bool securityTokenLibraryInitialized = true;
bool scardLibraryInitialized = true;
try{
foreach (SecurityTokenKeyfile k, SecurityToken::GetAvailableKeyfiles()) {
try
{
foreach (SecurityTokenKeyfile k, SecurityToken::GetAvailableKeyfiles())
{
availableKeyfiles.push_back(shared_ptr<TokenKeyfile>(new SecurityTokenKeyfile(k)));
}
} catch (SecurityTokenLibraryNotInitialized){
}
catch (SecurityTokenLibraryNotInitialized&)
{
securityTokenLibraryInitialized = false;
}
if (isEMVSupportEnabled)
{
try
{
foreach (EMVTokenKeyfile k, EMVToken::GetAvailableKeyfiles())
{
availableKeyfiles.push_back(shared_ptr<TokenKeyfile>(new EMVTokenKeyfile(k)));
}
}
catch (ScardLibraryInitializationFailed&)
{
scardLibraryInitialized = false;
}
}
if(EMVOption){
foreach (EMVTokenKeyfile k, EMVToken::GetAvailableKeyfiles()) {
availableKeyfiles.push_back(shared_ptr<TokenKeyfile>(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 <shared_ptr<TokenInfo>> Token::GetAvailableTokens()
{
list <shared_ptr<TokenInfo>> availableTokens;
foreach(SecurityTokenInfo securityToken, SecurityToken::GetAvailableTokens()){
foreach(SecurityTokenInfo securityToken, SecurityToken::GetAvailableTokens())
{
availableTokens.push_back(shared_ptr<TokenInfo>(new SecurityTokenInfo(std::move(securityToken))));
}
return availableTokens ;
}
shared_ptr<TokenKeyfile> Token::getTokenKeyfile(const TokenKeyfilePath path){
shared_ptr<TokenKeyfile> Token::getTokenKeyfile(const TokenKeyfilePath& path)
{
shared_ptr<TokenKeyfile> tokenKeyfile;
if(SecurityToken::IsKeyfilePathValid(path)){
if (SecurityToken::IsKeyfilePathValid(path))
{
tokenKeyfile = shared_ptr<TokenKeyfile>(new SecurityTokenKeyfile(path));
} else {
if(EMVToken::IsKeyfilePathValid(path)){
}
else
{
if (EMVToken::IsKeyfilePathValid(path))
{
tokenKeyfile = shared_ptr<TokenKeyfile>(new EMVTokenKeyfile(path));
}
}

View File

@ -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 <byte>& keyfileData) const = 0;
string IdUtf8; // Was used in SecurityToken to compare with the file name from a PKCS11 card, remove from token ?
shared_ptr<TokenInfo> Token;
wstring Id;
};
class Token {
class Token
{
public:
static vector<shared_ptr<TokenKeyfile>> GetAvailableKeyfiles(bool EMVOption);
static bool IsKeyfilePathValid(const wstring& tokenKeyfilePath, bool EMVOption);
static list <shared_ptr<TokenInfo>> GetAvailableTokens(); // List available token to write
static shared_ptr<TokenKeyfile> getTokenKeyfile(const TokenKeyfilePath path);
static vector<shared_ptr<TokenKeyfile>> GetAvailableKeyfiles(bool isEMVSupportEnabled);
static bool IsKeyfilePathValid(const wstring& tokenKeyfilePath, bool isEMVSupportEnabled);
static list <shared_ptr<TokenInfo>> GetAvailableTokens();
static shared_ptr<TokenKeyfile> getTokenKeyfile(const TokenKeyfilePath& path);
};
};

271
src/Common/reader.h Normal file
View File

@ -0,0 +1,271 @@
/*
* MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
*
* Copyright (C) 1999-2005
* David Corcoran <corcoran@musclecard.com>
* Copyright (C) 2005-2009
* Ludovic Rousseau <ludovic.rousseau@free.fr>
*
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 <inttypes.h>
/* 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

View File

@ -82,10 +82,10 @@ namespace VeraCrypt
shared_ptr <KeyfileList> m_newKeyfiles;
shared_ptr <Pkcs5Kdf> m_newPkcs5Kdf;
int m_wipeCount;
bool m_emvoption;
ChangePasswordThreadRoutine(shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, shared_ptr <Pkcs5Kdf> 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> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, shared_ptr <Pkcs5Kdf> 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 <Volume> m_pVolume;
bool m_emvoption;
bool m_emvSupportEnabled;
OpenVolumeThreadRoutine(shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr<Pkcs5Kdf> Kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr<Pkcs5Kdf> protectionKdf = shared_ptr<Pkcs5Kdf> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false):
OpenVolumeThreadRoutine(shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr<Pkcs5Kdf> Kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr<Pkcs5Kdf> protectionKdf = shared_ptr<Pkcs5Kdf> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), 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 <VolumePassword> m_password;
int m_pim;
shared_ptr <KeyfileList> m_keyfiles;
bool m_emvoption;
ReEncryptHeaderThreadRoutine(const BufferPtr &newHeaderBuffer, shared_ptr <VolumeHeader> header, shared_ptr <VolumePassword> password, int pim, shared_ptr <KeyfileList> 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 <VolumeHeader> header, shared_ptr <VolumePassword> password, int pim, shared_ptr <KeyfileList> 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

View File

@ -30,7 +30,7 @@ namespace VeraCrypt
{
}
void CoreBase::ChangePassword (shared_ptr <Volume> openVolume, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, bool EMVOption, shared_ptr <Pkcs5Kdf> newPkcs5Kdf, int wipeCount) const
void CoreBase::ChangePassword (shared_ptr <Volume> openVolume, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, bool emvSupportEnabled, shared_ptr <Pkcs5Kdf> 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 <VolumePassword> password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword, EMVOption));
shared_ptr <VolumePassword> password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword, emvSupportEnabled));
bool backupHeader = false;
while (true)
@ -83,10 +83,10 @@ namespace VeraCrypt
}
}
void CoreBase::ChangePassword (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, bool EMVOption, shared_ptr <Pkcs5Kdf> newPkcs5Kdf, int wipeCount) const
void CoreBase::ChangePassword (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, bool emvSupportEnabled, shared_ptr <Pkcs5Kdf> newPkcs5Kdf, int wipeCount) const
{
shared_ptr <Volume> volume = OpenVolume (volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, EMVOption);
ChangePassword (volume, newPassword, newPim, newKeyfiles, EMVOption, newPkcs5Kdf, wipeCount);
shared_ptr <Volume> 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 <Volume> CoreBase::OpenVolume (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr<Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool EMVOption, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, int protectionPim, shared_ptr<Pkcs5Kdf> protectionKdf, shared_ptr <KeyfileList> protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) const
shared_ptr <Volume> CoreBase::OpenVolume (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr<Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, int protectionPim, shared_ptr<Pkcs5Kdf> protectionKdf, shared_ptr <KeyfileList> 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 <VolumeHeader> header, shared_ptr <VolumePassword> password, int pim, shared_ptr <KeyfileList> keyfiles, bool EMVOption) const
void CoreBase::ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr <VolumeHeader> header, shared_ptr <VolumePassword> password, int pim, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled) const
{
shared_ptr <Pkcs5Kdf> pkcs5Kdf = header->GetPkcs5Kdf();
@ -288,7 +288,7 @@ namespace VeraCrypt
SecureBuffer newSalt (header->GetSaltSize());
SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize());
shared_ptr <VolumePassword> passwordKey (Keyfile::ApplyListToPassword (keyfiles, password, EMVOption));
shared_ptr <VolumePassword> passwordKey (Keyfile::ApplyListToPassword (keyfiles, password, emvSupportEnabled));
RandomNumberGenerator::GetData (newSalt);
pkcs5Kdf->DeriveKey (newHeaderKey, *passwordKey, pim, newSalt);

View File

@ -33,8 +33,8 @@ namespace VeraCrypt
public:
virtual ~CoreBase ();
virtual void ChangePassword (shared_ptr <Volume> openVolume, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, bool EMVOption, shared_ptr <Pkcs5Kdf> newPkcs5Kdf = shared_ptr <Pkcs5Kdf> (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const;
virtual void ChangePassword (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, bool EMVOption, shared_ptr <Pkcs5Kdf> newPkcs5Kdf = shared_ptr <Pkcs5Kdf> (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const;
virtual void ChangePassword (shared_ptr <Volume> openVolume, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, bool emvSupportEnabled, shared_ptr <Pkcs5Kdf> newPkcs5Kdf = shared_ptr <Pkcs5Kdf> (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const;
virtual void ChangePassword (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> newPassword, int newPim, shared_ptr <KeyfileList> newKeyfiles, bool emvSupportEnabled, shared_ptr <Pkcs5Kdf> newPkcs5Kdf = shared_ptr <Pkcs5Kdf> (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const;
virtual void CheckFilesystem (shared_ptr <VolumeInfo> 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 <VolumeInfo> MountVolume (MountOptions &options) = 0;
virtual shared_ptr <Volume> OpenVolume (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr<Pkcs5Kdf> Kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr<Pkcs5Kdf> protectionKdf = shared_ptr<Pkcs5Kdf> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false) const;
virtual shared_ptr <Volume> OpenVolume (shared_ptr <VolumePath> volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr<Pkcs5Kdf> Kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr<Pkcs5Kdf> protectionKdf = shared_ptr<Pkcs5Kdf> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false) const;
virtual void RandomizeEncryptionAlgorithmKey (shared_ptr <EncryptionAlgorithm> encryptionAlgorithm) const;
virtual void ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr <VolumeHeader> header, shared_ptr <VolumePassword> password, int pim, shared_ptr <KeyfileList> keyfiles, bool EMVOption) const;
virtual void ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr <VolumeHeader> header, shared_ptr <VolumePassword> password, int pim, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled) const;
virtual void SetAdminPasswordCallback (shared_ptr <GetStringFunctor> functor) { }
virtual void SetApplicationExecutablePath (const FilePath &path) { ApplicationExecutablePath = path; }
virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const = 0;

View File

@ -73,7 +73,7 @@ namespace VeraCrypt
VolumeSlotNumber SlotNumber;
bool UseBackupHeaders;
bool TrueCryptMode;
bool EMVOption;
bool EMVSupportEnabled;
protected:
void CopyFrom (const MountOptions &other);

View File

@ -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));
}
}

View File

@ -548,7 +548,7 @@ namespace VeraCrypt
options.Kdf,
options.TrueCryptMode,
options.Keyfiles,
options.EMVOption,
options.EMVSupportEnabled,
options.Protection,
options.ProtectionPassword,
options.ProtectionPim,

View File

@ -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;

View File

@ -38,7 +38,7 @@ namespace VeraCrypt
shared_ptr <Pkcs5Kdf> VolumeHeaderKdf;
shared_ptr <EncryptionAlgorithm> EA;
bool Quick;
bool EMVOption;
bool EMVSupportEnabled;
struct FilesystemType
{

View File

@ -5,6 +5,10 @@
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
@ -13,6 +17,10 @@
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
@ -34,6 +42,9 @@
<ClCompile Include="..\Crypto\Aeskey.c" />
<ClCompile Include="..\Crypto\Aestab.c" />
<ClCompile Include="..\Crypto\blake2s.c" />
<ClCompile Include="..\Crypto\blake2s_SSE2.c" />
<ClCompile Include="..\Crypto\blake2s_SSE41.c" />
<ClCompile Include="..\Crypto\blake2s_SSSE3.c" />
<ClCompile Include="..\Crypto\Camellia.c" />
<ClCompile Include="..\Crypto\chacha-xmm.c" />
<ClCompile Include="..\Crypto\chacha256.c" />
@ -44,21 +55,27 @@
<ClCompile Include="..\Crypto\kuznyechik_simd.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\Crypto\rdrand.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\Crypto\SerpentFast.c" />
<ClCompile Include="..\Crypto\SerpentFast_simd.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\Crypto\Sha2.c" />
<ClCompile Include="..\Crypto\Streebog.c" />
@ -106,6 +123,16 @@
<_NT_TARGET_VERSION>0x0A00</_NT_TARGET_VERSION>
<SupportsPackaging>false</SupportsPackaging>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<_NT_TARGET_VERSION>0x0A00</_NT_TARGET_VERSION>
<SupportsPackaging>false</SupportsPackaging>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
@ -124,6 +151,15 @@
<_NT_TARGET_VERSION>0x0A00</_NT_TARGET_VERSION>
<SupportsPackaging>false</SupportsPackaging>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
<_NT_TARGET_VERSION>0x0A00</_NT_TARGET_VERSION>
<SupportsPackaging>false</SupportsPackaging>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
@ -141,6 +177,10 @@
<TargetName>veracrypt</TargetName>
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetName>veracrypt</TargetName>
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<OutDir>$(ProjectDir)$(Platform)\$(ConfigurationName)\</OutDir>
@ -150,6 +190,10 @@
<TargetName>veracrypt</TargetName>
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetName>veracrypt</TargetName>
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<Link>
<AdditionalDependencies>fltmgr.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -184,6 +228,23 @@
<SpecifyDriverVerDirectiveVersion>false</SpecifyDriverVerDirectiveVersion>
</Inf>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
<AdditionalDependencies>fltmgr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)Common;$(SolutionDir)Crypto;$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>TC_WINDOWS_DRIVER;_WIN32;_NO_CRT_STDIO_INLINE;DEBUG;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4064;4627;4627;4366;4100;4057;4457;4456;4152;4213;4244;4127;4706;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<PostBuildEvent>
<Command>copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-arm64.sys"</Command>
</PostBuildEvent>
<Inf>
<SpecifyDriverVerDirectiveVersion>false</SpecifyDriverVerDirectiveVersion>
</Inf>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<Link>
<AdditionalDependencies>fltmgr.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -220,6 +281,24 @@
<SpecifyDriverVerDirectiveVersion>false</SpecifyDriverVerDirectiveVersion>
</Inf>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
<AdditionalDependencies>fltmgr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)Common;$(SolutionDir)Crypto;$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>TC_WINDOWS_DRIVER;_WIN32;_NO_CRT_STDIO_INLINE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4064;4627;4627;4366;4100;4057;4457;4456;4152;4213;4244;4127;4706;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<PostBuildEvent>
<Command>copy $(TargetPath) "..\Release\Setup Files\VeraCrypt-arm64.sys"</Command>
</PostBuildEvent>
<Inf>
<SpecifyArchitecture>true</SpecifyArchitecture>
<SpecifyDriverVerDirectiveVersion>false</SpecifyDriverVerDirectiveVersion>
</Inf>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
@ -265,27 +344,37 @@
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win64 -Ox -g -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\Crypto\Aes_x64.asm">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -293,19 +382,27 @@
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo %(Filename)%(Extension) &amp; nasm.exe -Xvc -f win32 -Ox -g --prefix _ -o "$(TargetDir)\%(Filename).obj" "%(FullPath)"
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -313,8 +410,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -322,8 +421,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -331,8 +432,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -345,8 +448,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -354,8 +459,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -363,8 +470,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -372,8 +481,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -381,8 +492,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -390,8 +503,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -399,8 +514,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -408,8 +525,10 @@
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -418,19 +537,27 @@
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>
@ -439,19 +566,27 @@
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo %(Filename)%(Extension) &amp; ml64.exe /nologo /D_M_X64 /W3 /Cx /Zi /Fo "$(TargetDir)\%(Filename).obj" /c "%(FullPath)"
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)\%(Filename).obj;%(Outputs)</Outputs>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</CustomBuild>
</ItemGroup>
<ItemGroup>

View File

@ -148,6 +148,15 @@
<ClCompile Include="..\Crypto\blake2s.c">
<Filter>Crypto\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Crypto\blake2s_SSE2.c">
<Filter>Crypto\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Crypto\blake2s_SSE41.c">
<Filter>Crypto\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Crypto\blake2s_SSSE3.c">
<Filter>Crypto\Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="DriveFilter.h">

View File

@ -245,7 +245,7 @@ copy Debug\VeraCryptExpander.exe "..\Debug\Setup Files" &gt;NUL:
<DisableSpecificWarnings>4311;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptExpander.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -336,7 +336,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4311;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptExpander.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -428,7 +428,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4311;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptExpander.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -476,7 +476,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4311;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptExpander.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -575,8 +575,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" &gt;NUL:
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\Common\CommandAPDU.cpp" />
<ClCompile Include="..\Common\EMVCard.cpp" />
<ClCompile Include="..\Common\EMVToken.cpp" />
<ClCompile Include="..\Common\IccDataExtractor.cpp" />
<ClCompile Include="..\Common\PCSCException.cpp" />
<ClCompile Include="..\Common\ResponseAPDU.cpp" />
<ClCompile Include="..\Common\SCard.cpp" />
<ClCompile Include="..\Common\SCardLoader.cpp" />
<ClCompile Include="..\Common\SCardManager.cpp" />
<ClCompile Include="..\Common\SCardReader.cpp" />
<ClCompile Include="..\Common\TLVParser.cpp" />
<ClCompile Include="..\Common\Token.cpp" />
<ClCompile Include="..\Setup\SelfExtract.c" />
@ -659,8 +666,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" &gt;NUL:
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Common\CommandAPDU.h" />
<ClInclude Include="..\Common\EMVCard.h" />
<ClInclude Include="..\Common\EMVToken.h" />
<ClInclude Include="..\Common\IccDataExtractor.h" />
<ClInclude Include="..\Common\PCSCException.h" />
<ClInclude Include="..\Common\ResponseAPDU.h" />
<ClInclude Include="..\Common\SCard.h" />
<ClInclude Include="..\Common\SCardLoader.h" />
<ClInclude Include="..\Common\SCardManager.h" />
<ClInclude Include="..\Common\SCardReader.h" />
<ClInclude Include="..\Common\TLVParser.h" />
<ClInclude Include="..\Common\Token.h" />
<ClInclude Include="..\Common\Wipe.h" />

View File

@ -132,10 +132,31 @@
<ClCompile Include="..\Common\Token.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\IccDataExtractor.cpp">
<ClCompile Include="..\Common\TLVParser.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\TLVParser.cpp">
<ClCompile Include="..\Common\CommandAPDU.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardReader.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardLoader.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardManager.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\ResponseAPDU.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\PCSCException.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\EMVCard.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCard.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
</ItemGroup>
@ -248,10 +269,31 @@
<ClInclude Include="..\Common\Token.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\IccDataExtractor.h">
<ClInclude Include="..\Common\TLVParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\TLVParser.h">
<ClInclude Include="..\Common\CommandAPDU.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardLoader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\PCSCException.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardReader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\ResponseAPDU.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\EMVCard.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCard.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>

View File

@ -641,6 +641,17 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-arm64.exe" &gt;NUL:
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\Common\CommandAPDU.cpp" />
<ClCompile Include="..\Common\EMVCard.cpp" />
<ClCompile Include="..\Common\EMVToken.cpp" />
<ClCompile Include="..\Common\PCSCException.cpp" />
<ClCompile Include="..\Common\ResponseAPDU.cpp" />
<ClCompile Include="..\Common\SCard.cpp" />
<ClCompile Include="..\Common\SCardLoader.cpp" />
<ClCompile Include="..\Common\SCardManager.cpp" />
<ClCompile Include="..\Common\SCardReader.cpp" />
<ClCompile Include="..\Common\TLVParser.cpp" />
<ClCompile Include="..\Common\Token.cpp" />
<ClCompile Include="..\Setup\SelfExtract.c" />
<ClCompile Include="DlgExpandVolume.cpp" />
<ClCompile Include="ExpandVolume.c" />
@ -726,6 +737,17 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-arm64.exe" &gt;NUL:
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Common\CommandAPDU.h" />
<ClInclude Include="..\Common\EMVCard.h" />
<ClInclude Include="..\Common\EMVToken.h" />
<ClInclude Include="..\Common\PCSCException.h" />
<ClInclude Include="..\Common\ResponseAPDU.h" />
<ClInclude Include="..\Common\SCard.h" />
<ClInclude Include="..\Common\SCardLoader.h" />
<ClInclude Include="..\Common\SCardManager.h" />
<ClInclude Include="..\Common\SCardReader.h" />
<ClInclude Include="..\Common\TLVParser.h" />
<ClInclude Include="..\Common\Token.h" />
<ClInclude Include="..\Common\Wipe.h" />
<ClInclude Include="..\Common\Apidrvr.h" />
<ClInclude Include="..\Common\BaseCom.h" />

View File

@ -126,6 +126,39 @@
<ClCompile Include="..\Setup\SelfExtract.c">
<Filter>Source Files\Setup</Filter>
</ClCompile>
<ClCompile Include="..\Common\EMVToken.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\TLVParser.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\Token.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\CommandAPDU.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\PCSCException.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\ResponseAPDU.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardLoader.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardManager.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardReader.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\EMVCard.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCard.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Common\Wipe.h">
@ -230,6 +263,39 @@
<ClInclude Include="..\Common\Xts.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\EMVToken.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\TLVParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\Token.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\CommandAPDU.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\PCSCException.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\ResponseAPDU.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardLoader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardReader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\EMVCard.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCard.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Midl Include="..\Mount\MainCom.idl">

View File

@ -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};

View File

@ -218,7 +218,7 @@ copy Debug\VeraCryptFormat.exe "..\Debug\Setup Files\VeraCrypt Format.exe" &gt;N
<DisableSpecificWarnings>4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptFormat.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -301,7 +301,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptFormat.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -385,7 +385,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptFormat.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -429,7 +429,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptFormat.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -497,8 +497,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Common\CommandAPDU.cpp" />
<ClCompile Include="..\Common\EMVCard.cpp" />
<ClCompile Include="..\Common\EMVToken.cpp" />
<ClCompile Include="..\Common\IccDataExtractor.cpp" />
<ClCompile Include="..\Common\PCSCException.cpp" />
<ClCompile Include="..\Common\ResponseAPDU.cpp" />
<ClCompile Include="..\Common\SCard.cpp" />
<ClCompile Include="..\Common\SCardLoader.cpp" />
<ClCompile Include="..\Common\SCardManager.cpp" />
<ClCompile Include="..\Common\SCardReader.cpp" />
<ClCompile Include="..\Common\TLVParser.cpp" />
<ClCompile Include="..\Common\Token.cpp" />
<ClCompile Include="FormatCom.cpp" />
@ -581,18 +588,25 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Common\BaseCom.h" />
<ClInclude Include="..\Common\CommandAPDU.h" />
<ClInclude Include="..\Common\Common.h" />
<ClInclude Include="..\Common\Crc.h" />
<ClInclude Include="..\Common\Crypto.h" />
<ClInclude Include="..\Common\Dictionary.h" />
<ClInclude Include="..\Common\Dlgcode.h" />
<ClInclude Include="..\Common\EMVCard.h" />
<ClInclude Include="..\Common\EMVToken.h" />
<ClInclude Include="..\Common\EncryptionThreadPool.h" />
<ClInclude Include="..\Common\Endian.h" />
<ClInclude Include="..\Common\Exception.h" />
<ClInclude Include="..\Common\Fat.h" />
<ClInclude Include="..\Common\Format.h" />
<ClInclude Include="..\Common\IccDataExtractor.h" />
<ClInclude Include="..\Common\PCSCException.h" />
<ClInclude Include="..\Common\ResponseAPDU.h" />
<ClInclude Include="..\Common\SCard.h" />
<ClInclude Include="..\Common\SCardLoader.h" />
<ClInclude Include="..\Common\SCardManager.h" />
<ClInclude Include="..\Common\SCardReader.h" />
<ClInclude Include="..\Common\TLVParser.h" />
<ClInclude Include="..\Common\Token.h" />
<ClInclude Include="FormatCom.h" />

View File

@ -114,10 +114,31 @@
<ClCompile Include="..\Common\Token.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\IccDataExtractor.cpp">
<ClCompile Include="..\Common\TLVParser.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\TLVParser.cpp">
<ClCompile Include="..\Common\CommandAPDU.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\PCSCException.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\ResponseAPDU.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardLoader.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardManager.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardReader.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\EMVCard.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCard.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
</ItemGroup>
@ -226,10 +247,31 @@
<ClInclude Include="..\Common\Token.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\IccDataExtractor.h">
<ClInclude Include="..\Common\TLVParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\TLVParser.h">
<ClInclude Include="..\Common\CommandAPDU.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\PCSCException.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\ResponseAPDU.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardLoader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardReader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\EMVCard.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCard.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>

View File

@ -557,6 +557,17 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-arm64.exe" &gt;NUL:
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Common\CommandAPDU.cpp" />
<ClCompile Include="..\Common\EMVCard.cpp" />
<ClCompile Include="..\Common\EMVToken.cpp" />
<ClCompile Include="..\Common\PCSCException.cpp" />
<ClCompile Include="..\Common\ResponseAPDU.cpp" />
<ClCompile Include="..\Common\SCard.cpp" />
<ClCompile Include="..\Common\SCardLoader.cpp" />
<ClCompile Include="..\Common\SCardManager.cpp" />
<ClCompile Include="..\Common\SCardReader.cpp" />
<ClCompile Include="..\Common\TLVParser.cpp" />
<ClCompile Include="..\Common\Token.cpp" />
<ClCompile Include="FormatCom.cpp" />
<ClCompile Include="InPlace.c">
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CompileAsCpp</CompileAs>
@ -642,16 +653,27 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-arm64.exe" &gt;NUL:
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Common\BaseCom.h" />
<ClInclude Include="..\Common\CommandAPDU.h" />
<ClInclude Include="..\Common\Common.h" />
<ClInclude Include="..\Common\Crc.h" />
<ClInclude Include="..\Common\Crypto.h" />
<ClInclude Include="..\Common\Dictionary.h" />
<ClInclude Include="..\Common\Dlgcode.h" />
<ClInclude Include="..\Common\EMVCard.h" />
<ClInclude Include="..\Common\EMVToken.h" />
<ClInclude Include="..\Common\EncryptionThreadPool.h" />
<ClInclude Include="..\Common\Endian.h" />
<ClInclude Include="..\Common\Exception.h" />
<ClInclude Include="..\Common\Fat.h" />
<ClInclude Include="..\Common\Format.h" />
<ClInclude Include="..\Common\PCSCException.h" />
<ClInclude Include="..\Common\ResponseAPDU.h" />
<ClInclude Include="..\Common\SCard.h" />
<ClInclude Include="..\Common\SCardLoader.h" />
<ClInclude Include="..\Common\SCardManager.h" />
<ClInclude Include="..\Common\SCardReader.h" />
<ClInclude Include="..\Common\TLVParser.h" />
<ClInclude Include="..\Common\Token.h" />
<ClInclude Include="FormatCom.h" />
<ClInclude Include="..\Common\GfMul.h" />
<ClInclude Include="InPlace.h" />

View File

@ -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};

View File

@ -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"))

View File

@ -39,9 +39,9 @@ namespace VeraCrypt
DismountVolumes,
DisplayVersion,
DisplayVolumeProperties,
ExportSecurityTokenKeyfile,
ExportTokenKeyfile,
Help,
ImportSecurityTokenKeyfiles,
ImportTokenKeyfiles,
ListTokenKeyfiles,
ListSecurityTokenKeyfiles,
ListEMVTokenKeyfiles,

View File

@ -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);
}

View File

@ -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 );

View File

@ -593,7 +593,7 @@ namespace VeraCrypt
wxTextCtrl* Pkcs11ModulePathTextCtrl;
wxButton* SelectPkcs11ModuleButton;
wxCheckBox* CloseSecurityTokenSessionsAfterMountCheckBox;
wxCheckBox* ActivateEMVOptionCheckBox;
wxCheckBox* EMVSupportEnabledCheckBox;
wxListCtrl* HotkeyListCtrl;
wxTextCtrl* HotkeyTextCtrl;
wxButton* AssignHotkeyButton;

View File

@ -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
{

View File

@ -193,7 +193,7 @@ namespace VeraCrypt
Options.MountPoint = make_shared <DirectoryPath> (mountPoint);
Options.FilesystemOptions = FilesystemOptionsTextCtrl->GetValue();
Options.EMVOption = Gui->GetPreferences().ActivateEMVOption;
Options.EMVSupportEnabled = Gui->GetPreferences().EMVSupportEnabled;
EndModal (wxID_OK);
}

View File

@ -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);

View File

@ -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<TokenKeyfile> 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 <TokenKeyfile *> (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 <TokenKeyfile *> (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 <TokenKeyfile *> (SecurityTokenKeyfileListCtrl->GetItemData(item));
{
TokenKeyfile *key = reinterpret_cast <TokenKeyfile *> (SecurityTokenKeyfileListCtrl->GetItemData(item));
SelectedSecurityTokenKeyfilePaths.push_back(*key);
}
SelectedSecurityTokenKeyfilePaths.push_back(*key);
}
EndModal (wxID_OK);
}
}

View File

@ -795,7 +795,7 @@ namespace VeraCrypt
shared_ptr <VolumePassword> 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 <VolumePassword> 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 (...)
{

View File

@ -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;
}

View File

@ -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 <VolumePassword> passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVOption);
shared_ptr <VolumePassword> 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);

View File

@ -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 <GetStringFunctor> GetAdminPasswordRequestHandler ();
virtual int GetCharHeight (wxWindow *window) const;
@ -58,7 +58,7 @@ namespace VeraCrypt
virtual int GetScrollbarWidth (wxWindow *window, bool noScrollBar = false) const;
virtual list <long> 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 <wstring> &itemFields, int imageIndex = -1, void *itemDataPtr = nullptr) const;
virtual bool IsInBackgroundMode () const { return BackgroundMode; }

View File

@ -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 <VolumeInfo> volume = Core->MountVolume (mountOptions);
finally_do_arg (shared_ptr <VolumeInfo>, volume, { Core->DismountVolume (finally_arg, true); });
@ -1053,9 +1057,9 @@ namespace VeraCrypt
wcerr << L"Warning: " << static_cast<wstring> (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 <GetStringFunctor> (new AdminPasswordRequestHandler (this));
}
void TextUserInterface::ImportSecurityTokenKeyfiles () const
void TextUserInterface::ImportTokenKeyfiles () const
{
list <shared_ptr<TokenInfo>> 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> 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 <VolumeLayout> decryptedLayout;
@ -1649,7 +1659,7 @@ namespace VeraCrypt
backupFile.ReadAt (headerBuffer, layout->GetType() == VolumeType::Hidden ? layout->GetHeaderSize() : 0);
// Decrypt header
shared_ptr <VolumePassword> passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, true);
shared_ptr <VolumePassword> 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();

View File

@ -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 <GetStringFunctor> 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

View File

@ -17,6 +17,7 @@
#include <wx/cmdline.h>
#include "Crypto/cpu.h"
#include "Platform/PlatformTest.h"
#include "Common/PCSCException.h"
#ifdef TC_UNIX
#include <errno.h>
#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;
}

View File

@ -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 <GetStringFunctor> 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;

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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 ();

View File

@ -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

View File

@ -236,7 +236,7 @@ copy Debug\VeraCrypt.exe "..\Debug\Setup Files" &gt;NUL:
<DisableSpecificWarnings>4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCrypt.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -325,7 +325,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCrypt.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -415,7 +415,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCrypt.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -462,7 +462,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCrypt.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -533,8 +533,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" &gt;NUL:
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Common\CommandAPDU.cpp" />
<ClCompile Include="..\Common\EMVCard.cpp" />
<ClCompile Include="..\Common\EMVToken.cpp" />
<ClCompile Include="..\Common\IccDataExtractor.cpp" />
<ClCompile Include="..\Common\PCSCException.cpp" />
<ClCompile Include="..\Common\ResponseAPDU.cpp" />
<ClCompile Include="..\Common\SCard.cpp" />
<ClCompile Include="..\Common\SCardLoader.cpp" />
<ClCompile Include="..\Common\SCardManager.cpp" />
<ClCompile Include="..\Common\SCardReader.cpp" />
<ClCompile Include="..\Common\TLVParser.cpp" />
<ClCompile Include="..\Common\Token.cpp" />
<ClCompile Include="..\Setup\SelfExtract.c" />
@ -606,8 +613,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" &gt;NUL:
<Midl Include="MainCom.idl" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Common\CommandAPDU.h" />
<ClInclude Include="..\Common\EMVCard.h" />
<ClInclude Include="..\Common\EMVToken.h" />
<ClInclude Include="..\Common\IccDataExtractor.h" />
<ClInclude Include="..\Common\PCSCException.h" />
<ClInclude Include="..\Common\ResponseAPDU.h" />
<ClInclude Include="..\Common\SCard.h" />
<ClInclude Include="..\Common\SCardLoader.h" />
<ClInclude Include="..\Common\SCardManager.h" />
<ClInclude Include="..\Common\SCardReader.h" />
<ClInclude Include="..\Common\TLVParser.h" />
<ClInclude Include="..\Common\Token.h" />
<ClInclude Include="..\Common\Wipe.h" />

View File

@ -114,10 +114,31 @@
<ClCompile Include="..\Common\Token.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\IccDataExtractor.cpp">
<ClCompile Include="..\Common\TLVParser.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\TLVParser.cpp">
<ClCompile Include="..\Common\CommandAPDU.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\PCSCException.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\ResponseAPDU.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardLoader.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardManager.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCardReader.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\EMVCard.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\SCard.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
</ItemGroup>
@ -229,10 +250,31 @@
<ClInclude Include="..\Common\Token.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\IccDataExtractor.h">
<ClInclude Include="..\Common\TLVParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\TLVParser.h">
<ClInclude Include="..\Common\CommandAPDU.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\PCSCException.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\ResponseAPDU.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardLoader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCardReader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\EMVCard.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\SCard.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>

View File

@ -602,6 +602,17 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-arm64.exe" &gt;NUL:
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Common\CommandAPDU.cpp" />
<ClCompile Include="..\Common\EMVCard.cpp" />
<ClCompile Include="..\Common\EMVToken.cpp" />
<ClCompile Include="..\Common\PCSCException.cpp" />
<ClCompile Include="..\Common\ResponseAPDU.cpp" />
<ClCompile Include="..\Common\SCard.cpp" />
<ClCompile Include="..\Common\SCardLoader.cpp" />
<ClCompile Include="..\Common\SCardManager.cpp" />
<ClCompile Include="..\Common\SCardReader.cpp" />
<ClCompile Include="..\Common\TLVParser.cpp" />
<ClCompile Include="..\Common\Token.cpp" />
<ClCompile Include="..\Setup\SelfExtract.c" />
<ClCompile Include="Favorites.cpp" />
<ClCompile Include="Hotkeys.c" />
@ -675,6 +686,17 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-arm64.exe" &gt;NUL:
<Midl Include="MainCom.idl" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Common\CommandAPDU.h" />
<ClInclude Include="..\Common\EMVCard.h" />
<ClInclude Include="..\Common\EMVToken.h" />
<ClInclude Include="..\Common\PCSCException.h" />
<ClInclude Include="..\Common\ResponseAPDU.h" />
<ClInclude Include="..\Common\SCard.h" />
<ClInclude Include="..\Common\SCardLoader.h" />
<ClInclude Include="..\Common\SCardManager.h" />
<ClInclude Include="..\Common\SCardReader.h" />
<ClInclude Include="..\Common\TLVParser.h" />
<ClInclude Include="..\Common\Token.h" />
<ClInclude Include="..\Common\Wipe.h" />
<ClInclude Include="..\Common\Apidrvr.h" />
<ClInclude Include="..\Common\BaseCom.h" />

View File

@ -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

View File

@ -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

View File

@ -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 <byte> keyfileData;
Token::getTokenKeyfile(wstring(Path))->GetKeyfileData(keyfileData);
if (Token::IsKeyfilePathValid (Path, emvSupportEnabled))
{
// Apply keyfile generated by a security token
vector <byte> 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 <VolumePassword> Keyfile::ApplyListToPassword (shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> password, bool EMVOption)
shared_ptr <VolumePassword> Keyfile::ApplyListToPassword (shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> 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);

View File

@ -29,7 +29,7 @@ namespace VeraCrypt
virtual ~Keyfile () { };
operator FilesystemPath () const { return Path; }
static shared_ptr <VolumePassword> ApplyListToPassword (shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> password, bool EMVOption = false);
static shared_ptr <VolumePassword> ApplyListToPassword (shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> password, bool emvSupportEnabled = false);
static shared_ptr <KeyfileList> DeserializeList (shared_ptr <Stream> stream, const string &name);
static void SerializeList (shared_ptr <Stream> stream, const string &name, shared_ptr <KeyfileList> 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;

View File

@ -71,7 +71,7 @@ namespace VeraCrypt
return EA->GetMode();
}
void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool EMVOption, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, int protectionPim, shared_ptr <Pkcs5Kdf> protectionKdf, shared_ptr <KeyfileList> protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope)
void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, int protectionPim, shared_ptr <Pkcs5Kdf> protectionKdf, shared_ptr <KeyfileList> 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 <File> volumeFile, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool EMVOption, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, int protectionPim, shared_ptr <Pkcs5Kdf> protectionKdf,shared_ptr <KeyfileList> protectionKeyfiles, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope)
void Volume::Open (shared_ptr <File> volumeFile, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection, shared_ptr <VolumePassword> protectionPassword, int protectionPim, shared_ptr <Pkcs5Kdf> protectionKdf,shared_ptr <KeyfileList> 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 <VolumePassword> passwordKey = Keyfile::ApplyListToPassword (keyfiles, password, EMVOption);
shared_ptr <VolumePassword> 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 <VolumePassword> (), 0, shared_ptr <Pkcs5Kdf> (),shared_ptr <KeyfileList> (),
VolumeType::Hidden,

View File

@ -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 <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr <Pkcs5Kdf> protectionKdf = shared_ptr <Pkcs5Kdf> (),shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false);
void Open (shared_ptr <File> volumeFile, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr <Pkcs5Kdf> protectionKdf = shared_ptr <Pkcs5Kdf> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false);
void Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr <Pkcs5Kdf> protectionKdf = shared_ptr <Pkcs5Kdf> (),shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false);
void Open (shared_ptr <File> volumeFile, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool emvSupportEnabled, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr <Pkcs5Kdf> protectionKdf = shared_ptr <Pkcs5Kdf> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), 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 <Pkcs5Kdf> newPkcs5Kdf);
void WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset);

View File

@ -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