Skip to content

Add PIV smart card keyfile encryption - #1451

Open
the-dan wants to merge 10 commits into
veracrypt:masterfrom
the-dan:integration
Open

the-dan wants to merge 10 commits into
veracrypt:masterfrom
the-dan:integration

Conversation

@the-dan

@the-dan the-dan commented Dec 3, 2024

Copy link
Copy Markdown

Add an option to create a keyfile which is encrypted using a smart card's private key (e.g. YubiKey)

Comment thread src/Common/Language.xml Outdated
Comment on lines +206 to +209
<entry lang="en" key="IDM_REVEAL_REDKEY">Reveal Red Key...</entry>
<entry lang="en" key="REVEAL_REDKEY_INFO">This will produce decrypted keyfile which can be used without using the smart card, thus reducing security to two factors. This keyfile should be stored securely. Are you sure to continue?</entry>
<entry lang="en" key="REVEAL_REDKEY_DONE">Red key is saved</entry>
<entry lang="en" key="REVEAL_REDKEY_PATH">Choose file to save red key to</entry>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addition of new entries must always be done at the bottom of the XML file to preserve position of existing entries.

Comment thread src/Common/Language.xml Outdated
Comment on lines +374 to +379
<entry lang="en" key="IDC_SECURITY_TOKEN_KEY">Security token key</entry>
<entry lang="en" key="IDT_SECURITY_TOKENS">Security Tokens...</entry>
<entry lang="en" key="TOKEN_SLOT_ID">Slot ID</entry>
<entry lang="en" key="SELECT_TOKEN_KEYS">Select token keys</entry>
<entry lang="en" key="TOKEN_NAME">Token name</entry>
<entry lang="en" key="TOKEN_KEY_LABEL">Key label</entry>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: new entries should be added at the bottom.

Comment thread src/Common/SecurityToken.cpp Outdated
Comment on lines +266 to +275
if (privateAttrib.size() == sizeof (CK_BBOOL) && *(CK_BBOOL *) &privateAttrib.front() != CK_TRUE)
continue;

GetObjectAttribute (slotId, dataHandle, CKA_MODULUS_BITS, privateAttrib);
if (privateAttrib.size() == sizeof (CK_ULONG)) {
CK_ULONG modulus = *(CK_ULONG *) &privateAttrib.front();
key.maxDecryptBufferSize = modulus / 8 - 11;
key.maxEncryptBufferSize = modulus / 8;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic will fail for cards that contain ECC keys. Since the current implementation supports only RSA keys, the code should use CKA_KEY_TYPE to restrict logic to RSA keys only (CKK_RSA)

Comment thread src/Common/SecurityToken.cpp Outdated
Comment on lines +358 to +364
GetObjectAttribute (slotId, dataHandle, CKA_MODULUS_BITS, publicAttrib);
if (publicAttrib.size() == sizeof (CK_ULONG)) {
CK_ULONG modulus = *(CK_ULONG *) &publicAttrib.front();
key.maxDecryptBufferSize = modulus / 8 - 11;
key.maxEncryptBufferSize = modulus / 8;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above: the code should restrict logic to RSA keys only.

Comment thread src/Common/SecurityToken.cpp Outdated
Comment on lines +643 to +644
CK_MECHANISM m = { CKM_RSA_PKCS, 0, 0 };
CK_RV status = Pkcs11Functions->C_EncryptInit (Sessions[slotId].Handle, &m, tokenObject);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not use CKM_RSA_PKCS since it is insecure. We must use CKM_RSA_PKCS_OAEP with SHA256 MGF.

Comment thread src/Common/SecurityToken.cpp Outdated
Comment on lines +671 to +672
CK_MECHANISM m = { CKM_RSA_PKCS, 0, 0 };
CK_RV status = Pkcs11Functions->C_DecryptInit (Sessions[slotId].Handle, &m, tokenObject);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like above, we should not use CKM_RSA_PKCS since it is insecure. We must use CKM_RSA_PKCS_OAEP with SHA256 MGF.

@idrassi

idrassi commented Dec 8, 2024

Copy link
Copy Markdown
Member

@the-dan Thank you for this contribution.
Native support for PKI smart cards has always been planned but I personally never found the time to work on it. Your approach strikes a good balance between native support and the keyfiles mechanism, making it a strong first step.

I will need some time to review the code changes because there are so many...this is the largest PR I have ever had to review.

That being said, I have already provided some comments and will add more as I progress with the review.

In addition to security token keys show compatible and approved
security token mechanism. Together they will be used to create an
encrypted keyfile
@the-dan

the-dan commented Feb 6, 2025

Copy link
Copy Markdown
Author

@idrassi I’m happy that this change aligns with VeraCrypt’s direction.

Thanks for going through this! I haven’t touched the encryption part since the initial prototype started working, which is why plain RSA PKCS was used.

Instead of selecting only RSA keys and locking in the mechanism, I revisited the approach to make it more flexible. For now, it supports only RSA OAEP, but I believe it could be extended in the future.

Please take a look when you have time. Apologies for the large commits—this time, I also did a lot of renaming for clarity, which affected many files

@war59312

Copy link
Copy Markdown

DOA?

@idrassi

idrassi commented May 20, 2026

Copy link
Copy Markdown
Member

@war59312 This feature is not dead. It is just the amount of work necessary for its integration is not trivial and there are issues that have more demand from user community. Of course, if someone is willing to sponsor work on it, it can get more priority.
Anyway, I will try to revive this PR after I finish preparing 1.26.28 version.

Reconcile PIV keyfile support with the current KDF/password APIs, hidden
volume protection, FUSE service lifecycle, and reproducible build rules.
Preserve upstream CoreTest.cpp and rename the PR's standalone suite to
KeyfileTest.cpp, using the selected FUSE package when linking it.

Move Bluekeys documentation into doc/html/en, reuse existing localization
keys, and append English fallbacks for the nine new keys to all language
packs. Register the hidden-volume security-token CLI option so startup
and the built-in self-tests work with current wxWidgets.

Validation:
- Linux GUI build: make -j6 WITHFUSE3=1
- Built-in algorithm, platform, and core self-tests
- Six pipeline-stream tests and three mock-token keyfile tests
- XML validation for the English resource and all 42 translations
Validate OAEP keys, descriptors, PIN/session state and output lengths.
Wipe plaintext buffers and write keyfiles atomically.

Fix Unix GUI/CLI credential flows and preserve legacy keyfile behavior.
Keep regression tests optional and document recovery and platform limits.

Validated Linux GUI/console builds, 39 regression tests, token sanitizers,
SoftHSM interoperability and localization XML.
… writes

Keep the unmarked keyfile format. Require an explicit new token choice for
unattended credential changes, inherit the current key in the GUI until edited,
and confirm token removal. Preserve redirected TUI input and retry keyfiles.

Resolve credentials before creation opens its destination and reuse them for
formatting. Resolve external restore credentials once and prepare both headers
before writing. Reject non-regular atomic destinations and distinguish a
published file with uncertain durability from a failed publication.

Resolve token IDs across matching slots, expose slot alternatives, and allow a
unique matching public object to supply a private key's RSA modulus. Add typed,
localized errors, console recovery export, clearer key selection, mount-helper
forwarding, documentation, and Linux CI regression coverage. Remove unreachable
PKCS#1 v1.5 support and late static-destructor provider shutdown.

Validation: Linux GUI and clean console builds without warnings; 49 C++ tests
on both builds; credential, backup-retry and redirected-input harnesses; actual
wxWidgets credential dialogs under Xvfb; RSA-2048 and RSA-3072 always-authenticate
software-token workflows including independent OAEP verification and recovery.
Hardware with released providers and native Windows/macOS/FreeBSD validation
remain release gates. Original contributor history is retained.
Preserve current upstream translations and append the 28 PIV keyfile
entries in the English resource and all 42 language packs.

Keep the PR's stream-based keyfile implementation. Its WipeVector guard
is installed before token data retrieval and SecureBuffer owns the
plaintext stream, preserving upstream's cleanup-on-failure fix.

Adapt the new volume-read test to the security-token descriptor argument.

Validation:
- Linux console and GUI builds with FUSE 3; 49 standalone tests on each
- Algorithm self-tests on both builds
- Token credential, backup-header retry and redirected CLI workflows
- Actual GUI token-dialog regression under Xvfb
- Single- and multi-threaded reads across all five volume fixtures
- XML structure, keys and escapes checked across all 43 language resources
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants