mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2026-08-30 20:57:10 +00:00
Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9089b0202 | ||
|
|
4ad36447b2 | ||
|
|
9b20099255 | ||
|
|
d0bc546614 | ||
|
|
6774de941d | ||
|
|
5d7a2a78b8 | ||
|
|
0190270f9d | ||
|
|
3c771c07fc | ||
|
|
a173a11cfe | ||
|
|
66ddd29c91 | ||
|
|
0d86b9b3e6 | ||
|
|
5bd9277970 | ||
|
|
854f85f013 | ||
|
|
fc2efd0b8f | ||
|
|
d1f73ce429 | ||
|
|
79bee911be | ||
|
|
1fd2fb06cd | ||
|
|
c3ce2db9ac |
@@ -4,6 +4,10 @@
|
||||
# CLion
|
||||
.idea/
|
||||
|
||||
# Python build/test artifacts
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# VC Linux build artifacts
|
||||
*.o
|
||||
*.o0
|
||||
|
||||
Binary file not shown.
@@ -161,7 +161,7 @@ When using Argon2id in VeraCrypt:
|
||||
<strong>Algorithm:</strong> Argon2id as defined in RFC 9106<br/>
|
||||
<strong>Internal hash:</strong> BLAKE2b<br/>
|
||||
<strong>Salt size:</strong> 512 bits (same as PBKDF2-HMAC)<br/>
|
||||
<strong>Output length:</strong> Variable, depending on the encryption algorithm (e.g., 256 bits for AES-256, 768 bits for AES-Twofish-Serpent cascade)<br/>
|
||||
<strong>Header KDF output length:</strong> Fixed at 1536 bits (192 bytes) for the current VeraCrypt format. The required prefix is used for the selected encryption algorithm (for example, the first 64 bytes for AES (AES-256-XTS)). Third-party implementations must request 192 bytes from Argon2id before selecting the required prefix; requesting only the selected algorithm's key material length produces a different Argon2id output.<br/>
|
||||
<strong>Version:</strong> Argon2 version 0x13 (19 decimal)
|
||||
</div>
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>--quick</em></td>
|
||||
<td>Enable quick formatting when creating a volume. This option must not be used when creating an outer volume.</td>
|
||||
<td>Enable quick formatting when creating a normal file-hosted or device-hosted volume. Do not use this option when creating an outer volume. In text mode, VeraCrypt cannot infer that a normal volume is intended to become an outer volume. For file containers, Quick Format may create sparse or unwritten host regions. Allocation behavior depends on host filesystem sparse-file support, and later writes can fail if the host filesystem runs out of space.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>--random-source=FILE</em></td>
|
||||
@@ -326,7 +326,7 @@
|
||||
<h4>Hidden Volume Creation in Text Mode</h4>
|
||||
<p>Inexperienced users should use the graphical user interface to create a hidden volume. When using the text user interface, the following procedure must be followed:</p>
|
||||
<ol>
|
||||
<li>Create an outer volume with no filesystem.</li>
|
||||
<li>Create an outer volume with no filesystem and without <em>--quick</em>.</li>
|
||||
<li>Create a hidden volume within the outer volume.</li>
|
||||
<li>Mount the outer volume using hidden volume protection.</li>
|
||||
<li>Create a filesystem on the virtual device of the outer volume.</li>
|
||||
|
||||
@@ -56,10 +56,11 @@ Note that the output of a hash function is <em>never </em>used directly as an en
|
||||
<p>This allows you to select the encryption algorithm with which your new volume will be encrypted. Note that the encryption algorithm cannot be changed after the volume is created. For more information, please see the chapter
|
||||
<a href="Encryption%20Algorithms.html"><em>Encryption Algorithms</em></a>.</p>
|
||||
<h3 id="QuickFormat">Quick Format</h3>
|
||||
<p>If you are not sure whether to enable or disable Quick Format, we recommend that you leave this option unchecked.</p>
|
||||
<p>If unchecked, each sector of the new volume will be formatted. This means that the new volume will be
|
||||
<em>entirely </em>filled with random data. Quick format is much faster but may be less secure because until the whole volume has been filled with files, it may be possible to tell how much data it contains (if the space was not filled with random data beforehand).
|
||||
If you are not sure whether to enable or disable Quick Format, we recommend that you leave this option unchecked. Note that Quick Format can only be enabled when encrypting partitions/devices, except on Windows where it is also available when creating file containers.</p>
|
||||
<p>Important: When encrypting a partition/device within which you intend to create a hidden volume afterwards, leave this option unchecked.</p>
|
||||
For file containers, the host filesystem may create sparse or unwritten regions, which can reveal unused areas and reduce plausible deniability. Host allocation behavior depends on filesystem sparse-file support. On filesystems without sparse-file support, creating the container may allocate most or all of its space immediately or fail if there is not enough host space. The encrypted filesystem may also report more free space than the host filesystem can actually provide. If host space runs out, later writes may fail or corrupt the encrypted filesystem. Quick Format is available for normal file containers and when encrypting partitions/devices.</p>
|
||||
<p>Important: When creating an outer volume within which you intend to create a hidden volume afterwards, do not use Quick Format.</p>
|
||||
<h3 id="dynamic">Dynamic</h3>
|
||||
<p>Dynamic VeraCrypt container is a pre-allocated NTFS sparse file whose physical size (actual disk space used) grows as new data is added to it. Note that the physical size of the container (actual disk space that the container uses) will not decrease when
|
||||
files are deleted on the VeraCrypt volume. The physical size of the container can only
|
||||
|
||||
@@ -304,6 +304,8 @@ The System Favorites Organizer window should appear now. In this window, enable
|
||||
For more information, see the chapter <a href="System%20Favorite%20Volumes.html" target="_blank" style="text-align:left; color:#0080c0; text-decoration:none">
|
||||
System Favorite Volumes</a>.</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
Note: System favorite volumes are not available during the earlier Windows boot and storage initialization phases. Therefore, Windows-managed startup dependencies such as automatically attached VHD/VHDX files, Dev Drive backing VHDX files, and native-boot VHD/VHDX files must not be stored on system favorite volumes. For VHD/VHDX files that are not required during boot or early startup, use a delayed/retrying task or a service that depends on <em>VeraCryptSystemFavorites</em> to attach them after the system favorite volume has been mounted. This workaround is not suitable for native-boot VHD/VHDX files or any other file that Windows must access before services can run.</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
<br style="text-align:left">
|
||||
<strong style="text-align:left">Can a volume be automatically mounted whenever I log on to Windows?</strong></div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
|
||||
@@ -87,6 +87,7 @@ PIM </a>value is given by the user, the number of iterations of the PBKDF2 key d
|
||||
|
||||
<h4>Argon2id Parameters</h4>
|
||||
<p>When Argon2id is selected as the key derivation function, the PIM value controls both memory and time costs as described in the <a href="Personal%20Iterations%20Multiplier%20%28PIM%29.html">PIM section</a>. If no PIM is specified, default parameters equivalent to PIM = 12 are used (416 MiB memory, 6 iterations).</p>
|
||||
<p>For Argon2id, VeraCrypt derives a fixed 192 bytes of header key material for the current volume format, independently of the selected encryption algorithm. The selected encryption algorithm then uses the required prefix of that derived output. For example, AES-XTS uses the first 64 bytes. Implementations must request 192 bytes from Argon2id and then select the required prefix; requesting only the selected algorithm's key material length produces a different Argon2id output because Argon2id includes the requested output length in its computation.</p>
|
||||
|
||||
</div>
|
||||
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
|
||||
|
||||
@@ -62,7 +62,8 @@ In such situations, the issue can be solved by disabling VeraCrypt waiting dialo
|
||||
by selecting <em>System</em> > <em>Mount Without Pre-Boot Authentication,</em> is limited to primary partitions (extended/logical partitions cannot be mounted this way).
|
||||
</li><li>Due to a Windows 2000 issue, VeraCrypt does not support the Windows Mount Manager under Windows 2000. Therefore, some Windows 2000 built-in tools, such as Disk Defragmenter, do not work on VeraCrypt volumes. Furthermore, it is not possible to use the Mount
|
||||
Manager services under Windows 2000, e.g., assign a mount point to a VeraCrypt volume (i.e., attach a VeraCrypt volume to a folder).
|
||||
</li><li>VeraCrypt does not support pre-boot authentication for operating systems installed within VHD files, except when booted using appropriate virtual-machine software such as Microsoft Virtual PC.
|
||||
</li><li>VeraCrypt does not support pre-boot authentication for operating systems installed within VHD/VHDX files, except when booted using appropriate virtual-machine software such as Microsoft Virtual PC.
|
||||
</li><li>VHD/VHDX files that Windows must attach automatically during startup, including Dev Drive backing VHDX files, cannot be stored on system favorite volumes because these volumes are mounted only after the earlier Windows boot and storage initialization phases have already started. Store such non-boot VHD/VHDX files on the encrypted system partition/drive or on another partition within the key scope of system encryption. Native-boot VHD/VHDX files also cannot be stored on system favorite volumes; they remain subject to the preceding limitation on pre-boot authentication for operating systems installed within VHD/VHDX files. For VHD/VHDX files that are not required for boot or early Windows startup, disable Windows automatic attachment and attach them later using a delayed/retrying startup task or a service that depends on the <em>VeraCryptSystemFavorites</em> service. This workaround is not suitable for native-boot VHD/VHDX files or any other file that Windows must access before services can run.
|
||||
</li><li>The Windows Volume Shadow Copy Service is currently supported only for partitions within the key scope of system encryption (e.g. a system partition encrypted by VeraCrypt, or a non- system partition located on a system drive encrypted by VeraCrypt, mounted
|
||||
when the encrypted operating system is running). Note: For other types of volumes, the Volume Shadow Copy Service is not supported because the documentation for the necessary API is not available.
|
||||
</li><li>Windows boot settings cannot be changed from within a hidden operating system if the system does not boot from the partition on which it is installed. This is due to the fact that, for security reasons, the boot partition is mounted as read-only when the
|
||||
|
||||
@@ -48,6 +48,11 @@
|
||||
<li>Translator note: the previous Linux ntfs3 preference strings were replaced by generic in-kernel NTFS driver strings and should be retranslated.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>Linux and macOS:</strong>
|
||||
<ul>
|
||||
<li>Enable Quick Format for normal file containers. The container is sized with <code>ftruncate()</code>, so the host filesystem may keep regions unwritten or sparse until data is written to them.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p><strong style="text-align:left">1.26.27</strong> (September 20<sup>th</sup>, 2025):</p>
|
||||
|
||||
@@ -74,8 +74,8 @@ System favorite volumes <strong>can be configured to be available within VeraCry
|
||||
<br>
|
||||
Warning: When the drive letter assigned to a system favorite volume (saved in the configuration file) is not free, the volume is not mounted and no error message is displayed.<br>
|
||||
<br>
|
||||
Note that Windows needs to use some files (e.g. paging files, Active Directory files, etc.) before system favorite volumes are mounted. Therefore, such files cannot be stored on system favorite volumes. Note, however, that they
|
||||
<em>can </em>be stored on any partition that is within the key scope of system encryption (e.g. on the system partition or on any partition of a system drive that is entirely encrypted by VeraCrypt).<br>
|
||||
Note that Windows needs to use some files (e.g. paging files, Active Directory files, VHD/VHDX files configured for automatic attachment at startup, Dev Drive backing VHDX files, native-boot VHD/VHDX files, etc.) before system favorite volumes are mounted. Therefore, such files cannot be stored on system favorite volumes. Note, however, that files supported by VeraCrypt system encryption
|
||||
<em>can </em>be stored on any partition that is within the key scope of system encryption (e.g. on the system partition or on any partition of a system drive that is entirely encrypted by VeraCrypt). Native-boot VHD/VHDX files remain subject to the limitation that VeraCrypt does not support pre-boot authentication for operating systems installed within VHD/VHDX files. For VHD/VHDX files that are not required for boot or early Windows startup, a possible workaround is to disable Windows automatic attachment and attach them only after the corresponding system favorite volume has been mounted, for example by using a delayed/retrying startup task or a service that depends on the <em>VeraCryptSystemFavorites</em> service and runs <code>Mount-DiskImage</code> or <code>diskpart attach vdisk</code>. This workaround is not suitable for paging files, Active Directory files, native-boot VHD/VHDX files, or any other file that Windows must access before services can run.<br>
|
||||
<br>
|
||||
<strong>To remove a volume from the list of system favorite volumes</strong>, select
|
||||
<em>Favorites </em>> <em>Organize System Favorite Volumes</em>, select the volume, click
|
||||
|
||||
@@ -96,7 +96,7 @@ endif
|
||||
|
||||
# Embedded files
|
||||
ifeq "$(PLATFORM)" "OpenBSD"
|
||||
OD_BIN := ggod -v -t u1 -A n
|
||||
OD_BIN := hexdump -v -e '1/1 "%u "'
|
||||
else
|
||||
OD_BIN := od -v -t u1 -A n
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
# OpenWrt packaging
|
||||
|
||||
This directory contains the canonical OpenWrt package template and local test
|
||||
configuration for building VeraCrypt console-only with the OpenWrt SDK.
|
||||
It is a maintainer build-and-test harness for the VeraCrypt working tree, not
|
||||
an OpenWrt packages-feed submission recipe.
|
||||
|
||||
The current supported target is `x86/64`, matching the QEMU runtime smoke test.
|
||||
The build uses:
|
||||
|
||||
- OpenWrt 24.10.6 x86/64 SDK by default
|
||||
- musl through the OpenWrt toolchain
|
||||
- `NOGUI=1`
|
||||
- `WITHFUSE3=1`
|
||||
- `WXSTATIC=1`
|
||||
- wxWidgets 3.2.10 built as static wxBase
|
||||
- `NOTEST=1` during cross compilation
|
||||
- `NOSTRIP=1`, with OpenWrt package stripping disabled for maintainer
|
||||
diagnostics
|
||||
|
||||
The package installs only:
|
||||
|
||||
- `/usr/bin/veracrypt`
|
||||
- `/sbin/mount.veracrypt`
|
||||
- `/usr/share/licenses/veracrypt/License.txt`
|
||||
|
||||
`mount.veracrypt` uses a Bash shebang, so the OpenWrt package declares `bash`
|
||||
as a runtime dependency.
|
||||
|
||||
## Build
|
||||
|
||||
From the VeraCrypt checkout root:
|
||||
|
||||
```sh
|
||||
src/Build/build_veracrypt_openwrt.sh
|
||||
```
|
||||
|
||||
The script downloads and verifies the OpenWrt SDK against a pinned SHA-256 for
|
||||
the supported release/target, downloads and verifies wxWidgets 3.2.10, installs
|
||||
the required OpenWrt feeds, renders
|
||||
`package/utils/veracrypt/Makefile` inside the SDK, builds the `.ipk`, and
|
||||
also builds the local userland `bash`, `fuse3`, `util-linux`, and `lvm2` feed
|
||||
packages used by the QEMU runtime test. Kernel modules for the stock OpenWrt
|
||||
image are resolved by the test from the official OpenWrt kmod feed for the
|
||||
selected release and target.
|
||||
|
||||
Default output location:
|
||||
|
||||
```text
|
||||
../openwrt-veracrypt/openwrt-sdk-24.10.6-x86-64_gcc-13.3.0_musl.Linux-x86_64/bin/packages/x86_64/base/veracrypt_<version>-r1_x86_64.ipk
|
||||
```
|
||||
|
||||
Useful options:
|
||||
|
||||
```sh
|
||||
src/Build/build_veracrypt_openwrt.sh --fresh-sdk
|
||||
src/Build/build_veracrypt_openwrt.sh --work-dir /tmp/veracrypt-openwrt
|
||||
src/Build/build_veracrypt_openwrt.sh --sdk-dir /path/to/openwrt-sdk
|
||||
src/Build/build_veracrypt_openwrt.sh --sdk-url URL --sdk-sha256 HASH
|
||||
src/Build/build_veracrypt_openwrt.sh --wx-version 3.2.10
|
||||
```
|
||||
|
||||
Custom SDK URLs or unsupported OpenWrt release/target combinations must pass
|
||||
`--sdk-sha256`; the build script does not trust an unsigned `sha256sums` file as
|
||||
the sole integrity source for SDK archives.
|
||||
|
||||
If the host only has `mawk`, the build script downloads and builds GNU awk
|
||||
locally under the OpenWrt work directory because OpenWrt feed scripts require
|
||||
GNU awk behavior on some hosts.
|
||||
|
||||
## QEMU Runtime Test
|
||||
|
||||
Install or provide `qemu-system-x86_64`. On Debian/Ubuntu hosts:
|
||||
|
||||
```sh
|
||||
sudo apt install qemu-system-x86
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```sh
|
||||
python3 src/Build/test_veracrypt_openwrt_qemu.py \
|
||||
--ipk ../openwrt-veracrypt/openwrt-sdk-24.10.6-x86-64_gcc-13.3.0_musl.Linux-x86_64/bin/packages/x86_64/base/veracrypt_<version>-r1_x86_64.ipk
|
||||
```
|
||||
|
||||
The test script downloads and verifies the matching OpenWrt x86/64 ext4 image,
|
||||
boots it with QEMU user networking, waits for OpenWrt network init to settle,
|
||||
gets a DHCP lease on `br-lan` or `eth0`, resolves the needed dependency closure
|
||||
from local SDK `.ipk` control metadata plus the official OpenWrt kmod feed,
|
||||
serves those packages to the guest, and installs them with `opkg`. It then runs:
|
||||
|
||||
```sh
|
||||
veracrypt --text --version
|
||||
veracrypt --text --test
|
||||
```
|
||||
|
||||
By default it also creates a 16 MiB AES/SHA-512 test container, opens it with
|
||||
`--filesystem=none`, verifies it appears in `veracrypt --text --list`, and
|
||||
unmounts it. Use `--skip-container` to run only the package install, version,
|
||||
and algorithm self-test path.
|
||||
|
||||
If QEMU was extracted locally instead of installed system-wide, pass the binary
|
||||
and firmware directory explicitly:
|
||||
|
||||
```sh
|
||||
LD_LIBRARY_PATH=/path/to/qemu-libs \
|
||||
python3 src/Build/test_veracrypt_openwrt_qemu.py \
|
||||
--qemu /path/to/qemu-system-x86_64 \
|
||||
--qemu-data-dir /path/to/pc-bios \
|
||||
--ipk /path/to/veracrypt_<version>-r1_x86_64.ipk
|
||||
```
|
||||
|
||||
The runner defaults to one QEMU vCPU because TCG with multiple vCPUs can
|
||||
intermittently trip x86 APIC timer startup in the stock OpenWrt image.
|
||||
The runner does not require external package feed access from the guest; all
|
||||
runtime packages are served over the host-to-guest QEMU user-networking link.
|
||||
Local userland packages come from the SDK `bin/` directory, while stock-image
|
||||
kmods are downloaded by the host from the official OpenWrt kmod feed and staged
|
||||
locally. If the VeraCrypt `.ipk` is not below the SDK `bin/` directory, pass
|
||||
`--package-bin-dir /path/to/sdk/bin`.
|
||||
|
||||
For custom images whose kernel does not match the official release feed, pass
|
||||
`--kmod-feed-url` for the matching kmod feed, or `--local-kmods` to resolve
|
||||
kmods from `--package-bin-dir`.
|
||||
|
||||
The test log is written to:
|
||||
|
||||
```text
|
||||
../openwrt-veracrypt/openwrt-qemu-test.log
|
||||
```
|
||||
|
||||
## Runtime Packages
|
||||
|
||||
The VeraCrypt package itself declares the direct userland dependencies using
|
||||
OpenWrt package symbols:
|
||||
|
||||
- `libstdcpp`
|
||||
- `libfuse3`
|
||||
- `bash`
|
||||
|
||||
OpenWrt's FUSE3 recipe defines `Package/libfuse3` with ABI version `3`, so the
|
||||
binary IPK and package-index metadata are emitted as `libfuse3-3` while still
|
||||
providing `libfuse3`. The QEMU test installs the seed runtime support normally
|
||||
needed for useful mounts using package-index names:
|
||||
|
||||
- `libfuse3-3`
|
||||
- `fuse3-utils`
|
||||
- `kmod-fuse`
|
||||
- `kmod-loop`
|
||||
- `lvm2`
|
||||
- `kmod-dm`
|
||||
- `losetup`
|
||||
- `blkid`
|
||||
- `mount-utils`
|
||||
- `kmod-crypto-misc`
|
||||
|
||||
The test resolver also stages required transitive dependencies from package
|
||||
metadata, such as `libdevmapper` when pulled by `lvm2`.
|
||||
|
||||
Filesystem-specific mounts also need the corresponding OpenWrt filesystem
|
||||
kernel modules and tools. Smart-card and EMV keyfile support should install
|
||||
`libpcsclite`, `pcscd`, and the appropriate reader driver such as `ccid`; these
|
||||
are optional and are not part of the base package dependency set.
|
||||
@@ -0,0 +1,23 @@
|
||||
CONFIG_TARGET_x86=y
|
||||
CONFIG_TARGET_x86_64=y
|
||||
# CONFIG_TARGET_MULTI_PROFILE is not set
|
||||
# CONFIG_TARGET_ALL_PROFILES is not set
|
||||
CONFIG_TARGET_DEVICE_x86_64_DEVICE_generic=y
|
||||
|
||||
# CONFIG_ALL is not set
|
||||
# CONFIG_ALL_KMODS is not set
|
||||
# CONFIG_ALL_NONSHARED is not set
|
||||
# CONFIG_DEVEL is not set
|
||||
|
||||
CONFIG_PACKAGE_veracrypt=m
|
||||
CONFIG_PACKAGE_bash=m
|
||||
CONFIG_PACKAGE_libfuse3=m
|
||||
CONFIG_PACKAGE_fuse3-utils=m
|
||||
CONFIG_PACKAGE_kmod-fuse=m
|
||||
CONFIG_PACKAGE_kmod-loop=m
|
||||
CONFIG_PACKAGE_kmod-dm=m
|
||||
CONFIG_PACKAGE_kmod-crypto-misc=m
|
||||
CONFIG_PACKAGE_lvm2=m
|
||||
CONFIG_PACKAGE_losetup=m
|
||||
CONFIG_PACKAGE_blkid=m
|
||||
CONFIG_PACKAGE_mount-utils=m
|
||||
@@ -0,0 +1,90 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=veracrypt
|
||||
PKG_VERSION:=@VERACRYPT_VERSION@
|
||||
PKG_RELEASE:=1
|
||||
PKG_LICENSE:=Apache-2.0 AND LicenseRef-TrueCrypt
|
||||
PKG_LICENSE_FILES:=veracrypt/src/License.txt
|
||||
PKG_MAINTAINER:=Mounir IDRASSI <mounir.idrassi@amcrypto.jp>
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_BUILD_DEPENDS:=fuse3 pcsc-lite
|
||||
|
||||
VERACRYPT_STAGED_SOURCE:=sources/veracrypt
|
||||
WXWIDGETS_STAGED_SOURCE:=sources/wxWidgets
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
RSTRIP:=:
|
||||
STRIP:=:
|
||||
|
||||
define Package/veracrypt
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
SUBMENU:=Filesystem
|
||||
TITLE:=VeraCrypt console
|
||||
URL:=https://www.veracrypt.fr/
|
||||
DEPENDS:=+libstdcpp +libfuse3 +bash
|
||||
endef
|
||||
|
||||
define Package/veracrypt/description
|
||||
Console-only VeraCrypt build for OpenWrt using FUSE3 and a static wxBase.
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
rm -rf "$(PKG_BUILD_DIR)"
|
||||
$(INSTALL_DIR) "$(PKG_BUILD_DIR)"
|
||||
rsync -a --delete \
|
||||
--exclude .git \
|
||||
--exclude 'src/wxrelease' \
|
||||
--exclude 'src/wxdebug' \
|
||||
--exclude 'src/Main/veracrypt' \
|
||||
--exclude 'src/Setup/Linux/usr' \
|
||||
--exclude '*.o' \
|
||||
--exclude '*.d' \
|
||||
--exclude '*.a' \
|
||||
"$(VERACRYPT_STAGED_SOURCE)/" "$(PKG_BUILD_DIR)/veracrypt/"
|
||||
rsync -a --delete "$(WXWIDGETS_STAGED_SOURCE)/" "$(PKG_BUILD_DIR)/wxWidgets/"
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
VC_COMMON_MAKE_FLAGS = \
|
||||
AR="$(TARGET_AR)" \
|
||||
CC="$(TARGET_CC)" \
|
||||
CXX="$(TARGET_CXX)" \
|
||||
AS="yasm" \
|
||||
RANLIB="$(TARGET_RANLIB)" \
|
||||
PKG_CONFIG="$(PKG_CONFIG)" \
|
||||
PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" \
|
||||
WX_ROOT="$(PKG_BUILD_DIR)/wxWidgets" \
|
||||
WX_BUILD_DIR="$(PKG_BUILD_DIR)/wxBuildConsole" \
|
||||
WX_CONFIGURE_EXTRA_FLAGS="--target=$(GNU_TARGET_NAME) --host=$(GNU_TARGET_NAME) --build=$(GNU_HOST_NAME) --prefix=/usr --exec-prefix=/usr --disable-rpath" \
|
||||
TC_EXTRA_CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
|
||||
TC_EXTRA_CXXFLAGS="$(TARGET_CXXFLAGS) $(TARGET_CPPFLAGS)" \
|
||||
TC_EXTRA_LFLAGS="$(TARGET_LDFLAGS)" \
|
||||
NOGUI=1 \
|
||||
WITHFUSE3=1 \
|
||||
WXSTATIC=1 \
|
||||
NOTEST=1 \
|
||||
NOSTRIP=1 \
|
||||
VERBOSE=1
|
||||
|
||||
define Build/Compile
|
||||
+$(MAKE) -C "$(PKG_BUILD_DIR)/veracrypt/src" $(VC_COMMON_MAKE_FLAGS) clean
|
||||
+$(MAKE) -C "$(PKG_BUILD_DIR)/veracrypt/src" $(VC_COMMON_MAKE_FLAGS) wxbuild
|
||||
+$(MAKE) -C "$(PKG_BUILD_DIR)/veracrypt/src" $(PKG_JOBS) $(VC_COMMON_MAKE_FLAGS)
|
||||
endef
|
||||
|
||||
define Package/veracrypt/install
|
||||
$(INSTALL_DIR) "$(1)/usr/bin"
|
||||
$(INSTALL_BIN) "$(PKG_BUILD_DIR)/veracrypt/src/Main/veracrypt" "$(1)/usr/bin/veracrypt"
|
||||
$(INSTALL_DIR) "$(1)/sbin"
|
||||
$(INSTALL_BIN) "$(PKG_BUILD_DIR)/veracrypt/src/Setup/Linux/mount.veracrypt" "$(1)/sbin/mount.veracrypt"
|
||||
$(INSTALL_DIR) "$(1)/usr/share/licenses/veracrypt"
|
||||
$(INSTALL_DATA) "$(PKG_BUILD_DIR)/veracrypt/src/License.txt" "$(1)/usr/share/licenses/veracrypt/License.txt"
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,veracrypt))
|
||||
Executable
+452
@@ -0,0 +1,452 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2026 AM Crypto
|
||||
# Governed by the Apache License 2.0 the full text of which is contained
|
||||
# in the file License.txt included in VeraCrypt binary and source
|
||||
# code distribution packages.
|
||||
#
|
||||
|
||||
set -eu
|
||||
umask 022
|
||||
|
||||
OPENWRT_VERSION=24.10.6
|
||||
OPENWRT_TARGET=x86/64
|
||||
WX_VERSION=3.2.10
|
||||
WX_URL=
|
||||
WX_SHA256=d66e929569947a4a5920699539089a9bda83a93e5f4917fb313a61f0c344b896
|
||||
SDK_URL=
|
||||
SDK_SHA256=
|
||||
SDK_DIR=
|
||||
FRESH_SDK=0
|
||||
|
||||
SCRIPT=$(readlink -f "$0")
|
||||
SCRIPTPATH=$(dirname "$SCRIPT")
|
||||
REPOROOT=$(readlink -f "$SCRIPTPATH/../..")
|
||||
SOURCEPATH="$REPOROOT/src"
|
||||
PARENTDIR=$(readlink -f "$SCRIPTPATH/../../..")
|
||||
WORK_DIR="$PARENTDIR/openwrt-veracrypt"
|
||||
JOBS=$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1)
|
||||
|
||||
GAWK_VERSION=5.3.2
|
||||
GAWK_URL="https://ftp.gnu.org/gnu/gawk/gawk-$GAWK_VERSION.tar.xz"
|
||||
GAWK_SHA256=f8c3486509de705192138b00ef2c00bbbdd0e84c30d5c07d23fc73a9dc4cc9cc
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [options]
|
||||
|
||||
Build the VeraCrypt console-only OpenWrt package with the OpenWrt SDK.
|
||||
|
||||
Options:
|
||||
--openwrt-version VERSION OpenWrt release to use (default: $OPENWRT_VERSION)
|
||||
--target TARGET OpenWrt target/subtarget (default: $OPENWRT_TARGET)
|
||||
--work-dir DIR Download/build workspace (default: $WORK_DIR)
|
||||
--sdk-url URL SDK archive URL (auto-detected for x86/64)
|
||||
--sdk-sha256 HASH SDK archive SHA-256 (required for custom SDKs)
|
||||
--sdk-dir DIR Use an already extracted SDK directory
|
||||
--fresh-sdk Re-extract the SDK before building
|
||||
--wx-version VERSION wxWidgets version (default: $WX_VERSION)
|
||||
--wx-url URL wxWidgets source archive URL
|
||||
--wx-sha256 HASH wxWidgets source archive SHA-256
|
||||
-j, --jobs N Parallel make jobs (default: host CPU count)
|
||||
-h, --help Show this help
|
||||
|
||||
Only x86/64 is currently wired because it is the QEMU smoke-test target.
|
||||
EOF
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "Error: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
need_tool() {
|
||||
command -v "$1" >/dev/null 2>&1 || die "Required tool '$1' was not found"
|
||||
}
|
||||
|
||||
require_option_arg() {
|
||||
[ $# -ge 2 ] || die "Option $1 requires an argument"
|
||||
}
|
||||
|
||||
validate_version_token() {
|
||||
name=$1
|
||||
value=$2
|
||||
|
||||
case "$value" in
|
||||
''|*[!A-Za-z0-9._+-]*)
|
||||
die "$name must contain only letters, digits, '.', '_', '+', or '-'"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
download_file() {
|
||||
url=$1
|
||||
out=$2
|
||||
expected_sha=$3
|
||||
tmp="$out.tmp.$$"
|
||||
|
||||
mkdir -p "$(dirname "$out")"
|
||||
if [ -f "$out" ]; then
|
||||
if [ -z "$expected_sha" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
actual_sha=$(sha256sum "$out" | awk '{print $1}')
|
||||
if [ "$actual_sha" = "$expected_sha" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Checksum mismatch for existing $out; re-downloading" >&2
|
||||
rm -f "$out"
|
||||
fi
|
||||
|
||||
rm -f "$tmp"
|
||||
echo "Downloading $url"
|
||||
if ! wget -O "$tmp" "$url"; then
|
||||
rm -f "$tmp"
|
||||
die "Download failed: $url"
|
||||
fi
|
||||
|
||||
if [ -n "$expected_sha" ]; then
|
||||
actual_sha=$(sha256sum "$tmp" | awk '{print $1}')
|
||||
if [ "$actual_sha" != "$expected_sha" ]; then
|
||||
rm -f "$tmp"
|
||||
die "SHA-256 mismatch for $out: expected $expected_sha, got $actual_sha"
|
||||
fi
|
||||
fi
|
||||
|
||||
mv "$tmp" "$out"
|
||||
}
|
||||
|
||||
pinned_sdk_sha256() {
|
||||
archive_name=$1
|
||||
|
||||
case "$OPENWRT_VERSION:$OPENWRT_TARGET:$archive_name" in
|
||||
24.10.6:x86/64:openwrt-sdk-24.10.6-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst)
|
||||
printf '%s\n' "9e398ea7efc098e4a986f97efff595e32d08c615fe356bcb3d885d7ad3a39ac0"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
target_defaults() {
|
||||
case "$OPENWRT_TARGET" in
|
||||
x86/64)
|
||||
OPENWRT_TARGET_SLUG=x86-64
|
||||
OPENWRT_CONFIG="$REPOROOT/src/Build/Packaging/openwrt/configs/x86_64-minimal.config"
|
||||
;;
|
||||
*)
|
||||
die "Unsupported target '$OPENWRT_TARGET'. Add a config under src/Build/Packaging/openwrt/configs first."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
openwrt_base_url() {
|
||||
printf 'https://downloads.openwrt.org/releases/%s/targets/%s\n' "$OPENWRT_VERSION" "$OPENWRT_TARGET"
|
||||
}
|
||||
|
||||
resolve_sdk() {
|
||||
if [ -n "$SDK_DIR" ]; then
|
||||
SDK_DIR=$(readlink -f "$SDK_DIR")
|
||||
[ -d "$SDK_DIR" ] || die "SDK directory does not exist: $SDK_DIR"
|
||||
return
|
||||
fi
|
||||
|
||||
base_url=$(openwrt_base_url)
|
||||
|
||||
mkdir -p "$WORK_DIR/downloads"
|
||||
if [ -z "$SDK_URL" ]; then
|
||||
index_file="$WORK_DIR/downloads/openwrt-$OPENWRT_VERSION-$OPENWRT_TARGET_SLUG-index.html"
|
||||
wget -q -O "$index_file" "$base_url/"
|
||||
sdk_archive=$(sed -n "s/.*href=\"\\(openwrt-sdk-$OPENWRT_VERSION-${OPENWRT_TARGET_SLUG}_[^\"]*\\.Linux-x86_64\\.tar\\.zst\\)\".*/\\1/p" "$index_file" | head -n 1)
|
||||
[ -n "$sdk_archive" ] || die "Could not find an SDK archive at $base_url/"
|
||||
SDK_URL="$base_url/$sdk_archive"
|
||||
else
|
||||
sdk_archive=$(basename "$SDK_URL")
|
||||
fi
|
||||
|
||||
if [ -z "$SDK_SHA256" ]; then
|
||||
SDK_SHA256=$(pinned_sdk_sha256 "$sdk_archive")
|
||||
fi
|
||||
|
||||
[ -n "$SDK_SHA256" ] || die "No trusted SDK SHA-256 is available for $sdk_archive; pass --sdk-sha256 for custom SDKs"
|
||||
|
||||
SDK_ARCHIVE_PATH="$WORK_DIR/downloads/$sdk_archive"
|
||||
download_file "$SDK_URL" "$SDK_ARCHIVE_PATH" "$SDK_SHA256"
|
||||
|
||||
sdk_top=$(zstd -dc "$SDK_ARCHIVE_PATH" | tar -tf - | sed -n '1{s,/.*,,;p;q;}')
|
||||
[ -n "$sdk_top" ] || die "Could not determine SDK archive top-level directory"
|
||||
SDK_DIR="$WORK_DIR/$sdk_top"
|
||||
|
||||
if [ "$FRESH_SDK" = "1" ]; then
|
||||
rm -rf "$SDK_DIR"
|
||||
fi
|
||||
|
||||
if [ ! -d "$SDK_DIR" ]; then
|
||||
echo "Extracting $SDK_ARCHIVE_PATH"
|
||||
zstd -dc "$SDK_ARCHIVE_PATH" | tar -xf - -C "$WORK_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_gawk() {
|
||||
HOST_TOOLS="$WORK_DIR/host-tools"
|
||||
if command -v gawk >/dev/null 2>&1; then
|
||||
mkdir -p "$HOST_TOOLS/bin"
|
||||
ln -sf "$(command -v gawk)" "$HOST_TOOLS/bin/gawk"
|
||||
ln -sf "$(command -v gawk)" "$HOST_TOOLS/bin/awk"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -x "$HOST_TOOLS/prefix/bin/gawk" ]; then
|
||||
mkdir -p "$HOST_TOOLS/bin"
|
||||
ln -sf ../prefix/bin/gawk "$HOST_TOOLS/bin/gawk"
|
||||
ln -sf ../prefix/bin/gawk "$HOST_TOOLS/bin/awk"
|
||||
return
|
||||
fi
|
||||
|
||||
need_tool make
|
||||
if ! command -v gcc >/dev/null 2>&1 && ! command -v cc >/dev/null 2>&1; then
|
||||
die "GNU awk is not installed and no C compiler was found to build it"
|
||||
fi
|
||||
|
||||
mkdir -p "$HOST_TOOLS/src"
|
||||
gawk_archive="$HOST_TOOLS/src/gawk-$GAWK_VERSION.tar.xz"
|
||||
download_file "$GAWK_URL" "$gawk_archive" "$GAWK_SHA256"
|
||||
|
||||
rm -rf "$HOST_TOOLS/src/gawk-$GAWK_VERSION"
|
||||
tar -xf "$gawk_archive" -C "$HOST_TOOLS/src"
|
||||
echo "Building GNU awk $GAWK_VERSION for OpenWrt feed scripts"
|
||||
(
|
||||
cd "$HOST_TOOLS/src/gawk-$GAWK_VERSION"
|
||||
./configure --prefix="$HOST_TOOLS/prefix" >/dev/null
|
||||
make -j "$JOBS" >/dev/null
|
||||
make install >/dev/null
|
||||
)
|
||||
mkdir -p "$HOST_TOOLS/bin"
|
||||
ln -sf ../prefix/bin/gawk "$HOST_TOOLS/bin/gawk"
|
||||
ln -sf ../prefix/bin/gawk "$HOST_TOOLS/bin/awk"
|
||||
}
|
||||
|
||||
prepare_wxwidgets() {
|
||||
if [ -z "$WX_URL" ]; then
|
||||
WX_URL="https://github.com/wxWidgets/wxWidgets/releases/download/v$WX_VERSION/wxWidgets-$WX_VERSION.tar.bz2"
|
||||
fi
|
||||
|
||||
wx_archive="$WORK_DIR/downloads/wxWidgets-$WX_VERSION.tar.bz2"
|
||||
WX_SOURCE_DIR="$WORK_DIR/sources/wxWidgets-$WX_VERSION"
|
||||
download_file "$WX_URL" "$wx_archive" "$WX_SHA256"
|
||||
|
||||
if [ ! -f "$WX_SOURCE_DIR/configure" ]; then
|
||||
rm -rf "$WX_SOURCE_DIR"
|
||||
mkdir -p "$WORK_DIR/sources"
|
||||
echo "Extracting $wx_archive"
|
||||
tar -xjf "$wx_archive" -C "$WORK_DIR/sources"
|
||||
fi
|
||||
}
|
||||
|
||||
sed_escape() {
|
||||
printf '%s' "$1" | sed 's/[&|]/\\&/g'
|
||||
}
|
||||
|
||||
assert_package_dir_outside_checkout() {
|
||||
package_dir=$1
|
||||
|
||||
case "$package_dir/" in
|
||||
"$REPOROOT"/*)
|
||||
die "OpenWrt package directory is inside the VeraCrypt checkout; choose a --work-dir or --sdk-dir outside the repository"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
stage_package_sources() {
|
||||
package_dir=$1
|
||||
staging_dir="$package_dir/sources"
|
||||
|
||||
assert_package_dir_outside_checkout "$package_dir"
|
||||
|
||||
rm -rf "$staging_dir"
|
||||
mkdir -p "$staging_dir/veracrypt" "$staging_dir/wxWidgets"
|
||||
|
||||
rsync -a --delete \
|
||||
--exclude .git \
|
||||
--exclude 'src/wxrelease' \
|
||||
--exclude 'src/wxdebug' \
|
||||
--exclude 'src/Main/veracrypt' \
|
||||
--exclude 'src/Setup/Linux/usr' \
|
||||
--exclude '*.o' \
|
||||
--exclude '*.d' \
|
||||
--exclude '*.a' \
|
||||
"$REPOROOT/" "$staging_dir/veracrypt/"
|
||||
|
||||
rsync -a --delete "$WX_SOURCE_DIR/" "$staging_dir/wxWidgets/"
|
||||
}
|
||||
|
||||
render_package_makefile() {
|
||||
version=$(sed -n 's/^#define[[:space:]][[:space:]]*VERSION_STRING[[:space:]][[:space:]]*"\([^"]*\)".*/\1/p' "$SOURCEPATH/Common/Tcdefs.h" | head -n 1)
|
||||
[ -n "$version" ] || die "Could not determine VeraCrypt version from src/Common/Tcdefs.h"
|
||||
validate_version_token "VeraCrypt version" "$version"
|
||||
|
||||
package_dir="$SDK_DIR/package/utils/veracrypt"
|
||||
template="$REPOROOT/src/Build/Packaging/openwrt/package/utils/veracrypt/Makefile.in"
|
||||
|
||||
assert_package_dir_outside_checkout "$package_dir"
|
||||
rm -rf "$package_dir"
|
||||
mkdir -p "$package_dir"
|
||||
stage_package_sources "$package_dir"
|
||||
sed \
|
||||
-e "s|@VERACRYPT_VERSION@|$(sed_escape "$version")|g" \
|
||||
"$template" > "$package_dir/Makefile"
|
||||
|
||||
VERACRYPT_VERSION=$version
|
||||
}
|
||||
|
||||
configure_sdk() {
|
||||
[ -f "$OPENWRT_CONFIG" ] || die "Missing OpenWrt config seed: $OPENWRT_CONFIG"
|
||||
|
||||
cp "$OPENWRT_CONFIG" "$SDK_DIR/.config"
|
||||
(
|
||||
cd "$SDK_DIR"
|
||||
if ! PATH="$HOST_TOOLS/bin:$PATH" ./scripts/feeds update packages base; then
|
||||
echo "Feed update failed; removing stale feed checkouts and retrying" >&2
|
||||
rm -rf feeds/base feeds/packages
|
||||
PATH="$HOST_TOOLS/bin:$PATH" ./scripts/feeds update packages base
|
||||
fi
|
||||
PATH="$HOST_TOOLS/bin:$PATH" ./scripts/feeds install fuse3 lvm2 util-linux pcsc-lite bash
|
||||
PATH="$HOST_TOOLS/bin:$PATH" make defconfig
|
||||
)
|
||||
}
|
||||
|
||||
build_package() {
|
||||
(
|
||||
cd "$SDK_DIR"
|
||||
PATH="$HOST_TOOLS/bin:$PATH" make package/utils/veracrypt/clean V=s
|
||||
PATH="$HOST_TOOLS/bin:$PATH" make package/utils/veracrypt/compile V=s -j "$JOBS"
|
||||
)
|
||||
|
||||
IPK_PATH=$(find "$SDK_DIR/bin/packages" "$SDK_DIR/bin/targets" -name "veracrypt_${VERACRYPT_VERSION}-*.ipk" 2>/dev/null | sort | tail -n 1)
|
||||
[ -n "$IPK_PATH" ] || die "Build completed but no VeraCrypt .ipk was found"
|
||||
}
|
||||
|
||||
build_runtime_packages() {
|
||||
(
|
||||
cd "$SDK_DIR"
|
||||
for target in \
|
||||
package/feeds/packages/bash/compile \
|
||||
package/feeds/packages/fuse3/compile \
|
||||
package/feeds/base/util-linux/compile \
|
||||
package/feeds/packages/lvm2/compile
|
||||
do
|
||||
echo "Building OpenWrt runtime dependency: $target"
|
||||
PATH="$HOST_TOOLS/bin:$PATH" make "$target" V=s -j "$JOBS"
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--openwrt-version)
|
||||
require_option_arg "$@"
|
||||
OPENWRT_VERSION=$2
|
||||
shift 2
|
||||
;;
|
||||
--target)
|
||||
require_option_arg "$@"
|
||||
OPENWRT_TARGET=$2
|
||||
shift 2
|
||||
;;
|
||||
--work-dir)
|
||||
require_option_arg "$@"
|
||||
WORK_DIR=$(readlink -m "$2")
|
||||
shift 2
|
||||
;;
|
||||
--sdk-url)
|
||||
require_option_arg "$@"
|
||||
SDK_URL=$2
|
||||
shift 2
|
||||
;;
|
||||
--sdk-sha256)
|
||||
require_option_arg "$@"
|
||||
SDK_SHA256=$2
|
||||
shift 2
|
||||
;;
|
||||
--sdk-dir)
|
||||
require_option_arg "$@"
|
||||
SDK_DIR=$2
|
||||
shift 2
|
||||
;;
|
||||
--fresh-sdk)
|
||||
FRESH_SDK=1
|
||||
shift
|
||||
;;
|
||||
--wx-version)
|
||||
require_option_arg "$@"
|
||||
WX_VERSION=$2
|
||||
shift 2
|
||||
;;
|
||||
--wx-url)
|
||||
require_option_arg "$@"
|
||||
WX_URL=$2
|
||||
shift 2
|
||||
;;
|
||||
--wx-sha256)
|
||||
require_option_arg "$@"
|
||||
WX_SHA256=$2
|
||||
shift 2
|
||||
;;
|
||||
-j|--jobs)
|
||||
require_option_arg "$@"
|
||||
JOBS=$2
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
die "Unknown option: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$JOBS" in
|
||||
''|*[!0-9]*)
|
||||
die "jobs must be a positive integer"
|
||||
;;
|
||||
esac
|
||||
[ "$JOBS" -gt 0 ] || die "jobs must be a positive integer"
|
||||
validate_version_token "wxWidgets version" "$WX_VERSION"
|
||||
|
||||
need_tool awk
|
||||
need_tool find
|
||||
need_tool make
|
||||
need_tool rsync
|
||||
need_tool sed
|
||||
need_tool sha256sum
|
||||
need_tool tar
|
||||
need_tool wget
|
||||
need_tool yasm
|
||||
need_tool zstd
|
||||
|
||||
mkdir -p "$WORK_DIR"
|
||||
target_defaults
|
||||
resolve_sdk
|
||||
ensure_gawk
|
||||
prepare_wxwidgets
|
||||
render_package_makefile
|
||||
configure_sdk
|
||||
build_package
|
||||
build_runtime_packages
|
||||
|
||||
echo
|
||||
echo "OpenWrt release: $OPENWRT_VERSION $OPENWRT_TARGET"
|
||||
if [ -n "$SDK_URL" ]; then
|
||||
echo "OpenWrt SDK: $SDK_URL"
|
||||
else
|
||||
echo "OpenWrt SDK: existing directory supplied with --sdk-dir"
|
||||
fi
|
||||
echo "SDK directory: $SDK_DIR"
|
||||
echo "wxWidgets: $WX_URL"
|
||||
echo "VeraCrypt package: $IPK_PATH"
|
||||
sha256sum "$IPK_PATH"
|
||||
echo
|
||||
echo "Run the QEMU runtime test with:"
|
||||
echo " python3 \"$SCRIPTPATH/test_veracrypt_openwrt_qemu.py\" --ipk \"$IPK_PATH\" --work-dir \"$WORK_DIR\""
|
||||
Executable
+864
@@ -0,0 +1,864 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2026 AM Crypto
|
||||
# Governed by the Apache License 2.0 the full text of which is contained
|
||||
# in the file License.txt included in VeraCrypt binary and source
|
||||
# code distribution packages.
|
||||
#
|
||||
|
||||
import argparse
|
||||
import gzip
|
||||
import hashlib
|
||||
import http.server
|
||||
import io
|
||||
import lzma
|
||||
import os
|
||||
import re
|
||||
import selectors
|
||||
import shutil
|
||||
import socketserver
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
DEFAULT_OPENWRT_VERSION = "24.10.6"
|
||||
DEFAULT_TARGET = "x86/64"
|
||||
DEFAULT_PASSWORD = "OpenWrt-VeraCrypt-Test-Password-123456"
|
||||
SHELL_PROMPT = ":~#"
|
||||
PREINSTALLED_PACKAGES = {
|
||||
"base-files",
|
||||
"busybox",
|
||||
"kernel",
|
||||
"libc",
|
||||
"libgcc1",
|
||||
"libpthread",
|
||||
"librt",
|
||||
"opkg",
|
||||
}
|
||||
DEFAULT_RUNTIME_PACKAGES = [
|
||||
"bash",
|
||||
# OpenWrt emits the FUSE3 library IPK with its ABI suffix; it still
|
||||
# Provides: libfuse3.
|
||||
"libfuse3-3",
|
||||
"fuse3-utils",
|
||||
"lvm2",
|
||||
"losetup",
|
||||
"blkid",
|
||||
"mount-utils",
|
||||
"kmod-fuse",
|
||||
"kmod-loop",
|
||||
"kmod-dm",
|
||||
"kmod-crypto-misc",
|
||||
"veracrypt",
|
||||
]
|
||||
|
||||
|
||||
class TestError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ReusableTCPServer(socketserver.TCPServer):
|
||||
allow_reuse_address = True
|
||||
|
||||
|
||||
class PackageMetadata:
|
||||
def __init__(self, path, fields, url=None, source="local"):
|
||||
self.path = path
|
||||
self.url = url
|
||||
self.source = source
|
||||
self.package = fields.get("Package", "")
|
||||
self.version = fields.get("Version", "")
|
||||
self.filename = fields.get("Filename", "")
|
||||
self.sha256sum = fields.get("SHA256sum", "")
|
||||
self.depends = parse_depends(fields.get("Depends", ""))
|
||||
self.provides = parse_name_list(fields.get("Provides", ""))
|
||||
|
||||
def identity(self):
|
||||
if self.path:
|
||||
return f"local:{self.path.resolve()}"
|
||||
return f"remote:{self.url}"
|
||||
|
||||
def display_location(self):
|
||||
return str(self.path) if self.path else self.url
|
||||
|
||||
def package_file_name(self):
|
||||
if self.path:
|
||||
return self.path.name
|
||||
url_path = urllib.parse.urlparse(self.url).path
|
||||
return Path(url_path).name
|
||||
|
||||
|
||||
class Console:
|
||||
def __init__(self, proc, log_path):
|
||||
self.proc = proc
|
||||
self.selector = selectors.DefaultSelector()
|
||||
self.selector.register(proc.stdout, selectors.EVENT_READ)
|
||||
os.set_blocking(proc.stdout.fileno(), False)
|
||||
self.buffer = ""
|
||||
self.log = open(log_path, "w", encoding="utf-8", errors="replace")
|
||||
self.command_index = 0
|
||||
|
||||
def close(self):
|
||||
self.log.close()
|
||||
|
||||
def _record(self, data):
|
||||
text = data.decode("utf-8", errors="replace")
|
||||
self.buffer += text
|
||||
self.log.write(text)
|
||||
self.log.flush()
|
||||
sys.stdout.write(text)
|
||||
sys.stdout.flush()
|
||||
|
||||
def send(self, text):
|
||||
self.proc.stdin.write(text.encode("utf-8"))
|
||||
self.proc.stdin.flush()
|
||||
|
||||
def read_until(self, patterns, timeout, start=0):
|
||||
if isinstance(patterns, str):
|
||||
patterns = [patterns]
|
||||
deadline = time.monotonic() + timeout
|
||||
while time.monotonic() < deadline:
|
||||
tail = self.buffer[start:]
|
||||
for pattern in patterns:
|
||||
if pattern in tail:
|
||||
return pattern
|
||||
if self.proc.poll() is not None:
|
||||
raise TestError(f"QEMU exited before seeing {patterns}")
|
||||
events = self.selector.select(0.25)
|
||||
for key, _ in events:
|
||||
try:
|
||||
data = os.read(key.fileobj.fileno(), 8192)
|
||||
except BlockingIOError:
|
||||
continue
|
||||
if data:
|
||||
self._record(data)
|
||||
raise TestError(f"Timed out waiting for {patterns}")
|
||||
|
||||
def run(self, command, timeout=120):
|
||||
self.command_index += 1
|
||||
marker = f"__VC_STATUS_{self.command_index:03d}__"
|
||||
start = len(self.buffer)
|
||||
wrapped = (
|
||||
f"printf '\\n__VC_BEGIN_{self.command_index:03d}__\\n'\n"
|
||||
"{\n"
|
||||
f"{command}\n"
|
||||
"}\n"
|
||||
f"echo {marker}:$?\n"
|
||||
)
|
||||
self.send(wrapped)
|
||||
deadline = time.monotonic() + timeout
|
||||
status_re = re.compile(rf"{re.escape(marker)}:(\d+)")
|
||||
while time.monotonic() < deadline:
|
||||
tail = self.buffer[start:]
|
||||
match = status_re.search(tail)
|
||||
if match:
|
||||
self.read_until(SHELL_PROMPT, 60, start + match.end())
|
||||
tail = self.buffer[start:]
|
||||
status = int(match.group(1))
|
||||
if status != 0:
|
||||
raise TestError(f"Command failed with status {status}: {command}")
|
||||
return tail
|
||||
if self.proc.poll() is not None:
|
||||
raise TestError(f"QEMU exited while running: {command}")
|
||||
events = self.selector.select(0.25)
|
||||
for key, _ in events:
|
||||
try:
|
||||
data = os.read(key.fileobj.fileno(), 8192)
|
||||
except BlockingIOError:
|
||||
continue
|
||||
if data:
|
||||
self._record(data)
|
||||
raise TestError(f"Timed out running: {command}")
|
||||
|
||||
|
||||
def target_info(target, version):
|
||||
if target != "x86/64":
|
||||
raise TestError("Only x86/64 is currently supported by this QEMU test")
|
||||
return {
|
||||
"slug": "x86-64",
|
||||
"image": f"openwrt-{version}-x86-64-generic-ext4-combined.img.gz",
|
||||
"manifest": f"openwrt-{version}-x86-64.manifest",
|
||||
"base_url": f"https://downloads.openwrt.org/releases/{version}/targets/x86/64",
|
||||
}
|
||||
|
||||
|
||||
def sha256_file(path):
|
||||
digest = hashlib.sha256()
|
||||
with open(path, "rb") as fh:
|
||||
for chunk in iter(lambda: fh.read(1024 * 1024), b""):
|
||||
digest.update(chunk)
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def download(url, path, expected_sha256=None):
|
||||
if path.exists() and expected_sha256:
|
||||
actual_sha = sha256_file(path)
|
||||
if actual_sha == expected_sha256:
|
||||
return
|
||||
print(f"Checksum mismatch for existing {path}; re-downloading", file=sys.stderr)
|
||||
path.unlink()
|
||||
elif path.exists():
|
||||
return
|
||||
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
tmp = path.with_name(f"{path.name}.tmp-{os.getpid()}")
|
||||
if tmp.exists():
|
||||
tmp.unlink()
|
||||
|
||||
print(f"Downloading {url}")
|
||||
try:
|
||||
with urllib.request.urlopen(url) as response, open(tmp, "wb") as out:
|
||||
shutil.copyfileobj(response, out)
|
||||
if expected_sha256:
|
||||
actual_sha = sha256_file(tmp)
|
||||
if actual_sha != expected_sha256:
|
||||
raise TestError(f"SHA-256 mismatch for {path}: expected {expected_sha256}, got {actual_sha}")
|
||||
tmp.replace(path)
|
||||
finally:
|
||||
if tmp.exists():
|
||||
tmp.unlink()
|
||||
|
||||
|
||||
def read_text_archive(path):
|
||||
data = path.read_bytes()
|
||||
if path.name.endswith(".gz"):
|
||||
return gzip.decompress(data).decode("utf-8", errors="replace")
|
||||
if path.name.endswith(".xz"):
|
||||
return lzma.decompress(data).decode("utf-8", errors="replace")
|
||||
return data.decode("utf-8", errors="replace")
|
||||
|
||||
|
||||
def expected_sha_from_sums(sums_path, filename):
|
||||
with open(sums_path, "r", encoding="utf-8") as fh:
|
||||
for line in fh:
|
||||
parts = line.split()
|
||||
if len(parts) >= 2 and parts[1].lstrip("*") == filename:
|
||||
return parts[0]
|
||||
return None
|
||||
|
||||
|
||||
def sh_quote(text):
|
||||
return "'" + str(text).replace("'", "'\"'\"'") + "'"
|
||||
|
||||
|
||||
def read_ar_control_archive(ipk_path):
|
||||
with open(ipk_path, "rb") as fh:
|
||||
magic = fh.read(8)
|
||||
if magic != b"!<arch>\n":
|
||||
raise TestError(f"Unsupported .ipk format for {ipk_path}")
|
||||
|
||||
while True:
|
||||
header = fh.read(60)
|
||||
if not header:
|
||||
break
|
||||
if len(header) != 60 or header[58:60] != b"`\n":
|
||||
raise TestError(f"Malformed ar archive in {ipk_path}")
|
||||
|
||||
name = header[:16].decode("utf-8", errors="replace").strip().rstrip("/")
|
||||
size = int(header[48:58].decode("ascii").strip())
|
||||
data = fh.read(size)
|
||||
if size % 2:
|
||||
fh.read(1)
|
||||
|
||||
if Path(name).name.startswith("control.tar"):
|
||||
return name, data
|
||||
|
||||
raise TestError(f"No control archive found in {ipk_path}")
|
||||
|
||||
|
||||
def extract_top_level_control_archive(ipk_path):
|
||||
with open(ipk_path, "rb") as fh:
|
||||
magic = fh.read(8)
|
||||
|
||||
if magic == b"!<arch>\n":
|
||||
return read_ar_control_archive(ipk_path)
|
||||
|
||||
try:
|
||||
with tarfile.open(ipk_path, "r:*") as outer:
|
||||
for member in outer:
|
||||
if Path(member.name).name.startswith("control.tar"):
|
||||
member_file = outer.extractfile(member)
|
||||
if member_file:
|
||||
return member.name, member_file.read()
|
||||
except tarfile.TarError as exc:
|
||||
raise TestError(f"Unsupported .ipk format for {ipk_path}: {exc}") from exc
|
||||
|
||||
raise TestError(f"No control archive found in {ipk_path}")
|
||||
|
||||
|
||||
def open_control_tar(name, data):
|
||||
try:
|
||||
return tarfile.open(fileobj=io.BytesIO(data), mode="r:*")
|
||||
except tarfile.TarError:
|
||||
pass
|
||||
|
||||
if name.endswith(".zst"):
|
||||
zstd = shutil.which("zstd")
|
||||
if not zstd:
|
||||
raise TestError(f"{name} is zstd-compressed, but zstd was not found")
|
||||
result = subprocess.run([zstd, "-dc"], input=data, stdout=subprocess.PIPE, check=False)
|
||||
if result.returncode != 0:
|
||||
raise TestError(f"zstd failed while reading {name}")
|
||||
return tarfile.open(fileobj=io.BytesIO(result.stdout), mode="r:")
|
||||
|
||||
if name.endswith(".gz"):
|
||||
return tarfile.open(fileobj=io.BytesIO(gzip.decompress(data)), mode="r:")
|
||||
if name.endswith(".xz"):
|
||||
return tarfile.open(fileobj=io.BytesIO(lzma.decompress(data)), mode="r:")
|
||||
|
||||
raise TestError(f"Unsupported control archive compression: {name}")
|
||||
|
||||
|
||||
def read_control_fields(ipk_path):
|
||||
control_name, control_data = extract_top_level_control_archive(ipk_path)
|
||||
with open_control_tar(control_name, control_data) as control_tar:
|
||||
for member in control_tar:
|
||||
if member.name in ("control", "./control") or member.name.endswith("/control"):
|
||||
member_file = control_tar.extractfile(member)
|
||||
if member_file:
|
||||
text = member_file.read().decode("utf-8", errors="replace")
|
||||
return parse_control_fields(text)
|
||||
raise TestError(f"No control file found in {ipk_path}")
|
||||
|
||||
|
||||
def parse_control_fields(text):
|
||||
fields = {}
|
||||
current = None
|
||||
for line in text.splitlines():
|
||||
if not line:
|
||||
current = None
|
||||
continue
|
||||
if line[0].isspace() and current:
|
||||
fields[current] += "\n" + line.strip()
|
||||
continue
|
||||
key, sep, value = line.partition(":")
|
||||
if not sep:
|
||||
continue
|
||||
current = key
|
||||
fields[key] = value.strip()
|
||||
return fields
|
||||
|
||||
|
||||
def parse_control_paragraphs(text):
|
||||
paragraphs = []
|
||||
lines = []
|
||||
for line in text.splitlines():
|
||||
if line.strip():
|
||||
lines.append(line)
|
||||
continue
|
||||
if lines:
|
||||
paragraphs.append(parse_control_fields("\n".join(lines)))
|
||||
lines = []
|
||||
if lines:
|
||||
paragraphs.append(parse_control_fields("\n".join(lines)))
|
||||
return paragraphs
|
||||
|
||||
|
||||
def parse_package_name(text):
|
||||
text = re.sub(r"\s*\([^)]*\)", "", text).strip()
|
||||
return text.split()[0] if text else ""
|
||||
|
||||
|
||||
def parse_depends(value):
|
||||
groups = []
|
||||
for item in value.replace("\n", " ").split(","):
|
||||
alternatives = [parse_package_name(part) for part in item.split("|")]
|
||||
alternatives = [name for name in alternatives if name]
|
||||
if alternatives:
|
||||
groups.append(alternatives)
|
||||
return groups
|
||||
|
||||
|
||||
def parse_name_list(value):
|
||||
names = []
|
||||
for item in value.replace("\n", " ").split(","):
|
||||
name = parse_package_name(item)
|
||||
if name:
|
||||
names.append(name)
|
||||
return names
|
||||
|
||||
|
||||
def infer_package_bin_dir(ipk_path):
|
||||
for parent in [ipk_path.parent] + list(ipk_path.parents):
|
||||
if parent.name == "bin":
|
||||
return parent
|
||||
return ipk_path.parent
|
||||
|
||||
|
||||
def read_package_metadata(ipk_path):
|
||||
meta = PackageMetadata(ipk_path, read_control_fields(ipk_path))
|
||||
if not meta.package:
|
||||
raise TestError(f"Package metadata in {ipk_path} has no Package field")
|
||||
return meta
|
||||
|
||||
|
||||
def add_package_metadata(index, meta, override=False):
|
||||
for name in [meta.package] + meta.provides:
|
||||
if name and (override or name not in index):
|
||||
index[name] = meta
|
||||
|
||||
|
||||
def build_package_index(package_bin_dir, veracrypt_ipk, skip_local_kmods=False):
|
||||
if not package_bin_dir.is_dir():
|
||||
raise TestError(f"Package bin directory does not exist: {package_bin_dir}")
|
||||
|
||||
index = {}
|
||||
|
||||
for ipk in sorted(package_bin_dir.rglob("*.ipk")):
|
||||
if skip_local_kmods and ipk.name.startswith("kmod-"):
|
||||
continue
|
||||
add_package_metadata(index, read_package_metadata(ipk))
|
||||
|
||||
add_package_metadata(index, read_package_metadata(veracrypt_ipk), override=True)
|
||||
return index
|
||||
|
||||
|
||||
def parse_packages_index(text, feed_url, source):
|
||||
index = {}
|
||||
feed_url = feed_url.rstrip("/") + "/"
|
||||
for fields in parse_control_paragraphs(text):
|
||||
package = fields.get("Package", "")
|
||||
filename = fields.get("Filename", "")
|
||||
if not package or not filename:
|
||||
continue
|
||||
url = urllib.parse.urljoin(feed_url, filename)
|
||||
meta = PackageMetadata(None, fields, url=url, source=source)
|
||||
add_package_metadata(index, meta)
|
||||
return index
|
||||
|
||||
|
||||
def download_packages_index(index_url, cache_path):
|
||||
download(index_url, cache_path)
|
||||
return read_text_archive(cache_path)
|
||||
|
||||
|
||||
def official_index_cache_path(work_dir, info, name):
|
||||
safe_name = re.sub(r"[^A-Za-z0-9._-]+", "_", name).strip("_")
|
||||
return work_dir / "package-indexes" / info["slug"] / safe_name
|
||||
|
||||
|
||||
def kmod_dir_from_kernel_version(version):
|
||||
match = re.match(r"^([^~]+)~([0-9a-fA-F]+)-r([0-9A-Za-z_.+-]+)$", version)
|
||||
if not match:
|
||||
return None
|
||||
linux_version, vermagic, release = match.groups()
|
||||
return f"{linux_version}-{release}-{vermagic}"
|
||||
|
||||
|
||||
def official_manifest_kernel_version(args, info):
|
||||
manifest_url = f"{info['base_url']}/{info['manifest']}"
|
||||
cache_path = official_index_cache_path(args.work_dir, info, info["manifest"])
|
||||
download(manifest_url, cache_path)
|
||||
manifest = read_text_archive(cache_path)
|
||||
for line in manifest.splitlines():
|
||||
name, sep, version = line.partition(" - ")
|
||||
if sep and name == "kernel":
|
||||
return version.strip()
|
||||
return None
|
||||
|
||||
|
||||
def discover_single_kmod_feed_url(info):
|
||||
kmods_url = f"{info['base_url']}/kmods/"
|
||||
print(f"Discovering OpenWrt kmod feed from {kmods_url}")
|
||||
with urllib.request.urlopen(kmods_url) as response:
|
||||
html = response.read().decode("utf-8", errors="replace")
|
||||
candidates = sorted(set(re.findall(r'href="([^"/]+-[^"/]+-[0-9a-fA-F]+/)"', html)))
|
||||
if len(candidates) == 1:
|
||||
return urllib.parse.urljoin(kmods_url, candidates[0]).rstrip("/")
|
||||
if not candidates:
|
||||
raise TestError(f"Could not discover an OpenWrt kmod feed at {kmods_url}")
|
||||
raise TestError(
|
||||
"Multiple OpenWrt kmod feeds are available; pass --kmod-feed-url explicitly: "
|
||||
+ ", ".join(urllib.parse.urljoin(kmods_url, candidate).rstrip("/") for candidate in candidates)
|
||||
)
|
||||
|
||||
|
||||
def resolve_official_kmod_feed_url(args, info):
|
||||
if args.kmod_feed_url:
|
||||
return args.kmod_feed_url.rstrip("/")
|
||||
|
||||
kernel_version = official_manifest_kernel_version(args, info)
|
||||
if kernel_version:
|
||||
kmod_dir = kmod_dir_from_kernel_version(kernel_version)
|
||||
if kmod_dir:
|
||||
return f"{info['base_url']}/kmods/{kmod_dir}"
|
||||
|
||||
return discover_single_kmod_feed_url(info)
|
||||
|
||||
|
||||
def official_kmod_package_index(args):
|
||||
info = target_info(args.target, args.openwrt_version)
|
||||
feed_url = resolve_official_kmod_feed_url(args, info)
|
||||
index_url = f"{feed_url}/Packages.gz"
|
||||
cache_path = official_index_cache_path(args.work_dir, info, f"kmods-{Path(feed_url).name}-Packages.gz")
|
||||
text = download_packages_index(index_url, cache_path)
|
||||
index = parse_packages_index(text, feed_url, f"official kmods {feed_url}")
|
||||
if not index:
|
||||
raise TestError(f"No packages were found in OpenWrt kmod feed {index_url}")
|
||||
return index, feed_url
|
||||
|
||||
|
||||
def overlay_package_index(index, overlay):
|
||||
seen = set()
|
||||
for meta in overlay.values():
|
||||
meta_key = meta.identity()
|
||||
if meta_key in seen:
|
||||
continue
|
||||
seen.add(meta_key)
|
||||
add_package_metadata(index, meta, override=True)
|
||||
|
||||
|
||||
def resolve_runtime_packages(package_index, seed_packages):
|
||||
resolved = []
|
||||
resolved_paths = set()
|
||||
visiting = set()
|
||||
|
||||
def visit(name, chain):
|
||||
if name in PREINSTALLED_PACKAGES:
|
||||
return
|
||||
meta = package_index.get(name)
|
||||
if not meta:
|
||||
chain_text = " -> ".join(chain + [name])
|
||||
raise TestError(f"Missing .ipk metadata for dependency '{name}' while resolving {chain_text}")
|
||||
|
||||
meta_key = meta.identity()
|
||||
if meta_key in resolved_paths:
|
||||
return
|
||||
if meta_key in visiting:
|
||||
return
|
||||
|
||||
visiting.add(meta_key)
|
||||
for alternatives in meta.depends:
|
||||
selected = None
|
||||
for alternative in alternatives:
|
||||
if alternative in PREINSTALLED_PACKAGES or alternative in package_index:
|
||||
selected = alternative
|
||||
break
|
||||
if not selected:
|
||||
chain_text = " -> ".join(chain + [meta.package])
|
||||
raise TestError(
|
||||
f"Missing .ipk metadata for dependency '{alternatives[0]}' required by {chain_text}"
|
||||
)
|
||||
visit(selected, chain + [meta.package])
|
||||
|
||||
visiting.remove(meta_key)
|
||||
resolved_paths.add(meta_key)
|
||||
resolved.append(meta)
|
||||
|
||||
for package in seed_packages:
|
||||
visit(package, [])
|
||||
|
||||
return resolved
|
||||
|
||||
|
||||
def staged_package_name(index, meta):
|
||||
return f"{index:03d}-{meta.package_file_name()}"
|
||||
|
||||
|
||||
def ensure_remote_package(meta, cache_dir):
|
||||
if not meta.url:
|
||||
raise TestError(f"Package {meta.package} has no local path or remote URL")
|
||||
|
||||
file_name = meta.package_file_name()
|
||||
cache_name = f"{hashlib.sha256(meta.url.encode('utf-8')).hexdigest()[:12]}-{file_name}"
|
||||
cached = cache_dir / cache_name
|
||||
|
||||
def verify_cached():
|
||||
if meta.sha256sum and sha256_file(cached) != meta.sha256sum:
|
||||
cached.unlink()
|
||||
return False
|
||||
return True
|
||||
|
||||
if cached.exists() and verify_cached():
|
||||
return cached
|
||||
|
||||
download(meta.url, cached, meta.sha256sum)
|
||||
if meta.sha256sum and sha256_file(cached) != meta.sha256sum:
|
||||
raise TestError(f"SHA-256 mismatch for {cached} downloaded from {meta.url}")
|
||||
return cached
|
||||
|
||||
|
||||
def stage_packages(packages, directory, cache_dir):
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
for index, meta in enumerate(packages):
|
||||
source = meta.path if meta.path else ensure_remote_package(meta, cache_dir)
|
||||
shutil.copy2(source, directory / staged_package_name(index, meta))
|
||||
|
||||
|
||||
def package_download_command(packages, http_port):
|
||||
lines = [
|
||||
"set -e",
|
||||
"rm -rf /tmp/veracrypt-ipks",
|
||||
"mkdir -p /tmp/veracrypt-ipks",
|
||||
]
|
||||
for index, meta in enumerate(packages):
|
||||
package_name = staged_package_name(index, meta)
|
||||
url_path = urllib.parse.quote(package_name, safe="")
|
||||
lines.append(
|
||||
f"wget -O {sh_quote(f'/tmp/veracrypt-ipks/{package_name}')} "
|
||||
f"{sh_quote(f'http://10.0.2.2:{http_port}/{url_path}')}"
|
||||
)
|
||||
lines.append("opkg install /tmp/veracrypt-ipks/*.ipk")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def prepare_image(args):
|
||||
if args.image:
|
||||
image = Path(args.image).resolve()
|
||||
if not image.exists():
|
||||
raise TestError(f"Image does not exist: {image}")
|
||||
return image
|
||||
|
||||
info = target_info(args.target, args.openwrt_version)
|
||||
image_gz = args.work_dir / "images" / info["image"]
|
||||
image = image_gz.with_suffix("")
|
||||
sums = args.work_dir / "images" / f"sha256sums-{args.openwrt_version}-{info['slug']}"
|
||||
|
||||
download(f"{info['base_url']}/sha256sums", sums)
|
||||
expected_sha = expected_sha_from_sums(sums, info["image"])
|
||||
if not expected_sha:
|
||||
raise TestError(f"Could not find {info['image']} in {sums}")
|
||||
download(f"{info['base_url']}/{info['image']}", image_gz, expected_sha)
|
||||
actual_sha = sha256_file(image_gz)
|
||||
if actual_sha != expected_sha:
|
||||
raise TestError(f"SHA-256 mismatch for {image_gz}: expected {expected_sha}, got {actual_sha}")
|
||||
|
||||
if not image.exists():
|
||||
print(f"Extracting {image_gz}")
|
||||
with open(image, "wb") as out:
|
||||
result = subprocess.run(["gzip", "-cd", str(image_gz)], stdout=out)
|
||||
if result.returncode not in (0, 2):
|
||||
raise TestError(f"gzip failed while extracting {image_gz}")
|
||||
|
||||
return image
|
||||
|
||||
|
||||
def start_http_server(directory, address, port):
|
||||
handler = lambda *args, **kwargs: http.server.SimpleHTTPRequestHandler(
|
||||
*args, directory=str(directory), **kwargs
|
||||
)
|
||||
server = ReusableTCPServer((address, port), handler)
|
||||
thread = threading.Thread(target=server.serve_forever, daemon=True)
|
||||
thread.start()
|
||||
return server
|
||||
|
||||
|
||||
def boot_qemu(args, image):
|
||||
qemu = shutil.which(args.qemu) if os.sep not in args.qemu else args.qemu
|
||||
if not qemu:
|
||||
raise TestError("qemu-system-x86_64 was not found; install QEMU or pass --qemu")
|
||||
|
||||
netdev = "user,id=net0"
|
||||
if args.ssh_port is not None:
|
||||
netdev += f",hostfwd=tcp::{args.ssh_port}-:22"
|
||||
|
||||
qemu_cmd = [
|
||||
qemu,
|
||||
"-accel", args.accel,
|
||||
"-M", "pc",
|
||||
"-cpu", args.cpu,
|
||||
"-m", args.memory,
|
||||
"-smp", str(args.smp),
|
||||
"-nographic",
|
||||
"-drive", f"file={image},format=raw,if=virtio",
|
||||
"-netdev", netdev,
|
||||
"-device", "virtio-net-pci,netdev=net0",
|
||||
]
|
||||
if args.qemu_data_dir:
|
||||
qemu_cmd[1:1] = ["-L", str(args.qemu_data_dir)]
|
||||
|
||||
print("Starting QEMU:")
|
||||
print(" ".join(qemu_cmd))
|
||||
return subprocess.Popen(
|
||||
qemu_cmd,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
|
||||
|
||||
def run_guest_tests(args, console, http_port, packages):
|
||||
console.read_until(["Please press Enter", SHELL_PROMPT], args.boot_timeout)
|
||||
prompt_start = len(console.buffer)
|
||||
console.send("\n")
|
||||
console.read_until(SHELL_PROMPT, 90, prompt_start)
|
||||
|
||||
console.run(
|
||||
"sleep 20\n"
|
||||
"if ip link show br-lan >/dev/null 2>&1; then NETDEV=br-lan; else NETDEV=eth0; fi\n"
|
||||
"ip addr flush dev \"$NETDEV\" || true\n"
|
||||
"ip link set \"$NETDEV\" up\n"
|
||||
"udhcpc -n -q -t 10 -i \"$NETDEV\"\n"
|
||||
"ip -4 addr show \"$NETDEV\"\n"
|
||||
"ping -c 1 10.0.2.2",
|
||||
timeout=120,
|
||||
)
|
||||
|
||||
console.run(package_download_command(packages, http_port), timeout=900)
|
||||
|
||||
version_output = console.run("veracrypt --text --version", timeout=120)
|
||||
if "VeraCrypt " not in version_output:
|
||||
raise TestError("version command did not print a VeraCrypt version")
|
||||
|
||||
test_output = console.run("veracrypt --text --test", timeout=240)
|
||||
if "Self-tests of all algorithms passed" not in test_output:
|
||||
raise TestError("algorithm self-test did not report success")
|
||||
|
||||
if not args.skip_container:
|
||||
quoted_container_size = sh_quote(args.container_size)
|
||||
quoted_password = sh_quote(args.password)
|
||||
console.run("dd if=/dev/urandom of=/tmp/vc-random.bin bs=1M count=1", timeout=120)
|
||||
console.run(
|
||||
"veracrypt --text --create /tmp/openwrt-test.hc "
|
||||
f"--size={quoted_container_size} "
|
||||
f"--password={quoted_password} "
|
||||
"--encryption=AES --hash=SHA-512 --filesystem=none "
|
||||
"--volume-type=normal --random-source=/tmp/vc-random.bin "
|
||||
"--quick --force --non-interactive",
|
||||
timeout=360,
|
||||
)
|
||||
console.run("mkdir -p /mnt/veracrypt-test", timeout=60)
|
||||
console.run(
|
||||
"veracrypt --text --mount /tmp/openwrt-test.hc /mnt/veracrypt-test "
|
||||
f"--password={quoted_password} "
|
||||
"--pim=0 --keyfiles='' --protect-hidden=no --filesystem=none --non-interactive",
|
||||
timeout=240,
|
||||
)
|
||||
list_output = console.run("veracrypt --text --list", timeout=120)
|
||||
if "/dev/mapper/veracrypt" not in list_output:
|
||||
raise TestError("container did not appear in veracrypt --list output")
|
||||
console.run("veracrypt --text --unmount /tmp/openwrt-test.hc", timeout=180)
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description="Boot OpenWrt in QEMU and test a VeraCrypt .ipk")
|
||||
parser.add_argument("--ipk", required=True, type=Path, help="Path to veracrypt_*.ipk")
|
||||
parser.add_argument(
|
||||
"--package-bin-dir",
|
||||
type=Path,
|
||||
help="SDK bin directory containing local dependency .ipk files; defaults to the nearest bin parent of --ipk",
|
||||
)
|
||||
parser.add_argument("--openwrt-version", default=DEFAULT_OPENWRT_VERSION)
|
||||
parser.add_argument("--target", default=DEFAULT_TARGET)
|
||||
parser.add_argument("--work-dir", type=Path, default=None)
|
||||
parser.add_argument("--image", type=Path, help="Use an already extracted OpenWrt raw image")
|
||||
parser.add_argument("--qemu", default="qemu-system-x86_64")
|
||||
parser.add_argument("--qemu-data-dir", type=Path, help="QEMU pc-bios directory for locally extracted QEMU builds")
|
||||
parser.add_argument("--accel", default="tcg")
|
||||
parser.add_argument("--cpu", default="max")
|
||||
parser.add_argument("--memory", default="512M")
|
||||
parser.add_argument("--smp", default=1, type=int)
|
||||
parser.add_argument(
|
||||
"--ssh-port",
|
||||
type=int,
|
||||
metavar="PORT",
|
||||
help="Forward host TCP PORT to guest SSH; disabled by default",
|
||||
)
|
||||
parser.add_argument("--http-port", default=0, type=int)
|
||||
parser.add_argument(
|
||||
"--http-bind-address",
|
||||
default="127.0.0.1",
|
||||
help="Host address for the temporary package server (default: 127.0.0.1)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--kmod-feed-url",
|
||||
help="OpenWrt kmod feed URL; defaults to the official feed matching --openwrt-version and --target",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--local-kmods",
|
||||
action="store_true",
|
||||
help="Resolve kmod-* packages from --package-bin-dir instead of the official OpenWrt kmod feed",
|
||||
)
|
||||
parser.add_argument("--boot-timeout", default=180, type=int)
|
||||
parser.add_argument("--container-size", default="16M")
|
||||
parser.add_argument("--password", default=DEFAULT_PASSWORD)
|
||||
parser.add_argument("--skip-container", action="store_true")
|
||||
parser.add_argument("--keep-image", action="store_true")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
args.ipk = args.ipk.resolve()
|
||||
if not args.ipk.exists():
|
||||
raise TestError(f"Package does not exist: {args.ipk}")
|
||||
if args.package_bin_dir is None:
|
||||
args.package_bin_dir = infer_package_bin_dir(args.ipk)
|
||||
args.package_bin_dir = args.package_bin_dir.resolve()
|
||||
|
||||
repo_root = Path(__file__).resolve().parents[2]
|
||||
if args.work_dir is None:
|
||||
args.work_dir = repo_root.parent / "openwrt-veracrypt"
|
||||
args.work_dir = args.work_dir.resolve()
|
||||
args.work_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
package_index = build_package_index(
|
||||
args.package_bin_dir,
|
||||
args.ipk,
|
||||
skip_local_kmods=not args.local_kmods,
|
||||
)
|
||||
if not args.local_kmods:
|
||||
kmod_index, kmod_feed_url = official_kmod_package_index(args)
|
||||
overlay_package_index(package_index, kmod_index)
|
||||
print(f"Using OpenWrt kmod feed: {kmod_feed_url}")
|
||||
packages = resolve_runtime_packages(package_index, DEFAULT_RUNTIME_PACKAGES)
|
||||
print("Resolved OpenWrt packages:")
|
||||
for index, meta in enumerate(packages):
|
||||
print(f" {index:02d} {meta.package}: {meta.display_location()}")
|
||||
|
||||
base_image = prepare_image(args)
|
||||
test_image = args.work_dir / "images" / f"{base_image.stem}-veracrypt-test.img"
|
||||
test_image.parent.mkdir(parents=True, exist_ok=True)
|
||||
if test_image.exists():
|
||||
test_image.unlink()
|
||||
shutil.copyfile(base_image, test_image)
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix="veracrypt-ipks-", dir=args.work_dir) as package_dir:
|
||||
server_root = Path(package_dir)
|
||||
stage_packages(packages, server_root, args.work_dir / "package-cache")
|
||||
server = start_http_server(server_root, args.http_bind_address, args.http_port)
|
||||
http_port = server.server_address[1]
|
||||
print(f"Serving staged packages from {server_root} on http://{args.http_bind_address}:{http_port}/")
|
||||
|
||||
log_path = args.work_dir / "openwrt-qemu-test.log"
|
||||
proc = None
|
||||
console = None
|
||||
try:
|
||||
proc = boot_qemu(args, test_image)
|
||||
console = Console(proc, log_path)
|
||||
run_guest_tests(args, console, http_port, packages)
|
||||
console.send("poweroff\n")
|
||||
try:
|
||||
proc.wait(timeout=90)
|
||||
except subprocess.TimeoutExpired:
|
||||
proc.terminate()
|
||||
proc.wait(timeout=30)
|
||||
finally:
|
||||
server.shutdown()
|
||||
server.server_close()
|
||||
if console:
|
||||
console.close()
|
||||
if proc and proc.poll() is None:
|
||||
proc.terminate()
|
||||
if not args.keep_image and test_image.exists():
|
||||
test_image.unlink()
|
||||
|
||||
print()
|
||||
print("OpenWrt QEMU test passed")
|
||||
print(f"Log: {log_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except TestError as exc:
|
||||
print(f"Error: {exc}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
@@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,26,28,0
|
||||
PRODUCTVERSION 1,26,28,0
|
||||
FILEVERSION 1,26,28,1
|
||||
PRODUCTVERSION 1,26,28,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -5043,6 +5043,12 @@ namespace VeraCrypt
|
||||
|
||||
EfiBootInst.PrepareBootPartition();
|
||||
|
||||
if (!EfiBootInst.FileExists (szStdMsBootloader))
|
||||
{
|
||||
Error ("WINDOWS_EFI_BOOT_LOADER_MISSING", ParentWindow);
|
||||
throw UserAbort (SRC_POS);
|
||||
}
|
||||
|
||||
EfiBootInst.GetFileSize(szStdMsBootloader, loaderSize);
|
||||
bootLoaderBuf.resize ((size_t) loaderSize);
|
||||
EfiBootInst.ReadFile(szStdMsBootloader, &bootLoaderBuf[0], (DWORD) loaderSize);
|
||||
|
||||
+2
-2
@@ -801,7 +801,8 @@ int EAGetLargestKeyForMode (int mode)
|
||||
return key;
|
||||
}
|
||||
|
||||
// Returns the maximum number of bytes necessary to be generated by the PBKDF2 (PKCS #5)
|
||||
// Returns the maximum number of bytes necessary to be generated by PBKDF2 (PKCS #5).
|
||||
// Argon2id header key material uses the fixed ARGON2_HEADER_KEYDATA_SIZE value.
|
||||
int GetMaxPkcs5OutSize (void)
|
||||
{
|
||||
int size = 32;
|
||||
@@ -1488,4 +1489,3 @@ void VcUnprotectKeys (PCRYPTO_INFO pCryptoInfo, uint64 encID)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -44,6 +44,12 @@ extern "C" {
|
||||
// Size of the volume header area containing concatenated master key(s) and secondary key(s) (XTS mode)
|
||||
#define MASTER_KEYDATA_SIZE 256
|
||||
|
||||
#ifndef VC_DCS_DISABLE_ARGON2
|
||||
// VeraCrypt Argon2id header key material size, in bytes, for the current volume format.
|
||||
// This is intentionally fixed for compatibility and must not depend on GetMaxPkcs5OutSize().
|
||||
#define ARGON2_HEADER_KEYDATA_SIZE 192
|
||||
#endif
|
||||
|
||||
// The first PRF to try when mounting
|
||||
#define FIRST_PRF_ID 1
|
||||
|
||||
|
||||
@@ -6570,7 +6570,7 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
|
||||
|
||||
case ARGON2:
|
||||
/* test with ARGON2 used as the PRF */
|
||||
if (derive_key_argon2 ((const unsigned char*) "passphrase-1234567890", 21, (const unsigned char*)tmp_salt, 64, iterations, memoryCost, dk, MASTER_KEYDATA_SIZE, NULL) != 0)
|
||||
if (derive_key_argon2 ((const unsigned char*) "passphrase-1234567890", 21, (const unsigned char*)tmp_salt, 64, iterations, memoryCost, dk, ARGON2_HEADER_KEYDATA_SIZE, NULL) != 0)
|
||||
goto key_derivation_error;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
|
||||
|
||||
case ARGON2:
|
||||
derivationResult = derive_key_argon2(workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
|
||||
workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.Memorycost, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize(), workItem->KeyDerivation.pAbortKeyDerivation);
|
||||
workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.Memorycost, workItem->KeyDerivation.DerivedKey, ARGON2_HEADER_KEYDATA_SIZE, workItem->KeyDerivation.pAbortKeyDerivation);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -7,12 +7,16 @@ namespace VeraCrypt
|
||||
|
||||
SCardManager::SCardManager()
|
||||
{
|
||||
#ifndef TC_OPENBSD
|
||||
loader->Initialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
SCardManager::~SCardManager()
|
||||
{
|
||||
#ifndef TC_OPENBSD
|
||||
loader->Finalize();
|
||||
#endif
|
||||
}
|
||||
|
||||
vector<wstring> SCardManager::GetReaders()
|
||||
@@ -106,4 +110,4 @@ namespace VeraCrypt
|
||||
|
||||
throw InvalidEMVPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace VeraCrypt
|
||||
throw;
|
||||
}
|
||||
|
||||
for(const CK_OBJECT_HANDLE & dataHandle: GetObjects(slotId, CKO_DATA))
|
||||
foreach(const CK_OBJECT_HANDLE & dataHandle, GetObjects(slotId, CKO_DATA))
|
||||
{
|
||||
SecurityTokenKeyfile keyfile;
|
||||
keyfile.Handle = dataHandle;
|
||||
|
||||
+17
-2
@@ -448,7 +448,7 @@ KeyReady: ;
|
||||
case ARGON2:
|
||||
{
|
||||
int derivationResult = derive_key_argon2(keyInfo->userKey, keyInfo->keyLength, keyInfo->salt,
|
||||
PKCS5_SALT_SIZE, keyInfo->noIterations, keyInfo->memoryCost, dk, GetMaxPkcs5OutSize(), &abortKeyDerivation);
|
||||
PKCS5_SALT_SIZE, keyInfo->noIterations, keyInfo->memoryCost, dk, ARGON2_HEADER_KEYDATA_SIZE, &abortKeyDerivation);
|
||||
if (derivationResult != 0)
|
||||
{
|
||||
if (selected_pkcs5_prf == 0)
|
||||
@@ -492,6 +492,12 @@ KeyReady: ;
|
||||
if (!EAIsModeSupported (cryptoInfo->ea, cryptoInfo->mode))
|
||||
continue; // This encryption algorithm has never been available with this mode of operation
|
||||
|
||||
#ifndef VC_DCS_DISABLE_ARGON2
|
||||
/* Only XTS mode reaches this point; both XTS keys must fit in the fixed Argon2id output. */
|
||||
if (pkcs5_prf == ARGON2 && EAGetKeySize (cryptoInfo->ea) * 2 > ARGON2_HEADER_KEYDATA_SIZE)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
blockSize = CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea));
|
||||
|
||||
status = EAInit (cryptoInfo->ea, dk + primaryKeyOffset, cryptoInfo->ks);
|
||||
@@ -1074,6 +1080,15 @@ int CreateVolumeHeaderInMemory (HWND hwndDlg, BOOL bBoot, unsigned char *header,
|
||||
// User selected encryption algorithm
|
||||
cryptoInfo->ea = ea;
|
||||
|
||||
#ifndef VC_DCS_DISABLE_ARGON2
|
||||
if (pkcs5_prf == ARGON2 && EAGetKeySize (ea) * 2 > ARGON2_HEADER_KEYDATA_SIZE)
|
||||
{
|
||||
crypto_close (cryptoInfo);
|
||||
retVal = ERR_PARAMETER_INCORRECT;
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
// User selected PRF
|
||||
cryptoInfo->pkcs5 = pkcs5_prf;
|
||||
cryptoInfo->noIterations = keyInfo.noIterations;
|
||||
@@ -1130,7 +1145,7 @@ int CreateVolumeHeaderInMemory (HWND hwndDlg, BOOL bBoot, unsigned char *header,
|
||||
case ARGON2:
|
||||
{
|
||||
int derivationResult = derive_key_argon2(keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
|
||||
PKCS5_SALT_SIZE, keyInfo.noIterations, keyInfo.memoryCost, dk, GetMaxPkcs5OutSize(), NULL);
|
||||
PKCS5_SALT_SIZE, keyInfo.noIterations, keyInfo.memoryCost, dk, ARGON2_HEADER_KEYDATA_SIZE, NULL);
|
||||
if (derivationResult != 0)
|
||||
{
|
||||
crypto_close (cryptoInfo);
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace VeraCrypt
|
||||
RandomNumberGenerator::SetHash (newPkcs5Kdf->GetHash());
|
||||
|
||||
SecureBuffer newSalt (openVolume->GetSaltSize());
|
||||
SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize());
|
||||
SecureBuffer newHeaderKey (VolumeHeader::GetHeaderKeyDerivationSize (newPkcs5Kdf));
|
||||
|
||||
shared_ptr <VolumePassword> password (Keyfile::ApplyListToPassword (newKeyfiles, newPassword, emvSupportEnabled));
|
||||
|
||||
@@ -286,7 +286,7 @@ namespace VeraCrypt
|
||||
RandomNumberGenerator::SetHash (pkcs5Kdf->GetHash());
|
||||
|
||||
SecureBuffer newSalt (header->GetSaltSize());
|
||||
SecureBuffer newHeaderKey (VolumeHeader::GetLargestSerializedKeySize());
|
||||
SecureBuffer newHeaderKey (VolumeHeader::GetHeaderKeyDerivationSize (pkcs5Kdf));
|
||||
|
||||
shared_ptr <VolumePassword> passwordKey (Keyfile::ApplyListToPassword (keyfiles, password, emvSupportEnabled));
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#ifdef TC_LINUX
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
#ifdef TC_OPENBSD
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "Platform/FileStream.h"
|
||||
@@ -40,6 +43,26 @@ namespace VeraCrypt
|
||||
static bool SamePath (const string& path1, const string& path2);
|
||||
#endif
|
||||
|
||||
#ifdef TC_OPENBSD
|
||||
static bool GetDoasUserIds (uid_t *uid, gid_t *gid)
|
||||
{
|
||||
const char *env = getenv ("DOAS_USER");
|
||||
if (!env || !env[0])
|
||||
return false;
|
||||
|
||||
struct passwd *pw = getpwnam (env);
|
||||
if (!pw)
|
||||
return false;
|
||||
|
||||
if (uid)
|
||||
*uid = pw->pw_uid;
|
||||
if (gid)
|
||||
*gid = pw->pw_gid;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Struct to hold terminal emulator information
|
||||
struct TerminalInfo {
|
||||
const char* name;
|
||||
@@ -634,6 +657,12 @@ namespace VeraCrypt
|
||||
catch (...) { }
|
||||
}
|
||||
|
||||
#ifdef TC_OPENBSD
|
||||
gid_t doasGid;
|
||||
if (GetDoasUserIds (nullptr, &doasGid))
|
||||
return doasGid;
|
||||
#endif
|
||||
|
||||
return getgid();
|
||||
}
|
||||
|
||||
@@ -650,6 +679,12 @@ namespace VeraCrypt
|
||||
catch (...) { }
|
||||
}
|
||||
|
||||
#ifdef TC_OPENBSD
|
||||
uid_t doasUid;
|
||||
if (GetDoasUserIds (&doasUid, nullptr))
|
||||
return doasUid;
|
||||
#endif
|
||||
|
||||
return getuid();
|
||||
}
|
||||
|
||||
@@ -1405,8 +1440,8 @@ namespace VeraCrypt
|
||||
while (getline(ss, token, ':'))
|
||||
{
|
||||
// remove any trailing slashes from the token
|
||||
while (!token.empty() && token.back() == '/')
|
||||
token.pop_back();
|
||||
while (!token.empty() && token[token.length() - 1] == '/')
|
||||
token.erase(token.length() - 1);
|
||||
|
||||
if (token.empty())
|
||||
continue;
|
||||
@@ -1424,8 +1459,8 @@ namespace VeraCrypt
|
||||
free(resolvedEntry);
|
||||
|
||||
// remove any trailing slashes from the token
|
||||
while (!entryPath.empty() && entryPath.back() == '/')
|
||||
entryPath.pop_back();
|
||||
while (!entryPath.empty() && entryPath[entryPath.length() - 1] == '/')
|
||||
entryPath.erase(entryPath.length() - 1);
|
||||
|
||||
// perform check again if the resolved path is different from the original (symlink)
|
||||
if (dirPath == entryPath || dirPath.find(entryPath + "/") == 0)
|
||||
|
||||
@@ -253,7 +253,17 @@ namespace VeraCrypt
|
||||
(options->Path.IsDevice() || options->Type == VolumeType::Hidden) ? File::OpenReadWrite : File::CreateReadWrite,
|
||||
File::ShareNone);
|
||||
|
||||
HostSize = VolumeFile->Length();
|
||||
if (!options->Path.IsDevice() && options->Type == VolumeType::Normal)
|
||||
{
|
||||
HostSize = options->Size;
|
||||
|
||||
if (options->Quick)
|
||||
VolumeFile->SetLength (options->Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
HostSize = VolumeFile->Length();
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
@@ -272,6 +282,9 @@ namespace VeraCrypt
|
||||
{
|
||||
throw UnsupportedSectorSize (SRC_POS);
|
||||
}
|
||||
|
||||
if (HostSize % options->SectorSize != 0)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
}
|
||||
else
|
||||
options->SectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME;
|
||||
@@ -315,6 +328,12 @@ namespace VeraCrypt
|
||||
if (headerOptions.VolumeDataSize < 1)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
#ifndef VC_DCS_DISABLE_ARGON2
|
||||
// New volumes are created in XTS mode; Argon2id header key material has a fixed format size.
|
||||
if (options->VolumeHeaderKdf->IsArgon2() && options->EA->GetKeySize() * 2 > ARGON2_HEADER_KEYDATA_SIZE)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
#endif
|
||||
|
||||
// Master data key
|
||||
MasterKey.Allocate (options->EA->GetKeySize() * 2);
|
||||
RandomNumberGenerator::GetData (MasterKey);
|
||||
@@ -331,7 +350,7 @@ namespace VeraCrypt
|
||||
headerOptions.Salt = salt;
|
||||
|
||||
// Header key
|
||||
HeaderKey.Allocate (VolumeHeader::GetLargestSerializedKeySize());
|
||||
HeaderKey.Allocate (VolumeHeader::GetHeaderKeyDerivationSize (options->VolumeHeaderKdf));
|
||||
PasswordKey = Keyfile::ApplyListToPassword (options->Keyfiles, options->Password, options->EMVSupportEnabled);
|
||||
int derivationResult = options->VolumeHeaderKdf->DeriveKey (HeaderKey, *PasswordKey, options->Pim, salt);
|
||||
if (derivationResult != 0)
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#if defined(__AVX2__)
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
#include "blake2/blake2b.h"
|
||||
#include "blake2/blamka-round-opt.h"
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,26,28,0
|
||||
PRODUCTVERSION 1,26,28,0
|
||||
FILEVERSION 1,26,28,1
|
||||
PRODUCTVERSION 1,26,28,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -111,8 +111,8 @@
|
||||
<Inf>
|
||||
<ProviderName>
|
||||
</ProviderName>
|
||||
<TimeStamp>1.26.28.0</TimeStamp>
|
||||
<DateStamp>04/30/2026</DateStamp>
|
||||
<TimeStamp>1.26.28.1</TimeStamp>
|
||||
<DateStamp>05/22/2026</DateStamp>
|
||||
</Inf>
|
||||
<Link>
|
||||
<AdditionalDependencies>fltmgr.lib;%(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfLdr.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfDriverEntry.lib</AdditionalDependencies>
|
||||
@@ -139,8 +139,8 @@ copy $(OutDir)veracrypt.inf "$(SolutionDir)Debug\Setup Files\veracrypt.inf"</Com
|
||||
<Inf>
|
||||
<ProviderName>
|
||||
</ProviderName>
|
||||
<TimeStamp>1.26.28.0</TimeStamp>
|
||||
<DateStamp>04/30/2026</DateStamp>
|
||||
<TimeStamp>1.26.28.1</TimeStamp>
|
||||
<DateStamp>05/22/2026</DateStamp>
|
||||
</Inf>
|
||||
<Link>
|
||||
<AdditionalDependencies>fltmgr.lib;%(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfLdr.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfDriverEntry.lib</AdditionalDependencies>
|
||||
@@ -166,8 +166,8 @@ copy $(OutDir)veracrypt.inf "$(SolutionDir)Release\Setup Files\veracrypt.inf"</C
|
||||
<Inf>
|
||||
<ProviderName>
|
||||
</ProviderName>
|
||||
<TimeStamp>1.26.28.0</TimeStamp>
|
||||
<DateStamp>04/30/2026</DateStamp>
|
||||
<TimeStamp>1.26.28.1</TimeStamp>
|
||||
<DateStamp>05/22/2026</DateStamp>
|
||||
</Inf>
|
||||
<Link>
|
||||
<AdditionalDependencies>fltmgr.lib;%(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfLdr.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfDriverEntry.lib</AdditionalDependencies>
|
||||
@@ -193,15 +193,15 @@ copy $(OutDir)veracrypt.inf "$(SolutionDir)Release\Setup Files\veracrypt.inf"</C
|
||||
<Inf>
|
||||
<ProviderName>
|
||||
</ProviderName>
|
||||
<TimeStamp>1.26.28.0</TimeStamp>
|
||||
<DateStamp>04/30/2026</DateStamp>
|
||||
<TimeStamp>1.26.28.1</TimeStamp>
|
||||
<DateStamp>05/22/2026</DateStamp>
|
||||
</Inf>
|
||||
<Link>
|
||||
<AdditionalDependencies>fltmgr.lib;%(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfLdr.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfDriverEntry.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>copy $(OutDir)veracrypt.sys "$(SolutionDir)Debug\Setup Files\veracrypt-arm64.sys"
|
||||
copy $(OutDir)veracrypt.pdb "$(SolutionDir\Debug\Setup Files\veracrypt-arm64.pdb"
|
||||
copy $(OutDir)veracrypt.pdb "$(SolutionDir)Debug\Setup Files\veracrypt-arm64.pdb"
|
||||
copy $(OutDir)vc143.pdb "$(SolutionDir)Debug\Setup Files\vc143-arm64.pdb"
|
||||
copy $(OutDir)veracrypt.inf "$(SolutionDir)Debug\Setup Files\veracrypt.inf"</Command>
|
||||
</PostBuildEvent>
|
||||
|
||||
@@ -249,7 +249,7 @@ static void OnItemCompleted (EncryptedIoQueueItem *item, BOOL freeItem)
|
||||
DecrementOutstandingIoCount (item->Queue);
|
||||
IoReleaseRemoveLock (&item->Queue->RemoveLock, item->OriginalIrp);
|
||||
|
||||
if (NT_SUCCESS (item->Status))
|
||||
if (NT_SUCCESS (item->Status) && !item->Flush)
|
||||
{
|
||||
if (item->Write)
|
||||
item->Queue->TotalBytesWritten += item->OriginalLength;
|
||||
@@ -630,6 +630,29 @@ static VOID IoThreadProc (PVOID threadArg)
|
||||
InterlockedDecrement (&queue->IoThreadPendingRequestCount);
|
||||
request = CONTAINING_RECORD (listEntry, EncryptedIoRequest, ListEntry);
|
||||
|
||||
if (request->Item->Flush)
|
||||
{
|
||||
#ifdef TC_TRACE_IO_QUEUE
|
||||
Dump ("F [%I64d]\n", GetElapsedTime (&queue->LastPerformanceCounter));
|
||||
#endif
|
||||
if (NT_SUCCESS (request->Item->Status))
|
||||
{
|
||||
if (queue->HostFileHandle)
|
||||
{
|
||||
IO_STATUS_BLOCK ioStatus;
|
||||
request->Item->Status = ZwFlushBuffersFile (queue->HostFileHandle, &ioStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
request->Item->Status = STATUS_DEVICE_NOT_READY;
|
||||
}
|
||||
}
|
||||
|
||||
HandleCompleteOriginalIrp (queue, request);
|
||||
ReleasePoolBuffer (queue, request);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef TC_TRACE_IO_QUEUE
|
||||
Dump ("%c %I64d [%I64d] roff=%I64d rlen=%d\n", request->Item->Write ? 'W' : 'R', request->Item->OriginalIrpOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), request->Offset.QuadPart, request->Length);
|
||||
#endif
|
||||
@@ -832,6 +855,7 @@ static VOID MainThreadProc (PVOID threadArg)
|
||||
item->OriginalIrp = irp;
|
||||
item->TempUserMdl = NULL;
|
||||
item->Status = STATUS_SUCCESS;
|
||||
item->Flush = FALSE;
|
||||
|
||||
IoAcquireCancelSpinLock(&irql);
|
||||
(PDRIVER_CANCEL)IoSetCancelRoutine(irp, NULL);
|
||||
@@ -858,6 +882,13 @@ static VOID MainThreadProc (PVOID threadArg)
|
||||
item->OriginalLength = irpSp->Parameters.Write.Length;
|
||||
break;
|
||||
|
||||
case IRP_MJ_FLUSH_BUFFERS:
|
||||
item->Write = FALSE;
|
||||
item->Flush = TRUE;
|
||||
item->OriginalOffset.QuadPart = 0;
|
||||
item->OriginalLength = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Defer completion for invalid parameter
|
||||
QueueIrpCompletionFromItem(queue, item, STATUS_INVALID_PARAMETER);
|
||||
@@ -868,6 +899,32 @@ static VOID MainThreadProc (PVOID threadArg)
|
||||
item->OriginalIrpOffset = item->OriginalOffset;
|
||||
#endif
|
||||
|
||||
if (item->Flush)
|
||||
{
|
||||
InterlockedIncrement (&queue->IoThreadPendingRequestCount);
|
||||
|
||||
request = GetPoolBuffer (queue, sizeof (EncryptedIoRequest));
|
||||
if (!request)
|
||||
{
|
||||
InterlockedDecrement (&queue->IoThreadPendingRequestCount);
|
||||
QueueIrpCompletionFromItem (queue, item, STATUS_INSUFFICIENT_RESOURCES);
|
||||
continue;
|
||||
}
|
||||
|
||||
request->Item = item;
|
||||
request->CompleteOriginalIrp = TRUE;
|
||||
request->Offset.QuadPart = 0;
|
||||
request->Data = NULL;
|
||||
request->OrigDataBufferFragment = NULL;
|
||||
request->Length = 0;
|
||||
request->EncryptedOffset = 0;
|
||||
request->EncryptedLength = 0;
|
||||
|
||||
ExInterlockedInsertTailList (&queue->IoThreadQueue, &request->ListEntry, &queue->IoThreadQueueLock);
|
||||
KeSetEvent (&queue->IoThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle misaligned read operations to work around a bug in Windows System Assessment Tool which does not follow FILE_FLAG_NO_BUFFERING requirements when benchmarking disk devices
|
||||
if (queue->IsFilterDevice
|
||||
&& !item->Write
|
||||
@@ -1155,7 +1212,11 @@ NTSTATUS EncryptedIoQueueAddIrp (EncryptedIoQueue *queue, PIRP irp)
|
||||
#ifdef TC_TRACE_IO_QUEUE
|
||||
{
|
||||
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp);
|
||||
Dump ("* %I64d [%I64d] %c len=%d out=%d\n", irpSp->MajorFunction == IRP_MJ_WRITE ? irpSp->Parameters.Write.ByteOffset : irpSp->Parameters.Read.ByteOffset, GetElapsedTime (&queue->LastPerformanceCounter), irpSp->MajorFunction == IRP_MJ_WRITE ? 'W' : 'R', irpSp->MajorFunction == IRP_MJ_WRITE ? irpSp->Parameters.Write.Length : irpSp->Parameters.Read.Length, queue->OutstandingIoCount);
|
||||
|
||||
if (irpSp->MajorFunction == IRP_MJ_FLUSH_BUFFERS)
|
||||
Dump ("* F [%I64d] out=%d\n", GetElapsedTime (&queue->LastPerformanceCounter), queue->OutstandingIoCount);
|
||||
else
|
||||
Dump ("* %I64d [%I64d] %c len=%d out=%d\n", irpSp->MajorFunction == IRP_MJ_WRITE ? irpSp->Parameters.Write.ByteOffset : irpSp->Parameters.Read.ByteOffset, GetElapsedTime (&queue->LastPerformanceCounter), irpSp->MajorFunction == IRP_MJ_WRITE ? 'W' : 'R', irpSp->MajorFunction == IRP_MJ_WRITE ? irpSp->Parameters.Write.Length : irpSp->Parameters.Read.Length, queue->OutstandingIoCount);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -155,6 +155,7 @@ typedef struct
|
||||
EncryptedIoQueue *Queue;
|
||||
PIRP OriginalIrp;
|
||||
BOOL Write;
|
||||
BOOL Flush;
|
||||
ULONG OriginalLength;
|
||||
LARGE_INTEGER OriginalOffset;
|
||||
NTSTATUS Status;
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#ifdef TC_OPENBSD
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#include <sys/mman.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h>
|
||||
@@ -65,6 +68,26 @@ namespace VeraCrypt
|
||||
static const uint64 VC_FUSE_METADATA_SIZE = 64 * 1024;
|
||||
static const uint64 VC_FUSE_STAT_BLOCK_SIZE = 512;
|
||||
|
||||
#ifdef TC_OPENBSD
|
||||
static bool fuse_service_get_doas_user_ids (uid_t *uid, gid_t *gid)
|
||||
{
|
||||
const char *env = getenv ("DOAS_USER");
|
||||
if (!env || !env[0])
|
||||
return false;
|
||||
|
||||
struct passwd *pw = getpwnam (env);
|
||||
if (!pw)
|
||||
return false;
|
||||
|
||||
if (uid)
|
||||
*uid = pw->pw_uid;
|
||||
if (gid)
|
||||
*gid = pw->pw_gid;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint64 fuse_service_ceil_div (uint64 value, uint64 divisor)
|
||||
{
|
||||
return (value / divisor) + ((value % divisor) ? 1 : 0);
|
||||
@@ -790,6 +813,18 @@ namespace VeraCrypt
|
||||
}
|
||||
catch (...) { }
|
||||
}
|
||||
#ifdef TC_OPENBSD
|
||||
else
|
||||
{
|
||||
uid_t doasUid;
|
||||
gid_t doasGid;
|
||||
if (fuse_service_get_doas_user_ids (&doasUid, &doasGid))
|
||||
{
|
||||
FuseService::UserId = doasUid;
|
||||
FuseService::GroupId = doasGid;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static fuse_operations fuse_service_oper;
|
||||
|
||||
|
||||
+12
-1
@@ -621,7 +621,18 @@ NTSTATUS TCDispatchQueueIRP (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
return STATUS_PENDING;
|
||||
|
||||
case IRP_MJ_FLUSH_BUFFERS:
|
||||
return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0);
|
||||
if (Extension->hDeviceFile == NULL || Extension->bReadOnly)
|
||||
return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0);
|
||||
|
||||
if (!EncryptedIoQueueIsRunning (&Extension->Queue))
|
||||
return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0);
|
||||
|
||||
ntStatus = EncryptedIoQueueAddIrp (&Extension->Queue, Irp);
|
||||
|
||||
if (ntStatus != STATUS_PENDING)
|
||||
TCCompleteDiskIrp (Irp, ntStatus, 0);
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -909,6 +909,13 @@ void TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
|
||||
{
|
||||
RestoreTimeStamp (Extension);
|
||||
}
|
||||
if (!Extension->bReadOnly)
|
||||
{
|
||||
IO_STATUS_BLOCK ioStatus;
|
||||
NTSTATUS flushStatus = ZwFlushBuffersFile (Extension->hDeviceFile, &ioStatus);
|
||||
if (!NT_SUCCESS (flushStatus))
|
||||
Dump ("ZwFlushBuffersFile failed before closing volume: NTSTATUS 0x%08x\n", flushStatus);
|
||||
}
|
||||
ZwClose (Extension->hDeviceFile);
|
||||
Extension->hDeviceFile = NULL;
|
||||
}
|
||||
|
||||
@@ -192,8 +192,8 @@ IDR_MOUNT_RSRC_HEADER HEADER "resource.h"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,26,28,0
|
||||
PRODUCTVERSION 1,26,28,0
|
||||
FILEVERSION 1,26,28,1
|
||||
PRODUCTVERSION 1,26,28,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,26,28,0
|
||||
PRODUCTVERSION 1,26,28,0
|
||||
FILEVERSION 1,26,28,1
|
||||
PRODUCTVERSION 1,26,28,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,26,28,0
|
||||
PRODUCTVERSION 1,26,28,0
|
||||
FILEVERSION 1,26,28,1
|
||||
PRODUCTVERSION 1,26,28,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -48,6 +48,11 @@ namespace VeraCrypt
|
||||
MainFrame::MainFrame (wxWindow* parent) : MainFrameBase (parent),
|
||||
#ifdef HAVE_INDICATORS
|
||||
indicator (NULL),
|
||||
indicator_item_showhide (NULL),
|
||||
indicator_item_mountfavorites (NULL),
|
||||
indicator_item_dismountall (NULL),
|
||||
indicator_item_prefs (NULL),
|
||||
indicator_item_exit (NULL),
|
||||
#endif
|
||||
ListItemRightClickEventPending (false),
|
||||
SelectedItemIndex (-1),
|
||||
@@ -1445,7 +1450,7 @@ namespace VeraCrypt
|
||||
try
|
||||
{
|
||||
uint8 buf[128];
|
||||
if (read (ShowRequestFifo, buf, sizeof (buf)) > 0 && Gui->IsInBackgroundMode())
|
||||
if (read (ShowRequestFifo, buf, sizeof (buf)) > 0)
|
||||
Gui->SetBackgroundMode (false);
|
||||
}
|
||||
catch (...)
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
#include "Main/Main.h"
|
||||
#include "Main/Application.h"
|
||||
#include "Main/GraphicUserInterface.h"
|
||||
#ifdef TC_LINUX
|
||||
#include "Platform/Unix/Process.h"
|
||||
#endif
|
||||
#include "Volume/Cipher.h"
|
||||
#include "PreferencesDialog.h"
|
||||
|
||||
@@ -132,7 +135,16 @@ namespace VeraCrypt
|
||||
#if defined (TC_MACOSX)
|
||||
wxDir languagesFolder(StringConverter::ToSingle (Application::GetExecutableDirectory()) + "/../Resources/languages/");
|
||||
#else
|
||||
wxDir languagesFolder("/usr/share/veracrypt/languages/");
|
||||
wxString languagesFolderPath("/usr/share/veracrypt/languages/");
|
||||
#ifdef TC_LINUX
|
||||
if (Process::IsRunningUnderAppImage (StringConverter::ToSingle (wstring (Application::GetExecutablePath()))))
|
||||
{
|
||||
const char* appDirEnv = getenv ("APPDIR");
|
||||
if (appDirEnv)
|
||||
languagesFolderPath = wxString::FromUTF8 (appDirEnv) + "/usr/share/veracrypt/languages/";
|
||||
}
|
||||
#endif
|
||||
wxDir languagesFolder(languagesFolderPath);
|
||||
#endif
|
||||
wxArrayString langArray;
|
||||
LanguageListBox->Append("System default");
|
||||
|
||||
@@ -391,6 +391,7 @@ namespace VeraCrypt
|
||||
DisplayKeyInfo (false),
|
||||
LargeFilesSupport (false),
|
||||
QuickFormatEnabled (false),
|
||||
QuickFormatEnabledByWizard (false),
|
||||
SelectedFilesystemClusterSize (0),
|
||||
SelectedFilesystemType (VolumeCreationOptions::FilesystemType::FAT),
|
||||
SelectedVolumeHostType (VolumeHostType::File),
|
||||
@@ -446,6 +447,7 @@ namespace VeraCrypt
|
||||
OuterVolume = false;
|
||||
LargeFilesSupport = false;
|
||||
QuickFormatEnabled = false;
|
||||
QuickFormatEnabledByWizard = false;
|
||||
Pim = 0;
|
||||
|
||||
SingleChoiceWizardPage <VolumeHostType::Enum> *page = new SingleChoiceWizardPage <VolumeHostType::Enum> (GetPageParent(), wxEmptyString, true);
|
||||
@@ -595,15 +597,29 @@ namespace VeraCrypt
|
||||
{
|
||||
shared_ptr <VolumeLayout> layout ((OuterVolume || SelectedVolumeType != VolumeType::Hidden)? (VolumeLayout*) new VolumeLayoutV2Normal() : (VolumeLayout*) new VolumeLayoutV2Hidden());
|
||||
uint64 filesystemSize = layout->GetMaxDataSize (VolumeSize);
|
||||
bool hiddenVolumeItself = !OuterVolume && SelectedVolumeType == VolumeType::Hidden;
|
||||
bool normalFileContainer = !OuterVolume && SelectedVolumeType == VolumeType::Normal && SelectedVolumeHostType == VolumeHostType::File;
|
||||
bool existingDeviceSupportedCase = SelectedVolumePath.IsDevice() && !hiddenVolumeItself;
|
||||
bool quickFormatSupported = existingDeviceSupportedCase || normalFileContainer;
|
||||
|
||||
VolumeFormatOptionsWizardPage *page = new VolumeFormatOptionsWizardPage (GetPageParent(), filesystemSize, SectorSize,
|
||||
SelectedVolumePath.IsDevice() && (OuterVolume || SelectedVolumeType != VolumeType::Hidden), OuterVolume, LargeFilesSupport);
|
||||
quickFormatSupported, OuterVolume, LargeFilesSupport);
|
||||
|
||||
page->SetPageTitle (LangString["FORMAT_TITLE"]);
|
||||
page->SetFilesystemType (SelectedFilesystemType);
|
||||
|
||||
if (!OuterVolume && SelectedVolumeType == VolumeType::Hidden)
|
||||
if (hiddenVolumeItself)
|
||||
{
|
||||
QuickFormatEnabled = true;
|
||||
QuickFormatEnabledByWizard = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!quickFormatSupported || QuickFormatEnabledByWizard)
|
||||
QuickFormatEnabled = false;
|
||||
|
||||
QuickFormatEnabledByWizard = false;
|
||||
}
|
||||
page->SetQuickFormat (QuickFormatEnabled);
|
||||
|
||||
return page;
|
||||
@@ -1332,6 +1348,7 @@ namespace VeraCrypt
|
||||
|
||||
SelectedFilesystemType = page->GetFilesystemType();
|
||||
QuickFormatEnabled = page->IsQuickFormatEnabled();
|
||||
QuickFormatEnabledByWizard = !OuterVolume && SelectedVolumeType == VolumeType::Hidden;
|
||||
|
||||
if (SelectedFilesystemType != VolumeCreationOptions::FilesystemType::None
|
||||
&& SelectedFilesystemType != VolumeCreationOptions::FilesystemType::FAT)
|
||||
|
||||
@@ -76,6 +76,7 @@ namespace VeraCrypt
|
||||
shared_ptr <VolumeInfo> MountedOuterVolume;
|
||||
bool OuterVolume;
|
||||
bool QuickFormatEnabled;
|
||||
bool QuickFormatEnabledByWizard;
|
||||
shared_ptr <EncryptionAlgorithm> SelectedEncryptionAlgorithm;
|
||||
uint32 SelectedFilesystemClusterSize;
|
||||
VolumeCreationOptions::FilesystemType::Enum SelectedFilesystemType;
|
||||
|
||||
@@ -1037,7 +1037,6 @@ namespace VeraCrypt
|
||||
if (write (showFifo, buf, 1) == 1)
|
||||
{
|
||||
close (showFifo);
|
||||
Gui->ShowInfo (LangString["LINUX_VC_RUNNING_ALREADY"]);
|
||||
Application::SetExitCode (0);
|
||||
return false;
|
||||
}
|
||||
@@ -1872,7 +1871,9 @@ namespace VeraCrypt
|
||||
BackgroundMode = state;
|
||||
|
||||
#ifdef HAVE_INDICATORS
|
||||
gtk_menu_item_set_label ((GtkMenuItem*) ((MainFrame*) mMainFrame)->indicator_item_showhide, LangString[Gui->IsInBackgroundMode() ? "SHOW_TC" : "HIDE_TC"].mb_str());
|
||||
MainFrame *mainFrame = (MainFrame*) mMainFrame;
|
||||
if (mainFrame->indicator_item_showhide)
|
||||
gtk_menu_item_set_label ((GtkMenuItem*) mainFrame->indicator_item_showhide, LangString[Gui->IsInBackgroundMode() ? "SHOW_TC" : "HIDE_TC"].mb_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+29
-2
@@ -106,7 +106,8 @@ FUSE_LIBS = $(shell $(PKG_CONFIG) $(VC_FUSE_PACKAGE) --libs)
|
||||
|
||||
#------ Executable ------
|
||||
|
||||
export TC_VERSION := $(shell awk -F '"' '/^[[:space:]]*\#define[[:space:]]+VERSION_STRING[[:space:]]*"/ { print $$2; exit }' ../Common/Tcdefs.h)
|
||||
HASH_CHAR := \#
|
||||
export TC_VERSION := $(shell awk -F '"' '/^[[:space:]]*$(HASH_CHAR)define[[:space:]]+VERSION_STRING[[:space:]]*"/ { print $$2; exit }' ../Common/Tcdefs.h)
|
||||
|
||||
#------ Linux package naming ------
|
||||
ifeq "$(PLATFORM)" "Linux"
|
||||
@@ -327,6 +328,7 @@ INSTALL_DESKTOP ?= 1
|
||||
INSTALL_MIME ?= 1
|
||||
INSTALL_ICONS ?= 1
|
||||
INSTALL_APPIMAGE_FILES ?= 1
|
||||
APPIMAGE_BUNDLE_FUSE2 ?= 1
|
||||
|
||||
# These override values are appended below usr and used in shell recipes.
|
||||
# Keep command-line/environment overrides literal and path-like.
|
||||
@@ -425,6 +427,27 @@ endif
|
||||
ifneq "$(INSTALL_APPIMAGE_FILES)" "0"
|
||||
rm -fr $(BASE_DIR)/Setup/Linux/veracrypt.AppDir/usr
|
||||
cp -r $(BASE_DIR)/Setup/Linux/usr $(BASE_DIR)/Setup/Linux/veracrypt.AppDir/.
|
||||
ifneq "$(APPIMAGE_BUNDLE_FUSE2)" "0"
|
||||
@set -e; \
|
||||
_appdir="$(BASE_DIR)/Setup/Linux/veracrypt.AppDir"; \
|
||||
_fuse_lib="$$( (ldconfig -p 2>/dev/null || /sbin/ldconfig -p 2>/dev/null || true) | awk '/libfuse\.so\.2[[:space:]]/ { print $$NF; exit }')"; \
|
||||
if [ -z "$$_fuse_lib" ]; then \
|
||||
for _candidate in /lib64/libfuse.so.2 /usr/lib64/libfuse.so.2 /lib/libfuse.so.2 /usr/lib/libfuse.so.2 /lib/*/libfuse.so.2 /usr/lib/*/libfuse.so.2; do \
|
||||
if [ -e "$$_candidate" ]; then _fuse_lib="$$_candidate"; break; fi; \
|
||||
done; \
|
||||
fi; \
|
||||
if [ -n "$$_fuse_lib" ]; then \
|
||||
echo "Bundling AppImage FUSE2 userspace library: $$_fuse_lib"; \
|
||||
mkdir -p "$$_appdir/usr/lib"; \
|
||||
cp -P "$$_fuse_lib" "$$_appdir/usr/lib/"; \
|
||||
_fuse_real="$$(readlink -f "$$_fuse_lib" 2>/dev/null || true)"; \
|
||||
if [ -n "$$_fuse_real" ] && [ "$$_fuse_real" != "$$_fuse_lib" ]; then \
|
||||
cp "$$_fuse_real" "$$_appdir/usr/lib/"; \
|
||||
fi; \
|
||||
else \
|
||||
echo "Warning: libfuse.so.2 not found; AppImage will rely on a host FUSE2 userspace library"; \
|
||||
fi
|
||||
endif
|
||||
ifneq "$(INSTALL_ICONS)" "0"
|
||||
ln -sf usr/share/icons/hicolor/1024x1024/apps/$(APPNAME).png $(BASE_DIR)/Setup/Linux/veracrypt.AppDir/$(APPNAME).png
|
||||
endif
|
||||
@@ -549,7 +572,11 @@ appimage: prepare
|
||||
_appimagetool_executable_name="appimagetool-$${_appimagetool_arch_suffix}.AppImage"; \
|
||||
_appimagetool_executable_path="$(BASE_DIR)/Setup/Linux/$${_appimagetool_executable_name}"; \
|
||||
_appimagetool_url="https://github.com/AppImage/appimagetool/releases/download/continuous/$${_appimagetool_executable_name}"; \
|
||||
_final_appimage_filename="VeraCrypt-$(TC_VERSION)-$${_final_appimage_arch_suffix}.AppImage"; \
|
||||
_final_appimage_gtk_suffix=""; \
|
||||
if [ "$(GTK_VERSION)" = "2" ]; then \
|
||||
_final_appimage_gtk_suffix="-gtk2-legacy"; \
|
||||
fi; \
|
||||
_final_appimage_filename="VeraCrypt-$(TC_VERSION)$${_final_appimage_gtk_suffix}-$${_final_appimage_arch_suffix}.AppImage"; \
|
||||
_final_appimage_path="$(BASE_DIR)/Setup/Linux/$${_final_appimage_filename}"; \
|
||||
\
|
||||
echo "Preparing AppImage for $(CPU_ARCH) (using $${_appimagetool_arch_suffix})..."; \
|
||||
|
||||
+11
-2
@@ -17,13 +17,14 @@
|
||||
#ifdef TC_WINDOWS
|
||||
#include "Main/resource.h"
|
||||
#else
|
||||
#ifdef TC_MACOSX
|
||||
#include "Application.h"
|
||||
#endif
|
||||
#include "Platform/File.h"
|
||||
#include "Platform/StringConverter.h"
|
||||
#include <stdio.h>
|
||||
#include "UserPreferences.h"
|
||||
#if defined(TC_LINUX)
|
||||
#include "Platform/Unix/Process.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace VeraCrypt
|
||||
@@ -66,6 +67,14 @@ namespace VeraCrypt
|
||||
string filenamePrefix = StringConverter::ToSingle (Application::GetExecutableDirectory()) + "/../Resources/languages/Language.";
|
||||
#else
|
||||
string filenamePrefix("/usr/share/veracrypt/languages/Language.");
|
||||
#if defined(TC_LINUX)
|
||||
if (Process::IsRunningUnderAppImage (StringConverter::ToSingle (wstring (Application::GetExecutablePath()))))
|
||||
{
|
||||
const char* appDirEnv = getenv ("APPDIR");
|
||||
if (appDirEnv)
|
||||
filenamePrefix = string (appDirEnv) + "/usr/share/veracrypt/languages/Language.";
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
string filenamePost(".xml");
|
||||
string filename = filenamePrefix + defaultLang + filenamePost;
|
||||
|
||||
@@ -766,8 +766,6 @@ namespace VeraCrypt
|
||||
}
|
||||
}
|
||||
|
||||
options->Quick = false;
|
||||
|
||||
uint32 sectorSizeRem = options->Size % options->SectorSize;
|
||||
if (sectorSizeRem != 0)
|
||||
options->Size += options->SectorSize - sectorSizeRem;
|
||||
@@ -964,6 +962,18 @@ namespace VeraCrypt
|
||||
throw_err (_("Specified volume size is too small to be used with Btrfs filesystem."));
|
||||
}
|
||||
|
||||
if (options->Quick && options->Type == VolumeType::Normal)
|
||||
{
|
||||
if (Preferences.NonInteractive)
|
||||
{
|
||||
ShowWarning (_("Quick Format is enabled. Do not use --quick for an outer volume intended to contain a hidden volume. It skips writing random data to unused volume space, reducing plausible deniability. For file containers, actual disk savings depend on host filesystem sparse-file support, and later writes can fail if host space runs out."));
|
||||
}
|
||||
else if (!AskYesNo (LangString["WARN_QUICK_FORMAT"], false, true))
|
||||
{
|
||||
throw UserAbort (SRC_POS);
|
||||
}
|
||||
}
|
||||
|
||||
// Password
|
||||
if (!options->Password && !Preferences.NonInteractive)
|
||||
{
|
||||
|
||||
@@ -1219,7 +1219,7 @@ const FileManager fileManagers[] = {
|
||||
" Inexperienced users should use the graphical user interface to create a hidden\n"
|
||||
" volume. When using the text user interface, the following procedure must be\n"
|
||||
" followed to create a hidden volume:\n"
|
||||
" 1) Create an outer volume with no filesystem.\n"
|
||||
" 1) Create an outer volume with no filesystem and without --quick.\n"
|
||||
" 2) Create a hidden volume within the outer volume.\n"
|
||||
" 3) Mount the outer volume using hidden volume protection.\n"
|
||||
" 4) Create a filesystem on the virtual device of the outer volume.\n"
|
||||
@@ -1428,8 +1428,12 @@ const FileManager fileManagers[] = {
|
||||
" See also options -p and --protect-hidden.\n"
|
||||
"\n"
|
||||
"--quick\n"
|
||||
" Do not encrypt free space when creating a device-hosted volume. This option\n"
|
||||
" must not be used when creating an outer volume.\n"
|
||||
" Do not encrypt free space when creating a normal file-hosted or\n"
|
||||
" device-hosted volume. This option must not be used when creating an outer\n"
|
||||
" volume; text mode cannot infer that a normal volume will later be\n"
|
||||
" used as an outer volume. For file containers, Quick Format may create sparse\n"
|
||||
" or unwritten host regions; actual disk savings depend on host filesystem\n"
|
||||
" sparse-file support, and later writes can fail if host space runs out.\n"
|
||||
"\n"
|
||||
"--random-source=FILE\n"
|
||||
" Use FILE as a source of random data (e.g., when creating a volume) instead\n"
|
||||
|
||||
+3
-1
@@ -19,6 +19,8 @@
|
||||
# NOTEST: Do not test release binary
|
||||
# RESOURCEDIR: Run-time resource directory
|
||||
# VERBOSE: Enable verbose messages
|
||||
# WITHFUSE3: Build with FUSE3 support instead of FUSE2
|
||||
# WX_CONFIGURE_EXTRA_FLAGS: Extra flags passed to wxWidgets configure
|
||||
# WXSTATIC: Use static wxWidgets library
|
||||
# SSSE3: Enable SSSE3 support in compiler
|
||||
# SSE41: Enable SSE4.1 support in compiler
|
||||
@@ -736,7 +738,7 @@ endif
|
||||
WX_CONFIGURE_LEGACY_FLAGS="$$WX_CONFIGURE_LEGACY_FLAGS --enable-$$option"; \
|
||||
fi; \
|
||||
done; \
|
||||
"$(WX_ROOT)/configure" $(WX_CONFIGURE_FLAGS) $$WX_CONFIGURE_LEGACY_FLAGS >/dev/null
|
||||
"$(WX_ROOT)/configure" $(WX_CONFIGURE_FLAGS) $(WX_CONFIGURE_EXTRA_FLAGS) $$WX_CONFIGURE_LEGACY_FLAGS >/dev/null
|
||||
|
||||
@echo Building wxWidgets library...
|
||||
cd "$(WX_BUILD_DIR)" && $(MAKE) -j 4
|
||||
|
||||
+2
-2
@@ -587,8 +587,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,26,28,0
|
||||
PRODUCTVERSION 1,26,28,0
|
||||
FILEVERSION 1,26,28,1
|
||||
PRODUCTVERSION 1,26,28,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -87,6 +87,7 @@ namespace VeraCrypt
|
||||
uint64 ReadAt (const BufferPtr &buffer, uint64 position) const;
|
||||
void SeekAt (uint64 position) const;
|
||||
void SeekEnd (int ofset) const;
|
||||
void SetLength (uint64 length) const;
|
||||
void Write (const ConstBufferPtr &buffer) const;
|
||||
void Write (const ConstBufferPtr &buffer, size_t length) const { Write (buffer.GetRange (0, length)); }
|
||||
void WriteAt (const ConstBufferPtr &buffer, uint64 position) const;
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace VeraCrypt
|
||||
SyncEvent ();
|
||||
~SyncEvent ();
|
||||
|
||||
void Reset ();
|
||||
void Signal ();
|
||||
void Wait ();
|
||||
|
||||
|
||||
@@ -125,7 +125,11 @@ namespace VeraCrypt
|
||||
|
||||
#elif defined (TC_OPENBSD)
|
||||
struct disklabel dl;
|
||||
throw_sys_sub_if (ioctl (FileHandle, DIOCGPDINFO, &dl) == -1, wstring (Path));
|
||||
throw_sys_sub_if (ioctl (FileHandle, DIOCGDINFO, &dl) == -1, wstring (Path));
|
||||
|
||||
if (dl.d_secsize == 0)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
return (uint32) dl.d_secsize;
|
||||
|
||||
#elif defined (TC_SOLARIS)
|
||||
@@ -213,8 +217,31 @@ namespace VeraCrypt
|
||||
return blockCount * blockSize;
|
||||
# elif TC_OPENBSD
|
||||
struct disklabel dl;
|
||||
throw_sys_sub_if (ioctl (FileHandle, DIOCGPDINFO, &dl) == -1, wstring (Path));
|
||||
return DL_GETDSIZE(&dl);
|
||||
struct stat statData;
|
||||
throw_sys_sub_if (ioctl (FileHandle, DIOCGDINFO, &dl) == -1, wstring (Path));
|
||||
throw_sys_sub_if (fstat (FileHandle, &statData) == -1, wstring (Path));
|
||||
|
||||
if (dl.d_secsize == 0)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
uint64 sectors;
|
||||
int partition = DISKPART (statData.st_rdev);
|
||||
if (partition == RAW_PART)
|
||||
{
|
||||
sectors = DL_GETDSIZE (&dl);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (partition < 0 || partition >= dl.d_npartitions)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
sectors = DL_GETPSIZE (&dl.d_partitions[partition]);
|
||||
}
|
||||
|
||||
if (sectors > ((uint64) -1) / dl.d_secsize)
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
|
||||
return sectors * dl.d_secsize;
|
||||
# else
|
||||
uint64 mediaSize;
|
||||
throw_sys_sub_if (ioctl (FileHandle, DIOCGMEDIASIZE, &mediaSize) == -1, wstring (Path));
|
||||
@@ -385,6 +412,12 @@ namespace VeraCrypt
|
||||
throw_sys_sub_if (lseek (FileHandle, offset, SEEK_END) == -1, wstring (Path));
|
||||
}
|
||||
|
||||
void File::SetLength (uint64 length) const
|
||||
{
|
||||
if_debug (ValidateState());
|
||||
throw_sys_sub_if (ftruncate (FileHandle, length) == -1, wstring (Path));
|
||||
}
|
||||
|
||||
void File::Write (const ConstBufferPtr &buffer) const
|
||||
{
|
||||
if_debug (ValidateState());
|
||||
|
||||
@@ -41,6 +41,14 @@ namespace VeraCrypt
|
||||
Initialized = false;
|
||||
}
|
||||
|
||||
void SyncEvent::Reset ()
|
||||
{
|
||||
assert (Initialized);
|
||||
|
||||
ScopeLock lock (EventMutex);
|
||||
Signaled = false;
|
||||
}
|
||||
|
||||
void SyncEvent::Signal ()
|
||||
{
|
||||
assert (Initialized);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
for upgrades to work ; Windows Installer ignores the 4th part -->
|
||||
<?define var.FullProductVersion = 1.26.28?>
|
||||
<?define var.ProductName = VeraCrypt $(var.FullProductVersion)?>
|
||||
<?define var.StartMenuFolderName = VeraCrypt?>
|
||||
|
||||
<!-- Unique GUID identifying this family of product (32-bit and 64-bit have the same) -->
|
||||
<?define var.UpgradeCode = {298F5D2B-3B01-4A13-BEFD-4B3C7BE43BC6}?>
|
||||
@@ -186,7 +187,7 @@
|
||||
<!-- Reference APPLICATIONPROGRAMSFOLDER to create a Start Menu Shortcut -->
|
||||
<!-- See https://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/create_start_menu_shortcut.html -->
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" Name="$(var.ProductName)"/>
|
||||
<Directory Id="ApplicationProgramsFolder" Name="$(var.StartMenuFolderName)"/>
|
||||
</Directory>
|
||||
|
||||
<!-- We do not Reference QuickLaunchFolder under AppDataFolder to create a Quick Launch Shortcut -->
|
||||
@@ -2440,7 +2441,7 @@
|
||||
<DirectoryRef Id="ApplicationProgramsFolder">
|
||||
|
||||
<!-- Creating an advertised shortcut : enhances resiliency by verifying that all the components in the feature are installed when the shortcut is activated -->
|
||||
<Component Id="VCShortcutStartMenu" Guid="{9CA5F425-0268-4424-8E41-A94D90F1118D}">
|
||||
<Component Id="VCShortcutStartMenu" Guid="{684DA19F-50FC-43AA-89BA-1685DAC0D585}">
|
||||
|
||||
<Condition>INSTALLSTARTMENUSHORTCUT</Condition>
|
||||
<Shortcut Id="VCMenuShortcut"
|
||||
@@ -2456,7 +2457,7 @@
|
||||
<RegistryValue
|
||||
Root="HKCU"
|
||||
Key="Software\VeraCrypt_MSI"
|
||||
Name="VCStartMenuShortcutInstalled"
|
||||
Name="VCStartMenuShortcutInstalledStable"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes"/>
|
||||
@@ -2464,7 +2465,7 @@
|
||||
</Component>
|
||||
|
||||
<!-- Creating an advertised shortcut : enhances resiliency by verifying that all the components in the feature are installed when the shortcut is activated -->
|
||||
<Component Id="VCExpanderShortcutStartMenu" Guid="9BA70A97-CB6D-4ED4-A0F7-A4CF9885DC33">
|
||||
<Component Id="VCExpanderShortcutStartMenu" Guid="{E0C191AE-86EB-462A-9C8A-73338EC7A153}">
|
||||
|
||||
<Condition>INSTALLSTARTMENUSHORTCUT</Condition>
|
||||
<Shortcut Id="VCExpanderStartMenuShortcut"
|
||||
@@ -2480,7 +2481,7 @@
|
||||
<RegistryValue
|
||||
Root="HKCU"
|
||||
Key="Software\VeraCrypt_MSI"
|
||||
Name="VCEexpanderStartMenuShortcutInstalled"
|
||||
Name="VCExpanderStartMenuShortcutInstalledStable"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes"/>
|
||||
@@ -2488,7 +2489,7 @@
|
||||
</Component>
|
||||
|
||||
<!-- Creating an advertised shortcut : enhances resiliency by verifying that all the components in the feature are installed when the shortcut is activated -->
|
||||
<Component Id="VCWebsiteShortcutStartMenu" Guid="{D5AA7FFE-5256-4234-AEE1-F9F1EB6ECA4A}">
|
||||
<Component Id="VCWebsiteShortcutStartMenu" Guid="{00CA573B-4B04-4397-8061-CF5B5515DDBD}">
|
||||
|
||||
<Condition>INSTALLSTARTMENUSHORTCUT</Condition>
|
||||
<util:InternetShortcut Id="VCWebsiteStartMenuShortcut"
|
||||
@@ -2503,7 +2504,7 @@
|
||||
<RegistryValue
|
||||
Root="HKCU"
|
||||
Key="Software\VeraCrypt_MSI"
|
||||
Name="VCWebsiteStartMenuShortcutInstalled"
|
||||
Name="VCWebsiteStartMenuShortcutInstalledStable"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes"/>
|
||||
@@ -3444,6 +3445,12 @@
|
||||
<CustomAction Id="PostInst_SetData"
|
||||
Property="DoPostInstall"
|
||||
Value="INSTALLDIR=[APPLICATIONROOTFOLDER]" />
|
||||
|
||||
<!-- Create a Custom Action which sets the CustomActionData property
|
||||
for CleanupOldStartMenuFolders Deferred Custom Action. -->
|
||||
<CustomAction Id="CleanupOldStartMenuFolders_SetData"
|
||||
Property="CleanupOldStartMenuFolders"
|
||||
Value="PROGRAMMENUFOLDER=[ProgramMenuFolder]" />
|
||||
|
||||
<!-- Create a Custom Action which sets the CustomActionData property
|
||||
for DoPostUninstall Deferred Custom Action.
|
||||
@@ -3474,6 +3481,14 @@
|
||||
Return="check"
|
||||
BinaryKey="VeraCryptCustomActions"
|
||||
DllEntry="VC_CustomAction_PostInstall" />
|
||||
|
||||
<!-- Best-effort cleanup of obsolete versioned Start Menu folders from previous MSI releases. -->
|
||||
<CustomAction Id="CleanupOldStartMenuFolders"
|
||||
Execute="deferred"
|
||||
Impersonate="no"
|
||||
Return="ignore"
|
||||
BinaryKey="VeraCryptCustomActions"
|
||||
DllEntry="VC_CustomAction_CleanupOldStartMenuFolders" />
|
||||
|
||||
<!-- Create our Pre-Uninstall Custom Action.
|
||||
We need to run it as deferred so that it runs
|
||||
@@ -3602,6 +3617,10 @@
|
||||
it will execute it twice : once when it installs new files (NOT Installed), and then when it removes unnecessary files (actual upgrade: UPGRADINGPRODUCTCODE).
|
||||
Therefore, we do not need to execute it at UPGRADINGPRODUCTCODE. -->
|
||||
<Custom Action="DoPostInstall" After="InstallFiles">(NOT Installed AND NOT REMOVE) OR REINSTALL</Custom>
|
||||
|
||||
<!-- Cleanup obsolete versioned Start Menu folders as late as possible in the install transaction. -->
|
||||
<Custom Action="CleanupOldStartMenuFolders_SetData" Before="CleanupOldStartMenuFolders">(NOT Installed AND NOT REMOVE) OR REINSTALL</Custom>
|
||||
<Custom Action="CleanupOldStartMenuFolders" After="PublishProduct">(NOT Installed AND NOT REMOVE) OR REINSTALL</Custom>
|
||||
|
||||
<!-- UNINSTALLATION ONLY CAs -->
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
for upgrades to work ; Windows Installer ignores the 4th part -->
|
||||
<?define var.FullProductVersion = 1.26.28?>
|
||||
<?define var.ProductName = VeraCrypt $(var.FullProductVersion)?>
|
||||
<?define var.StartMenuFolderName = VeraCrypt?>
|
||||
|
||||
<!-- Unique GUID identifying this family of product (32-bit and 64-bit have the same) -->
|
||||
<?define var.UpgradeCode = {813AB9FC-2117-4961-B459-EB65028EEC93}?>
|
||||
@@ -186,7 +187,7 @@
|
||||
<!-- Reference APPLICATIONPROGRAMSFOLDER to create a Start Menu Shortcut -->
|
||||
<!-- See https://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/create_start_menu_shortcut.html -->
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" Name="$(var.ProductName)"/>
|
||||
<Directory Id="ApplicationProgramsFolder" Name="$(var.StartMenuFolderName)"/>
|
||||
</Directory>
|
||||
|
||||
<!-- We do not Reference QuickLaunchFolder under AppDataFolder to create a Quick Launch Shortcut -->
|
||||
@@ -2440,7 +2441,7 @@
|
||||
<DirectoryRef Id="ApplicationProgramsFolder">
|
||||
|
||||
<!-- Creating an advertised shortcut : enhances resiliency by verifying that all the components in the feature are installed when the shortcut is activated -->
|
||||
<Component Id="VCShortcutStartMenu" Guid="{9CA5F425-0268-4424-8E41-A94D90F1118D}">
|
||||
<Component Id="VCShortcutStartMenu" Guid="{684DA19F-50FC-43AA-89BA-1685DAC0D585}">
|
||||
|
||||
<Condition>INSTALLSTARTMENUSHORTCUT</Condition>
|
||||
<Shortcut Id="VCMenuShortcut"
|
||||
@@ -2456,7 +2457,7 @@
|
||||
<RegistryValue
|
||||
Root="HKCU"
|
||||
Key="Software\VeraCrypt_MSI"
|
||||
Name="VCStartMenuShortcutInstalled"
|
||||
Name="VCStartMenuShortcutInstalledStable"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes"/>
|
||||
@@ -2464,7 +2465,7 @@
|
||||
</Component>
|
||||
|
||||
<!-- Creating an advertised shortcut : enhances resiliency by verifying that all the components in the feature are installed when the shortcut is activated -->
|
||||
<Component Id="VCExpanderShortcutStartMenu" Guid="9BA70A97-CB6D-4ED4-A0F7-A4CF9885DC33">
|
||||
<Component Id="VCExpanderShortcutStartMenu" Guid="{E0C191AE-86EB-462A-9C8A-73338EC7A153}">
|
||||
|
||||
<Condition>INSTALLSTARTMENUSHORTCUT</Condition>
|
||||
<Shortcut Id="VCExpanderStartMenuShortcut"
|
||||
@@ -2480,7 +2481,7 @@
|
||||
<RegistryValue
|
||||
Root="HKCU"
|
||||
Key="Software\VeraCrypt_MSI"
|
||||
Name="VCEexpanderStartMenuShortcutInstalled"
|
||||
Name="VCExpanderStartMenuShortcutInstalledStable"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes"/>
|
||||
@@ -2488,7 +2489,7 @@
|
||||
</Component>
|
||||
|
||||
<!-- Creating an advertised shortcut : enhances resiliency by verifying that all the components in the feature are installed when the shortcut is activated -->
|
||||
<Component Id="VCWebsiteShortcutStartMenu" Guid="{D5AA7FFE-5256-4234-AEE1-F9F1EB6ECA4A}">
|
||||
<Component Id="VCWebsiteShortcutStartMenu" Guid="{00CA573B-4B04-4397-8061-CF5B5515DDBD}">
|
||||
|
||||
<Condition>INSTALLSTARTMENUSHORTCUT</Condition>
|
||||
<util:InternetShortcut Id="VCWebsiteStartMenuShortcut"
|
||||
@@ -2503,7 +2504,7 @@
|
||||
<RegistryValue
|
||||
Root="HKCU"
|
||||
Key="Software\VeraCrypt_MSI"
|
||||
Name="VCWebsiteStartMenuShortcutInstalled"
|
||||
Name="VCWebsiteStartMenuShortcutInstalledStable"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes"/>
|
||||
@@ -3444,6 +3445,12 @@
|
||||
<CustomAction Id="PostInst_SetData"
|
||||
Property="DoPostInstall"
|
||||
Value="INSTALLDIR=[APPLICATIONROOTFOLDER]" />
|
||||
|
||||
<!-- Create a Custom Action which sets the CustomActionData property
|
||||
for CleanupOldStartMenuFolders Deferred Custom Action. -->
|
||||
<CustomAction Id="CleanupOldStartMenuFolders_SetData"
|
||||
Property="CleanupOldStartMenuFolders"
|
||||
Value="PROGRAMMENUFOLDER=[ProgramMenuFolder]" />
|
||||
|
||||
<!-- Create a Custom Action which sets the CustomActionData property
|
||||
for DoPostUninstall Deferred Custom Action.
|
||||
@@ -3474,6 +3481,14 @@
|
||||
Return="check"
|
||||
BinaryKey="VeraCryptCustomActions"
|
||||
DllEntry="VC_CustomAction_PostInstall" />
|
||||
|
||||
<!-- Best-effort cleanup of obsolete versioned Start Menu folders from previous MSI releases. -->
|
||||
<CustomAction Id="CleanupOldStartMenuFolders"
|
||||
Execute="deferred"
|
||||
Impersonate="no"
|
||||
Return="ignore"
|
||||
BinaryKey="VeraCryptCustomActions"
|
||||
DllEntry="VC_CustomAction_CleanupOldStartMenuFolders" />
|
||||
|
||||
<!-- Create our Pre-Uninstall Custom Action.
|
||||
We need to run it as deferred so that it runs
|
||||
@@ -3614,6 +3629,10 @@
|
||||
it will execute it twice : once when it installs new files (NOT Installed), and then when it removes unnecessary files (actual upgrade: UPGRADINGPRODUCTCODE).
|
||||
Therefore, we do not need to execute it at UPGRADINGPRODUCTCODE. -->
|
||||
<Custom Action="DoPostInstall" After="InstallFiles">(NOT Installed AND NOT REMOVE) OR REINSTALL</Custom>
|
||||
|
||||
<!-- Cleanup obsolete versioned Start Menu folders as late as possible in the install transaction. -->
|
||||
<Custom Action="CleanupOldStartMenuFolders_SetData" Before="CleanupOldStartMenuFolders">(NOT Installed AND NOT REMOVE) OR REINSTALL</Custom>
|
||||
<Custom Action="CleanupOldStartMenuFolders" After="PublishProduct">(NOT Installed AND NOT REMOVE) OR REINSTALL</Custom>
|
||||
|
||||
<!-- UNINSTALLATION ONLY CAs -->
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -10,7 +10,7 @@ signature = "$Windows NT$"
|
||||
Class = "Encryption" ;This is determined by the work this filter driver does
|
||||
ClassGuid = {a0a701c0-a511-42ff-aa6c-06dc0395576f} ;This value is determined by the Class
|
||||
Provider = %ProviderString%
|
||||
DriverVer = 04/30/2026,1.26.28.0
|
||||
DriverVer = 05/22/2026,1.26.28.1
|
||||
CatalogFile = veracrypt.cat
|
||||
PnpLockdown = 1
|
||||
|
||||
|
||||
@@ -2,5 +2,16 @@
|
||||
# Get the directory where AppRun is located
|
||||
APPDIR=$(dirname "$(readlink -f "$0")")
|
||||
|
||||
# Prefer libraries bundled inside the AppImage. This lets the official
|
||||
# AppImage carry its private FUSE2 userspace library on systems where
|
||||
# libfuse.so.2 is no longer installed by default.
|
||||
if [ -d "${APPDIR}/usr/lib" ]; then
|
||||
if [ -n "${LD_LIBRARY_PATH:-}" ]; then
|
||||
export LD_LIBRARY_PATH="${APPDIR}/usr/lib:${LD_LIBRARY_PATH}"
|
||||
else
|
||||
export LD_LIBRARY_PATH="${APPDIR}/usr/lib"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Execute the main VeraCrypt application
|
||||
exec "${APPDIR}/usr/bin/veracrypt" "$@"
|
||||
|
||||
@@ -26,8 +26,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,26,28,0
|
||||
PRODUCTVERSION 1,26,28,0
|
||||
FILEVERSION 1,26,28,1
|
||||
PRODUCTVERSION 1,26,28,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,26,28,0
|
||||
PRODUCTVERSION 1,26,28,0
|
||||
FILEVERSION 1,26,28,1
|
||||
PRODUCTVERSION 1,26,28,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
+233
-5
@@ -2134,6 +2134,225 @@ void Tokenize(const wchar_t* szInput, std::vector<std::wstring>& szTokens)
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL JoinPath(wchar_t *szPath, size_t cbPath, const wchar_t *szDirectory, const wchar_t *szFileName)
|
||||
{
|
||||
if (FAILED(StringCbCopyW(szPath, cbPath, szDirectory)))
|
||||
return FALSE;
|
||||
|
||||
size_t cchPath = wcslen(szPath);
|
||||
if (cchPath > 0 && szPath[cchPath - 1] != L'\\' && szPath[cchPath - 1] != L'/')
|
||||
{
|
||||
if (FAILED(StringCbCatW(szPath, cbPath, L"\\")))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return SUCCEEDED(StringCbCatW(szPath, cbPath, szFileName));
|
||||
}
|
||||
|
||||
static BOOL IsVersionedVeraCryptStartMenuFolderName(const wchar_t *szFolderName)
|
||||
{
|
||||
const wchar_t szPrefix[] = L"VeraCrypt ";
|
||||
const wchar_t *szVersion = NULL;
|
||||
BOOL bHasDigit = FALSE;
|
||||
BOOL bHasDot = FALSE;
|
||||
BOOL bPreviousDot = FALSE;
|
||||
|
||||
if (!szFolderName || _wcsnicmp(szFolderName, szPrefix, wcslen(szPrefix)) != 0)
|
||||
return FALSE;
|
||||
|
||||
szVersion = szFolderName + wcslen(szPrefix);
|
||||
if (*szVersion == L'\0')
|
||||
return FALSE;
|
||||
|
||||
while (*szVersion)
|
||||
{
|
||||
if (*szVersion >= L'0' && *szVersion <= L'9')
|
||||
{
|
||||
bHasDigit = TRUE;
|
||||
bPreviousDot = FALSE;
|
||||
}
|
||||
else if (*szVersion == L'.')
|
||||
{
|
||||
if (bPreviousDot)
|
||||
return FALSE;
|
||||
|
||||
bHasDot = TRUE;
|
||||
bPreviousDot = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
++szVersion;
|
||||
}
|
||||
|
||||
return bHasDigit && bHasDot && !bPreviousDot;
|
||||
}
|
||||
|
||||
static void DeleteStartMenuShortcutIfExists(MSIHANDLE hInstaller, const wchar_t *szFolderPath, const wchar_t *szShortcutName)
|
||||
{
|
||||
wchar_t szShortcutPath[TC_MAX_PATH];
|
||||
DWORD dwAttributes;
|
||||
|
||||
if (!JoinPath(szShortcutPath, sizeof(szShortcutPath), szFolderPath, szShortcutName))
|
||||
{
|
||||
MSILog(hInstaller, MSI_WARNING_LEVEL, L"Could not build Start Menu shortcut path for '%s'", szShortcutName);
|
||||
return;
|
||||
}
|
||||
|
||||
dwAttributes = GetFileAttributesW(szShortcutPath);
|
||||
if (dwAttributes == INVALID_FILE_ATTRIBUTES || (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
return;
|
||||
|
||||
MSILog(hInstaller, MSI_INFO_LEVEL, L"Removing obsolete Start Menu shortcut '%s'", szShortcutPath);
|
||||
|
||||
if (dwAttributes & FILE_ATTRIBUTE_READONLY)
|
||||
SetFileAttributesW(szShortcutPath, dwAttributes & ~FILE_ATTRIBUTE_READONLY);
|
||||
|
||||
if (!DeleteFileW(szShortcutPath))
|
||||
{
|
||||
DWORD dwError = GetLastError();
|
||||
if (dwError != ERROR_FILE_NOT_FOUND && dwError != ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
MSILog(hInstaller, MSI_WARNING_LEVEL, L"Could not remove obsolete Start Menu shortcut '%s' (error %lu)", szShortcutPath, dwError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CleanupVersionedVeraCryptStartMenuFolder(MSIHANDLE hInstaller, const wchar_t *szFolderPath)
|
||||
{
|
||||
/* Delete only known VeraCrypt-created shortcuts; keep folders with any other content. */
|
||||
static const wchar_t *szShortcutNames[] =
|
||||
{
|
||||
L"VeraCrypt.lnk",
|
||||
L"VeraCryptExpander.lnk",
|
||||
L"VeraCrypt Website.url",
|
||||
L"VeraCrypt User's Guide.lnk",
|
||||
L"VeraCrypt User Guide.lnk",
|
||||
L"Uninstall VeraCrypt.lnk"
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(szShortcutNames); ++i)
|
||||
DeleteStartMenuShortcutIfExists(hInstaller, szFolderPath, szShortcutNames[i]);
|
||||
|
||||
if (RemoveDirectoryW(szFolderPath))
|
||||
{
|
||||
MSILog(hInstaller, MSI_INFO_LEVEL, L"Removed obsolete Start Menu folder '%s'", szFolderPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwError = GetLastError();
|
||||
if (dwError == ERROR_DIR_NOT_EMPTY)
|
||||
{
|
||||
MSILog(hInstaller, MSI_INFO_LEVEL, L"Obsolete Start Menu folder '%s' was left in place because it contains non-VeraCrypt items", szFolderPath);
|
||||
}
|
||||
else if (dwError != ERROR_FILE_NOT_FOUND && dwError != ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
MSILog(hInstaller, MSI_WARNING_LEVEL, L"Could not remove obsolete Start Menu folder '%s' (error %lu)", szFolderPath, dwError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CleanupVersionedVeraCryptStartMenuFoldersInRoot(MSIHANDLE hInstaller, const wchar_t *szProgramMenuFolder)
|
||||
{
|
||||
wchar_t szSearchPath[TC_MAX_PATH];
|
||||
WIN32_FIND_DATAW findData;
|
||||
HANDLE hFind;
|
||||
|
||||
if (!szProgramMenuFolder || szProgramMenuFolder[0] == L'\0')
|
||||
return;
|
||||
|
||||
if (!JoinPath(szSearchPath, sizeof(szSearchPath), szProgramMenuFolder, L"VeraCrypt *"))
|
||||
{
|
||||
MSILog(hInstaller, MSI_WARNING_LEVEL, L"Could not build obsolete Start Menu folder search path for '%s'", szProgramMenuFolder);
|
||||
return;
|
||||
}
|
||||
|
||||
hFind = FindFirstFileW(szSearchPath, &findData);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD dwError = GetLastError();
|
||||
if (dwError != ERROR_FILE_NOT_FOUND && dwError != ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
MSILog(hInstaller, MSI_WARNING_LEVEL, L"Could not search obsolete Start Menu folders in '%s' (error %lu)", szProgramMenuFolder, dwError);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
&& IsVersionedVeraCryptStartMenuFolderName(findData.cFileName))
|
||||
{
|
||||
wchar_t szFolderPath[TC_MAX_PATH];
|
||||
|
||||
if (JoinPath(szFolderPath, sizeof(szFolderPath), szProgramMenuFolder, findData.cFileName))
|
||||
CleanupVersionedVeraCryptStartMenuFolder(hInstaller, szFolderPath);
|
||||
else
|
||||
MSILog(hInstaller, MSI_WARNING_LEVEL, L"Could not build obsolete Start Menu folder path for '%s'", findData.cFileName);
|
||||
}
|
||||
}
|
||||
while (FindNextFileW(hFind, &findData));
|
||||
|
||||
FindClose(hFind);
|
||||
}
|
||||
|
||||
static void CleanupVersionedVeraCryptStartMenuFolders(MSIHANDLE hInstaller, const wchar_t *szProgramMenuFolder)
|
||||
{
|
||||
wchar_t szCommonPrograms[TC_MAX_PATH];
|
||||
|
||||
CleanupVersionedVeraCryptStartMenuFoldersInRoot(hInstaller, szProgramMenuFolder);
|
||||
|
||||
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_COMMON_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, szCommonPrograms)))
|
||||
CleanupVersionedVeraCryptStartMenuFoldersInRoot(hInstaller, szCommonPrograms);
|
||||
}
|
||||
|
||||
EXTERN_C UINT STDAPICALLTYPE VC_CustomAction_CleanupOldStartMenuFolders(MSIHANDLE hInstaller)
|
||||
{
|
||||
std::wstring szValueBuf = L"";
|
||||
std::wstring szProgramMenuFolder = L"";
|
||||
DWORD cchValueBuf = 0;
|
||||
UINT uiStat = 0;
|
||||
|
||||
MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin VC_CustomAction_CleanupOldStartMenuFolders");
|
||||
|
||||
uiStat = MsiGetProperty(hInstaller, TEXT("CustomActionData"), (LPWSTR)TEXT(""), &cchValueBuf);
|
||||
if (ERROR_MORE_DATA == uiStat)
|
||||
{
|
||||
++cchValueBuf; // add 1 for null termination
|
||||
szValueBuf.resize(cchValueBuf);
|
||||
uiStat = MsiGetProperty(hInstaller, TEXT("CustomActionData"), &szValueBuf[0], &cchValueBuf);
|
||||
if (ERROR_SUCCESS == uiStat)
|
||||
{
|
||||
MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_CleanupOldStartMenuFolders: CustomActionData = '%s'", szValueBuf.c_str());
|
||||
|
||||
std::vector<std::wstring> szTokens;
|
||||
Tokenize(szValueBuf.c_str(), szTokens);
|
||||
|
||||
for (size_t i = 0; i < szTokens.size(); i++)
|
||||
{
|
||||
std::wstring szToken = szTokens[i];
|
||||
|
||||
if (wcsncmp(szToken.c_str(), L"PROGRAMMENUFOLDER=", wcslen(L"PROGRAMMENUFOLDER=")) == 0)
|
||||
{
|
||||
size_t index0 = szToken.find_first_of(L"=");
|
||||
if (index0 != std::wstring::npos)
|
||||
{
|
||||
szProgramMenuFolder = szToken.substr(index0 + 1);
|
||||
MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_CleanupOldStartMenuFolders: PROGRAMMENUFOLDER = '%s'", szProgramMenuFolder.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CleanupVersionedVeraCryptStartMenuFolders(hInstaller, szProgramMenuFolder.c_str());
|
||||
|
||||
MSILog(hInstaller, MSI_INFO_LEVEL, L"End VC_CustomAction_CleanupOldStartMenuFolders");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as Setup.c, function DoInstall(), but
|
||||
* without the actual installation, it only prepares the system
|
||||
@@ -2390,13 +2609,22 @@ EXTERN_C UINT STDAPICALLTYPE VC_CustomAction_PostInstall(MSIHANDLE hInstaller)
|
||||
if ((ERROR_SUCCESS == uiStat))
|
||||
{
|
||||
MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PostInstall: CustomActionData = '%s'", szValueBuf.c_str());
|
||||
if (wcsncmp(szValueBuf.c_str(), L"INSTALLDIR=", wcslen(L"INSTALLDIR=")) == 0)
|
||||
|
||||
std::vector<std::wstring> szTokens;
|
||||
Tokenize(szValueBuf.c_str(), szTokens);
|
||||
|
||||
for (size_t i = 0; i < szTokens.size(); i++)
|
||||
{
|
||||
size_t index0 = szValueBuf.find_first_of(L"=");
|
||||
if (index0 != std::wstring::npos)
|
||||
std::wstring szToken = szTokens[i];
|
||||
|
||||
if (wcsncmp(szToken.c_str(), L"INSTALLDIR=", wcslen(L"INSTALLDIR=")) == 0)
|
||||
{
|
||||
szInstallDir = szValueBuf.substr(index0 + 1);
|
||||
MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PostInstall: INSTALLDIR = '%s'", szInstallDir.c_str());
|
||||
size_t index0 = szToken.find_first_of(L"=");
|
||||
if (index0 != std::wstring::npos)
|
||||
{
|
||||
szInstallDir = szToken.substr(index0 + 1);
|
||||
MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PostInstall: INSTALLDIR = '%s'", szInstallDir.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,26,28,0
|
||||
PRODUCTVERSION 1,26,28,0
|
||||
FILEVERSION 1,26,28,1
|
||||
PRODUCTVERSION 1,26,28,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -2,6 +2,7 @@ LIBRARY VERACRYPTSETUP
|
||||
EXPORTS
|
||||
VC_CustomAction_PreInstall
|
||||
VC_CustomAction_PostInstall
|
||||
VC_CustomAction_CleanupOldStartMenuFolders
|
||||
VC_CustomAction_PreUninstall
|
||||
VC_CustomAction_PostUninstall
|
||||
VC_CustomAction_DoChecks
|
||||
VC_CustomAction_DoChecks
|
||||
|
||||
@@ -50,6 +50,12 @@ namespace VeraCrypt
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
(void) pAbortKeyDerivation;
|
||||
return DeriveKey (key, password, salt, iterationCount);
|
||||
}
|
||||
|
||||
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Blake2b); }
|
||||
virtual int GetIterationCount (int pim) const { return 1; }
|
||||
virtual wstring GetName () const { return L"Argon2"; }
|
||||
@@ -1204,14 +1210,26 @@ namespace VeraCrypt
|
||||
0x30, 0x86, 0x51, 0x21, 0x69, 0x94, 0xab, 0xbf,
|
||||
0xdd, 0xd6, 0x9b, 0x25, 0x92, 0x03, 0x2e, 0xfd
|
||||
};
|
||||
static const uint8 argon2Pim1HeaderKeyPrefix[] =
|
||||
{
|
||||
0x48, 0x8d, 0x71, 0xbd, 0x71, 0x6e, 0x68, 0x45,
|
||||
0xaa, 0xe6, 0xe2, 0x29, 0x74, 0x18, 0x2c, 0x20,
|
||||
0xe9, 0x42, 0x8d, 0x7b, 0x3d, 0x4b, 0xcf, 0x54,
|
||||
0x04, 0x6c, 0x3e, 0xbe, 0x80, 0x33, 0x8f, 0x20
|
||||
};
|
||||
ConstBufferPtr argon2Salt (argon2SaltData, sizeof (argon2SaltData));
|
||||
Buffer argon2DerivedKey (sizeof (argon2Pim1DerivedKey));
|
||||
Buffer argon2HeaderKey (ARGON2_HEADER_KEYDATA_SIZE);
|
||||
|
||||
// PIM 1 maps to Argon2id t=3, m=64 MiB, p=1.
|
||||
if (pkcs5Argon2.DeriveKey (argon2DerivedKey, password, 1, argon2Salt) != 0)
|
||||
throw TestFailed (SRC_POS);
|
||||
if (memcmp (argon2DerivedKey.Ptr(), argon2Pim1DerivedKey, sizeof (argon2Pim1DerivedKey)) != 0)
|
||||
throw TestFailed (SRC_POS);
|
||||
if (pkcs5Argon2.DeriveKey (argon2HeaderKey, password, 1, argon2Salt) != 0)
|
||||
throw TestFailed (SRC_POS);
|
||||
if (memcmp (argon2HeaderKey.Ptr(), argon2Pim1HeaderKeyPrefix, sizeof (argon2Pim1HeaderKeyPrefix)) != 0)
|
||||
throw TestFailed (SRC_POS);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -23,9 +23,62 @@
|
||||
#include "Platform/SystemLog.h"
|
||||
#include "Common/Crypto.h"
|
||||
#include "EncryptionThreadPool.h"
|
||||
#include "Pkcs5Kdf.h"
|
||||
|
||||
namespace VeraCrypt
|
||||
{
|
||||
EncryptionThreadPool::KeyDerivationWorkItem::KeyDerivationWorkItem (shared_ptr <Pkcs5Kdf> kdf, size_t derivedKeySize)
|
||||
: Completed (false), DerivedKey (derivedKeySize), Kdf (kdf), Processed (false), Result (0)
|
||||
{
|
||||
}
|
||||
|
||||
EncryptionThreadPool::KeyDerivationWorkItem::~KeyDerivationWorkItem ()
|
||||
{
|
||||
}
|
||||
|
||||
void EncryptionThreadPool::BeginKeyDerivation (KeyDerivationWorkItem &keyDerivationWorkItem, const VolumePassword &password, int pim, const ConstBufferPtr &salt, SyncEvent &completionEvent, SyncEvent &noOutstandingWorkItemEvent, SharedVal <size_t> &outstandingWorkItemCount, long volatile *abortFlag)
|
||||
{
|
||||
if (!ThreadPoolRunning)
|
||||
throw NotInitialized (SRC_POS);
|
||||
|
||||
ScopeLock lock (EnqueueMutex);
|
||||
|
||||
WorkItem *workItem = &WorkItemQueue[EnqueuePosition++];
|
||||
|
||||
if (EnqueuePosition >= QueueSize)
|
||||
EnqueuePosition = 0;
|
||||
|
||||
while (workItem->State != WorkItem::State::Free)
|
||||
{
|
||||
WorkItemCompletedEvent.Wait();
|
||||
}
|
||||
|
||||
keyDerivationWorkItem.Completed.Set (false);
|
||||
keyDerivationWorkItem.ItemException.reset();
|
||||
keyDerivationWorkItem.Processed = false;
|
||||
keyDerivationWorkItem.Result = 0;
|
||||
|
||||
workItem->Type = WorkType::DeriveKey;
|
||||
workItem->KeyDerivation.AbortFlag = abortFlag;
|
||||
workItem->KeyDerivation.CompletionEvent = &completionEvent;
|
||||
workItem->KeyDerivation.NoOutstandingWorkItemEvent = &noOutstandingWorkItemEvent;
|
||||
workItem->KeyDerivation.OutstandingWorkItemCount = &outstandingWorkItemCount;
|
||||
workItem->KeyDerivation.Password = &password;
|
||||
workItem->KeyDerivation.Pim = pim;
|
||||
workItem->KeyDerivation.Salt = salt.Get();
|
||||
workItem->KeyDerivation.SaltSize = salt.Size();
|
||||
workItem->KeyDerivation.WorkItem = &keyDerivationWorkItem;
|
||||
|
||||
{
|
||||
ScopeLock outstandingWorkItemLock (KeyDerivationCompletionMutex);
|
||||
if (outstandingWorkItemCount.Increment() == 1)
|
||||
noOutstandingWorkItemEvent.Reset();
|
||||
}
|
||||
|
||||
workItem->State.Set (WorkItem::State::Ready);
|
||||
WorkItemReadyEvent.Signal();
|
||||
}
|
||||
|
||||
void EncryptionThreadPool::DoWork (WorkType::Enum type, const EncryptionMode *encryptionMode, uint8 *data, uint64 startUnitNo, uint64 unitCount, size_t sectorSize)
|
||||
{
|
||||
size_t fragmentCount;
|
||||
@@ -272,21 +325,54 @@ namespace VeraCrypt
|
||||
workItem->Encryption.Mode->EncryptSectorsCurrentThread (workItem->Encryption.Data, workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.SectorSize);
|
||||
break;
|
||||
|
||||
case WorkType::DeriveKey:
|
||||
{
|
||||
KeyDerivationWorkItem *keyDerivationWorkItem = workItem->KeyDerivation.WorkItem;
|
||||
if (workItem->KeyDerivation.AbortFlag && *workItem->KeyDerivation.AbortFlag)
|
||||
keyDerivationWorkItem->Result = ERR_USER_ABORT;
|
||||
else
|
||||
keyDerivationWorkItem->Result = keyDerivationWorkItem->Kdf->DeriveKey (keyDerivationWorkItem->DerivedKey, *workItem->KeyDerivation.Password, workItem->KeyDerivation.Pim, ConstBufferPtr (workItem->KeyDerivation.Salt, workItem->KeyDerivation.SaltSize), workItem->KeyDerivation.AbortFlag);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
}
|
||||
}
|
||||
catch (Exception &e)
|
||||
{
|
||||
workItem->FirstFragment->ItemException.reset (e.CloneNew());
|
||||
if (workItem->Type == WorkType::DeriveKey)
|
||||
workItem->KeyDerivation.WorkItem->ItemException.reset (e.CloneNew());
|
||||
else
|
||||
workItem->FirstFragment->ItemException.reset (e.CloneNew());
|
||||
}
|
||||
catch (exception &e)
|
||||
{
|
||||
workItem->FirstFragment->ItemException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e)));
|
||||
if (workItem->Type == WorkType::DeriveKey)
|
||||
workItem->KeyDerivation.WorkItem->ItemException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e)));
|
||||
else
|
||||
workItem->FirstFragment->ItemException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e)));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
workItem->FirstFragment->ItemException.reset (new UnknownException (SRC_POS));
|
||||
if (workItem->Type == WorkType::DeriveKey)
|
||||
workItem->KeyDerivation.WorkItem->ItemException.reset (new UnknownException (SRC_POS));
|
||||
else
|
||||
workItem->FirstFragment->ItemException.reset (new UnknownException (SRC_POS));
|
||||
}
|
||||
|
||||
if (workItem->Type == WorkType::DeriveKey)
|
||||
{
|
||||
workItem->KeyDerivation.WorkItem->Completed.Set (true);
|
||||
workItem->KeyDerivation.CompletionEvent->Signal();
|
||||
{
|
||||
ScopeLock outstandingWorkItemLock (KeyDerivationCompletionMutex);
|
||||
if (workItem->KeyDerivation.OutstandingWorkItemCount->Decrement() == 0)
|
||||
workItem->KeyDerivation.NoOutstandingWorkItemEvent->Signal();
|
||||
}
|
||||
workItem->State.Set (WorkItem::State::Free);
|
||||
WorkItemCompletedEvent.Signal();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (workItem != workItem->FirstFragment)
|
||||
@@ -321,6 +407,7 @@ namespace VeraCrypt
|
||||
|
||||
Mutex EncryptionThreadPool::EnqueueMutex;
|
||||
Mutex EncryptionThreadPool::DequeueMutex;
|
||||
Mutex EncryptionThreadPool::KeyDerivationCompletionMutex;
|
||||
|
||||
SyncEvent EncryptionThreadPool::WorkItemReadyEvent;
|
||||
SyncEvent EncryptionThreadPool::WorkItemCompletedEvent;
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
namespace VeraCrypt
|
||||
{
|
||||
class Pkcs5Kdf;
|
||||
class VolumePassword;
|
||||
|
||||
class EncryptionThreadPool
|
||||
{
|
||||
public:
|
||||
@@ -31,6 +34,8 @@ namespace VeraCrypt
|
||||
};
|
||||
};
|
||||
|
||||
struct KeyDerivationWorkItem;
|
||||
|
||||
struct WorkItem
|
||||
{
|
||||
struct State
|
||||
@@ -60,9 +65,37 @@ namespace VeraCrypt
|
||||
uint64 UnitCount;
|
||||
size_t SectorSize;
|
||||
} Encryption;
|
||||
|
||||
struct
|
||||
{
|
||||
long volatile *AbortFlag;
|
||||
SyncEvent *CompletionEvent;
|
||||
SyncEvent *NoOutstandingWorkItemEvent;
|
||||
SharedVal <size_t> *OutstandingWorkItemCount;
|
||||
const VolumePassword *Password;
|
||||
int Pim;
|
||||
const uint8 *Salt;
|
||||
size_t SaltSize;
|
||||
KeyDerivationWorkItem *WorkItem;
|
||||
} KeyDerivation;
|
||||
};
|
||||
};
|
||||
|
||||
struct KeyDerivationWorkItem
|
||||
{
|
||||
KeyDerivationWorkItem (shared_ptr <Pkcs5Kdf> kdf, size_t derivedKeySize);
|
||||
~KeyDerivationWorkItem ();
|
||||
|
||||
SharedVal <bool> Completed;
|
||||
SecureBuffer DerivedKey;
|
||||
unique_ptr <Exception> ItemException;
|
||||
shared_ptr <Pkcs5Kdf> Kdf;
|
||||
bool Processed;
|
||||
int Result;
|
||||
};
|
||||
|
||||
// Caller-owned references and pointers must remain valid until noOutstandingWorkItemEvent is signaled.
|
||||
static void BeginKeyDerivation (KeyDerivationWorkItem &keyDerivationWorkItem, const VolumePassword &password, int pim, const ConstBufferPtr &salt, SyncEvent &completionEvent, SyncEvent &noOutstandingWorkItemEvent, SharedVal <size_t> &outstandingWorkItemCount, long volatile *abortFlag);
|
||||
static void DoWork (WorkType::Enum type, const EncryptionMode *mode, uint8 *data, uint64 startUnitNo, uint64 unitCount, size_t sectorSize);
|
||||
static bool IsRunning () { return ThreadPoolRunning; }
|
||||
static void Start ();
|
||||
@@ -78,6 +111,8 @@ namespace VeraCrypt
|
||||
static volatile size_t DequeuePosition;
|
||||
static volatile size_t EnqueuePosition;
|
||||
static Mutex EnqueueMutex;
|
||||
// Orders KDF outstanding-count transitions against no-outstanding event updates.
|
||||
static Mutex KeyDerivationCompletionMutex;
|
||||
static list < shared_ptr <Thread> > RunningThreads;
|
||||
static volatile bool StopPending;
|
||||
static size_t ThreadCount;
|
||||
|
||||
+72
-10
@@ -30,7 +30,18 @@ namespace VeraCrypt
|
||||
|
||||
int Pkcs5Kdf::DeriveKey (const BufferPtr &key, const VolumePassword &password, int pim, const ConstBufferPtr &salt) const
|
||||
{
|
||||
return DeriveKey (key, password, salt, GetIterationCount(pim));
|
||||
return DeriveKey (key, password, pim, salt, nullptr);
|
||||
}
|
||||
|
||||
int Pkcs5Kdf::DeriveKey (const BufferPtr &key, const VolumePassword &password, int pim, const ConstBufferPtr &salt, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
return DeriveKey (key, password, salt, GetIterationCount(pim), pAbortKeyDerivation);
|
||||
}
|
||||
|
||||
int Pkcs5Kdf::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
(void) pAbortKeyDerivation;
|
||||
return DeriveKey (key, password, salt, iterationCount);
|
||||
}
|
||||
|
||||
wstring Pkcs5Kdf::GetDerivationFailureMessage (int result) const
|
||||
@@ -88,65 +99,105 @@ namespace VeraCrypt
|
||||
|
||||
#ifndef WOLFCRYPT_BACKEND
|
||||
int Pkcs5HmacBlake2s_Boot::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
|
||||
{
|
||||
return DeriveKey (key, password, salt, iterationCount, nullptr);
|
||||
}
|
||||
|
||||
int Pkcs5HmacBlake2s_Boot::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
ValidateParameters (key, password, salt, iterationCount);
|
||||
derive_key_blake2s (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), NULL);
|
||||
derive_key_blake2s (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), pAbortKeyDerivation);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Pkcs5HmacBlake2s::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
|
||||
{
|
||||
return DeriveKey (key, password, salt, iterationCount, nullptr);
|
||||
}
|
||||
|
||||
int Pkcs5HmacBlake2s::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
ValidateParameters (key, password, salt, iterationCount);
|
||||
derive_key_blake2s (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), NULL);
|
||||
derive_key_blake2s (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), pAbortKeyDerivation);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int Pkcs5HmacSha256_Boot::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
|
||||
{
|
||||
return DeriveKey (key, password, salt, iterationCount, nullptr);
|
||||
}
|
||||
|
||||
int Pkcs5HmacSha256_Boot::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
ValidateParameters (key, password, salt, iterationCount);
|
||||
derive_key_sha256 (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), NULL);
|
||||
derive_key_sha256 (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), pAbortKeyDerivation);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Pkcs5HmacSha256::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
|
||||
{
|
||||
return DeriveKey (key, password, salt, iterationCount, nullptr);
|
||||
}
|
||||
|
||||
int Pkcs5HmacSha256::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
ValidateParameters (key, password, salt, iterationCount);
|
||||
derive_key_sha256 (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), NULL);
|
||||
derive_key_sha256 (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), pAbortKeyDerivation);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Pkcs5HmacSha512::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
|
||||
{
|
||||
return DeriveKey (key, password, salt, iterationCount, nullptr);
|
||||
}
|
||||
|
||||
int Pkcs5HmacSha512::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
ValidateParameters (key, password, salt, iterationCount);
|
||||
derive_key_sha512 (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), NULL);
|
||||
derive_key_sha512 (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), pAbortKeyDerivation);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef WOLFCRYPT_BACKEND
|
||||
int Pkcs5HmacWhirlpool::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
|
||||
{
|
||||
return DeriveKey (key, password, salt, iterationCount, nullptr);
|
||||
}
|
||||
|
||||
int Pkcs5HmacWhirlpool::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
ValidateParameters (key, password, salt, iterationCount);
|
||||
derive_key_whirlpool (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), NULL);
|
||||
derive_key_whirlpool (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), pAbortKeyDerivation);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Pkcs5HmacStreebog::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
|
||||
{
|
||||
return DeriveKey (key, password, salt, iterationCount, nullptr);
|
||||
}
|
||||
|
||||
int Pkcs5HmacStreebog::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
ValidateParameters (key, password, salt, iterationCount);
|
||||
derive_key_streebog (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), NULL);
|
||||
derive_key_streebog (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), pAbortKeyDerivation);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef VC_DCS_DISABLE_ARGON2
|
||||
int Pkcs5Argon2::DeriveKey (const BufferPtr &key, const VolumePassword &password, int pim, const ConstBufferPtr &salt) const
|
||||
{
|
||||
return DeriveKey (key, password, pim, salt, nullptr);
|
||||
}
|
||||
|
||||
int Pkcs5Argon2::DeriveKey (const BufferPtr &key, const VolumePassword &password, int pim, const ConstBufferPtr &salt, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
int iterationCount;
|
||||
int memoryCost;
|
||||
get_argon2_params (pim, &iterationCount, &memoryCost);
|
||||
|
||||
ValidateParameters (key, password, salt, iterationCount);
|
||||
return derive_key_argon2 (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, memoryCost, key.Get(), (int) key.Size(), NULL);
|
||||
return derive_key_argon2 (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, memoryCost, key.Get(), (int) key.Size(), pAbortKeyDerivation);
|
||||
}
|
||||
|
||||
int Pkcs5Argon2::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
|
||||
@@ -158,6 +209,12 @@ namespace VeraCrypt
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
}
|
||||
|
||||
int Pkcs5Argon2::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
(void) pAbortKeyDerivation;
|
||||
return DeriveKey (key, password, salt, iterationCount);
|
||||
}
|
||||
|
||||
wstring Pkcs5Argon2::GetDerivationFailureMessage (int result) const
|
||||
{
|
||||
return L"Argon2 key derivation failed: " + StringConverter::ToWide (argon2_error_message (result));
|
||||
@@ -173,9 +230,14 @@ namespace VeraCrypt
|
||||
#endif
|
||||
|
||||
int Pkcs5HmacStreebog_Boot::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
|
||||
{
|
||||
return DeriveKey (key, password, salt, iterationCount, nullptr);
|
||||
}
|
||||
|
||||
int Pkcs5HmacStreebog_Boot::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const
|
||||
{
|
||||
ValidateParameters (key, password, salt, iterationCount);
|
||||
derive_key_streebog (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), NULL);
|
||||
derive_key_streebog (password.DataPtr(), (int) password.Size(), salt.Get(), (int) salt.Size(), iterationCount, key.Get(), (int) key.Size(), pAbortKeyDerivation);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,9 @@ namespace VeraCrypt
|
||||
virtual ~Pkcs5Kdf ();
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, int pim, const ConstBufferPtr &salt) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, int pim, const ConstBufferPtr &salt, long volatile *pAbortKeyDerivation) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const = 0;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const = 0;
|
||||
static shared_ptr <Pkcs5Kdf> GetAlgorithm (const wstring &name);
|
||||
static shared_ptr <Pkcs5Kdf> GetAlgorithm (const Hash &hash);
|
||||
static Pkcs5KdfList GetAvailableAlgorithms ();
|
||||
@@ -63,6 +65,7 @@ namespace VeraCrypt
|
||||
virtual ~Pkcs5HmacBlake2s_Boot () { }
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const;
|
||||
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Blake2s); }
|
||||
virtual int GetDefaultPim () const { return 98; }
|
||||
virtual int GetIterationCount (int pim) const { return pim <= 0 ? 200000 : (pim * 2048); }
|
||||
@@ -81,6 +84,7 @@ namespace VeraCrypt
|
||||
virtual ~Pkcs5HmacBlake2s () { }
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const;
|
||||
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Blake2s); }
|
||||
virtual int GetIterationCount (int pim) const { return pim <= 0 ? 500000 : (15000 + (pim * 1000)); }
|
||||
virtual wstring GetName () const { return L"HMAC-BLAKE2s-256"; }
|
||||
@@ -99,6 +103,7 @@ namespace VeraCrypt
|
||||
virtual ~Pkcs5HmacSha256_Boot () { }
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const;
|
||||
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Sha256); }
|
||||
virtual int GetDefaultPim () const { return 98; }
|
||||
virtual int GetIterationCount (int pim) const { return pim <= 0 ? 200000 : (pim * 2048); }
|
||||
@@ -117,6 +122,7 @@ namespace VeraCrypt
|
||||
virtual ~Pkcs5HmacSha256 () { }
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const;
|
||||
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Sha256); }
|
||||
virtual int GetIterationCount (int pim) const { return pim <= 0 ? 500000 : (15000 + (pim * 1000)); }
|
||||
virtual wstring GetName () const { return L"HMAC-SHA-256"; }
|
||||
@@ -134,6 +140,7 @@ namespace VeraCrypt
|
||||
virtual ~Pkcs5HmacSha512 () { }
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const;
|
||||
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Sha512); }
|
||||
virtual int GetIterationCount (int pim) const { return (pim <= 0 ? 500000 : (15000 + (pim * 1000))); }
|
||||
virtual wstring GetName () const { return L"HMAC-SHA-512"; }
|
||||
@@ -151,6 +158,7 @@ namespace VeraCrypt
|
||||
virtual ~Pkcs5HmacWhirlpool () { }
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const;
|
||||
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Whirlpool); }
|
||||
virtual int GetIterationCount (int pim) const { return (pim <= 0 ? 500000 : (15000 + (pim * 1000))); }
|
||||
virtual wstring GetName () const { return L"HMAC-Whirlpool"; }
|
||||
@@ -168,6 +176,7 @@ namespace VeraCrypt
|
||||
virtual ~Pkcs5HmacStreebog () { }
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const;
|
||||
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Streebog); }
|
||||
virtual int GetIterationCount (int pim) const { return pim <= 0 ? 500000 : (15000 + (pim * 1000)); }
|
||||
virtual wstring GetName () const { return L"HMAC-Streebog"; }
|
||||
@@ -186,7 +195,9 @@ namespace VeraCrypt
|
||||
virtual ~Pkcs5Argon2 () { }
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, int pim, const ConstBufferPtr &salt) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, int pim, const ConstBufferPtr &salt, long volatile *pAbortKeyDerivation) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const;
|
||||
virtual wstring GetDerivationFailureMessage (int result) const;
|
||||
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Blake2b); }
|
||||
virtual int GetDefaultPim () const { return 12; }
|
||||
@@ -212,6 +223,7 @@ namespace VeraCrypt
|
||||
virtual ~Pkcs5HmacStreebog_Boot () { }
|
||||
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
|
||||
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount, long volatile *pAbortKeyDerivation) const;
|
||||
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Streebog); }
|
||||
virtual int GetDefaultPim () const { return 98; }
|
||||
virtual int GetIterationCount (int pim) const { return pim <= 0 ? 200000 : pim * 2048; }
|
||||
|
||||
+144
-40
@@ -11,18 +11,27 @@
|
||||
*/
|
||||
|
||||
#include "Crc32.h"
|
||||
#include "EncryptionThreadPool.h"
|
||||
#include "EncryptionModeXTS.h"
|
||||
#ifdef WOLFCRYPT_BACKEND
|
||||
#include "EncryptionModeWolfCryptXTS.h"
|
||||
#endif
|
||||
#include "Pkcs5Kdf.h"
|
||||
#include "Pkcs5Kdf.h"
|
||||
#include "VolumeHeader.h"
|
||||
#include "VolumeException.h"
|
||||
#include "Common/Crypto.h"
|
||||
|
||||
namespace VeraCrypt
|
||||
{
|
||||
static void DrainKeyDerivationWorkItems (SyncEvent &noOutstandingWorkItemEvent, size_t enqueuedWorkItemCount, bool &workItemsDrained)
|
||||
{
|
||||
if (enqueuedWorkItemCount > 0 && !workItemsDrained)
|
||||
{
|
||||
noOutstandingWorkItemEvent.Wait();
|
||||
workItemsDrained = true;
|
||||
}
|
||||
}
|
||||
|
||||
VolumeHeader::VolumeHeader (uint32 size)
|
||||
{
|
||||
Init();
|
||||
@@ -99,14 +108,83 @@ namespace VeraCrypt
|
||||
throw PasswordEmpty (SRC_POS);
|
||||
|
||||
ConstBufferPtr salt (encryptedData.GetRange (SaltOffset, SaltSize));
|
||||
SecureBuffer header (EncryptedHeaderDataSize);
|
||||
SecureBuffer headerKey (GetLargestSerializedKeySize());
|
||||
|
||||
if (!kdf && EncryptionThreadPool::IsRunning() && keyDerivationFunctions.size() > 1)
|
||||
{
|
||||
typedef EncryptionThreadPool::KeyDerivationWorkItem KeyDerivationWorkItem;
|
||||
|
||||
list < shared_ptr <KeyDerivationWorkItem> > keyDerivationWorkItems;
|
||||
SharedVal <size_t> outstandingWorkItemCount (0);
|
||||
SyncEvent keyDerivationCompletedEvent;
|
||||
SyncEvent noOutstandingWorkItemEvent;
|
||||
long volatile abortKeyDerivation = 0;
|
||||
size_t enqueuedWorkItemCount = 0;
|
||||
size_t processedWorkItemCount = 0;
|
||||
bool workItemsDrained = false;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (shared_ptr <Pkcs5Kdf> pkcs5, keyDerivationFunctions)
|
||||
{
|
||||
shared_ptr <KeyDerivationWorkItem> keyDerivationWorkItem (new KeyDerivationWorkItem (pkcs5, GetHeaderKeyDerivationSize (pkcs5)));
|
||||
keyDerivationWorkItems.push_back (keyDerivationWorkItem);
|
||||
EncryptionThreadPool::BeginKeyDerivation (*keyDerivationWorkItem, password, pim, salt, keyDerivationCompletedEvent, noOutstandingWorkItemEvent, outstandingWorkItemCount, &abortKeyDerivation);
|
||||
++enqueuedWorkItemCount;
|
||||
}
|
||||
|
||||
while (processedWorkItemCount < keyDerivationWorkItems.size())
|
||||
{
|
||||
bool processed = false;
|
||||
|
||||
foreach (shared_ptr <KeyDerivationWorkItem> keyDerivationWorkItem, keyDerivationWorkItems)
|
||||
{
|
||||
if (!keyDerivationWorkItem->Processed && keyDerivationWorkItem->Completed.Get())
|
||||
{
|
||||
keyDerivationWorkItem->Processed = true;
|
||||
++processedWorkItemCount;
|
||||
processed = true;
|
||||
|
||||
if (keyDerivationWorkItem->ItemException.get())
|
||||
{
|
||||
// KDF exceptions are fatal setup/runtime errors; candidate failures are reported via Result.
|
||||
abortKeyDerivation = 1;
|
||||
DrainKeyDerivationWorkItems (noOutstandingWorkItemEvent, enqueuedWorkItemCount, workItemsDrained);
|
||||
keyDerivationWorkItem->ItemException->Throw();
|
||||
}
|
||||
|
||||
if (keyDerivationWorkItem->Result != 0)
|
||||
continue;
|
||||
|
||||
if (DecryptWithHeaderKey (encryptedData, keyDerivationWorkItem->Kdf, keyDerivationWorkItem->DerivedKey, encryptionAlgorithms, encryptionModes))
|
||||
{
|
||||
abortKeyDerivation = 1;
|
||||
DrainKeyDerivationWorkItems (noOutstandingWorkItemEvent, enqueuedWorkItemCount, workItemsDrained);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (processedWorkItemCount < keyDerivationWorkItems.size() && !processed)
|
||||
keyDerivationCompletedEvent.Wait();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
abortKeyDerivation = 1;
|
||||
DrainKeyDerivationWorkItems (noOutstandingWorkItemEvent, enqueuedWorkItemCount, workItemsDrained);
|
||||
throw;
|
||||
}
|
||||
|
||||
DrainKeyDerivationWorkItems (noOutstandingWorkItemEvent, enqueuedWorkItemCount, workItemsDrained);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (shared_ptr <Pkcs5Kdf> pkcs5, keyDerivationFunctions)
|
||||
{
|
||||
if (kdf && (kdf->GetName() != pkcs5->GetName()))
|
||||
continue;
|
||||
|
||||
SecureBuffer headerKey (GetHeaderKeyDerivationSize (pkcs5));
|
||||
int derivationResult = pkcs5->DeriveKey (headerKey, password, pim, salt);
|
||||
if (derivationResult != 0)
|
||||
{
|
||||
@@ -116,50 +194,66 @@ namespace VeraCrypt
|
||||
throw ExternalException (SRC_POS, pkcs5->GetDerivationFailureMessage (derivationResult));
|
||||
}
|
||||
|
||||
foreach (shared_ptr <EncryptionMode> mode, encryptionModes)
|
||||
if (DecryptWithHeaderKey (encryptedData, pkcs5, headerKey, encryptionAlgorithms, encryptionModes))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VolumeHeader::DecryptWithHeaderKey (const ConstBufferPtr &encryptedData, shared_ptr <Pkcs5Kdf> pkcs5, const ConstBufferPtr &headerKey, const EncryptionAlgorithmList &encryptionAlgorithms, const EncryptionModeList &encryptionModes)
|
||||
{
|
||||
SecureBuffer header (EncryptedHeaderDataSize);
|
||||
|
||||
foreach (shared_ptr <EncryptionMode> mode, encryptionModes)
|
||||
{
|
||||
#ifdef WOLFCRYPT_BACKEND
|
||||
bool xtsMode = typeid (*mode) == typeid (EncryptionModeWolfCryptXTS);
|
||||
#else
|
||||
bool xtsMode = typeid (*mode) == typeid (EncryptionModeXTS);
|
||||
#endif
|
||||
|
||||
if (!xtsMode)
|
||||
{
|
||||
#ifdef WOLFCRYPT_BACKEND
|
||||
if (typeid (*mode) != typeid (EncryptionModeWolfCryptXTS))
|
||||
#else
|
||||
if (typeid (*mode) != typeid (EncryptionModeXTS))
|
||||
#endif
|
||||
mode->SetKey (headerKey.GetRange (0, mode->GetKeySize()));
|
||||
if (mode->GetKeySize() > headerKey.Size())
|
||||
continue;
|
||||
mode->SetKey (headerKey.GetRange (0, mode->GetKeySize()));
|
||||
}
|
||||
|
||||
foreach (shared_ptr <EncryptionAlgorithm> ea, encryptionAlgorithms)
|
||||
foreach (shared_ptr <EncryptionAlgorithm> ea, encryptionAlgorithms)
|
||||
{
|
||||
if (!ea->IsModeSupported (mode))
|
||||
continue;
|
||||
|
||||
size_t requiredHeaderKeySize = xtsMode ? ea->GetKeySize() * 2 : LegacyEncryptionModeKeyAreaSize + ea->GetKeySize();
|
||||
if (requiredHeaderKeySize > headerKey.Size())
|
||||
continue;
|
||||
|
||||
if (xtsMode)
|
||||
{
|
||||
if (!ea->IsModeSupported (mode))
|
||||
continue;
|
||||
ea->SetKey (headerKey.GetRange (0, ea->GetKeySize()));
|
||||
#ifdef WOLFCRYPT_BACKEND
|
||||
ea->SetKeyXTS (headerKey.GetRange (ea->GetKeySize(), ea->GetKeySize()));
|
||||
#endif
|
||||
|
||||
#ifndef WOLFCRYPT_BACKEND
|
||||
if (typeid (*mode) == typeid (EncryptionModeXTS))
|
||||
{
|
||||
ea->SetKey (headerKey.GetRange (0, ea->GetKeySize()));
|
||||
#else
|
||||
if (typeid (*mode) == typeid (EncryptionModeWolfCryptXTS))
|
||||
{
|
||||
ea->SetKey (headerKey.GetRange (0, ea->GetKeySize()));
|
||||
ea->SetKeyXTS (headerKey.GetRange (ea->GetKeySize(), ea->GetKeySize()));
|
||||
#endif
|
||||
mode = mode->GetNew();
|
||||
mode->SetKey (headerKey.GetRange (ea->GetKeySize(), ea->GetKeySize()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ea->SetKey (headerKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
|
||||
}
|
||||
|
||||
mode = mode->GetNew();
|
||||
mode->SetKey (headerKey.GetRange (ea->GetKeySize(), ea->GetKeySize()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ea->SetKey (headerKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
|
||||
}
|
||||
ea->SetMode (mode);
|
||||
|
||||
ea->SetMode (mode);
|
||||
header.CopyFrom (encryptedData.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize));
|
||||
ea->Decrypt (header);
|
||||
|
||||
header.CopyFrom (encryptedData.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize));
|
||||
ea->Decrypt (header);
|
||||
|
||||
if (Deserialize (header, ea, mode))
|
||||
{
|
||||
EA = ea;
|
||||
Pkcs5 = pkcs5;
|
||||
return true;
|
||||
}
|
||||
if (Deserialize (header, ea, mode))
|
||||
{
|
||||
EA = ea;
|
||||
Pkcs5 = pkcs5;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,6 +413,16 @@ namespace VeraCrypt
|
||||
Pkcs5 = newPkcs5Kdf;
|
||||
}
|
||||
|
||||
size_t VolumeHeader::GetHeaderKeyDerivationSize (shared_ptr <Pkcs5Kdf> kdf)
|
||||
{
|
||||
#ifndef VC_DCS_DISABLE_ARGON2
|
||||
if (kdf && kdf->IsArgon2())
|
||||
return ARGON2_HEADER_KEYDATA_SIZE;
|
||||
#endif
|
||||
|
||||
return GetLargestSerializedKeySize();
|
||||
}
|
||||
|
||||
size_t VolumeHeader::GetLargestSerializedKeySize ()
|
||||
{
|
||||
size_t largestKey = EncryptionAlgorithm::GetLargestKeySize (EncryptionAlgorithm::GetAvailableAlgorithms());
|
||||
|
||||
@@ -68,6 +68,7 @@ namespace VeraCrypt
|
||||
uint32 GetFlags () const { return Flags; }
|
||||
VolumeTime GetHeaderCreationTime () const { return HeaderCreationTime; }
|
||||
uint64 GetHiddenVolumeDataSize () const { return HiddenVolumeDataSize; }
|
||||
static size_t GetHeaderKeyDerivationSize (shared_ptr <Pkcs5Kdf> kdf);
|
||||
static size_t GetLargestSerializedKeySize ();
|
||||
shared_ptr <Pkcs5Kdf> GetPkcs5Kdf () const { return Pkcs5; }
|
||||
uint16 GetRequiredMinProgramVersion () const { return RequiredMinProgramVersion; }
|
||||
@@ -79,6 +80,7 @@ namespace VeraCrypt
|
||||
bool IsMasterKeyVulnerable () const { return XtsKeyVulnerable; }
|
||||
|
||||
protected:
|
||||
bool DecryptWithHeaderKey (const ConstBufferPtr &encryptedData, shared_ptr <Pkcs5Kdf> pkcs5, const ConstBufferPtr &headerKey, const EncryptionAlgorithmList &encryptionAlgorithms, const EncryptionModeList &encryptionModes);
|
||||
bool Deserialize (const ConstBufferPtr &header, shared_ptr <EncryptionAlgorithm> &ea, shared_ptr <EncryptionMode> &mode);
|
||||
template <typename T> T DeserializeEntry (const ConstBufferPtr &header, size_t &offset) const;
|
||||
template <typename T> T DeserializeEntryAt (const ConstBufferPtr &header, const size_t &offset) const;
|
||||
|
||||
Reference in New Issue
Block a user