📄 lowlvl.c
字号:
/****************************************************************************
* *
* cryptlib Low-level Test Routines *
* Copyright Peter Gutmann 1995-2004 *
* *
****************************************************************************/
#ifdef _MSC_VER
#include "../cryptlib.h"
#include "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 /* IBM big iron */
#if defined( __ILEC400__ )
#pragma convert( 0 )
#endif /* IBM medium iron */
/* The size of the test buffers */
#define TESTBUFFER_SIZE 256
/* Since the DH operations aren't visible externally, we have to use the
kernel API to perform the test. To get the necessary definitions and
prototypes, we have to use crypt.h, however since we've already included
cryptlib.h the built-in guards preclude us from pulling it in again with
the internal-only values defined, so we have to explicitly define things
like attribute values that normally aren't visible externally */
#ifdef TEST_DH
#undef __WINDOWS__
#undef __WIN16__
#undef __WIN32__
#undef BYTE
#ifdef _MSC_VER
#define INC_CHILD
#include "../crypt.h"
#else
#include "crypt.h"
#endif /* Braindamaged MSC include handling */
#endif /* TEST_DH */
/****************************************************************************
* *
* 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 );
}
#ifdef UNICODE_STRINGS
printf( "cryptQueryCapability() reports availability of %S algorithm "
"with\n block size %d bits", cryptQueryInfo.algoName,
cryptQueryInfo.blockSize << 3 );
#else
printf( "cryptQueryCapability() reports availability of %s algorithm "
"with\n block size %d bits", cryptQueryInfo.algoName,
cryptQueryInfo.blockSize << 3 );
#endif /* UNICODE_STRINGS */
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 /* IBM big iron */
#if defined( __ILEC400__ )
#pragma convert( 819 )
#endif /* IBM medium iron */
/* 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 /* IBM big iron */
#if defined( __ILEC400__ )
#pragma convert( 0 )
#endif /* IBM medium iron */
}
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( 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 );
}
/* Decrypt the buffer in different odd-size chunks */
status = cryptDecrypt( decryptContext, buffer, 128 );
if( cryptStatusOK( status ) )
status = cryptDecrypt( decryptContext, buffer + 128,
TESTBUFFER_SIZE - 128 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -