📄 pgpdisklowlevelutils.cpp
字号:
// Assume always enough room to store main header in beginning.
if (derr.IsntError())
{
PGPBoolean usedUpReservedBlocks = FALSE;
PGPUInt32 blocksCurItem, nextBlock, remainingBlocks;
curItem = itemList;
nextBlock = 0;
remainingBlocks = mainHdr->numHeaderBlocks;
// Calculate new offsets for each header.
while (IsntNull(curItem))
{
blocksCurItem = (PGPUInt32) CeilDiv(curItem->hdr->headerSize,
kDefaultBlockSize);
nextItem = curItem->next;
// Any space left at beginning of file?
if (!usedUpReservedBlocks)
{
if (blocksCurItem <= remainingBlocks)
{
remainingBlocks -= blocksCurItem;
nextBlock += blocksCurItem;
// OK to put at current offset.
curItem->hdr->nextHeaderOffset = nextBlock *
kDefaultBlockSize;
}
else
{
nextBlock = blockAfterData + blocksCurItem;
usedUpReservedBlocks = TRUE;
// Exhausted bytes at beginning of file.
if (IsntNull(curItem->prev))
{
curItem->prev->hdr->nextHeaderOffset =
blockAfterData * kDefaultBlockSize;
}
curItem->hdr->nextHeaderOffset = nextBlock *
kDefaultBlockSize;
}
}
else
{
nextBlock += blocksCurItem;
// Already after end of file.
curItem->hdr->nextHeaderOffset =
nextBlock * kDefaultBlockSize;
}
if (IsNull(nextItem))
curItem->hdr->nextHeaderOffset = 0;
curItem = nextItem;
}
}
// Write out all the headers.
if (derr.IsntError())
{
PGPUInt64 curOffset;
curItem = itemList;
curOffset = 0;
while (derr.IsntError() && IsntNull(curItem))
{
derr = WritePGPdiskFileHeaderAtOffset(diskFile, curOffset,
curItem->hdr);
curOffset = curItem->hdr->nextHeaderOffset;
curItem = curItem->next;
}
}
// Restore main and alternate header.
if (derr.IsntError())
{
derr = diskFile->GetLength(&length);
}
if (derr.IsntError())
{
mainHdr->numFileBlocks = (PGPUInt32) (length/kDefaultBlockSize +
kPGPdiskAlternateHeaderBlocks);
derr = diskFile->SetLength(length + kPGPdiskAlternateHeaderBlocks *
kDefaultBlockSize);
}
if (derr.IsntError())
{
derr = WritePGPdiskFileMainHeader(diskFile, mainHdr);
}
return derr;
}
// ReadPGPdiskFilePrimaryHeader reads in and verifies the primary PGPdisk
// header.
DualErr
ReadPGPdiskFilePrimaryHeader(File *diskFile, PGPdiskFileHeader **fileHeader)
{
DualErr derr;
PGPBoolean readHeader = FALSE;
PGPUInt64 bytesFile;
pgpAssertAddrValid(diskFile, File);
pgpAssert(diskFile->Opened());
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader *);
derr = ReadPGPdiskFileHeaderAtOffset(diskFile, 0,
(PGPdiskFileHeaderInfo **) fileHeader);
readHeader = derr.IsntError();
if (derr.IsntError())
{
derr = diskFile->GetLength(&bytesFile);
}
if (derr.IsntError())
{
derr = VerifyPGPdiskFileMainHeader((* fileHeader), bytesFile);
}
if (derr.IsError())
{
if (readHeader)
FreePGPdiskFileHeader((PGPdiskFileHeaderInfo *) (* fileHeader));
}
return derr;
}
// WritePGPdiskFilePrimaryHeader verifies and writes out the primary PGPdisk
// file header to a PGPdisk file.
DualErr
WritePGPdiskFilePrimaryHeader(
File *diskFile,
const PGPdiskFileHeader *fileHeader)
{
DualErr derr;
PGPUInt64 bytesFile;
pgpAssertAddrValid(diskFile, File);
pgpAssert(diskFile->Opened());
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
derr = diskFile->GetLength(&bytesFile);
if (derr.IsntError())
{
derr = WritePGPdiskFileHeaderAtOffset(diskFile, 0,
(PGPdiskFileHeaderInfo *) fileHeader);
}
return derr;
}
// ReadPGPdiskFileAlternateHeader reads in and verifies the alternate PGPdisk
// header.
DualErr
ReadPGPdiskFileAlternateHeader(File *diskFile, PGPdiskFileHeader **fileHeader)
{
DualErr derr;
PGPBoolean readHeader = FALSE;
PGPUInt64 bytesFile;
pgpAssertAddrValid(diskFile, File);
pgpAssert(diskFile->Opened());
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader *);
derr = diskFile->GetLength(&bytesFile);
if (derr.IsntError())
{
derr = ReadPGPdiskFileHeaderAtOffset(diskFile,
bytesFile - kPGPdiskAlternateHeaderSize,
(PGPdiskFileHeaderInfo **) fileHeader);
readHeader = derr.IsntError();
}
if (derr.IsError())
{
if (readHeader)
FreePGPdiskFileHeader((PGPdiskFileHeaderInfo *) (* fileHeader));
}
return derr;
}
// WritePGPdiskFileAlternateHeader verifies and writes out the alternate
// PGPdisk file header to a PGPdisk file.
DualErr
WritePGPdiskFileAlternateHeader(
File *diskFile,
const PGPdiskFileHeader *fileHeader)
{
DualErr derr;
PGPUInt64 bytesFile;
pgpAssertAddrValid(diskFile, File);
pgpAssert(diskFile->Opened());
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
derr = diskFile->GetLength(&bytesFile);
if (derr.IsntError())
{
// Alternate header is ALWAYS 'kPGPdiskAlternateHeaderSize' bytes
// from the end of the file.
derr = WritePGPdiskFileHeaderAtOffset(diskFile,
bytesFile - kPGPdiskAlternateHeaderSize,
(PGPdiskFileHeaderInfo *) fileHeader);
}
return derr;
}
// VerifyPGPdiskFileMainHeader verifies certain fields of the given PGPdisk
// file header for a file of the given size.
DualErr
VerifyPGPdiskFileMainHeader(
const PGPdiskFileHeader *fileHeader,
PGPUInt64 bytesFile)
{
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
if (strncmp(fileHeader->headerInfo.headerMagic, kPGPdiskHeaderMagic, 4)
!= 0)
{
return DualErr(kPGDMinorError_BadHeaderMagic);
}
if (fileHeader->headerInfo.headerSize > sizeof(PGPdiskFileHeader))
{
return DualErr(kPGDMinorError_BadHeaderSize);
}
if (fileHeader->headerInfo.headerCRC !=
ComputePGPdiskFileHeaderCRC((PGPdiskFileHeaderInfo *) fileHeader))
{
return DualErr(kPGDMinorError_BadHeaderCRC);
}
if (strncmp(fileHeader->headerInfo.headerType,
kPGPdiskPrimaryHeaderType, 4) != 0)
{
return DualErr(kPGDMinorError_InvalidHeaderType);
}
if (fileHeader->majorVersion > kPGPdiskPrimaryHeaderMajorVersion)
{
return DualErr(kPGDMinorError_NewerHeaderVersion);
}
if ((fileHeader->algorithm != kBrokenCASTEncryptionAlgorithm) &&
(fileHeader->algorithm != kCASTEncryptionAlgorithm) &&
(fileHeader->algorithm != kCopyDataEncryptionAlgorithm))
{
return DualErr(kPGDMinorError_InvalidAlgorithm);
}
if ((PGPUInt64) fileHeader->numFileBlocks*kDefaultBlockSize != bytesFile)
{
return DualErr(kPGDMinorError_InvalidTotalFileSize);
}
if (fileHeader->numDataBlocks > fileHeader->numFileBlocks)
{
return DualErr(kPGDMinorError_InvalidFileDataSize);
}
if (fileHeader->numHeaderBlocks + fileHeader->numDataBlocks >
fileHeader->numFileBlocks)
{
return DualErr(kPGDMinorError_InvalidHeaderBlocks);
}
return DualErr::NoError;
}
// ComputePGPdiskFileHeaderCRC computes and returns a checksum over the given
// PGPdisk file header.
CRC32
ComputePGPdiskFileHeaderCRC(PGPdiskFileHeaderInfo *fileHeader)
{
CRC32 saveCRCValue;
CRC32 crc;
pgpAssertAddrValid(fileHeader, PGPdiskFileHeaderInfo);
// Always set CRC value to zero before computing.
saveCRCValue = fileHeader->headerCRC;
fileHeader->headerCRC = 0;
crc = ComputeCRC32((const PGPUInt32 *) fileHeader,
fileHeader->headerSize / sizeof(PGPUInt32));
fileHeader->headerCRC = saveCRCValue;
return crc;
}
// UpdatePGPdiskFileHeaderCRC stores the checksum of the PGPdisk file header
// in its 'headerCRC' member.
void
UpdatePGPdiskFileHeaderCRC(PGPdiskFileHeaderInfo *fileHeader)
{
pgpAssertAddrValid(fileHeader, PGPdiskFileHeaderInfo);
fileHeader->headerCRC = ComputePGPdiskFileHeaderCRC(fileHeader);
}
/////////////////////////////////////////
// Low-level passphrase utility functions
/////////////////////////////////////////
// FindMatchingPassphrase determines if the specified passphrase is
// legitimate for any of the keys.
DualErr
FindMatchingPassphrase(
const PGPdiskFileHeader *fileHeader,
SecureString *passphrase,
PGPUInt16 *index)
{
DualErr derr;
PGPBoolean foundKey = FALSE;
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
pgpAssertAddrValid(passphrase, SecureString);
pgpAssertAddrValid(index, PGPUInt16);
pgpAssert(kMasterPassphraseIndex == 0);
for (PGPUInt16 keyIndex = 0; keyIndex <= kMaxAlternatePassphrases;
++keyIndex)
{
const PassphraseKey *userInfo = NULL;
userInfo = GetPassphraseKeyPtr(fileHeader, keyIndex);
if (userInfo->inUse)
{
derr = VerifyPassphraseKey(userInfo, &fileHeader->salt,
passphrase);
foundKey = derr.IsntError();
if (foundKey)
{
(* index) = keyIndex;
break;
}
}
}
if (!foundKey)
derr = DualErr(kPGDMinorError_IncorrectPassphrase);
return derr;
}
// GetPassphraseKeyPtr returns a pointer to the PassphraseKey corresponding to
// the index.
const PassphraseKey *
GetPassphraseKeyPtr(
const PGPdiskFileHeader *fileHeader,
PGPUInt16 whichPassphrase)
{
const PassphraseKey *userInfo = NULL;
// 0 being master, 1...kMaxAlternatePassphrases alternates.
pgpAssert(whichPassphrase <= kMaxAlternatePassphrases);
if (whichPassphrase == kMasterPassphraseIndex)
userInfo = &fileHeader->masterPassphrase;
else
userInfo = &fileHeader->otherPassphrases[whichPassphrase-1];
return userInfo;
}
// VerifyPassphraseKey verifies that the specified passphrase unlocks the
// specified key.
DualErr
VerifyPassphraseKey(
const PassphraseKey *userInfo,
const PassphraseSalt *salt,
SecureString *passphrase)
{
DualErr derr;
CASTKey *decryptedKey;
SecureMemory smDecryptedKey(sizeof(CASTKey));
pgpAssertAddrValid(userInfo, PassphraseKey);
pgpAssertAddrValid(passphrase, SecureString);
pgpAssertAddrValid(salt, PassphraseSalt);
pgpAssert(userInfo->inUse);
// Did we get our locked memory?
derr = smDecryptedKey.mInitErr;
if (derr.IsntError())
{
// Set the locked memory pointer.
decryptedKey = (CASTKey *) smDecryptedKey.GetPtr();
// Attempt to decypt the key
derr = DecryptPassphraseKey(userInfo, salt, passphrase,
decryptedKey);
}
return derr;
}
// VerifyFileHeaderPassphrase verifies that a passphrase is valid for the
// specified passphrase index in the specified header.
DualErr
VerifyFileHeaderPassphrase(
const PGPdiskFileHeader *fileHeader,
SecureString *passphrase,
PGPUInt16 whichKey)
{
DualErr derr;
const PassphraseKey *userInfo;
pgpAssertAddrValid(fileHeader, PGPdiskFileHeader);
pgpAssertAddrValid(passphrase, SecureString);
userInfo = GetPassphraseKeyPtr(fileHeader, whichKey);
if (!userInfo->inUse)
derr = DualErr(kPGDMinorError_IncorrectPassphrase);
if (derr.IsntError())
{
derr = VerifyPassphraseKey(userInfo, &fileHeader->salt, passphrase);
}
return derr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -