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

📄 cryptcfg.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
			   setting, clear and free it */
			if( optionInfoPtr->strValue != fixedOptionInfoPtr->strDefault )
				{
				zeroise( optionInfoPtr->strValue,
						 strlen( optionInfoPtr->strValue ) );
				free( optionInfoPtr->strValue );
				}
			}
		}

	/* Clear the free the overall option collection */
	memset( optionList, 0, OPTION_INFO_SIZE );
	free( optionList );
	}

/****************************************************************************
*																			*
*						Read and Write the Config Options 					*
*																			*
****************************************************************************/

/* Read any user-defined configuration options.  Since the config file is an
   untrusted source, we set the values in it via external messages rather than
   manipulating the config info directly, which means everything read is
   subject to the usual ACL checks */

static int readTrustedCerts( const CRYPT_KEYSET iCryptKeyset )
	{
	RESOURCE_DATA msgData;
	BYTE buffer[ 2048 ];
	int status;

	/* Read each trusted cert from the keyset */
	setResourceData( &msgData, buffer, 2048 );
	status = krnlSendMessage( iCryptKeyset, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_TRUSTEDCERT );
	while( cryptStatusOK( status ) )
		{
		/* Add the cert data as a trusted cert item and look for the next
		   cert */
		setTrustedCert( msgData.data, msgData.length );
		setResourceData( &msgData, buffer, 2048 );
		status = krnlSendMessage( iCryptKeyset, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT );
		}

	return( ( status == CRYPT_ERROR_NOTFOUND ) ? CRYPT_OK : status );
	}

int readConfig( const CRYPT_USER iCryptUser, const char *fileName )
	{
	CRYPT_KEYSET iCryptKeyset;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	RESOURCE_DATA msgData;
	STREAM stream;
	char configFilePath[ MAX_PATH_LENGTH + 128 ];	/* Protection for Windows */
	BYTE buffer[ 1024 ], *bufPtr = buffer;
	int dataLength, status;

	/* Try and open the config file.  If we can't open it, it means the file
	   doesn't exist, which isn't an error */
	fileBuildCryptlibPath( configFilePath, fileName, FALSE );
	setMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE );
	createInfo.arg2 = CRYPT_KEYOPT_READONLY;
	createInfo.strArg1 = configFilePath;
	createInfo.strArgLen1 = strlen( configFilePath );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_KEYSET );
	if( cryptStatusError( status ) )
		return( CRYPT_OK );
	iCryptKeyset = createInfo.cryptHandle;

	/* Get the config info from the keyset */
	setResourceData( &msgData, NULL, 0 );
	status = krnlSendMessage( iCryptKeyset, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_CONFIGDATA );
	if( status == CRYPT_ERROR_NOTFOUND )
		{
		/* No config options present, there may still be trusted certs
		   present */
		status = readTrustedCerts( iCryptKeyset );
		krnlSendNotifier( iCryptKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( status );
		}
	if( cryptStatusOK( status ) && msgData.length > 1024 && \
		( bufPtr = malloc( msgData.length ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( status ) )
		{
		msgData.data = bufPtr;
		status = krnlSendMessage( iCryptKeyset, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_CONFIGDATA );
		}
	if( cryptStatusOK( status ) )
		status = readTrustedCerts( iCryptKeyset );
	krnlSendNotifier( iCryptKeyset, RESOURCE_IMESSAGE_DECREFCOUNT );
	if( cryptStatusError( status ) )
		{
		if( bufPtr != buffer && bufPtr != NULL )
			free( bufPtr );
		return( status );
		}
	dataLength = msgData.length;

	/* Read each config option */
	sMemConnect( &stream, bufPtr, msgData.length );
	while( cryptStatusOK( status ) && stell( &stream ) < dataLength )
		{
		CRYPT_ATTRIBUTE_TYPE attributeType;
		long option;
		int value, tag, i;

		/* Read the wrapper and option index and map it to the actual option.
		   If we find an unknown index, we skip it and continue (this is done
		   to handle new options which may have been added) */
		readSequence( &stream, NULL );
		status = readShortInteger( &stream, &option );
		if( cryptStatusError( status ) )
			continue;
		for( i = 1; fixedOptionInfo[ i ].option <= LAST_STORED_OPTION; i++ )
			if( fixedOptionInfo[ i ].index == option )
				break;
		if( fixedOptionInfo[ i ].option > LAST_STORED_OPTION )
			{
			readUniversal( &stream );
			continue;
			}
		attributeType = fixedOptionInfo[ i ].option;

		/* Read the option value and set the option.  We don't treat a failure
		   to set the option as a problem since the user probably doesn't want
		   the entire system to fail because of a bad config option, and in any
		   case we'll fall back to a safe default value */
		tag = peekTag( &stream );
		if( tag == BER_BOOLEAN || tag == BER_INTEGER )
			{
			/* It's a numeric value, read the appropriate type and try and set
			   the option */
			if( tag == BER_BOOLEAN )
				status = readBoolean( &stream, &value );
			else
				{
				long integer;

				status = readShortInteger( &stream, &integer );
				value = ( int ) integer;
				}
			krnlSendMessage( iCryptUser, RESOURCE_IMESSAGE_SETATTRIBUTE,
							 &value, attributeType );
			}
		else
			{
			int length;

			/* It's a string value, set the option straight from the encoded
			   data */
			status = readGenericHole( &stream, &length );
			if( cryptStatusError( status ) )
				continue;
			setResourceData( &msgData, sMemBufPtr( &stream ), length );
			krnlSendMessage( iCryptUser, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
							 &msgData, attributeType );
			status = sSkip( &stream, length );
			}
		}
	sMemClose( &stream );

	/* Clean up */
	if( bufPtr != buffer )
		free( bufPtr );
	return( status );
	}

/* Write any user-defined configuration options.  This is performed in two
   phases, a first phase which encodes the config data and a second phase
   which writes the data to disk.  The reason for the split is that the
   second phase doesn't require the use of the user object data any more
   and can be a somewhat lengthy process due to disk accesses and other bits
   and pieces.  Because of this the caller is expected to unlock the user
   object between the two phases to ensure that the second phase doesn't
   stall all other operations which require this user object */

int encodeConfigData( OPTION_INFO *optionList, const char *fileName,
					  void **data, int *length )
	{
	STREAM stream;
	void *trustedCertStatePtr;
	int trustedCertStateIndex, i;

	/* Clear the return values */
	*data = NULL;
	*length = 0;

	/* Make a first pass through the config options to determine the total
	   encoded length of the ones which don't match the default setting */
	for( i = 1; fixedOptionInfo[ i ].option <= LAST_STORED_OPTION; i++ )
		{
		const FIXED_OPTION_INFO *fixedOptionInfoPtr = &fixedOptionInfo[ i ];
		const OPTION_INFO *optionInfoPtr = &optionList[ i ];

		if( fixedOptionInfoPtr->type == OPTION_STRING )
			{
			/* If the string value is the same as the default, there's
			   nothing to do.  Note that we compare the value rather than
			   the pointers since they could point to the same value */
			if( optionInfoPtr->strValue == NULL || \
				( fixedOptionInfoPtr->strDefault != NULL && \
				  !strcmp( optionInfoPtr->strValue, fixedOptionInfoPtr->strDefault ) ) )
				continue;
			assert( fixedOptionInfoPtr->index != CRYPT_UNUSED );
			*length += ( int ) sizeofObject( \
						sizeofShortInteger( fixedOptionInfoPtr->index ) + \
						sizeofObject( strlen( optionInfoPtr->strValue ) ) );
			}
		else
			{
			/* If the integer/boolean value which is currently set isn't the
			   default setting, update it */
			if( optionInfoPtr->intValue == fixedOptionInfoPtr->intDefault )
				continue;
			assert( fixedOptionInfoPtr->index != CRYPT_UNUSED );
			*length += ( int ) sizeofObject( \
						sizeofShortInteger( fixedOptionInfoPtr->index ) + \
						( fixedOptionInfoPtr->type == OPTION_NUMERIC ? \
						  sizeofShortInteger( optionInfoPtr->intValue ) : \
						  sizeofBoolean() ) );
			}
		}

	/* If there are config options to store, write them to a memory buffer */
	if( *length )
		{
		/* Allocate a buffer to hold the encoded values */
		if( ( *data = malloc( *length ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );

		/* Write the config options */
		sMemOpen( &stream, *data, *length );
		for( i = 1; fixedOptionInfo[ i ].option <= LAST_STORED_OPTION; i++ )
			{
			const FIXED_OPTION_INFO *fixedOptionInfoPtr = &fixedOptionInfo[ i ];
			const OPTION_INFO *optionInfoPtr = &optionList[ i ];

			if( fixedOptionInfoPtr->type == OPTION_STRING )
				{
				if( optionInfoPtr->strValue == NULL || \
					( fixedOptionInfoPtr->strDefault != NULL && \
					  !strcmp( optionInfoPtr->strValue,
							   fixedOptionInfoPtr->strDefault ) ) )
					continue;
				writeSequence( &stream,
							   sizeofShortInteger( fixedOptionInfoPtr->index ) +
							   sizeofObject( strlen( optionInfoPtr->strValue ) ) );
				writeShortInteger( &stream, fixedOptionInfoPtr->index,
								   DEFAULT_TAG );
				writeCharacterString( &stream, optionInfoPtr->strValue,
									  strlen( optionInfoPtr->strValue ),
									  BER_STRING_UTF8 );
				continue;
				}

			if( optionInfoPtr->intValue == fixedOptionInfoPtr->intDefault )
				continue;
			if( fixedOptionInfoPtr->type == OPTION_NUMERIC )
				{
				writeSequence( &stream,
							   sizeofShortInteger( fixedOptionInfoPtr->index ) +
							   sizeofShortInteger( optionInfoPtr->intValue ) );
				writeShortInteger( &stream, fixedOptionInfoPtr->index,
								   DEFAULT_TAG );
				writeShortInteger( &stream, optionInfoPtr->intValue,
								   DEFAULT_TAG );
				}
			else
				{
				writeSequence( &stream,
							   sizeofShortInteger( fixedOptionInfoPtr->index ) +
							   sizeofBoolean() );
				writeShortInteger( &stream, fixedOptionInfoPtr->index,
								   DEFAULT_TAG );
				writeBoolean( &stream, optionInfoPtr->intValue, DEFAULT_TAG );
				}
			}
		assert( sGetStatus( &stream ) == CRYPT_OK );
		sMemDisconnect( &stream );
		}

	/* If we've gone back to all default values from having non-default ones
	   stored and there aren't any implicitly trusted certs, there won't be
	   anything to write, so we just delete the config file */
	if( !*length && \
		getFirstTrustedCert( &trustedCertStatePtr,
							 &trustedCertStateIndex ) == CRYPT_ERROR )
		{
		char configFilePath[ MAX_PATH_LENGTH + 128 ];	/* Protection for Windows */

		fileBuildCryptlibPath( configFilePath, fileName, FALSE );
		fileUnlink( configFilePath );
		return( CRYPT_OK );
		}

	/* We've written the config data to the memory buffer, let the caller
	   know that they can unlock it and commit it to permanent storage */
	return( OK_SPECIAL );
	}

int commitConfigData( const char *fileName, const void *data,
					  const int length )
	{
	CRYPT_CERTIFICATE iCryptCert;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	RESOURCE_DATA msgData;
	char configFilePath[ MAX_PATH_LENGTH + 128 ];	/* Protection for Windows */
	void *trustedCertStatePtr;
	int trustedCertStateIndex, status;

	/* Build the path to the config file and try and create it */
	fileBuildCryptlibPath( configFilePath, fileName, TRUE );
	setMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE );
	createInfo.arg2 = CRYPT_KEYOPT_CREATE;
	createInfo.strArg1 = configFilePath;
	createInfo.strArgLen1 = strlen( configFilePath );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_KEYSET );
	if( cryptStatusError( status ) )
		/* Map the lower-level keyset-specific error into a more meaningful
		   generic error */
		return( CRYPT_ERROR_OPEN );

	/* Send the config info to the keyset if there is any */
	if( length )
		{
		setResourceData( &msgData, ( void * ) data, length );
		status = krnlSendMessage( createInfo.cryptHandle,
								  RESOURCE_IMESSAGE_SETATTRIBUTE_S, &msgData,
								  CRYPT_IATTRIBUTE_CONFIGDATA );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( createInfo.cryptHandle,
							  RESOURCE_IMESSAGE_DECREFCOUNT );
			fileUnlink( configFilePath );
			return( CRYPT_ERROR_WRITE );
			}
		}

	/* Send any implicitly trusted certs to the keyset.  Since there's not
	   much we can do in terms of error recovery if a failure occurs at this
	   point, we just record the fact that a problem occurred and move on to
	   the next cert */
	iCryptCert = getFirstTrustedCert( &trustedCertStatePtr,
									  &trustedCertStateIndex );
	while( iCryptCert != CRYPT_ERROR )
		{
		MESSAGE_KEYMGMT_INFO setkeyInfo;
		int newStatus;

		setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,
							   NULL, 0, KEYMGMT_FLAG_NONE );
		setkeyInfo.cryptHandle = iCryptCert;
		newStatus = krnlSendMessage( createInfo.cryptHandle,
									 RESOURCE_IMESSAGE_KEY_SETKEY,
									 &setkeyInfo, KEYMGMT_ITEM_PUBLICKEY );
		if( cryptStatusOK( status ) )
			status = CRYPT_ERROR_WRITE;
		iCryptCert = getNextTrustedCert( &trustedCertStatePtr,
										 &trustedCertStateIndex );
		}

	/* Clean up */
	krnlSendNotifier( createInfo.cryptHandle, RESOURCE_IMESSAGE_DECREFCOUNT );
	return( status );
	}

⌨️ 快捷键说明

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