📄 testll.c
字号:
/****************************************************************************
* *
* cryptlib Low-level Test Routines *
* Copyright Peter Gutmann 1995-2003 *
* *
****************************************************************************/
#ifdef _MSC_VER
#include "../cryptlib.h"
#include "../test/test.h"
#else
#include "cryptlib.h"
#include "test/test.h"
#endif /* Braindamaged VC++ include handling */
#if defined( __MVS__ ) || defined( __VMCMS__ )
/* Suspend conversion of literals to ASCII. */
#pragma convlit( suspend )
#endif /* EBCDIC systems */
/* The size of the test buffers */
#define TESTBUFFER_SIZE 256
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Check for an algorithm/mode */
static BOOLEAN checkLowlevelInfo( const CRYPT_DEVICE cryptDevice,
const CRYPT_ALGO_TYPE cryptAlgo )
{
CRYPT_QUERY_INFO cryptQueryInfo;
const BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;
int status;
if( isDevice )
status = cryptDeviceQueryCapability( cryptDevice, cryptAlgo,
&cryptQueryInfo );
else
status = cryptQueryCapability( cryptAlgo, &cryptQueryInfo );
if( cryptStatusError( status ) )
{
printf( "crypt%sQueryCapability() reports algorithm %d is not "
"available, status = %d.\n", isDevice ? "Device" : "",
cryptAlgo, status );
return( FALSE );
}
printf( "cryptQueryCapability() reports availability of %s algorithm "
"with\n block size %d bits", cryptQueryInfo.algoName,
cryptQueryInfo.blockSize << 3 );
if( cryptAlgo < CRYPT_ALGO_FIRST_HASH || cryptAlgo > CRYPT_ALGO_LAST_HASH )
{
printf( ", keysize %d-%d bits (recommended = %d bits)",
cryptQueryInfo.minKeySize << 3,
cryptQueryInfo.maxKeySize << 3, cryptQueryInfo.keySize << 3 );
}
puts( "." );
return( TRUE );
}
/* Set a pair of encrypt/decrypt buffers to a known state, and make sure
that they're still in that known state */
static void initTestBuffers( BYTE *buffer1, BYTE *buffer2, const int length )
{
#if defined( __MVS__ ) || defined( __VMCMS__ )
#pragma convlit( resume )
#endif /* EBCDIC systems */
/* Set the buffers to a known state */
memset( buffer1, '*', length );
memcpy( buffer1, "12345678", 8 ); /* For endianness check */
if( buffer2 != NULL )
memcpy( buffer2, buffer1, length );
#if defined( __MVS__ ) || defined( __VMCMS__ )
#pragma convlit( suspend )
#endif /* EBCDIC systems */
}
static BOOLEAN checkTestBuffers( const BYTE *buffer1, const BYTE *buffer2 )
{
/* Make sure that 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 );
}
/* Load the encryption contexts */
static BOOLEAN loadContexts( CRYPT_CONTEXT *cryptContext, CRYPT_CONTEXT *decryptContext,
const CRYPT_DEVICE cryptDevice,
const CRYPT_ALGO_TYPE cryptAlgo,
const CRYPT_MODE_TYPE 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 */
return( status );
printf( "Encryption mode %d selection failed with status %d.\n",
cryptMode, status );
return( FALSE );
}
}
if( hasKey )
{
status = cryptSetAttributeString( *cryptContext, CRYPT_CTXINFO_KEY,
key, length );
if( length > 16 && status == CRYPT_ERROR_PARAM4 )
{
status = cryptSetAttributeString( *cryptContext, CRYPT_CTXINFO_KEY,
key, 16 );
if( cryptStatusOK( status ) )
{
puts( " Load of full-length key failed, using shorter 128-"
"bit key." );
adjustKey = TRUE;
}
}
if( cryptStatusError( status ) )
{
printf( "Key load failed with error code %d.\n", status );
return( FALSE );
}
}
if( decryptContext == NULL )
return( TRUE );
/* Create the decryption context */
if( cryptDevice == CRYPT_UNUSED )
status = cryptCreateContext( decryptContext, CRYPT_UNUSED, cryptAlgo );
else
status = cryptDeviceCreateContext( cryptDevice, decryptContext,
cryptAlgo );
if( cryptStatusError( status ) )
{
printf( "crypt%sCreateContext() failed with error code %d.\n",
( cryptDevice != CRYPT_UNUSED ) ? "Device" : "", status );
return( FALSE );
}
if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
{
status = cryptSetAttribute( *decryptContext, 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 */
return( status );
printf( "Encryption mode %d selection failed with status %d.\n",
cryptMode, status );
return( FALSE );
}
}
if( hasKey )
{
status = cryptSetAttributeString( *decryptContext, CRYPT_CTXINFO_KEY,
key, adjustKey ? 16 : length );
if( cryptStatusError( status ) )
{
printf( "Key load failed with error code %d.\n", status );
return( FALSE );
}
}
return( TRUE );
}
/* Perform a test en/decryption */
int testCrypt( CRYPT_CONTEXT cryptContext, CRYPT_CONTEXT decryptContext,
BYTE *buffer, const BOOLEAN isDevice,
const BOOLEAN noWarnFail )
{
BYTE iv[ CRYPT_MAX_IVSIZE ];
BYTE localBuffer[ TESTBUFFER_SIZE ];
int cryptAlgo, cryptMode, status;
/* If the user hasn't supplied a test buffer, use our own one */
if( buffer == NULL )
{
buffer = localBuffer;
initTestBuffers( buffer, NULL, TESTBUFFER_SIZE );
}
/* 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 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -