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

📄 crypt.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*					  cryptlib Encryption Context Routines					*
*						Copyright Peter Gutmann 1992-2002					*
*																			*
****************************************************************************/

/* "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"
#include "cryptctx.h"
#ifdef INC_ALL
  #include "asn1.h"
#else
  #include "keymgmt/asn1.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 */

BOOLEAN needsKey( const CRYPT_INFO *cryptInfoPtr );
int getOptimalKeysize( CRYPT_INFO *cryptInfoPtr,
					   const int requestedKeyLength );
int generateKey( CRYPT_INFO *cryptInfoPtr, const BOOLEAN isAsync );
int loadKey( CRYPT_INFO *cryptInfoPtr, BYTE *key, const int keyLength );

/* Prototypes for functions in asn1keys.c */

int writePublicKey( STREAM *stream, const CRYPT_INFO *cryptInfoPtr );
int writeSsh1PublicKey( STREAM *stream, const CRYPT_INFO *cryptInfoPtr );
int writeSsh2PublicKey( STREAM *stream, const CRYPT_INFO *cryptInfoPtr );
int readSsh1PublicKey( STREAM *stream, CRYPT_INFO *cryptInfoPtr );
int readSsh2PublicKey( STREAM *stream, CRYPT_INFO *cryptInfoPtr );

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

/* 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 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 the algorithm/mode names will fit inside the query
	   information structure */
	if( strlen( capabilityInfoPtr->algoName ) > CRYPT_MAX_TEXTSIZE - 1 )
		return( FALSE );

	/* Make sure 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->keySize < bitsToBytes( 40 ) || \
			  capabilityInfoPtr->keySize > CRYPT_MAX_KEYSIZE || \
			  capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) )
			return( FALSE );
		if( !isStreamCipher( cryptAlgo ) && \
			( capabilityInfoPtr->initIVFunction == NULL || \
			  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->keySize < bitsToBytes( 512 ) || \
			  capabilityInfoPtr->keySize > CRYPT_MAX_PKCSIZE || \
			  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->keySize < bitsToBytes( 40 ) || \
			  capabilityInfoPtr->keySize > CRYPT_MAX_KEYSIZE || \
			  capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) )
			return( FALSE );
		if( capabilityInfoPtr->initKeyFunction == NULL )
			return( FALSE );
		}

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

/* Copy information from a capability record to a query record */

void copyCapabilityInfo( const CAPABILITY_INFO FAR_BSS *capabilityInfoPtr,
						 CRYPT_QUERY_INFO *cryptQueryInfo )
	{
	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 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 );
	}

/* Load an IV, shared by most capabilities */

int loadIV( CRYPT_INFO *cryptInfoPtr, const void *iv, const int ivLength )
	{
	const int ivSize = ( ivLength == CRYPT_USE_DEFAULT ) ? \
					   cryptInfoPtr->capabilityInfo->blockSize : ivLength;

	/* Load the IV of the required length.  If the required IV size is less
	   than the maximum possible IV size, we pad it to the right with
	   zeroes */
	cryptInfoPtr->ctxConv.ivLength = ivSize;
	cryptInfoPtr->ctxConv.ivCount = 0;
	memset( cryptInfoPtr->ctxConv.iv, 0, CRYPT_MAX_IVSIZE );
	memcpy( cryptInfoPtr->ctxConv.iv, iv, ivSize );
	memcpy( cryptInfoPtr->ctxConv.currentIV, cryptInfoPtr->ctxConv.iv,
			CRYPT_MAX_IVSIZE );
	cryptInfoPtr->ctxConv.ivSet = TRUE;

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*					Encryption Context Management Functions					*
*																			*
****************************************************************************/

/* Create a deep clone of a conventional encryption or hash/MAC context.
   This code is used when it's necessary to create a local copy of a context
   the caller has passed in */

static int contextMessageFunction( const CRYPT_CONTEXT cryptContext,
								   const RESOURCE_MESSAGE_TYPE message,
								   void *messageDataPtr,
								   const int messageValue );

static int cloneContext( CRYPT_CONTEXT *iDestContext,
						 const CRYPT_CONTEXT srcContext )
	{
	CRYPT_INFO *srcInfoPtr, *destInfoPtr;
	CONTEXT_TYPE contextType;
	void *keyPtr = NULL, *privateDataPtr = NULL;
	int status, actionFlags, subType;

	/* Get the action permissions for the source object */
	status = krnlSendMessage( srcContext, RESOURCE_IMESSAGE_GETATTRIBUTE,
							  &actionFlags, CRYPT_IATTRIBUTE_ACTIONPERMS );
	if( cryptStatusError( status ) )
		return( status );

	getCheckInternalResource( srcContext, srcInfoPtr, OBJECT_TYPE_CONTEXT );
	contextType = srcInfoPtr->type;
	assert( contextType == CONTEXT_CONV || \
			contextType == CONTEXT_HASH || \
			contextType == CONTEXT_MAC );
	subType = ( contextType == CONTEXT_CONV ) ? SUBTYPE_CTX_CONV : \
			  ( contextType == CONTEXT_HASH ) ? SUBTYPE_CTX_HASH : SUBTYPE_CTX_MAC;

	/* We need to preallocate all required memory so we can check for
	   allocation failures before we copy the source context because undoing
	   the shallow cloning of the context isn't easily possible */
	if( contextType == CONTEXT_CONV && srcInfoPtr->ctxConv.key != NULL )
		{
		const int size = krnlMemsize( srcInfoPtr->ctxConv.key );

		status = krnlMemalloc( &keyPtr, size );
		if( cryptStatusOK( status ) )
			memcpy( keyPtr, srcInfoPtr->ctxConv.key, size );
		}
	if( contextType == CONTEXT_HASH && srcInfoPtr->ctxHash.hashInfo != NULL )
		{
		const int size = krnlMemsize( srcInfoPtr->ctxHash.hashInfo );

		status = krnlMemalloc( &privateDataPtr, size );
		if( cryptStatusOK( status ) )
			memcpy( privateDataPtr, srcInfoPtr->ctxHash.hashInfo, size );
		}
	if( contextType == CONTEXT_MAC && srcInfoPtr->ctxMAC.macInfo != NULL )
		{
		const int size = krnlMemsize( srcInfoPtr->ctxMAC.macInfo );

		status = krnlMemalloc( &privateDataPtr, size );
		if( cryptStatusOK( status ) )
			memcpy( privateDataPtr, srcInfoPtr->ctxMAC.macInfo, size );
		}
	if( cryptStatusError( status ) )
		unlockResourceExit( srcInfoPtr, status );

	/* Create the encryption context object */
	status = krnlCreateObject( ( void ** ) &destInfoPtr, 
							   srcInfoPtr->ownerHandle, OBJECT_TYPE_CONTEXT,
							   subType, sizeof( CRYPT_INFO ),
							   ( needsSecureMemory( srcInfoPtr->type ) ? \
								CREATEOBJECT_FLAG_SECUREMALLOC: 0 ),
							   actionFlags, contextMessageFunction );
	if( cryptStatusError( status ) )
		{
		/* Undo the previous mallocs and exit */
		if( keyPtr != NULL )
			krnlMemfree( keyPtr );
		if( privateDataPtr != NULL )
			krnlMemfree( privateDataPtr );
		unlockResourceExit( srcInfoPtr, status );
		}
	initResourceLock( destInfoPtr );
	lockResource( destInfoPtr );
	*iDestContext = destInfoPtr->objectHandle = status;

	/* Now that all the things which could fail have been done, copy across
	   the shared fields (the expression mimics the offsetof() operator,
	   which isn't available with all compilers.  A more general-purpose
	   alternative is to use (NULL->fieldName - NULL) (with some casting),
	   but since we know the structure and field in advance we don't need to
	   do this).

	   Since this operation copies over a few items of instance-specific
	   information, we have to make sure we reset or re-initialise this
	   information after the block copy */
	memcpy( destInfoPtr, srcInfoPtr, ( size_t ) \
			( ( BYTE * ) &srcInfoPtr->_sharedEnd - ( BYTE * ) srcInfoPtr ) );
	if( contextType == CONTEXT_CONV )
		destInfoPtr->ctxConv.key = keyPtr;
	if( contextType == CONTEXT_HASH )
		destInfoPtr->ctxHash.hashInfo = privateDataPtr;
	if( contextType == CONTEXT_MAC )
		destInfoPtr->ctxMAC.macInfo = privateDataPtr;

	unlockResource( srcInfoPtr );

	/* We've finished setting up the object-type-specific info, tell the
	   kernel the object is ready for use and initialised */
	unlockResource( destInfoPtr );
	status = krnlSendMessage( *iDestContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
							  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
	if( cryptStatusOK( status ) )
		{
		/* Since this is an internal-use-only object, lock down the action
		   permissions so that only encryption and hash actions from internal
		   sources are allowed (assuming they were allowed to begin with).
		   Keygen is disabled entirely (there should already be a key loaded),
		   and signing isn't possible with a non-PKC object anyway */
		actionFlags = \
			MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
			MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
			MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_HASH, ACTION_PERM_NONE_EXTERNAL );
		krnlSendMessage( *iDestContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
						 &actionFlags, CRYPT_IATTRIBUTE_ACTIONPERMS );
		status = krnlSendMessage( *iDestContext,
						RESOURCE_IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED,
						CRYPT_IATTRIBUTE_INITIALISED );
		if( cryptStatusError( status ) )

⌨️ 快捷键说明

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