📄 pgpkeyman.c
字号:
if (error) {
ringSetDestroy (addset);
return error;
}
error = pgpAddObjects (keys, addset);
ringSetDestroy (addset);
return error;
}
/* Given a cert, return the certifying key object. The signing key does not
have to be in the same set as <cert>, and may be in the <allkeys> set. */
PGPError
pgpGetCertifier (PGPCert *cert, PGPKeySet *allkeys, PGPKey **certkey)
{
char keyID[33];
size_t keyIDLength = sizeof(keyID);
pgpa(pgpaPGPCertValid(cert));
CHECKREMOVED(cert);
pgpGetCertString(cert, kPGPCertPropKeyID, keyID, &keyIDLength);
*certkey = pgpGetKeyByKeyID(allkeys, (unsigned char *) keyID, keyIDLength);
return PGPERR_OK;
}
/* Revoke a certification. If allkeys == NULL, the certifying key
must be in the same keyDB as the certificate. */
PGPError
pgpRevokeCert (PGPCert *cert, PGPKeySet *allkeys, char *passphrase)
{
PGPKeyDB *keys;
PGPKey *certkey;
struct RingSet *allset, *addset, *signerset;
union RingObject *sigobj, *nameobj;
Boolean revoked;
PGPError error = PGPERR_OK;
pgpa(pgpaPGPCertValid(cert));
CHECKREMOVED(cert);
keys = cert->up.userID->key->keyDB;
sigobj = cert->cert;
if (!(*keys->isMutable) (keys))
return PGPERR_KEYDB_KEYDBREADONLY;
error = pgpGetCertBoolean (cert, kPGPCertPropIsRevoked, &revoked);
if (error)
return error;
if (revoked)
return PGPERR_OK; /* already revoked */
/* Get certifying key and its RingSet */
error = pgpGetCertifier (cert, allkeys, &certkey);
if (error)
return error;
if (!certkey)
return PGPERR_NO_SECKEY;
if (pgpKeyIsDead (certkey))
return PGPERR_KEYDB_CERTIFYINGKEY_DEAD;
signerset = pgpKeyDBRingSet (certkey->keyDB);
/* Get signature RingSet and its name object */
allset = pgpKeyDBRingSet (cert->up.userID->key->keyDB);
nameobj = cert->up.userID->userID;
error = pgpCopyKey (allset, nameobj, &addset);
if (error)
return error;
error = pgpCertifyObject (nameobj, addset, certkey->key, signerset,
PGP_SIGTYPE_KEY_UID_REVOKE, passphrase, FALSE);
if (error) {
ringSetDestroy (addset);
return error;
}
error = pgpAddObjects (keys, addset);
ringSetDestroy (addset);
return error;
}
/* Remove a certification. If the certification was revoked, the
revocation signature remains. This ensures that the same
signature on someone else's keyring is properly revoked
if this key is exported. A future certification will have
a later creation timestamp than the revocation and will therefore
not be affected. */
PGPError
pgpRemoveCert (PGPCert *cert)
{
PGPKeyDB *keys;
union RingObject *sigobj;
pgpa(pgpaPGPCertValid(cert));
CHECKREMOVED(cert);
keys = cert->up.userID->key->keyDB;
sigobj = cert->cert;
if (!(*keys->isMutable) (keys))
return PGPERR_KEYDB_KEYDBREADONLY;
if (!(*keys->objIsMutable) (keys, sigobj))
return PGPERR_KEYDB_OBJECTREADONLY;
return pgpRemoveObject (keys, sigobj);
}
/* Given a key, return the nth (0 based) message recovery key, if one exists.
Also return the class of the MRK, and the number of MRK's for the
base key. Any of the return pointers may be NULL. */
PGPError
pgpGetMessageRecoveryKey (PGPKey *basekey, PGPKeySet *allkeys, unsigned nth,
PGPKey **mrkey, byte *mrclass, unsigned *numbermrks)
{
struct RingSet *ringset; /* Aurora ringset to look in */
union RingObject *keyobj; /* Aurora base key */
union RingObject *rkey; /* Aurora message recovery key */
unsigned nmrks; /* Number MRK's available */
byte tclass; /* Class code from MRK */
PGPError error; /* Error return from Aurora */
byte keyID[8]; /* keyid of MRK */
pgpa(pgpaPGPKeyValid(basekey));
ringset = pgpKeyDBRingSet (basekey->keyDB);
keyobj = basekey->key;
rkey = ringKeyRecoveryKey (keyobj, ringset, nth, &tclass, &nmrks, &error);
if (!rkey) {
/* No key found, or error */
if (mrkey)
*mrkey = NULL;
if (mrclass)
*mrclass = 0;
if (numbermrks)
*numbermrks = 0;
return error;
}
/* Success */
if (mrkey) {
/* Can only look up master keys at this level */
if (ringKeyIsSubkey(ringset, rkey))
rkey = ringKeyMasterkey (ringset, rkey);
ringKeyID8 (ringset, rkey, NULL, keyID);
*mrkey = pgpGetKeyByKeyID (allkeys, keyID, sizeof(keyID));
}
if (mrclass)
*mrclass = tclass;
if (numbermrks)
*numbermrks = nmrks;
return PGPERR_OK;
}
/* Trust-related functions */
PGPError
pgpSetUserIDConf (PGPUserID *userid, unsigned long confidence)
{
PGPKeyDB *keys;
struct RingSet *allset = NULL, *addset = NULL;
union RingObject *nameobj;
PGPError error = PGPERR_OK;
pgpa(pgpaPGPUserIDValid(userid));
pgpAssert (pgpTrustModel (pgpRingPool) > PGPTRUST0);
CHECKREMOVED(userid);
if (pgpKeyIsDead (userid->key))
return PGPERR_BADPARAM;
keys = userid->key->keyDB;
allset = pgpKeyDBRingSet (keys);
nameobj = userid->userID;
if (ringKeyIsSec (allset, userid->key->key))
return PGPERR_BADPARAM;
if (!(*keys->isMutable) (keys))
return PGPERR_KEYDB_KEYDBREADONLY;
error = pgpCopyKey (allset, nameobj, &addset);
if (error)
return error;
if (!(*keys->objIsMutable) (keys, nameobj)) {
error = pgpAddObjects (keys, addset);
if (error)
goto cleanup;
}
ringNameSetConfidence (allset, nameobj, (unsigned short) confidence);
pgpKeyDBChanged (keys, addset);
cleanup:
if (addset)
ringSetDestroy (addset);
return error;
}
/* Set the trust on a key. Cannot be used to set undefined or
axiomatic trust. The key must be valid to assign trust. */
PGPError
pgpSetKeyTrust (PGPKey *key, unsigned char trust)
{
PGPKeyDB *keys;
struct RingSet *allset, *addset = NULL;
union RingObject *keyobj;
PGPError error = PGPERR_OK;
#if ONLY_TRUST_VALID_KEYS
long validity;
#endif
pgpa(pgpaPGPKeyValid(key));
pgpAssert (pgpTrustModel (pgpRingPool) == PGPTRUST0);
keys = key->keyDB;
if (!(*keys->isMutable) (keys))
return PGPERR_KEYDB_KEYDBREADONLY;
allset = pgpKeyDBRingSet (keys);
keyobj = key->key;
if (trust <= PGP_KEYTRUST_UNDEFINED || trust > PGP_KEYTRUST_COMPLETE ||
pgpKeyIsDead (key) || ringKeyAxiomatic (allset, keyobj))
return PGPERR_BADPARAM;
#if ONLY_TRUST_VALID_KEYS
/* Should not set trust on key that is not completely valid
(who is it we are trusting?) */
pgpGetKeyNumber (key, kPGPKeyPropValidity, &validity);
if (validity != PGP_VALIDITY_COMPLETE)
return PGPERR_BADPARAM;
#endif
error = pgpCopyKey (allset, keyobj, &addset);
if (error)
return error;
if (!(*keys->objIsMutable) (keys, keyobj)) {
error = pgpAddObjects (keys, addset);
if (error)
goto cleanup;
}
ringKeySetTrust (allset, keyobj, trust);
pgpKeyDBChanged (keys, addset);
cleanup:
if (addset)
ringSetDestroy (addset);
return error;
}
/* Set a secret key as the axiomatic key. If checkPassphrase == TRUE,
the user must prove knowledge of the passphrase in order to do
this. */
PGPError
pgpSetKeyAxiomatic (PGPKey *key, Boolean checkPassphrase, char *passphrase)
{
Boolean secret, axiomatic;
struct RingSet *allset, *addset = NULL;
union RingObject *keyobj;
struct PgpSecKey *seckey;
PGPKeyDB *keys;
PGPError error = PGPERR_OK;
pgpa(pgpaPGPKeyValid(key));
pgpGetKeyBoolean (key, kPGPKeyPropIsSecret, &secret);
if (!secret)
return PGPERR_BADPARAM;
pgpGetKeyBoolean (key, kPGPKeyPropIsAxiomatic, &axiomatic);
if (axiomatic)
return PGPERR_OK;
keys = key->keyDB;
allset = pgpKeyDBRingSet (keys);
keyobj = key->key;
if (checkPassphrase) {
/* Get the secret key and attempt to unlock it */
seckey = ringSecSecKey (allset, keyobj, PGP_PKUSE_SIGN);
if (!seckey)
return ringSetError(allset)->error;
if (pgpSecKeyIslocked (seckey)) {
if (!passphrase) {
pgpSecKeyDestroy (seckey);
return PGPERR_KEYDB_BADPASSPHRASE;
}
error = pgpSecKeyUnlock (seckey, pgpEnv, passphrase,
strlen (passphrase));
pgpSecKeyDestroy (seckey);
if (error != 1) {
if (error == 0)
error = PGPERR_KEYDB_BADPASSPHRASE;
return error;
}
}
}
/* Make sure it's enabled first before setting axiomatic */
if ((error = pgpEnableKey (key)) != PGPERR_OK)
return error;
if ((error = pgpCopyKey (allset, keyobj, &addset)) != PGPERR_OK)
return error;
if (!(*keys->objIsMutable) (keys, keyobj)) {
if ((error = pgpAddObjects (keys, addset)) != PGPERR_OK)
goto cleanup;
}
ringKeySetAxiomatic (allset, keyobj);
pgpKeyDBChanged (keys, addset);
cleanup:
if (addset)
ringSetDestroy (addset);
return error;
}
PGPError
pgpUnsetKeyAxiomatic (PGPKey *key)
{
Boolean axiomatic;
struct RingSet *allset, *addset = NULL;
union RingObject *keyobj;
PGPKeyDB *keys;
PGPError error = PGPERR_OK;
pgpa(pgpaPGPKeyValid(key));
pgpGetKeyBoolean (key, kPGPKeyPropIsAxiomatic, &axiomatic);
if (!axiomatic)
return PGPERR_BADPARAM;
keys = key->keyDB;
allset = pgpKeyDBRingSet (keys);
keyobj = key->key;
error = pgpCopyKey (allset, keyobj, &addset);
if (error)
return error;
if (!(*keys->objIsMutable) (keys, keyobj)) {
error = pgpAddObjects (keys, addset);
if (error)
goto cleanup;
}
ringKeyResetAxiomatic (allset, keyobj);
pgpKeyDBChanged (keys, addset);
cleanup:
if (addset)
ringSetDestroy (addset);
return error;
}
/* Get property functions. Internal GetKey functions work for both
master keys and subkeys. */
static PGPError
pgpReturnPropBuffer (char const *src, char *prop,
size_t srclen, size_t proplen)
{
PGPError result = PGPERR_OK;
if (srclen > proplen) {
srclen = proplen;
result = PGPERR_KEYDB_BUFFERTOOSHORT;
}
if (prop && srclen > 0)
pgpCopyMemory (src, prop, srclen);
return result;
}
static PGPError
pgpGetKeyNumberInternal (RingSet *ringset, RingObject *keyobj,
PGPKeyPropName propname, long *prop)
{
byte keyid[8];
unsigned long longkeyid;
unsigned char pkalg;
int i;
byte trust;
switch (propname) {
case kPGPKeyPropKeyId:
ringKeyID8 (ringset, keyobj, NULL, keyid);
longkeyid = 0;
for (i = 4; i < 8; i++)
longkeyid = (longkeyid << 8) + keyid[i];
*prop = (long) longkeyid; /* *prop should be cast to (unsigned long) */
break;
case kPGPKeyPropAlgId:
ringKeyID8 (ringset, keyobj, &pkalg, NULL);
*prop = (long) pkalg;
break;
case kPGPKeyPropBits:
*prop = (long) ringKeyBits (ringset, keyobj);
break;
case kPGPKeyPropTrust:
if (pgpTrustModel (pgpRingPool) == PGPTRUST0) {
trust = ringKeyTrust (ringset, keyobj);
if (trust == PGP_KEYTRUST_UNDEFINED ||
trust == PGP_KEYTRUST_UNKNOWN)
trust = PGP_KEYTRUST_NEVER;
*prop = (long) trust;
break;
}
default:
return PGPERR_KEYDB_INVALIDPROPERTY;
}
return PGPERR_OK;
}
PGPError
pgpGetKeyNumber (PGPKey *key, PGPKeyPropName propname, long *prop)
{
PGPError error = PGPERR_OK;
PGPUserID *userid;
RingSet *ringset;
long trustval;
pgpa(pgpaPGPKeyValid(key));
switch (propname) {
case kPGPKeyPropValidity:
if (pgpTrustModel (pgpRingPool) == PGPTRUST0) {
*prop = PGP_VALIDITY_UNKNOWN;
pgpIncKeyRefCount (key);
for (userid = (PGPUserID *) key->userIDs.next;
userid != (PGPUserID *) &key->userIDs;
userid = userid->next) {
if (!userid->removed) {
pgpGetUserIDNumber (userid, kPGPUserIDPropValidity,
&trustval);
if (trustval > *prop)
*prop = trustval;
}
}
pgpFreeKey (key);
}
else {
ringset = pgpKeyDBRingSet (key->keyDB);
*prop = (long) ringKeyConfidence (ringset, key->key);
}
break;
default:
ringset = pgpKeyDBRingSet (key->keyDB);
error = pgpGetKeyNumberInternal (ringset, key->key, propname, prop);
}
return error;
}
PGPError
pgpGetSubKeyNumber (PGPSubKey *subkey, PGPKeyPropName propname, long *prop)
{
PGPError error = PGPERR_OK;
RingSet *ringset;
pgpa(pgpaPGPSubKeyValid(subkey));
CHECKREMOVED(subkey);
switch (propname) {
case kPGPKeyPropKeyId:
case kPGPKeyPropAlgId:
case kPGPKeyPropBits:
ringset = pgpKeyDBRingSet (subkey->key->keyDB);
error = pgpGetKeyNumberInternal (ringset, subkey->subKey,
propname, prop);
break;
default:
return PGPERR_KEYDB_INVALIDPROPERTY;
}
return error;
}
static PGPError
pgpGetKeyTimeInternal (RingSet *ringset, RingObject *keyobj,
PGPKeyPropName propname, PGPTime *prop)
{
switch (propname) {
case kPGPKeyPropCreation:
*prop = ringKeyCreation (ringset, keyobj);
break;
case kPGPKeyPropExpiration:
*prop = ringKeyExpiration (ringset, keyobj);
break;
default:
return PGPERR_KEYDB_INVALIDPROPERTY;
}
return PGPERR_OK;
}
PGPError
pgpGetKeyTime (PGPKey *key, PGPKeyPropName propname, PGPTime *prop)
{
RingSet *ringset;
pgpa(pgpaPGPKeyValid(key));
ringset = pgpKeyDBRingSet (key->keyDB);
return pgpGetKeyTimeInternal (ringset, key->key, propname, prop);
}
PGPError
pgpGetSubKeyTime (PGPSubKey *subkey, PGPKeyPropName propname, PGPTime *prop)
{
RingSet *ringset;
pgpa(pgpaPGPSubKeyValid(subkey));
CHECKREMOVED(subkey);
ringset = pgpKeyDBRingSet (subkey->key->keyDB);
return pgpGetKeyTimeInternal (ringset, subkey->subKey, propname, prop);
}
static PGPError
pgpGetKeyStringInternal (RingSet *ringset, RingObject *keyobj,
PGPKeyPropName propname, char *prop, size_t *len)
{
unsigned char pkalg;
unsigned char buffer[20];
size_t length = *len;
switch (propname) {
case kPGPKeyPropKeyId:
ringKeyID8 (ringset, keyobj, NULL, buffer);
*len = 8;
break;
case kPGPKeyPropFingerprint:
ringKeyID8 (ringset, keyobj, &pkalg, NULL);
if (pkalg == 1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -