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

📄 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 */
#ifdef _MSC_VER
  #include "../cryptlib.h"
  #include "test.h"
#else
  #include "cryptlib.h"
  #include "test/test.h"
#endif /* Braindamaged MSC include handling */

#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;

/****************************************************************************
*																			*
*								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() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}

	return( TRUE );
	}

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

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

		/* Add the appropriate enveloping information 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 decryptoin 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 );

		/* If we're using some form of encrypted enveloping, report the
		   algorithm and keysize used */
		if( cryptEnvInfo == CRYPT_ATTRIBUTE_NONE || \
			cryptEnvInfo == CRYPT_ENVINFO_PRIVATEKEY || \
			cryptEnvInfo == CRYPT_ENVINFO_PASSWORD )
			{
			int cryptAlgo, keySize;

			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 );
			}

		/* If we only got some of the data in due to the envelope stopping to
		   ask us for a decryption resource, push in the rest */
		if( bytesIn < length && isRestartable )
			{
			const int initialBytesIn = bytesIn;

			status = cryptPushData( envelope, buffer + initialBytesIn, 
									length - initialBytesIn, &bytesIn );
			if( cryptStatusError( status ) )
				{
				printf( "cryptPushData() for remaining data failed with "
						"error code %d, line %d.\n", status, __LINE__ );
				return( status );
				}
			bytesIn += initialBytesIn;

⌨️ 快捷键说明

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