📄 envelope.c
字号:
/* If the hash value is being supplied externally, add it to the envelope
before we add the signature data */
if( detachedSig && hashContext != CRYPT_UNUSED )
{
status = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_HASH,
hashContext );
if( cryptStatusError( status ) )
{
printf( "Couldn't add externally-generated hash value to "
"envelope, status %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
}
/* Push in the data */
count = pushData( cryptEnvelope, buffer, length, NULL, 0 );
if( !cryptStatusError( count ) )
{
if( detachedSig )
{
if( hashContext == CRYPT_UNUSED )
count = pushData( cryptEnvelope, ENVELOPE_TESTDATA,
ENVELOPE_TESTDATA_SIZE, NULL, 0 );
}
else
count = popData( cryptEnvelope, buffer, length );
}
if( cryptStatusError( count ) )
return( FALSE );
/* Determine the result of the signature check */
if( !getSigCheckResult( cryptEnvelope, sigContext, TRUE ) )
return( FALSE );
/* If we supplied the sig-checking key, make sure that it's handled
correctly by the envelope. We shouldn't be able to read it back from
a PGP envelope, and from a cryptlib/CMS/SMIME envelope we should get
back only a cert, not the full private key that we added */
if( sigContext != CRYPT_UNUSED )
{
CRYPT_CONTEXT sigCheckContext;
status = cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,
&sigCheckContext );
if( formatType == CRYPT_FORMAT_PGP )
{
/* If it's a PGP envelope, we can't retrieve the signing key from
it */
if( cryptStatusOK( status ) )
{
printf( "Attempt to read signature check key from PGP "
"envelope succeeded when it\nshould have failed, "
"line %d.\n", __LINE__ );
return( FALSE );
}
}
else
{
CRYPT_ENVELOPE testEnvelope;
/* If it's a cryptlib/CMS/SMIME envelope, we should be able to
retrieve the signing key from it */
if( cryptStatusError( status ) )
{
printf( "Couldn't retrieve signature check key from "
"envelope, status %d, line %d.\n", status,
__LINE__ );
return( FALSE );
}
/* The signing key should be a pure cert, not the private key+
cert combination that we pushed in. Note that the following
will result in an error message being printed in
addEnvInfoNumeric() */
createEnvelope( &testEnvelope, CRYPT_FORMAT_CRYPTLIB );
if( addEnvInfoNumeric( testEnvelope, CRYPT_ENVINFO_SIGNATURE,
sigCheckContext ) )
{
printf( "Retrieved signature check key is a private key, not "
"a certificate, line %d.\n", __LINE__ );
return( FALSE );
}
else
puts( " (The above message indicates that the test "
"condition was successfully\n checked)." );
destroyEnvelope( testEnvelope );
cryptDestroyCert( sigCheckContext );
}
}
/* Clean up */
if( !destroyEnvelope( cryptEnvelope ) )
return( FALSE );
return( count );
}
static int envelopeSign( const void *data, const int dataLength,
const char *dumpFileName, const BOOLEAN useDatasize,
const BOOLEAN useRawKey, const BOOLEAN useAltRawKey,
const BOOLEAN useCustomHash,
const BOOLEAN useSuppliedKey,
const CRYPT_FORMAT_TYPE formatType )
{
CRYPT_ENVELOPE cryptEnvelope;
CRYPT_KEYSET cryptKeyset;
CRYPT_CONTEXT cryptContext;
int count, status;
if( !keyReadOK )
{
puts( "Couldn't find key files, skipping test of signed "
"enveloping..." );
return( TRUE );
}
printf( "Testing %ssigned enveloping%s",
( formatType == CRYPT_FORMAT_PGP ) ? "PGP " : \
( formatType == CRYPT_FORMAT_SMIME ) ? "S/MIME " : "",
( useDatasize && ( formatType != CRYPT_FORMAT_PGP ) ) ? \
" with datasize hint" : "" );
if( useCustomHash )
printf( " %s custom hash",
( formatType == CRYPT_FORMAT_PGP ) ? "with" :"and" );
printf( " using %s", useAltRawKey ? "raw DSA key" : \
useRawKey ? "raw public key" : useSuppliedKey ? \
"supplied X.509 cert" : "X.509 cert" );
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, TEXT( "test" ),
useAltRawKey ? TEXT( "test1" ) : \
TEXT( "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 that 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 ];
const BOOLEAN forceOverflow = ( dataLength <= 8192 ) ? TRUE : FALSE;
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 ) && forceOverflow )
/* Set an artificially-small buffer to force an overflow */
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( forceOverflow && 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -