📄 pgpdisk.cpp
字号:
}
MessageBeep(MB_OK);
return derr;
}
// ConvertPGPdisk attempts to re-encrypt a broken CAST PGPdisk using the
// correct implementation of CAST.
DualErr
PGPdisk::ConvertPGPdisk(LPCSTR path, SecureString *passphrase)
{
DualErr derr;
CASTKey *newSessionKey;
PGPBoolean conversionRestarting, readHeader;
PGPdiskCASTConvertInfo CCI;
PGPdiskFileHeader *fileHeader;
SecureMemory smFileHeader(sizeof(PGPdiskFileHeader));
SecureMemory smNewSessionKey(sizeof(CASTKey));
conversionRestarting = readHeader = FALSE;
pgpAssertStrValid(path);
pgpAssertAddrValid(passphrase, SecureString);
// Did we get our locked memory?
derr = smFileHeader.mInitErr;
if (derr.IsntError())
{
derr = smNewSessionKey.mInitErr;
}
if (derr.IsntError())
{
// Set up secure pointers.
fileHeader = (PGPdiskFileHeader *) smFileHeader.GetPtr();
newSessionKey = (CASTKey *) smNewSessionKey.GetPtr();
// Open the PGPdisk.
derr = Open(path, kOF_MustExist);
}
// Read in main header.
if (derr.IsntError())
{
derr = ReadPGPdiskFileMainHeader(this, &fileHeader);
readHeader = derr.IsntError();
}
if (derr.IsntError())
{
// Are we restarting an already begun conversion?
conversionRestarting = (fileHeader->majorVersion ==
kPGPdiskConvertInProgressMajorVersion);
if (conversionRestarting)
{
// Read CCI struct.
derr = File::Read((PGPUInt8 *) &CCI, kOffsetToCCIStruct,
sizeof(CCI));
// Verify the stored conversion information.
if (derr.IsntError())
{
if (strncmp(CCI.convertInfoMagic, kPGPdiskBadCASTInfoMagic,
4) != 0)
{
derr = DualErr(kPGDMinorError_BadHeaderMagic);
}
}
// Retrieve the new session key.
if (derr.IsntError())
{
derr = DecryptPassphraseKey(GetPassphraseKeyPtr(fileHeader,
kMasterPassphraseIndex), &fileHeader->salt, passphrase,
newSessionKey);
}
}
else
{
// Prepare the main header for conversion.
fileHeader->majorVersion =
kPGPdiskConvertInProgressMajorVersion;
// Clear alternate passphrases.
pgpClearMemory(fileHeader->otherPassphrases,
sizeof(fileHeader->otherPassphrases));
// Prepare conversion info structure.
strncpy(CCI.convertInfoMagic, kPGPdiskBadCASTInfoMagic, 4);
CCI.lastConvertedBlock = fileHeader->numHeaderBlocks - 1;
CCI.oldSalt = fileHeader->salt;
// Retrieve and save the old session key.
derr = GetOldSessionKey(path, fileHeader, passphrase,
&CCI.oldSessionKey);
// Put a new session key in the header.
if (derr.IsntError())
{
derr = InitHeaderWithNewSessionKey(fileHeader,
kCASTEncryptionAlgorithm, passphrase);
}
// Retrieve the new session key from the header.
if (derr.IsntError())
{
derr = DecryptPassphraseKey(GetPassphraseKeyPtr(fileHeader,
kMasterPassphraseIndex), &fileHeader->salt, passphrase,
newSessionKey);
}
// Update main header.
if (derr.IsntError())
{
derr = WritePGPdiskFileMainHeader(this, fileHeader);
}
if (derr.IsntError())
{
// Remove other headers (non-fatal).
NukeAllNonADKHeaders(this, newSessionKey);
// Write out CCI.
derr = File::Write((PGPUInt8 *) &CCI, kOffsetToCCIStruct,
sizeof(CCI));
}
// Read in main header again.
if (derr.IsntError())
{
FreePGPdiskFileHeader((PGPdiskFileHeaderInfo *) fileHeader);
derr = ReadPGPdiskFileMainHeader(this, &fileHeader);
readHeader = derr.IsntError();
}
}
}
// Convert all non-converted blocks.
if (derr.IsntError())
{
PGPUInt32 numBlocks;
numBlocks = fileHeader->numDataBlocks -
(CCI.lastConvertedBlock - fileHeader->numHeaderBlocks + 1);
derr = ConvertBlocks(fileHeader, &CCI, &CCI.oldSessionKey,
&CCI.oldSalt, newSessionKey, &fileHeader->salt,
CCI.lastConvertedBlock + 1, numBlocks);
}
// Mark the PGPdisk as finished with the conversion process.
if (derr.IsntError())
{
fileHeader->majorVersion = kPGPdiskPrimaryHeaderMajorVersion;
fileHeader->minorVersion = kPGPdiskPrimaryHeaderMinorVersion;
fileHeader->algorithm = kCASTEncryptionAlgorithm;
derr = WritePGPdiskFileMainHeader(this, fileHeader);
}
if (derr.IsntError())
{
MessageBeep(MB_OK);
}
if (readHeader)
FreePGPdiskFileHeader((PGPdiskFileHeaderInfo *) fileHeader);
if (Opened())
Close();
return derr;
}
// HighLevelFormatPGPdisk displays the format dialog. Failing that, it
// formats using our own algorithm.
DualErr
PGPdisk::HighLevelFormatPGPdisk()
{
DualErr derr;
pgpAssert(Mounted());
// Display the format dialog.
derr = App->ShowWindowsFormatDialog(GetDrive());
// If failed, warn user and format using our own algorithm if we can.
if (derr.IsError())
{
ReportError(kPGDMajorError_WindowsFormatFailed, derr);
derr = Format();
// Set the volume label.
if (derr.IsntError())
{
SetVolumeLabel(kPGPdiskDefaultVolLabel);
}
}
return derr;
}
// SetProgressBarInfo is called to specify the window handle of a progress
// bar slider control to be used during disk creation, and also to specify
// a pointer to a shared boolean that will be polled to determine if the user
// has canceled the operation.
void
PGPdisk::SetProgressBarInfo(HWND hWnd, PGPBoolean *pCancelFlag)
{
pgpAssertAddrValid(pCancelFlag, PGPBoolean);
mProgressBarHwnd = hWnd;
mPCancelFlag = pCancelFlag;
SetProgressBarRange(0, 100);
SetProgressBarPos(0);
}
/////////////////////////////////////////
// Class PGPdisk private member functions
/////////////////////////////////////////
// HasUserCanceled checks the shared cancel variable to determine if the user
// has canceled the request.
PGPBoolean
PGPdisk::HasUserCanceled()
{
if (mProgressBarHwnd && mPCancelFlag)
{
pgpAssertAddrValid(mPCancelFlag, PGPBoolean);
return (* mPCancelFlag);
}
else
{
return FALSE;
}
}
// SetProgressBarPos sets the position of the disk creation progress bar.
void
PGPdisk::SetProgressBarPos(PGPUInt32 nPos)
{
if (mProgressBarHwnd)
PostMessage(mProgressBarHwnd, PBM_SETPOS, nPos, 0);
}
// SetProgressBarRange sets the range of the disk creation progress bar.
void
PGPdisk::SetProgressBarRange(PGPUInt32 nMin, PGPUInt32 nMax)
{
if (mProgressBarHwnd)
{
PostMessage(mProgressBarHwnd, PBM_SETRANGE, 0,
MAKELPARAM(nMin, nMax));
}
}
// IsNTFSPGPdisk checks if the PGPdisk is NTFS formatted.
PGPBoolean
PGPdisk::IsPGPdiskNTFS(LPCSTR path, CipherContext *pContext)
{
DualErr derr;
PGPBoolean isNTFS = FALSE;
PGPUInt8 *bootBlock;
pgpAssertStrValid(path);
pgpAssertAddrValid(pContext, CipherContext);
try
{
bootBlock = new PGPUInt8[kDefaultBlockSize];
// Open the PGPdisk.
derr = Open(path, kOF_MustExist | kOF_ReadOnly);
// Read on the boot block.
if (derr.IsntError())
{
derr = File::Read(bootBlock,
kPGPdiskReservedHeaderBlocks*kDefaultBlockSize,
kDefaultBlockSize);
}
if (derr.IsntError())
{
// Decrypt it.
pContext->CipherBlocks(0, 1, bootBlock, bootBlock,
kCipherOp_Decrypt);
// Is it NTFS?
isNTFS = (strncmp((LPCSTR) &bootBlock[3], "NTFS", 4) == 0);
}
// Close the PGPdisk.
if (Opened())
Close();
delete[] bootBlock;
}
catch (CMemoryException *ex)
{
derr = DualErr(kPGDMinorError_OutOfMemory);
ex->Delete();
if (Opened())
Close();
}
return isNTFS;
}
// InitHeaderWithNewSessionKey initializes the header with a new session
// key generated from the specified master passphrase and random data.
DualErr
PGPdisk::InitHeaderWithNewSessionKey(
PGPdiskFileHeader *fileHeader,
PGPdiskEncryptionAlgorithm algorithm,
SecureString *passphrase)
{
DualErr derr;
EncryptedCASTKey *key;
ExpandedCASTKey *expandedKey;
PGPUInt8 *secureBuf;
PGPUInt32 i, index;
SecureMemory smKey(sizeof(EncryptedCASTKey));
SecureMemory smExpandedKey(sizeof(ExpandedCASTKey));
SecureMemory smSecureBuf(kMaxPassphraseLength);
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
pgpAssertAddrValid(passphrase, SecureString);
// Make sure we got our locked memory.
derr = smKey.mInitErr;
if (derr.IsntError())
{
derr = smExpandedKey.mInitErr;
}
if (derr.IsntError())
{
derr = smSecureBuf.mInitErr;
}
if (derr.IsntError())
{
// Initialize the pointers to our locked memory.
key = (EncryptedCASTKey *) smKey.GetPtr();
expandedKey = (ExpandedCASTKey *) smExpandedKey.GetPtr();
secureBuf = (PGPUInt8 *) smSecureBuf.GetPtr();
// Initialize the salt with random data.
PGPContextGetRandomBytes(GetGlobalPGPContext(),
fileHeader->salt.saltBytes, sizeof(fileHeader->salt));
// Initialize the master passphrase with random data.
PGPContextGetRandomBytes(GetGlobalPGPContext(),
fileHeader->masterPassphrase.encryptedKey.keyBytes,
sizeof(fileHeader->masterPassphrase.encryptedKey));
// Hash, salt, and schedule the passphrase. Ask for the unexpanded
// key since we will need it later.
derr = HashSaltAndSchedule(passphrase, expandedKey,
&fileHeader->salt, &fileHeader->masterPassphrase.hashReps, key);
}
if (derr.IsntError())
{
// Encrypt the random key twice
for (i = 0; i < 2; i++)
{
CAST5encrypt(
&fileHeader->masterPassphrase.encryptedKey.keyBytes[0],
&fileHeader->masterPassphrase.encryptedKey.keyBytes[0],
expandedKey->keyDWords);
CAST5encrypt(
&fileHeader->masterPassphrase.encryptedKey.keyBytes[8],
&fileHeader->masterPassphrase.encryptedKey.keyBytes[8],
expandedKey->keyDWords);
}
// Encrypt the key itself for checkbytes purposes.
CAST5encrypt(key->keyBytes, key->keyBytes, expandedKey->keyDWords);
for (index = 0;
index < sizeof(fileHeader->masterPassphrase.checkBytes);
index++)
{
fileHeader->masterPassphrase.checkBytes.theBytes[index] =
key->keyBytes[index];
}
// Must mark as in use.
fileHeader->masterPassphrase.inUse = TRUE;
}
return derr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -