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

📄 pgpkeyio.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 C
📖 第 1 页 / 共 4 页
字号:
/*____________________________________________________________________________
        Copyright (C) 2002 PGP Corporation
        All rights reserved.

        Input, output (export) functions for keydbs

        $Id: pgpKeyIO.c,v 1.72 2002/08/06 20:11:00 dallen Exp $
____________________________________________________________________________*/

#include "pgpConfig.h"

#if HAVE_UNISTD_H
#include <unistd.h>
#endif


#include "pgpContext.h"
#include "pgpKeyPriv.h"
#include "pgpDebug.h"
#include "pgpAnnotate.h"
#include "pgpEncodePriv.h"
#include "pgpEnv.h"
#include "pgpErrors.h"
#include "pgpFileNames.h"
#include "pgpFileRef.h"
#include "pgpFileSpec.h"
#include "pgpPipeline.h"
#include "pgpRandomX9_17.h"
#include "pgpRandomPoolPriv.h"
#include "pgpRndSeed.h"
#include "pgpSigSpec.h"
#include "pgpPubKey.h"
#include "pgpTimeDate.h"
#include "pgpTrustPriv.h"
#include "pgpOptionList.h"
#include "pgpUtilitiesPriv.h"
#include "pgpX509Priv.h"

#if PGP_MACINTOSH
#include "MacStrings.h"
#include "MacFiles.h"
#endif


#define elemsof(x) ((unsigned)(sizeof(x)/sizeof(*x)))



/* See if the newly opened keyring appears to needs sig checking */
	static PGPError
sIsSigCheckNeeded( PGPKeyDB *db, PGPBoolean *sigCheckNeeded )
{
	PGPBoolean			needSigCheck;
	PGPKeyDBObj *		key;
	PGPKeyDBObj *		child;

	*sigCheckNeeded = FALSE;
	needSigCheck = FALSE;

	/*
	 * We look for a key with a revocation signature which has not
	 * been tried, such that the key's revoke bit is not set.  This is
	 * how some old version of PGP leave revocations.  We always set the
	 * key's revocation bit in the file, so this will not happen with
	 * keyrings written by this library.
	 */
	for( key = db->firstKeyInDB; IsntNull(key); key = key->next )
	{
		if( !pgpKeyDBObjIsReal( key ) )
			continue;
		for( child = key->down; IsntNull(child); child = child->next )
		{
			if( !pgpKeyDBObjIsReal( child ) )
				continue;
			if ( pgpObjectType( child ) == RINGTYPE_SIG  &&
				 pgpSigType( child ) == PGP_SIGTYPE_KEY_REVOKE &&
				 pgpSigTrust( child ) == PGP_SIGTRUST_UNTRIED )
			 {
				if ( pgpObjectType( key ) == RINGTYPE_KEY &&
					 !pgpKeyRevoked( key ) )
				{
					/* Here we have our case we are looking for */
					needSigCheck = TRUE;
					break;
				}
			}
		}
	}

	*sigCheckNeeded = needSigCheck;
	return kPGPError_NoErr;
}


	PGPError
pgpOpenKeyDBFile_internal( 
	PGPContextRef			cdkContext,
	PGPOpenKeyDBFileOptions	openFlags,
	PFLFileSpecRef			pubFileRef,
	PFLFileSpecRef			privFileRef,
	PGPKeyDBRef *			keyDBOut )
{
	PGPKeyDB	   *db = NULL;
	PGPBoolean		sigCheckNeeded;
	PGPError		err;
	PFLFileInfo		pubFileInfo;
	PGPTime			curTime, pubModTime;

	/*
	 * Check creation time of pub file so we can check for objects
	 * expired since then.
	 */
	err = PFLGetFileInfo( pubFileRef, &pubFileInfo );
	if( IsPGPError( err ) )
	{
		err = kPGPError_NoErr;
		pubModTime = 0UL;
	} else {
		pubModTime = PGPGetPGPTimeFromStdTime( pubFileInfo.modificationTime );
	}

	db = pgpCreateKeyDBFromKeyRings( cdkContext, pubFileRef, privFileRef,
									 openFlags, &err );
	if( IsPGPError( err ) )
		goto error;

	/*
	 * Some earlier versions of PGP don't cache revocation info.  We will
	 * check signatures if the keyring has unchecked revocation signatures
	 * where the key does not have the revoke flag cached.
	 */
	if( IsPGPError( err = sIsSigCheckNeeded( db, &sigCheckNeeded ) ) )
		goto error;
	if( sigCheckNeeded )
	{
		if ( IsPGPError( err = PGPCheckKeyRingSigs( pgpKeyDBPeekRootSet(db),
													NULL, FALSE, NULL, NULL )))
			goto error;
		if ( IsPGPError( err = PGPCalculateTrust( db->rootSet, NULL ) ) )
			goto error;
	} else {
		/* We will re-run trust propagation if anything has expired */
		curTime = PGPGetTime();
		if( pgpKeyDBHasExpiringObjects( db, pubModTime, curTime ) ) {
			if ( IsPGPError( err = PGPCalculateTrust( db->rootSet, NULL ) ) )
				goto error;
		}
	}

	err = kPGPError_NoErr;
	
error:
	if (db != NULL && IsPGPError( err ))
	{
		PGPFreeKeyDB(db);
		db = NULL;
	}
	*keyDBOut	= db;
	
	pgpAssertErrWithPtr( err, *keyDBOut );
	return err;
}


/*
 * Open the specified keyrings for user, return keyset for it.
 */
	PGPError
PGPOpenKeyDBFile( 
	PGPContextRef			cdkContext,
	PGPOpenKeyDBFileOptions	openFlags,
	PGPFileSpecRef			pubFileRefIn,
	PGPFileSpecRef			privFileRefIn,
	PGPKeyDBRef *			keyDBOut )
{
	PFLFileSpecRef	pubFileRef	= (PFLFileSpecRef)pubFileRefIn;
	PFLFileSpecRef	privFileRef	= (PFLFileSpecRef)privFileRefIn;
	PGPUInt32		kdbid;
	PGPUInt32		numKeys;
	PGPUInt32 *		keyArray;
	PGPSize			keyArraySize;
	PGPError		err;

	PGPValidatePtr( keyDBOut );
	*keyDBOut	= NULL;
	PGPValidateContext( cdkContext );
	PFLValidateFileSpec( pubFileRef );
	if( IsntNull( privFileRef ) )
		PFLValidateFileSpec( privFileRef );
	
	pgpEnterPGPErrorFunction();

	/* In production mode, if no server, don't use double data structs */
#if !PGP_FORCEBACKEND
	if( !pgpRPCEnabled() )
	{
		/* Open it locally */
		return pgpOpenKeyDBFile_internal( cdkContext, openFlags, pubFileRef,
										  privFileRef, keyDBOut );
	}
#endif

	err = pgpOpenKeyDBFile_back( cdkContext, openFlags, pubFileRef,
								 privFileRef, &kdbid, &numKeys, &keyArray,
								 &keyArraySize );
	if( IsPGPError( err ) )
		return err;

	err = pgpNewFrontEndKeyDB( cdkContext, kdbid, keyArray, numKeys, keyDBOut);
	if( IsntNull( keyArray) )
		PGPFreeData( keyArray );

	return err;
}



/*
 * Add keys to a keydb from a dynamically allocated binary key buffer.
 * Makes a copy of the binary key buffer data, so caller can dispose of
 * it after this call.
 */
	PGPError
pgpImportKeyBinary_internal (
	PGPContextRef	cdkContext,
	const PGPByte		   *buffer,
	size_t			length,
	PGPKeyDBRef *	outRef
	)
{
	PGPKeyDBRef		kdb;
	PGPError		err	= kPGPError_NoErr;

	*outRef	= NULL;

	/* Create a file type KeyDB from the buffer */
	kdb = pgpCreateKeyDBFromMemory (cdkContext, buffer, length, &err );
	if ( IsNull( kdb ) )
	{
		pgpAssert( IsPGPError( err ) );
	}
	*outRef	= kdb;
	
	return err;
}


/* This is only called from the front end */
	PGPError
pgpImportKeyBinary (
	PGPContextRef	cdkContext,
	PGPByte		   *buffer,
	size_t			length,
	PGPKeyDBRef *	outRef
	)
{
	PGPUInt32		kdbid;
	PGPUInt32		numKeys;
	PGPUInt32 *		keyArray;
	PGPSize			keyArraySize;
	PGPError		err	= kPGPError_NoErr;

	err = pgpImportKeyBinary_back( cdkContext, buffer, length, &kdbid,
								   &numKeys, &keyArray, &keyArraySize );
	
	if( IsPGPError( err ) )
		return err;

	err = pgpNewFrontEndKeyDB( cdkContext, kdbid, keyArray, numKeys, outRef);
	if( IsntNull( keyArray) )
		PGPFreeData( keyArray );
	
	return err;
}


/* Import an x509 cert from the specified optionlist input */
	static PGPError
sImportX509Certificate( PGPContextRef context, PGPKeyDBRef *db,
	PGPInputFormat inputFormat, PGPOptionListRef optionList)
{
	PGPByte		   *bufPtr;
	PGPSize			bufLength;
	PGPByte		   *outBuf=NULL, *certSet=NULL, *crlSet=NULL;
	PGPSize			outBufLength, certSetLength, crlSetLength;
	PGPBoolean		mustFreeBuf = FALSE;
	PGPKeyDB	   *db2 = NULL;
	char		   *passphrase;
	PGPSize			passphraseLength = 0;
	PGPKeyDBRef		refdb;
	PGPError		err = kPGPError_NoErr;
	
	pgpAssert(IsntNull( db ) );
	*db = NULL;

	err = pgpSetupInputToBuffer( context, optionList, &bufPtr, &bufLength,
								 &mustFreeBuf );
	if( IsPGPError( err ) )
		goto error;

	/* Refdb helps on input */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_KeyDBRef, FALSE,
						 "%p", &refdb ) ) )
		goto error;

	if( inputFormat == kPGPInputFormat_PKCS12 ||
		inputFormat == kPGPInputFormat_PrivateKeyInfo )
	{
		/* Input a private X.509 key */
		PGPKeyDBObj *key = NULL;
		if( inputFormat == kPGPInputFormat_PKCS12 )
		{

			/* Pick up optional passphrase */
			if( IsPGPError( err = pgpFindOptionArgs( optionList,
								kPGPOptionType_Passphrase, FALSE,
								"%p%l", &passphrase, &passphraseLength ) ) )
				goto error;

			err = PKCS12InputKey( context, bufPtr, bufLength,
								  (PGPByte *) passphrase, passphraseLength,
								  &outBuf, &outBufLength,
								  &certSet, &certSetLength );
			if( IsPGPError( err ) )
				goto error;
			
			/* Switch input to PKCS-8 data */
			if( mustFreeBuf )
				PGPFreeData( bufPtr );
			bufPtr = outBuf;
			bufLength = outBufLength;
			mustFreeBuf = TRUE;
		}

		/* Now have PKCS-8 data in bufPtr/bufLength */
		
		/* Process the returned cert set */
		if( IsntNull( certSet ) )
		{
			err = pgpDecodeX509CertSet( certSet, certSetLength,
										context, refdb, db );
			if( IsPGPError( err ) )
				goto error;
			refdb = *db;		/* Use just-imported cert as ref */
		}

		/* Decode PKCS-8 data */
		err = pgpDecodePCKS8( bufPtr, bufLength, context, refdb,
							  IsntNull(*db)?&db2:db );
		if( IsPGPError( err ) )
			goto error;

		/* Combine keysets if necessary */
		if( IsntNull( db2 ) )
		{
			err = PGPCopyKeys( pgpKeyDBPeekRootSet(db2), *db, NULL );
			if( IsPGPError( err ) )
				goto error;
			PGPFreeKeyDB( db2 );
			db2 = NULL;
		}

		/* Set passphrase on newly imported key */
		if( passphraseLength != 0 )
		{
			/* Find key we just imported */
			for( key = (*db)->firstKeyInDB; IsntNull(key); key=key->next )
			{
				if( !pgpKeyDBObjIsReal( key ) )
					continue;
				if (pgpKeyIsSec( key ) )
					break;
			}
			if( key )
			{
				err = pgpDoChangePassphrase_internal( *db, key, NULL, NULL, 0,
												passphrase, passphraseLength,
												FALSE, 0, FALSE );
				if( IsPGPError( err ) )
					goto error;
			}
		}

		/* Done */
		goto error;
	}

	if( inputFormat >= kPGPInputFormat_PEMEncodedX509Cert &&
		inputFormat <= kPGPInputFormat_NetscapeV1_PEMEncoded )
	{
		/* Need to remove PEM encoding */
		PGPByte *tmpBuf;
		PGPSize tmpBufLength;
		err = pgpRemovePEMEncoding( context, bufPtr, bufLength,
									&tmpBuf, &tmpBufLength );
		if( IsPGPError( err ) )
			goto error;
		/* Replace bufPtr, bufLength with tmp versions (which must be freed) */
		if( mustFreeBuf )
			PGPFreeData( bufPtr );
		mustFreeBuf = TRUE;
		bufPtr = tmpBuf;
		bufLength = tmpBufLength;
	}

	/* Process buffer to strip off any PKCS-7 layering */
	{
		PGPKeyDBObjRef dummy1, dummy2;
		PGPBoolean dummy3, dummy4, dummy5;
		PGPAttributeValue *dummy6;
		PGPUInt32 dummy7;

		err = X509InputCertificate( context, bufPtr, bufLength, refdb,
									inputFormat, NULL, &dummy1, &dummy2,
									&dummy3, &dummy4, &dummy5,
									&dummy6, &dummy7, &certSet, &certSetLength,
									&crlSet, &crlSetLength );
		if( IsPGPError( err ) )
			goto error;
		
		if( IsntNull( certSet ) )
		{
			err = pgpDecodeX509CertSet( certSet, certSetLength, context,
										refdb, db );
			if( IsPGPError( err ) )
				goto error;
		}

		if( IsntNull( crlSet ) )
		{
			err = pgpDecodeX509CRLSet( crlSet, crlSetLength, context, refdb,

⌨️ 快捷键说明

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