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

📄 pgpkeyman.c

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

        $Id: pgpKeyMan.c,v 1.141 2002/10/29 04:50:59 ajivsov Exp $
____________________________________________________________________________*/
#include <string.h>

#include "pgpConfig.h"
#include "pgpSDKPriv.h"		/* DO NOT REMOVE */

#include "pgpContext.h"
#include "pgpEncodePriv.h"
#include "pgpEventPriv.h"
#include "pgpDebug.h"
#include "pgpKeyPriv.h"
#include "pgpPubKey.h"
#include "pgpRandomX9_17.h"
#include "pgpRandomPool.h"
#include "pgpSigSpec.h"
#include "pgpStr2Key.h"
#include "pgpKeySpec.h"
#include "pgpHash.h"
#include "pgpEnv.h"
#include "pgpP11Key.h"
#include "pgpTokenLib.h"
#include "pgpRegExp.h"
#include "pgpTimeDate.h"
#include "pgpTrustPriv.h"
#include "pgpUtilitiesPriv.h"
#include "pgpRandomPoolPriv.h"
#include "pgpRnd.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpX509Priv.h"
#include "pgpPassCach.h"

#define MAXRSABITS		4096

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

/*  INTERNAL FUNCTIONS */

/*
 * Internal functions for certifying a key or userid.
 *
 *  Sigspec holds the information about the kind of signature to make.
 *  It is automatically freed after the sig itself is created, or if there
 *  is an error in trying to modify it.
 */

#define SIG_EXPORTABLE			TRUE
#define SIG_NON_EXPORTABLE		FALSE
#define SIG_EXPORTABLEHASHED	TRUE
#define SIG_EXPORTABLEUNHASHED	FALSE

extern PGPMutex_t sRpcMutex;

static PGPError
sCreateSigSpec(
	PGPContextRef 		context,
	PGPKeyDBObj		   *signer,
	PGPByte 			sigtype,
	char const 			*passphrase,
	PGPSize 			passphraseLength,
	PGPBoolean 			hashedPhrase,
	PGPUInt32			cacheTimeOut,
	PGPBoolean			cacheGlobal,
	PGPSigSpec		  **psigspec)
{
    PGPSigSpec		*sigspec = NULL;
	PGPEnv			*pgpEnv;
	PGPError		error = kPGPError_NoErr;

	pgpEnv = pgpContextGetEnvironment( context );

	/* Error if not enough entropy for a safe signature */
	if( ! PGPGlobalRandomPoolHasMinimumEntropy() )
		return kPGPError_OutOfEntropy;
	
	if (IsntNull(passphrase) && passphraseLength == 0)
		passphrase = NULL;

	if (!signer || !pgpKeyIsSec (signer) ||
		!(pgpKeyUse (signer) & PGP_PKUSE_SIGN))
	    return kPGPError_SecretKeyNotFound;

	if( !pgpSecPassphraseOK( signer, (PGPByte *) passphrase,
						passphraseLength, hashedPhrase, cacheTimeOut,
						cacheGlobal  ) )
		return kPGPError_BadPassphrase;
    sigspec = pgpSigSpecCreate (pgpEnv, signer, sigtype);
    if (!sigspec)
	    return kPGPError_OutOfMemory;
	pgpSigSpecSetPassphrase( sigspec, (PGPByte *) passphrase,
					passphraseLength, hashedPhrase );

	*psigspec = sigspec;
	return error;
}

	static PGPError
sSigSpecAddRAK(
	PGPSigSpec			*sigspec,
	PGPKeySet			*rakset,
	PGPUInt32			rakclass)
{
	PGPKeyDBObj		*krkey;
	PGPKeyIter		*rakIter;
	PGPError		err = kPGPError_NoErr;

	/* Handle revocation authorizations */
	pgpAssert( IsntNull( rakset ) );

	err = PGPNewKeyIterFromKeySet( rakset, &rakIter );
	if (IsPGPError( err )) {
		pgpSigSpecDestroy (sigspec);
		return err;
	}
	while( IsntPGPError( PGPKeyIterNextKeyDBObj( rakIter,
				kPGPKeyDBObjType_Key, &krkey ) ) ) {
		PGPByte krinfo[22];
		PGPByte pkalg;

		/* Note that rakclass must have 0x80 set to be effective */
		pgpKeyID8 (krkey, &pkalg, NULL);
		krinfo[0] = rakclass;
		krinfo[1] = pkalg;
		pgpKeyFingerprint20 (krkey, krinfo+2);
		err = pgpSigSpecSetRevocationKey (sigspec, 0, krinfo,
										  sizeof(krinfo) );
		if (IsPGPError(err)) {
			pgpSigSpecDestroy (sigspec);
			PGPFreeKeyIter (rakIter);
			return err;
		}
	}
	PGPFreeKeyIter (rakIter);
	/* Make this signature non-revocable */
	pgpSigSpecSetRevocable (sigspec, 0, FALSE);

	return kPGPError_NoErr;
}

	static PGPError
sSigSpecSetExportability(
	PGPSigSpec			*sigspec,
	PGPBoolean 			exportable,
	PGPBoolean 			exportableHashed)
{
	if (!exportable) {
		pgpSigSpecSetExportable (sigspec,
							 (exportableHashed ? 0 : kPGPSigFlags_Unhashed),
							 exportable);
	}
	return kPGPError_NoErr;
}


static PGPError
sSigSpecSetTimes(
	PGPSigSpec			*sigspec,
	PGPTime				sigCreation,
	PGPUInt32 			sigExpiration)
{
	PGPContextRef	 context;
	PGPEnv			*pgpEnv;

	context = pgpSigSpecContext( sigspec );
	pgpEnv = pgpContextGetEnvironment( context );

	if( sigCreation != 0 )
		pgpSigSpecSetTimestamp( sigspec, sigCreation +
				(60 * 60 * pgpenvGetInt(pgpEnv, PGPENV_TZFIX,  NULL, NULL)));
	
	if (sigExpiration)
		pgpSigSpecSetSigExpiration (sigspec, 0, sigExpiration);

	return kPGPError_NoErr;
}


static PGPError
sSigSpecSetTrustParams(
	PGPSigSpec		   *sigspec,
	PGPKeyDB		   *kdb,
	PGPByte 			trustDepth,
	PGPByte 			trustValue,
	char const 			*sRegExp)
{
	PGPEnv				*pgpEnv;
	PGPContextRef		context;

	if( IsntNull( sRegExp ) )
		pgpSigSpecSetRegExp (sigspec, 0, sRegExp);

	context = PGPPeekKeyDBContext( kdb );
	pgpEnv = pgpContextGetEnvironment( context );

	/* Ignore trustValue for ordinary level 0 signatures */
	if (trustDepth != 0) {
		/* Convert trust value to extern format */
		if (trustValue != 0)
			trustValue = pgpTrustOldToExtern(pgpEnv, trustValue);
		/* Note that setting nonzero trustvalue forces V4 sigs */
		pgpSigSpecSetTrustLevel (sigspec, 0, trustDepth, trustValue);
	}

	return kPGPError_NoErr;
}

/* Create the certification based on info in sigspec */
static PGPError
sCertifyObject(
	PGPSigSpec		   *sigspec,
	PGPKeyDBObj		   *signee)
{
	PGPContextRef		context;
	PGPBoolean		 	selfsig = FALSE;
	PGPKeyDBObj *	 	parent;
 	PGPKeyDBObj *	  	signer;
	PGPByte			 	sigtype;
	PGPInt32			pkalg;
    PGPError		 	error = kPGPError_NoErr;

	context = pgpSigSpecContext( sigspec );
	sigtype = pgpSigSpecSigType( sigspec );
	signer = pgpSigSpecSeckey( sigspec );
	pgpGetKeyNumber( signer, kPGPKeyProperty_AlgorithmID, &pkalg );

	parent = PGPPeekKeyDBObjKey( signee );
	if( parent == signer )
		selfsig = TRUE;

	if (pkalg > kPGPPublicKeyAlgorithm_RSA &&
			sigtype == PGP_SIGTYPE_KEY_GENERIC && selfsig) {
		/* Propagate sig subpacket information */
		PGPByte const *p;
		PGPSize plen;
		PGPBoolean hashed;
		PGPError dumerr;
		pgpSigSpecSetVersion (sigspec, PGPVERSION_4);
		if ((p=pgpKeyFindSubpacket (signer,
				SIGSUB_PREFERRED_ENCRYPTION_ALGS, 0,
				&plen, NULL, &hashed, NULL, NULL, &dumerr)) != 0
			&& hashed) {
			pgpSigSpecSetPrefAlgs (sigspec, 0, p, plen);
		}
		if (pgpKeyExpiration (signer)) {
			PGPUInt32 period = pgpKeyExpiration (signer) -
				pgpKeyCreation (signer);
			pgpSigSpecSetKeyExpiration (sigspec, 0, period);
		}
	}
	
	/* Due to a bug in 5.0, all sigs directly on keys must be version 2_6.
	 * However the only signatures 5.0 handles directly on keys are key
	 * revocations.
	 */
	if (pgpObjectType( signee ) == RINGTYPE_KEY &&
			!pgpKeyIsSubkey( signee )  &&
			sigtype == PGP_SIGTYPE_KEY_REVOKE ) {
		pgpSigSpecSetVersion( sigspec, PGPVERSION_3 );
	}

	/* Perform the signature calculation */
	error = pgpSignObject (signee, sigspec);
	pgpKeyDBChanged( PGPPeekKeyDBObjKeyDB(signee), TRUE );

	pgpSigSpecDestroy (sigspec);

	return error;
}



/*  Check for a 'dead' key.  A dead key is revoked or expired. 
	There's not much you can do with such a key. */

	static PGPError
pgpKeyDeadCheck( PGPKeyDBObjRef	key)
{
    PGPBoolean	revoked, expired;
    PGPError	err;
	
	err	= pgpGetKeyBoolean (key, kPGPKeyProperty_IsRevoked, &revoked);
	if ( IsntPGPError( err ) && revoked )
		err	= kPGPError_KeyRevoked;
	
	if ( IsntPGPError( err ) )
	{
		err	= pgpGetKeyBoolean (key, kPGPKeyProperty_IsExpired, &expired);
		if ( IsntPGPError( err ) && expired )
			err	= kPGPError_KeyExpired;
	}
	
	return ( err );
}


/* Same for subkey... */

static PGPBoolean
pgpSubKeyIsDead (PGPKeyDBObjRef subkey)
{
    PGPBoolean   revoked, expired;
	
	pgpGetSubKeyBoolean (subkey, kPGPSubKeyProperty_IsRevoked, &revoked);
	pgpGetSubKeyBoolean (subkey, kPGPSubKeyProperty_IsExpired, &expired);
	return (revoked || expired);
}


#if 0
/*  Find the default private key.  Get the name (or keyid) from the 
	environment, and find the PGPKeyDBObj.  If there is no default 
	key defined in the environment, return NULL unless there is 
	only one private key in the key database.
	*/

	static PGPError
pgpGetDefaultPrivateKeyInternal(
	PGPKeyDBRef	keyDB,
	PGPKeyDBObj **	outKey)
{
	PGPError			err			= kPGPError_NoErr;
	PGPByte *			keyIDData	= NULL;
	void *				vkeyIDData;
	PGPSize				keyIDSize	= 0;
	PGPContextRef		context		= PGPPeekKeyDBContext( keyDB );
	
	PGPValidatePtr( outKey );
	*outKey	= kInvalidPGPKeyDBObjRef;
	
	err	= PGPsdkPrefGetData( context, kPGPsdkPref_DefaultKeyID,
				&vkeyIDData, &keyIDSize );
	keyIDData = vkeyIDData;
	if ( IsntPGPError( err ) )
	{
		PGPKeyID		keyID;
		
		err	= PGPImportKeyID( keyIDData, &keyID );
		if ( IsntPGPError( err ) )
		{
			err	= PGPGetKeyByKeyID( keyDB, &keyID,
						kPGPPublicKeyAlgorithm_Invalid, outKey );
		}
		
		/* we used public API call; must free using PGPFreeData() */
		PGPFreeData( keyIDData );
	}
	
	return err;
}
#endif

static PGPInt32
sGetKeyTokenNum( PGPKeyDBObj *key )  
{
	PGPKeyInfo *kinfo;

	if( !pgpKeyIsOnToken(key) )
		return -1;

	pgpAssert(OBJISKEY(key));

	kinfo = pgpKeyToKeyInfo( key );

	return kinfo->tokenNum1 - 1;
}

/*  END OF INTERNAL FUNCTIONS */



/* This is also called on the backend for revoking subkeys */
	PGPError
pgpRevokeKey_internal (
	PGPKeyDBObjRef		key,
	char const *		passphrase,
	PGPSize				passphraseLength,
	PGPBoolean			hashedPhrase,
	PGPUInt32			cacheTimeOut,
	PGPBoolean			cacheGlobal
	)
{
    PGPKeyDBRef			 keys = NULL;
	PGPContextRef		 context;
	PGPKeyDBObj      	*signkey = NULL;
	PGPUInt32			 revnum = 0;
	PGPSigSpec *		 sigspec;
	PGPError			 error = kPGPError_NoErr;
	
	if( pgpObjectType( key ) == RINGTYPE_SUBKEY )
		return pgpRevokeSubKey_internal( key, passphrase, passphraseLength,
							hashedPhrase, cacheTimeOut, cacheGlobal );
	
	keys =	PGPPeekKeyDBObjKeyDB( key );
	context =	PGPPeekKeyDBContext( keys );

	if ( IsPGPError( pgpKeyDeadCheck(key) ) )
	   return kPGPError_NoErr;	/* no need */
	
	for ( ; ; ) {
		signkey = key;
		/* See if we have an authorized revocation signature */
		if (!pgpKeyIsSec (key)) {
			PGPByte revclass;
			signkey = pgpKeyRevocationKey (key, revnum++, NULL, NULL,
											  &revclass, NULL, &error);
			if( IsPGPError( error ) ) {
				if( error == kPGPError_ItemNotFound )
					error = kPGPError_NoErr;
				break;
			}
			if( IsNull( signkey ) )
				continue;
			if (!(revclass & 0x80))
				continue;
			if (!pgpKeyIsSec (signkey))
				continue;
		}
		error = sCreateSigSpec( context, signkey, PGP_SIGTYPE_KEY_REVOKE,
								passphrase, passphraseLength, hashedPhrase,
								cacheTimeOut, cacheGlobal, &sigspec );
		if( IsntPGPError( error ) )
			error = sCertifyObject( sigspec, key );

		/* Retry if bad passphrase and we are an authorized revoker */
		if (error != kPGPError_BadPassphrase || signkey == key)
			break;
	}

	return error;
}
 

static const PGPOptionType revkeyOptionSet[] = {
	kPGPOptionType_Passphrase,
	kPGPOptionType_Passkey,
	kPGPOptionType_CachePassphrase
};

	PGPError
pgpRevokeKeyInternal(
	PGPKeyDBObjRef			key,
	PGPOptionListRef	optionList )
{
	char *				passphrase;
	PGPSize				passphraseLength;
	PGPBoolean			hashedPhrase = FALSE;
	PGPUInt32			cacheTimeOut = 0;
	PGPBoolean			cacheGlobal;
	PGPError			err = kPGPError_NoErr;

	pgpa(pgpaPGPKeyValid(key));
	PGPValidateKey( key );

	if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
						revkeyOptionSet, elemsof( revkeyOptionSet ) ) ) )
		return err;

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

⌨️ 快捷键说明

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