📄 envelope.c
字号:
CRYPT_ENVELOPE cryptEnvelope;
CRYPT_CONTEXT cryptContext;
CRYPT_ALGO_TYPE cryptAlgo = ( formatType == CRYPT_FORMAT_PGP ) ? \
selectCipher( CRYPT_ALGO_IDEA ) : \
selectCipher( CRYPT_ALGO_CAST );
BYTE *inBufPtr = ENVELOPE_TESTDATA, *outBufPtr = globalBuffer;
const int length = useLargeBuffer ? \
( ( INT_MAX <= 32768L ) ? 16384 : 1048576 ) : \
ENVELOPE_TESTDATA_SIZE;
const int bufSize = length + 128;
int count;
if( useLargeBuffer )
{
int i;
printf( "Testing %sraw-session-key encrypted enveloping of large "
"data quantity...\n",
( formatType == CRYPT_FORMAT_PGP ) ? "PGP " : "" );
/* Allocate a large buffer and fill it with a known value */
if( ( inBufPtr = malloc( bufSize ) ) == NULL )
{
printf( "Couldn't allocate buffer of %d bytes, skipping large "
"buffer enveloping test.\n", length );
return( TRUE );
}
outBufPtr = inBufPtr;
for( i = 0; i < length; i++ )
inBufPtr[ i ] = i & 0xFF;
}
else
printf( "Testing %sraw-session-key encrypted enveloping%s...\n",
( formatType == CRYPT_FORMAT_PGP ) ? "PGP " : "",
( useDatasize && ( formatType != CRYPT_FORMAT_PGP ) ) ? \
" with datasize hint" : "" );
if( formatType != CRYPT_FORMAT_PGP )
{
/* Create the session key context. We don't check for errors here
since this code will already have been tested earlier */
cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );
}
else
{
/* PGP only allows a limited subset of algorithms and modes, in
addition we have to specifically check that IDEA is available
since it's possible to build cryptlib without IDEA support */
if( cryptAlgo != CRYPT_ALGO_IDEA )
{
puts( "Can't test PGP enveloping because the IDEA algorithm "
"isn't available in this\nbuild of cryptlib.\n" );
return( TRUE );
}
cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );
cryptSetAttribute( cryptContext, CRYPT_CTXINFO_MODE, CRYPT_MODE_CFB );
}
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,
"0123456789ABCDEF", 16 );
/* Create the envelope, push in a password and the data, pop the
enveloped result, and destroy the envelope */
if( !createEnvelope( &cryptEnvelope, formatType ) || \
!addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SESSIONKEY,
cryptContext ) )
return( FALSE );
if( useDatasize && !useLargeBuffer )
{
/* Test the ability to destroy the context after it's been added
(we replace it with a different context that's used later for
de-enveloping) */
cryptDestroyContext( cryptContext );
cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,
"0123456789ABCDEF", 16 );
}
if( useDatasize )
cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE, length );
if( useLargeBuffer )
cryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_BUFFERSIZE,
length + 1024 );
count = pushData( cryptEnvelope, inBufPtr, length, NULL, 0 );
if( cryptStatusError( count ) )
return( FALSE );
count = popData( cryptEnvelope, outBufPtr, bufSize );
if( cryptStatusError( count ) )
return( FALSE );
if( !destroyEnvelope( cryptEnvelope ) )
return( FALSE );
/* Tell them what happened */
printf( "Enveloped data has size %d bytes.\n", count );
if( !useLargeBuffer )
debugDump( dumpFileName, outBufPtr, count );
/* Create the envelope, push in the data, pop the de-enveloped result,
and destroy the envelope */
if( !createDeenvelope( &cryptEnvelope ) )
return( FALSE );
if( useLargeBuffer )
cryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_BUFFERSIZE,
length + 1024 );
count = pushData( cryptEnvelope, outBufPtr, count, NULL, cryptContext );
if( cryptStatusError( count ) )
return( FALSE );
count = popData( cryptEnvelope, outBufPtr, bufSize );
if( cryptStatusError( count ) )
return( FALSE );
if( !destroyEnvelope( cryptEnvelope ) )
return( FALSE );
/* Make sure that the result matches what we pushed */
if( count != length )
{
puts( "De-enveloped data length != original length." );
return( FALSE );
}
if( useLargeBuffer )
{
int i;
for( i = 0; i < length; i++ )
if( outBufPtr[ i ] != ( i & 0xFF ) )
{
printf( "De-enveloped data != original data at byte %d.\n", i );
return( FALSE );
}
}
else
if( memcmp( outBufPtr, ENVELOPE_TESTDATA, length ) )
{
puts( "De-enveloped data != original data." );
return( FALSE );
}
/* Clean up */
if( useLargeBuffer )
free( inBufPtr );
cryptDestroyContext( cryptContext );
puts( "Enveloping of raw-session-key-encrypted data succeeded.\n" );
return( TRUE );
}
int testEnvelopeSessionCrypt( void )
{
if( !envelopeSessionCrypt( "env_sesn", FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Indefinite length */
if( !envelopeSessionCrypt( "env_ses", TRUE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Datasize */
#if 0
/* Although in theory PGP supports raw session-key based enveloping, in
practice this key is always (implicitly) derived from a user password,
so the enveloping code doesn't allow the use of raw session keys */
return( envelopeSessionCrypt( "env_ses.pgp", TRUE, FALSE, CRYPT_FORMAT_PGP ) );
#endif /* 0 */
return( TRUE );
}
int testEnvelopeSessionCryptLargeBuffer( void )
{
return( envelopeSessionCrypt( "env_ses", TRUE, TRUE, CRYPT_FORMAT_CRYPTLIB ) );
} /* Datasize, large buffer */
/* Test encrypted enveloping */
static int envelopeDecrypt( BYTE *buffer, const int length,
const CRYPT_CONTEXT cryptContext )
{
CRYPT_ENVELOPE cryptEnvelope;
int count;
/* Create the envelope, push in the data, pop the de-enveloped result,
and destroy the envelope */
if( !createDeenvelope( &cryptEnvelope ) )
return( FALSE );
count = pushData( cryptEnvelope, buffer, length, NULL, cryptContext );
if( cryptStatusError( count ) )
return( FALSE );
count = popData( cryptEnvelope, buffer, BUFFER_SIZE );
if( cryptStatusError( count ) )
return( FALSE );
destroyEnvelope( cryptEnvelope );
return( count );
}
static int envelopeCrypt( const char *dumpFileName,
const BOOLEAN useDatasize,
const CRYPT_FORMAT_TYPE formatType )
{
CRYPT_CONTEXT cryptContext;
CRYPT_ENVELOPE cryptEnvelope;
int count;
printf( "Testing encrypted enveloping%s...\n",
useDatasize ? " with datasize hint" : "" );
/* Create the session key context. We don't check for errors here
since this code will already have been tested earlier */
cryptCreateContext( &cryptContext, CRYPT_UNUSED, CRYPT_ALGO_3DES );
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,
"0123456789ABCDEF", 16 );
/* Create the envelope, push in a KEK and the data, pop the enveloped
result, and destroy the envelope */
if( !createEnvelope( &cryptEnvelope, formatType ) || \
!addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_KEY, cryptContext ) )
return( FALSE );
if( useDatasize )
cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,
ENVELOPE_TESTDATA_SIZE );
count = pushData( cryptEnvelope, ENVELOPE_TESTDATA,
ENVELOPE_TESTDATA_SIZE, 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 = envelopeDecrypt( globalBuffer, count, cryptContext );
if( !count )
return( FALSE );
if( count != ENVELOPE_TESTDATA_SIZE || \
memcmp( globalBuffer, ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE ) )
{
puts( "De-enveloped data != original data." );
return( FALSE );
}
/* Clean up */
cryptDestroyContext( cryptContext );
puts( "Enveloping of encrypted data succeeded.\n" );
return( TRUE );
}
int testEnvelopeCrypt( void )
{
if( !envelopeCrypt( "env_kekn", FALSE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Indefinite length */
return( envelopeCrypt( "env_kek", TRUE, CRYPT_FORMAT_CRYPTLIB ) );
} /* Datasize */
/* Test password-based encrypted enveloping */
static int envelopePasswordDecrypt( BYTE *buffer, const int length )
{
CRYPT_ENVELOPE cryptEnvelope;
int count;
/* Create the envelope, push in the data, pop the de-enveloped result,
and destroy the envelope */
if( !createDeenvelope( &cryptEnvelope ) )
return( FALSE );
count = pushData( cryptEnvelope, buffer, length, TEXT( "Password" ),
paramStrlen( TEXT( "Password" ) ) );
if( cryptStatusError( count ) )
return( FALSE );
count = popData( cryptEnvelope, buffer, BUFFER_SIZE );
if( cryptStatusError( count ) )
return( FALSE );
destroyEnvelope( cryptEnvelope );
return( count );
}
static int envelopePasswordCrypt( const char *dumpFileName,
const BOOLEAN useDatasize,
const BOOLEAN useAltCipher,
const BOOLEAN multiKeys,
const CRYPT_FORMAT_TYPE formatType )
{
CRYPT_ENVELOPE cryptEnvelope;
int count;
printf( "Testing %s%spassword-encrypted enveloping%s",
( formatType == CRYPT_FORMAT_PGP ) ? "PGP " : "",
multiKeys ? "multiple-" : "",
( useDatasize && ( formatType != CRYPT_FORMAT_PGP ) ) ? \
" with datasize hint" : "" );
if( useAltCipher )
printf( ( formatType == CRYPT_FORMAT_PGP ) ? \
" with non-default cipher type" : " and stream cipher" );
puts( "..." );
/* Create the envelope, push in a password and the data, pop the
enveloped result, and destroy the envelope */
if( !createEnvelope( &cryptEnvelope, formatType ) || \
!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,
TEXT( "Password" ),
paramStrlen( TEXT( "Password" ) ) ) )
return( FALSE );
if( useAltCipher )
{
CRYPT_CONTEXT sessionKeyContext;
int status;
/* Test enveloping with an IV-less stream cipher, which tests the
handling of algorithms that can't be used to wrap themselves in
the RecipientInfo */
status = cryptCreateContext( &sessionKeyContext, CRYPT_UNUSED,
CRYPT_ALGO_RC4 );
if( cryptStatusOK( status ) )
{
cryptGenerateKey( sessionKeyContext );
status = cryptSetAttribute( cryptEnvelope,
CRYPT_ENVINFO_SESSIONKEY,
sessionKeyContext );
cryptDestroyContext( sessionKeyContext );
}
if( cryptStatusError( status ) )
{
printf( "Couldn't set non-default envelope cipher, error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
}
if( multiKeys && \
( !addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,
TEXT( "Password1" ),
paramStrlen( TEXT( "Password1" ) ) ) || \
!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,
TEXT( "Password2" ),
paramStrlen( TEXT( "Password2" ) ) ) || \
!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,
TEXT( "Password3" ),
paramStrlen( TEXT( "Password3" ) ) ) ) )
return( FALSE );
if( useDatasize )
cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,
ENVELOPE_TESTDATA_SIZE );
count = pushData( cryptEnvelope, ENVELOPE_TESTDATA,
ENVELOPE_TESTDATA_SIZE, 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 = envelopePasswordDecrypt( globalBuffer, count );
if( !count )
return( FALSE );
if( count != ENVELOPE_TESTDATA_SIZE || \
memcmp( globalBuffer, ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE ) )
{
puts( "De-enveloped data != original data." );
return( FALSE );
}
/* Clean up */
puts( "Enveloping of password-encrypted data succeeded.\n" );
return( TRUE );
}
int testEnvelopePasswordCrypt( void )
{
if( !envelopePasswordCrypt( "env_pasn", FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Indefinite length */
if( !envelopePasswordCrypt( "env_pas", TRUE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Datasize */
if( !envelopePasswordCrypt( "env_mpas", TRUE, FALSE, TRUE, CRYPT_FORMAT_CRYPTLIB ) )
return( FALSE ); /* Datasize, multiple keys */
if( !envelopePasswordCrypt( "env_pas.pgp", TRUE, FALSE, FALSE, CRYPT_FORMAT_PGP ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -