📄 cpgpdiskheaders.cpp
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: CPGPdiskHeaders.cpp,v 1.20 2002/11/21 18:42:55 wjb Exp $
____________________________________________________________________________*/
#include "pgpClassesConfig.h"
#include "pgpBuild.h"
#include "CArray.h"
#include "CFile.h"
#include "CString.h"
#include "UMath.h"
#include "UString.h"
#include "pgpClientErrors.h"
#include "CCipherContext.h"
#include "CCRC32.h"
#include "UCommonStrings.h"
#include "CPGPGlobalRandomPool.h"
#include "CPGPKey.h"
#include "CPGPdiskContext.h"
#include "CPGPdiskHeaders.h"
#include "CPGPdiskUser.h"
#include "CPGPdiskUserSet.h"
#include "PGPdiskOldFormat.h"
_USING_PGP
_UNNAMED_BEGIN
// Types
// Align to 1.
#if PGP_WIN32
#pragma pack(push, 1)
#endif
struct OnDiskHeaderInfo
{
enum
{
kReservedHeaderBlocks = 4,
kMaxBlocksHeader = 128 // arbitrary
};
#if defined(_M_IX86)
enum
{
kHeaderMagic = 'dPGP', // backwards since little-endian
kMainType = 'NIAM',
kUserType = 'RESU',
kOldPubKeyType = 'YEKP',
};
#endif // _M_IX86
PGPUInt32 headerMagic; // Always OnDiskHeaderInfo::kHeaderMagic
PGPUInt32 headerType; // One of the HeaderType enums
PGPUInt32 headerSize; // Total size of this header, in bytes
PGPUInt32 headerCRC; // CRC of this header
PGPUInt64 nextHeaderOffset; // Offset to next header from file start
// 0 = no additional headers
PGPUInt32 reserved[2];
};
struct OnDiskMainHeader
{
enum
{
kMajorVersion = 6,
kMinorVersion = 0,
kCompatMajorVersion = 1,
kPreSubKeyMajorVersion = 5,
kMaxSizeRoot = 256,
};
OnDiskHeaderInfo hdrInfo;
PGPUInt8 majorVersion;
PGPUInt8 minorVersion;
PGPUInt16 reserved;
PGPUInt64 numFileBlocks; // Size of the file, in blocks
PGPUInt64 numHeaderBlocks; // Size of leading header data
PGPUInt64 numDataBlocks; // Size of encrypted data
PGPdiskEncryptionAlgorithm algorithm;
Crypto::PassphraseSalt salt;
PGPUInt32 isBeingReEncrypted : 1; // is disk being reencrypted?
PGPUInt32 isWiped : 1; // users wiped?
PGPUInt32 usesCustomTimeout : 1; // custom timeout?
PGPUInt32 unused : 29;
PGPUInt32 customTimeout; // custom unmount timeout
PGPUInt64 numBlocksReEncrypted; // number of blocks reencrypted
char defaultRoot[kMaxSizeRoot]; // Preferred mount point
};
struct OnDiskUserHeader
{
OnDiskHeaderInfo hdrInfo;
PGPUInt32 notExported : 1;
PGPUInt32 unused : 31;
PGPUInt32 exportedUserOffset;
PGPUInt32 exportedUserSize;
PGPUInt32 reserved[4];
// Exported PGPdisk user structure goes here...
};
// Restore alignment.
#if PGP_WIN32
#pragma pack(pop)
#endif
_UNNAMED_END
_PGP_BEGIN
// Class CPGPdiskHeader
class CPGPdiskHeader : public CListableObject<CPGPdiskHeader>
{
NOT_COPYABLE(CPGPdiskHeader);
public:
CPGPdiskHeader(const CPGPdiskContext *pContext);
virtual ~CPGPdiskHeader() { }
const CPGPdiskContext * Context() const {return mPContext;}
OnDiskHeaderInfo * GetAsHeaderInfo() const
{
return reinterpret_cast<OnDiskHeaderInfo *>(mHeaderBytes.Get());
}
PGPUInt32& HeaderMagic() const
{
return GetAsHeaderInfo()->headerMagic;
}
PGPUInt32& HeaderType() const
{
return GetAsHeaderInfo()->headerType;
}
PGPUInt32& HeaderSize() const
{
return GetAsHeaderInfo()->headerSize;
}
PGPUInt32& HeaderCRC() const
{
return GetAsHeaderInfo()->headerCRC;
}
PGPUInt64& NextHeaderOffset() const
{
return GetAsHeaderInfo()->nextHeaderOffset;
}
PGPBoolean IsMainType() const
{
return (HeaderType() == OnDiskHeaderInfo::kMainType);
}
PGPBoolean IsUserType() const
{
return (HeaderType() == OnDiskHeaderInfo::kUserType);
}
PGPBoolean IsOldPubKeyType() const
{
return (HeaderType() == OnDiskHeaderInfo::kOldPubKeyType);
}
void UpdateCRC()
{
HeaderCRC() = ComputeCRC();
}
virtual void ReadAtOffset(const CFile& diskFile, PGPUInt64 offset);
virtual void WriteAtOffset(CFile& diskFile, PGPUInt64 offset);
virtual void Assign(const CPGPdiskHeader *pHeader);
protected:
const CPGPdiskContext *mPContext;
CArray<PGPByte> mHeaderBytes;
PGPUInt32 ComputeCRC();
void ValidateHeaderSize();
virtual void CanonicalizeHeader();
};
// Class CPGPdiskMainHeader
class CPGPdiskMainHeader : public CPGPdiskHeader
{
public:
CPGPdiskMainHeader(const CPGPdiskContext *pContext);
~CPGPdiskMainHeader();
OnDiskMainHeader * GetAsMainHeader() const
{
return reinterpret_cast<OnDiskMainHeader *>(mHeaderBytes.Get());
}
PGPBoolean IsOldHeaderAvailable() const
{
return mIsOldHeaderAvailable;
}
const PGPdiskOldFormat::MainHeader * GetOldHeader() const
{
return mOldHeader;
}
PGPUInt8& MajorVersion() const
{
return GetAsMainHeader()->majorVersion;
}
PGPUInt8& MinorVersion() const
{
return GetAsMainHeader()->minorVersion;
}
PGPUInt64& NumFileBlocks() const
{
return GetAsMainHeader()->numFileBlocks;
}
PGPUInt64& NumHeaderBlocks() const
{
return GetAsMainHeader()->numHeaderBlocks;
}
PGPUInt64& NumDataBlocks() const
{
return GetAsMainHeader()->numDataBlocks;
}
PGPdiskEncryptionAlgorithm& Algorithm() const
{
return GetAsMainHeader()->algorithm;
}
Crypto::PassphraseSalt& Salt() const
{
return GetAsMainHeader()->salt;
}
PGPBoolean GetIsBeingReEncrypted() const
{
return GetAsMainHeader()->isBeingReEncrypted;
}
PGPBoolean GetIsWiped() const
{
return GetAsMainHeader()->isWiped;
}
PGPBoolean GetUsesCustomTimeout() const
{
return GetAsMainHeader()->usesCustomTimeout;
}
const char * DefaultRoot() const
{
return GetAsMainHeader()->defaultRoot;
}
PGPUInt32& CustomTimeout() const
{
return GetAsMainHeader()->customTimeout;
}
PGPUInt64& NumBlocksReEncrypted() const
{
return GetAsMainHeader()->numBlocksReEncrypted;
}
void SetIsBeingReEncrypted(PGPBoolean isBeingReEncrypted)
{
GetAsMainHeader()->isBeingReEncrypted = isBeingReEncrypted;
}
void SetIsWiped(PGPBoolean isWiped)
{
GetAsMainHeader()->isWiped = isWiped;
}
void SetUsesCustomTimeout(PGPBoolean usesCustom) const
{
GetAsMainHeader()->usesCustomTimeout = usesCustom;
}
void SetDefaultRoot(const char *defaultRoot)
{
pgpAssertStrValid(defaultRoot);
UString::SmartStringCopy(GetAsMainHeader()->defaultRoot,
defaultRoot, OnDiskMainHeader::kMaxSizeRoot);
}
void Create(PGPUInt64 headerBlocks, PGPUInt64 dataBlocks,
PGPdiskEncryptionAlgorithm algorithm,
const Crypto::PassphraseSalt& salt, const char *defaultRoot);
private:
PGPBoolean mIsOldHeaderAvailable;
PGPdiskOldFormat::MainHeader *mOldHeader;
void ConvertOldVersion();
void CanonicalizeHeader();
void CommonCreate(PGPUInt64 headerBlocks, PGPUInt64 dataBlocks,
PGPdiskEncryptionAlgorithm algorithm,
const Crypto::PassphraseSalt& salt, const char *defaultRoot);
};
// Class CPGPdiskUserHeader
class CPGPdiskUserHeader : public CPGPdiskHeader
{
public:
CPGPdiskUserHeader(const CPGPdiskContext *pContext);
~CPGPdiskUserHeader() { }
OnDiskUserHeader * GetAsUserHeader() const
{
return reinterpret_cast<OnDiskUserHeader *>(mHeaderBytes.Get());
}
PGPUInt32& ExportedUserOffset() const
{
return GetAsUserHeader()->exportedUserOffset;
}
PGPUInt32& ExportedUserSize() const
{
return GetAsUserHeader()->exportedUserSize;
}
PGPBoolean GetIsNotExported() const
{
return GetAsUserHeader()->notExported;
}
void SetIsNotExported(PGPBoolean isNotExported)
{
GetAsUserHeader()->notExported = isNotExported;
}
void GetUser(CPGPdiskUser& user);
void Create(const CPGPdiskUser& user);
void CreateFromOldKeyInfo(
const PGPdiskOldCrypto::PassphraseKeyInfo *pOldKeyInfo,
PGPBoolean isAdmin = FALSE);
private:
void ConvertFromOldPubKeyHeader();
void CanonicalizeHeader();
};
_PGP_END
// Class CPGPdiskHeader member functions
CPGPdiskHeader::CPGPdiskHeader(const CPGPdiskContext *pContext) :
mPContext(pContext)
{
pgpAssertAddrValid(pContext, CPGPdiskContext);
}
void
CPGPdiskHeader::ReadAtOffset(const CFile& diskFile, PGPUInt64 offset)
{
pgpAssert(diskFile.IsOpened());
// Read in at least one block.
pgpAssert(sizeof(OnDiskHeaderInfo) <= kPGPdiskBlockSize);
mHeaderBytes.Resize(kPGPdiskBlockSize);
diskFile.Read(mHeaderBytes.Get(), offset, kPGPdiskBlockSize);
// Validate size.
ValidateHeaderSize();
// Read in rest of header if necessary.
if (HeaderSize() > kPGPdiskBlockSize)
{
mHeaderBytes.Resize(HeaderSize());
diskFile.Read(mHeaderBytes.Get(), offset, HeaderSize());
}
// Make sure everything is kosher.
CanonicalizeHeader();
}
void
CPGPdiskHeader::WriteAtOffset(CFile& diskFile, PGPUInt64 offset)
{
pgpAssert(diskFile.IsOpened());
// Update header CRC.
UpdateCRC();
// Write it out.
diskFile.Write(mHeaderBytes.Get(), offset, HeaderSize());
// Clear bytes up to block boundary.
if (HeaderSize()%kPGPdiskBlockSize > 0)
{
CArray<PGPUInt8> blanks(kPGPdiskBlockSize);
blanks.Wipe();
diskFile.Write(blanks.Get(), offset + HeaderSize(),
kPGPdiskBlockSize - (HeaderSize()%kPGPdiskBlockSize));
}
}
void
CPGPdiskHeader::Assign(const CPGPdiskHeader *pHeader)
{
pgpAssertAddrValid(pHeader, CPGPdiskHeader);
mHeaderBytes.Resize(pHeader->HeaderSize());
pgpCopyMemory(pHeader->mHeaderBytes.Get(), mHeaderBytes.Get(),
pHeader->HeaderSize());
// Make sure everything is kosher.
CanonicalizeHeader();
}
PGPUInt32
CPGPdiskHeader::ComputeCRC()
{
CCRC32 theCrc;
// Always set CRC value to zero before computing.
PGPUInt32 oldCRC = HeaderCRC();
HeaderCRC() = 0;
theCrc.Init();
theCrc.Continue(reinterpret_cast<const PGPUInt32 *>(mHeaderBytes.Get()),
HeaderSize() / sizeof(PGPUInt32));
HeaderCRC() = oldCRC;
return theCrc.GetCRC();
}
void
CPGPdiskHeader::ValidateHeaderSize()
{
if ((HeaderSize() < sizeof(OnDiskHeaderInfo)) ||
(HeaderSize() > OnDiskHeaderInfo::kMaxBlocksHeader *
kPGPdiskBlockSize))
{
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
}
}
void
CPGPdiskHeader::CanonicalizeHeader()
{
if (HeaderMagic() != OnDiskHeaderInfo::kHeaderMagic)
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
if (HeaderCRC() != ComputeCRC())
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
ValidateHeaderSize();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -