📄 pgprngpub.c
字号:
* 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 + -