📄 pgpdiskpublickeyutils.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
// PGPdiskPublicKeyUtils.cpp
//
// Utility functions for working with public keys and PGPdisks.
//////////////////////////////////////////////////////////////////////////////
// $Id: PGPdiskPublicKeyUtils.cpp,v 1.5 1999/02/26 04:09:59 nryan Exp $
// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.
#if defined(PGPDISK_MFC)
#include "StdAfx.h"
#include <new.h>
#elif defined(PGPDISK_95DRIVER)
#include <vtoolscp.h>
#include "PlacementNew.h"
#elif defined(PGPDISK_NTDRIVER)
#include <vdw.h>
#else
#error Define PGPDISK_MFC, PGPDISK_95DRIVER, or PGPDISK_NTDRIVER.
#endif // PGPDISK_MFC
#include "Required.h"
#include "PGPclx.h"
#include "pflPrefs.h"
#include "pflPrefTypes.h"
#include "pgpAdminPrefs.h"
#include "pgpErrors.h"
#include "pgpPublicKey.h"
#include "pgpUtilities.h"
#include "GlobalPGPContext.h"
#include "PGPdiskHighLevelUtils.h"
#include "PGPdiskLowLevelUtils.h"
#include "PGPdiskPublicKeyUtils.h"
#include "SecureMemory.h"
#include "UtilityFunctions.h"
#include "File.h"
////////////
// Constants
////////////
static LPCSTR kPGPdiskPassesWipedId = "WIPED";
///////////////////////////////
// Public key utility functions
///////////////////////////////
// DoesPGPdiskHavePublicKey returns TRUE if the specified PGPdisk has a
// public key passphrase, FALSE otherwise.
PGPBoolean
DoesPGPdiskHavePublicKey(LPCSTR path)
{
DualErr derr;
File diskFile;
PGPBoolean gotItemList, hasPublicKey;
PGPdiskFileHeaderItem *curItem, *itemList;
gotItemList = hasPublicKey = FALSE;
pgpAssertStrValid(path);
// Open the PGPdisk.
derr = diskFile.Open(path, kOF_MustExist | kOF_ReadOnly);
// Get list of headers.
if (derr.IsntError())
{
derr = GetHeaderItemList(&diskFile, &itemList);
gotItemList = derr.IsntError();
}
// Look for a public key header.
if (derr.IsntError())
{
curItem = itemList;
while (IsntNull(curItem))
{
if (IsPublicKeyHeader(curItem->hdr))
{
hasPublicKey = TRUE;
break;
}
curItem = curItem->next;
}
}
if (gotItemList)
FreeHeaderItemList(itemList);
if (diskFile.Opened())
diskFile.Close();
if (derr.IsError())
return FALSE;
else
return hasPublicKey;
}
// IsKeyIDMemberOfRecipList returns TRUE if the given key ID corresponds to a
// key in the given recipient list, FALSE otherwise.
DualErr
IsKeyIDMemberOfRecipList(
PGPKeyID goalKeyID,
PGPRecipientSpec *recipList,
PGPUInt32 size,
PGPBoolean *isMember)
{
DualErr derr;
PGPUInt32 i;
pgpAssertAddrValid(recipList, PGPRecipientSpec);
pgpAssertAddrValid(isMember, PGPBoolean);
(* isMember) = FALSE;
// For every recipient spec...
for (i = 0; i < size; i++)
{
PGPKeyID keyID;
// ... if its key ID equals goal key ID, goal key is a member.
switch (recipList[i].type)
{
case kPGPRecipientSpecType_Key:
pgpAssert(PGPKeyRefIsValid(recipList[i].u.key));
derr = PGPGetKeyIDFromKey(recipList[i].u.key, &keyID);
if (derr.IsntError())
{
if (PGPCompareKeyIDs(&keyID, &goalKeyID) == 0)
(* isMember) = TRUE;
}
break;
case kPGPRecipientSpecType_KeyID:
if (PGPCompareKeyIDs(&recipList[i].u.id.keyID, &goalKeyID) == 0)
(* isMember) = TRUE;
break;
default:
break;
}
if ((* isMember) || derr.IsError())
break;
}
return derr;
}
// AddRecipientSpecToList adds a single PGPRecipientSpec to the given array.
DualErr
AddRecipientSpecToList(PGPRecipientSpec **recipList, PGPUInt32 size)
{
DualErr derr;
PGPRecipientSpec *newList;
pgpAssertAddrValid(recipList, PGPRecipientSpec *);
try
{
newList = new PGPRecipientSpec[size + 1];
}
catch (CMemoryException *ex)
{
derr = DualErr(kPGDMinorError_OutOfMemory);
ex->Delete();
}
if (derr.IsntError())
{
pgpClearMemory((void *) &newList[size], sizeof(PGPRecipientSpec));
if (size > 0)
{
pgpCopyMemory((* recipList), newList,
sizeof(PGPRecipientSpec) * size);
delete[] (* recipList);
}
(* recipList) = newList;
}
return derr;
}
// FreeRecipientSpecList frees a list of recipient specs and the keys within.
void
FreeRecipientSpecList(PGPRecipientSpec *recipList, PGPUInt32 size)
{
if (size > 0)
{
pgpAssertAddrValid(recipList, PGPRecipientSpec);
delete[] recipList;
}
}
// GetPGPdiskRecipKeys returns a list of the public keys associated with a
// PGPdisk.
DualErr
GetPGPdiskRecipKeys(
LPCSTR path,
PGPKeySetRef allKeys,
PGPRecipientSpec **pDiskRecipKeys,
PGPUInt32 *pNumRecipKeys)
{
File diskFile;
DualErr derr;
PGPBoolean gotAnyRecips, gotItemList;
PGPdiskFileHeaderItem *curItem, *itemList;
PGPdiskPublicKeyHeader *pubKeyHdr;
PGPRecipientSpec *diskRecipKeys;
PGPUInt32 numRecipKeys;
gotAnyRecips = gotItemList = FALSE;
pgpAssertStrValid(path);
pgpAssert(PGPKeySetRefIsValid(allKeys));
pgpAssertAddrValid(pDiskRecipKeys, PGPRecipientSpec *);
pgpAssertAddrValid(pNumRecipKeys, PGPUInt32);
(* pNumRecipKeys) = numRecipKeys = 0;
// Open the PGPdisk.
derr = diskFile.Open(path, kOF_MustExist | kOF_ReadOnly);
// Get list of headers.
if (derr.IsntError())
{
derr = GetHeaderItemList(&diskFile, &itemList);
gotItemList = derr.IsntError();
}
if (derr.IsntError())
{
curItem = itemList;
// Extract key from each public key header.
while (derr.IsntError() && IsntNull(curItem))
{
PGPByte *exportedKeyID;
PGPKeyID keyID;
PGPKeyRef curKey;
PGPRecipientSpec *curRecipSpec;
if (IsPublicKeyHeader(curItem->hdr))
{
pubKeyHdr = (PGPdiskPublicKeyHeader *) curItem->hdr;
exportedKeyID = (PGPByte *) pubKeyHdr +
pubKeyHdr->keyIDOffset;
// Create new recip spec.
derr = AddRecipientSpecToList(&diskRecipKeys, numRecipKeys);
if (!gotAnyRecips)
gotAnyRecips = derr.IsntError();
if (derr.IsntError())
{
// Get pointer to current recip spec.
curRecipSpec = &diskRecipKeys[numRecipKeys++];
// Read in key ID.
derr = PGPImportKeyID(exportedKeyID, &keyID);
}
// If actual key found, add key ref to spec, else add ID.
if (derr.IsntError())
{
DualErr keyInRingErr;
keyInRingErr = PGPGetKeyByKeyID(allKeys, &keyID,
pubKeyHdr->algorithm, &curKey);
if (keyInRingErr.IsntError())
{
curRecipSpec->type = kPGPRecipientSpecType_Key;
curRecipSpec->locked = pubKeyHdr->locked;
curRecipSpec->u.key = curKey;
}
else
{
curRecipSpec->type = kPGPRecipientSpecType_KeyID;
curRecipSpec->locked = pubKeyHdr->locked;
curRecipSpec->u.id.keyID = keyID;
curRecipSpec->u.id.algorithm = pubKeyHdr->algorithm;
}
#if !PGP_BUSINESS_SECURITY
// No locked keys in personal build.
curRecipSpec->locked = FALSE;
#endif // !PGP_BUSINESS_SECURITY
}
}
curItem = curItem->next;
}
}
if (derr.IsntError())
{
(* pDiskRecipKeys) = diskRecipKeys;
(* pNumRecipKeys) = numRecipKeys;
}
// Cleanup on error.
if (derr.IsError())
{
if (gotAnyRecips)
FreeRecipientSpecList(diskRecipKeys, numRecipKeys);
}
if (gotItemList)
FreeHeaderItemList(itemList);
if (diskFile.Opened())
diskFile.Close();
return derr;
}
// UpdatePGPdiskPublicKeys updates the public keys headers on a PGPdisk.
DualErr
UpdatePGPdiskPublicKeys(
LPCSTR path,
SecureString *masterPassphrase,
PGPKeySetRef allKeys,
PGPRecipientSpec *newRecipKeys,
PGPUInt32 numRecipKeys,
PGPBoolean newKeysReadOnly)
{
File diskFile;
CASTKey *decryptedKey;
DualErr derr;
PGPBoolean gotItemList = FALSE;
PGPdiskFileHeader *mainHeader;
PGPdiskFileHeaderItem *curItem, *itemList;
PGPdiskPublicKeyHeader *pubKeyHdr;
PGPKeyRef curKey;
PGPUInt32 i;
SecureMemory smDecryptedKey(sizeof(CASTKey));
pgpAssertStrValid(path);
pgpAssertAddrValid(masterPassphrase, SecureString);
pgpAssert(PGPKeySetRefIsValid(allKeys));
pgpAssertAddrValid(newRecipKeys, PGPRecipientSpec);
// Did we get our locked memory?
derr = smDecryptedKey.mInitErr;
if (derr.IsntError())
{
// Set the locked memory pointer.
decryptedKey = (CASTKey *) smDecryptedKey.GetPtr();
// Open the PGPdisk.
derr = diskFile.Open(path, kOF_MustExist);
}
// Get list of headers.
if (derr.IsntError())
{
derr = GetHeaderItemList(&diskFile, &itemList);
gotItemList = derr.IsntError();
}
if (derr.IsntError())
{
// Get main header pointer.
mainHeader = (PGPdiskFileHeader *) itemList->hdr;
// Decrypt the master key
derr = DecryptPassphraseKey(&mainHeader->masterPassphrase,
&mainHeader->salt, masterPassphrase, decryptedKey);
}
// Add keys not in the PGPdisk to the PGPdisk.
if (derr.IsntError())
{
// For each recipient spec...
for (i = 0; i < numRecipKeys; i++)
{
// ... if it is a key ref...
if ((newRecipKeys[i].type) == kPGPRecipientSpecType_Key)
{
curKey = newRecipKeys[i].u.key;
pgpAssert(PGPKeyRefIsValid(curKey));
// ... and if not in header list...
derr = FindPublicKeyInHeaderList(&diskFile, curKey,
itemList, &curItem);
if (derr.IsntError() && IsNull(curItem))
{
// Create a new header for it.
derr = CreatePublicKeyHeader(curKey, decryptedKey,
FALSE, newKeysReadOnly, &pubKeyHdr);
// ...insert the new header after the main header.
if (derr.IsntError())
{
derr = InsertPGPdiskHeaderInList(itemList,
(PGPdiskFileHeaderInfo *) pubKeyHdr);
}
}
}
}
}
// Remove keys not in the key list from the PGPdisk.
if (derr.IsntError())
{
curItem = itemList;
// For every header...
while (derr.IsntError() && IsntNull(curItem))
{
PGPBoolean isMember;
PGPByte *exportedKeyID;
PGPKeyID keyID;
// ...if it's a public key header...
if (IsPublicKeyHeader(curItem->hdr))
{
pubKeyHdr = (PGPdiskPublicKeyHeader *) curItem->hdr;
exportedKeyID = (PGPByte *) pubKeyHdr +
pubKeyHdr->keyIDOffset;
// Read in key ID.
derr = PGPImportKeyID(exportedKeyID, &keyID);
// ... and isn't in the list, remove it from PGPdisk.
if (derr.IsntError())
{
derr = IsKeyIDMemberOfRecipList(keyID, newRecipKeys,
numRecipKeys, &isMember);
}
if (derr.IsntError())
{
if (!isMember)
RemovePGPdiskHeaderFromList(&curItem);
}
}
if (IsntNull(curItem))
curItem = curItem->next;
}
}
// Write out the updated headers to the PGPdisk.
if (derr.IsntError())
{
derr = UpdateHeaderItemList(&diskFile, itemList);
}
if (gotItemList)
FreeHeaderItemList(itemList);
if (diskFile.Opened())
diskFile.Close();
return derr;
}
// FindPublicKeyInHeaderList finds the header item in the given list, if any,
// that corresponds to the given public key.
DualErr
FindPublicKeyInHeaderList(
File *diskFile,
PGPKeyRef curKey,
PGPdiskFileHeaderItem *itemList,
PGPdiskFileHeaderItem **keyItem)
{
DualErr derr;
PGPdiskFileHeaderItem *curItem;
PGPdiskPublicKeyHeader *pubKeyHdr;
PGPKeyID goalKeyID;
pgpAssertAddrValid(diskFile, File);
pgpAssert(diskFile->Opened());
pgpAssert(PGPKeyRefIsValid(curKey));
pgpAssertAddrValid(itemList, PGPdiskFileHeaderItem);
pgpAssertAddrValid(keyItem, PGPdiskFileHeaderItem *);
(* keyItem) = NULL;
// Get ID of key to look for.
derr = PGPGetKeyIDFromKey(curKey, &goalKeyID);
curItem = itemList;
while (derr.IsntError() && IsntNull(curItem))
{
PGPByte *exportedKeyID;
PGPKeyID keyID;
if (IsPublicKeyHeader(curItem->hdr))
{
pubKeyHdr = (PGPdiskPublicKeyHeader *) curItem->hdr;
exportedKeyID = (PGPByte *) pubKeyHdr + pubKeyHdr->keyIDOffset;
// Read in key ID.
derr = PGPImportKeyID(exportedKeyID, &keyID);
// Do they match?
if (PGPCompareKeyIDs(&keyID, &goalKeyID) == 0)
{
(* keyItem) = curItem;
break;
}
}
curItem = curItem->next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -