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

📄 cryptctx.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*					  cryptlib Encryption Context Routines					*
*						Copyright Peter Gutmann 1992-2003					*
*																			*
****************************************************************************/

/* "Modern cryptography is nothing more than a mathematical framework for
	debating the implications of various paranoid delusions"
												- Don Alvarez */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "crypt.h"
#ifdef INC_ALL
  #include "asn1_rw.h"
  #include "context.h"
#else
  #include "misc/asn1_rw.h"
  #include "misc/context.h"
#endif /* Compiler-specific includes */

/* The default size of the salt for PKCS #5v2 key derivation, needed when we
   set the CRYPT_CTXINFO_KEYING_VALUE */

#define PKCS5_SALT_SIZE		8	/* 64 bits */

/* Prototypes for functions in cryptkey.c */

void initKeyHandling( CONTEXT_INFO *contextInfoPtr );

/* Prototypes for functions in lib_krw.c */

void initKeyReadWrite( CONTEXT_INFO *contextInfoPtr );

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Exit after setting extended error information */

static int exitError( CONTEXT_INFO *contextInfoPtr,
					  const CRYPT_ATTRIBUTE_TYPE errorLocus,
					  const CRYPT_ERRTYPE_TYPE errorType, const int status )
	{
	setErrorInfo( contextInfoPtr, errorLocus, errorType );
	return( status );
	}

static int exitErrorInited( CONTEXT_INFO *contextInfoPtr,
							const CRYPT_ATTRIBUTE_TYPE errorLocus )
	{
	return( exitError( contextInfoPtr, errorLocus, 
					   CRYPT_ERRTYPE_ATTR_PRESENT, CRYPT_ERROR_INITED ) );
	}

static int exitErrorNotInited( CONTEXT_INFO *contextInfoPtr,
							   const CRYPT_ATTRIBUTE_TYPE errorLocus )
	{
	return( exitError( contextInfoPtr, errorLocus, 
					   CRYPT_ERRTYPE_ATTR_ABSENT, CRYPT_ERROR_NOTINITED ) );
	}

static int exitErrorNotFound( CONTEXT_INFO *contextInfoPtr,
							  const CRYPT_ATTRIBUTE_TYPE errorLocus )
	{
	return( exitError( contextInfoPtr, errorLocus, 
					   CRYPT_ERRTYPE_ATTR_ABSENT, CRYPT_ERROR_NOTFOUND ) );
	}

/* Check that a capability info record is consistent.  This is a complex
   function which is called from an assert() macro, so we only need to define
   it when we're building a debug version */

#ifndef NDEBUG

BOOLEAN capabilityInfoOK( const CAPABILITY_INFO *capabilityInfoPtr,
						  const BOOLEAN asymmetricOK )
	{
	CRYPT_ALGO_TYPE cryptAlgo = capabilityInfoPtr->cryptAlgo;

	/* Check the algorithm and mode parameters */
	if( cryptAlgo <= CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST_MAC || \
		capabilityInfoPtr->algoName == NULL )
		return( FALSE );

	/* Make sure that the minimum functions are present */
	if( isStreamCipher( cryptAlgo ) )
		{
		if( capabilityInfoPtr->encryptOFBFunction == NULL || \
			capabilityInfoPtr->decryptOFBFunction == NULL )
			return( FALSE );
		}
	else
		if( asymmetricOK )
			{
			/* If asymmetric capabilities (eg decrypt but not encrypt,
			   present in some tinkertoy tokens) are OK, we only check
			   that there's at least one useful capability available */
			if( capabilityInfoPtr->decryptFunction == NULL && \
				capabilityInfoPtr->signFunction == NULL )
				return( FALSE );
			}
		else
			if( ( capabilityInfoPtr->encryptFunction == NULL || \
				  capabilityInfoPtr->decryptFunction == NULL ) && \
				( capabilityInfoPtr->signFunction == NULL || \
				  capabilityInfoPtr->sigCheckFunction == NULL ) )
				return( FALSE );

	/* Make sure that the algorithm/mode names will fit inside the query
	   information structure */
	if( strlen( capabilityInfoPtr->algoName ) > CRYPT_MAX_TEXTSIZE - 1 )
		return( FALSE );

	/* Make sure that the algorithm/mode-specific parameters are
	   consistent */
	if( capabilityInfoPtr->minKeySize > capabilityInfoPtr->keySize || \
		capabilityInfoPtr->maxKeySize < capabilityInfoPtr->keySize )
		return( FALSE );
	if( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
		cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
		{
		if( ( capabilityInfoPtr->blockSize < bitsToBytes( 8 ) || \
        	  capabilityInfoPtr->blockSize > CRYPT_MAX_IVSIZE ) || \
			( capabilityInfoPtr->minKeySize < bitsToBytes( 40 ) || \
			  capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) )
			return( FALSE );
		if( capabilityInfoPtr->initKeyParamsFunction == NULL || \
			!( isStreamCipher( cryptAlgo ) || \
			   capabilityInfoPtr->blockSize >= bitsToBytes( 64 ) ) )
			return( FALSE );
		if( capabilityInfoPtr->initKeyFunction == NULL )
			return( FALSE );
		if( ( capabilityInfoPtr->encryptCBCFunction != NULL && \
			  capabilityInfoPtr->decryptCBCFunction == NULL ) || \
			( capabilityInfoPtr->encryptCBCFunction == NULL && \
			  capabilityInfoPtr->decryptCBCFunction != NULL ) )
			return( FALSE );
		if( ( capabilityInfoPtr->encryptCFBFunction != NULL && \
			  capabilityInfoPtr->decryptCFBFunction == NULL ) || \
			( capabilityInfoPtr->encryptCFBFunction == NULL && \
			  capabilityInfoPtr->decryptCFBFunction != NULL ) )
			return( FALSE );
		if( ( capabilityInfoPtr->encryptOFBFunction != NULL && \
			  capabilityInfoPtr->decryptOFBFunction == NULL ) || \
			( capabilityInfoPtr->encryptOFBFunction == NULL && \
			  capabilityInfoPtr->decryptOFBFunction != NULL ) )
			return( FALSE );
		}
	if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
		cryptAlgo <= CRYPT_ALGO_LAST_PKC )
		{
		if( capabilityInfoPtr->blockSize || \
			( capabilityInfoPtr->minKeySize < bitsToBytes( 512 ) || \
			  capabilityInfoPtr->maxKeySize > CRYPT_MAX_PKCSIZE ) )
			return( FALSE );
		if( capabilityInfoPtr->initKeyFunction == NULL )
			return( FALSE );
		}
	if( cryptAlgo >= CRYPT_ALGO_FIRST_HASH && \
		cryptAlgo <= CRYPT_ALGO_LAST_HASH )
		{
		if( ( capabilityInfoPtr->blockSize < bitsToBytes( 64 ) || \
			  capabilityInfoPtr->blockSize > 256 ) || \
			( capabilityInfoPtr->minKeySize || capabilityInfoPtr->keySize || \
			  capabilityInfoPtr->maxKeySize ) )
			return( FALSE );
		}
	if( cryptAlgo >= CRYPT_ALGO_FIRST_MAC && \
		cryptAlgo <= CRYPT_ALGO_LAST_MAC )
		{
		if( ( capabilityInfoPtr->blockSize < bitsToBytes( 64 ) || \
			  capabilityInfoPtr->blockSize > 256 ) || \
			( capabilityInfoPtr->minKeySize < bitsToBytes( 40 ) || \
			  capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) )
			return( FALSE );
		if( capabilityInfoPtr->initKeyFunction == NULL )
			return( FALSE );
		}

	return( TRUE );
	}
#endif /* !NDEBUG */

/* Get information from a capability record */

void getCapabilityInfo( CRYPT_QUERY_INFO *cryptQueryInfo,
						const CAPABILITY_INFO FAR_BSS *capabilityInfoPtr )
	{
	memset( cryptQueryInfo, 0, sizeof( CRYPT_QUERY_INFO ) );
	strcpy( cryptQueryInfo->algoName, capabilityInfoPtr->algoName );
	cryptQueryInfo->blockSize = capabilityInfoPtr->blockSize;
	cryptQueryInfo->minKeySize = capabilityInfoPtr->minKeySize;
	cryptQueryInfo->keySize = capabilityInfoPtr->keySize;
	cryptQueryInfo->maxKeySize = capabilityInfoPtr->maxKeySize;
	}

/* Find the capability record for a given encryption algorithm */

const CAPABILITY_INFO FAR_BSS *findCapabilityInfo(
					const CAPABILITY_INFO FAR_BSS *capabilityInfoList,
					const CRYPT_ALGO_TYPE cryptAlgo )
	{
	const CAPABILITY_INFO *capabilityInfoPtr;

	/* Find the capability corresponding to the requested algorithm/mode */
	for( capabilityInfoPtr = capabilityInfoList;
		 capabilityInfoPtr != NULL;
		 capabilityInfoPtr = capabilityInfoPtr->next )
		if( capabilityInfoPtr->cryptAlgo == cryptAlgo )
			return( capabilityInfoPtr );

	return( NULL );
	}

/* Initialise key parameters such as the IV and encryption mode, shared by
   most capabilities.  This is never called directly, but is accessed
   through function pointers in the capability lists */

int initKeyParams( CONTEXT_INFO *contextInfoPtr, const void *iv,
				   const int ivLength, const CRYPT_MODE_TYPE mode )
	{
	const int ivSize = ( ivLength == CRYPT_USE_DEFAULT ) ? \
					   contextInfoPtr->capabilityInfo->blockSize : ivLength;

	assert( ( iv != NULL && ( ivLength == CRYPT_USE_DEFAULT || ivLength > 0 ) ) || \
			( mode != CRYPT_UNUSED ) );

	/* Set the en/decryption mode if required */
	if( mode != CRYPT_UNUSED )
		{
		const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
		int ( *encryptFunction )( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
								  int length ) = NULL;
		int ( *decryptFunction )( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
								  int length ) = NULL;

		switch( mode )
			{
			case CRYPT_MODE_ECB:
				encryptFunction = capabilityInfoPtr->encryptFunction;
				decryptFunction = capabilityInfoPtr->decryptFunction;
				break;
			case CRYPT_MODE_CBC:
				encryptFunction = capabilityInfoPtr->encryptCBCFunction;
				decryptFunction = capabilityInfoPtr->decryptCBCFunction;
				break;
			case CRYPT_MODE_CFB:
				encryptFunction = capabilityInfoPtr->encryptCFBFunction;
				decryptFunction = capabilityInfoPtr->decryptCFBFunction;
				break;
			case CRYPT_MODE_OFB:
				encryptFunction = capabilityInfoPtr->encryptOFBFunction;
				decryptFunction = capabilityInfoPtr->decryptOFBFunction;
				break;
			default:
				assert( NOTREACHED );
				return( CRYPT_ERROR );
			}
		if( encryptFunction == NULL )
			return( CRYPT_ERROR_NOTAVAIL );
		contextInfoPtr->ctxConv->mode = mode;
		contextInfoPtr->encryptFunction = encryptFunction;
		contextInfoPtr->decryptFunction = decryptFunction;
		}

	/* If there's no IV present, we're done */
	if( iv == NULL )
		return( CRYPT_OK );

	/* Load an IV of the required length.  If the supplied IV size is less
	   than the actual IV size, we pad it to the right with zeroes */
	contextInfoPtr->ctxConv->ivLength = ivSize;
	contextInfoPtr->ctxConv->ivCount = 0;
	memset( contextInfoPtr->ctxConv->iv, 0, CRYPT_MAX_IVSIZE );
	memcpy( contextInfoPtr->ctxConv->iv, iv, ivSize );
	memcpy( contextInfoPtr->ctxConv->currentIV, contextInfoPtr->ctxConv->iv,
			CRYPT_MAX_IVSIZE );
	contextInfoPtr->flags |= CONTEXT_IV_SET;

	return( CRYPT_OK );
	}

/* Determine the optimal size for the generated key.  This isn't as easy as
   just taking the default key size since some algorithms have variable key
   sizes (RCx) or alternative key sizes where the default isn't necessarily
   the best choice (two-key vs three-key 3DES) */

static int getKeysize( CONTEXT_INFO *contextInfoPtr,
					   const int requestedKeyLength )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
	int keyLength, maxKeyLength = capabilityInfoPtr->maxKeySize;

	assert( requestedKeyLength == 0 || \
			( requestedKeyLength >= bitsToBytes( MIN_KEYSIZE_BITS ) && \
			  requestedKeyLength <= bitsToBytes( MAX_PKCSIZE_BITS ) ) );

	/* Determine the upper limit on the key size and make sure that the 
	   requested length is valid */
	if( requestedKeyLength == 0 )
		{
		/* For PKC contexts where we're generating a new key, we want to use
		   the recommended (rather than the longest possible) key size,
		   whereas for conventional contexts we want to use the longest
		   possible size for the session key (this will be adjusted further
		   down if necessary for those algorithms where it's excessively
		   long) */
		keyLength = ( contextInfoPtr->type == CONTEXT_PKC ) ? \
					capabilityInfoPtr->keySize : maxKeyLength;

		/* Although RC2 will handle keys of up to 1024 bits and RC4 up to 
		   2048 bits, they're never used with this maximum size but (at 
		   least in non-crippled implementations) always fixed at 128 bits, 
		   so we limit them to the default rather than maximum possible 
		   size */
		if( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RC2 || \
			capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RC4 )
			keyLength = capabilityInfoPtr->keySize;
		}
	else
		{
		if( requestedKeyLength < capabilityInfoPtr->minKeySize || \
			requestedKeyLength > maxKeyLength )
			{
			setErrorInfo( contextInfoPtr, CRYPT_CTXINFO_KEY, 
						  CRYPT_ERRTYPE_ATTR_SIZE );
			return( CRYPT_ARGERROR_NUM1 );
			}
		keyLength = requestedKeyLength;
		}

	/* If we're generating a conventional/MAC key we need to limit the
	   maximum length in order to make it exportable via the smallest normal
	   (i.e. non-elliptic-curve) public key */
	if( contextInfoPtr->type != CONTEXT_PKC && \
		keyLength > bitsToBytes( MAX_KEYSIZE_BITS ) )
		keyLength = bitsToBytes( MAX_KEYSIZE_BITS );

	return( keyLength );
	}

/* Get object subtype-specific information.  This is a shared function that 
   can be overridden on a per-object-type basis, usually individual values
   are handled in the override function and anything that's left gets passed
   down here */

int getInfo( const CAPABILITY_INFO_TYPE type, 
			 void *varParam, const int constParam )
	{
	switch( type )
		{

⌨️ 快捷键说明

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