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

📄 cryptkey.c

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "crypt.h"
#include "cryptctx.h"

/****************************************************************************
*																			*
*								Key Load Functions							*
*																			*
****************************************************************************/

/* Determine whether a context needs to have a key loaded */

BOOLEAN needsKey( const CRYPT_INFO *cryptInfoPtr )
	{
	if( cryptInfoPtr->type == CONTEXT_CONV )
		return( !cryptInfoPtr->ctxConv.keySet );
	if( cryptInfoPtr->type == CONTEXT_PKC )
		return( !cryptInfoPtr->ctxPKC.keySet );
	if( cryptInfoPtr->type == CONTEXT_MAC )
		return( !cryptInfoPtr->ctxMAC.keySet );
	return( FALSE );
	}

/* Check that the supplied PKC parameters make sense (algorithm-specific 
   validity checks are performed at a lower level).  Although the checks are 
   somewhat algorithm-specific, we have to do them at this point in order to 
   avoid duplicating them in every plug-in PKC module, and because strictly 
   speaking it's the job of the higher-level code to ensure the lower-level 
   routines at least get fed approximately valid input */

static int checkPKCparams( const CRYPT_ALGO cryptAlgo, const void *keyInfo )
	{
	const CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) keyInfo;

	/* The DLP check is simpler than the RSA one because there are less
	   odd parameter combinations possible, so we get this one out of the
	   way first */
	if( cryptAlgo != CRYPT_ALGO_RSA )
		{
		const CRYPT_PKCINFO_DLP *dlpKey = ( CRYPT_PKCINFO_DLP * ) keyInfo;

		/* Check the general and public components */
		if( ( dlpKey->isPublicKey != TRUE && dlpKey->isPublicKey != FALSE ) )
			return( CRYPT_ARGERROR_STR1 );
		if( dlpKey->pLen < 510 || dlpKey->pLen > MAX_PKCSIZE_BITS || \
			dlpKey->qLen < 128 || dlpKey->qLen > MAX_PKCSIZE_BITS || \
			dlpKey->gLen < 2 || dlpKey->gLen > MAX_PKCSIZE_BITS || \
			dlpKey->yLen < 0 || dlpKey->yLen > MAX_PKCSIZE_BITS )
			/* y may be 0 if only x and the public params are available */
			return( CRYPT_ARGERROR_STR1 );
		if( dlpKey->isPublicKey )
			return( CRYPT_OK );

		/* Check the private components */
		if( dlpKey->xLen < 128 || dlpKey->xLen > MAX_PKCSIZE_BITS )
			return( CRYPT_ARGERROR_STR1 );
		return( CRYPT_OK );
		}

	/* Check the general and public components */
	if( rsaKey->isPublicKey != TRUE && rsaKey->isPublicKey != FALSE )
		return( CRYPT_ARGERROR_STR1 );
	if( rsaKey->nLen < 504 || rsaKey->nLen > MAX_PKCSIZE_BITS || \
		rsaKey->eLen < 2 || rsaKey->eLen > MAX_PKCSIZE_BITS )
		return( CRYPT_ARGERROR_STR1 );
	if( rsaKey->isPublicKey )
		return( CRYPT_OK );

	/* Check the private components.  This can get somewhat complex, possible
	   combinations are:

		d, p, q
		d, p, q, e1, e2
		p, q, e1, e2

	   The reason for some of the odder combinations is because some 
	   implementations don't use all the values (for example d isn't needed at
	   all for the CRT shortcut).  If only d, p, and q are present we recreate
	   e1 and e2 from them, we also create u if necessary */
	if( rsaKey->pLen < 240 || rsaKey->pLen > MAX_PKCSIZE_BITS || \
		rsaKey->qLen < 240 || rsaKey->qLen > MAX_PKCSIZE_BITS )
		return( CRYPT_ARGERROR_STR1 );
	if( !rsaKey->dLen && !rsaKey->e1Len )
		/* Must have either d or e1 et al */
		return( CRYPT_ARGERROR_STR1 );
	if( rsaKey->dLen && \
		( rsaKey->dLen < 504 || rsaKey->dLen > MAX_PKCSIZE_BITS ) )
		return( CRYPT_ARGERROR_STR1 );
	if( rsaKey->e1Len && \
		( rsaKey->e1Len < 240 || rsaKey->e1Len > MAX_PKCSIZE_BITS || \
		  rsaKey->e2Len < 240 || rsaKey->e2Len > MAX_PKCSIZE_BITS ) )
		return( CRYPT_ARGERROR_STR1 );
	if( rsaKey->uLen && \
		( rsaKey->uLen < 240 || rsaKey->uLen > MAX_PKCSIZE_BITS ) )
		return( CRYPT_ARGERROR_STR1 );
	return( CRYPT_OK );
	}

/* Load a key into a CRYPT_INFO structure.  This function is called by the
   various higher-level functions which move a key into a context */

int loadKey( CRYPT_INFO *cryptInfoPtr, BYTE *key, const int keyLength )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
	int status;

	/* If it's a PKC context, load the PKC keying information */
	if( cryptInfoPtr->type == CONTEXT_PKC )
		{
		/* If we're loading from externally-supplied parameters, make sure 
		   the parameters make sense */
		if( keyLength != sizeof( PKCINFO_LOADINTERNAL ) )
			{
			status = checkPKCparams( capabilityInfoPtr->cryptAlgo, key );
			if( cryptStatusError( status ) )
				return( status );
			}

		/* Load the keying info */
		status = capabilityInfoPtr->initKeyFunction( cryptInfoPtr, key, keyLength );
		if( cryptStatusOK( status ) )
			cryptInfoPtr->ctxPKC.keySet = TRUE;

		return( status );
		}

	/* If it's a MAC algorithm, load the key */
	if( cryptInfoPtr->type == CONTEXT_MAC )
		{
		status = capabilityInfoPtr->initKeyFunction( cryptInfoPtr, key, keyLength );
		if( cryptStatusOK( status ) )
			cryptInfoPtr->ctxMAC.keySet = TRUE;

		return( status );
		}

	/* If we don't need an IV, record it as being set */
	if( !needsIV( cryptInfoPtr->ctxConv.mode ) || \
		isStreamCipher( cryptInfoPtr->capabilityInfo->cryptAlgo ) )
		cryptInfoPtr->ctxConv.ivSet = TRUE;

	/* Perform the key setup */
	assert( capabilityInfoPtr->initKeyFunction != NULL );
	status = capabilityInfoPtr->initKeyFunction( cryptInfoPtr, key, keyLength );
	if( cryptStatusOK( status ) )
		cryptInfoPtr->ctxConv.keySet = TRUE;

	return( status );
	}

/****************************************************************************
*																			*
*							Key Generation Functions						*
*																			*
****************************************************************************/

/* Threaded key generation for those OS's which support threads.  The
   following function *must* be called as a thread */

#if defined( __WIN32__ ) || defined( __OS2__ ) || \
	( defined( __UNIX__ ) && defined( USE_THREADS ) ) || defined( __BEOS__ )

#define HAS_THREADS		/* Enable use of threads throughout this module */

THREADFUNC_DEFINE( threadKeygen, ptr )
	{
	CRYPT_INFO *cryptInfoPtr = ( CRYPT_INFO * ) ptr;
	int busyStatus = CRYPT_ERROR_BUSY;

	/* Mark the object as busy, perform the keygen, and set it back to non-
	   busy */
	krnlSendMessage( cryptInfoPtr->objectHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 &busyStatus, CRYPT_IATTRIBUTE_STATUS );
	cryptInfoPtr->asyncStatus = \
		cryptInfoPtr->capabilityInfo->generateKeyFunction( cryptInfoPtr,
										cryptInfoPtr->ctxPKC.keySizeBits );
	if( cryptStatusOK( cryptInfoPtr->asyncStatus ) )
		cryptInfoPtr->ctxPKC.keySet = TRUE;	/* There's now a key loaded */
	cryptInfoPtr->doAbort = FALSE;
	cryptInfoPtr->done = TRUE;
	krnlSendMessage( cryptInfoPtr->objectHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
	THREAD_EXIT();
	}
#endif /* Threaded keygen function */

/* 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) */

int getOptimalKeysize( CRYPT_INFO *cryptInfoPtr,
					   const int requestedKeyLength )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = cryptInfoPtr->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 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 = ( cryptInfoPtr->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 use 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
		{

⌨️ 快捷键说明

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