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

📄 pgprngread.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * pgpRngRead.c - Read in various parts of a keyring.
 *
 * The big function (>500 lines, yeep!) is ringFileOpen(); it opens another
 * keyring and merges it with the collection in memory.	 Most of the others
 * are its helpers.  This is where PGPlib's great robustness in the face of
 * badly mangled keyrings is achieved.	*Every* keyring comes through here,
 * and it validates its inputs to the point of paranoia.
 *
 * This file is too big - what should be split out?
 * There are a lot of similar-but-not-quite functions.	Perhaps some
 * rethinking will allow parts of them to be merged?
 *
 * Written by Colin Plumb.
 *
 * $Id: pgpRngRead.c,v 1.96 1999/04/14 05:45:21 hal Exp $
 */
#include "pgpConfig.h"

#include <errno.h>
#include <stdio.h>
#include <string.h>

#include "pgpDebug.h"
#include "pgpMakeSig.h"
#include "pgpMemPool.h"
#include "pgpPktByte.h"
#include "pgpRngMnt.h"
#include "pgpRngPars.h"
#include "pgpRngPkt.h"
#include "pgpRngPriv.h"
#include "pgpTrust.h"
#include "pgpTrstPkt.h"		/* for PGP_SIGTRUSTF_CHECKED_TRIED */
#include "pgpHash.h"
#include "pgpKeySpec.h"
#include "pgpMem.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpEnv.h"
#include "pgpErrors.h"
#include "pgpPubKey.h"
#include "pgpFile.h"
#include "pgpRngRead.h"
#include "pgpSigSpec.h"
#include "pgpContext.h"
#include "pgpX509Priv.h"

#ifndef NULL
#define NULL 0
#endif

static PGPContextRef
RingSetGetContext( const RingSet *set )
{
	pgpAssert( pgpContextIsValid( set->pool->context ) );
	return( set->pool->context );
}


/*
 * The largest legal PGP key uses a 64Kbit key, which is 8Kbytes.
 * As a public key, there's also 12 bytes of overhead, plus a
 * public exponent (usually 1 byte, sometimes 3, it's just stupid
 * to make it any larger).  
 * Stored in a secret key an extra 11+IV bytes of overhead and
 * the secret exponent (8K), factors p and q (4+4=8K), and multiplicative
 * inverse u (4K).  A total of 28K of data, plus 23+IV+e extra bytes.
 * With an 8-byte IV, that's 31+e bytes.  Add an extra byte to allow
 * for p and q of differing lengths.
 * But for now, reduce this by a factor of 8, to 8Kbits, which changes
 * the maximum sizes to 1K+overhead and 3.5K + overhead.
 *
 * Without these limits, a non-fatal error (object too big) becomes
 * a fatal error (out of memory) and the implementation becomes
 * less robust.  However, the limits can be set quite high without
 * harm.  (Keep the maximum key size to 64K, though.)
 *
 * The limits above were derived for RSA keys.  DSA/ElG keys have a prime
 * p, a small (~160 bit) prime q, a generator g, and a public exponent y.
 * That's four numbers, one of them small.  If we allow enough space for four
 * full-sized numbers that should be safe.  Secrets have in addition a
 * secret exponent x, generally small, so allow an additional number.
 * Signatures are small with DSA, two 160 bit numbers.  However the new
 * signature packets can in principle have a lot of data.  Allow two full
 * sized numbers to give us plenty of room; we may have to increase the value
 * in the future.
 */
#define RINGMPI_MAX	1024				/* Maximum 8Kbits */
#define RINGKEY_MAXLEN	(4*RINGMPI_MAX)	/* Public key maximum size */
#define RINGSEC_MAXLEN	(5*RINGMPI_MAX)	/* Secret key maximum size */
#define RINGNAME_MAXLEN	150000			/* Name/attribute maximum size */
#define RINGSIG_MAXLEN	150000			/* Signature maximum size */
#define RINGCRL_MAXLEN	MAX_PGPSize		/* CRL maximum size */
#define RINGUNK_MAXLEN	RINGSEC_MAXLEN
/* RINGTRUST_MAXLEN is implicit */

/* Threshold for caching name/attribute objects in memory */
#define NAMECACHETHRESHOLD	1024

/*** Working with the FilePos chain ***/

/*
 * A note about the FilePos chain.  Each object has one FilePos right
 * inside itself, which is the head of a list of external (allocated)
 * ones.  There is one FilePos for each key file an object exists in,
 * and they are kept in increasing order by bit number.
 * Every object (except dummy keys, which aren't excessively numerous,
 * especially in large keyrings) is present in at least one physical
 * keyring, so this saves one next pointer when we're trying to conserve
 * memory for MS-DOS, at the expense of complicating the task of
 * adding to and removing from the list.
 *
 * This is because the first entry in the chain is statically allocated.
 * An actual allocation is performed when an entry is added to the
 * chain in a location other than the first, or is bumped from first
 * place by something else.  A FilePos is freed when an entry is deleted
 * from the chain, or the first one is deleted and the second moves into
 * its place.
 *
 * One more special feature: the MEMRING filepos is put as the last entry
 * in the chain.  In that filepos, the "next" pointer actually points at
 * the memory data, and the fpos field holds the size of the memory block.
 */

/* Find the position of an object in the given file */
static FilePos *
ringFilePos(union RingObject const *obj, RingFile const *file)
{
	FilePos const *pos = &obj->g.pos;
	PGPVirtMask mask;
	RingPool *pool = file->set.pool;

	pgpVirtMaskInit (pool, &mask);
	pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
	pgpVirtMaskAND (pool, &pool->filemask, &mask);
	/* Keep only bits before the one we are interested in */
	/* But for MEMRING go to the last in the chain */
	pgpVirtMaskANDNOT(pool, &pool->memringmask, &mask);
	if (!pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask)) {
		PGPInt32 filebit = pgpVirtMaskLSBit (&file->set.mask);
		pgpVirtMaskClearGreaterBits (pool, &mask, filebit);
	}
	while (!pgpVirtMaskIsEmpty(&mask)) {
		PGPInt32 bit = pgpVirtMaskLSBit (&mask);
		pgpAssert (bit >= 0);
		pgpVirtMaskClearBit (pool, &mask, bit);
		pos = pos->ptr.next;
	}
	pgpVirtMaskCleanup (pool, &mask);
	return (FilePos *)pos;
}

/* Allocate a FilePos from a RingFile. */
static FilePos *
ringFileNewFilePos(RingFile *file)
{
	FilePos *pos = file->freepos;

	if (pos) {
		file->freepos = pos->ptr.next;
	} else {
		pos = (FilePos *)memPoolNew(&file->fpos,FilePos);
		if (!pos)
			ringAllocErr(file->set.pool);
	}

	return pos;
}

static void
ringFileFreeFilePos(RingFile *file, FilePos *pos)
{
	pos->ptr.next = file->freepos;
	file->freepos = pos;
}

/*
 * Allocate and add a FilePos to the object's chain in the right place.
 * This function makes no attempt to initialize the resultant FilePos.
 *
 * NOTE that the bit specified to add may or may not be present in
 * the ring's filemask.  This function must not care.
 */
static FilePos *
ringAddFilePos(union RingObject *obj, RingFile *file)
{
	RingPool *pool = file->set.pool;
	PGPVirtMask mask, tmpmask;
	FilePos *pos, *pos2;
	PGPInt32 bit;
	RingFile *file2;

	pgpVirtMaskInit (pool, &mask);
	pgpVirtMaskInit (pool, &tmpmask);

	pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
	pgpVirtMaskAND (pool, &pool->filemask, &mask);

	pgpAssert (!pgpVirtMaskIsOverlapping (&mask, &file->set.mask));

	pgpVirtMaskCopy (pool, &mask, &tmpmask);
	pgpVirtMaskANDNOT (pool, &pool->memringmask, &tmpmask);
	if (!pgpVirtMaskIsEqual(&pool->memringmask, &file->set.mask)) {
		PGPInt32 filebit = pgpVirtMaskLSBit (&file->set.mask);
		pgpVirtMaskClearGreaterBits (pool, &tmpmask, filebit);
	}
	if (!pgpVirtMaskIsEmpty (&tmpmask)) {
		/* FilePos to add is not the first in the chain */
		pgpVirtMaskCopy (pool, &tmpmask, &mask);
		pos2 = ringFileNewFilePos(file);
		if (!pos2)
			return NULL;
		/* Find the predecessor of the one to be added */
		pos = &obj->g.pos;
		bit = pgpVirtMaskLSBit (&mask);
		pgpAssert (bit >= 0);
		pgpVirtMaskClearBit (pool, &mask, bit);
		while ((bit = pgpVirtMaskLSBit (&mask)) >= 0) {
			pos = pos->ptr.next;
			pgpAssert(IsntNull(pos));
			pgpVirtMaskClearBit (pool, &mask, bit);
		}
		/* Insert pos2 into the chain after pos */
		pos2->ptr.next = pos->ptr.next;
		pos->ptr.next = pos2;
	} else {
		/* First FilePos in the chain */
		pos2 = &obj->g.pos;
		if (pgpVirtMaskIsEmpty(&mask)) {
			/* First and only FilePos on chain */
			pos = NULL;
		} else {
			/* First FilePos; bump down the old first */
			bit = pgpVirtMaskLSBit(&mask);
			pgpAssert(bit >= 0);
			/* Allocate pos from pool for existing bit */
			file2 = file->set.pool->files[bit];
			pos = ringFileNewFilePos(file2);
			if (!pos)
				return NULL;
			*pos = *pos2;
		}
		pos2->ptr.next = pos;
	}
	pgpVirtMaskOR (pool, &file->set.mask, &obj->g.mask);
	pgpVirtMaskCleanup (pool, &mask);
	pgpVirtMaskCleanup (pool, &tmpmask);
	return pos2;
}

static int
ringAddPos(union RingObject *obj, RingFile *file, PGPUInt32 fpos)
{
	FilePos *pos;

	pos = ringAddFilePos(obj, file);
	if (!pos)
		return kPGPError_OutOfMemory;
	pos->fpos = fpos;
	return 0;
}

/*
 * This is needed in one obscure error case to keep things
 * consistent.  The case is when a secret key appears in the same
 * file as the corresponding public key, only later.
 */
static void
ringAlterFilePos(union RingObject *obj, RingFile const *file,
	PGPUInt32 fpos)
{
	PGPVirtMask mask;
	RingPool *pool = file->set.pool;
	FilePos *pos;

	pgpVirtMaskInit (pool, &mask);
	pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
	pgpVirtMaskAND (pool, &pool->filemask, &mask);

	pgpAssert (pgpVirtMaskIsOverlapping(&mask, &file->set.mask));
	
	pgpVirtMaskANDNOT (pool, &pool->memringmask, &mask);

	if (!pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask)) {
		PGPInt32 filebit = pgpVirtMaskLSBit (&file->set.mask);
		pgpVirtMaskClearGreaterBits (pool, &mask, filebit);
	}
	pos = &obj->g.pos;
	while (!pgpVirtMaskIsEmpty (&mask)) {
		PGPInt32 bit = pgpVirtMaskLSBit (&mask);
		pgpVirtMaskClearBit (pool, &mask, bit);
		pos = pos->ptr.next;
	}
	pos->fpos = fpos;
	pgpVirtMaskCleanup (pool, &mask);
}

/*
 * Remove a FilePos from an object's list.
 *
 * file is the filepos corresponding to "bit", pos is the head of a
 * FilePos chain, mask is the bitmask of physical key rings, and
 * bit is the number of the ring to have its position removed.
 *
 * NOTE that the bit specified to remove may or may not be present in
 * the ring->filemask.  This function must not care.
 */
static void
ringRemFilePos(union RingObject *obj, RingFile *file)
{
	PGPVirtMask mask, tmpmask;
	RingPool *pool = file->set.pool;
	FilePos *pos, *pos2;
	PGPInt32 bit;
	RingFile *file2;

	pgpVirtMaskInit (pool, &mask);
	pgpVirtMaskInit (pool, &tmpmask);

	pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
	pgpVirtMaskAND (pool, &pool->filemask, &mask);

	/* Is the bit to remove *not* the least significant bit? */
	pgpVirtMaskCopy (pool, &mask, &tmpmask);
	pgpVirtMaskANDNOT (pool, &pool->memringmask, &tmpmask);
	if (!pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask)) {
		bit = pgpVirtMaskLSBit (&file->set.mask);
		pgpVirtMaskClearGreaterBits (pool, &tmpmask, bit);
	}
	if (!pgpVirtMaskIsEmpty (&tmpmask)) {
		/* FilePos to remove is not the first in the chain */
		/* Find the predecessor of the one to be removed */
		pgpVirtMaskCopy (pool, &tmpmask, &mask);
		pos = &obj->g.pos;
		bit = pgpVirtMaskLSBit (&mask);
		pgpAssert (bit >= 0);
		pgpVirtMaskClearBit (pool, &mask, bit);
		while ((bit = pgpVirtMaskLSBit (&mask)) >= 0) {
			pos = pos->ptr.next;
			pgpAssert(IsntNull(pos));
			pgpVirtMaskClearBit (pool, &mask, bit);
		}
		/* pos->next is the one to be removed */
		pos2 = pos->ptr.next;
		pgpAssert(IsntNull(pos2));
		pos->ptr = pos2->ptr;
		if (pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask))
			pos->ptr.next = NULL;	/* debugging aid */
		file2 = file;
	} else {
		/* First FilePos - copy second to first, remove second */

		/* Clear this bit from the mask (in case we need to) */
		pgpVirtMaskANDNOT (pool, &file->set.mask, &mask);

		/*
		 * That's it?  Well, return then.  The caller better
		 * deallocate this object, 'cause it no longer exists
 		 * anywhere.  Use position -1 to mark an unused slot.
		 */
		if (pgpVirtMaskIsEmpty(&mask)) {
			pgpVirtMaskANDNOT (pool, &file->set.mask, &obj->g.mask);
			if (pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask))
				obj->g.pos.ptr.next = NULL;		/* Debugging aid */
			obj->g.pos.fpos = (PGPUInt32)-1;	/* Debugging aid */
			pgpVirtMaskCleanup (pool, &mask);
			pgpVirtMaskCleanup (pool, &tmpmask);
			return;
		}

		/* Find the bit of the fpos we are removing, the 2nd fpos in list */
		/* Note we have already cleared the bit for the 1st fpos */
		pgpVirtMaskANDNOT (pool, &pool->memringmask, &mask);
		if (pgpVirtMaskIsEmpty(&mask))
			bit = 0;
		else
			bit = pgpVirtMaskLSBit (&mask);
		pgpAssert(bit >= 0);
		file2 = file->set.pool->files[bit];	/* where to stash reclaimed pos */

		/* Copy the next pos to the current one */
		pos2 = obj->g.pos.ptr.next;
		pgpAssert(IsntNull(pos2));
		obj->g.pos = *pos2;
	}
	/* Free the FilePos */
	ringFileFreeFilePos(file2, pos2);
	pgpVirtMaskANDNOT (pool, &file->set.mask, &obj->g.mask);
	pgpVirtMaskCleanup (pool, &mask);
	pgpVirtMaskCleanup (pool, &tmpmask);
}


/* Remove an object and its children from a specific file */
/* If an object is left unhomed, delete it */
static void
ringRemFileObjChildren(union RingObject *obj, RingFile *file)
{
	RingPool *pool = file->set.pool;
	RingObject *obj1, *nextobj1;
	RingObject *obj2, *nextobj2;

	if (pgpIsRingSetMember(&file->set, obj)) {
		ringRemFilePos(obj, file);
		if (!OBJISBOT(obj)) {
			for (obj1=obj->g.down; obj1; obj1=nextobj1) {
				nextobj1 = obj1->g.next;
				if (pgpIsRingSetMember(&file->set, obj1)) {
					ringRemFilePos(obj1, file);
					if (!OBJISBOT(obj1)) {
						for (obj2=obj1->g.down; obj2; obj2=nextobj2) {
							nextobj2 = obj2->g.next;
							if (pgpIsRingSetMember(&file->set, obj2)) {
								ringRemFilePos(obj2, file);
								if (!pgpVirtMaskIsOverlapping (&obj2->g.mask,
														&pool->filemask))
									ringRemObject (pool, obj2);
							}
						}
					}
					if (!pgpVirtMaskIsOverlapping (&obj1->g.mask,
												   &pool->filemask)) {
						/* Parents share all homes of children */
						pgpAssert (OBJISBOT(obj1) || IsNull(obj1->g.down));
						ringRemObject (pool, obj1);
					}
				}
			}
		}
		if (!pgpVirtMaskIsOverlapping (&obj->g.mask, &pool->filemask)) {

⌨️ 快捷键说明

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