📄 pgpcfb.c
字号:
/*____________________________________________________________________________
pgpCipherFeedback.c
Copyright (C) 1997 Network Associates Inc. and affiliated companies.
All rights reserved.
$Id: pgpCFB.c,v 1.23 1999/03/10 02:47:11 heller Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"
#include <string.h>
#include "pgpSDKBuildFlags.h"
#include "pgpMem.h"
#include "pgpErrors.h"
#include "pgpContext.h"
#include "pgpSymmetricCipherPriv.h"
#include "pgpCFBPriv.h"
#include "pgpUtilitiesPriv.h"
#define PGPValidateCFB( cfb ) \
PGPValidateParam( pgpCFBIsValid( cfb ) );
/*____________________________________________________________________________
Some stuff does double duty for CFB encryption/decryption,
and for X9.17 random number generation.
For random number generate, it is illegal to attempt to use
an interleaved CFB.
When used for CFB, iv[] is used as a circular buffer. bufLeft is
the number of bytes at the end which have to be filled in before we
crank the block cipher again. We do the block cipher operation
lazily: bufLeft may be 0. When we need one more byte, we
crank the block cipher and set bufLeft to 7.
prev[] holds the previous 8 bytes of ciphertext, for use
by ideaCFBSync() and Phil's, ahem, unique (not insecure, just
unusual) way of doing CFB encryption.
When used for X9.17 random number generation, iv[] holds the V initial
vector, and prev[] holds the R random output. bufLeft indicates how
much of R is still available before the generator has to be cranked again.
____________________________________________________________________________*/
/*____________________________________________________________________________
Each interleaved CFB has its own data.
____________________________________________________________________________*/
typedef struct
{
PGPSymmetricCipherContextRef symmetricRef;
PGPByte prev[ PGP_CFB_MAXBLOCKSIZE ];
PGPByte iv[ PGP_CFB_MAXBLOCKSIZE ];
/* note bufLeft could actually be in the main structure,
but it's more convenient here */
PGPSize bufLeft;
} CFBInterleaveStruct;
#define kCFBSize sizeof( CFBInterleaveStruct )
struct PGPCFBContext
{
#define kCFBMagic 0xBAABBAAB
PGPUInt32 magic;
PGPMemoryMgrRef memoryMgr;
PGPUInt16 interleave;
PGPUInt16 curCFBIndex;
PGPSize bytesInCur;
PGPBoolean cfbInited;
CFBInterleaveStruct cfbData[ 1 ]; /* variable */
};
#define IndCFB( ref, x ) (ref)->cfbData[ x ]
static PGPSize
CalcContextSize( PGPUInt16 numInterleaves )
{
/* one CFBInterleaveStruct is already declared in main struct */
return( sizeof( PGPCFBContext ) +
numInterleaves * ( kCFBSize - 1 ) );
}
static PGPBoolean
pgpCFBIsValid( const PGPCFBContext * ref)
{
PGPBoolean valid = FALSE;
valid = IsntNull( ref ) && ref->magic == kCFBMagic;
return( valid );
}
static void pgpCFBSync(CFBInterleaveStruct *cfb);
static void pgpCFBRandCycle(PGPCFBContext *ref,
void const *salt);
static void pgpCFBRandWash(PGPCFBContext *ref,
void const *buf, PGPSize len);
static void pgpCFBInit( PGPCFBContext * ref,
void const * key, void const * iv);
static void pgpCFBEncrypt( CFBInterleaveStruct *ref,
void const * src, PGPSize len, void * dest );
static void pgpCFBDecrypt( CFBInterleaveStruct *ref,
void const * src, PGPSize len, void * dest );
/* Returns as many bytes as are available before more salt is needed */
static PGPSize pgpCFBRandBytes(PGPCFBContext *ref,
PGPSize len, void *dest );
/*____________________________________________________________________________
____________________________________________________________________________*/
PGPError
PGPNewCFBContext(
PGPSymmetricCipherContextRef symmetricRef,
PGPUInt16 interleave,
PGPCFBContextRef * outRef )
{
PGPCFBContextRef newRef = NULL;
PGPError err = kPGPError_NoErr;
PGPValidatePtr( outRef );
*outRef = NULL;
PGPValidatePtr( symmetricRef );
PGPValidateParam( interleave != 0 );
newRef = (PGPCFBContextRef)
PGPNewData( pgpGetSymmetricCipherMemoryMgr( symmetricRef ),
CalcContextSize( interleave ),
0 | kPGPMemoryMgrFlags_Clear);
if ( IsntNull( newRef ) )
{
PGPUInt32 cfbIndex;
#if PGP_DEBUG
/* make original invalid to enforce semantics */
PGPSymmetricCipherContextRef tempRef;
err = PGPCopySymmetricCipherContext( symmetricRef, &tempRef );
if ( IsntPGPError( err ) )
{
PGPFreeSymmetricCipherContext( symmetricRef );
symmetricRef = tempRef;
}
err = kPGPError_NoErr;
#endif
newRef->magic = kCFBMagic;
newRef->interleave = interleave;
newRef->cfbInited = FALSE;
IndCFB( newRef, 0 ).symmetricRef = symmetricRef;
newRef->memoryMgr = pgpGetSymmetricCipherMemoryMgr( symmetricRef );
/* create a separate symmetric cipher for each cfb */
for ( cfbIndex = 1; cfbIndex < interleave; ++ cfbIndex )
{
err = PGPCopySymmetricCipherContext( symmetricRef,
&IndCFB( newRef, cfbIndex ).symmetricRef );
if ( IsPGPError( err ) )
{
break;
}
}
/* make sure we clean up */
if ( IsPGPError( err ) )
{
PGPFreeCFBContext( newRef );
newRef = NULL;
}
}
else
{
/* we own it, so dispose it */
PGPFreeSymmetricCipherContext( symmetricRef );
err = kPGPError_OutOfMemory;
}
*outRef = newRef;
return( err );
}
/*____________________________________________________________________________
____________________________________________________________________________*/
PGPError
PGPFreeCFBContext( PGPCFBContextRef ref )
{
PGPError err = kPGPError_NoErr;
PGPUInt32 cfbIndex;
PGPValidateCFB( ref );
for( cfbIndex = 0; cfbIndex < ref->interleave; ++cfbIndex )
{
if ( IsntNull( IndCFB( ref, cfbIndex ).symmetricRef ) )
{
PGPFreeSymmetricCipherContext(
IndCFB( ref, cfbIndex ).symmetricRef );
IndCFB( ref, cfbIndex ).symmetricRef = NULL;
}
}
pgpClearMemory( ref, sizeof( *ref ) );
PGPFreeData( ref );
return( err );
}
/*____________________________________________________________________________
____________________________________________________________________________*/
PGPError
PGPCopyCFBContext(
PGPCFBContextRef inRef,
PGPCFBContextRef * outRef )
{
PGPError err = kPGPError_NoErr;
PGPCFBContextRef newRef = NULL;
PGPValidatePtr( outRef );
*outRef = NULL;
PGPValidateCFB( inRef );
newRef = (PGPCFBContextRef)
PGPNewData( inRef->memoryMgr,
CalcContextSize( inRef->interleave ), 0);
if ( IsntNull( newRef ) )
{
PGPUInt32 cfbIndex;
*newRef = *inRef;
/* clear each symmetric cipher in case later allocation fails */
for ( cfbIndex = 0; cfbIndex < inRef->interleave; ++cfbIndex )
{
IndCFB( newRef, cfbIndex ).symmetricRef = NULL;
}
/* copy each symmetric cipher */
for ( cfbIndex = 0; cfbIndex < inRef->interleave; ++cfbIndex )
{
err = PGPCopySymmetricCipherContext(
IndCFB( inRef, cfbIndex ).symmetricRef,
&IndCFB( newRef, cfbIndex ).symmetricRef );
if ( IsPGPError( err ) )
{
break;
}
}
if ( IsPGPError( err ) )
{
PGPFreeCFBContext( newRef );
newRef = NULL;
}
}
else
{
err = kPGPError_OutOfMemory;
}
*outRef = newRef;
return( err );
}
/*____________________________________________________________________________
____________________________________________________________________________*/
PGPError
PGPInitCFB(
PGPCFBContextRef ref,
const void * key,
const void * initializationVector )
{
PGPError err = kPGPError_NoErr;
PGPValidateCFB( ref );
/* at least one param must be non-nil */
PGPValidateParam( IsntNull( key ) || IsntNull( initializationVector ) );
pgpCFBInit( ref, key, initializationVector);
return( err );
}
static void
pgpEncryptDecryptInterleaved(
PGPBoolean encrypt,
PGPCFBContextRef ref,
const void * in,
PGPSize bytesIn,
void * out )
{
PGPSize blockSize = pgpCFBGetBlockSize( ref );
PGPUInt16 cfbIndex;
PGPSize remaining;
const PGPByte * curIn = (const PGPByte *) in;
PGPByte * curOut = (PGPByte *) out;
cfbIndex = ref->curCFBIndex;
remaining = bytesIn;
while ( remaining != 0 )
{
CFBInterleaveStruct * cfb = NULL;
PGPUInt32 bytesAvail;
bytesAvail = blockSize - ref->bytesInCur;
if ( bytesAvail > remaining )
bytesAvail = remaining;
cfb = &IndCFB( ref, cfbIndex );
if ( encrypt )
pgpCFBEncrypt( cfb, curIn, bytesAvail, curOut);
else
pgpCFBDecrypt( cfb, curIn, bytesAvail, curOut);
ref->bytesInCur += bytesAvail;
curIn += bytesAvail;
curOut += bytesAvail;
remaining -= bytesAvail;
/* do we need to go onto the next CFB? */
pgpAssert( ref->bytesInCur <= blockSize );
if ( ref->bytesInCur == blockSize )
{
++cfbIndex;
/* wrap around to first CFB if necessary */
if ( cfbIndex == ref->interleave )
{
cfbIndex = 0;
}
ref->bytesInCur = 0;
}
}
ref->curCFBIndex = cfbIndex;
(void)encrypt;
(void)ref;
(void)in;
(void)bytesIn;
(void)out;
}
PGPError
pgpCFBEncryptInternal(
PGPCFBContextRef ref,
const void * in,
PGPSize bytesIn,
void * out )
{
PGPError err = kPGPError_NoErr;
if ( ref->cfbInited )
{
if ( ref->interleave == 1 )
{
/* keep it most efficient for common case */
CFBInterleaveStruct *cfb = &IndCFB( ref, 0);
pgpCFBEncrypt( cfb, in, bytesIn, out);
}
else
{
pgpEncryptDecryptInterleaved( TRUE, ref, in, bytesIn, out );
}
}
else
{
err = kPGPError_ImproperInitialization;
}
return( err );
}
PGPError
PGPCFBEncrypt(
PGPCFBContextRef ref,
const void * in,
PGPSize bytesIn,
void * out )
{
PGPValidatePtr( out );
PGPValidateCFB( ref );
PGPValidatePtr( in );
PGPValidateParam( bytesIn != 0 );
#if PGP_ENCRYPT_DISABLE
return( kPGPError_FeatureNotAvailable );
#else
return( pgpCFBEncryptInternal( ref, in, bytesIn, out ) );
#endif
}
PGPError
pgpCFBDecryptInternal(
PGPCFBContextRef ref,
const void * in,
PGPSize bytesIn,
void * out )
{
PGPError err = kPGPError_NoErr;
if ( ref->cfbInited )
{
if ( ref->interleave == 1 )
{
/* keep it most efficient for common case */
CFBInterleaveStruct *cfb = &IndCFB( ref, 0);
pgpCFBDecrypt( cfb, in, bytesIn, out);
}
else
{
pgpEncryptDecryptInterleaved( FALSE, ref, in, bytesIn, out );
}
}
else
{
err = kPGPError_ImproperInitialization;
}
return( err );
}
PGPError
PGPCFBDecrypt(
PGPCFBContextRef ref,
const void * in,
PGPSize bytesIn,
void * out )
{
PGPValidatePtr( out );
PGPValidateCFB( ref );
PGPValidatePtr( in );
PGPValidateParam( bytesIn != 0 );
#if PGP_DECRYPT_DISABLE
return( kPGPError_FeatureNotAvailable );
#else
return( pgpCFBDecryptInternal( ref, in, bytesIn, out ) );
#endif
}
PGPError
PGPCFBGetSymmetricCipher(
PGPCFBContextRef ref,
PGPSymmetricCipherContextRef * outRef )
{
PGPError err = kPGPError_NoErr;
PGPSymmetricCipherContextRef symmetricRef = NULL;
PGPValidatePtr( outRef );
*outRef = NULL;
PGPValidateCFB( ref );
symmetricRef = IndCFB( ref, 0).symmetricRef;
*outRef = symmetricRef;
return( err );
}
/*____________________________________________________________________________
____________________________________________________________________________*/
PGPError
PGPCFBSync( PGPCFBContextRef ref )
{
PGPError err = kPGPError_NoErr;
PGPValidateCFB( ref );
pgpCFBSync( &IndCFB( ref, ref->curCFBIndex ) );
return( err );
}
/*____________________________________________________________________________
____________________________________________________________________________*/
PGPError
PGPCFBGetRandom(
PGPCFBContextRef ref,
PGPSize requestCount,
void * outBytes,
PGPSize * outCount )
{
PGPError err = kPGPError_NoErr;
PGPValidatePtr( outCount );
*outCount = 0;
PGPValidateCFB( ref );
PGPValidatePtr( outBytes );
PGPValidateParam( ref->interleave == 1 );
*outCount = pgpCFBRandBytes( ref, requestCount, outBytes);
return( err );
}
/*____________________________________________________________________________
____________________________________________________________________________*/
PGPError
PGPCFBRandomCycle(
PGPCFBContextRef ref,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -