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

📄 pgprngpriv.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 4 页
字号:
			}
		}
		/* Skip to next object */
		if( IsPGPError( err = 
				pgpVirtMaskOR (pool, &objmask, &remmask) ) )
			goto error;
		objp = &robj->g.next;
	}
	pgpVirtMaskCleanup (pool, omask);
	*omask = remmask;
error:
	pgpVirtMaskCleanup (pool, &tmpmask);
	pgpVirtMaskCleanup (pool, &objmask);
	return err;
}

/*
 * Reclaim all unused bits and delete any unreferenced memory objects.
 * Return TRUE if did some reclamation.
 */
PGPBoolean
ringGarbageCollect(RingPool *pool)
{
	PGPVirtMask mask;
	PGPError err;

	/*  Build sig lists so we know which keys act as signers.
	    These should be left as dummy keys rather than freed. */
	ringPoolListSigsBy (pool);
	if (IsPGPError( err = pgpVirtMaskInit (pool, &mask) ) )
		return FALSE;
	if (IsPGPError (err = ringAllocMask(pool, (RingSet const *)NULL, &mask)))
		return FALSE;
	if (!pgpVirtMaskIsEqual (&mask, &pool->allocmask)) {
		pgpVirtMaskCopy (pool, &mask, &pool->allocmask);
		if (IsPGPError( err = ringClearMask(pool, &pool->keys, &mask,
											NULL, &mask)))
			return FALSE;
		pgpVirtMaskAND(pool, &pool->memringmask, &mask);
		if (pgpVirtMaskIsEmpty(&mask)) {
			memPoolEmpty(&pool->files[MEMRINGBIT]->strings);
			memPoolEmpty(&pool->files[MEMRINGBIT]->fpos);
			pool->files[MEMRINGBIT]->freepos = NULL;
			pgpVirtMaskCleanup (pool, &mask);
			return TRUE;	/* Something freed */
		}
	}
	pgpVirtMaskCleanup (pool, &mask);
	return FALSE;	/* Nothing freed */
}

/* Remove a single key from its hash chain */
static void
ringGarbageHackKey(RingPool *pool, RingKey *key)
{
	RingKey **keyp;
	
	keyp = &pool->hashtable[key->keyID[0]];

	while (*keyp != key) {
		pgpAssert(*keyp);
		keyp = &(*keyp)->util;
	}

	*keyp = key->util;
}

/* Remove a single signature from its sigsby list */
static void
ringGarbageHackSig(RingSig *sig)
{
	RingKey *key;
	RingSig **sigp;
	
	key = &sig->by->k;
	pgpAssert(KEYISKEY(key));

	/*
	 * This could be one loop but for type rules, sigh...
	 * The problem doesn't happen often, fortunately.
	 * (The single loop can be expressed in C using the
	 * cheat sigp = (RingSig **)&key->sigsby; but
	 * while that's portable in practice, we eschew it
	 * for the sake of ANSI C purity.)
	 */
	if (&key->sigsby->s == sig) {
		key->sigsby = (union RingObject *)sig->nextby;
	} else {
		sigp = &key->sigsby->s.nextby;
		while (*sigp != sig)
			sigp = &(*sigp)->nextby;
		*sigp = sig->nextby;
	}
}

/*
 * Delete a single object from the global pool if it is an unreferenced
 * memory object.
 */
void
ringGarbageCollectObject(RingPool *pool, union RingObject *robj)
{
	union RingObject **objp;

	if (pgpVirtMaskIsEqual (&robj->g.mask, &pool->memringmask)) {
		pgpAssert(!robj->g.down);
		objp = OBJISTOP(robj) ? &pool->keys : &robj->g.up->g.down;
		while (*objp != robj) {
			pgpAssert(*objp);
			objp = &(*objp)->g.next;
		}
		*objp = robj->g.next;
		if (OBJISKEY(robj))
			ringGarbageHackKey(pool, &robj->k);
		else if (OBJISSIG(robj))
			ringGarbageHackSig(&robj->s);
		ringFreeObject(pool, robj);
	}
}

/* Find and allocate a new, unused mask bit.  Search through all bits
 * until we find one unused.
 */
PGPError
ringBitAlloc(RingPool *pool, PGPUInt32 *newbit)
{
	PGPVirtMask mask;

#if VIRTMASK
	PGPUInt32 maskbit;
	PGPError err;

	maskbit = MEMRINGBIT + 1;
	if( IsPGPError( err = pgpVirtMaskInit (pool, &mask) ) )
		return err;
	for ( ; ; ) {
		if( IsPGPError( err =
				pgpVirtMaskSetBit (pool, &mask, maskbit) ) )
			return err;
		if (!pgpVirtMaskIsOverlapping (&mask, &pool->allocmask)) {
			/* Occasionally reclaim unused bits */
			if (maskbit % 32 == 0) {
				ringGarbageCollect(pool);
			}
			*newbit = maskbit;
			err = pgpVirtMaskCleanup (pool, &mask);
			return err;
		}
		pgpVirtMaskClearBit (pool, &mask, maskbit);
		++maskbit;
	}
	/* NOTREACHED */
#else
	/* Allocate a new bit */
	pgpVirtMaskInit (pool, &mask);
	pgpVirtMaskCopy (pool, &pool->allocmask, &mask);
#if MULTIMASK
	pgpVirtMaskNOT (pool, &mask, 32*MULTIMASK);
#else
	pgpVirtMaskNOT (pool, &mask, 32);
#endif
	if (pgpVirtMaskIsEmpty(&mask)) {
		/* Wups, out of bits - try something before dying */
		ringGarbageCollect(pool);
		pgpVirtMaskCopy (pool, &pool->allocmask, &mask);
#if MULTIMASK
		pgpVirtMaskNOT (pool, &mask, 32*MULTIMASK);
#else
		pgpVirtMaskNOT (pool, &mask, 32);
#endif
		if (pgpVirtMaskIsEmpty(&mask)) {
			ringSimpleErr(pool, kPGPError_OutOfRings);
			return kPGPError_OutOfRings;
		}
	}
	*newbit = pgpVirtMaskLSBit(&mask);
	return kPGPError_NoErr;
#endif
}

/*
 * Allocate and deallocate useful structures.
 * Note the interesting shenanigans used to allocate
 * a structure the alignment of an enclosing union, ensuring
 * that even on a maximally-perverse ANSI C implementation,
 * it is safe to cast the returned structure pointer to a union
 * pointer.
 */
union RingObject *
ringNewObject(RingPool *pool, int objtype)
{
	union RingObject *robj;
	/* How to initialize each object to empty */
	static RingKey const nullkey = NULLRINGKEY;
	static RingSec const nullsec = NULLRINGSEC;
	static RingName const nullname = NULLRINGNAME;
	static RingSig const nullsig = NULLRINGSIG;
	static RingCRL const nullcrl = NULLRINGCRL;
	static RingUnk const nullunk = NULLRINGUNK;
	static void const *nullobjs[RINGTYPE_MAX] = {
		&nullkey, &nullsec, &nullname, &nullsig, &nullcrl, &nullunk
	};
	size_t const sizes[RINGTYPE_MAX] = {
		sizeof(RingKey),  sizeof(RingSec),
		sizeof(RingName), sizeof(RingSig),
		sizeof(RingCRL),  sizeof(RingUnk)
	};

	/* Object types are 1-based */
	pgpAssert(objtype > 0);
	pgpAssert(objtype <= RINGTYPE_MAX);

	robj = pool->freeobjs[objtype-1];
	if (robj) {
		pool->freeobjs[objtype-1] = robj->g.next;
	} else {
		robj = (union RingObject *)
			memPoolAlloc(&pool->structs, sizes[objtype-1],
				     alignof(union RingObject));
		if (!robj) {
			ringAllocErr(pool);
			return NULL;
		}
	}
	memcpy(robj, nullobjs[objtype-1], sizes[objtype-1]);
	pgpAssert(ringObjectType(robj) == objtype);
	return robj;
}

/*
 * Free an object.  This does not do any cleanup with any pointers in the
 * object, except the regexp which belongs to sig objects.
 */
void
ringFreeObject(RingPool *pool, union RingObject *obj)
{
	int type = ringObjectType(obj);

	pgpAssert(type > 0);
	pgpAssert(type <= RINGTYPE_MAX);

	if (OBJISSIG(obj)) {
		if (obj->s.regexp) {
			pgpContextMemFree( pool->context, obj->s.regexp );
			obj->s.regexp = NULL;
		}
	}

	pgpVirtMaskCleanup (pool, &obj->g.mask);

	obj->g.next = pool->freeobjs[type-1];
	pool->freeobjs[type-1] = obj;
}

/*
 * Remove an object from its parent and free it.  This does not do
 * anything with the object's FilePos list.
 */
void
ringRemObject(RingPool *pool, union RingObject *obj)
{
	union RingObject **objp;

	pgpAssert(!OBJISTOP(obj));
	objp = &obj->g.up->g.down;

	/* Unlink the object from its parent */
	while (*objp != obj) {
		pgpAssert(*objp);
		objp = &(*objp)->g.next;
	}
	*objp = obj->g.next;
	ringFreeObject(pool, obj);
}

/*
 * Rebuild the pool's hash table from scratch,
 * inserting all keys and subkeys.
 */
void
ringPoolHash(RingPool *pool)
{
	union RingObject *key, *subkey;
	int i;

	for (i = 0; i < 256; i++)
		pool->hashtable[i] = NULL;

	for (key = pool->keys; key; key = key->g.next) {
		pgpAssert(OBJISKEY(key));
		RINGPOOLHASHKEY(pool, key);
		for (subkey = key->g.down; subkey; subkey = subkey->g.next) {
			if (OBJISKEY(subkey))
				RINGPOOLHASHKEY(pool, subkey);
		}
	}
}

/*
 * Find a key given a keyID.
 *
 * ViaCrypt added pkalgs 2 and 3 which are limited RSA, but doesn't
 * completely distinguish beterrn them, so this doesn't either.  Sigh.
 */
union RingObject *
ringPoolFindKey(RingPool const *pool, PGPByte pkalg, PGPByte const keyID[8])
{
	RingKey *key;

	if ((pkalg | 1) == 3)
		pkalg = 1;
	for (key = pool->hashtable[keyID[0]]; key; key = key->util) {
		if (memcmp(keyID, key->keyID, 8) == 0) {
			if (pkalg == key->pkalg)
				break;
			/* Cope with ViaCrypt's things */
			if (pkalg == 1 && (key->pkalg | 1) == 3)
				break;
		}
	}

	return (union RingObject *)key;
}


/*
 * Find a key given a "20n" fingerprint (SHA-1 hash over numeric data)
 * Note that this does disk accesses and may change RingFile pointers.
 */
RingObject *
ringPoolFindKey20n(RingPool *pool, PGPByte const *fp20n)
{
	RingObject *key;
	RingSet *allset;
	PGPByte hashbuf[20];

	allset = ringSetCreateUniversal (pool);
	for (key = pool->keys; key; key = key->g.next) {
		/* Look for non-dummy key which matches fingerprint */
		if (pgpIsRingSetMember( allset, key ) &&
			key->k.fp20n == fp20n[0]) {
			ringKeyFingerprint20n (allset, key, hashbuf);
			pgpAssert (hashbuf[0] == key->k.fp20n);
			if (memcmp (fp20n, hashbuf, sizeof(hashbuf)) == 0)
				break;
		}
	}
	ringSetDestroy (allset);
	return (union RingObject *)key;
}


/*
 * Ensure that each key's list of the signatures by it is
 * valid.  This also establishes the extra invariant (used in
 * pgpRngMnt.c) that all signatures by one key on another object
 * are adjacent on that key's sigsby list.
 */
void
ringPoolListSigsBy(RingPool *pool)
{
	union RingObject *key, *n, *s;

	/* Initialize sigsby lists to null */
	for (key = pool->keys; key; key = key->g.next) {
		pgpAssert(OBJISTOPKEY(key));
		key->k.sigsby = NULL;
	}

	/* Install every sig on a sigsby list */
	for (key = pool->keys; key; key = key->g.next) {
	    for (n = key->k.down; n; n = n->g.next) {
	        if (OBJISSIG(n)) {
		    n->s.nextby = (RingSig *) n->s.by->k.sigsby;
		    n->s.by->k.sigsby = n;
		} else for (s = n->g.down; s; s = s->g.next) {
		    if (OBJISSIG(s)) {
		        s->s.nextby = (RingSig *) s->s.by->k.sigsby;
			s->s.by->k.sigsby = s;
		    }
		}
	    }
	}
}


/*
 * Return the mask of RingFiles that are "better" (higher priority
 * for fetching) than *any* home of the specified object.
 */
	PGPError
ringObjBetters(union RingObject const *obj, RingPool const *pool,
			   PGPVirtMask *omask)
{
	PGPVirtMask better;
	PGPVirtMask mask;
	PGPInt32 bit;

	pgpVirtMaskCleanup (pool, omask);

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

	pgpAssert(!pgpVirtMaskIsEmpty(&mask));

	while (!pgpVirtMaskIsEmpty(&mask)) {
		bit = pgpVirtMaskLSBit(&mask);
		pgpVirtMaskAND (pool, &pool->files[bit]->higherpri, &better);
		pgpVirtMaskClearBit(pool, &mask, bit);
	}

	pgpVirtMaskCleanup (pool, &mask);
	*omask = better;
	return kPGPError_NoErr;
}


/*
 * Return TRUE if the specified subkey has a valid sig from the main key.
 * Assumes subkey sigs are always tried, which should happen when they are
 * created or added to the keyring.  The only time this isn't true is when
 * we are considering adding a key.  We will give the sig the benefit of
 * the doubt in that case as we aren't using it yet.
 */
int
ringSubkeyValid(RingSet const *set, union RingObject *subkey,
	PGPBoolean unExpired)
{
	union RingObject *sig;
	union RingObject *key;
	PGPUInt32		  curtime;
	PGPUInt32		  exptime;

	pgpAssert(OBJISSUBKEY(subkey));
	pgpAssert(pgpIsRingSetMember(set, subkey));
	key = subkey->g.up;
	pgpAssert(OBJISTOPKEY(key));

	if (subkey->k.trust & PGP_KEYTRUSTF_REVOKED)
	    return 0;
	if (unExpired) {
		/* Don't use key if has expired or creation time is > 24 hours
			in future */
		if (subkey->k.trust & PGP_KEYTRUSTF_EXPIRED)
			return 0;
		curtime = (PGPUInt32) PGPGetTime();
		exptime = (PGPUInt32) ringKeyExpiration(set, subkey);
		if ((exptime != 0  &&  curtime > exptime)  ||
			curtime < ringKeyCreation(set, subkey) - 24*60*60)
			return 0;
	}
	/* Check legality of subkey */
	for (sig = subkey->g.down; sig; sig = sig->g.next) {
		if (OBJISSIG(sig) &&

⌨️ 快捷键说明

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