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

📄 lowlvl.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't decrypt data, status = %d.\n", status );
			return( status );
			}

		return( CRYPT_OK );
		}
#ifdef TEST_DH
	if( cryptAlgo == CRYPT_ALGO_DH )
		{
		KEYAGREE_PARAMS keyAgreeParams;
		int status;

		/* Perform the DH key agreement */
		memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
#if 0
		status = krnlSendMessage( cryptContext, IMESSAGE_CTX_ENCRYPT,
								  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( cryptContext, IMESSAGE_CTX_DECRYPT,
									  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
#else
		status = cryptDeviceQueryCapability( cryptContext, 1001,
									( CRYPT_QUERY_INFO * ) &keyAgreeParams );
		if( cryptStatusOK( status ) )
			status = cryptDeviceQueryCapability( cryptContext, 1002,
										( CRYPT_QUERY_INFO * ) &keyAgreeParams );
#endif /* 0 */
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't perform DH key agreement, status = %d.\n",
					status );
			return( FALSE );
			}

		return( CRYPT_OK );
		}
#endif /* TEST_DH */
	if( cryptAlgo == CRYPT_ALGO_RSA )
		{
		static const BYTE rsa512Value[] = \
			"\x4E\x1F\x2F\x10\xA9\xFB\x4F\xD9\xC1\x25\x79\x7A\x36\x00\x58\xD0"
			"\x9E\x8B\x9F\xBA\xC7\x04\x10\x77\xDB\xBC\xC9\xD1\x70\xCD\xF6\x86"
			"\xA4\xDC\x39\xA9\x57\xD7\xC7\xE0\x87\xF2\x31\xDF\x83\x7d\x27\x0E"
			"\xB4\xA6\x93\x3D\x11\xEB\xA5\x0E\x42\x66\x7B\x30\x50\x84\xC1\x81";
		static const BYTE rsa1024Value[] = \
			"\x84\x8E\x00\x3E\x49\x11\x0D\x42\x4C\x71\x6B\xB4\xCF\x13\xDD\xCD"
			"\x12\x30\x56\xC2\x4A\x55\x3B\xD8\x30\xA2\xB8\x73\xA7\xAB\xF0\x7A"
			"\x2E\x07\x20\xCC\xBE\xEA\x58\x03\x56\xF6\x18\x27\x28\x4F\xE1\x02"
			"\xC6\x49\x79\x6C\xB4\x7E\x6C\xC6\x93\x2E\xF1\x46\x83\x15\x5A\xB7"
			"\x7D\xCC\x21\xEE\x4E\x3E\x0B\x8B\x85\xEE\x08\x21\xE6\xA7\x31\x53"
			"\x2E\x92\x3D\x2D\xB0\xD4\xA1\x30\xF4\xE9\xEB\x37\xBF\xCD\x2F\xE1"
			"\x60\x89\x19\xB6\x8C\x01\xFB\xD8\xAC\xF5\xC7\x4B\xB4\x74\x8A\x35"
			"\x79\xE6\xE0\x48\xBD\x9C\x9F\xD7\x4A\x1C\x8A\x58\xAB\xA9\x3C\x44";
		BYTE testBuffer[ TESTBUFFER_SIZE ], tmpBuffer[ 32 ];
		BOOLEAN encryptOK = TRUE;
		int length;

		/* Take a copy of the input so we can compare it with decrypted
		   output and find out how much data we need to process */
		memcpy( testBuffer, buffer, TESTBUFFER_SIZE );
		cryptGetAttribute( cryptContext, CRYPT_CTXINFO_KEYSIZE, &length );

		/* Since we're doing raw RSA encryption we need to format the data
		   specially to work with the RSA key being used.  If we're using the
		   cryptlib native routines, we need to ensure that the magnitude of
		   the integer corresponding to the data to be encrypted is less than
		   the modulus, which we do by setting the first byte of the buffer
		   to 1.  If we're using a crypto device, we need to create a (dummy)
		   PKCS #1-like format since some devices expect to see PKCS #1-
		   formatted data as input to/output from the RSA encryption/
		   decryption operation */
		memcpy( tmpBuffer, buffer, 18 );
		if( isDevice )
			memcpy( buffer, "\x00\x02\xA5\xA5\xA5\xA5\xA5\xA5"
							"\xA5\xA5\xA5\xA5\xA5\xA5\xA5\xA5"
							"\xA5\x00", 18 );
		else
			buffer[ 0 ] = 1;

		/* Since the PKC algorithms only handle a single block, we only
		   perform a single encrypt and decrypt operation */
		status = cryptEncrypt( cryptContext, buffer, length );
		if( cryptStatusError( status ) )
			{
			if( !noWarnFail )
				printf( "Couldn't encrypt data, status = %d.\n", status );
			return( status );
			}
		if( cryptAlgo == CRYPT_ALGO_RSA && !isDevice && \
			memcmp( buffer, ( length == 64 ) ? rsa512Value : rsa1024Value,
					length ) )
			{
			/* For a non-randomized PKC the encryption of the fixed value
			   produces known output, we make sure that this matches the 
			   expected value.  This makes diagnosing problems with crypto 
			   devices rather easier */
			puts( "The actual encrypted value doesn't match the expected value." );
			encryptOK = FALSE;
			}
		status = cryptDecrypt( decryptContext, buffer, length );
		if( cryptStatusError( status ) )
			{
			if( !noWarnFail )
				{
				if( encryptOK )
					printf( "Couldn't decrypt data even though the "
							"encrypted input data was valid,\nstatus = "
							"%d.\n", status );
				else
					printf( "Couldn't decrypt data, probably because the "
							"data produced by the encrypt step\nwas "
							"invalid, status = %d.\n", status );
				}
			return( status );
			}
		if( isDevice )
			memcpy( buffer, tmpBuffer, 18 );
		else
			buffer[ 0 ] = tmpBuffer[ 0 ];

		/* Make sure that the recovered result matches the input data */
		if( memcmp( buffer, testBuffer, length ) )
			{
			if( encryptOK )
				/* This could happen with simple-minded CRT implementations
				   that only work when p > q (the test key has p < q in 
				   order to find this problem) */
				puts( "Decryption failed even though encryption produced "
					  "valid data.  The RSA\ndecryption step is broken." );
			else
				puts( "Decryption failed because the encryption step "
					  "produced invalid data. The RSA\nencryption step is "
					  "broken." );
			return( status );
			}
		else
			if( !encryptOK )
				{
				puts( "Decryption succeeded even though encryption produced "
					  "invalid data.  The RSA\nimplementation is broken." );
				return( status );
				}

		return( CRYPT_OK );
		}
	if( cryptAlgo >= CRYPT_ALGO_FIRST_HASH && \
		cryptAlgo <= CRYPT_ALGO_LAST_MAC )
		{
		/* Hash the buffer in two odd-sized chunks.  Note the use of the hash
		   wrap-up call, this is the only time when we can call 
		   cryptEncrypt() with a zero length */
		status = cryptEncrypt( cryptContext, buffer, 80 );
		if( cryptStatusOK( status ) )
			status = cryptEncrypt( cryptContext, buffer + 80,
								   TESTBUFFER_SIZE - 80 );
		if( cryptStatusOK( status ) )
			status = cryptEncrypt( cryptContext, buffer + TESTBUFFER_SIZE, 0 );
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't hash data, status = %d.\n", status );
			return( status );
			}

		/* Hash the buffer in different odd-size chunks */
		status = cryptEncrypt( decryptContext, buffer, 128 );
		if( cryptStatusOK( status ) )
			status = cryptEncrypt( decryptContext, buffer + 128,
								   TESTBUFFER_SIZE - 128 );
		if( cryptStatusOK( status ) )
			status = cryptEncrypt( decryptContext, buffer + TESTBUFFER_SIZE, 0 );
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't hash data, status = %d.\n", status );
			return( status );
			}

		return( CRYPT_OK );
		}

	printf( "Unknown encryption algorithm/mode %d.\n", cryptAlgo );
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Low-level Routines Test							*
*																			*
****************************************************************************/

/* Test an algorithm/mode implementation */

int testLowlevel( const CRYPT_DEVICE cryptDevice,
				  const CRYPT_ALGO_TYPE cryptAlgo, const BOOLEAN checkOnly )
	{
	CRYPT_MODE_TYPE cryptMode = CRYPT_MODE_ECB;
	CRYPT_CONTEXT cryptContext, decryptContext;
	BYTE buffer[ TESTBUFFER_SIZE ], testBuffer[ TESTBUFFER_SIZE ];
	const BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;
	BOOLEAN modesTested[ 8 ] = { 0 }, testSucceeded = FALSE;
	int status;

	/* Initialise the test buffers */
	initTestBuffers( buffer, testBuffer, TESTBUFFER_SIZE );

	/* Check cryptlib's capabilities */
	if( !checkLowlevelInfo( cryptDevice, cryptAlgo ) )
		return( FALSE );

	/* If we're only doing a capability check, don't try anything else */
	if( checkOnly )
		return( TRUE );

	/* Since DH and KEA only perform key agreement rather than a true key
	   exchange, we can't test their encryption capabilities unless we're 
	   using a custom-modified version of cryptlib */
#ifndef TEST_DH
	if( cryptAlgo == CRYPT_ALGO_DH )
		return( TRUE );
#endif /* TEST_DH */
	if( cryptAlgo == CRYPT_ALGO_KEA )
		return( TRUE );

	/* Test each mode of an algorithm.  We have to be very careful about
	   destroying any objects we create before we exit, because objects left
	   active in a device will prevent it from being shut down once the 
	   tests have completed */
	do
		{
		/* Set up an encryption context, load a user key into it, and
		   perform a key setup */
		switch( cryptAlgo )
			{
			case CRYPT_ALGO_DES:
				status = loadContexts( &cryptContext, &decryptContext,
									   cryptDevice, cryptAlgo, cryptMode,
									   ( BYTE * ) "12345678", 8 );
				break;

			case CRYPT_ALGO_SKIPJACK:
				status = loadContexts( &cryptContext, &decryptContext,
									   cryptDevice, cryptAlgo, cryptMode,
									   ( BYTE * ) "1234567890", 10 );
				break;

			case CRYPT_ALGO_CAST:
			case CRYPT_ALGO_IDEA:
			case CRYPT_ALGO_AES:
				status = loadContexts( &cryptContext, &decryptContext,
									   cryptDevice, cryptAlgo, cryptMode,
									   ( BYTE * ) "1234567887654321", 16 );
				break;

			case CRYPT_ALGO_3DES:
				status = loadContexts( &cryptContext, &decryptContext,
									   cryptDevice, cryptAlgo, cryptMode,
									   ( BYTE * ) "123456788765432112345678", 24 );
				break;

			case CRYPT_ALGO_RC2:
			case CRYPT_ALGO_RC4:
			case CRYPT_ALGO_RC5:
			case CRYPT_ALGO_BLOWFISH:
			case CRYPT_ALGO_HMAC_MD5:
			case CRYPT_ALGO_HMAC_SHA:
			case CRYPT_ALGO_HMAC_RIPEMD160:
				status = loadContexts( &cryptContext, &decryptContext,
									   cryptDevice, cryptAlgo, cryptMode,
									   ( BYTE * ) "1234567890098765432112345678900987654321", 40 );
				break;

			case CRYPT_ALGO_MD2:
			case CRYPT_ALGO_MD4:
			case CRYPT_ALGO_MD5:
			case CRYPT_ALGO_SHA:
			case CRYPT_ALGO_SHA2:
			case CRYPT_ALGO_RIPEMD160:
				status = loadContexts( &cryptContext, &decryptContext,
									   cryptDevice, cryptAlgo, CRYPT_MODE_NONE,
									   ( BYTE * ) "", 0 );
				break;

#ifdef TEST_DH
			case CRYPT_ALGO_DH:
				status = loadDHKey( cryptDevice, &cryptContext );
				break;
#endif /* TEST_DH */

			case CRYPT_ALGO_RSA:
				status = loadRSAContexts( cryptDevice, &cryptContext,
										  &decryptContext );
				break;

			case CRYPT_ALGO_DSA:
				status = loadDSAContexts( cryptDevice, &cryptContext,
										  &decryptContext );
				break;

			case CRYPT_ALGO_ELGAMAL:
				status = loadElgamalContexts( &cryptContext, &decryptContext );
				break;

			default:
				printf( "Unknown encryption algorithm ID %d, cannot perform "
						"encryption test\n", cryptAlgo );
				return( FALSE );
			}
		if( status == CRYPT_ERROR_NOTAVAIL )
			{
			/* It's a conventional algorithm for which this mode isn't
			   available, try a different mode */
			cryptMode++;
			continue;
			}
		if( !status )
			return( FALSE );

		/* DLP-based algorithms can't be called directly from user code
		   because of the special data-formatting requirements */
		if( cryptAlgo == CRYPT_ALGO_DSA || cryptAlgo == CRYPT_ALGO_ELGAMAL )
			{
			destroyContexts( cryptDevice, cryptContext, decryptContext );
			return( TRUE );
			}

		/* Perform a test en/decryption */
		status = testCrypt( cryptContext, decryptContext, buffer, isDevice, 
							FALSE );
		if( cryptStatusError( status ) )
			{
			destroyContexts( cryptDevice, cryptContext, decryptContext );
			if( isDevice && status == CRYPT_ERROR_NOTAVAIL )
				{
				/* Some primitive tokens or accelerators support only the
				   barest minimum of functionality, which may include being
				   able to create objects but not use them (e.g. public key
				   objects in a device which is just an RSA private-key
				   modexp engine).  Because of this we may get a
				   CRYPT_ERROR_NOTAVAIL when we try and perform a low-level
				   crypto test, this isn't normally a problem for cryptlib
				   high-level objects because public-key ops are always done
				   in software, but when we explicitly try to do them in the
				   token it's a problem.  Because of this we report a problem
				   but continue anyway */
				puts( "The crypto device reported that this operation isn't "
					  "available even though it\nsupports the use of "
					  "encryption objects that implement this algorithm.  "
					  "This\nis probably a bare-bones device that only "
					  "supports minimal functionality (eg\nprivate-key "
					  "decryption but not encryption)." );
				continue;
				}
			return( FALSE );
			}

		/* Make sure that everything went OK */
		if( cryptAlgo >= CRYPT_ALGO_FIRST_HASH )
			{
			BYTE hash1[ CRYPT_MAX_HASHSIZE ], hash2[ CRYPT_MAX_HASHSIZE ];
			int length1, length2;

			status = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_HASHVALUE,
											  hash1, &length1 );
			cryptGetAttributeString( decryptContext, CRYPT_CTXINFO_HASHVALUE,
									 hash2, &length2 );
			if( cryptStatusError( status ) )

⌨️ 快捷键说明

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