From 502ab9112a7624dbd7c1c90c2e12ed45512b8b3c Mon Sep 17 00:00:00 2001 From: mmauv <99472743+mmauv@users.noreply.github.com> Date: Wed, 28 Jun 2023 22:51:43 +0200 Subject: Add EMV functionality (#1080) * Add basic strcture needed for EMV implementation * Add demo EMV functionality with C code pasted in a very dirty and unsafe way. NOT FINAL * Refactor IccExtractor Structure * Fix Makefile * fix include file * move global variables from h to c * revert to memcpy * fix icc data recovery functions * Add EMV functionalities on windows * Make EMVToken structures like SecurityToken * Define constants instead of hard coded values * Token structures created with inheritance * refactor TokenKeyfile to use inherit. + polymor. * add Token.h + Token.cpp in modules in VS2010 * Add a comment at each use of SecurityToken class or objects * SecurityTokenKeyfilesDialog preparation * Implemennt GetAvailableTokens in Token class on windows * merge * up (patching for Windows) * foreach Token.cpp corrected * Display EMV keyfiles on first window in graphic interface * Add token to Windows UI * EMVToken selection on OKButton on Linux * Keyfile.cpp optimization * Move getKeyfileData in the token class * EMV::Token GetAvailableKeyfiles() base * Move getKeyfileData in the token class on unix * Remove test comments * Warnings resolved * RemoveeSecurityTokenLibraryNotInitialized exception if at least one emv token is detected * Adding new files * Remove old files and add the new version to the windows project * Change make_shared to shared_ptr constructor * IccExtractor integration working on linux * Throwing card not EMV execption * catch error when not EMV type in EMVToken::GetAvailableKeyfiles * Change types to compile on windows * list all keyfiles, security keyfiles and emv keyfiles in command line * Change type to be coherent and remove old todo comments * Remove todo comments * Change indentation and resolve a bug from previous commit * Use polymorphism for GetKeyfileData and add export option for EMVTokens on Linux * Linux : Allow to export EMV Tokens in command lines, Windows : Disable the delete button when EMV Keyfiles are selected * Remove SlotId from TokenInfo as it is already in Token * Correct errors on Linux * Disable delete option if one EMV Token is selected on Linux * Fix bug enabling delete button if nothing is selected * emv data used as reference then burnt * use of normal files in linux corrected * help updated * help updated for export functionnality * option EMV added to graphic interface but not yet working * Bug fix : Allow to use multiple EMV on windows * EMV Option added to UserPreferences * EMV Option working for Linux * EMV option added to Windows (not working yet) * [NOT TESTED] EMV option for Windows * Working EMV option on Windows * EMV Option for data extraction working for volume creation * EMV Option for data extraction working for Mount * EMV Option for data extraction working for mounting favorites volumes * EMV Option for extraction working for Changing volume password, Set Derivation Key Algorithm and Add or remove keyfile from volume * Windows : re-checking EMV Option when getting data * Removing error catches in the IccDataExtractor classe (It only throws error now). Changing GetPan signature to resemble the other functions signatures more * Changing EMV errors - Only throwing ICCExtractionException from outside of the ICC module. - Catching all TLVExceptions and PCSCExceptions to throw the right ICCExtractionException - Deleting APDU exceptions. * First version of the documentation * Adding function pointers for winscard library (but it crashes VeraCrypt) * Debugging function pointers * The import of the library on windows work as expected now * Reverting EMVToken.cpp changes used to test to library import * Searching for the System32 path instead of hard codding it * Fixing the bug were VeraCrypt crashes if there is no readers when "add Token files" is clicked * Winscard library not initialized in object constructor anymore to delay it after EMVOption check * Remove winscard lib from windows dependencies * Properly displaying errors * Adding a dot in Language.xml * Catching TLVException * Removing unused code * Remove unusefull comments * Trying to fix 0x1f error * Update IccDataExtractor.cpp * Delete History.xml * Fix get data without get pan * Cleanup code * changes for linux compilation but linking not working * error handling for linux * erasing emv data * Burn PAN * Burn PAN from memory * Uncomment selfcheck before merging master * burn corrected * EMV errors handling for Linux * EMV working for Linux CLI * Doc : Winscard Linux package and VeraCrypt versions --------- Co-authored-by: doriandu45 Co-authored-by: red4game Co-authored-by: Brice.Namy Co-authored-by: vocthor Co-authored-by: vocthor <67202139+vocthor@users.noreply.github.com> Co-authored-by: Andrei COCAN Co-authored-by: AndreiCocan <95496161+AndreiCocan@users.noreply.github.com> Co-authored-by: francoisLEROUX --- doc/html/Documentation.html | 1 + doc/html/EMV Smart Cards.html | 87 +++ doc/html/Keyfiles in VeraCrypt.html | 19 + doc/html/Keyfiles.html | 295 +++++++--- src/Common/Dlgcode.c | 58 +- src/Common/Dlgcode.h | 1 + src/Common/EMVToken.cpp | 121 ++++ src/Common/EMVToken.h | 50 ++ src/Common/IccDataExtractor.cpp | 777 +++++++++++++++++++++++++ src/Common/IccDataExtractor.h | 231 ++++++++ src/Common/Keyfiles.c | 15 +- src/Common/Language.xml | 8 + src/Common/SecurityToken.cpp | 522 +++++++++-------- src/Common/SecurityToken.h | 126 ++-- src/Common/TLVParser.cpp | 179 ++++++ src/Common/TLVParser.h | 80 +++ src/Common/Token.cpp | 82 +++ src/Common/Token.h | 57 ++ src/Core/Core.h | 19 +- src/Core/CoreBase.cpp | 18 +- src/Core/CoreBase.h | 8 +- src/Core/MountOptions.h | 1 + src/Core/Unix/CoreServiceProxy.h | 6 +- src/Core/Unix/CoreUnix.cpp | 1 + src/Core/VolumeCreator.cpp | 2 +- src/Core/VolumeCreator.h | 1 + src/ExpandVolume/ExpandVolume.vcxproj | 16 +- src/ExpandVolume/ExpandVolume.vcxproj.filters | 24 + src/ExpandVolume/WinMain.cpp | 1 + src/Format/Format.vcxproj | 20 +- src/Format/Format.vcxproj.filters | 24 + src/Format/Tcformat.c | 4 +- src/Main/CommandLineInterface.cpp | 16 +- src/Main/CommandLineInterface.h | 4 +- src/Main/Forms/ChangePasswordDialog.cpp | 2 +- src/Main/Forms/Forms.cpp | 13 +- src/Main/Forms/Forms.h | 1 + src/Main/Forms/KeyfilesPanel.cpp | 2 +- src/Main/Forms/MainFrame.cpp | 3 +- src/Main/Forms/MountOptionsDialog.cpp | 1 + src/Main/Forms/PreferencesDialog.cpp | 1 + src/Main/Forms/SecurityTokenKeyfilesDialog.cpp | 53 +- src/Main/Forms/SecurityTokenKeyfilesDialog.h | 8 +- src/Main/Forms/VolumeCreationWizard.cpp | 8 +- src/Main/Forms/VolumePasswordPanel.cpp | 2 +- src/Main/Forms/WaitDialog.cpp | 9 + src/Main/GraphicUserInterface.cpp | 27 +- src/Main/GraphicUserInterface.h | 4 +- src/Main/TextUserInterface.cpp | 62 +- src/Main/TextUserInterface.h | 4 +- src/Main/UserInterface.cpp | 67 ++- src/Main/UserInterface.h | 2 + src/Main/UserPreferences.cpp | 2 + src/Main/UserPreferences.h | 2 + src/Makefile | 4 + src/Mount/Mount.c | 27 +- src/Mount/Mount.rc | 8 +- src/Mount/Mount.vcxproj | 16 +- src/Mount/Mount.vcxproj.filters | 24 + src/Mount/Resource.h | 2 + src/Volume/Keyfile.cpp | 84 ++- src/Volume/Keyfile.h | 4 +- src/Volume/Volume.cpp | 9 +- src/Volume/Volume.h | 4 +- src/Volume/Volume.make | 4 + 65 files changed, 2721 insertions(+), 612 deletions(-) create mode 100644 doc/html/EMV Smart Cards.html create mode 100644 src/Common/EMVToken.cpp create mode 100644 src/Common/EMVToken.h create mode 100644 src/Common/IccDataExtractor.cpp create mode 100644 src/Common/IccDataExtractor.h create mode 100644 src/Common/TLVParser.cpp create mode 100644 src/Common/TLVParser.h create mode 100644 src/Common/Token.cpp create mode 100644 src/Common/Token.h diff --git a/doc/html/Documentation.html b/doc/html/Documentation.html index f6a46629..e18feb35 100644 --- a/doc/html/Documentation.html +++ b/doc/html/Documentation.html @@ -66,6 +66,7 @@
  • Hot keys
  • Keyfiles
  • Security Tokens & Smart Cards +
  • EMV Smart Cards
  • Portable Mode
  • TrueCrypt Support
  • Converting TrueCrypt Volumes & Partitions diff --git a/doc/html/EMV Smart Cards.html b/doc/html/EMV Smart Cards.html new file mode 100644 index 00000000..d9c8716a --- /dev/null +++ b/doc/html/EMV Smart Cards.html @@ -0,0 +1,87 @@ + + + + + + VeraCrypt - Free Open source disk encryption with strong security for the + Paranoid + + + + + + +
    + VeraCrypt +
    + + + + + +
    +

    EMV Smart Cards

    +
    +

    + Windows and Linux versions of VeraCrypt offer to use EMV compliant + smart cards as a feature. Indeed, the use of PKCS#11 compliant smart + cards is dedicated to users with more or less cybersecurity skills. + However, in some situations, having such a card strongly reduces the + plausible deniability of the user. +

    +

    + To overcome this problem, the idea is to allow the use of a type of + smart card owned by anyone: EMV compliant smart cards. According to + the standard of the same name, these cards spread all over the world + are used to carry out banking operations. Using internal data of the + user's EMV card as keyfiles will strengthen the security of his volume + while keeping his denial plausible. +

    +

    + For more technical information, please see the section + EMV Smart Cards in the chapter + + Keyfiles. +

    +
    +
    + + diff --git a/doc/html/Keyfiles in VeraCrypt.html b/doc/html/Keyfiles in VeraCrypt.html index ed940d53..eea6939a 100644 --- a/doc/html/Keyfiles in VeraCrypt.html +++ b/doc/html/Keyfiles in VeraCrypt.html @@ -114,6 +114,25 @@ To close all opened security token sessions, either select Close All Security Token Sessions or define and use a hotkey combination (Settings > Hot Keys > Close All Security Token Sessions).

     

    +

    +EMV Smart Cards

    +
    +Windows and Linux versions of VeraCrypt can use directly as keyfiles data extracted from EMV compliant smart cards, supporting Visa, Mastecard or Maestro applications. As with PKCS-11 compliant smart cards, to use such data as VeraCrypt keyfiles, +click Add Token Files (in the keyfile dialog window). The last four digits of the card's Primary Account Number will be displayed, allowing the selection of the card as a keyfile source. +
    +The data extracted and concatenated into a single keyfile are as follow : ICC Public Key Certificate, Issuer Public Key Certificate and Card Production Life +Cycle (CPLC) data. They are respectively identified by the tags '9F46', '90' and '9F7F' in the card's data management system. These two certificates are specific to an application deployed on the EMV card and used for the Dynamic Data Authentication of the card +during banking transactions. CPLC data are specific to the card and not to any of its applications. They contain information on the production process of the smart card. Therefore both certificates and data are unique and static on any EMV compliant smart card.
    +
    +According to the ISO/IEC 7816 standard on which the EMV standard is based, communication with an EMV smart card is done through structured commands called APDUs, allowing to extract the data from the smart card. These data are encoded in the BER-TLV format, +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.
    +
    +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.
    +
    +It important to note that this feature is optional and disabled by default. It can be enabled in the Security Token Preferences parameters by checking the box provided.
    +

     

    Keyfile Search Path

    diff --git a/doc/html/Keyfiles.html b/doc/html/Keyfiles.html index db4fb52c..04dd3463 100644 --- a/doc/html/Keyfiles.html +++ b/doc/html/Keyfiles.html @@ -1,81 +1,222 @@ - + - - -VeraCrypt - Free Open source disk encryption with strong security for the Paranoid - - - - - + + + + VeraCrypt - Free Open source disk encryption with strong security for the + Paranoid + + + + + + +
    + VeraCrypt +
    -
    -VeraCrypt -
    + - + - - -
    -

    Keyfiles

    -
    -

    VeraCrypt keyfile is a file whose content is combined with a password. The user can use any kind of file as a VeraCrypt keyfile. The user can also generate a keyfile using the built-in keyfile generator, which utilizes the VeraCrypt RNG to generate a file - with random content (for more information, see the section -Random Number Generator).

    -

    The maximum size of a keyfile is not limited; however, only its first 1,048,576 bytes (1 MiB) are processed (all remaining bytes are ignored due to performance issues connected with processing extremely large files). The user can supply one or more keyfiles - (the number of keyfiles is not limited).

    -

    Keyfiles can be stored on PKCS-11-compliant [23] security tokens and smart cards protected by multiple PIN codes (which can be entered either using a hardware PIN pad or via the VeraCrypt GUI).

    -

    Keyfiles are processed and applied to a password using the following method:

    -
      -
    1. Let P be a VeraCrypt volume password supplied by user (may be empty) -
    2. Let KP be the keyfile pool
    3. Let kpl be the size of the keyfile pool KP, in bytes (64, i.e., 512 bits); -

      kpl must be a multiple of the output size of a hash function H

      -
    4. Let pl be the length of the password P, in bytes (in the current version: 0 ≤ -pl ≤ 64)
    5. if kpl > pl, append (kpl – pl) zero bytes to the password -P (thus pl = kpl)
    6. Fill the keyfile pool KP with kpl zero bytes.
    7. For each keyfile perform the following steps: -
        -
      1. Set the position of the keyfile pool cursor to the beginning of the pool
      2. Initialize the hash function H
      3. Load all bytes of the keyfile one by one, and for each loaded byte perform the following steps: -
          -
        1. Hash the loaded byte using the hash function H without initializing the hash, to obtain an intermediate hash (state) -M. Do not finalize the hash (the state is retained for next round).
        2. Divide the state M into individual bytes.
          -For example, if the hash output size is 4 bytes, (T0 || T1 || -T2 || T3) = M
        3. Write these bytes (obtained in step 7.c.ii) individually to the keyfile pool with the modulo 28 addition operation (not by replacing the old values in the pool) at the position of the pool cursor. After a byte is written, the pool cursor position - is advanced by one byte. When the cursor reaches the end of the pool, its position is set to the beginning of the pool. -
        -
      -
    8. Apply the content of the keyfile pool to the password P using the following method: -
        -
      1. Divide the password P into individual bytes B0...Bpl-1.
        -Note that if the password was shorter than the keyfile pool, then the password was padded with zero bytes to the length of the pool in Step 5 (hence, at this point the length of the password is always greater than or equal to the length of the keyfile pool). -
      2. Divide the keyfile pool KP into individual bytes G0...Gkpl-1 -
      3. For 0 ≤ i < kpl perform: Bi = Bi ⊕ Gi
      4. P = B0 || B1 || ... || Bpl-2 || -Bpl-1
      -
    9. The password P (after the keyfile pool content has been applied to it) is now passed to the header key derivation function PBKDF2 (PKCS #5 v2), which processes it (along with salt and other data) using a cryptographically secure hash algorithm - selected by the user (e.g., SHA-512). See the section -Header Key Derivation, Salt, and Iteration Count for more information. -
    -

    The role of the hash function H is merely to perform diffusion [2]. CRC-32 is used as the hash function -H. Note that the output of CRC-32 is subsequently processed using a cryptographically secure hash algorithm: The keyfile pool content (in addition to being hashed using CRC-32) is applied to the password, which is then passed to the header key derivation - function PBKDF2 (PKCS #5 v2), which processes it (along with salt and other data) using a cryptographically secure hash algorithm selected by the user (e.g., SHA-512). The resultant values are used to form the header key and the secondary header key (XTS mode).

    -

     

    -

    Next Section >>

    -
    -
    +
    +

    Keyfiles

    +
    +

    + VeraCrypt keyfile is a file whose content is combined with a password. + The user can use any kind of file as a VeraCrypt keyfile. The user can + also generate a keyfile using the built-in keyfile generator, which + utilizes the VeraCrypt RNG to generate a file with random content (for + more information, see the section + + Random Number Generator). +

    +

    + The maximum size of a keyfile is not limited; however, only its first + 1,048,576 bytes (1 MiB) are processed (all remaining bytes are ignored + due to performance issues connected with processing extremely large + files). The user can supply one or more keyfiles (the number of + keyfiles is not limited). +

    +

    + Keyfiles can be stored on PKCS-11-compliant [23] security tokens and + smart cards protected by multiple PIN codes (which can be entered + either using a hardware PIN pad or via the VeraCrypt GUI). +

    +

    + EMV-compliant smart cards' data can be used as keyfile, see chapter + + EMV Smart Cards. +

    +

    + Keyfiles are processed and applied to a password using the following + method: +

    +
      +
    1. + Let P be a VeraCrypt volume password supplied by user (may + be empty) +
    2. +
    3. Let KP be the keyfile pool
    4. +
    5. + Let kpl be the size of the keyfile pool KP, in + bytes (64, i.e., 512 bits); +

      + kpl must be a multiple of the output size of a hash function H +

      +
    6. +
    7. + Let pl be the length of the password P, in bytes + (in the current version: 0 ≤ pl ≤ 64) +
    8. +
    9. + if kpl > pl, append (kpl – pl) zero bytes + to the password P (thus pl = kpl) +
    10. +
    11. + Fill the keyfile pool KP with kpl zero bytes. +
    12. +
    13. + For each keyfile perform the following steps: +
        +
      1. + Set the position of the keyfile pool cursor to the beginning of + the pool +
      2. +
      3. Initialize the hash function H
      4. +
      5. + Load all bytes of the keyfile one by one, and for each loaded + byte perform the following steps: +
          +
        1. + Hash the loaded byte using the hash function + H without initializing the hash, to obtain an + intermediate hash (state) M. Do not finalize the + hash (the state is retained for next round). +
        2. +
        3. + Divide the state M into individual bytes.
          + For example, if the hash output size is 4 bytes, (T0 || T1 || T2 || T3) = M +
        4. +
        5. + Write these bytes (obtained in step 7.c.ii) individually to + the keyfile pool with the modulo 28 addition + operation (not by replacing the old values in the pool) at + the position of the pool cursor. After a byte is written, + the pool cursor position is advanced by one byte. When the + cursor reaches the end of the pool, its position is set to + the beginning of the pool. +
        6. +
        +
      6. +
      +
    14. +
    15. + Apply the content of the keyfile pool to the password + P using the following method: +
        +
      1. + Divide the password P into individual bytes B0...Bpl-1.
        + Note that if the password was shorter than the keyfile pool, + then the password was padded with zero bytes to the length of + the pool in Step 5 (hence, at this point the length of the + password is always greater than or equal to the length of the + keyfile pool). +
      2. +
      3. + Divide the keyfile pool KP into individual bytes + G0...Gkpl-1 +
      4. +
      5. For 0 ≤ i < kpl perform: Bi = Bi ⊕ Gi
      6. +
      7. + P = B0 || B1 || + ... || Bpl-2 || Bpl-1 +
      8. +
      +
    16. +
    17. + The password P (after the keyfile pool content has been + applied to it) is now passed to the header key derivation function + PBKDF2 (PKCS #5 v2), which processes it (along with salt and other + data) using a cryptographically secure hash algorithm selected by + the user (e.g., SHA-512). See the section + + Header Key Derivation, Salt, and Iteration Count + for more information. +
    18. +
    +

    + The role of the hash function H is merely to perform + diffusion [2]. CRC-32 is used as the hash function H. Note + that the output of CRC-32 is subsequently processed using a + cryptographically secure hash algorithm: The keyfile pool content (in + addition to being hashed using CRC-32) is applied to the password, + which is then passed to the header key derivation function PBKDF2 + (PKCS #5 v2), which processes it (along with salt and other data) + using a cryptographically secure hash algorithm selected by the user + (e.g., SHA-512). The resultant values are used to form the header key + and the secondary header key (XTS mode). +

    +

     

    +

    + Next Section >> +

    +
    +
    +
    + + diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index e1170d84..dfcc3d03 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -207,6 +207,7 @@ BOOL LastMountedVolumeDirty; BOOL MountVolumesAsSystemFavorite = FALSE; BOOL FavoriteMountOnArrivalInProgress = FALSE; BOOL MultipleMountOperationInProgress = FALSE; +BOOL ActivateEMVOption = FALSE; volatile BOOL NeedPeriodicDeviceListUpdate = FALSE; BOOL DisablePeriodicDeviceListUpdate = FALSE; @@ -12206,11 +12207,11 @@ static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPA WaitCursor(); finally_do ({ NormalCursor(); }); - list tokens; + list > tokens; try { - tokens = SecurityToken::GetAvailableTokens(); + tokens = Token::GetAvailableTokens(); } catch (Exception &e) { @@ -12224,12 +12225,12 @@ static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPA return 1; } - foreach (const SecurityTokenInfo &token, tokens) + foreach (const shared_ptr token, tokens) { wstringstream tokenLabel; - tokenLabel << L"[" << token.SlotId << L"] " << token.Label; + tokenLabel << L"[" << token->SlotId << L"] " << token->Label; - AddComboPair (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), tokenLabel.str().c_str(), token.SlotId); + AddComboPair (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), tokenLabel.str().c_str(), token->SlotId); } ComboBox_SetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), 0); @@ -12283,7 +12284,7 @@ static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPA } -static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector &keyfiles) +static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector > &keyfiles) { HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); LVITEMW lvItem; @@ -12291,18 +12292,18 @@ static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector keyfile, keyfiles) { memset (&lvItem, 0, sizeof(lvItem)); lvItem.mask = LVIF_TEXT; lvItem.iItem = line++; wstringstream s; - s << keyfile.SlotId; + s << keyfile->Token->SlotId; ListItemAdd (tokenListControl, lvItem.iItem, (wchar_t *) s.str().c_str()); - ListSubItemSet (tokenListControl, lvItem.iItem, 1, (wchar_t *) keyfile.Token.Label.c_str()); - ListSubItemSet (tokenListControl, lvItem.iItem, 2, (wchar_t *) keyfile.Id.c_str()); + ListSubItemSet (tokenListControl, lvItem.iItem, 1, (wchar_t *) keyfile->Token->Label.c_str()); + ListSubItemSet (tokenListControl, lvItem.iItem, 2, (wchar_t *) keyfile->Id.c_str()); } BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); @@ -12311,10 +12312,10 @@ static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector &keyfiles) +static list > SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector > &keyfiles) { HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); - list selectedKeyfiles; + list > selectedKeyfiles; int itemId = -1; while ((itemId = ListView_GetNextItem (tokenListControl, itemId, LVIS_SELECTED)) != -1) @@ -12328,8 +12329,8 @@ static list SecurityTokenKeyfileDlgGetSelected (HWND hwnd BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { - static list *selectedTokenKeyfiles; - static vector keyfiles; + static list *selectedTokenKeyfiles; + static vector > keyfiles; WORD lw = LOWORD (wParam); @@ -12337,7 +12338,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam { case WM_INITDIALOG: { - selectedTokenKeyfiles = (list *) lParam; + selectedTokenKeyfiles = (list *) lParam; LVCOLUMNW LvCol; HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); @@ -12372,7 +12373,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam WaitCursor(); finally_do ({ NormalCursor(); }); - keyfiles = SecurityToken::GetAvailableKeyfiles(); + keyfiles = Token::GetAvailableKeyfiles(ActivateEMVOption); } catch (UserAbort&) { @@ -12400,9 +12401,9 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam { if (selectedTokenKeyfiles) { - foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) + foreach (const shared_ptr &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) { - selectedTokenKeyfiles->push_back (SecurityTokenKeyfilePath (keyfile)); + selectedTokenKeyfiles->push_back (TokenKeyfilePath (*keyfile)); } } @@ -12413,8 +12414,15 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) { BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); + BOOL deletable = selected; + foreach (const shared_ptr &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) + { + if( ! keyfile->Token->isEditable()){ + deletable = false; + } + } EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); - EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); + EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), deletable); return 1; } @@ -12461,7 +12469,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam SecurityToken::CreateKeyfile (newParams.SlotId, keyfileDataVector, newParams.Name); - keyfiles = SecurityToken::GetAvailableKeyfiles(); + keyfiles = Token::GetAvailableKeyfiles(ActivateEMVOption); SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); } catch (Exception &e) @@ -12489,7 +12497,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam { try { - foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) + foreach (const shared_ptr &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) { wchar_t keyfilePath[TC_MAX_PATH]; @@ -12502,7 +12510,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam vector keyfileData; - SecurityToken::GetKeyfileData (keyfile, keyfileData); + keyfile->GetKeyfileData (keyfileData); if (keyfileData.empty()) { @@ -12538,12 +12546,12 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam WaitCursor(); finally_do ({ NormalCursor(); }); - foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) + foreach (const shared_ptr keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) { - SecurityToken::DeleteKeyfile (keyfile); + SecurityToken::DeleteKeyfile (dynamic_cast(*keyfile.get())); } - keyfiles = SecurityToken::GetAvailableKeyfiles(); + keyfiles = Token::GetAvailableKeyfiles(ActivateEMVOption); SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); } catch (Exception &e) diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h index 362b2d6d..2004eb2a 100644 --- a/src/Common/Dlgcode.h +++ b/src/Common/Dlgcode.h @@ -166,6 +166,7 @@ extern BOOL LastMountedVolumeDirty; extern BOOL MountVolumesAsSystemFavorite; extern BOOL FavoriteMountOnArrivalInProgress; extern BOOL MultipleMountOperationInProgress; +extern BOOL ActivateEMVOption; extern volatile BOOL NeedPeriodicDeviceListUpdate; extern BOOL DisablePeriodicDeviceListUpdate; diff --git a/src/Common/EMVToken.cpp b/src/Common/EMVToken.cpp new file mode 100644 index 00000000..aac59a6a --- /dev/null +++ b/src/Common/EMVToken.cpp @@ -0,0 +1,121 @@ +#include "EMVToken.h" + +#include "Platform/Finally.h" +#include "Platform/ForEach.h" +#include +#include + + + +#if !defined(TC_WINDOWS) || defined(TC_PROTOTYPE) +#include "Platform/SerializerFactory.h" +#include "Platform/StringConverter.h" +#include "Platform/SystemException.h" +#else +#include "Dictionary.h" +#include "Language.h" +#endif + + +using namespace std; + +namespace VeraCrypt +{ + + IccDataExtractor EMVToken::extractor; + + EMVTokenInfo::~EMVTokenInfo() + { + burn(&Label,Label.size()); + } + + EMVTokenKeyfile::EMVTokenKeyfile(const TokenKeyfilePath& path) + { + Id = EMV_CARDS_LABEL; + Token = shared_ptr(new EMVTokenInfo()); + wstring pathStr = path; + unsigned long slotId; + + if (swscanf(pathStr.c_str(), TC_EMV_TOKEN_KEYFILE_URL_PREFIX TC_EMV_TOKEN_KEYFILE_URL_SLOT L"/%lu", &slotId) != 1) + throw InvalidEMVPath(); + + Token->SlotId = slotId; + } + + EMVTokenKeyfile::operator TokenKeyfilePath () const + { + wstringstream path; + path << TC_EMV_TOKEN_KEYFILE_URL_PREFIX TC_EMV_TOKEN_KEYFILE_URL_SLOT L"/" << Token->SlotId; + return path.str(); + } + + void EMVTokenKeyfile::GetKeyfileData(vector & keyfileData) const + { + #ifdef TC_WINDOWS + EMVToken::extractor.InitLibrary(); + #endif + + EMVToken::extractor.GetReaders(); + EMVToken::extractor.GettingAllCerts(Token->SlotId, keyfileData); + } + + bool EMVToken::IsKeyfilePathValid(const wstring& emvTokenKeyfilePath) + { + return emvTokenKeyfilePath.find(TC_EMV_TOKEN_KEYFILE_URL_PREFIX) == 0; + } + + vector EMVToken::GetAvailableKeyfiles(unsigned long int* slotIdFilter, const wstring keyfileIdFilter) { + #ifdef TC_WINDOWS + EMVToken::extractor.InitLibrary(); + #endif + + vector keyfiles; + unsigned long int nb = 0; + + nb = EMVToken::extractor.GetReaders(); + + + for(unsigned long int slotId = 0; slotIdSlotId = slotId; + keyfile.Token = shared_ptr(new EMVTokenInfo(token)); + + keyfiles.push_back(keyfile); + + if (!keyfileIdFilter.empty()) + break; + } + + return keyfiles; + + } + + + EMVTokenInfo EMVToken::GetTokenInfo(unsigned long int slotId) { + EMVTokenInfo token; + 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()); + return token; + } + +} diff --git a/src/Common/EMVToken.h b/src/Common/EMVToken.h new file mode 100644 index 00000000..1d84ec28 --- /dev/null +++ b/src/Common/EMVToken.h @@ -0,0 +1,50 @@ +#ifndef TC_HEADER_Common_EMVToken +#define TC_HEADER_Common_EMVToken + +#define TC_EMV_TOKEN_KEYFILE_URL_PREFIX L"emv://" +#define TC_EMV_TOKEN_KEYFILE_URL_SLOT L"slot" + +#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 { + + struct EMVTokenInfo: TokenInfo + { + virtual ~EMVTokenInfo(); + virtual BOOL isEditable() const {return false;} + }; + + struct EMVTokenKeyfile: TokenKeyfile + { + EMVTokenKeyfile(){Id = EMV_CARDS_LABEL; Token = shared_ptr(new EMVTokenInfo());}; + EMVTokenKeyfile(const TokenKeyfilePath& path); + + virtual operator TokenKeyfilePath () const; + virtual void GetKeyfileData(vector & keyfileData) const; + + }; + + class EMVToken { + private: + static IccDataExtractor extractor; + public: + static bool IsKeyfilePathValid(const wstring& emvTokenKeyfilePath); + static vector GetAvailableKeyfiles(unsigned long int* slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring()); + static EMVTokenInfo GetTokenInfo(unsigned long int slotId); + + friend void EMVTokenKeyfile::GetKeyfileData(vector & keyfileData) const; + + }; +} + +#endif diff --git a/src/Common/IccDataExtractor.cpp b/src/Common/IccDataExtractor.cpp new file mode 100644 index 00000000..d98bc360 --- /dev/null +++ b/src/Common/IccDataExtractor.cpp @@ -0,0 +1,777 @@ +// +// Created by bshp on 1/14/23. +// + +#include "IccDataExtractor.h" + +#if !defined (TC_WINDOWS) || defined (TC_PROTOTYPE) +# include "Platform/SerializerFactory.h" +# include "Platform/StringConverter.h" +# include "Platform/SystemException.h" +#else +# include "Dictionary.h" +# include "Language.h" +#endif + +#include "Tcdefs.h" + +namespace VeraCrypt +{ + + + #ifdef TC_WINDOWS + bool VeraCrypt::IccDataExtractor::Initialized; + #endif + //using namespace std; + const BYTE IccDataExtractor::SELECT_MASTERCARD[] = {00, 0xA4, 0x04, 00, 0x07, 0xA0, 00, 00, 00, 0x04, 0x10, 0x10}; + const BYTE IccDataExtractor::SELECT_VISA[] = {00, 0xA4, 0x04, 00, 0x07, 0xA0, 00, 00, 00, 0x03, 0x10, 0x10}; + const BYTE IccDataExtractor::SELECT_AMEX[] = {00, 0xA4, 0x04, 00, 0x07, 0xA0, 00, 00, 00, 00, 0x25, 0x10}; + const BYTE * IccDataExtractor::SELECT_TYPES[]={SELECT_MASTERCARD, SELECT_VISA, SELECT_AMEX}; + + IccDataExtractor::IccDataExtractor(){} + + IccDataExtractor::~IccDataExtractor(){ + /* Disconnect card if connected */ + if(hCard){ + #ifdef TC_WINDOWS + WSCardDisconnect(hContext,hCard); + #else + SCardDisconnect(hContext,hCard); + #endif + } + /* Release memory that has been returned from the resource manager using the SCARD_AUTOALLOCATE length + * designator*/ + if (mszReaders){ + #ifdef TC_WINDOWS + WSCardFreeMemory(hContext, mszReaders); + #else + SCardFreeMemory(hContext, mszReaders); + #endif + } + + /* Closing the established resource manager context freeing any resources allocated under that context + * including SCARDHANDLE objects and memory allocated using the SCARD_AUTOALLOCATE length designator*/ + if(hContext){ + #ifdef TC_WINDOWS + WSCardReleaseContext(hContext); + #else + SCardReleaseContext(hContext); + #endif + } + + /* Freeing winscard library */ + #ifdef TC_WINDOWS + FreeLibrary(WinscardLibraryHandle); + #endif + } + + #ifdef TC_WINDOWS + void IccDataExtractor::InitLibrary(){ + + if(Initialized) return; + + /* Getting the System32 directory */ + char sysDir[MAX_PATH-20]; + GetSystemDirectoryA(sysDir, MAX_PATH); + + /* Getting the winscard dll path directory */ + char winscardPath[MAX_PATH]; + sprintf_s(winscardPath, "%s\\Winscard.dll", sysDir); + + /* Loading the winscard dll from System32 */ + WinscardLibraryHandle = LoadLibraryA(winscardPath); + throw_sys_if(!WinscardLibraryHandle); + + /* Fetching the functions pointers from the dll */ + WSCardEstablishContext = (SCardEstablishContextPtr) GetProcAddress(WinscardLibraryHandle,"SCardEstablishContext"); + if(!WSCardEstablishContext) throw WinscardLibraryNotInitialized(); + + WSCardReleaseContext= (SCardReleaseContextPtr) GetProcAddress(WinscardLibraryHandle,"SCardReleaseContext"); + if(!WSCardReleaseContext) throw WinscardLibraryNotInitialized(); + + WSCardConnectA = (SCardConnectAPtr) GetProcAddress(WinscardLibraryHandle,"SCardConnectA"); + if(!WSCardConnectA) throw WinscardLibraryNotInitialized(); + + WSCardDisconnect = (SCardDisconnectPtr) GetProcAddress(WinscardLibraryHandle,"SCardDisconnect"); + if(!WSCardDisconnect) throw WinscardLibraryNotInitialized(); + + WSCardFreeMemory = ( SCardFreeMemoryPtr) GetProcAddress(WinscardLibraryHandle,"SCardFreeMemory"); + if(!WSCardFreeMemory) throw WinscardLibraryNotInitialized(); + + WSCardListReadersA = (SCardListReadersAPtr) GetProcAddress(WinscardLibraryHandle,"SCardListReadersA"); + if(!WSCardListReadersA) throw WinscardLibraryNotInitialized(); + + WSCardTransmit = ( SCardTransmitPtr) GetProcAddress(WinscardLibraryHandle,"SCardTransmit"); + if(!WSCardTransmit) throw WinscardLibraryNotInitialized(); + + Initialized = true; + + } + #endif + + /* Establishing the resource manager context (the scope) within which database operations are performed. + * The module of the smart card subsystem that manages access to multiple readers and smart cards. The + * resource manager identifies and tracks resources, allocates readers and resources across multiple + * applications,and supports transaction primitives for accessing services available on a given card.*/ + int IccDataExtractor::EstablishRSContext(){ + + #ifdef TC_WINDOWS + LONG returnValue = WSCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); + #else + LONG returnValue = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); + #endif + + /* Check if the establishment of the context was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + return EXIT_SUCCESS; + } + + /* Detecting available readers and filling the reader table */ + unsigned long IccDataExtractor::GetReaders(){ + + #ifdef TC_WINDOWS + if(!Initialized) + throw WinscardLibraryNotInitialized(); + #endif + + EstablishRSContext(); + + /* Length of the mszReaders buffer in characters. If the buffer length is specified as + * SCARD_AUTOALLOCATE, then mszReaders is converted to a pointer to a byte pointer, and + * receives the address of a block of memory containing the multi-string structure */ + DWORD dwReaders = SCARD_AUTOALLOCATE; + + /* Retrieving the available readers list and putting it in mszReaders*/ // Use LPSTR on linux + #ifdef TC_WINDOWS + LONG returnValue = WSCardListReadersA(hContext, NULL, (LPSTR)&mszReaders, &dwReaders); + #else + LONG returnValue = SCardListReaders(hContext, NULL, (LPTSTR)&mszReaders, &dwReaders); + #endif + + /* If the is no readers, return */ + if(returnValue == SCARD_E_NO_READERS_AVAILABLE) return 0; + + /* Check if the listing of the connected readers was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + nbReaders = 0; + LPSTR ReaderPtr = mszReaders; + + /* Getting the total number of readers */ + while (*ReaderPtr != '\0') + { + readers.push_back(ReaderPtr); + ReaderPtr += strlen((char*)ReaderPtr) + 1; + nbReaders++; + } + + return nbReaders; + } + + /* Connecting to the card in the given reader*/ + int IccDataExtractor::ConnectCard(unsigned long int reader_nb){ + + /* Check if the given reader slot number is possible */ + if (reader_nb < 0 || reader_nb >= nbReaders) + throw InvalidEMVPath(); + + dwActiveProtocol = SCARD_PROTOCOL_UNDEFINED; + + #ifdef TC_WINDOWS + LONG returnValue = WSCardConnectA(hContext, readers[reader_nb], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); + #else + LONG returnValue = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); + #endif + + /* Check is the card connection was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + return EXIT_SUCCESS; + } + + /* Disconnect the card currently connected*/ + int IccDataExtractor::DisconnectCard(){ + #ifdef TC_WINDOWS + LONG returnValue = WSCardDisconnect(hCard, SCARD_UNPOWER_CARD); + #else + LONG returnValue = SCardDisconnect(hCard, SCARD_UNPOWER_CARD); + #endif + + /* Check is the card deconnection was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + return EXIT_SUCCESS; + } + + /* Testing if the card contains the application of the given EMV type (0:Mastercard, 1:Visa, 2:Amex) */ + bool IccDataExtractor::TestingCardType(const int SELECT_TYPE_NUMBER){ + + const BYTE * SELECTED_TYPE = SELECT_TYPES[SELECT_TYPE_NUMBER]; + + BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */ + + DWORD dwSendLength = SELECT_TYPE_SIZE; /* Set the size of the send buffer */ + DWORD dwRecvLength = sizeof(pbRecvBuffer); /* Set the size of the reception buffer */ + + /* Set up the io request */ + SCARD_IO_REQUEST ioRequest; + ioRequest.dwProtocol = dwActiveProtocol; + ioRequest.cbPciLength = sizeof(ioRequest); + + #ifdef TC_WINDOWS + LONG returnValue = WSCardTransmit(hCard, &ioRequest, SELECTED_TYPE, dwSendLength, NULL, pbRecvBuffer, &dwRecvLength); + #else + LONG returnValue = SCardTransmit(hCard, &ioRequest, SELECTED_TYPE, dwSendLength, NULL, pbRecvBuffer, &dwRecvLength); + #endif + + /* Check if the transmission was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + /* It received a response. Check if it didn't get a recognisable response */ + if (dwRecvLength < 2) + return false; + + /* Check if the command successfully executed (the card is the type passed in the parameter) */ + if (pbRecvBuffer[0] == 0x61) + return true; + + return false; + } + + /* Getting the ICC Public Key Certificates and the Issuer Public Key Certificates by parsing the application + * (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/ + void IccDataExtractor::GetCerts(vector &CERTS){ + + CERTS.clear(); + + bool iccFound= false; + bool issuerFound= false; + + shared_ptr node; + shared_ptr ICC_Public_Key_Certificate; + shared_ptr Issuer_PK_Certificate; + + BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */ + BYTE pbRecvBufferFat[256]; /* Bigger buffer to receive the card response */ + + DWORD dwSendLength; /* Size of the send buffer */ + DWORD dwRecvLength; /* Size of the reception buffer */ + + /* Set up the io request */ + SCARD_IO_REQUEST ioRequest; + ioRequest.dwProtocol = dwActiveProtocol; + ioRequest.cbPciLength = sizeof(ioRequest); + + LONG returnValue; + + /* Parsing root folders */ + for (int sfi = 0; sfi < 32; sfi++) + { + /* Parsing sub folders */ + for (int rec = 0; rec < 17; rec++) + { + BYTE SELECT_APDU_FILE[] = {00, 0xB2, static_cast(rec), static_cast((sfi << 3) | 4), 0x00}; + + dwSendLength = sizeof(SELECT_APDU_FILE); + dwRecvLength = sizeof(pbRecvBuffer); + + /* Check if there is data in the folder */ + #ifdef TC_WINDOWS + returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength); + #else + returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength); + #endif + + /* Check if the transmission was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + /* There is no data in the folder */ + if (pbRecvBuffer[0] != 0x6C) + continue; + + /* It set the proper expected length of the data in the APDU */ + SELECT_APDU_FILE[4] = pbRecvBuffer[1]; + + dwRecvLength = sizeof(pbRecvBufferFat); + + /* Get the data from the folder */ + #ifdef TC_WINDOWS + returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength, NULL, pbRecvBufferFat, &dwRecvLength); + #else + returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength, NULL, pbRecvBufferFat, &dwRecvLength); + #endif + + /* Check if the transmission was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + /* It received a response. Check if it didn't get a recognisable response */ + if (dwRecvLength < 2) + continue; + + /* Parsing the TLV */ + try{ + node = TLVParser::TLV_Parse(pbRecvBufferFat,sizeof(pbRecvBufferFat)); + }catch(TLVException){ + continue; + } + + /* Finding the ICC_Public_Key_Certificate */ + try{ + ICC_Public_Key_Certificate = TLVParser::TLV_Find(node, 0x9F46); + }catch(TLVException){ + continue; + } + if(ICC_Public_Key_Certificate) { + iccFound=true; + for (int i = 0; i < ICC_Public_Key_Certificate->Length;i++) { + CERTS.push_back(static_cast(ICC_Public_Key_Certificate->Value[i])); + } + } + + /* Finding the Issuer_Public_Key_Certificate */ + try{ + Issuer_PK_Certificate = TLVParser::TLV_Find(node, 0x90); + }catch(TLVException){ + continue; + } + + if(Issuer_PK_Certificate) { + issuerFound=true; + for (int i = 0; i < Issuer_PK_Certificate->Length;i++) { + CERTS.push_back(static_cast(Issuer_PK_Certificate->Value[i])); + } + } + + /* Limiting the search to at least one occurrence of both PKs to speed up the process. + * There might be more certificates tho */ + if(iccFound && issuerFound){ + burn(pbRecvBuffer, sizeof(pbRecvBuffer)); + burn(pbRecvBufferFat, sizeof(pbRecvBufferFat)); + return; + } + } + } + burn(pbRecvBuffer, sizeof(pbRecvBuffer)); + burn(pbRecvBufferFat, sizeof(pbRecvBufferFat)); + throw EMVKeyfileDataNotFound(); + } + + /* Getting CPCL data from the card*/ + void IccDataExtractor::GetCPCL(vector &v){ + + BYTE SELECT_APDU_CPCL[] = {0x80,0xCA, 0x9F, 0x7F, 0x00}; + + BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */ + BYTE pbRecvBufferFat[256]; /* Bigger buffer to receive the card response */ + + DWORD dwSendLength = sizeof (SELECT_APDU_CPCL); /* Set the size of the send buffer */ + DWORD dwRecvLength = sizeof(pbRecvBuffer); /* Set the size of the reception buffer */ + + /* Set up the io request */ + SCARD_IO_REQUEST ioRequest; + ioRequest.dwProtocol = dwActiveProtocol; + ioRequest.cbPciLength = sizeof(ioRequest); + + /* Check if there is the TAG for CPCL Data in the card */ + #ifdef TC_WINDOWS + LONG returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength, NULL, pbRecvBuffer, &dwRecvLength); + #else + LONG returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength, NULL, pbRecvBuffer, &dwRecvLength); + #endif + + /* Check if the transmission was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + /* Not the correct APDU response code */ + if (pbRecvBuffer[0] != 0x6C) + throw EMVKeyfileDataNotFound(); + + /* It set the proper expected length of the data in the APDU */ + SELECT_APDU_CPCL[4] = pbRecvBuffer[1]; + + dwRecvLength = sizeof(pbRecvBufferFat); + + /* Get the CPCL data */ + #ifdef TC_WINDOWS + returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength); + #else + returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength); + #endif + + /* Check if the transmission was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + /* It received a response. Check if it didn't get a recognisable response */ + if (dwRecvLength < 2) + throw EMVKeyfileDataNotFound(); + + /* We add CPCL data and crop the TAG and the data length at the start and the trailer at the end */ + for (unsigned long i = 3; i < dwRecvLength-2; i++) { + v.push_back(static_cast(pbRecvBufferFat[i])); + } + burn(pbRecvBuffer, sizeof(pbRecvBuffer)); + burn(pbRecvBufferFat, sizeof(pbRecvBufferFat)); + + } + + /* Getting an ICC Public Key Certificates and an Issuer Public Key Certificates for the first application with the cpcl + * data present on the card and finally merge it into one byte array */ + void IccDataExtractor::GettingAllCerts(int readerNumber, vector &v){ + + #ifdef TC_WINDOWS + if(!Initialized) + throw WinscardLibraryNotInitialized(); + #endif + + bool isEMV= false; + + ConnectCard(readerNumber); + + /* Test all the type of applications and get the certificates from the first one found */ + for(int i=0;i &v) { + + bool PANFound= false; + shared_ptr node; + shared_ptr PAN; + + BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */ + BYTE pbRecvBufferFat[256]; /* Bigger buffer to receive the card response */ + + DWORD dwSendLength; /* Size of the send buffer */ + DWORD dwRecvLength; /* Size of the reception buffer */ + + /* Set up the io request */ + SCARD_IO_REQUEST ioRequest; + ioRequest.dwProtocol = dwActiveProtocol; + ioRequest.cbPciLength = sizeof(ioRequest); + + LONG returnValue; + + /* Parsing root folders */ + for (int sfi = 0; sfi < 32; sfi++) + { + /* Parsing sub folders */ + for (int rec = 0; rec < 17; rec++) + { + BYTE SELECT_APDU_FILE[] = {00, 0xB2, static_cast(rec), static_cast((sfi << 3) | 4), 0x00}; + + dwSendLength = sizeof(SELECT_APDU_FILE); + dwRecvLength = sizeof(pbRecvBuffer); + + /* Check if there is data in the folder */ + #ifdef TC_WINDOWS + returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength); + #else + returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength); + #endif + + /* Check if the transmission was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + /* There is no data in the folder */ + if (pbRecvBuffer[0] != 0x6C) + continue; + + /* It set the proper expected length of the data in the APDU */ + SELECT_APDU_FILE[4] = pbRecvBuffer[1]; + + dwRecvLength = sizeof(pbRecvBufferFat); + + /* Get the data from the folder */ + #ifdef TC_WINDOWS + returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength); + #else + returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength); + #endif + + /* Check if the transmission was unsuccessful */ + if (returnValue != SCARD_S_SUCCESS) + throw PCSCException(returnValue); + + /* It received a response. Check if it didn't get a recognisable response */ + if (dwRecvLength < 2) + continue; + + /* Parsing the TLV */ + try{ + node = TLVParser::TLV_Parse(pbRecvBufferFat,sizeof(pbRecvBufferFat)); + }catch(TLVException){ + continue; + } + + /* Finding the PAN */ + try{ + PAN = TLVParser::TLV_Find(node, 0x5A); + }catch(TLVException){ + continue; + } + if(PAN) { + PANFound=true; + if (PAN->Length >= 8){ + for (int i = 6; i < 8;i++) { + v.push_back(static_cast(PAN->Value[i])); + } + } + } + + if(PANFound){ + burn(pbRecvBuffer, sizeof(pbRecvBuffer)); + burn(pbRecvBufferFat, sizeof(pbRecvBufferFat)); + return ; + } + } + } + burn(pbRecvBuffer, sizeof(pbRecvBuffer)); + burn(pbRecvBufferFat, sizeof(pbRecvBufferFat)); + throw EMVPANNotFound(); + } + + /* Helper function to transform the PAN received (vector of byte) to a string */ + template + void IccDataExtractor::make_hex_string(TInputIter first, TInputIter last, string& returnValue, bool use_uppercase, bool insert_spaces) { + ostringstream ss; + ss << hex << std::setfill('0'); + if (use_uppercase) + ss << uppercase; + while (first != last) + { + ss << setw(2) << static_cast(*first++); + if (insert_spaces && first != last) + ss << " "; + } + + returnValue = ss.str(); + } + + /* Wrapper function to get the PAN of the card*/ + void IccDataExtractor::GettingPAN(int readerNumber, string& panString) { + + #ifdef TC_WINDOWS + if(!Initialized) + throw WinscardLibraryNotInitialized(); + #endif + + vector PAN; + + bool isEMV= false; + + ConnectCard(readerNumber); + + /* Test all the type of applications and get the PAN from the first one found */ + for(int i=0;i stream) + { + Exception::Deserialize(stream); + Serializer sr(stream); + uint64 code; + sr.Deserialize("ErrorCode", code); + sr.Deserialize("SubjectErrorCodeValid", SubjectErrorCodeValid); + sr.Deserialize("SubjectErrorCode", SubjectErrorCode); + ErrorCode = (LONG)code; + } + + void PCSCException::Serialize(shared_ptr stream) const + { + Exception::Serialize(stream); + Serializer sr(stream); + sr.Serialize("ErrorCode", (uint64)ErrorCode); + sr.Serialize("SubjectErrorCodeValid", SubjectErrorCodeValid); + sr.Serialize("SubjectErrorCode", SubjectErrorCode); + } + +# define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +# undef TC_EXCEPTION_NODECL +# define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET(PCSCTokenException); + +#endif + +} \ No newline at end of file diff --git a/src/Common/IccDataExtractor.h b/src/Common/IccDataExtractor.h new file mode 100644 index 00000000..777a3555 --- /dev/null +++ b/src/Common/IccDataExtractor.h @@ -0,0 +1,231 @@ +// +// Created by bshp on 1/14/23. +// + +#ifndef NEWEMV_ICCDATAEXTRACTOR_H +#define NEWEMV_ICCDATAEXTRACTOR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Platform/PlatformBase.h" +#include "TLVParser.h" + +#ifdef __linux__ +#include +#endif + +#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) +# include "Exception.h" +#else +# include "Platform/Exception.h" +#endif + +#ifdef TC_WINDOWS +#include +#include +#endif +#ifdef TC_UNIX +#undef BOOL +#include +using VeraCrypt::byte; +#define BOOL int +//#include //Works without on windows +#endif + +#ifdef _WIN32 +#include +#endif + +#ifdef _WIN64 +#define ssize_t __int64 +#else +#define ssize_t long +#endif + +#define SELECT_TYPE_SIZE 12 /* Size of the SELECT_TYPE APDU */ + +/* Winscard function pointers definitions for windows import */ +#ifdef TC_WINDOWS +typedef LONG (WINAPI *SCardEstablishContextPtr)(DWORD dwScope,LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext); +typedef LONG (WINAPI *SCardReleaseContextPtr)(SCARDCONTEXT hContext); +typedef LONG (WINAPI *SCardConnectAPtr)(SCARDCONTEXT hContext,LPCSTR szReader,DWORD dwShareMode,DWORD dwPreferredProtocols,LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol); +typedef LONG (WINAPI *SCardDisconnectPtr)(SCARDHANDLE hCard, DWORD dwDisposition); +typedef LONG (WINAPI *SCardTransmitPtr)(SCARDHANDLE hCard,LPCSCARD_IO_REQUEST pioSendPci,const BYTE* pbSendBuffer, DWORD cbSendLength,LPSCARD_IO_REQUEST pioRecvPci,BYTE* pbRecvBuffer, LPDWORD pcbRecvLength); +typedef LONG (WINAPI *SCardListReadersAPtr)(SCARDCONTEXT hContext,LPCSTR mszGroups,LPSTR mszReaders, LPDWORD pcchReaders); +typedef LONG (WINAPI *SCardFreeMemoryPtr)(SCARDCONTEXT hContext,LPCVOID pvMem); +#endif + +namespace VeraCrypt +{ + class IccDataExtractor { + private: + + /* Used for loading winscard on windows */ + #ifdef TC_WINDOWS + /* Winscard Library Handle */ + HMODULE WinscardLibraryHandle; + + /* Winscard function pointers */ + SCardEstablishContextPtr WSCardEstablishContext; + SCardReleaseContextPtr WSCardReleaseContext; + SCardConnectAPtr WSCardConnectA; + SCardDisconnectPtr WSCardDisconnect; + SCardFreeMemoryPtr WSCardFreeMemory; + SCardListReadersAPtr WSCardListReadersA; + SCardTransmitPtr WSCardTransmit; + + /* Is the winscard library loaded */ + static bool Initialized; + #endif + + /* SELECT_TYPES FOR DIFFERENT AIDs*/ + const static BYTE SELECT_MASTERCARD[SELECT_TYPE_SIZE]; + const static BYTE SELECT_VISA[SELECT_TYPE_SIZE]; + const static BYTE SELECT_AMEX[SELECT_TYPE_SIZE]; + const static BYTE * SELECT_TYPES[3]; + + + SCARDCONTEXT hContext; /* Handle that identifies the resource manager context.*/ + + SCARDHANDLE hCard; /* A handle that identifies the connection to the smart card in the designated reader*/ + + std::vector readers; /* Card reader list */ + + unsigned long int nbReaders; /* Number of connected (available) readers */ + + LPSTR mszReaders; /* Names of the reader groups defined to the system, as a multi-string. Use a NULL value to + * list all readers in the system */ + + DWORD dwActiveProtocol; /* A flag that indicates the established active protocol. + * SCARD_PROTOCOL_T0: An asynchronous, character-oriented half-duplex transmission protocol. + * SCARD_PROTOCOL_T1: An asynchronous, block-oriented half-duplex transmission protocol.*/ + + + /* Establishing the resource manager context (the scope) within which database operations are performed. + * The module of the smart card subsystem that manages access to multiple readers and smart cards. The + * resource manager identifies and tracks resources, allocates readers and resources across multiple + * applications,and supports transaction primitives for accessing services available on a given card.*/ + int EstablishRSContext(); + + /* Connecting to the card in the given reader*/ + int ConnectCard(unsigned long int reader_nb); + + /* Disconnect the card currently connected*/ + int DisconnectCard(); + + /* Testing if the card contains the application of the given EMV type */ + bool TestingCardType(const int SELECT_TYPE_NUMBER); + + /* Getting the ICC Public Key Certificates and the Issuer Public Key Certificates by parsing the application + * (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/ + void GetCerts(vector &CERTS); + + /* Getting CPCL data from the card and put it into a reference*/ + void GetCPCL(vector &v); + + /* Getting the PAN by parsing the application + * (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/ + void GetPAN(vector &v); + + /* Helper function to make a string from plain arrays and various standard containers of bytes */ + template + void make_hex_string(TInputIter first, TInputIter last, std::string& panString, bool use_uppercase = true, bool insert_spaces = false); + + public: + IccDataExtractor(); + + ~IccDataExtractor(); + + /* Used to initialize the winscard library on windows to make sure the dll is in System32 */ + #ifdef TC_WINDOWS + void IccDataExtractor::InitLibrary(); + #endif + + /* Detecting available readers and filling the reader table. Returns + * the number of available readers */ + unsigned long GetReaders(); + + + /* Getting an ICC Public Key Certificates, an Issuer Public Key Certificates and the CPCL data + * from the card designated by the reader number. Appending them into a byte vector */ + void GettingAllCerts(int readerNumber, vector &v); + + /* Getting the PAN from the card designated by the reader number */ + void GettingPAN(int readerNumber, string& panString); + }; + + struct PCSCException: public Exception + { + PCSCException(LONG errorCode = (LONG) -1): ErrorCode(errorCode), SubjectErrorCodeValid(false), SubjectErrorCode((uint64)-1){} + PCSCException(LONG errorCode, uint64 subjectErrorCode): ErrorCode(errorCode), SubjectErrorCodeValid(true), SubjectErrorCode(subjectErrorCode){} + + #ifdef TC_HEADER_Platform_Exception + virtual ~PCSCException() throw () { } + TC_SERIALIZABLE_EXCEPTION(PCSCException); + #else + + void Show(HWND parent) const; + #endif + + operator string () const; + LONG GetErrorCode() const { return ErrorCode; } + + protected: + LONG ErrorCode; + bool SubjectErrorCodeValid; + uint64 SubjectErrorCode; + }; + + #ifdef TC_HEADER_Platform_Exception + + #define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception) + + #undef TC_EXCEPTION_SET + #define TC_EXCEPTION_SET \ + TC_EXCEPTION_NODECL (PCSCException); \ + TC_EXCEPTION (WinscardLibraryNotInitialized); \ + TC_EXCEPTION (InvalidEMVPath); \ + TC_EXCEPTION (EMVKeyfileDataNotFound); \ + TC_EXCEPTION (EMVPANNotFound); \ + TC_EXCEPTION (EMVUnknownCardType); + TC_EXCEPTION_SET; + + #undef TC_EXCEPTION + + #else // !TC_HEADER_Platform_Exception + + struct WinscardLibraryNotInitialized: public Exception + { + void Show(HWND parent) const { Error("WINSCARD_MODULE_INIT_FAILED", parent); } + }; + + struct InvalidEMVPath: public Exception + { + void Show(HWND parent) const { Error("INVALID_EMV_PATH", parent); } + }; + + struct EMVKeyfileDataNotFound: public Exception + { + void Show(HWND parent) const { Error("EMV_KEYFILE_DATA_NOT_FOUND", parent); } + }; + + struct EMVPANNotFound: public Exception + { + void Show(HWND parent) const { Error("EMV_PAN_NOT_FOUND", parent); } + }; + + struct EMVUnknownCardType: public Exception + { + void Show(HWND parent) const { Error("EMV_UNKNOWN_CARD_TYPE", parent); } + }; + + #endif // !TC_HEADER_Platform_Exception +} + +#endif //NEWEMV_ICCDATAEXTRACTOR_H diff --git a/src/Common/Keyfiles.c b/src/Common/Keyfiles.c index 174aed92..d2207f5f 100644 --- a/src/Common/Keyfiles.c +++ b/src/Common/Keyfiles.c @@ -23,6 +23,7 @@ #include "Dlgcode.h" #include "Language.h" #include "SecurityToken.h" +#include "EMVToken.h" #include "Common/resource.h" #include "Platform/Finally.h" #include "Platform/ForEach.h" @@ -249,12 +250,12 @@ BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFile, con // Determine whether it's a security token path try { - if (SecurityToken::IsKeyfilePathValid (kf->FileName)) + if (Token::IsKeyfilePathValid (kf->FileName, ActivateEMVOption)) { // Apply security token keyfile vector keyfileData; - SecurityTokenKeyfilePath secPath (kf->FileName); - SecurityToken::GetKeyfileData (SecurityTokenKeyfile (secPath), keyfileData); + TokenKeyfilePath secPath (kf->FileName); + Token::getTokenKeyfile (secPath)->GetKeyfileData (keyfileData); if (keyfileData.empty()) { @@ -551,10 +552,10 @@ BOOL CALLBACK KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa if (lw == IDC_TOKEN_FILES_ADD) { - list selectedTokenKeyfiles; + list selectedTokenKeyfiles; if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, (LPARAM) &selectedTokenKeyfiles) == IDOK) { - foreach (const SecurityTokenKeyfilePath &keyPath, selectedTokenKeyfiles) + foreach (const TokenKeyfilePath &keyPath, selectedTokenKeyfiles) { KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); if (kf) @@ -758,10 +759,10 @@ BOOL KeyfilesPopupMenu (HWND hwndDlg, POINT popupPosition, KeyFilesDlgParam *par case IDM_KEYFILES_POPUP_ADD_TOKEN_FILES: { - list selectedTokenKeyfiles; + list selectedTokenKeyfiles; if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_KEYFILES), hwndDlg, (DLGPROC) SecurityTokenKeyfileDlgProc, (LPARAM) &selectedTokenKeyfiles) == IDOK) { - foreach (const SecurityTokenKeyfilePath &keyPath, selectedTokenKeyfiles) + foreach (const TokenKeyfilePath &keyPath, selectedTokenKeyfiles) { KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile)); if (kf) diff --git a/src/Common/Language.xml b/src/Common/Language.xml index 540f6867..cd996bce 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -113,6 +113,7 @@ Cache passwords and keyfil&es in memory Exit when there are no mounted volumes &Close token session (log out) after a volume is successfully mounted + Activate EMV Option Include VeraCrypt Volume Expander Include VeraCrypt Volume Creation Wizard Create @@ -295,6 +296,7 @@ PKCS-5 PRF: Password Cache Security Options + EMV Options VeraCrypt Background Task VeraCrypt volume to mount (relative to traveler disk root): Upon insertion of traveler disk: @@ -1278,6 +1280,12 @@ Password for security token is incorrect. The security token does not have enough memory/space to perform the requested operation.\n\nIf you are attempting to import a keyfile, you should select a smaller file or use a keyfile generated by VeraCrypt (select 'Tools' > 'Keyfile Generator'). All open security token sessions have been closed. + Error when loading the winscard library.\n\nPlease make sure the WinSCard.dll is present in your System32 folder. + EMV path is invalid. + Unable to build a keyfile from the EMV card's data.\n\nOne of the following is missing:\n- ICC Public Key Certificate.\n- Issuer Public Key Certificate.\n- CPCL data. + No Primary Account Number (PAN) found in the EMV card. + The card in the reader is not a supported EMV card. + No card in the reader.\n\nPlease make sure the card is correctly slotted. Select Security Token Keyfiles Slot Token name diff --git a/src/Common/SecurityToken.cpp b/src/Common/SecurityToken.cpp index 8401a0eb..ad8ed33e 100644 --- a/src/Common/SecurityToken.cpp +++ b/src/Common/SecurityToken.cpp @@ -36,23 +36,31 @@ using namespace std; namespace VeraCrypt { - SecurityTokenKeyfile::SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path) + SecurityTokenKeyfile::SecurityTokenKeyfile(): Handle(CK_INVALID_HANDLE) { + SecurityTokenInfo* token = new SecurityTokenInfo(); + Token = shared_ptr(token); + Token->SlotId = CK_UNAVAILABLE_INFORMATION; + token->Flags = 0; + } + + SecurityTokenKeyfile::SecurityTokenKeyfile(const TokenKeyfilePath& path) { + Token = shared_ptr(new SecurityTokenInfo()); wstring pathStr = path; unsigned long slotId; - if (swscanf (pathStr.c_str(), TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/%lu", &slotId) != 1) + if (swscanf(pathStr.c_str(), TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/%lu", &slotId) != 1) throw InvalidSecurityTokenKeyfilePath(); - SlotId = slotId; + Token->SlotId = slotId; - size_t keyIdPos = pathStr.find (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/"); + size_t keyIdPos = pathStr.find(L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/"); if (keyIdPos == wstring::npos) throw InvalidSecurityTokenKeyfilePath(); - 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 keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id); + vector keyfiles = SecurityToken::GetAvailableKeyfiles(&Token->SlotId, Id); if (keyfiles.empty()) throw SecurityTokenKeyfileNotFound(); @@ -60,69 +68,69 @@ namespace VeraCrypt *this = keyfiles.front(); } - SecurityTokenKeyfile::operator SecurityTokenKeyfilePath () const + SecurityTokenKeyfile::operator TokenKeyfilePath () const { wstringstream path; - path << TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/" << SlotId << L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/" << Id; + path << TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/" << Token->SlotId << L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/" << Id; return path.str(); } - void SecurityToken::CheckLibraryStatus () + void SecurityToken::CheckLibraryStatus() { if (!Initialized) throw SecurityTokenLibraryNotInitialized(); } - void SecurityToken::CloseLibrary () + void SecurityToken::CloseLibrary() { if (Initialized) { CloseAllSessions(); - Pkcs11Functions->C_Finalize (NULL_PTR); + Pkcs11Functions->C_Finalize(NULL_PTR); #ifdef TC_WINDOWS - FreeLibrary (Pkcs11LibraryHandle); + FreeLibrary(Pkcs11LibraryHandle); #else - dlclose (Pkcs11LibraryHandle); + dlclose(Pkcs11LibraryHandle); #endif Initialized = false; } } - void SecurityToken::CloseAllSessions () throw () + void SecurityToken::CloseAllSessions() throw () { if (!Initialized) return; typedef pair SessionMapPair; - foreach (SessionMapPair p, Sessions) + foreach(SessionMapPair p, Sessions) { try { - CloseSession (p.first); + CloseSession(p.first); } - catch (...) { } + catch (...) {} } } - void SecurityToken::CloseSession (CK_SLOT_ID slotId) + void SecurityToken::CloseSession(CK_SLOT_ID slotId) { - if (Sessions.find (slotId) == Sessions.end()) - throw ParameterIncorrect (SRC_POS); + if (Sessions.find(slotId) == Sessions.end()) + throw ParameterIncorrect(SRC_POS); - Pkcs11Functions->C_CloseSession (Sessions[slotId].Handle); - Sessions.erase (Sessions.find (slotId)); + Pkcs11Functions->C_CloseSession(Sessions[slotId].Handle); + Sessions.erase(Sessions.find(slotId)); } - void SecurityToken::CreateKeyfile (CK_SLOT_ID slotId, vector &keyfileData, const string &name) + void SecurityToken::CreateKeyfile(CK_SLOT_ID slotId, vector & keyfileData, const string& name) { if (name.empty()) - throw ParameterIncorrect (SRC_POS); + throw ParameterIncorrect(SRC_POS); - LoginUserIfRequired (slotId); + LoginUserIfRequired(slotId); - foreach (const SecurityTokenKeyfile &keyfile, GetAvailableKeyfiles (&slotId)) + foreach(const SecurityTokenKeyfile & keyfile, GetAvailableKeyfiles(&slotId)) { if (keyfile.IdUtf8 == name) throw SecurityTokenKeyfileAlreadyExists(); @@ -133,16 +141,16 @@ namespace VeraCrypt CK_ATTRIBUTE keyfileTemplate[] = { - { CKA_CLASS, &dataClass, sizeof (dataClass) }, - { CKA_TOKEN, &trueVal, sizeof (trueVal) }, - { CKA_PRIVATE, &trueVal, sizeof (trueVal) }, - { CKA_LABEL, (CK_UTF8CHAR *) name.c_str(), (CK_ULONG) name.size() }, - { CKA_VALUE, &keyfileData.front(), (CK_ULONG) keyfileData.size() } + { CKA_CLASS, &dataClass, sizeof(dataClass) }, + { CKA_TOKEN, &trueVal, sizeof(trueVal) }, + { CKA_PRIVATE, &trueVal, sizeof(trueVal) }, + { CKA_LABEL, (CK_UTF8CHAR*)name.c_str(), (CK_ULONG)name.size() }, + { CKA_VALUE, &keyfileData.front(), (CK_ULONG)keyfileData.size() } }; CK_OBJECT_HANDLE keyfileHandle; - CK_RV status = Pkcs11Functions->C_CreateObject (Sessions[slotId].Handle, keyfileTemplate, array_capacity (keyfileTemplate), &keyfileHandle); + CK_RV status = Pkcs11Functions->C_CreateObject(Sessions[slotId].Handle, keyfileTemplate, array_capacity(keyfileTemplate), &keyfileHandle); switch (status) { @@ -156,36 +164,36 @@ namespace VeraCrypt } if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); // Some tokens report success even if the new object was truncated to fit in the available memory vector objectData; - GetObjectAttribute (slotId, keyfileHandle, CKA_VALUE, objectData); - finally_do_arg (vector *, &objectData, { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); }); + GetObjectAttribute(slotId, keyfileHandle, CKA_VALUE, objectData); + finally_do_arg(vector *, &objectData, { if (!finally_arg->empty()) burn(&finally_arg->front(), finally_arg->size()); }); if (objectData.size() != keyfileData.size()) { - Pkcs11Functions->C_DestroyObject (Sessions[slotId].Handle, keyfileHandle); - throw Pkcs11Exception (CKR_DEVICE_MEMORY); + Pkcs11Functions->C_DestroyObject(Sessions[slotId].Handle, keyfileHandle); + throw Pkcs11Exception(CKR_DEVICE_MEMORY); } } - void SecurityToken::DeleteKeyfile (const SecurityTokenKeyfile &keyfile) + void SecurityToken::DeleteKeyfile(const SecurityTokenKeyfile& keyfile) { - LoginUserIfRequired (keyfile.SlotId); + LoginUserIfRequired(keyfile.Token->SlotId); - CK_RV status = Pkcs11Functions->C_DestroyObject (Sessions[keyfile.SlotId].Handle, keyfile.Handle); + CK_RV status = Pkcs11Functions->C_DestroyObject(Sessions[keyfile.Token->SlotId].Handle, keyfile.Handle); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); } - vector SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter) + vector SecurityToken::GetAvailableKeyfiles(CK_SLOT_ID* slotIdFilter, const wstring keyfileIdFilter) { bool unrecognizedTokenPresent = false; vector keyfiles; - foreach (const CK_SLOT_ID &slotId, GetTokenSlots()) + foreach(const CK_SLOT_ID & slotId, GetTokenSlots()) { SecurityTokenInfo token; @@ -194,14 +202,14 @@ namespace VeraCrypt try { - LoginUserIfRequired (slotId); - token = GetTokenInfo (slotId); + LoginUserIfRequired(slotId); + token = GetTokenInfo(slotId); } - catch (UserAbort &) + catch (UserAbort&) { continue; } - catch (Pkcs11Exception &e) + catch (Pkcs11Exception& e) { if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED) { @@ -212,34 +220,34 @@ namespace VeraCrypt throw; } - foreach (const CK_OBJECT_HANDLE &dataHandle, GetObjects (slotId, CKO_DATA)) + foreach(const CK_OBJECT_HANDLE & dataHandle, GetObjects(slotId, CKO_DATA)) { SecurityTokenKeyfile keyfile; keyfile.Handle = dataHandle; - keyfile.SlotId = slotId; - keyfile.Token = token; + keyfile.Token->SlotId = slotId; + keyfile.Token = shared_ptr(new SecurityTokenInfo(token)); vector privateAttrib; - GetObjectAttribute (slotId, dataHandle, CKA_PRIVATE, privateAttrib); + GetObjectAttribute(slotId, dataHandle, CKA_PRIVATE, privateAttrib); - if (privateAttrib.size() == sizeof (CK_BBOOL) && *(CK_BBOOL *) &privateAttrib.front() != CK_TRUE) + if (privateAttrib.size() == sizeof(CK_BBOOL) && *(CK_BBOOL*)&privateAttrib.front() != CK_TRUE) continue; vector label; - GetObjectAttribute (slotId, dataHandle, CKA_LABEL, label); - label.push_back (0); + GetObjectAttribute(slotId, dataHandle, CKA_LABEL, label); + label.push_back(0); - keyfile.IdUtf8 = (char *) &label.front(); + keyfile.IdUtf8 = (char*)&label.front(); #if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) - keyfile.Id = Utf8StringToWide ((const char *) &label.front()); + keyfile.Id = Utf8StringToWide((const char*)&label.front()); #else - keyfile.Id = StringConverter::ToWide ((const char *) &label.front()); + keyfile.Id = StringConverter::ToWide((const char*)&label.front()); #endif if (keyfile.Id.empty() || (!keyfileIdFilter.empty() && keyfileIdFilter != keyfile.Id)) continue; - keyfiles.push_back (keyfile); + keyfiles.push_back(keyfile); if (!keyfileIdFilter.empty()) break; @@ -247,23 +255,23 @@ namespace VeraCrypt } if (keyfiles.empty() && unrecognizedTokenPresent) - throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED); + throw Pkcs11Exception(CKR_TOKEN_NOT_RECOGNIZED); return keyfiles; } - list SecurityToken::GetAvailableTokens () + list SecurityToken::GetAvailableTokens() { bool unrecognizedTokenPresent = false; list tokens; - foreach (const CK_SLOT_ID &slotId, GetTokenSlots()) + foreach(const CK_SLOT_ID & slotId, GetTokenSlots()) { try { - tokens.push_back (GetTokenInfo (slotId)); + tokens.push_back(GetTokenInfo(slotId)); } - catch (Pkcs11Exception &e) + catch (Pkcs11Exception& e) { if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED) { @@ -276,63 +284,63 @@ namespace VeraCrypt } if (tokens.empty() && unrecognizedTokenPresent) - throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED); + throw Pkcs11Exception(CKR_TOKEN_NOT_RECOGNIZED); return tokens; } - SecurityTokenInfo SecurityToken::GetTokenInfo (CK_SLOT_ID slotId) + SecurityTokenInfo SecurityToken::GetTokenInfo(CK_SLOT_ID slotId) { CK_TOKEN_INFO info; - CK_RV status = Pkcs11Functions->C_GetTokenInfo (slotId, &info); + CK_RV status = Pkcs11Functions->C_GetTokenInfo(slotId, &info); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); SecurityTokenInfo token; token.SlotId = slotId; token.Flags = info.flags; - char label[sizeof (info.label) + 1]; - memset (label, 0, sizeof (label)); - memcpy (label, info.label, sizeof (info.label)); + char label[sizeof(info.label) + 1]; + memset(label, 0, sizeof(label)); + memcpy(label, info.label, sizeof(info.label)); token.LabelUtf8 = label; - size_t lastSpace = token.LabelUtf8.find_last_not_of (' '); + size_t lastSpace = token.LabelUtf8.find_last_not_of(' '); if (lastSpace == string::npos) token.LabelUtf8.clear(); else - token.LabelUtf8 = token.LabelUtf8.substr (0, lastSpace + 1); + token.LabelUtf8 = token.LabelUtf8.substr(0, lastSpace + 1); #if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) - token.Label = Utf8StringToWide (token.LabelUtf8); + token.Label = Utf8StringToWide(token.LabelUtf8); #else - token.Label = StringConverter::ToWide (token.LabelUtf8); + token.Label = StringConverter::ToWide(token.LabelUtf8); #endif return token; } - void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector &keyfileData) + void SecurityTokenKeyfile::GetKeyfileData(vector & keyfileData) const { - LoginUserIfRequired (keyfile.SlotId); - GetObjectAttribute (keyfile.SlotId, keyfile.Handle, CKA_VALUE, keyfileData); + SecurityToken::LoginUserIfRequired(Token->SlotId); + SecurityToken::GetObjectAttribute(Token->SlotId, Handle, CKA_VALUE, keyfileData); } - vector SecurityToken::GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass) + vector SecurityToken::GetObjects(CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass) { - if (Sessions.find (slotId) == Sessions.end()) - throw ParameterIncorrect (SRC_POS); + if (Sessions.find(slotId) == Sessions.end()) + throw ParameterIncorrect(SRC_POS); CK_ATTRIBUTE findTemplate; findTemplate.type = CKA_CLASS; findTemplate.pValue = &objectClass; - findTemplate.ulValueLen = sizeof (objectClass); + findTemplate.ulValueLen = sizeof(objectClass); - CK_RV status = Pkcs11Functions->C_FindObjectsInit (Sessions[slotId].Handle, &findTemplate, 1); + CK_RV status = Pkcs11Functions->C_FindObjectsInit(Sessions[slotId].Handle, &findTemplate, 1); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); - finally_do_arg (CK_SLOT_ID, slotId, { Pkcs11Functions->C_FindObjectsFinal (Sessions[finally_arg].Handle); }); + finally_do_arg(CK_SLOT_ID, slotId, { Pkcs11Functions->C_FindObjectsFinal(Sessions[finally_arg].Handle); }); CK_ULONG objectCount; vector objects; @@ -340,112 +348,112 @@ namespace VeraCrypt while (true) { CK_OBJECT_HANDLE object; - CK_RV status = Pkcs11Functions->C_FindObjects (Sessions[slotId].Handle, &object, 1, &objectCount); + CK_RV status = Pkcs11Functions->C_FindObjects(Sessions[slotId].Handle, &object, 1, &objectCount); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); if (objectCount != 1) break; - objects.push_back (object); + objects.push_back(object); } return objects; } - void SecurityToken::GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector &attributeValue) + void SecurityToken::GetObjectAttribute(CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector & attributeValue) { attributeValue.clear(); - if (Sessions.find (slotId) == Sessions.end()) - throw ParameterIncorrect (SRC_POS); + if (Sessions.find(slotId) == Sessions.end()) + throw ParameterIncorrect(SRC_POS); CK_ATTRIBUTE attribute; attribute.type = attributeType; attribute.pValue = NULL_PTR; - CK_RV status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1); + CK_RV status = Pkcs11Functions->C_GetAttributeValue(Sessions[slotId].Handle, tokenObject, &attribute, 1); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); if (attribute.ulValueLen == 0) return; - attributeValue = vector (attribute.ulValueLen); + attributeValue = vector (attribute.ulValueLen); attribute.pValue = &attributeValue.front(); - status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1); + status = Pkcs11Functions->C_GetAttributeValue(Sessions[slotId].Handle, tokenObject, &attribute, 1); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); } - list SecurityToken::GetTokenSlots () + list SecurityToken::GetTokenSlots() { CheckLibraryStatus(); list slots; CK_ULONG slotCount; - CK_RV status = Pkcs11Functions->C_GetSlotList (TRUE, NULL_PTR, &slotCount); + CK_RV status = Pkcs11Functions->C_GetSlotList(TRUE, NULL_PTR, &slotCount); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); if (slotCount > 0) { - vector slotArray (slotCount); - status = Pkcs11Functions->C_GetSlotList (TRUE, &slotArray.front(), &slotCount); + vector slotArray(slotCount); + status = Pkcs11Functions->C_GetSlotList(TRUE, &slotArray.front(), &slotCount); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); for (size_t i = 0; i < slotCount; i++) { CK_SLOT_INFO slotInfo; - status = Pkcs11Functions->C_GetSlotInfo (slotArray[i], &slotInfo); + status = Pkcs11Functions->C_GetSlotInfo(slotArray[i], &slotInfo); if (status != CKR_OK || !(slotInfo.flags & CKF_TOKEN_PRESENT)) continue; - slots.push_back (slotArray[i]); + slots.push_back(slotArray[i]); } } return slots; } - bool SecurityToken::IsKeyfilePathValid (const wstring &securityTokenKeyfilePath) + bool SecurityToken::IsKeyfilePathValid(const wstring& securityTokenKeyfilePath) { - 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 char* pin) + void SecurityToken::Login(CK_SLOT_ID slotId, const char* pin) { - if (Sessions.find (slotId) == Sessions.end()) - OpenSession (slotId); + if (Sessions.find(slotId) == Sessions.end()) + OpenSession(slotId); else if (Sessions[slotId].UserLoggedIn) return; - 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); + 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); + throw Pkcs11Exception(status); Sessions[slotId].UserLoggedIn = true; } - void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId) + void SecurityToken::LoginUserIfRequired(CK_SLOT_ID slotId) { CheckLibraryStatus(); CK_RV status; - if (Sessions.find (slotId) == Sessions.end()) + if (Sessions.find(slotId) == Sessions.end()) { - OpenSession (slotId); + OpenSession(slotId); } else { CK_SESSION_INFO sessionInfo; - status = Pkcs11Functions->C_GetSessionInfo (Sessions[slotId].Handle, &sessionInfo); + status = Pkcs11Functions->C_GetSessionInfo(Sessions[slotId].Handle, &sessionInfo); if (status == CKR_OK) { @@ -455,14 +463,14 @@ namespace VeraCrypt { try { - CloseSession (slotId); + CloseSession(slotId); } - catch (...) { } - OpenSession (slotId); + catch (...) {} + OpenSession(slotId); } } - SecurityTokenInfo tokenInfo = GetTokenInfo (slotId); + SecurityTokenInfo tokenInfo = GetTokenInfo(slotId); while (!Sessions[slotId].UserLoggedIn && (tokenInfo.Flags & CKF_LOGIN_REQUIRED)) { @@ -470,9 +478,9 @@ namespace VeraCrypt { if (tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH) { - status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, NULL_PTR, 0); + status = Pkcs11Functions->C_Login(Sessions[slotId].Handle, CKU_USER, NULL_PTR, 0); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); } else { @@ -484,15 +492,15 @@ namespace VeraCrypt pin = s.str(); } - 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); - Login (slotId, pin.c_str()); + Login(slotId, pin.c_str()); } Sessions[slotId].UserLoggedIn = true; } - catch (Pkcs11Exception &e) + catch (Pkcs11Exception& e) { CK_RV error = e.GetErrorCode(); @@ -502,8 +510,8 @@ namespace VeraCrypt } else if (error == CKR_PIN_INCORRECT && !(tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { - PinCallback->notifyIncorrectPin (); - (*WarningCallback) (Pkcs11Exception (CKR_PIN_INCORRECT)); + PinCallback->notifyIncorrectPin(); + (*WarningCallback) (Pkcs11Exception(CKR_PIN_INCORRECT)); continue; } @@ -513,40 +521,40 @@ namespace VeraCrypt } #ifdef TC_WINDOWS - void SecurityToken::InitLibrary (const wstring &pkcs11LibraryPath, unique_ptr pinCallback, unique_ptr warningCallback) + void SecurityToken::InitLibrary(const wstring& pkcs11LibraryPath, unique_ptr pinCallback, unique_ptr warningCallback) #else - void SecurityToken::InitLibrary (const string &pkcs11LibraryPath, unique_ptr pinCallback, unique_ptr warningCallback) + void SecurityToken::InitLibrary(const string& pkcs11LibraryPath, unique_ptr pinCallback, unique_ptr warningCallback) #endif { if (Initialized) CloseLibrary(); #ifdef TC_WINDOWS - Pkcs11LibraryHandle = LoadLibraryW (pkcs11LibraryPath.c_str()); - throw_sys_if (!Pkcs11LibraryHandle); + Pkcs11LibraryHandle = LoadLibraryW(pkcs11LibraryPath.c_str()); + throw_sys_if(!Pkcs11LibraryHandle); #else - Pkcs11LibraryHandle = dlopen (pkcs11LibraryPath.c_str(), RTLD_NOW | RTLD_LOCAL); - throw_sys_sub_if (!Pkcs11LibraryHandle, dlerror()); + Pkcs11LibraryHandle = dlopen(pkcs11LibraryPath.c_str(), RTLD_NOW | RTLD_LOCAL); + throw_sys_sub_if(!Pkcs11LibraryHandle, dlerror()); #endif - typedef CK_RV (*C_GetFunctionList_t) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList); + typedef CK_RV(*C_GetFunctionList_t) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList); #ifdef TC_WINDOWS - C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) GetProcAddress (Pkcs11LibraryHandle, "C_GetFunctionList"); + C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t)GetProcAddress(Pkcs11LibraryHandle, "C_GetFunctionList"); #else - C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) dlsym (Pkcs11LibraryHandle, "C_GetFunctionList"); + C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t)dlsym(Pkcs11LibraryHandle, "C_GetFunctionList"); #endif if (!C_GetFunctionList) throw SecurityTokenLibraryNotInitialized(); - CK_RV status = C_GetFunctionList (&Pkcs11Functions); + CK_RV status = C_GetFunctionList(&Pkcs11Functions); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); - status = Pkcs11Functions->C_Initialize (NULL_PTR); + status = Pkcs11Functions->C_Initialize(NULL_PTR); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); PinCallback = move_ptr(pinCallback); WarningCallback = move_ptr(warningCallback); @@ -554,21 +562,21 @@ namespace VeraCrypt Initialized = true; } - void SecurityToken::OpenSession (CK_SLOT_ID slotId) + void SecurityToken::OpenSession(CK_SLOT_ID slotId) { - if (Sessions.find (slotId) != Sessions.end()) + if (Sessions.find(slotId) != Sessions.end()) return; CK_SESSION_HANDLE session; CK_FLAGS flags = CKF_SERIAL_SESSION; - if (!(GetTokenInfo (slotId).Flags & CKF_WRITE_PROTECTED)) - flags |= CKF_RW_SESSION; + if (!(GetTokenInfo(slotId).Flags & CKF_WRITE_PROTECTED)) + flags |= CKF_RW_SESSION; - CK_RV status = Pkcs11Functions->C_OpenSession (slotId, flags, NULL_PTR, NULL_PTR, &session); + CK_RV status = Pkcs11Functions->C_OpenSession(slotId, flags, NULL_PTR, NULL_PTR, &session); if (status != CKR_OK) - throw Pkcs11Exception (status); + throw Pkcs11Exception(status); Sessions[slotId].Handle = session; } @@ -581,103 +589,103 @@ namespace VeraCrypt static const struct { CK_RV ErrorCode; - const char *ErrorString; + const char* ErrorString; } ErrorStrings[] = { # define TC_TOKEN_ERR(CODE) { CODE, #CODE }, - TC_TOKEN_ERR (CKR_CANCEL) - TC_TOKEN_ERR (CKR_HOST_MEMORY) - TC_TOKEN_ERR (CKR_SLOT_ID_INVALID) - TC_TOKEN_ERR (CKR_GENERAL_ERROR) - TC_TOKEN_ERR (CKR_FUNCTION_FAILED) - TC_TOKEN_ERR (CKR_ARGUMENTS_BAD) - TC_TOKEN_ERR (CKR_NO_EVENT) - TC_TOKEN_ERR (CKR_NEED_TO_CREATE_THREADS) - TC_TOKEN_ERR (CKR_CANT_LOCK) - TC_TOKEN_ERR (CKR_ATTRIBUTE_READ_ONLY) - TC_TOKEN_ERR (CKR_ATTRIBUTE_SENSITIVE) - TC_TOKEN_ERR (CKR_ATTRIBUTE_TYPE_INVALID) - TC_TOKEN_ERR (CKR_ATTRIBUTE_VALUE_INVALID) - TC_TOKEN_ERR (CKR_DATA_INVALID) - TC_TOKEN_ERR (CKR_DATA_LEN_RANGE) - TC_TOKEN_ERR (CKR_DEVICE_ERROR) - TC_TOKEN_ERR (CKR_DEVICE_MEMORY) - TC_TOKEN_ERR (CKR_DEVICE_REMOVED) - TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_INVALID) - TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_LEN_RANGE) - TC_TOKEN_ERR (CKR_FUNCTION_CANCELED) - TC_TOKEN_ERR (CKR_FUNCTION_NOT_PARALLEL) - TC_TOKEN_ERR (CKR_FUNCTION_NOT_SUPPORTED) - TC_TOKEN_ERR (CKR_KEY_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_KEY_SIZE_RANGE) - TC_TOKEN_ERR (CKR_KEY_TYPE_INCONSISTENT) - TC_TOKEN_ERR (CKR_KEY_NOT_NEEDED) - TC_TOKEN_ERR (CKR_KEY_CHANGED) - TC_TOKEN_ERR (CKR_KEY_NEEDED) - TC_TOKEN_ERR (CKR_KEY_INDIGESTIBLE) - TC_TOKEN_ERR (CKR_KEY_FUNCTION_NOT_PERMITTED) - TC_TOKEN_ERR (CKR_KEY_NOT_WRAPPABLE) - TC_TOKEN_ERR (CKR_KEY_UNEXTRACTABLE) - TC_TOKEN_ERR (CKR_MECHANISM_INVALID) - TC_TOKEN_ERR (CKR_MECHANISM_PARAM_INVALID) - TC_TOKEN_ERR (CKR_OBJECT_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_OPERATION_ACTIVE) - TC_TOKEN_ERR (CKR_OPERATION_NOT_INITIALIZED) - TC_TOKEN_ERR (CKR_PIN_INCORRECT) - TC_TOKEN_ERR (CKR_PIN_INVALID) - TC_TOKEN_ERR (CKR_PIN_LEN_RANGE) - TC_TOKEN_ERR (CKR_PIN_EXPIRED) - TC_TOKEN_ERR (CKR_PIN_LOCKED) - TC_TOKEN_ERR (CKR_SESSION_CLOSED) - TC_TOKEN_ERR (CKR_SESSION_COUNT) - TC_TOKEN_ERR (CKR_SESSION_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_SESSION_PARALLEL_NOT_SUPPORTED) - TC_TOKEN_ERR (CKR_SESSION_READ_ONLY) - TC_TOKEN_ERR (CKR_SESSION_EXISTS) - TC_TOKEN_ERR (CKR_SESSION_READ_ONLY_EXISTS) - TC_TOKEN_ERR (CKR_SESSION_READ_WRITE_SO_EXISTS) - TC_TOKEN_ERR (CKR_SIGNATURE_INVALID) - TC_TOKEN_ERR (CKR_SIGNATURE_LEN_RANGE) - TC_TOKEN_ERR (CKR_TEMPLATE_INCOMPLETE) - TC_TOKEN_ERR (CKR_TEMPLATE_INCONSISTENT) - TC_TOKEN_ERR (CKR_TOKEN_NOT_PRESENT) - TC_TOKEN_ERR (CKR_TOKEN_NOT_RECOGNIZED) - TC_TOKEN_ERR (CKR_TOKEN_WRITE_PROTECTED) - TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_SIZE_RANGE) - TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT) - TC_TOKEN_ERR (CKR_USER_ALREADY_LOGGED_IN) - TC_TOKEN_ERR (CKR_USER_NOT_LOGGED_IN) - TC_TOKEN_ERR (CKR_USER_PIN_NOT_INITIALIZED) - TC_TOKEN_ERR (CKR_USER_TYPE_INVALID) - TC_TOKEN_ERR (CKR_USER_ANOTHER_ALREADY_LOGGED_IN) - TC_TOKEN_ERR (CKR_USER_TOO_MANY_TYPES) - TC_TOKEN_ERR (CKR_WRAPPED_KEY_INVALID) - TC_TOKEN_ERR (CKR_WRAPPED_KEY_LEN_RANGE) - TC_TOKEN_ERR (CKR_WRAPPING_KEY_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_WRAPPING_KEY_SIZE_RANGE) - TC_TOKEN_ERR (CKR_WRAPPING_KEY_TYPE_INCONSISTENT) - TC_TOKEN_ERR (CKR_RANDOM_SEED_NOT_SUPPORTED) - TC_TOKEN_ERR (CKR_RANDOM_NO_RNG) - TC_TOKEN_ERR (CKR_DOMAIN_PARAMS_INVALID) - TC_TOKEN_ERR (CKR_BUFFER_TOO_SMALL) - TC_TOKEN_ERR (CKR_SAVED_STATE_INVALID) - TC_TOKEN_ERR (CKR_INFORMATION_SENSITIVE) - TC_TOKEN_ERR (CKR_STATE_UNSAVEABLE) - TC_TOKEN_ERR (CKR_CRYPTOKI_NOT_INITIALIZED) - TC_TOKEN_ERR (CKR_CRYPTOKI_ALREADY_INITIALIZED) - TC_TOKEN_ERR (CKR_MUTEX_BAD) - TC_TOKEN_ERR (CKR_MUTEX_NOT_LOCKED) - TC_TOKEN_ERR (CKR_NEW_PIN_MODE) - TC_TOKEN_ERR (CKR_NEXT_OTP) - TC_TOKEN_ERR (CKR_FUNCTION_REJECTED) + TC_TOKEN_ERR(CKR_CANCEL) + TC_TOKEN_ERR(CKR_HOST_MEMORY) + TC_TOKEN_ERR(CKR_SLOT_ID_INVALID) + TC_TOKEN_ERR(CKR_GENERAL_ERROR) + TC_TOKEN_ERR(CKR_FUNCTION_FAILED) + TC_TOKEN_ERR(CKR_ARGUMENTS_BAD) + TC_TOKEN_ERR(CKR_NO_EVENT) + TC_TOKEN_ERR(CKR_NEED_TO_CREATE_THREADS) + TC_TOKEN_ERR(CKR_CANT_LOCK) + TC_TOKEN_ERR(CKR_ATTRIBUTE_READ_ONLY) + TC_TOKEN_ERR(CKR_ATTRIBUTE_SENSITIVE) + TC_TOKEN_ERR(CKR_ATTRIBUTE_TYPE_INVALID) + TC_TOKEN_ERR(CKR_ATTRIBUTE_VALUE_INVALID) + TC_TOKEN_ERR(CKR_DATA_INVALID) + TC_TOKEN_ERR(CKR_DATA_LEN_RANGE) + TC_TOKEN_ERR(CKR_DEVICE_ERROR) + TC_TOKEN_ERR(CKR_DEVICE_MEMORY) + TC_TOKEN_ERR(CKR_DEVICE_REMOVED) + TC_TOKEN_ERR(CKR_ENCRYPTED_DATA_INVALID) + TC_TOKEN_ERR(CKR_ENCRYPTED_DATA_LEN_RANGE) + TC_TOKEN_ERR(CKR_FUNCTION_CANCELED) + TC_TOKEN_ERR(CKR_FUNCTION_NOT_PARALLEL) + TC_TOKEN_ERR(CKR_FUNCTION_NOT_SUPPORTED) + TC_TOKEN_ERR(CKR_KEY_HANDLE_INVALID) + TC_TOKEN_ERR(CKR_KEY_SIZE_RANGE) + TC_TOKEN_ERR(CKR_KEY_TYPE_INCONSISTENT) + TC_TOKEN_ERR(CKR_KEY_NOT_NEEDED) + TC_TOKEN_ERR(CKR_KEY_CHANGED) + TC_TOKEN_ERR(CKR_KEY_NEEDED) + TC_TOKEN_ERR(CKR_KEY_INDIGESTIBLE) + TC_TOKEN_ERR(CKR_KEY_FUNCTION_NOT_PERMITTED) + TC_TOKEN_ERR(CKR_KEY_NOT_WRAPPABLE) + TC_TOKEN_ERR(CKR_KEY_UNEXTRACTABLE) + TC_TOKEN_ERR(CKR_MECHANISM_INVALID) + TC_TOKEN_ERR(CKR_MECHANISM_PARAM_INVALID) + TC_TOKEN_ERR(CKR_OBJECT_HANDLE_INVALID) + TC_TOKEN_ERR(CKR_OPERATION_ACTIVE) + TC_TOKEN_ERR(CKR_OPERATION_NOT_INITIALIZED) + TC_TOKEN_ERR(CKR_PIN_INCORRECT) + TC_TOKEN_ERR(CKR_PIN_INVALID) + TC_TOKEN_ERR(CKR_PIN_LEN_RANGE) + TC_TOKEN_ERR(CKR_PIN_EXPIRED) + TC_TOKEN_ERR(CKR_PIN_LOCKED) + TC_TOKEN_ERR(CKR_SESSION_CLOSED) + TC_TOKEN_ERR(CKR_SESSION_COUNT) + TC_TOKEN_ERR(CKR_SESSION_HANDLE_INVALID) + TC_TOKEN_ERR(CKR_SESSION_PARALLEL_NOT_SUPPORTED) + TC_TOKEN_ERR(CKR_SESSION_READ_ONLY) + TC_TOKEN_ERR(CKR_SESSION_EXISTS) + TC_TOKEN_ERR(CKR_SESSION_READ_ONLY_EXISTS) + TC_TOKEN_ERR(CKR_SESSION_READ_WRITE_SO_EXISTS) + TC_TOKEN_ERR(CKR_SIGNATURE_INVALID) + TC_TOKEN_ERR(CKR_SIGNATURE_LEN_RANGE) + TC_TOKEN_ERR(CKR_TEMPLATE_INCOMPLETE) + TC_TOKEN_ERR(CKR_TEMPLATE_INCONSISTENT) + TC_TOKEN_ERR(CKR_TOKEN_NOT_PRESENT) + TC_TOKEN_ERR(CKR_TOKEN_NOT_RECOGNIZED) + TC_TOKEN_ERR(CKR_TOKEN_WRITE_PROTECTED) + TC_TOKEN_ERR(CKR_UNWRAPPING_KEY_HANDLE_INVALID) + TC_TOKEN_ERR(CKR_UNWRAPPING_KEY_SIZE_RANGE) + TC_TOKEN_ERR(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT) + TC_TOKEN_ERR(CKR_USER_ALREADY_LOGGED_IN) + TC_TOKEN_ERR(CKR_USER_NOT_LOGGED_IN) + TC_TOKEN_ERR(CKR_USER_PIN_NOT_INITIALIZED) + TC_TOKEN_ERR(CKR_USER_TYPE_INVALID) + TC_TOKEN_ERR(CKR_USER_ANOTHER_ALREADY_LOGGED_IN) + TC_TOKEN_ERR(CKR_USER_TOO_MANY_TYPES) + TC_TOKEN_ERR(CKR_WRAPPED_KEY_INVALID) + TC_TOKEN_ERR(CKR_WRAPPED_KEY_LEN_RANGE) + TC_TOKEN_ERR(CKR_WRAPPING_KEY_HANDLE_INVALID) + TC_TOKEN_ERR(CKR_WRAPPING_KEY_SIZE_RANGE) + TC_TOKEN_ERR(CKR_WRAPPING_KEY_TYPE_INCONSISTENT) + TC_TOKEN_ERR(CKR_RANDOM_SEED_NOT_SUPPORTED) + TC_TOKEN_ERR(CKR_RANDOM_NO_RNG) + TC_TOKEN_ERR(CKR_DOMAIN_PARAMS_INVALID) + TC_TOKEN_ERR(CKR_BUFFER_TOO_SMALL) + TC_TOKEN_ERR(CKR_SAVED_STATE_INVALID) + TC_TOKEN_ERR(CKR_INFORMATION_SENSITIVE) + TC_TOKEN_ERR(CKR_STATE_UNSAVEABLE) + TC_TOKEN_ERR(CKR_CRYPTOKI_NOT_INITIALIZED) + TC_TOKEN_ERR(CKR_CRYPTOKI_ALREADY_INITIALIZED) + TC_TOKEN_ERR(CKR_MUTEX_BAD) + TC_TOKEN_ERR(CKR_MUTEX_NOT_LOCKED) + TC_TOKEN_ERR(CKR_NEW_PIN_MODE) + TC_TOKEN_ERR(CKR_NEXT_OTP) + TC_TOKEN_ERR(CKR_FUNCTION_REJECTED) #undef TC_TOKEN_ERR }; - for (size_t i = 0; i < array_capacity (ErrorStrings); ++i) + for (size_t i = 0; i < array_capacity(ErrorStrings); ++i) { if (ErrorStrings[i].ErrorCode == ErrorCode) return ErrorStrings[i].ErrorString; @@ -690,9 +698,9 @@ namespace VeraCrypt } #ifdef TC_HEADER_Common_Exception - void Pkcs11Exception::Show (HWND parent) const + void Pkcs11Exception::Show(HWND parent) const { - string errorString = string (*this); + string errorString = string(*this); if (!errorString.empty()) { @@ -700,11 +708,11 @@ namespace VeraCrypt if (SubjectErrorCodeValid) subjectErrorCode << L": " << SubjectErrorCode; - if (!GetDictionaryValue (errorString.c_str())) + if (!GetDictionaryValue(errorString.c_str())) { - if (errorString.find ("CKR_") == 0) + if (errorString.find("CKR_") == 0) { - errorString = errorString.substr (4); + errorString = errorString.substr(4); for (size_t i = 0; i < errorString.size(); ++i) { if (errorString[i] == '_') @@ -712,17 +720,17 @@ namespace VeraCrypt } } wchar_t err[8192]; - StringCbPrintfW (err, sizeof(err),L"%s:\n\n%hs%s", GetString ("SECURITY_TOKEN_ERROR"), errorString.c_str(), subjectErrorCode.str().c_str()); - ErrorDirect (err, parent); + StringCbPrintfW(err, sizeof(err), L"%s:\n\n%hs%s", GetString("SECURITY_TOKEN_ERROR"), errorString.c_str(), subjectErrorCode.str().c_str()); + ErrorDirect(err, parent); } else { - wstring err = GetString (errorString.c_str()); + wstring err = GetString(errorString.c_str()); if (SubjectErrorCodeValid) err += L"\n\nError code" + subjectErrorCode.str(); - ErrorDirect (err.c_str(), parent); + ErrorDirect(err.c_str(), parent); } } } @@ -738,36 +746,36 @@ namespace VeraCrypt #ifdef TC_WINDOWS HMODULE SecurityToken::Pkcs11LibraryHandle; #else - void *SecurityToken::Pkcs11LibraryHandle; + void* SecurityToken::Pkcs11LibraryHandle; #endif #ifdef TC_HEADER_Platform_Exception - void Pkcs11Exception::Deserialize (shared_ptr stream) + void Pkcs11Exception::Deserialize(shared_ptr stream) { - Exception::Deserialize (stream); - Serializer sr (stream); + Exception::Deserialize(stream); + Serializer sr(stream); uint64 code; - sr.Deserialize ("ErrorCode", code); - sr.Deserialize ("SubjectErrorCodeValid", SubjectErrorCodeValid); - sr.Deserialize ("SubjectErrorCode", SubjectErrorCode); - ErrorCode = (CK_RV) code; + sr.Deserialize("ErrorCode", code); + sr.Deserialize("SubjectErrorCodeValid", SubjectErrorCodeValid); + sr.Deserialize("SubjectErrorCode", SubjectErrorCode); + ErrorCode = (CK_RV)code; } - void Pkcs11Exception::Serialize (shared_ptr stream) const + void Pkcs11Exception::Serialize(shared_ptr stream) const { - Exception::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("ErrorCode", (uint64) ErrorCode); - sr.Serialize ("SubjectErrorCodeValid", SubjectErrorCodeValid); - sr.Serialize ("SubjectErrorCode", SubjectErrorCode); + 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 (SecurityTokenException); + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET(SecurityTokenException); #endif } diff --git a/src/Common/SecurityToken.h b/src/Common/SecurityToken.h index 6b228895..0d671dcc 100644 --- a/src/Common/SecurityToken.h +++ b/src/Common/SecurityToken.h @@ -53,62 +53,55 @@ #define TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"slot" #define TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"file" +#include "Token.h" + namespace VeraCrypt { - struct SecurityTokenInfo + struct SecurityTokenInfo: TokenInfo { - CK_SLOT_ID SlotId; + virtual BOOL isEditable() const {return true;} + CK_FLAGS Flags; - wstring Label; string LabelUtf8; }; - struct SecurityTokenKeyfilePath + struct SecurityTokenKeyfile: TokenKeyfile { - SecurityTokenKeyfilePath () { } - SecurityTokenKeyfilePath (const wstring &path) : Path (path) { } - operator wstring () const { return Path; } - wstring Path; - }; + SecurityTokenKeyfile(); - 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 TokenKeyfilePath& path); + + operator TokenKeyfilePath () const; - operator SecurityTokenKeyfilePath () const; + void GetKeyfileData(vector& keyfileData) const; CK_OBJECT_HANDLE Handle; - wstring Id; - string IdUtf8; - CK_SLOT_ID SlotId; - SecurityTokenInfo Token; }; - struct Pkcs11Exception : public Exception + struct Pkcs11Exception: public Exception { - Pkcs11Exception (CK_RV errorCode = (CK_RV) -1) - : ErrorCode (errorCode), - SubjectErrorCodeValid (false), - SubjectErrorCode( (uint64) -1) + Pkcs11Exception(CK_RV errorCode = (CK_RV)-1) + : ErrorCode(errorCode), + SubjectErrorCodeValid(false), + SubjectErrorCode((uint64)-1) { } - Pkcs11Exception (CK_RV errorCode, uint64 subjectErrorCode) - : ErrorCode (errorCode), - SubjectErrorCodeValid (true), - SubjectErrorCode (subjectErrorCode) + Pkcs11Exception(CK_RV errorCode, uint64 subjectErrorCode) + : ErrorCode(errorCode), + SubjectErrorCodeValid(true), + SubjectErrorCode(subjectErrorCode) { } #ifdef TC_HEADER_Platform_Exception - virtual ~Pkcs11Exception () throw () { } - TC_SERIALIZABLE_EXCEPTION (Pkcs11Exception); + virtual ~Pkcs11Exception() throw () { } + TC_SERIALIZABLE_EXCEPTION(Pkcs11Exception); #else - void Show (HWND parent) const; + void Show(HWND parent) const; #endif operator string () const; - CK_RV GetErrorCode () const { return ErrorCode; } + CK_RV GetErrorCode() const { return ErrorCode; } protected: CK_RV ErrorCode; @@ -135,24 +128,24 @@ namespace VeraCrypt #else // !TC_HEADER_Platform_Exception - struct SecurityTokenLibraryNotInitialized : public Exception + struct SecurityTokenLibraryNotInitialized: public Exception { - void Show (HWND parent) const { Error (SecurityTokenLibraryPath[0] == 0 ? "NO_PKCS11_MODULE_SPECIFIED" : "PKCS11_MODULE_INIT_FAILED", parent); } + void Show(HWND parent) const { Error(SecurityTokenLibraryPath[0] == 0 ? "NO_PKCS11_MODULE_SPECIFIED" : "PKCS11_MODULE_INIT_FAILED", parent); } }; - struct InvalidSecurityTokenKeyfilePath : public Exception + struct InvalidSecurityTokenKeyfilePath: public Exception { - void Show (HWND parent) const { Error ("INVALID_TOKEN_KEYFILE_PATH", parent); } + void Show(HWND parent) const { Error("INVALID_TOKEN_KEYFILE_PATH", parent); } }; - struct SecurityTokenKeyfileAlreadyExists : public Exception + struct SecurityTokenKeyfileAlreadyExists: public Exception { - void Show (HWND parent) const { Error ("TOKEN_KEYFILE_ALREADY_EXISTS", parent); } + void Show(HWND parent) const { Error("TOKEN_KEYFILE_ALREADY_EXISTS", parent); } }; - struct SecurityTokenKeyfileNotFound : public Exception + struct SecurityTokenKeyfileNotFound: public Exception { - void Show (HWND parent) const { Error ("TOKEN_KEYFILE_NOT_FOUND", parent); } + void Show(HWND parent) const { Error("TOKEN_KEYFILE_NOT_FOUND", parent); } }; #endif // !TC_HEADER_Platform_Exception @@ -160,7 +153,7 @@ namespace VeraCrypt struct Pkcs11Session { - Pkcs11Session () : Handle (CK_UNAVAILABLE_INFORMATION), UserLoggedIn (false) { } + Pkcs11Session(): Handle(CK_UNAVAILABLE_INFORMATION), UserLoggedIn(false) { } CK_SESSION_HANDLE Handle; bool UserLoggedIn; @@ -168,47 +161,46 @@ namespace VeraCrypt struct GetPinFunctor { - virtual ~GetPinFunctor () { } - virtual void operator() (string &str) = 0; - virtual void notifyIncorrectPin () = 0; + virtual ~GetPinFunctor() { } + virtual void operator() (string& str) = 0; + virtual void notifyIncorrectPin() = 0; }; struct SendExceptionFunctor { - virtual ~SendExceptionFunctor () { } - virtual void operator() (const Exception &e) = 0; + virtual ~SendExceptionFunctor() { } + virtual void operator() (const Exception& e) = 0; }; class SecurityToken { public: - static void CloseAllSessions () throw (); - 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 void GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector &keyfileData); - static list GetAvailableTokens (); - static SecurityTokenInfo GetTokenInfo (CK_SLOT_ID slotId); + static void CloseAllSessions() throw (); + 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 list GetAvailableTokens(); + static SecurityTokenInfo GetTokenInfo(CK_SLOT_ID slotId); #ifdef TC_WINDOWS - static void InitLibrary (const wstring &pkcs11LibraryPath, unique_ptr pinCallback, unique_ptr warningCallback); + static void InitLibrary(const wstring& pkcs11LibraryPath, unique_ptr pinCallback, unique_ptr warningCallback); #else - static void InitLibrary (const string &pkcs11LibraryPath, unique_ptr pinCallback, unique_ptr warningCallback); + static void InitLibrary(const string& pkcs11LibraryPath, unique_ptr pinCallback, unique_ptr warningCallback); #endif - static bool IsInitialized () { return Initialized; } - static bool IsKeyfilePathValid (const wstring &securityTokenKeyfilePath); + static bool IsInitialized() { return Initialized; } + static bool IsKeyfilePathValid(const wstring& securityTokenKeyfilePath); static const size_t MaxPasswordLength = 128; protected: - static void CloseSession (CK_SLOT_ID slotId); - 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 char* pin); - static void LoginUserIfRequired (CK_SLOT_ID slotId); - static void OpenSession (CK_SLOT_ID slotId); - static void CheckLibraryStatus (); + static void CloseSession(CK_SLOT_ID slotId); + 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 char* pin); + static void LoginUserIfRequired(CK_SLOT_ID slotId); + static void OpenSession(CK_SLOT_ID slotId); + static void CheckLibraryStatus(); static bool Initialized; static unique_ptr PinCallback; @@ -216,10 +208,12 @@ namespace VeraCrypt #ifdef TC_WINDOWS static HMODULE Pkcs11LibraryHandle; #else - static void *Pkcs11LibraryHandle; + static void* Pkcs11LibraryHandle; #endif static map Sessions; static unique_ptr WarningCallback; + + friend void SecurityTokenKeyfile::GetKeyfileData(vector & keyfileData) const; }; } diff --git a/src/Common/TLVParser.cpp b/src/Common/TLVParser.cpp new file mode 100644 index 00000000..bda9dec0 --- /dev/null +++ b/src/Common/TLVParser.cpp @@ -0,0 +1,179 @@ +#include "TLVParser.h" +#include + +using namespace std; + +/* TLV node structure creation */ +shared_ptr TLVParser::TLV_CreateNode() +{ + shared_ptr node= shared_ptr(new TLVNode); + memset(node.get(),0,sizeof(*node)); + return node; +} + +/* Check if the bit is correct */ +uint16_t TLVParser::CheckBit(unsigned char value, int bit){ + unsigned char bitvalue[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; + + if((bit >= 1)&&(bit <= 8)){ + if(value & bitvalue[bit-1]) { + return (1); + } + else { + return (0); + } + } + else{ + throw TLVException("FILE:"+string(__FILE__)+"LINE: "+to_string(static_cast((__LINE__)))+" fonction parameter incorrect! bit=["+to_string(static_cast(bit))); + return(2); + } +} + +/* Parsing one TLV node */ +shared_ptr TLVParser::TLV_Parse_One(unsigned char* buf,int size){ + int index = 0; + int i; + unsigned char tag1,tag2,tagsize; + unsigned char len,lensize; + unsigned char* value; + shared_ptr node = TLV_CreateNode(); + + tag1 = tag2 = 0; + tagsize = 1; + tag1 = buf[index++]; + if((tag1 & 0x1f) == 0x1f){ + tagsize++; + tag2 = buf[index++]; + //tag2 b8 must be 0! + } + if(tagsize == 1) { + node->Tag = tag1; + } + else { + node->Tag = (tag1 << 8) + tag2; + } + node->TagSize = tagsize; + + //SubFlag + node->SubFlag = CheckBit(tag1,6); + + //L zone + len = 0; + lensize = 1; + len = buf[index++]; + if(CheckBit(len,8) == 0){ + node->Length = len; + } + else{ + lensize = len & 0x7f; + len = 0; + for(i=0;iLength = len; + node->LengthSize = lensize; + + //V zone + value = new unsigned char[len]; + std::copy(buf+index,buf+index+len,value); + node->Value = value; + index += len; + + if(index < size){ + node->MoreFlag = 1; + } + else if(index == size){ + node->MoreFlag = 0; + } + else{ + throw TLVException("Parse Error! index="+to_string(static_cast(index))+"size="+to_string(static_cast(size))); + } + + return node; +} + +/* Parsing all sub-nodes (in width not in depth) of a given parent node */ +int TLVParser::TLV_Parse_SubNodes(shared_ptr parent){ + int sublen = 0; + int i; + + //No sub-nodes + if(parent->SubFlag == 0) + return 0; + + for(i=0;iSubCount;i++) + { + sublen += (parent->Sub[i]->TagSize + parent->Sub[i]->Length + parent->Sub[i]->LengthSize); + } + + if(sublen < parent->Length) + { + shared_ptr subnode = TLV_Parse_One(parent->Value+sublen,parent->Length-sublen); + parent->Sub[parent->SubCount++] = subnode; + return subnode->MoreFlag; + } + else + { + return 0; + } +} + +/* Recursive function to parse all nodes starting from a root parent node */ +void TLVParser::TLV_Parse_Sub(shared_ptr parent) +{ + int i; + if(parent->SubFlag != 0) + { + //Parse all sub nodes. + while(TLV_Parse_SubNodes(parent) != 0); + + for(i=0;iSubCount;i++) + { + if(parent->Sub[i]->SubFlag != 0) + { + TLV_Parse_Sub(parent->Sub[i]); + } + } + } + return; +} + +/* Parsing TLV from a buffer and constructing TLV structure */ +shared_ptr TLVParser::TLV_Parse(unsigned char* buf,int size) +{ + shared_ptr node = TLV_Parse_One(buf,size); + TLV_Parse_Sub(node); + + return node; +} + +/* Finding a TLV node with a particular tag */ +shared_ptr TLVParser::TLV_Find(shared_ptr node,uint16_t tag){ + int i; + shared_ptr tmpnode; + if(node->Tag == tag) + { + return node; + } + for(i=0;iSubCount;i++) + { + tmpnode = NULL; + tmpnode = TLV_Find(node->Sub[i],tag); + if(tmpnode != NULL){ + return tmpnode; + } + } + if(node->Next) + { + tmpnode = NULL; + tmpnode = TLV_Find(node->Next,tag); + if(tmpnode != NULL){ + return tmpnode; + } + } + + return nullptr; +} + diff --git a/src/Common/TLVParser.h b/src/Common/TLVParser.h new file mode 100644 index 00000000..e25e429f --- /dev/null +++ b/src/Common/TLVParser.h @@ -0,0 +1,80 @@ +// +// Created by bshp on 1/20/23. +// + +#ifndef ICC_EXTRACTOR_TLVPARSER_H +#define ICC_EXTRACTOR_TLVPARSER_H +#include +#include +#include +#include +#include +#include +#include "iostream" +#include "Tcdefs.h" +using namespace std; +struct TLVNode{ + uint16_t Tag; /* T */ + uint16_t Length; /* L */ + unsigned char* Value; /* V */ + unsigned char TagSize; + unsigned char LengthSize; + uint16_t MoreFlag; /* Used In Sub */ + uint16_t SubFlag; /* Does it have sub-nodes? */ + uint16_t SubCount; + shared_ptr Sub[256]; + shared_ptr Next; + + ~TLVNode() { + burn(Value, Length); + delete Value; + } +}; + +class TLVParser{ +private : + + /* TLV node structure creation */ + static shared_ptr TLV_CreateNode(); + + /* Check if the bit is correct */ + static uint16_t CheckBit(unsigned char value, int bit); + + /* Parsing one TLV node */ + static shared_ptr TLV_Parse_One(unsigned char* buf,int size); + + /* Parsing all TLV nodes */ + static int TLV_Parse_SubNodes(shared_ptr parent); + + /* Parsing all sub-nodes (in width not in depth) of a given parent node */ + static int TLV_Parse_All(shared_ptr parent); + + /* Recursive function to parse all nodes starting from a root parent node */ + static void TLV_Parse_Sub(shared_ptr parent); + +public: + + /* Parsing TLV from a buffer and constructing TLV structure */ + static shared_ptr TLV_Parse(unsigned char* buf,int size); + + /* Finding a TLV node with a particular tag */ + static shared_ptr TLV_Find(shared_ptr node,uint16_t tag); +}; + +/* The definition of the exception class related to the TLV parsing */ +class TLVException +{ +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 //ICC_EXTRACTOR_TLVPARSER_H diff --git a/src/Common/Token.cpp b/src/Common/Token.cpp new file mode 100644 index 00000000..5da677de --- /dev/null +++ b/src/Common/Token.cpp @@ -0,0 +1,82 @@ +#include "Token.h" +#include "Platform/Finally.h" +#include "Platform/ForEach.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 +#include +#include + +#include "SecurityToken.h" +#include "EMVToken.h" +#include "iostream" + +using namespace std; + +namespace VeraCrypt +{ + vector> Token::GetAvailableKeyfiles(bool EMVOption) { + vector> availableKeyfiles; + bool securityTokenLibraryInitialized = true; + + try{ + foreach (SecurityTokenKeyfile k, SecurityToken::GetAvailableKeyfiles()) { + availableKeyfiles.push_back(shared_ptr(new SecurityTokenKeyfile(k))); + } + } catch (SecurityTokenLibraryNotInitialized){ + securityTokenLibraryInitialized = false; + } + + if(EMVOption){ + foreach (EMVTokenKeyfile k, EMVToken::GetAvailableKeyfiles()) { + availableKeyfiles.push_back(shared_ptr(new EMVTokenKeyfile(k))); + } + } + + if(availableKeyfiles.size() == 0 && ! securityTokenLibraryInitialized){ + throw SecurityTokenLibraryNotInitialized(); + } + + return availableKeyfiles; + } + + bool Token::IsKeyfilePathValid(const wstring& tokenKeyfilePath, bool EMVOption) + { + if(EMVOption){ + return SecurityToken::IsKeyfilePathValid(tokenKeyfilePath) || EMVToken::IsKeyfilePathValid(tokenKeyfilePath); + } + return SecurityToken::IsKeyfilePathValid(tokenKeyfilePath); + } + + list > Token::GetAvailableTokens() + { + list > availableTokens; + foreach(SecurityTokenInfo securityToken, SecurityToken::GetAvailableTokens()){ + availableTokens.push_back(shared_ptr(new SecurityTokenInfo(std::move(securityToken)))); + } + + return availableTokens ; + } + + shared_ptr Token::getTokenKeyfile(const TokenKeyfilePath path){ + shared_ptr tokenKeyfile; + + if(SecurityToken::IsKeyfilePathValid(path)){ + tokenKeyfile = shared_ptr(new SecurityTokenKeyfile(path)); + } else { + if(EMVToken::IsKeyfilePathValid(path)){ + tokenKeyfile = shared_ptr(new EMVTokenKeyfile(path)); + } + } + + return tokenKeyfile; + } +} \ No newline at end of file diff --git a/src/Common/Token.h b/src/Common/Token.h new file mode 100644 index 00000000..28c6a489 --- /dev/null +++ b/src/Common/Token.h @@ -0,0 +1,57 @@ +#ifndef TC_HEADER_Common_Token +#define TC_HEADER_Common_Token + +#include "Platform/PlatformBase.h" + +#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) +# include "Exception.h" +#else + +# include "Platform/Exception.h" + +#endif + +#include + +#define UNAVAILABLE_SLOT ~0UL + +namespace VeraCrypt { + + struct TokenKeyfilePath { + TokenKeyfilePath(const wstring& path): Path(path) { } + operator wstring () const { return Path; } + + wstring Path; //Complete path + + }; + struct TokenInfo { + TokenInfo() {} + virtual ~TokenInfo() {} + + virtual BOOL isEditable() const=0; + + unsigned long int SlotId; + wstring Label; //Card name + }; + + struct TokenKeyfile { + virtual operator TokenKeyfilePath () const = 0; + virtual void GetKeyfileData(vector & keyfileData) const = 0; + + string IdUtf8; // Was used in SecurityToken to compare with the file name from a PKCS11 card, remove from token ? + shared_ptr Token; + wstring Id; + }; + + class Token { + public: + static vector> GetAvailableKeyfiles(bool EMVOption); + static bool IsKeyfilePathValid(const wstring& tokenKeyfilePath, bool EMVOption); + static list > GetAvailableTokens(); // List available token to write + static shared_ptr getTokenKeyfile(const TokenKeyfilePath path); + }; + +}; + + +#endif //TC_HEADER_Common_Token diff --git a/src/Core/Core.h b/src/Core/Core.h index 3a2235a5..d2a4c593 100644 --- a/src/Core/Core.h +++ b/src/Core/Core.h @@ -82,9 +82,10 @@ namespace VeraCrypt shared_ptr m_newKeyfiles; shared_ptr m_newPkcs5Kdf; int m_wipeCount; - ChangePasswordThreadRoutine(shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf, int wipeCount) : 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) {} + bool m_emvoption; + ChangePasswordThreadRoutine(shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf, int wipeCount, bool EMVOption) : m_volumePath(volumePath), m_preserveTimestamps(preserveTimestamps), m_password(password), m_pim(pim), m_kdf(kdf), m_truecryptMode(truecryptMode), m_keyfiles(keyfiles), m_newPassword(newPassword), m_newPim(newPim), m_newKeyfiles(newKeyfiles), m_newPkcs5Kdf(newPkcs5Kdf), m_wipeCount(wipeCount), m_emvoption(EMVOption) {} 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_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_emvoption, m_newPkcs5Kdf, m_wipeCount); } }; class OpenVolumeThreadRoutine : public WaitThreadRoutine @@ -107,15 +108,16 @@ namespace VeraCrypt bool m_useBackupHeaders; bool m_partitionInSystemEncryptionScope; shared_ptr m_pVolume; + bool m_emvoption; - OpenVolumeThreadRoutine(shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr Kdf, bool truecryptMode, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false): + OpenVolumeThreadRoutine(shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr Kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false): 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_partitionInSystemEncryptionScope(partitionInSystemEncryptionScope), m_emvoption(EMVOption) {} ~OpenVolumeThreadRoutine() {} - virtual void ExecutionCode(void) { m_pVolume = Core->OpenVolume(m_volumePath,m_preserveTimestamps,m_password,m_pim,m_Kdf,m_truecryptMode,m_keyfiles, 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_emvoption, m_protection,m_protectionPassword,m_protectionPim,m_protectionKdf, m_protectionKeyfiles,m_sharedAccessAllowed,m_volumeType,m_useBackupHeaders, m_partitionInSystemEncryptionScope); } }; @@ -127,10 +129,11 @@ namespace VeraCrypt shared_ptr m_password; int m_pim; shared_ptr m_keyfiles; - ReEncryptHeaderThreadRoutine(const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles) - : m_newHeaderBuffer(newHeaderBuffer), m_header(header), m_password(password), m_pim(pim), m_keyfiles(keyfiles) {} + bool m_emvoption; + ReEncryptHeaderThreadRoutine(const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles, bool EMVOption) + : m_newHeaderBuffer(newHeaderBuffer), m_header(header), m_password(password), m_pim(pim), m_keyfiles(keyfiles), m_emvoption(EMVOption) {} virtual ~ReEncryptHeaderThreadRoutine() { } - virtual void ExecutionCode(void) { Core->ReEncryptVolumeHeaderWithNewSalt (m_newHeaderBuffer, m_header, m_password, m_pim, m_keyfiles); } + virtual void ExecutionCode(void) { Core->ReEncryptVolumeHeaderWithNewSalt (m_newHeaderBuffer, m_header, m_password, m_pim, m_keyfiles, m_emvoption); } }; class DecryptThreadRoutine : public WaitThreadRoutine diff --git a/src/Core/CoreBase.cpp b/src/Core/CoreBase.cpp index 29bfb74d..ce6e0c20 100644 --- a/src/Core/CoreBase.cpp +++ b/src/Core/CoreBase.cpp @@ -30,7 +30,7 @@ namespace VeraCrypt { } - void CoreBase::ChangePassword (shared_ptr openVolume, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf, int wipeCount) const + void CoreBase::ChangePassword (shared_ptr openVolume, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool EMVOption, shared_ptr newPkcs5Kdf, int wipeCount) const { if ((!newPassword || newPassword->Size() < 1) && (!newKeyfiles || newKeyfiles->empty())) throw PasswordEmpty (SRC_POS); @@ -58,7 +58,7 @@ namespace VeraCrypt SecureBuffer newSalt (openVolume->GetSaltSize()); SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize()); - shared_ptr password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword)); + shared_ptr password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword, EMVOption)); bool backupHeader = false; while (true) @@ -83,10 +83,10 @@ namespace VeraCrypt } } - void CoreBase::ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf, int wipeCount) const + void CoreBase::ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool EMVOption, shared_ptr newPkcs5Kdf, int wipeCount) const { - shared_ptr volume = OpenVolume (volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles); - ChangePassword (volume, newPassword, newPim, newKeyfiles, newPkcs5Kdf, wipeCount); + shared_ptr volume = OpenVolume (volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, EMVOption); + ChangePassword (volume, newPassword, newPim, newKeyfiles, EMVOption, newPkcs5Kdf, wipeCount); } void CoreBase::CoalesceSlotNumberAndMountPoint (MountOptions &options) const @@ -261,10 +261,10 @@ namespace VeraCrypt return false; } - shared_ptr CoreBase::OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) const + shared_ptr CoreBase::OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) const { make_shared_auto (Volume, volume); - volume->Open (*volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, protection, protectionPassword, protectionPim, protectionKdf, protectionKeyfiles, sharedAccessAllowed, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); + volume->Open (*volumePath, preserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, EMVOption, protection, protectionPassword, protectionPim, protectionKdf, protectionKeyfiles, sharedAccessAllowed, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); return volume; } @@ -279,7 +279,7 @@ namespace VeraCrypt encryptionAlgorithm->GetMode()->SetKey (modeKey); } - void CoreBase::ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles) const + void CoreBase::ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles, bool EMVOption) const { shared_ptr pkcs5Kdf = header->GetPkcs5Kdf(); @@ -288,7 +288,7 @@ namespace VeraCrypt SecureBuffer newSalt (header->GetSaltSize()); SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize()); - shared_ptr passwordKey (Keyfile::ApplyListToPassword (keyfiles, password)); + shared_ptr passwordKey (Keyfile::ApplyListToPassword (keyfiles, password, EMVOption)); RandomNumberGenerator::GetData (newSalt); pkcs5Kdf->DeriveKey (newHeaderKey, *passwordKey, pim, newSalt); diff --git a/src/Core/CoreBase.h b/src/Core/CoreBase.h index 8f41ddd8..8df644c3 100644 --- a/src/Core/CoreBase.h +++ b/src/Core/CoreBase.h @@ -33,8 +33,8 @@ namespace VeraCrypt public: virtual ~CoreBase (); - virtual void ChangePassword (shared_ptr openVolume, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf = shared_ptr (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const; - virtual void ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, shared_ptr newPkcs5Kdf = shared_ptr (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const; + virtual void ChangePassword (shared_ptr openVolume, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool EMVOption, shared_ptr newPkcs5Kdf = shared_ptr (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const; + virtual void ChangePassword (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, shared_ptr newPassword, int newPim, shared_ptr newKeyfiles, bool EMVOption, shared_ptr newPkcs5Kdf = shared_ptr (), int wipeCount = PRAND_HEADER_WIPE_PASSES) const; virtual void CheckFilesystem (shared_ptr mountedVolume, bool repair = false) const = 0; virtual void CoalesceSlotNumberAndMountPoint (MountOptions &options) const; virtual void CreateKeyfile (const FilePath &keyfilePath) const; @@ -69,9 +69,9 @@ namespace VeraCrypt virtual bool IsVolumeMounted (const VolumePath &volumePath) const; virtual VolumeSlotNumber MountPointToSlotNumber (const DirectoryPath &mountPoint) const = 0; virtual shared_ptr MountVolume (MountOptions &options) = 0; - virtual shared_ptr OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr Kdf, bool truecryptMode, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false) const; + virtual shared_ptr OpenVolume (shared_ptr volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr Kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false) const; virtual void RandomizeEncryptionAlgorithmKey (shared_ptr encryptionAlgorithm) const; - virtual void ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles) const; + virtual void ReEncryptVolumeHeaderWithNewSalt (const BufferPtr &newHeaderBuffer, shared_ptr header, shared_ptr password, int pim, shared_ptr keyfiles, bool EMVOption) const; virtual void SetAdminPasswordCallback (shared_ptr functor) { } virtual void SetApplicationExecutablePath (const FilePath &path) { ApplicationExecutablePath = path; } virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const = 0; diff --git a/src/Core/MountOptions.h b/src/Core/MountOptions.h index 83a8bffc..6daecadd 100644 --- a/src/Core/MountOptions.h +++ b/src/Core/MountOptions.h @@ -73,6 +73,7 @@ namespace VeraCrypt VolumeSlotNumber SlotNumber; bool UseBackupHeaders; bool TrueCryptMode; + bool EMVOption; protected: void CopyFrom (const MountOptions &other); diff --git a/src/Core/Unix/CoreServiceProxy.h b/src/Core/Unix/CoreServiceProxy.h index f5bbae3d..63b208a8 100644 --- a/src/Core/Unix/CoreServiceProxy.h +++ b/src/Core/Unix/CoreServiceProxy.h @@ -98,11 +98,11 @@ namespace VeraCrypt { MountOptions newOptions = options; - newOptions.Password = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password); + newOptions.Password = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVOption); if (newOptions.Keyfiles) newOptions.Keyfiles->clear(); - newOptions.ProtectionPassword = Keyfile::ApplyListToPassword (options.ProtectionKeyfiles, options.ProtectionPassword); + newOptions.ProtectionPassword = Keyfile::ApplyListToPassword (options.ProtectionKeyfiles, options.ProtectionPassword, options.EMVOption); 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)); + VolumePasswordCache::Store (*Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVOption)); } } diff --git a/src/Core/Unix/CoreUnix.cpp b/src/Core/Unix/CoreUnix.cpp index 56382c18..3b495e5f 100644 --- a/src/Core/Unix/CoreUnix.cpp +++ b/src/Core/Unix/CoreUnix.cpp @@ -548,6 +548,7 @@ namespace VeraCrypt options.Kdf, options.TrueCryptMode, options.Keyfiles, + options.EMVOption, options.Protection, options.ProtectionPassword, options.ProtectionPim, diff --git a/src/Core/VolumeCreator.cpp b/src/Core/VolumeCreator.cpp index 1cc45b27..8a4baeed 100644 --- a/src/Core/VolumeCreator.cpp +++ b/src/Core/VolumeCreator.cpp @@ -307,7 +307,7 @@ namespace VeraCrypt // Header key HeaderKey.Allocate (VolumeHeader::GetLargestSerializedKeySize()); - PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password); + PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password, options->EMVOption); options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, options->Pim, salt); headerOptions.HeaderKey = HeaderKey; diff --git a/src/Core/VolumeCreator.h b/src/Core/VolumeCreator.h index 3e051bc7..dc742911 100644 --- a/src/Core/VolumeCreator.h +++ b/src/Core/VolumeCreator.h @@ -38,6 +38,7 @@ namespace VeraCrypt shared_ptr VolumeHeaderKdf; shared_ptr EA; bool Quick; + bool EMVOption; struct FilesystemType { diff --git a/src/ExpandVolume/ExpandVolume.vcxproj b/src/ExpandVolume/ExpandVolume.vcxproj index c4f8ce09..c182afe5 100644 --- a/src/ExpandVolume/ExpandVolume.vcxproj +++ b/src/ExpandVolume/ExpandVolume.vcxproj @@ -245,7 +245,7 @@ copy Debug\VeraCryptExpander.exe "..\Debug\Setup Files" >NUL: 4311;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCryptExpander.exe false mpr.dll;%(DelayLoadDLLs) @@ -336,7 +336,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" >NUL: 4311;4131;%(DisableSpecificWarnings) - ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCryptExpander.exe false mpr.dll;%(DelayLoadDLLs) @@ -428,7 +428,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" >NUL: 4311;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCryptExpander.exe false mpr.dll;%(DelayLoadDLLs) @@ -476,7 +476,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" >NUL: 4311;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCryptExpander.exe false mpr.dll;%(DelayLoadDLLs) @@ -575,6 +575,10 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" >NUL: + + + + @@ -655,6 +659,10 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" >NUL: + + + + diff --git a/src/ExpandVolume/ExpandVolume.vcxproj.filters b/src/ExpandVolume/ExpandVolume.vcxproj.filters index 007757ff..3997d07f 100644 --- a/src/ExpandVolume/ExpandVolume.vcxproj.filters +++ b/src/ExpandVolume/ExpandVolume.vcxproj.filters @@ -126,6 +126,18 @@ Source Files\Setup + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + @@ -230,6 +242,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/src/ExpandVolume/WinMain.cpp b/src/ExpandVolume/WinMain.cpp index 42f1c28d..57e58b4f 100644 --- a/src/ExpandVolume/WinMain.cpp +++ b/src/ExpandVolume/WinMain.cpp @@ -321,6 +321,7 @@ void LoadSettings (HWND hwndDlg) mountOptions = defaultMountOptions; CloseSecurityTokenSessionsAfterMount = ConfigReadInt ("CloseSecurityTokenSessionsAfterMount", 0); + ActivateEMVOption = ConfigReadInt ("ActivateEMVOption", 0); { char szTmp[TC_MAX_PATH] = {0}; diff --git a/src/Format/Format.vcxproj b/src/Format/Format.vcxproj index e377c1e0..9f5abbc0 100644 --- a/src/Format/Format.vcxproj +++ b/src/Format/Format.vcxproj @@ -218,7 +218,7 @@ copy Debug\VeraCryptFormat.exe "..\Debug\Setup Files\VeraCrypt Format.exe" >N 4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCryptFormat.exe false mpr.dll;%(DelayLoadDLLs) @@ -301,7 +301,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: 4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCryptFormat.exe false mpr.dll;%(DelayLoadDLLs) @@ -385,7 +385,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: 4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCryptFormat.exe false mpr.dll;%(DelayLoadDLLs) @@ -429,7 +429,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: 4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCryptFormat.exe false mpr.dll;%(DelayLoadDLLs) @@ -497,6 +497,10 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: + + + + CompileAsCpp @@ -582,11 +586,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: + + + + @@ -644,7 +652,9 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" >NUL: - + + Designer + diff --git a/src/Format/Format.vcxproj.filters b/src/Format/Format.vcxproj.filters index 4f0e81eb..e6615982 100644 --- a/src/Format/Format.vcxproj.filters +++ b/src/Format/Format.vcxproj.filters @@ -108,6 +108,18 @@ Source Files\Common + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + @@ -208,6 +220,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/src/Format/Tcformat.c b/src/Format/Tcformat.c index 9c8648a8..1e605c4d 100644 --- a/src/Format/Tcformat.c +++ b/src/Format/Tcformat.c @@ -802,6 +802,8 @@ static void LoadSettingsAndCheckModified (HWND hwndDlg, BOOL bOnlyCheckModified, ConfigReadCompareInt ("UseLegacyMaxPasswordLength", FALSE, &bUseLegacyMaxPasswordLength, bOnlyCheckModified, pbSettingsModified); + ConfigReadCompareInt ("ActivateEMVOption", 0, &ActivateEMVOption, bOnlyCheckModified, pbSettingsModified); + { char szTmp[MAX_PATH] = {0}; WideCharToMultiByte (CP_UTF8, 0, SecurityTokenLibraryPath, -1, szTmp, MAX_PATH, NULL, NULL); @@ -9589,7 +9591,7 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine) case OptionTokenPin: { - wchar_t szTmp[SecurityToken::MaxPasswordLength + 1] = {0}; + wchar_t szTmp[SecurityToken::MaxPasswordLength + 1] = {0}; // TODO Use Token if (GetArgumentValue (lpszCommandLineArgs, &i, nNoCommandLineArgs, szTmp, ARRAYSIZE (szTmp)) == HAS_ARGUMENT) { if (0 == WideCharToMultiByte (CP_UTF8, 0, szTmp, -1, CmdTokenPin, TC_MAX_PATH, nullptr, nullptr)) diff --git a/src/Main/CommandLineInterface.cpp b/src/Main/CommandLineInterface.cpp index 865f69dd..dabfcad6 100644 --- a/src/Main/CommandLineInterface.cpp +++ b/src/Main/CommandLineInterface.cpp @@ -67,7 +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 security 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"load-preferences", _("Load user preferences")); parser.AddSwitch (L"", L"mount", _("Mount volume interactively")); parser.AddOption (L"m", L"mount-options", _("VeraCrypt volume mount options")); @@ -238,8 +240,18 @@ namespace VeraCrypt if (parser.Found (L"list-token-keyfiles")) { CheckCommandSingle(); - ArgCommand = CommandId::ListSecurityTokenKeyfiles; + ArgCommand = CommandId::ListTokenKeyfiles; } + if (parser.Found (L"list-securitytoken-keyfiles")) + { + CheckCommandSingle(); + ArgCommand = CommandId::ListSecurityTokenKeyfiles; + } + if (parser.Found (L"list-emvtoken-keyfiles")) + { + CheckCommandSingle(); + ArgCommand = CommandId::ListEMVTokenKeyfiles; + } if (parser.Found (L"mount")) { diff --git a/src/Main/CommandLineInterface.h b/src/Main/CommandLineInterface.h index 23693330..21fb5c89 100644 --- a/src/Main/CommandLineInterface.h +++ b/src/Main/CommandLineInterface.h @@ -42,7 +42,9 @@ namespace VeraCrypt ExportSecurityTokenKeyfile, Help, ImportSecurityTokenKeyfiles, - ListSecurityTokenKeyfiles, + ListTokenKeyfiles, + ListSecurityTokenKeyfiles, + ListEMVTokenKeyfiles, ListVolumes, MountVolume, RestoreHeaders, diff --git a/src/Main/Forms/ChangePasswordDialog.cpp b/src/Main/Forms/ChangePasswordDialog.cpp index 585d14a5..0992cf3b 100644 --- a/src/Main/Forms/ChangePasswordDialog.cpp +++ b/src/Main/Forms/ChangePasswordDialog.cpp @@ -204,7 +204,7 @@ namespace VeraCrypt wxBusyCursor busy; ChangePasswordThreadRoutine routine(Path, Gui->GetPreferences().DefaultMountOptions.PreserveTimestamps, CurrentPasswordPanel->GetPassword(), CurrentPasswordPanel->GetVolumePim(), CurrentPasswordPanel->GetPkcs5Kdf(bUnsupportedKdf), CurrentPasswordPanel->GetTrueCryptMode(),CurrentPasswordPanel->GetKeyfiles(), - newPassword, newPim, newKeyfiles, NewPasswordPanel->GetPkcs5Kdf(bUnsupportedKdf), NewPasswordPanel->GetHeaderWipeCount()); + newPassword, newPim, newKeyfiles, NewPasswordPanel->GetPkcs5Kdf(bUnsupportedKdf), NewPasswordPanel->GetHeaderWipeCount(), Gui->GetPreferences().ActivateEMVOption); Gui->ExecuteWaitThreadRoutine (this, &routine); } diff --git a/src/Main/Forms/Forms.cpp b/src/Main/Forms/Forms.cpp index b601839e..8667a741 100644 --- a/src/Main/Forms/Forms.cpp +++ b/src/Main/Forms/Forms.cpp @@ -2204,11 +2204,18 @@ PreferencesDialogBase::PreferencesDialogBase( wxWindow* parent, wxWindowID id, c CloseSecurityTokenSessionsAfterMountCheckBox = new wxCheckBox( sbSizer37->GetStaticBox(), wxID_ANY, _("IDC_CLOSE_TOKEN_SESSION_AFTER_MOUNT"), wxDefaultPosition, wxDefaultSize, 0 ); sbSizer37->Add( CloseSecurityTokenSessionsAfterMountCheckBox, 0, wxALL, 5 ); - + bSizer128->Add( sbSizer37, 0, wxEXPAND|wxALL, 5 ); - - + + 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 ); + + bSizer128->Add( sbSizer38, 0, wxEXPAND|wxALL, 5 ); + bSizer127->Add( bSizer128, 1, wxEXPAND|wxALL, 5 ); diff --git a/src/Main/Forms/Forms.h b/src/Main/Forms/Forms.h index 245087de..904e96dd 100644 --- a/src/Main/Forms/Forms.h +++ b/src/Main/Forms/Forms.h @@ -593,6 +593,7 @@ namespace VeraCrypt wxTextCtrl* Pkcs11ModulePathTextCtrl; wxButton* SelectPkcs11ModuleButton; wxCheckBox* CloseSecurityTokenSessionsAfterMountCheckBox; + wxCheckBox* ActivateEMVOptionCheckBox; wxListCtrl* HotkeyListCtrl; wxTextCtrl* HotkeyTextCtrl; wxButton* AssignHotkeyButton; diff --git a/src/Main/Forms/KeyfilesPanel.cpp b/src/Main/Forms/KeyfilesPanel.cpp index c1f26d86..e3d086fc 100644 --- a/src/Main/Forms/KeyfilesPanel.cpp +++ b/src/Main/Forms/KeyfilesPanel.cpp @@ -115,7 +115,7 @@ namespace VeraCrypt SecurityTokenKeyfilesDialog dialog (this); if (dialog.ShowModal() == wxID_OK) { - foreach (const SecurityTokenKeyfilePath &path, dialog.GetSelectedSecurityTokenKeyfilePaths()) + foreach (const TokenKeyfilePath &path, dialog.GetSelectedSecurityTokenKeyfilePaths()) { vector fields; fields.push_back (path); diff --git a/src/Main/Forms/MainFrame.cpp b/src/Main/Forms/MainFrame.cpp index ab42ac06..b52682ce 100644 --- a/src/Main/Forms/MainFrame.cpp +++ b/src/Main/Forms/MainFrame.cpp @@ -683,7 +683,7 @@ namespace VeraCrypt { mountOptions.Pim = CmdLine->ArgPim; } - + mountOptions.EMVOption = GetPreferences().ActivateEMVOption; Gui->MountAllFavoriteVolumes (mountOptions); } catch (exception &e) @@ -718,6 +718,7 @@ namespace VeraCrypt { mountOptions.Pim = CmdLine->ArgPim; } + mountOptions.EMVOption = GetPreferences().ActivateEMVOption; try { diff --git a/src/Main/Forms/MountOptionsDialog.cpp b/src/Main/Forms/MountOptionsDialog.cpp index 04410922..28a9919c 100644 --- a/src/Main/Forms/MountOptionsDialog.cpp +++ b/src/Main/Forms/MountOptionsDialog.cpp @@ -193,6 +193,7 @@ namespace VeraCrypt Options.MountPoint = make_shared (mountPoint); Options.FilesystemOptions = FilesystemOptionsTextCtrl->GetValue(); + Options.EMVOption = Gui->GetPreferences().ActivateEMVOption; EndModal (wxID_OK); } diff --git a/src/Main/Forms/PreferencesDialog.cpp b/src/Main/Forms/PreferencesDialog.cpp index 2815c9b5..6caae325 100644 --- a/src/Main/Forms/PreferencesDialog.cpp +++ b/src/Main/Forms/PreferencesDialog.cpp @@ -96,6 +96,7 @@ namespace VeraCrypt // Security tokens Pkcs11ModulePathTextCtrl->SetValue (wstring (Preferences.SecurityTokenModule)); TC_CHECK_BOX_VALIDATOR (CloseSecurityTokenSessionsAfterMount); + TC_CHECK_BOX_VALIDATOR (ActivateEMVOption); // System integration TC_CHECK_BOX_VALIDATOR (StartOnLogon); diff --git a/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp b/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp index c4492599..2c5896a7 100644 --- a/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp +++ b/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp @@ -12,7 +12,6 @@ #include "System.h" #include "Main/GraphicUserInterface.h" -#include "Common/SecurityToken.h" #include "NewSecurityTokenKeyfileDialog.h" #include "SecurityTokenKeyfilesDialog.h" @@ -54,18 +53,18 @@ namespace VeraCrypt wxBusyCursor busy; SecurityTokenKeyfileListCtrl->DeleteAllItems(); - SecurityTokenKeyfileList = SecurityToken::GetAvailableKeyfiles(); + SecurityTokenKeyfileList = Token::GetAvailableKeyfiles(Gui->GetPreferences().ActivateEMVOption); size_t i = 0; - foreach (const SecurityTokenKeyfile &key, SecurityTokenKeyfileList) + foreach (const shared_ptr key, SecurityTokenKeyfileList) { vector fields (SecurityTokenKeyfileListCtrl->GetColumnCount()); - fields[ColumnSecurityTokenSlotId] = StringConverter::ToWide ((uint64) key.SlotId); - fields[ColumnSecurityTokenLabel] = key.Token.Label; - fields[ColumnSecurityTokenKeyfileLabel] = key.Id; + fields[ColumnSecurityTokenSlotId] = StringConverter::ToWide ((uint64) key->Token->SlotId); + fields[ColumnSecurityTokenLabel] = key->Token->Label; + fields[ColumnSecurityTokenKeyfileLabel] = key->Id; - Gui->AppendToListCtrl (SecurityTokenKeyfileListCtrl, fields, 0, &SecurityTokenKeyfileList[i++]); + Gui->AppendToListCtrl (SecurityTokenKeyfileListCtrl, fields, 0, key.get()); } } @@ -97,7 +96,7 @@ namespace VeraCrypt { foreach (long item, Gui->GetListCtrlSelectedItems (SecurityTokenKeyfileListCtrl)) { - SecurityTokenKeyfile *keyfile = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData (item)); + TokenKeyfile *keyfile = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData (item)); FilePathList files = Gui->SelectFiles (this, wxEmptyString, true); @@ -106,7 +105,7 @@ namespace VeraCrypt wxBusyCursor busy; vector keyfileData; - SecurityToken::GetKeyfileData (*keyfile, keyfileData); + keyfile->GetKeyfileData (keyfileData); BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); @@ -178,24 +177,34 @@ namespace VeraCrypt } } - void SecurityTokenKeyfilesDialog::OnListItemSelected (wxListEvent& event) - { - if (event.GetItem().GetData() != (wxUIntPtr) nullptr) - { - DeleteButton->Enable(); - ExportButton->Enable(); - OKButton->Enable(); - } - } + void SecurityTokenKeyfilesDialog::OnListItemSelected(wxListEvent &event) { + if (event.GetItem().GetData() != (wxUIntPtr) nullptr) { + BOOL deletable = true; + foreach(long + item, Gui->GetListCtrlSelectedItems(SecurityTokenKeyfileListCtrl)) + { + TokenKeyfile *keyfile = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData( + item)); + if (!keyfile->Token->isEditable()) { + deletable = false; + } + } + if (deletable) { + DeleteButton->Enable(); + } + ExportButton->Enable(); + OKButton->Enable(); + } + } void SecurityTokenKeyfilesDialog::OnOKButtonClick () { foreach (long item, Gui->GetListCtrlSelectedItems (SecurityTokenKeyfileListCtrl)) - { - SecurityTokenKeyfile *key = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData (item)); - SelectedSecurityTokenKeyfilePaths.push_back (*key); - } + { + TokenKeyfile *key = reinterpret_cast (SecurityTokenKeyfileListCtrl->GetItemData(item)); + SelectedSecurityTokenKeyfilePaths.push_back(*key); + } EndModal (wxID_OK); } } diff --git a/src/Main/Forms/SecurityTokenKeyfilesDialog.h b/src/Main/Forms/SecurityTokenKeyfilesDialog.h index 8ba7fa9d..92119e1e 100644 --- a/src/Main/Forms/SecurityTokenKeyfilesDialog.h +++ b/src/Main/Forms/SecurityTokenKeyfilesDialog.h @@ -14,7 +14,9 @@ #define TC_HEADER_Main_Forms_SecurityTokenKeyfilesDialog #include "Forms.h" +#include "Common/Token.h" #include "Common/SecurityToken.h" +#include "Common/EMVToken.h" #include "Main/Main.h" namespace VeraCrypt @@ -23,7 +25,7 @@ namespace VeraCrypt { public: SecurityTokenKeyfilesDialog (wxWindow* parent, bool selectionMode = true); - list GetSelectedSecurityTokenKeyfilePaths() const { return SelectedSecurityTokenKeyfilePaths; } + list GetSelectedSecurityTokenKeyfilePaths() const { return SelectedSecurityTokenKeyfilePaths; } protected: enum @@ -43,8 +45,8 @@ namespace VeraCrypt void OnOKButtonClick (); void OnOKButtonClick (wxCommandEvent& event) { OnOKButtonClick(); } - vector SecurityTokenKeyfileList; - list SelectedSecurityTokenKeyfilePaths; + vector > SecurityTokenKeyfileList; + list SelectedSecurityTokenKeyfilePaths; }; } diff --git a/src/Main/Forms/VolumeCreationWizard.cpp b/src/Main/Forms/VolumeCreationWizard.cpp index dbb01974..0487455f 100644 --- a/src/Main/Forms/VolumeCreationWizard.cpp +++ b/src/Main/Forms/VolumeCreationWizard.cpp @@ -795,7 +795,7 @@ namespace VeraCrypt shared_ptr hiddenPassword; try { - hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password); + hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().ActivateEMVOption); } catch (...) { @@ -846,7 +846,7 @@ namespace VeraCrypt shared_ptr hiddenPassword; try { - hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password); + hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().ActivateEMVOption); } catch (...) { @@ -1032,6 +1032,8 @@ namespace VeraCrypt options->Size = VolumeSize; options->Type = OuterVolume ? VolumeType::Normal : SelectedVolumeType; options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*SelectedHash, false); + options->EMVOption = Gui->GetPreferences().ActivateEMVOption; + Creator.reset (new VolumeCreator); VolumeCreatorThreadRoutine routine(options, Creator); @@ -1160,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); + OuterPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().ActivateEMVOption); } catch (...) { diff --git a/src/Main/Forms/VolumePasswordPanel.cpp b/src/Main/Forms/VolumePasswordPanel.cpp index 3b624340..5bd98daa 100644 --- a/src/Main/Forms/VolumePasswordPanel.cpp +++ b/src/Main/Forms/VolumePasswordPanel.cpp @@ -383,7 +383,7 @@ namespace VeraCrypt SecurityTokenKeyfilesDialog dialog (this); if (dialog.ShowModal() == wxID_OK) { - foreach (const SecurityTokenKeyfilePath &path, dialog.GetSelectedSecurityTokenKeyfilePaths()) + foreach (const TokenKeyfilePath &path, dialog.GetSelectedSecurityTokenKeyfilePaths()) { Keyfiles->push_back (make_shared (wstring (path))); } diff --git a/src/Main/Forms/WaitDialog.cpp b/src/Main/Forms/WaitDialog.cpp index 795d7763..c2e0be96 100644 --- a/src/Main/Forms/WaitDialog.cpp +++ b/src/Main/Forms/WaitDialog.cpp @@ -10,6 +10,7 @@ #include "Volume/EncryptionModeXTS.h" #include "Main/GraphicUserInterface.h" #include "Common/SecurityToken.h" +#include "Common/IccDataExtractor.h" #include "WaitDialog.h" namespace VeraCrypt @@ -101,6 +102,14 @@ namespace VeraCrypt VC_CONVERT_EXCEPTION (CipherException); 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); + throw *ex; } } diff --git a/src/Main/GraphicUserInterface.cpp b/src/Main/GraphicUserInterface.cpp index ba5c4e50..c76f1886 100644 --- a/src/Main/GraphicUserInterface.cpp +++ b/src/Main/GraphicUserInterface.cpp @@ -193,6 +193,7 @@ namespace VeraCrypt options->Kdf, false, options->Keyfiles, + options->EMVOption, options->Protection, options->ProtectionPassword, options->ProtectionPim, @@ -221,6 +222,7 @@ namespace VeraCrypt options->Kdf, false, options->Keyfiles, + options->EMVOption, options->Protection, options->ProtectionPassword, options->ProtectionPim, @@ -315,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); + ReEncryptHeaderThreadRoutine routine(newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Pim, normalVolumeMountOptions.Keyfiles, normalVolumeMountOptions.EMVOption); ExecuteWaitThreadRoutine (parent, &routine); @@ -324,7 +326,7 @@ namespace VeraCrypt if (hiddenVolume) { // Re-encrypt hidden volume header - ReEncryptHeaderThreadRoutine hiddenRoutine(newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Pim, hiddenVolumeMountOptions.Keyfiles); + ReEncryptHeaderThreadRoutine hiddenRoutine(newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Pim, hiddenVolumeMountOptions.Keyfiles, hiddenVolumeMountOptions.EMVOption); ExecuteWaitThreadRoutine (parent, &hiddenRoutine); } @@ -677,11 +679,21 @@ namespace VeraCrypt return true; } - void GraphicUserInterface::ListSecurityTokenKeyfiles () const + void GraphicUserInterface::ListTokenKeyfiles () const { SecurityTokenKeyfilesDialog dialog (nullptr); dialog.ShowModal(); } + void GraphicUserInterface::ListSecurityTokenKeyfiles () const + { + SecurityTokenKeyfilesDialog dialog (nullptr); + dialog.ShowModal(); + } + void GraphicUserInterface::ListEMVTokenKeyfiles () const + { + SecurityTokenKeyfilesDialog dialog (nullptr); + dialog.ShowModal(); + } #ifdef TC_MACOSX void GraphicUserInterface::MacOpenFiles (const wxArrayString &fileNames) @@ -1456,6 +1468,7 @@ namespace VeraCrypt options.Kdf, options.TrueCryptMode, options.Keyfiles, + options.EMVOption, options.Protection, options.ProtectionPassword, options.ProtectionPim, @@ -1488,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); + ReEncryptHeaderThreadRoutine routine(newHeaderBuffer, volume->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVOption); ExecuteWaitThreadRoutine (parent, &routine); @@ -1569,7 +1582,7 @@ namespace VeraCrypt backupFile.ReadAt (headerBuffer, layout->GetType() == VolumeType::Hidden ? layout->GetHeaderSize() : 0); // Decrypt header - shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password); + shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVOption); Pkcs5KdfList keyDerivationFunctions = layout->GetSupportedKeyDerivationFunctions(options.TrueCryptMode); EncryptionAlgorithmList encryptionAlgorithms = layout->GetSupportedEncryptionAlgorithms(); EncryptionModeList encryptionModes = layout->GetSupportedEncryptionModes(); @@ -1603,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); + ReEncryptHeaderThreadRoutine routine(newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVOption); ExecuteWaitThreadRoutine (parent, &routine); @@ -1619,7 +1632,7 @@ namespace VeraCrypt if (decryptedLayout->HasBackupHeader()) { // Re-encrypt backup volume header - ReEncryptHeaderThreadRoutine backupRoutine(newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles); + ReEncryptHeaderThreadRoutine backupRoutine(newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, options.EMVOption); ExecuteWaitThreadRoutine (parent, &backupRoutine); diff --git a/src/Main/GraphicUserInterface.h b/src/Main/GraphicUserInterface.h index 06ea6772..e50c6386 100644 --- a/src/Main/GraphicUserInterface.h +++ b/src/Main/GraphicUserInterface.h @@ -63,7 +63,9 @@ namespace VeraCrypt virtual void InsertToListCtrl (wxListCtrl *listCtrl, long itemIndex, const vector &itemFields, int imageIndex = -1, void *itemDataPtr = nullptr) const; virtual bool IsInBackgroundMode () const { return BackgroundMode; } virtual bool IsTheOnlyTopLevelWindow (const wxWindow *window) const; - virtual void ListSecurityTokenKeyfiles () const; + virtual void ListTokenKeyfiles () const; + virtual void ListSecurityTokenKeyfiles () const; + virtual void ListEMVTokenKeyfiles () const; virtual VolumeInfoList MountAllDeviceHostedVolumes (MountOptions &options) const; virtual shared_ptr MountVolume (MountOptions &options) const; virtual void MoveListCtrlItem (wxListCtrl *listCtrl, long itemIndex, long newItemIndex) const; diff --git a/src/Main/TextUserInterface.cpp b/src/Main/TextUserInterface.cpp index ec3ed531..f4f73d7f 100644 --- a/src/Main/TextUserInterface.cpp +++ b/src/Main/TextUserInterface.cpp @@ -21,7 +21,9 @@ #endif #include +#include "Common/Token.h" #include "Common/SecurityToken.h" +#include "Common/EMVToken.h" #include "Core/RandomNumberGenerator.h" #include "Application.h" #include "TextUserInterface.h" @@ -312,6 +314,7 @@ namespace VeraCrypt kdf, false, options->Keyfiles, + true, options->Protection, options->ProtectionPassword, options->ProtectionPim, @@ -337,6 +340,7 @@ namespace VeraCrypt kdf, false, options->Keyfiles, + true, options->Protection, options->ProtectionPassword, options->ProtectionPim, @@ -407,14 +411,14 @@ namespace VeraCrypt // Re-encrypt volume header SecureBuffer newHeaderBuffer (normalVolume->GetLayout()->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Pim, normalVolumeMountOptions.Keyfiles); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, normalVolume->GetHeader(), normalVolumeMountOptions.Password, normalVolumeMountOptions.Pim, normalVolumeMountOptions.Keyfiles, true); backupFile.Write (newHeaderBuffer); if (hiddenVolume) { // Re-encrypt hidden volume header - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Pim, hiddenVolumeMountOptions.Keyfiles); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, hiddenVolume->GetHeader(), hiddenVolumeMountOptions.Password, hiddenVolumeMountOptions.Pim, hiddenVolumeMountOptions.Keyfiles, true); } else { @@ -482,7 +486,7 @@ namespace VeraCrypt try { keyfiles.reset (new KeyfileList); - volume = Core->OpenVolume (volumePath, Preferences.DefaultMountOptions.PreserveTimestamps, password, pim, kdf, truecryptMode, keyfiles); + volume = Core->OpenVolume (volumePath, Preferences.DefaultMountOptions.PreserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, true); } catch (PasswordException&) { @@ -492,7 +496,7 @@ namespace VeraCrypt } if (!volume.get()) - volume = Core->OpenVolume (volumePath, Preferences.DefaultMountOptions.PreserveTimestamps, password, pim, kdf, truecryptMode, keyfiles); + volume = Core->OpenVolume (volumePath, Preferences.DefaultMountOptions.PreserveTimestamps, password, pim, kdf, truecryptMode, keyfiles, true); } catch (PasswordException &e) { @@ -527,7 +531,7 @@ namespace VeraCrypt RandomNumberGenerator::SetEnrichedByUserStatus (false); UserEnrichRandomPool(); - Core->ChangePassword (volume, newPassword, newPim, newKeyfiles, + Core->ChangePassword (volume, newPassword, newPim, newKeyfiles, true, newHash ? Pkcs5Kdf::GetAlgorithm (*newHash, false) : shared_ptr ()); ShowInfo ("PASSWORD_CHANGED"); @@ -911,6 +915,7 @@ namespace VeraCrypt wxLongLong startTime = wxGetLocalTimeMillis(); VolumeCreator creator; + options->EMVOption = true; creator.CreateVolume (options); bool volumeCreated = false; @@ -1024,7 +1029,7 @@ namespace VeraCrypt foreach_ref (const Keyfile &keyfile, *keyfiles) { - SecurityToken::DeleteKeyfile (SecurityTokenKeyfilePath (FilePath (keyfile))); + SecurityToken::DeleteKeyfile (TokenKeyfilePath (FilePath (keyfile))); } } @@ -1055,10 +1060,10 @@ namespace VeraCrypt if (keyfilePath.empty()) throw UserAbort (SRC_POS); - SecurityTokenKeyfile tokenKeyfile (keyfilePath); + shared_ptr tokenKeyfile = Token::getTokenKeyfile(keyfilePath); vector keyfileData; - SecurityToken::GetKeyfileData (tokenKeyfile, keyfileData); + tokenKeyfile->GetKeyfileData (keyfileData); BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); @@ -1100,7 +1105,7 @@ namespace VeraCrypt void TextUserInterface::ImportSecurityTokenKeyfiles () const { - list tokens = SecurityToken::GetAvailableTokens(); + list > tokens = Token::GetAvailableTokens(); if (tokens.empty()) throw_err (LangString ["NO_TOKENS_FOUND"]); @@ -1109,19 +1114,19 @@ namespace VeraCrypt if (tokens.size() == 1) { - slotId = tokens.front().SlotId; + slotId = tokens.front()->SlotId; } else { - foreach (const SecurityTokenInfo &token, tokens) + foreach (const shared_ptr &token, tokens) { wstringstream tokenLabel; - tokenLabel << L"[" << token.SlotId << L"] " << LangString["TOKEN_SLOT_ID"].c_str() << L" " << token.SlotId << L" " << token.Label; + tokenLabel << L"[" << token->SlotId << L"] " << LangString["TOKEN_SLOT_ID"].c_str() << L" " << token->SlotId << L" " << token->Label; ShowInfo (tokenLabel.str()); } - slotId = (CK_SLOT_ID) AskSelection (tokens.back().SlotId, tokens.front().SlotId); + slotId = (CK_SLOT_ID) AskSelection (tokens.back()->SlotId, tokens.front()->SlotId); } shared_ptr keyfiles; @@ -1225,14 +1230,30 @@ namespace VeraCrypt } } - void TextUserInterface::ListSecurityTokenKeyfiles () const + void TextUserInterface::ListTokenKeyfiles () const { - foreach (const SecurityTokenKeyfile &keyfile, SecurityToken::GetAvailableKeyfiles()) + foreach (const shared_ptr keyfile, Token::GetAvailableKeyfiles(true)) { - ShowString (wstring (SecurityTokenKeyfilePath (keyfile))); + ShowString (wstring (TokenKeyfilePath (*keyfile))); ShowString (L"\n"); } } + void TextUserInterface::ListSecurityTokenKeyfiles () const + { + foreach (const TokenKeyfile &keyfile, SecurityToken::GetAvailableKeyfiles()) + { + ShowString (wstring (TokenKeyfilePath (keyfile))); + ShowString (L"\n"); + } + } + void TextUserInterface::ListEMVTokenKeyfiles () const + { + foreach (const TokenKeyfile &keyfile, EMVToken::GetAvailableKeyfiles()) + { + ShowString (wstring (TokenKeyfilePath (keyfile))); + ShowString (L"\n"); + } + } VolumeInfoList TextUserInterface::MountAllDeviceHostedVolumes (MountOptions &options) const { @@ -1523,6 +1544,7 @@ namespace VeraCrypt kdf, false, options.Keyfiles, + true, options.Protection, options.ProtectionPassword, options.ProtectionPim, @@ -1550,7 +1572,7 @@ namespace VeraCrypt // Re-encrypt volume header SecureBuffer newHeaderBuffer (volume->GetLayout()->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, volume->GetHeader(), options.Password, options.Pim, options.Keyfiles); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, volume->GetHeader(), options.Password, options.Pim, options.Keyfiles, true); // Write volume header int headerOffset = volume->GetLayout()->GetHeaderOffset(); @@ -1627,7 +1649,7 @@ namespace VeraCrypt backupFile.ReadAt (headerBuffer, layout->GetType() == VolumeType::Hidden ? layout->GetHeaderSize() : 0); // Decrypt header - shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password); + shared_ptr passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, true); if (layout->GetHeader()->Decrypt (headerBuffer, *passwordKey, options.Pim, kdf, false, layout->GetSupportedKeyDerivationFunctions(false), layout->GetSupportedEncryptionAlgorithms(), layout->GetSupportedEncryptionModes())) { decryptedLayout = layout; @@ -1652,7 +1674,7 @@ namespace VeraCrypt // Re-encrypt volume header SecureBuffer newHeaderBuffer (decryptedLayout->GetHeaderSize()); - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, true); // Write volume header int headerOffset = decryptedLayout->GetHeaderOffset(); @@ -1666,7 +1688,7 @@ namespace VeraCrypt if (decryptedLayout->HasBackupHeader()) { // Re-encrypt backup volume header - Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles); + Core->ReEncryptVolumeHeaderWithNewSalt (newHeaderBuffer, decryptedLayout->GetHeader(), options.Password, options.Pim, options.Keyfiles, true); // Write backup volume header headerOffset = decryptedLayout->GetBackupHeaderOffset(); diff --git a/src/Main/TextUserInterface.h b/src/Main/TextUserInterface.h index 14eb2c0e..5e64aac7 100644 --- a/src/Main/TextUserInterface.h +++ b/src/Main/TextUserInterface.h @@ -51,7 +51,9 @@ namespace VeraCrypt virtual bool Initialize (int &argc, wxChar **argv) { return wxAppBase::Initialize(argc, argv); } #endif virtual void InitSecurityTokenLibrary () const; - virtual void ListSecurityTokenKeyfiles () const; + virtual void ListTokenKeyfiles () const; + virtual void ListSecurityTokenKeyfiles () const; + virtual void ListEMVTokenKeyfiles () const; virtual VolumeInfoList MountAllDeviceHostedVolumes (MountOptions &options) const; virtual shared_ptr MountVolume (MountOptions &options) const; virtual bool OnInit (); diff --git a/src/Main/UserInterface.cpp b/src/Main/UserInterface.cpp index 1a237bbe..132ad0e0 100644 --- a/src/Main/UserInterface.cpp +++ b/src/Main/UserInterface.cpp @@ -24,6 +24,7 @@ #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" @@ -436,6 +437,27 @@ namespace VeraCrypt return LangString["SECURITY_TOKEN_ERROR"] + L":\n\n" + StringConverter::ToWide (errorString); } + + // PCSC Exception + if (dynamic_cast (&ex)) + { + string errorString = string (dynamic_cast (ex)); + + if (LangString.Exists (errorString)) + return LangString[errorString]; + + 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] = ' '; + } + } + return LangString["PCSC_ERROR"] + L":\n\n" + StringConverter::ToWide (errorString); + } + // Other library exceptions return ExceptionTypeToString (typeid (ex)); } @@ -479,6 +501,12 @@ 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"]); #if defined (TC_LINUX) EX2MSG (TerminalNotFound, LangString["LINUX_EX2MSG_TERMINALNOTFOUND"]); @@ -1122,7 +1150,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 security token. See also command --list-token-keyfiles.\n" + " Export a keyfile from a token keyfile. See also command --list-token-keyfiles.\n" "\n" "--import-token-keyfiles\n" " Import keyfiles to a security token. See also option --token-lib.\n" @@ -1134,9 +1162,15 @@ namespace VeraCrypt " output option (-v). See below for description of MOUNTED_VOLUME.\n" "\n" "--list-token-keyfiles\n" - " Display a list of all available security token keyfiles. See also command\n" + " Display a list of all available token keyfiles. See also command\n" " --import-token-keyfiles.\n" - "\n" + "\n""--list-securitytoken-keyfiles\n" + " Display a list of all available security token keyfiles. See also command\n" + " --import-token-keyfiles.\n" + "\n" + "\n""--list-emvtoken-keyfiles\n" + " Display a list of all available emv token keyfiles. See also command\n" + "\n" "--mount[=VOLUME_PATH]\n" " Mount a volume. Volume path and other options are requested from the user\n" " if not specified on command line.\n" @@ -1199,9 +1233,12 @@ namespace VeraCrypt " used (non-recursively). Multiple keyfiles must be separated by comma.\n" " Use double comma (,,) to specify a comma contained in keyfile's name.\n" " Keyfile stored on a security token must be specified as\n" - " token://slot/SLOT_NUMBER/file/FILENAME. An empty keyfile (-k \"\") disables\n" + " token://slot/SLOT_NUMBER/file/FILENAME for a security token keyfile\n" + " and emv://slot/SLOT_NUMBER for an EMV token keyfile.\n" + " An empty keyfile (-k \"\") disables\n" " interactive requests for keyfiles. See also options --import-token-keyfiles,\n" - " --list-token-keyfiles, --new-keyfiles, --protection-keyfiles.\n" + " --list-token-keyfiles, --list-securitytoken-keyfiles, --list-emvtoken-keyfiles,\n" + " --new-keyfiles, --protection-keyfiles.\n" "\n" "--load-preferences\n" " Load user preferences.\n" @@ -1364,10 +1401,18 @@ namespace VeraCrypt ImportSecurityTokenKeyfiles(); return true; - case CommandId::ListSecurityTokenKeyfiles: - ListSecurityTokenKeyfiles(); + case CommandId::ListTokenKeyfiles: + ListTokenKeyfiles(); return true; + case CommandId::ListSecurityTokenKeyfiles: + ListSecurityTokenKeyfiles(); + return true; + + case CommandId::ListEMVTokenKeyfiles: + ListEMVTokenKeyfiles(); + return true; + case CommandId::ListVolumes: if (Preferences.Verbose) DisplayVolumeProperties (cmdLine.ArgVolumes); @@ -1648,6 +1693,14 @@ namespace VeraCrypt VC_CONVERT_EXCEPTION (CipherException); 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); + throw *ex; } } diff --git a/src/Main/UserInterface.h b/src/Main/UserInterface.h index 8c8cca7b..4b628235 100644 --- a/src/Main/UserInterface.h +++ b/src/Main/UserInterface.h @@ -56,7 +56,9 @@ namespace VeraCrypt virtual void Init (); virtual void InitSecurityTokenLibrary () const = 0; virtual void ListMountedVolumes (const VolumeInfoList &volumes) const; + virtual void ListTokenKeyfiles () const = 0; virtual void ListSecurityTokenKeyfiles () const = 0; + virtual void ListEMVTokenKeyfiles () const = 0; virtual shared_ptr MountVolume (MountOptions &options) const; virtual shared_ptr MountVolumeThread (MountOptions &options) const { return Core->MountVolume (options);} virtual VolumeInfoList MountAllDeviceHostedVolumes (MountOptions &options) const; diff --git a/src/Main/UserPreferences.cpp b/src/Main/UserPreferences.cpp index db54b4a4..d5b37bab 100644 --- a/src/Main/UserPreferences.cpp +++ b/src/Main/UserPreferences.cpp @@ -79,6 +79,7 @@ namespace VeraCrypt TC_CONFIG_SET (CloseBackgroundTaskOnNoVolumes); TC_CONFIG_SET (CloseExplorerWindowsOnDismount); TC_CONFIG_SET (CloseSecurityTokenSessionsAfterMount); + TC_CONFIG_SET (ActivateEMVOption); TC_CONFIG_SET (DisableKernelEncryptionModeWarning); TC_CONFIG_SET (DismountOnInactivity); TC_CONFIG_SET (DismountOnLogOff); @@ -197,6 +198,7 @@ namespace VeraCrypt TC_CONFIG_ADD (CloseBackgroundTaskOnNoVolumes); TC_CONFIG_ADD (CloseExplorerWindowsOnDismount); TC_CONFIG_ADD (CloseSecurityTokenSessionsAfterMount); + TC_CONFIG_ADD (ActivateEMVOption); TC_CONFIG_ADD (DisableKernelEncryptionModeWarning); TC_CONFIG_ADD (DismountOnInactivity); TC_CONFIG_ADD (DismountOnLogOff); diff --git a/src/Main/UserPreferences.h b/src/Main/UserPreferences.h index 96faf8a2..bc9cc0c7 100644 --- a/src/Main/UserPreferences.h +++ b/src/Main/UserPreferences.h @@ -31,6 +31,7 @@ namespace VeraCrypt CloseBackgroundTaskOnNoVolumes (true), CloseExplorerWindowsOnDismount (true), CloseSecurityTokenSessionsAfterMount (false), + ActivateEMVOption (false), DisableKernelEncryptionModeWarning (false), DismountOnInactivity (false), DismountOnLogOff (true), @@ -72,6 +73,7 @@ namespace VeraCrypt bool CloseBackgroundTaskOnNoVolumes; bool CloseExplorerWindowsOnDismount; bool CloseSecurityTokenSessionsAfterMount; + bool ActivateEMVOption; bool DisableKernelEncryptionModeWarning; bool DismountOnInactivity; bool DismountOnLogOff; diff --git a/src/Makefile b/src/Makefile index 98b3dd1a..53e460b6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -190,6 +190,10 @@ 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 + # GNU GCC version 11 and higher compile with -std=gnu++17 by default # which breaks "byte" definitions in Crypto++ library. So set diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index 5a7e40fe..a7552411 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -954,6 +954,7 @@ void LoadSettingsAndCheckModified (HWND hwndDlg, BOOL bOnlyCheckModified, BOOL* } ConfigReadCompareInt ("CloseSecurityTokenSessionsAfterMount", 0, &CloseSecurityTokenSessionsAfterMount, bOnlyCheckModified, pbSettingsModified); + ConfigReadCompareInt ("ActivateEMVOption", 0, &ActivateEMVOption, bOnlyCheckModified, pbSettingsModified); if (IsHiddenOSRunning()) ConfigReadCompareInt ("HiddenSystemLeakProtNotifStatus", TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE, &HiddenSysLeakProtectionNotificationStatus, bOnlyCheckModified, pbSettingsModified); @@ -1126,6 +1127,7 @@ void SaveSettings (HWND hwndDlg) } ConfigWriteInt ("CloseSecurityTokenSessionsAfterMount", CloseSecurityTokenSessionsAfterMount); + ConfigWriteInt ("ActivateEMVOption", ActivateEMVOption); // Hotkeys ConfigWriteInt ("HotkeyModAutoMountDevices", Hotkeys[HK_AUTOMOUNT_DEVICES].vKeyModifiers); @@ -5401,7 +5403,7 @@ ret: bCacheInDriver = bCacheInDriverDefault; if (status && CloseSecurityTokenSessionsAfterMount && !MultipleMountOperationInProgress) - SecurityToken::CloseAllSessions(); + SecurityToken::CloseAllSessions(); // TODO Use Token return status; } @@ -5903,7 +5905,7 @@ static BOOL MountAllDevicesThreadCode (HWND hwndDlg, BOOL bPasswordPrompt) } if (status && CloseSecurityTokenSessionsAfterMount) - SecurityToken::CloseAllSessions(); + SecurityToken::CloseAllSessions(); // TODO Use Token ret: MultipleMountOperationInProgress = FALSE; @@ -7653,7 +7655,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa if (bWipeCacheOnAutoDismount) { DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - SecurityToken::CloseAllSessions(); + SecurityToken::CloseAllSessions(); // TODO Use Token } DismountAll (hwndDlg, bForceAutoDismount, TRUE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); @@ -7692,7 +7694,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa if (bWipeCacheOnAutoDismount) { DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - SecurityToken::CloseAllSessions(); + SecurityToken::CloseAllSessions(); // TODO Use Token } DismountAll (hwndDlg, bForceAutoDismount, TRUE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); @@ -7749,7 +7751,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa if (bWipeCacheOnAutoDismount) { DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - SecurityToken::CloseAllSessions(); + SecurityToken::CloseAllSessions(); // TODO Use Token } DismountAll (hwndDlg, bForceAutoDismount, FALSE, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY); @@ -8648,7 +8650,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa WaitCursor(); finally_do ({ NormalCursor(); }); - SecurityToken::CloseAllSessions(); + SecurityToken::CloseAllSessions(); // TODO Use Token } InfoBalloon (NULL, "ALL_TOKEN_SESSIONS_CLOSED", hwndDlg); @@ -9637,7 +9639,7 @@ void ExtractCommandLine (HWND hwndDlg, wchar_t *lpszCommandLine) case OptionTokenPin: { - wchar_t szTmp[SecurityToken::MaxPasswordLength + 1] = {0}; + wchar_t szTmp[SecurityToken::MaxPasswordLength + 1] = {0}; // TODO Use Token if (GetArgumentValue (lpszCommandLineArgs, &i, nNoCommandLineArgs, szTmp, ARRAYSIZE (szTmp)) == HAS_ARGUMENT) { if (0 == WideCharToMultiByte (CP_UTF8, 0, szTmp, -1, CmdTokenPin, TC_MAX_PATH, nullptr, nullptr)) @@ -10303,7 +10305,7 @@ void DismountIdleVolumes () if (bWipeCacheOnAutoDismount) { DeviceIoControl (hDriver, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0, &dwResult, NULL); - SecurityToken::CloseAllSessions(); + SecurityToken::CloseAllSessions(); // TODO Use Token } } } @@ -10632,7 +10634,7 @@ BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOO burn (&VolumeTrueCryptMode, sizeof (VolumeTrueCryptMode)); if (bRet && CloseSecurityTokenSessionsAfterMount) - SecurityToken::CloseAllSessions(); + SecurityToken::CloseAllSessions(); // TODO Use Token return bRet; } @@ -10810,7 +10812,7 @@ static void HandleHotKey (HWND hwndDlg, WPARAM wParam) break; case HK_CLOSE_SECURITY_TOKEN_SESSIONS: - SecurityToken::CloseAllSessions(); + SecurityToken::CloseAllSessions(); // TODO Use Token InfoBalloon (NULL, "ALL_TOKEN_SESSIONS_CLOSED", hwndDlg); @@ -11879,6 +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); SetWindowTextW (GetDlgItem (hwndDlg, IDT_PKCS11_LIB_HELP), GetString("PKCS11_LIB_LOCATION_HELP")); @@ -11901,7 +11904,7 @@ static BOOL CALLBACK SecurityTokenPreferencesDlgProc (HWND hwndDlg, UINT msg, WP { try { - SecurityToken::CloseLibrary(); + SecurityToken::CloseLibrary(); // TODO Use Token } catch (...) { } @@ -11921,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); WaitCursor (); SaveSettings (hwndDlg); NormalCursor (); diff --git a/src/Mount/Mount.rc b/src/Mount/Mount.rc index a524d9f0..d6d766c5 100644 --- a/src/Mount/Mount.rc +++ b/src/Mount/Mount.rc @@ -270,7 +270,7 @@ BEGIN GROUPBOX "Shortcut",IDT_ASSIGN_HOTKEY,7,127,375,53 END -IDD_TOKEN_PREFERENCES DIALOGEX 0, 0, 316, 199 +IDD_TOKEN_PREFERENCES DIALOGEX 0, 0, 316, 229 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "VeraCrypt - Security Token Preferences" FONT 8, "MS Shell Dlg", 400, 0, 0x1 @@ -280,10 +280,12 @@ 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 - DEFPUSHBUTTON "OK",IDOK,205,178,50,14 - PUSHBUTTON "Cancel",IDCANCEL,259,178,50,14 + CONTROL "&Activate EMV Option",IDC_ACTIVATE_EMV_OPTION,"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 GROUPBOX "Security Options",IDT_SECURITY_OPTIONS,7,140,302,30 + GROUPBOX "EMV Options",IDT_EMV_OPTIONS,7,172,302,30 LTEXT "",IDT_PKCS11_LIB_HELP,16,63,286,65 END diff --git a/src/Mount/Mount.vcxproj b/src/Mount/Mount.vcxproj index 1c55193a..5aeb6722 100644 --- a/src/Mount/Mount.vcxproj +++ b/src/Mount/Mount.vcxproj @@ -236,7 +236,7 @@ copy Debug\VeraCrypt.exe "..\Debug\Setup Files" >NUL: 4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCrypt.exe false mpr.dll;%(DelayLoadDLLs) @@ -325,7 +325,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" >NUL: 4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCrypt.exe false mpr.dll;%(DelayLoadDLLs) @@ -415,7 +415,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" >NUL: 4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCrypt.exe false mpr.dll;%(DelayLoadDLLs) @@ -462,7 +462,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" >NUL: 4057;4100;4127;4201;4701;4706;4131;%(DisableSpecificWarnings) - ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies) + ..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies) $(OutDir)VeraCrypt.exe false mpr.dll;%(DelayLoadDLLs) @@ -533,6 +533,10 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" >NUL: + + + + @@ -602,6 +606,10 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt-x64.exe" >NUL: + + + + diff --git a/src/Mount/Mount.vcxproj.filters b/src/Mount/Mount.vcxproj.filters index e1dfd652..033a76ff 100644 --- a/src/Mount/Mount.vcxproj.filters +++ b/src/Mount/Mount.vcxproj.filters @@ -108,6 +108,18 @@ Source Files\Setup + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + + + Source Files\Common + @@ -211,6 +223,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/src/Mount/Resource.h b/src/Mount/Resource.h index f7b3ff05..69f99080 100644 --- a/src/Mount/Resource.h +++ b/src/Mount/Resource.h @@ -199,6 +199,8 @@ #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 IDT_EMV_OPTIONS 1180 #define IDM_HELP 40001 #define IDM_ABOUT 40002 #define IDM_UNMOUNT_VOLUME 40003 diff --git a/src/Volume/Keyfile.cpp b/src/Volume/Keyfile.cpp index d171458c..9527fd11 100644 --- a/src/Volume/Keyfile.cpp +++ b/src/Volume/Keyfile.cpp @@ -12,13 +12,13 @@ #include "Platform/Serializer.h" #include "Common/SecurityToken.h" +#include "Common/EMVToken.h" #include "Crc32.h" #include "Keyfile.h" #include "VolumeException.h" - namespace VeraCrypt { - void Keyfile::Apply (const BufferPtr &pool) const + void Keyfile::Apply (const BufferPtr &pool, bool EMVOption) const { if (Path.IsDirectory()) throw ParameterIncorrect (SRC_POS); @@ -32,61 +32,57 @@ namespace VeraCrypt SecureBuffer keyfileBuf (File::GetOptimalReadSize()); - if (SecurityToken::IsKeyfilePathValid (Path)) - { - // Apply keyfile generated by a security token - vector keyfileData; - SecurityToken::GetKeyfileData (SecurityTokenKeyfile (wstring (Path)), keyfileData); + std::wcout << wstring (Path) << std::endl; + if (Token::IsKeyfilePathValid (Path, EMVOption)) { + // Apply keyfile generated by a security token + vector keyfileData; + Token::getTokenKeyfile(wstring(Path))->GetKeyfileData(keyfileData); - if (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 (++totalLength >= MaxProcessedLength) - break; - } + if (poolPos >= pool.Size()) + poolPos = 0; - burn (&keyfileData.front(), keyfileData.size()); - goto done; - } + if (++totalLength >= MaxProcessedLength) + break; + } - 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]); + burn(&keyfileData.front(), keyfileData.size()); + goto done; + } - pool[poolPos++] += (byte) (crc >> 24); - pool[poolPos++] += (byte) (crc >> 16); - pool[poolPos++] += (byte) (crc >> 8); - pool[poolPos++] += (byte) crc; + file.Open (Path, File::OpenRead, File::ShareRead); - if (poolPos >= pool.Size()) - poolPos = 0; + 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 >= MaxProcessedLength) - goto done; - } - } -done: if (totalLength < MinProcessedLength) throw InsufficientData (SRC_POS, Path); } - shared_ptr Keyfile::ApplyListToPassword (shared_ptr keyfiles, shared_ptr password) + shared_ptr Keyfile::ApplyListToPassword (shared_ptr keyfiles, shared_ptr password, bool EMVOption) { if (!password) password.reset (new VolumePassword); @@ -143,7 +139,7 @@ done: // Apply all keyfiles foreach_ref (const Keyfile &k, keyfilesExp) { - k.Apply (keyfilePool); + k.Apply (keyfilePool, EMVOption); } newPassword->Set (keyfilePool); diff --git a/src/Volume/Keyfile.h b/src/Volume/Keyfile.h index 04674178..bf0a524b 100644 --- a/src/Volume/Keyfile.h +++ b/src/Volume/Keyfile.h @@ -29,7 +29,7 @@ namespace VeraCrypt virtual ~Keyfile () { }; operator FilesystemPath () const { return Path; } - static shared_ptr ApplyListToPassword (shared_ptr keyfiles, shared_ptr password); + static shared_ptr ApplyListToPassword (shared_ptr keyfiles, shared_ptr password, bool EMVOption = false); static shared_ptr DeserializeList (shared_ptr stream, const string &name); static void SerializeList (shared_ptr stream, const string &name, shared_ptr keyfiles); static bool WasHiddenFilePresentInKeyfilePath() { bool r = HiddenFileWasPresentInKeyfilePath; HiddenFileWasPresentInKeyfilePath = false; return r; } @@ -38,7 +38,7 @@ namespace VeraCrypt static const size_t MaxProcessedLength = 1024 * 1024; protected: - void Apply (const BufferPtr &pool) const; + void Apply (const BufferPtr &pool, bool EMVOption) const; static bool HiddenFileWasPresentInKeyfilePath; diff --git a/src/Volume/Volume.cpp b/src/Volume/Volume.cpp index c4a21b3e..6fb906b6 100644 --- a/src/Volume/Volume.cpp +++ b/src/Volume/Volume.cpp @@ -71,7 +71,7 @@ namespace VeraCrypt return EA->GetMode(); } - void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) + void Volume::Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf, shared_ptr protectionKeyfiles, bool sharedAccessAllowed, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) { make_shared_auto (File, file); @@ -102,10 +102,10 @@ namespace VeraCrypt throw; } - return Open (file, password, pim, kdf, truecryptMode, keyfiles, protection, protectionPassword, protectionPim, protectionKdf,protectionKeyfiles, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); + return Open (file, password, pim, kdf, truecryptMode, keyfiles, EMVOption, protection, protectionPassword, protectionPim, protectionKdf,protectionKeyfiles, volumeType, useBackupHeaders, partitionInSystemEncryptionScope); } - void Volume::Open (shared_ptr volumeFile, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf,shared_ptr protectionKeyfiles, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) + void Volume::Open (shared_ptr volumeFile, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection, shared_ptr protectionPassword, int protectionPim, shared_ptr protectionKdf,shared_ptr protectionKeyfiles, VolumeType::Enum volumeType, bool useBackupHeaders, bool partitionInSystemEncryptionScope) { if (!volumeFile) throw ParameterIncorrect (SRC_POS); @@ -121,7 +121,7 @@ namespace VeraCrypt try { VolumeHostSize = VolumeFile->Length(); - shared_ptr passwordKey = Keyfile::ApplyListToPassword (keyfiles, password); + shared_ptr passwordKey = Keyfile::ApplyListToPassword (keyfiles, password, EMVOption); bool skipLayoutV1Normal = false; @@ -249,6 +249,7 @@ namespace VeraCrypt protectedVolume.Open (VolumeFile, protectionPassword, protectionPim, protectionKdf, truecryptMode, protectionKeyfiles, + EMVOption, VolumeProtection::ReadOnly, shared_ptr (), 0, shared_ptr (),shared_ptr (), VolumeType::Hidden, diff --git a/src/Volume/Volume.h b/src/Volume/Volume.h index a743a161..85fdbe41 100644 --- a/src/Volume/Volume.h +++ b/src/Volume/Volume.h @@ -123,8 +123,8 @@ namespace VeraCrypt uint64 GetVolumeCreationTime () const { return Header->GetVolumeCreationTime(); } bool IsHiddenVolumeProtectionTriggered () const { return HiddenVolumeProtectionTriggered; } bool IsInSystemEncryptionScope () const { return SystemEncryption; } - void Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (),shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); - void Open (shared_ptr volumeFile, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); + void Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (),shared_ptr protectionKeyfiles = shared_ptr (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); + void Open (shared_ptr volumeFile, shared_ptr password, int pim, shared_ptr kdf, bool truecryptMode, shared_ptr keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr protectionPassword = shared_ptr (), int protectionPim = 0, shared_ptr protectionKdf = shared_ptr (), shared_ptr protectionKeyfiles = shared_ptr (), VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false); void ReadSectors (const BufferPtr &buffer, uint64 byteOffset); void ReEncryptHeader (bool backupHeader, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr newPkcs5Kdf); void WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset); diff --git a/src/Volume/Volume.make b/src/Volume/Volume.make index 91f40fb7..03e06eaa 100644 --- a/src/Volume/Volume.make +++ b/src/Volume/Volume.make @@ -96,11 +96,15 @@ OBJS += ../Crypto/kuznyechik_simd.o OBJSNOOPT += ../Crypto/jitterentropy-base.o0 +OBJS += ../Common/Token.o OBJS += ../Common/Crc.o +OBJS += ../Common/TLVParser.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 -- cgit v1.2.3