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

📄 keyload.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*						  cryptlib Key Load Routines						*
*						Copyright Peter Gutmann 1992-2008					*
*																			*
****************************************************************************/

#define PKC_CONTEXT		/* Indicate that we're working with PKC contexts */
#if defined( INC_ALL )
  #include "crypt.h"
  #include "context.h"
#else
  #include "crypt.h"
  #include "context/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 */

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

/* Convert a key attribute type into a key format type */

CHECK_RETVAL \
int attributeToFormatType( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,
						   OUT_ENUM_OPT( KEYFORMAT ) KEYFORMAT_TYPE *keyformat )
	{
	static const MAP_TABLE attributeMapTbl[] = {
		{ CRYPT_IATTRIBUTE_KEY_SSH, KEYFORMAT_SSH },
		{ CRYPT_IATTRIBUTE_KEY_SSH1,  KEYFORMAT_SSH1 },
		{ CRYPT_IATTRIBUTE_KEY_SSL, KEYFORMAT_SSL },
		{ CRYPT_IATTRIBUTE_KEY_PGP, KEYFORMAT_PGP },
		{ CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL, KEYFORMAT_PGP },
		{ CRYPT_IATTRIBUTE_KEY_SPKI, KEYFORMAT_CERT },
		{ CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL, KEYFORMAT_CERT },
		{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
		};
	int value, status;

	assert( isWritePtr( keyformat, sizeof( KEYFORMAT_TYPE ) ) );

	REQUIRES( isAttribute( attribute ) || \
			  isInternalAttribute( attribute ) );

	/* Clear return value */
	*keyformat = KEYFORMAT_NONE;

	status = mapValue( attribute, &value, attributeMapTbl, 
					   FAILSAFE_ARRAYSIZE( attributeMapTbl, MAP_TABLE ) );
	ENSURES( cryptStatusOK( status ) );
	*keyformat = value;

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						Key Parameter Handling Functions					*
*																			*
****************************************************************************/

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

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int initKeyParams( INOUT CONTEXT_INFO *contextInfoPtr, 
				   IN_ENUM( KEYPARAM ) const KEYPARAM_TYPE paramType,
				   IN_OPT const void *data, 
				   IN_INT const int dataLength )
	{
	CONV_INFO *convInfo = contextInfoPtr->ctxConv;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );

	REQUIRES( contextInfoPtr->type == CONTEXT_CONV );
	REQUIRES( paramType > KEYPARAM_NONE && paramType < KEYPARAM_LAST );

	/* Set the en/decryption mode if required */
	switch( paramType )
		{
		case KEYPARAM_MODE:
			{
			const CAPABILITY_INFO *capabilityInfoPtr = \
										contextInfoPtr->capabilityInfo;

			REQUIRES( data == NULL );
			REQUIRES( dataLength > CRYPT_MODE_NONE && \
					  dataLength < CRYPT_MODE_LAST );

			switch( dataLength )
				{
				case CRYPT_MODE_ECB:
					contextInfoPtr->encryptFunction = \
							capabilityInfoPtr->encryptFunction;
					contextInfoPtr->decryptFunction = \
							capabilityInfoPtr->decryptFunction;
					break;
				case CRYPT_MODE_CBC:
					contextInfoPtr->encryptFunction = \
							capabilityInfoPtr->encryptCBCFunction;
					contextInfoPtr->decryptFunction = \
							capabilityInfoPtr->decryptCBCFunction;
					break;
				case CRYPT_MODE_CFB:
					contextInfoPtr->encryptFunction = \
							capabilityInfoPtr->encryptCFBFunction;
					contextInfoPtr->decryptFunction = \
							capabilityInfoPtr->decryptCFBFunction;
					break;
				case CRYPT_MODE_OFB:
					contextInfoPtr->encryptFunction = \
							capabilityInfoPtr->encryptOFBFunction;
					contextInfoPtr->decryptFunction = \
							capabilityInfoPtr->decryptOFBFunction;
					break;
				default:
					retIntError();
				}
			ENSURES( ( contextInfoPtr->encryptFunction == NULL && \
					   contextInfoPtr->decryptFunction == NULL ) || \
					 ( contextInfoPtr->encryptFunction != NULL && \
					   contextInfoPtr->decryptFunction != NULL ) );
			if( contextInfoPtr->encryptFunction == NULL || \
				contextInfoPtr->decryptFunction == NULL )
				{
				setErrorInfo( contextInfoPtr, CRYPT_CTXINFO_MODE, 
							  CRYPT_ERRTYPE_ATTR_PRESENT );
				return( CRYPT_ERROR_NOTAVAIL );
				}
			convInfo->mode = dataLength;

			return( CRYPT_OK );
			}

		case KEYPARAM_IV:
			assert( isReadPtr( data, dataLength ) );

			REQUIRES( data != NULL && \
					  dataLength >= 8 && dataLength <= CRYPT_MAX_IVSIZE );

			/* Load an IV of the required length */
			memcpy( convInfo->iv, data, dataLength );
			convInfo->ivLength = dataLength;
			convInfo->ivCount = 0;
			memcpy( convInfo->currentIV, convInfo->iv, dataLength );
			contextInfoPtr->flags |= CONTEXT_FLAG_IV_SET;

			return( CRYPT_OK );
			}

	retIntError();
	}

/* Trim a user-supplied key down to an appropriate size */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int adjustUserKeySize( const CONTEXT_INFO *contextInfoPtr, 
					   IN_RANGE( MIN_KEYSIZE, \
								 CRYPT_MAX_PKCSIZE ) const int requestedKeySize, 
					   OUT_LENGTH_PKC_Z int *keyLength )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;

	assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isWritePtr( keyLength, sizeof( int ) ) );

	REQUIRES( requestedKeySize >= MIN_KEYSIZE && \
			  requestedKeySize <= CRYPT_MAX_PKCSIZE );

	/* Clear return value */
	*keyLength = 0;

	/* Trim the key to the appropriate size */
	if( requestedKeySize < capabilityInfoPtr->minKeySize || \
		requestedKeySize > capabilityInfoPtr->maxKeySize )
		return( CRYPT_ARGERROR_NUM1 );
	ENSURES( requestedKeySize > MIN_KEYSIZE && \
			 requestedKeySize <= CRYPT_MAX_PKCSIZE );

	/* If it's a PKC key we're done */
	if( contextInfoPtr->type == CONTEXT_PKC )
		{
		*keyLength = requestedKeySize;

		return( CRYPT_OK );
		}

	/* For conventional/MAC keys we need to limit the maximum working key 
	   length to a sane size since the other side may not be able to handle
	   stupidly large keys */
	*keyLength = min( requestedKeySize, MAX_WORKING_KEYSIZE );

	return( CRYPT_OK );
	}

/* Determine the optimal size for a 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) */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int getDefaultKeysize( const CONTEXT_INFO *contextInfoPtr, 
							  OUT_LENGTH_PKC_Z int *keyLength )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
	int localKeyLength;

	assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isWritePtr( keyLength, sizeof( int ) ) );

	/* Clear return value */
	*keyLength = 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 (this 
	   will be adjusted further down if necessary for those algorithms where 
	   it's excessively long) */
	if( contextInfoPtr->type == CONTEXT_PKC )
		localKeyLength = capabilityInfoPtr->keySize;
	else
		localKeyLength = capabilityInfoPtr->maxKeySize;

#if defined( USE_RC2 ) || defined( USE_RC4 )
	/* 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 )
		localKeyLength = capabilityInfoPtr->keySize;
#endif /* USE_RC2 || USE_RC4 */

	ENSURES( localKeyLength > MIN_KEYSIZE && \
			 localKeyLength <= CRYPT_MAX_PKCSIZE );

	/* Trim the key size to fit */
	return( adjustUserKeySize( contextInfoPtr, localKeyLength, keyLength ) );
	}

/* Check that user-supplied supplied PKC parameters make sense (algorithm-
   parameter-specific validity checks are performed at a lower level).  
   Although the checks are somewhat specific to particular PKC algorithm 
   classes 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 that the lower-level routines get 
   fed at least approximately valid input */

#ifndef USE_FIPS140

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
static int checkPKCparams( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo, 
						   const void *keyInfo )
	{
	const CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) keyInfo;

	REQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
			  cryptAlgo <= CRYPT_ALGO_LAST_PKC );
	REQUIRES( keyInfo != NULL );

	/* The ECC check is somewhat different to the others because ECC key
	   sizes work in different ways so we have to special-case this one */
	if( isEccAlgo( cryptAlgo ) )
		{
		const CRYPT_PKCINFO_ECC *eccKey = ( CRYPT_PKCINFO_ECC * ) keyInfo;

		assert( isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_ECC ) ) );

		/* Check the general info and make sure that all required values are
		   initialised */
		if( ( eccKey->isPublicKey != TRUE && eccKey->isPublicKey != FALSE ) )
			return( CRYPT_ARGERROR_STR1 );
		if( eccKey->pLen <= 0 || eccKey->aLen <= 0 || eccKey->bLen <= 0 || \
			eccKey->gxLen <= 0 || eccKey->gyLen <= 0 || eccKey->rLen <= 0 || \
			eccKey->qxLen <= 0 || eccKey->qyLen <= 0 || eccKey->dLen < 0 )
			return( CRYPT_ARGERROR_STR1 );

		/* Check the parameters and public components */
		if( eccKey->pLen < bytesToBits( ECCPARAM_MIN_P ) || \
			eccKey->pLen > bytesToBits( ECCPARAM_MAX_P ) || \
			eccKey->aLen < bytesToBits( ECCPARAM_MIN_A ) || \
			eccKey->aLen > bytesToBits( ECCPARAM_MAX_A ) || \
			eccKey->bLen < bytesToBits( ECCPARAM_MIN_B ) || \
			eccKey->bLen > bytesToBits( ECCPARAM_MAX_B ) || \
			eccKey->gxLen < bytesToBits( ECCPARAM_MIN_GX ) || \
			eccKey->gxLen > bytesToBits( ECCPARAM_MAX_GX ) || \
			eccKey->gyLen < bytesToBits( ECCPARAM_MIN_GY ) || \
			eccKey->gyLen > bytesToBits( ECCPARAM_MAX_GY ) || \
			eccKey->rLen < bytesToBits( ECCPARAM_MIN_R ) || \
			eccKey->rLen > bytesToBits( ECCPARAM_MAX_R ) )
			return( CRYPT_ARGERROR_STR1 );
		if( eccKey->qxLen < bytesToBits( ECCPARAM_MIN_QX ) || \
			eccKey->qxLen > bytesToBits( ECCPARAM_MAX_QX ) || \
			eccKey->qyLen < bytesToBits( ECCPARAM_MIN_QY ) || \
			eccKey->qyLen > bytesToBits( ECCPARAM_MAX_QY ) )
			return( CRYPT_ARGERROR_STR1 ); 
		if( eccKey->isPublicKey )
			return( CRYPT_OK );

		/* Check the private components */
		if( eccKey->dLen < bytesToBits( ECCPARAM_MIN_D ) || \
			eccKey->dLen > bytesToBits( ECCPARAM_MAX_D ) )
			return( CRYPT_ARGERROR_STR1 );
		return( CRYPT_OK );
		}

	/* For the non-ECC algorithms 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.  Note that we don't get PKCS #3 DH 
	   keys at this level so we always require that q be present */
	if( isDlpAlgo( cryptAlgo ) )
		{
		const CRYPT_PKCINFO_DLP *dlpKey = ( CRYPT_PKCINFO_DLP * ) keyInfo;

		assert( isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_DLP ) ) );

		/* Check the general info and make sure that all required values are
		   initialised */
		if( ( dlpKey->isPublicKey != TRUE && dlpKey->isPublicKey != FALSE ) )
			return( CRYPT_ARGERROR_STR1 );
		if( dlpKey->pLen <= 0 || dlpKey->qLen <= 0 || dlpKey->gLen <= 0 || \
			dlpKey->yLen < 0 || dlpKey->xLen < 0 )
			return( CRYPT_ARGERROR_STR1 );

		/* Check the public components */
		if( isShortPKCKey( dlpKey->pLen ) )
			{
			/* Special-case handling for insecure-sized public keys */
			return( CRYPT_ERROR_NOSECURE );
			}
		if( dlpKey->pLen < bytesToBits( DLPPARAM_MIN_P ) || \
			dlpKey->pLen > bytesToBits( DLPPARAM_MAX_P ) || \

⌨️ 快捷键说明

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