mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2026-10-18 04:15:56 +00:00
Security tokens: improve cleanup while preserving EMV caching
Wipe keyfile buffers before reporting errors and releasing storage. Handle allocation failures during Windows token import. Preserve EMV session caching to avoid repeated card resets and reads. Clarify cache lifetimes and release token labels when dialogs close. Fix reader ownership during EMV card moves.
This commit is contained in:
@@ -126,8 +126,11 @@ According to the ISO/IEC 7816 standard on which the EMV standard is based, commu
|
||||
defined by the ASN.1 standard, and therefore need to be parsed before being concatenated into a keyfile. No PIN is required to access and retrieve data from the card. To cope with the diversity of smart cards readers on the market, librairies compliant with the Microsoft Personal
|
||||
Computer/Smart Card communication standard are used. The Winscard library is used. Natively available on Windows in System32, it then doesn't require any installation on this operating system. However, the libpcsclite1 package has to be installed on Linux.</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
Since the card is read-only, it is not possible to import or delete data. However, data used as keyfiles can be exported locally in any binary file. During the entire cryptographic process of mounting or creating a volume, the certificates and CPLC data are never stored anywhere
|
||||
other than in the user's machine RAM. Once the process is complete, these RAM memory areas are rigorously erased.</div>
|
||||
Since the card is read-only, it is not possible to import or delete data. However, data used as keyfiles can be exported locally in any binary file. VeraCrypt caches the certificates and CPLC data in memory for reuse while the card connection remains valid. This avoids resetting and reading the card again for each keyfile use. VeraCrypt erases the temporary buffers used to assemble and apply the keyfile after use, including when an operation returns an error.</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
Cached EMV keyfile data and card identification information may remain in memory until VeraCrypt closes the token sessions or exits normally. To clear this cache, select <em>Tools > Close All Security Token Sessions</em> or enable the option to close token sessions after mounting. Password caching is separate: when it is enabled, processed keyfile contents can remain in the password cache and allow a volume to be mounted without reading the card again. Use <em>Wipe Cache</em> to clear that password cache, or disable password caching to prevent this retention.</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
Abrupt termination can prevent cleanup. These measures do not guarantee that RAM contains no sensitive data or that other copies, such as those in a paging file, have been erased. See <a href="Unencrypted%20Data%20in%20RAM.html">Unencrypted Data in RAM</a> for the precautions that still apply.</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
It important to note that this feature is optional and disabled by default. It can be enabled in the <em style="text-align:left">Security Token Preferences</em> parameters by checking the box provided.</div>
|
||||
<p> </p>
|
||||
|
||||
@@ -148,8 +148,11 @@ VeraCrypt, нажмите кнопку <em style="text-align:left">Токен-ф
|
||||
определённом в стандарте ASN.1, и поэтому должны быть проанализированы перед объединением в ключевой файл. Для доступа и извлечения данных с карты не требуется PIN-код. Чтобы справиться с разнообразием считывателей смарт-карт, представленных на рынке, используются библиотеки, совместимые со стандартом связи
|
||||
Microsoft Personal Computer/Smart Card. Применяется библиотека Winscard. Изначально доступная в Windows в System32, она не требует установки в этой ОС. В Linux же необходимо установить пакет libpcsclite1.</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
Поскольку карта доступна только для чтения, импортировать или удалить данные невозможно. Однако данные, используемые в качестве ключевых файлов, можно экспортировать локально в любой двоичный файл. В течение всего криптографического процесса монтирования или создания тома сертификаты и данные CPLC сохраняются
|
||||
только в оперативной памяти компьютера. После завершения процесса эти области памяти ОЗУ тщательно стираются.</div>
|
||||
Поскольку карта доступна только для чтения, импортировать или удалить данные невозможно. Однако данные, используемые в качестве ключевых файлов, можно экспортировать локально в любой двоичный файл. VeraCrypt кэширует сертификаты и данные CPLC в памяти для повторного использования, пока подключение к карте остаётся действительным. Это позволяет не сбрасывать и не считывать карту заново при каждом использовании ключевого файла. VeraCrypt стирает временные буферы, используемые для формирования и обработки ключевого файла, после использования, в том числе при завершении операции с ошибкой.</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
Кэшированные данные ключевых файлов EMV и сведения для идентификации карт могут оставаться в памяти до закрытия сессий токенов или нормального выхода из VeraCrypt. Чтобы очистить этот кэш, выберите <em>Сервис > Закрыть все токен-сессии</em> или включите автоматическое закрытие сессий токенов после монтирования. Кэширование паролей работает отдельно: если оно включено, обработанное содержимое ключевого файла может оставаться в кэше паролей и позволять монтировать том без повторного чтения карты. Используйте <em>Очистить кэш</em> для очистки кэша паролей или отключите кэширование паролей, чтобы предотвратить такое сохранение.</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
Внезапное завершение работы может помешать очистке. Эти меры не гарантируют отсутствия конфиденциальных данных в ОЗУ или удаления других копий, например в файле подкачки. Необходимые меры предосторожности описаны в разделе <a href="Unencrypted%20Data%20in%20RAM.html">Незашифрованные данные в ОЗУ</a>.</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
Важно отметить, что эта функция не является обязательной и по умолчанию отключена. Её можно включить в <em style="text-align:left">настройках токенов безопасности</em>.</div>
|
||||
<p> </p>
|
||||
|
||||
@@ -102,7 +102,13 @@ VeraCrypt的Windows和Linux版本可以直接将从符合EMV标准、支持Visa
|
||||
根据EMV标准所基于的ISO/IEC 7816标准,与EMV智能卡的通信是通过称为APDU的结构化命令完成的,这些命令允许从智能卡中提取数据。这些数据采用由ASN.1标准定义的BER - TLV格式进行编码,因此在拼接成密钥文件之前需要进行解析。访问和检索卡片中的数据不需要PIN码。为了适应市场上各种智能卡读卡器,使用了符合Microsoft个人计算机/智能卡通信标准的库。使用了Winscard库。该库在Windows系统的System32目录中是原生可用的,因此在该操作系统上无需安装。然而,在Linux系统上必须安装libpcsclite1软件包。
|
||||
</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
由于卡片是只读的,因此无法导入或删除数据。但是,用作密钥文件的数据可以导出到本地的任何二进制文件中。在挂载或创建卷的整个加密过程中,证书和CPLC数据仅存储在用户计算机的RAM中。一旦过程完成,这些RAM内存区域将被严格擦除。
|
||||
由于卡片是只读的,因此无法导入或删除数据。但是,用作密钥文件的数据可以导出到本地的任何二进制文件中。VeraCrypt会将证书和CPLC数据缓存在内存中,在卡片连接仍然有效时重复使用。这样就不必在每次使用密钥文件时重置并重新读取卡片。VeraCrypt会在使用后擦除用于拼接和处理密钥文件的临时缓冲区,包括操作因错误而结束的情况。
|
||||
</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
缓存的EMV密钥文件数据和卡片标识信息可能会保留在内存中,直到令牌会话关闭或VeraCrypt正常退出。要清除此缓存,请选择<em>工具 > 关闭所有安全口令牌会话</em>,或启用挂载后自动关闭令牌会话的选项。密码缓存是独立的功能:启用后,处理过的密钥文件内容可能会保留在密码缓存中,从而允许在不重新读取卡片的情况下挂载卷。使用<em>擦除缓存</em>可清除此密码缓存,也可以禁用密码缓存以避免保留这些内容。
|
||||
</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
程序突然终止可能会导致清理无法完成。这些措施不能保证RAM中不含敏感数据,也不能保证其他副本(例如分页文件中的副本)已被擦除。仍需遵循的预防措施请参阅<a href="Unencrypted%20Data%20in%20RAM.html">RAM中的未加密数据</a>。
|
||||
</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
需要注意的是,此功能是可选的,默认情况下处于禁用状态。可以在<em style="text-align:left">安全令牌首选项</em>参数中,通过勾选提供的复选框来启用该功能。
|
||||
@@ -193,4 +199,4 @@ VeraCrypt的Windows和Linux版本可以直接将从符合EMV标准、支持Visa
|
||||
<p><span style="text-align:left; font-size:10px; line-height:12px">* 在挂载卷、更改其密码或执行任何涉及重新加密卷头的操作时找到的文件。<br style="text-align:left">
|
||||
** 但是,如果您使用MP3文件作为密钥文件,则必须确保没有程序修改MP3文件中的ID3标签(例如歌曲标题、艺术家姓名等)。否则,将无法挂载使用该密钥文件的卷。<br style="text-align:left">
|
||||
</span></p>
|
||||
</div><div class="ClearBoth"></div></div></body></html>
|
||||
</div><div class="ClearBoth"></div></div></body></html>
|
||||
|
||||
+42
-37
@@ -23,6 +23,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <math.h>
|
||||
#include <new>
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -552,6 +553,8 @@ char *LoadFile (const wchar_t *fileName, DWORD *size)
|
||||
|
||||
if (!ReadFile (h, buf, fileSize, size, NULL))
|
||||
{
|
||||
// A failed read may have already copied part of a keyfile into the buffer.
|
||||
burn (buf, fileSize);
|
||||
free (buf);
|
||||
buf = NULL;
|
||||
}
|
||||
@@ -12889,6 +12892,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
keyfiles.clear();
|
||||
DetachProtectionFromCurrentThread();
|
||||
break;
|
||||
|
||||
@@ -12937,34 +12941,36 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
|
||||
|
||||
case IDC_IMPORT_KEYFILE:
|
||||
{
|
||||
wchar_t keyfilePath[TC_MAX_PATH];
|
||||
|
||||
if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE))
|
||||
try
|
||||
{
|
||||
DWORD keyfileSize;
|
||||
uint8 *keyfileData = (uint8 *) LoadFile (keyfilePath, &keyfileSize);
|
||||
if (!keyfileData)
|
||||
wchar_t keyfilePath[TC_MAX_PATH];
|
||||
|
||||
if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE))
|
||||
{
|
||||
handleWin32Error (hwndDlg, SRC_POS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (keyfileSize != 0)
|
||||
{
|
||||
NewSecurityTokenKeyfileDlgProcParams newParams;
|
||||
newParams.Name = WideToUtf8String (keyfilePath);
|
||||
|
||||
size_t lastBackSlash = newParams.Name.find_last_of ('\\');
|
||||
if (lastBackSlash != string::npos)
|
||||
newParams.Name = newParams.Name.substr (lastBackSlash + 1);
|
||||
|
||||
if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_NEW_TOKEN_KEYFILE), hwndDlg, (DLGPROC) NewSecurityTokenKeyfileDlgProc, (LPARAM) &newParams) == IDOK)
|
||||
DWORD keyfileSize;
|
||||
uint8 *keyfileData = (uint8 *) LoadFile (keyfilePath, &keyfileSize);
|
||||
if (!keyfileData)
|
||||
{
|
||||
vector <uint8> keyfileDataVector (keyfileSize);
|
||||
memcpy (&keyfileDataVector.front(), keyfileData, keyfileSize);
|
||||
handleWin32Error (hwndDlg, SRC_POS);
|
||||
return 1;
|
||||
}
|
||||
finally_do_arg2 (uint8 *, keyfileData, DWORD, keyfileSize, { burn (finally_arg, finally_arg2); TCfree (finally_arg); });
|
||||
|
||||
try
|
||||
if (keyfileSize != 0)
|
||||
{
|
||||
NewSecurityTokenKeyfileDlgProcParams newParams;
|
||||
newParams.Name = WideToUtf8String (keyfilePath);
|
||||
|
||||
size_t lastBackSlash = newParams.Name.find_last_of ('\\');
|
||||
if (lastBackSlash != string::npos)
|
||||
newParams.Name = newParams.Name.substr (lastBackSlash + 1);
|
||||
|
||||
if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_NEW_TOKEN_KEYFILE), hwndDlg, (DLGPROC) NewSecurityTokenKeyfileDlgProc, (LPARAM) &newParams) == IDOK)
|
||||
{
|
||||
vector <uint8> keyfileDataVector (keyfileSize);
|
||||
finally_do_arg (vector <uint8> *, &keyfileDataVector, { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); });
|
||||
memcpy (&keyfileDataVector.front(), keyfileData, keyfileSize);
|
||||
|
||||
WaitCursor();
|
||||
finally_do ({ NormalCursor(); });
|
||||
|
||||
@@ -12973,22 +12979,21 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
|
||||
keyfiles = Token::GetAvailableKeyfiles(EMVSupportEnabled? true : false);
|
||||
SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles);
|
||||
}
|
||||
catch (Exception &e)
|
||||
{
|
||||
e.Show (hwndDlg);
|
||||
}
|
||||
|
||||
burn (&keyfileDataVector.front(), keyfileSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError (ERROR_HANDLE_EOF);
|
||||
handleWin32Error (hwndDlg, SRC_POS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError (ERROR_HANDLE_EOF);
|
||||
handleWin32Error (hwndDlg, SRC_POS);
|
||||
}
|
||||
|
||||
burn (keyfileData, keyfileSize);
|
||||
TCfree (keyfileData);
|
||||
}
|
||||
catch (Exception &e)
|
||||
{
|
||||
e.Show (hwndDlg);
|
||||
}
|
||||
catch (const std::bad_alloc&)
|
||||
{
|
||||
Error ("OUTOFMEMORY", hwndDlg);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace VeraCrypt
|
||||
}
|
||||
|
||||
EMVCard::EMVCard(EMVCard&& other) :
|
||||
SCard(other),
|
||||
SCard(std::move(other)),
|
||||
m_aid(std::move(other.m_aid)),
|
||||
m_supportedAids(std::move(other.m_supportedAids)),
|
||||
m_iccCert(std::move(other.m_iccCert)),
|
||||
@@ -259,7 +259,7 @@ namespace VeraCrypt
|
||||
size_t remainingDirectoryBytes = maxDirectoryRecords * SCardReader::shortAPDUMaxTransSize;
|
||||
for (unsigned int rec = 1; rec <= maxDirectoryRecords; ++rec)
|
||||
{
|
||||
command = CommandAPDU(CLA_ISO7816, INS_READ_RECORD, rec, (sfi << 3) | 4, SCardReader::shortAPDUMaxTransSize);
|
||||
command = CommandAPDU(CLA_ISO7816, INS_READ_RECORD, static_cast<uint8>(rec), (sfi << 3) | 4, SCardReader::shortAPDUMaxTransSize);
|
||||
m_reader->ApduProcessData(command, response);
|
||||
if (response.getSW() == SW_NO_ERROR && response.getData().size() > 0)
|
||||
{
|
||||
|
||||
@@ -25,10 +25,8 @@ namespace VeraCrypt
|
||||
{
|
||||
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.
|
||||
// Reuse certificate and CPLC data while the card handle remains valid.
|
||||
// Clear erases the cached keyfile bytes when the card is discarded.
|
||||
vector<uint8> m_aid;
|
||||
vector<vector<uint8>> m_supportedAids;
|
||||
vector<uint8> m_iccCert;
|
||||
|
||||
@@ -243,6 +243,7 @@ BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFile, con
|
||||
if (firstKeyFile == NULL) return TRUE;
|
||||
|
||||
VirtualLock (keyPool, sizeof (keyPool));
|
||||
finally_do_arg (unsigned __int8 *, keyPool, { burn (finally_arg, KEYFILE_POOL_SIZE); });
|
||||
memset (keyPool, 0, sizeof (keyPool));
|
||||
|
||||
for (kf = firstKeyFile; kf != NULL; kf = kf->Next)
|
||||
@@ -292,6 +293,7 @@ BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFile, con
|
||||
}
|
||||
catch (Exception &e)
|
||||
{
|
||||
burn (keyPool, sizeof (keyPool));
|
||||
e.Show (NULL);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -400,8 +402,6 @@ BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFile, con
|
||||
if (password->Length < keyPoolSize)
|
||||
password->Length = keyPoolSize;
|
||||
|
||||
burn (keyPool, sizeof (keyPool));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user