📄 testenv.c
字号:
puts( "..." );
/* Get the private key */
if( useRawKey || useAltRawKey )
{
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
CRYPT_KEYSET_FILE, useAltRawKey ? \
OPENPGP_PRIVKEY_FILE : PGP_PRIVKEY_FILE,
CRYPT_KEYOPT_READONLY );
if( cryptStatusOK( status ) )
{
status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
CRYPT_KEYID_NAME, "test",
useAltRawKey ? "test1" : "test10" );
cryptKeysetClose( cryptKeyset );
}
}
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 "
"enveloping." );
return( FALSE );
}
/* Create the envelope, push in the signing key, any extra information,
and the data to sign, pop the enveloped result, and destroy the
envelope */
if( !createEnvelope( &cryptEnvelope, formatType ) )
return( FALSE );
if( useCustomHash )
{
CRYPT_CONTEXT hashContext;
/* Add the (nonstandard) hash algorithm information. We need to do
this before we add the signing key since it's automatically
associated with the last hash algorithm added */
cryptCreateContext( &hashContext, CRYPT_UNUSED, CRYPT_ALGO_MD5 );
status = addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_HASH,
hashContext );
cryptDestroyContext( hashContext );
if( !status )
return( FALSE );
}
if( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,
cryptContext ) )
return( FALSE );
if( useDatasize && !useRawKey && !useCustomHash && \
( formatType != CRYPT_FORMAT_PGP ) )
{
CRYPT_CONTEXT hashContext;
/* Make sure that adding a (pseudo-duplicate) hash action that
duplicates the one already added implicitly by the addition of
the signature key succeeds (internally, nothing is really done
since the hash action is already present) */
cryptCreateContext( &hashContext, CRYPT_UNUSED, CRYPT_ALGO_SHA );
status = addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_HASH,
hashContext );
cryptDestroyContext( hashContext );
if( !status )
return( FALSE );
}
if( cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,
cryptContext ) != CRYPT_ERROR_INITED )
{
puts( "Addition of duplicate key to envelope wasn't detected." );
return( FALSE );
}
if( !useSuppliedKey )
cryptDestroyContext( cryptContext );
if( useDatasize )
cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,
dataLength );
count = pushData( cryptEnvelope, data, dataLength, NULL, 0 );
if( cryptStatusError( count ) )
return( FALSE );
count = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );
if( cryptStatusError( count ) )
return( FALSE );
if( !destroyEnvelope( cryptEnvelope ) )
return( FALSE );
/* Tell them what happened */
printf( "Enveloped data has size %d bytes.\n", count );
debugDump( dumpFileName, globalBuffer, count );
/* De-envelope the data and make sure the result matches what we
pushed */
count = envelopeSigCheck( globalBuffer, count, CRYPT_UNUSED,
( useSuppliedKey ) ? cryptContext : CRYPT_UNUSED,
useRawKey, useAltRawKey, FALSE, formatType );
if( !count )
return( FALSE );
if( count != dataLength || memcmp( globalBuffer, data, dataLength ) )
{
puts( "De-enveloped data != original data." );
return( FALSE );
}
if( useSuppliedKey )
{
/* If the following fails, there's a problem with handling reference
counting for keys */
status = cryptDestroyContext( cryptContext );
if( cryptStatusError( status ) )
{
printf( "Attempt to destroy externally-added sig.check key "
"returned %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
}
/* Clean up */
puts( "Enveloping of signed data succeeded.\n" );
return( TRUE );
}
int testEnvelopeSign( void )
{
if( cryptQueryCapability( CRYPT_ALGO_IDEA, NULL ) == CRYPT_ERROR_NOTAVAIL )
puts( "Skipping raw public-key based signing, which requires the "
"IDEA cipher to\nbe enabled.\n" );
else
{
if( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_sign", FALSE, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Indefinite length, raw key */
if( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_sig", TRUE, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Datasize, raw key */
if( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_sig.pgp", TRUE, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP ) )
return( FALSE ); /* PGP format, raw key */
if( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_sigd.pgp", TRUE, TRUE, TRUE, FALSE, FALSE, CRYPT_FORMAT_PGP ) )
return( FALSE ); /* PGP format, raw DSA key */
}
if( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_csgn", FALSE, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Indefinite length, certificate */
if( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_csg", TRUE, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Datasize, certificate */
if( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_csgs", TRUE, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_SMIME ) )
return( FALSE ); /* Datasize, certificate, S/MIME semantics */
if( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_csg", TRUE, FALSE, FALSE, FALSE, TRUE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Datasize, certificate, sigcheck key supplied */
if( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_csg.pgp", TRUE, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP ) )
return( FALSE ); /* PGP format, certificate */
if( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_hsg", TRUE, FALSE, FALSE, TRUE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Datasize, cert, externally-suppl.hash */
return( envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, "env_csg", TRUE, FALSE, FALSE, FALSE, TRUE, CRYPT_FORMAT_CRYPTLIB ) );
} /* Externally-supplied key, to test isolation of sig.check key */
/* Test signed envelope with forced envelope buffer overflow */
static int envelopeSignOverflow( const void *data, const int dataLength,
const char *dumpFileName,
const CRYPT_FORMAT_TYPE formatType )
{
CRYPT_ENVELOPE cryptEnvelope;
CRYPT_CONTEXT cryptContext;
BYTE localBuffer[ 8192 + 4096 ];
int localBufPos, bytesIn, bytesOut, status;
if( !keyReadOK )
{
puts( "Couldn't find key files, skipping test of signed "
"enveloping..." );
return( TRUE );
}
printf( "Testing %ssigned enveloping with forced overflow...\n",
( formatType == CRYPT_FORMAT_PGP ) ? "PGP " : \
( formatType == CRYPT_FORMAT_SMIME ) ? "S/MIME " : "" );
/* Get the private key */
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 "
"enveloping." );
return( FALSE );
}
/* Create the envelope and push in the signing key and any extra
information */
if( !createEnvelope( &cryptEnvelope, formatType ) )
return( FALSE );
if( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,
cryptContext ) )
return( FALSE );
cryptDestroyContext( cryptContext );
status = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,
dataLength );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_BUFFERSIZE,
8192 );
if( cryptStatusError( status ) )
{
printf( "Couldn't set envelope parameters to force overflow, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
/* Push in the data to sign. Since we're forcing an overflow, we can't
do this via the usual pushData() but have to do it manually to handle
the restart once the overflow occurs */
status = cryptPushData( cryptEnvelope, data, dataLength, &bytesIn );
if( cryptStatusError( status ) || bytesIn != dataLength )
{
printf( "cryptPushData() failed with status %d, copied %d of %d "
"bytes, line %d.\n", status, bytesIn, dataLength, __LINE__ );
return( FALSE );
}
status = cryptFlushData( cryptEnvelope );
if( status != CRYPT_ERROR_OVERFLOW )
{
printf( "cryptFlushData() returned status %d, should have been "
"CRYPT_ERROR_OVERFLOW,\n line %d.\n", status, __LINE__ );
return( FALSE );
}
status = cryptPopData( cryptEnvelope, localBuffer, 8192 + 4096,
&bytesOut );
if( cryptStatusError( status ) )
{
printf( "cryptPopData() #1 failed with status %d, line %d.\n",
status, bytesOut, dataLength, __LINE__ );
return( FALSE );
}
localBufPos = bytesOut;
status = cryptFlushData( cryptEnvelope );
if( cryptStatusError( status ) )
{
printf( "cryptFlushData() failed with error code %d, line %d.\n",
status, __LINE__ );
printErrorAttributeInfo( cryptEnvelope );
return( FALSE );
}
status = cryptPopData( cryptEnvelope, localBuffer + localBufPos,
8192 + 4096 - localBufPos, &bytesOut );
if( cryptStatusError( status ) )
{
printf( "cryptPopData() #2 failed with status %d, line %d.\n",
status, bytesOut, dataLength, __LINE__ );
return( FALSE );
}
localBufPos += bytesOut;
if( !destroyEnvelope( cryptEnvelope ) )
return( FALSE );
/* Tell them what happened */
printf( "Enveloped data has size %d bytes.\n", localBufPos );
debugDump( dumpFileName, localBuffer, localBufPos );
/* De-envelope the data and make sure the result matches what we
pushed */
bytesOut = envelopeSigCheck( localBuffer, localBufPos, CRYPT_UNUSED,
CRYPT_UNUSED, FALSE, FALSE, FALSE,
formatType );
if( !bytesOut )
return( FALSE );
if( bytesOut != dataLength || memcmp( localBuffer, data, dataLength ) )
{
puts( "De-enveloped data != original data." );
return( FALSE );
}
/* Clean up */
puts( "Enveloping of signed data succeeded.\n" );
return( TRUE );
}
int testEnvelopeSignOverflow( void )
{
BYTE buffer[ 8192 ];
/* Push in just the right amount of data to force an overflow when we
generate the signature, to check overflow handling in the enveloping
code.
For PGP it's almost impossible to invoke overflow handling since the
enveloping code is set up to either emit the signature directly into
the buffer or, via an over-conservative estimation of buffer space,
ensure that the user leaves enough space in the buffer for the entire
sig. For an estimated space requirement of 256 bytes, 8192 - 280
will force the sig into the auxBuffer, but since this is an over-
conservative estimate it'll then be flushed straight into the
envelope buffer. The only way to actually force overflow handling
would be to use the longest possible key size and a cert with a large
issuerAndSerialNumber.
For CMS, we can cause an overflow in one of two locations. The first,
with 8192 - 1152 bytes of data, causes an overflow when emitting the
signing certs. This is fairly straightforward, the enveloping code
always requires enough room for the signing certs, so all that happens
is that the user pops some data and tries again.
The second overflow is with 8192 - 1280 bytes of data, which causes an
overflow on signing.
*/
memset( buffer, '*', 8192 );
if( !envelopeSignOverflow( buffer, 8192 - 280, "env_sigo.pgp", CRYPT_FORMAT_PGP ) )
return( FALSE ); /* PGP format, raw key */
if( !envelopeSignOverflow( buffer, 8192 - 1152, "env_csgo1", CRYPT_FORMAT_SMIME ) )
return( FALSE ); /* Datasize, certificate, S/MIME semantics */
return( envelopeSignOverflow( buffer, 8192 - 1280, "env_csgo2", CRYPT_FORMAT_SMIME ) );
} /* Datasize, certificate, S/MIME semantics */
/* Test authenticated (MACd) enveloping */
static int envelopeAuthent( const void *data, const int dataLength,
const BOOLEAN useDatasize )
{
CRYPT_ENVELOPE cryptEnvelope;
int count;
printf( "Testing authenticated enveloping" );
if( useDatasize )
printf( " with datasize hint" );
puts( "..." );
/* Create the envelope and push in the password after telling the
enveloping code we want to MAC rather than encrypt */
if( !createEnvelope( &cryptEnvelope, CRYPT_FORMAT_CRYPTLIB ) || \
!addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_MAC,
TRUE ) || \
!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD, "Password", 8 ) )
return( FALSE );
/* Push in the data, pop the enveloped result, and destroy the
envelope */
if( useDatasize )
cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,
dataLength );
count = pushData( cryptEnvelope, data, dataLength, NULL, 0 );
if( cryptStatusError( count ) )
return( FALSE );
count = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );
if( cryptStatusError( count ) )
return( FALSE );
if( !destroyEnvelope( cryptEnvelope ) )
return( FALSE );
/* Tell them what happened */
printf( "Enveloped data has size %d bytes.\n", count );
debugDump( useDatasize ? "env_mac" : "env_macn", globalBuffer, count );
/* Create the envelope */
if( !createDeenvelope( &cryptEnvelope ) )
return( FALSE );
/* Push in the data */
count = pushData( cryptEnvelope, globalBuffer, count, NULL, 0 );
if( cryptStatusError( count ) )
return( FALSE );
count = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );
if( cryptStatusError( count ) )
return( FALSE );
/* Determine the result of the MAC check */
if( !getSigCheckResult( cryptEnvelope, CRYPT_UNUSED ) || \
!destroyEnvelope( cryptEnvelope ) )
return( FALSE );
/* Make sure the result matches what we pushed */
if( count != dataLength || memcmp( globalBuffer, data, dataLength ) )
{
puts( "De-enveloped data != original data." );
return( FALSE );
}
/* Clean up */
puts( "Enveloping of authenticated data succeeded.\n" );
return( TRUE );
}
int testEnvelopeAuthenticate( void )
{
/* As of mid 2003 there are no known implementations of this CMS
mechanism, any at
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -