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

📄 pgprngpub.c

📁 PGP—Pretty Good Privacy
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Return TRUE if the key comes only from sources where it has secret
 * objects.  In other words, the key comes from a secret key ring.  This
 * is used in adding that key so that we only add it to the secret ring,
 * which is necessary due to complications relating to the "version bug".
 * Otherwise if we add a secret keyring we may end up putting the key on
 * the pubring, and it could have the incorrect version.
 * (See pgpRngRead.c for discussion of the version bug.)
 * Don't count if just on MEMRING, otherwise newly created keys return TRUE.
 */
int
ringKeyIsSecOnly(RingSet const *set, union RingObject *key)
{
	RingPool *pool = set->pool;
	PGPVirtMask keyfilemask;
	PGPVirtMask secfilemask;
	PGPBoolean seconly;

	pgpVirtMaskInit (pool, &keyfilemask);
	pgpVirtMaskInit (pool, &secfilemask);

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

	if (pgpVirtMaskIsEqual (&keyfilemask, &pool->memringmask)) {
		pgpVirtMaskCleanup (pool, &keyfilemask);
		pgpVirtMaskCleanup (pool, &secfilemask);
		return 0;			/* Newly generated keys */
	}
		
	/* Accumulate all sec objects into secfilemask */
	for (key = key->g.down; key; key = key->g.next) {
		if (pgpIsRingSetMember(set, key) && OBJISSEC(key)) {
			pgpVirtMaskOR (pool, &key->g.mask, &secfilemask);
		}
	}
	pgpVirtMaskAND (pool, &pool->filemask, &secfilemask);
	pgpVirtMaskANDNOT (pool, &secfilemask, &keyfilemask);
	seconly = pgpVirtMaskIsEmpty(&keyfilemask);

	pgpVirtMaskCleanup (pool, &keyfilemask);
	pgpVirtMaskCleanup (pool, &secfilemask);

	return seconly;
}


/*
 * Return the most recent subkey associated with the key, if there is one.
 */
union RingObject *
ringKeySubkey(RingSet const *set, union RingObject const *key)
{
	union RingObject *obj, *best = NULL;
	PGPUInt32 objtime, besttime = 0;

	pgpAssert(OBJISKEY(key));
	for (obj = key->g.down; obj; obj = obj->g.next) {
		if (pgpIsRingSetMember(set, obj) && OBJISSUBKEY(obj)
		    && ringSubkeyValid(set, obj, TRUE)) {
			objtime = ringKeyCreation(set, obj);
			if (besttime <= objtime) {
				best = obj;
				besttime = objtime;
			}
		}
	}
	return best;
}

/* Given a subkey, return its master key */
union RingObject *
ringKeyMasterkey (RingSet const *set, union RingObject const *subkey)
{
	(void)set;

	pgpAssert (OBJISSUBKEY(subkey));
	pgpAssert (OBJISTOPKEY(subkey->g.up));
	return subkey->g.up;
}


/*
 * Given a public key on the keyring, get the corresponding PGPPubKey.
 * Use is a usage code which limits the kinds of keys we will accept.
 * For keys which have subkeys this chooses which one to use.  If use is
 * 0 we do a straight conversion of the key or subkey; if nonzero we
 * verify that the key has the required use.  Return NULL if we can't
 * get a key with the required use.
 */
PGPPubKey *
ringKeyPubKey(RingSet const *set, union RingObject *key, int use)
{
	PGPByte const *p;
	PGPSize len;
	PGPPubKey *pub;
	union RingObject *subkey = NULL;
	unsigned vsize;
	PGPError i;
	PGPContextRef	context;

	pgpAssertAddrValid( set, RingSet );
	pgpAssertAddrValid( set->pool, RingPool );
	context	= set->pool->context;

	pgpAssert(OBJISKEY(key));
	pgpAssert(pgpIsRingSetMember(set, key));

	/* Select between subkey and key if necessary */
	if (use &&  (OBJISSUBKEY(key)
			|| ((subkey=ringKeySubkey(set, key)) != NULL))) {
		if (use == PGP_PKUSE_SIGN_ENCRYPT) {
			ringSimpleErr(set->pool, kPGPError_PublicKeyUnimplemented);
			return NULL;
		}
		if (use == PGP_PKUSE_ENCRYPT) {
			if (OBJISTOPKEY(key)) {
				pgpAssert(subkey);
				key = subkey;
				pgpAssert (OBJISSUBKEY(key));
			}
		} else if (use == PGP_PKUSE_SIGN) {
			if (OBJISSUBKEY(key)) {
				key = key->g.up;
				pgpAssert (OBJISTOPKEY(key));
			}
		}
	}

	/* Verify key satisfies required usage */
	if (use && ((pgpKeyUse(pgpPkalgByNumber(key->k.pkalg)) & use) != use)){
		ringSimpleErr(set->pool, kPGPError_PublicKeyUnimplemented);
		return NULL;
	}

	p = (PGPByte const *)ringFetchObject(set, key, &len);
	if (!p)
		return NULL;
	if (key->g.flags & KEYF_ERROR || len < 8) {
		i = (PGPError)ringKeyParse(context, p, len, NULL, NULL, NULL, NULL,
								   NULL, NULL, NULL, 0);
		ringSimpleErr(set->pool, i);
		return NULL;
	}
	/*
	 * A key starts with 5 or 7 bytes of data, an algorithm byte, and
	 * the public components.
	 */
	if (p[0] == PGPVERSION_4) {
		vsize = 0;
	} else {
		vsize = 2;
	}
	pgpAssert(p[5+vsize] == key->k.pkalg);	/* Checked by ringKeyVerify */
	pub = pgpPubKeyFromBuf( context, p[5+vsize], p+6+vsize, len-6-vsize, &i);
	if (!pub) {
 		ringSimpleErr(set->pool, i);
		return NULL;
	}
	memcpy(pub->keyID, key->k.keyID, sizeof(key->k.keyID));
	return pub;
}

