Skip to content

New features added to VeraCryptFormat.dll#1659

Open
YonyUk wants to merge 3 commits intoveracrypt:masterfrom
YonyUk:yonyuk-contrib
Open

New features added to VeraCryptFormat.dll#1659
YonyUk wants to merge 3 commits intoveracrypt:masterfrom
YonyUk:yonyuk-contrib

Conversation

@YonyUk
Copy link
Copy Markdown

@YonyUk YonyUk commented Feb 16, 2026

Pull Request: Extend VeraCrypt Format SDK with Mount/Dismount Support and Enum-Based Configuration

Summary

This PR extends the VeraCrypt Format SDK by adding volume mounting and dismounting capabilities, replacing string-based algorithm and filesystem identifiers with enums, introducing size units for container creation, and providing utility functions for path resolution.

Detailed Changes

1. New Enumerations for Type-Safe Configuration

  • DriveLetter: Defines all possible drive letters (A–Z) for mount operations.
  • VolumeEncryptionAlgorithm: Replaces free-form encryption algorithm strings with a fixed list of supported algorithms (e.g., AES, Serpent, cascades).
  • HashAlgorithm: Replaces hash algorithm strings with an enum covering all supported PRF/Hash functions.
  • FileSystemFormat: Replaces filesystem strings with an enum (NTFS, FAT, ExFAT, ReFS, None).
  • SizeMeasureUnity: Allows specifying container size in KB, MB, or GB instead of raw bytes.

Rationale: Using enums eliminates the risk of typos, simplifies validation, and makes the API self-documenting. It also enables better compile-time checks for client applications.

2. Modified VeraCryptFormatOptions Structure

  • Changed encryptionAlgorithm, hashAlgorithm, and filesystem from const wchar_t* to the respective enum types.
  • Added sizeMeasureUnity field to interpret the size field in kilobytes, megabytes, or gigabytes.
  • This is a breaking change for existing clients; they must migrate to enum values and adjust size calculations.

3. New Mount/Dismount Functionality

  • VeraCryptMount: Mounts an existing VeraCrypt volume to a specified drive letter.
    • Accepts a VeraCryptMountOptions struct containing password, keyfiles, PIM, mount flags (read-only, hidden volume protection, etc.), and optional hidden volume password.
    • Supports auto-detection of encryption algorithm.
    • Handles hidden volume protection and caching options.
  • VeraCryptDismount: Unmounts a volume from a given drive letter, with an option to force dismount.
  • GetAbsolutePath: Converts a relative path to an absolute path (useful for resolving keyfile or container paths).
  • GetDevicePath: Retrieves the Windows device path (e.g., \Device\HarddiskVolumeX) for a mounted drive letter.

Rationale: These additions transform the SDK from a volume-creation-only tool into a comprehensive volume management library, enabling applications to fully integrate VeraCrypt operations.

4. Internal Improvements

  • Added constexpr arrays in the .cpp file to map enum values to the corresponding string identifiers required by the underlying VeraCrypt core.
  • Updated CreateVolumeInternal to use these mappings and to compute the actual byte size based on sizeMeasureUnity.
  • Implemented VeraCryptMount by leveraging VeraCrypt’s MountVolume function, carefully managing global state and cleaning up sensitive data with finally_do.
  • Added validation for drive letter availability.
  • Introduced two new error codes: VCF_ERROR_FULL_PATH_GETTING_ERROR (24) and VCF_ERROR_DRIVE_LETTER_UNAVIABLE (25).

6. Header and Documentation Updates

  • Expanded VeraCryptFormatSDK.h with detailed comments for new structures and functions.
  • Added missing includes in the .cpp file (<array>, <Shlwapi.h>) to support new functionality.

Breaking Changes & Migration Guide

  • VeraCryptFormatOptions:
    • encryptionAlgorithm, hashAlgorithm, filesystem are now enums. Replace string literals with the corresponding enum values (e.g., L"AES"VERACRYPT_VOLUME_ENCRYPTION_AES).
    • size now requires sizeMeasureUnity to be set. Previously size was in bytes; now specify the unit separately. For example, to create a 100 MB container, set size = 100, sizeMeasureUnity = Megabytes.
  • Clients using the old string-based API must update their code accordingly.

@idrassi
Copy link
Copy Markdown
Member

idrassi commented Apr 13, 2026

Thank you for the contribution.
I reviewed the changes and this PR cannot be merged in its current form. The direction of extending the Format SDK with mount/dismount support is useful but the current implementation has several correctness and API issues that need a rework rather than small fixes.

Main blockers:

  1. VeraCryptMount passes the wrong value to MountVolume

MountVolume takes int pkcs5 as its fifth parameter, i.e. the PRF/hash algorithm used for header key derivation. The PR currently passes:

options->autoDetectEncryptionAlgorithm ? 0 : static_cast<int>(options->encryptionAlgorithm)

That is an encryption algorithm enum value, not a PRF/hash id. The mount API should expose a PRF/hash option or use 0 for autodetection. Encryption algorithm selection is not the right parameter here.

  1. Mount failures are reported as success

MountVolume returns:

  • 1 for successful exclusive mount
  • 2 for successful shared mount
  • 0 for mount failure, including wrong password
  • -1 for error/user-abort paths

But VeraCryptMount returns raw 0 when MountVolume fails, and 0 is VCF_SUCCESS. This means a wrong password or normal mount failure can be reported to SDK callers as success. This is a critical bug and needs explicit mapping to nonzero SDK error codes.

  1. The public C ABI is broken

The header uses declarations such as:

typedef enum DriveLetter {
...
};

This does not create a C typedef named DriveLetter: it only defines enum DriveLetter. Later declarations like DriveLetter letter; therefore do not work for C consumers. Since this is a C-style DLL API, the header must be valid C as well as C++.

  1. Existing VeraCryptFormat callers would be ABI-broken

VeraCryptFormatOptions is changed in place: string fields are replaced with enums and a new sizeMeasureUnity field is inserted. Existing clients compiled against the current SDK header would pass the old struct layout to the same exported VeraCryptFormat function, and the DLL would misinterpret the fields.

Please either preserve the existing struct/API or introduce a versioned API, for example VeraCryptFormatOptionsV2 plus VeraCryptFormatEx, preferably with a structSize field for forward compatibility.

  1. Enum values are used as unchecked array indexes

The PR indexes arrays with values coming from public enum fields:

VolumeEncryptionAlgorithmOptions[static_cast(options->encryptionAlgorithm)]
HashAlgorithmOptions[static_cast(options->hashAlgorithm)]
FileSystemFormatOptions[static_cast(options->filesystem)]

For a C ABI, callers can pass any integer value. These must be bounds-checked before indexing.

  1. The hash enum does not match current VeraCrypt master

Current master supports SHA-512, SHA-256, BLAKE2s-256, Whirlpool, Streebog, and BLAKE2b-512/Argon2 in the current hash table. The PR exposes RIPEMD-160, which is no longer present in the current table and omits Streebog and BLAKE2b-512.

  1. Mount input validation and path handling need work

VeraCryptMount dereferences options before checking it, does not validate options->path and passes the caller-provided path buffer directly to MountVolume.
MountVolume can modify the path buffer, so the SDK should copy the path into an internal writable TC_MAX_PATH buffer before calling it.

Suggested way forward:

  • Keep the existing VeraCryptFormat ABI unchanged, or introduce a versioned V2 API.
  • Fix the public header so it is valid C.
  • Add explicit validation for all public enum values.
  • For mount, expose a PRF/hash option rather than an encryption algorithm option.
  • Map all internal mount results to SDK-specific nonzero error codes.
  • Copy mutable inputs into SDK-owned buffers before passing them to internal VeraCrypt functions.
  • Add at least basic SDK tests or a sample covering create, mount success, wrong password, invalid enum, keyfile use, and dismount.

I recommend reworking the API and implementation around these points before continuing with merge review.

Copy link
Copy Markdown
Member

@idrassi idrassi left a comment

Choose a reason for hiding this comment

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

Requesting changes because the current implementation has several merge-blocking API and correctness issues: the public C header is not valid C, the existing VeraCryptFormatOptions ABI is broken in place, mount passes an encryption enum as the PRF/hash parameter, mount failures can be returned as VCF_SUCCESS, public enum values are used as unchecked array indexes, and VeraCryptMount lacks basic input/path validation.

The feature direction is useful, but this should be reworked around a versioned SDK API, validated enum mappings, correct mount PRF handling, explicit SDK error mapping, and safe copying of mutable inputs before calling internal VeraCrypt functions.

Comment on lines +45 to +72
typedef enum DriveLetter {
DRIVE_LETTER_A = 0,
DRIVE_LETTER_B,
DRIVE_LETTER_C,
DRIVE_LETTER_D,
DRIVE_LETTER_E,
DRIVE_LETTER_F,
DRIVE_LETTER_G,
DRIVE_LETTER_H,
DRIVE_LETTER_I,
DRIVE_LETTER_J,
DRIVE_LETTER_K,
DRIVE_LETTER_L,
DRIVE_LETTER_M,
DRIVE_LETTER_N,
DRIVE_LETTER_O,
DRIVE_LETTER_P,
DRIVE_LETTER_Q,
DRIVE_LETTER_R,
DRIVE_LETTER_S,
DRIVE_LETTER_T,
DRIVE_LETTER_U,
DRIVE_LETTER_V,
DRIVE_LETTER_W,
DRIVE_LETTER_X,
DRIVE_LETTER_Y,
DRIVE_LETTER_Z
};
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 breaks the public C header. In C, typedef enum DriveLetter { ... }; does not create a typedef named DriveLetter; it only declares enum DriveLetter. The later fields using DriveLetter, VolumeEncryptionAlgorithm, etc. will not compile for C consumers of this C-style DLL API.

Please use the C-compatible form for all these enums, e.g.:

typedef enum DriveLetter {
    ...
} DriveLetter;

int pim;

/** size measure unity */
SizeMeasureUnity sizeMeasureUnity;
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 changes the existing VeraCryptFormatOptions layout in place while keeping the same exported VeraCryptFormat API. Existing SDK clients compiled against the current header will pass the old struct layout, and the new DLL will interpret the following fields incorrectly.

This needs to preserve the existing ABI, or introduce a versioned API/struct, e.g. VeraCryptFormatOptionsV2 plus VeraCryptFormatEx, preferably with a structSize field for forward compatibility.

typedef enum HashAlgorithm{
VERACRYPT_HASH_SHA_512 = 0,
VERACRYPT_HASH_SHA_256,
VERACRYPT_HASH_RIPEMD_160,
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 hash enum does not match current VeraCrypt master. RIPEMD-160 is no longer present in the current hash table, while Streebog and BLAKE2b-512/Argon2 are supported. This would expose an invalid option and omit valid ones.

Please derive this list from the current PRF/hash support or update the enum and mapping to match Crypto.c.

}

nVolumeEA = MapEncryptionAlgorithm(options->encryptionAlgorithm);
nVolumeEA = MapEncryptionAlgorithm(VolumeEncryptionAlgorithmOptions[static_cast<int>(options->encryptionAlgorithm)]);
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 indexes a fixed array using a public enum value without bounds checking. Since this is a C ABI, callers can pass any integer value, not only valid enum constants. An invalid value here can read out of bounds before MapEncryptionAlgorithm has a chance to reject it.

The same issue exists for HashAlgorithmOptions and FileSystemFormatOptions below. Please validate each enum value before indexing, and return the appropriate VCF_ERROR_INVALID_* code.

bDevice = options->isDevice;
nVolumeSize = options->size;
if (!options->isDevice) {
nVolumeSize = options->size * (options->sizeMeasureUnity == SizeMeasureUnity::Kilobytes ?
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 multiplication can overflow uint64_t before the later size checks run. For example, a large options->size value with Gigabytes can wrap to a small value and pass subsequent validation incorrectly.

Please validate sizeMeasureUnity, check options->size <= UINT64_MAX / multiplier, and update the public comment because size is no longer always expressed in bytes.

KeyFileRemoveAll(&FirstKeyFile);
});

if (!IsDriveAvailable(static_cast<int>(options->letter))) {
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.

options is dereferenced here before any null check, and options->path is not validated at all. A null options or null/empty path will crash instead of returning VCF_ERROR_INVALID_PARAMETER.

Please validate options, options->path, and required password/keyfile inputs before using any fields.

mountOptions.SkipCachedPasswords = options->SkipCachedPasswords;
mountOptions.UseBackupHeader = options->UseBackupHeader;

int result = MountVolume(NULL, static_cast<int>(options->letter), options->path, &volumePassword,
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.

MountVolume can modify the volumePath buffer it receives. Passing options->path directly makes the SDK mutate caller-owned input, and the public struct does not document that requirement.

Please copy options->path into an SDK-owned writable buffer, sized for TC_MAX_PATH, validate/copy safely, and pass that internal buffer to MountVolume.

mountOptions.UseBackupHeader = options->UseBackupHeader;

int result = MountVolume(NULL, static_cast<int>(options->letter), options->path, &volumePassword,
options->autoDetectEncryptionAlgorithm ? 0 : static_cast<int>(options->encryptionAlgorithm),
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 passes an encryption algorithm enum where MountVolume expects the pkcs5 PRF/hash id. The fifth parameter of MountVolume is int pkcs5, not an encryption algorithm selector.

The mount API should expose a PRF/hash option, or pass 0 for autodetection. Encryption algorithm selection is not the right parameter for this call.

if (options->sharedAccess)
return result == 2 ? VCF_SUCCESS : result;
return result == 1 ? VCF_SUCCESS : result;
}
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 maps mount failures to VCF_SUCCESS. MountVolume returns 0 for mount failure, including wrong password, and VCF_SUCCESS is also 0. As written, a wrong password can be reported to SDK callers as success.

Please map MountVolume results explicitly: 1 and 2 should map to VCF_SUCCESS, while 0 and -1 must map to nonzero SDK error codes.

@idrassi idrassi self-assigned this Apr 13, 2026
@YonyUk
Copy link
Copy Markdown
Author

YonyUk commented Apr 13, 2026 via email

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.

2 participants