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

📄 pgpencode.c

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

	$Id: pgpEncode.c,v 1.31 2002/11/15 04:40:11 ajivsov Exp $
____________________________________________________________________________*/
/*
 * pgpEncode.c -- High level encode functionality
 */
#include "pgpConfig.h"

#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 "pgpKeyPriv.h"
#include "pgpMem.h"
#include "pgpMemMod.h"
#include "pgpOptionList.h"
#include "pgpPipeline.h"
#include "pgpPubKey.h"
#include "pgpRandomPoolPriv.h"
#include "pgpRndSeed.h"
#include "pgpSigSpec.h"
#include "pgpTextFilt.h"
#include "pgpVMemMod.h"
#include "pgpX509Priv.h"
#include "pgpFIPSPriv.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 */
	PGPBoolean		oldkeys;			/* Had old keys in a set  */
};
typedef struct PGPPreferredAlgs_ PGPPreferredAlgs;

#define kPGPCipherAlgorithm_Last	kPGPCipherAlgorithm_Twofish256

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

	algInfo->oldkeys = FALSE;
	
	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,
	PGPKeyDBObj			*key
	)
{
	PGPByte const		*prefs;
	PGPSize				 plen;
	PGPByte				 algDefault[3];
	PGPByte				 alg;
	PGPUInt32			 i;
	PGPBoolean			 hashed;
	PGPError			 err;

	if( pgpFIPSModeEnabled() )
	{
		/* Force the use of 3DES */
		algDefault[0] = kPGPCipherAlgorithm_3DES;
		prefs = algDefault;
		plen = 1;
	}
	else
	{
		PGPByte pkalg;
		PGPBoolean oldkeys; 
		
		pgpKeyID8 ( key, &pkalg, NULL );
		oldkeys = (pkalg <= kPGPPublicKeyAlgorithm_RSA+2  && pgpKeyV3(key));

		prefs = pgpKeyFindSubpacket (key,
						SIGSUB_PREFERRED_ENCRYPTION_ALGS,
						0, &plen, NULL, &hashed, NULL, NULL, &err);
		
		if( IsNull( prefs )  || !hashed ) {
			/* Use a default.  RSA V3 keys get IDEA, later get 3DES. */
			if (oldkeys) {
				algDefault[0] = kPGPCipherAlgorithm_IDEA;
				prefs = algDefault;
				plen = 1;
			} else {
				algDefault[0] = kPGPCipherAlgorithm_3DES;
				algDefault[1] = kPGPCipherAlgorithm_CAST5;
				algDefault[2] = kPGPCipherAlgorithm_IDEA;
				prefs = algDefault;
				plen = 3;
			}
		}
		if( oldkeys && ! algInfo->oldkeys )
			algInfo->oldkeys = oldkeys;
	}
	
	++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;
}


/*
 * 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. 
	 * Treat it as unordered set */
	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];
			/* no voting is done here */
		}
	}

	/* 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;
			/* Choose favorite of others from algInfo. 
			 * Some of those alg preferences can be generated by us */
			if( bestalg == 0  ||  algInfo->votes[i] < bestvote ) {
				/* First acceptable, or best one so far */
				bestvote = algInfo->votes[i];
				bestalg = i+1;
			}
		}
	}

	/* If still no acceptable algorithms, choose most acceptable one */
	if (algsOK == 0) {
		/* Choose an algorithm which we support and most people accept */
		for( i=0; i<algInfo->n; ++i ) {
			if( IsNull( pgpCipherGetVTBL( (PGPCipherAlgorithm)(i+1) ) ) )
				continue;
			algsOK += 1;
			if ( bestalg == 0 || algInfo->algok[i] > bestvote ) {
				/* First acceptable, or best one so far */
				bestvote = algInfo->algok[i];
				bestalg = i+1;
			}
		}
	}
	
	if (algsOK == 0) {
		/* None of the algs we support are acceptable to anyone;
		 * choose IDEA if at least one key is old, else 3DES. */
		algsOK = 1;

⌨️ 快捷键说明

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