pgprngpub.c

来自「著名的加密软件的应用于电子邮件中」· C语言 代码 · 共 2,518 行 · 第 1/4 页

C
2,518
字号
	set = ringSetAlloc(pool);
	if (set) {
		set->mask = mask;
		set->type = RINGSET_MUTABLE;
		pool->allocmask |= mask;
	}
	return set;
}

void
ringSetDestroy(struct RingSet *set)
{
	struct RingPool *pool;
	struct RingSet **setp;

	if (set) {
		pool = set->pool;
		pgpAssert(set->type < RINGSET_FREE);
		set->type = RINGSET_FREE;

		/* Remove it from the list of allocated sets */
		setp = &pool->sets;
		while (*setp != set) {
			pgpAssert(*setp);
			setp = &(*setp)->next;
		}
		*setp = set->next;

		/* Add to the list of free sets. */
		set->next = pool->freesets;
		pool->freesets = set;
	}
}

/*
 * Freeze a RingSet so that you can start doing set operations
 * on it, copying it, etc.
*/
int
ringSetFreeze(struct RingSet *set)
{
	if (set) {
		if (set->type == RINGSET_MUTABLE)
			set->type = RINGSET_IMMUTABLE;
		pgpAssert(set->type == RINGSET_IMMUTABLE);
	}
	return 0;
}

struct RingSet *
ringSetCopy(struct RingSet const *s)
{
	struct RingSet *set;

	if (!s)
		return NULL;

	pgpAssert(!RINGSETISMUTABLE(s));
	set = ringSetAlloc(s->pool);
	if (set) {
		set->mask = s->mask;
		set->type = RINGSET_IMMUTABLE;
	}
	return set;
}

/* This accepts NULL as an alias for "no such set" */
struct RingSet *
ringSetUnion(struct RingSet const *s1, struct RingSet const *s2)
{
	struct RingSet *set;

	if (!s1)
		return ringSetCopy(s2);

	set = ringSetCopy(s1);
	if (set && s2) {
		pgpAssert(s1->pool == s2->pool);
		pgpAssert(!RINGSETISMUTABLE(s2));
		set->mask |= s2->mask;
	}
	return set;
}


/** The following operations only apply to mutable RingSets **/

/*
* Add an object to a mutable RingSet. That includes the all of the
* object's parents in order to main the proper RingSet invariants.
*/
int
ringSetAddObject(struct RingSet *set, union RingObject *obj)
{
	ringmask mask = set->mask;

	pgpAssert(RINGSETISMUTABLE(set));
	pgpAssert(!(mask & (mask-1)));

	if (obj && !(obj->g.mask & mask)) {
		obj->g.mask |= mask;
		/* Ensure all parents are added, too. */
		while (!OBJISTOP(obj)) {
			obj = obj->g.up;
			if (obj->g.mask & mask)
				break;
			obj->g.mask |= mask;
		}
	}
	return 0;
}

/*
 * Add an object and its children to a mutable RingSet. Also will do
 * the object's parents. src RingSet controls which children are added.
 */
int
ringSetAddObjectChildren(struct RingSet *dest, struct RingSet const *src,
	union RingObject *obj)
{
	struct RingSet const *srcx;
	struct RingIterator *iter;
	int level, initlevel;
	int nobjs;
	int err;

	/* Need to iterate over src, make a copy if necessary */
	srcx = src;
	if (RINGSETISMUTABLE(src)) {
		struct RingSet *src1 = ringSetCreate (ringSetPool (src));
		if (!src1)
			return ringSetError(src)->error;
		ringSetAddSet (src1, src);
		ringSetFreeze (src1);
		src = (struct RingSet const *)src1;
	}
			
	/* First add the object */
	if ((err=ringSetAddObject(dest, obj)) < 0)
		return err;

	iter = ringIterCreate(src);
	if (!iter)
		return ringSetError(src)->error;

	nobjs = 1;
	initlevel=ringIterSeekTo(iter, obj);
	if (initlevel < 0)
		return initlevel;
	level = initlevel + 1;
	while (level > initlevel) {
		union RingObject *child;
		err = ringIterNextObject(iter, level);
		if (err < 0) {
			ringIterDestroy(iter);
			return err;
		}
		if (err > 0) {
			child = ringIterCurrentObject(iter, level);
			if (!child)
				return ringSetError(src)->error;
			if ((err=ringSetAddObject(dest, child)) < 0)
				return err;
			++nobjs;
			++level;
		} else {
			--level;
		}
	}
	ringIterDestroy(iter);
	/* Destroy set copy if we made one */
	if (src != srcx)
		ringSetDestroy ((struct RingSet *)src);
	return nobjs;
}

/*
 * Remove an object from a mutable RingSet. That includes the all of the
 * object's children in order to main the proper RingSet invariants.
 * (Done recursively.)
 */
int
ringSetRemObject(struct RingSet *set, union RingObject *obj)
{
	pgpAssert(RINGSETISMUTABLE(set));
	pgpAssert(!(set->mask & (set->mask-1)));

	/*
	* Remove this object and all its children.
	* As an optimization, omit scanning children if the
	* object is not already in the set.
	*/
	if (obj && obj->g.mask & set->mask) {
		if (!OBJISBOT(obj)) {
			union RingObject *obj2 = obj;
			for (obj2 = obj2->g.down; obj2; obj2 = obj2->g.next)
				ringSetRemObject(set, obj2);
		}
		obj->g.mask &= ~set->mask;
		ringGarbageCollectObject(set->pool, obj);
	}
	return 0;
}

/* Helper function for ringSetAddSet */
static void
ringSetAddList(union RingObject *obj, ringmask destmask, ringmask srcmask)
{
	while (obj) {
		if (obj->g.mask & srcmask) {
			obj->g.mask |= destmask;
			if (!OBJISBOT(obj))
				ringSetAddList(obj->g.down, destmask, srcmask);
		}
		obj = obj->g.next;
	}
}

int
ringSetAddSet(struct RingSet *set, struct RingSet const *set2)
{
	pgpAssert(RINGSETISMUTABLE(set));
	if (set2) {
		pgpAssert(set->pool == set2->pool);

		ringSetAddList(set->pool->keys, set->mask, set2->mask);
	}
	return 0;
}

/*
 * Subtracting sets is simplified by the proper-set requirement.
 * If I remove a key (because it's in set2), I have to remove all
 * children of the key, so I just use ringClearMask to do
 * the job. If I don't (because it's not in set2), then it's
 * guaranteed that none of its children are in set2 either,
 * so there's no need to examine any children.
 */
int
ringSetSubtractSet(struct RingSet *set, struct RingSet const *set2)
{
	union RingObject *obj;
	ringmask mask = set->mask;

	pgpAssert(RINGSETISMUTABLE(set));
	pgpAssert(mask);

	if (set2 && set2->mask) {
		pgpAssert(set->pool == set2->pool);
		for (obj = set->pool->keys; obj; obj = obj->g.next) {
			if (obj->g.mask & mask && obj->g.mask & set2->mask) {
				obj->g.mask &= ~mask;
				if (!OBJISBOT(obj))
					ringClearMask(set->pool, &obj->g.down,
						~mask);
			}
		}
	}
	return 0;
}

static int
ringSetIntersectList(union RingObject *obj, ringmask m1, ringmask m2,
ringmask mdest)
{
	int flag = 0;

	while (obj) {
		if ((obj->g.mask & m1) && (obj->g.mask & m2)) {
			flag = 1;
			obj->g.mask |= mdest;
			if (!OBJISBOT(obj))
				ringSetIntersectList(obj->g.down,
					m1, m2, mdest);
		}
		obj = obj->g.next;
	}
	return flag;
}

struct RingSet *
ringSetIntersection(struct RingSet const *s1, struct RingSet const *s2)
{
	struct RingSet *set;

	if (!s1 || !s2)
		return (struct RingSet *)NULL;

	pgpAssert(s1->pool == s2->pool);
	pgpAssert(!RINGSETISMUTABLE(s1));
	pgpAssert(!RINGSETISMUTABLE(s2));

	/* Do a few trivial cases without allocating bits. */
	if (!(s1->mask & ~s2->mask))	/* s1 is a subset of s2 - copy s1 */
		return ringSetCopy(s1);
	if (!(s2->mask & ~s1->mask))	/* s2 is a subset of s1 - copy s2 */
		return ringSetCopy(s2);

	set = ringSetCreate(s1->pool);
	if (set) {
		if (!ringSetIntersectList(s1->pool->keys, s1->mask, s2->mask,
		set->mask))
		{
			/* Empty set - free bit */
			s1->pool->allocmask &= ~set->mask;
			set->mask = 0;
		}
		set->type = RINGSET_IMMUTABLE;
	}
	return set;
}

static void
ringSetDiffList(union RingObject *obj, ringmask m1, ringmask m2,
ringmask mdest)
{
	while (obj) {
		if ((obj->g.mask & m1) && !(obj->g.mask & m2)) {
			obj->g.mask |= mdest;
			if (!OBJISBOT(obj))
				ringSetDiffList(obj->g.down, m1, m2, mdest);
		}
		obj = obj->g.next;
	}
}

/* Return s1-s2. */
struct RingSet *
ringSetDifference(struct RingSet const *s1, struct RingSet const *s2)
{
	struct RingSet *set;

	if (!s1)
		return NULL;
	if (!s2 || !s2->mask)
		return ringSetCopy(s1);

	pgpAssert(s1->pool == s2->pool);
	pgpAssert(!RINGSETISMUTABLE(s1));
	pgpAssert(!RINGSETISMUTABLE(s2));

	if (!(s1->mask & ~s2->mask)) {
		/* s1->mask is a subset of s2->mask, so result is empty */
		set = ringSetAlloc(s1->pool);
		if (set) {
			set->mask = 0;
			set->type = RINGSET_IMMUTABLE;
		}
	} else {
		set = ringSetCreate(s1->pool);
		if (set) {
			ringSetDiffList(s1->pool->keys, s1->mask, s2->mask,
					set->mask);
			set->type = RINGSET_IMMUTABLE;
		}
	}
	return set;
}

int
ringFileIsDirty(struct RingFile const *file)
{
	return file ? file->flags & RINGFILEF_DIRTY : 0;
}

int
ringFileIsTrustChanged(struct RingFile const *file)
{
	return file ? file->flags & RINGFILEF_TRUSTCHANGED : 0;
}

struct RingPool *
ringPoolCreate(struct PgpEnv const *env)
{
	struct RingPool *pool;

	pool = (struct RingPool *)pgpMemAlloc(sizeof(*pool));
	if (pool)
		ringPoolInit(pool, env);
	return pool;
}

void
ringPoolDestroy(struct RingPool *pool)
{
	if (pool) {
		ringPoolFini(pool);
		pgpMemFree(pool);
	}
}

union RingObject *
ringKeyById8(struct RingSet const *set, byte pkalg, byte const *keyID)
{
	struct RingKey *key;

	if ((pkalg|1) == 3)	/* viacrypt */
		pkalg = 1;
	for (key = set->pool->hashtable[keyID[0]]; key; key = key->util) {
		if ((((key->pkalg|1) == 3) ? 1 : key->pkalg) == pkalg &&
		memcmp(keyID, key->keyID, 8) == 0) {
			if (!(key->mask & set->mask))
				break;
			ringObjectHold((union RingObject *)key);
			return (union RingObject *)key;
		}
	}
	/* Failed */
	return NULL;
}

/*** Access functions for information about objects ***/

int
ringKeyError(struct RingSet const *set, union RingObject *key)
{
	byte const *p;
	size_t len;

	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);

	if (!(key->g.flags & KEYF_ERROR))
		return 0;

	p = (byte const *)ringFetchObject(set, key, &len);
	if (!p)
		return ringSetError(set)->error;
	return ringKeyParse(p, len, NULL, NULL, NULL, NULL, NULL, 0);
}

unsigned
ringKeyBits(struct RingSet const *set, union RingObject *key)
{
	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);
	(void)set;
	return key->k.keybits;
}

word32
ringKeyCreation(struct RingSet const *set, union RingObject *key)
{
	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);
	(void)set;
	return key->k.tstamp;
}

word32
ringKeyExpiration(struct RingSet const *set, union RingObject *key)
{
	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);
	(void)set;
	if (key->k.tstamp == 0 || key->k.validity == 0)
		return 0; /* valid indefinitely */
	else
		return key->k.tstamp + (key->k.validity * 3600 * 24);
}

/*
 * If called for a subkey, force to just encryption.
 * If called for a key with a subkey, return the "or" of both.
 * Else just do the key itself.
 */
int
ringKeyUse(struct RingSet const *set, union RingObject *key)
{
	int use;

	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);

	use = pgpKeyUse(pgpPkalgByNumber(key->k.pkalg));
	if (OBJISSUBKEY(key))
		use &= PGP_PKUSE_ENCRYPT;
	for (key=key->g.down; key; key=key->g.next) {
		if (OBJISSUBKEY(key) && ringSubkeyValid(set, key))
			use |= pgpKeyUse(pgpPkalgByNumber(key->k.pkalg));
	}
	return use;
}

byte
ringKeyTrust(struct RingSet const *set, union RingObject *key)
{
	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);
	(void)set;
	if (!(key->g.flags & (RINGOBJF_TRUST)))
		ringMntValidateKey (set, key);	
	return key->k.trust & PGP_KEYTRUST_MASK;
}

void
ringKeySetTrust(struct RingSet const *set, union RingObject *key, byte trust)
{
	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);
	pgpAssert(trust==PGP_KEYTRUST_UNKNOWN || trust==PGP_KEYTRUST_NEVER ||
	trust==PGP_KEYTRUST_MARGINAL || trust==PGP_KEYTRUST_COMPLETE);
	pgpAssert (!(key->k.trust & PGP_KEYTRUSTF_BUCKSTOP));
	if (key->k.trust & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED))
	return;
	if ((key->k.trust & PGP_KEYTRUST_MASK) != trust) {
		key->k.trust = (key->k.trust & ~PGP_KEYTRUST_MASK) + trust;
		key->g.flags |= RINGOBJF_TRUSTCHANGED;
		ringPoolMarkTrustChanged (set->pool, key->g.mask);
	}
	key->g.flags |= RINGOBJF_TRUST;
}


/*
 * Used to set a key as an "axiomatic" key, that is, one for which
 * we hold the private key. This also involves setting each name on that
 * key as having complete validity.
 */
void
ringKeySetAxiomatic(struct RingSet const *set, union RingObject *key)
{
    pgpAssert(OBJISKEY(key));
    pgpAssert(key->g.mask & set->mask);
    if (!ringKeyIsSec (set, key) ||
	key->k.trust & (PGP_KEYTRUSTF_BUCKSTOP | PGP_KEYTRUSTF_REVOKED))
	return; /* already axiomatic or can't set */
    key->k.trust &= ~PGP_KEYTRUST_MASK;
    key->k.trust |= (PGP_KEYTRUSTF_BUCKSTOP | PGP_KEYTRUST_ULTIMATE);
    ringPoolMarkTrustChanged (set->pool, key->g.mask);
key->g.flags |= (RINGOBJF_TRUSTCHANGED | RINGOBJF_TRUST);
}


/* Reset an axiomatic key. Trust is set to undefined. */

void
ringKeyResetAxiomatic (struct RingSet const *set, union RingObject *key)
{
pgpAssert(OBJISKEY(key));
pgpAssert(key->g.mask & set->mask);
if (!(key->k.trust & PGP_KEYTRUSTF_BUCKSTOP))
	return; /* not axiomatic */
key->k.trust &= ~PGP_KEYTRUSTF_BUCKSTOP;
key->k.trust = (key->k.trust & ~PGP_KEYTRUST_MASK) +
PGP_KEYTRUST_UNDEFINED;
ringPoolMarkTrustChanged (set->pool, key->g.mask);
key->g.flags |= (RINGOBJF_TRUSTCHANGED | RINGOBJF_TRUST);
}

int
ringKeyAxiomatic(struct RingSet const *set, union RingObject *key)
{
	(void)set;	/* Avoid warning */
	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);
	return key->k.trust & PGP_KEYTRUSTF_BUCKSTOP;
}


/* Return TRUE if the key is a subkey */
int
ringKeyIsSubkey (struct RingSet const *set, union RingObject *key)
{
(void)set;
return OBJISSUBKEY(key);
}


int
ringKeyDisabled(struct RingSet const *set, union RingObject *key)
{
	(void)set;	/* Avoid warning */
	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);
	return key->k.trust & PGP_KEYTRUSTF_DISABLED;
}

void
ringKeyDisable(struct RingSet const *set, union RingObject *key)
{
	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);
	if (!(key->k.trust & PGP_KEYTRUSTF_DISABLED)) {
		key->k.trust |= PGP_KEYTRUSTF_DISABLED;
		key->g.flags |= RINGOBJF_TRUSTCHANGED;
		ringPoolMarkTrustChanged (set->pool, key->g.mask);
	}
	key->g.flags |= RINGOBJF_TRUST;
}

void
ringKeyEnable(struct RingSet const *set, union RingObject *key)
{
	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);
	if (key->k.trust & PGP_KEYTRUSTF_DISABLED) {
		key->k.trust &= ~PGP_KEYTRUSTF_DISABLED;
		key->g.flags |= RINGOBJF_TRUSTCHANGED;
		ringPoolMarkTrustChanged (set->pool, key->g.mask);
	}
	key->g.flags |= RINGOBJF_TRUST;
}



int
ringKeyRevoked(struct RingSet const *set, union RingObject *key)
{
	pgpAssert(OBJISKEY(key));
	pgpAssert(key->g.mask & set->mask);
	(void)set;
#if PGPTRUSTMODEL>0
	if (!(key->g.flags & (RINGOBJF_TRUST)))
		ringMntValidateKey (set, key);
#endif
	return key->k.trust & PGP_KEYTRUSTF_REVOKED;
}


/*
 * Return true if the specified signature has been revoked, that is,
 * if there is a newer signature by the same key which is of type
 * UID_REVOKE.
 */
int
ringSigRevoked (struct RingSet const *set, union RingObject *sig)
{
	RingObject		*parent,
					*sibling;

⌨️ 快捷键说明

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