📄 cpgpdiskdiskimp.cpp
字号:
const char *path,
const CPGPdiskUser& diskUser,
const char *root,
PGPBoolean readOnly)
{
if (!diskUser.IsCipheringEnabled())
THROW_PGPERROR(kPGPError_BadParams);
// Get cipher context of user.
CCipherContext cipher;
diskUser.GetCipherContext(cipher);
Mount(pContext, path, cipher, root, readOnly || diskUser.IsReadOnly());
}
void
CPGPdiskDiskImp::Mount(
const CPGPdiskContext *pContext,
const char *path,
const CCipherContext& cipher,
const char *root,
PGPBoolean readOnly)
{
pgpAssertAddrValid(pContext, CPGPdiskContext);
pgpAssertStrValid(path);
pgpAssertStrValid(root);
if (IsMounted() || IsOpened())
THROW_PGPERROR(kPGPError_FeatureNotAvailable);
// Open the PGPdisk file.
PGPUInt32 openFlags = CFile::kNoFlags;
if (readOnly)
openFlags |= CFile::kReadOnlyFlag;
mDiskFile.Open(path, openFlags);
try
{
// Read in list of headers.
mHeaders.ReadHeaders(pContext, mDiskFile);
if (IsBeingReEncrypted())
THROW_PGPERROR(kPGPClientError_DiskDiskIsBeingReEncrypted);
// Perform filesystem compatibility checks (forcing RO if needed).
CheckFilesystemCompatibility(cipher, readOnly);
// Save some information.
PGPUInt64 numHeaderBlocks = mHeaders.NumHeaderBlocks();
PGPUInt64 numDataBlocks = mHeaders.NumDataBlocks();
// Close the PGPdisk file in preparation for mounting.
if (!readOnly)
{
mHeaders.SetDefaultRoot(root);
mHeaders.WriteHeaders(mDiskFile);
}
mDiskFile.Close();
// Get exported key data in locked memory.
CArray<PGPUInt8> exportedContext(cipher.GetSizeForExport());
cipher.Export(exportedContext.Get(), exportedContext.Size());
// Perform the mount.
CEngineSubsystems::DriverComm().Mount(path, root,
cipher.Algorithm(), exportedContext.Get(),
exportedContext.Size(), numHeaderBlocks, numDataBlocks,
mDeviceName, readOnly);
// set timeout
try
{
if (UsesCustomTimeout())
{
CEngineSubsystems::DriverComm().SetTimeout(root,
CustomTimeout());
}
else
{
PGPBoolean autoUnmount = pContext->PGPclPrefs().
GetBoolean(kPGPPrefDiskUnmountOnInactivity);
PGPUInt32 unmountTimeout = pContext->PGPclPrefs().
GetNumber(kPGPPrefDiskAutoUnmountTimeout);
if (autoUnmount)
{
CEngineSubsystems::DriverComm().SetTimeout(root,
unmountTimeout);
}
}
}
catch (CComboError&) {}
mPContext = pContext;
mIsReadOnly = readOnly;
mPath = path;
mRoot = root;
mDiskState = kDiskStateMounted;
}
catch (CComboError&)
{
if (IsOpened())
Close();
throw;
}
}
void
CPGPdiskDiskImp::Unmount(PGPBoolean isForced)
{
if (!IsMounted())
THROW_PGPERROR(kPGPError_FeatureNotAvailable);
if (IsLockedForFormat() || IsLockedForIO())
UnlockVolume();
// Perform the unmount.
CString savedRoot(Root());
CEngineSubsystems::DriverComm().Unmount(Root(), isForced);
// Clear headers.
mHeaders.ClearHeaders();
mPContext = NULL;
mPath.Empty();
mRoot.Empty();
mDiskState = kDiskStateNone;
}
void
CPGPdiskDiskImp::Create(
const CPGPdiskContext *pContext,
const char *path,
PGPUInt64 blocksDisk,
PGPdiskEncryptionAlgorithm algorithm,
const char *adminPassphrase,
const char *userName,
const char *defaultRoot,
NewDiskStatusFuncType statusFunc,
void *userValue)
{
if (IsMounted() || IsOpened())
THROW_PGPERROR(kPGPError_FeatureNotAvailable);
CreateCommon(pContext, path, blocksDisk, algorithm, adminPassphrase,
userName, NULL, defaultRoot, statusFunc, userValue);
}
void
CPGPdiskDiskImp::Create(
const CPGPdiskContext *pContext,
const char *path,
PGPUInt64 blocksDisk,
PGPdiskEncryptionAlgorithm algorithm,
const CPGPKey& pubKey,
const char *defaultRoot,
NewDiskStatusFuncType statusFunc,
void *userValue)
{
if (IsMounted() || IsOpened())
THROW_PGPERROR(kPGPError_FeatureNotAvailable);
CreateCommon(pContext, path, blocksDisk, algorithm, NULL, NULL, &pubKey,
defaultRoot, statusFunc, userValue);
}
void
CPGPdiskDiskImp::EncryptNewPGPdiskFile(
const CCipherContext& cipher,
NewDiskStatusFuncType statusFunc,
void *userValue)
{
pgpAssert(!IsMounted());
pgpAssert(!IsOpened());
pgpAssert(mDiskFile.IsOpened());
pgpAssert(cipher.IsKeyAttached());
// Get the memory for our data buffer.
CArray<PGPUInt8> dataBuf(kBlocksPerWrite * kPGPdiskBlockSize);
// Calculate the starting and ending blocks.
PGPUInt64 startBlock = mHeaders.NumHeaderBlocks();
PGPUInt64 endBlock = startBlock + mHeaders.NumDataBlocks();
// Calculate information used for progress updates.
PGPUInt32 totalWrites = static_cast<PGPUInt32>(
UMath::CeilDiv<PGPUInt64>(endBlock - startBlock, kBlocksPerWrite));
PGPUInt32 writesDone = 0;
PGPUInt32 writesPerUpdate = static_cast<PGPUInt32>(
UMath::CeilDiv<PGPUInt64>(totalWrites, 100));
// Encrypt the PGPdisk.
for (PGPUInt64 i = startBlock; i < endBlock; i += kBlocksPerWrite)
{
PGPUInt32 blocksThisTime = static_cast<PGPUInt32>(
pgpMin(kBlocksPerWrite, endBlock - i));
dataBuf.Wipe();
// Encrypt the blocks and output them.
cipher.EncryptCFB(i - startBlock, blocksThisTime, dataBuf.Get(),
dataBuf.Get());
mDiskFile.Write(dataBuf.Get(), i * kPGPdiskBlockSize,
blocksThisTime * kPGPdiskBlockSize);
// Call the progress function.
PGPBoolean continueCreate = TRUE;
if (writesDone++ % writesPerUpdate == 0)
{
continueCreate = statusFunc(FALSE, writesDone*100/totalWrites,
userValue);
}
if (!continueCreate)
THROW_PGPERROR(kPGPError_UserAbort);
}
statusFunc(FALSE, 100, userValue);
}
void
CPGPdiskDiskImp::CreateCommon(
const CPGPdiskContext *pContext,
const char *path,
PGPUInt64 blocksDisk,
PGPdiskEncryptionAlgorithm algorithm,
const char *adminPass,
const char *userName,
const CPGPKey *pPubKey,
const char *defaultRoot,
NewDiskStatusFuncType statusFunc,
void *userValue)
{
pgpAssertAddrValid(pContext, CPGPdiskContext);
pgpAssert(blocksDisk > 0);
pgpAssertStrValid(defaultRoot);
pgpAssertAddrValid(statusFunc, NewDiskStatusFuncType);
if (IsMounted() || IsOpened())
THROW_PGPERROR(kPGPError_FeatureNotAvailable);
mPContext = pContext;
// Private key of public key must be present and usable
if (IsntNull(pPubKey))
{
pgpAssertAddrValid(pPubKey, CPGPKey);
if (!pPubKey->GetBooleanProp(kPGPKeyProperty_CanDecrypt))
THROW_PGPERROR(kPGPClientError_BadDiskPassphrase);
}
try
{
mDiskFile.Open(path, CFile::kCreateIfFlag);
mDiskFile.SetLength(0);
// It's important we don't write out the headers until we're done
// encrypting all the new disk - else we wait ages for NTFS to zero
// out the new disk file when we write the admin user header to the
// end of the disk.
CCipherContext cipher;
if (IsntNull(pPubKey))
{
mHeaders.CreateHeaders(Context(), mDiskFile, blocksDisk,
algorithm, *pPubKey, defaultRoot, cipher);
}
else
{
mHeaders.CreateHeaders(Context(), mDiskFile, blocksDisk,
algorithm, adminPass, userName, defaultRoot, cipher);
}
mDiskFile.SetLength(mHeaders.NumFileBlocks() * kPGPdiskBlockSize);
EncryptNewPGPdiskFile(cipher, statusFunc, userValue);
mHeaders.WriteHeaders(mDiskFile);
mPContext = pContext;
mIsReadOnly = FALSE;
mPath = path;
mRoot.Empty();
mDiskFile.Close();
// Mount the disk.
/* PGPBoolean oldBrowsePref;
try
{
// gets around a spurious Win2k warning dialog
oldBrowsePref = mPContext->PGPclPrefs().GetBoolean(
kPGPPrefDiskBrowseAfterMount);
mPContext->PGPclPrefs().SetBoolean(kPGPPrefDiskBrowseAfterMount,
FALSE);
}
catch (CComboError&) { }*/
Mount(pContext, path, cipher, defaultRoot, FALSE);
/* try
{
mPContext->PGPclPrefs().SetBoolean(kPGPPrefDiskBrowseAfterMount,
oldBrowsePref);
}
catch (CComboError&) { }*/
}
catch (CComboError&)
{
mHeaders.ClearHeaders();
if (mDiskFile.IsOpened())
mDiskFile.Close();
// work around warn on delete
CString temp(path);
temp += "not";
CFile deleter;
deleter.Move(path, temp);
deleter.Delete(temp);
throw;
}
}
void
CPGPdiskDiskImp::ReEncryptBlocks(
const CCipherContext& oldCipher,
const CCipherContext& newCipher,
ReEncryptDiskStatusFuncType statusFunc,
void *userValue,
PGPUInt64 numBlocksReEncrypted)
{
pgpAssert(IsOpened());
pgpAssert(oldCipher.IsInitialized());
pgpAssert(newCipher.IsInitialized());
pgpAssertAddrValid(statusFunc, ReEncryptDiskStatusFuncType);
// Get the memory for our data buffer.
CArray<PGPUInt8> dataBuf(kBlocksPerWrite * kPGPdiskBlockSize);
// Calculate the starting and ending blocks.
PGPUInt64 firstBlock = mHeaders.NumHeaderBlocks();
PGPUInt64 startBlock = firstBlock + numBlocksReEncrypted;
PGPUInt64 endBlock = firstBlock +mHeaders.NumDataBlocks();
// Calculate information used for progress updates.
PGPUInt32 totalWrites = static_cast<PGPUInt32>(
UMath::CeilDiv<PGPUInt64>(mHeaders.NumDataBlocks(),
kBlocksPerWrite));
PGPUInt32 writesDone = static_cast<PGPUInt32>(
(totalWrites * numBlocksReEncrypted) / mHeaders.NumDataBlocks());
PGPUInt32 writesPerUpdate = UMath::CeilDiv<PGPUInt32>(totalWrites,
100);
// Re-encrypt the PGPdisk.
for (PGPUInt64 i = startBlock; i < endBlock; i += kBlocksPerWrite)
{
PGPUInt32 blocksThisTime = static_cast<PGPUInt32>(
pgpMin(kBlocksPerWrite, endBlock - i));
dataBuf.Wipe();
// Read in the old blocks.
mDiskFile.Read(dataBuf.Get(), i * kPGPdiskBlockSize,
blocksThisTime * kPGPdiskBlockSize);
// Decrypt the blocks using the old algorithm.
oldCipher.DecryptCFB(i - firstBlock, blocksThisTime, dataBuf.Get(),
dataBuf.Get());
// Encrypt the blocks using the new algorithm.
newCipher.EncryptCFB(i - firstBlock, blocksThisTime, dataBuf.Get(),
dataBuf.Get());
// Write out the newly ReEncrypted blocks.
mDiskFile.Write(dataBuf.Get(), i * kPGPdiskBlockSize,
blocksThisTime * kPGPdiskBlockSize);
// Write out now the # of the last ReEncrypted block.
numBlocksReEncrypted += blocksThisTime;
mHeaders.WriteReEncryptionProgress(mDiskFile, numBlocksReEncrypted);
// Call the progress function.
PGPBoolean continueReEncrypt = TRUE;
if (writesDone++ % writesPerUpdate == 0)
{
continueReEncrypt = statusFunc(writesDone*100/totalWrites,
userValue);
}
if (!continueReEncrypt)
THROW_PGPERROR(kPGPError_UserAbort);
}
statusFunc(100, userValue);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -