Files
des_undes/third_party/cryptlib-0.99/test.c
T

520 lines
16 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "crypt.h"
/* The size of the test buffers */
#define TESTBUFFER_SIZE 256
/* Work routines: Set a pair of encrypt/decrypt buffers to a known state,
and make sure they're still in that known state */
static void initTestBuffers( BYTE *buffer1, BYTE *buffer2 )
{
/* Set the buffers to a known state */
memset( buffer1, '*', TESTBUFFER_SIZE );
memcpy( buffer1, "12345678", 8 ); /* For endianness check */
memcpy( buffer2, buffer1, TESTBUFFER_SIZE );
}
static void checkTestBuffers( BYTE *buffer1, BYTE *buffer2 )
{
/* Make sure everything went OK */
if( memcmp( buffer1, buffer2, TESTBUFFER_SIZE ) )
{
puts( "Warning: Decrypted data != original plaintext." );
/* Try and guess at block chaining problems */
if( !memcmp( buffer1, "12345678****", 12 ) )
puts( "\t It looks like there's a problem with block chaining." );
else
/* Try and guess at endianness problems - we want "1234" */
if( !memcmp( buffer1, "4321", 4 ) )
puts( "\t It looks like the 32-bit word endianness is "
"reversed." );
else
if( !memcmp( buffer1, "2143", 4 ) )
puts( "\t It looks like the 16-bit word endianness is "
"reversed." );
else
if( buffer1[ 0 ] >= '1' && buffer1[ 0 ] <= '9' )
puts( "\t It looks like there's some sort of endianness "
"problem which is\n\t more complex than just a "
"reversal." );
else
puts( "\t It's probably more than just an endianness "
"problem." );
}
}
/* Report information on the encryption algorithm */
static void reportAlgorithmInformation( char *algorithmName,
CRYPT_QUERY_INFO *cryptQueryInfo )
{
char speedFactor[ 50 ];
/* Determine the speed factor relative to a block copy */
if( cryptQueryInfo->speed == CRYPT_ERROR )
strcpy( speedFactor, "unknown speed factor" );
else
sprintf( speedFactor, "0.%03d times the speed of a block copy",
cryptQueryInfo->speed );
printf( "%s algorithm is available with\n"
" name `%s', block size %d bits, %s,\n"
" min key size %d bits, recommended key size %d bits, "
"max key size %d bits,\n"
" min IV size %d bits, recommended IV size %d bits, "
"max IV size %d bits.\n",
algorithmName, cryptQueryInfo->algoName,
bytesToBits( cryptQueryInfo->blockSize ), speedFactor,
bytesToBits( cryptQueryInfo->minKeySize ),
bytesToBits( cryptQueryInfo->keySize ),
bytesToBits( cryptQueryInfo->maxKeySize ),
bytesToBits( cryptQueryInfo->minIVsize ),
bytesToBits( cryptQueryInfo->ivSize ),
bytesToBits( cryptQueryInfo->maxIVsize ) );
}
/* Check the library for an algorithm/mode */
static BOOLEAN checkLibraryInfo( char *name, char *longName,
CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode )
{
CRYPT_QUERY_INFO cryptQueryInfo;
int status;
status = queryAlgoAvailability( cryptAlgo );
if( isStatusError( status ) )
{
printf( "queryAlgoAvailability() reports %s is not available: "
"Code %d.\n", name, status );
return( FALSE );
}
status = queryModeAvailability( cryptAlgo, cryptMode );
if( isStatusError( status ) )
{
printf( "queryModeAvailability() reports %s is not available: "
"Code %d.\n", longName, status );
return( FALSE );
}
status = queryAlgoModeInformation( cryptAlgo, cryptMode, &cryptQueryInfo );
printf( "queryModeAvailability() reports " );
if( isStatusOK( status ) )
reportAlgorithmInformation( longName, &cryptQueryInfo );
else
{
printf( "no information available on %s algorithm: Code %d.\n",
name, status );
return( FALSE );
}
return( TRUE );
}
/* Load the encryption contexts */
static BOOLEAN loadContexts( CRYPT_INFO *cryptInfo, CRYPT_INFO *decryptInfo,
CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode,
BYTE *key, int length )
{
int status;
/* Create the encryption context */
status = initCryptContext( cryptInfo, cryptAlgo, cryptMode );
if( isStatusError( status ) )
{
printf( "initCryptContext(): Failed with error code %d.\n", status );
return( FALSE );
}
status = loadCryptContext( cryptInfo, key, length );
if( isStatusError( status ) )
{
printf( "loadCryptContext(): Failed with error code %d.\n", status );
return( FALSE );
}
/* Create the decryption context */
status = initCryptContext( decryptInfo, cryptAlgo, cryptMode );
if( isStatusError( status ) )
{
printf( "initCryptContext(): Failed with error code %d.\n", status );
return( FALSE );
}
status = loadCryptContext( decryptInfo, key, length );
if( isStatusError( status ) )
{
printf( "loadCryptContext(): Failed with error code %d.\n", status );
return( FALSE );
}
return( TRUE );
}
/* Perform a test en/decryption */
static void testCrypt( CRYPT_INFO *cryptInfo, CRYPT_INFO *decryptInfo,
BYTE *buffer )
{
CRYPT_QUERY_INFO cryptQueryInfo;
BYTE iv[ 100 ];
int status;
/* Find out about the algorithm we're using */
queryContextInformation( cryptInfo, &cryptQueryInfo );
if( cryptQueryInfo.cryptMode == CRYPT_MODE_CFB ||
cryptQueryInfo.cryptMode == CRYPT_MODE_OFB ||
cryptQueryInfo.cryptMode == CRYPT_MODE_STREAM )
{
/* Encrypt the buffer in two odd-sized chunks */
status = encryptBuffer( cryptInfo, buffer, 79 );
if( isStatusError( status ) )
printf( "Couldn't encrypt data: Code %d.\n", status );
status = encryptBuffer( cryptInfo, buffer + 79, TESTBUFFER_SIZE - 79 );
if( isStatusError( status ) )
printf( "Couldn't encrypt data: Code %d.\n", status );
status = encryptBuffer( cryptInfo, buffer + TESTBUFFER_SIZE, 0 );
/* Copy the IV from the encryption to the decryption context */
status = retrieveIV( cryptInfo, iv );
if( isStatusError( status ) )
printf( "Couldn't retrieve IV after encryption: Code %d.\n",
status );
status = loadIV( decryptInfo, iv, cryptQueryInfo.ivSize );
if( isStatusError( status ) )
printf( "Couldn't load IV for decryption: Code %d.\n", status );
/* Decrypt the buffer in different odd-size chunks */
status = decryptBuffer( decryptInfo, buffer, 125 );
if( isStatusError( status ) )
printf( "Couldn't decrypt data: Code %d.\n", status );
status = decryptBuffer( decryptInfo, buffer + 125, TESTBUFFER_SIZE - 125 );
if( isStatusError( status ) )
printf( "Couldn't decrypt data: Code %d.\n", status );
return;
}
if( cryptQueryInfo.cryptMode == CRYPT_MODE_ECB ||
cryptQueryInfo.cryptMode == CRYPT_MODE_CBC ||
cryptQueryInfo.cryptMode == CRYPT_MODE_PCBC )
{
/* Encrypt the buffer in two odd-sized chunks */
status = encryptBuffer( cryptInfo, buffer, 80 );
if( isStatusError( status ) )
printf( "Couldn't encrypt data: Code %d.\n", status );
status = encryptBuffer( cryptInfo, buffer + 80, TESTBUFFER_SIZE - 80 );
if( isStatusError( status ) )
printf( "Couldn't encrypt data: Code %d.\n", status );
status = encryptBuffer( cryptInfo, buffer + TESTBUFFER_SIZE, 0 );
/* Copy the IV from the encryption to the decryption context */
status = retrieveIV( cryptInfo, iv );
if( isStatusError( status ) )
printf( "Couldn't retrieve IV after encryption: Code %d.\n",
status );
status = loadIV( decryptInfo, iv, cryptQueryInfo.ivSize );
if( isStatusError( status ) )
printf( "Couldn't load IV for decryption: Code %d.\n", status );
/* Decrypt the buffer in different odd-size chunks */
status = decryptBuffer( decryptInfo, buffer, 128 );
if( isStatusError( status ) )
printf( "Couldn't decrypt data: Code %d.\n", status );
status = decryptBuffer( decryptInfo, buffer + 128, TESTBUFFER_SIZE - 128 );
if( isStatusError( status ) )
printf( "Couldn't decrypt data: Code %d.\n", status );
return;
}
puts( "Unknown encryption mode found in test code." );
}
/* Destroy the encryption contexts */
static void destroyContexts( CRYPT_INFO *cryptInfo, CRYPT_INFO *decryptInfo )
{
int status;
status = destroyCryptContext( cryptInfo );
if( isStatusError( status ) )
printf( "destroyCryptContext(): Failed with error code %d.\n", status );
status = destroyCryptContext( decryptInfo );
if( isStatusError( status ) )
printf( "destroyCryptContext(): Failed with error code %d.\n", status );
}
/* Sample code to test an algorithm/mode implementation */
static int testLibrary( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode,
char *name, char *longName )
{
BYTE buffer[ TESTBUFFER_SIZE ], testBuffer[ TESTBUFFER_SIZE ];
CRYPT_INFO cryptInfo, decryptInfo;
CRYPT_INFO_MDCSHS cryptInfoEx;
int status;
/* Initialise the test buffers */
initTestBuffers( buffer, testBuffer );
/* Check the capabilities of the library */
putchar( '\n' );
if( !checkLibraryInfo( name, longName, cryptAlgo, cryptMode ) )
return( FALSE );
/* Set up an encryption context, load a user key into it, and perform a
key setup */
switch( cryptAlgo )
{
case CRYPT_ALGO_MDCSHS:
/* We use an extended setup with reduced iteration count for
people who have to run this thing 2000 times while debugging */
cryptInfoEx.keySetupIterations = 10;
status = initCryptContextEx( &cryptInfo, cryptAlgo, cryptMode,
&cryptInfoEx );
if( isStatusError( status ) )
{
printf( "initCryptContext(): Failed with error code %d.\n",
status );
return( FALSE );
}
status = loadCryptContext( &cryptInfo, "Test key", 8 );
if( isStatusError( status ) )
{
printf( "loadCryptContext(): Failed with error code %d.\n",
status );
return( FALSE );
}
/* Create another crypt context for decryption. The error
checking here is a bit less picky to save space */
cryptInfoEx.keySetupIterations = 10;
initCryptContextEx( &decryptInfo, cryptAlgo, cryptMode,
&cryptInfoEx );
status = loadCryptContext( &decryptInfo, "Test key", 8 );
if( isStatusError( status ) )
{
printf( "loadCryptContext(): Failed with error code %d.\n",
status );
return( FALSE );
}
break;
case CRYPT_ALGO_DES:
if( !loadContexts( &cryptInfo, &decryptInfo, cryptAlgo, cryptMode,
( BYTE * ) "1234567", 7 ) )
return( FALSE );
break;
case CRYPT_ALGO_3DES:
if( !loadContexts( &cryptInfo, &decryptInfo, cryptAlgo, cryptMode,
( BYTE * ) "12345677654321", 14 ) )
return( FALSE );
break;
case CRYPT_ALGO_IDEA:
if( !loadContexts( &cryptInfo, &decryptInfo, cryptAlgo, cryptMode,
( BYTE * ) "1234567887654321", 16 ) )
return( FALSE );
break;
case CRYPT_ALGO_RC4:
if( !loadContexts( &cryptInfo, &decryptInfo, cryptAlgo, cryptMode,
( BYTE * ) "12345678900987654321", 20 ) )
return( FALSE );
break;
case CRYPT_ALGO_SAFER:
if( !loadContexts( &cryptInfo, &decryptInfo, cryptAlgo, cryptMode,
( BYTE * ) "1234567887654321", 16 ) )
return( FALSE );
break;
default:
printf( "Unknown encryption algorithm = ID %d, cannot perform "
"encryption test\n", cryptAlgo );
return( FALSE );
}
/* Perform a test en/decryption */
testCrypt( &cryptInfo, &decryptInfo, buffer );
/* Make sure everything went OK */
checkTestBuffers( buffer, testBuffer );
/* Destroy the encryption contexts */
destroyContexts( &cryptInfo, &decryptInfo );
return( TRUE );
}
/* Exercise various aspects of the encryption library */
int main( int argc, char **argv )
{
int status, bigEndian;
/* Get rid of compiler warning */
if( argc || argv );
/* Make sure we've got the endianness set right. If the machine is
big-endian (up to 64 bits) the following value will be signed,
otherwise it will be unsigned. Unfortunately we can't test for
things like middle-endianness without knowing the size of the data
types */
bigEndian = ( *( long * ) "\x80\x00\x00\x00\x00\x00\x00\x00" < 0 );
#ifdef LITTLE_ENDIAN
if( bigEndian )
{
puts( "The CPU endianness define is set wrong in crypt.h, this "
"machine appears to be\nbig-endian, not little-endian. Edit "
"the file and rebuild the library." );
exit( EXIT_FAILURE );
}
#else
if( !bigEndian )
{
puts( "The CPU endianness define is set wrong in crypt.h, this "
"machine appears to be\nlittle-endian, not big-endian. Edit "
"the file and rebuild the library." );
exit( EXIT_FAILURE );
}
#endif /* LITTLE_ENDIAN */
/* If we're compiling under Windoze, make sure that this weeks version
of Visual C gets the LONG type right */
#ifdef __WINDOWS__
{
LONG test = 0x80000000L;
if( test < 0 )
{
puts( "typeof( LONG ) is incorrect. It evaluates to a signed 32-bit "
"value rather\nthan an unsigned 32-bit value. You need to edit "
"crypt.h and recompile the\nencryption library" );
exit( EXIT_FAILURE );
}
}
#endif /* __WINDOWS__ */
/* Initialise the library */
status = initLibrary();
if( isStatusError( status ) )
{
printf( "Couldn't init library, code %d.\n", status );
exit( EXIT_FAILURE );
}
/* Test the encryption routines contained in the library */
#if 1
if( !testLibrary( CRYPT_ALGO_MDCSHS, CRYPT_MODE_CFB, "MDC/SHS",
"MDC/SHS-CFB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_DES, CRYPT_MODE_ECB, "DES", "DES-ECB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_DES, CRYPT_MODE_CBC, "DES", "DES-CBC" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_DES, CRYPT_MODE_CFB, "DES", "DES-CFB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_DES, CRYPT_MODE_OFB, "DES", "DES-OFB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_DES, CRYPT_MODE_PCBC, "DES", "DES-PCBC" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_3DES, CRYPT_MODE_ECB, "3DES", "3DES-ECB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_3DES, CRYPT_MODE_CBC, "3DES", "3DES-CBC" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_3DES, CRYPT_MODE_CFB, "3DES", "3DES-CFB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_3DES, CRYPT_MODE_OFB, "3DES", "3DES-OFB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_IDEA, CRYPT_MODE_ECB, "IDEA", "IDEA-ECB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_IDEA, CRYPT_MODE_CBC, "IDEA", "IDEA-CBC" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_IDEA, CRYPT_MODE_CFB, "IDEA", "IDEA-CFB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_IDEA, CRYPT_MODE_OFB, "IDEA", "IDEA-OFB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_RC4, CRYPT_MODE_STREAM, "RC4", "RC4" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_SAFER, CRYPT_MODE_ECB, "SAFER", "SAFER-ECB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_SAFER, CRYPT_MODE_CBC, "SAFER", "SAFER-CBC" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_SAFER, CRYPT_MODE_CFB, "SAFER", "SAFER-CFB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
if( !testLibrary( CRYPT_ALGO_SAFER, CRYPT_MODE_OFB, "SAFER", "SAFER-OFB" ) )
{
puts( "Tests aborted due to encryption library error." );
exit( EXIT_FAILURE );
}
#endif /* 0 or 1 */
/* Shut down the library */
status = endLibrary();
if( isStatusError( status ) )
{
printf( "endLibrary(): Failed with error code %d.\n", status );
exit( EXIT_FAILURE );
}
return( EXIT_SUCCESS );
}