📄 highlvl.c
字号:
"%d.\n", status, __LINE__ );
return( FALSE );
}
/* Hang around a bit to allow things to start. This value is a bit of a
difficult quantity to get right since VC++ can spend longer than the
startup time thrashing the drive doing nothing so it has to be high,
but on faster PC's even a 3K bit key can be generated in a few
seconds, so it can't be too high or the keygen will have finished.
The following value was safe for a 700MHz PIII, but the next step
would be to move to 4K bit keys (4096 bits, 512 in the above keygen
call) */
printf( "Delaying 2s to allow keygen to start..." );
delayThread( 2 );
puts( "done." );
/* Check that the async keygen is still in progress */
status = cryptAsyncQuery( cryptContext );
if( status == CRYPT_ERROR_TIMEOUT )
puts( "Async keygen in progress." );
else
{
/* If the machine's really fast, the keygen could have completed
already */
if( status == CRYPT_OK )
{
printf( "The async keygen has completed before the rest of the "
"test code could run.\nTo fix this, either decrease "
"the startup delay on line %d\nof " __FILE__ " or "
"increase the size of the key being generated to slow\n"
"down the generation process.\n\n", __LINE__ - 15 );
cryptDestroyContext( cryptContext );
return( TRUE );
}
printf( "Async keygen failed with error code %d, line %d.\n", status,
__LINE__ );
return( FALSE );
}
/* Cancel the async keygen */
status = cryptAsyncCancel( cryptContext );
if( cryptStatusError( status ) )
{
printf( "cryptAsyncCancel() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
printf( "Cancelling async operation..." );
while( cryptAsyncQuery( cryptContext ) == CRYPT_ERROR_TIMEOUT )
{
cancelCount++;
printf( "*" );
delayThread( 1 );
}
puts( "...done." );
/* Check the context to make sure that the keygen was actually
cancelled */
status = cryptCreateContext( &hashContext, CRYPT_UNUSED,
CRYPT_ALGO_SHA );
if( cryptStatusError( status ) )
return( FALSE );
cryptEncrypt( hashContext, hashBuffer, 26 );
cryptEncrypt( hashContext, hashBuffer, 0 );
status = cryptCreateSignature( buffer, BUFFER_SIZE, &length,
cryptContext, hashContext );
if( cryptStatusOK( status ) )
{
/* We have to be a bit careful here to try and eliminate false
positives due to fast CPUs. As a rule of thumb, it shouldn't
take more than 1s for a cancel to propagate through the system.
On the other hand we can also run into problems with very slow
CPUs that take so long to get started that the cancel never
arrives, to handle the entire spectrum of system types we just
print a warning but don't abort if there's a problem */
if( cancelCount <= 1 )
puts( "The async keygen completed even though the operation was "
"cancelled. This was\nprobably because the CPU was fast "
"enough that the keygen completed before the\ncancel could "
"take effect." );
else
puts( "The async keygen completed even though the operation was "
"cancelled. The\ncancel should have stopped the keygen from "
"completing.\n" );
}
/* Clean up */
cryptDestroyContext( cryptContext );
cryptDestroyContext( hashContext );
puts( "Asynchronous key generation succeeded.\n" );
return( TRUE );
#endif /* Systems with threading support */
}
#endif /* TEST_MIDLEVEL */
/****************************************************************************
* *
* Random Routines Test *
* *
****************************************************************************/
#ifdef TEST_RANDOM
/* 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 */
status = cryptCreateContext( &cryptContext, CRYPT_UNUSED,
CRYPT_ALGO_DES );
if( cryptStatusError( status ) )
return( FALSE );
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 random/<osname>.c\n" );
return( FALSE );
}
puts( "Randomness-gathering self-test succeeded.\n" );
return( TRUE );
}
#endif /* TEST_RANDOM */
/****************************************************************************
* *
* High-level Routines Test *
* *
****************************************************************************/
#ifdef TEST_HIGHLEVEL
/* Test the code to export/import a CMS key */
int testKeyExportImportCMS( void )
{
CRYPT_OBJECT_INFO cryptObjectInfo;
CRYPT_KEYSET cryptKeyset;
CRYPT_CONTEXT cryptContext;
CRYPT_CONTEXT sessionKeyContext1, sessionKeyContext2;
BYTE *buffer;
int status, length;
puts( "Testing CMS public-key export/import..." );
/* Get a private key with a cert chain attached */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
USER_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );
if( cryptStatusOK( status ) )
{
status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
CRYPT_KEYID_NAME, USER_PRIVKEY_LABEL,
TEST_PRIVKEY_PASSWORD );
cryptKeysetClose( cryptKeyset );
}
if( cryptStatusError( status ) )
{
printf( "Couldn't read private key, status %d, line %d.\n", status,
__LINE__ );
return( FALSE );
}
/* Create triple-DES encryption contexts for the exported and imported
session keys */
status = cryptCreateContext( &sessionKeyContext1, CRYPT_UNUSED,
CRYPT_ALGO_3DES );
if( cryptStatusOK( status ) )
status = cryptGenerateKey( sessionKeyContext1 );
if( cryptStatusOK( status ) )
status = cryptCreateContext( &sessionKeyContext2, CRYPT_UNUSED,
CRYPT_ALGO_3DES );
if( cryptStatusError( status ) )
return( FALSE );
/* Find out how big the exported key will be */
status = cryptExportKeyEx( NULL, 0, &length, CRYPT_FORMAT_SMIME,
cryptContext, sessionKeyContext1 );
if( cryptStatusError( status ) )
{
printf( "cryptExportKeyEx() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
printf( "cryptExportKeyEx() reports CMS exported key will be %d bytes "
"long\n", length );
if( ( buffer = malloc( length ) ) == NULL )
return( FALSE );
/* Export the key */
status = cryptExportKeyEx( buffer, length, &length, CRYPT_FORMAT_SMIME,
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, mode "
"%d.\n", cryptObjectInfo.objectType, cryptObjectInfo.cryptAlgo,
cryptObjectInfo.cryptMode );
memset( &cryptObjectInfo, 0, sizeof( CRYPT_OBJECT_INFO ) );
debugDump( "cms_ri", buffer, length );
/* Import the encrypted key and load it into the session key context */
status = cryptImportKey( buffer, length, cryptContext,
sessionKeyContext2 );
if( cryptStatusError( status ) )
{
printf( "cryptImportKey() failed with error code %d, line %d.\n",
status, __LINE__ );
free( buffer );
return( FALSE );
}
/* Make sure that the two keys match */
if( !compareSessionKeys( sessionKeyContext1, sessionKeyContext2 ) )
return( FALSE );
/* Clean up */
destroyContexts( CRYPT_UNUSED, sessionKeyContext1, sessionKeyContext2 );
cryptDestroyContext( cryptContext );
puts( "Export/import of CMS session key succeeded.\n" );
free( buffer );
return( TRUE );
}
/* Test the code to create an CMS signature */
static const CERT_DATA cmsAttributeData[] = {
/* Content type */
{ CRYPT_CERTINFO_CMS_CONTENTTYPE, IS_NUMERIC, CRYPT_CONTENT_SPCINDIRECTDATACONTEXT },
/* Odds and ends. We can't (portably) set the opusInfo name since it's
a Unicode string, so we only add this one under Windows */
#ifdef __WINDOWS__
{ CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME, IS_WCSTRING, 0, L"Program v3.0 SP2" },
#endif /* __WINDOWS__ */
{ CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL, IS_STRING, 0, TEXT( "http://bugs-r-us.com" ) },
{ CRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING, IS_NUMERIC, CRYPT_UNUSED },
{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
};
static int signDataCMS( const char *description,
const CRYPT_CERTIFICATE signingAttributes )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cmsAttributes = signingAttributes;
CRYPT_CONTEXT signContext, hashContext;
BYTE *buffer, hashBuffer[] = "abcdefghijklmnopqrstuvwxyz";
int status, length;
printf( "Testing %s...\n", description );
/* Create an SHA hash context and hash the test buffer */
status = cryptCreateContext( &hashContext, CRYPT_UNUSED,
CRYPT_ALGO_SHA );
if( cryptStatusError( status ) )
return( FALSE );
cryptEncrypt( hashContext, hashBuffer, 26 );
cryptEncrypt( hashContext, hashBuffer, 0 );
/* Get a private key with a cert chain attached */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
USER_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );
if( cryptStatusOK( status ) )
{
status = cryptGetPrivateKey( cryptKeyset, &signContext,
CRYPT_KEYID_NAME, USER_PRIVKEY_LABEL,
TEST_PRIVKEY_PASSWORD );
cryptKeysetClose( cryptKeyset );
}
if( cryptStatusError( status ) )
{
printf( "Couldn't read private key, status %d, line %d.\n", status,
__LINE__ );
return( FALSE );
}
/* Find out how big the signature will be */
status = cryptCreateSignatureEx( NULL, 0, &length, CRYPT_FORMAT_SMIME,
signContext, hashContext, cmsAttributes );
if( cryptStatusError( status ) )
{
printf( "cryptCreateSignatureEx() failed with error code %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
printf( "cryptCreateSignatureEx() reports CMS signature will be %d "
"bytes long\n", length );
if( ( buffer = malloc( length ) ) == NULL )
return( FALSE );
/* Sign the hashed data */
status = cryptCreateSignatureEx( buffer, length, &length,
CRYPT_FORMAT_SMIME, signContext,
hashContext, cmsAttributes );
if( cryptStatusError( status ) )
{
printf( "cryptCreateSignatureEx() failed with error code %d, line "
"%d.\n", status, __LINE__ );
free( buffer );
return( FALSE );
}
debugDump( ( signingAttributes == CRYPT_USE_DEFAULT ) ? \
"cms_sigd" : "cms_sig", buffer, length );
/* Check the signature on the hash */
status = cryptCheckSignatureEx( buffer, length, signContext, hashContext,
( cmsAttributes == CRYPT_USE_DEFAULT ) ? NULL : &cmsAttributes );
if( cryptStatusError( status ) )
{
printf( "cryptCheckSignatureEx() failed with error code %d, line "
"%d.\n", status, __LINE__ );
free( buffer );
return( FALSE );
}
/* Display the signing attributes */
if( cmsAttributes != CRYPT_USE_DEFAULT )
printCertInfo( cmsAttributes );
/* Clean up */
cryptDestroyContext( hashContext );
cryptDestroyContext( signContext );
cryptDestroyCert( cmsAttributes );
printf( "Generation and checking of %s succeeded.\n\n", description );
free( buffer );
return( TRUE );
}
int testSignDataCMS( void )
{
CRYPT_CERTIFICATE cmsAttributes;
int status;
/* First test the basic CMS signature with default attributes (content
type, signing time, and message digest) */
if( !signDataCMS( "CMS signature", CRYPT_USE_DEFAULT ) )
return( FALSE );
/* Create some CMS attributes and sign the data with the user-defined
attributes */
status = cryptCreateCert( &cmsAttributes, CRYPT_UNUSED,
CRYPT_CERTTYPE_CMS_ATTRIBUTES );
if( cryptStatusError( status ) || \
!addCertFields( cmsAttributes, cmsAttributeData, __LINE__ ) )
return( FALSE );
status = signDataCMS( "complex CMS signature", cmsAttributes );
cryptDestroyCert( cmsAttributes );
return( status );
}
#endif /* TEST_HIGHLEVEL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -