📄 testenv.c
字号:
const BOOLEAN useTimestamp, const BOOLEAN useNonDataContent,
const CRYPT_CONTEXT externalSignContext )
{
CRYPT_ENVELOPE cryptEnvelope;
CRYPT_CONTEXT cryptContext, hashContext = CRYPT_UNUSED;
int count, status;
if( !keyReadOK )
{
puts( "Couldn't find key files, skipping test of CMS signed "
"enveloping..." );
return( TRUE );
}
printf( "Testing CMS %s%s", ( useExtAttributes ) ? "extended " : "",
( detachedSig ) ? "detached signature" : "signed enveloping" );
if( useNonDataContent )
printf( " of non-data content" );
if( useExternalHash )
printf( " with externally-supplied hash" );
if( !useAttributes )
printf( " without signing attributes" );
if( useDatasize && \
!( useNonDataContent || useAttributes || useExtAttributes || \
detachedSig || useTimestamp ) )
/* Keep the amount of stuff being printed down */
printf( " with datasize hint" );
if( useTimestamp )
printf( " and timestamp" );
puts( "..." );
/* Get the private key */
if( externalSignContext != CRYPT_UNUSED )
cryptContext = externalSignContext;
else
{
status = getPrivateKey( &cryptContext, USER_PRIVKEY_FILE,
USER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
if( cryptStatusError( status ) )
{
puts( "Read of private key from key file failed, cannot test "
"CMS enveloping." );
return( FALSE );
}
}
/* Create the CMS envelope, push in the signing key and data, pop the
enveloped result, and destroy the envelope */
if( !createEnvelope( &cryptEnvelope, CRYPT_FORMAT_CMS ) || \
!addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,
cryptContext ) )
return( FALSE );
if( externalSignContext == CRYPT_UNUSED )
cryptDestroyContext( cryptContext );
if( useNonDataContent )
/* Test non-data content type w.automatic attribute handling */
status = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_CONTENTTYPE,
CRYPT_CONTENT_SIGNEDDATA );
if( cryptStatusOK( status ) && useDatasize )
status = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,
ENVELOPE_TESTDATA_SIZE );
if( cryptStatusOK( status ) && useExtAttributes )
{
CRYPT_CERTIFICATE cmsAttributes;
/* Add an ESS security label as signing attributes */
cryptCreateCert( &cmsAttributes, CRYPT_UNUSED,
CRYPT_CERTTYPE_CMS_ATTRIBUTES );
status = cryptSetAttributeString( cmsAttributes,
CRYPT_CERTINFO_CMS_SECLABEL_POLICY,
"1 3 6 1 4 1 9999 1", 18 );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cmsAttributes,
CRYPT_CERTINFO_CMS_SECLABEL_CLASSIFICATION,
CRYPT_CLASSIFICATION_SECRET );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptEnvelope,
CRYPT_ENVINFO_SIGNATURE_EXTRADATA, cmsAttributes );
cryptDestroyCert( cmsAttributes );
}
if( cryptStatusOK( status ) && detachedSig )
status = cryptSetAttribute( cryptEnvelope,
CRYPT_ENVINFO_DETACHEDSIGNATURE, TRUE );
if( cryptStatusOK( status ) && !useAttributes )
status = cryptSetAttribute( CRYPT_UNUSED,
CRYPT_OPTION_CMS_DEFAULTATTRIBUTES, FALSE );
if( cryptStatusOK( status ) && useTimestamp )
status = cryptSetAttributeString( cryptEnvelope,
CRYPT_ENVINFO_TIMESTAMP_AUTHORITY,
TSP_DEFAULTSERVER_NAME,
strlen( TSP_DEFAULTSERVER_NAME ) );
if( cryptStatusError( status ) )
{
printf( "cryptSetAttribute() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
count = pushData( cryptEnvelope, ENVELOPE_TESTDATA,
ENVELOPE_TESTDATA_SIZE, NULL, 0 );
if( !useAttributes )
/* Restore the default attributes setting */
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CMS_DEFAULTATTRIBUTES,
TRUE );
if( cryptStatusError( count ) )
{
/* The timestamping can fail for a wide range of (non-fatal) reasons,
typically either because this build doesn't have networking
enabled or because the TSA can't be contacted, so we don't treat
this one as a fatal error */
if( useTimestamp )
{
puts( "Envelope timestamping failed due to problems talking to "
"TSA, this is a non-\ncritical problem. Continuing...\n" );
cryptDestroyEnvelope( cryptEnvelope );
return( TRUE );
}
return( FALSE );
}
count = popData( cryptEnvelope, buffer, BUFFER_SIZE );
if( cryptStatusError( count ) )
return( FALSE );
if( !destroyEnvelope( cryptEnvelope ) )
return( FALSE );
/* Tell them what happened */
printf( "CMS %s has size %d bytes.\n", ( detachedSig ) ? \
"detached signature" : "signed data", count );
debugDump( ( detachedSig ) ?
( ( useDatasize ) ? "smi_dsg" : "smi_dsgn" ) : \
( useExtAttributes ) ? \
( ( useDatasize ) ? "smi_esg" : "smi_esgn" ) : \
( useTimestamp ) ? \
( ( useDatasize ) ? "smi_tsg" : "smi_tsgn" ) : \
( useNonDataContent ) ? \
( ( useDatasize ) ? "smi_ndc" : "smi_ndcn" ) : \
( useDatasize ) ? "smi_sig" : "smi_sign", buffer, count );
/* If we're supplying the hash value externally, calculate it now */
if( useExternalHash )
{
status = cryptCreateContext( &hashContext, CRYPT_UNUSED,
CRYPT_ALGO_SHA );
if( cryptStatusOK( status ) )
status = cryptEncrypt( hashContext, ENVELOPE_TESTDATA,
ENVELOPE_TESTDATA_SIZE );
if( cryptStatusOK( status ) )
status = cryptEncrypt( hashContext, "", 0 );
if( cryptStatusError( status ) )
{
puts( "Couldn't create external hash of data." );
return( FALSE );
}
}
/* Make sure the signature is valid */
status = cmsEnvelopeSigCheck( buffer, count, hashContext, detachedSig,
TRUE );
if( hashContext != CRYPT_UNUSED )
cryptDestroyContext( hashContext );
if( !status )
return( FALSE );
if( detachedSig )
printf( "Creation of CMS %sdetached signature %ssucceeded.\n\n",
( useExtAttributes ) ? "extended " : "",
( hashContext != CRYPT_UNUSED ) ? \
"with externally-supplied hash " : "" );
else
printf( "Enveloping of CMS %s%ssigned data succeeded.\n\n",
( useExtAttributes ) ? "extended " : "",
( useTimestamp ) ? "timestamped " : "" );
return( TRUE );
}
int testCMSEnvelopeSign( void )
{
if( !cmsEnvelopeSign( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED ) )
return( FALSE ); /* Minimal (no default S/MIME attributes) */
if( !cmsEnvelopeSign( FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED ) )
return( FALSE ); /* Standard (default S/MIME signing attributes) */
if( !cmsEnvelopeSign( TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED ) )
return( FALSE ); /* Datasize and attributes */
if( !cmsEnvelopeSign( FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED ) )
return( FALSE ); /* Extended signing attributes */
if( !cmsEnvelopeSign( TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED ) )
return( FALSE ); /* Datasize and extended attributes */
return( cmsEnvelopeSign( TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, CRYPT_UNUSED ) );
} /* Signing of non-data content */
int testCMSEnvelopeDetachedSig( void )
{
if( !cmsEnvelopeSign( FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, CRYPT_UNUSED ) )
return( FALSE ); /* Detached sig and attributes */
return( cmsEnvelopeSign( FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, CRYPT_UNUSED ) );
} /* Detached sig, attributes, externally-suppl.hash */
int testCMSEnvelopeSignEx( const CRYPT_CONTEXT signContext )
{
return( cmsEnvelopeSign( TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, signContext ) );
} /* Datasize, attributes, external signing context */
int testSessionEnvTSP( void )
{
/* This is a pseudo-enveloping test which uses the enveloping
functionality but is called as part of the session tests since full
testing of the TSP handling requires that it be used to timestamp an
S/MIME sig */
return( cmsEnvelopeSign( TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, CRYPT_UNUSED ) );
} /* Datasize, attributes, timestamp */
static int cmsImportSignedData( const char *fileName )
{
BYTE *bufPtr = buffer;
int count, status;
/* Read the test data */
count = getFileSize( fileName ) + 10;
if( count >= BUFFER_SIZE )
{
if( ( bufPtr = malloc( count ) ) == NULL )
{
printf( "Couldn't allocate test buffer of %d bytes.\n", count );
return( FALSE );
}
}
count = readFileData( fileName, "S/MIME SignedData", bufPtr, count );
if( !count )
{
if( bufPtr != buffer )
free( bufPtr );
return( count );
}
/* Check the signature on the data */
status = cmsEnvelopeSigCheck( bufPtr, count, CRYPT_UNUSED, FALSE, FALSE );
if( bufPtr != buffer )
free( bufPtr );
return( status );
}
int testCMSEnvelopeSignedDataImport( void )
{
FILE *filePtr;
BYTE fileName[ BUFFER_SIZE ];
int i;
/* Make sure the test data is present so we can return a useful error
message */
filenameFromTemplate( fileName, SMIME_SIG_FILE_TEMPLATE, 1 );
if( ( filePtr = fopen( fileName, "rb" ) ) == NULL )
{
puts( "Couldn't find S/MIME SignedData file, skipping test of "
"SignedData import..." );
return( TRUE );
}
fclose( filePtr );
/* There are many encoding variations possible for signed data so we try
a representative sample to make sure the code works in all cases */
for( i = 1; i <= 4; i++ )
{
filenameFromTemplate( fileName, SMIME_SIG_FILE_TEMPLATE, i );
if( !cmsImportSignedData( fileName ) )
return( FALSE );
}
puts( "Import of S/MIME SignedData succeeded.\n" );
return( TRUE );
}
/* Test CMS enveloping/de-enveloping */
static int cmsEnvelopeDecrypt( const void *envelopedData,
const int envelopedDataLength,
const CRYPT_HANDLE externalKeyset,
const char *externalPassword )
{
CRYPT_ENVELOPE cryptEnvelope;
int count, status;
/* Create the envelope and push in the decryption keyset */
if( !createDeenvelope( &cryptEnvelope ) )
return( FALSE );
if( externalKeyset != CRYPT_UNUSED )
status = addEnvInfoNumeric( cryptEnvelope,
CRYPT_ENVINFO_KEYSET_DECRYPT, externalKeyset );
else
{
CRYPT_KEYSET cryptKeyset;
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
CRYPT_KEYSET_FILE, USER_PRIVKEY_FILE,
CRYPT_KEYOPT_READONLY );
if( cryptStatusOK( status ) )
status = addEnvInfoNumeric( cryptEnvelope,
CRYPT_ENVINFO_KEYSET_DECRYPT, cryptKeyset );
cryptKeysetClose( cryptKeyset );
}
if( !status )
return( FALSE );
/* Push in the data */
count = pushData( cryptEnvelope, envelopedData, envelopedDataLength,
( externalPassword == NULL ) ? TEST_PRIVKEY_PASSWORD :
externalPassword, 0 );
if( cryptStatusError( count ) )
return( ( externalPassword != NULL ) ? count : FALSE );
count = popData( cryptEnvelope, buffer, BUFFER_SIZE );
if( cryptStatusError( count ) )
return( FALSE );
if( !destroyEnvelope( cryptEnvelope ) )
return( FALSE );
/* Make sure the result matches what we pushed */
if( count != ENVELOPE_TESTDATA_SIZE || \
memcmp( buffer, ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE ) )
{
puts( "De-enveloped data != original data." );
return( FALSE );
}
return( TRUE );
}
static int cmsEnvelopeCrypt( const BOOLEAN useDatasize,
const BOOLEAN useStreamCipher,
const BOOLEAN useLargeBlockCipher,
const CRYPT_HANDLE externalCryptContext,
const CRYPT_HANDLE externalKeyset,
const char *externalPassword,
const char *recipientName )
{
CRYPT_ENVELOPE cryptEnvelope;
CRYPT_HANDLE cryptKey;
BOOLEAN isKeyAgreementKey = FALSE;
int count, status;
if( !keyReadOK )
{
puts( "Couldn't find key files, skipping test of CMS encrypted "
"enveloping..." );
return( TRUE );
}
printf( "Testing CMS public-key encrypted enveloping" );
if( externalKeyset != CRYPT_UNUSED && recipientName != NULL )
printf( " with dual encryption/signing certs" );
else
if( useStreamCipher )
printf( " with stream cipher" );
else
if( useLargeBlockCipher )
printf( " with large block size cipher" );
else
if( useDatasize )
printf( " with datasize hint" );
puts( "..." );
/* Get the public key. We use assorted variants to make sure they all
work */
if( externalCryptContext != CRYPT_UNUSED )
{
int cryptAlgo;
status = cryptGetAttribute( externalCryptContext, CRYPT_CTXINFO_ALGO,
&cryptAlgo );
if( cryptStatusError( status ) )
{
puts( "Couldn't determine algorithm for public key, cannot test "
"CMS enveloping." );
return( FALSE );
}
if( cryptAlgo == CRYPT_ALGO_KEA )
isKeyAgreementKey = TRUE;
cryptKey = externalCryptContext;
}
else
if( recipientName == NULL )
{
CRYPT_KEYSET cryptKeyset;
/* No recipient name, get the public key */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -