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

📄 pgpkeylib.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * pgpKeyLib.c
 * Initialization and cleanup functions related to the keydb library
 *
 * Copyright (C) 1996,1997 Network Associates Inc. and affiliated companies.
 * All rights reserved
 *
 * $Id: pgpKeyLib.c,v 1.134.2.1 1999/06/11 00:30:38 heller Exp $
 */

#include "pgpConfig.h"

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


#include "pgpContext.h"
#include "pgpKeyDB.h"
#include "pgpDebug.h"
#include "pgpKDBInt.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 "pgpRngRead.h"
#include "pgpSigSpec.h"
#include "pgpTimeDate.h"
#include "pgpTrstPkt.h"
#include "pgpSDKPrefs.h"
#include "pgpOptionList.h"
#include "pgpUtilitiesPriv.h"
#include "pgpX509Priv.h"


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


#include "pgpDEBUGStartup.h"

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



/* See if the newly opened keyring appears to needs sig checking */
	static PGPError
sIsSigCheckNeeded( PGPKeySetRef set, PGPBoolean *sigCheckNeeded )
{
	RingSet const *		rset;
	RingIterator *		riter;
	int					level;
	PGPBoolean			needSigCheck;

	*sigCheckNeeded = FALSE;
	needSigCheck = FALSE;

	rset = pgpKeyDBRingSet( set->keyDB );
	riter = ringIterCreate( rset );
	if ( !riter )
		return ringSetError( rset )->error;

	/*
	 * 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.
	 */
	while ( (level = ringIterNextObjectAnywhere( riter ) ) > 0 )
	{
		if ( level == 2 )
		{
			RingObject *obj = ringIterCurrentObject( riter, level );
			if ( ringObjectType( obj ) == RINGTYPE_SIG  &&
				 ringSigType( rset, obj ) == PGP_SIGTYPE_KEY_REVOKE &&
				 ringSigTrust( rset, obj ) == PGP_SIGTRUST_UNTRIED )
			 {
				RingObject *parent = ringIterCurrentObject( riter, level - 1 );
				if ( ringObjectType( parent ) == RINGTYPE_KEY &&
					 !ringKeyRevoked( rset, parent ) )
				{
					/* Here we have our case we are looking for */
					needSigCheck = TRUE;
					break;
				}
			}
		}
	}
	ringIterDestroy( riter );

	*sigCheckNeeded = needSigCheck;
	return kPGPError_NoErr;
}

	static PGPError
pgpGetDefaultRingFileRefs(
	PGPContextRef	cdkContext,
	PFLFileSpecRef		*pubRefOut,
	PFLFileSpecRef		*privRefOut )
{
	PGPError		err = kPGPError_NoErr;

	/* set outputs to default */
	if ( IsntNull( privRefOut ) )
		*privRefOut = NULL;
	if ( IsntNull( pubRefOut ) )
		*pubRefOut = NULL;
		
	/* load preferences if not already loaded */
	if ( IsNull( pgpContextGetPrefs( cdkContext ) ) )
	{
		err	= PGPsdkLoadDefaultPrefs( cdkContext );
	}
	
	if ( IsntPGPError( err ) )
	{
		if ( IsntNull( privRefOut ) )
		{
			err = PGPsdkPrefGetFileSpec( cdkContext,
				kPGPsdkPref_PrivateKeyring, (PGPFileSpecRef *)privRefOut);
		}

		if ( IsntPGPError( err ) && IsntNull( pubRefOut ) )
		{
			err = PGPsdkPrefGetFileSpec( cdkContext,
				kPGPsdkPref_PublicKeyring, (PGPFileSpecRef *)pubRefOut);
			if ( IsPGPError( err ) )
			{
				PFLFreeFileSpec( *privRefOut );
				*privRefOut	= NULL;
			}
		}
	}
	
	return err;
}

/*
 * Open default keyrings for user, return keyset for it.
 * If isMutable is false, keyrings are read only.
 */
	PGPError
PGPOpenDefaultKeyRings(
	PGPContextRef		cdkContext,
	PGPKeyRingOpenFlags	openFlags,
	PGPKeySetRef *		keySetOut )
{
	PFLFileSpecRef	secFileRef = NULL;	/* File reference for secret keyring */
	PFLFileSpecRef	pubFileRef = NULL;	/* File reference for public keyring */
	PGPError		err = kPGPError_NoErr;
	PGPKeySetRef	set	= NULL;

	PGPValidatePtr( keySetOut );
	*keySetOut	= NULL;
	PGPValidateContext( cdkContext );

	err	= pgpGetDefaultRingFileRefs( cdkContext, &pubFileRef, &secFileRef);
	if ( IsntPGPError( err ) )
	{
		pgpAssert( IsntNull( pubFileRef ) );
		pgpAssert( IsntNull( secFileRef ) );
		
		err = PGPOpenKeyRingPair(cdkContext, openFlags,
					(PGPFileSpecRef)pubFileRef,
					(PGPFileSpecRef)secFileRef, &set);
			
		PFLFreeFileSpec( secFileRef );
		PFLFreeFileSpec( pubFileRef );
	}
		
	if ( IsPGPError( err ) && IsntNull( set ) )
	{
		PGPFreeKeySet( set );
		set	= NULL;
	}
	
	*keySetOut	= set;
	pgpAssertErrWithPtr( err, *keySetOut );
	return err;
}

/*
 * Open the specified keyrings for user, return keyset for it.
 * If isMutable is false, keyrings are read only.
 */
	PGPError
PGPOpenKeyRingPair(
	PGPContextRef		cdkContext,
	PGPKeyRingOpenFlags	openFlags,
	PGPFileSpecRef		pubFileRefIn,
	PGPFileSpecRef		privFileRefIn,
	PGPKeySetRef *		keySetOut )
{
	PGPKeyDB	   *dbsec = NULL,		/* KeyDB for secret keyring */
				   *dbpub = NULL,		/* KeyDB for public keyring */
				   *dbunion = NULL;		/* KeyDB for union of both keyrings */
	RingPool	   *pgpRingPool;		/* RingPool from cdkContext */
	PGPKeySet	   *set = NULL;
	PGPBoolean		sigCheckNeeded;
	PGPError		err;
	PFLFileSpecRef	pubFileRef	= (PFLFileSpecRef)pubFileRefIn;
	PFLFileSpecRef	privFileRef	= (PFLFileSpecRef)privFileRefIn;
	PFLFileInfo		pubFileInfo;
	PGPTime			curTime, pubModTime;

	PGPValidatePtr( keySetOut );
	*keySetOut	= NULL;
	PGPValidateContext( cdkContext );
	PFLValidateFileSpec( pubFileRef );
	PFLValidateFileSpec( privFileRef );
	
	pgpAssert( (openFlags & kPGPKeyRingOpenFlags_Reserved) == 0 );
	pgpAssert(0 == (openFlags & (kPGPKeyRingOpenFlags_Private |
								 kPGPKeyRingOpenFlags_Trusted)));

	pgpRingPool = pgpContextGetRingPool( cdkContext );

	/*
	 * 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 );
	}

	/* Create key databases for these files.  Don't bother with keypool. 
	   Private keyring is not trusted (no trust packets) */
	if ((dbsec = pgpCreateFileKeyDB(cdkContext, privFileRef,
								(PGPKeyRingOpenFlags)
								(openFlags | kPGPKeyRingOpenFlags_Private),
								pgpRingPool, &err)) == NULL)
		goto error;
	if ((dbpub = pgpCreateFileKeyDB(cdkContext, pubFileRef,
								(PGPKeyRingOpenFlags)
								(openFlags | kPGPKeyRingOpenFlags_Trusted),
								pgpRingPool, &err)) == NULL)
		goto error;

	/* Create union database for these two files */
	if ((dbunion = pgpCreateUnionKeyDB(cdkContext, &err)) == NULL)
		goto error;
	
	err	= pgpUnionKeyDBAdd(dbunion, dbsec);
	if ( IsPGPError( err ) )
		goto error;
	dbsec = NULL;	/* dbunion now has responsibility for freeing dbsec */
	
	err	= pgpUnionKeyDBAdd(dbunion, dbpub);
	if ( IsPGPError( err ) )
		goto error;
	dbpub = NULL;	/* dbunion now has responsibility for freeing dbpub */

	/*
	 * Verify that we have sufficient ringsets to work with union.
	 * It is easier to check for this now than to check everywhere we
	 * ask for a ringset.
	 */
	if (dbunion->getRingSet(dbunion) == NULL) {
		/* Insufficient ringsets */
		err = kPGPError_OutOfRings;
		goto error;
	}

	err	= pgpBuildKeyPool(dbunion, 0);
	if ( IsPGPError( err ) )
		goto error;

	set = pgpKeyDBRootSet(dbunion);
	if ( IsNull( set ) )
	{
		err = kPGPError_OutOfMemory;	/* XXX Improve error */
		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( set, &sigCheckNeeded ) ) )
		goto error;
	if( sigCheckNeeded )
	{
		if ( IsPGPError( err = PGPCheckKeyRingSigs( set, set, FALSE,
													NULL, NULL ) ) )
			goto error;
		if ( IsPGPError( err = PGPPropagateTrust( set ) ) )
			goto error;
		if ( PGPKeySetIsMutable( set ) )
		{
			if ( IsPGPError( err = PGPCommitKeyRingChanges( set ) ) )
				goto error;
		}
	} else {
		/* We will re-run trust propagation if anything has expired */
		RingSet const *ringset = pgpKeyDBRingSet( dbunion );
		curTime = PGPGetTime();
		if( ringSetHasExpiringObjects( ringset, curTime, pubModTime ) ) {
			if ( IsPGPError( err = PGPPropagateTrust( set ) ) )
				goto error;
		}
	}

	err = kPGPError_NoErr;
	
error:
	if (dbsec != NULL)
		pgpFreeKeyDB(dbsec);
	if (dbpub != NULL)
		pgpFreeKeyDB(dbpub);
	if (dbunion != NULL)
		pgpFreeKeyDB(dbunion);
	if (set != NULL && IsPGPError( err ))
	{
		PGPFreeKeySet(set);
		set = NULL;
	}
	*keySetOut	= set;
	
	pgpAssertErrWithPtr( err, *keySetOut );
	return err;
}

/*
 * Open a single specified keyring for user, return keyset for it.
 * If isMutable is false, keyrings are read only.
 * If isTrusted is false, trust packets are ignored.
 */
	PGPError
PGPOpenKeyRing(
	PGPContextRef		cdkContext,
	PGPKeyRingOpenFlags	openFlags,
	PGPFileSpecRef		fileRefIn,
	PGPKeySetRef *		keySetOut )
{
	PGPKeyDB	   *db = NULL;
	PGPKeySet	   *set = NULL;
	RingPool	   *pgpRingPool;
	PGPBoolean		sigCheckNeeded;
	PGPError		err = kPGPError_NoErr;
	PFLFileSpecRef	fileRef	= (PFLFileSpecRef)fileRefIn;

	PGPValidatePtr( keySetOut );
	*keySetOut	= NULL;
	PGPValidateContext( cdkContext );
	PFLValidateFileSpec( fileRef );
	
	pgpAssert( (openFlags & kPGPKeyRingOpenFlags_Reserved) == 0 );
	

	pgpRingPool = pgpContextGetRingPool( cdkContext );

	/* Create key database for this files.  Don't bother with keypool. */
	if ((db = pgpCreateFileKeyDB(cdkContext, fileRef, openFlags,
								 pgpRingPool, &err)) == NULL)
		goto error;

	err	= pgpBuildKeyPool(db, 0);
	if ( IsPGPError( err ) )
		goto error;

	set = pgpKeyDBRootSet(db);
	if ( IsNull( set ) )
	{
		err = kPGPError_OutOfMemory;	/* XXX Improve error */
		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( set, &sigCheckNeeded ) ) )
		goto error;
	if( sigCheckNeeded )
	{
		if ( IsPGPError( err = PGPCheckKeyRingSigs( set, set, FALSE,
													NULL, NULL ) ) )
			goto error;
		if ( IsPGPError( err = PGPPropagateTrust( set ) ) )
			goto error;
		if ( PGPKeySetIsMutable( set ) )
		{
			if ( IsPGPError( err = PGPCommitKeyRingChanges( set ) ) )
				goto error;
		}
	}
	err = kPGPError_NoErr;
	
error:
	if (db != NULL)
		pgpFreeKeyDB(db);
	if (set != NULL && IsPGPError( err ))
	{
		PGPFreeKeySet(set);
		set = NULL;
	}
	*keySetOut	= set;
	pgpAssertErrWithPtr( err, *keySetOut );
	return err;
}

/*
 * Add keys to a keyset 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 (
	PGPContextRef	cdkContext,
	PGPByte		   *buffer,
	size_t			length,
	PGPKeySetRef *	outRef
	)
{
	PGPKeyDBRef		kdb;
	PGPKeySetRef	set	= NULL;
	RingPool	   *pgpRingPool;
	PGPError		err	= kPGPError_NoErr;

	*outRef	= NULL;
	
	/* Create a file type KeyDB from the buffer */
	pgpRingPool = pgpContextGetRingPool( cdkContext );
	kdb = pgpCreateMemFileKeyDB (cdkContext, buffer, length, pgpRingPool,
								 &err);
	if ( IsNull( kdb ) )
	{
		pgpAssert( IsPGPError( err ) );
	}
	else
	{
		err = pgpBuildKeyPool (kdb, 0);
		if ( IsntPGPError( err ) )
		{
			set = pgpKeyDBRootSet (kdb);
		}
		pgpFreeKeyDB (kdb);
	}
	
	*outRef	= set;
	
	return err;
}


/* Import an x509 cert from the specified optionlist input */
	static PGPError
sImportX509Certificate( PGPContextRef context, PGPKeySetRef *keys,
	PGPInputFormat inputFormat, PGPOptionListRef optionList)
{
	PGPByte		   *bufPtr;
	PGPSize			bufLength;
	PGPByte		   *outBuf=NULL, *certSet=NULL;
	PGPSize			outBufLength, certSetLength;
	PGPBoolean		mustFreeBuf = FALSE;
	PGPKeySet	   *keys2 = NULL;
	char		   *passphrase;
	PGPSize			passphraseLength = 0;
	PGPError		err = kPGPError_NoErr;
	
	err = pgpSetupInputToBuffer( context, optionList, &bufPtr, &bufLength,
								 &mustFreeBuf );
	if( IsPGPError( err ) )
		goto error;

	if( inputFormat == kPGPInputFormat_PKCS12 ||
		inputFormat == kPGPInputFormat_PrivateKeyInfo )
	{
		/* Input a private X.509 key */
		RingObject *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,

⌨️ 快捷键说明

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