📄 envelope.c
字号:
{
if( !envelopePKCCrypt( "env_pkcn", FALSE, KEYFILE_PGP, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* Indefinite length, raw key */
if( !envelopePKCCrypt( "env_pkc", TRUE, KEYFILE_PGP, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* Datasize, raw key */
if( !envelopePKCCrypt( "env_pkc.pgp", TRUE, KEYFILE_PGP, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* PGP format */
if( !envelopePKCCrypt( "env_pkc.pgp", TRUE, KEYFILE_PGP, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* PGP format, recipient */
if( !envelopePKCCrypt( "env_pkca.pgp", TRUE, KEYFILE_PGP, TRUE, FALSE, TRUE, FALSE, CRYPT_FORMAT_PGP, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* PGP format, recipient, nonstandard bulk encr.algo */
if( !envelopePKCCrypt( "env_pkc.gpg", TRUE, KEYFILE_OPENPGP, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* OpenPGP format, recipient (required for DSA/Elgamal keys) */
if( !envelopePKCCrypt( "env_pkce.der", TRUE, KEYFILE_OPENPGP, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* Datasize, recipient w/Elgamal key for indef-length recipient info */
}
if( !envelopePKCCrypt( "env_crt.pgp", TRUE, KEYFILE_X509, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* PGP format, certificate */
if( !envelopePKCCrypt( "env_crtn", FALSE, KEYFILE_X509, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* Indefinite length, certificate */
if( !envelopePKCCrypt( "env_crt", TRUE, KEYFILE_X509, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* Datasize, certificate */
if( !envelopePKCCrypt( "env_crt", TRUE, KEYFILE_X509, FALSE, FALSE, FALSE, TRUE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* Datasize, certificate, decrypt key provided directly */
if( !envelopePKCCrypt( "env_crt", TRUE, KEYFILE_X509, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )
return( FALSE ); /* Datasize, cerficate, recipient */
return( envelopePKCCrypt( "env_crtp", TRUE, KEYFILE_X509, FALSE, TRUE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) );
} /* Datasize, cerficate+password */
int testEnvelopePKCCryptEx( const CRYPT_CONTEXT cryptContext,
const CRYPT_HANDLE decryptKeyset )
{
/* Note that we can't test PGP enveloping with device-based keys since
the PGP keyIDs aren't supported by any known device type */
#if 0
if( !envelopePKCCrypt( "env_pkc.pgp", TRUE, KEYFILE_NONE, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP, cryptContext, decryptKeyset ) )
return( FALSE ); /* PGP format */
#endif
return( envelopePKCCrypt( "env_pkc", TRUE, KEYFILE_NONE, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, cryptContext, decryptKeyset ) );
} /* Datasize, raw key */
/* Test signed enveloping */
static int getSigCheckResult( const CRYPT_ENVELOPE cryptEnvelope,
const CRYPT_CONTEXT sigCheckContext,
const BOOLEAN showAttributes,
const BOOLEAN isAuthData )
{
int value, status;
/* Display all of the attributes that we've got */
if( showAttributes && !displayAttributes( cryptEnvelope ) )
return( FALSE );
/* Determine the result of the signature check. If it's authenticated
data there's no need to do anything with keys, if it's signed data
we have to do some extra processing */
if( !isAuthData )
{
status = cryptGetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_CURRENT,
&value );
if( cryptStatusError( status ) )
{
printf( "Read of required attribute for signature check "
"returned status %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
if( value != CRYPT_ENVINFO_SIGNATURE )
{
printf( "Envelope requires unexpected enveloping information "
"type %d, line %d.\n", value, __LINE__ );
return( FALSE );
}
if( sigCheckContext != CRYPT_UNUSED )
{
status = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,
sigCheckContext );
if( cryptStatusError( status ) )
{
printf( "Attempt to add signature check key returned status "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
}
}
status = cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE_RESULT,
&value );
if( cryptStatusError( status ) )
{
printf( "Signature check returned status %d, line %d.\n", status,
__LINE__ );
return( FALSE );
}
switch( value )
{
case CRYPT_OK:
puts( "Signature is valid." );
return( TRUE );
case CRYPT_ERROR_NOTFOUND:
puts( "Cannot find key to check signature." );
break;
case CRYPT_ERROR_SIGNATURE:
puts( "Signature is invalid." );
break;
case CRYPT_ERROR_NOTAVAIL:
puts( "Warning: Couldn't verify signature due to use of a "
"deprecated/insecure\n signature algorithm.\n" );
return( TRUE );
default:
printf( "Signature check failed, result = %d, line %d.\n",
value, __LINE__ );
}
return( FALSE );
}
static int envelopeSigCheck( BYTE *buffer, const int length,
const CRYPT_CONTEXT hashContext,
const CRYPT_CONTEXT sigContext,
const BOOLEAN useRawKey,
const BOOLEAN useAltRawKey,
const BOOLEAN detachedSig,
const CRYPT_FORMAT_TYPE formatType )
{
CRYPT_ENVELOPE cryptEnvelope;
int count, status;
/* Create the envelope and push in the sig.check keyset if we're not
using a supplied context for the sig.check */
if( !createDeenvelope( &cryptEnvelope ) )
return( FALSE );
if( sigContext == CRYPT_UNUSED )
{
CRYPT_KEYSET cryptKeyset;
if( useRawKey )
{
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
CRYPT_KEYSET_FILE,
useAltRawKey ? \
OPENPGP_PUBKEY_FILE : PGP_PUBKEY_FILE,
CRYPT_KEYOPT_READONLY );
}
else
{
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
CRYPT_KEYSET_FILE, USER_PRIVKEY_FILE,
CRYPT_KEYOPT_READONLY );
}
if( cryptStatusOK( status ) )
status = addEnvInfoNumeric( cryptEnvelope,
CRYPT_ENVINFO_KEYSET_SIGCHECK, cryptKeyset );
cryptKeysetClose( cryptKeyset );
if( status <= 0 )
return( FALSE );
}
/* 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, FALSE ) )
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,
getKeyfileUserID( KEYFILE_PGP, TRUE ),
getKeyfilePassword( useAltRawKey ? \
KEYFILE_OPENPGP : KEYFILE_PGP ) );
cryptKeysetClose( cryptKeyset );
}
}
else
status = getPrivateKey( &cryptContext, USER_PRIVKEY_FILE,
USER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
if( cryptStatusError( status ) )
{
printf( "Read of private key from key file failed, status %d, "
"line %d, cannot test enveloping.\n", status, __LINE__ );
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 */
status = cryptCreateContext( &hashContext, CRYPT_UNUSED,
CRYPT_ALGO_RIPEMD160 );
if( cryptStatusError( status ) )
return( FALSE );
status = addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_HASH,
hashContext );
cryptDestroyContext( hashContext );
if( status <= 0 )
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) */
status = cryptCreateContext( &hashContext, CRYPT_UNUSED,
CRYPT_ALGO_SHA );
if( cryptStatusError( status ) )
return( FALSE );
status = addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_HASH,
hashContext );
cryptDestroyContext( hashContext );
if( status <= 0 )
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-envelo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -