📄 pgpdisk.cpp
字号:
// InitPGPdiskFileHeader initializes a brand new PGPdisk file header.
DualErr
PGPdisk::InitPGPdiskFileHeader(
PGPdiskFileHeader *fileHeader,
PGPUInt64 blocksDisk,
PGPdiskEncryptionAlgorithm algorithm,
SecureString *passphrase,
PGPUInt8 drive)
{
DualErr derr;
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
pgpAssertAddrValid(passphrase, SecureString);
pgpAssert(algorithm != kInvalidEncryptionAlgorithm);
pgpAssert(blocksDisk > 0);
pgpAssert(blocksDisk < 0xFFFFFFFF); // header doesn't do 64-bit yet
// Initialize the default fields of the header.
pgpClearMemory(fileHeader, sizeof(PGPdiskFileHeader));
strncpy(fileHeader->headerInfo.headerMagic, kPGPdiskHeaderMagic, 4);
strncpy(fileHeader->headerInfo.headerType, kPGPdiskPrimaryHeaderType, 4);
fileHeader->headerInfo.headerSize = sizeof(PGPdiskFileHeader);
fileHeader->majorVersion = kPGPdiskPrimaryHeaderMajorVersion;
fileHeader->minorVersion = kPGPdiskPrimaryHeaderMinorVersion;
fileHeader->algorithm = algorithm;
fileHeader->numHeaderBlocks = kPGPdiskReservedHeaderBlocks;
fileHeader->numDataBlocks = (PGPUInt32) blocksDisk;
fileHeader->numFileBlocks = kPGPdiskReservedHeaderBlocks +
fileHeader->numDataBlocks + kPGPdiskAlternateHeaderBlocks;
fileHeader->drive = drive;
fileHeader->mountedFlag = FALSE;
fileHeader->uniqueSessionId = kInvalidSessionId;
// Initialize the header with a new session key.
derr = InitHeaderWithNewSessionKey(fileHeader, algorithm, passphrase);
if (derr.IsntError())
{
// Update the CRC.
UpdatePGPdiskFileHeaderCRC((PGPdiskFileHeaderInfo *) fileHeader);
}
return derr;
}
// FirstTimeEncryptDiskFile wipes the non-FAT blocks and encrypts all of the
// non-header blocks in a new, open PGPdisk.
DualErr
PGPdisk::FirstTimeEncryptDiskFile(
PGPdiskFileHeader *fileHeader,
SecureString *passphrase)
{
CASTKey *decryptedKey;
CipherContext *pContext = NULL;
DualErr derr;
PGPBoolean createdWriteBuffer = FALSE;
PGPUInt8 *dataBuf;
PGPUInt32 blocksBuf;
SecureMemory smDecryptedKey(sizeof(CASTKey));
SecureMemory smContext(sizeof(CipherContext));
pgpAssert(Opened());
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
pgpAssertAddrValid(passphrase, SecureString);
// Make sure we got our locked memory.
derr = smDecryptedKey.mInitErr;
if (derr.IsntError())
{
derr = smContext.mInitErr;
}
if (derr.IsntError())
{
// Initialize the pointers to our locked memory.
decryptedKey = (CASTKey *) smDecryptedKey.GetPtr();
pContext = new (smContext.GetPtr()) CipherContext; // <new.h>
// Decrypt the encrypted key.
derr = DecryptPassphraseKey(&fileHeader->masterPassphrase,
&fileHeader->salt, passphrase, decryptedKey);
}
if (derr.IsntError())
{
// Initialize the cipher context.
pContext->InitContext(fileHeader->algorithm, decryptedKey->keyBytes,
fileHeader->salt.saltBytes);
// Get the memory for our data buffer.
derr = CreateReasonableWriteBuffer(fileHeader->numDataBlocks,
&dataBuf, &blocksBuf);
createdWriteBuffer = derr.IsntError();
}
// Format the PGPdisk.
if (derr.IsntError() && !HasUserCanceled())
{
PGPUInt32 blocksThisTime, endBlock, startBlock;
PGPUInt32 totalWrites, writesDone, writesPerUpdate;
// Calculate the starting and ending blocks.
startBlock = fileHeader->numHeaderBlocks;
endBlock = startBlock + fileHeader->numDataBlocks;
// Calculate information used for progress bar updates.
totalWrites = (PGPUInt32)
CeilDiv(endBlock - startBlock, blocksBuf);
writesDone = 0;
writesPerUpdate = (PGPUInt32) CeilDiv(totalWrites, 100);
// Encrypt the PGPdisk.
for (PGPUInt32 i = startBlock; i < endBlock; i += blocksBuf)
{
blocksThisTime = min(blocksBuf, endBlock - i);
// Encrypt the blocks and output them.
if (derr.IsntError())
{
pgpClearMemory(dataBuf, blocksThisTime*kDefaultBlockSize);
pContext->CipherBlocks(i - fileHeader->numHeaderBlocks,
blocksThisTime, dataBuf, dataBuf, kCipherOp_Encrypt);
derr = File::Write(dataBuf, i*kDefaultBlockSize,
blocksThisTime*kDefaultBlockSize);
}
// Update the progress dialog.
if (derr.IsntError())
{
if (writesDone++ % writesPerUpdate == 0)
SetProgressBarPos(writesDone*100/totalWrites);
}
if (derr.IsError() || HasUserCanceled())
{
break;
}
}
}
// If the user cancelled the creation, fail but don't be noisy.
if (HasUserCanceled())
derr = DualErr(kPGDMinorError_FailSilently);
if (createdWriteBuffer)
FreeByteBuffer(dataBuf);
if (IsntNull(pContext))
pContext->~CipherContext();
return derr;
}
// FirstTimeWriteHeaderDiskFile clears the reserved headers blocks and writes
// out the header to the specified PGPdisk.
DualErr
PGPdisk::FirstTimeWriteHeaderDiskFile(PGPdiskFileHeader* fileHeader)
{
DualErr derr;
PGPUInt8 blanks[kDefaultBlockSize];
PGPUInt32 i;
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
pgpAssert(Opened());
pgpClearMemory(blanks, kDefaultBlockSize);
// Clear the main header blocks.
for (i = 0; i < fileHeader->numHeaderBlocks; i++)
{
derr = File::Write(blanks, i*kDefaultBlockSize,
kDefaultBlockSize);
if (derr.IsError())
break;
}
// Clear the alternate header blocks.
if (derr.IsntError())
{
PGPUInt32 altStart;
altStart = fileHeader->numHeaderBlocks + fileHeader->numDataBlocks;
for (i=0; i<kPGPdiskAlternateHeaderBlocks; i++)
{
derr = File::Write(blanks, (altStart+i)*kDefaultBlockSize,
kDefaultBlockSize);
if (derr.IsError())
break;
}
}
// Write out the header.
if (derr.IsntError())
{
derr = WritePGPdiskFileMainHeader(this, fileHeader);
}
return derr;
}
// GetOldSessionKey extracts the old session key from a PGPdisk.
DualErr
PGPdisk::GetOldSessionKey(
LPCSTR path,
PGPdiskFileHeader *fileHeader,
SecureString *passphrase,
CASTKey *oldSessionKey)
{
DualErr derr;
pgpAssertStrValid(path);
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
pgpAssertAddrValid(passphrase, SecureString);
pgpAssertAddrValid(oldSessionKey, CASTKey);
pgpAssert(Opened());
// Must close file first.
derr = Close();
if (derr.IsntError())
{
if (ArePGPdiskPassesWiped(path))
{
PGPBoolean gotPubKeyHdr = FALSE;
PGPdiskPublicKeyHeader *pubKeyHdr;
// Look for corresponding public key header.
derr = FindPublicPGPdiskKeyHeader(path, passphrase, &pubKeyHdr);
gotPubKeyHdr = derr.IsntError();
if (derr.IsntError())
{
// Get decrypted key.
derr = GetDecryptedKeyUsingPublicKey(passphrase, pubKeyHdr,
oldSessionKey);
}
if (gotPubKeyHdr)
FreePGPdiskFileHeader((PGPdiskFileHeaderInfo *) pubKeyHdr);
}
else
{
// Get old session key from master passphrase.
derr = DecryptPassphraseKey(GetPassphraseKeyPtr(fileHeader,
kMasterPassphraseIndex), &fileHeader->salt, passphrase,
oldSessionKey);
}
}
if (derr.IsntError())
{
derr = Open(path, kOF_MustExist);
}
return derr;
}
// ConvertBlocks converts the specified blocks in the PGPdisk to the new
// session key.
DualErr
PGPdisk::ConvertBlocks(
PGPdiskFileHeader *fileHeader,
PGPdiskCASTConvertInfo *pCCI,
const CASTKey *oldSessionKey,
const PassphraseSalt *oldSalt,
const CASTKey *newSessionKey,
const PassphraseSalt *newSalt,
PGPUInt32 startingBlock,
PGPUInt32 numBlocks)
{
CipherContext *pNewContext, *pOldContext;
DualErr derr;
PGPBoolean createdWriteBuffer = FALSE;
PGPUInt8 *dataBuf;
SecureMemory smNewContext(sizeof(CipherContext));
SecureMemory smOldContext(sizeof(CipherContext));
pNewContext = pOldContext = NULL;
pgpAssert(Opened());
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
pgpAssertAddrValid(pCCI, PGPdiskCASTConvertInfo);
pgpAssertAddrValid(oldSessionKey, CASTKey);
pgpAssertAddrValid(newSessionKey, CASTKey);
// Make sure we got our locked memory.
derr = smNewContext.mInitErr;
if (derr.IsntError())
{
derr = smOldContext.mInitErr;
}
if (derr.IsntError())
{
// Initialize the pointers to our locked memory.
pNewContext = new (smNewContext.GetPtr()) CipherContext;
pOldContext = new (smOldContext.GetPtr()) CipherContext;
// Initialize the cipher contexts.
pNewContext->InitContext(kCASTEncryptionAlgorithm,
newSessionKey->keyBytes, newSalt->saltBytes);
pOldContext->InitContext(kBrokenCASTEncryptionAlgorithm,
oldSessionKey->keyBytes, oldSalt->saltBytes);
// Get the memory for our data buffer.
derr = GetByteBuffer(kNumBlocksToConvertAtATime * kDefaultBlockSize,
&dataBuf);
createdWriteBuffer = derr.IsntError();
}
// Convert the blocks.
if (derr.IsntError() && !HasUserCanceled())
{
PGPUInt32 blocksBuf, blocksThisTime, endBlock, startBlock;
PGPUInt32 totalWrites, writesDone, writesPerUpdate;
blocksBuf = kNumBlocksToConvertAtATime;
// Calculate the starting and ending blocks.
startBlock = startingBlock;
endBlock = startBlock + numBlocks;
// Calculate information used for progress bar updates.
totalWrites = (PGPUInt32)
CeilDiv(endBlock - startBlock, blocksBuf);
writesDone = 0;
writesPerUpdate = (PGPUInt32) CeilDiv(totalWrites, 100);
// Encrypt the PGPdisk.
for (PGPUInt32 i = startBlock; i < endBlock; i += blocksBuf)
{
blocksThisTime = min(blocksBuf, endBlock - i);
// Read the blocks.
derr = File::Read(dataBuf, i*kDefaultBlockSize,
blocksThisTime*kDefaultBlockSize);
if (derr.IsntError())
{
// Decrypt the blocks.
pOldContext->CipherBlocks(i - fileHeader->numHeaderBlocks,
blocksThisTime, dataBuf, dataBuf, kCipherOp_Decrypt);
// Encrypt the blocks.
pNewContext->CipherBlocks(i - fileHeader->numHeaderBlocks,
blocksThisTime, dataBuf, dataBuf, kCipherOp_Encrypt);
// Write the blocks.
derr = File::Write(dataBuf, i*kDefaultBlockSize,
blocksThisTime*kDefaultBlockSize);
}
// Write the updated block counter.
if (derr.IsntError())
{
pCCI->lastConvertedBlock = i + blocksThisTime - 1;
derr = File::Write((PGPUInt8 *) pCCI, kOffsetToCCIStruct,
sizeof(PGPdiskCASTConvertInfo));
}
// Update the progress dialog.
if (derr.IsntError())
{
if (writesDone++ % writesPerUpdate == 0)
SetProgressBarPos(writesDone*100/totalWrites);
}
if (derr.IsError() || HasUserCanceled())
{
break;
}
}
}
// If the user cancelled the creation, fail but don't be noisy.
if (HasUserCanceled())
derr = DualErr(kPGDMinorError_FailSilently);
if (createdWriteBuffer)
FreeByteBuffer(dataBuf);
if (IsntNull(pOldContext))
pOldContext->~CipherContext();
if (IsntNull(pNewContext))
pNewContext->~CipherContext();
return derr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -