📄 highlvl.c
字号:
/****************************************************************************
* *
* cryptlib Mid and High-Level Test Routines *
* Copyright Peter Gutmann 1995-2005 *
* *
****************************************************************************/
#include <limits.h> /* To determine max.buffer size we can encrypt */
#ifdef _MSC_VER
#include "../cryptlib.h"
#include "test.h"
#else
#include "cryptlib.h"
#include "test/test.h"
#endif /* Braindamaged MSC 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 */
/****************************************************************************
* *
* Mid-level Routines Test *
* *
****************************************************************************/
#ifndef max /* Some compilers don't define this */
#define max( a, b ) ( ( ( a ) > ( b ) ) ? ( ( int ) a ) : ( ( int ) b ) )
#endif /* !max */
/* Test whether two session keys are identical */
static int compareSessionKeys( const CRYPT_CONTEXT cryptContext1,
const CRYPT_CONTEXT cryptContext2 )
{
BYTE buffer[ CRYPT_MAX_IVSIZE ];
int blockSize, ivSize, status;
cryptGetAttribute( cryptContext1, CRYPT_CTXINFO_BLOCKSIZE, &blockSize );
cryptGetAttribute( cryptContext1, CRYPT_CTXINFO_IVSIZE, &ivSize );
cryptSetAttributeString( cryptContext1, CRYPT_CTXINFO_IV,
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00", ivSize );
cryptSetAttributeString( cryptContext2, CRYPT_CTXINFO_IV,
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00", ivSize );
memcpy( buffer, "0123456789ABCDEF", max( blockSize, 8 ) );
status = cryptEncrypt( cryptContext1, buffer, max( blockSize, 8 ) );
if( cryptStatusError( status ) )
{
printf( "cryptEncrypt() with first key failed with error "
"code %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
status = cryptDecrypt( cryptContext2, buffer, max( blockSize, 8 ) );
if( cryptStatusError( status ) )
{
printf( "cryptDecrypt() with second key failed with error "
"code %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
if( memcmp( buffer, "012345678ABCDEF", max( blockSize, 8 ) ) )
{
puts( "Data decrypted with key2 != plaintext encrypted with key1." );
return( FALSE );
}
return( TRUE );
}
/* General-purpose routines to perform a key exchange and sign and sig
check data */
static int signData( const char *algoName, const CRYPT_ALGO_TYPE algorithm,
const CRYPT_CONTEXT externalSignContext,
const CRYPT_CONTEXT externalCheckContext,
const BOOLEAN useSidechannelProtection,
const BOOLEAN useSHA2,
const CRYPT_FORMAT_TYPE formatType )
{
CRYPT_OBJECT_INFO cryptObjectInfo;
CRYPT_CONTEXT signContext, checkContext;
CRYPT_CONTEXT hashContext;
BYTE buffer[ 1024 ], hashBuffer[] = "abcdefghijklmnopqrstuvwxyz";
int status, value, length;
printf( "Testing %s%s digital signature%s...\n",
( formatType == CRYPT_FORMAT_PGP ) ? "PGP " : "", algoName,
useSidechannelProtection ? " with side-channel protection" : "" );
/* Create an SHA/SHA2 hash context and hash the test buffer. We don't
complete the hashing if it's a PGP signature since this hashes in
extra data before generating the signature */
cryptCreateContext( &hashContext, CRYPT_UNUSED, \
useSHA2 ? CRYPT_ALGO_SHA2 : CRYPT_ALGO_SHA );
cryptEncrypt( hashContext, hashBuffer, 26 );
if( formatType != CRYPT_FORMAT_PGP )
cryptEncrypt( hashContext, hashBuffer, 0 );
/* Create the appropriate en/decryption contexts */
if( externalSignContext != CRYPT_UNUSED )
{
signContext = externalSignContext;
checkContext = externalCheckContext;
}
else
{
if( algorithm == CRYPT_ALGO_DSA )
status = loadDSAContexts( CRYPT_UNUSED, &signContext,
&checkContext );
else
status = loadRSAContexts( CRYPT_UNUSED, &checkContext,
&signContext );
if( !status )
return( FALSE );
}
/* Find out how big the signature will be */
status = cryptCreateSignatureEx( NULL, 0, &length, formatType,
signContext, hashContext,
CRYPT_USE_DEFAULT );
if( cryptStatusError( status ) )
{
printf( "cryptCreateSignature() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
printf( "cryptCreateSignature() reports signature object will be %d "
"bytes long\n", length );
assert( length <= 1024 );
/* Sign the hashed data */
if( useSidechannelProtection )
{
cryptGetAttribute( CRYPT_UNUSED,
CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, &value );
cryptSetAttribute( CRYPT_UNUSED,
CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, TRUE );
}
status = cryptCreateSignatureEx( buffer, 1024, &length, formatType,
signContext, hashContext,
CRYPT_USE_DEFAULT );
if( cryptStatusError( status ) )
{
printf( "cryptCreateSignature() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
if( useSidechannelProtection && !value )
cryptSetAttribute( CRYPT_UNUSED,
CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, value );
/* Query the signed object */
status = cryptQueryObject( buffer, length, &cryptObjectInfo );
if( cryptStatusError( status ) )
{
printf( "cryptQueryObject() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
printf( "cryptQueryObject() reports object type %d, algorithm %d, "
"hash algorithm %d.\n", cryptObjectInfo.objectType,
cryptObjectInfo.cryptAlgo, cryptObjectInfo.hashAlgo );
memset( &cryptObjectInfo, 0, sizeof( CRYPT_OBJECT_INFO ) );
if( formatType == CRYPT_FORMAT_CRYPTLIB )
debugDump( ( algorithm == CRYPT_ALGO_DSA ) ? "sigd" : \
useSHA2 ? "sigr2" : "sigr", buffer, length );
else
debugDump( ( algorithm == CRYPT_ALGO_RSA ) ? \
"sigr.pgp" : "sigd.pgp", buffer, length );
/* Check the signature on the hash. We have to redo the hashing for PGP
signatures since PGP hashes in extra odds and ends after the data has
been hashed */
if( formatType == CRYPT_FORMAT_PGP )
{
cryptDeleteAttribute( hashContext, CRYPT_CTXINFO_HASHVALUE );
cryptEncrypt( hashContext, hashBuffer, 26 );
}
status = cryptCheckSignature( buffer, length, checkContext, hashContext );
if( cryptStatusError( status ) )
{
printf( "cryptCheckSignature() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Clean up */
cryptDestroyContext( hashContext );
if( externalSignContext == CRYPT_UNUSED )
destroyContexts( CRYPT_UNUSED, checkContext, signContext );
printf( "Generation and checking of %s digital signature via %d-bit "
"data block\n succeeded.\n\n", algoName, PKC_KEYSIZE );
return( TRUE );
}
static int keyExportImport( const char *algoName,
const CRYPT_ALGO_TYPE algorithm,
const CRYPT_CONTEXT externalCryptContext,
const CRYPT_CONTEXT externalDecryptContext,
const CRYPT_FORMAT_TYPE formatType )
{
const CRYPT_ALGO_TYPE cryptAlgo = ( formatType == CRYPT_FORMAT_PGP ) ? \
CRYPT_ALGO_IDEA : CRYPT_ALGO_RC2;
CRYPT_OBJECT_INFO cryptObjectInfo;
CRYPT_CONTEXT cryptContext, decryptContext;
CRYPT_CONTEXT sessionKeyContext1, sessionKeyContext2;
BYTE *buffer;
int status, length;
printf( "Testing %s%s public-key export/import...\n",
( formatType == CRYPT_FORMAT_PGP ) ? "PGP " : "", algoName );
/* Create encryption contexts for the session key. PGP stores the
session key information with the encrypted key data, so we can't
create the context at this point */
cryptCreateContext( &sessionKeyContext1, CRYPT_UNUSED,
selectCipher( cryptAlgo ) );
cryptSetAttribute( sessionKeyContext1, CRYPT_CTXINFO_MODE,
( formatType == CRYPT_FORMAT_PGP ) ? \
CRYPT_MODE_CFB : CRYPT_MODE_OFB );
cryptGenerateKey( sessionKeyContext1 );
if( formatType != CRYPT_FORMAT_PGP )
{
cryptCreateContext( &sessionKeyContext2, CRYPT_UNUSED,
selectCipher( cryptAlgo ) );
cryptSetAttribute( sessionKeyContext2, CRYPT_CTXINFO_MODE,
CRYPT_MODE_OFB );
}
/* Create the appropriate en/decryption contexts */
if( externalCryptContext != CRYPT_UNUSED )
{
cryptContext = externalCryptContext;
decryptContext = externalDecryptContext;
}
else
{
if( algorithm == CRYPT_ALGO_ELGAMAL )
status = loadElgamalContexts( &cryptContext, &decryptContext );
else
status = loadRSAContexts( CRYPT_UNUSED, &cryptContext, &decryptContext );
if( !status )
return( FALSE );
}
/* Find out how big the exported key will be */
status = cryptExportKeyEx( NULL, 0, &length, formatType, cryptContext,
sessionKeyContext1 );
if( cryptStatusError( status ) )
{
printf( "cryptExportKeyEx() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
printf( "cryptExportKeyEx() reports exported key object will be %d "
"bytes long\n", length );
if( ( buffer = malloc( length ) ) == NULL )
return( FALSE );
/* Export the session key */
status = cryptExportKeyEx( buffer, length, &length, formatType,
cryptContext, sessionKeyContext1 );
if( cryptStatusError( status ) )
{
printf( "cryptExportKeyEx() failed with error code %d, line %d.\n",
status, __LINE__ );
free( buffer );
return( FALSE );
}
/* Query the encrypted key object */
status = cryptQueryObject( buffer, length, &cryptObjectInfo );
if( cryptStatusError( status ) )
{
printf( "cryptQueryObject() failed with error code %d, line %d.\n",
status, __LINE__ );
free( buffer );
return( FALSE );
}
printf( "cryptQueryObject() reports object type %d, algorithm %d.\n",
cryptObjectInfo.objectType, cryptObjectInfo.cryptAlgo );
memset( &cryptObjectInfo, 0, sizeof( CRYPT_OBJECT_INFO ) );
if( formatType == CRYPT_FORMAT_CRYPTLIB )
debugDump( ( algorithm == CRYPT_ALGO_RSA ) ? \
"keytrans" : "keytr_el", buffer, length );
else
debugDump( ( algorithm == CRYPT_ALGO_RSA ) ? \
"keytrans.pgp" : "keytr_el.pgp", buffer, length );
/* Recreate the session key by importing the encrypted key */
if( formatType == CRYPT_FORMAT_PGP )
status = cryptImportKeyEx( buffer, length, decryptContext,
CRYPT_UNUSED, &sessionKeyContext2 );
else
status = cryptImportKeyEx( buffer, length, decryptContext,
sessionKeyContext2, NULL );
if( cryptStatusError( status ) )
{
printf( "cryptImportKeyEx() failed with error code %d, line %d.\n",
status, __LINE__ );
free( buffer );
return( FALSE );
}
/* Make sure the two keys match */
if( !compareSessionKeys( sessionKeyContext1, sessionKeyContext2 ) )
return( FALSE );
/* Clean up */
destroyContexts( CRYPT_UNUSED, sessionKeyContext1, sessionKeyContext2 );
if( externalCryptContext == CRYPT_UNUSED )
destroyContexts( CRYPT_UNUSED, cryptContext, decryptContext );
printf( "Export/import of session key via %d-bit %s-encrypted data "
"block\n succeeded.\n\n", PKC_KEYSIZE, algoName );
free( buffer );
return( TRUE );
}
/* Test the randomness gathering routines */
int testRandomRoutines( void )
{
CRYPT_CONTEXT cryptContext;
int status;
puts( "Testing randomness routines. This may take a few seconds..." );
/* Create an encryption context to generate a key into */
cryptCreateContext( &cryptContext, CRYPT_UNUSED, CRYPT_ALGO_DES );
status = cryptGenerateKey( cryptContext );
cryptDestroyContext( cryptContext );
/* Check whether we got enough randomness */
if( status == CRYPT_ERROR_RANDOM )
{
puts( "The randomness-gathering routines can't acquire enough random information to" );
puts( "allow key generation and public-key encryption to function. You will need to" );
puts( "change the randomness-polling code or reconfigure your system to allow the" );
puts( "randomness-gathering routines to function. The code to change can be found" );
puts( "in misc/rndXXXX.c\n" );
return( FALSE );
}
puts( "Randomness-gathering self-test succeeded.\n" );
return( TRUE );
}
/* Test the ability to encrypt a large amount of data */
int testLargeBufferEncrypt( void )
{
CRYPT_CONTEXT cryptContext;
BYTE *buffer;
const size_t length = ( INT_MAX <= 32768L ) ? 16384 : 1048576;
int i, status;
puts( "Testing encryption of large data quantity..." );
/* Allocate a large buffer and fill it with a known value */
if( ( buffer = malloc( length ) ) == NULL )
{
printf( "Couldn't allocate buffer of %ld bytes, skipping large "
"buffer encryption test.\n", ( long ) length );
return( TRUE );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -