Windows: Implement passing smart card PIN as command line argument (/tokenpin switch) when explicitly mounting a volume.

This commit is contained in:
Mounir IDRASSI 2016-03-23 00:14:07 +01:00
parent 6738cba617
commit ece26c7481
6 changed files with 63 additions and 21 deletions

View File

@ -45,14 +45,14 @@ BEGIN
CONTROL IDB_TEXTUAL_LOGO_96DPI,IDC_TEXTUAL_LOGO_IMG,"Static",SS_BITMAP,12,26,157,16 CONTROL IDB_TEXTUAL_LOGO_96DPI,IDC_TEXTUAL_LOGO_IMG,"Static",SS_BITMAP,12,26,157,16
END END
IDD_COMMANDHELP_DLG DIALOGEX 0, 0, 249, 274 IDD_COMMANDHELP_DLG DIALOGEX 0, 0, 249, 289
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Command Line Help" CAPTION "Command Line Help"
CLASS "VeraCryptCustomDlg" CLASS "VeraCryptCustomDlg"
FONT 8, "MS Shell Dlg", 0, 0, 0x0 FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN BEGIN
DEFPUSHBUTTON "OK",IDOK,93,252,59,14 DEFPUSHBUTTON "OK",IDOK,93,267,59,14
LTEXT "",IDC_COMMANDHELP_TEXT,20,10,208,241 LTEXT "",IDC_COMMANDHELP_TEXT,20,7,208,256
END END
IDD_RAWDEVICES_DLG DIALOGEX 0, 0, 305, 209 IDD_RAWDEVICES_DLG DIALOGEX 0, 0, 305, 209
@ -345,7 +345,7 @@ BEGIN
IDD_COMMANDHELP_DLG, DIALOG IDD_COMMANDHELP_DLG, DIALOG
BEGIN BEGIN
BOTTOMMARGIN, 266 BOTTOMMARGIN, 281
END END
IDD_RAWDEVICES_DLG, DIALOG IDD_RAWDEVICES_DLG, DIALOG

View File

@ -237,6 +237,11 @@ static BOOL KeyFileProcess (unsigned __int8 *keyPool, KeyFile *keyFile)
BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFile, const wchar_t* volumeFileName) BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFile, const wchar_t* volumeFileName)
{
return KeyFilesApplyWithPin (hwndDlg, password, nullptr, firstKeyFile, volumeFileName);
}
BOOL KeyFilesApplyWithPin (HWND hwndDlg, Password *password, char* pin, KeyFile *firstKeyFile, const wchar_t* volumeFileName)
{ {
BOOL status = TRUE; BOOL status = TRUE;
KeyFile kfSubStruct; KeyFile kfSubStruct;
@ -266,7 +271,7 @@ BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFile, con
// Apply security token keyfile // Apply security token keyfile
vector <byte> keyfileData; vector <byte> keyfileData;
SecurityTokenKeyfilePath secPath (kf->FileName); SecurityTokenKeyfilePath secPath (kf->FileName);
SecurityToken::GetKeyfileData (SecurityTokenKeyfile (secPath), keyfileData); SecurityToken::GetKeyfileData (SecurityTokenKeyfile (secPath, pin), pin, keyfileData);
if (keyfileData.empty()) if (keyfileData.empty())
{ {

View File

@ -40,6 +40,7 @@ void KeyFileRemoveAll (KeyFile **firstKeyFile);
KeyFile *KeyFileClone (KeyFile *keyFile); KeyFile *KeyFileClone (KeyFile *keyFile);
void KeyFileCloneAll (KeyFile *firstKeyFile, KeyFile **outputKeyFile); void KeyFileCloneAll (KeyFile *firstKeyFile, KeyFile **outputKeyFile);
BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFilem, const wchar_t* volumeFileName); BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFilem, const wchar_t* volumeFileName);
BOOL KeyFilesApplyWithPin (HWND hwndDlg, Password *password, char* pin, KeyFile *firstKeyFilem, const wchar_t* volumeFileName);
BOOL CALLBACK KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); BOOL CALLBACK KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL KeyfilesPopupMenu (HWND hwndDlg, POINT popupPosition, KeyFilesDlgParam *dialogParam); BOOL KeyfilesPopupMenu (HWND hwndDlg, POINT popupPosition, KeyFilesDlgParam *dialogParam);

View File

@ -36,7 +36,7 @@ using namespace std;
namespace VeraCrypt namespace VeraCrypt
{ {
SecurityTokenKeyfile::SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path) SecurityTokenKeyfile::SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path, char* pin)
{ {
wstring pathStr = path; wstring pathStr = path;
unsigned long slotId; unsigned long slotId;
@ -52,7 +52,7 @@ namespace VeraCrypt
Id = pathStr.substr (keyIdPos + wstring (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/").size()); Id = pathStr.substr (keyIdPos + wstring (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/").size());
vector <SecurityTokenKeyfile> keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id); vector <SecurityTokenKeyfile> keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id, pin);
if (keyfiles.empty()) if (keyfiles.empty())
throw SecurityTokenKeyfileNotFound(); throw SecurityTokenKeyfileNotFound();
@ -180,7 +180,7 @@ namespace VeraCrypt
throw Pkcs11Exception (status); throw Pkcs11Exception (status);
} }
vector <SecurityTokenKeyfile> SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter) vector <SecurityTokenKeyfile> SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter, char* pin)
{ {
bool unrecognizedTokenPresent = false; bool unrecognizedTokenPresent = false;
vector <SecurityTokenKeyfile> keyfiles; vector <SecurityTokenKeyfile> keyfiles;
@ -194,7 +194,7 @@ namespace VeraCrypt
try try
{ {
LoginUserIfRequired (slotId); LoginUserIfRequired (slotId, pin);
token = GetTokenInfo (slotId); token = GetTokenInfo (slotId);
} }
catch (UserAbort &) catch (UserAbort &)
@ -314,7 +314,12 @@ namespace VeraCrypt
void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector <byte> &keyfileData) void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector <byte> &keyfileData)
{ {
LoginUserIfRequired (keyfile.SlotId); GetKeyfileData (keyfile, nullptr, keyfileData);
}
void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, char* pin, vector <byte> &keyfileData)
{
LoginUserIfRequired (keyfile.SlotId, pin);
GetObjectAttribute (keyfile.SlotId, keyfile.Handle, CKA_VALUE, keyfileData); GetObjectAttribute (keyfile.SlotId, keyfile.Handle, CKA_VALUE, keyfileData);
} }
@ -417,22 +422,23 @@ namespace VeraCrypt
return securityTokenKeyfilePath.find (TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX) == 0; return securityTokenKeyfilePath.find (TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX) == 0;
} }
void SecurityToken::Login (CK_SLOT_ID slotId, const string &pin) void SecurityToken::Login (CK_SLOT_ID slotId, const char* pin)
{ {
if (Sessions.find (slotId) == Sessions.end()) if (Sessions.find (slotId) == Sessions.end())
OpenSession (slotId); OpenSession (slotId);
else if (Sessions[slotId].UserLoggedIn) else if (Sessions[slotId].UserLoggedIn)
return; return;
CK_RV status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, (CK_CHAR_PTR) pin.c_str(), (CK_ULONG) pin.size()); size_t pinLen = pin? strlen (pin) : 0;
CK_RV status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, (CK_CHAR_PTR) pin, (CK_ULONG) pinLen);
if (status != CKR_OK) if (status != CKR_OK)
throw Pkcs11Exception (status); throw Pkcs11Exception (status);
Sessions[slotId].UserLoggedIn = true; Sessions[slotId].UserLoggedIn = true;
} }
void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId) void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId, char* cmdPin)
{ {
CheckLibraryStatus(); CheckLibraryStatus();
CK_RV status; CK_RV status;
@ -473,6 +479,10 @@ namespace VeraCrypt
if (status != CKR_OK) if (status != CKR_OK)
throw Pkcs11Exception (status); throw Pkcs11Exception (status);
} }
else if (cmdPin && cmdPin [0])
{
Login (slotId, cmdPin);
}
else else
{ {
string pin = tokenInfo.LabelUtf8; string pin = tokenInfo.LabelUtf8;
@ -486,7 +496,7 @@ namespace VeraCrypt
finally_do_arg (string*, &pin, { burn ((void *) finally_arg->c_str(), finally_arg->size()); }); finally_do_arg (string*, &pin, { burn ((void *) finally_arg->c_str(), finally_arg->size()); });
(*PinCallback) (pin); (*PinCallback) (pin);
Login (slotId, pin); Login (slotId, pin.c_str());
} }
Sessions[slotId].UserLoggedIn = true; Sessions[slotId].UserLoggedIn = true;
@ -501,6 +511,12 @@ namespace VeraCrypt
} }
else if (error == CKR_PIN_INCORRECT && !(tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH)) else if (error == CKR_PIN_INCORRECT && !(tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH))
{ {
if (cmdPin && cmdPin [0])
{
// clear wrong PIN
size_t cmdPinLen = strlen (cmdPin);
burn (cmdPin, cmdPinLen);
}
(*WarningCallback) (Pkcs11Exception (CKR_PIN_INCORRECT)); (*WarningCallback) (Pkcs11Exception (CKR_PIN_INCORRECT));
continue; continue;
} }

View File

@ -74,7 +74,7 @@ namespace VeraCrypt
struct SecurityTokenKeyfile struct SecurityTokenKeyfile
{ {
SecurityTokenKeyfile () : Handle(CK_INVALID_HANDLE), SlotId(CK_UNAVAILABLE_INFORMATION) { Token.SlotId = CK_UNAVAILABLE_INFORMATION; Token.Flags = 0; } SecurityTokenKeyfile () : Handle(CK_INVALID_HANDLE), SlotId(CK_UNAVAILABLE_INFORMATION) { Token.SlotId = CK_UNAVAILABLE_INFORMATION; Token.Flags = 0; }
SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path); SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path, char* pin = nullptr);
operator SecurityTokenKeyfilePath () const; operator SecurityTokenKeyfilePath () const;
@ -185,8 +185,9 @@ namespace VeraCrypt
static void CloseLibrary (); static void CloseLibrary ();
static void CreateKeyfile (CK_SLOT_ID slotId, vector <byte> &keyfileData, const string &name); static void CreateKeyfile (CK_SLOT_ID slotId, vector <byte> &keyfileData, const string &name);
static void DeleteKeyfile (const SecurityTokenKeyfile &keyfile); static void DeleteKeyfile (const SecurityTokenKeyfile &keyfile);
static vector <SecurityTokenKeyfile> GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring()); static vector <SecurityTokenKeyfile> GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring(), char* pin = nullptr);
static void GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector <byte> &keyfileData); static void GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector <byte> &keyfileData);
static void GetKeyfileData (const SecurityTokenKeyfile &keyfile, char* pin, vector <byte> &keyfileData);
static list <SecurityTokenInfo> GetAvailableTokens (); static list <SecurityTokenInfo> GetAvailableTokens ();
static SecurityTokenInfo GetTokenInfo (CK_SLOT_ID slotId); static SecurityTokenInfo GetTokenInfo (CK_SLOT_ID slotId);
#ifdef TC_WINDOWS #ifdef TC_WINDOWS
@ -204,8 +205,8 @@ namespace VeraCrypt
static vector <CK_OBJECT_HANDLE> GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass); static vector <CK_OBJECT_HANDLE> GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass);
static void GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector <byte> &attributeValue); static void GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector <byte> &attributeValue);
static list <CK_SLOT_ID> GetTokenSlots (); static list <CK_SLOT_ID> GetTokenSlots ();
static void Login (CK_SLOT_ID slotId, const string &pin); static void Login (CK_SLOT_ID slotId, const char* pin);
static void LoginUserIfRequired (CK_SLOT_ID slotId); static void LoginUserIfRequired (CK_SLOT_ID slotId, char* cmdPin = nullptr);
static void OpenSession (CK_SLOT_ID slotId); static void OpenSession (CK_SLOT_ID slotId);
static void CheckLibraryStatus (); static void CheckLibraryStatus ();

View File

@ -129,6 +129,7 @@ int nSelectedDriveIndex = -1; /* Item number of selected drive */
int cmdUnmountDrive = -2; /* Volume drive letter to unmount (-1 = all) */ int cmdUnmountDrive = -2; /* Volume drive letter to unmount (-1 = all) */
Password VolumePassword; /* Password used for mounting volumes */ Password VolumePassword; /* Password used for mounting volumes */
Password CmdVolumePassword; /* Password passed from command line */ Password CmdVolumePassword; /* Password passed from command line */
char CmdTokenPin [SecurityToken::MaxPasswordLength + 1] = {0};
int VolumePkcs5 = 0; int VolumePkcs5 = 0;
int CmdVolumePkcs5 = 0; int CmdVolumePkcs5 = 0;
int VolumePim = -1; int VolumePim = -1;
@ -237,6 +238,7 @@ static void localcleanup (void)
burn (&mountOptions, sizeof (mountOptions)); burn (&mountOptions, sizeof (mountOptions));
burn (&defaultMountOptions, sizeof (defaultMountOptions)); burn (&defaultMountOptions, sizeof (defaultMountOptions));
burn (szFileName, sizeof(szFileName)); burn (szFileName, sizeof(szFileName));
burn (&CmdTokenPin, sizeof (CmdTokenPin));
/* Cleanup common code resources */ /* Cleanup common code resources */
cleanup (); cleanup ();
@ -6334,7 +6336,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
BOOL reportBadPasswd = CmdVolumePassword.Length > 0; BOOL reportBadPasswd = CmdVolumePassword.Length > 0;
if (FirstCmdKeyFile) if (FirstCmdKeyFile)
KeyFilesApply (hwndDlg, &CmdVolumePassword, FirstCmdKeyFile, szFileName); KeyFilesApplyWithPin (hwndDlg, &CmdVolumePassword, CmdTokenPin, FirstCmdKeyFile, szFileName);
mounted = MountVolume (hwndDlg, szDriveLetter[0] - L'A', mounted = MountVolume (hwndDlg, szDriveLetter[0] - L'A',
szFileName, &CmdVolumePassword, EffectiveVolumePkcs5, CmdVolumePim, EffectiveVolumeTrueCryptMode, bCacheInDriver, bIncludePimInCache, bForceMount, szFileName, &CmdVolumePassword, EffectiveVolumePkcs5, CmdVolumePim, EffectiveVolumeTrueCryptMode, bCacheInDriver, bIncludePimInCache, bForceMount,
@ -6379,7 +6381,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
WaitCursor (); WaitCursor ();
if (KeyFilesEnable && FirstKeyFile) if (KeyFilesEnable && FirstKeyFile)
KeyFilesApply (hwndDlg, &VolumePassword, FirstKeyFile, szFileName); KeyFilesApplyWithPin (hwndDlg, &VolumePassword, CmdTokenPin, FirstKeyFile, szFileName);
mounted = MountVolume (hwndDlg, szDriveLetter[0] - L'A', szFileName, &VolumePassword, VolumePkcs5, VolumePim, VolumeTrueCryptMode, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, FALSE, TRUE); mounted = MountVolume (hwndDlg, szDriveLetter[0] - L'A', szFileName, &VolumePassword, VolumePkcs5, VolumePim, VolumeTrueCryptMode, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, FALSE, TRUE);
@ -8136,6 +8138,7 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
OptionQuit, OptionQuit,
OptionSilent, OptionSilent,
OptionTokenLib, OptionTokenLib,
OptionTokenPin,
OptionVolume, OptionVolume,
CommandWipeCache, CommandWipeCache,
OptionPkcs5, OptionPkcs5,
@ -8163,6 +8166,7 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
{ OptionQuit, L"/quit", L"/q", FALSE }, { OptionQuit, L"/quit", L"/q", FALSE },
{ OptionSilent, L"/silent", L"/s", FALSE }, { OptionSilent, L"/silent", L"/s", FALSE },
{ OptionTokenLib, L"/tokenlib", NULL, FALSE }, { OptionTokenLib, L"/tokenlib", NULL, FALSE },
{ OptionTokenPin, L"/tokenpin", NULL, FALSE },
{ OptionTrueCryptMode, L"/truecrypt", L"/tc", FALSE }, { OptionTrueCryptMode, L"/truecrypt", L"/tc", FALSE },
{ OptionVolume, L"/volume", L"/v", FALSE }, { OptionVolume, L"/volume", L"/v", FALSE },
{ CommandWipeCache, L"/wipecache", L"/w", FALSE }, { CommandWipeCache, L"/wipecache", L"/w", FALSE },
@ -8449,6 +8453,20 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine)
break; break;
case OptionTokenPin:
{
wchar_t szTmp[SecurityToken::MaxPasswordLength + 1] = {0};
if (GetArgumentValue (lpszCommandLineArgs, &i, nNoCommandLineArgs, szTmp, ARRAYSIZE (szTmp)) == HAS_ARGUMENT)
{
if (0 == WideCharToMultiByte (CP_UTF8, 0, szTmp, -1, CmdTokenPin, array_capacity (CmdTokenPin), nullptr, nullptr))
AbortProcess ("COMMAND_LINE_ERROR");
}
else
AbortProcess ("COMMAND_LINE_ERROR");
}
break;
case CommandWipeCache: case CommandWipeCache:
bWipe = TRUE; bWipe = TRUE;
break; break;
@ -8667,6 +8685,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpsz
VirtualLock (&mountOptions, sizeof (mountOptions)); VirtualLock (&mountOptions, sizeof (mountOptions));
VirtualLock (&defaultMountOptions, sizeof (defaultMountOptions)); VirtualLock (&defaultMountOptions, sizeof (defaultMountOptions));
VirtualLock (&szFileName, sizeof(szFileName)); VirtualLock (&szFileName, sizeof(szFileName));
VirtualLock (&CmdTokenPin, sizeof (CmdTokenPin));
DetectX86Features (); DetectX86Features ();