📄 pgpdecode.c
字号:
if( !s->fUsedDetachedSigOp && IsOp( op ) && IsntNull( op.subOptions ) ) {
/* Only use the detachedsig op once, after that we will ask user */
s->fUsedDetachedSigOp = TRUE;
setupOp = op.subOptions;
} else {
/* Ask user for detached signature input */
if( IsNull( s->func ) ) {
err = kPGPError_DetachedSignatureFound;
goto error;
}
if( IsPGPError (err = pgpEventDetachedSignature( s->context,
&s->newOptionList, s->func, s->userValue ) ) )
goto error;
if( IsPGPError( err = pgpSearchOptionSingle( s->newOptionList,
kPGPOptionType_DetachedSignature, &op ) ) )
goto error;
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, &bLargeFile,
&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,
PGPSigData 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 */
PGPKeyDBObjRef signKey; /* Signing key as PGPKeyDBObj */
PGPKeyDBRef alternateKeyDB; /* Extra keydb to try lookup */
PGPKeyID keyid; /* KeyID from signature */
PGPTime timeStamp; /* Issuance time of sig */
PGPUInt32 timeValidityPeriod; /* signature validity period in seconds */
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;
alternateKeyDB = 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 */
pgpGetSigDataKeyID ( sig, &keyid );
/* Get time stamp / expiration */
pgpSigDataTime (sig, &timeStamp, &timeValidityPeriod);
retrykeydb:
if( IsNull( s->keyDB ) ) {
err = kPGPError_MissingKeyDB;
} else {
err = PGPFindKeyByKeyID ( s->keyDB, &keyid, &signKey);
}
if( IsPGPError( err ) && IsntNull( alternateKeyDB ) ) {
err = PGPFindKeyByKeyID ( alternateKeyDB, &keyid, &signKey);
}
/* Check for sig by subkeys - OK as long as it's a valid subkey */
if( IsntPGPError( err ) && pgpKeyIsSubkey( signKey ) )
{
if( !pgpSubkeyValid( signKey, FALSE, FALSE ) )
{
err = kPGPError_MissingKeyDB; // Actual error code is ignored
signKey = NULL;
}
}
if( IsPGPError( err ) ) {
/* 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, timeValidityPeriod );
if( IsntNull( alternateKeyDB ) )
PGPFreeKeyDB (alternateKeyDB);
pgpSetupKeyDB (s->newOptionList, &alternateKeyDB);
if( IsntNull( alternateKeyDB ) ) {
PGPIncKeyDBRefCount( alternateKeyDB );
pgpCleanupOptionList( &s->newOptionList );
goto retrykeydb;
}
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, 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,
kPGPKeyProperty_IsRevoked,
&fRevoked ) ) )
goto error;
if( IsPGPError( err = pgpGetKeyBoolean( signKey,
kPGPKeyProperty_IsDisabled,
&fDisabled ) ) )
goto error;
if( IsPGPError( err = pgpGetKeyBoolean( signKey,
kPGPKeyProperty_IsExpired,
&fExpired ) ) )
goto error;
} else if( err != kPGPError_NoErr ) {
goto error;
}
/* Check signature, returns 1 if OK */
err = pgpSigDataCheck (sig, signKey, hash);
if( err != 1 ) {
if( err == kPGPError_KeyUnusableForSignature )
{
/* 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, timeValidityPeriod );
if( IsntNull( alternateKeyDB ) )
PGPFreeKeyDB (alternateKeyDB);
pgpSetupKeyDB (s->newOptionList, &alternateKeyDB);
if( IsntNull( alternateKeyDB ) ) {
PGPIncKeyDBRefCount( alternateKeyDB );
pgpCleanupOptionList( &s->newOptionList );
goto retrykeydb;
}
pgpCleanupOptionList( &s->newOptionList );
goto error;
}
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,
timeValidityPeriod );
pgpCleanupOptionList( &s->newOptionList );
goto error;
}
/* Good signature, tell him! */
err = pgpEventSignature( s->context, &s->newOptionList,
s->func, s->userValue, &keyid, signKey,
TRUE, TRUE, fDisabled, fRevoked, fExpired,
fValidityThreshold, keyValidity, timeStamp,
timeValidityPeriod );
pgpCleanupOptionList( &s->newOptionList );
/* Fall through */
error:
if ( IsntNull( alternateKeyDB ) )
PGPFreeKeyDB( alternateKeyDB );
return err;
#endif /* PGP_VERIFY_DISABLE */ /* ] */
}
/*
* 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,
int (*tryKey)(void *arg, PGPByte const *key, PGPSize keylen),
void *tryarg
)
{
#if PGP_DECRYPT_DISABLE /* [ */
(void) arg;
(void) esklist;
(void) tryKey;
(void) tryarg;
return kPGPError_FeatureNotAvailable;
#else /* PGP_DECRYPT_DISABLE */ /* ] [ */
PGPDecodeJob *s; /* Parameters for callbacks */
PGPESK const *esk; /* ESK being tested */
PGPKeyDBObjRef decKey; /* PGPKeyDBObj for decryption key */
PGPKeySet *decKeySet; /* Keyset with all decryption keys */
PGPBoolean success; /* True if had a successful decrypt */
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 */
PGPByte *key; /* Buffer holding decrypted key */
PGPSize keylen; /* Size of key buffer */
s = (PGPDecodeJob *) arg;
decKeySet = NULL;
keyIDArray = NULL;
key = NULL;
/* First loop over all ESK's to set up recipient list */
passPhraseCount = 0;
keyIDCount = 0;
if( IsntNull( s->keyDB ) ) {
if( IsPGPError( err = PGPNewEmptyKeySet( s->keyDB, &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;
decKey = NULL;
if( IsntNull( s->keyDB ) ) {
(void)pgpGetKeyByKeyID ( s->keyDB, &keyid, FALSE, FALSE,
&decKey);
}
if( IsNull( decKey ) ) {
/* We don't have the decryption key */
} else {
/* Accumulate into recipient key set */
if( IsPGPError( err = PGPAddKey(decKey, decKeySet ) ) )
goto error;
}
break;
}
default:
pgpAssert(0);
break;
}
}
/* 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->keyDB ) ) {
if( IsPGPError( err = PGPNewEmptyKeySet( s->keyDB, &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 */
keylen = pgpEskMaxKeySize( esk );
key = pgpContextMemAlloc( s->context, keylen, 0 );
if( IsNull( key ) )
{
err = kPGPError_OutOfMemory;
goto error;
}
if (s->passPhraseIsSessionKey) {
keylen = pgpMin( keylen, s->passLength );
pgpCopyMemory( s->passPhrase, key, keylen );
} else {
err = pgpEskConvDecrypt (esk, s->env,
(char *)s->passPhrase, s->passLength, key);
if( err < 0 ) {
err = keylen;
goto error;
}
keylen = err;
}
/* Returns 0 on success, nonzero on failure */
if( tryKey (tryarg, key, keylen) == 0 ) {
/* Success */
success = 1;
/* Report it worked OK */
cipheralg = (PGPCipherAlgorithm)key[0];
if( IsPGPError( err = pgpEventDecryption( s->context,
&s->newOptionList, s->func,
s->userValue, cipheralg,
key, keylen) ) )
goto error;
pgpCleanupOptionList( &s->newOptionList );
}
break;
case PGP_ESKTYPE_PUBKEY:
{
PGPKeyID keyid; /* Key ID from ESK */
PGPBoolean bOnToken;
if (s->passPhraseIsSessionKey) {
keylen = s->passLength;
key = pgpContextMemAlloc( s->context, keylen, 0 );
if( IsNull( key ) )
{
err = kPGPError_OutOfMemory;
goto error;
}
pgpCopyMemory( s->passPhrase, key, keylen );
} else {
/* Look up key from ESK */
err = pgpGetEskKeyID( esk, &keyid );
if ( IsPGPError( err ) )
goto error;
/*
* If don't have key, go on to next one.
*/
decKey = NULL;
if( IsntNull( s->keyDB ) ) {
(void)pgpGetKeyByKeyID( s->keyDB, &keyid, FALSE,
FALSE, &decKey);
}
if( IsNull( decKey ) )
break;
if( !pgpKeyIsSec( decKey ) )
break;
bOnToken = pgpKeyIsOnToken( decKey );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -