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 + -
显示快捷键?