📄 testll.c
字号:
/****************************************************************************
* *
* cryptlib Low-level Test Routines *
* Copyright Peter Gutmann 1995-2001 *
* *
****************************************************************************/
#ifdef _MSC_VER
#include "../cryptlib.h"
#include "../test/test.h"
#else
#include "cryptlib.h"
#include "test/test.h"
#endif /* Braindamaged VC++ include handling */
/* The size of the test buffers */
#define TESTBUFFER_SIZE 256
/****************************************************************************
* *
* Low-level Routines Test *
* *
****************************************************************************/
#if defined( TEST_LOWLEVEL ) || defined( TEST_DEVICE )
/* 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, const int length )
{
/* Set the buffers to a known state */
memset( buffer1, '*', length );
memcpy( buffer1, "12345678", 8 ); /* For endianness check */
memcpy( buffer2, buffer1, length );
}
static BOOLEAN checkTestBuffers( const BYTE *buffer1, const BYTE *buffer2 )
{
/* Make sure everything went OK */
if( memcmp( buffer1, buffer2, TESTBUFFER_SIZE ) )
{
puts( "Error: Decrypted data != original plaintext." );
/* Try and guess at block chaining problems */
if( !memcmp( buffer1, "12345678****", 12 ) )
puts( "\t\bIt 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\bIt looks like the 32-bit word endianness is "
"reversed." );
else
if( !memcmp( buffer1, "2143", 4 ) )
puts( "\t\bIt looks like the 16-bit word endianness is "
"reversed." );
else
if( buffer1[ 0 ] >= '1' && buffer1[ 0 ] <= '9' )
puts( "\t\bIt looks like there's some sort of endianness "
"problem which is\n\t more complex than just a "
"reversal." );
else
puts( "\t\bIt's probably more than just an endianness "
"problem." );
return( FALSE );
}
return( TRUE );
}
/* Perform a test en/decryption */
static int testCrypt( CRYPT_CONTEXT cryptContext, CRYPT_CONTEXT decryptContext,
BYTE *buffer, const BOOLEAN isDevice )
{
BYTE iv[ CRYPT_MAX_IVSIZE ];
int cryptAlgo, cryptMode, status;
/* Find out about the algorithm we're using */
cryptGetAttribute( cryptContext, CRYPT_CTXINFO_ALGO, &cryptAlgo );
cryptGetAttribute( cryptContext, CRYPT_CTXINFO_MODE, &cryptMode );
if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \
( cryptMode == CRYPT_MODE_CFB || cryptMode == CRYPT_MODE_OFB ) )
{
/* Encrypt the buffer in two odd-sized chunks */
status = cryptEncrypt( cryptContext, buffer, 79 );
if( cryptStatusOK( status ) )
status = cryptEncrypt( cryptContext, buffer + 79,
TESTBUFFER_SIZE - 79 );
if( cryptStatusError( status ) )
{
printf( "Couldn't encrypt data, status = %d.\n", status );
return( status );
}
/* Copy the IV from the encryption to the decryption context if
necessary */
if( cryptAlgo != CRYPT_ALGO_RC4 )
{
int ivLength;
status = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_IV,
iv, &ivLength );
if( cryptStatusError( status ) )
{
printf( "Couldn't retrieve IV after encryption, status = %d.\n",
status );
return( status );
}
status = cryptSetAttributeString( decryptContext, CRYPT_CTXINFO_IV,
iv, ivLength );
if( cryptStatusError( status ) )
{
printf( "Couldn't load IV for decryption, status = %d.\n", status );
return( status );
}
}
/* Decrypt the buffer in different odd-size chunks */
status = cryptDecrypt( decryptContext, buffer, 125 );
if( cryptStatusOK( status ) )
status = cryptDecrypt( decryptContext, buffer + 125,
TESTBUFFER_SIZE - 125 );
if( cryptStatusError( status ) )
{
printf( "Couldn't decrypt data, status = %d.\n", status );
return( status );
}
return( CRYPT_OK );
}
if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \
( cryptMode == CRYPT_MODE_ECB || cryptMode == CRYPT_MODE_CBC ) )
{
/* Encrypt the buffer in two odd-sized chunks */
status = cryptEncrypt( cryptContext, buffer, 80 );
if( cryptStatusOK( status ) )
status = cryptEncrypt( cryptContext, buffer + 80,
TESTBUFFER_SIZE - 80 );
if( cryptStatusOK( status ) )
status = cryptEncrypt( cryptContext, buffer + TESTBUFFER_SIZE, 0 );
if( cryptStatusError( status ) )
{
printf( "Couldn't encrypt data, status = %d.\n", status );
return( status );
}
/* Copy the IV from the encryption to the decryption context if
necessary */
if( cryptMode != CRYPT_MODE_ECB )
{
int ivLength;
status = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_IV,
iv, &ivLength );
if( cryptStatusError( status ) )
printf( "Couldn't retrieve IV after encryption, status = %d.\n",
status );
status = cryptSetAttributeString( decryptContext, CRYPT_CTXINFO_IV,
iv, ivLength );
if( cryptStatusError( status ) )
printf( "Couldn't load IV for decryption, status = %d.\n", status );
status = cryptEncrypt( cryptContext, buffer + TESTBUFFER_SIZE, 0 );
}
/* Decrypt the buffer in different odd-size chunks */
status = cryptDecrypt( decryptContext, buffer, 128 );
if( cryptStatusOK( status ) )
status = cryptDecrypt( decryptContext, buffer + 128,
TESTBUFFER_SIZE - 128 );
if( cryptStatusOK( status ) )
status = cryptDecrypt( decryptContext, buffer + TESTBUFFER_SIZE, 0 );
if( cryptStatusError( status ) )
{
printf( "Couldn't decrypt data, status = %d.\n", status );
return( status );
}
return( CRYPT_OK );
}
if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
{
static const BYTE rsa512Value[] = \
"\x4E\x1F\x2F\x10\xA9\xFB\x4F\xD9\xC1\x25\x79\x7A\x36\x00\x58\xD0"
"\x9E\x8B\x9F\xBA\xC7\x04\x10\x77\xDB\xBC\xC9\xD1\x70\xCD\xF6\x86"
"\xA4\xDC\x39\xA9\x57\xD7\xC7\xE0\x87\xF2\x31\xDF\x83\x7d\x27\x0E"
"\xB4\xA6\x93\x3D\x11\xEB\xA5\x0E\x42\x66\x7B\x30\x50\x84\xC1\x81";
static const BYTE rsa1024Value[] = \
"\x84\x8E\x00\x3E\x49\x11\x0D\x42\x4C\x71\x6B\xB4\xCF\x13\xDD\xCD"
"\x12\x30\x56\xC2\x4A\x55\x3B\xD8\x30\xA2\xB8\x73\xA7\xAB\xF0\x7A"
"\x2E\x07\x20\xCC\xBE\xEA\x58\x03\x56\xF6\x18\x27\x28\x4F\xE1\x02"
"\xC6\x49\x79\x6C\xB4\x7E\x6C\xC6\x93\x2E\xF1\x46\x83\x15\x5A\xB7"
"\x7D\xCC\x21\xEE\x4E\x3E\x0B\x8B\x85\xEE\x08\x21\xE6\xA7\x31\x53"
"\x2E\x92\x3D\x2D\xB0\xD4\xA1\x30\xF4\xE9\xEB\x37\xBF\xCD\x2F\xE1"
"\x60\x89\x19\xB6\x8C\x01\xFB\xD8\xAC\xF5\xC7\x4B\xB4\x74\x8A\x35"
"\x79\xE6\xE0\x48\xBD\x9C\x9F\xD7\x4A\x1C\x8A\x58\xAB\xA9\x3C\x44";
BYTE testBuffer[ TESTBUFFER_SIZE ], tmpBuffer[ 32 ];
BOOLEAN encryptOK = TRUE;
int length;
/* Take a copy of the input so we can compare it with decrypted
output and find out how much data we need to process */
memcpy( testBuffer, buffer, TESTBUFFER_SIZE );
cryptGetAttribute( cryptContext, CRYPT_CTXINFO_KEYSIZE, &length );
/* Since we're doing raw RSA encryption we need to format the data
specially to work with the RSA key being used. If we're using the
cryptlib native routines, we need to ensure that the magnitude of
the integer corresponding to the data to be encrypted is less than
the modulus, which we do by setting the first byte of the buffer
to 1. If we're using a crypto device, we need to create a (dummy)
PKCS #1-like format since some devices expect to see PKCS #1-
formatted data as input to/output from the RSA encryption/
decryption operation */
memcpy( tmpBuffer, buffer, 18 );
if( isDevice )
memcpy( buffer, "\x00\x02\xA5\xA5\xA5\xA5\xA5\xA5"
"\xA5\xA5\xA5\xA5\xA5\xA5\xA5\xA5"
"\xA5\x00", 18 );
else
buffer[ 0 ] = 1;
/* Since the PKC algorithms only handle a single block, we only
perform a single encrypt and decrypt operation */
status = cryptEncrypt( cryptContext, buffer, length );
if( cryptStatusError( status ) )
{
printf( "Couldn't encrypt data, status = %d.\n", status );
return( status );
}
if( cryptAlgo == CRYPT_ALGO_RSA && !isDevice && \
memcmp( buffer, ( length == 64 ) ? rsa512Value : rsa1024Value,
length ) )
{
/* For a non-randomized PKC the encryption of the fixed value
produces known output, we make sure this matches the expected
value. This makes diagnosing problems with crypto devices
rather easier */
puts( "The actual encrypted value doesn't match the expected value." );
encryptOK = FALSE;
}
status = cryptDecrypt( decryptContext, buffer, length );
if( cryptStatusError( status ) )
{
if( encryptOK )
printf( "Couldn't decrypt data even though the encrypted "
"input data was valid,\nstatus = %d.\n", status );
else
printf( "Couldn't decrypt data, probably because the data "
"produced by the encrypt step\nwas invalid, status = "
"%d.\n", status );
return( status );
}
if( isDevice )
memcpy( buffer, tmpBuffer, 18 );
else
buffer[ 0 ] = tmpBuffer[ 0 ];
/* Make sure the recovered result matches the input data */
if( memcmp( buffer, testBuffer, length ) )
{
if( encryptOK )
/* This could happen with simple-minded CRT implementations
which only work when p > q (the test key has p < q in
order to find this problem) */
puts( "Decryption failed even though encryption produced "
"valid data. The RSA\ndecryption step is broken." );
else
puts( "Decryption failed because the encryption step "
"produced invalid data. The RSA\nencryption step is "
"broken." );
return( status );
}
else
if( !encryptOK )
{
puts( "Decryption succeeded even though encryption produced "
"invalid data. The RSA\nimplementation is broken." );
return( status );
}
return( CRYPT_OK );
}
if( cryptAlgo >= CRYPT_ALGO_FIRST_HASH && \
cryptAlgo <= CRYPT_ALGO_LAST_MAC )
{
/* Hash the buffer in two odd-sized chunks */
status = cryptEncrypt( cryptContext, buffer, 80 );
if( cryptStatusOK( status ) )
status = cryptEncrypt( cryptContext, buffer + 80,
TESTBUFFER_SIZE - 80 );
if( cryptStatusOK( status ) )
status = cryptEncrypt( cryptContext, buffer + TESTBUFFER_SIZE, 0 );
if( cryptStatusError( status ) )
{
printf( "Couldn't hash data, status = %d.\n", status );
return( status );
}
/* Hash the buffer in different odd-size chunks */
status = cryptEncrypt( decryptContext, buffer, 128 );
if( cryptStatusOK( status ) )
status = cryptEncrypt( decryptContext, buffer + 128,
TESTBUFFER_SIZE - 128 );
if( cryptStatusOK( status ) )
status = cryptEncrypt( decryptContext, buffer + TESTBUFFER_SIZE, 0 );
if( cryptStatusError( status ) )
{
printf( "Couldn't hash data, status = %d.\n", status );
return( status );
}
return( status );
}
printf( "Unknown encryption algorithm/mode %d.\n", cryptAlgo );
return( CRYPT_OK );
}
/* Load the encryption contexts */
static BOOLEAN loadContexts( CRYPT_CONTEXT *cryptContext, CRYPT_CONTEXT *decryptContext,
const CRYPT_DEVICE cryptDevice,
const CRYPT_ALGO cryptAlgo,
const CRYPT_MODE cryptMode,
const BYTE *key, const int length )
{
const BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;
const BOOLEAN hasKey = ( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL ) || \
( cryptAlgo >= CRYPT_ALGO_FIRST_MAC && \
cryptAlgo <= CRYPT_ALGO_LAST_MAC );
BOOLEAN adjustKey = FALSE;
int status;
/* Create the encryption context */
if( isDevice )
status = cryptDeviceCreateContext( cryptDevice, cryptContext,
cryptAlgo );
else
status = cryptCreateContext( cryptContext, CRYPT_UNUSED, cryptAlgo );
if( cryptStatusError( status ) )
{
printf( "crypt%sCreateContext() failed with error code %d.\n",
isDevice ? "Device" : "", status );
return( FALSE );
}
if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
{
status = cryptSetAttribute( *cryptContext, CRYPT_CTXINFO_MODE,
cryptMode );
if( cryptStatusError( status ) )
{
cryptDestroyContext( *cryptContext );
if( status == CRYPT_ERROR_NOTAVAIL )
/* This mode isn't available, return a special-case value to
tell the calling code to continue */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -