📄 pgpencode.c
字号:
kPGPOptionType_Passphrase, FALSE,
"%p%l", &passPhrase, &passLength ) ) )
goto error;
if( IsNull( passPhrase ) ) {
hashedPhrase = TRUE;
if( IsPGPError( err = pgpFindOptionArgs( op.subOptions,
kPGPOptionType_Passkey, FALSE,
"%p%l", &passPhrase, &passLength ) ) )
goto error;
}
if( IsPGPError( err = pgpFindOptionArgs( op.subOptions,
kPGPOptionType_CachePassphrase, FALSE,
"%d%b", &cacheTimeOut, &cacheGlobal ) ) )
goto error;
if( !pgpSecPassphraseOK( signKey, passPhrase, passLength,
hashedPhrase, cacheTimeOut, cacheGlobal ))
{
err = kPGPError_BadPassphrase;
goto error;
}
}
/* See if text or binary mode */
if( knownBinaryInput )
{
signMode = PGP_SIGTYPE_BINARY;
}
else
{
signMode =
( PGPByte ) (pgpenvGetInt( env, PGPENV_TEXTMODE, NULL, NULL) ?
PGP_SIGTYPE_TEXT : PGP_SIGTYPE_BINARY );
}
*sigspec = pgpSigSpecCreate( env, signKey, signMode );
if( needsPassphrase )
pgpSigSpecSetPassphrase( *sigspec, passPhrase, passLength,
hashedPhrase );
}
if( sepsig && IsNull( *sigspec ) ) {
/* Error, detached sig requested without signing! */
pgpDebugMsg( "Error: detached signature without signing key" );
err = kPGPError_BadParams;
goto error;
}
if( sepsig && fHaveEncryption ) {
/* Error, can't do detached sig if encrypting */
pgpDebugMsg( "Error: detached signature with encryption" );
err = kPGPError_BadParams;
goto error;
}
return kPGPError_NoErr;
error:
if( IsntNull( *sigspec ) )
pgpSigSpecDestroy (*sigspec);
return err;
}
/************************** Main encode function ****************************/
/* All state information for pgpEncode is kept in a struct like this */
struct pgpEncodeJobState_
{
PGPContextRef context; /* Context pointer */
PGPOptionListRef optionList; /* List of all our options */
PGPOptionListRef newOptionList; /* Options changed by callback */
PGPError err; /* Error */
PGPPipeline *head, **tail; /* Low level pipeline */
PGPConvKey *convkey; /* Conventional encryption params */
PGPSigSpec *sigspec; /* Message signing params */
PGPKeySetRef pubkeys; /* Message encryption keys */
PgpLiteralParams literal; /* Filename, type info */
PGPBoolean sepsig; /* Create detached signature */
PFLConstFileSpecRef inFileRef; /* Input filename handle */
PGPFileRead *pfrin; /* Input file reading structure */
PGPByte *inBufPtr; /* Input buffer pointer */
PGPSize inBufLength; /* Size of input buffer */
PFLConstFileSpecRef outFileRef; /* Output filename handle */
PGPFile *pfout; /* Output file writing structure */
PGPByte *outBufPtr; /* Output buffer pointer */
PGPByte **outBufPtrPtr; /* Dynamically allocated buf ptr */
PGPSize outBufMaxLength; /* Allocated size of outBufPtr */
PGPSize *outBufUsedLength; /* Amount output to outBufPtr */
PGPPipeline *outPipe; /* Output-buffer pipeline module */
PGPEnv *env; /* Environment for low-level fns */
PGPRandomContext *rng; /* Random state */
PGPOption op; /* Selected option from list */
PGPEventHandlerProcPtr func; /* Pointer to user callback func */
PGPUserValue userValue; /* Arg to callback func */
PGPBoolean fNullEvents; /* True if user wants null events */
PGPOutputFormat outputFormat; /* Format of output data, PGP vs ... */
};
typedef struct pgpEncodeJobState_ pgpEncodeJobState;
static PGPError sPackageOutputX509( pgpEncodeJobState *s );
/* Local callback function */
static PGPError
encodeLocalCallBack (
void *arg,
PGPFileOffset soFar,
PGPFileOffset total
)
{
PGPError err = kPGPError_NoErr;
pgpEncodeJobState *s = ( pgpEncodeJobState * ) arg;
if( IsntNull( s->func ) && s->fNullEvents ) {
err = pgpEventNull( s->context, &s->newOptionList, s->func,
s->userValue, soFar, total );
pgpCleanupOptionList( &s->newOptionList );
}
return err;
}
static PGPError
encodePKEncryptCallBack (
void *arg,
int code
)
{
PGPError err = kPGPError_NoErr;
pgpEncodeJobState *s = ( pgpEncodeJobState * ) arg;
(void) code;
if( IsntNull( s->func ) && s->fNullEvents ) {
err = pgpEventNull( s->context, &s->newOptionList, s->func,
s->userValue, 0, 1 );
pgpCleanupOptionList( &s->newOptionList );
}
return err;
}
static const PGPOptionType encodeOptionSet[] = {
kPGPOptionType_InputFileRef,
kPGPOptionType_InputBuffer,
kPGPOptionType_InputFileName,
kPGPOptionType_OutputFileRef,
kPGPOptionType_OutputBuffer,
kPGPOptionType_OutputAllocatedBuffer,
kPGPOptionType_AppendOutput,
kPGPOptionType_DiscardOutput,
kPGPOptionType_LocalEncoding,
kPGPOptionType_RawPGPInput,
kPGPOptionType_EncryptToKeyDBObj,
kPGPOptionType_EncryptToKeySet,
kPGPOptionType_SignWithKey,
kPGPOptionType_ConventionalEncrypt,
kPGPOptionType_Passphrase,
kPGPOptionType_Passkey,
kPGPOptionType_CachePassphrase,
kPGPOptionType_DetachedSignature,
kPGPOptionType_CipherAlgorithm,
kPGPOptionType_HashAlgorithm,
kPGPOptionType_FailBelowValidity,
kPGPOptionType_WarnBelowValidity,
kPGPOptionType_PGPMIMEEncoding,
kPGPOptionType_OutputLineEndType,
kPGPOptionType_EventHandler,
kPGPOptionType_SendNullEvents,
kPGPOptionType_AskUserForEntropy,
kPGPOptionType_ArmorOutput,
kPGPOptionType_DataIsASCII,
kPGPOptionType_ClearSign,
kPGPOptionType_ForYourEyesOnly,
kPGPOptionType_CommentString,
kPGPOptionType_Compression,
kPGPOptionType_VersionString,
kPGPOptionType_OmitMIMEVersion,
kPGPOptionType_PreferredAlgorithms,
kPGPOptionType_OutputFormat,
/* really only for PGPExport, but that routine calls this */
kPGPOptionType_ExportPrivateKeys,
kPGPOptionType_ExportPrivateSubkeys,
kPGPOptionType_ExportFormat,
kPGPOptionType_ExportKeySet,
kPGPOptionType_ExportKeyDBObj
};
/* Main entry point for this module */
PGPError
pgpEncodeInternal(
PGPContextRef context,
PGPOptionListRef optionList
)
{
pgpEncodeJobState jobState, /* State in a struct */
*s=&jobState; /* Use s-> to access all state */
PGPByte *charMap; /* Charmap for armor output */
PGPLineEndType lineEnd; /* Line endings for armor output */
PGPBoolean fEncrypt; /* Encryption */
PGPBoolean fSign; /* Signature */
PGPUInt32 fRawPGPInput; /* Don't put on literal packet */
PGPUInt32 fAppendOutput; /* Append to existing outfile */
PGPOption op; /* Selected option from list */
PGPByte *sessionKey = NULL; /* session key for encryption */
PGPSize sessionKeyLength;
PGPFileDataType inFileDataType; /* Input file data trype (ascii or binary) */
PGPBoolean bLargeFile;
/* Initialize pointers to NULL for easier error cleanup */
pgpClearMemory( s, sizeof( *s ) );
s->context = context;
s->optionList = optionList;
s->tail = &s->head;
if (IsPGPError( s->err = pgpCheckOptionsInSet( optionList,
encodeOptionSet, elemsof( encodeOptionSet ) ) ) )
return s->err;
/* Get copies of info from context */
s->rng = pgpContextGetX9_17RandomContext ( s->context );
/* Get a copy of the env to work with so our changes aren't permanent */
if( IsPGPError( pgpenvCopy( pgpContextGetEnvironment( s->context ),
&s->env ) ) )
goto error;
/* Set up PGPEnv structure for library internals */
if( IsPGPError( s->err = pgpMakeEnvFromOptionList( s->optionList,
s->env ) ) )
goto error;
/* 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;
/* Set up for conventional encryption if requested */
if( IsPGPError( s->err = pgpSetupConventionalEncryption( s->context,
s->optionList, s->func, s->userValue,
&s->convkey ) ) )
goto error;
/* Set up for public key encryption if requested */
if( IsPGPError( s->err = pgpSetupPublicKeyEncryption( s->context,
s->optionList,
s->env, &s->pubkeys ) ) )
goto error;
fEncrypt = (PGPBoolean) (IsntNull( s->pubkeys ) || IsntNull( s->convkey ));
/* Determine if a detached signature has been requested */
if( IsPGPError( s->err = pgpSearchOptionSingle( s->optionList,
kPGPOptionType_DetachedSignature, &op ) ) )
goto error;
s->sepsig = IsOp( op );
/* Check output format and handle X.509 related formats */
if( IsPGPError( s->err = pgpFindOptionArgs( s->optionList,
kPGPOptionType_OutputFormat, FALSE,
"%d", &s->outputFormat ) ) )
goto error;
if( s->outputFormat >= kPGPOutputFormat_X509CertReqInPKCS7 ) {
/* Handle output X.509 data */
s->err = sPackageOutputX509 (s);
goto error;
}
/* Set up input filenames and open file if any */
if( IsPGPError( s->err = pgpSetupInput( s->context, s->optionList,
&s->literal, s->rng, TRUE, s->sepsig,
&s->inFileRef, &s->pfrin, &inFileDataType, &bLargeFile,
&s->inBufPtr, &s->inBufLength ) ) )
goto error;
/* Set up for any signing operation requested */
if( IsPGPError( s->err = pgpSetupSigning( s->context, s->optionList,
fEncrypt, s->env, s->func, s->userValue,
(PGPBoolean) (inFileDataType == kPGPFileDataType_Binary),
s->sepsig, &s->sigspec ) ) )
goto error;
/* Set up main processing pipeline (will set up output afterwards) */
if( IsPGPError( s->err = pgpFindOptionArgs( s->optionList,
kPGPOptionType_RawPGPInput, FALSE,
"%d", &fRawPGPInput ) ) )
goto error;
/* Allocate space for session key if needed */
if( fEncrypt ) {
sessionKey = (PGPByte *)PGPNewSecureData(
PGPPeekContextMemoryMgr( context ),
PGP_CIPHER_MAXKEYSIZE+1, 0 );
if (!sessionKey)
goto error;
}
s->tail = pgpEncryptPipelineCreate( context, &s->head, s->env, NULL,
s->rng, s->convkey, s->pubkeys, s->sigspec,
(fRawPGPInput?NULL:&s->literal), s->sepsig, sessionKey,
(PGPBoolean) (inFileDataType == kPGPFileDataType_Binary),
bLargeFile, encodePKEncryptCallBack, s, &sessionKeyLength,
&s->err );
if( IsPGPError( s->err ) )
goto error;
if( IsntNull( sessionKey ) ) {
s->err = pgpEventEncryption( s->context, &s->newOptionList,
s->func, s->userValue,
(PGPCipherAlgorithm)sessionKey[0],
sessionKey, sessionKeyLength );
pgpCleanupOptionList( &s->newOptionList );
PGPFreeData( sessionKey ); /* wipes it automatically */
sessionKey = NULL;
}
/* Add a text conversion if needed for output */
if( pgpenvGetInt( s->env, PGPENV_ARMOR, NULL, NULL ) ) {
/* Ascii armoring output */
/* Convert to local line endings if appropriate */
charMap = (PGPByte *)pgpenvGetPointer( s->env, PGPENV_CHARMAPTOLATIN1,
NULL );
lineEnd = pgpGetDefaultLineEndType ();
if( IsPGPError( s->err = pgpSearchOptionSingle( optionList,
kPGPOptionType_OutputLineEndType, &s->op ) ) )
goto error;
if( IsOp( s->op ) ) {
PGPUInt32 uintLineEnd;
if( IsPGPError( s->err = pgpOptionUInt( &s->op, &uintLineEnd ) ) )
goto error;
lineEnd = (PGPLineEndType)uintLineEnd;
}
s->tail = pgpTextFiltCreate( s->context, s->tail, charMap,0,lineEnd );
}
/*
* Check for sufficient entropy. Error if not enough, unless
* AskUserForEntropy option is specified, in which case we give an event.
*/
if( IsntNull( s->sigspec ) || fEncrypt ) {
if( !PGPGlobalRandomPoolHasMinimumEntropy() ) {
PGPUInt32 fEntropyEvent;
if( IsPGPError( s->err = pgpFindOptionArgs( s->optionList,
kPGPOptionType_AskUserForEntropy,
FALSE, "%d", &fEntropyEvent ) ) )
goto error;
if( !fEntropyEvent ) {
s->err = kPGPError_OutOfEntropy;
goto error;
}
while( !PGPGlobalRandomPoolHasMinimumEntropy() ) {
PGPUInt32 entropy_needed;
entropy_needed = PGPGlobalRandomPoolGetMinimumEntropy() -
PGPGlobalRandomPoolGetEntropy();
s->err = pgpEventEntropy( s->context, &s->newOptionList,
s->func, s->userValue, entropy_needed );
pgpCleanupOptionList( &s->newOptionList );
if( IsPGPError( s->err ) )
goto error;
}
}
}
/* Set up output pipeline */
fSign = (PGPBoolean) IsntNull( s->sigspec );
if( IsPGPError( s->err = pgpFindOptionArgs( s->optionList,
kPGPOptionType_AppendOutput, FALSE,
"%d", &fAppendOutput ) ) )
goto error;
if( IsPGPError( s->err = pgpSetupOutputPipeline( s->context, s->optionList,
s->env, fEncrypt, fSign, s->sepsig,
(PGPBoolean)fAppendOutput, FALSE,
&s->tail, &s->outFileRef, &s->pfout,
&s->outBufPtr, &s->outBufPtrPtr,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -