📄 pgpkeyobj.c
字号:
}
else
return 0;
}
PGPUInt32
pgpSigType(PGPKeyDBObj const *sig)
{
PGPSigInfo *sinfo;
pgpAssert(OBJISSIG(sig));
sinfo = pgpSigToSigInfo( sig );
return sinfo->type;
}
PGPUInt32
pgpSigTimestamp(PGPKeyDBObj const *sig)
{
PGPSigInfo *sinfo;
pgpAssert(OBJISSIG(sig));
sinfo = pgpSigToSigInfo( sig );
return sinfo->tstamp;
}
PGPUInt32
pgpSigExpiration(PGPKeyDBObj const *sig)
{
PGPSigInfo *sinfo;
pgpAssert(OBJISSIG(sig));
sinfo = pgpSigToSigInfo( sig );
if (sinfo->tstamp == 0 || sinfo->sigvalidity == 0)
return 0; /* valid indefinitely */
else
return sinfo->tstamp + sinfo->sigvalidity;
}
/*
* True if sig is a self-sig.
*/
PGPBoolean
pgpSigIsSelfSig(PGPKeyDBObj const *sig)
{
PGPKeyDBObj const *parent;
PGPSigInfo *sinfo;
pgpAssert(OBJISSIG(sig));
sinfo = pgpSigToSigInfo( sig );
/* Find top-level key */
parent = sig;
while (!OBJISTOPKEY(parent))
parent = parent->up;
/* No good if not signed by top-level key (selfsig) */
if (sinfo->by != parent)
return FALSE;
/* All OK */
return TRUE;
}
/*
* True if sig is an X509 sig.
*/
PGPBoolean
pgpSigIsX509(PGPKeyDBObj const *sig)
{
PGPSigInfo *sinfo;
pgpAssert(OBJISSIG(sig));
sinfo = pgpSigToSigInfo( sig );
return SIGISX509(sinfo) != 0;
}
PGPByte *
pgpSigX509Certificate(PGPKeyDBObj *sig, PGPSize *len)
{
PGPSigInfo *sinfo;
PGPByte *ptr;
pgpAssert(OBJISSIG(sig));
pgpAssert(IsntNull(len));
sinfo = pgpSigToSigInfo( sig );
*len = 0;
if (!SIGISX509 (sinfo))
return NULL;
ptr = (PGPByte *)pgpFetchObject(sig, len);
if (IsNull( ptr ) )
return NULL;
ptr = (PGPByte *)pgpSigFindNAISubSubpacket(ptr, SIGSUBSUB_X509, 0, len,
NULL, NULL, NULL, NULL);
if( IsntNull( ptr ) ) {
/* Skip type, version bytes */
pgpAssert (ptr[0] == SIGSUBSUB_X509);
ptr += 3;
*len -= 3;
}
return ptr;
}
PGPBoolean
pgpCRLChecked(PGPKeyDBObj const *crl)
{
PGPCRLInfo *cinfo;
pgpAssert(OBJISCRL(crl));
cinfo = pgpCRLToCRLInfo( crl );
return (cinfo->trust & PGP_SIGTRUSTF_CHECKED) != 0;
}
PGPBoolean
pgpCRLTried(PGPKeyDBObj const *crl)
{
PGPCRLInfo *cinfo;
pgpAssert(OBJISCRL(crl));
cinfo = pgpCRLToCRLInfo( crl );
return (cinfo->trust & PGP_SIGTRUSTF_TRIED) != 0;
}
PGPUInt32
pgpCRLCreation(PGPKeyDBObj const *crl)
{
PGPCRLInfo *cinfo;
pgpAssert(OBJISCRL(crl));
cinfo = pgpCRLToCRLInfo( crl );
return cinfo->tstamp;
}
PGPUInt32
pgpCRLExpiration(PGPKeyDBObj const *crl)
{
PGPCRLInfo *cinfo;
pgpAssert(OBJISCRL(crl));
cinfo = pgpCRLToCRLInfo( crl );
return cinfo->tstampnext;
}
/* True if the key has a CRL */
PGPBoolean
pgpKeyHasCRL(PGPKeyDBObj *key)
{
PGPKeyDBObj *child;
for (child = key->down; IsntNull(child); child = child->next) {
if (!OBJISCRL(child))
continue;
if( !pgpKeyDBObjIsReal(child) )
continue;
if (!pgpCRLChecked(child))
continue;
return TRUE;
}
return FALSE;
}
/* Return nth CRL of key, along with a count of all CRLs if requested.
* Doesn't count superceded CRLs.
* Call this the first time with n=0 and &crlcount, and later times with
* crlcount holding NULL.
*/
PGPKeyDBObj *
pgpKeyNthCRL(PGPKeyDBObj *key, PGPUInt32 n, PGPUInt32 *crlcount)
{
PGPKeyDBObj *obj;
PGPKeyDBObj *nthcrl = NULL;
PGPUInt32 count = 0;
if( IsntNull( crlcount ) )
*crlcount = 0;
for (obj = key->down; IsntNull(obj); obj = obj->next) {
if (!OBJISCRL(obj))
continue;
if( !pgpKeyDBObjIsReal(obj) )
continue;
if (!pgpCRLChecked(obj))
continue;
if (!pgpCRLIsCurrent(obj, 0))
continue;
if (count++ == n) {
nthcrl = obj;
if (IsNull( crlcount ))
break;
}
}
if( IsntNull( crlcount ) )
*crlcount = count;
return nthcrl;
}
/*
* Find the earliest non-replaced CRL issued by a key.
* If expiration is true, use expiration dates, else creation dates.
*/
PGPKeyDBObj *
pgpKeyEarliestCRL(PGPKeyDBObj *key, PGPBoolean expiration)
{
PGPKeyDBObj *crl;
PGPKeyDBObj *bestcrl = NULL;
PGPUInt32 crltime;
PGPUInt32 besttime = (PGPUInt32)-1L;
PGPUInt32 n = 0;
PGPUInt32 crlcount = 0;
do {
crl = pgpKeyNthCRL(key, n, (n?NULL:&crlcount));
if( IsNull( crl ) )
break;
if( expiration )
crltime = pgpCRLExpiration( crl );
else
crltime = pgpCRLCreation( crl );
if (crltime < besttime) {
besttime = crltime;
bestcrl = crl;
}
} while (n++ < crlcount);
return bestcrl;
}
/*
* See whether there is a more recent CRL for this key with the same
* dist. point.
* If tstamp is nonzero, also checks for expiration of CRL.
*/
PGPBoolean
pgpCRLIsCurrent (PGPKeyDBObj *crl, PGPUInt32 tstamp)
{
PGPKeyDBObj *obj;
PGPKeyDBObj *key;
PGPKeyDB *db;
PGPCRLInfo *cinfo;
PGPCRLInfo *cinfo2;
PGPUInt32 crlcreation, crlexpiration;
PGPUInt32 objcreation;
PGPByte const *tmpdpoint;
PGPByte *dpoint = NULL;
PGPByte const *dpoint2;
PGPSize dpointlen;
PGPSize dpoint2len;
PGPContextRef context;
pgpAssert (OBJISCRL(crl));
cinfo = pgpCRLToCRLInfo( crl );
db = PGPPeekKeyDBObjKeyDB( crl );
context = PGPPeekKeyDBContext( db );
crlcreation = pgpCRLCreation(crl);
crlexpiration = pgpCRLExpiration(crl);
if (tstamp != 0) {
if (crlexpiration < tstamp)
return FALSE;
}
if( CRLHASDPOINT( cinfo ) ) {
/* Read dpoint data structure */
tmpdpoint = pgpCRLDistributionPoint( crl, &dpointlen );
dpoint = pgpContextMemAlloc( context, dpointlen, 0 );
pgpCopyMemory( tmpdpoint, dpoint, dpointlen );
if( IsNull( dpoint ) ) {
return TRUE;
}
}
/* Find key above CRL */
key = crl->up;
pgpAssert (OBJISKEY(key));
for (obj = key->down; IsntNull(obj); obj = obj->next) {
pgpAssert(obj);
if (obj == crl)
continue;
if (!OBJISCRL(obj))
continue;
if( !pgpKeyDBObjIsReal(obj) )
continue;
if (!pgpCRLChecked(obj))
continue;
cinfo2 = pgpCRLToCRLInfo( obj );
if (CRLHASDPOINT(cinfo2) != CRLHASDPOINT(cinfo))
continue;
if (CRLHASDPOINT(cinfo)) {
dpoint2 = pgpCRLDistributionPoint( obj, &dpoint2len );
if (dpointlen != dpoint2len ||
!pgpMemoryEqual( dpoint, dpoint2, dpointlen ))
continue;
}
objcreation = pgpCRLCreation(obj);
if (objcreation > crlcreation) {
if (CRLHASDPOINT( cinfo ) )
pgpContextMemFree( context, dpoint );
return FALSE;
}
}
if (CRLHASDPOINT( cinfo ) )
pgpContextMemFree( context, dpoint );
return TRUE;
}
/* Return CRL Distribution Point, in the "fetch" buffer */
/* Return NULL if CRL has no distribution point */
PGPByte const *
pgpCRLDistributionPoint( PGPKeyDBObj *crl, PGPSize *len )
{
PGPByte const *ptr;
PGPCRLInfo *cinfo;
pgpAssert (OBJISCRL(crl));
pgpAssert (IsntNull( len ) );
cinfo = pgpCRLToCRLInfo( crl );
*len = 0;
if( !CRLHASDPOINT( cinfo ) )
return NULL;
ptr = pgpFetchObject(crl, len);
if (IsNull( ptr ) )
return NULL;
ptr = pgpCRLFindDPoint( ptr, *len, len );
return ptr;
}
/*
* Return a buffer full of all the CRL Distribution Points associated with
* a given key. We find them by listing those in the CRLs we have stored
* with the key, plus we search all certs which the key has issued and get
* any others from those. Also return the number of CDP's in the buffer.
* The buffer is a newly allocated buffer.
* Also return a newly allocated buffer of sizes of the CDP's.
*/
PGPError
pgpListCRLDistributionPoints(
PGPMemoryMgrRef mgr, /* Input parameters */
PGPKeyDBObj *key,
PGPUInt32 *pnDistPoints, /* Output parameters */
PGPByte **pbuf,
PGPSize **pbufsizes
)
{
PGPContextRef context;
PGPKeyInfo *kinfo;
PGPSigInfo *sinfo;
PGPASN_XTBSCertificate *xtbscert;
PGPUInt32 nDistPoints = 0;
PGPByte *buf = NULL;
PGPSize bufsize = 0;
PGPSize *bufsizes = NULL;
PGPByte const *crldpoint;
PGPByte const *certdpoint = NULL; /* dynamically allocated */
PGPSize dpointlen;
PGPError err = kPGPError_NoErr;
PGPUInt32 nth;
PGPKeyDBObj *crlobj;
PGPKeyDBObj *sig;
PGPByte *p;
PGPSize len;
void *vbuf;
PGPUInt32 crlcount;
pgpAssert( IsntNull( pbuf ) );
pgpAssert( IsntNull( pbufsizes ) );
pgpAssert( IsntNull( pnDistPoints ) );
pgpAssert (OBJISTOPKEY(key));
kinfo = pgpKeyToKeyInfo( key );
context = PGPPeekKeyDBContext(PGPPeekKeyDBObjKeyDB( key ) );
*pbuf = NULL;
*pbufsizes = NULL;
*pnDistPoints = 0;
/* First check any CRLs stored with the key */
nth = 0;
do
{
crlobj = pgpKeyNthCRL( key, nth, &crlcount );
if( IsNull( crlobj ) )
break;
crldpoint = pgpCRLDistributionPoint( crlobj, &dpointlen );
if( IsntNull( crldpoint ) )
{
if( !pgpX509BufInSequenceList( crldpoint,dpointlen,buf,bufsize ) )
{
bufsize += dpointlen;
vbuf = buf;
err = PGPReallocData( mgr, &vbuf, bufsize, 0 );
buf = vbuf;
if( IsPGPError( err ) )
goto error;
pgpCopyMemory( crldpoint, buf+bufsize-dpointlen, dpointlen );
++nDistPoints;
vbuf = bufsizes;
err = PGPReallocData( mgr, &vbuf,
nDistPoints*sizeof(PGPSize), 0 );
bufsizes = vbuf;
if( IsPGPError( err ) )
goto error;
bufsizes[nDistPoints-1] = dpointlen;
}
}
} while (++nth < crlcount);
/* Now check all certs signed by key */
for( sig = kinfo->sigsby; IsntNull( sig ); sig = sinfo->nextby )
{
sinfo = pgpSigToSigInfo(sig);
if( !pgpKeyDBObjIsReal(sig) )
continue;
if( !SIGISX509( sinfo ) || !SIGHASDISTPOINT( sinfo ) )
continue;
/* Find distribution point in cert */
p = (PGPByte *)pgpFetchObject(sig, &len);
if( IsNull( p ) )
continue;
p = (PGPByte *)pgpSigFindNAISubSubpacket(p, SIGSUBSUB_X509, 0, &len,
NULL, NULL, NULL, NULL);
if( IsNull( p ) )
continue;
p += 3;
len -= 3;
err = pgpX509BufferToXTBSCert( context, p, len, &xtbscert);
if( IsPGPError( err ) ) {
err = kPGPError_NoErr;
continue;
}
/* Note that dpointcert is dynamically allocated */
certdpoint = pgpX509XTBSCertToDistPoint( xtbscert, &dpointlen );
pgpX509FreeXTBSCert( context, xtbscert );
if( IsntNull( certdpoint ) &&
!pgpX509BufInSequenceList( certdpoint, dpointlen, buf, bufsize ) )
{
bufsize += dpointlen;
vbuf = buf;
err = PGPReallocData( mgr, &vbuf, bufsize, 0 );
buf = vbuf;
if( IsPGPError( err ) )
goto error;
pgpCopyMemory( certdpoint, buf+bufsize-dpointlen, dpointlen );
++nDistPoints;
vbuf = bufsizes;
err = PGPReallocData( mgr, &vbuf,
nDistPoints*sizeof(PGPSize), 0);
bufsizes = vbuf;
if( IsPGPError( err ) )
goto error;
bufsizes[nDistPoints-1] = dpointlen;
}
PGPFreeData( (PGPByte *)certdpoint );
certdpoint = NULL;
}
*pbuf = buf;
*pbufsizes = bufsizes;
*pnDistPoints = nDistPoints;
return kPGPError_NoErr;
error:
if( IsntNull( buf ) )
PGPFreeData( buf );
if( IsntNull( bufsizes ) )
PGPFreeData( bufsizes );
if( IsntNull( certdpoint ) )
PGPFreeData( (PGPByte *)certdpoint );
return err;
}
/* Helper function for below - Given a sig, see if it has a subpacket
* of the type we are interested in. Given that we have seen *pmatches
* other subpackets of that type so far, see if this is the nth one.
* If so, set the various return parameters to point at the data for
* this subpacket.
*/
static PGPError
sFindSubpacket (PGPKeyDBObj *sig, int subpacktype, unsigned nth,
PGPByte const **pdata, PGPSize *plen, PGPBoolean *pcritical,
PGPBoolean *phashed, PGPUInt32 *pcreation, unsigned *pmatches,
PGPKeyDBObj **psig )
{
PGPByte *p;
PGPByte *subp;
PGPUInt32 matches;
PGPSize len;
/* Here we have a nonrevocable self signature */
p = (PGPByte *)pgpFetchObject(sig, &len);
if (!p)
return pgpKeyDBError(PGPPeekKeyDBObjKeyDB(sig));
subp = (PGPByte *)pgpSigFindSubpacket (p, subpacktype, 0, NULL, NULL,
NULL, NULL, &matches);
if (subp)
{
if (nth >= *pmatches && nth < *pmatches+matches)
{
/* This packet has the nth instance */
*psig = sig;
*pdata = pgpSigFindSubpacket (p, subpacktype, nth - *pmatches,
plen, pcritical, phashed, pcreation, NULL );
}
*pmatches += matches;
}
return kPGPError_NoErr;
}
/*
* Return key self-sig subpacket information. Searches all sigs below
* the key for a self sig, finds most recent one with desired info.
* nth is 0 to find first matching packet, 1 for second, etc. The
* semantics have changed (yet again) from earlier versions in order
* to more easily supercede old signatures.
*
* The rule now is that non-revocable signatures always have precedence.
* Any subpacket in such a signature cannot be revoked, and will be returned
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -