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 <d45.poubelle@gmail.com>
Co-authored-by: red4game <redemgaiming@gmail.com>
Co-authored-by: Brice.Namy <brice.namy@insa-rennes.fr>
Co-authored-by: vocthor <pieceo108@gmail.com>
Co-authored-by: vocthor <67202139+vocthor@users.noreply.github.com>
Co-authored-by: Andrei COCAN <andrei.cocan@insa-rennes.fr>
Co-authored-by: AndreiCocan <95496161+AndreiCocan@users.noreply.github.com>
Co-authored-by: francoisLEROUX <francois3443@gmail.com>
This commit is contained in:
mmauv 2023-06-28 22:51:43 +02:00 committed by GitHub
parent f4e109afcf
commit 502ab9112a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 2721 additions and 612 deletions

View File

@ -66,6 +66,7 @@ <h1>Table of Contents</h1>
</li><li><strong><a href="Hot%20Keys.html">Hot keys</a></strong>
</li><li><strong><a href="Keyfiles%20in%20VeraCrypt.html">Keyfiles</a></strong>
</li><li><strong><a href="Security%20Tokens%20%26%20Smart%20Cards.html">Security Tokens &amp; Smart Cards</a></strong>
</li><li><strong><a href="EMV%20Smart%20Cards.html">EMV Smart Cards</a></strong>
</li><li><strong><a href="Portable%20Mode.html">Portable Mode</a></strong>
</li><li><strong><a href="TrueCrypt%20Support.html">TrueCrypt Support</a></strong>
</li><li><strong><a href="Converting%20TrueCrypt%20volumes%20and%20partitions.html">Converting TrueCrypt Volumes &amp; Partitions</a></strong>

View File

@ -0,0 +1,87 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>
VeraCrypt - Free Open source disk encryption with strong security for the
Paranoid
</title>
<meta
name="description"
content="VeraCrypt is free open-source disk encryption software for Windows, Mac OS X and Linux. In case an attacker forces you to reveal the password, VeraCrypt provides plausible deniability. In contrast to file encryption, data encryption performed by VeraCrypt is real-time (on-the-fly), automatic, transparent, needs very little memory, and does not involve temporary unencrypted files."
/>
<meta name="keywords" content="encryption, security" />
<link href="styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div>
<a href="Documentation.html"
><img src="VeraCrypt128x128.png" alt="VeraCrypt"
/></a>
</div>
<div id="menu">
<ul>
<li><a href="Home.html">Home</a></li>
<li><a href="/code/">Source Code</a></li>
<li><a href="Downloads.html">Downloads</a></li>
<li><a class="active" href="Documentation.html">Documentation</a></li>
<li><a href="Donation.html">Donate</a></li>
<li>
<a
href="https://sourceforge.net/p/veracrypt/discussion/"
target="_blank"
>Forums</a
>
</li>
</ul>
</div>
<div>
<p>
<a href="Documentation.html">Documentation</a>
<img src="arrow_right.gif" alt=">>" style="margin-top: 5px" />
<a href="EMV%20Smart%20Cards.html">EMV Smart Cards</a>
</p>
</div>
<div class="wikidoc">
<h1>EMV Smart Cards</h1>
<div
style="
text-align: left;
margin-top: 19px;
margin-bottom: 19px;
padding-top: 0px;
padding-bottom: 0px;
"
>
<p>
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.
</p>
<p>
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.
</p>
<p>
For more technical information, please see the section
<em style="text-align: left">EMV Smart Cards</em> in the chapter
<a
href="Keyfiles%20in%20VeraCrypt.html"
style="text-align: left; color: #0080c0; text-decoration: none.html"
>
<em style="text-align: left">Keyfiles</em></a
>.
</p>
</div>
</div>
</body>
</html>

View File

@ -114,6 +114,25 @@ <h3 id="SmartCard" style="text-align:left; font-family:Arial,Helvetica,Verdana,s
Tools</em> &gt; <em style="text-align:left">Close All Security Token Sessions</em> or define and use a hotkey combination (<em style="text-align:left">Settings</em> &gt;
<em style="text-align:left">Hot Keys &gt; Close All Security Token Sessions</em>).</div>
<p>&nbsp;</p>
<h3 id="SmartCard" style="text-align:left; font-family:Arial,Helvetica,Verdana,sans-serif; font-weight:bold; margin-top:0px; font-size:13px; margin-bottom:4px">
EMV Smart Cards</h3>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
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 <em style="text-align:left">Add Token Files</em> (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.
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
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.</div>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
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.</div>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
Since the card is read-only, it is not possible to import or delete data. However, data used as keyfiles can be exported locally in any binary file. During the entire cryptographic process of mounting or creating a volume, the certificates and CPLC data are never stored anywhere
other than in the user's machine RAM. Once the process is complete, these RAM memory areas are rigorously erased.</div>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
It important to note that this feature is optional and disabled by default. It can be enabled in the <em style="text-align:left">Security Token Preferences</em> parameters by checking the box provided.</div>
<p>&nbsp;</p>
<h3 style="text-align:left; font-family:Arial,Helvetica,Verdana,sans-serif; font-weight:bold; margin-top:0px; font-size:13px; margin-bottom:4px">
Keyfile Search Path</h3>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">

View File

@ -1,81 +1,222 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>VeraCrypt - Free Open source disk encryption with strong security for the Paranoid</title>
<meta name="description" content="VeraCrypt is free open-source disk encryption software for Windows, Mac OS X and Linux. In case an attacker forces you to reveal the password, VeraCrypt provides plausible deniability. In contrast to file encryption, data encryption performed by VeraCrypt is real-time (on-the-fly), automatic, transparent, needs very little memory, and does not involve temporary unencrypted files."/>
<meta name="keywords" content="encryption, security"/>
<link href="styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>
VeraCrypt - Free Open source disk encryption with strong security for the
Paranoid
</title>
<meta
name="description"
content="VeraCrypt is free open-source disk encryption software for Windows, Mac OS X and Linux. In case an attacker forces you to reveal the password, VeraCrypt provides plausible deniability. In contrast to file encryption, data encryption performed by VeraCrypt is real-time (on-the-fly), automatic, transparent, needs very little memory, and does not involve temporary unencrypted files."
/>
<meta name="keywords" content="encryption, security" />
<link href="styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div>
<a href="Documentation.html"
><img src="VeraCrypt128x128.png" alt="VeraCrypt"
/></a>
</div>
<div>
<a href="Documentation.html"><img src="VeraCrypt128x128.png" alt="VeraCrypt"/></a>
</div>
<div id="menu">
<ul>
<li><a href="Home.html">Home</a></li>
<li><a href="/code/">Source Code</a></li>
<li><a href="Downloads.html">Downloads</a></li>
<li><a class="active" href="Documentation.html">Documentation</a></li>
<li><a href="Donation.html">Donate</a></li>
<li>
<a
href="https://sourceforge.net/p/veracrypt/discussion/"
target="_blank"
>Forums</a
>
</li>
</ul>
</div>
<div id="menu">
<ul>
<li><a href="Home.html">Home</a></li>
<li><a href="/code/">Source Code</a></li>
<li><a href="Downloads.html">Downloads</a></li>
<li><a class="active" href="Documentation.html">Documentation</a></li>
<li><a href="Donation.html">Donate</a></li>
<li><a href="https://sourceforge.net/p/veracrypt/discussion/" target="_blank">Forums</a></li>
</ul>
</div>
<div>
<p>
<a href="Documentation.html">Documentation</a>
<img src="arrow_right.gif" alt=">>" style="margin-top: 5px" />
<a href="Technical%20Details.html">Technical Details</a>
<img src="arrow_right.gif" alt=">>" style="margin-top: 5px" />
<a href="Keyfiles.html">Keyfiles</a>
</p>
</div>
<div>
<p>
<a href="Documentation.html">Documentation</a>
<img src="arrow_right.gif" alt=">>" style="margin-top: 5px">
<a href="Technical%20Details.html">Technical Details</a>
<img src="arrow_right.gif" alt=">>" style="margin-top: 5px">
<a href="Keyfiles.html">Keyfiles</a>
</p></div>
<div class="wikidoc">
<h1>Keyfiles</h1>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
<p>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 <a href="Random%20Number%20Generator.html">
<em>Random Number Generator</em></a>).</p>
<p>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).</p>
<p>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).</p>
<p>Keyfiles are processed and applied to a password using the following method:</p>
<ol>
<li>Let <em>P</em> be a VeraCrypt volume password supplied by user (may be empty)
</li><li>Let <em>KP</em> be the keyfile pool </li><li>Let <em>kpl</em> be the size of the keyfile pool <em>KP</em>, in bytes (64, i.e., 512 bits);
<p>kpl must be a multiple of the output size of a hash function H</p>
</li><li>Let <em>pl</em> be the length of the password <em>P</em>, in bytes (in the current version: 0 &le;
<em>pl</em> &le; 64) </li><li>if <em>kpl &gt; pl</em>, append (<em>kpl &ndash; pl</em>) zero bytes to the password
<em>P</em> (thus <em>pl = kpl</em>) </li><li>Fill the keyfile pool <em>KP</em> with <em>kpl</em> zero bytes. </li><li>For each keyfile perform the following steps:
<ol type="a">
<li>Set the position of the keyfile pool cursor to the beginning of the pool </li><li>Initialize the hash function <em>H</em> </li><li>Load all bytes of the keyfile one by one, and for each loaded byte perform the following steps:
<ol type="i">
<li>Hash the loaded byte using the hash function <em>H</em> without initializing the hash, to obtain an intermediate hash (state)
<em>M.</em> Do not finalize the hash (the state is retained for next round). </li><li>Divide the state <em>M</em> into individual bytes.<br>
For example, if the hash output size is 4 bytes, (<em>T</em><sub>0</sub> || <em>T</em><sub>1</sub> ||
<em>T</em><sub>2</sub> || <em>T</em><sub>3</sub>) = <em>M</em> </li><li>Write these bytes (obtained in step 7.c.ii) individually to the keyfile pool with the modulo 2<sup>8</sup> 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.
</li></ol>
</li></ol>
</li><li>Apply the content of the keyfile pool to the password <em>P</em> using the following method:
<ol type="a">
<li>Divide the password <em>P</em> into individual bytes <em>B</em><sub>0</sub>...<em>B</em><sub>pl-1</sub>.<br>
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).
</li><li>Divide the keyfile pool <em>KP</em> into individual bytes <em>G</em><sub>0</sub>...<em>G</em><sub>kpl-1</sub>
</li><li>For 0 &le; i &lt; kpl perform: Bi = Bi &oplus; Gi </li><li><em>P</em> = <em>B</em><sub>0</sub> || <em>B</em><sub>1</sub> || ... || <em>B</em><sub>pl-2</sub> ||
<em>B</em><sub>pl-1</sub> </li></ol>
</li><li>The password <em>P</em> (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 <a href="Header%20Key%20Derivation.html">
<em>Header Key Derivation, Salt, and Iteration Count</em></a> for more information.
</li></ol>
<p>The role of the hash function <em>H</em> is merely to perform diffusion [2]. CRC-32 is used as the hash function
<em>H</em>. 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).</p>
<p>&nbsp;</p>
<p><a href="Personal%20Iterations%20Multiplier%20%28PIM%29.html" style="text-align:left; color:#0080c0; text-decoration:none; font-weight:bold.html">Next Section &gt;&gt;</a></p>
</div>
</div><div class="ClearBoth"></div></body></html>
<div class="wikidoc">
<h1>Keyfiles</h1>
<div
style="
text-align: left;
margin-top: 19px;
margin-bottom: 19px;
padding-top: 0px;
padding-bottom: 0px;
"
>
<p>
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
<a href="Random%20Number%20Generator.html">
<em>Random Number Generator</em></a
>).
</p>
<p>
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).
</p>
<p>
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).
</p>
<p>
EMV-compliant smart cards' data can be used as keyfile, see chapter
<a
href="EMV%20Smart%20Cards.html"
style="text-align: left; color: #0080c0; text-decoration: none.html"
>
<em style="text-align: left">EMV Smart Cards</em></a
>.
</p>
<p>
Keyfiles are processed and applied to a password using the following
method:
</p>
<ol>
<li>
Let <em>P</em> be a VeraCrypt volume password supplied by user (may
be empty)
</li>
<li>Let <em>KP</em> be the keyfile pool</li>
<li>
Let <em>kpl</em> be the size of the keyfile pool <em>KP</em>, in
bytes (64, i.e., 512 bits);
<p>
kpl must be a multiple of the output size of a hash function H
</p>
</li>
<li>
Let <em>pl</em> be the length of the password <em>P</em>, in bytes
(in the current version: 0 &le; <em>pl</em> &le; 64)
</li>
<li>
if <em>kpl &gt; pl</em>, append (<em>kpl &ndash; pl</em>) zero bytes
to the password <em>P</em> (thus <em>pl = kpl</em>)
</li>
<li>
Fill the keyfile pool <em>KP</em> with <em>kpl</em> zero bytes.
</li>
<li>
For each keyfile perform the following steps:
<ol type="a">
<li>
Set the position of the keyfile pool cursor to the beginning of
the pool
</li>
<li>Initialize the hash function <em>H</em></li>
<li>
Load all bytes of the keyfile one by one, and for each loaded
byte perform the following steps:
<ol type="i">
<li>
Hash the loaded byte using the hash function
<em>H</em> without initializing the hash, to obtain an
intermediate hash (state) <em>M.</em> Do not finalize the
hash (the state is retained for next round).
</li>
<li>
Divide the state <em>M</em> into individual bytes.<br />
For example, if the hash output size is 4 bytes, (<em>T</em
><sub>0</sub> || <em>T</em><sub>1</sub> || <em>T</em
><sub>2</sub> || <em>T</em><sub>3</sub>) = <em>M</em>
</li>
<li>
Write these bytes (obtained in step 7.c.ii) individually to
the keyfile pool with the modulo 2<sup>8</sup> 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.
</li>
</ol>
</li>
</ol>
</li>
<li>
Apply the content of the keyfile pool to the password
<em>P</em> using the following method:
<ol type="a">
<li>
Divide the password <em>P</em> into individual bytes <em>B</em
><sub>0</sub>...<em>B</em><sub>pl-1</sub>.<br />
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).
</li>
<li>
Divide the keyfile pool <em>KP</em> into individual bytes
<em>G</em><sub>0</sub>...<em>G</em><sub>kpl-1</sub>
</li>
<li>For 0 &le; i &lt; kpl perform: Bi = Bi &oplus; Gi</li>
<li>
<em>P</em> = <em>B</em><sub>0</sub> || <em>B</em><sub>1</sub> ||
... || <em>B</em><sub>pl-2</sub> || <em>B</em><sub>pl-1</sub>
</li>
</ol>
</li>
<li>
The password <em>P</em> (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
<a href="Header%20Key%20Derivation.html">
<em>Header Key Derivation, Salt, and Iteration Count</em></a
>
for more information.
</li>
</ol>
<p>
The role of the hash function <em>H</em> is merely to perform
diffusion [2]. CRC-32 is used as the hash function <em>H</em>. 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).
</p>
<p>&nbsp;</p>
<p>
<a
href="Personal%20Iterations%20Multiplier%20%28PIM%29.html"
style="
text-align: left;
color: #0080c0;
text-decoration: none;
font-weight: bold.html;
"
>Next Section &gt;&gt;</a
>
</p>
</div>
</div>
<div class="ClearBoth"></div>
</body>
</html>

View File

@ -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 <SecurityTokenInfo> tokens;
list <shared_ptr<TokenInfo>> 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<TokenInfo> 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 <SecurityTokenKeyfile> &keyfiles)
static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector <shared_ptr<TokenKeyfile>> &keyfiles)
{
HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST);
LVITEMW lvItem;
@ -12291,18 +12292,18 @@ static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector <Securit
ListView_DeleteAllItems (tokenListControl);
foreach (const SecurityTokenKeyfile &keyfile, keyfiles)
foreach (const shared_ptr<TokenKeyfile> 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 <Securit
}
static list <SecurityTokenKeyfile> SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector <SecurityTokenKeyfile> &keyfiles)
static list <shared_ptr<TokenKeyfile>> SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector <shared_ptr<TokenKeyfile>> &keyfiles)
{
HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST);
list <SecurityTokenKeyfile> selectedKeyfiles;
list <shared_ptr<TokenKeyfile>> selectedKeyfiles;
int itemId = -1;
while ((itemId = ListView_GetNextItem (tokenListControl, itemId, LVIS_SELECTED)) != -1)
@ -12328,8 +12329,8 @@ static list <SecurityTokenKeyfile> SecurityTokenKeyfileDlgGetSelected (HWND hwnd
BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static list <SecurityTokenKeyfilePath> *selectedTokenKeyfiles;
static vector <SecurityTokenKeyfile> keyfiles;
static list <TokenKeyfilePath> *selectedTokenKeyfiles;
static vector <shared_ptr<TokenKeyfile>> keyfiles;
WORD lw = LOWORD (wParam);
@ -12337,7 +12338,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
{
case WM_INITDIALOG:
{
selectedTokenKeyfiles = (list <SecurityTokenKeyfilePath> *) lParam;
selectedTokenKeyfiles = (list <TokenKeyfilePath> *) 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<TokenKeyfile> &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<TokenKeyfile> &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<TokenKeyfile> &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles))
{
wchar_t keyfilePath[TC_MAX_PATH];
@ -12502,7 +12510,7 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
vector <byte> 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<TokenKeyfile> keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles))
{
SecurityToken::DeleteKeyfile (keyfile);
SecurityToken::DeleteKeyfile (dynamic_cast<SecurityTokenKeyfile&>(*keyfile.get()));
}
keyfiles = SecurityToken::GetAvailableKeyfiles();
keyfiles = Token::GetAvailableKeyfiles(ActivateEMVOption);
SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles);
}
catch (Exception &e)

View File

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

121
src/Common/EMVToken.cpp Normal file
View File

@ -0,0 +1,121 @@
#include "EMVToken.h"
#include "Platform/Finally.h"
#include "Platform/ForEach.h"
#include <vector>
#include <iostream>
#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<EMVTokenInfo>(new EMVTokenInfo());
wstring pathStr = path;
unsigned long slotId;
if (swscanf(pathStr.c_str(), TC_EMV_TOKEN_KEYFILE_URL_PREFIX TC_EMV_TOKEN_KEYFILE_URL_SLOT L"/%lu", &slotId) != 1)
throw InvalidEMVPath();
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 <byte>& 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<EMVTokenKeyfile> EMVToken::GetAvailableKeyfiles(unsigned long int* slotIdFilter, const wstring keyfileIdFilter) {
#ifdef TC_WINDOWS
EMVToken::extractor.InitLibrary();
#endif
vector <EMVTokenKeyfile> keyfiles;
unsigned long int nb = 0;
nb = EMVToken::extractor.GetReaders();
for(unsigned long int slotId = 0; slotId<nb; slotId++)
{
EMVTokenInfo token;
if (slotIdFilter && *slotIdFilter != slotId)
continue;
try{
token = GetTokenInfo(slotId);
} catch(EMVUnknownCardType) {
continue;
}catch(PCSCException){
continue;
}
EMVTokenKeyfile keyfile;
keyfile.Token->SlotId = slotId;
keyfile.Token = shared_ptr<TokenInfo>(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;
}
}

50
src/Common/EMVToken.h Normal file
View File

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

View File

@ -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<byte> &CERTS){
CERTS.clear();
bool iccFound= false;
bool issuerFound= false;
shared_ptr<TLVNode> node;
shared_ptr<TLVNode> ICC_Public_Key_Certificate;
shared_ptr<TLVNode> Issuer_PK_Certificate;
BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */
BYTE pbRecvBufferFat[256]; /* Bigger buffer to receive the card response */
DWORD dwSendLength; /* Size of the send buffer */
DWORD dwRecvLength; /* Size of the reception buffer */
/* Set up the io request */
SCARD_IO_REQUEST ioRequest;
ioRequest.dwProtocol = dwActiveProtocol;
ioRequest.cbPciLength = sizeof(ioRequest);
LONG returnValue;
/* Parsing root folders */
for (int sfi = 0; sfi < 32; sfi++)
{
/* Parsing sub folders */
for (int rec = 0; rec < 17; rec++)
{
BYTE SELECT_APDU_FILE[] = {00, 0xB2, static_cast<unsigned char>(rec), static_cast<unsigned char>((sfi << 3) | 4), 0x00};
dwSendLength = sizeof(SELECT_APDU_FILE);
dwRecvLength = sizeof(pbRecvBuffer);
/* Check if there is data in the folder */
#ifdef TC_WINDOWS
returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength);
#else
returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength);
#endif
/* Check if the transmission was unsuccessful */
if (returnValue != SCARD_S_SUCCESS)
throw PCSCException(returnValue);
/* There is no data in the folder */
if (pbRecvBuffer[0] != 0x6C)
continue;
/* It set the proper expected length of the data in the APDU */
SELECT_APDU_FILE[4] = pbRecvBuffer[1];
dwRecvLength = sizeof(pbRecvBufferFat);
/* Get the data from the folder */
#ifdef TC_WINDOWS
returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength, NULL, pbRecvBufferFat, &dwRecvLength);
#else
returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength, NULL, pbRecvBufferFat, &dwRecvLength);
#endif
/* Check if the transmission was unsuccessful */
if (returnValue != SCARD_S_SUCCESS)
throw PCSCException(returnValue);
/* It received a response. Check if it didn't get a recognisable response */
if (dwRecvLength < 2)
continue;
/* Parsing the TLV */
try{
node = TLVParser::TLV_Parse(pbRecvBufferFat,sizeof(pbRecvBufferFat));
}catch(TLVException){
continue;
}
/* Finding the ICC_Public_Key_Certificate */
try{
ICC_Public_Key_Certificate = TLVParser::TLV_Find(node, 0x9F46);
}catch(TLVException){
continue;
}
if(ICC_Public_Key_Certificate) {
iccFound=true;
for (int i = 0; i < ICC_Public_Key_Certificate->Length;i++) {
CERTS.push_back(static_cast<byte>(ICC_Public_Key_Certificate->Value[i]));
}
}
/* Finding the Issuer_Public_Key_Certificate */
try{
Issuer_PK_Certificate = TLVParser::TLV_Find(node, 0x90);
}catch(TLVException){
continue;
}
if(Issuer_PK_Certificate) {
issuerFound=true;
for (int i = 0; i < Issuer_PK_Certificate->Length;i++) {
CERTS.push_back(static_cast<byte>(Issuer_PK_Certificate->Value[i]));
}
}
/* Limiting the search to at least one occurrence of both PKs to speed up the process.
* There might be more certificates tho */
if(iccFound && issuerFound){
burn(pbRecvBuffer, sizeof(pbRecvBuffer));
burn(pbRecvBufferFat, sizeof(pbRecvBufferFat));
return;
}
}
}
burn(pbRecvBuffer, sizeof(pbRecvBuffer));
burn(pbRecvBufferFat, sizeof(pbRecvBufferFat));
throw EMVKeyfileDataNotFound();
}
/* Getting CPCL data from the card*/
void IccDataExtractor::GetCPCL(vector<byte> &v){
BYTE SELECT_APDU_CPCL[] = {0x80,0xCA, 0x9F, 0x7F, 0x00};
BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */
BYTE pbRecvBufferFat[256]; /* Bigger buffer to receive the card response */
DWORD dwSendLength = sizeof (SELECT_APDU_CPCL); /* Set the size of the send buffer */
DWORD dwRecvLength = sizeof(pbRecvBuffer); /* Set the size of the reception buffer */
/* Set up the io request */
SCARD_IO_REQUEST ioRequest;
ioRequest.dwProtocol = dwActiveProtocol;
ioRequest.cbPciLength = sizeof(ioRequest);
/* Check if there is the TAG for CPCL Data in the card */
#ifdef TC_WINDOWS
LONG returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength, NULL, pbRecvBuffer, &dwRecvLength);
#else
LONG returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength, NULL, pbRecvBuffer, &dwRecvLength);
#endif
/* Check if the transmission was unsuccessful */
if (returnValue != SCARD_S_SUCCESS)
throw PCSCException(returnValue);
/* Not the correct APDU response code */
if (pbRecvBuffer[0] != 0x6C)
throw EMVKeyfileDataNotFound();
/* It set the proper expected length of the data in the APDU */
SELECT_APDU_CPCL[4] = pbRecvBuffer[1];
dwRecvLength = sizeof(pbRecvBufferFat);
/* Get the CPCL data */
#ifdef TC_WINDOWS
returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength);
#else
returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_CPCL, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength);
#endif
/* Check if the transmission was unsuccessful */
if (returnValue != SCARD_S_SUCCESS)
throw PCSCException(returnValue);
/* It received a response. Check if it didn't get a recognisable response */
if (dwRecvLength < 2)
throw EMVKeyfileDataNotFound();
/* We add CPCL data and crop the TAG and the data length at the start and the trailer at the end */
for (unsigned long i = 3; i < dwRecvLength-2; i++) {
v.push_back(static_cast<byte>(pbRecvBufferFat[i]));
}
burn(pbRecvBuffer, sizeof(pbRecvBuffer));
burn(pbRecvBufferFat, sizeof(pbRecvBufferFat));
}
/* Getting an ICC Public Key Certificates and an Issuer Public Key Certificates for the first application with the cpcl
* data present on the card and finally merge it into one byte array */
void IccDataExtractor::GettingAllCerts(int readerNumber, vector<byte> &v){
#ifdef TC_WINDOWS
if(!Initialized)
throw WinscardLibraryNotInitialized();
#endif
bool isEMV= false;
ConnectCard(readerNumber);
/* Test all the type of applications and get the certificates from the first one found */
for(int i=0;i<sizeof(SELECT_TYPES)/sizeof(SELECT_TYPES[0]); i++){
/* The card does not contain this application (0:Mastercard, 1:Visa, 2:Amex) */
if(!TestingCardType(i)) continue;
isEMV= true;
GetCerts(v);
break;
}
/* Need to disconnect reconnect the card to access CPLC data (not located in any application) */
DisconnectCard();
/* Check if the card is not an EMV one */
if(!isEMV)
throw EMVUnknownCardType();
ConnectCard(readerNumber);
GetCPCL(v);
DisconnectCard();
}
/* Getting the PAN by parsing the application
* (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/
void IccDataExtractor::GetPAN(vector<byte> &v) {
bool PANFound= false;
shared_ptr<TLVNode> node;
shared_ptr<TLVNode> PAN;
BYTE pbRecvBuffer[64]; /* Buffer to receive the card response */
BYTE pbRecvBufferFat[256]; /* Bigger buffer to receive the card response */
DWORD dwSendLength; /* Size of the send buffer */
DWORD dwRecvLength; /* Size of the reception buffer */
/* Set up the io request */
SCARD_IO_REQUEST ioRequest;
ioRequest.dwProtocol = dwActiveProtocol;
ioRequest.cbPciLength = sizeof(ioRequest);
LONG returnValue;
/* Parsing root folders */
for (int sfi = 0; sfi < 32; sfi++)
{
/* Parsing sub folders */
for (int rec = 0; rec < 17; rec++)
{
BYTE SELECT_APDU_FILE[] = {00, 0xB2, static_cast<unsigned char>(rec), static_cast<unsigned char>((sfi << 3) | 4), 0x00};
dwSendLength = sizeof(SELECT_APDU_FILE);
dwRecvLength = sizeof(pbRecvBuffer);
/* Check if there is data in the folder */
#ifdef TC_WINDOWS
returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength);
#else
returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBuffer, &dwRecvLength);
#endif
/* Check if the transmission was unsuccessful */
if (returnValue != SCARD_S_SUCCESS)
throw PCSCException(returnValue);
/* There is no data in the folder */
if (pbRecvBuffer[0] != 0x6C)
continue;
/* It set the proper expected length of the data in the APDU */
SELECT_APDU_FILE[4] = pbRecvBuffer[1];
dwRecvLength = sizeof(pbRecvBufferFat);
/* Get the data from the folder */
#ifdef TC_WINDOWS
returnValue = WSCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength);
#else
returnValue = SCardTransmit(hCard, &ioRequest, SELECT_APDU_FILE, dwSendLength,NULL, pbRecvBufferFat, &dwRecvLength);
#endif
/* Check if the transmission was unsuccessful */
if (returnValue != SCARD_S_SUCCESS)
throw PCSCException(returnValue);
/* It received a response. Check if it didn't get a recognisable response */
if (dwRecvLength < 2)
continue;
/* Parsing the TLV */
try{
node = TLVParser::TLV_Parse(pbRecvBufferFat,sizeof(pbRecvBufferFat));
}catch(TLVException){
continue;
}
/* Finding the PAN */
try{
PAN = TLVParser::TLV_Find(node, 0x5A);
}catch(TLVException){
continue;
}
if(PAN) {
PANFound=true;
if (PAN->Length >= 8){
for (int i = 6; i < 8;i++) {
v.push_back(static_cast<byte>(PAN->Value[i]));
}
}
}
if(PANFound){
burn(pbRecvBuffer, sizeof(pbRecvBuffer));
burn(pbRecvBufferFat, sizeof(pbRecvBufferFat));
return ;
}
}
}
burn(pbRecvBuffer, sizeof(pbRecvBuffer));
burn(pbRecvBufferFat, sizeof(pbRecvBufferFat));
throw EMVPANNotFound();
}
/* Helper function to transform the PAN received (vector of byte) to a string */
template<typename TInputIter>
void IccDataExtractor::make_hex_string(TInputIter first, TInputIter last, string& returnValue, bool use_uppercase, bool insert_spaces) {
ostringstream ss;
ss << hex << std::setfill('0');
if (use_uppercase)
ss << uppercase;
while (first != last)
{
ss << setw(2) << static_cast<int>(*first++);
if (insert_spaces && first != last)
ss << " ";
}
returnValue = ss.str();
}
/* Wrapper function to get the PAN of the card*/
void IccDataExtractor::GettingPAN(int readerNumber, string& panString) {
#ifdef TC_WINDOWS
if(!Initialized)
throw WinscardLibraryNotInitialized();
#endif
vector<byte> PAN;
bool isEMV= false;
ConnectCard(readerNumber);
/* Test all the type of applications and get the PAN from the first one found */
for(int i=0;i<sizeof(SELECT_TYPES)/sizeof(SELECT_TYPES[0]); i++){
/* The card does not contain this application (0:Mastercard, 1:Visa, 2:Amex) */
if(!TestingCardType(i)) continue;
isEMV=true;
GetPAN(PAN);
break;
}
DisconnectCard();
/* Check if the card is not an EMV one */
if(!isEMV)
throw EMVUnknownCardType();
make_hex_string(PAN.begin(),PAN.end(),panString);
burn(&PAN.front(),PAN.size());
}
PCSCException::operator string() const{
if (ErrorCode == SCARD_S_SUCCESS)
return string();
static const struct{
LONG ErrorCode;
const char* ErrorString;
} ErrorStrings[] = {
#define SC_ERR(CODE) { CODE, #CODE },
#ifdef TC_WINDOWS
SC_ERR(ERROR_BROKEN_PIPE)
SC_ERR(SCARD_E_NO_PIN_CACHE)
SC_ERR(SCARD_E_PIN_CACHE_EXPIRED)
SC_ERR(SCARD_E_READ_ONLY_CARD)
SC_ERR(SCARD_W_CACHE_ITEM_NOT_FOUND)
SC_ERR(SCARD_W_CACHE_ITEM_STALE)
SC_ERR(SCARD_W_CACHE_ITEM_TOO_BIG)
#endif
SC_ERR(SCARD_E_BAD_SEEK)
SC_ERR(SCARD_E_CANCELLED)
SC_ERR(SCARD_E_CANT_DISPOSE)
SC_ERR(SCARD_E_CARD_UNSUPPORTED)
SC_ERR(SCARD_E_CERTIFICATE_UNAVAILABLE)
SC_ERR(SCARD_E_COMM_DATA_LOST)
SC_ERR(SCARD_E_COMM_DATA_LOST)
SC_ERR(SCARD_E_DIR_NOT_FOUND)
SC_ERR(SCARD_E_DUPLICATE_READER)
SC_ERR(SCARD_E_FILE_NOT_FOUND)
SC_ERR(SCARD_E_ICC_CREATEORDER)
SC_ERR(SCARD_E_ICC_INSTALLATION)
SC_ERR(SCARD_E_INSUFFICIENT_BUFFER)
SC_ERR(SCARD_E_INVALID_ATR)
SC_ERR(SCARD_E_INVALID_CHV)
SC_ERR(SCARD_E_INVALID_HANDLE)
SC_ERR(SCARD_E_INVALID_PARAMETER)
SC_ERR(SCARD_E_INVALID_TARGET)
SC_ERR(SCARD_E_INVALID_VALUE)
SC_ERR(SCARD_E_NO_ACCESS)
SC_ERR(SCARD_E_NO_DIR)
SC_ERR(SCARD_E_NO_FILE)
SC_ERR(SCARD_E_NO_KEY_CONTAINER)
SC_ERR(SCARD_E_NO_MEMORY)
SC_ERR(SCARD_E_NO_READERS_AVAILABLE)
SC_ERR(SCARD_E_NO_SERVICE)
SC_ERR(SCARD_E_NO_SMARTCARD)
SC_ERR(SCARD_E_NO_SUCH_CERTIFICATE)
SC_ERR(SCARD_E_NOT_READY)
SC_ERR(SCARD_E_NOT_TRANSACTED)
SC_ERR(SCARD_E_PCI_TOO_SMALL)
SC_ERR(SCARD_E_PROTO_MISMATCH)
SC_ERR(SCARD_E_READER_UNAVAILABLE)
SC_ERR(SCARD_E_READER_UNSUPPORTED)
SC_ERR(SCARD_E_SERVER_TOO_BUSY)
SC_ERR(SCARD_E_SERVICE_STOPPED)
SC_ERR(SCARD_E_SHARING_VIOLATION)
SC_ERR(SCARD_E_SYSTEM_CANCELLED)
SC_ERR(SCARD_E_TIMEOUT)
SC_ERR(SCARD_E_UNEXPECTED)
SC_ERR(SCARD_E_UNKNOWN_CARD)
SC_ERR(SCARD_E_UNKNOWN_READER)
SC_ERR(SCARD_E_UNKNOWN_RES_MNG)
SC_ERR(SCARD_E_UNSUPPORTED_FEATURE)
SC_ERR(SCARD_E_WRITE_TOO_MANY)
SC_ERR(SCARD_F_COMM_ERROR)
SC_ERR(SCARD_F_INTERNAL_ERROR)
SC_ERR(SCARD_F_UNKNOWN_ERROR)
SC_ERR(SCARD_W_CANCELLED_BY_USER)
SC_ERR(SCARD_W_CARD_NOT_AUTHENTICATED)
SC_ERR(SCARD_W_CHV_BLOCKED)
SC_ERR(SCARD_W_EOF)
SC_ERR(SCARD_W_REMOVED_CARD)
SC_ERR(SCARD_W_RESET_CARD)
SC_ERR(SCARD_W_SECURITY_VIOLATION)
SC_ERR(SCARD_W_UNPOWERED_CARD)
SC_ERR(SCARD_W_UNRESPONSIVE_CARD)
SC_ERR(SCARD_W_UNSUPPORTED_CARD)
SC_ERR(SCARD_W_WRONG_CHV)
#undef SC_ERR
};
for (size_t i = 0; i < array_capacity(ErrorStrings); ++i)
{
if (ErrorStrings[i].ErrorCode == ErrorCode)
return ErrorStrings[i].ErrorString;
}
stringstream s;
s << "0x" << ErrorCode;
return s.str();
}
#ifdef TC_HEADER_Common_Exception
void PCSCException::Show(HWND parent) const
{
string errorString = string(*this);
if (!errorString.empty())
{
wstringstream subjectErrorCode;
if (SubjectErrorCodeValid)
subjectErrorCode << L": " << SubjectErrorCode;
if (!GetDictionaryValue(errorString.c_str()))
{
if (errorString.find("SCARD_E_") == 0 || errorString.find("SCARD_F_") == 0 || errorString.find("SCARD_W_") == 0)
{
errorString = errorString.substr(8);
for (size_t i = 0; i < errorString.size(); ++i)
{
if (errorString[i] == '_')
errorString[i] = ' ';
}
}
wchar_t err[8192];
StringCbPrintfW(err, sizeof(err), L"%s:\n\n%hs%s", GetString("PCSC_ERROR"), errorString.c_str(), subjectErrorCode.str().c_str());
ErrorDirect(err, parent);
}
else
{
wstring err = GetString(errorString.c_str());
if (SubjectErrorCodeValid)
err += L"\n\nError code" + subjectErrorCode.str();
ErrorDirect(err.c_str(), parent);
}
}
}
#endif // TC_HEADER_Common_Exception
#ifdef TC_HEADER_Platform_Exception
void PCSCException::Deserialize(shared_ptr <Stream> stream)
{
Exception::Deserialize(stream);
Serializer sr(stream);
uint64 code;
sr.Deserialize("ErrorCode", code);
sr.Deserialize("SubjectErrorCodeValid", SubjectErrorCodeValid);
sr.Deserialize("SubjectErrorCode", SubjectErrorCode);
ErrorCode = (LONG)code;
}
void PCSCException::Serialize(shared_ptr <Stream> stream) const
{
Exception::Serialize(stream);
Serializer sr(stream);
sr.Serialize("ErrorCode", (uint64)ErrorCode);
sr.Serialize("SubjectErrorCodeValid", SubjectErrorCodeValid);
sr.Serialize("SubjectErrorCode", SubjectErrorCode);
}
# define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
# undef TC_EXCEPTION_NODECL
# define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET(PCSCTokenException);
#endif
}

View File

@ -0,0 +1,231 @@
//
// Created by bshp on 1/14/23.
//
#ifndef NEWEMV_ICCDATAEXTRACTOR_H
#define NEWEMV_ICCDATAEXTRACTOR_H
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sstream>
#include <vector>
#include <iomanip>
#include <memory>
#include "Platform/PlatformBase.h"
#include "TLVParser.h"
#ifdef __linux__
#include <unistd.h>
#endif
#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE)
# include "Exception.h"
#else
# include "Platform/Exception.h"
#endif
#ifdef TC_WINDOWS
#include <winscard.h>
#include <windows.h>
#endif
#ifdef TC_UNIX
#undef BOOL
#include <PCSC/winscard.h>
using VeraCrypt::byte;
#define BOOL int
//#include <unistd.h> //Works without on windows
#endif
#ifdef _WIN32
#include <windows.h>
#endif
#ifdef _WIN64
#define ssize_t __int64
#else
#define ssize_t long
#endif
#define SELECT_TYPE_SIZE 12 /* Size of the SELECT_TYPE APDU */
/* Winscard function pointers definitions for windows import */
#ifdef TC_WINDOWS
typedef LONG (WINAPI *SCardEstablishContextPtr)(DWORD dwScope,LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext);
typedef LONG (WINAPI *SCardReleaseContextPtr)(SCARDCONTEXT hContext);
typedef LONG (WINAPI *SCardConnectAPtr)(SCARDCONTEXT hContext,LPCSTR szReader,DWORD dwShareMode,DWORD dwPreferredProtocols,LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol);
typedef LONG (WINAPI *SCardDisconnectPtr)(SCARDHANDLE hCard, DWORD dwDisposition);
typedef LONG (WINAPI *SCardTransmitPtr)(SCARDHANDLE hCard,LPCSCARD_IO_REQUEST pioSendPci,const BYTE* pbSendBuffer, DWORD cbSendLength,LPSCARD_IO_REQUEST pioRecvPci,BYTE* pbRecvBuffer, LPDWORD pcbRecvLength);
typedef LONG (WINAPI *SCardListReadersAPtr)(SCARDCONTEXT hContext,LPCSTR mszGroups,LPSTR mszReaders, LPDWORD pcchReaders);
typedef LONG (WINAPI *SCardFreeMemoryPtr)(SCARDCONTEXT hContext,LPCVOID pvMem);
#endif
namespace VeraCrypt
{
class IccDataExtractor {
private:
/* Used for loading winscard on windows */
#ifdef TC_WINDOWS
/* Winscard Library Handle */
HMODULE WinscardLibraryHandle;
/* Winscard function pointers */
SCardEstablishContextPtr WSCardEstablishContext;
SCardReleaseContextPtr WSCardReleaseContext;
SCardConnectAPtr WSCardConnectA;
SCardDisconnectPtr WSCardDisconnect;
SCardFreeMemoryPtr WSCardFreeMemory;
SCardListReadersAPtr WSCardListReadersA;
SCardTransmitPtr WSCardTransmit;
/* Is the winscard library loaded */
static bool Initialized;
#endif
/* SELECT_TYPES FOR DIFFERENT AIDs*/
const static BYTE SELECT_MASTERCARD[SELECT_TYPE_SIZE];
const static BYTE SELECT_VISA[SELECT_TYPE_SIZE];
const static BYTE SELECT_AMEX[SELECT_TYPE_SIZE];
const static BYTE * SELECT_TYPES[3];
SCARDCONTEXT hContext; /* Handle that identifies the resource manager context.*/
SCARDHANDLE hCard; /* A handle that identifies the connection to the smart card in the designated reader*/
std::vector<char*> readers; /* Card reader list */
unsigned long int nbReaders; /* Number of connected (available) readers */
LPSTR mszReaders; /* Names of the reader groups defined to the system, as a multi-string. Use a NULL value to
* list all readers in the system */
DWORD dwActiveProtocol; /* A flag that indicates the established active protocol.
* SCARD_PROTOCOL_T0: An asynchronous, character-oriented half-duplex transmission protocol.
* SCARD_PROTOCOL_T1: An asynchronous, block-oriented half-duplex transmission protocol.*/
/* Establishing the resource manager context (the scope) within which database operations are performed.
* The module of the smart card subsystem that manages access to multiple readers and smart cards. The
* resource manager identifies and tracks resources, allocates readers and resources across multiple
* applications,and supports transaction primitives for accessing services available on a given card.*/
int EstablishRSContext();
/* Connecting to the card in the given reader*/
int ConnectCard(unsigned long int reader_nb);
/* Disconnect the card currently connected*/
int DisconnectCard();
/* Testing if the card contains the application of the given EMV type */
bool TestingCardType(const int SELECT_TYPE_NUMBER);
/* Getting the ICC Public Key Certificates and the Issuer Public Key Certificates by parsing the application
* (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/
void GetCerts(vector<byte> &CERTS);
/* Getting CPCL data from the card and put it into a reference*/
void GetCPCL(vector<byte> &v);
/* Getting the PAN by parsing the application
* (!NEED TO TEST CARD TYPE TO SELECT APPLICATION FIRST!)*/
void GetPAN(vector<byte> &v);
/* Helper function to make a string from plain arrays and various standard containers of bytes */
template<typename TInputIter>
void make_hex_string(TInputIter first, TInputIter last, std::string& panString, bool use_uppercase = true, bool insert_spaces = false);
public:
IccDataExtractor();
~IccDataExtractor();
/* Used to initialize the winscard library on windows to make sure the dll is in System32 */
#ifdef TC_WINDOWS
void IccDataExtractor::InitLibrary();
#endif
/* Detecting available readers and filling the reader table. Returns
* the number of available readers */
unsigned long GetReaders();
/* Getting an ICC Public Key Certificates, an Issuer Public Key Certificates and the CPCL data
* from the card designated by the reader number. Appending them into a byte vector */
void GettingAllCerts(int readerNumber, vector<byte> &v);
/* Getting the PAN from the card designated by the reader number */
void GettingPAN(int readerNumber, string& panString);
};
struct PCSCException: public Exception
{
PCSCException(LONG errorCode = (LONG) -1): ErrorCode(errorCode), SubjectErrorCodeValid(false), SubjectErrorCode((uint64)-1){}
PCSCException(LONG errorCode, uint64 subjectErrorCode): ErrorCode(errorCode), SubjectErrorCodeValid(true), SubjectErrorCode(subjectErrorCode){}
#ifdef TC_HEADER_Platform_Exception
virtual ~PCSCException() throw () { }
TC_SERIALIZABLE_EXCEPTION(PCSCException);
#else
void Show(HWND parent) const;
#endif
operator string () const;
LONG GetErrorCode() const { return ErrorCode; }
protected:
LONG ErrorCode;
bool SubjectErrorCodeValid;
uint64 SubjectErrorCode;
};
#ifdef TC_HEADER_Platform_Exception
#define TC_EXCEPTION(NAME) TC_EXCEPTION_DECL(NAME,Exception)
#undef TC_EXCEPTION_SET
#define TC_EXCEPTION_SET \
TC_EXCEPTION_NODECL (PCSCException); \
TC_EXCEPTION (WinscardLibraryNotInitialized); \
TC_EXCEPTION (InvalidEMVPath); \
TC_EXCEPTION (EMVKeyfileDataNotFound); \
TC_EXCEPTION (EMVPANNotFound); \
TC_EXCEPTION (EMVUnknownCardType);
TC_EXCEPTION_SET;
#undef TC_EXCEPTION
#else // !TC_HEADER_Platform_Exception
struct WinscardLibraryNotInitialized: public Exception
{
void Show(HWND parent) const { Error("WINSCARD_MODULE_INIT_FAILED", parent); }
};
struct InvalidEMVPath: public Exception
{
void Show(HWND parent) const { Error("INVALID_EMV_PATH", parent); }
};
struct EMVKeyfileDataNotFound: public Exception
{
void Show(HWND parent) const { Error("EMV_KEYFILE_DATA_NOT_FOUND", parent); }
};
struct EMVPANNotFound: public Exception
{
void Show(HWND parent) const { Error("EMV_PAN_NOT_FOUND", parent); }
};
struct EMVUnknownCardType: public Exception
{
void Show(HWND parent) const { Error("EMV_UNKNOWN_CARD_TYPE", parent); }
};
#endif // !TC_HEADER_Platform_Exception
}
#endif //NEWEMV_ICCDATAEXTRACTOR_H

View File

@ -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 <byte> 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 <SecurityTokenKeyfilePath> selectedTokenKeyfiles;
list <TokenKeyfilePath> 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 <SecurityTokenKeyfilePath> selectedTokenKeyfiles;
list <TokenKeyfilePath> 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)

View File

@ -113,6 +113,7 @@
<entry lang="en" key="IDC_CACHE">Cache passwords and keyfil&amp;es in memory</entry>
<entry lang="en" key="IDC_CLOSE_BKG_TASK_WHEN_NOVOL">Exit when there are no mounted volumes</entry>
<entry lang="en" key="IDC_CLOSE_TOKEN_SESSION_AFTER_MOUNT">&amp;Close token session (log out) after a volume is successfully mounted</entry>
<entry lang="en" key="IDC_ACTIVATE_EMV_OPTION">Activate EMV Option</entry>
<entry lang="en" key="IDC_COPY_EXPANDER">Include VeraCrypt Volume Expander</entry>
<entry lang="en" key="IDC_COPY_WIZARD">Include VeraCrypt Volume Creation Wizard</entry>
<entry lang="en" key="IDC_CREATE">Create</entry>
@ -295,6 +296,7 @@
<entry lang="en" key="IDT_NEW_PKCS5_PRF">PKCS-5 PRF:</entry>
<entry lang="en" key="IDT_PW_CACHE_OPTIONS">Password Cache</entry>
<entry lang="en" key="IDT_SECURITY_OPTIONS">Security Options</entry>
<entry lang="en" key="IDT_EMV_OPTIONS">EMV Options</entry>
<entry lang="en" key="IDT_TASKBAR_ICON">VeraCrypt Background Task</entry>
<entry lang="en" key="IDT_TRAVELER_MOUNT">VeraCrypt volume to mount (relative to traveler disk root):</entry>
<entry lang="en" key="IDT_TRAVEL_INSERTION">Upon insertion of traveler disk: </entry>
@ -1278,6 +1280,12 @@
<entry lang="en" key="CKR_PIN_INCORRECT">Password for security token is incorrect.</entry>
<entry lang="en" key="CKR_DEVICE_MEMORY">The security token does not have enough memory/space to perform the requested operation.\n\nIf you are attempting to import a keyfile, you should select a smaller file or use a keyfile generated by VeraCrypt (select 'Tools' > 'Keyfile Generator').</entry>
<entry lang="en" key="ALL_TOKEN_SESSIONS_CLOSED">All open security token sessions have been closed.</entry>
<entry lang="en" key="WINSCARD_MODULE_INIT_FAILED">Error when loading the winscard library.\n\nPlease make sure the WinSCard.dll is present in your System32 folder.</entry>
<entry lang="en" key="INVALID_EMV_PATH">EMV path is invalid.</entry>
<entry lang="en" key="EMV_KEYFILE_DATA_NOT_FOUND">Unable to build a keyfile from the EMV card's data.\n\nOne of the following is missing:\n- ICC Public Key Certificate.\n- Issuer Public Key Certificate.\n- CPCL data.</entry>
<entry lang="en" key="EMV_PAN_NOT_FOUND">No Primary Account Number (PAN) found in the EMV card.</entry>
<entry lang="en" key="EMV_UNKNOWN_CARD_TYPE">The card in the reader is not a supported EMV card.</entry>
<entry lang="en" key="SCARD_W_REMOVED_CARD">No card in the reader.\n\nPlease make sure the card is correctly slotted.</entry>
<entry lang="en" key="SELECT_TOKEN_KEYFILES">Select Security Token Keyfiles</entry>
<entry lang="en" key="TOKEN_SLOT_ID">Slot</entry>
<entry lang="en" key="TOKEN_NAME">Token name</entry>

View File

@ -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<SecurityTokenInfo>(token);
Token->SlotId = CK_UNAVAILABLE_INFORMATION;
token->Flags = 0;
}
SecurityTokenKeyfile::SecurityTokenKeyfile(const TokenKeyfilePath& path)
{
Token = shared_ptr<SecurityTokenInfo>(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 <SecurityTokenKeyfile> keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id);
vector <SecurityTokenKeyfile> 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 <CK_SLOT_ID, Pkcs11Session> 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 <byte> &keyfileData, const string &name)
void SecurityToken::CreateKeyfile(CK_SLOT_ID slotId, vector <byte>& 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 <byte> objectData;
GetObjectAttribute (slotId, keyfileHandle, CKA_VALUE, objectData);
finally_do_arg (vector <byte> *, &objectData, { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); });
GetObjectAttribute(slotId, keyfileHandle, CKA_VALUE, objectData);
finally_do_arg(vector <byte> *, &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 <SecurityTokenKeyfile> SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter)
vector <SecurityTokenKeyfile> SecurityToken::GetAvailableKeyfiles(CK_SLOT_ID* slotIdFilter, const wstring keyfileIdFilter)
{
bool unrecognizedTokenPresent = false;
vector <SecurityTokenKeyfile> 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<SecurityTokenInfo>(new SecurityTokenInfo(token));
vector <byte> 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 <byte> 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 <SecurityTokenInfo> SecurityToken::GetAvailableTokens ()
list <SecurityTokenInfo> SecurityToken::GetAvailableTokens()
{
bool unrecognizedTokenPresent = false;
list <SecurityTokenInfo> 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 <byte> &keyfileData)
void SecurityTokenKeyfile::GetKeyfileData(vector <byte>& 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 <CK_OBJECT_HANDLE> SecurityToken::GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass)
vector <CK_OBJECT_HANDLE> 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 <CK_OBJECT_HANDLE> 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 <byte> &attributeValue)
void SecurityToken::GetObjectAttribute(CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector <byte>& 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 <byte> (attribute.ulValueLen);
attributeValue = vector <byte>(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 <CK_SLOT_ID> SecurityToken::GetTokenSlots ()
list <CK_SLOT_ID> SecurityToken::GetTokenSlots()
{
CheckLibraryStatus();
list <CK_SLOT_ID> 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 <CK_SLOT_ID> slotArray (slotCount);
status = Pkcs11Functions->C_GetSlotList (TRUE, &slotArray.front(), &slotCount);
vector <CK_SLOT_ID> 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 <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> warningCallback)
void SecurityToken::InitLibrary(const wstring& pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> warningCallback)
#else
void SecurityToken::InitLibrary (const string &pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> warningCallback)
void SecurityToken::InitLibrary(const string& pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> 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> stream)
void Pkcs11Exception::Deserialize(shared_ptr <Stream> 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> stream) const
void Pkcs11Exception::Serialize(shared_ptr <Stream> stream) const
{
Exception::Serialize (stream);
Serializer sr (stream);
sr.Serialize ("ErrorCode", (uint64) ErrorCode);
sr.Serialize ("SubjectErrorCodeValid", SubjectErrorCodeValid);
sr.Serialize ("SubjectErrorCode", SubjectErrorCode);
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
}

View File

@ -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 SecurityTokenKeyfilePath () const;
operator TokenKeyfilePath () const;
void GetKeyfileData(vector<byte>& 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 <byte> &keyfileData, const string &name);
static void DeleteKeyfile (const SecurityTokenKeyfile &keyfile);
static vector <SecurityTokenKeyfile> GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring());
static void GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector <byte> &keyfileData);
static list <SecurityTokenInfo> GetAvailableTokens ();
static SecurityTokenInfo GetTokenInfo (CK_SLOT_ID slotId);
static void CloseAllSessions() throw ();
static void CloseLibrary();
static void CreateKeyfile(CK_SLOT_ID slotId, vector <byte>& keyfileData, const string& name);
static void DeleteKeyfile(const SecurityTokenKeyfile& keyfile);
static vector <SecurityTokenKeyfile> GetAvailableKeyfiles(CK_SLOT_ID* slotIdFilter = nullptr, const wstring keyfileIdFilter = wstring());
static list <SecurityTokenInfo> GetAvailableTokens();
static SecurityTokenInfo GetTokenInfo(CK_SLOT_ID slotId);
#ifdef TC_WINDOWS
static void InitLibrary (const wstring &pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> warningCallback);
static void InitLibrary(const wstring& pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> warningCallback);
#else
static void InitLibrary (const string &pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> warningCallback);
static void InitLibrary(const string& pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> 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 <CK_OBJECT_HANDLE> GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass);
static void GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector <byte> &attributeValue);
static list <CK_SLOT_ID> 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 <CK_OBJECT_HANDLE> GetObjects(CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass);
static void GetObjectAttribute(CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector <byte>& attributeValue);
static list <CK_SLOT_ID> 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 <GetPinFunctor> PinCallback;
@ -216,10 +208,12 @@ namespace VeraCrypt
#ifdef TC_WINDOWS
static HMODULE Pkcs11LibraryHandle;
#else
static void *Pkcs11LibraryHandle;
static void* Pkcs11LibraryHandle;
#endif
static map <CK_SLOT_ID, Pkcs11Session> Sessions;
static unique_ptr <SendExceptionFunctor> WarningCallback;
friend void SecurityTokenKeyfile::GetKeyfileData(vector <byte>& keyfileData) const;
};
}

179
src/Common/TLVParser.cpp Normal file
View File

@ -0,0 +1,179 @@
#include "TLVParser.h"
#include <string.h>
using namespace std;
/* TLV node structure creation */
shared_ptr<TLVNode> TLVParser::TLV_CreateNode()
{
shared_ptr<TLVNode> node= shared_ptr<TLVNode>(new TLVNode);
memset(node.get(),0,sizeof(*node));
return node;
}
/* Check if the bit is correct */
uint16_t TLVParser::CheckBit(unsigned char value, int bit){
unsigned char bitvalue[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
if((bit >= 1)&&(bit <= 8)){
if(value & bitvalue[bit-1]) {
return (1);
}
else {
return (0);
}
}
else{
throw TLVException("FILE:"+string(__FILE__)+"LINE: "+to_string(static_cast<long long>((__LINE__)))+" fonction parameter incorrect! bit=["+to_string(static_cast<long long>(bit)));
return(2);
}
}
/* Parsing one TLV node */
shared_ptr<TLVNode> TLVParser::TLV_Parse_One(unsigned char* buf,int size){
int index = 0;
int i;
unsigned char tag1,tag2,tagsize;
unsigned char len,lensize;
unsigned char* value;
shared_ptr<TLVNode> node = TLV_CreateNode();
tag1 = tag2 = 0;
tagsize = 1;
tag1 = buf[index++];
if((tag1 & 0x1f) == 0x1f){
tagsize++;
tag2 = buf[index++];
//tag2 b8 must be 0!
}
if(tagsize == 1) {
node->Tag = tag1;
}
else {
node->Tag = (tag1 << 8) + tag2;
}
node->TagSize = tagsize;
//SubFlag
node->SubFlag = CheckBit(tag1,6);
//L zone
len = 0;
lensize = 1;
len = buf[index++];
if(CheckBit(len,8) == 0){
node->Length = len;
}
else{
lensize = len & 0x7f;
len = 0;
for(i=0;i<lensize;i++){
len += (uint16_t)buf[index++] << (i*8);
}
lensize++;
}
node->Length = len;
node->LengthSize = lensize;
//V zone
value = new unsigned char[len];
std::copy(buf+index,buf+index+len,value);
node->Value = value;
index += len;
if(index < size){
node->MoreFlag = 1;
}
else if(index == size){
node->MoreFlag = 0;
}
else{
throw TLVException("Parse Error! index="+to_string(static_cast<long long>(index))+"size="+to_string(static_cast<long long>(size)));
}
return node;
}
/* Parsing all sub-nodes (in width not in depth) of a given parent node */
int TLVParser::TLV_Parse_SubNodes(shared_ptr<TLVNode> parent){
int sublen = 0;
int i;
//No sub-nodes
if(parent->SubFlag == 0)
return 0;
for(i=0;i<parent->SubCount;i++)
{
sublen += (parent->Sub[i]->TagSize + parent->Sub[i]->Length + parent->Sub[i]->LengthSize);
}
if(sublen < parent->Length)
{
shared_ptr<TLVNode> 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<TLVNode> parent)
{
int i;
if(parent->SubFlag != 0)
{
//Parse all sub nodes.
while(TLV_Parse_SubNodes(parent) != 0);
for(i=0;i<parent->SubCount;i++)
{
if(parent->Sub[i]->SubFlag != 0)
{
TLV_Parse_Sub(parent->Sub[i]);
}
}
}
return;
}
/* Parsing TLV from a buffer and constructing TLV structure */
shared_ptr<TLVNode> TLVParser::TLV_Parse(unsigned char* buf,int size)
{
shared_ptr<TLVNode> node = TLV_Parse_One(buf,size);
TLV_Parse_Sub(node);
return node;
}
/* Finding a TLV node with a particular tag */
shared_ptr<TLVNode> TLVParser::TLV_Find(shared_ptr<TLVNode> node,uint16_t tag){
int i;
shared_ptr<TLVNode> tmpnode;
if(node->Tag == tag)
{
return node;
}
for(i=0;i<node->SubCount;i++)
{
tmpnode = NULL;
tmpnode = TLV_Find(node->Sub[i],tag);
if(tmpnode != NULL){
return tmpnode;
}
}
if(node->Next)
{
tmpnode = NULL;
tmpnode = TLV_Find(node->Next,tag);
if(tmpnode != NULL){
return tmpnode;
}
}
return nullptr;
}

80
src/Common/TLVParser.h Normal file
View File

@ -0,0 +1,80 @@
//
// Created by bshp on 1/20/23.
//
#ifndef ICC_EXTRACTOR_TLVPARSER_H
#define ICC_EXTRACTOR_TLVPARSER_H
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string>
#include <memory>
#include "iostream"
#include "Tcdefs.h"
using namespace std;
struct TLVNode{
uint16_t Tag; /* T */
uint16_t Length; /* L */
unsigned char* Value; /* V */
unsigned char TagSize;
unsigned char LengthSize;
uint16_t MoreFlag; /* Used In Sub */
uint16_t SubFlag; /* Does it have sub-nodes? */
uint16_t SubCount;
shared_ptr<TLVNode> Sub[256];
shared_ptr<TLVNode> Next;
~TLVNode() {
burn(Value, Length);
delete Value;
}
};
class TLVParser{
private :
/* TLV node structure creation */
static shared_ptr<TLVNode> TLV_CreateNode();
/* Check if the bit is correct */
static uint16_t CheckBit(unsigned char value, int bit);
/* Parsing one TLV node */
static shared_ptr<TLVNode> TLV_Parse_One(unsigned char* buf,int size);
/* Parsing all TLV nodes */
static int TLV_Parse_SubNodes(shared_ptr<TLVNode> parent);
/* Parsing all sub-nodes (in width not in depth) of a given parent node */
static int TLV_Parse_All(shared_ptr<TLVNode> parent);
/* Recursive function to parse all nodes starting from a root parent node */
static void TLV_Parse_Sub(shared_ptr<TLVNode> parent);
public:
/* Parsing TLV from a buffer and constructing TLV structure */
static shared_ptr<TLVNode> TLV_Parse(unsigned char* buf,int size);
/* Finding a TLV node with a particular tag */
static shared_ptr<TLVNode> TLV_Find(shared_ptr<TLVNode> node,uint16_t tag);
};
/* The definition of the exception class related to the TLV parsing */
class TLVException
{
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

82
src/Common/Token.cpp Normal file
View File

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

57
src/Common/Token.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -98,11 +98,11 @@ namespace VeraCrypt
{
MountOptions newOptions = options;
newOptions.Password = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password);
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));
}
}

View File

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

View File

@ -307,7 +307,7 @@ namespace VeraCrypt
// Header key
HeaderKey.Allocate (VolumeHeader::GetLargestSerializedKeySize());
PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password);
PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password, options->EMVOption);
options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, options->Pim, salt);
headerOptions.HeaderKey = HeaderKey;

View File

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

View File

@ -245,7 +245,7 @@ copy Debug\VeraCryptExpander.exe "..\Debug\Setup Files" &gt;NUL:
<DisableSpecificWarnings>4311;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptExpander.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -336,7 +336,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4311;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptExpander.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -428,7 +428,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4311;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptExpander.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -476,7 +476,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4311;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptExpander.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -575,6 +575,10 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" &gt;NUL:
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\Common\EMVToken.cpp" />
<ClCompile Include="..\Common\IccDataExtractor.cpp" />
<ClCompile Include="..\Common\TLVParser.cpp" />
<ClCompile Include="..\Common\Token.cpp" />
<ClCompile Include="..\Setup\SelfExtract.c" />
<ClCompile Include="DlgExpandVolume.cpp" />
<ClCompile Include="ExpandVolume.c" />
@ -655,6 +659,10 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCryptExpander-x64.exe" &gt;NUL:
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Common\EMVToken.h" />
<ClInclude Include="..\Common\IccDataExtractor.h" />
<ClInclude Include="..\Common\TLVParser.h" />
<ClInclude Include="..\Common\Token.h" />
<ClInclude Include="..\Common\Wipe.h" />
<ClInclude Include="..\Common\Apidrvr.h" />
<ClInclude Include="..\Common\BaseCom.h" />

View File

@ -126,6 +126,18 @@
<ClCompile Include="..\Setup\SelfExtract.c">
<Filter>Source Files\Setup</Filter>
</ClCompile>
<ClCompile Include="..\Common\EMVToken.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\Token.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\IccDataExtractor.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\TLVParser.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Common\Wipe.h">
@ -230,6 +242,18 @@
<ClInclude Include="..\Common\Xts.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\EMVToken.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\Token.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\IccDataExtractor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\TLVParser.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Midl Include="..\Mount\MainCom.idl">

View File

@ -321,6 +321,7 @@ void LoadSettings (HWND hwndDlg)
mountOptions = defaultMountOptions;
CloseSecurityTokenSessionsAfterMount = ConfigReadInt ("CloseSecurityTokenSessionsAfterMount", 0);
ActivateEMVOption = ConfigReadInt ("ActivateEMVOption", 0);
{
char szTmp[TC_MAX_PATH] = {0};

View File

@ -218,7 +218,7 @@ copy Debug\VeraCryptFormat.exe "..\Debug\Setup Files\VeraCrypt Format.exe" &gt;N
<DisableSpecificWarnings>4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Debug\crypto.lib;..\Common\x64\Debug\Zip.lib;..\Common\x64\Debug\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptFormat.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -301,7 +301,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\Release\crypto.lib;..\Common\Release\Zip.lib;..\Common\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptFormat.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -385,7 +385,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptFormat.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -429,7 +429,7 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
<DisableSpecificWarnings>4057;4100;4127;4201;4204;4701;4706;4131;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>..\Crypto\x64\Release\crypto.lib;..\Common\x64\Release\Zip.lib;..\Common\x64\Release\lzma.lib;mpr.lib;winscard.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)VeraCryptFormat.exe</OutputFile>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>mpr.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
@ -497,6 +497,10 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Common\EMVToken.cpp" />
<ClCompile Include="..\Common\IccDataExtractor.cpp" />
<ClCompile Include="..\Common\TLVParser.cpp" />
<ClCompile Include="..\Common\Token.cpp" />
<ClCompile Include="FormatCom.cpp" />
<ClCompile Include="InPlace.c">
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CompileAsCpp</CompileAs>
@ -582,11 +586,15 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
<ClInclude Include="..\Common\Crypto.h" />
<ClInclude Include="..\Common\Dictionary.h" />
<ClInclude Include="..\Common\Dlgcode.h" />
<ClInclude Include="..\Common\EMVToken.h" />
<ClInclude Include="..\Common\EncryptionThreadPool.h" />
<ClInclude Include="..\Common\Endian.h" />
<ClInclude Include="..\Common\Exception.h" />
<ClInclude Include="..\Common\Fat.h" />
<ClInclude Include="..\Common\Format.h" />
<ClInclude Include="..\Common\IccDataExtractor.h" />
<ClInclude Include="..\Common\TLVParser.h" />
<ClInclude Include="..\Common\Token.h" />
<ClInclude Include="FormatCom.h" />
<ClInclude Include="..\Common\GfMul.h" />
<ClInclude Include="InPlace.h" />
@ -644,7 +652,9 @@ copy $(TargetPath) "..\Debug\Setup Files\VeraCrypt Format-x64.exe" &gt;NUL:
<None Include="..\Boot\Windows\Release_Twofish\BootSector.bin" />
<None Include="..\Boot\Windows\Release_AES\BootSector.bin" />
<None Include="..\Boot\Windows\Release\Decompressor.com" />
<None Include="..\Common\Language.xml" />
<None Include="..\Common\Language.xml">
<SubType>Designer</SubType>
</None>
<None Include="..\Resources\Texts\License.rtf" />
<None Include="..\Common\Textual_logo_288dpi.bmp" />
<None Include="..\Common\Textual_logo_96dpi.bmp" />

View File

@ -108,6 +108,18 @@
<ClCompile Include="..\Common\Xts.c">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\EMVToken.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\Token.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\IccDataExtractor.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\TLVParser.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Midl Include="FormatCom.idl">
@ -208,6 +220,18 @@
<ClInclude Include="..\Common\Xts.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\EMVToken.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\Token.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\IccDataExtractor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\TLVParser.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\Boot\Windows\Release_Serpent_SHA2\BootSector.bin">

View File

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

View File

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

View File

@ -42,7 +42,9 @@ namespace VeraCrypt
ExportSecurityTokenKeyfile,
Help,
ImportSecurityTokenKeyfiles,
ListSecurityTokenKeyfiles,
ListTokenKeyfiles,
ListSecurityTokenKeyfiles,
ListEMVTokenKeyfiles,
ListVolumes,
MountVolume,
RestoreHeaders,

View File

@ -204,7 +204,7 @@ namespace VeraCrypt
wxBusyCursor busy;
ChangePasswordThreadRoutine routine(Path, Gui->GetPreferences().DefaultMountOptions.PreserveTimestamps,
CurrentPasswordPanel->GetPassword(), CurrentPasswordPanel->GetVolumePim(), CurrentPasswordPanel->GetPkcs5Kdf(bUnsupportedKdf), CurrentPasswordPanel->GetTrueCryptMode(),CurrentPasswordPanel->GetKeyfiles(),
newPassword, newPim, newKeyfiles, NewPasswordPanel->GetPkcs5Kdf(bUnsupportedKdf), NewPasswordPanel->GetHeaderWipeCount());
newPassword, newPim, newKeyfiles, NewPasswordPanel->GetPkcs5Kdf(bUnsupportedKdf), NewPasswordPanel->GetHeaderWipeCount(), Gui->GetPreferences().ActivateEMVOption);
Gui->ExecuteWaitThreadRoutine (this, &routine);
}

View File

@ -2208,6 +2208,13 @@ PreferencesDialogBase::PreferencesDialogBase( wxWindow* parent, wxWindowID id, c
bSizer128->Add( sbSizer37, 0, wxEXPAND|wxALL, 5 );
wxStaticBoxSizer* sbSizer38;
sbSizer38 = new wxStaticBoxSizer( new wxStaticBox( SecurityTokensPage, wxID_ANY, _("IDT_EMV_OPTIONS") ), wxVERTICAL );
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 );

View File

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

View File

@ -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 <wstring> fields;
fields.push_back (path);

View File

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

View File

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

View File

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

View File

@ -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<TokenKeyfile> key, SecurityTokenKeyfileList)
{
vector <wstring> 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 <SecurityTokenKeyfile *> (SecurityTokenKeyfileListCtrl->GetItemData (item));
TokenKeyfile *keyfile = reinterpret_cast <TokenKeyfile *> (SecurityTokenKeyfileListCtrl->GetItemData (item));
FilePathList files = Gui->SelectFiles (this, wxEmptyString, true);
@ -106,7 +105,7 @@ namespace VeraCrypt
wxBusyCursor busy;
vector <byte> 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 <TokenKeyfile *> (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 <SecurityTokenKeyfile *> (SecurityTokenKeyfileListCtrl->GetItemData (item));
SelectedSecurityTokenKeyfilePaths.push_back (*key);
}
{
TokenKeyfile *key = reinterpret_cast <TokenKeyfile *> (SecurityTokenKeyfileListCtrl->GetItemData(item));
SelectedSecurityTokenKeyfilePaths.push_back(*key);
}
EndModal (wxID_OK);
}
}

View File

@ -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 <SecurityTokenKeyfilePath> GetSelectedSecurityTokenKeyfilePaths() const { return SelectedSecurityTokenKeyfilePaths; }
list <TokenKeyfilePath> GetSelectedSecurityTokenKeyfilePaths() const { return SelectedSecurityTokenKeyfilePaths; }
protected:
enum
@ -43,8 +45,8 @@ namespace VeraCrypt
void OnOKButtonClick ();
void OnOKButtonClick (wxCommandEvent& event) { OnOKButtonClick(); }
vector <SecurityTokenKeyfile> SecurityTokenKeyfileList;
list <SecurityTokenKeyfilePath> SelectedSecurityTokenKeyfilePaths;
vector <shared_ptr<TokenKeyfile>> SecurityTokenKeyfileList;
list <TokenKeyfilePath> SelectedSecurityTokenKeyfilePaths;
};
}

View File

@ -795,7 +795,7 @@ namespace VeraCrypt
shared_ptr <VolumePassword> hiddenPassword;
try
{
hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password);
hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().ActivateEMVOption);
}
catch (...)
{
@ -846,7 +846,7 @@ namespace VeraCrypt
shared_ptr <VolumePassword> 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 (...)
{

View File

@ -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 <Keyfile> (wstring (path)));
}

View File

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

View File

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

View File

@ -63,7 +63,9 @@ namespace VeraCrypt
virtual void InsertToListCtrl (wxListCtrl *listCtrl, long itemIndex, const vector <wstring> &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 <VolumeInfo> MountVolume (MountOptions &options) const;
virtual void MoveListCtrlItem (wxListCtrl *listCtrl, long itemIndex, long newItemIndex) const;

View File

@ -21,7 +21,9 @@
#endif
#include <wx/platinfo.h>
#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 <Pkcs5Kdf>());
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> tokenKeyfile = Token::getTokenKeyfile(keyfilePath);
vector <byte> 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 <SecurityTokenInfo> tokens = SecurityToken::GetAvailableTokens();
list <shared_ptr<TokenInfo>> 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<TokenInfo> &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 <KeyfileList> 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<TokenKeyfile> 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 <VolumePassword> passwordKey = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password);
shared_ptr <VolumePassword> 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();

View File

@ -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 <VolumeInfo> MountVolume (MountOptions &options) const;
virtual bool OnInit ();

View File

@ -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 <const PCSCException *> (&ex))
{
string errorString = string (dynamic_cast <const PCSCException &> (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));
}
@ -480,6 +502,12 @@ namespace VeraCrypt
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"]);
EX2MSG (UnsupportedSectorSize, LangString["SECTOR_SIZE_UNSUPPORTED"]);
@ -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;
}
}

View File

@ -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 <VolumeInfo> MountVolume (MountOptions &options) const;
virtual shared_ptr <VolumeInfo> MountVolumeThread (MountOptions &options) const { return Core->MountVolume (options);}
virtual VolumeInfoList MountAllDeviceHostedVolumes (MountOptions &options) const;

View File

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

View File

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

View File

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

View File

@ -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 @@ static BOOL Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szFileName, int pim,
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 ();

View File

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

View File

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

View File

@ -108,6 +108,18 @@
<ClCompile Include="..\Setup\SelfExtract.c">
<Filter>Source Files\Setup</Filter>
</ClCompile>
<ClCompile Include="..\Common\EMVToken.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\Token.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\IccDataExtractor.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\TLVParser.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Midl Include="MainCom.idl">
@ -211,6 +223,18 @@
<ClInclude Include="..\Common\Xts.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\EMVToken.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\Token.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\IccDataExtractor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Common\TLVParser.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\Boot\Windows\Rescue_Serpent_SHA2\BootSector.bin">

View File

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

View File

@ -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 <byte> 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 <byte> keyfileData;
Token::getTokenKeyfile(wstring(Path))->GetKeyfileData(keyfileData);
if (keyfileData.size() < MinProcessedLength)
throw InsufficientData (SRC_POS, Path);
if (keyfileData.size() < MinProcessedLength)
throw InsufficientData(SRC_POS, Path);
for (size_t i = 0; i < keyfileData.size(); i++)
{
uint32 crc = crc32.Process (keyfileData[i]);
for (size_t i = 0; i < keyfileData.size(); i++) {
uint32 crc = crc32.Process(keyfileData[i]);
pool[poolPos++] += (byte) (crc >> 24);
pool[poolPos++] += (byte) (crc >> 16);
pool[poolPos++] += (byte) (crc >> 8);
pool[poolPos++] += (byte) crc;
pool[poolPos++] += (byte)(crc >> 24);
pool[poolPos++] += (byte)(crc >> 16);
pool[poolPos++] += (byte)(crc >> 8);
pool[poolPos++] += (byte) crc;
if (poolPos >= pool.Size())
poolPos = 0;
if (poolPos >= pool.Size())
poolPos = 0;
if (++totalLength >= MaxProcessedLength)
break;
}
if (++totalLength >= MaxProcessedLength)
break;
}
burn (&keyfileData.front(), keyfileData.size());
goto done;
}
file.Open (Path, File::OpenRead, File::ShareRead);
burn(&keyfileData.front(), keyfileData.size());
goto done;
}
while ((readLength = file.Read (keyfileBuf)) > 0)
{
for (size_t i = 0; i < readLength; i++)
{
uint32 crc = crc32.Process (keyfileBuf[i]);
file.Open (Path, File::OpenRead, File::ShareRead);
pool[poolPos++] += (byte) (crc >> 24);
pool[poolPos++] += (byte) (crc >> 16);
pool[poolPos++] += (byte) (crc >> 8);
pool[poolPos++] += (byte) crc;
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 (poolPos >= pool.Size())
poolPos = 0;
if (++totalLength >= MaxProcessedLength)
goto done;
}
}
done:
if (totalLength < MinProcessedLength)
throw InsufficientData (SRC_POS, Path);
}
shared_ptr <VolumePassword> Keyfile::ApplyListToPassword (shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> password)
shared_ptr <VolumePassword> Keyfile::ApplyListToPassword (shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> password, bool EMVOption)
{
if (!password)
password.reset (new VolumePassword);
@ -143,7 +139,7 @@ namespace VeraCrypt
// Apply all keyfiles
foreach_ref (const Keyfile &k, keyfilesExp)
{
k.Apply (keyfilePool);
k.Apply (keyfilePool, EMVOption);
}
newPassword->Set (keyfilePool);

View File

@ -29,7 +29,7 @@ namespace VeraCrypt
virtual ~Keyfile () { };
operator FilesystemPath () const { return Path; }
static shared_ptr <VolumePassword> ApplyListToPassword (shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> password);
static shared_ptr <VolumePassword> ApplyListToPassword (shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> password, bool EMVOption = false);
static shared_ptr <KeyfileList> DeserializeList (shared_ptr <Stream> stream, const string &name);
static void SerializeList (shared_ptr <Stream> stream, const string &name, shared_ptr <KeyfileList> keyfiles);
static bool WasHiddenFilePresentInKeyfilePath() { bool r = HiddenFileWasPresentInKeyfilePath; HiddenFileWasPresentInKeyfilePath = false; return r; }
@ -38,7 +38,7 @@ namespace VeraCrypt
static const size_t MaxProcessedLength = 1024 * 1024;
protected:
void Apply (const BufferPtr &pool) const;
void Apply (const BufferPtr &pool, bool EMVOption) const;
static bool HiddenFileWasPresentInKeyfilePath;

View File

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

View File

@ -123,8 +123,8 @@ namespace VeraCrypt
uint64 GetVolumeCreationTime () const { return Header->GetVolumeCreationTime(); }
bool IsHiddenVolumeProtectionTriggered () const { return HiddenVolumeProtectionTriggered; }
bool IsInSystemEncryptionScope () const { return SystemEncryption; }
void Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr <Pkcs5Kdf> protectionKdf = shared_ptr <Pkcs5Kdf> (),shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false);
void Open (shared_ptr <File> volumeFile, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr <Pkcs5Kdf> protectionKdf = shared_ptr <Pkcs5Kdf> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false);
void Open (const VolumePath &volumePath, bool preserveTimestamps, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr <Pkcs5Kdf> protectionKdf = shared_ptr <Pkcs5Kdf> (),shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), bool sharedAccessAllowed = false, VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false);
void Open (shared_ptr <File> volumeFile, shared_ptr <VolumePassword> password, int pim, shared_ptr <Pkcs5Kdf> kdf, bool truecryptMode, shared_ptr <KeyfileList> keyfiles, bool EMVOption, VolumeProtection::Enum protection = VolumeProtection::None, shared_ptr <VolumePassword> protectionPassword = shared_ptr <VolumePassword> (), int protectionPim = 0, shared_ptr <Pkcs5Kdf> protectionKdf = shared_ptr <Pkcs5Kdf> (), shared_ptr <KeyfileList> protectionKeyfiles = shared_ptr <KeyfileList> (), VolumeType::Enum volumeType = VolumeType::Unknown, bool useBackupHeaders = false, bool partitionInSystemEncryptionScope = false);
void ReadSectors (const BufferPtr &buffer, uint64 byteOffset);
void ReEncryptHeader (bool backupHeader, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr <Pkcs5Kdf> newPkcs5Kdf);
void WriteSectors (const ConstBufferPtr &buffer, uint64 byteOffset);

View File

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