📄 pgpkeysig.c
字号:
if( IsPGPError(err ) )
goto error;
pgpPubKeyDestroy( (PGPPubKey *)pub );
pub = NULL;
/* Process cert into a structure using ASN.1 library */
err = pgpX509BufferToCert( context, x509cert, x509len, &cert );
if( IsPGPError( err ) )
goto error;
/* At this point we can destroy the raw X.509 buffer data */
x509cert = NULL;
/* Check to see if data from X.509 cert matches parent key and userid */
err = pgpX509CertToKeyBuffer(context, &keydb->objPool, keydb, cert,
loversion, &buf, &len);
if( IsPGPError( err ) || sObjDiffers( parentkey, buf, len ) )
goto error;
err = pgpX509CertToUserIDBuffer (context, &keydb->objPool, cert, loversion,
&buf, &len );
if( IsPGPError( err ) || sObjDiffers( parentuserid, buf, len ) )
goto error;
err = pgpX509CertToSigBuffer (context, &keydb->objPool, cert, loversion,
&buf, &len );
if( IsPGPError( err ) || sObjDiffers( obj, buf, len ) )
goto error;
pgpX509FreeCert( context, cert );
memPoolCutBack( &keydb->objPool, &mempoolinit );
/* All OK */
return TRUE;
error:
if( IsntNull( pub ) )
pgpPubKeyDestroy( (PGPPubKey *)pub );
if( IsntNull( cert ) )
pgpX509FreeCert( context, cert );
memPoolCutBack( &keydb->objPool, &mempoolinit );
return FALSE;
}
/*
* Mark all the signatures in its keydb that crl revokes as REVOKEDBYCRL.
* crl's parent is "key".
* If otherdb is not null, ONLY mark the ones there. In that case
* return changedSet as being the changed keys in that set as it is the
* primary one of interest. (The idea here is that this is used for the
* case where "otherdb" is really the main db and the key is a signer
* in another keydb.)
*/
static PGPError
sPropagateOneCRL( PGPKeyDBObj *key, PGPKeyDBObj *crl, PGPKeyDBRef otherdb,
PGPKeySetRef changedSet )
{
PGPASN_Certificate *cert = NULL;
PGPASN_CertificateRevocationList *crl509 = NULL;
PGPASN_revokedCertificates_SEQ_OF *revs;
PGPASN_INTEGER *certnum, *revnum;
PGPByte *buf;
PGPSize len;
PGPByte *x509cert;
PGPSize x509len;
PGPKeyDBObj *sig;
PGPInt32 i;
PGPInt32 count;
PGPInt32 numrevsleft;
PGPKeyInfo *kinfo;
PGPKeyDBObj *pairkey = NULL;
PGPSigInfo *sinfo = NULL;
PGPKeyDB *keydb;
PGPContextRef context;
PGPError err = kPGPError_NoErr;
pgpAssert (OBJISKEY(key));
pgpAssert (OBJISCRL(crl));
keydb = PGPPeekKeyDBObjKeyDB( crl );
context = PGPPeekKeyDBContext( keydb );
kinfo = pgpKeyToKeyInfo( key );
buf = (PGPByte *)pgpFetchObject( crl, &len );
if( IsNull(buf) )
{
err = pgpKeyDBError( keydb );
goto error;
}
buf = (PGPByte *)pgpCRLFindCRL( buf, len, &len );
if( IsNull( buf ) )
{
/* Unknown CRL type, ignore it */
err = kPGPError_NoErr;
goto error;
}
err = pgpX509BufferToCRL( context, buf, len, &crl509 );
if( IsPGPError( err ) )
goto error;
if( IsNull( crl509->tbsCertList.revokedCertificates ) )
{
/* Nothing to do */
goto error;
}
revs = crl509->tbsCertList.revokedCertificates;
count = revs->n;
if( count == 0 )
{
/* Nothing to do */
goto error;
}
numrevsleft = count;
/* Find corresponding key in otherdb if it exists */
if( IsntNull( otherdb ) )
{
pairkey = pgpFindPairedX509Key( key, otherdb );
/* If no such key in otherdb, we are done */
if( IsNull( pairkey ) )
goto error;
kinfo = pgpKeyToKeyInfo( pairkey );
/* By setting kinfo we will look in otherdb for sigs to propagate */
}
/* Check all sigs issued by key to see if any are revoked */
for( sig=kinfo->sigsby; IsntNull(sig); sig=sinfo->nextby )
{
pgpAssert( OBJISSIG( sig ) );
sinfo = pgpSigToSigInfo(sig);
if( !SIGISX509(sinfo) )
continue;
buf = (PGPByte *)pgpFetchObject( sig, &len );
if( IsNull(buf) )
{
err = pgpKeyDBError( keydb );
goto error;
}
x509cert = (PGPByte *)pgpSigFindNAISubSubpacket(buf,
SIGSUBSUB_X509, 0, &x509len, NULL, NULL,
NULL, NULL);
if( IsNull( x509cert ) )
continue;
/* Skip type, version bytes */
pgpAssert (x509cert[0] == SIGSUBSUB_X509);
x509cert += 3;
x509len -= 3;
/* Process cert into a structure using ASN.1 library */
err = pgpX509BufferToCert( context, x509cert, x509len, &cert );
if( IsPGPError( err ) )
continue;
/* Get pointer to cert's serial number, which we will compare */
certnum = &cert->tbsCertificate.serialNumber;
/* Compare against each entry in the CRL */
for (i=0; i<count; ++i)
{
revnum = &revs->elt[i]->userCertificate;
if( certnum->len == revnum->len &&
pgpMemoryEqual( certnum->val, revnum->val, revnum->len) )
{
/* Have a match, cert is revoked */
if( IsntNull( changedSet ) &&
!(sinfo->trust & PGP_SIGTRUSTF_REVOKEDBYCRL) )
PGPAddKey( PGPPeekKeyDBObjKey(sig), changedSet );
sinfo->trust |= PGP_SIGTRUSTF_REVOKEDBYCRL;
if( --numrevsleft == 0 )
{
/* We have accounted for all revocations */
err = kPGPError_NoErr;
goto error;
}
break;
}
}
pgpX509FreeCert( context, cert );
cert = NULL;
}
error:
if( IsntNull( cert ) )
pgpX509FreeCert( context, cert );
if( IsntNull( crl509 ) )
pgpX509FreeCRL( context, crl509 );
return err;
}
/*
* Check one CRL on a keyring. Set its trust flags to show whether the
* signature checks OK.
*/
static PGPError
sCheckOneCRL( PGPKeyDBObj *key, PGPKeyDBObj *crl, PGPKeySetRef changedSet )
{
PGPByte *buf;
PGPSize len;
PGPPubKey *pub = NULL;
PGPKeyDB *keydb;
PGPContextRef context;
PGPCRLInfo *cinfo;
PGPError err = kPGPError_NoErr;
pgpAssert (OBJISKEY(key));
pgpAssert (OBJISCRL(crl));
keydb = PGPPeekKeyDBObjKeyDB( key );
context = PGPPeekKeyDBContext( keydb );
cinfo = pgpCRLToCRLInfo( crl );
/* Get the pubkey struct for signing key */
pub = pgpKeyPubKey(key, PGP_PKUSE_SIGN);
if( IsNull(pub) )
{
err = pgpKeyDBError(keydb);
if( pgpIsKeyRelatedError( err ) )
err = kPGPError_NoErr;
goto error;
}
buf = (PGPByte *)pgpFetchObject( crl, &len );
if( IsNull(buf) )
{
err = pgpKeyDBError(keydb);
goto error;
}
buf = (PGPByte *)pgpCRLFindCRL( buf, len, &len );
err = pgpX509VerifySignedObject( context, pub, buf, len );
if( IsPGPError(err ) )
{
if( err == kPGPError_X509InvalidCertificateSignature )
{
if( IsntNull( changedSet ) &&
(cinfo->trust & PGP_SIGTRUSTF_CHECKED_TRIED) !=
PGP_SIGTRUSTF_TRIED )
PGPAddKey( key, changedSet );
cinfo->trust &= ~PGP_SIGTRUSTF_CHECKED;
cinfo->trust |= PGP_SIGTRUSTF_TRIED;
}
err = kPGPError_NoErr;
} else {
if( IsntNull( changedSet ) &&
(cinfo->trust & PGP_SIGTRUSTF_CHECKED_TRIED) !=
PGP_SIGTRUSTF_CHECKED_TRIED )
PGPAddKey( key, changedSet );
cinfo->trust |= PGP_SIGTRUSTF_CHECKED_TRIED;
}
error:
if( IsntNull( pub ) )
pgpPubKeyDestroy( pub );
return err;
}
/*
* Check the CRLs on a keyring. If allflag is true, recheck all, else
* only check unchecked ones. Propagate revocations to sigs in keyset.
* If otherdb is not null, we return the changedSet as keys in that
* set, as it is the primary one of interest.
*/
static PGPError
sCheckCRLs( PGPKeySet *keyset, int allflag, PGPKeyDBRef otherdb,
PGPKeySetRef changedSet )
{
PGPKeyDBObj *key = NULL;
PGPKeyDB *keydb;
PGPKeyDBObj *obj;
PGPCRLInfo *cinfo;
PGPError err = kPGPError_NoErr;
keydb = PGPPeekKeySetKeyDB( keyset );
for( key = keydb->firstKeyInDB; IsntNull( key ); key = key->next )
{
if( !pgpKeyDBObjIsReal( key ) )
continue;
if( !pgpKeySetIsMember( key, keyset ) )
continue;
for( obj = key->down; IsntNull( obj ); obj = obj->next )
{
if( !pgpKeyDBObjIsReal( obj ) )
continue;
if( !OBJISCRL(obj) )
continue;
cinfo = pgpCRLToCRLInfo( obj );
if( allflag || !(cinfo->trust & PGP_SIGTRUSTF_CHECKED_TRIED) )
{
pgpAssert( IsntNull( key ) );
err = sCheckOneCRL (key, obj,
IsntNull(otherdb)?changedSet:NULL);
if( IsPGPError( err ) )
goto error;
}
if( cinfo->trust & PGP_SIGTRUSTF_CHECKED )
{
err = sPropagateOneCRL (key, obj, otherdb, changedSet);
if( IsPGPError( err ) )
goto error;
}
}
}
error:
return err;
}
/*
* Check the signatures in a keydb. Checks only unchecked signatures,
* or all signatures if allflag is true. If revocationonly is set,
* only revocation signatures are checked (allflag again controls whether
* previously checked rev sigs are rechecked).
*
* Signatures may be made either by keys in keydb or in otherdb.
*
* If func is non-null, calls it with each checked signature, after
* checking. This is for progress indications. If func returns a
* negative value, the check is aborted.
*
* If frontEnd is true we are called on the front end and must do it all
* on the back end.
*/
PGPError
pgpCheckKeySigs(PGPKeySet *keyset, PGPKeyDB *otherdb,
PGPBoolean allflag, PGPBoolean revocationonly, PGPBoolean frontEnd,
PGPError (*func)(void *, PGPKeyDBObj *, int), void *arg,
PGPKeySetRef changeSet )
{
PGPContextRef context;
PGPKeyDB *keydb;
PGPKeyDBObj *key;
PGPKeyDBObj *child;
PGPKeyDBObj *gchild;
PGPUInt32 setID;
PGPUInt32 otherID;
PGPBoolean handled, verified, changed;
PGPError err = kPGPError_NoErr;
if( frontEnd )
pgpAssert( IsntNull( func ) );
keydb = PGPPeekKeySetKeyDB( keyset );
context = PGPPeekKeyDBContext( keydb );
setID = keydb->id;
otherID = IsNull(otherdb) ? 0 : otherdb->id;
if( !frontEnd )
{
if( IsPGPError( err = sCheckCRLs( keyset, allflag, NULL, changeSet )))
goto error;
if( IsntNull( otherdb ) )
{
/* Must check CRLs in otherdb against this one */
PGPKeySetRef oroot = PGPPeekKeyDBRootKeySet( otherdb );
if( IsPGPError( err = sCheckCRLs( oroot, allflag,
keydb, changeSet ) ) )
goto error;
}
}
for( key = keydb->firstKeyInDB; IsntNull( key ); key = key->next)
{
if( !pgpKeyDBObjIsReal( key ) )
continue;
if( !pgpKeySetIsMember( key, keyset ) )
continue;
for( child = key->down; IsntNull( child ); child = child->next)
{
if( !pgpKeyDBObjIsReal( child ) )
continue;
if( !pgpKeySetIsMember( child, keyset ) )
continue;
if( pgpObjectType( child ) == RINGTYPE_SIG )
{
if( frontEnd )
{
err = pgpCheckSig_back( context, setID,
pgpKeyDBObjID(child), otherID,
allflag, revocationonly,
&handled, &changed, &verified);
} else {
err = pgpCheckSig_internal( keydb, child, otherdb,
allflag, revocationonly,
&handled, &changed,
&verified);
}
if( IsPGPError( err ) )
goto error;
if( changed && IsntNull(changeSet) )
PGPAddKey( key, changeSet );
if( handled && IsntNull(func) )
{
err = func( arg, child, verified );
if( IsPGPError( err ) )
goto error;
}
}
for( gchild = child->down; IsntNull(gchild); gchild = gchild->next)
{
if( !pgpKeyDBObjIsReal( gchild ) )
continue;
if( !pgpKeySetIsMember( gchild, keyset ) )
continue;
if( pgpObjectType( gchild ) == RINGTYPE_SIG )
{
if( frontEnd )
{
err = pgpCheckSig_back( context, setID,
pgpKeyDBObjID(gchild), otherID,
allflag, revocationonly,
&handled, &changed, &verified);
} else {
err = pgpCheckSig_internal( keydb, gchild, otherdb,
allflag, revocationonly,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -