Skip to content

Tests: read known data from the test volumes without mounting - #1907

Merged
idrassi merged 1 commit into
veracrypt:masterfrom
flatstik:volume-read
Oct 11, 2026
Merged

idrassi merged 1 commit into
veracrypt:masterfrom
flatstik:volume-read

Conversation

@flatstik

@flatstik flatstik commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to the suggestion in #1905: a test that reads known volume data through Volume::ReadSectors, without mounting, so it can run on other architectures too.

The Linux workflow already checks the content of the Tests/*.hc volumes, but by mounting them, which needs root, FUSE and the installed package, so it only runs on x86_64. This recovers the same data through the volume layer instead; the mount checks stay, as they cover the integration with the operating system.

  • Tests/volume_read_test.cpp opens a volume read-only and reads its data area with Volume::ReadSectors: in one call; as multi-sector ranges at nonzero offsets with odd sector counts; again with the encryption thread pool running (whole area and the same ranges); and one sector at a time. Every read must match the first. If the pool does not start (fewer than two processors), that part is reported as skipped, or fails with --require-thread-pool. CPU features are detected as in the application, so the accelerated cipher code is used where available. The character set is taken from the environment (LC_CTYPE) so paths with non-ASCII characters work; if that locale is unavailable, the test continues in the C locale and says so.

  • Tests/test_volume_read.py builds it against Volume.a and Platform.a of a finished standard Linux build (matching the libstdc++ ABI of the archives; supported configurations are documented in the script) and checks the plaintext of every Tests/test.*.hc volume:

    • a FAT boot sector;
    • DUMMY.TXT with the content Dummy, at the cluster given by the root directory;
    • a known SHA-256 digest of the whole data area.

    Without --fixture, a volume without a digest (or a digest without a volume) is an error, so a new fixture can't be left out. For a cross build, set CXX and NM to the cross tools; the program then runs through qemu-user.

  • build-linux.yml runs it after the .deb build, which leaves the archives of the console build in src.

  • build-linux-big-endian.yml runs it in the build job, where the archives are available: test.sha512.hc only in the automatic check, all five volumes in the full run, on s390x and amd64.

python3 Tests/test_volume_read.py --build-dir src [--require-thread-pool] [--fixture test.sha512.hc]

Testing (on my fork, with the workflow triggers changed to run on push):

@idrassi idrassi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for adding this. I'm in favor of the approach, especially keeping the digest of the complete data area. It caught corruption outside DUMMY.TXT in my checks.

Now that #1905 has landed, I would include the big endian workflow integration here. As submitted, this only adds execution to the native Ubuntu workflow. The helper should run in the build job while Volume.a and Platform.a are available; the later jobs receive only the executable.

The linked s390x run is encouraging, but this step took about 123 seconds there, compared with about 12 seconds in the native jobs. To keep the automatic check short, I would use --fixture test.sha512.hc for ordinary runs and check all five fixtures during the full run.

Successful payload reads currently cover AES and Kuznyechik. A fixture using a cascade would be a useful later addition. The existing mount checks should stay, since they exercise the integration with the operating system that direct calls to the volume library don't cover.

Comment thread Tests/volume_read_test.cpp
Comment thread Tests/volume_read_test.cpp
Comment thread Tests/volume_read_test.cpp Outdated
Comment thread Tests/test_volume_read.py
Comment thread Tests/test_volume_read.py
The Linux workflow checks the content of the Tests/*.hc volumes by
mounting them, which needs root, FUSE and the installed package, and so
only runs on x86_64. Add a test that recovers the same data through the
volume layer instead, so it also runs on other architectures, e.g. on the
big-endian cross build under qemu-user.

Tests/volume_read_test.cpp opens a volume read-only and reads its data
area with Volume::ReadSectors: in one call, as multi-sector ranges at
nonzero offsets with odd sector counts, again with the encryption thread
pool running, and one sector at a time; every read must match the first.
CPU features are detected as in the application, and the character set
is taken from the environment (LC_CTYPE) so that paths with non-ASCII
characters work; if that locale is unavailable, the test continues in the
C locale and says so.

Tests/test_volume_read.py builds it against Volume.a and Platform.a of a
finished standard Linux build (CXX and NM can be set for a cross build)
and checks the plaintext of every Tests/test.*.hc volume: the FAT boot
sector, DUMMY.TXT with the content "Dummy" at the cluster given by the
root directory, and a known SHA-256 digest of the whole data area. A
volume without a digest, or a digest without a volume, is an error.

It runs in the Linux workflow after the .deb build and in the build job
of the big-endian workflow (test.sha512.hc only in the automatic check,
all volumes in the full run), and requires the thread pool there.

Signed-off-by: Ville Takio <ville+git@takio.fi>
@flatstik

Copy link
Copy Markdown
Contributor Author

@idrassi Thanks for the thorough review. Everything is addressed in f64e6e9 (rebased on master after #1905). I also replied to each inline comment.

  • Big-endian workflow: the step now runs in the build job, where Volume.a and Platform.a are available. The automatic check uses --fixture test.sha512.hc, and the full run checks all five volumes on s390x and amd64. On my fork, the automatic s390x check took about 2 min for the one volume (run). The full run is here and the native Linux workflow here. All three require the thread pool.
  • Mount checks: they are unchanged. I added a sentence to the description saying why they stay.
  • Cascade fixture: agreed, that would be a good addition. I'd do it in a separate PR, since it adds a new binary volume and a digest.

@idrassi idrassi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the update. Looks good to me now.

@idrassi
idrassi merged commit df2e9dc into veracrypt:master Oct 11, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants