Use direct burn in BufferPtr::Erase and guard token keyfile data#1816
Use direct burn in BufferPtr::Erase and guard token keyfile data#1816damianrickard wants to merge 1 commit into
Conversation
|
Thank you for looking into this. I can't merge this PR as-is. In particular, the statement that this is not on a bulk path is not correct. During non quick volume creation, For me, the right approach is to introduce a dedicated secure erasure API, e.g. So I agree with the goal, but not with changing |
| // buffer that is not read afterwards can be removed as a dead store, | ||
| // leaving secrets in memory. burn() is the same volatile-write wipe | ||
| // already used by Buffer::Erase(). This is not on the bulk I/O path. | ||
| burn (memory, size); |
There was a problem hiding this comment.
I don't think Memory::Zero should call burn globally. This function is a generic zero fill primitive and is used outside secret erasure contexts, including repeated large buffer paths such as non quick volume creation via outputBuffer.Zero in VolumeCreator.cpp. Please introduce a dedicated secure erasure API instead, use it from BufferPtr::Erase, and leave generic Zero as normal zero initialization.
ca467fa to
4539200
Compare
|
Thanks — that's a fair objection, and you're right that the "not on a bulk path" claim was wrong: I've reworked this along the lines you suggested. Going through the call sites case by case, this turned out to fix a real gap rather than just harden one: every Rebased onto current master. Builds clean (C++03 and C++11); |
|
Thanks for reworking the PR. First, I initially suggested introducing The affected sensitive call sites were changed to expand Reintroducing Please therefore:
Second, the review of the current callers exposed an exception handling gap in the token keyfile cleanup. In four token keyfile paths, the cleanup guard is installed only after the sensitive vector has been populated:
If either operation throws after allocating or partially filling the vector, the cleanup guard is never constructed. The vector is then released without wiping its contents. Please install the cleanup guard immediately after declaring or allocating the vector. The guard should reference the vector itself instead of capturing a BufferPtr containing its current address. For example: For the import paths, use the same pattern immediately after constructing the sized vector and before calling Referencing the vector ensures that the cleanup uses its current storage if the vector was reallocated. After a successful The cleanup guards for the password arrays are already installed before the sensitive operations and don't require changes. Finally, please update the PR title and description. They still describe changing Memory::Zero, while the revised implementation correctly leaves Memory::Zero unchanged. The commit message should also avoid claiming that every cleanup path is covered until the exception handling issue described above has been addressed. |
BufferPtr::Erase() previously delegated to Zero()/memset even though its current callers use it to wipe sensitive data. Expand burn() directly in the inline Erase implementation, matching VeraCrypt's established erasure design without adding an out-of-line wrapper. Install vector-referencing cleanup guards before token keyfile reads and fetches in the four GUI and text-mode import/export paths. This ensures partially populated data is wiped when an operation throws and avoids retaining a stale BufferPtr if the vector reallocates. Reject empty token exports before accessing vector::front(). Memory::Zero(), Buffer::Erase(), and the existing password guards remain unchanged.
4539200 to
d9486dd
Compare
|
Thanks for the detailed follow-up. I’ve amended the existing commit and rebased it onto current master.
Validation completed:
Could you please re-review when convenient? I’ve left the existing review thread unresolved for you. |
Problem
BufferPtr::Erase()currently delegates toZero(), which usesmemset(). Since sensitive buffers are not subsequently read, that wipe may be removed as a dead store.The four GUI and text-mode token import/export paths also install their cleanup guards only after
GetKeyfileData()orReadCompleteBuffer(). If either operation throws after allocating or partially populating the vector, its contents can be released without being wiped.Changes
burn()directly insideBufferPtr::Erase(), following VeraCrypt’s established direct-erasure design from commit885cc1d0.Memory::Zero()and the existing direct-burnimplementation ofBuffer::Erase()unchanged.vector::front().The existing password cleanup guards are already installed before their sensitive operations and remain unchanged.
Validation
VeraCrypt --text --test