From d9486dd1c95e6e8952bb310a0eb0ac1222c90ca6 Mon Sep 17 00:00:00 2001 From: Damian Rickard Date: Tue, 7 Jul 2026 20:33:42 -0400 Subject: [PATCH] Use direct burn in BufferPtr::Erase and guard token keyfile data 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. --- src/Main/Forms/SecurityTokenKeyfilesDialog.cpp | 15 +++++++++++++-- src/Main/TextUserInterface.cpp | 15 +++++++++++++-- src/Platform/Buffer.h | 6 +++++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp b/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp index 84c30d65fe..c3bfd308a8 100644 --- a/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp +++ b/src/Main/Forms/SecurityTokenKeyfilesDialog.cpp @@ -104,10 +104,17 @@ namespace VeraCrypt wxBusyCursor busy; vector keyfileData; + finally_do_arg ( + vector *, &keyfileData, + { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); } + ); + keyfile->GetKeyfileData (keyfileData); + if (keyfileData.empty()) + throw InsufficientData (SRC_POS); + BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); - finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); File keyfile; keyfile.Open (*files.front(), File::CreateWrite); @@ -142,10 +149,14 @@ namespace VeraCrypt if (keyfile.Length() > 0) { vector keyfileData (keyfile.Length()); + finally_do_arg ( + vector *, &keyfileData, + { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); } + ); + BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); keyfile.ReadCompleteBuffer (keyfileDataBuf); - finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); NewSecurityTokenKeyfileDialog newKeyfileDialog (this, keyfilePath.ToBaseName()); diff --git a/src/Main/TextUserInterface.cpp b/src/Main/TextUserInterface.cpp index cd46b11207..08e53a2875 100644 --- a/src/Main/TextUserInterface.cpp +++ b/src/Main/TextUserInterface.cpp @@ -1269,10 +1269,17 @@ namespace VeraCrypt shared_ptr tokenKeyfile = Token::getTokenKeyfile(keyfilePath); vector keyfileData; + finally_do_arg ( + vector *, &keyfileData, + { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); } + ); + tokenKeyfile->GetKeyfileData (keyfileData); + if (keyfileData.empty()) + throw InsufficientData (SRC_POS); + BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); - finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); FilePath exportFilePath = AskFilePath(); @@ -1336,10 +1343,14 @@ namespace VeraCrypt if (keyfile.Length() > 0) { vector keyfileData (keyfile.Length()); + finally_do_arg ( + vector *, &keyfileData, + { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); } + ); + BufferPtr keyfileDataBuf (&keyfileData.front(), keyfileData.size()); keyfile.ReadCompleteBuffer (keyfileDataBuf); - finally_do_arg (BufferPtr, keyfileDataBuf, { finally_arg.Erase(); }); SecurityToken::CreateKeyfile (slotId, keyfileData, string (FilePath (keyfilePath).ToBaseName())); } diff --git a/src/Platform/Buffer.h b/src/Platform/Buffer.h index 5e5e989527..5d14d6a6b8 100644 --- a/src/Platform/Buffer.h +++ b/src/Platform/Buffer.h @@ -53,7 +53,11 @@ namespace VeraCrypt operator uint8 * () const { return DataPtr; } void CopyFrom (const ConstBufferPtr &bufferPtr) const; - void Erase () const { Zero(); } + void Erase () const + { + if (DataSize > 0) + burn (DataPtr, DataSize); + } uint8 *Get () const { return DataPtr; } BufferPtr GetRange (size_t offset, size_t size) const; void Set (uint8 *data, size_t size) { DataPtr = data; DataSize = size; }