📄 pgpkeyadd.c
字号:
PGPBoolean revocable;
PGPByte trustLevel;
PGPByte trustValue;
PGPBoolean hasRegExp;
PGPBoolean hasDPoint = FALSE;
PGPBoolean isX509;
PGPBoolean primaryUID;
PGPKeyID keyID;
PGPError err;
(void)pkttype;
pgpAssert( IsntNull( parent ) );
/* Look for matching sig structure */
sig = pgpFindMatchingChild( parent, buf, len );
if( IsntNull( sig ) ) {
/* Got a match */
if( sig->objflags & kPGPKeyDBObjFlags_Deleted )
{
/* Bring back to life at end of list */
sig->objflags &= ~kPGPKeyDBObjFlags_Deleted;
pgpUnlinkChild( sig, parent );
pgpLinkChild( sig, parent );
/* See if sig is on sigsby list, put it there if not */
sinfo = pgpSigToSigInfo( sig );
key = sinfo->by;
kinfo = pgpKeyToKeyInfo( key );
for( tsig = kinfo->sigsby; IsntNull(tsig); tsig=sinfo->nextby )
{
if ( tsig == sig )
return sig; /* Done */
sinfo = pgpSigToSigInfo( tsig );
}
/* Not found, put it on list */
sinfo = pgpSigToSigInfo( sig );
sinfo->nextby = kinfo->sigsby;
kinfo->sigsby = sig;
}
return sig;
} else {
err = pgpSigParse(buf, len, FALSE, &pkalg, keyidbytes, &tstamp,
&sigvalidity, &type, &hashalg, &extralen, &version,
&exportable, &revocable, &trustLevel, &trustValue,
&hasRegExp, &isX509, &primaryUID);
if( IsPGPError( err ) )
return NULL;
/* X.509 sigs use hash of issuer name as keyid; also get hash of
* subject name for later. */
if( isX509 )
{
sX509KeyIDBytes( kdb, buf, len, &hasDPoint,
keyidbytes, x509subjectkeyidbytes);
}
if( isX509 ) /* Use high values for pkalg on X509's */
pkalg = 0x80;
vpkalg = pkalg; /* Viacrypt correction */
if ((vpkalg | 1) == 3)
vpkalg = 1;
pgpNewKeyIDFromRawData(keyidbytes, vpkalg, sizeof(keyidbytes), &keyID);
(void)pgpGetKeyByKeyID( kdb, &keyID, TRUE, TRUE, &key);
if( IsNull( key ) ) {
/* Must create dummy key */
key = sNewKey( kdb );
if( IsNull( key ) )
{
err = kPGPError_OutOfMemory;
goto error;
}
kinfo = pgpKeyToKeyInfo( key );
pgpCopyMemory( keyidbytes, kinfo->keyID, sizeof(keyidbytes));
kinfo->pkalg = pkalg;
key->objflags |= kPGPKeyDBObjFlags_Dummy;
if( isX509 )
key->objflags |= kPGPKeyDBObjFlags_X509;
pgpLinkKey( key, kdb );
pgpLinkKeyToTree( key, kdb );
} else if( pgpKeyDBObjIsDeleted( key ) ) {
key->objflags &= ~kPGPKeyDBObjFlags_Deleted;
key->objflags |= kPGPKeyDBObjFlags_Dummy;
}
sig = sNewSig( kdb );
if ( sig == NULL ) {
err = kPGPError_OutOfMemory;
goto error;
}
pgpLinkChild( sig, parent );
sinfo = pgpSigToSigInfo( sig );
sinfo->by = key;
kinfo = pgpKeyToKeyInfo( key );
sinfo->nextby = kinfo->sigsby;
kinfo->sigsby = sig;
if (extralen != 5)
sinfo->flags |= SIGF_NONFIVE;
sinfo->tstamp = tstamp;
sinfo->sigvalidity = sigvalidity;
sinfo->type = type;
sinfo->version = version;
sinfo->hashalg = hashalg;
sinfo->trust = 0;
sinfo->trustLevel = trustLevel;
sinfo->trustValue = trustValue;
if (exportable)
SIGSETEXPORTABLE(sinfo);
else
SIGSETNONEXPORTABLE(sinfo);
if (revocable)
SIGSETREVOCABLE(sinfo);
else
SIGSETNONREVOCABLE(sinfo);
if (hasRegExp)
SIGSETUSESREGEXP(sinfo);
else
SIGCLEARUSESREGEXP(sinfo);
if (isX509)
SIGSETX509(sinfo);
else
SIGCLEARX509(sinfo);
if (hasDPoint)
SIGSETDISTPOINT(sinfo);
else
SIGCLEARDISTPOINT(sinfo);
if (primaryUID)
SIGSETPRIMARYUID(sinfo);
else
SIGCLEARPRIMARYUID(sinfo);
}
if( isX509 )
sFixupX509ParentKey( kdb, sig, x509subjectkeyidbytes );
sinfo = pgpSigToSigInfo( sig );
if( IS_OLD_PKTBYTE(buf[0])
&& PKTBYTE_LLEN(buf[0]) == 0
&& pkalg == kPGPPublicKeyAlgorithm_RSA )
{
/* PGP 2.6.2 requires RSA sigs to have two byte lengths */
PGPByte pktbyte;
PGPByte *pktbuf;
PGPContextRef context;
pktbyte = PKTBYTE_BUILD( PKTBYTE_SIG, 1 );
/* Len will be 1 bigger */
len += 1;
/* Allocate space */
context = PGPPeekKeyDBContext( kdb );
pktbuf = pgpContextMemAlloc( context, len, 0 );
if( IsNull(pktbuf) )
return NULL;
/* Fill buffer. len-3 is length of payload. */
pgpPktHeaderPut( pktbuf, pktbyte, len-3 );
pgpCopyMemory( buf+2, pktbuf+3, len-3 );
/* Store data buffer */
sinfo->data = pgpNewObjData( kdb, pktbuf, len );
PGPFreeData( pktbuf );
} else
sinfo->data = pgpNewObjData( kdb, buf, len );
return sig;
error:
*error = err;
return NULL;
}
PGPKeyDBObj *
pgpAddCRL( PGPInt32 pkttype, PGPByte const *buf, PGPSize len,
PGPKeyDB *kdb, PGPKeyDBObj *parent, PGPError *outerr )
{
PGPKeyDBObj * crl;
PGPCRLInfo * cinfo;
PGPContextRef context;
PGPUInt32 tstamp, tstampnext;
PGPByte version;
PGPByte type;
PGPByte const * dpoint;
PGPSize dpointlen;
PGPError err;
(void)pkttype;
pgpAssert( IsntNull( parent ) );
if( !OBJISTOPKEY( parent ) )
return NULL;
/* Find any matching CRL structure */
crl = pgpFindMatchingChild( parent, buf, len );
if( IsntNull( crl ) ) {
/* Got a match */
crl->objflags &= ~kPGPKeyDBObjFlags_Deleted;
return crl;
} else {
crl = sNewCRL( kdb );
if ( crl == NULL ) {
err = kPGPError_OutOfMemory;
goto error;
}
pgpLinkChild( crl, parent );
}
cinfo = pgpCRLToCRLInfo( crl );
context = PGPPeekKeyDBContext( kdb );
(void)pgpCRLParse( context, buf, len, &version, &type, &tstamp,
&tstampnext, &dpoint, &dpointlen );
cinfo->version = version;
cinfo->tstamp = tstamp;
cinfo->tstampnext = tstampnext;
if (type == PGPCRLTYPE_X509 || type == PGPCRLTYPE_X509DPOINT)
CRLSETX509(cinfo);
else
CRLCLEARX509(cinfo);
if (type == PGPCRLTYPE_X509DPOINT) {
CRLSETDPOINT(cinfo);
} else {
CRLCLEARDPOINT(cinfo);
}
cinfo->data = pgpNewObjData( kdb, buf, len );
return crl;
error:
*outerr = err;
return NULL;
}
PGPKeyDBObj *
pgpAddUnknown( PGPInt32 pkttype, PGPByte const *buf, PGPSize len,
PGPKeyDB *kdb, PGPKeyDBObj *parent, PGPError *outerr )
{
PGPKeyDBObj * unk;
PGPUnkInfo * ninfo;
PGPError err;
(void)pkttype;
pgpAssert( IsntNull( parent ) );
if( !OBJISTOPKEY( parent ) )
return NULL;
/* Find any matching Unknown structure */
unk = pgpFindMatchingChild( parent, buf, len );
if( IsntNull( unk ) ) {
/* Got a match */
unk->objflags &= ~kPGPKeyDBObjFlags_Deleted;
return unk;
} else {
unk = sNewUnknown( kdb );
if ( unk == NULL ) {
err = kPGPError_OutOfMemory;
goto error;
}
pgpLinkChild( unk, parent );
}
ninfo = pgpUnkToUnkInfo( unk );
ninfo->data = pgpNewObjData( kdb, buf, len );
return unk;
error:
*outerr = err;
return NULL;
}
PGPKeyDBObj *
pgpAddObject( PGPByte const *buf, PGPSize len,
PGPKeyDB *kdb, PGPKeyDBObj *parent, PGPBoolean trusted, PGPError *err )
{
PGPByte pkttype;
if( len == 0 )
return NULL;
pkttype = PKTBYTE_TYPE(*buf);
switch (pkttype) {
case PKTBYTE_PUBKEY:
case PKTBYTE_PUBSUBKEY:
case PKTBYTE_SECKEY:
case PKTBYTE_SECSUBKEY:
return pgpAddKey( pkttype, buf, len, kdb, parent, trusted, err );
case PKTBYTE_ATTRIBUTE:
case PKTBYTE_USERID:
return pgpAddUserID( pkttype, buf, len, kdb, parent, err );
case PKTBYTE_SIG:
return pgpAddSig( pkttype, buf, len, kdb, parent, err );
case PKTBYTE_CRL:
return pgpAddCRL( pkttype, buf, len, kdb, parent, err );
default:
return pgpAddUnknown( pkttype, buf, len, kdb, parent, err );
}
}
static PGPError
pgpTrustPacket( PGPByte const *buf, PGPSize len, PGPKeyDB *kdb,
PGPKeyDBObj *lastobj, PGPEnv *env )
{
PGPKeyInfo *kinfo;
PGPUserIDInfo *uinfo;
PGPSigInfo *sinfo;
PGPCRLInfo *cinfo;
PGPUnkInfo *ninfo;
PGPByte trust;
PGPByte validity;
PGPByte confidence;
PGPContextRef context;
PGPSize hlen;
PGPEnv *pgpEnv;
if( len == 0 )
return kPGPError_NoErr;
context = PGPPeekKeyDBContext( kdb );
pgpEnv = pgpContextGetEnvironment( context );
hlen = pgpPktBufferHeaderLen( buf );
buf += hlen;
len -= hlen;
if( len == 0 )
return kPGPError_NoErr;
trust = buf[0];
if( OBJISUSERID( lastobj ) ) {
/*
* Name trust packets can be up to 3 bytes
* long:
* Byte 1: old-style trust packet
* Byte 2: validity of name
* Byte 3: confidence in name as introducer
*/
/* Default trust and validity bytes */
switch (trust & kPGPUserIDTrust_Mask) {
case kPGPUserIDTrust_Complete:
validity = pgpenvCompleteTrust( env );
break;
case kPGPUserIDTrust_Marginal:
validity = pgpenvMarginalTrust( env );
break;
default:
validity = 0;
break;
}
pgpAssert(OBJISKEY(lastobj->up));
kinfo = pgpKeyToKeyInfo( lastobj->up );
confidence = pgpTrustOldToExtern(pgpEnv, kinfo->trust);
if (len > 1) {
/* Fetch validity */
validity = buf[1];
if (len > 2) {
/* Fetch confidence */
confidence = buf[2];
}
}
uinfo = pgpUserIDToUserIDInfo( lastobj );
uinfo->oldvalidity = trust;
uinfo->validity = validity;
uinfo->confidence = confidence;
uinfo->valid = pgpTrustToIntern (validity);
} else { /* Not a name */
/* Set the appropriate flags */
switch (pgpObjectType(lastobj)) {
default:
pgpAssert(0);
case RINGTYPE_KEY:
case RINGTYPE_SUBKEY:
kinfo = pgpKeyToKeyInfo( lastobj );
kinfo->trust = trust;
break;
case RINGTYPE_SIG:
sinfo = pgpSigToSigInfo( lastobj );
sinfo->trust = trust;
break;
case RINGTYPE_CRL:
cinfo = pgpCRLToCRLInfo( lastobj );
cinfo->trust = trust;
break;
case RINGTYPE_UNK:
ninfo = pgpUnkToUnkInfo( lastobj );
ninfo->trust = trust;
break;
}
}
/* Handle key validity info from trusted self-signatures */
if( OBJISSIG(lastobj) ) {
PGPKeyDBObj *keyobj;
PGPKeyDBObj *topkeyobj;
PGPByte const *sdata;
PGPSize sdatalen;
PGPByte const *pk;
sinfo = pgpSigToSigInfo( lastobj );
if( (sinfo->trust & PGP_SIGTRUSTF_CHECKED) &&
!(sinfo->trust & PGP_SIGTRUSTF_REVOKEDBYCRL) ) {
keyobj = lastobj->up;
while( !OBJISKEY( keyobj ) )
keyobj = keyobj->up;
topkeyobj = keyobj;
while( !OBJISTOPKEY( topkeyobj ) )
topkeyobj = topkeyobj->up;
if( sinfo->by == topkeyobj ) {
sdata = pgpFetchObject( lastobj, &sdatalen );
pk = pgpSigFindSubpacket ( sdata,
SIGSUB_KEY_EXPIRATION,
0, NULL, NULL, NULL, NULL, NULL);
if( IsntNull(pk) ) {
PGPUInt32 keyexp;
keyexp = (PGPUInt32)((unsigned)pk[0]<<8|pk[1]) << 16 |
((unsigned)pk[2]<<8|pk[3]);
kinfo = pgpKeyToKeyInfo( keyobj );
kinfo->validityperiod = keyexp / (24 * 3600);
}
}
}
}
return kPGPError_NoErr;
}
/*
* When copying an obj from one db to another, copy its trust info. We will
* keep the max of the old and new trust.
*/
void
pgpCopyObjectTrust( PGPKeyDBObj *oldobj, PGPKeyDBObj *newobj )
{
PGPKeyInfo *okinfo, *nkinfo;
PGPUserIDInfo *ouinfo, *nuinfo;
PGPSigInfo *osinfo, *nsinfo;
PGPCRLInfo *ocinfo, *ncinfo;
PGPUnkInfo *oninfo, *nninfo;
if( OBJISUSERID( oldobj ) ) {
pgpAssert( OBJISUSERID( newobj ) );
ouinfo = pgpUserIDToUserIDInfo( oldobj );
nuinfo = pgpUserIDToUserIDInfo( newobj );
nuinfo->oldvalidity =
((ouinfo->oldvalidity|nuinfo->oldvalidity) &
(PGP_USERIDTRUSTF_WARNONLY|PGP_USERIDTRUSTF_PRIMARY)) |
pgpMax(ouinfo->oldvalidity&3, nuinfo->oldvalidity&3);
nuinfo->validity = (nuinfo->validity == PGP_NEWTRUST_UNDEFINED)
? ouinfo->validity
: ( (ouinfo->validity == PGP_NEWTRUST_UNDEFINED)
? nuinfo->validity
: pgpMax(ouinfo->validity, nuinfo->validity) );
nuinfo->confidence = (nuinfo->confidence == PGP_NEWTRUST_UNDEFINED)
? ouinfo->confidence
: ( (ouinfo->confidence == PGP_NEWTRUST_UNDEFINED)
? nuinfo->confidence
: pgpMax(ouinfo->confidence, nuinfo->confidence) );
nuinfo->valid = pgpMax(ouinfo->valid, nuinfo->valid);
} else { /* Not a name */
/* Set the appropriate flags */
switch (pgpObjectType(oldobj)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -