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

📄 pgpkeysig.c

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

		Check and create keyring signatures
		
        $Id: pgpKeySig.c,v 1.37 2002/08/06 20:11:00 dallen Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"


#include "pgpDebug.h"
#include "pgpMakeSig.h"
#include "pgpMem.h"
#include "pgpPktByte.h"
#include "pgpRegExp.h"
#include "pgpKeyPriv.h"
#include "pgpTimeDate.h"
#include "pgpHashPriv.h"
#include "pgpErrors.h"
#include "pgpPubKey.h"
#include "pgpSig.h"
#include "pgpSigSpec.h"
#include "pgpTrustPriv.h"
#include "pgpUsuals.h"
#include "pgpTypes.h"
#include "pgpX509Priv.h"
#include "pgpOptionListPriv.h"


/*
 * Keyring signature checking code.
 */



/* Callback for checking function */
typedef struct PGPKeyCheckState {
	PGPContextRef			context;
	PGPEventHandlerProcPtr	progress;
	PGPUserValue			userValue;
	PGPUInt32				total;
	PGPUInt32				sofar;
} PGPKeyCheckState;



static PGPError
sCheckCRLs( PGPKeySet *keyset, int allflag, PGPKeyDBRef otherdb,
	PGPKeySetRef changedSet );

static PGPBoolean
sCheckableSig( PGPKeyDBObj const *sig, PGPKeyDB *otherdb,
	PGPBoolean allflag, PGPBoolean revocationonly, PGPKeyDBObj **retsignkey);

	static void
sUncheckSig( PGPKeyDBObj *sig, PGPKeyDB *keydb, PGPBoolean *changed );

	static PGPError
sCheckSig(PGPKeyDBObj *sig, PGPKeyDBObj *key, PGPBoolean *changed,
	PGPBoolean *verified );





	static PGPError
sCheckKeysCallback(void *arg, PGPKeyDBObj *obj, int status)
{
	PGPKeyCheckState		*s = (PGPKeyCheckState *)arg;
	PGPError				err = kPGPError_NoErr;
	PGPOptionListRef		newOptionList = NULL;

	(void) obj;
	(void) status;

	if (IsntNull (s->progress)) {
		err = pgpEventNull (s->context, &newOptionList,
							s->progress, s->userValue, ++s->sofar, s->total);
		if (IsntNull (newOptionList))
			pgpFreeOptionList (newOptionList);
	}
	return err;
}
	

/* Called on the back end from the front end preparatory to doing a one
 * key at a time series of key checks.
 */
	PGPError
pgpPrepareToCheckKeyRingSigs_internal( PGPKeySetRef keysToCheck,
	PGPKeyDBRef otherDB, PGPBoolean checkAll, PGPUInt32 *nsigs,
	PGPKeySetRef changedSet )
{
	PGPError err;

	*nsigs = pgpCountCheckableKeySigs( keysToCheck, otherDB, checkAll, FALSE );
	err = sCheckCRLs( keysToCheck, checkAll, NULL, changedSet );
	if( IsPGPError( err ) )
		return err;
	if( IsntNull( otherDB ) )
	{
		/* Must check CRLs in otherdb against this one */
		PGPKeySetRef oroot = PGPPeekKeyDBRootKeySet( otherDB );
		PGPKeyDBRef keydb = PGPPeekKeySetKeyDB( keysToCheck );
		if( IsPGPError( err = sCheckCRLs( oroot, checkAll,
										  keydb, changedSet ) ) )
			return err;
	}
	return kPGPError_NoErr;
}


	PGPError
pgpCheckKeyRingSigs_internal( PGPKeySetRef keysToCheck, PGPKeyDBRef otherDB,
	PGPBoolean checkAll, PGPEventHandlerProcPtr eventHandler,
	PGPUserValue eventHandlerData, PGPKeySetRef changeSet )
{
	PGPKeyCheckState		s;

	s.context = PGPPeekKeySetContext( keysToCheck );
	s.progress = eventHandler;
	s.userValue = eventHandlerData;
	s.sofar = 0;
	if( IsntNull( eventHandler ) )
	{
		s.total = pgpCountCheckableKeySigs( keysToCheck, otherDB, checkAll,
											FALSE );
	}

	return pgpCheckKeySigs( keysToCheck, otherDB, checkAll, FALSE, FALSE,
							sCheckKeysCallback, &s, changeSet );
}

	PGPError
PGPCheckKeyRingSigs( PGPKeySetRef keysToCheck, PGPKeyDBRef otherDB,
	PGPBoolean checkAll, PGPEventHandlerProcPtr eventHandler,
	PGPUserValue eventHandlerData )
{
	PGPKeyDBRef				setDB;
	PGPKeySetRef			changedSet;
	PGPError				err;
	PGPUInt32				nsigs;
	PGPKeyCheckState		s;

	PGPValidateKeySet( keysToCheck );
	if( IsntNull( otherDB ) )
		PGPValidateKeyDB( otherDB );

	pgpEnterPGPErrorFunction();

	setDB = PGPPeekKeySetKeyDB( keysToCheck );
	if( otherDB == setDB )
		otherDB = NULL;
	
	if( pgpFrontEndKeyDB( setDB ) )
	{
		PGPUInt32 *keylist;
		PGPSize keylistsize;
		PGPUInt32 *changelist;
		PGPSize changelistsize;
		PGPContextRef context = PGPPeekKeyDBContext( setDB );

		if( IsNull( eventHandler ) )
		{
			/* Do it all in background if he doesn't want events */

			err = pgpKeySetFlatten( keysToCheck, &keylist, &keylistsize );
			if( IsPGPError( err ) )
				return err;
			err = pgpCheckKeyRingSigs_back( context, setDB->id, keylist,
											keylistsize,
											(IsNull(otherDB)?0:otherDB->id),
											checkAll, &changelist,
											&changelistsize );
			if( IsPGPError( err ) )
				return err;
			err = pgpKeyRefreshFromList( setDB, changelist, changelistsize );
			if( IsPGPError( err ) )
				return err;
			return PGPCalculateTrust( keysToCheck, otherDB );
		}
		/* Else he wants events, must do it one at a time */
		err = pgpKeySetFlatten( keysToCheck, &keylist, &keylistsize );
		if( IsPGPError( err ) )
			return err;
		err = pgpPrepareToCheckKeyRingSigs_back( context, setDB->id,
											keylist, keylistsize,
											(IsNull(otherDB)?0:otherDB->id),
											checkAll, &nsigs, &changelist,
											&changelistsize );
		if( IsPGPError( err ) )
			return err;
		if( IsPGPError( err = pgpKeySetUnflattenFree( setDB, changelist,
													  changelistsize,
													  &changedSet ) ) )
			return err;
						
		
		s.context = context;
		s.progress = eventHandler;
		s.userValue = eventHandlerData;
		s.sofar = 0;
		s.total = nsigs;

		err = pgpCheckKeySigs( keysToCheck, otherDB, checkAll, FALSE, TRUE,
							   sCheckKeysCallback, &s, changedSet );
		if( IsPGPError( err ) )
		{
			PGPFreeKeySet( changedSet );
			return err;
		}
		if( IsPGPError( err = pgpKeySetRefreshFree( changedSet ) ) )
			return err;
		return PGPCalculateTrust( keysToCheck, otherDB );
	}

	err = pgpCheckKeyRingSigs_internal( keysToCheck, otherDB, checkAll,
										 eventHandler, eventHandlerData,
										 NULL );
	if( IsPGPError( err ) )
		return err;

	return PGPCalculateTrust( keysToCheck, otherDB );
}




/*
 * Count the number of sigs we would check with pgpCheckKeySigs.
 * The return value is the number of times the progress func() function
 * will be called by pgpCheckKeySigs().
 * NOTE: this tries to be as accurate as possible, but user code
 * should not die if it is slightly incorrect.
 */
	PGPUInt32
pgpCountCheckableKeySigs(PGPKeySet *keyset, PGPKeyDB *otherdb,
	PGPBoolean allflag, PGPBoolean revocationonly)
{
	PGPKeyDB *keydb;
	PGPKeyDBObj  *key;
	PGPKeyDBObj  *child;
	PGPKeyDBObj  *gchild;
	PGPKeyDBObj *signkey;
	PGPUInt32 count = 0;

	keydb = PGPPeekKeySetKeyDB( keyset );

	for( key = keydb->firstKeyInDB; IsntNull( key ); key = key->next)
	{
		if( !pgpKeyDBObjIsReal( key ) )
			continue;
		if( !pgpKeySetIsMember( key, keyset ) )
			continue;
		for( child = key->down; IsntNull( child ); child = child->next)
		{
			if( !pgpKeyDBObjIsReal( child ) )
				continue;
			if( !pgpKeySetIsMember( child, keyset ) )
				continue;
			if( pgpObjectType( child ) == RINGTYPE_SIG &&
				sCheckableSig( child, otherdb,
							   allflag, revocationonly, &signkey ) )
			{
				if( IsntNull( signkey ) )
					++count;
			}
			for( gchild = child->down; IsntNull(gchild); gchild = gchild->next)
			{
				if( !pgpKeyDBObjIsReal( gchild ) )
					continue;
				if( !pgpKeySetIsMember( gchild, keyset ) )
					continue;
				if( pgpObjectType( gchild ) == RINGTYPE_SIG &&
					sCheckableSig( gchild, otherdb,
								   allflag, revocationonly, &signkey ) )
				{
					if( IsntNull( signkey ) )
						++count;
				}
			}
		}
	}
	return count;
}


/* True if signature would be checked given the specified parameters */
/* Return *retsignkey as signing key if we return TRUE */
static PGPBoolean
sCheckableSig( PGPKeyDBObj const *sig, PGPKeyDB *otherdb,
	PGPBoolean allflag, PGPBoolean revocationonly, PGPKeyDBObj **retsignkey)
{
	PGPKeyDBObj *		signkey;
	PGPKeyID 			signkeyid;
	PGPSigInfo *		sinfo;
	PGPByte				sigalg;
	PGPError			err;

	if( IsntNull( retsignkey ) )
		*retsignkey = NULL;

	pgpAssert( pgpObjectType( sig ) == RINGTYPE_SIG );

	sinfo = pgpSigToSigInfo( sig );
	signkey = sinfo->by;
	if( !pgpKeyDBObjIsReal( signkey ) )
	{
		if( IsNull( otherdb ) )
		{
			/* leave *retsignkey as NULL so caller knows we don't have it */
			return TRUE;
		}
		/* Else see if it is in other db */
		pgpSigID8( sig, &sigalg, &signkeyid );
		err = pgpGetKeyByKeyID(otherdb, &signkeyid, TRUE, FALSE, &signkey );
		if( IsPGPError( err ) )
			return FALSE;
		if( !pgpKeyDBObjIsReal( signkey ) )
		{
			/* leave *retsignkey as NULL so caller knows we don't have it */
			return TRUE;
		}

	}
	if ( (allflag || !(sinfo->trust & (PGP_SIGTRUSTF_CHECKED_TRIED |
									   PGP_SIGTRUSTF_REVOKEDBYCRL)))
		 && (!revocationonly || sinfo->type == PGP_SIGTYPE_KEY_REVOKE) )
	{
		if( IsntNull( retsignkey ) )
			*retsignkey = signkey;
		return TRUE;
	}
	
	return FALSE;
}



/* Compare an object with a buffer */
	static PGPBoolean
sObjDiffers( PGPKeyDBObj *obj, PGPByte *buf, PGPSize len )
{
	PGPBoolean mustFree = FALSE;
	PGPBoolean match = FALSE;
	PGPByte const *objdata;
	PGPSize objlen;
	PGPSize hlen;

	/* Fetch public version of secret key for this */
	if( OBJISKEY( obj ) && pgpKeyIsSec( obj ) )
	{
		objdata = pgpKeyDBObjToPubData( obj, &objlen );
		mustFree = TRUE;
	} else {
		objdata = pgpFetchObject( obj, &objlen );
	}

	hlen = pgpPktBufferHeaderLen( objdata );

	if( len == objlen-hlen && pgpMemoryEqual( objdata+hlen, buf, len ) )
		match = TRUE;

	if( mustFree )
		PGPFreeData( (PGPByte *)objdata );

	return !match;
}


/* True if X.509 sig is valid */
	static PGPBoolean
pgpSigX509Valid (PGPKeyDBObj *obj, PGPKeyDBObjRef key )
{
	PGPASN_Certificate *cert = NULL;
	PGPPubKey const *pub = NULL;
	PGPByte *buf;
	PGPByte *x509cert;
	PGPSize len;
	PGPSize x509len;
	PGPKeyDBRef keydb;
	PGPContextRef context;
	PGPKeyDBObj *parentkey;
	PGPKeyDBObj *parentuserid;
	PGPByte loversion;
	MemPool mempoolinit;
	PGPError err = kPGPError_NoErr;

	/*
	 * Steps:
	 * 1) Compare the key and userid data with that in the cert.
	 * 2) Validate the signature in the cert, using pub
	 */

	keydb = PGPPeekKeyDBObjKeyDB( obj );
	context = PGPPeekKeyDBContext( keydb );
	mempoolinit = keydb->objPool;

	pub = pgpKeyPubKey( key, PGP_PKUSE_SIGN );
	if( IsNull( pub ) )
		goto error;

	parentuserid = obj->up;
	if( !OBJISUSERID(parentuserid) )
		goto error;
	parentkey = parentuserid->up;
	if( !OBJISTOPKEY(parentkey) )
		goto error;

	/* Find embedded X509 cert */
	buf = (PGPByte *)pgpFetchObject(obj, &len);
	if( IsNull( buf )  )
		goto error;
	x509cert = (PGPByte *)pgpSigFindNAISubSubpacket(buf, SIGSUBSUB_X509, 0,
										&x509len, NULL, NULL, NULL, NULL);
	if( IsNull( x509cert )  )
		goto error;

	/* Check type, version bytes */
	if( x509len < 3 )
		goto error;
	pgpAssert (x509cert[0] == SIGSUBSUB_X509);
	if( x509cert[1] != SIGSUBSUB_X509_VERSION_HI )
		goto error;
	loversion = x509cert[2];
	x509cert += 3;
	x509len -= 3;

	err = pgpX509VerifySignedObject( context, pub, x509cert, x509len );

⌨️ 快捷键说明

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