Skip to content

Document that encrypted VM disks already work, no code needed - #7

Open
doccaz wants to merge 4 commits into
cloudbase:masterfrom
doccaz:encryption-investigation
Open

doccaz wants to merge 4 commits into
cloudbase:masterfrom
doccaz:encryption-investigation

Conversation

@doccaz

@doccaz doccaz commented Sep 19, 2026 •

Copy link
Copy Markdown

Summary

Investigated the "encrypted disks" backlog item by building a vCenter + Native Key Provider lab from the existing bare-ESXi host, encrypting a test VM/disk, and capturing native VDDK opening it with the SSL hook (docs/ssl_hook.md).

Found no extra key-provisioning calls in the wire capture, and proved via openvixdisklib itself (zero encryption-specific code) that a known byte pattern round-trips correctly through normal NFC read/write while the bytes on disk are genuine ciphertext at rest. ESXi's storage stack handles VM disk encryption entirely below the NFC layer whenever the serving host already holds the key.

Update: the one case this originally couldn't test — a host that doesn't already have the key cached — became testable once a second ESXi host existed (built for the related host-switch investigation, PR #9). Cold-relocated the encrypted VM (compute + disk) to that host and read its disk from there: it just worked, via both openvixdisklib and cross-checked native VDDK. vCenter pushes the key to the destination host automatically as part of any relocation — nothing for this project to implement. That was the last open question; encryption support needs no code at all, full stop.

Same treatment as the earlier NFC_DELTA_DISK finding (PR #5): documented as an "investigated, not needed" note rather than a new feature, plus a regression test against the lab's persistent encrypted VM (skips if not configured). Also wrote up the lab-building procedure itself (VCSA deploy, cluster + Native Key Provider setup, encrypting a VM) since none of it was straightforward and all of it is reusable.

  • docs/encryption.md — the investigation and evidence, including the cross-host resolution
  • docs/encryption_lab_setup.md — the lab methodology, gotcha by gotcha
  • docs/reverse_engineering_procedure.md — new "investigated, not needed" note, same pattern as NFC_DELTA_DISK
  • tests/integration/test_encryption.py — regression test

Test plan

  • Read/write round-trip against a real encrypted disk via openvixdisklib — matches, and the raw on-disk bytes are confirmed ciphertext
  • Native VDDK 8.0.2 opens/reads the same encrypted disk with no special handling required
  • Cold-relocated the encrypted VM to a host that never held its key — reads from there decrypt correctly (both clients)
  • tests/integration/test_encryption.py passing against the live lab

Note on PR sequencing

Stacked on top of the unmerged direct-ESXi/GetInfo/QueryAllocatedBlocks/CBT work (PRs #3–#6) — this branch's history includes their combined commit, so the diff shown here will shrink to just the two new commits (9e7670c, e762597) once those merge. No code changes at all in this PR, only docs + one new test file, so there's no actual dependency to worry about when reviewing.

Reverse-engineered and implemented against a live standalone ESXi 8.0.3
host (no vCenter), closing most of the gap versus the proprietary VDDK:

- Direct ESXi (no vCenter) connectivity: nfc_service() previously
  hardcoded the NfcService moref as "nfcService" (vCenter's name),
  which fails on bare ESXi (moref is "ha-nfc-service" there). Now
  resolved dynamically via RetrieveInternalContent, same as VDDK
  itself does. Also fixes connect_authd() for tickets that omit
  `host` (implicit on a direct-ESXi ticket).

- VixDiskLib_GetInfo: capacity and physical geometry come free from
  the OPEN_FILE reply (offsets already in the wire frame). biosGeo,
  adapterType, and uuid are fetched via DDB_GET, matching real VDDK's
  behavior and cost exactly.

- DDB_GET (VMDK descriptor lookups): generic key/value NFC message,
  values are ASCII text on the wire (not binary), matching how a VMDK
  descriptor's DDB section is stored.

- VixDiskLib_QueryAllocatedBlocks: allocated-block bitmap query.
  Verified against a live disk to exactly match native VDDK's output,
  including two non-obvious wire details: a field-order swap that's
  invisible in a zero-offset capture, and 4-byte bitmap padding that
  only shows up for small chunk counts.

- Changed Block Tracking: turned out to need no NFC work at all --
  VirtualMachine.QueryChangedDiskAreas is public VIM API. Added thin
  wrappers (enable_change_tracking / disk_change_id /
  query_changed_disk_areas) and documented real-world characteristics
  (extent granularity, wildcard changeId semantics) from live testing.

- Investigated NFC_DELTA_DISK: found it's an optional VMFS-only VDDK
  client optimization (per `strings` on libvixDiskLib.so), not a
  correctness requirement -- reading, writing, and querying allocated
  blocks on an actual snapshot delta file already work with the
  existing NFC_DISK-only implementation. Documented a real gotcha
  found along the way: querying allocated blocks on the same
  still-open handle a write just went through can see stale data.

Adds unit tests (bitmap decode/merge, DDB_GET wire format, CBT
dataclass conversion, validation errors) and integration tests
(GetInfo, QueryAllocatedBlocks, CBT full cycle, delta-disk read/write/
query) validated against a live ESXi 8.0.3 lab. Full protocol details
and the reverse-engineering process are in docs/nfc_auth.md,
docs/nfc_open.md, docs/nfc_read.md, docs/cbt.md, and
docs/reverse_engineering_procedure.md.
Investigated the "encrypted disks" backlog item by building a vCenter +
Native Key Provider lab from the existing bare-ESXi host, encrypting a
test VM/disk, and capturing native VDDK opening it with the SSL hook.

Found no extra key-provisioning calls in the wire capture, and proved
via openvixdisklib itself (zero encryption-specific code) that a known
byte pattern round-trips correctly through normal NFC read/write while
the bytes on disk are genuine ciphertext at rest. ESXi's storage stack
handles VM disk encryption entirely below the NFC layer whenever the
serving host already holds the key -- the only case a single-host lab
can exercise, and, per the VDDK binary's own strings, likely the only
case that needs no extra provisioning step at all.

Same treatment as the earlier NFC_DELTA_DISK finding: documented as an
"investigated, not needed" note rather than a new feature, plus a
regression test against the lab's persistent encrypted VM (skips if
not configured). Also wrote up the lab-building procedure itself
(VCSA deploy, cluster + Native Key Provider setup, encrypting a VM)
since none of it was straightforward and all of it is reusable.
@doccaz
doccaz marked this pull request as ready for review September 19, 2026 23:55
…tion

The one case the original encryption investigation couldn't test --
a host that doesn't already have an encrypted disk's key cached --
became testable once a second ESXi host existed (built for the
host-switch investigation). Cold-relocated the encrypted test VM
(compute and disk together) to that host, then read its disk from
there: it just worked, decrypting correctly, via both openvixdisklib
and cross-checked native VDDK.

vCenter pushes the key to the destination host automatically as part
of any relocation of an encrypted VM. There is nothing for
OpenVixDiskLib to implement -- the "host doesn't have the key yet"
case can't arise for a client reading through an already-completed
migration, since vCenter resolves it before the migration finishes.
@doccaz
doccaz marked this pull request as draft September 20, 2026 14:25
@doccaz
doccaz marked this pull request as ready for review September 20, 2026 14:54
Comment thread tests/integration/test_encryption.py Outdated
Comment thread tests/integration/test_encryption.py Outdated
"vcenter_host",
"vcenter_username",
"vcenter_password",
"encrypted_vm_moref",

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.

It would be nice if we could spin up an encrypted vm on the fly instead of requiring a pre-existing one.

Comment thread docs/encryption.md
@petrutlucian94

Copy link
Copy Markdown
Member

This will have to be rebased once the other PRs merge.

Comment thread docs/encryption_lab_setup.md Outdated
Reuse the standard vCenter keys from .test_config.yaml in the
encryption test, document the extra keys it needs, note that the san
and hotadd transports were not covered, and soften the lab wording.
@doccaz

doccaz commented Sep 23, 2026

Copy link
Copy Markdown
Author

Thanks for the review. I pushed changes for these:

  • .test_config.yaml keys: the test now uses the standard host, port, username, password and allow_untrusted keys. It only needs encrypted_vm_moref and encrypted_disk_path on top, and it skips without them. I documented those two in docs/encryption_lab_setup.md.
  • may be a standalone ESXi host: changed.
  • san transport: good question, and I hadn't tested it. I added a "Transports not covered" note to docs/encryption.md. hotadd probably behaves like NBD/NFC. On san, VDDK reads the LUNs and parses VMFS itself, so it bypasses the IOFilter layer that does the decryption. It would presumably see ciphertext, but that's unverified.
  • Creating an encrypted VM on the fly: I agree it would be better, but I couldn't automate it. Disk encryption needs an SPBM storage policy, and the scripted PBM call failed with a SecurityError on PbmQueryProfile despite what looked like a correct session cookie. Only the vSphere Client UI worked. I noted this in the test docstring. I can look again at pbm.version.version2/version11 or the vmware-api-session-id header if you'd like.

@petrutlucian94

Copy link
Copy Markdown
Member

Thanks for updating the PR. No worries about the encrypted VM test, I'd say it's ok for now to use an existing vm.

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