diff --git a/src/FormatDLL/VeraCryptFormatSDK.cpp b/src/FormatDLL/VeraCryptFormatSDK.cpp index e841c0c11e..acb2390c36 100644 --- a/src/FormatDLL/VeraCryptFormatSDK.cpp +++ b/src/FormatDLL/VeraCryptFormatSDK.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include "Dlgcode.h" #include "Crypto.h" @@ -73,6 +75,39 @@ extern "C" DWORD GetFormatSectorSize(); void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine); void cleanup (); +constexpr std::array VolumeEncryptionAlgorithmOptions = std::array{ + L"AES", + L"Serpent", + L"Twofish", + L"Camellia", + L"Kuznyechik", + L"Serpent(Twofish(AES))", + L"Serpent(AES)", + L"AES(Twofish(Serpent))", + L"Twofish(Serpent)", + L"Camellia(Kuznyechik)", + L"Kuznyechik(Twofish)", + L"Camellia(Serpent)", + L"Kuznyechik(AES)", + L"Kuznyechik(Serpent(Camellia))", +}; + +constexpr std::array HashAlgorithmOptions = std::array{ + L"SHA-512", + L"SHA-256", + L"RIPEMD-160", + L"Whirlpool", + L"BLAKE2s-256" +}; + +constexpr std::array FileSystemFormatOptions = std::array{ + L"NTFS", + L"FAT", + L"ExFAT", + L"ReFS", + L"None" +}; + // Global mutex to ensure that volume creation operations are serialized, // as the underlying code uses extensive global state. static std::mutex g_sdkMutex; @@ -184,15 +219,18 @@ static int CreateVolumeInternal(const VeraCryptFormatOptions* options) // --- Setup VeraCrypt's global state from our options struct --- bDevice = options->isDevice; - nVolumeSize = options->size; + if (!options->isDevice) { + nVolumeSize = options->size * (options->sizeMeasureUnity == SizeMeasureUnity::Kilobytes ? + 1024 : options->sizeMeasureUnity == SizeMeasureUnity::Megabytes ? 1024 * 1024 : 1024 * 1024 * 1024); + } - nVolumeEA = MapEncryptionAlgorithm(options->encryptionAlgorithm); + nVolumeEA = MapEncryptionAlgorithm(VolumeEncryptionAlgorithmOptions[static_cast(options->encryptionAlgorithm)]); if (nVolumeEA == 0) return VCF_ERROR_INVALID_ENCRYPTION_ALGORITHM; - hash_algo = MapHashAlgorithm(options->hashAlgorithm); + hash_algo = MapHashAlgorithm(HashAlgorithmOptions[static_cast(options->hashAlgorithm)]); if (hash_algo == 0) return VCF_ERROR_INVALID_HASH_ALGORITHM; - fileSystem = MapFilesystem(options->filesystem); + fileSystem = MapFilesystem(FileSystemFormatOptions[static_cast(options->filesystem)]); if (fileSystem == -1) return VCF_ERROR_INVALID_FILESYSTEM; volumePim = options->pim; @@ -332,7 +370,6 @@ static int CreateVolumeInternal(const VeraCryptFormatOptions* options) } } - // --- Public DLL Exported Functions --- extern "C" @@ -378,6 +415,161 @@ extern "C" return CreateVolumeInternal(options); } + VCF_API int __cdecl VeraCryptMount(const VeraCryptMountOptions* options) { + if (!g_isInitialized) + { + return VCF_ERROR_NOT_INITIALIZED; + } + + // Lock the mutex to protect the global state used by VeraCrypt's format code + std::lock_guard lock(g_sdkMutex); + + finally_do({ + // Clean up all sensitive data from globals + WipePasswordsAndKeyfiles(true); + // Reset globals to default state + KeyFileRemoveAll(&FirstKeyFile); + }); + + if (!IsDriveAvailable(static_cast(options->letter))) { + return VCF_ERROR_DRIVE_LETTER_UNAVIABLE; + } + + MountOptions mountOptions = { 0 }; + + if (options->password) + { + if (!CheckPasswordLength(NULL, (int)strlen(options->password), options->pim, FALSE, 0, TRUE, TRUE)) + { + return VCF_ERROR_PASSWORD_POLICY; + } + strcpy_s((char*)volumePassword.Text, sizeof(volumePassword.Text), options->password); + volumePassword.Length = (unsigned __int32)strlen(options->password); + } + else + { + volumePassword.Text[0] = 0; + volumePassword.Length = 0; + } + + if (options->protectedHidVolPassword) { + if (!CheckPasswordLength(NULL, (int)strlen(options->protectedHidVolPassword), options->pim, FALSE, 0, TRUE, TRUE)) { + return VCF_ERROR_PASSWORD_POLICY; + } + strcpy_s((char*)mountOptions.ProtectedHidVolPassword.Text, sizeof(mountOptions.ProtectedHidVolPassword.Text), options->protectedHidVolPassword); + mountOptions.ProtectedHidVolPassword.Length = (unsigned __int32)strlen(options->protectedHidVolPassword); + } + else { + mountOptions.ProtectedHidVolPassword.Text[0] = 0; + mountOptions.ProtectedHidVolPassword.Length = 0; + } + + FirstKeyFile = nullptr; + if (options->keyfiles) + { + for (int i = 0; options->keyfiles[i] != nullptr; ++i) + { + KeyFile* kf = (KeyFile*)malloc(sizeof(KeyFile)); + if (!kf) + { + KeyFileRemoveAll(&FirstKeyFile); + return VCF_ERROR_OUT_OF_MEMORY; + } + StringCbCopyW(kf->FileName, sizeof(kf->FileName), options->keyfiles[i]); + FirstKeyFile = KeyFileAdd(FirstKeyFile, kf); + } + } + + if (!KeyFilesApply(NULL, &volumePassword, FirstKeyFile, NULL)) + { + return VCF_ERROR_KEYFILE_ERROR; + } + mountOptions.DisableMountManager = options->DisableMountManager; + StringCbCopyW(mountOptions.Label, sizeof(mountOptions.Label), options->Label); + mountOptions.PartitionInInactiveSysEncScope = options->PartitionInInactiveSysEncScope; + mountOptions.PreserveTimestamp = options->PreserveTimestamp; + mountOptions.ProtectedHidVolPim = options->ProtectedHidVolPim; + mountOptions.ProtectedHidVolPkcs5Prf = options->ProtectedHidVolPkcs5Prf; + mountOptions.ProtectHiddenVolume = options->ProtectHiddenVolume; + mountOptions.ReadOnly = options->ReadOnly; + mountOptions.RecoveryMode = options->RecoveryMode; + mountOptions.Removable = options->Removable; + mountOptions.SkipCachedPasswords = options->SkipCachedPasswords; + mountOptions.UseBackupHeader = options->UseBackupHeader; + + int result = MountVolume(NULL, static_cast(options->letter), options->path, &volumePassword, + options->autoDetectEncryptionAlgorithm ? 0 : static_cast(options->encryptionAlgorithm), + options->pim, options->cachePassword, options->cachePim, options->sharedAccess, &mountOptions, + TRUE, TRUE + ); + if (options->sharedAccess) + return result == 2 ? VCF_SUCCESS : result; + return result == 1 ? VCF_SUCCESS : result; + } + + VCF_API int __cdecl VeraCryptDismount(DriveLetter letter, BOOL force) { + if (!g_isInitialized) + { + return VCF_ERROR_NOT_INITIALIZED; + } + + // Lock the mutex to protect the global state used by VeraCrypt's format code + std::lock_guard lock(g_sdkMutex); + + return UnmountVolume(NULL, static_cast(letter), force) == TRUE ? VCF_SUCCESS : VCF_ERROR_GENERIC; + } + + VCF_API int __cdecl GetAbsolutePath(const wchar_t* relativePath, wchar_t* absolutePath, DWORD absolutePathSize) + { + if (!relativePath || !absolutePath || absolutePathSize == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return VCF_ERROR_FULL_PATH_GETTING_ERROR; + } + + absolutePath[0] = L'\0'; + + DWORD requiredSize; + + requiredSize = GetFullPathNameW(relativePath, 0, NULL, NULL); + if (requiredSize == 0) + { + return VCF_ERROR_FULL_PATH_GETTING_ERROR; + } + + if (requiredSize > absolutePathSize) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return VCF_ERROR_FULL_PATH_GETTING_ERROR; + } + + DWORD result = GetFullPathNameW(relativePath, absolutePathSize, absolutePath, NULL); + if (result == 0 || result >= absolutePathSize) + { + return VCF_ERROR_FULL_PATH_GETTING_ERROR; + } + + return VCF_SUCCESS; + } + + VCF_API int __cdecl GetDevicePath(DriveLetter letter, wchar_t* devicePath, DWORD devicePathSize) + { + if (!devicePath || devicePathSize == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return VCF_ERROR_FULL_PATH_GETTING_ERROR; + } + devicePath[0] = L'\0'; + + wchar_t drive[4] = { static_cast(L'A' + static_cast(letter)), L':', L'\0' }; + if (QueryDosDeviceW(drive, devicePath, devicePathSize) == 0) + { + // Error, possibly insufficient buffer + return VCF_ERROR_FULL_PATH_GETTING_ERROR; + } + return VCF_SUCCESS; + } + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) diff --git a/src/FormatDLL/VeraCryptFormatSDK.h b/src/FormatDLL/VeraCryptFormatSDK.h index 5f77cdbb12..e1b441aad1 100644 --- a/src/FormatDLL/VeraCryptFormatSDK.h +++ b/src/FormatDLL/VeraCryptFormatSDK.h @@ -39,7 +39,84 @@ extern "C" { #endif // --- Public Data Structures and Callbacks --- - +/** +* @brief enum with all the drive letters aviables +*/ +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 +}; +/** +* @brief enum with all the encryption algorithms aviables for volumen creation +*/ +typedef enum VolumeEncryptionAlgorithm{ + VERACRYPT_VOLUME_ENCRYPTION_AES = 0, + VERACRYPT_VOLUME_ENCRYPTION_Serpent, + VERACRYPT_VOLUME_ENCRYPTION_Twofish, + VERACRYPT_VOLUME_ENCRYPTION_Camellia, + VERACRYPT_VOLUME_ENCRYPTION_Kuznyechik, + VERACRYPT_VOLUME_ENCRYPTION_AES_Twofish_Serpent, + VERACRYPT_VOLUME_ENCRYPTION_AES_Serpent, + VERACRYPT_VOLUME_ENCRYPTION_Serpent_Twofish_AES, + VERACRYPT_VOLUME_ENCRYPTION_Serpent_Twofish, + VERACRYPT_VOLUME_ENCRYPTION_Kuznyechik_Camellia, + VERACRYPT_VOLUME_ENCRYPTION_Twofish_Kuznyechik, + VERACRYPT_VOLUME_ENCRYPTION_Serpent_Camellia, + VERACRYPT_VOLUME_ENCRYPTION_AES_Kuznyechik, + VERACRYPT_VOLUME_ENCRYPTION_Camellia_Serpent_Kuznyechik +}; +/** +* @brief enum with all the hash algorithms aviables for volumen creation +*/ +typedef enum HashAlgorithm{ + VERACRYPT_HASH_SHA_512 = 0, + VERACRYPT_HASH_SHA_256, + VERACRYPT_HASH_RIPEMD_160, + VERACRYPT_HASH_Whirlpool, + VERACRYPT_HASH_BLAKE2s_256 +}; +/** +* @brief enum with all the filesystem format options aviables for volumen creation +*/ +typedef enum FileSystemFormat{ + VERACRYPT_FILESYSTEM_FORMAT_NTFS = 0, + VERACRYPT_FILESYSTEM_FORMAT_FAT, + VERACRYPT_FILESYSTEM_FORMAT_ExFAT, + VERACRYPT_FILESYSTEM_FORMAT_ReFS, + VERACRYPT_FILESYSTEM_FORMAT_None +}; +/** +* @brief enum with all the size measure unity options aviables for volumen creation +*/ +typedef enum SizeMeasureUnity{ + Kilobytes = 0, + Megabytes, + Gigabytes +}; /** * @brief Defines the parameters for creating a VeraCrypt volume. */ @@ -60,17 +137,20 @@ typedef struct _VeraCryptFormatOptions /** The Personal Iterations Multiplier (PIM). Use 0 for default PIM. */ int pim; + /** size measure unity */ + SizeMeasureUnity sizeMeasureUnity; + /** The size of the volume in bytes. This is only used for file containers (when isDevice is FALSE). Must be a multiple of 512. */ uint64_t size; - /** The encryption algorithm to use. E.g., L"AES", L"Serpent", L"Twofish", L"AES-Twofish-Serpent". */ - const wchar_t* encryptionAlgorithm; + /** The encryption algorithm to use. E.g., AES, Serpent, Twofish, AES_Twofish_Serpent. */ + VolumeEncryptionAlgorithm encryptionAlgorithm; - /** The header key derivation and random pool hash algorithm. E.g., L"SHA-512", L"RIPEMD-160", L"Whirlpool", L"BLAKE2s-256", L"SHA-256". */ - const wchar_t* hashAlgorithm; + /** The header key derivation and random pool hash algorithm. E.g., SHA_512, RIPEMD_160, Whirlpool, BLAKE2s_256, SHA_256. */ + HashAlgorithm hashAlgorithm; - /** The filesystem for the new volume. E.g., L"NTFS", L"FAT", L"ExFAT", L"ReFS", or L"None". */ - const wchar_t* filesystem; + /** The filesystem for the new volume. E.g., NTFS, FAT, ExFAT, ReFS, or None. */ + FileSystemFormat filesystem; /** The cluster size in sectors (e.g., 1, 2, 4, 8...). Use 0 for default. */ int clusterSize; @@ -91,7 +171,34 @@ typedef struct _VeraCryptFormatOptions void* progressUserData; } VeraCryptFormatOptions; - +/** +* @brief Defines the parameters for mount a volume +*/ +typedef struct _VeraCryptMountOptions { + int pim; + DriveLetter letter; + const char* password; + const char* protectedHidVolPassword;/* Password of hidden volume to protect against overwriting */ + wchar_t* path; + VolumeEncryptionAlgorithm encryptionAlgorithm; + const wchar_t** keyfiles; + BOOL autoDetectEncryptionAlgorithm; + BOOL ReadOnly; + BOOL Removable; + BOOL ProtectHiddenVolume; + BOOL PreserveTimestamp; + BOOL PartitionInInactiveSysEncScope; /* If TRUE, we are to attempt to mount a partition located on an encrypted system drive without pre-boot authentication. */ + BOOL UseBackupHeader; + BOOL RecoveryMode; + int ProtectedHidVolPkcs5Prf; + int ProtectedHidVolPim; + wchar_t Label[33]; /* maximum label length is 32 for NTFS and 11 for FAT32 */ + BOOL DisableMountManager; + BOOL SkipCachedPasswords; + BOOL cachePassword; + BOOL cachePim; + BOOL sharedAccess; +} VeraCryptMountOptions; /** * @brief Progress callback function pointer type. * @param percentComplete The percentage of the format operation that is complete (0-100). @@ -99,8 +206,6 @@ typedef struct _VeraCryptFormatOptions * @return Returns TRUE to continue the operation, or FALSE to abort it. */ typedef BOOL (CALLBACK *VeraCrypt_Progress_Callback)(int percentComplete, void* userData); - - // --- Public Error Codes --- #define VCF_SUCCESS 0 #define VCF_ERROR_GENERIC 1 // A generic or unknown error occurred. @@ -125,8 +230,8 @@ typedef BOOL (CALLBACK *VeraCrypt_Progress_Callback)(int percentComplete, void* #define VCF_ERROR_FILESYSTEM_INVALID_FOR_SIZE 21 // The selected filesystem cannot be used for the given volume size. #define VCF_ERROR_CONTAINER_TOO_LARGE_FOR_HOST 22 // The file container is larger than the available free space. #define VCF_ERROR_ACCESS_DENIED 23 // The target path is read-only or cannot be created. - - +#define VCF_ERROR_FULL_PATH_GETTING_ERROR 24 +#define VCF_ERROR_DRIVE_LETTER_UNAVIABLE 25 // --- Public API Functions --- /** @@ -156,7 +261,29 @@ VCF_API void __cdecl VeraCryptFormat_Shutdown(); * @return Returns VCF_SUCCESS (0) on success, or a non-zero VCF_ERROR_* code on failure. */ VCF_API int __cdecl VeraCryptFormat(const VeraCryptFormatOptions* options); - +/** +* @brief get the absolute path into the absolutePath parameter +*/ +VCF_API int __cdecl GetAbsolutePath(const wchar_t* relativePath, wchar_t* absolutePath, DWORD absolutePathSize); +/** +* @brief Get the absolute path to a device mounted at the given drive letter +*/ +VCF_API int __cdecl GetDevicePath(DriveLetter letter, wchar_t* devicePath, DWORD devicePathSize); +/** +* @brief Mount a a VeraCrypt volume. VeraCryptFormat_Initialize() must be called successfully +* before using this function. +* @param options A pointer to a VeraCryptMountOptions struct containing all parameters for the operation. +* @return Return VCF_SUCCESS (0) on success, or a non-zero VCF_ERROR_* code on failure +*/ +VCF_API int __cdecl VeraCryptMount(const VeraCryptMountOptions* options); +/** +* @brief Dismount a VeraCrypt volume. VeraCryptFormat_Initialize() must be called successfully +* before using this function. +* @param letter The drive letter where the volume is mounted +* @param force Tells if the unmount operation will be forced +* @return Return VCF_SUCCESS (0) on success, or a non-zero VCF_ERROR_* code on failure +*/ +VCF_API int __cdecl VeraCryptDismount(DriveLetter letter, BOOL force); #ifdef __cplusplus } #endif \ No newline at end of file