📄 pgpencsubr.c
字号:
/*____________________________________________________________________________
pgpEncSubr.c
Helper subroutines for encode/decode API
Copyright (C) 1997 Network Associates Inc. and affiliated companies.
All rights reserved.
$Id: pgpEncSubr.c,v 1.59 1999/04/23 00:36:44 hal Exp $
____________________________________________________________________________*/
#include "pgpConfig.h" /* or pgpConfig.h in the CDK */
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
/* Public headers */
#include "pgpPubTypes.h"
#include "pgpContext.h"
#include "pgpEncode.h"
#include "pgpErrors.h"
#include "pgpFileRef.h"
#include "pgpKeys.h"
#include "pgpMem.h"
/* Private headers */
#include "pgpDebug.h"
#include "pgpAnnotate.h"
#include "pgpDevNull.h"
#include "pgpEncodePriv.h"
#include "pgpEnv.h"
#include "pgpEventPriv.h"
#include "pgpMemMod.h"
#include "pgpPipeline.h"
#include "pgpPrsAsc.h"
#include "pgpRandomContext.h"
#include "pgpRngPub.h"
#include "pgpVMemMod.h"
#include "pgpUtilities.h"
/******************* Misc functions for encode/decode ********************/
/*
* Convert the user flags used to specify local encoding into a flag value
* from pgpFileRef.h
*/
PGPFileOpenFlags
pgpLocalEncodingToFlags( PGPUInt32 localEncode )
{
PGPFileOpenFlags flags = (PGPFileOpenFlags)0;
/* Wrapper function ensured that only one of these was given */
if( localEncode & kPGPLocalEncoding_Auto )
flags = kPGPFileOpenMaybeLocalEncode;
else if( localEncode & kPGPLocalEncoding_Force )
flags = kPGPFileOpenForceLocalEncode;
/* Add optional modifier flags */
if( localEncode & kPGPLocalEncoding_NoMacBinCRCOkay )
flags |= kPGPFileOpenNoMacBinCRCOkay;
return flags;
}
/******************* Helper functions for encode/decode ********************/
/*
* Pump data from the memory buffer at inBufPtr, of size InBufLength,
* into head. Do the terminating sizeAdvise but don't do the teardown.
*/
PGPError
pgpPumpMem(
PGPPipeline *head,
PGPByte *inBufPtr,
PGPSize inBufLength,
PGPProgressCallBack callBack,
void *callBackArg
)
{
PGPSize totalSize;
PGPError err = kPGPError_NoErr;
PGPSize written;
totalSize = inBufLength;
err = head->sizeAdvise( head, inBufLength );
if( IsPGPError( err ) )
return err;
err = head->annotate (head, NULL, PGPANN_FILE_BEGIN, NULL, 0);
if( IsPGPError( err ) )
return err;
err = head->sizeAdvise( head, inBufLength );
while( inBufLength>0 && IsntPGPError( err ) ) {
written = head->write( head, inBufPtr,
pgpMin(inBufLength, 4096), &err );
inBufPtr += written;
inBufLength -= written;
if( IsPGPError( err ) )
break;
if( IsntNull( callBack ) )
err = callBack( callBackArg, totalSize - inBufLength, totalSize );
}
if( IsntPGPError( err ) )
err = head->sizeAdvise( head, 0 );
if( IsntPGPError( err ) )
err = head->annotate (head, NULL, PGPANN_FILE_END, NULL, 0);
if( IsntPGPError( err ) )
err = head->sizeAdvise( head, 0 );
return err;
}
/* Send a warning event to the user if he is set up for events */
PGPError
pgpWarnUser(
PGPContextRef context, /* Input parameters */
PGPOptionListRef optionList,
PGPError errCode,
void *warnArg
)
{
PGPError err;
PGPEventHandlerProcPtr handler;
PGPUserValue arg;
PGPOptionListRef dummyOptionList = NULL;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_EventHandler, FALSE,
"%p%p", &handler, &arg ) ) )
goto error;
if( IsntNull( handler ) ) {
if( IsPGPError( err = pgpEventWarning( context, &dummyOptionList,
handler, arg, errCode, warnArg ) ) )
goto error;
pgpCleanupOptionList( &dummyOptionList );
}
return kPGPError_NoErr;
error:
return err;
}
/* Set fail-below validity values for failure and warning */
PGPError
pgpGetMinValidity(
PGPOptionListRef optionList,
PGPValidity *failValidity, /* Output parameters */
PGPValidity *warnValidity
)
{
PGPError err;
PGPOption op;
PGPUInt32 temp;
/* Init return pointers */
pgpa( pgpaAddrValid( failValidity, PGPValidity ) );
pgpa( pgpaAddrValid( warnValidity, PGPValidity ) );
/* XXX Need to fix these based on trust model and other aspects */
*failValidity = kPGPValidity_Unknown;
*warnValidity = kPGPValidity_Marginal;
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_FailBelowValidity, &op ) ) )
goto error;
if( IsOp( op ) ) {
if( IsPGPError( err = pgpOptionUInt( &op, &temp ) ) )
goto error;
*failValidity = (PGPValidity)temp;
}
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_WarnBelowValidity, &op ) ) )
goto error;
if( IsOp( op ) ) {
if( IsPGPError( err = pgpOptionUInt( &op, &temp ) ) )
goto error;
*warnValidity = (PGPValidity)temp;
}
return kPGPError_NoErr;
error:
return err;
}
/* Check a key for encryption or signature-verification validity. Return
an error if it is no good, no error to proceed */
PGPError
pgpCheckKeyValidity(
PGPContextRef context, /* Input parameters */
PGPOptionListRef optionList,
PGPKey *key,
RingSet const *ringSet,
PGPValidity failValidity,
PGPValidity warnValidity,
PGPKeySet *warnKeySet, /* Output parameters */
PGPValidity *pValidity
)
{
PGPValidity validity;
PgpTrustModel pgptrustmodel;
PGPError err;
PGPBoolean fRevoked,
fExpired,
fDisabled;
(void) context;
(void) optionList;
if( IsntNull( pValidity ) )
*pValidity = kPGPValidity_Unknown;
pgptrustmodel = pgpTrustModel (ringSetPool (ringSet));
/* First calculate validity level */
if (pgptrustmodel == PGPTRUST0) {
if( IsPGPError( err = PGPGetKeyNumber( key, kPGPKeyPropValidity,
(PGPInt32 *)&validity ) ) )
goto error;
} else {
/* Not yet supported */
if( IsPGPError( err = PGPGetKeyNumber( key, kPGPKeyPropValidity,
(PGPInt32 *)&validity ) ) )
goto error;
}
if( IsntNull( pValidity ) )
*pValidity = validity;
if( IsPGPError( err = PGPGetKeyBoolean( key, kPGPKeyPropIsRevoked,
&fRevoked ) ) )
goto error;
if( fRevoked ) {
err = kPGPError_KeyRevoked;
goto error;
}
if( IsPGPError( err = PGPGetKeyBoolean( key, kPGPKeyPropIsDisabled,
&fDisabled ) ) )
goto error;
if( fDisabled ) {
err = kPGPError_KeyDisabled;
goto error;
}
if( IsPGPError( err = PGPGetKeyBoolean( key, kPGPKeyPropIsExpired,
&fExpired ) ) )
goto error;
if( fExpired ) {
err = kPGPError_KeyExpired;
goto error;
}
if( validity < failValidity ) {
/* Return an error */
err = kPGPError_KeyInvalid;
goto error;
} else if( validity < warnValidity && IsntNull( warnKeySet ) ) {
/* Send a warning */
PGPKeySet *tmpKeySet;
if( IsPGPError( err = PGPNewSingletonKeySet( key,
&tmpKeySet ) ) )
goto error;
if( IsNull( tmpKeySet ) ) {
err = kPGPError_OutOfMemory;
goto error;
}
if( IsPGPError( err = PGPAddKeys( tmpKeySet, warnKeySet ) ) )
goto error;
if( IsPGPError( err = PGPFreeKeySet( tmpKeySet ) ) )
goto error;
}
/* Everything is OK, proceed */
return kPGPError_NoErr;
error:
return err;
}
/*
* Set *outputBufferLen from pipeBuf.
* bufferSize is the allocated size of the buffer, and we return an error
* if we exceeded the allocated size. (We don't actually write beyond
* the end of the buffer, of course.)
*/
PGPError
pgpGetMemOutput(
PGPPipeline *pipeBuf,
PGPSize bufferSize,
PGPSize *outputBufferLen
)
{
pgpa( pgpaAddrValid( pipeBuf, PGPPipeline ) );
pipeBuf->annotate( pipeBuf, NULL,
PGPANN_MEM_BYTECOUNT, (PGPByte *)outputBufferLen,
sizeof( *outputBufferLen ) );
if( *outputBufferLen > bufferSize )
return kPGPError_OutputBufferTooSmall;
return kPGPError_NoErr;
}
/*
* Set *outputBufferPtr and *outputBufferLen from pipeBuf. maxSize
* was our limit on the allocated size of the buffer, and we return an
* error if we exceeded the max size. (We don't actually write more data
* than that into our dynamically allocated buffer, though.) The difference
* from the above is that in this case the buffer was dynamically allocated
* while in the previous routine it was a static buffer we were given.
*/
PGPError
pgpGetVariableMemOutput(
PGPPipeline *pipeBuf,
PGPSize maxSize,
PGPByte **outputBufferPtr,
PGPSize *outputBufferLen
)
{
PGPError err = kPGPError_NoErr;
pgpa( pgpaAddrValid( pipeBuf, PGPPipeline ) );
err = pipeBuf->annotate( pipeBuf, NULL,
PGPANN_MEM_BYTECOUNT, (PGPByte *)outputBufferLen,
sizeof( *outputBufferLen ) );
if ( IsntPGPError( err ) )
{
pipeBuf->annotate( pipeBuf, NULL,
PGPANN_MEM_MEMBUF, (PGPByte *)outputBufferPtr,
sizeof( *outputBufferPtr ) );
}
if ( IsntPGPError( err ) )
{
if( *outputBufferLen > maxSize )
err = kPGPError_OutputBufferTooSmall;
}
return err;
}
/*
* See if optionList specifies PGPMIME encoding, and if so, get MIME body
* offset and return it to caller.
*/
PGPError
pgpGetPGPMIMEBodyOffset(
PGPPipeline *pipeBuf,
PGPOptionListRef optionList)
{
PGPSize *mimeBodyOffPtr;
PGPSize mimeBodyOff;
char *mimeSeparator;
PGPUInt32 mimeHeaderLines;
PGPUInt32 mimeFlag;
PGPUInt32 lineEndFlag;
PGPLineEndType lineEnd;
PGPUInt32 uintLineEnd;
PGPError err = kPGPError_NoErr;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_PGPMIMEEncoding, FALSE,
"%d%p%p", &mimeFlag, &mimeBodyOffPtr,
&mimeSeparator) ) )
goto error;
if( mimeFlag ) {
if( IsntNull( mimeBodyOffPtr ) ) {
if( IsPGPError( err = pipeBuf->annotate( pipeBuf, NULL,
PGPANN_PGPMIME_HEADER_SIZE,
(unsigned char *)&mimeBodyOff, sizeof(mimeBodyOff) ) ) )
goto error;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_OutputLineEndType, FALSE,
"%b%d", &lineEndFlag, &uintLineEnd ) ) )
goto error;
if( lineEndFlag )
lineEnd = (PGPLineEndType)uintLineEnd;
else
lineEnd = pgpGetDefaultLineEndType ();
if( lineEnd == kPGPLineEnd_CRLF ) {
if( IsPGPError( err = pipeBuf->annotate( pipeBuf, NULL,
PGPANN_PGPMIME_HEADER_LINES,
(unsigned char *)&mimeHeaderLines,
sizeof(mimeHeaderLines) ) ) )
goto error;
mimeBodyOff += mimeHeaderLines;
}
*mimeBodyOffPtr = mimeBodyOff;
}
if( IsntNull( mimeSeparator ) ) {
if( IsPGPError( err = pipeBuf->annotate( pipeBuf, NULL,
PGPANN_PGPMIME_SEPARATOR,
(unsigned char *)mimeSeparator,
kPGPMimeSeparatorSize ) ) )
goto error;
}
}
error:
return err;
}
/* Line ending control */
PGPLineEndType
pgpGetDefaultLineEndType ()
{
#if defined(PGP_MSDOS) || defined(PGP_WIN32)
return kPGPLineEnd_CRLF;
#elif PGP_MACINTOSH
return kPGPLineEnd_CR;
#else
return kPGPLineEnd_LF;
#endif
}
/* Parse an optionlist structure and extract callback info */
PGPError
pgpSetupCallback(
PGPOptionListRef optionList,
PGPEventHandlerProcPtr *func, /* Output params */
PGPUserValue *userValue,
PGPBoolean *fNullEvents
)
{
PGPError err;
PGPBoolean lNullEvents;
/* Init return data to default states */
pgpa( pgpaAddrValid( func, PGPEventHandlerProcPtr ) );
pgpa( pgpaAddrValid( userValue, PGPUserValue ) );
pgpa( pgpaAddrValid( fNullEvents, PGPBoolean ) );
*func = NULL;
*userValue = (PGPUserValue)0;
*fNullEvents = FALSE;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_EventHandler, FALSE,
"%p%p", func, userValue ) ) )
goto error;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_SendNullEvents, FALSE,
"%b", &lNullEvents ) ) )
goto error;
if( lNullEvents ) {
/* Wants notification of null events */
if( IsNull (*func) ) {
pgpDebugMsg(
"Error: Null events requested without event handler" );
err = kPGPError_BadParams;
goto error;
}
*fNullEvents = TRUE;
}
return kPGPError_NoErr;
error:
*func = NULL;
*userValue = (PGPUserValue)0;
*fNullEvents = FALSE;
return err;
}
/* Open input specification if there is one. Optionally set up filename
* literal structure, and seed RNG.
*/
PGPError
pgpSetupInput(
PGPContextRef context, /* Input params */
PGPOptionListRef optionList,
PgpLiteralParams *literal,
PGPRandomContext *rng,
PGPBoolean inputMode,
PGPBoolean detachedSignature,
PFLConstFileSpecRef *inFileRef, /* Output params */
PGPFileRead **pfrin,
PGPFileDataType *inFileDataType,
PGPByte **inBufPtr,
PGPSize *inBufLength
)
{
PGPOption op; /* Selected option from list */
PGPError err; /* Error return code */
static char fyeomagic[] = "_CONSOLE"; /* Display-only mode */
PGPUInt32 localEncode; /* Special input encoding (macbin) */
PGPFileOpenFlags localEncodeFlags; /* Flag form of localEncode */
PGPByte const *peekBuf; /* For RNG seeding from file */
PGPSize peekLength; /* Length of peekBuf */
/* Init return data to default states */
pgpa( pgpaAddrValid( inFileRef, PFLConstFileSpecRef ) );
pgpa( pgpaAddrValid( pfrin, PGPFileRead * ) );
pgpa( pgpaAddrValid( inFileDataType, PGPFileDataType ) );
pgpa( pgpaAddrValid( inBufPtr, PGPByte * ) );
pgpa( pgpaAddrValid( inBufLength, PGPSize ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -