📄 pgpdecode.c
字号:
/* Try decrypting the ESK */
err = pgpEskPKdecrypt (esk, decKey, s->passPhrase,
s->passLength, s->hashedPhrase,
s->cacheTimeOut, s->cacheGlobal,
&key );
if( err == kPGPError_BadPassphrase ||
pgpIsKeyRelatedError( err ) )
{
/* Pass phrase failed to unlock. Try next ESK. */
if( firstpass ) {
/* Accumulate decryption keys into decKeySet */
if( IsPGPError( err = PGPAddKey(decKey,decKeySet)))
goto error;
}
break;
}
if (err <= 0) {
/* Key was on token before
but now there some problem with the token */
if( bOnToken && err == kPGPError_KeyUnusableForEncryption )
break;
/* Failed to decrypt, indicates corrupt ESK */
if (err != kPGPError_CAPIUnsupportedKey)
err = kPGPError_CorruptSessionKey;
goto error;
}
keylen = err;
}
/* 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( IsntNull( key ) )
{
PGPFreeData( key );
key = NULL;
}
}
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;
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->cacheTimeOut, &s->cacheGlobal,
&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( keyIDArray ) ) {
PGPFreeData( keyIDArray );
keyIDArray = NULL;
}
if( IsntNull( key ) ) {
PGPFreeData( key );
key = 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_CachePassphrase,
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_KeyDBRef,
kPGPOptionType_RecursivelyDecode,
kPGPOptionType_InputFormat,
kPGPOptionType_X509Encoding, /* allow calling from pgpimportkeydb */
kPGPOptionType_DataIsASCII
};
/* 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 */
PGPBoolean bLargeFile;
PGPError err2 = kPGPError_NoErr;
/* 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 keydb, passphrase data from user */
if( IsPGPError( s->err = pgpSetupKeyDB( s->optionList,
&s->keyDB ) ) )
goto error;
if( IsPGPError( s->err = pgpSetupDecodePassphrase( s->context,
s->optionList, &s->passPhrase, &s->passLength,
&s->hashedPhrase, &s->cacheTimeOut, &s->cacheGlobal,
&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, &bLargeFile, &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 ) {
if( IsntNull( *s->prevOutput ) )
(*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 error is used to abort early in the process */
if( s->err == kPGPError_Interrupted )
s->err = kPGPError_NoErr;
/* Notify user via callback of error if requested */
if( IsPGPError( s->err ) && IsntNull( s->func ) ) {
(void)pgpEventError( s->context, &s->newOptionList, s->func,
s->userValue, s->err, NULL );
pgpCleanupOptionList( &s->newOptionList );
}
err2 = pgpEventFinal( s->context, &s->newOptionList, s->func,
s->userValue );
if( IsPGPError( err2 ) ) {
s->err = err2;
}
pgpCleanupOptionList( &s->newOptionList );
return s->err;
}
/************************** X509 decode function ****************************/
static PGPError
sDecodeInputX509(
PGPDecodeJob *s
)
{
PGPKeyDBObjRef signKey;
PGPKeyDBObjRef decryptKey;
PGPBoolean isSigned;
PGPBoolean sigChecked;
PGPBoolean sigVerified;
PGPBoolean fMustFreeBuf;
PGPBoolean fMoreData;
const PGPTime sigCreationTime = 0;
const PGPUInt32 sigExpirationPeriod = 0;
PGPAttributeValue *extraData;
PGPUInt32 extraDataLength;
PGPByte *certSet = NULL;
PGPSize certSetLength;
PGPByte *crlSet = NULL;
PGPSize crlSetLength;
PGPKeyDBRef importKeyDB;
PGPKeyDBRef newKeyDB = NULL;
PGPOption passop;
PGPOptionListRef passphrase = NULL;
PGPByte *inBufPtr;
PGPSize inBufLength;
PGPInputFormat inputFormat;
/* There must be a keydb to import keys to */
if( IsPGPError( s->err = pgpFindOptionArgs( s->optionList,
kPGPOptionType_ImportKeysTo, TRUE,
"%p", &importKeyDB ) ) )
return s->err;
/* Send initial events */
s->err = pgpEventBeginLex( s->context, &s->newOptionList,
s->func, s->userValue, s->sectionNumber,
s->sectOffset );
pgpCleanupOptionList( &s->newOptionList );
if( IsPGPError( s->err ) )
return s->err;
s->analyzeType = kPGPAnalyze_X509Certificate;
s->err = pgpEventAnalyze( s->context, &s->newOptionList,
s->func, s->userValue, s->analyzeType );
pgpCleanupOptionList( &s->newOptionList );
if( IsPGPError( s->err ) )
return s->err;
/* Ge
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -