keyload.c

来自「cryptlib安全工具包」· C语言 代码 · 共 1,016 行 · 第 1/3 页

C
1,016
字号
			dlpKey->qLen < bytesToBits( DLPPARAM_MIN_Q ) || \
			dlpKey->qLen > bytesToBits( DLPPARAM_MAX_Q ) || \
			dlpKey->gLen < bytesToBits( DLPPARAM_MIN_G ) || \
			dlpKey->gLen > bytesToBits( DLPPARAM_MAX_G ) || \
			dlpKey->yLen < bytesToBits( 0 ) || \
			dlpKey->yLen > bytesToBits( DLPPARAM_MAX_Y ) )
			/* y may be 0 if only x and the public parameters are available */
			{
			return( CRYPT_ARGERROR_STR1 );
			}
		if( dlpKey->isPublicKey )
			return( CRYPT_OK );

		/* Check the private components */
		if( dlpKey->xLen < bytesToBits( DLPPARAM_MIN_X ) || \
			dlpKey->xLen > bytesToBits( DLPPARAM_MAX_X ) )
			return( CRYPT_ARGERROR_STR1 );
		return( CRYPT_OK );
		}

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

	/* Check the general info and make sure that all required values are
	   initialised */
	if( rsaKey->isPublicKey != TRUE && rsaKey->isPublicKey != FALSE )
		return( CRYPT_ARGERROR_STR1 );
	if( rsaKey->nLen <= 0 || rsaKey->eLen <= 0 || \
		rsaKey->dLen < 0 || rsaKey->pLen < 0 || rsaKey->qLen < 0 || \
		rsaKey->uLen < 0 || rsaKey->e1Len < 0 || rsaKey->e2Len < 0 )
		return( CRYPT_ARGERROR_STR1 );

	/* Check the public components */
	if( isShortPKCKey( rsaKey->nLen ) )
		{
		/* Special-case handling for insecure-sized public keys */
		return( CRYPT_ERROR_NOSECURE );
		}
	if( rsaKey->nLen < bytesToBits( RSAPARAM_MIN_N ) || \
		rsaKey->nLen > bytesToBits( RSAPARAM_MAX_N ) || \
		rsaKey->eLen < bytesToBits( RSAPARAM_MIN_E ) || \
		rsaKey->eLen > bytesToBits( RSAPARAM_MAX_E ) || \
		rsaKey->eLen > rsaKey->nLen )
		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, u
		d, p, q, e1, e2, u
		   p, q, e1, e2, u

	   The reason for some of the odder combinations is that some 
	   implementations don't use all of the values (for example d isn't 
	   needed at all for the CRT shortcut) or recreate them when the key is 
	   loaded.  If only d, p, and q are present we recreate e1 and e2 from 
	   them, we also create u if necessary */
	if( rsaKey->pLen < bytesToBits( RSAPARAM_MIN_P ) || \
		rsaKey->pLen > bytesToBits( RSAPARAM_MAX_P ) || \
		rsaKey->pLen >= rsaKey->nLen || \
		rsaKey->qLen < bytesToBits( RSAPARAM_MIN_Q ) || \
		rsaKey->qLen > bytesToBits( RSAPARAM_MAX_Q ) || \
		rsaKey->qLen >= rsaKey->nLen )
		return( CRYPT_ARGERROR_STR1 );
	if( rsaKey->dLen <= 0 && rsaKey->e1Len <= 0 )
		{
		/* Must have either d or e1 et al */
		return( CRYPT_ARGERROR_STR1 );
		}
	if( rsaKey->dLen > 0 && \
		( rsaKey->dLen < bytesToBits( RSAPARAM_MIN_D ) || \
		  rsaKey->dLen > bytesToBits( RSAPARAM_MAX_D ) ) )
		return( CRYPT_ARGERROR_STR1 );
	if( rsaKey->e1Len > 0 && \
		( rsaKey->e1Len < bytesToBits( RSAPARAM_MIN_EXP1 ) || \
		  rsaKey->e1Len > bytesToBits( RSAPARAM_MAX_EXP1 ) || \
		  rsaKey->e2Len < bytesToBits( RSAPARAM_MIN_EXP2 ) || \
		  rsaKey->e2Len > bytesToBits( RSAPARAM_MAX_EXP2 ) ) )
		return( CRYPT_ARGERROR_STR1 );
	if( rsaKey->uLen > 0 && \
		( rsaKey->uLen < bytesToBits( RSAPARAM_MIN_U ) || \
		  rsaKey->uLen > bytesToBits( RSAPARAM_MAX_U ) ) )
		return( CRYPT_ARGERROR_STR1 );
	return( CRYPT_OK );
	}
#endif /* USE_FIPS140 */

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

/* Load a key into a CONTEXT_INFO structure.  These functions are called by 
   the various higher-level functions that move a key into a context */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int loadKeyConvFunction( INOUT CONTEXT_INFO *contextInfoPtr, 
								IN_BUFFER( keyLength ) const void *key, 
								IN_LENGTH_KEY const int keyLength )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;

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

	REQUIRES( contextInfoPtr->type == CONTEXT_CONV );
	REQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= CRYPT_MAX_KEYSIZE );

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

	/* Perform the key setup */
	return( capabilityInfoPtr->initKeyFunction( contextInfoPtr, key, 
												keyLength ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int loadKeyPKCFunction( INOUT CONTEXT_INFO *contextInfoPtr, 
							   IN_BUFFER_OPT( keyLength ) const void *key, 
							   IN_LENGTH_SHORT_Z const int keyLength )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
	int status;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( ( key == NULL ) || isReadPtr( key, keyLength ) );

	REQUIRES( contextInfoPtr->type == CONTEXT_PKC );
	REQUIRES( ( key == NULL && keyLength == 0 ) || \
			  ( key != NULL && \
			    keyLength > 16 && keyLength < MAX_INTLENGTH_SHORT ) );
			  /* The key data for this function may be NULL if the values
			     have been read from encoded X.509/SSH/SSL/PPG data straight
				 into the context bignums */

#ifndef USE_FIPS140
	/* If we're loading from externally-supplied parameters, make sure that 
	   the parameters make sense */
	if( key != NULL )
		{
		status = checkPKCparams( capabilityInfoPtr->cryptAlgo, key );
		if( cryptStatusError( status ) )
			return( status );
		contextInfoPtr->flags |= 0x08;	/* Tell lib_kg to check params too */
		}
#endif /* USE_FIPS140 */

	/* Load the keying info */
	status = capabilityInfoPtr->initKeyFunction( contextInfoPtr, key, 
												 keyLength );
	if( !( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY ) )
		clearTempBignums( contextInfoPtr->ctxPKC );
	return( status );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int loadKeyMacFunction( INOUT CONTEXT_INFO *contextInfoPtr, 
							   IN_BUFFER( keyLength ) const void *key, 
							   IN_LENGTH_KEY const int keyLength )
	{
	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isReadPtr( key, keyLength ) );

	REQUIRES( contextInfoPtr->type == CONTEXT_MAC );
	REQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= CRYPT_MAX_KEYSIZE );

	return( contextInfoPtr->capabilityInfo->initKeyFunction( contextInfoPtr, 
															 key, keyLength ) );
	}

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

/* Load an encoded X.509/SSH/SSL/PGP key into a context.  This is used for 
   two purposes, to load public key components into native contexts and to 
   save encoded X.509 public-key data for use in certificates associated 
   with non-native contexts held in a device.  The latter is required 
   because there's no key data stored with the context itself that we can 
   use to create the SubjectPublicKeyInfo, however it's necessary to have 
   SubjectPublicKeyInfo available for certificate requests/certificates.  

   Normally this is sufficient because cryptlib always generates native 
   contexts for public keys/certificates and for private keys the data is 
   generated in the device with the encoded public components attached to 
   the context as described above.  However for DH keys this gets a bit more 
   complex because although the private key is generated in the device, in 
   the case of the DH responder this is only the DH x value, with the 
   parameters (p and g) being supplied externally by the initiator.  This 
   means that it's necessary to decode at least some of the public key data 
   in order to create the y value after the x value has been generated in 
   the device.  The only situation where this functionality is currently 
   needed is for the SSHv2 code, which at the moment always uses native DH 
   contexts.  For this reason we leave off resolving this issue until it's 
   actually required */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
int setEncodedKey( INOUT CONTEXT_INFO *contextInfoPtr, 
				   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE keyType, 
				   IN_BUFFER( keyDataLen ) const void *keyData, 
				   IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \
					const int keyDataLen )
	{
	static const int actionFlags = \
		MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL ) | \
		MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
	static const int actionFlagsDH = ACTION_PERM_NONE_EXTERNAL_ALL;
	static const int actionFlagsPGP = \
		MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \
		MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
	STREAM stream;
	KEYFORMAT_TYPE formatType;
	int status;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isReadPtr( keyData, keyDataLen ) );

	REQUIRES( contextInfoPtr->type == CONTEXT_PKC );
	REQUIRES( needsKey( contextInfoPtr ) || \
			  ( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY ) );
	REQUIRES( keyType == CRYPT_IATTRIBUTE_KEY_SPKI || \
			  keyType == CRYPT_IATTRIBUTE_KEY_PGP || \
			  keyType == CRYPT_IATTRIBUTE_KEY_SSH || \
			  keyType == CRYPT_IATTRIBUTE_KEY_SSH1 || \
			  keyType == CRYPT_IATTRIBUTE_KEY_SSL || \
			  keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL || \
			  keyType == CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL );
	REQUIRES( keyDataLen >= MIN_CRYPT_OBJECTSIZE && \
			  keyDataLen < MAX_INTLENGTH_SHORT );

	/* If the keys are held externally (e.g. in a crypto device), copy the 
	   SubjectPublicKeyInfo data in and set up any other information that we 
	   may need from it.  This information is used when loading a context 
	   from a key contained in a device, for which the actual key components 
	   aren't directly available in the context but may be needed in the 
	   future for things like certificate requests and certificates */
	if( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY )
		{
		REQUIRES( keyType == CRYPT_IATTRIBUTE_KEY_SPKI || \
				  keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );

		if( ( contextInfoPtr->ctxPKC->publicKeyInfo = \
					clAlloc( "setEncodedKey", keyDataLen ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		memcpy( contextInfoPtr->ctxPKC->publicKeyInfo, keyData, keyDataLen );
		contextInfoPtr->ctxPKC->publicKeyInfoSize = keyDataLen;
		return( contextInfoPtr->ctxPKC->calculateKeyIDFunction( contextInfoPtr ) );
		}

	/* Read the appropriately-formatted key data into the context, applying 
	   a lowest-common-denominator set of usage flags to the loaded key */
	status = attributeToFormatType( keyType, &formatType );
	if( cryptStatusError( status ) )
		return( status );
	sMemConnect( &stream, keyData, keyDataLen );
	status = contextInfoPtr->ctxPKC->readPublicKeyFunction( &stream,
											contextInfoPtr, formatType );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );

	/* If it's a partial load of the initial public portions of a private 
	   key with further key component operations to follow, there's nothing 
	   more to do at this point and we're done */
	if( keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL || \
		keyType == CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL )
		return( contextInfoPtr->ctxPKC->calculateKeyIDFunction( contextInfoPtr ) );

	/* Perform an internal load that uses the key component values that 
	   we've just read into the context */
	contextInfoPtr->flags |= CONTEXT_FLAG_ISPUBLICKEY;
	status = contextInfoPtr->loadKeyFunction( contextInfoPtr, NULL, 0 );
	if( cryptStatusError( status ) )
		{
		/* Map the status to a more appropriate code if necessary */
		return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
		}
	contextInfoPtr->flags |= CONTEXT_FLAG_KEY_SET;

	/* Restrict the key usage to public-key-only actions if necessary.  For 
	   PGP key loads (which, apart from the restrictions specified with the 
	   stored key data aren't constrained by the presence of ACLs in the 
	   form of certificates) we allow external usage, for DH (whose keys can be 
	   both public and private keys even though technically it's a public 
	   key) we allow both encryption and decryption usage, and for public 
	   keys read from certificates we  allow internal usage only */
	status = krnlSendMessage( contextInfoPtr->objectHandle,
						IMESSAGE_SETATTRIBUTE, 
						( keyType == CRYPT_IATTRIBUTE_KEY_PGP ) ? \
							( void * ) &actionFlagsPGP : \
						( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH ) ? \
							( void * ) &actionFlagsDH : \
							( void * ) &actionFlags,
						CRYPT_IATTRIBUTE_ACTIONPERMS );
	if( cryptStatusError( status ) )
		return( status );
	return( contextInfoPtr->ctxPKC->calculateKeyIDFunction( contextInfoPtr ) );
	}

/* Load the components of a composite PKC key into a context */

#ifndef USE_FIPS140

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int setKeyComponents( INOUT CONTEXT_INFO *contextInfoPtr, 
					  IN_BUFFER( keyDataLen ) const void *keyData, 
					  IN_LENGTH_SHORT_MIN( 32 ) const int keyDataLen )
	{
	static const int actionFlags = \
		MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \
		MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
	BOOLEAN isPublicKey;
	int status;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isReadPtr( keyData, keyDataLen ) );

	REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
			  needsKey( contextInfoPtr ) );
	REQUIRES( keyDataLen == sizeof( CRYPT_PKCINFO_RSA ) || \
			  keyDataLen == sizeof( CRYPT_PKCINFO_DLP ) || \
			  keyDataLen == sizeof( CRYPT_PKCINFO_ECC ) );

	/* If it's a private key we need to have a key label set before we can 
	   continue.  The checking for this is a bit complex because at this
	   point all that the context knows is that it's a generic PKC context,
	   but it won't know whether it's a public- or private-key context until
	   the key is actually loaded.  To determine what it'll become we look
	   into the key data to see what's being loaded */
	isPublicKey = isEccAlgo( capabilityInfoPtr->cryptAlgo ) ? \
					( ( CRYPT_PKCINFO_ECC * ) keyData )->isPublicKey : \

⌨️ 快捷键说明

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