⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 envelope.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*						cryptlib Enveloping Test Routines					*
*						Copyright Peter Gutmann 1996-2005					*
*																			*
****************************************************************************/

#include <limits.h>		/* To determine max.buffer size we can encrypt */
#include "cryptlib.h"
#include "test/test.h"

#if defined( __MVS__ ) || defined( __VMCMS__ )
  /* Suspend conversion of literals to ASCII. */
  #pragma convlit( suspend )
#endif /* IBM big iron */
#if defined( __ILEC400__ )
  #pragma convert( 0 )
#endif /* IBM medium iron */

/* Test data to use for the self-test.  The PGP test data is slightly
   different since it's not possible to include a null character in data
   generated via the command-line versions of PGP.  On EBCDIC systems we
   have to hardcode in the character codes since the pre-generated data
   came from an ASCII system */

#if defined( __MVS__ ) || defined( __VMCMS__ )
  #define ENVELOPE_TESTDATA		( ( BYTE * ) "\x53\x6F\x6D\x65\x20\x74\x65\x73\x74\x20\x64\x61\x74\x61" )
  #define ENVELOPE_PGP_TESTDATA	( ( BYTE * ) "\x53\x6F\x6D\x65\x20\x74\x65\x73\x74\x20\x64\x61\x74\x61\x2E" )
  #define ENVELOPE_COMPRESSEDDATA	"\x2F\x2A\x20\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x6C\x6F\x77\x65\x73\x74\x2D"
#else
  #define ENVELOPE_TESTDATA		( ( BYTE * ) "Some test data" )
  #define ENVELOPE_PGP_TESTDATA	( ( BYTE * ) "Some test data." )
  #define ENVELOPE_COMPRESSEDDATA	"/* This is a lowest-"
#endif /* EBCDIC systems */
#define ENVELOPE_TESTDATA_SIZE			15
#define ENVELOPE_COMPRESSEDDATA_SIZE	20

/* To convert a CMS blob into an S/MIME message, base64 encode it and add
   the following header:

	To: <address>
	Subject: S/MIME test
	From: <address>
	MIME-Version: 1.0
	Content-Type: application/x-pkcs7-mime;smime-type=signed-data;name="smime.p7m"
	Content-Disposition: attachment;filename="smime.p7m"
	Content-Transfer-Encoding: base64

	<base64-encoded data>

   To allow the inner message to be processed by a mailer, the contents will
   themselves have to be MIME-formatted:

	MIME-Version: 1.0
	Content-Type: text/plain;charset="us-ascii"
	Content-Transfer-Encoding: 7bit

	<text> */

/* External flags which indicate that the key read/update routines worked OK.
   This is set by earlier self-test code, if it isn't set some of the tests
   are disabled */

extern int keyReadOK, doubleCertOK;

#if defined( TEST_ENVELOPE ) || defined( TEST_SESSION )	/* For TSP enveloping */

/****************************************************************************
*																			*
*								Utility Routines 							*
*																			*
****************************************************************************/

/* The general-purpose buffer used for enveloping.  We use a fixed buffer
   if possible to save having to add huge amounts of allocation/deallocation
   code */

BYTE FAR_BSS globalBuffer[ BUFFER_SIZE ];

/* Determine the size of a file.  If there's a problem, we return the
   default buffer size, which will cause a failure further up the chain
   where the error can be reported better */

static int getFileSize( const char *fileName )
	{
	FILE *filePtr;
	long size;

	if( ( filePtr = fopen( fileName, "rb" ) ) == NULL )
		return( BUFFER_SIZE );
	fseek( filePtr, 0L, SEEK_END );
	size = ftell( filePtr );
	fclose( filePtr );
	if( size > INT_MAX )
		return( BUFFER_SIZE );

	return( ( int ) size );
	}

/* Read test data from a file */

static int readFileData( const char *fileName, const char *description,
						 BYTE *buffer, const int bufSize )
	{
	FILE *filePtr;
	int count;

	if( ( filePtr = fopen( fileName, "rb" ) ) == NULL )
		{
		printf( "Couldn't find %s file, skipping test of data import...\n",
				description );
		return( 0 );
		}
	printf( "Testing %s import...\n", description );
	count = fread( buffer, 1, bufSize, filePtr );
	fclose( filePtr );
	if( count >= bufSize )
		{
		puts( "The data buffer size is too small for the data.  To fix this, "
			  "either increase\nthe BUFFER_SIZE value in " __FILE__ " and "
			  "recompile the code, or use the\ntest code with dynamically-"
			  "allocated buffers." );
		return( 0 );		/* Skip this test and continue */
		}
	if( count < 16 )
		{
		printf( "Read failed, only read %d bytes.\n", count );
		return( 0 );		/* Skip this test and continue */
		}
	printf( "%s has size %d bytes.\n", description, count );
	return( count );
	}

/* Common routines to create an envelope, add enveloping information, push
   data, pop data, and destroy an envelope */

static int createEnvelope( CRYPT_ENVELOPE *envelope,
						   const CRYPT_FORMAT_TYPE formatType )
	{
	int status;

	/* Create the envelope */
	status = cryptCreateEnvelope( envelope, CRYPT_UNUSED, formatType );
	if( cryptStatusError( status ) )
		{
		printf( "cryptCreateEnvelope() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}

	return( TRUE );
	}

static int createDeenvelope( CRYPT_ENVELOPE *envelope )
	{
	int status;

	/* Create the envelope */
	status = cryptCreateEnvelope( envelope, CRYPT_UNUSED, CRYPT_FORMAT_AUTO );
	if( cryptStatusError( status ) )
		{
		printf( "cryptCreateDeevelope() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}

	return( TRUE );
	}

static int addEnvInfoString( const CRYPT_ENVELOPE envelope,
							 const CRYPT_ATTRIBUTE_TYPE type,
							 const void *envInfo, const int envInfoLen )
	{
	int status;

	status = cryptSetAttributeString( envelope, type, envInfo, envInfoLen );
	if( cryptStatusError( status ) )
		{
		printf( "cryptSetAttributeString() failed with error code %d, "
				"line %d.\n", status, __LINE__ );
		return( FALSE );
		}

	return( TRUE );
	}

static int addEnvInfoNumeric( const CRYPT_ENVELOPE envelope,
							  const CRYPT_ATTRIBUTE_TYPE type,
							  const int envInfo )
	{
	int status;

	status = cryptSetAttribute( envelope, type, envInfo );
	if( cryptStatusError( status ) )
		{
		printf( "cryptSetAttribute() of %d failed with error code %d, "
				"line %d.\n", type, status, __LINE__ );
		return( FALSE );
		}

	return( TRUE );
	}

static int processEnvelopeResource( const CRYPT_ENVELOPE envelope, 
									const void *stringEnvInfo,
									const int numericEnvInfo,
									BOOLEAN *isRestartable )
	{
	int cryptEnvInfo, cryptAlgo, keySize, integrityLevel, status;

	/* Clear return value */
	*isRestartable = FALSE;
	
	/* Add the appropriate enveloping information that we need to 
	   continue */
	status = cryptSetAttribute( envelope, CRYPT_ATTRIBUTE_CURRENT_GROUP,
								CRYPT_CURSOR_FIRST );
	if( cryptStatusError( status ) )
		{
		printf( "Attempt to move cursor to start of list failed with error "
				"code %d, line %d.\n", status, __LINE__ );
		return( status );
		}
	do
		{
		C_CHR label[ CRYPT_MAX_TEXTSIZE + 1 ];
		int labelLength;

		status = cryptGetAttribute( envelope, CRYPT_ATTRIBUTE_CURRENT,
									&cryptEnvInfo );
		if( cryptStatusError( status ) )
			{
			printf( "Attempt to read current group failed with error code "
					"%d, line %d.\n", status, __LINE__ );
			return( status );
			}

		switch( cryptEnvInfo )
			{
			case CRYPT_ATTRIBUTE_NONE:
				/* The required information was supplied via other means (in 
				   practice this means there's a crypto device available and 
				   that was used for the decrypt), there's nothing left to 
				   do */
				puts( "(Decryption key was recovered using crypto device or "
					  "non-password-protected\n private key)." );
				break;

			case CRYPT_ENVINFO_PRIVATEKEY:
				/* If there's no decryption password present, the private 
				   key must be passed in directly */
				if( stringEnvInfo == NULL )
					{
					status = cryptSetAttribute( envelope,
												CRYPT_ENVINFO_PRIVATEKEY,
												numericEnvInfo );
					if( cryptStatusError( status ) )
						{
						printf( "Attempt to add private key failed with "
								"error code %d, line %d.\n", status, 
								__LINE__ );
						return( status );
						}
					*isRestartable = TRUE;
					break;
					}

				/* A private-key keyset is present in the envelope, we need 
				   a password to decrypt the key */
				status = cryptGetAttributeString( envelope,
									CRYPT_ENVINFO_PRIVATEKEY_LABEL,
									label, &labelLength );
				if( cryptStatusError( status ) )
					{
					printf( "Private key label read failed with error code "
							"%d, line %d.\n", status, __LINE__ );
					return( status );
					}
#ifdef UNICODE_STRINGS
				label[ labelLength / sizeof( wchar_t ) ] = '\0';
				printf( "Need password to decrypt private key '%S'.\n", 
						label );
#else
				label[ labelLength ] = '\0';
				printf( "Need password to decrypt private key '%s'.\n",
						label );
#endif /* UNICODE_STRINGS */
				if( !addEnvInfoString( envelope, CRYPT_ENVINFO_PASSWORD,
								stringEnvInfo, paramStrlen( stringEnvInfo ) ) )
					return( SENTINEL );
				*isRestartable = TRUE;
				break;

			case CRYPT_ENVINFO_PASSWORD:
				puts( "Need user password." );
				if( !addEnvInfoString( envelope, CRYPT_ENVINFO_PASSWORD,
							stringEnvInfo, paramStrlen( stringEnvInfo ) ) )
					return( SENTINEL );
				*isRestartable = TRUE;
				break;

			case CRYPT_ENVINFO_SESSIONKEY:
				puts( "Need session key." );
				if( !addEnvInfoNumeric( envelope, CRYPT_ENVINFO_SESSIONKEY,
										numericEnvInfo ) )
					return( SENTINEL );
				*isRestartable = TRUE;
				break;

			case CRYPT_ENVINFO_KEY:
				puts( "Need conventional encryption key." );
				if( !addEnvInfoNumeric( envelope, CRYPT_ENVINFO_KEY,
										numericEnvInfo ) )
					return( SENTINEL );
				*isRestartable = TRUE;
				break;

			case CRYPT_ENVINFO_SIGNATURE:
				/* If we've processed the entire data block in one go, we 
				   may end up with only signature information available, in 
				   which case we defer processing them until after we've 
				   finished with the deenveloped data */
				break;

			default:
				printf( "Need unknown enveloping information type %d.\n",
						cryptEnvInfo );
				return( SENTINEL );
			}
		}
	while( cryptSetAttribute( envelope, CRYPT_ATTRIBUTE_CURRENT_GROUP,
							  CRYPT_CURSOR_NEXT ) == CRYPT_OK );

	/* Check whether there's any integrity protection present */
	status = cryptGetAttribute( envelope, CRYPT_ENVINFO_INTEGRITY, 
								&integrityLevel );
	if( cryptStatusError( status ) )
		{
		printf( "Couldn't query integrity protection used in envelope, "
				"status %d, line %d.\n", status, __LINE__ );
		return( status );
		}
	if( integrityLevel > CRYPT_INTEGRITY_NONE )
		{
		printf( "Data is integrity-proteced using %s authentication.\n",
				( integrityLevel == CRYPT_INTEGRITY_MACONLY ) ? \
					"MAC" : "MAC+encrypt" );
		}

	/* If we're not using encryption, we're done */
	if( cryptEnvInfo != CRYPT_ATTRIBUTE_NONE && \
		cryptEnvInfo != CRYPT_ENVINFO_PRIVATEKEY && \
		cryptEnvInfo != CRYPT_ENVINFO_PASSWORD )
		return( CRYPT_OK );
	if( integrityLevel == CRYPT_INTEGRITY_MACONLY )
		return( CRYPT_OK );

	/* If we're using some form of encrypted enveloping, report the 
	   algorithm and keysize used */
	status = cryptGetAttribute( envelope, CRYPT_CTXINFO_ALGO, &cryptAlgo );
	if( cryptStatusOK( status ) )
		status = cryptGetAttribute( envelope, CRYPT_CTXINFO_KEYSIZE, 
									&keySize );
	if( cryptStatusError( status ) )
		{
		printf( "Couldn't query encryption algorithm and keysize used in "
				"envelope, status %d, line %d.\n", status, __LINE__ );
		return( status );
		}
	printf( "Data is protected using algorithm %d with %d bit key.\n", 
			cryptAlgo, keySize * 8 );
	
	return( CRYPT_OK );
	}

static int pushData( const CRYPT_ENVELOPE envelope, const BYTE *buffer,
					 const int length, const void *stringEnvInfo,
					 const int numericEnvInfo )
	{
	int bytesIn, contentType, status;

	/* Push in the data */
	status = cryptPushData( envelope, buffer, length, &bytesIn );
	if( status == CRYPT_ENVELOPE_RESOURCE )
		{
		BOOLEAN isRestartable = FALSE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -