📄 pgpkeyobj.c
字号:
void
pgpSecClearValidated(PGPKeyDBObj *sec)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(sec));
pgpAssert(pgpKeyIsSec(sec));
kinfo = pgpKeyToKeyInfo( sec );
KEYCLEARVALIDATED( kinfo );
}
PGPBoolean
pgpSecIsValidated(PGPKeyDBObj *sec)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(sec));
pgpAssert(pgpKeyIsSec(sec));
kinfo = pgpKeyToKeyInfo( sec );
return KEYISVALIDATED( kinfo );
}
/*
* 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, or if it has been revoked by CRL.
*/
PGPBoolean
pgpSigRevoked (PGPKeyDBObj *sig)
{
PGPKeyDBObj *parent,
*sibling;
PGPSigInfo *sinfo;
PGPSigInfo *sibinfo;
pgpAssert (OBJISSIG(sig));
sinfo = pgpSigToSigInfo( sig );
/* Sigs can be declared irrevocable at creation time */
if (!SIGISREVOCABLE(sinfo))
return FALSE;
/* Check revoked flag */
if (sinfo->trust & PGP_SIGTRUSTF_REVOKEDBYCRL)
return TRUE;
parent = sig->up;
for (sibling = parent->down; sibling ; sibling = sibling->next) {
if( !pgpKeyDBObjIsReal(sibling) )
continue;
if (!OBJISSIG(sibling) || sibling == sig)
continue;
sibinfo = pgpSigToSigInfo( sibling );
if (sibinfo->by == sinfo->by) {
if (sibinfo->trust & PGP_SIGTRUSTF_CHECKED) {
if (sibinfo->tstamp > sinfo->tstamp) {
if (sibinfo->type == PGP_SIGTYPE_KEY_UID_REVOKE) {
/* Valid revocation */
return TRUE;
}
}
}
}
}
return FALSE;
}
PGPUInt16
pgpKeyConfidence(PGPKeyDBObj *key)
{
pgpAssert(OBJISKEY(key));
/* pgpKeyCalcTrust handles revoked/expired keys */
return pgpKeyCalcTrust (key);
}
void
pgpKeyID8(
PGPKeyDBObj const *key,
PGPByte *pkalg,
PGPKeyID *keyID)
{
PGPKeyInfo *kinfo;
PGPByte keypkalg;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
keypkalg = kinfo->pkalg;
if ((keypkalg | 1) == 3) /* ViaCrypt */
keypkalg = 1;
if (pkalg)
*pkalg = keypkalg;
if (keyID)
{
pgpNewKeyIDFromRawData( kinfo->keyID, keypkalg, 8, keyID );
}
}
void
pgpKeyID4(
PGPKeyDBObj const *key,
PGPByte *pkalg,
PGPKeyID *keyID)
{
PGPKeyInfo *kinfo;
PGPByte keypkalg;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
keypkalg = kinfo->pkalg;
if ((keypkalg | 1) == 3) /* ViaCrypt */
keypkalg = 1;
if (pkalg)
*pkalg = keypkalg;
if (keyID)
{
pgpNewKeyIDFromRawData( &kinfo->keyID[4], keypkalg, 4, keyID );
}
}
PGPBoolean
pgpKeyV3(PGPKeyDBObj const *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
return KEYISV3(kinfo) != 0;
}
PGPError
pgpKeyFingerprint16(PGPKeyDBObj *key,
PGPByte *buf)
{
PGPByte const *p;
PGPContextRef context;
PGPSize len;
pgpAssert(OBJISKEY(key));
context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( key ) );
p = (PGPByte const *)pgpFetchObject(key, &len);
if (!p)
return kPGPError_OutOfMemory;
return pgpKeyParseFingerprint16(context, p, len, buf);
}
PGPError
pgpKeyFingerprint20(PGPKeyDBObj *key,
PGPByte *buf)
{
PGPContextRef context;
PGPSize objlen;
PGPSize hlen;
PGPByte const *objbuf;
PGPBoolean mustFree = FALSE;
PGPError err;
pgpAssert(OBJISKEY(key));
context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( key ) );
if( pgpKeyIsSec( key ) )
{
objbuf = pgpKeyDBObjToPubData( key, &objlen );
mustFree = TRUE;
} else {
objbuf = (PGPByte const *)pgpFetchObject(key, &objlen);
}
hlen = pgpPktBufferHeaderLen( objbuf );
err = pgpFingerprint20HashBuf(context, objbuf+hlen, objlen-hlen, buf);
if( mustFree )
PGPFreeData( (PGPByte *)objbuf );
return err;
}
/* This does a 20 byte fingerprint based solely on the numeric material */
PGPError
pgpKeyFingerprint20n(PGPKeyDBObj *key,
PGPByte *buf)
{
PGPContextRef context;
PGPSize objlen;
PGPSize numlen;
PGPByte const *objbuf, *numbuf;
PGPBoolean mustfree = FALSE;
PGPError err;
pgpAssert(OBJISKEY(key));
context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( key ) );
if( pgpKeyIsSec (key) ) {
objbuf = pgpKeyDBObjToPubData( key, &objlen );
mustfree = TRUE;
} else {
objbuf = (PGPByte const *)pgpFetchObject(key, &objlen);
}
numbuf = pgpKeyParseNumericData(objbuf, objlen, &numlen);
err = pgpFingerprint20HashBuf(context, numbuf, numlen, buf);
if( mustfree )
PGPFreeData( (PGPByte *)objbuf );
return err;
}
/* Return TRUE if the key is a secret key */
PGPBoolean
pgpKeyIsSec(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
return KEYISSEC(kinfo) || KEYISTOKEN(kinfo);
}
/*
* Return the most recent subkey associated with the key, if there is one.
* The subkey must be in the specified keyset.
*/
PGPKeyDBObj *
pgpKeySubkey(PGPKeyDBObj const *key, PGPKeySet *set)
{
PGPKeyDBObj *obj, *best = NULL;
PGPUInt32 objtime, besttime = 0;
pgpAssert(OBJISKEY(key));
for (obj = key->down; IsntNull(obj); obj = obj->next) {
if( !pgpKeyDBObjIsReal(obj) )
continue;
if( !OBJISSUBKEY(obj) )
continue;
if( IsntNull(set) && !pgpKeySetIsMember(obj, set ) )
continue;
if (pgpSubkeyValid(obj, TRUE, FALSE)) {
objtime = pgpKeyCreation(obj);
if (besttime <= objtime) {
best = obj;
besttime = objtime;
}
}
}
return best;
}
/* Given a subkey, return its master key */
PGPKeyDBObj *
pgpKeyMasterkey (PGPKeyDBObj const *subkey)
{
pgpAssert (OBJISSUBKEY(subkey));
pgpAssert (OBJISTOPKEY(subkey->up));
return subkey->up;
}
/* Return MPI data of key */
PGPByte const *
pgpKeyMPIData( PGPKeyDBObj const *key, PGPSize *plen )
{
PGPSize len;
PGPSize hlen;
PGPSize offset;
PGPByte const *buf;
pgpAssert (OBJISKEY(key));
pgpAssert( IsntNull( plen ) );
*plen = 0;
buf = pgpFetchObject( key, &len );
if( IsNull( buf ) )
return buf;
hlen = pgpPktBufferHeaderLen( buf );
buf += hlen;
len -= hlen;
/* V4 keys are two bytes shorter than V3 */
offset = 6;
if (buf[0] <= PGPVERSION_3)
offset += 2;
len -= offset;
*plen = len;
return buf + offset;
}
/*
* 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 *
pgpKeyPubKey(PGPKeyDBObj *key, int use)
{
PGPKeyInfo *kinfo;
PGPByte const *p;
PGPSize len;
PGPSize hlen;
PGPPubKey *pub;
PGPKeyDBObj *subkey = NULL;
unsigned vsize;
PGPError i;
PGPContextRef context;
context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( key ) );
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
/* Select between subkey and key if necessary */
if (use && (OBJISSUBKEY(key)
|| ((subkey=pgpKeySubkey(key, NULL)) != NULL))) {
if (use == PGP_PKUSE_SIGN_ENCRYPT) {
pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(key),
kPGPError_PublicKeyUnimplemented);
return NULL;
}
if (use == PGP_PKUSE_ENCRYPT) {
/* Always encrypt to subkey if there is one */
/* Eventually need to make this skip signature subkeys */
if (OBJISTOPKEY(key)) {
pgpAssert(subkey);
key = subkey;
pgpAssert (OBJISSUBKEY(key));
kinfo = pgpKeyToKeyInfo( key );
}
} else if (use == PGP_PKUSE_SIGN) {
/* Allow verification with subkey if explicit, else go up */
if (use && ((pgpKeyAlgUse(pgpPkalgByNumber(kinfo->pkalg)) & use) !=
(unsigned)use)){
if (OBJISSUBKEY(key)) {
key = key->up;
pgpAssert (OBJISTOPKEY(key));
kinfo = pgpKeyToKeyInfo( key );
}
}
}
}
/* Verify key satisfies required usage */
if (use && ((pgpKeyAlgUse(pgpPkalgByNumber(kinfo->pkalg)) & use) !=
(unsigned)use)){
pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(key),
kPGPError_PublicKeyUnimplemented);
return NULL;
}
p = (PGPByte const *)pgpFetchObject(key, &len);
if (!p)
return NULL;
hlen = pgpPktBufferHeaderLen( p );
p += hlen;
len -= hlen;
/*
* 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] == kinfo->pkalg); /* Checked by pgpKeyVerify */
pub = pgpPubKeyFromBuf( context, p[5+vsize], p+6+vsize, len-6-vsize, &i);
if (!pub) {
pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(key), i);
return NULL;
}
memcpy(pub->keyID, kinfo->keyID, sizeof(kinfo->keyID));
pub->keyDBObj = key;
return pub;
}
/*
* Return the version for a key.
*/
PgpVersion
pgpKeyVersion (PGPKeyDBObj *key)
{
PGPByte *kdata;
PGPSize kdatalen;
PGPSize hlen;
pgpAssert(OBJISKEY( key ) );
kdata = (PGPByte *)pgpFetchObject (key, &kdatalen);
pgpAssert( IsntNull( kdata ) );
hlen = pgpPktBufferHeaderLen( kdata );
kdata += hlen;
kdatalen -= hlen;
return (PgpVersion)kdata[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 *
pgpSecSecKey(PGPKeyDBObj *sec, int use)
{
PGPKeyInfo *kinfo;
PGPByte const *p;
PGPSize len;
PGPSize hlen;
PGPSecKey *seckey;
PGPKeyDBObj *subkey = NULL;
unsigned vsize;
PGPError i;
PGPContextRef context;
PGPToken *tok = NULL;
context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( sec ) );
pgpAssert(OBJISKEY(sec));
pgpAssert(pgpKeyIsSec(sec));
kinfo = pgpKeyToKeyInfo( sec );
/* Select between subkey and sec if necessary */
if (use && (OBJISSUBKEY(sec)
|| ((subkey=pgpKeySubkey(sec, NULL)) != NULL))) {
if (use == PGP_PKUSE_SIGN_ENCRYPT) {
pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(sec),
kPGPError_PublicKeyUnimplemented);
return NULL;
}
/* For decrypt/sign, we will use the specified key if legal */
/* This will allow us to decrypt with top level RSA key */
/* Could also sign with subkeys eventually */
if (use && ((pgpKeyAlgUse(pgpPkalgByNumber(kinfo->pkalg)) & use) !=
(unsigned)use)){
if (use == PGP_PKUSE_ENCRYPT) {
if (OBJISTOPKEY(sec)) {
pgpAssert(subkey);
sec = subkey;
pgpAssert (OBJISSUBKEY(sec));
kinfo = pgpKeyToKeyInfo( sec );
}
} else if (use == PGP_PKUSE_SIGN) {
if (OBJISSUBKEY(sec)) {
sec = sec->up;
pgpAssert (OBJISTOPKEY(sec));
kinfo = pgpKeyToKeyInfo( sec );
}
}
}
}
/* Verify sec satisfies required usage */
if (use && ((pgpKeyAlgUse(pgpPkalgByNumber(kinfo->pkalg)) & use) !=
(unsigned)use)){
pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(sec),
kPGPError_PublicKeyUnimplemented);
return NULL;
}
/* See if key is on a hardware token */
if( !KEYISSEC(kinfo) && KEYISTOKEN(kinfo) )
tok = pgpTokenFromKeyID( kinfo->keyID );
p = (PGPByte const *)pgpFetchObject(sec, &len);
if (!p)
return NULL;
hlen = pgpPktBufferHeaderLen( p );
p += hlen;
len -= hlen;
if (p[0] == PGPVERSION_4) {
vsize = 0;
} else {
vsize = 2;
}
pgpAssert(p[5+vsize] == kinfo->pkalg);
seckey = pgpSecKeyFromBuf( context, p[5+vsize], p+6+vsize, len-6-vsize,
(PGPBoolean)!!KEYISV3(kinfo), tok, &i);
if (!seckey) {
pgpKeyDBSetError(PGPPeekKeyDBObjKeyDB(sec), i);
return NULL;
}
memcpy(seckey->keyID, kinfo->keyID, sizeof(kinfo->keyID));
seckey->keyDBObj = sec;
return seckey;
}
/* Return the latest valid sig on the object by the specified key */
PGPKeyDBObj *
pgpLatestSigByKey (PGPKeyDBObj const *obj, PGPKeyDBObj const *key)
{
PGPKeyDBObj *sig;
PGPKeyDBObj *latestsig;
pgpAssert (!OBJISSIG(obj));
latestsig = NULL;
for (sig=obj->down; IsntNull(sig); sig=sig->next) {
if( !pgpKeyDBObjIsReal(sig) )
continue;
if (!OBJISSIG(sig))
continue;
if (pgpSigMaker (sig) != key)
continue;
if ((pgpSigType (sig) & 0xf0) != PGP_SIGTYPE_KEY_GENERIC)
continue;
if (!pgpSigChecked (sig) || pgpSigRevoked (sig))
continue;
/* Save the newest such signature on the name */
if (!latestsig) {
latestsig = sig;
} else {
if (pgpSigTimestamp(sig) > pgpSigTimestamp(latestsig))
latestsig = sig;
}
}
return latestsig;
}
/* True if there is a newer sig of the same type by the same key */
PGPBoolean
pgpSigIsSuperceded( PGPKeyDBObj const *sig )
{
PGPKeyDBObj *obj;
PGPKeyDBObj *signer;
PGPUInt32 type;
PGPSigInfo *sinfo;
pgpAssert( OBJISSIG(sig) );
sinfo = pgpSigToSigInfo( sig );
if( !SIGISREVOCABLE(sinfo) )
return FALSE;
signer = pgpSigMaker( sig );
type = pgpSigType( sig ) & 0xf0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -