📄 pgpdecode.c
字号:
/*____________________________________________________________________________
pgpDecode.c
High level decode functionality
Copyright (C) 1997 Network Associates Inc. and affiliated companies.
All rights reserved.
$Id: pgpDecode.c,v 1.119 1999/05/07 23:47:44 hal Exp $
____________________________________________________________________________*/
#include "pgpConfig.h" /* or pgpConfig.h in the CDK */
#include <string.h>
/* Public headers */
#include "pgpPubTypes.h"
#include "pgpContext.h"
#include "pgpEncode.h"
#include "pgpErrors.h"
#include "pgpKeys.h"
#include "pgpMem.h"
/* Private headers */
#include "pgpSDKBuildFlags.h"
#include "pgpDebug.h"
#include "pgpEncodePriv.h"
#include "pgpAnnotate.h"
#include "pgpArmor.h"
#include "pgpBufMod.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpConvKey.h"
#include "pgpDecPipe.h"
#include "pgpDevNull.h"
#include "pgpEnv.h"
#include "pgpESK.h"
#include "pgpEventPriv.h"
#include "pgpFIFO.h"
#include "pgpFile.h"
#include "pgpFileMod.h"
#include "pgpFileRef.h"
#include "pgpFileSpec.h"
#include "pgpFileType.h"
#include "pgpHash.h"
#include "pgpKeyDB.h"
#include "pgpKeyIDPriv.h"
#include "pgpKDBInt.h"
#include "pgpMem.h"
#include "pgpMemMod.h"
#include "pgpOptionList.h"
#include "pgpPipeline.h"
#include "pgpPubKey.h"
#include "pgpRandomPoolPriv.h"
#include "pgpRngPub.h"
#include "pgpSig.h"
#include "pgpTextFilt.h"
#include "pgpTrstPkt.h"
#include "pgpUI.h"
#include "pgpVMemMod.h"
#include "pgpX509Priv.h"
#define elemsof(x) ((unsigned)(sizeof(x)/sizeof(*x)))
/************************** Types and Constants ***************************/
/* All state information for pgpDecode is kept in a struct like this */
struct PGPDecodeJob_
{
PGPContextRef context; /* Context pointer */
PGPOptionListRef optionList; /* List of all our options */
PGPOptionListRef newOptionList; /* New options from user callback */
PGPUICb ui; /* Callback functions */
PGPError err; /* Error */
PGPEnv *env; /* Environment for low-level fns */
PGPRandomContext *rng; /* Random state */
PGPOption op; /* Selected option from list */
PGPBoolean fUsedDetachedSigOp; /* Have used detachedsig op */
PGPPipeline *head, **tail; /* Low level pipeline */
PGPPipeline *outPipe; /* Dynamic memory output module */
PGPFile *pfout; /* Output file handle */
PGPPipeline *outKey; /* Key data output module */
PGPPipeline *prevStarOutput;/* Deferred tail of output pipeline */
PGPPipeline **prevOutput; /* Address of pointer to pipe tail */
PGPPipeline *prevOutPipe; /* Dynamic memory mod for prevoutput */
PGPFile *prevPFout; /* Output file handle for prevoutput */
PGPBoolean fPrevOutput; /* Have set prevOutput */
PFLConstFileSpecRef inFileRef; /* Input filename handle */
PGPFileRead *pfrin; /* Input file reading structure */
PGPByte *inBufPtr; /* Input buffer pointer */
PGPSize inBufLength; /* Size of input buffer */
PFLFileSpecRef outFileRef; /* Output filename handle */
PGPByte *outBufPtr; /* Output buffer pointer */
PGPByte **outBufPtrPtr; /* Dynamically allocated buf ptr */
PGPSize outBufMaxLength; /* Allocated size of outBufPtr */
PGPSize *outBufUsedLength; /* Amount output to outBufPtr */
PGPBoolean outDiscard; /* True if want to discard output */
PGPBoolean fixedOutput; /* Use same output throughout */
PGPBoolean fAppendOutput; /* Append output to buffer or file */
PGPEventHandlerProcPtr func; /* Pointer to user callback func */
PGPUserValue userValue; /* Arg to callback func */
PGPBoolean fNullEvents; /* True if user wants null events */
PGPUInt32 localEncodeFlags; /* Macbinary etc. for output */
PGPLineEndType lineEnd; /* Line endings for text output */
PGPKeySetRef keySet; /* Keyset to check sigs, decrypt */
PGPByte *passPhrase; /* Pass phrase from user */
PGPSize passLength; /* Length of passPhrase */
PGPBoolean hashedPhrase; /* True if given passkey */
PGPBoolean passPhraseIsSessionKey; /* in passphrase buffer */
PGPUInt32 sectionNumber; /* Number of section we are on */
PGPAnalyzeType analyzeType; /* Type of section we found */
PGPInt32 analyzeState; /* kAnalyze status */
PGPInt32 scopeLevel; /* Nesting scope */
PGPInt32 scopeSegment; /* scopeLevel at start of segment */
PGPSize sectOffset; /* Offset in input to start of sect */
PGPBoolean passThrough; /* True if outputing without change */
PGPFifoContext *passThroughFifo; /* Accumulate some passthrough data*/
PGPByte literalType; /* type of literal packet */
PGPBoolean recurse; /* Recursing on decode */
PGPInputFormat inputFormat; /* Format of input data, PGP vs ... */
};
typedef struct PGPDecodeJob_ PGPDecodeJob;
/* analyzeState values */
enum {
kAnalyzeWaiting = 1,
kAnalyzeGotType,
kAnalyzeSegmentEndWait
};
static PGPError sDecodeInputX509( PGPDecodeJob *s );
/*********** Functions to set up data structures for pipeline *************/
/* Parse output specifications */
/*
* Note that any outFileRef returned will be a fresh copy, which the
* caller is responsible for freeing after use.
*/
static PGPError
pgpSetupOutput(
PGPOptionListRef optionList,
PGPEnv *env,
PFLFileSpecRef *outFileRef, /* Output params */
PGPByte **outBufPtr,
PGPByte ***outBufPtrPtr,
PGPSize *outBufLength,
PGPSize **outBufUsed,
PGPBoolean *outDiscard,
PGPUInt32 *localEncodeFlags,
PGPLineEndType *lineEnd,
PGPBoolean *pAppendOutput
)
{
PGPOption op; /* Selected option from list */
PGPError err; /* Error return code */
PGPUInt32 localEncode; /* Enum for macbinary, etc. */
PFLConstFileSpecRef lOutFileRef; /* Local copy of outfileref */
PGPFileSpecRef lOutFileRefPGP;/* Another local copy of outfileref */
PGPUInt32 fDiscard; /* Discard output option flag */
PGPUInt32 fAppendOutput; /* Append to output flag */
(void) env;
/* Init return data to default states */
pgpa( pgpaAddrValid( outFileRef, PFLConstFileSpecRef ) );
pgpa( pgpaAddrValid( outBufPtr, PGPByte * ) );
pgpa( pgpaAddrValid( outBufLength, PGPSize ) );
pgpa( pgpaAddrValid( outBufUsed, PGPSize * ) );
pgpa( pgpaAddrValid( outDiscard, PGPBoolean ) );
pgpa( pgpaAddrValid( localEncodeFlags, PGPUInt32 ) );
pgpa( pgpaAddrValid( lineEnd, PGPLineEndType ) );
*outFileRef = NULL;
*outBufPtr = NULL;
*outBufLength = 0;
*outBufUsed = NULL;
*outDiscard = FALSE;
*localEncodeFlags = 0;
*lineEnd = pgpGetDefaultLineEndType ();
*pAppendOutput = FALSE;
/* Test for append flag */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_AppendOutput, FALSE,
"%d", &fAppendOutput ) ) )
goto error;
*pAppendOutput = (PGPBoolean)fAppendOutput;
/* See if there is an output file specified */
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_OutputFileRef, &op ) ) )
goto error;
if( IsOp( op ) ) {
/* Have an output file specified */
if( IsPGPError( err = pgpOptionPtr( &op, (void **)&lOutFileRefPGP ) ) )
goto error;
lOutFileRef = (PFLConstFileSpecRef) lOutFileRefPGP;
if( IsPGPError( err = PFLCopyFileSpec( lOutFileRef, outFileRef ) ) )
goto error;
}
/* See if there is an output buffer specified */
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_OutputBuffer, &op ) ) )
goto error;
if( IsOp( op ) ) {
/* Have an output buffer specified */
if( IsntNull( *outFileRef ) ) {
pgpDebugMsg( "Error: multiple output options" );
err = kPGPError_BadParams;
goto error;
}
if( IsPGPError( err = pgpOptionPtrLengthPtr( &op, (void **)outBufPtr,
outBufLength, (void **)outBufUsed ) ) )
goto error;
}
/* Check for variable-sized output buffer specification */
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_OutputAllocatedBuffer, &op ) ) )
goto error;
if( IsOp( op ) ) {
/* Have an output buffer specified */
if( IsntNull( *outFileRef ) || IsntNull( *outBufPtr ) ) {
pgpDebugMsg( "Error: multiple output options" );
err = kPGPError_BadParams;
goto error;
}
if( IsPGPError( err = pgpOptionPtrLengthPtr( &op,
(void **)outBufPtrPtr, outBufLength, (void **)outBufUsed ) ) )
goto error;
}
/* Check for request to discard output (send to devnull module) */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_DiscardOutput, FALSE,
"%d", &fDiscard ) ) )
goto error;
if( fDiscard ) {
/* User wants to go to /dev/null */
if( IsntNull( *outFileRef ) || IsntNull( *outBufPtr ) ||
IsntNull( *outBufPtrPtr ) ) {
pgpDebugMsg( "Error: multiple output options" );
err = kPGPError_BadParams;
goto error;
}
*outDiscard = TRUE;
}
/* Read output local encoding and line endings */
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_LocalEncoding, &op ) ) )
goto error;
if( IsOp( op ) ) {
if( IsPGPError( err = pgpOptionUInt( &op, &localEncode ) ) )
goto error;
*localEncodeFlags = pgpLocalEncodingToFlags( localEncode );
}
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_OutputLineEndType, &op ) ) )
goto error;
if( IsOp( op ) ) {
PGPUInt32 uintLineEnd;
if( IsPGPError( err = pgpOptionUInt( &op, &uintLineEnd ) ) )
goto error;
*lineEnd = (PGPLineEndType) uintLineEnd;
}
return kPGPError_NoErr;
error:
*outFileRef = NULL;
*outBufPtr = NULL;
*outBufPtrPtr = NULL;
*outBufLength = 0;
*outDiscard = FALSE;
*localEncodeFlags = 0;
*lineEnd = pgpGetDefaultLineEndType();
return err;
}
/* Get keyring set from user if specified */
static PGPError
pgpSetupKeySet(
PGPOptionListRef optionList,
PGPKeySetRef *keySet /* Output params */
)
{
PGPOption op; /* Selected option from list */
PGPError err; /* Error return code */
/* Init return data to default states */
pgpa( pgpaAddrValid( keySet, PGPKeySetRef ) );
*keySet = NULL;
/* See if there is a keyset specified */
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_KeySetRef, &op ) ) )
goto error;
if( IsOp( op ) ) {
if( IsPGPError( err = pgpOptionPtr( &op, (void **)keySet ) ) )
goto error;
}
return kPGPError_NoErr;
error:
*keySet = NULL;
return err;
}
/*
* Get passphrase from user. We make a copy of the passphrase because if
* it is specified from a callback, when we free the optionlist it will
* go away.
*/
static PGPError
pgpSetupDecodePassphrase(
PGPContextRef context, /* Input params */
PGPOptionListRef optionList,
PGPByte **passPhrase, /* Output params */
PGPSize *passLength,
PGPBoolean *hashedPhrase,
PGPBoolean *sessionKey
)
{
void *vPassPhrase; /* Pointer to option pphrase */
PGPByte *lPassPhrase; /* Local allocated passphrase */
PGPSize lPassLength; /* Local copy of pphrase length */
PGPError err; /* Error return code */
/* Init return data to default states */
pgpa( pgpaAddrValid( passPhrase, PGPByte * ) );
pgpa( pgpaAddrValid( passLength, PGPSize ) );
pgpa( pgpaAddrValid( passLength, PGPBoolean ) );
*passPhrase = NULL;
*passLength = (PGPSize)0;
*hashedPhrase = FALSE;
*sessionKey = FALSE;
/* See if there is a pass phrase specified */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_Passphrase, FALSE,
"%p%l", &vPassPhrase, &lPassLength ) ) )
goto error;
if( IsNull( vPassPhrase ) ) {
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_Passkey, FALSE,
"%p%l", &vPassPhrase, &lPassLength ) ) )
goto error;
if( IsntNull( vPassPhrase ) )
*hashedPhrase = TRUE;
}
if( IsNull( vPassPhrase ) ) {
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_SessionKey, FALSE,
"%p%l", &vPassPhrase, &lPassLength ) ) )
goto error;
if( IsntNull( vPassPhrase ) )
*sessionKey = TRUE;
}
if( IsntNull( vPassPhrase ) ) {
lPassPhrase = (PGPByte *)
PGPNewSecureData(PGPGetContextMemoryMgr(context), lPassLength, 0);
if( IsNull( lPassPhrase ) ) {
err = kPGPError_OutOfMemory;
goto error;
}
pgpCopyMemory( vPassPhrase, lPassPhrase, lPassLength );
*passPhrase = lPassPhrase;
*passLength = lPassLength;
}
return kPGPError_NoErr;
error:
*passPhrase = NULL;
*passLength = (PGPSize)0;
return err;
}
/*
* Handle options requesting that we pass clearsigned data and/or keys
* through to the output, unchanged. We still do the signature checking
* on signed text, and we still do the key callbacks. This just affects
* what goes into the output.
*/
static PGPError
pgpSetupPassThrough(
PGPContextRef context, /* Input params */
PGPOptionListRef optionList,
PGPPipeline *pipeHead,
PGPFifoContext **fifo, /* Output params */
PGPBoolean *recurse
)
{
PGPUInt32 fPassClear; /* True if passthroughcleartext */
PGPUInt32 fPassKeys; /* True if passthroughkeys */
PGPUInt32 fRecurse; /* True if recursivelydecode */
PGPByte boolFlag = TRUE; /* Flag for turning on modes */
PGPError err; /* Error return code */
/* Init return data to default states */
pgpa( pgpaAddrValid( fifo, PGPByte * ) );
pgpa( pgpaAddrValid( recurse, PGPBoolean ) );
*fifo = NULL;
*recurse = FALSE;
/* Read our passthroughoptions */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_PassThroughClearSigned, FALSE,
"%d", &fPassClear ) ) )
goto error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -