📄 pgpkeyobj.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
low level functions for keydb objects
$Id: pgpKeyObj.c,v 1.99 2002/10/29 04:50:59 ajivsov Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"
#include <string.h>
#include <ctype.h> /* For tolower() */
#include "pgpDebug.h"
#include "pgpKeyPriv.h"
#include "pgpErrors.h"
#include "pgpPubKey.h"
#include "pgpPktByte.h"
#include "pgpSigSpec.h"
#include "pgpMem.h"
#include "pgpContext.h"
#include "pgpEnv.h"
#include "pgpP11Key.h"
#include "pgpTrustPriv.h"
#include "pgpX509Priv.h"
#include "pgpHashPriv.h"
#include "pgpRegExp.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpPassCach.h"
#ifndef NULL
#define NULL 0
#endif
/* Return the type of a PGPKeyDBObj */
PGPUInt32
pgpObjectType(PGPKeyDBObj const *obj)
{
pgpAssert (obj);
if (obj->objflags & kPGPKeyDBObjType_Key )
return RINGTYPE_KEY;
if (obj->objflags & kPGPKeyDBObjType_SubKey )
return RINGTYPE_SUBKEY;
if (obj->objflags & kPGPKeyDBObjType_UserID )
return RINGTYPE_USERID;
if (obj->objflags & kPGPKeyDBObjType_Signature )
return RINGTYPE_SIG;
if (obj->objflags & kPGPKeyDBObjType_CRL )
return RINGTYPE_CRL;
return RINGTYPE_UNK;
}
static ObjDataHeader **
sObjectDataPointer( PGPKeyDBObj const *obj )
{
PGPKeyInfo *kinfo;
PGPUserIDInfo *uinfo;
PGPSigInfo *sinfo;
PGPCRLInfo *cinfo;
PGPUnkInfo *xinfo;
ObjDataHeader **dptr = NULL;
switch( pgpObjectType( obj ) )
{
case RINGTYPE_KEY:
case RINGTYPE_SUBKEY:
kinfo = pgpKeyToKeyInfo( obj );
dptr = &kinfo->data;
break;
case RINGTYPE_USERID:
uinfo = pgpUserIDToUserIDInfo( obj );
dptr = &uinfo->data;
break;
case RINGTYPE_SIG:
sinfo = pgpSigToSigInfo( obj );
dptr = &sinfo->data;
break;
case RINGTYPE_CRL:
cinfo = pgpCRLToCRLInfo( obj );
dptr = &cinfo->data;
break;
case RINGTYPE_UNK:
xinfo = pgpUnkToUnkInfo( obj );
dptr = &xinfo->data;
break;
default:
pgpAssert( 0 );
break;
}
return dptr;
}
/* Return pointer to obj's info id field */
static PGPUInt32 *
sObjectIDPointer( PGPKeyDBObj const *obj )
{
PGPKeyInfo *kinfo;
PGPUserIDInfo *uinfo;
PGPSigInfo *sinfo;
PGPCRLInfo *cinfo;
PGPUnkInfo *xinfo;
PGPUInt32 *idptr = NULL;
switch( pgpObjectType( obj ) )
{
case RINGTYPE_KEY:
case RINGTYPE_SUBKEY:
kinfo = pgpKeyToKeyInfo( obj );
idptr = &kinfo->id;
break;
case RINGTYPE_USERID:
uinfo = pgpUserIDToUserIDInfo( obj );
idptr = &uinfo->id;
break;
case RINGTYPE_SIG:
sinfo = pgpSigToSigInfo( obj );
idptr = &sinfo->id;
break;
case RINGTYPE_CRL:
cinfo = pgpCRLToCRLInfo( obj );
idptr = &cinfo->id;
break;
case RINGTYPE_UNK:
xinfo = pgpUnkToUnkInfo( obj );
idptr = &xinfo->id;
break;
default:
pgpAssert( 0 );
break;
}
return idptr;
}
/* Return ID corresponding to front end object */
PGPUInt32
pgpKeyDBObjID( PGPKeyDBObj const *obj )
{
if( obj->objflags & kPGPKeyDBObjFlags_ID )
return obj->idinfo.id;
else
return *sObjectIDPointer(obj);
}
/* True if key belongs to a front-end keydb */
PGPBoolean
pgpFrontEndKey( PGPKeyDBObj const *obj )
{
PGPKeyDB *db = PGPPeekKeyDBObjKeyDB( (PGPKeyDBObj *)obj );
return pgpFrontEndKeyDB( db );
}
static ObjDataHeader *
sObjectDataHeader( PGPKeyDBObj const *obj )
{
return *sObjectDataPointer( obj );
}
/* Refcount the data buffers */
void
pgpObjectHold(PGPKeyDBObj *obj)
{
ObjDataHeader *objdata;
objdata = sObjectDataHeader( obj );
if( IsntNull( objdata ) )
++objdata->refcount;
}
void
pgpObjectRelease(PGPKeyDBObj *obj)
{
ObjDataHeader *objdata;
objdata = sObjectDataHeader( obj );
if( IsntNull( objdata ) && objdata->refcount > 0)
--objdata->refcount;
}
PGPByte const *
pgpFetchObject( PGPKeyDBObj const *obj, PGPSize *len )
{
ObjDataHeader *objdata;
objdata = sObjectDataHeader( obj );
if( IsNull( objdata ) )
{
PGPByte *buf;
PGPSize buflen;
PGPKeyDB *kdb = PGPPeekKeyDBObjKeyDB( (PGPKeyDBObj *)obj );
PGPContextRef context = PGPPeekKeyDBContext( kdb );
pgpFetchObjectData_back( context, pgpKeyDBObjID( obj ),
&buf, &buflen );
objdata = pgpNewObjData( kdb, buf, buflen );
PGPFreeData( buf );
*sObjectDataPointer( obj ) = objdata;
}
*len = objdata->len;
return objdata->data;
}
/* Return a new data header suitable for assigning to ->data */
void *
pgpNewObjData( PGPKeyDB *kdb, PGPByte const *buf, PGPSize len )
{
ObjDataHeader *data;
PGPByte *databuf;
MemPool cutback;
cutback = kdb->objPool;
data = memPoolAlloc( &kdb->objPool, sizeof(ObjDataHeader), 4 );
if( data == NULL )
goto outofmem;
databuf = memPoolAlloc( &kdb->objPool, len, 1 );
if( databuf == NULL )
goto outofmem;
pgpCopyMemory( buf, databuf, len );
data->data = databuf;
data->len = len;
data->refcount = 1;
return data;
outofmem:
memPoolCutBack( &kdb->objPool, &cutback );
pgpKeyDBSetError( kdb, kPGPError_OutOfMemory );
return NULL;
}
/* Change the data buffer associated with an object */
PGPError
pgpUpdateObjData( PGPKeyDBObj *obj, PGPByte *buf, PGPSize len )
{
ObjDataHeader *objdata;
PGPKeyDB *kdb;
PGPByte *databuf;
objdata = sObjectDataHeader( obj );
if( IsNull( objdata ) )
{
return pgpKeyDBError( PGPPeekKeyDBObjKeyDB( obj ) );
}
kdb = PGPPeekKeyDBObjKeyDB( obj );
databuf = memPoolAlloc( &kdb->objPool, len, 1 );
if( databuf == NULL )
return kPGPError_OutOfMemory;
pgpCopyMemory( buf, databuf, len );
objdata->data = databuf;
objdata->len = len;
return kPGPError_NoErr;
}
/*** Access functions for information about objects ***/
PGPUInt32
pgpKeyBits(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
return kinfo->keybits;
}
PGPUInt32
pgpKeyCreation(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
return kinfo->creationtime;
}
PGPUInt32
pgpKeyExpiration(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
if (kinfo->creationtime == 0 || kinfo->validityperiod == 0)
return 0; /* valid indefinitely */
else
return kinfo->creationtime + (kinfo->validityperiod * 3600 * 24);
}
/*
* If called for a subkey, force to just encryption if subkeyCanVerify is FALSE.
* If called for a key with a subkey, return the "or" of both.
* Else just do the key itself.
* Internal form of pgpKeyUse - if unExpired is true, check that the
* subkeys are unexpired before saying it has encryption usage.
* pgpKeyUse and pgpKeyUnexpiredUse are macros that call this now.
*/
PGPUInt32
pgpKeyUseInternal(PGPKeyDBObj *key, PGPBoolean unExpired, PGPBoolean revokedOK, PGPBoolean subkeyCanVerify)
{
PGPKeyInfo *kinfo;
int use;
int first = TRUE;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
use = pgpKeyAlgUse(pgpPkalgByNumber(kinfo->pkalg));
if (OBJISSUBKEY(key) && !subkeyCanVerify)
use &= PGP_PKUSE_ENCRYPT; /* force key capabilities to encryption only */
for (key=key->down; key; key=key->next) {
if( !pgpKeyDBObjIsReal(key) )
continue;
if (OBJISSUBKEY(key) && pgpSubkeyValid(key, unExpired, revokedOK))
{
kinfo = pgpKeyToKeyInfo( key );
if( first )
use &= PGP_PKUSE_SIGN;
first = FALSE;
use |= pgpKeyAlgUse(pgpPkalgByNumber(kinfo->pkalg));
}
}
return use;
}
PGPByte
pgpKeyTrust(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
return pgpMax(kinfo->trust & kPGPKeyTrust_Mask,
kinfo->signedTrust & kPGPKeyTrust_Mask);
}
void
pgpKeySetTrust(PGPKeyDBObj *key, PGPByte trust)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
pgpAssert(trust==kPGPKeyTrust_Unknown || trust==kPGPKeyTrust_Never ||
trust==kPGPKeyTrust_Marginal || trust==kPGPKeyTrust_Complete);
pgpAssert (!(kinfo->trust & PGP_KEYTRUSTF_BUCKSTOP));
if (kinfo->trust & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED))
return;
if ((kinfo->trust & kPGPKeyTrust_Mask) != trust) {
kinfo->trust = (kinfo->trust & ~kPGPKeyTrust_Mask) + trust;
}
}
/*
* Used to set a key as an "axiomatic" key, that is, one for which
* we hold the private key. This also involves setting each name on that
* key as having complete validity.
*/
void
pgpKeySetAxiomatic(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
PGPUserIDInfo *uinfo;
PGPKeyDBObj *name = NULL;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
if( !pgpKeyIsSec (key) ||
(kinfo->trust & PGP_KEYTRUSTF_REVOKED) )
return; /* already axiomatic or can't set */
kinfo->trust &= ~kPGPKeyTrust_Mask;
kinfo->trust |= (PGP_KEYTRUSTF_BUCKSTOP | kPGPKeyTrust_Ultimate);
/* Make sure all names have axiomatic confidence */
for (name=key->down; name; name=name->next) {
if( !pgpKeyDBObjIsReal(name) )
continue;
if (OBJISUSERID(name)) {
uinfo = pgpUserIDToUserIDInfo( name );
uinfo->confidence = PGP_NEWTRUST_INFINITE;
}
}
}
/* Reset an axiomatic key. Trust is set to undefined. */
void
pgpKeyResetAxiomatic (PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
PGPUserIDInfo *uinfo;
PGPKeyDBObj *name = NULL;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
kinfo->trust &= ~PGP_KEYTRUSTF_BUCKSTOP;
kinfo->trust = (kinfo->trust & ~kPGPKeyTrust_Mask) +
kPGPKeyTrust_Undefined;
/* Make sure all names have undefined confidence */
for (name=key->down; name; name=name->next) {
if( !pgpKeyDBObjIsReal(name) )
continue;
if (OBJISUSERID(name)) {
uinfo = pgpUserIDToUserIDInfo( name );
uinfo->confidence = PGP_NEWTRUST_UNDEFINED;
}
}
}
PGPBoolean
pgpKeyAxiomatic(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
return (kinfo->trust & PGP_KEYTRUSTF_BUCKSTOP) != 0;
}
/* Return TRUE if the key is a subkey */
PGPBoolean
pgpKeyIsSubkey (PGPKeyDBObj const *key)
{
return OBJISSUBKEY(key) != 0;
}
PGPBoolean
pgpKeyDisabled(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
return (kinfo->trust & PGP_KEYTRUSTF_DISABLED) != 0;
}
void
pgpKeyDisable(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
if (!(kinfo->trust & PGP_KEYTRUSTF_DISABLED)) {
kinfo->trust |= PGP_KEYTRUSTF_DISABLED;
}
}
void
pgpKeyEnable(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
if (kinfo->trust & PGP_KEYTRUSTF_DISABLED) {
kinfo->trust &= ~PGP_KEYTRUSTF_DISABLED;
}
}
PGPBoolean
pgpKeyRevoked(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
return (kinfo->trust & PGP_KEYTRUSTF_REVOKED) != 0;
}
/* Flag for keys whose secret part is on a token. Only for back end.
'tok' is the token object to which 'key' belongs, or NULL if this is unknown
*/
void
pgpKeyOnToken(PGPKeyDBObj *key, PGPToken *tok)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
pgpAssert(!pgpFrontEndKey(key));
kinfo = pgpKeyToKeyInfo( key );
KEYSETTOKEN( kinfo );
pgpKeySetAxiomatic( key );
pgpSetKeyTokenNum( key, tok );
}
void
pgpKeyOffToken(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
pgpAssert(!pgpFrontEndKey(key));
kinfo = pgpKeyToKeyInfo( key );
KEYCLEARTOKEN( kinfo );
/* Mark as no longer axiomatic unless we have a secret part */
if( !KEYISSEC( kinfo ) )
pgpKeyResetAxiomatic( key );
kinfo->tokenNum1 = 0;
}
PGPBoolean
pgpKeyIsOnToken(PGPKeyDBObj *key)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
return KEYISTOKEN( kinfo );
}
/* Flag for keys whose secret part has been mathematically checked */
void
pgpSecSetValidated(PGPKeyDBObj *sec)
{
PGPKeyInfo *kinfo;
pgpAssert(OBJISKEY(sec));
pgpAssert(pgpKeyIsSec(sec));
kinfo = pgpKeyToKeyInfo( sec );
KEYSETVALIDATED( kinfo );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -