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

📄 pgpkeyman.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*____________________________________________________________________________
	Copyright (C) 1997 Network Associates Inc. and affiliated companies.
	All rights reserved.

	$Id: pgpKeyMan.c,v 1.208 1999/05/17 05:08:11 hal Exp $
____________________________________________________________________________*/
#include <string.h>

#include "pgpConfig.h"

#include "pgpContext.h"
#include "pgpEncodePriv.h"
#include "pgpEventPriv.h"
#include "pgpKDBInt.h"
#include "pgpDebug.h"
#include "pgpRngPub.h"
#include "pgpRngRead.h"
#include "pgpPubKey.h"
#include "pgpRandomX9_17.h"
#include "pgpRandomPool.h"
#include "pgpSigSpec.h"
#include "pgpStr2Key.h"
#include "pgpKeySpec.h"
#include "pgpTrstPkt.h"
#include "pgpTrust.h"
#include "pgpHash.h"
#include "pgpEnv.h"
#include "pgpSDKPrefs.h"
#include "bn.h"
#include "pgpRegExp.h"
#include "pgpRngPub.h"
#include "pgpRngMnt.h"
#include "pgpTimeDate.h"
#include "pgpKeyIDPriv.h"
#include "pgpUtilitiesPriv.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpX509Priv.h"


#define MAXRSABITS		2048

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

/*  INTERNAL FUNCTIONS */

/*  Internal function for certifying a key or userid.  Object to be signed 
	must be	in dest.  Signing key should be in src.  selfsig should be
    set for self-certifying names. */

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

static PGPError
pgpCertifyObject(
	PGPContextRef 		context,
	union RingObject 	*to_sign,
	RingSet	 			*dest,
	union RingObject 	*signer,
	RingSet const 		*src, 
	PGPByte 			sigtype,
	char const 			*passphrase,
	PGPSize 			passphraseLength,
	PGPBoolean 			hashedPhrase,
	PGPBoolean 			selfsig,
	PGPBoolean 			exportable,
	PGPBoolean 			exportableHashed,
	PGPTime				sigCreation,
	PGPUInt32 			sigExpiration,
	PGPByte 			trustDepth,
	PGPByte 			trustValue,
	char const 			*sRegExp,
	RingSet const		*rakset,
	PGPUInt32			rakclass
	)
{
    PGPSecKey		*seckey = NULL;
    PGPSigSpec		*sigspec = NULL;
	PGPEnv			*pgpEnv;
	PGPRandomContext *pgpRng;
	RingIterator	*rakIter;
    PGPError		error = kPGPError_NoErr;

	pgpEnv = pgpContextGetEnvironment( context );
	pgpRng = pgpContextGetX9_17RandomContext( context );

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

	if (!signer || !ringKeyIsSec (src, signer) ||
		!(ringKeyUse (src, signer) & PGP_PKUSE_SIGN))
	    return kPGPError_SecretKeyNotFound;

    seckey = ringSecSecKey (src, signer, PGP_PKUSE_SIGN);
    if (!seckey)
	    return ringSetError(src)->error;
    if (pgpSecKeyIslocked (seckey)) {
	    if (IsNull( passphrase )) {
		    pgpSecKeyDestroy (seckey);
			return kPGPError_BadPassphrase;
		}
	    error = (PGPError)pgpSecKeyUnlock (seckey, pgpEnv, passphrase, 
								 passphraseLength, hashedPhrase);
		if (error != 1)
		{
	        pgpSecKeyDestroy (seckey);
			if (error == 0)
			    error = kPGPError_BadPassphrase;
			return error;
	    }
    }
    sigspec = pgpSigSpecCreate (pgpEnv, seckey, sigtype);
    if (!sigspec) {
	    pgpSecKeyDestroy (seckey);
	    return kPGPError_OutOfMemory;
    }
	if (seckey->pkAlg > kPGPPublicKeyAlgorithm_RSA + 2 &&
			sigtype == PGP_SIGTYPE_KEY_GENERIC && selfsig) {
		/* Propagate sig subpacket information */
		PGPByte const *p;
		PGPSize plen;
		pgpSigSpecSetVersion (sigspec, PGPVERSION_4);
		if ((p=ringKeyFindSubpacket (signer, src,
				SIGSUB_PREFERRED_ENCRYPTION_ALGS, 0,
				&plen, NULL, NULL, NULL, NULL, NULL)) != 0) {
			pgpSigSpecSetPrefAlgs (sigspec, 0, p, plen);
		}
		if (ringKeyExpiration (src, signer)) {
			PGPUInt32 period = ringKeyExpiration (src, signer) -
				ringKeyCreation (src, signer);
			pgpSigSpecSetKeyExpiration (sigspec, 0, period);
		}
	}
	if (!exportable) {
		pgpSigSpecSetExportable (sigspec,
							 (exportableHashed ? 0 : kPGPSigFlags_Unhashed),
							 exportable);
	}
	
	if( sigCreation != 0 )
	{
		pgpSigSpecSetTimestamp( sigspec, sigCreation +
				(60 * 60 * pgpenvGetInt(pgpEnv, PGPENV_TZFIX,  NULL, NULL)));
	}
	
	if (sigExpiration)
		pgpSigSpecSetSigExpiration (sigspec, 0, sigExpiration);
	if( IsntNull( sRegExp ) )
		pgpSigSpecSetRegExp (sigspec, 0, sRegExp);

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

	/* 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 (ringObjectType( to_sign ) == RINGTYPE_KEY &&
			!ringKeyIsSubkey( dest, to_sign )  &&
			sigtype == PGP_SIGTYPE_KEY_REVOKE ) {
		pgpSigSpecSetVersion( sigspec, PGPVERSION_3 );
	}

	/* Handle revocation authorizations */
	if( IsntNull( rakset ) ) {
		rakIter = ringIterCreate (rakset);
		if (!rakIter) {
			pgpSecKeyDestroy (seckey);
			pgpSigSpecDestroy (sigspec);
			return ringSetError(rakset)->error;
		}
		while (ringIterNextObject (rakIter, 1) > 0) {
			PGPByte krinfo[22];
			PGPByte pkalg;
			RingObject *krkey = ringIterCurrentObject (rakIter, 1);
			/* Note that rakclass must have 0x80 set to be effective */
			ringKeyID8 (rakset, krkey, &pkalg, NULL);
			krinfo[0] = rakclass;
			krinfo[1] = pkalg;
			ringKeyFingerprint20 (rakset, krkey, krinfo+2);
			error = pgpSigSpecSetRevocationKey (sigspec, 0, krinfo,
												sizeof(krinfo) );
			if (IsPGPError(error)) {
				pgpSecKeyDestroy (seckey);
				pgpSigSpecDestroy (sigspec);
				ringIterDestroy (rakIter);
				return error;
			}
		}
		ringIterDestroy (rakIter);
		/* Make this signature non-revocable */
		pgpSigSpecSetRevocable (sigspec, 0, FALSE);
	}

	/* Do the signature at the Aurora level */
	error = ringSignObject (dest, to_sign, sigspec, pgpRng);
	pgpSecKeyDestroy (seckey);
	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( PGPKeyRef	key)
{
    PGPBoolean	revoked, expired;
    PGPError	err;
	
	err	= PGPGetKeyBoolean (key, kPGPKeyPropIsRevoked, &revoked);
	if ( IsntPGPError( err ) && revoked )
		err	= kPGPError_KeyRevoked;
	
	if ( IsntPGPError( err ) )
	{
		err	= PGPGetKeyBoolean (key, kPGPKeyPropIsExpired, &expired);
		if ( IsntPGPError( err ) && expired )
			err	= kPGPError_KeyExpired;
	}
	
	return ( err );
}


/* Same for subkey... */

static PGPBoolean
pgpSubKeyIsDead (PGPSubKeyRef subkey)
{
    PGPBoolean   revoked, expired;
	
	PGPGetSubKeyBoolean (subkey, kPGPKeyPropIsRevoked, &revoked);
	PGPGetSubKeyBoolean (subkey, kPGPKeyPropIsExpired, &expired);
	return (revoked || expired);
}


/*  Find the default private key.  Get the name (or keyid) from the 
	environment, and find the PGPKey object.  If there is no default 
	key defined in the environment, return NULL unless there is 
	only one private key in the key database.
	
	The refCount on the key is incremented by this routine.
	*/

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

/*  END OF INTERNAL FUNCTIONS */


/*  Copy an entire key to a new ringset.  The newly created ringset is
	returned.  This function is necessary for two reasons:
    1. ringRaiseName requires all names to be present on the ringset to have 
	   any effect. 
	2. to ensure a complete key (i.e. all it's sub-objects) are copied from 
	   a modified read-only key to a writable keyring. 
*/

PGPError
pgpCopyKey (RingSet const *src, union RingObject *obj, RingSet **dest)
{
	RingIterator *iter = NULL;
	int					 level;

	if (!ringSetIsMember (src, obj))
		return kPGPError_BadParams;
	*dest = ringSetCreate (ringSetPool (src));
	if (!*dest)
		return kPGPError_OutOfMemory;
	iter = ringIterCreate (src);
	if (!iter) {
		ringSetDestroy (*dest);
		return kPGPError_OutOfMemory;
	}

	ringIterSeekTo (iter, obj);
	ringIterRewind (iter, 2);   /* reset iterator to key object */
	/*  Loop adding objects until next key (level 1), or no more keys 
		(level 0) */
	while ((level = ringIterNextObjectAnywhere (iter)) > 1) {
		obj = ringIterCurrentObject (iter, level);
		ringSetAddObject (*dest, obj);
	}
	ringIterDestroy (iter);
	return kPGPError_NoErr;
}


/*  Given a key ring object, find the corresponding PGPKey object. */

PGPKey *
pgpGetKeyByRingObject (PGPKeyDBRef keyDB, union RingObject *keyobj)
{
	PGPKeyRef	keyptr;

	pgpAssert (ringObjectType (keyobj) == RINGTYPE_KEY);

	for (keyptr = keyDB->firstKeyInDB; keyptr; keyptr = keyptr->nextKeyInDB) {
		if (keyobj == keyptr->key)
			return keyptr;
	}
	return NULL;
}


static PGPError
sRevokeKey (
	PGPContextRef		context,
	PGPKeyRef			key,
	char const *		passphrase,
	PGPSize				passphraseLength,
	PGPBoolean			hashedPhrase
	)
{
    PGPKeyDBRef			 keys = NULL;
	RingSet	const *		allset = NULL;
	RingSet *			addset = NULL;
	union RingObject    *keyobj;
	union RingObject	*signkeyobj = NULL;
	PGPUInt32			 revnum;
	PGPError			 error = kPGPError_NoErr;
	
	keys =		key->keyDB;
	keyobj =	key->key;

	if ( !keys->objIsMutable( keys, keyobj ) )
		return kPGPError_ItemIsReadOnly;
	if ( IsPGPError( pgpKeyDeadCheck(key) ) )
	   return kPGPError_NoErr;	/* no need */
	
	allset = pgpKeyDBRingSet (keys);

	error = pgpCopyKey (allset, keyobj, &addset);
	if (error)
		return error;

	revnum = 0;
	for ( ; ; ) {
		signkeyobj = keyobj;
		/* See if we have an authorized revocation signature */
		if (!ringKeyIsSec (allset, keyobj)) {
			PGPByte revclass;
			signkeyobj = ringKeyRevocationKey (keyobj, allset, revnum++,
											   NULL, NULL,
											   &revclass, NULL, &error);
			if( IsPGPError( error ) ) {
				if( error == kPGPError_ItemNotFound )
					error = kPGPError_NoErr;
				break;
			}
			if( IsNull( signkeyobj ) )
				continue;
			if (!(revclass & 0x80))
				continue;
			if (!ringKeyIsSec (allset, signkeyobj))
				continue;
		}
		error = pgpCertifyObject (context, keyobj, addset, signkeyobj, allset, 
							 PGP_SIGTYPE_KEY_REVOKE, passphrase,
							 passphraseLength, hashedPhrase, FALSE,
							 SIG_EXPORTABLE, 0, 0, kPGPExpirationTime_Never,
							 0, 0, NULL, NULL, 0);
		/* Retry if bad passphrase and we are an authorized revoker */
		if (error != kPGPError_BadPassphrase || signkeyobj == keyobj)
			break;
	}

	if (error) {
		ringSetDestroy (addset);
		return error;
	}

	/*  Update the KeyDB */
	error = pgpAddObjects (keys, addset);
	ringSetDestroy (addset);

	/* Calculate trust changes as a result */
	if( error == kPGPError_NoErr )
		(void)pgpPropagateTrustKeyDB (keys);

	return error;
}
 

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

PGPError
pgpRevokeKeyInternal(
	PGPKeyRef			key,
	PGPOptionListRef	optionList )
{
	PGPContextRef		context;
	char *				passphrase;
	PGPSize				passphraseLength;
	PGPBoolean			hashedPhrase = FALSE;
	PGPError			err = kPGPError_NoErr;

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

	context = key->keyDB->context;

	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,
							"%p%l", &passphrase, &passphraseLength ) ) )
			goto error;
	}

	err = sRevokeKey( context, key, passphrase, passphraseLength,
					  hashedPhrase );
error:
	return err;
}


static const PGPOptionType keyentOptionSet[] = {
	kPGPOptionType_KeyGenParams,
	kPGPOptionType_KeyGenFast,
	kPGPOptionType_KeyGenUseExistingEntropy
};

⌨️ 快捷键说明

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