/*
 * Find the best Secret which is a descendant of the given key,
 * in the given set.
 */
union RingObject *
ringBestSec(RingSet const *set, union RingObject const *key)
{
	PGPVirtMask better;
	union RingObject *obj, *best = 0;

	pgpVirtMaskInit (set->pool, &better);
	pgpVirtMaskNOT (set->pool, &better, set->pool->nfiles);

	pgpAssert(OBJISKEY(key));
	for (obj = key->g.down; obj; obj = obj->g.next) {
		if (pgpVirtMaskIsOverlapping (&obj->g.mask, &better)
			&& pgpIsRingSetMember (set, obj)
		    && OBJISSEC(obj)) {
			best = obj;
			ringObjBetters(obj, set->pool, &better);
		}
	}
	pgpVirtMaskCleanup (set->pool, &better);
	return best;

}

/*
 * Return the version for a secret key.  Also permissible to pass a key.
 * This should be used when we edit a pass phrase to preserve the version
 * number and avoid the infamous "version bug".
 */
PgpVersion
ringSecVersion (RingSet const *set, union RingObject *sec)
{
	PGPByte *secdata;
	PGPSize secdatalen;

	if (!OBJISSEC(sec)) {
		sec = ringBestSec(set, sec);
		if (!sec) {
			ringSimpleErr(set->pool, kPGPError_SecretKeyNotFound);
			return (PgpVersion)0;
		}
	}
	secdata = (PGPByte *)ringFetchObject (set, sec, &secdatalen);
	return (PgpVersion)secdata[0];
}


/*
 * Given a secret on a keyring, get a PGPSecKey (possibly locked).
 * As a hack to help the lazy programmer, you can also pass a key.
 * Use is a usage code which limits the kinds of keys we will accept.
 * For keys which have subkeys this chooses which one to use.
 */
PGPSecKey *
ringSecSecKey(RingSet const *set, union RingObject *sec, int use)
{
	PGPByte const *p;
	PGPSize len;
	PGPSecKey *seckey;
	union RingObject *key;
	union RingObject *subkey = NULL;
	unsigned vsize;
	PGPError i;
	PGPContextRef	context;

	pgpAssertAddrValid( set, RingSet );
	pgpAssertAddrValid( set->pool, RingPool );
	context	= set->pool->context;

	if (OBJISSEC(sec)) {
		key = sec->g.up;
	} else {
		key = sec;
	}
	pgpAssert(OBJISKEY(key));
	pgpAssert(pgpIsRingSetMember(set, sec));

	/* Select between subkey and key if necessary */
	if (use	 &&  (OBJISSUBKEY(key)
			|| ((subkey=ringKeySubkey(set, key)) != NULL))) {
		int newkey = 0;
		if (use == PGP_PKUSE_SIGN_ENCRYPT) {
			ringSimpleErr(set->pool, kPGPError_PublicKeyUnimplemented);
			return NULL;
		}
		if (use == PGP_PKUSE_ENCRYPT) {
			if (OBJISTOPKEY(key)) {
				pgpAssert(subkey);
				key = subkey;
				pgpAssert (OBJISSUBKEY(key));
				newkey = 1;
			}
		} else if (use == PGP_PKUSE_SIGN) {
			if (OBJISSUBKEY(key)) {
				key = key->g.up;
				pgpAssert (OBJISTOPKEY(key));
				newkey = 1;
			}
		}
		if (newkey || !OBJISSEC(sec)) {
			sec = ringBestSec(set, key);
			if (!sec) {
				ringSimpleErr(set->pool, kPGPError_SecretKeyNotFound);
				return NULL;
			}
		}
	} else if (OBJISKEY(sec)) {
		sec = ringBestSec(set, sec);
		if (!sec) {
			ringSimpleErr(set->pool, kPGPError_SecretKeyNotFound);
			return NULL;
		}
	}

	/* Verify key satisfies required usage */
	if (use && ((pgpKeyUse(pgpPkalgByNumber(key->k.pkalg)) & use) != use)){
		ringSimpleErr(set->pool, kPGPError_PublicKeyUnimplemented);
		return NULL;
	}

	p = (PGPByte const *)ringFetchObject(set, sec, &len);
	if (!p)
		return NULL;
	if (sec->g.up->g.flags & KEYF_ERROR || len < 8) {
		i = (PGPError)ringKeyParse(set->pool->context, p, len, NULL, NULL,
								  NULL, NULL, NULL, NULL, NULL, 0);
		ringSimpleErr(set->pool, i);
		return NULL;
	}
	if (p[0] == PGPVERSION_4) {
		vsize = 0;
	} else {
		vsize = 2;
	}
	pgpAssert(p[5+vsize] == sec->g.up->k.pkalg); /* Checked by ringKeyVerify */
	seckey = pgpSecKeyFromBuf( context, p[5+vsize], p+6+vsize, len-6-vsize,
							   (PGPBoolean)!!KEYISV3(&sec->g.up->k), &i);
	if (!seckey) {
 		ringSimpleErr(set->pool, i);
		return NULL;
	}
	memcpy(seckey->keyID, sec->g.up->k.keyID, sizeof(sec->g.up->k.keyID));
	return seckey;
}


/* Return the latest valid sig on the object by the specified key */
RingObject *
ringLatestSigByKey (RingObject const *obj, RingSet const *set,
	RingObject const *key)
{
	RingObject *sig;
	RingObject *latestsig;

	pgpAssert (pgpIsRingSetMember(set, obj));
	pgpAssert (!OBJISBOT(obj));

	latestsig = NULL;
	for (sig=obj->g.down; sig; sig=sig->g.next) {
		if (!OBJISSIG(sig))
			continue;
		if (!pgpIsRingSetMember(set, sig))
			continue;
		if (ringSigMaker (set, sig, set) != key)
			continue;
		if ((ringSigType (set, sig) & 0xf0) != PGP_SIGTYPE_KEY_GENERIC)
			continue;
		if (!ringSigChecked (set, sig) || ringSigRevoked (set, sig))
			continue;
		/* Save the newest such signature on the name */
		if (!latestsig) {
			latestsig = sig;
		} else {
			if (ringSigTimestamp(set,sig) > ringSigTimestamp(set,latestsig))
				latestsig = sig;
		}
	}		
	return latestsig;
}


/* There ain't much to know about a name... */
char const *
ringNameName(RingSet const *set, union RingObject *name, PGPSize *lenp)
{
	pgpAssert(pgpIsRingSetMember(set, name));
	pgpAssert(OBJISNAME(name));
	return (char const *)ringFetchObject(set, name, lenp);
}

PGPBoolean
ringNameIsAttribute(RingSet const *set, union RingObject *name)
{
	(void) set; /* Avoid warning */
	
	pgpAssert(pgpIsRingSetMember(set, name));
	pgpAssert(OBJISNAME(name));
	
	(void) set;
	(void) name;
	
	return (PGPBoolean)NAMEISATTR(&name->n);
}

PGPUInt32
ringNameCountAttributes(RingSet const *set, union RingObject *name)
{
	PGPByte			*p;
	PGPSize			len;
	
	pgpAssert(pgpIsRingSetMember(set, name));
	pgpAssert(OBJISNAME(name));
	if (!NAMEISATTR(&name->n))
		return 0;

	p = (PGPByte *)ringFetchObject(set, name, &len);
	if (!p) {
		return 0;
	}

	return ringAttrCountSubpackets (p, len);
}


/* Return the nth attribute subpacket for the specified name */
/* This reads from disk and munges the pktbuf */
PGPByte const *
ringNameAttributeSubpacket (RingObject *name, RingSet const *set,
	PGPUInt32 nth, PGPUInt32 *subpacktype, PGPSize *plen, PGPError *error)
{
	PGPByte			*p;
	PGPSize			len;
	RingPool *pool = set->pool;
	
	pgpAssert(OBJISNAME(name));
	pgpAssert(pgpIsRingSetMember(set, name));

	if (error)
		*error = kPGPError_NoErr;

	if (!NAMEISATTR(&name->n)) {
		if (error)
			*error = kPGPError_BadParams;
		return NULL;
	}

	p = (PGPByte *)ringFetchObject(set, name, &len);

	/* ringAttrSubpacket munges the packets so make a copy */
	if (IsntNull(p)  &&  p != (PGPByte *)pool->pktbuf) {
		PGPByte *pktbuf = (PGPByte *)ringReserve(pool, len);
		if (IsntNull(pktbuf)) {
			pgpCopyMemory(p, pktbuf, len);
		}
		p = pktbuf;
	}
	if (!p) {
		if (error)
			*error = ringSetError(set)->error;
		return NULL;
	}

	return ringAttrSubpacket(p, len, nth, subpacktype, plen);
}	

/* Return the primary userid of the specified attribute type */
/* This reads from disk and munges the pktbuf for nonzero attribute */
RingObject *
ringKeyPrimaryName (RingObject *key, RingSet const *set,
	PGPUInt32 type)
{
	RingObject *name;
	RingObject *firstname;
	RingObject *sig;
	RingObject *newestsig;
	PGPUInt32 subpacktype;

    pgpAssert(OBJISKEY(key));
	pgpAssert(pgpIsRingSetMember(set, key));

	newestsig = NULL;
	firstname = NULL;
	for (name=key->g.down; name; name=name->g.next) {
		if (!pgpIsRingSetMember(set, name))
			continue;
		if (!OBJISNAME(name))
			continue;
		if ((type == 0) != !NAMEISATTR(&name->n))
			continue;
		subpacktype = 0;
		if (NAMEISATTR(&name->n)) {
			(void)ringNameAttributeSubpacket (name, set, 0, &subpacktype,
											  NULL, NULL);
			if (subpacktype != type)
				continue;
		}
		/* Have a name which is the right attribute type */
		if (!firstname)
			firstname = name;
		sig = ringLatestSigByKey (name, set, key);
		if (sig) {
			pgpAssert (OBJISSIG(sig));
			if (SIGISPRIMARYUID (&sig->s)) {
				if (!newestsig) {
					newestsig = sig;
				} else {
					/* Don't override irrevocable settings */
					if (SIGISREVOCABLE(&newestsig->s) &&
								(ringSigTimestamp(set, sig) >
								 ringSigTimestamp(set,newestsig))) {
						newestsig = sig;
					}
				}
			}
		}
	}

	if (firstname == NULL)
		return NULL;

	if (newestsig) {
		name = newestsig->g.up;
	} else {
		name = firstname;
	}

	pgpAssert (name);
	pgpAssert (OBJISNAME(name));
	return name;
}


/*  Return the validity (*not* the trust) of a name */

PGPByte
ringNameTrust(RingSet const *set, union RingObject *name)
{
    union RingObject *key;
	
    pgpAssert(OBJISNAME(name));
	pgpAssert(pgpIsRingSetMember(set, name));
    (void)set;
    key = name->g.up;
    pgpAssert(OBJISTOPKEY(key));
    /*
	 * Force returned value if key is revoked or axiomatic.
	 * Allow expired keys to stay valid, so users can know what their status
	 * was before they expired.
	 */
    if (key->k.trust & PGP_KEYTRUSTF_REVOKED)
        return kPGPNameTrust_Untrusted;
    if (key->k.trust & PGP_KEYTRUSTF_BUCKSTOP)
        return kPGPNameTrust_Complete;
    if (!(name->g.flags & (RINGOBJF_TRUST)))
        ringMntValidateName (set, name);
    return name->n.trust & kPGPNameTrust_Mask;
}

int
ringNameWarnonly(RingSet const *set, union RingObject *name)
{
	pgpAssert(OBJISNAME(name));
	pgpAssert(pgpIsRingSetMember(set, name));
	(void)set;
	return name->n.trust & PGP_NAMETRUSTF_WARNONLY;
}

void
ringNameSetWarnonly(RingSet const *set, union RingObject *name)
{
	pgpAssert(OBJISNAME(name));
	pgpAssert(pgpIsRingSetMember(set, name));
	if (!(name->n.trust & PGP_NAMETRUSTF_WARNONLY)) {
		name->n.trust |= PGP_NAMETRUSTF_WARNONLY;
		name->g.flags |= RINGOBJF_TRUSTCHANGED;
		ringPoolMarkTrustChanged (set->pool, &name->g.mask);
	}
	name->g.flags |= RINGOBJF_TRUST;
}

PGPUInt16
ringNameValidity(RingSet const *set, union RingObject *name)
{
#if PGPTRUSTMODEL==0
    (void)set;
    (void)name;

⌨️ 快捷键说明

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