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

📄 pgpencode.c

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

	$Id: pgpEncode.c,v 1.107 1999/05/07 23:47:45 hal Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"	/* or pgpConfig.h in the CDK */

#include <string.h>

/* Public headers */
#include "pgpPubTypes.h"
#include "pgpContext.h"
#include "pgpEncode.h"
#include "pgpErrors.h"
#include "pgpKeys.h"
#include "pgpMem.h"

/* Private headers */
#include "pgpDebug.h"
#include "pgpEncodePriv.h"
#include "pgpAnnotate.h"
#include "pgpArmor.h"
#include "pgpBufMod.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpConvKey.h"
#include "pgpDevNull.h"
#include "pgpEncPipe.h"
#include "pgpEnv.h"
#include "pgpEventPriv.h"
#include "pgpFile.h"
#include "pgpFileMod.h"
#include "pgpFileRef.h"
#include "pgpFileSpec.h"
#include "pgpFileType.h"
#include "pgpHash.h"
#include "pgpKeyDB.h"
#include "pgpKDBInt.h"
#include "pgpMem.h"
#include "pgpMemMod.h"
#include "pgpOptionList.h"
#include "pgpPipeline.h"
#include "pgpPubKey.h"
#include "pgpRandomPoolPriv.h"
#include "pgpRndSeed.h"
#include "pgpRngPub.h"
#include "pgpSigSpec.h"
#include "pgpTextFilt.h"
#include "pgpTrstPkt.h"
#include "pgpVMemMod.h"
#include "pgpX509Priv.h"

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


/*********************** Helper functions for below ************************/


/* Set up PGPEnv structure for library internals */

	static PGPError
pgpMakeEnvFromOptionList(
	PGPOptionListRef	 optionList,
	PGPEnv				*env
	)
{
	PGPError		 err;				/* Error flag */
	PGPUInt32		 hashalg;			/* Default hash alg */
	PGPUInt32		 cipheralg;			/* Default cipher alg */
	PGPUInt32		 fOption;			/* Generic option flag */
	PGPBoolean		 fDefault;			/* True if have the option from usr */
	char			*comment;			/* Comment string for output */
	char			*version;			/* Version string for output */

	/* Ascii armor mode */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_ArmorOutput, FALSE,
						 "%d", &fOption ) ) )
		goto error;
	pgpenvSetInt( env, PGPENV_ARMOR, fOption, PGPENV_PRI_FORCE );

	/* Text mode (as compared to binary) */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_DataIsASCII, FALSE,
						 "%d", &fOption ) ) )
		goto error;
	pgpenvSetInt( env, PGPENV_TEXTMODE, fOption, PGPENV_PRI_FORCE );

	/* Control of compression (default on) */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_Compression, FALSE,
						 "%b%d", &fDefault, &fOption ) ) )
		goto error;
	if( !fDefault )
		fOption = TRUE;
	pgpenvSetInt( env, PGPENV_COMPRESS, fOption, PGPENV_PRI_FORCE );

	/* Clearsign mode, implies textmode and ascii armor */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_ClearSign, FALSE,
						 "%d", &fOption ) ) )
		goto error;
	if( fOption ) {
		pgpenvSetInt( env, PGPENV_CLEARSIG, TRUE, PGPENV_PRI_FORCE );
		pgpenvSetInt( env, PGPENV_TEXTMODE, TRUE, PGPENV_PRI_FORCE );
		pgpenvSetInt( env, PGPENV_ARMOR, TRUE, PGPENV_PRI_FORCE );
	} else {
		pgpenvSetInt( env, PGPENV_CLEARSIG, FALSE, PGPENV_PRI_FORCE );
	}

	/* PGP-MIME output, implies ascii armor */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_PGPMIMEEncoding, FALSE,
						 "%b%d", &fDefault, &fOption ) ) )
		goto error;
	if( fDefault ) {
		pgpenvSetInt( env, PGPENV_PGPMIME, fOption, PGPENV_PRI_FORCE );
		pgpenvSetInt( env, PGPENV_ARMOR, TRUE, PGPENV_PRI_FORCE );
	}
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_OmitMIMEVersion, FALSE,
						 "%d", &fOption ) ) )
		goto error;
	pgpenvSetInt( env, PGPENV_PGPMIMEVERSIONLINE, !fOption, PGPENV_PRI_FORCE );

	/* Non-default hash algorithm */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_HashAlgorithm, FALSE,
						 "%b%d", &fDefault, &hashalg ) ) )
		goto error;
	if( fDefault ) {
		pgpenvSetInt( env, PGPENV_HASH, hashalg, PGPENV_PRI_FORCE );
	}

	/* Non-default cipher algorithm - only effective with conv encr */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_CipherAlgorithm, FALSE,
						 "%b%d", &fDefault, &cipheralg ) ) )
		goto error;
	if( fDefault ) {
		if( IsNull( pgpCipherGetVTBL ( (PGPCipherAlgorithm)cipheralg ) ) ) {
			pgpDebugMsg( "Unsupported cipher algorithm" );
			err = kPGPError_FeatureNotAvailable;
			goto error;
		}
		pgpenvSetInt( env, PGPENV_CIPHER, cipheralg, PGPENV_PRI_FORCE );
	}

	/* Comment string */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_CommentString, FALSE,
						 "%b%p", &fDefault, &comment ) ) )
		goto error;
	if( fDefault ) {
		pgpenvSetString( env, PGPENV_COMMENT, comment, PGPENV_PRI_FORCE );
	}

	/* Comment string */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_VersionString, FALSE,
						 "%b%p", &fDefault, &version ) ) )
		goto error;
	if( fDefault ) {
		pgpenvSetString( env, PGPENV_VERSION_STRING,
						 version, PGPENV_PRI_FORCE );
	}
	return kPGPError_NoErr;

error:
	return err;
}





/* Preferred algorithm calculations */

/* Data structure to record preferences of recipients */
struct PGPPreferredAlgs_ {
	PGPUInt32		 n;					/* Number of algorithms */
	PGPByte			*algok;				/* # recips who can accept this */
	PGPUInt32		*votes;				/* Preference voting, lower=better */
	PGPUInt32		counts;				/* Number of recips */
};
typedef struct PGPPreferredAlgs_ PGPPreferredAlgs;


/* Init the structure we will use to choose the conv encryption alg */

	static PGPError
pgpInitPreferredAlgorithms(
	PGPContextRef	 	 context,
	PGPPreferredAlgs	*algInfo
	)
{
	PGPUInt32			n;
	PGPError			err;

	pgpa( pgpaAddrValid( algInfo, PGPPreferredAlgs ) );

	pgpClearMemory( algInfo, sizeof( *algInfo ) );
	
	n = kPGPCipherAlgorithm_Last + 1;
	
	algInfo->n = n;
	algInfo->algok = (PGPByte *)pgpContextMemAlloc( context, n, 0 );
	if ( IsNull( algInfo->algok ) ) {
		err = kPGPError_OutOfMemory;
		goto error;
	}
	algInfo->votes = (PGPUInt32 *)
		pgpContextMemAlloc( context, n * sizeof( PGPUInt32 ), 0 );
	if ( IsNull( algInfo->votes ) ) {
		err = kPGPError_OutOfMemory;
		goto error;
	}
	pgpClearMemory( algInfo->algok, n );
	pgpClearMemory( algInfo->votes, n * sizeof( PGPUInt32 ) );
	return kPGPError_NoErr;

error:
	if( IsntNull( algInfo->algok ) )
		pgpContextMemFree( context, algInfo->algok );
	if( IsntNull( algInfo->votes ) )
		pgpContextMemFree( context, algInfo->votes );
	return err;
}
	
/*
 * Add info for the preferred algs for one recipient.   We record which algs
 * are acceptable and then use preference voting.
 */

	static PGPError
pgpCheckPreferredAlgorithms(
	PGPPreferredAlgs	*algInfo,
	PGPKey				*key,
	RingSet const		*ringSet
	)
{
	RingObject			*ringObj;
	PGPByte const		*prefs;
	PGPSize				 plen;
	PGPByte				 algDefault[3];
	PGPByte				 alg;
	PGPUInt32			 i;
	PGPError			 err;


	if( IsPGPError( err = pgpGetKeyRingObject( key, TRUE, &ringObj ) ) )
		goto error;

	prefs = ringKeyFindSubpacket (ringObj, ringSet,
					SIGSUB_PREFERRED_ENCRYPTION_ALGS,
					0, &plen, NULL, NULL, NULL, NULL, &err);
	if( IsNull( prefs ) ) {
		/* Use a default.  RSA keys get IDEA, later get CAST.  */
		PGPByte pkalg;
		ringKeyID8 (ringSet, ringObj, &pkalg, NULL);
		if (pkalg <= kPGPPublicKeyAlgorithm_RSA+2) {
			algDefault[0] = kPGPCipherAlgorithm_IDEA;
			prefs = algDefault;
			plen = 1;
		} else {
			algDefault[0] = kPGPCipherAlgorithm_CAST5;
			algDefault[1] = kPGPCipherAlgorithm_IDEA;
			algDefault[2] = kPGPCipherAlgorithm_3DES;
			prefs = algDefault;
			plen = 3;
		}
	}

	++algInfo->counts;
	for( i=0; i<plen; ++i ) {
		alg = prefs[i];
		if( alg > algInfo->n )
			continue;
		algInfo->votes[alg-1] += i;	  /* Preference voting, lower=better */
		++algInfo->algok[alg-1];
	}
	return kPGPError_NoErr;
error:
	return err;
}


/*
 * Choose the most popular algorithm of those which were acceptable to all,
 * taking into consideration sender preferences if any
 */

	static PGPError
pgpSetPreferredAlgorithm(
	PGPOptionListRef	 optionList,
	PGPPreferredAlgs	*algInfo,
	PGPEnv				*env
	)
{
	PGPUInt32			 bestvote = 0;	/* Silence warning */
	PGPUInt32			 bestalg = 0;
	PGPUInt32			 i;
	PGPUInt32			 algsOK = 0;	/* Number of acceptable algs */
	PGPCipherAlgorithm	*prefalg;
	PGPCipherAlgorithm	 alg;
	PGPSize				 prefalgLength;
	PGPError			 err = kPGPError_NoErr;

	/* See if sender has a preferred algorithm specification */
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						kPGPOptionType_PreferredAlgorithms, FALSE,
						"%p%l", &prefalg, &prefalgLength ) ) )
		goto error;
	/* Convert prefalgLength from bytes to number of entries */
	prefalgLength /= sizeof(PGPCipherAlgorithm);
	
	/* If so, let sender have a veto vote too */
	if( prefalgLength != 0 ) {
		++algInfo->counts;
		for( i=0; i<prefalgLength; ++i ) {
			alg = prefalg[i];
			if( (PGPUInt32)alg > algInfo->n )
				continue;
			++algInfo->algok[alg-1];
			/* Don't bother with a preference vote, handled below */
		}
	}

	/* Loop for all algorithms we know about, see how many are OK */
	for( i=0; i<algInfo->n; ++i ) {
		if( algInfo->algok[i] == algInfo->counts ) {
			/* This algorithm was acceptable to all */
			/* Skip if not supported by this library */
			if( IsNull( pgpCipherGetVTBL( (PGPCipherAlgorithm)(i+1) ) ) )
				continue;
			algsOK += 1;
			if (prefalgLength != 0) {
				PGPUInt32 j;
				/* Choose acceptable algorithm which sender likes best */
				for( j=0; j<prefalgLength; ++j ) {
					if (prefalg[j] == (PGPCipherAlgorithm)(i+1))
						break;
				}
				pgpAssert (j < prefalgLength);
				if( bestalg == 0 || j < bestvote ) {
					/* First acceptable, or best one so far */
					bestvote = j;
					bestalg = i+1;
				}
			} else {
				/* Case of no sender preferences, choose favorite of others */
				if( bestalg == 0  ||  algInfo->votes[i] < bestvote ) {
					/* First acceptable, or best one so far */
					bestvote = algInfo->votes[i];
					bestalg = i+1;
				}
			}
		}
	}


	/* If no choice OK for all, choose sender's favorite if any */
	if (algsOK == 0 && prefalgLength != 0) {
		for (i=0; i<prefalgLength; ++i) {
			/* Find highest-sender-preference supported one */
			if( IsntNull( pgpCipherGetVTBL(
							   (PGPCipherAlgorithm) prefalg[i] ) ) ) {
				bestalg = prefalg[i];
				algsOK = 1;
				break;
			}
		}
	}
	
	/* If still no acceptable algorithms, choose most acceptable one */

⌨️ 快捷键说明

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