📄 cpgpdiskheaders.cpp
字号:
pgpAssert(HeadersRead());
pgpAssert(!IsBeingReEncrypted());
pgpAssert(diskFile.IsOpened());
pgpAssertStrValid(adminPassphrase);
// Get set of users on disk.
CPGPdiskUserSet userSet;
ExportUserSet(userSet);
// Find current admin user and copy it.
CPGPdiskUserIter userIter(&userSet);
CPGPdiskUser oldAdmin(*userIter.FindAdminUser());
// Create new session user and salt from random data.
CCipherContext newCipher(newAlgorithm);
GenerateNewKeyAndSalt(newCipher);
Crypto::PassphraseSalt newSalt;
newCipher.GetSalt(newSalt);
// Convert all users to the new session key.
userIter.Rewind();
while (TRUE)
{
CPGPdiskUser *pUser = userIter.Next();
if (IsNull(pUser))
break;
PGPBoolean removeUser = FALSE;
if (pUser->IsAdminUser())
{
// New admin gets converted whether symmetric or not.
pUser->ChangeCipher(newCipher, adminPassphrase);
}
else if (pUser->HasSymmetricKey())
{
// Non-admin symmetrics are hopeless, no passphrase.
removeUser = TRUE;
}
else
{
// We have a non-admin public key user, attempt a conversion.
try
{
pUser->ChangeCipher(newCipher, adminPassphrase);
}
catch (CComboError&)
{
if (pUser->IsLocked())
THROW_PGPERROR(kPGPClientError_DiskReEncryptWithBadADK);
removeUser = TRUE;
}
}
if (removeUser)
userSet.Remove(*pUser);
}
// Import the converted keys.
ImportUserSet(userSet);
// Re-create old admin user header.
auto_ptr<CPGPdiskUserHeader> pOldAdmin(
new CPGPdiskUserHeader(Context()));
pOldAdmin->Create(oldAdmin);
pOldAdmin->SetIsNotExported(TRUE);
// Create new main header.
auto_ptr<CPGPdiskMainHeader> pNewMain(
new CPGPdiskMainHeader(Context()));
pNewMain->Create(MainHeader()->NumHeaderBlocks(),
MainHeader()->NumDataBlocks(), newAlgorithm, newSalt,
MainHeader()->DefaultRoot());
// Add old admin user header and new main header.
mHeaders.InsertAfter(MainHeader(), pOldAdmin.release());
mHeaders.AddHead(pNewMain.release());
// Mark disk as being reencrypted.
MainHeader()->SetIsBeingReEncrypted(TRUE);
WriteHeaders(diskFile);
diskFile.Flush();
}
void
CPGPdiskHeaders::GetReEncryptionInfo(
const char *adminPassphrase,
CCipherContext& oldCipher,
CCipherContext& newCipher,
PGPUInt64& numBlocksReEncrypted) const
{
pgpAssert(HeadersRead());
pgpAssert(IsBeingReEncrypted());
pgpAssertStrValid(adminPassphrase);
pgpAssert(!oldCipher.IsInitialized());
pgpAssert(!newCipher.IsInitialized());
CPGPdiskMainHeader *pOldMain = reinterpret_cast<CPGPdiskMainHeader *>(
mHeaders.Next(MainHeader()));
CPGPdiskUserHeader *pOldAdmin = reinterpret_cast<CPGPdiskUserHeader *>(
mHeaders.Next(pOldMain));
// Get old admin user.
CPGPdiskUser oldAdminUser(Context());
pOldAdmin->GetUser(oldAdminUser);
// Get old cipher context.
// This is just conventional and the zero ok. -wjb
oldAdminUser.EnableCiphering(adminPassphrase, 0, pOldMain->Algorithm(),
pOldMain->Salt());
oldAdminUser.GetCipherContext(oldCipher);
// Get new admin user.
CPGPdiskUserSet userSet;
ExportUserSet(userSet);
CPGPdiskUserIter userIter(&userSet);
CPGPdiskUser *pNewAdminUser = userIter.FindAdminUser();
pgpAssertAddrValid(pNewAdminUser, CPGPdiskUser);
// Get new cipher context.
// This is just conventional and the zero ok. -wjb
pNewAdminUser->EnableCiphering(adminPassphrase, 0,
MainHeader()->Algorithm(), MainHeader()->Salt());
pNewAdminUser->GetCipherContext(newCipher);
// Get next block to reencrypt.
numBlocksReEncrypted = MainHeader()->NumBlocksReEncrypted();
}
void
CPGPdiskHeaders::WriteReEncryptionProgress(
CFile& diskFile,
PGPUInt64 numBlocksReEncrypted)
{
pgpAssert(HeadersRead());
pgpAssert(IsBeingReEncrypted());
pgpAssert(diskFile.IsOpened());
MainHeader()->NumBlocksReEncrypted() = numBlocksReEncrypted;
WriteHeaders(diskFile);
diskFile.Flush();
}
void
CPGPdiskHeaders::FinishReEncryption(CFile& diskFile)
{
pgpAssert(HeadersRead());
pgpAssert(IsBeingReEncrypted());
pgpAssert(diskFile.IsOpened());
// Remove old main and admin user headers.
CPGPdiskMainHeader *pOldMain = reinterpret_cast<CPGPdiskMainHeader *>(
mHeaders.Next(MainHeader()));
CPGPdiskUserHeader *pOldAdmin = reinterpret_cast<CPGPdiskUserHeader *>(
mHeaders.Next(pOldMain));
mHeaders.Remove(pOldMain);
mHeaders.Remove(pOldAdmin);
delete pOldMain;
delete pOldAdmin;
// Update new main header.
MainHeader()->SetIsBeingReEncrypted(FALSE);
WriteHeaders(diskFile);
diskFile.Flush();
}
void
CPGPdiskHeaders::ReadHeaders(
const CPGPdiskContext *pContext,
const CFile& diskFile)
{
pgpAssertAddrValid(pContext, CPGPdiskContext);
pgpAssert(diskFile.IsOpened());
mPContext = pContext;
ClearHeaders();
// Read in main header.
auto_ptr<CPGPdiskMainHeader> pMainHeader(
new CPGPdiskMainHeader(pContext));
pMainHeader->ReadAtOffset(diskFile, 0);
mHeaders.AddTail(pMainHeader.release());
// If this is an older PGPdisk, create symmetric user headers from main.
if (pMainHeader->IsOldHeaderAvailable())
CreateHeadersFromOldMainHeader(pMainHeader->GetOldHeader());
// Read in the remaining PGPdisk headers.
try
{
PGPUInt64 curOffset = MainHeader()->NextHeaderOffset();
while (curOffset != 0)
{
CPGPdiskHeader genericHeader(pContext);
// Read in current header.
genericHeader.ReadAtOffset(diskFile, curOffset);
// Generate and add header object of appropriate type.
CopyAndAddTypedHeader(&genericHeader);
// Determine offset of next header.
curOffset = genericHeader.NextHeaderOffset();
}
}
catch (CComboError&) { }
mHeadersRead = TRUE;
}
void
CPGPdiskHeaders::WriteHeaders(CFile& diskFile)
{
pgpAssert(HeadersRead());
pgpAssert(diskFile.IsOpened());
PGPUInt64 blockAfterData = MainHeader()->NumHeaderBlocks() +
MainHeader()->NumDataBlocks();
PGPUInt64 byteAfterData = blockAfterData * kPGPdiskBlockSize;
// Set file size to max we will need BEFORE beginning the writes. Headers
// after the first go at the END of the file.
CPGPdiskHeader *pHeader = mHeaders.Next(MainHeader());
PGPUInt32 blocksTail = 0;
while (IsntNull(pHeader))
{
blocksTail += UMath::CeilDiv<PGPUInt32>(pHeader->HeaderSize(),
kPGPdiskBlockSize);
pHeader = mHeaders.Next(pHeader);
}
diskFile.SetLength(byteAfterData + blocksTail * kPGPdiskBlockSize);
// Update file size in main header.
MainHeader()->NumFileBlocks() = MainHeader()->NumHeaderBlocks() +
MainHeader()->NumDataBlocks() + blocksTail;
// Wipe reserved header blocks.
CArray<PGPUInt8> blanks(kPGPdiskBlockSize);
blanks.Wipe();
for (PGPUInt32 i = 0; i < MainHeader()->NumHeaderBlocks(); i++)
{
diskFile.Write(blanks.Get(), i * kPGPdiskBlockSize,
kPGPdiskBlockSize);
}
// Calculate new offsets and write out all headers.
MainHeader()->NextHeaderOffset() = byteAfterData;
MainHeader()->WriteAtOffset(diskFile, 0);
pHeader = mHeaders.Next(MainHeader());
while (IsntNull(pHeader))
{
PGPUInt64 offset = mHeaders.Prev(pHeader)->NextHeaderOffset();
PGPUInt64 nextOffset = offset + UMath::RoundUpToMultiple<
PGPUInt32>(pHeader->HeaderSize(), kPGPdiskBlockSize);
if (IsNull(mHeaders.Next(pHeader)))
pHeader->NextHeaderOffset() = 0;
else
pHeader->NextHeaderOffset() = nextOffset;
pHeader->WriteAtOffset(diskFile, offset);
pHeader = mHeaders.Next(pHeader);
}
}
void
CPGPdiskHeaders::ClearHeaders()
{
mHeaders.EmptyWithDelete();
mHeadersRead = FALSE;
}
void
CPGPdiskHeaders::CreateHeaders(
const CPGPdiskContext *pContext,
const CFile& diskFile,
PGPUInt64 blocksDisk,
PGPdiskEncryptionAlgorithm algorithm,
const char *adminPassphrase,
const char *userName,
const char *defaultRoot,
CCipherContext& cipher)
{
ClearHeaders();
CreateHeadersCommon(pContext, diskFile, blocksDisk, algorithm,
adminPassphrase, userName, NULL, defaultRoot, cipher);
}
void
CPGPdiskHeaders::CreateHeaders(
const CPGPdiskContext *pContext,
const CFile& diskFile,
PGPUInt64 blocksDisk,
PGPdiskEncryptionAlgorithm algorithm,
const CPGPKey& pubKey,
const char *defaultRoot,
CCipherContext& cipher)
{
ClearHeaders();
CreateHeadersCommon(pContext, diskFile, blocksDisk, algorithm, NULL,
NULL, &pubKey, defaultRoot, cipher);
}
void
CPGPdiskHeaders::NukeAllUserHeaders()
{
CPGPdiskHeader *pHeader = MainHeader();
while (IsntNull(pHeader))
{
CPGPdiskHeader *pNextHeader = mHeaders.Next(pHeader);
if (pHeader->IsUserType())
{
mHeaders.Remove(pHeader);
delete pHeader;
}
pHeader = pNextHeader;
}
}
void
CPGPdiskHeaders::CopyAndAddTypedHeader(const CPGPdiskHeader *pHeader)
{
pgpAssertAddrValid(pHeader, CPGPdiskHeader);
// Allocate new header object according to type.
auto_ptr<CPGPdiskHeader> pNewHeader;
if (pHeader->IsMainType())
{
pNewHeader = auto_ptr<CPGPdiskHeader>(
new CPGPdiskMainHeader(Context()));
}
else if ((pHeader->IsUserType() || pHeader->IsOldPubKeyType()))
{
pNewHeader = auto_ptr<CPGPdiskHeader>(
new CPGPdiskUserHeader(Context()));
}
else
{
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
}
pNewHeader->Assign(pHeader);
// Add the new header to the header list.
mHeaders.AddTail(pNewHeader.release());
}
void
CPGPdiskHeaders::CreateHeadersFromOldMainHeader(
const PGPdiskOldFormat::MainHeader *pOldHeader)
{
pgpAssertAddrValid(pOldHeader, PGPdiskOldFormat::MainHeader);
// For each passphrase, add a new user header.
for (PGPUInt32 i = 0;
i <= PGPdiskOldFormat::MainHeader::kMaxAlternatePassphrases;
i++)
{
const PGPdiskOldCrypto::PassphraseKeyInfo *pUserInfo =
&pOldHeader->passphrases[i];
if (pUserInfo->inUse)
{
auto_ptr<CPGPdiskUserHeader> pNewHeader(
new CPGPdiskUserHeader(Context()));
PGPBoolean isAdmin = (i == 0);
pNewHeader->CreateFromOldKeyInfo(pUserInfo, isAdmin);
mHeaders.AddTail(pNewHeader.release());
}
}
}
void
CPGPdiskHeaders::GenerateNewKeyAndSalt(CCipherContext& cipher) const
{
pgpAssert(cipher.IsInitialized());
CPGPGlobalRandomPool randomPool(Context()->PGPContext());
CSecureArray<PGPUInt8> keyData(cipher.GetNeededRandomDataSize());
CSecureArray<PGPUInt8> mungeData(cipher.GetNeededRandomDataSize());
Crypto::PassphraseSalt salt;
randomPool.GetRandomBytes(keyData.Get(), keyData.Size());
randomPool.GetRandomBytes(salt.bytes, sizeof(salt.bytes));
randomPool.GetRandomBytes(mungeData.Get(), mungeData.Size());
cipher.GenerateNewSymmetricKey(keyData.Get(), mungeData.Get(),
keyData.Size(), salt);
}
void
CPGPdiskHeaders::CreateHeadersCommon(
const CPGPdiskContext *pContext,
const CFile& diskFile,
PGPUInt64 blocksDisk,
PGPdiskEncryptionAlgorithm algorithm,
const char *adminPass,
const char *userName,
const CPGPKey *pPubKey,
const char *defaultRoot,
CCipherContext& cipher)
{
pgpAssertAddrValid(pContext, CPGPdiskContext);
pgpAssert(diskFile.IsOpened());
pgpAssertStrValid(defaultRoot);
mPContext = pContext;
// Create new session user and salt from random data.
if (!cipher.IsInitialized())
cipher.Init(algorithm);
Crypto::PassphraseSalt salt;
GenerateNewKeyAndSalt(cipher);
cipher.GetSalt(salt);
// Create main header.
auto_ptr<CPGPdiskMainHeader> pMainHeader(
new CPGPdiskMainHeader(Context()));
pMainHeader->Create(OnDiskHeaderInfo::kReservedHeaderBlocks, blocksDisk,
algorithm, salt, defaultRoot);
// Create admin user header.
CPGPdiskUser user(Context());
if (IsntNull(pPubKey))
user.Create(cipher, *pPubKey);
else
user.Create(cipher, userName, adminPass);
user.SetIsAdminUser(TRUE);
auto_ptr<CPGPdiskUserHeader> pAdminUserHeader(
new CPGPdiskUserHeader(Context()));
pAdminUserHeader->Create(user);
// Add the headers to the disk
mHeaders.AddHead(pAdminUserHeader.release());
mHeaders.AddHead(pMainHeader.release());
if(PGPclEnterprise())
{
// Create ADK header if we must.
if (Context()->IsTherePGPdiskADK())
{
CPGPKey adkKey;
Context()->GetPGPdiskADKPubKey(adkKey);
user.Create(cipher, adkKey, FALSE, TRUE);
auto_ptr<CPGPdiskUserHeader> pADKeyHeader(
new CPGPdiskUserHeader(Context()));
pADKeyHeader->Create(user);
mHeaders.AddTail(pADKeyHeader.release());
}
}
mHeadersRead = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -