⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgpdiskpublickeyutils.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//////////////////////////////////////////////////////////////////////////////
// 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 + -