1050 lines
35 KiB
C
1050 lines
35 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include "crypt.h"
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* General Work Routines *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
/* Get an IV value. It doesn't matter much what it is, as long as it's
|
|
completely different for each call. We use the first built-in encrypt
|
|
capability we find (actually we just assume it's there to save some time) */
|
|
|
|
static void getIV( void *iv, int ivLength )
|
|
{
|
|
static BOOLEAN initialised = FALSE;
|
|
static BYTE ivBuffer[ CRYPT_MAX_IVSIZE ];
|
|
CRYPT_INFO cryptInfo;
|
|
CRYPT_INFO_MDCSHS cryptInfoEx;
|
|
|
|
if( !initialised )
|
|
{
|
|
/* Seed the data with a value which is guaranteed to be different
|
|
each time (unless the entire program is rerun more than twice a
|
|
second, which is doubtful) */
|
|
memset( ivBuffer, 0, CRYPT_MAX_IVSIZE );
|
|
time( ( time_t * ) ivBuffer );
|
|
initialised = TRUE;
|
|
}
|
|
|
|
/* Use an extended setup call to only perform 2 setup iterations for
|
|
speed, since we're not concerned about security */
|
|
cryptInfoEx.keySetupIterations = 2;
|
|
|
|
/* Shuffle the bits and return them to the user. Since the encryption
|
|
will force a call to getIV() again, we cheat a bit by poking around
|
|
the cryptInfo internals to fool encryptBuffer() into thinking the IV
|
|
is already set */
|
|
initCryptContextEx( &cryptInfo, CRYPT_ALGO_MDCSHS, CRYPT_MODE_CFB,
|
|
&cryptInfoEx );
|
|
loadCryptContext( &cryptInfo, ivBuffer, CRYPT_MAX_IVSIZE );
|
|
cryptInfo.ivSet = TRUE; /* Nasty hack to stop recursion */
|
|
encryptBuffer( &cryptInfo, ivBuffer, CRYPT_MAX_IVSIZE );
|
|
destroyCryptContext( &cryptInfo );
|
|
memcpy( iv, ivBuffer, ivLength );
|
|
}
|
|
|
|
#ifdef LITTLE_ENDIAN
|
|
|
|
/* Byte-reverse an array of 16- and 32-bit words to/from network byte order
|
|
to account for processor endianness. These routines assume the given
|
|
count is a multiple of 16 or 32 bits. They are safe even for CPU's with
|
|
a word size > 32 bits since on a little-endian CPU the important 32 bits
|
|
are stored first, so that by zeroizing the first 32 bits and oring the
|
|
reversed value back in we don't need to rely on the processor only writing
|
|
32 bits into memory */
|
|
|
|
void longReverse( LONG *buffer, int count )
|
|
{
|
|
#ifdef _BIG_WORDS
|
|
BYTE *bufPtr = ( BYTE * ) buffer, temp;
|
|
|
|
count /= 4; /* sizeof( LONG ) != 4 */
|
|
while( count-- )
|
|
{
|
|
#if 0
|
|
LONG temp;
|
|
|
|
/* This code is cursed */
|
|
temp = value = *buffer & 0xFFFFFFFFUL;
|
|
value = ( ( value & 0xFF00FF00UL ) >> 8 ) | \
|
|
( ( value & 0x00FF00FFUL ) << 8 );
|
|
value = ( ( value << 16 ) | ( value >> 16 ) ) ^ temp;
|
|
*buffer ^= value;
|
|
buffer = ( LONG * ) ( ( BYTE * ) buffer + 4 );
|
|
#endif /* 0 */
|
|
/* There's really no nice way to do this - the above code generates
|
|
misaligned accesses on processors with a word size > 32 bits, so
|
|
we have to work at the byte level (either that or turn misaligned
|
|
access warnings off by trapping the signal the access corresponds
|
|
to. However a context switch per memory access is probably
|
|
somewhat slower than the current byte-twiddling mess) */
|
|
temp = bufPtr[ 3 ];
|
|
bufPtr[ 3 ] = bufPtr[ 0 ];
|
|
bufPtr[ 0 ] = temp;
|
|
temp = bufPtr[ 2 ];
|
|
bufPtr[ 2 ] = bufPtr[ 1 ];
|
|
bufPtr[ 1 ] = temp;
|
|
bufPtr += 4;
|
|
}
|
|
#else
|
|
LONG value;
|
|
|
|
count /= sizeof( LONG );
|
|
while( count-- )
|
|
{
|
|
value = *buffer;
|
|
value = ( ( value & 0xFF00FF00UL ) >> 8 ) | \
|
|
( ( value & 0x00FF00FFUL ) << 8 );
|
|
*buffer++ = ( value << 16 ) | ( value >> 16 );
|
|
}
|
|
#endif /* _BIG_WORDS */
|
|
}
|
|
|
|
void wordReverse( WORD *buffer, int count )
|
|
{
|
|
WORD value;
|
|
|
|
count /= sizeof( WORD );
|
|
while( count-- )
|
|
{
|
|
value = *buffer;
|
|
*buffer++ = ( value << 8 ) | ( value >> 8 );
|
|
}
|
|
}
|
|
#endif /* LITTLE_ENDIAN */
|
|
|
|
/* A safe free function which scrubs memory and zeroes the pointer */
|
|
|
|
void secureFree( void **pointer, int count )
|
|
{
|
|
if( *pointer != NULL )
|
|
{
|
|
/* Scrub the memory, free it, and zero the pointer */
|
|
memset( *pointer, 0, count );
|
|
free( *pointer );
|
|
*pointer = NULL;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* Capability Management Functions *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
/* The parameters of most encryption algorithms are traditionally specified
|
|
in bytes, so we define a shorter form of the bitsToBytes() macro to allow
|
|
the capability information to be specified in bits */
|
|
|
|
#define bits(x) bitsToBytes(x)
|
|
|
|
/* The functions used to implement the null encryption routines */
|
|
|
|
int nullSelfTest( void );
|
|
int nullInit( CRYPT_INFO *cryptInfo );
|
|
int nullInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx );
|
|
int nullEnd( CRYPT_INFO *cryptInfo );
|
|
int nullInitKey( CRYPT_INFO *cryptInfo );
|
|
int nullInitIV( CRYPT_INFO *cryptInfo );
|
|
int nullEncrypt( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int nullDecrypt( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
|
|
/* The functions used to implement the MDC/SHS encryption routines */
|
|
|
|
int mdcshsSelfTest( void );
|
|
int mdcshsInit( CRYPT_INFO *cryptInfo );
|
|
int mdcshsInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx );
|
|
int mdcshsEnd( CRYPT_INFO *cryptInfo );
|
|
int mdcshsInitKey( CRYPT_INFO *cryptInfo );
|
|
int mdcshsInitIV( CRYPT_INFO *cryptInfo );
|
|
int mdcshsEncrypt( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int mdcshsDecrypt( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
|
|
/* The functions used to implement the DES encryption routines */
|
|
|
|
int desSelfTest( void );
|
|
int desInit( CRYPT_INFO *cryptInfo );
|
|
int desInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx );
|
|
int desEnd( CRYPT_INFO *cryptInfo );
|
|
int desInitKey( CRYPT_INFO *cryptInfo );
|
|
int desEncryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int desDecryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int desEncryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int desDecryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int desEncryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int desDecryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int desEncryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int desDecryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int desEncryptPCBC( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int desDecryptPCBC( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
|
|
/* The functions used to implement the two-key triple DES encryption
|
|
routines */
|
|
|
|
int des3SelfTest( void );
|
|
int des3Init( CRYPT_INFO *cryptInfo );
|
|
int des3InitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx );
|
|
int des3End( CRYPT_INFO *cryptInfo );
|
|
int des3InitKey( CRYPT_INFO *cryptInfo );
|
|
int des3EncryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int des3DecryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int des3EncryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int des3DecryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int des3EncryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int des3DecryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int des3EncryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int des3DecryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
|
|
/* The functions used to implement the IDEA encryption routines */
|
|
|
|
int ideaSelfTest( void );
|
|
int ideaInit( CRYPT_INFO *cryptInfo );
|
|
int ideaInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx );
|
|
int ideaEnd( CRYPT_INFO *cryptInfo );
|
|
int ideaInitKey( CRYPT_INFO *cryptInfo );
|
|
int ideaEncryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int ideaDecryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int ideaEncryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int ideaDecryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int ideaEncryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int ideaDecryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int ideaEncryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int ideaDecryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
|
|
/* The functions used to implement the RC4 encryption routines */
|
|
|
|
int rc4SelfTest( void );
|
|
int rc4Init( CRYPT_INFO *cryptInfo );
|
|
int rc4InitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx );
|
|
int rc4End( CRYPT_INFO *cryptInfo );
|
|
int rc4InitKey( CRYPT_INFO *cryptInfo );
|
|
int rc4Encrypt( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int rc4Decrypt( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
|
|
/* The functions used to implement the SAFER and SAFER_SK encryption
|
|
routines */
|
|
|
|
int saferSelfTest( void );
|
|
int saferInit( CRYPT_INFO *cryptInfo );
|
|
int saferInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx );
|
|
int saferEnd( CRYPT_INFO *cryptInfo );
|
|
int saferInitKey( CRYPT_INFO *cryptInfo );
|
|
int saferEncryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int saferDecryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int saferEncryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int saferDecryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int saferEncryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int saferDecryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int saferEncryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
int saferDecryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length );
|
|
|
|
/* The encryption library intrinsic capability list */
|
|
|
|
static CAPABILITY_INFO intrinsicCapabilities[] = {
|
|
/* The no-encryption capability */
|
|
{ CRYPT_ALGO_NONE, CRYPT_MODE_NONE, 0, "None", CRYPT_MAX_SPEED,
|
|
0, 0, 0,
|
|
0, 0, 0,
|
|
nullSelfTest, nullInit, nullInitEx, nullEnd, nullInitKey, nullInitIV,
|
|
nullEncrypt, nullDecrypt, CRYPT_ERROR, NULL },
|
|
|
|
/* The MDC/SHS capabilities */
|
|
{ CRYPT_ALGO_MDCSHS, CRYPT_MODE_CFB, bits( 8 ), "MDC/SHS", CRYPT_ERROR,
|
|
bits( 40 ), bits( 512 ), bits( 2048 ),
|
|
bits( 32 ), bits( 64 ), bits( 160 ),
|
|
mdcshsSelfTest, mdcshsInit, mdcshsInitEx, mdcshsEnd,
|
|
mdcshsInitKey, mdcshsInitIV, mdcshsEncrypt, mdcshsDecrypt,
|
|
CRYPT_ERROR, NULL },
|
|
|
|
/* The DES capabilities */
|
|
{ CRYPT_ALGO_DES, CRYPT_MODE_ECB, bits( 64 ), "DES-ECB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 56 ), bits( 56 ),
|
|
bits( 0 ), bits( 0 ), bits( 0 ),
|
|
desSelfTest, desInit, desInitEx, desEnd, desInitKey, NULL,
|
|
desEncryptECB, desDecryptECB, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_DES, CRYPT_MODE_CBC, bits( 64 ), "DES-CBC", CRYPT_ERROR,
|
|
bits( 40 ), bits( 56 ), bits( 56 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
desSelfTest, desInit, desInitEx, desEnd, desInitKey, NULL,
|
|
desEncryptCBC, desDecryptCBC, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_DES, CRYPT_MODE_CFB, bits( 8 ), "DES-CFB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 56 ), bits( 56 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
desSelfTest, desInit, desInitEx, desEnd, desInitKey, NULL,
|
|
desEncryptCFB, desDecryptCFB, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_DES, CRYPT_MODE_OFB, bits( 8 ), "DES-OFB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 56 ), bits( 56 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
desSelfTest, desInit, desInitEx, desEnd, desInitKey, NULL,
|
|
desEncryptOFB, desDecryptOFB, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_DES, CRYPT_MODE_PCBC, bits( 64 ), "DES-PCBC", CRYPT_ERROR,
|
|
bits( 40 ), bits( 56 ), bits( 56 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
desSelfTest, desInit, desInitEx, desEnd, desInitKey, NULL,
|
|
desEncryptPCBC, desDecryptPCBC, CRYPT_ERROR, NULL },
|
|
|
|
/* The two-key triple DES capabilities */
|
|
{ CRYPT_ALGO_3DES, CRYPT_MODE_ECB, bits( 64 ), "3DES-ECB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 112 ), bits( 112 ),
|
|
bits( 0 ), bits( 0 ), bits( 0 ),
|
|
des3SelfTest, des3Init, des3InitEx, des3End, des3InitKey, NULL,
|
|
des3EncryptECB, des3DecryptECB, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_3DES, CRYPT_MODE_CBC, bits( 64 ), "3DES-CBC", CRYPT_ERROR,
|
|
bits( 40 ), bits( 112 ), bits( 112 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
des3SelfTest, des3Init, des3InitEx, des3End, des3InitKey, NULL,
|
|
des3EncryptCBC, des3DecryptCBC, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_3DES, CRYPT_MODE_CFB, bits( 64 ), "3DES-CFB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 112 ), bits( 112 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
des3SelfTest, des3Init, des3InitEx, des3End, des3InitKey, NULL,
|
|
des3EncryptCFB, des3DecryptCFB, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_3DES, CRYPT_MODE_OFB, bits( 64 ), "3DES-OFB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 112 ), bits( 112 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
des3SelfTest, des3Init, des3InitEx, des3End, des3InitKey, NULL,
|
|
des3EncryptOFB, des3DecryptOFB, CRYPT_ERROR, NULL },
|
|
|
|
/* The IDEA capabilities */
|
|
{ CRYPT_ALGO_IDEA, CRYPT_MODE_ECB, bits( 64 ), "IDEA-ECB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 128 ), bits( 128 ),
|
|
bits( 0 ), bits( 0 ), bits( 0 ),
|
|
ideaSelfTest, ideaInit, ideaInitEx, ideaEnd, ideaInitKey, NULL,
|
|
ideaEncryptECB, ideaDecryptECB, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_IDEA, CRYPT_MODE_CBC, bits( 64 ), "IDEA-CBC", CRYPT_ERROR,
|
|
bits( 40 ), bits( 128 ), bits( 128 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
ideaSelfTest, ideaInit, ideaInitEx, ideaEnd, ideaInitKey, NULL,
|
|
ideaEncryptCBC, ideaDecryptCBC, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_IDEA, CRYPT_MODE_CFB, bits( 8 ), "IDEA-CFB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 128 ), bits( 128 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
ideaSelfTest, ideaInit, ideaInitEx, ideaEnd, ideaInitKey, NULL,
|
|
ideaEncryptCFB, ideaDecryptCFB, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_IDEA, CRYPT_MODE_OFB, bits( 8 ), "IDEA-OFB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 128 ), bits( 128 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
ideaSelfTest, ideaInit, ideaInitEx, ideaEnd, ideaInitKey, NULL,
|
|
ideaEncryptOFB, ideaDecryptOFB, CRYPT_ERROR, NULL },
|
|
|
|
/* The RC4 capabilities */
|
|
{ CRYPT_ALGO_RC4, CRYPT_MODE_STREAM, bits( 8 ), "RC4", CRYPT_ERROR,
|
|
bits( 40 ), bits( 128 ), bits( 256 ),
|
|
bits( 0 ), bits( 0 ), bits( 0 ),
|
|
rc4SelfTest, rc4Init, rc4InitEx, rc4End, rc4InitKey, NULL,
|
|
rc4Encrypt, rc4Decrypt, CRYPT_ERROR, NULL },
|
|
|
|
/* The SAFER capabilities */
|
|
{ CRYPT_ALGO_SAFER, CRYPT_MODE_ECB, bits( 64 ), "SAFER-ECB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 64 ), bits( 128 ),
|
|
bits( 0 ), bits( 0 ), bits( 0 ),
|
|
saferSelfTest, saferInit, saferInitEx, saferEnd, saferInitKey, NULL,
|
|
saferEncryptECB, saferDecryptECB, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_SAFER, CRYPT_MODE_CBC, bits( 64 ), "SAFER-CBC", CRYPT_ERROR,
|
|
bits( 40 ), bits( 64 ), bits( 128 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
saferSelfTest, saferInit, saferInitEx, saferEnd, saferInitKey, NULL,
|
|
saferEncryptCBC, saferDecryptCBC, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_SAFER, CRYPT_MODE_CFB, bits( 8 ), "SAFER-CFB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 64 ), bits( 128 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
saferSelfTest, saferInit, saferInitEx, saferEnd, saferInitKey, NULL,
|
|
saferEncryptCFB, saferDecryptCFB, CRYPT_ERROR, NULL },
|
|
{ CRYPT_ALGO_SAFER, CRYPT_MODE_OFB, bits( 8 ), "SAFER-OFB", CRYPT_ERROR,
|
|
bits( 40 ), bits( 64 ), bits( 128 ),
|
|
bits( 16 ), bits( 32 ), bits( 64 ),
|
|
saferSelfTest, saferInit, saferInitEx, saferEnd, saferInitKey, NULL,
|
|
saferEncryptOFB, saferDecryptOFB, CRYPT_ERROR, NULL },
|
|
|
|
/* The end-of-list marker */
|
|
{ CRYPT_ALGO_NONE, CRYPT_MODE_NONE, CRYPT_ERROR, "", 0,
|
|
0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, CRYPT_ERROR, NULL }
|
|
};
|
|
|
|
/* The list of crypt library capability records. Even if initCapabilities()
|
|
is never called we still have a minimum non-encryption method available */
|
|
|
|
static CAPABILITY_INFO *capabilityListHead = intrinsicCapabilities;
|
|
static CAPABILITY_INFO *capabilityListTail = intrinsicCapabilities;
|
|
static CAPABILITY_INFO *intrinsicCapabilityListEnd = NULL;
|
|
|
|
/* Free the capability list */
|
|
|
|
static void freeCapabilityList( void )
|
|
{
|
|
CAPABILITY_INFO *capabilityListPtr = intrinsicCapabilityListEnd;
|
|
void *capabilityToFree;
|
|
|
|
/* Mark the list as being empty */
|
|
intrinsicCapabilityListEnd = NULL;
|
|
|
|
/* Free the capability record list list */
|
|
while( capabilityListPtr != NULL )
|
|
{
|
|
capabilityToFree = capabilityListPtr;
|
|
capabilityListPtr = capabilityListPtr->next;
|
|
secureFree( &capabilityToFree, sizeof( CAPABILITY_INFO ) );
|
|
}
|
|
}
|
|
|
|
/* Initialise the intrinsic encryption library capability list */
|
|
|
|
static int initCapabilities( void )
|
|
{
|
|
CAPABILITY_INFO *capabilityInfoPtr;
|
|
CRYPT_ALGO cryptAlgo = CRYPT_ERROR;
|
|
int i;
|
|
|
|
/* Add the built-in encryption capabilities */
|
|
for( i = 0; intrinsicCapabilities[ i + 1 ].blockSize != CRYPT_ERROR; i++ )
|
|
intrinsicCapabilities[ i ].next = &intrinsicCapabilities[ i + 1 ];
|
|
|
|
/* Perform the self-test for each encryption algorithm */
|
|
for( capabilityInfoPtr = capabilityListHead;
|
|
capabilityInfoPtr != NULL;
|
|
capabilityInfoPtr = capabilityInfoPtr->next )
|
|
{
|
|
CAPABILITY_INFO *capabilitySelfTestPtr;
|
|
int status;
|
|
|
|
/* If we've already encountered this algorithm, don't try the
|
|
self-test again */
|
|
if( capabilityInfoPtr->cryptAlgo == cryptAlgo )
|
|
continue;
|
|
cryptAlgo = capabilityInfoPtr->cryptAlgo;
|
|
|
|
/* Perform the self-test for this algorithm type */
|
|
status = capabilityInfoPtr->selfTestFunction();
|
|
|
|
/* Set the test status for each capability using this algorithm */
|
|
for( capabilitySelfTestPtr = capabilityInfoPtr;
|
|
capabilitySelfTestPtr != NULL;
|
|
capabilitySelfTestPtr = capabilitySelfTestPtr->next )
|
|
if( capabilitySelfTestPtr->cryptAlgo == capabilityInfoPtr->cryptAlgo )
|
|
capabilitySelfTestPtr->selfTestStatus = status;
|
|
}
|
|
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
/* Add a capability record to the library */
|
|
|
|
static int addCapability( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, \
|
|
int blockSize, char *name, int speed, \
|
|
int minKeySize, int keySize, int maxKeySize )
|
|
{
|
|
CAPABILITY_INFO *newElement;
|
|
|
|
/* Check the passed-in parameters */
|
|
if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST )
|
|
return( CRYPT_BADPARM1 );
|
|
if( cryptMode < CRYPT_MODE_NONE || cryptMode > CRYPT_MODE_LAST )
|
|
return( CRYPT_BADPARM2 );
|
|
if( blockSize < 0 )
|
|
return( CRYPT_BADPARM3 );
|
|
if( name == NULL )
|
|
return( CRYPT_BADPARM4 );
|
|
if( ( speed != CRYPT_ERROR && speed < 0 ) || speed > CRYPT_MAX_SPEED )
|
|
return( CRYPT_BADPARM5 );
|
|
if( minKeySize < 0 )
|
|
return( CRYPT_BADPARM6 );
|
|
if( keySize < minKeySize )
|
|
return( CRYPT_BADPARM7 );
|
|
if( maxKeySize < keySize )
|
|
return( CRYPT_BADPARM8 );
|
|
|
|
/* Allocate memory for the new capability and its associated message */
|
|
if( ( newElement = ( CAPABILITY_INFO * ) malloc( sizeof( CAPABILITY_INFO ) ) ) == NULL )
|
|
return( CRYPT_NOMEM );
|
|
memset( newElement, 0, sizeof( CAPABILITY_INFO ) );
|
|
if( ( newElement->name = ( char * ) malloc( strlen( name ) + 1 ) ) == NULL )
|
|
{
|
|
free( newElement );
|
|
return( CRYPT_NOMEM );
|
|
}
|
|
|
|
/* Copy the information across */
|
|
newElement->cryptAlgo = cryptAlgo;
|
|
newElement->cryptMode = cryptMode;
|
|
newElement->blockSize = blockSize;
|
|
strcpy( newElement->name, name );
|
|
newElement->minKeySize = minKeySize;
|
|
newElement->keySize = keySize;
|
|
newElement->maxKeySize = maxKeySize;
|
|
newElement->next = NULL;
|
|
|
|
/* Link it into the list */
|
|
if( capabilityListHead == NULL )
|
|
capabilityListHead = newElement;
|
|
else
|
|
capabilityListTail->next = newElement;
|
|
capabilityListTail = newElement;
|
|
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
/* Find the capability record for a given encryption algorithm */
|
|
|
|
static CAPABILITY_INFO *findCapabilityInfo( CRYPT_ALGO cryptAlgo, \
|
|
CRYPT_MODE cryptMode )
|
|
{
|
|
CAPABILITY_INFO *capabilityInfoPtr;
|
|
|
|
/* Try and find information on the required algorithm */
|
|
for( capabilityInfoPtr = capabilityListHead;
|
|
capabilityInfoPtr != NULL;
|
|
capabilityInfoPtr = capabilityInfoPtr->next )
|
|
if( capabilityInfoPtr->cryptAlgo == cryptAlgo &&
|
|
( capabilityInfoPtr->cryptMode == cryptMode ||
|
|
cryptMode == CRYPT_MODE_NONE ) )
|
|
return( capabilityInfoPtr );
|
|
|
|
/* Nothing available */
|
|
return( NULL );
|
|
}
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* Capability Query Functions *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
/* Determine whether a given encryption mode is available */
|
|
|
|
CRET queryModeAvailability( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode )
|
|
{
|
|
/* Perform basic error checking */
|
|
if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST )
|
|
return( CRYPT_BADPARM1 );
|
|
if( cryptMode < CRYPT_MODE_NONE || cryptMode > CRYPT_MODE_LAST )
|
|
return( CRYPT_BADPARM2 );
|
|
|
|
/* Make sure the library has been initalised */
|
|
if( capabilityListHead == NULL )
|
|
return( CRYPT_NOTINITED );
|
|
|
|
/* See if we have any information on this encryption algo/mode */
|
|
if( findCapabilityInfo( cryptAlgo, cryptMode ) == NULL )
|
|
return( ( findCapabilityInfo( cryptAlgo, CRYPT_MODE_NONE ) == NULL ) ? \
|
|
CRYPT_NOALGO : CRYPT_NOMODE );
|
|
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
CRET queryAlgoAvailability( CRYPT_ALGO cryptAlgo )
|
|
{
|
|
return( queryModeAvailability( cryptAlgo, CRYPT_MODE_NONE ) );
|
|
}
|
|
|
|
/* Get information on a given encrytion algorithm */
|
|
|
|
CRET queryAlgoModeInformation( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, \
|
|
CRYPT_QUERY_INFO CPTR cryptQueryInfo )
|
|
{
|
|
CAPABILITY_INFO *capabilityInfo;
|
|
|
|
/* Perform basic error checking */
|
|
if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST )
|
|
return( CRYPT_BADPARM1 );
|
|
if( cryptMode < CRYPT_MODE_NONE || cryptMode > CRYPT_MODE_LAST )
|
|
return( CRYPT_BADPARM2 );
|
|
if( cryptQueryInfo == NULL )
|
|
return( CRYPT_BADPARM3 );
|
|
|
|
/* Make sure the library has been initalised */
|
|
if( capabilityListHead == NULL )
|
|
return( CRYPT_NOTINITED );
|
|
|
|
/* Clear the fields in the query structure */
|
|
memset( cryptQueryInfo, 0, sizeof( CRYPT_QUERY_INFO ) );
|
|
|
|
/* Find the information record on this algorithm */
|
|
if( ( capabilityInfo = findCapabilityInfo( cryptAlgo, cryptMode ) ) == NULL )
|
|
{
|
|
cryptQueryInfo->algoName = "";
|
|
cryptQueryInfo->blockSize = CRYPT_ERROR;
|
|
cryptQueryInfo->minKeySize = CRYPT_ERROR;
|
|
cryptQueryInfo->keySize = CRYPT_ERROR;
|
|
cryptQueryInfo->maxKeySize = CRYPT_ERROR;
|
|
cryptQueryInfo->minIVsize = CRYPT_ERROR;
|
|
cryptQueryInfo->ivSize = CRYPT_ERROR;
|
|
cryptQueryInfo->maxIVsize = CRYPT_ERROR;
|
|
cryptQueryInfo->speed = CRYPT_ERROR;
|
|
return( ( findCapabilityInfo( cryptAlgo, CRYPT_MODE_NONE ) == NULL ) ? \
|
|
CRYPT_NOALGO : CRYPT_NOMODE );
|
|
}
|
|
|
|
/* Return the appropriate information */
|
|
cryptQueryInfo->cryptAlgo = cryptAlgo;
|
|
cryptQueryInfo->cryptMode = cryptMode;
|
|
cryptQueryInfo->algoName = capabilityInfo->name;
|
|
cryptQueryInfo->blockSize = capabilityInfo->blockSize;
|
|
cryptQueryInfo->minKeySize = capabilityInfo->minKeySize;
|
|
cryptQueryInfo->keySize = capabilityInfo->keySize;
|
|
cryptQueryInfo->maxKeySize = capabilityInfo->maxKeySize;
|
|
cryptQueryInfo->minIVsize = capabilityInfo->minIVsize;
|
|
cryptQueryInfo->ivSize = capabilityInfo->ivSize;
|
|
cryptQueryInfo->maxIVsize = capabilityInfo->maxIVsize;
|
|
cryptQueryInfo->speed = capabilityInfo->speed;
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
/* Get information on the algorithm used by a given encryption context */
|
|
|
|
CRET queryContextInformation( CRYPT_INFO CPTR cryptInfo,
|
|
CRYPT_QUERY_INFO CPTR cryptQueryInfo )
|
|
{
|
|
/* Perform basic error checking */
|
|
if( cryptInfo == NULL )
|
|
return( CRYPT_BADPARM1 );
|
|
if( cryptInfo->capabilityInfo == NULL )
|
|
return( CRYPT_NOTINITED );
|
|
|
|
return( queryAlgoModeInformation( cryptInfo->capabilityInfo->cryptAlgo,
|
|
cryptInfo->capabilityInfo->cryptMode, cryptQueryInfo ) );
|
|
}
|
|
|
|
/* Initialise and shut down the encryption library */
|
|
|
|
CRET initLibrary( void )
|
|
{
|
|
return( initCapabilities() );
|
|
}
|
|
|
|
CRET endLibrary( void )
|
|
{
|
|
freeCapabilityList();
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* Encryption Context Management Functions *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
/* A magic value to detect whether an encryption context has been
|
|
initialised yet */
|
|
|
|
#define CRYPT_MAGIC 0xC0EDBABEL
|
|
|
|
/* Initialise and perform an extended initialisation of an encryption
|
|
context */
|
|
|
|
CRET initCryptContext( CRYPT_INFO CPTR cryptInfo, CRYPT_ALGO cryptAlgo, \
|
|
CRYPT_MODE cryptMode )
|
|
{
|
|
/* Perform basic error checking */
|
|
if( cryptInfo == NULL )
|
|
return( CRYPT_BADPARM1 );
|
|
if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST )
|
|
return( CRYPT_BADPARM2 );
|
|
if( cryptMode < CRYPT_MODE_NONE || cryptMode > CRYPT_MODE_LAST )
|
|
return( CRYPT_BADPARM3 );
|
|
|
|
/* Set all fields to zero */
|
|
memset( cryptInfo, 0, sizeof( CRYPT_INFO ) );
|
|
|
|
/* Set up the pointer to the capability information */
|
|
if( ( cryptInfo->capabilityInfo = findCapabilityInfo( cryptAlgo, cryptMode ) ) == NULL )
|
|
return( ( queryAlgoAvailability( cryptAlgo ) ) ? \
|
|
CRYPT_NOMODE : CRYPT_NOALGO );
|
|
|
|
/* Make sure the algorithm self-test went OK */
|
|
if( cryptInfo->capabilityInfo->selfTestStatus != CRYPT_OK )
|
|
return( CRYPT_SELFTEST );
|
|
|
|
/* Perform any algorithm-specific initialization */
|
|
if( cryptInfo->capabilityInfo->initFunction != NULL )
|
|
{
|
|
int status;
|
|
|
|
status = cryptInfo->capabilityInfo->initFunction( cryptInfo );
|
|
if( isStatusError( status ) )
|
|
return( status );
|
|
}
|
|
|
|
/* Set up the IV information to the default values. This can be
|
|
overridden later if required */
|
|
cryptInfo->ivLength = cryptInfo->capabilityInfo->ivSize;
|
|
|
|
/* Set the check value. Note that we set it after the capability info
|
|
has been set, so that a check on this value will also tell us whether
|
|
the capability info is present */
|
|
cryptInfo->checkValue = CRYPT_MAGIC;
|
|
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
CRET initCryptContextEx( CRYPT_INFO CPTR cryptInfo, CRYPT_ALGO cryptAlgo, \
|
|
CRYPT_MODE cryptMode, void *cryptInfoEx )
|
|
{
|
|
/* Perform basic error checking */
|
|
if( cryptInfo == NULL )
|
|
return( CRYPT_BADPARM1 );
|
|
if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST )
|
|
return( CRYPT_BADPARM2 );
|
|
if( cryptMode < CRYPT_MODE_NONE || cryptMode > CRYPT_MODE_LAST )
|
|
return( CRYPT_BADPARM3 );
|
|
if( cryptInfoEx == NULL )
|
|
return( CRYPT_BADPARM4 );
|
|
|
|
/* Set all fields to zero */
|
|
memset( cryptInfo, 0, sizeof( CRYPT_INFO ) );
|
|
|
|
/* Set up the pointer to the capability information */
|
|
if( ( cryptInfo->capabilityInfo = findCapabilityInfo( cryptAlgo, cryptMode ) ) == NULL )
|
|
return( ( queryAlgoAvailability( cryptAlgo ) ) ? \
|
|
CRYPT_NOMODE : CRYPT_NOALGO );
|
|
|
|
/* Make sure the algorithm self-test went OK */
|
|
if( cryptInfo->capabilityInfo->selfTestStatus != CRYPT_OK )
|
|
return( CRYPT_SELFTEST );
|
|
|
|
/* Perform any algorithm-specific initialization */
|
|
if( cryptInfo->capabilityInfo->initExFunction != NULL )
|
|
{
|
|
int status;
|
|
|
|
status = cryptInfo->capabilityInfo->initExFunction( cryptInfo, cryptInfoEx );
|
|
if( isStatusError( status ) )
|
|
return( status );
|
|
}
|
|
|
|
/* Set up the IV information to the default values. This can be
|
|
overridden later if required */
|
|
cryptInfo->ivLength = cryptInfo->capabilityInfo->ivSize;
|
|
|
|
/* Set the check value. Note that we set it after the capability info
|
|
has been set, so that a check on this value will also tell us whether
|
|
the capability info is present */
|
|
cryptInfo->checkValue = CRYPT_MAGIC;
|
|
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
/* Destroy an encryption context */
|
|
|
|
CRET destroyCryptContext( CRYPT_INFO CPTR cryptInfo )
|
|
{
|
|
/* Perform basic error checking */
|
|
if( cryptInfo == NULL )
|
|
return( CRYPT_BADPARM1 );
|
|
if( cryptInfo->checkValue != CRYPT_MAGIC ||
|
|
cryptInfo->capabilityInfo == NULL )
|
|
return( CRYPT_NOTINITED );
|
|
|
|
/* Perform any algorithm-specific shutdown */
|
|
if( cryptInfo->capabilityInfo->endFunction != NULL )
|
|
{
|
|
int status;
|
|
|
|
status = cryptInfo->capabilityInfo->endFunction( cryptInfo );
|
|
if( isStatusError( status ) )
|
|
return( status );
|
|
}
|
|
|
|
/* Clear all data in the encryption context */
|
|
memset( cryptInfo, 0, sizeof( CRYPT_INFO ) );
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* Keying Functions *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
/* Load a user key into an encryption context */
|
|
|
|
CRET loadCryptContext( CRYPT_INFO CPTR cryptInfo, void CPTR userKey,
|
|
int userKeyLength )
|
|
{
|
|
int status;
|
|
|
|
/* Perform basic error checking */
|
|
if( cryptInfo == NULL )
|
|
return( CRYPT_BADPARM1 );
|
|
if( userKey == NULL )
|
|
return( CRYPT_BADPARM2 );
|
|
if( cryptInfo->checkValue != CRYPT_MAGIC )
|
|
return( CRYPT_NOTINITED );
|
|
if( userKeyLength < cryptInfo->capabilityInfo->minKeySize ||
|
|
userKeyLength > cryptInfo->capabilityInfo->maxKeySize )
|
|
return( CRYPT_BADPARM3 );
|
|
if( cryptInfo->capabilityInfo->initKeyFunction == NULL )
|
|
return( CRYPT_NOALGO );
|
|
|
|
/* Load the user encryption key into the crypt context */
|
|
memcpy( cryptInfo->userKey, userKey, userKeyLength );
|
|
cryptInfo->userKeyLength = userKeyLength;
|
|
|
|
/* Remember that we need to set an IV before we encrypt anything */
|
|
cryptInfo->ivSet = FALSE;
|
|
|
|
/* Call the encryption routine for this algorithm/mode */
|
|
if( ( status = cryptInfo->capabilityInfo->initKeyFunction( cryptInfo ) ) != CRYPT_OK )
|
|
return( status );
|
|
|
|
/* Record the fact that the key has been initialized */
|
|
cryptInfo->keySet = TRUE;
|
|
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* IV Handling Functions *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
/* Load an IV key into an encryption context */
|
|
|
|
CRET loadIV( CRYPT_INFO CPTR cryptInfo, void CPTR iv, int ivLength )
|
|
{
|
|
/* Perform basic error checking */
|
|
if( cryptInfo == NULL )
|
|
return( CRYPT_BADPARM1 );
|
|
if( cryptInfo->checkValue != CRYPT_MAGIC )
|
|
return( CRYPT_NOTINITED );
|
|
if( ivLength < cryptInfo->capabilityInfo->minIVsize ||
|
|
ivLength > cryptInfo->capabilityInfo->maxIVsize )
|
|
return( CRYPT_BADPARM3 );
|
|
|
|
/* Set the IV length and check whether we'll be using a user-supplied
|
|
IV */
|
|
cryptInfo->ivLength = ivLength;
|
|
cryptInfo->ivCount = 0;
|
|
if( iv != NULL )
|
|
{
|
|
/* Load the IV of the required length. If the required IV size is
|
|
less than the maximum possible IV size, we pad it with zeroes */
|
|
memset( cryptInfo->iv, 0, CRYPT_MAX_IVSIZE );
|
|
memcpy( cryptInfo->iv, iv, cryptInfo->ivLength );
|
|
memcpy( cryptInfo->currentIV, cryptInfo->iv, CRYPT_MAX_IVSIZE );
|
|
cryptInfo->ivSet = TRUE;
|
|
}
|
|
if( cryptInfo->capabilityInfo->initIVFunction != NULL )
|
|
{
|
|
int status;
|
|
|
|
status = cryptInfo->capabilityInfo->initIVFunction( cryptInfo );
|
|
if( isStatusError( status ) )
|
|
return( status );
|
|
}
|
|
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
/* Retrieve an IV from an encryption context */
|
|
|
|
CRET retrieveIV( CRYPT_INFO CPTR cryptInfo, void CPTR iv )
|
|
{
|
|
/* Perform basic error checking */
|
|
if( cryptInfo == NULL )
|
|
return( CRYPT_BADPARM1 );
|
|
if( iv == NULL )
|
|
return( CRYPT_BADPARM2 );
|
|
if( cryptInfo->checkValue != CRYPT_MAGIC )
|
|
return( CRYPT_NOTINITED );
|
|
|
|
/* Make sure the IV has been set */
|
|
if( cryptInfo->ivSet == FALSE )
|
|
return( CRYPT_NOIV );
|
|
|
|
/* Copy the IV data of the required length to the output buffer */
|
|
memcpy( iv, cryptInfo->iv, cryptInfo->ivLength );
|
|
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* Encrypt/Decrypt Routines *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
/* Encrypt a block of memory */
|
|
|
|
CRET encryptBuffer( CRYPT_INFO CPTR cryptInfo, void CPTR buffer, int length )
|
|
{
|
|
/* Perform basic error checking */
|
|
if( cryptInfo == NULL )
|
|
return( CRYPT_BADPARM1 );
|
|
if( buffer == NULL )
|
|
return( CRYPT_BADPARM2 );
|
|
if( length < 0 )
|
|
return( CRYPT_BADPARM3 );
|
|
if( !cryptInfo->keySet )
|
|
return( CRYPT_NOKEY );
|
|
if( cryptInfo->checkValue != CRYPT_MAGIC )
|
|
return( CRYPT_NOTINITED );
|
|
if( cryptInfo->capabilityInfo->encryptFunction == NULL )
|
|
return( CRYPT_NOALGO );
|
|
|
|
/* If there's no IV set, generate one ourselves */
|
|
if( !cryptInfo->ivSet )
|
|
{
|
|
BYTE iv[ CRYPT_MAX_IVSIZE ];
|
|
int status;
|
|
|
|
getIV( iv, cryptInfo->ivLength );
|
|
status = loadIV( cryptInfo, iv, cryptInfo->ivLength );
|
|
if( isStatusError( status ) )
|
|
return( CRYPT_ERROR );
|
|
}
|
|
|
|
/* Call the encryption routine for this algorithm/mode */
|
|
return( cryptInfo->capabilityInfo->encryptFunction( cryptInfo, buffer, length ) );
|
|
}
|
|
|
|
/* Decrypt a block of memory */
|
|
|
|
CRET decryptBuffer( CRYPT_INFO CPTR cryptInfo, void CPTR buffer, int length )
|
|
{
|
|
/* Perform basic error checking */
|
|
if( cryptInfo == NULL )
|
|
return( CRYPT_BADPARM1 );
|
|
if( buffer == NULL )
|
|
return( CRYPT_BADPARM2 );
|
|
if( length < 0 )
|
|
return( CRYPT_BADPARM3 );
|
|
if( !cryptInfo->keySet )
|
|
return( CRYPT_NOKEY );
|
|
if( cryptInfo->checkValue != CRYPT_MAGIC )
|
|
return( CRYPT_NOTINITED );
|
|
if( cryptInfo->capabilityInfo->decryptFunction == NULL )
|
|
return( CRYPT_NOALGO );
|
|
|
|
/* Make sure the IV has been set */
|
|
if( cryptInfo->ivSet == FALSE )
|
|
return( CRYPT_NOIV );
|
|
|
|
/* Call the decryption routine for this algorithm/mode */
|
|
return( cryptInfo->capabilityInfo->decryptFunction( cryptInfo, buffer, length ) );
|
|
}
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* Dynamic Library Update Support *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
/* Add a new encryption capability to the library. This routine is quite
|
|
powerful, but what a kludge! */
|
|
|
|
CRET addCryptCapability( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, \
|
|
int blockSize, char *name, int speed, \
|
|
int minKeySize, int keySize, int maxKeySize )
|
|
{
|
|
int status;
|
|
|
|
/* Add the basic capability information */
|
|
status = addCapability( cryptAlgo, cryptMode, blockSize, name,
|
|
speed, minKeySize, keySize, maxKeySize );
|
|
if( isStatusError( status ) )
|
|
return( status );
|
|
|
|
/* Add the handlers */
|
|
/* Not implemented yet */
|
|
|
|
return( CRYPT_OK );
|
|
}
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* OS-Specific Support Routines *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
#if defined( __WINDOWS__ ) && !( defined( WIN32 ) || defined( _WIN32 ) )
|
|
|
|
/* Whether LibMain() has been called before */
|
|
|
|
static BOOLEAN libMainCalled = FALSE;
|
|
static HWND hInst;
|
|
|
|
/* The main function for the DLL */
|
|
|
|
int CALLBACK LibMain( HINSTANCE hInstance, WORD wDataSeg, WORD wHeapSize, \
|
|
LPSTR lpszCmdLine )
|
|
{
|
|
/* Rot bilong kargo */
|
|
if( wHeapSize > 0 )
|
|
UnlockData( 0 ); /* Allow heap to move */
|
|
|
|
/* If we've been called before, return with an error message */
|
|
if( libMainCalled )
|
|
return( FALSE );
|
|
libMainCalled = TRUE;
|
|
|
|
/* Initialise the library */
|
|
if( initLibrary() != CRYPT_OK )
|
|
return( FALSE );
|
|
|
|
/* Remember the proc instance for later */
|
|
hInst = hInstance;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
/* Shut down the DLL */
|
|
|
|
int CALLBACK WEP( int nSystemExit )
|
|
{
|
|
switch( nSystemExit )
|
|
{
|
|
case WEP_SYSTEM_EXIT:
|
|
/* System is shutting down */
|
|
break;
|
|
|
|
case WEP_FREE_DLL:
|
|
/* DLL reference count = 0, DLL-only shutdown */
|
|
break;
|
|
}
|
|
|
|
/* Shut down the encryption library if necessary */
|
|
endLibrary();
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
#elif defined( __WINDOWS__ ) && ( defined( WIN32 ) || defined( _WIN32 ) )
|
|
|
|
/* Whether LibMain() has been called before */
|
|
|
|
static BOOLEAN libMainCalled = FALSE;
|
|
static HWND hInst;
|
|
|
|
int LibMain( HANDLE hInstance, ULONG ulReasonCalled, LPVOID lpReserved )
|
|
{
|
|
/* If we've been called before, return with an error message */
|
|
if( libMainCalled )
|
|
return( FALSE );
|
|
libMainCalled = TRUE;
|
|
|
|
/* Initialise the library */
|
|
if( initLibrary() != CRYPT_OK )
|
|
return( FALSE );
|
|
|
|
/* Remember the proc instance for later */
|
|
hInst = hInstance;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
int CALLBACK WEP( int nSystemExit )
|
|
{
|
|
/* Shut down the encryption library if necessary */
|
|
endLibrary();
|
|
|
|
return( TRUE );
|
|
}
|
|
#endif /* __WINDOWS__ */
|