📄 pgpdecode.c
字号:
if( IsOp( op ) && IsntNull( op.subOptions ) ) {
setupOp = op.subOptions;
} else {
err = kPGPError_DetachedSignatureFound;
goto error;
}
freshOpList = s->newOptionList;
}
/* Set up input file or buffer */
err = pgpSetupInput( s->context, setupOp, NULL, NULL, TRUE, TRUE,
&detFileRef, &pfrdet, &inFileDataType, &detBufPtr,
&detBufLength );
if( IsPGPError( err ) )
goto error;
/* Now pump the sig-check data through the pipes */
if( detFileRef ) {
/* File input */
pgpFileReadSetCallBack( pfrdet, decodeLocalCallBack, s );
err = pgpFileReadPump( pfrdet, head );
pgpFileReadDestroy( pfrdet );
if( IsPGPError( err ) )
goto error;
} else {
/* Buffer input */
if( IsPGPError( err = pgpPumpMem( head, detBufPtr,
detBufLength, NULL, NULL ) ) )
goto error;
}
err = kPGPError_NoErr;
/* Fall through */
error:
/* Discard after one usage */
if( PGPOptionListRefIsValid( freshOpList ) ) {
pgpFreeOptionList( freshOpList );
}
s->newOptionList = kInvalidPGPOptionListRef;
return err;
}
/*
* Given the signature structure, sig, verify it against the hash
* to see if this signature is valid. This requires looking up the
* public key in the keyring and validating the key.
*
* Returns 0 on success or an error code.
*/
static PGPError
pgpDecodeVerifySig(
void *arg,
PGPSig const *sig,
PGPByte const *hash
)
{
#if PGP_VERIFY_DISABLE /* [ */
(void)arg;
(void)sig;
(void)hash;
return kPGPError_FeatureNotAvailable;
#else /* PGP_VERIFY_DISABLE */ /* ] [ */
PGPDecodeJob *s; /* Parameters for callbacks */
PGPKeyRef signKey; /* Signing key as PGPKey */
PGPKeySetRef alternateKeySet; /* Extra keyset to try lookup */
RingObject *ringKey; /* Public key ring object */
RingSet const *ringSet; /* Set holding ringKey */
PGPPubKey *pubkey; /* Public key for verify */
PGPKeyID keyid; /* KeyID from signature */
PGPPublicKeyAlgorithm pkalg; /* Public key alg from signature */
PGPTime timeStamp; /* Issuance time of sig */
PGPValidity failValidity, /* Fail on keys less valid */
warnValidity; /* Warn on keys less valid */
PGPBoolean fRevoked=FALSE,/* Status of signing key */
fExpired=FALSE,
fDisabled=FALSE,
fValidityThreshold=TRUE;
PGPValidity keyValidity=kPGPValidity_Unknown;
PGPError err; /* Error code */
s = (PGPDecodeJob *) arg;
pubkey = NULL;
alternateKeySet = NULL;
if( IsNull( s->func ) ) {
/* If can't report results, don't bother to do anything */
err = kPGPError_NoErr;
goto error;
}
/* Get info about sig */
err = pgpGetSigKeyID ( sig, &keyid );
if ( IsPGPError( err ) )
goto error;
pkalg = (PGPPublicKeyAlgorithm)pgpSigPKAlg (sig);
timeStamp = pgpSigTimestamp (sig);
retrykeyset:
if (pkalg >= kPGPPublicKeyAlgorithm_First &&
pkalg <= kPGPPublicKeyAlgorithm_Last) {
if( IsNull( s->keySet ) ) {
err = kPGPError_MissingKeySet;
} else {
err = PGPGetKeyByKeyID ( s->keySet, &keyid, pkalg, &signKey);
}
if( IsPGPError( err ) && IsntNull( alternateKeySet ) ) {
err = PGPGetKeyByKeyID ( alternateKeySet, &keyid, pkalg, &signKey);
}
}
if( IsPGPError( err ) ||
pkalg < kPGPPublicKeyAlgorithm_First ||
pkalg > kPGPPublicKeyAlgorithm_Last) {
/* Don't have signing key; notify him */
err = pgpEventSignature( s->context, &s->newOptionList,
s->func, s->userValue, &keyid, NULL,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
keyValidity, timeStamp );
if( IsntNull( alternateKeySet ) )
PGPFreeKeySet (alternateKeySet);
pgpSetupKeySet (s->newOptionList, &alternateKeySet);
if( IsntNull( alternateKeySet ) ) {
PGPIncKeySetRefCount( alternateKeySet );
pgpCleanupOptionList( &s->newOptionList );
goto retrykeyset;
}
pgpCleanupOptionList( &s->newOptionList );
goto error;
}
if( IsPGPError( err = pgpGetKeyRingObject( signKey, FALSE, &ringKey ) ) )
goto error;
if( IsPGPError( err = pgpGetKeyRingSet( signKey, FALSE, &ringSet ) ) )
goto error;
pubkey = ringKeyPubKey( ringSet, ringKey, PGP_PKUSE_SIGN );
if (pubkey && !pubkey->verify) {
/* Make sure we can use this key */
pgpPubKeyDestroy (pubkey);
pubkey = NULL;
}
if (!pubkey) {
/* Can't verify for some reason... notify him */
err = pgpEventSignature( s->context, &s->newOptionList,
s->func, s->userValue, &keyid, signKey,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
keyValidity, timeStamp );
if( IsntNull( alternateKeySet ) )
PGPFreeKeySet (alternateKeySet);
pgpSetupKeySet (s->newOptionList, &alternateKeySet);
if( IsntNull( alternateKeySet ) ) {
PGPIncKeySetRefCount( alternateKeySet );
pgpCleanupOptionList( &s->newOptionList );
goto retrykeyset;
}
pgpCleanupOptionList( &s->newOptionList );
goto error;
}
/* Determine validity of signing key */
if( IsPGPError( err = pgpGetMinValidity( s->optionList,
&failValidity, &warnValidity ) ) )
goto error;
err = pgpCheckKeyValidity( s->context, s->optionList,
signKey, ringSet, failValidity, warnValidity, NULL,
&keyValidity );
if( err == kPGPError_KeyInvalid ) {
fValidityThreshold = FALSE;
} else if( err == kPGPError_KeyRevoked ||
err == kPGPError_KeyExpired ||
err == kPGPError_KeyDisabled ) {
fValidityThreshold = FALSE;
if( IsPGPError( err = PGPGetKeyBoolean( signKey, kPGPKeyPropIsRevoked,
&fRevoked ) ) )
goto error;
if( IsPGPError( err = PGPGetKeyBoolean( signKey, kPGPKeyPropIsDisabled,
&fDisabled ) ) )
goto error;
if( IsPGPError( err = PGPGetKeyBoolean( signKey, kPGPKeyPropIsExpired,
&fExpired ) ) )
goto error;
} else if( err != kPGPError_NoErr ) {
goto error;
}
/* Check signature, returns 1 if OK */
err = pgpSigCheck (sig, pubkey, hash);
pgpPubKeyDestroy (pubkey);
pubkey = NULL;
if( err != 1 ) {
if( IsPGPError( err ) )
goto error;
/* Notify of bad signature and exit */
err = pgpEventSignature( s->context, &s->newOptionList,
s->func, s->userValue, &keyid, signKey,
TRUE, FALSE, fDisabled, fRevoked, fExpired,
fValidityThreshold, keyValidity, timeStamp );
pgpCleanupOptionList( &s->newOptionList );
goto error;
}
err = pgpEventSignature( s->context, &s->newOptionList,
s->func, s->userValue, &keyid, signKey,
TRUE, TRUE, fDisabled, fRevoked, fExpired,
fValidityThreshold, keyValidity, timeStamp );
pgpCleanupOptionList( &s->newOptionList );
/* Fall through */
error:
if ( IsntNull( pubkey ) )
pgpPubKeyDestroy( pubkey );
if ( IsntNull( alternateKeySet ) )
PGPFreeKeySet( alternateKeySet );
return err;
#endif /* PGP_VERIFY_DISABLE */ /* ] */
}
/*
* Remove any subkeys which don't have their keyids on the list
*/
static PGPError
sRemoveUnlistedSubkeys( PGPKeySetRef keyset, PGPKeyID *keyids,
PGPUInt32 nkeyids )
{
PGPKeyListRef klist;
PGPKeyIterRef kiter;
PGPKeyID skid;
PGPKeyRef key;
PGPSubKeyRef subkey;
PGPUInt32 i;
PGPError err = kPGPError_NoErr;
/* Skip if we have no keys (i.e. passphrase only) */
if( IsNull( keyset ) )
return err;
PGPOrderKeySet( keyset, kPGPUserIDOrdering, &klist );
PGPNewKeyIter( klist, &kiter );
while( IsntPGPError( PGPKeyIterNext( kiter, &key ) ) ) {
while( IsntPGPError( PGPKeyIterNextSubKey( kiter, &subkey ) ) ) {
if( IsPGPError( err = PGPGetKeyIDFromSubKey( subkey, &skid ) ) )
goto error;
/* See if subkey id skid matches one on the list */
for( i = 0; i < nkeyids; ++i ) {
if( PGPCompareKeyIDs( &skid, keyids+i ) == 0 )
break;
}
if( i == nkeyids ) {
/* No match, must remove subkey */
if( IsPGPError( err = PGPRemoveSubKey( subkey ) ) )
goto error;
}
}
}
error:
PGPFreeKeyIter( kiter );
PGPFreeKeyList( klist );
return err;
}
/*
* given a list of Encrypted Session Keys (esklist), try to decrypt
* them to get the session key. Fills in keylen with the length of
* the session key buffer.
*
* Returns 0 on success or PGPANN_PARSER_EATIT on failure.
*/
static PGPError
pgpDecodeDecryptESK(
void *arg,
PGPESK const *esklist,
PGPByte *key,
PGPSize *keylen,
int (*tryKey)(void *arg, PGPByte const *key, PGPSize keylen),
void *tryarg
)
{
#if PGP_DECRYPT_DISABLE /* [ */
(void) arg;
(void) esklist;
(void) key;
(void) keylen;
(void) tryKey;
(void) tryarg;
return kPGPError_FeatureNotAvailable;
#else /* PGP_DECRYPT_DISABLE */ /* ] [ */
PGPDecodeJob *s; /* Parameters for callbacks */
PGPESK const *esk; /* ESK being tested */
PGPKeyRef decKey; /* PGPKey for decryption key */
PGPKeySet *decKeySet1; /* Keyset with just decKey */
PGPKeySet *decKeySet; /* Keyset with all decryption keys */
RingObject *ringKey; /* Secret key ring object */
RingSet const *ringSet; /* Lowlevel keyring set for key */
PGPSecKey *seckey; /* Secret key */
PGPPublicKeyAlgorithm pkalg; /* Pubkey algorithm from ESK */
PGPBoolean success; /* True if had a successful decrypt */
PGPInt32 klen; /* Return code from key func */
PGPError err; /* Error from pgplib */
PGPUInt32 passPhraseCount; /* Count of possible pphrases */
PGPUInt32 keyIDCount; /* # deckeys unavail */
PGPKeyID *keyIDArray; /* Array of ptrs to keyids */
PGPCipherAlgorithm cipheralg; /* Decryption algorithm */
PGPBoolean firstpass; /* of passphrase checking */
s = (PGPDecodeJob *) arg;
decKeySet = NULL;
decKeySet1 = NULL;
seckey = NULL;
keyIDArray = NULL;
/* First loop over all ESK's to set up recipient list */
passPhraseCount = 0;
keyIDCount = 0;
if( IsntNull( s->keySet ) ) {
if( IsPGPError( err = PGPNewKeySet( s->context, &decKeySet ) ) )
goto error;
}
for( esk = esklist; IsntNull( esk ); esk = pgpEskNext( esk ) ) {
switch( pgpEskType( esk ) ) {
case PGP_ESKTYPE_PASSPHRASE:
passPhraseCount += 1;
break;
case PGP_ESKTYPE_PUBKEY:
{
PGPKeyID keyid; /* Key ID from ESK */
void * vKeyIDArray;
err = pgpGetEskKeyID( esk, &keyid);
if ( IsPGPError( err ) )
goto error;
/* Save keyids in list */
vKeyIDArray = keyIDArray;
err = pgpContextMemRealloc( s->context,
&vKeyIDArray,
(keyIDCount+1) * sizeof(keyIDArray[ 0 ]), 0 );
if( IsPGPError( err ) )
goto error;
keyIDArray = (PGPKeyID *)vKeyIDArray;
keyIDArray[keyIDCount++] = keyid;
pkalg = (PGPPublicKeyAlgorithm)pgpEskPKAlg (esk);
decKey = NULL;
if( IsntNull( s->keySet ) &&
pkalg >= kPGPPublicKeyAlgorithm_First &&
pkalg <= kPGPPublicKeyAlgorithm_Last) {
(void)PGPGetKeyByKeyID ( s->keySet, &keyid, pkalg, &decKey);
}
if( IsNull( decKey ) ) {
/* We don't have the decryption key */
} else {
/* Accumulate into recipient key set */
if( IsPGPError( err = PGPNewSingletonKeySet( decKey,
&decKeySet1 ) ) )
goto error;
if( IsPGPError( err = PGPAddKeys(decKeySet1, decKeySet ) ) )
goto error;
PGPFreeKeySet( decKeySet1 );
decKeySet1 = NULL;
}
break;
}
default:
pgpAssert(0);
break;
}
}
/* Remove any irrelevant subkeys from key we added */
if( IsPGPError( err = sRemoveUnlistedSubkeys( decKeySet, keyIDArray,
keyIDCount ) ) )
goto error;
/* Notify user about decryption keys */
if( IsPGPError( err = pgpEventRecipients( s->context, &s->newOptionList,
s->func, s->userValue, decKeySet, keyIDArray,
passPhraseCount, keyIDCount ) ) )
goto error;
pgpCleanupOptionList( &s->newOptionList );
if( IsntNull( decKeySet ) ) {
PGPFreeKeySet( decKeySet );
decKeySet = NULL;
}
/* Loop over all ESK's trying to find one we can decrypt */
/* decKeySet will hold decryption keys that we have secrets for */
success = FALSE;
if( IsntNull( s->keySet ) ) {
if( IsPGPError( err = PGPNewKeySet( s->context, &decKeySet ) ) )
goto error;
}
firstpass = TRUE;
while( !success ) {
for( esk = esklist; IsntNull( esk ) && !success;
esk = pgpEskNext( esk ) ) {
switch( pgpEskType( esk ) ) {
case PGP_ESKTYPE_PASSPHRASE:
/* Try the pass phrase */
if (s->passPhraseIsSessionKey) {
*keylen = pgpMin( *keylen, s->passLength );
pgpCopyMemory( s->passPhrase, key, *keylen );
} else {
klen = pgpEskConvDecrypt (esk, s->env,
(char *)s->passPhrase, s->passLength, key);
if( klen < 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -