📄 pgpdecode.c
字号:
err = klen;
goto error;
}
/* Else klen is length of key */
*keylen = klen;
}
/* 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 */
if (s->passPhraseIsSessionKey) {
*keylen = pgpMin( *keylen, s->passLength );
pgpCopyMemory( s->passPhrase, key, *keylen );
} else {
/* Look up key from ESK */
err = pgpGetEskKeyID( esk, &keyid );
if ( IsPGPError( err ) )
goto error;
pkalg = (PGPPublicKeyAlgorithm)pgpEskPKAlg (esk);
/* If don't have key, go on to next one */
decKey = NULL;
if( IsntNull( s->keySet ) &&
pkalg >= kPGPPublicKeyAlgorithm_First &&
pkalg <= kPGPPublicKeyAlgorithm_Last) {
(void)PGPGetKeyByKeyID( s->keySet, &keyid,
pkalg, &decKey);
}
if( IsNull( decKey ) )
break;
if( IsPGPError( err = pgpGetKeyRingSet( decKey, FALSE,
&ringSet ) ) )
goto error;
/*
* Use lower-level function to look up proper subkey.
* If key has more than one subkey then ringSecSecKey won't
* choose the right one if we give it a top level key.
*/
ringKey = ringKeyById8 (ringSet, (PGPByte)pkalg,
pgpGetKeyBytes (&keyid));
if( IsNull( ringKey ) )
break;
seckey = ringSecSecKey( ringSet, ringKey,
PGP_PKUSE_ENCRYPT );
/* See if have a good decryption key */
if (seckey && !seckey->decrypt) {
/* A matching secret key which can't decrypt? */
pgpSecKeyDestroy (seckey);
seckey = NULL;
}
if( IsNull( seckey ) )
break;
/* Try to unlock decryption key with passphrase */
err = pgpSecKeyUnlock (seckey, s->env,
(char *)s->passPhrase, s->passLength,
s->hashedPhrase );
if (err <= 0) {
/* Pass phrase failed to unlock. Try next ESK. */
pgpSecKeyDestroy (seckey);
seckey = NULL;
if( firstpass ) {
/* Accumulate decryption keys into decKeySet */
if( IsPGPError( err = PGPNewSingletonKeySet(
decKey, &decKeySet1 ) ) )
goto error;
if( IsPGPError( err = PGPAddKeys(decKeySet1,
decKeySet ) ) )
goto error;
PGPFreeKeySet( decKeySet1 );
decKeySet1 = NULL;
}
break;
}
/* Try decrypting the ESK */
err = pgpEskPKdecrypt (esk, s->env, seckey, key);
*keylen = err;
pgpSecKeyDestroy (seckey);
seckey = NULL;
if (err <= 0) {
/* Failed to decrypt, indicates corrupt ESK */
if (err != kPGPError_CAPIUnsupportedKey)
err = kPGPError_CorruptSessionKey;
goto error;
}
}
/* Now try the decrypted ESK against the rest of the message */
/* (save cipheralgorithm, first byte of key buffer) */
cipheralg = (PGPCipherAlgorithm)key[0];
err = tryKey (tryarg, key, *keylen);
if (err) {
/* Failure, indicates corrupt ESK */
err = kPGPError_CorruptSessionKey;
goto error;
}
/* Else it worked OK */
if( IsPGPError( err = pgpEventDecryption( s->context,
&s->newOptionList, s->func,
s->userValue, cipheralg,
key, *keylen) ) )
goto error;
pgpCleanupOptionList( &s->newOptionList );
success = 1;
break;
}
default:
/* Unknown ESK type */
pgpAssert (0);
break;
}
}
if( !success ) {
/* Get new passphrase from user */
if( IsNull( s->func ) ) {
/* If no callback, just skip undecryptable messages */
err = PGPANN_PARSER_EATIT;
goto error;
}
if( firstpass ) {
firstpass = FALSE;
/* Remove any irrelevant subkeys from key we add */
if( IsPGPError( err = sRemoveUnlistedSubkeys( decKeySet,
keyIDArray,
keyIDCount ) ) )
goto error;
}
if( IsPGPError( err = pgpEventPassphrase( s->context,
&s->newOptionList, s->func,
s->userValue,
(PGPBoolean)(passPhraseCount>0),
decKeySet ) ) )
goto error;
pgpBurnDecodePassphrase( s );
err = pgpSetupDecodePassphrase( s->context,
s->newOptionList, &s->passPhrase, &s->passLength,
&s->hashedPhrase, &s->passPhraseIsSessionKey );
pgpCleanupOptionList( &s->newOptionList );
if( IsPGPError( err ) )
goto error;
/* If he specified no passphrase, we will eat the message */
if( IsNull( s->passPhrase ) ) {
err = PGPANN_PARSER_EATIT;
goto error;
}
}
}
err = kPGPError_NoErr;
error:
if( IsntNull( decKeySet ) ) {
PGPFreeKeySet( decKeySet );
decKeySet = NULL;
}
if( IsntNull( decKeySet1 ) ) {
PGPFreeKeySet( decKeySet1 );
decKeySet1 = NULL;
}
if( IsntNull( seckey ) ) {
pgpSecKeyDestroy( seckey );
seckey = NULL;
}
if( IsntNull( keyIDArray ) ) {
pgpContextMemFree( s->context, keyIDArray );
keyIDArray = NULL;
}
return err;
#endif /* PGP_DECRYPT_DISABLE */ /* ] */
}
/************************** Main decode function ****************************/
static const PGPOptionType decodeOptionSet[] = {
kPGPOptionType_InputFileRef,
kPGPOptionType_InputBuffer,
kPGPOptionType_OutputFileRef,
kPGPOptionType_OutputBuffer,
kPGPOptionType_OutputAllocatedBuffer,
kPGPOptionType_AppendOutput,
kPGPOptionType_DiscardOutput,
kPGPOptionType_LocalEncoding,
kPGPOptionType_Passphrase,
kPGPOptionType_Passkey,
kPGPOptionType_SessionKey,
kPGPOptionType_DetachedSignature,
kPGPOptionType_FailBelowValidity,
kPGPOptionType_WarnBelowValidity,
kPGPOptionType_OutputLineEndType,
kPGPOptionType_EventHandler,
kPGPOptionType_SendNullEvents,
kPGPOptionType_ImportKeysTo,
kPGPOptionType_SendEventIfKeyFound,
kPGPOptionType_DecodeOnlyOne,
kPGPOptionType_PassThroughIfUnrecognized,
kPGPOptionType_PassThroughClearSigned,
kPGPOptionType_PassThroughKeys,
kPGPOptionType_KeySetRef,
kPGPOptionType_RecursivelyDecode,
kPGPOptionType_InputFormat,
kPGPOptionType_X509Encoding /* allow calling from pgpimportkeyset */
};
/* Main entry point for this module */
PGPError
pgpDecodeInternal(
PGPContextRef context,
PGPOptionListRef optionList
)
{
PGPDecodeJob jobState, /* State in a struct */
*s=&jobState; /* Use s-> to access all state */
PGPFileDataType inFileDataType; /* Unused */
/* Initialize pointers to NULL for easier error cleanup */
pgpClearMemory( s, sizeof( *s ) );
s->context = context;
s->optionList = optionList;
s->tail = &s->head;
s->analyzeState = kAnalyzeWaiting;
if (IsPGPError( s->err = pgpCheckOptionsInSet( optionList,
decodeOptionSet, elemsof( decodeOptionSet ) ) ) )
return s->err;
/* Get copies of info from context */
s->env = pgpContextGetEnvironment( s->context );
s->rng = pgpContextGetX9_17RandomContext ( s->context );
/* Setup the UI callback functions & args */
s->ui.message = pgpDecodeShowMessage;
s->ui.doCommit = pgpDecodeDoCommit;
s->ui.newOutput = pgpDecodeSetupNewOutput;
s->ui.needInput = pgpDecodeFindAltInput;
s->ui.sigVerify = pgpDecodeVerifySig;
s->ui.eskDecrypt = pgpDecodeDecryptESK;
s->ui.annotate = pgpDecodeHandleAnnotation;
/* Set up callback pointers and data */
if( IsPGPError( s->err = pgpSetupCallback( s->optionList,
&s->func, &s->userValue, &s->fNullEvents ) ) )
goto error;
s->err = pgpEventInitial( s->context, &s->newOptionList,
s->func, s->userValue );
pgpCleanupOptionList( &s->newOptionList );
if( IsPGPError( s->err ) )
goto error;
/* Get keyset, passphrase data from user */
if( IsPGPError( s->err = pgpSetupKeySet( s->optionList,
&s->keySet ) ) )
goto error;
if( IsPGPError( s->err = pgpSetupDecodePassphrase( s->context,
s->optionList, &s->passPhrase, &s->passLength,
&s->hashedPhrase, &s->passPhraseIsSessionKey ) ) )
goto error;
/* Check input format and handle X.509 related formats */
if( IsPGPError( s->err = pgpFindOptionArgs( s->optionList,
kPGPOptionType_InputFormat, FALSE,
"%d", &s->inputFormat ) ) )
goto error;
if( s->inputFormat >= kPGPInputFormat_X509DataInPKCS7 ) {
/* Handle input X.509 data */
s->err = sDecodeInputX509 (s);
goto error;
}
/* Set up input file or buffer */
if( IsPGPError( s->err = pgpSetupInput( s->context, s->optionList,
NULL, NULL, FALSE, FALSE, &s->inFileRef, &s->pfrin,
&inFileDataType, &s->inBufPtr, &s->inBufLength ) ) )
goto error;
/* Parse output information if any */
if( IsPGPError( s->err = pgpSetupOutput( s->optionList,
s->env, &s->outFileRef,
&s->outBufPtr, &s->outBufPtrPtr,
&s->outBufMaxLength, &s->outBufUsedLength,
&s->outDiscard, &s->localEncodeFlags,
&s->lineEnd, &s->fAppendOutput ) ) )
goto error;
/* If he set up output already, keep it throughout. Otherwise we need
* to see a callback function. */
s->fixedOutput = IsntNull( s->outFileRef ) || IsntNull( s->outBufPtr ) ||
IsntNull( s->outBufPtrPtr ) || s->outDiscard;
if( !s->fixedOutput && IsNull( s->func ) ) {
pgpDebugMsg( "Error: no output options" );
s->err = kPGPError_BadParams;
goto error;
}
/* Set up pipeline */
s->tail = pgpDecryptPipelineCreate ( context,
&s->head, s->env, NULL, &s->ui, s);
/* Handle clearsign and key passthroughs (nonpgp is in NewOutput) */
if( IsPGPError( s->err = pgpSetupPassThrough( s->context, s->optionList,
s->head,
&s->passThroughFifo,
&s->recurse ) ) )
goto error;
/* Now pump the data through the pipes */
if( s->inFileRef ) {
/* File input */
if( IsntNull( s->func ) && s->fNullEvents ) {
pgpFileReadSetCallBack( s->pfrin, decodeLocalCallBack, s );
}
s->err = pgpFileReadPump( s->pfrin, s->head );
pgpFileReadDestroy( s->pfrin );
s->pfrin = NULL;
if( IsPGPError( s->err ) )
goto error;
s->head->sizeAdvise( s->head, 0 );
} else {
/* Buffer input */
if( IsntNull( s->func ) && s->fNullEvents ) {
s->err = pgpPumpMem( s->head, s->inBufPtr, s->inBufLength,
decodeLocalCallBack, s );
} else {
s->err = pgpPumpMem( s->head, s->inBufPtr, s->inBufLength,
NULL, NULL );
}
if( IsPGPError( s->err ) )
goto error;
}
/* Clean up if we had diverted the output in the last section */
if( s->fPrevOutput ) {
(*s->prevOutput)->teardown( *s->prevOutput );
sRestoreOutputState( s, s->prevOutput );
}
/* Get output buffer bytes-used info if appropriate */
if( s->outPipe ) {
if( IsntNull( s->outBufPtrPtr ) ) {
/* Dynamically allocated buffer - tell user size & position */
if( IsPGPError( s->err = pgpGetVariableMemOutput( s->outPipe,
s->outBufMaxLength, s->outBufPtrPtr,
s->outBufUsedLength ) ) )
goto error;
} else {
/* Fixed size buffer - tell user actual size used */
pgpAssert( IsntNull( s->outBufPtr ) );
if( IsPGPError( s->err = pgpGetMemOutput( s->outPipe,
s->outBufMaxLength, s->outBufUsedLength ) ) )
goto error;
}
s->outPipe = NULL;
}
/* Now we can tear down the pipeline */
s->head->teardown( s->head );
s->head = NULL;
if( IsntNull( s->pfout ) ) {
pgpFileClose( s->pfout );
s->pfout = NULL;
}
/* Done, clean up and return */
s->err = kPGPError_NoErr;
error:
if( IsntNull( s->head ) ) {
s->head->teardown( s->head );
s->head = NULL;
}
if( IsntNull( s->pfrin ) ) {
pgpFileReadDestroy( s->pfrin );
s->pfrin = NULL;
}
if( IsntNull( s->pfout ) ) {
pgpFileClose( s->pfout );
s->pfout = NULL;
}
if( IsntNull( s->outFileRef ) ) {
PFLFreeFileSpec( s->outFileRef );
s->outFileRef = NULL;
}
if( IsntNull( s->passThroughFifo ) ) {
pgpFifoDestroy( &pgpByteFifoDesc, s->passThroughFifo );
s->passThroughFifo = NULL;
}
/* Burn passphrase from job structure, if any */
pgpBurnDecodePassphrase( s );
/* Interruption erro
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -