📄 pgpencode.c
字号:
&s->outBufMaxLength, &s->outBufUsedLength,
&s->outPipe ) ) )
goto error;
/* Now pump the data through the pipes */
if( s->inFileRef ) {
/* File input */
if( IsntNull( s->func ) && s->fNullEvents ) {
pgpFileReadSetCallBack( s->pfrin, encodeLocalCallBack, s );
}
s->err = pgpFileReadPump( s->pfrin, s->head );
pgpFileReadDestroy( s->pfrin );
s->pfrin = NULL;
if( IsPGPError( s->err ) )
goto error;
s->err = s->head->sizeAdvise( s->head, 0 );
if( IsPGPError( s->err ) )
goto error;
} else {
/* Buffer input */
if( IsntNull( s->func ) && s->fNullEvents ) {
s->err = pgpPumpMem( s->head, s->inBufPtr, s->inBufLength,
encodeLocalCallBack, s );
} else {
s->err = pgpPumpMem( s->head, s->inBufPtr, s->inBufLength,
NULL, NULL );
}
if( IsPGPError( s->err ) )
goto error;
}
/* 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;
}
}
/* Get PGPMIME header offset if appropriate */
if( IsPGPError( s->err = pgpGetPGPMIMEBodyOffset( s->head,
s->optionList ) ) )
goto error;
/* Now we can tear down the pipeline */
s->head->teardown( s->head );
s->head = NULL;
/* Done, clean up and return */
s->err = kPGPError_NoErr;
error:
if( IsntNull( sessionKey ) ) {
PGPFreeData( sessionKey );
sessionKey = NULL;
}
if( IsntNull( s->env ) ) {
pgpenvDestroy( s->env );
s->env = NULL;
}
if( IsntNull( s->head ) ) {
s->head->teardown( s->head );
s->head = NULL;
}
if( IsntNull( s->sigspec ) ) {
pgpSigSpecDestroy( s->sigspec );
s->sigspec = NULL;
}
if( IsntNull( s->pubkeys ) ) {
PGPFreeKeySet( s->pubkeys );
s->pubkeys = NULL;
}
if( IsntNull( s->convkey ) ) {
pgpClearMemory( (s->convkey)->pass, (s->convkey)->passlen );
pgpContextMemFree( context, (char *)(s->convkey)->pass );
pgpContextMemFree( context, s->convkey );
s->convkey = NULL;
}
if( IsntNull( s->literal.filename ) ) {
pgpContextMemFree( context, (char *)s->literal.filename );
s->literal.filename = NULL;
}
if( IsntNull( s->pfrin ) ) {
pgpFileReadDestroy( s->pfrin );
s->pfrin = NULL;
}
if ( s->err != kPGPError_NoErr && IsntNull( s->outFileRef ) ) {
PFLFileSpecDelete( s->outFileRef );
s->outFileRef = NULL;
}
/* 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 );
}
(void)pgpEventFinal( s->context, &s->newOptionList, s->func,
s->userValue );
pgpCleanupOptionList( &s->newOptionList );
return s->err;
}
/************************** X509 encode function ****************************/
/*
* Compute transaction ID for request, from key.
* We want successive requests for certs from the same CA to use different
* trans IDs, so we will base the trans ID on the key material, along
* with the creation time of the most recent X.509 cert on the key.
* If there is no X.509 cert we just use the MD5 hash of the key material.
* This way when we renew a cert, the existing cert will be the most
* recent one, and so we will use a different trans ID for the renewal
* request.
*/
static PGPByte *
sTransactionIDFromKey( PGPKeyDBObjRef key, PGPSize *idLength )
{
PGPTime latesttime = (PGPTime)0;
PGPTime sigtime;
PGPKeyIterRef iter;
PGPKeyDBObjRef obj;
PGPUInt32 objtype;
PGPBoolean isX509;
void *vbuf;
PGPByte *buf;
PGPUInt32 i;
PGPNewKeyIterFromKeyDB( PGPPeekKeyDBObjKeyDB( key ), &iter );
PGPKeyIterSeek( iter, key );
while( PGPKeyIterNextKeyDBObj( iter, kPGPKeyDBObjType_Any, &obj ),
(void)(IsntNull(obj) && PGPGetKeyDBObjNumericProperty( obj,
kPGPKeyDBObjProperty_ObjectType,
(PGPInt32*)&objtype )),
(IsntNull(obj) && objtype != kPGPKeyDBObjType_Key) )
{
if( objtype == kPGPKeyDBObjType_Signature )
{
PGPGetKeyDBObjBooleanProperty( obj, kPGPSigProperty_IsX509,
&isX509 );
if( isX509 )
{
PGPGetKeyDBObjTimeProperty( obj, kPGPSigProperty_Creation,
&sigtime );
if( latesttime == 0 || sigtime > latesttime )
latesttime = sigtime;
}
}
}
PGPFreeKeyIter( iter );
PGPGetKeyDBObjAllocatedDataProperty( key, kPGPKeyProperty_X509MD5Hash,
&vbuf, idLength );
buf = vbuf;
/* XOR latesttime into the MD5 hash to get a unique hash */
for( i=0; i<sizeof(latesttime); ++i )
{
buf[i] ^= (latesttime>>(i*8)) & 0xff;
}
return buf;
}
static PGPError
sPackageOutputX509( pgpEncodeJobState *s )
{
PGPOption passop;
PGPOptionListRef passphrase = NULL;
PGPCipherAlgorithm encalg;
PGPKeyDBObjRef enckey;
PGPKeyDBObjRef signkey;
PGPByte *outBuf = NULL;
PGPSize outBufLength;
PGPByte *transactionID = NULL;
PGPSize transactionIDLen;
PGPBoolean fEncrypt;
PGPBoolean fSign;
PGPBoolean fMustFreeBuf;
PGPUInt32 fAppendOutput;
PGPUInt32 keycnt;
/* 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, FALSE,
s->sepsig, &s->sigspec ) ) )
goto error;
/* Check for various things we can't do: conventional encryption,
* encryption to more than one recipient; signing by more than one
* signature key; detached sigs.
*/
if( IsntNull( s->convkey ) )
return kPGPError_BadParams;
if ( IsntNull( s->pubkeys ) &&
IsntPGPError(PGPCountKeys(s->pubkeys,&keycnt)) && keycnt > 1 )
return kPGPError_BadParams;
if ( IsntNull( s->sigspec) &&
IsntNull( pgpSigSpecNext (s->sigspec) ) )
return kPGPError_BadParams;
if( s->sepsig )
return kPGPError_BadParams;
encalg = (PGPCipherAlgorithm) pgpenvGetInt (s->env, PGPENV_CIPHER,
NULL, NULL);
/* Get passphrase from suboptions of signwithkey */
passphrase = NULL;
if( s->sigspec ) {
PGPOption signop;
if( IsPGPError( s->err = pgpSearchOptionSingle( s->optionList,
kPGPOptionType_SignWithKey, &signop ) ) )
goto error;
if( IsPGPError( s->err = pgpSearchOptionSingle( signop.subOptions,
kPGPOptionType_Passphrase, &passop ) ) )
goto error;
if( IsntOp( passop ) ) {
if( IsPGPError( s->err = pgpSearchOptionSingle( signop.subOptions,
kPGPOptionType_Passkey, &passop ) ) )
goto error;
}
if( IsOp( passop ) ) {
PGPOption passopcopy;
pgpCopyOption( s->context, &passop, &passopcopy );
passphrase = pgpNewOneOptionList( s->context, &passopcopy );
}
}
/*
* Check for sufficient entropy. Error if not enough, unless
* AskUserForEntropy option is specified, in which case we give an event.
*/
if( IsntNull( s->sigspec ) || IsntNull( s->pubkeys ) ) {
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;
}
}
}
/* Get input into a memory buffer */
s->err = pgpSetupInputToBuffer( s->context, s->optionList, &s->inBufPtr,
&s->inBufLength, &fMustFreeBuf );
if( IsPGPError( s->err ) )
goto error;
/* Do the operation */
enckey = IsntNull(s->pubkeys) ? pgpFirstKeyInKeySet( s->pubkeys ) : NULL;
signkey = IsntNull(s->sigspec) ? pgpSigSpecSeckey( s->sigspec ) : NULL;
if( IsntNull( enckey ) )
pgpAssert( pgpKeyIsValid( enckey ) );
if( IsntNull( signkey ) )
{
/* Get transaction ID from signing key */
transactionID = sTransactionIDFromKey( signkey, &transactionIDLen );
}
s->err = X509PackageCertificateRequest (s->context,
s->inBufPtr, s->inBufLength,
transactionID, transactionIDLen,
enckey, encalg,
signkey, passphrase,
s->outputFormat,
&outBuf, &outBufLength );
passphrase = NULL;
if( IsntNull( transactionID ) )
PGPFreeData( transactionID );
if( fMustFreeBuf ) {
PGPFreeData( s->inBufPtr );
s->inBufPtr = NULL;
s->inBufLength = 0;
}
if( IsPGPError( s->err ) )
goto error;
/* Push result out to user */
fEncrypt = (PGPBoolean) IsntNull( s->pubkeys );
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,
&s->outBufMaxLength, &s->outBufUsedLength,
&s->outPipe ) ) )
goto error;
s->err = pgpPumpMem( s->head, outBuf, outBufLength, NULL, NULL );
if( IsPGPError( s->err ) )
goto error;
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->head->teardown( s->head );
s->head = NULL;
error:
if( IsntNull( passphrase ) )
pgpFreeOptionList( passphrase );
if( IsntNull( s->head ) )
s->head->teardown( s->head );
if( IsntNull( outBuf ) )
PGPFreeData( outBuf );
return s->err;
}
/*__Editor_settings____
Local Variables:
tab-width: 4
comment-column: 40
End:
vi: ts=4 sw=4
vim: si
_____________________*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -