From ece26c74815c431b0c489a24292e7834181463a7 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 23 Mar 2016 00:14:07 +0100 Subject: Windows: Implement passing smart card PIN as command line argument (/tokenpin switch) when explicitly mounting a volume. --- src/Common/Common.rc | 8 ++++---- src/Common/Keyfiles.c | 7 ++++++- src/Common/Keyfiles.h | 1 + src/Common/SecurityToken.cpp | 36 ++++++++++++++++++++++++++---------- src/Common/SecurityToken.h | 9 +++++---- src/Mount/Mount.c | 23 +++++++++++++++++++++-- 6 files changed, 63 insertions(+), 21 deletions(-) diff --git a/src/Common/Common.rc b/src/Common/Common.rc index 8fa6c5ab..1abd1bbd 100644 --- a/src/Common/Common.rc +++ b/src/Common/Common.rc @@ -45,14 +45,14 @@ BEGIN CONTROL IDB_TEXTUAL_LOGO_96DPI,IDC_TEXTUAL_LOGO_IMG,"Static",SS_BITMAP,12,26,157,16 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 CAPTION "Command Line Help" CLASS "VeraCryptCustomDlg" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - DEFPUSHBUTTON "OK",IDOK,93,252,59,14 - LTEXT "",IDC_COMMANDHELP_TEXT,20,10,208,241 + DEFPUSHBUTTON "OK",IDOK,93,267,59,14 + LTEXT "",IDC_COMMANDHELP_TEXT,20,7,208,256 END IDD_RAWDEVICES_DLG DIALOGEX 0, 0, 305, 209 @@ -345,7 +345,7 @@ BEGIN IDD_COMMANDHELP_DLG, DIALOG BEGIN - BOTTOMMARGIN, 266 + BOTTOMMARGIN, 281 END IDD_RAWDEVICES_DLG, DIALOG diff --git a/src/Common/Keyfiles.c b/src/Common/Keyfiles.c index 366d65ee..8b3825d5 100644 --- a/src/Common/Keyfiles.c +++ b/src/Common/Keyfiles.c @@ -237,6 +237,11 @@ close: 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; KeyFile kfSubStruct; @@ -266,7 +271,7 @@ BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFile, con // Apply security token keyfile vector keyfileData; SecurityTokenKeyfilePath secPath (kf->FileName); - SecurityToken::GetKeyfileData (SecurityTokenKeyfile (secPath), keyfileData); + SecurityToken::GetKeyfileData (SecurityTokenKeyfile (secPath, pin), pin, keyfileData); if (keyfileData.empty()) { diff --git a/src/Common/Keyfiles.h b/src/Common/Keyfiles.h index 10b9b77e..899cd9e4 100644 --- a/src/Common/Keyfiles.h +++ b/src/Common/Keyfiles.h @@ -40,6 +40,7 @@ void KeyFileRemoveAll (KeyFile **firstKeyFile); KeyFile *KeyFileClone (KeyFile *keyFile); void KeyFileCloneAll (KeyFile *firstKeyFile, KeyFile **outputKeyFile); 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 KeyfilesPopupMenu (HWND hwndDlg, POINT popupPosition, KeyFilesDlgParam *dialogParam); diff --git a/src/Common/SecurityToken.cpp b/src/Common/SecurityToken.cpp index fcabce88..db80ff0d 100644 --- a/src/Common/SecurityToken.cpp +++ b/src/Common/SecurityToken.cpp @@ -36,7 +36,7 @@ using namespace std; namespace VeraCrypt { - SecurityTokenKeyfile::SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path) + SecurityTokenKeyfile::SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path, char* pin) { wstring pathStr = path; unsigned long slotId; @@ -52,7 +52,7 @@ namespace VeraCrypt Id = pathStr.substr (keyIdPos + wstring (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/").size()); - vector keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id); + vector keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id, pin); if (keyfiles.empty()) throw SecurityTokenKeyfileNotFound(); @@ -180,7 +180,7 @@ namespace VeraCrypt throw Pkcs11Exception (status); } - vector SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter) + vector SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter, char* pin) { bool unrecognizedTokenPresent = false; vector keyfiles; @@ -194,7 +194,7 @@ namespace VeraCrypt try { - LoginUserIfRequired (slotId); + LoginUserIfRequired (slotId, pin); token = GetTokenInfo (slotId); } catch (UserAbort &) @@ -314,7 +314,12 @@ namespace VeraCrypt void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector &keyfileData) { - LoginUserIfRequired (keyfile.SlotId); + GetKeyfileData (keyfile, nullptr, keyfileData); + } + + void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, char* pin, vector &keyfileData) + { + LoginUserIfRequired (keyfile.SlotId, pin); GetObjectAttribute (keyfile.SlotId, keyfile.Handle, CKA_VALUE, keyfileData); } @@ -417,22 +422,23 @@ namespace VeraCrypt 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()) OpenSession (slotId); else if (Sessions[slotId].UserLoggedIn) 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) throw Pkcs11Exception (status); Sessions[slotId].UserLoggedIn = true; } - - void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId) + + void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId, char* cmdPin) { CheckLibraryStatus(); CK_RV status; @@ -473,6 +479,10 @@ namespace VeraCrypt if (status != CKR_OK) throw Pkcs11Exception (status); } + else if (cmdPin && cmdPin [0]) + { + Login (slotId, cmdPin); + } else { string pin = tokenInfo.LabelUtf8; @@ -486,7 +496,7 @@ namespace VeraCrypt finally_do_arg (string*, &pin, { burn ((void *) finally_arg->c_str(), finally_arg->size()); }); (*PinCallback) (pin); - Login (slotId, pin); + Login (slotId, pin.c_str()); } Sessions[slotId].UserLoggedIn = true; @@ -501,6 +511,12 @@ namespace VeraCrypt } 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)); continue; } diff --git a/src/Common/SecurityToken.h b/src/Common/SecurityToken.h index c282365e..9c6c47cf 100644 --- a/src/Common/SecurityToken.h +++ b/src/Common/SecurityToken.h @@ -74,7 +74,7 @@ namespace VeraCrypt struct SecurityTokenKeyfile { 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; @@ -185,8 +185,9 @@ namespace VeraCrypt static void CloseLibrary (); static void CreateKeyfile (CK_SLOT_ID slotId, vector &keyfileData, const string &name); static void DeleteKeyfile (const SecurityTokenKeyfile &keyfile); - static vector GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring()); + static vector GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring(), char* pin = nullptr); static void GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector &keyfileData); + static void GetKeyfileData (const SecurityTokenKeyfile &keyfile, char* pin, vector &keyfileData); static list GetAvailableTokens (); static SecurityTokenInfo GetTokenInfo (CK_SLOT_ID slotId); #ifdef TC_WINDOWS @@ -204,8 +205,8 @@ namespace VeraCrypt static vector 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 &attributeValue); static list GetTokenSlots (); - static void Login (CK_SLOT_ID slotId, const string &pin); - static void LoginUserIfRequired (CK_SLOT_ID slotId); + static void Login (CK_SLOT_ID slotId, const char* pin); + static void LoginUserIfRequired (CK_SLOT_ID slotId, char* cmdPin = nullptr); static void OpenSession (CK_SLOT_ID slotId); static void CheckLibraryStatus (); diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index 6bb02d79..fbf631f8 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -129,6 +129,7 @@ int nSelectedDriveIndex = -1; /* Item number of selected drive */ int cmdUnmountDrive = -2; /* Volume drive letter to unmount (-1 = all) */ Password VolumePassword; /* Password used for mounting volumes */ Password CmdVolumePassword; /* Password passed from command line */ +char CmdTokenPin [SecurityToken::MaxPasswordLength + 1] = {0}; int VolumePkcs5 = 0; int CmdVolumePkcs5 = 0; int VolumePim = -1; @@ -237,6 +238,7 @@ static void localcleanup (void) burn (&mountOptions, sizeof (mountOptions)); burn (&defaultMountOptions, sizeof (defaultMountOptions)); burn (szFileName, sizeof(szFileName)); + burn (&CmdTokenPin, sizeof (CmdTokenPin)); /* Cleanup common code resources */ cleanup (); @@ -6334,7 +6336,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa BOOL reportBadPasswd = CmdVolumePassword.Length > 0; if (FirstCmdKeyFile) - KeyFilesApply (hwndDlg, &CmdVolumePassword, FirstCmdKeyFile, szFileName); + KeyFilesApplyWithPin (hwndDlg, &CmdVolumePassword, CmdTokenPin, FirstCmdKeyFile, szFileName); mounted = MountVolume (hwndDlg, szDriveLetter[0] - L'A', szFileName, &CmdVolumePassword, EffectiveVolumePkcs5, CmdVolumePim, EffectiveVolumeTrueCryptMode, bCacheInDriver, bIncludePimInCache, bForceMount, @@ -6379,7 +6381,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa WaitCursor (); 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); @@ -8136,6 +8138,7 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine) OptionQuit, OptionSilent, OptionTokenLib, + OptionTokenPin, OptionVolume, CommandWipeCache, OptionPkcs5, @@ -8163,6 +8166,7 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine) { OptionQuit, L"/quit", L"/q", FALSE }, { OptionSilent, L"/silent", L"/s", FALSE }, { OptionTokenLib, L"/tokenlib", NULL, FALSE }, + { OptionTokenPin, L"/tokenpin", NULL, FALSE }, { OptionTrueCryptMode, L"/truecrypt", L"/tc", FALSE }, { OptionVolume, L"/volume", L"/v", FALSE }, { CommandWipeCache, L"/wipecache", L"/w", FALSE }, @@ -8449,6 +8453,20 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine) 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: bWipe = TRUE; break; @@ -8667,6 +8685,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpsz VirtualLock (&mountOptions, sizeof (mountOptions)); VirtualLock (&defaultMountOptions, sizeof (defaultMountOptions)); VirtualLock (&szFileName, sizeof(szFileName)); + VirtualLock (&CmdTokenPin, sizeof (CmdTokenPin)); DetectX86Features (); -- cgit v1.2.3