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

📄 pgpdisk.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////////////
// PGPdisk.cpp
//
// Implementation of class PGPdisk.
//////////////////////////////////////////////////////////////////////////////

// $Id: PGPdisk.cpp,v 1.9 1999/02/13 04:24:35 nryan Exp $

// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.

#include <vtoolscp.h>

#include "Required.h"
#include "PGPdiskHighLevelUtils.h"
#include "PGPdiskLowLevelUtils.h"
#include "UtilityFunctions.h"

#include "Globals.h"
#include "PGPdisk.h"
#include "PlacementNew.h"


////////////////////////////////////////
// Class PGPdisk public member functions
////////////////////////////////////////

// The PGPdisk default constructor.

PGPdisk::PGPdisk() : VolFile(), mSmContextA(sizeof(CipherContext)), 
	mSmContextB(sizeof(CipherContext))
{
	mContextA	= NULL;
	mContextB	= NULL;

	mDataBuf = NULL;

	mPGPdiskReq.isInUse = FALSE;

	mInitErr = VolFile::mInitErr;

	if (mInitErr.IsntError())
	{
		mInitErr = mSmContextA.mInitErr;
	}

	if (mInitErr.IsntError())
	{
		mInitErr = mSmContextB.mInitErr;
	}

	// Get our data buffer.
	if (mInitErr.IsntError())
	{
		mInitErr = GetByteBuffer(kPGDBlocksPerOp*kDefaultBlockSize, 
			&mDataBuf);
	}

	if (mInitErr.IsntError())
	{
		// Use placement new.
		mContextA	= new (mSmContextA.GetPtr()) CipherContext;	
		mContextB	= new (mSmContextB.GetPtr()) CipherContext;
	}
}

// The PGPdisk destructor cleans up.

PGPdisk::~PGPdisk()
{
	if (Mounted())
		Unmount(TRUE);

	if (IsntNull(mContextB))
	{
		mContextB->~CipherContext();
		mContextB = NULL;
	}

	if (IsntNull(mContextA))
	{
		mContextA->~CipherContext();
		mContextA = NULL;
	}

	if (IsntNull(mDataBuf))
	{
		FreeByteBuffer(mDataBuf);
		mDataBuf = NULL;
	}
}

// BestGuessComparePaths uses a number of methods to determine if the
// specified file is the same as the current mounted PGPdisk.

PGPBoolean 
PGPdisk::BestGuessComparePaths(LPCSTR path)
{
	File		testFile;
	DualErr		derr;
	PGPBoolean	failedTest	= FALSE;
	PGPUInt32	i, numPGPdiskPathElems, numTestFilePathElems;
	PGPUInt64	PGPdiskLength, testFileLength;

	pgpAssert(Mounted());

	// First try the easy case.
	if (ComparePaths(path))
		return TRUE;

	// See if the number of path elements in each path is the same.
	numPGPdiskPathElems = 0;

	for (i=0; i<strlen(GetPath()); i++)
	{
		if ((GetPath()[i] == '\\') || (GetPath()[i] == '/'))
			numPGPdiskPathElems++;
	}

	numTestFilePathElems = 0;

	for (i=0; i<strlen(path); i++)
	{
		if ((path[i] == '\\') || (path[i] == '/'))
			numTestFilePathElems++;
	}

	if (numPGPdiskPathElems != numTestFilePathElems)
		failedTest = TRUE;

	// Make sure the files are the same size.
	if (!failedTest)
	{
		derr = GetLength(&PGPdiskLength);
	}

	if (derr.IsntError() && !failedTest)
	{
		derr = testFile.Open(path, kOF_MustExist | kOF_ReadOnly);
	}

	if (derr.IsntError() && !failedTest)
	{
		derr = testFile.GetLength(&testFileLength);
	}

	if (!failedTest && testFile.Opened())
	{
		testFile.Close();
	}

	if (derr.IsntError() && !failedTest)
	{
		if (PGPdiskLength != testFileLength)
			failedTest = TRUE;
	}

	// Check if the test file is in use (which must be the case with any
	// mounted PGPdisk.

	if (derr.IsntError() && !failedTest)
	{
		if (!Driver->IsFileInUse(path))
			failedTest = TRUE;
	}

	// Finally return false if there was an error.
	if (derr.IsError())
	{
		failedTest = TRUE;
	}

	return !failedTest;
}

// GetUniqueSessionId returns the unique session ID for the PGPdisk.

PGPUInt64 
PGPdisk::GetUniqueSessionId()
{
	pgpAssert(Mounted());

	return mUniqueSessionId;
}

// FlipContexts flips the key bits on each context.

void 
PGPdisk::FlipContexts()
{
	pgpAssertAddrValid(mContextA, CipherContext);
	pgpAssertAddrValid(mContextB, CipherContext);
	pgpAssert(Mounted());

	mContextA->FlipContext();
	mContextB->FlipContext();
}

// ValidateContexts makes sure the cipher procs aren't damaged.

DualErr 
PGPdisk::ValidateContexts()
{
	DualErr derr;

	pgpAssertAddrValid(mContextA, CipherContext);
	pgpAssertAddrValid(mContextB, CipherContext);
	pgpAssert(Mounted());

	derr = mContextA->ValidateContext();

	if (derr.IsntError())
	{
		derr = mContextB->ValidateContext();
	}

	return derr;
}

// Mount reads in the PGPdisk-specific header and asks VolFile to continue
// with the mount, passing along header and disk size information.

DualErr 
PGPdisk::Mount(
	LPCSTR			path, 
	CipherContext	*context, 
	PDCB			pDcb, 
	PGPUInt8		drive, 
	PGPBoolean		mountReadOnly)
{
	DualErr				derr;
	File				diskFile;
	PGPBoolean			readHeader	= FALSE;
	PGPdiskFileHeader	*fileHeader;

	pgpAssertStrValid(path);
	pgpAssertAddrValid(context, CipherContext);

	// Mark the PGPdisk as mounted.
	if (!mountReadOnly)
		SetPGPdiskMountedFlag(path, TRUE);

	// Read the session ID.
	mUniqueSessionId = GetPGPdiskUniqueSessionId(path);

	// Read in the header.
	derr = ReadPGPdiskFileMainHeader(path, &fileHeader);
	readHeader = derr.IsntError();

	// Initialize the contexts and flip context B.
	if (derr.IsntError())
	{
		pgpAssertAddrValid(mContextA, CipherContext);
		pgpAssertAddrValid(mContextB, CipherContext);

		(* mContextA) = (* mContextB) = (* context);

		mContextB->FlipContext();
	}

	// Finish the mount by calling down.
	if (derr.IsntError())
	{
		derr = VolFile::Mount(path, fileHeader->numHeaderBlocks, 
			fileHeader->numDataBlocks, pDcb, drive, mountReadOnly);
	}

	if (derr.IsError())
	{
		if (!mountReadOnly)
			SetPGPdiskMountedFlag(path, FALSE);
	}

	if (readHeader)
		FreePGPdiskFileHeader((PGPdiskFileHeaderInfo *) fileHeader);

	return derr;
}

// Unmount unmounts a mounted PGPdisk.

DualErr 
PGPdisk::Unmount(PGPBoolean isThisEmergency)
{
	DualErr		derr;
	LPSTR		pathCopy;
	PGPBoolean	dupedPath, wasReadOnly;

	pgpAssert(Mounted());

	dupedPath = FALSE;
	wasReadOnly = IsReadOnly();

	// Copy path.
	derr = DupeString(GetPath(), &pathCopy);
	dupedPath = derr.IsntError();

	// Unmount the PGPdisk volume.
	if (derr.IsntError())
	{
		derr = VolFile::Unmount(isThisEmergency);
	}

	if (derr.IsntError())
	{
		// Mark as not mounted.
		if (!wasReadOnly)
			SetPGPdiskMountedFlag(pathCopy, FALSE);

		// Unflip the contexts and destroy them.
		(mContextA->IsFlipped() ? mContextA->FlipContext() : 
			mContextB->FlipContext());

		mContextA->DestroyContext();
		mContextB->DestroyContext();
	}

	if (dupedPath)
		delete[] pathCopy;

	return derr;
}

// ReadAsync performs a read request on the mounted PGPdisk asynchronously.

void 
PGPdisk::ReadAsync(
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBytes, 
	GenericCallbackInfo	*upInfo)
{
	PGPBoolean doneWithRequest;

	pgpAssertAddrValid(upInfo, GenericCallbackInfo);
	pgpAssertAddrValid(upInfo->callback, PGPUInt8);
	pgpAssertAddrValid(buf, PGPUInt8);

	pgpAssert(Mounted());

	pgpAssert(!mPGPdiskReq.isInUse);
	mPGPdiskReq.isInUse = TRUE;

	// Prepare the request for execution.
	mPGPdiskReq.op = kPGDOP_Read;
	mPGPdiskReq.upInfo = upInfo;

	mPGPdiskReq.downInfo.callback = PGPdiskCallback;
	mPGPdiskReq.downInfo.refData[0] = (PGPUInt32) this;

	// We start out by initializing the request so that all possible
	// pieces of the request are marked as completed.

	mPGPdiskReq.read.readHeader	= TRUE;
	mPGPdiskReq.read.readMiddle	= TRUE;
	mPGPdiskReq.read.readTail	= TRUE;

	// Now we analyze the request and determine what pieces must be
	// read so that the entire request can be marked as done.

	if (pos%kDefaultBlockSize > 0)
	{
		PGPUInt32 bytesInHeader;

		// The request has a header - that is, it doesn't begin on a
		// block boundary.

		bytesInHeader = min(nBytes, kDefaultBlockSize - 
			(PGPUInt32) (pos%kDefaultBlockSize));

		mPGPdiskReq.read.readHeader		= FALSE;
		mPGPdiskReq.read.bufHeader		= buf;
		mPGPdiskReq.read.posHeader		= pos;
		mPGPdiskReq.read.nBytesHeader	= bytesInHeader;

		buf		+= bytesInHeader;
		pos		+= bytesInHeader;
		nBytes	-= bytesInHeader;
	}

	if (nBytes >= kDefaultBlockSize)
	{
		PGPUInt32 bytesInMiddle;

		// The request has a middle - that is, a section that begins and
		// ends on a block boundary and is more than one block in length.

		bytesInMiddle = nBytes - nBytes%kDefaultBlockSize;

		mPGPdiskReq.read.readMiddle		= FALSE;
		mPGPdiskReq.read.bufMiddle		= buf;
		mPGPdiskReq.read.posMiddle		= pos;
		mPGPdiskReq.read.nBytesMiddle	= bytesInMiddle;

		buf		+= bytesInMiddle;
		pos		+= bytesInMiddle;
		nBytes	-= bytesInMiddle;
	}

	if (nBytes > 0)
	{
		// The request has a tail - that is, it doesn't end on a
		// block boundary.

		mPGPdiskReq.read.readTail	= FALSE;
		mPGPdiskReq.read.bufTail	= buf;
		mPGPdiskReq.read.posTail	= pos;
		mPGPdiskReq.read.nBytesTail	= nBytes;
	}

	// Execute the request.
	ExecuteRequest(&doneWithRequest);

	// Should always have stuff to do at this point. But if we don't, then
	// don't hang the computer by not calling back.

	if (doneWithRequest)
	{
		pgpAssert(FALSE);
		ScheduleAsyncCallback();
	}
}

// WriteAsync performs a write request on the mounted PGPdisk asynchronously.

void 
PGPdisk::WriteAsync(
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBytes, 
	GenericCallbackInfo	*upInfo)
{
	PGPBoolean doneWithRequest;

	pgpAssertAddrValid(upInfo, GenericCallbackInfo);
	pgpAssertAddrValid(upInfo->callback, PGPUInt8);
	pgpAssertAddrValid(buf, PGPUInt8);

	pgpAssert(Mounted());

	pgpAssert(!mPGPdiskReq.isInUse);
	mPGPdiskReq.isInUse = TRUE;

	// Prepare the request for execution.
	mPGPdiskReq.op = kPGDOP_Write;
	mPGPdiskReq.upInfo = upInfo;

	mPGPdiskReq.downInfo.callback = PGPdiskCallback;
	mPGPdiskReq.downInfo.refData[0] = (PGPUInt32) this;

	// We start out by initializing the request so that all possible
	// pieces of the request are marked as completed.

	mPGPdiskReq.write.readHeader	= TRUE;
	mPGPdiskReq.write.wroteHeader	= TRUE;
	mPGPdiskReq.write.wroteMiddle	= TRUE;
	mPGPdiskReq.write.readTail		= TRUE;
	mPGPdiskReq.write.wroteTail		= TRUE;

	// Now we analyze the request and determine what pieces must be
	// written so that the entire request can be marked as done.

	if (pos%kDefaultBlockSize > 0)
	{
		PGPUInt32 bytesInHeader;

		// The request has a header - that is, it doesn't begin on a
		// block boundary.

		bytesInHeader = min(nBytes, kDefaultBlockSize - 
			(PGPUInt32) (pos%kDefaultBlockSize));

		mPGPdiskReq.write.readHeader	= FALSE;
		mPGPdiskReq.write.wroteHeader	= FALSE;
		mPGPdiskReq.write.bufHeader		= buf;
		mPGPdiskReq.write.posHeader		= pos;
		mPGPdiskReq.write.nBytesHeader	= bytesInHeader;

		buf		+= bytesInHeader;
		pos		+= bytesInHeader;
		nBytes	-= bytesInHeader;
	}

	if (nBytes >= kDefaultBlockSize)
	{
		PGPUInt32 bytesInMiddle;

		// The request has a middle - that is, a section that begins and
		// ends on a block boundary and is more than one block in length.

		bytesInMiddle = nBytes - nBytes%kDefaultBlockSize;

		mPGPdiskReq.write.wroteMiddle	= FALSE;
		mPGPdiskReq.write.bufMiddle		= buf;
		mPGPdiskReq.write.posMiddle		= pos;
		mPGPdiskReq.write.nBytesMiddle	= bytesInMiddle;

		buf		+= bytesInMiddle;
		pos		+= bytesInMiddle;
		nBytes	-= bytesInMiddle;
	}

	if (nBytes > 0)
	{
		// The request has a tail - that is, it doesn't end on a
		// block boundary.

		mPGPdiskReq.write.readTail		= FALSE;
		mPGPdiskReq.write.wroteTail		= FALSE;
		mPGPdiskReq.write.bufTail		= buf;
		mPGPdiskReq.write.posTail		= pos;
		mPGPdiskReq.write.nBytesTail	= nBytes;
	}

	// Execute the request.
	ExecuteRequest(&doneWithRequest);

	// Should always have stuff to do at this point. But if we don't, then
	// don't hang the computer by not calling back.

	if (doneWithRequest)
	{
		pgpAssert(FALSE);
		ScheduleAsyncCallback();
	}
}

// ReadSync performs a read request on the mounted PGPdisk synchronously.

DualErr 
PGPdisk::ReadSync(PGPUInt8 *buf, PGPUInt64 pos, PGPUInt32 nBytes)
{
	DualErr		derr;
	PGPUInt32	blocksChunk, blocksToRead, bufPos;
	PGPUInt64	blockPGPdisk;

	pgpAssertAddrValid(buf, PGPUInt8);
	pgpAssert(Mounted());

	// The position (pos) and size (nBytes) variables are in bytes, but we
	// can only perform encryption in blocks. What we have to do is handle
	// the request in at most three separate pieces - a head, middle, and
	// end.

	bufPos = 0;

	if (pos%kDefaultBlockSize > 0)	// is there a head?
	{
		PGPUInt32 headOffset, headSize;

		// Now read in the head.
		//
		// blockPGPdisk = block on PGPdisk containing the head.
		// headOffset = byte offset into blockPGPdisk where head starts
		// headSize = size of the head, in bytes

		blockPGPdisk	= pos/kDefaultBlockSize;
		headOffset		= (PGPUInt32) (pos%kDefaultBlockSize);
		headSize		= min(nBytes, kDefaultBlockSize - headOffset);

		derr = VolFile::Read(mDataBuf, blockPGPdisk*kDefaultBlockSize, 
			kDefaultBlockSize);

		if (derr.IsntError())
		{
			SmartCipherBlocks(blockPGPdisk, 1, mDataBuf, mDataBuf, 
				kCipherOp_Decrypt);

			pgpCopyMemory(mDataBuf + headOffset, buf, headSize);

			bufPos	= headSize;
			pos		+= headSize;
			nBytes	-= headSize;
		}
	}

	// Read in the middle, in 'kPGDBlocksPerOp' chunks.
	if (derr.IsntError())
	{
		blocksToRead = nBytes/kDefaultBlockSize;

		while (derr.IsntError() && (blocksToRead > 0))	// is there a middle?
		{
			// Determine exactly how many blocks to read this iteration.
			//
			// blockPGPdisk = block on the PGPdisk where this read begins
			// blocksChunk = the most blocks we can read in this iteration

			blockPGPdisk	= pos/kDefaultBlockSize;
			blocksChunk		= min(blocksToRead, kPGDBlocksPerOp);

			derr = VolFile::Read(mDataBuf, blockPGPdisk*kDefaultBlockSize, 
				blocksChunk*kDefaultBlockSize);

			if (derr.IsntError())
			{
				SmartCipherBlocks(blockPGPdisk, blocksChunk, mDataBuf, 
					buf + bufPos, kCipherOp_Decrypt);

				bufPos			+= blocksChunk * kDefaultBlockSize;
				nBytes			-= blocksChunk * kDefaultBlockSize;
				pos				+= blocksChunk * kDefaultBlockSize;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -