📄 testll.c
字号:
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 );
}
/* Check for an algorithm/mode */
static BOOLEAN checkLowlevelInfo( const CRYPT_DEVICE cryptDevice,
const CRYPT_ALGO 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,
bytesToBits( cryptQueryInfo.blockSize ) );
if( cryptAlgo < CRYPT_ALGO_FIRST_HASH || cryptAlgo > CRYPT_ALGO_LAST_HASH )
{
printf( ", keysize %d-%d bits (recommended = %d bits)",
bytesToBits( cryptQueryInfo.minKeySize ),
bytesToBits( cryptQueryInfo.maxKeySize ),
bytesToBits( cryptQueryInfo.keySize ) );
}
puts( "." );
return( TRUE );
}
/* Test an algorithm/mode implementation */
int testLowlevel( const CRYPT_DEVICE cryptDevice, const CRYPT_ALGO cryptAlgo,
const BOOLEAN checkOnly )
{
CRYPT_MODE cryptMode = CRYPT_MODE_ECB;
CRYPT_CONTEXT cryptContext, decryptContext;
BYTE buffer[ TESTBUFFER_SIZE ], testBuffer[ TESTBUFFER_SIZE ];
const BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;
BOOLEAN modesTested[ 8 ] = { 0 }, testSucceeded = FALSE;
int status;
/* Initialise the test buffers */
initTestBuffers( buffer, testBuffer, TESTBUFFER_SIZE );
/* Check cryptlib's capabilities */
if( !checkLowlevelInfo( cryptDevice, cryptAlgo ) )
return( FALSE );
/* If we're only doing a capability check, don't try anything else */
if( checkOnly )
return( TRUE );
/* Since DH and KEA only perform key agreement rather than a true key
exchange, we can't test their encryption capabilities */
if( cryptAlgo == CRYPT_ALGO_DH || cryptAlgo == CRYPT_ALGO_KEA )
return( TRUE );
do
{
/* Set up an encryption context, load a user key into it, and
perform a key setup */
switch( cryptAlgo )
{
case CRYPT_ALGO_DES:
status = loadContexts( &cryptContext, &decryptContext,
cryptDevice, cryptAlgo, cryptMode,
( BYTE * ) "12345678", 8 );
break;
case CRYPT_ALGO_SKIPJACK:
status = loadContexts( &cryptContext, &decryptContext,
cryptDevice, cryptAlgo, cryptMode,
( BYTE * ) "1234567890", 10 );
break;
case CRYPT_ALGO_CAST:
case CRYPT_ALGO_IDEA:
case CRYPT_ALGO_AES:
status = loadContexts( &cryptContext, &decryptContext,
cryptDevice, cryptAlgo, cryptMode,
( BYTE * ) "1234567887654321", 16 );
break;
case CRYPT_ALGO_3DES:
status = loadContexts( &cryptContext, &decryptContext,
cryptDevice, cryptAlgo, cryptMode,
( BYTE * ) "123456788765432112345678", 24 );
break;
case CRYPT_ALGO_RC2:
case CRYPT_ALGO_RC4:
case CRYPT_ALGO_RC5:
case CRYPT_ALGO_BLOWFISH:
case CRYPT_ALGO_HMAC_MD5:
case CRYPT_ALGO_HMAC_SHA:
case CRYPT_ALGO_HMAC_RIPEMD160:
status = loadContexts( &cryptContext, &decryptContext,
cryptDevice, cryptAlgo, cryptMode,
( BYTE * ) "1234567890098765432112345678900987654321", 40 );
break;
case CRYPT_ALGO_MD2:
case CRYPT_ALGO_MD4:
case CRYPT_ALGO_MD5:
case CRYPT_ALGO_SHA:
case CRYPT_ALGO_RIPEMD160:
status = loadContexts( &cryptContext, &decryptContext,
cryptDevice, cryptAlgo, CRYPT_MODE_NONE,
( BYTE * ) "", 0 );
break;
case CRYPT_ALGO_RSA:
status = loadRSAContexts( cryptDevice, &cryptContext,
&decryptContext );
break;
case CRYPT_ALGO_DSA:
status = loadDSAContexts( cryptDevice, &cryptContext,
&decryptContext );
break;
case CRYPT_ALGO_ELGAMAL:
status = loadElgamalContexts( &cryptContext, &decryptContext );
break;
default:
printf( "Unknown encryption algorithm ID %d, cannot perform "
"encryption test\n", cryptAlgo );
return( FALSE );
}
if( status == CRYPT_ERROR_NOTAVAIL )
{
/* It's a conventional algorithm for which this mode isn't
available, try a different mode */
cryptMode++;
continue;
}
if( !status )
return( FALSE );
/* DLP-based algorithms can't be called directly from user code
because of the special data-formatting requirements */
if( cryptAlgo == CRYPT_ALGO_DSA || cryptAlgo == CRYPT_ALGO_ELGAMAL )
{
destroyContexts( cryptDevice, cryptContext, decryptContext );
return( TRUE );
}
/* Perform a test en/decryption */
status = testCrypt( cryptContext, decryptContext, buffer, isDevice );
if( cryptStatusError( status ) )
if( isDevice && status == CRYPT_ERROR_NOTAVAIL )
{
/* Some primitive tokens or accelerators support only the
barest minimum of functionality, which may include being
able to create objects but not use them (eg public key
objects in a device which is just an RSA private-key
modexp engine). Because of this we may get a
CRYPT_ERROR_NOTAVAIL when we try and perform a low-level
crypto test, this isn't normally a problem for cryptlib
high-level objects because public-key ops are always done
in software, but when we explicitly try to do them in the
token it's a problem. Because of this we report a problem
but continue anyway */
puts( "The crypto device reported that this operation isn't "
"available even though it\nsupports the use of "
"encryption objects which implement this algorithm. "
"This\nis probably a bare-bones device which only "
"supports minimal functionality (eg\nprivate-key "
"decryption but not encryption)." );
destroyContexts( cryptDevice, cryptContext, decryptContext );
continue;
}
else
return( FALSE );
/* Make sure everything went OK */
if( cryptAlgo >= CRYPT_ALGO_FIRST_HASH )
{
BYTE hash1[ CRYPT_MAX_HASHSIZE ], hash2[ CRYPT_MAX_HASHSIZE ];
int length1, length2;
status = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_HASHVALUE,
hash1, &length1 );
cryptGetAttributeString( decryptContext, CRYPT_CTXINFO_HASHVALUE,
hash2, &length2 );
if( cryptStatusError( status ) )
{
printf( "Couldn't get hash information, status = %d.\n", status );
return( FALSE );
}
if( ( length1 != length2 ) || memcmp( hash1, hash2, length1 ) )
{
puts( "Error: Hash value of identical buffers differs." );
return( FALSE );
}
if( !memcmp( hash1, "\x00\x00\x00\x00\x00\x00\x00\x00", 8 ) || \
!memcmp( hash2, "\x00\x00\x00\x00\x00\x00\x00\x00", 8 ) )
{
puts( "Error: Hash contains all zeroes." );
return( FALSE );
}
/* Make sure we can get repeatable results after deleting the
hash/MAC and rehashing the data */
status = cryptDeleteAttribute( cryptContext,
CRYPT_CTXINFO_HASHVALUE );
if( cryptStatusOK( status ) )
status = cryptDeleteAttribute( decryptContext,
CRYPT_CTXINFO_HASHVALUE );
if( cryptStatusError( status ) )
{
printf( "Deletion of hash/MAC value failed with status %d.\n",
status );
return( FALSE );
}
if( cryptStatusError( testCrypt( cryptContext, decryptContext,
buffer, isDevice ) ) )
return( FALSE );
status = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_HASHVALUE,
hash1, &length1 );
if( cryptStatusError( status ) )
{
printf( "Couldn't get hash information for re-hashed data, "
"status = %d.\n", status );
return( FALSE );
}
if( ( length1 != length2 ) || memcmp( hash1, hash2, length1 ) )
{
puts( "Error: Hash value of re-hashed data differs." );
return( FALSE );
}
}
else
/* If it's a PKC we'll have performed the check during the
encrypt/decrypt step */
if( cryptAlgo < CRYPT_ALGO_FIRST_PKC && \
!checkTestBuffers( buffer, testBuffer ) )
return( FALSE );
/* Remember that at least one test succeeded */
testSucceeded = TRUE;
if( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL )
modesTested[ cryptMode++ ] = TRUE;
/* Clean up */
destroyContexts( cryptDevice, cryptContext, decryptContext );
}
while( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL && \
cryptMode < CRYPT_MODE_LAST );
/* If it's a conventional algorithm, report the encryption modes which
were tested */
if( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL )
{
printf( " Encryption modes tested:" );
if( modesTested[ CRYPT_MODE_ECB ] )
printf( " ECB" );
if( modesTested[ CRYPT_MODE_CBC ] )
printf( " CBC" );
if( modesTested[ CRYPT_MODE_CFB ] )
printf( " CFB" );
if( modesTested[ CRYPT_MODE_OFB ] )
printf( " OFB" );
puts( "." );
}
/* Make sure at least one of the algorithm's modes was tested */
if( !testSucceeded )
{
puts( "No processing modes were found for this algorithm.\n" );
return( FALSE );
}
return( TRUE );
}
#endif /* TEST_LOWLEVEL || TEST_DEVICE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -