📄 pgpkeyman.c
字号:
PGPByte flagbuf[4];
PGPUInt32 i;
PGPError err = kPGPError_NoErr;
keys = PGPPeekKeyDBObjKeyDB( key );
context = PGPPeekKeyDBContext( keys );
pgpEnv = pgpContextGetEnvironment( context );
tzFix = pgpenvGetInt (pgpEnv, PGPENV_TZFIX, NULL, NULL);
timestamp = pgpTimeStamp (tzFix);
/* Parse preferred algorithms into tight buffer */
prefalgByte = NULL;
if (prefalgLength > 0) {
/* Convert preferred algorithm to byte array */
prefalgLength /= sizeof(PGPCipherAlgorithm);
prefalgByte = (PGPByte *)pgpContextMemAlloc( context,
prefalgLength, 0);
if( IsNull( prefalgByte ) ) {
err = kPGPError_OutOfMemory;
goto error;
}
for (i=0; i<prefalgLength; ++i) {
prefalgByte[i] = (PGPByte)prefalg[i];
}
}
/* Verify passphrase */
if( !pgpSecPassphraseOK( key, (PGPByte *) passphrase, passphraseLength,
hashedPhrase, cacheTimeOut, cacheGlobal ) )
{
err = kPGPError_BadPassphrase;
goto error;
}
/* Update each self-sig on each name */
for (userid = key->down; IsntNull( userid ); userid = userid->next) {
if (!pgpKeyDBObjIsReal( userid) )
continue;
if( pgpObjectType( userid ) != RINGTYPE_USERID )
continue;
latestsig = pgpLatestSigByKey( userid, key );
if( IsntNull( latestsig ) )
{
/* Revoke existing cert */
sigspec = pgpSigSpecCreate (pgpEnv, key,
PGP_SIGTYPE_KEY_UID_REVOKE);
pgpSigSpecSetTimestamp( sigspec, timestamp );
err = pgpSignObject (userid, sigspec);
pgpSigSpecDestroy (sigspec);
sigspec = NULL;
/* Copy existing sigspec, set new timestamp */
sigspec = pgpSigSigSpec (latestsig, &err);
if( IsNull( sigspec ) )
continue;
pgpSigSpecSetTimestamp( sigspec, timestamp+1 );
}
else
{
/* No previous sig, must create one */
sigspec = pgpSigSpecCreate (pgpEnv, key, PGP_SIGTYPE_KEY_GENERIC);
if( IsNull( sigspec ) )
continue;
pgpSigSpecSetTimestamp( sigspec, timestamp+1 );
}
/* Set new values */
pgpSigSpecSetPrefAlgs (sigspec, 0, prefalgByte, prefalgLength);
pgpSigSpecSetPrefKeyServ (sigspec, 0, prefkeyserv, prefkeyservLength);
if( fkeyflags )
{
for( i=0; i<sizeof(flagbuf); ++i )
flagbuf[i] = (PGPByte)(keyflags >> (i*8));
pgpSigSpecSetKeyFlags( sigspec, 0, flagbuf, sizeof(flagbuf) );
}
if( fkeyservprefs )
{
for( i=0; i<sizeof(flagbuf); ++i )
flagbuf[i] = (PGPByte)(keyservprefs >> (i*8));
pgpSigSpecSetKeyServPrefs( sigspec, 0, flagbuf, sizeof(flagbuf) );
}
/* Issue new signature */
err = pgpSignObject (userid, sigspec);
pgpSigSpecDestroy (sigspec);
sigspec = NULL;
}
error:
if( IsntNull( sigspec ) )
pgpSigSpecDestroy (sigspec);
if( IsntNull( prefalgByte ) )
PGPFreeData (prefalgByte);
return err;
}
PGPError
pgpUpdateKeyOptionsInternal (
PGPKeyDBObjRef key,
PGPOptionListRef optionList
)
{
char * passphrase;
PGPSize passphraseLength;
PGPBoolean hashedPhrase = FALSE;
PGPUInt32 cacheTimeOut = 0;
PGPBoolean cacheGlobal;
PGPCipherAlgorithm *prefalg;
PGPSize prefalgLength;
PGPByte *prefkeyserv;
PGPSize prefkeyservLength;
PGPBoolean keyflagsop;
PGPUInt32 keyflags;
PGPBoolean keyservprefsop;
PGPUInt32 keyservprefs;
PGPError err = kPGPError_NoErr;
if ( IsPGPError( err = pgpKeyDeadCheck(key) ) )
goto error;
if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
keyoptionOptionSet, elemsof( keyoptionOptionSet ) ) ) )
goto error;
/* Pick up passphrase options */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_Passphrase, FALSE,
"%p%l", &passphrase, &passphraseLength ) ) )
goto error;
if (IsNull( passphrase )) {
hashedPhrase = TRUE;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_Passkey, FALSE,
"%p%l", &passphrase, &passphraseLength ) ) )
goto error;
}
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_CachePassphrase, FALSE,
"%d%b", &cacheTimeOut, &cacheGlobal ) ) )
goto error;
/* Get data to modify (require preferred algs for now) */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_PreferredAlgorithms, FALSE,
"%p%l", &prefalg, &prefalgLength ) ) )
goto error;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_PreferredKeyServer, FALSE,
"%p%l", &prefkeyserv, &prefkeyservLength ) ) )
goto error;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_KeyFlags, FALSE,
"%b%d", &keyflagsop, &keyflags ) ) )
goto error;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_KeyServerPreferences, FALSE,
"%b%d", &keyservprefsop, &keyservprefs ) ) )
goto error;
if( IsNull(prefalg) && IsNull(prefkeyserv) && !keyflagsop
&& !keyservprefsop )
goto error; /* Nothing to do */
if( pgpFrontEndKey( key ) )
{
PGPUInt32 *newobjs;
PGPSize newobjslen;
PGPKeyDB *keydb = PGPPeekKeyDBObjKeyDB( key );
err = pgpUpdateKeyOptions_back( PGPPeekKeyDBContext(keydb),
pgpKeyDBObjID(key), passphrase,
passphraseLength, hashedPhrase,
cacheTimeOut, cacheGlobal,
prefalg, prefalgLength,
prefkeyserv, prefkeyservLength,
keyflags, keyflagsop, keyservprefs,
keyservprefsop, &newobjs, &newobjslen);
if( IsPGPError( err ) )
return err;
err = pgpAddFromKeyArray( keydb, NULL, newobjs, 1, FALSE );
PGPFreeData( newobjs );
} else {
err = pgpUpdateKeyOptions_internal( key, passphrase, passphraseLength,
hashedPhrase, cacheTimeOut,
cacheGlobal, prefalg, prefalgLength,
prefkeyserv, prefkeyservLength,
keyflags, keyflagsop, keyservprefs,
keyservprefsop );
if( IsPGPError( err ) )
return err;
}
/* Calculate trust changes as a result */
if( err == kPGPError_NoErr )
(void)PGPCalculateTrust (PGPPeekKeyDBObjKeyDB(key)->rootSet, NULL);
error:
return err;
}
/* Disable the key. If key is not stored in a writeable KeySet, copy it
locally. Private keys cannot be disabled. */
PGPError
pgpDisableKey (PGPKeyDBObj *key)
{
PGPKeyDB *keys = NULL;
PGPError error = kPGPError_NoErr;
keys = PGPPeekKeyDBObjKeyDB( key );
/* Axiomatic keys cannot be disabled, but plain old private
keys can (because they may belong to someone else). */
if (pgpKeyAxiomatic (key))
return kPGPError_BadParams;
if (!pgpKeyDisabled (key)) {
pgpKeyDisable (key);
pgpKeyDBChanged (keys, TRUE);
}
return error;
}
/* Enable the key. */
PGPError
pgpEnableKey (PGPKeyDBObj *key)
{
PGPKeyDB *keys;
keys = PGPPeekKeyDBObjKeyDB( key );
if (pgpKeyDisabled (key)) {
pgpKeyEnable (key);
pgpKeyDBChanged (keys, TRUE);
}
return kPGPError_NoErr;
}
PGPError
PGPSetKeyEnabled( PGPKeyDBObjRef key, PGPBoolean enable )
{
PGPError error = kPGPError_NoErr;
PGPValidateKey( key );
pgpEnterPGPErrorFunction();
error = pgpKeyDeadCheck( key) ;
if ( IsPGPError( error ) )
return error;
if( pgpFrontEndKey( key ) )
{
error = pgpSetKeyEnabled_back( PGPPeekKeyDBObjContext(key),
pgpKeyDBObjID( key ), enable );
if( IsntPGPError( error ) )
{
pgpKeyDBObjRefresh( key, FALSE );
pgpKeyDBChanged (PGPPeekKeyDBObjKeyDB(key), TRUE);
}
} else if( enable ) {
error = pgpEnableKey( key );
} else {
error = pgpDisableKey( key );
}
if( IsntPGPError( error ) )
error = PGPCalculateTrust( PGPPeekKeyDBObjKeyDB(key)->rootSet, NULL );
return error;
}
/* Change the passphrase. If the new passphrase is the same as the
old passphrase, we still unlock the key as the user may be trying to
set the key's isAxiomatic flag. */
PGPError
pgpDoChangePassphrase_internal (PGPKeyDB *keyDB,
PGPKeyDBObj *key, PGPKeyDBObj *masterkey,
const char *oldphrase, PGPSize oldphraseLength,
const char *newphrase, PGPSize newphraseLength,
PGPBoolean newPassphraseIsKey,
PGPUInt32 cacheTimeOut, PGPBoolean cacheGlobal)
{
PGPError error = kPGPError_NoErr;
PGPSecKey *seckey = NULL;
PGPEnv *pgpEnv;
PGPEnv *pgpEnvCopy = NULL;
PGPRandomContext *pgpRng;
PGPStringToKeyType s2ktype;
PGPByte const *prefAlgs;
PGPSize prefAlgsLength;
PGPBoolean hashed;
PGPUInt32 i;
PGPBoolean locked = 0;
if (IsntNull(oldphrase) && oldphraseLength == 0)
oldphrase = NULL;
if (IsntNull(newphrase) && newphraseLength == 0)
newphrase = NULL;
if (!pgpKeyIsSec ( key ))
return kPGPError_SecretKeyNotFound;
/* Does the caller know the current passphrase? */
pgpEnv = pgpContextGetEnvironment( keyDB->context );
seckey = pgpSecSecKey (key, 0);
if (!seckey)
return pgpKeyDBError(keyDB);
if (pgpSecKeyIslocked (seckey)) {
locked = 1;
if (!oldphrase) {
error = kPGPError_BadPassphrase;
goto error;
}
error = (PGPError)pgpSecKeyUnlock (seckey, oldphrase,
oldphraseLength, FALSE);
if (error != 1) {
if (error == 0)
error = kPGPError_BadPassphrase;
goto error;
}
}
pgpRng = pgpContextGetX9_17RandomContext( keyDB->context );
if (newPassphraseIsKey) {
s2ktype = kPGPStringToKey_LiteralShared;
} else if (seckey->pkAlg <= kPGPPublicKeyAlgorithm_RSA) {
s2ktype = kPGPStringToKey_Simple;
} else {
s2ktype = kPGPStringToKey_IteratedSalted;
}
/* Lock using key's preferred algorithm if known */
if( IsPGPError( error = pgpenvCopy( pgpEnv, &pgpEnvCopy ) ) )
goto error;
prefAlgs = pgpKeyFindSubpacket (
(IsntNull(masterkey)?masterkey:key),
SIGSUB_PREFERRED_ENCRYPTION_ALGS, 0,
&prefAlgsLength, NULL, &hashed, NULL, NULL, &error);
for( i = 0; hashed && (i < prefAlgsLength); ++i ) {
PGPCipherAlgorithm lockAlg = (PGPCipherAlgorithm)prefAlgs[i];
if( IsntNull( pgpCipherGetVTBL ( lockAlg ) ) ) {
pgpenvSetInt (pgpEnvCopy, PGPENV_CIPHER, lockAlg,
PGPENV_PRI_FORCE);
break;
}
}
error = (PGPError)pgpSecKeyChangeLock (seckey, pgpEnvCopy, pgpRng,
oldphrase, oldphraseLength, FALSE,
newphrase, newphraseLength, s2ktype);
if (error)
goto error;
error = pgpUpdateSecKeyData( key, seckey );
if( IsPGPError( error ) )
goto error;
/* Add to cache if requested */
(void)pgpSecKeyCachePassphrase( seckey, (PGPByte *)newphrase,
newphraseLength, newPassphraseIsKey,
cacheTimeOut, cacheGlobal );
pgpKeyDBChanged (keyDB, TRUE);
pgpSecKeyDestroy (seckey); seckey = NULL;
error:
if (seckey)
pgpSecKeyDestroy (seckey);
if (pgpEnvCopy)
pgpenvDestroy (pgpEnvCopy);
return error;
}
static const PGPOptionType changepassphraseOptionSet[] = {
kPGPOptionType_Passphrase,
kPGPOptionType_Passkey,
kPGPOptionType_CachePassphrase
};
PGPError
pgpChangePassphraseInternal(
PGPKeyDBObjRef key,
PGPOptionListRef optionList
)
{
PGPKeyDBRef keydb;
void * oldPassphrase;
void * newPassphrase;
PGPSize oldPassphraseLength;
PGPSize newPassphraseLength;
PGPBoolean oldWasPasskey;
PGPBoolean newWasPasskey;
PGPUInt32 cacheTimeOut = 0;
PGPBoolean cacheGlobal;
PGPError err = kPGPError_NoErr;
pgpa(pgpaPGPKeyValid(key));
PGPValidateKey( key );
oldWasPasskey = FALSE;
newWasPasskey = FALSE;
keydb = PGPPeekKeyDBObjKeyDB( key );
if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
changepassphraseOptionSet,
elemsof( changepassphraseOptionSet ) ) ) )
goto error;
/*
* Read old and new passphrases
*/
if( 2 != pgpSearchPassphraseOptions( optionList, &oldPassphrase,
&oldPassphraseLength, &oldWasPasskey,
&newPassphrase, &newPassphraseLength,
&newWasPasskey ) )
{
err = kPGPError_BadParams;
goto error;
}
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_CachePassphrase, FALSE,
"%d%b", &cacheTimeOut, &cacheGlobal ) ) )
goto error;
if( pgpFrontEndKey( key ) )
{
err = pgpDoChangePassphrase_back (PGPPeekKeyDBContext(keydb),
keydb->id, pgpKeyDBObjID(key), 0,
(char const *)oldPassphrase, oldPassphraseLength,
(char const *)newPassphrase, newPassphraseLength,
newWasPasskey, cacheTimeOut, cacheGlobal );
if( IsntPGPError( err ) )
{
pgpKeyDBObjRefresh( key, FALSE );
pgpKeyDBChanged (keydb, TRUE);
}
} else {
err = pgpDoChangePassphrase_internal (keydb, key, NULL,
(char const *)oldPassphrase, oldPassphraseLength,
(char
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -