📄 pgpencode.c
字号:
PGPSigSpec **sigspec,
PGPKeyRef *signkeyref
)
{
PGPOption op; /* Selected option from list */
PGPError err; /* Error return code */
PGPKey *signKey; /* PGPKey struct for signing key */
PGPKeySet *signKeySet; /* PGPKeySet holding signKey */
PGPSecKey *seckey; /* Internal struct for signKey */
RingObject *ringKey; /* Keyring obj for signing key */
RingSet const *ringSet; /* Lowlevel keyring set for enc key */
PGPByte signMode; /* Text vs binary mode for sig */
PGPByte *passPhrase; /* Signing key pass phrase */
PGPSize passLength; /* Length of passPhrase */
PGPBoolean hashedPhrase = FALSE; /* True if passkey given */
PGPValidity failValidity, /* Fail on keys less valid */
warnValidity; /* Warn on keys less valid */
PGPInt32 rslt; /* Success code on unlock */
(void)func;
(void)userValue;
/* Init return pointers */
pgpa( pgpaAddrValid( sigspec, PGPSigSpec * ) );
pgpa( pgpaAddrValid( signkeyref, PGPKeyRef ) );
*sigspec = NULL;
*signkeyref = kInvalidPGPKeyRef;
seckey = NULL;
signKeySet = NULL;
/* See if signature requested. Only one signing key allowed. */
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_SignWithKey, &op ) ) )
goto error;
if( IsOp( op ) ) {
/* Get signing key and data */
if( IsPGPError( err = pgpOptionPtr( &op, (void **)&signKey ) ) )
goto error;
pgpa(pgpaPGPKeyValid(signKey));
if( !pgpKeyIsValid(signKey) ) {
pgpDebugMsg( "Error: invalid SignWithKey keyref" );
err = kPGPError_BadParams;
goto error;
}
*signkeyref = signKey;
if( IsPGPError( err = pgpGetKeyRingObject( signKey, FALSE, &ringKey )))
goto error;
if( IsPGPError( err = pgpGetKeyRingSet( signKey, FALSE, &ringSet ) ) )
goto error;
if( IsPGPError( err = pgpGetMinValidity( optionList,
&failValidity, &warnValidity ) ) )
goto error;
if( IsPGPError( err = pgpCheckKeyValidity( context, optionList,
signKey, ringSet, failValidity, warnValidity,
NULL, NULL ) ) )
goto error;
seckey = ringSecSecKey( ringSet, ringKey, PGP_PKUSE_SIGN );
if( IsNull( seckey ) ) {
/* err = kPGPError_KeyUnusableForSignature; */
err = ringSetError( ringSet ) -> error;
goto error;
}
/* Try to unlock secret key */
/* First see if a passphrase is needed at all for signing key */
rslt = pgpSecKeyUnlock( seckey, env, NULL, 0, FALSE );
if ( rslt <= 0 ) {
/* Failed, must try passphrase */
if( IsPGPError( err = pgpFindOptionArgs( op.subOptions,
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( IsNull( passPhrase ) ) {
err = kPGPError_MissingPassphrase;
goto error;
}
}
rslt = pgpSecKeyUnlock( seckey, env, (char *) passPhrase,
passLength, hashedPhrase );
if( rslt <= 0 ) {
err = kPGPError_BadPassphrase;
goto error;
}
}
/* At this point we have unlocked successfully */
/* 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, seckey, signMode );
}
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);
if( IsntNull( seckey ) )
pgpSecKeyDestroy (seckey);
if( IsntNull( signKeySet ) )
PGPFreeKeySet( signKeySet );
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 */
PGPPubKey *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 ... */
PGPKeyRef enckeyref; /* One of the encryption keys */
PGPKeyRef signkeyref; /* One of the signature keys */
};
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_EncryptToKey,
kPGPOptionType_EncryptToKeySet,
kPGPOptionType_EncryptToUserID,
kPGPOptionType_SignWithKey,
kPGPOptionType_ConventionalEncrypt,
kPGPOptionType_Passphrase,
kPGPOptionType_Passkey,
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_ExportKey,
kPGPOptionType_ExportUserID,
kPGPOptionType_ExportSig
};
/* 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) */
/* 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, &s->enckeyref ) ) )
goto error;
/* 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,
&s->inBufPtr, &s->inBufLength ) ) )
goto error;
/* Set up for any signing operation requested */
if( IsPGPError( s->err = pgpSetupSigning( s->context, s->optionList,
(PGPBoolean) ( IsntNull( s->convkey )
|| IsntNull( s->pubkeys ) ),
s->env, s->func, s->userValue,
(PGPBoolean) (inFileDataType == kPGPFileDataType_Binary),
s->sepsig, &s->sigspec, &s->signkeyref ) ) )
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( s->convkey || s->pubkeys ) {
sessionKey = (PGPByte *)PGPNewSecureData(
PGPGetContextMemoryMgr( context ),
PGP_CIPHER_MAXKEYSIZE, 0 );
if (!sessionKey)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -