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

📄 cryptlib.c

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

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

/* Prototypes for functions in cryptkrn.c */

BOOLEAN beginInitialisation( const BOOLEAN checkState );
void endInitialisation( const BOOLEAN newState );
int initInternalFunctions( void );
int destroyObjects( void );
void endInternalFunctions( void );

/* Prototypes for functions in cryptcrt.c */

int initTrustInfo( void );
void endTrustInfo( void );

/* Prototypes for functions in cryptdev.c and cryptusr.c */

int createSystemDeviceObject( void );
int createDefaultUserObject( void );

/****************************************************************************
*																			*
*							Startup/Shutdown Routines						*
*																			*
****************************************************************************/

/* Initialisation/shutdown functions for other parts of the library */

void initDevices( void );
void shutdownDevices( void );
void initKeysets( void );
void shutdownKeysets( void );

/* There isn't any good place to put the networking init/shutdown code so we
   handle it ourselves here.  Before we can end the networking subsystem we
   have to signal that a shutdown is about to occur in order to gracefully
   exit from any currently occurring network I/O, if we didn't do this then
   objects blocked on network I/O couldn't be cleaned up */

void netInitTCP( void );
void netSignalShutdown( void );
void netEndTCP( void );

static void initNetworking( void )
	{
#ifdef NET_TCP
	netInitTCP();
#endif /* NET_TCP */
	}

static void shutdownNetworking( void )
	{
#ifdef NET_TCP
	netEndTCP();
#endif /* NET_TCP */
	}

static void signalShutdownNetworking( void )
	{
#ifdef NET_TCP
  #if defined( __WIN32__ ) && !defined( NT_DRIVER )
	/* We have to wait for the driver binding to complete before we can
	   start the shutdown process */
	waitSemaphore( SEMAPHORE_DRIVERBIND );
  #endif /* __WIN32__ && !NT_DRIVER */
	netSignalShutdown();
#endif /* NET_TCP */
	}

/* Under various OS's we bind to a number of drivers at runtime.  We can
   either do this sychronously or, under Win32, asynchronously (depending on
   the setting of a config option).  By default we use the async init since
   it speeds up the startup.  Synchronisation is achieved by having the open/
   init functions in the modules which require the drivers call
   waitSemaphore() on the driver binding semaphore, which blocks until the
   drivers are bound if an async bind is in progress, or returns immediately
   if no bind is in progress */

#if defined( __WIN32__ ) && !defined( NT_DRIVER )

#include <process.h>

void threadedBind( void *dummy )
	{
	UNUSED( dummy );

	initKeysets();
	initDevices();
	initNetworking();
	clearSemaphore( SEMAPHORE_DRIVERBIND );
	_endthread();
	}

static void bindDrivers( void )
	{
	int asyncInit;

	/* Bind the drivers asynchronously or synchronously depending on the
	   config option setting.  We always send this query to the default
	   user object since no other user objects exist at this time */
	krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
					 RESOURCE_IMESSAGE_GETATTRIBUTE, &asyncInit,
					 CRYPT_OPTION_MISC_ASYNCINIT );
	if( asyncInit )
		{
		HANDLE hThread;

		/* Fire up the thread.  Note the use of _beginthread() rather than
		   _beginthreadex(), since we want the thread to close its own
		   handle when it terminates */
		hThread = ( HANDLE ) _beginthread( threadedBind, 0, NULL );
		if( hThread )
			{
			setSemaphore( SEMAPHORE_DRIVERBIND, hThread );
			return;
			}
		}
	initKeysets();
	initDevices();
	initNetworking();
	}

static void unbindDrivers( void )
	{
	/* Shut down any external interfaces after making sure that the
	   initalisation ran to completion */
	waitSemaphore( SEMAPHORE_DRIVERBIND );
	shutdownKeysets();
	shutdownDevices();
	shutdownNetworking();
	}
#else

static void bindDrivers( void )
	{
	initKeysets();
	initDevices();
	initNetworking();
	}

static void unbindDrivers( void )
	{
	shutdownKeysets();
	shutdownDevices();
	shutdownNetworking();
	}
#endif /* __WIN32__ && !NT_DRIVER */

/* Test the kernel mechanisms to make sure everything's working as expected */

static BOOLEAN testKernelMechanisms( void )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	RESOURCE_DATA msgData;
	CRYPT_CONTEXT cryptContext;
	static const BYTE key[] = { 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31 };
	BYTE buffer[ 8 ];
	int value, status;

	/* Verify object creation */
	setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DES );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( FALSE );
	cryptContext = createInfo.cryptHandle;

	/* Verify inability to access internal object using external message */
	if( krnlSendMessage( cryptContext, RESOURCE_MESSAGE_GETATTRIBUTE,
						 &value, CRYPT_CTXINFO_ALGO ) != CRYPT_ARGERROR_OBJECT )
		{
		krnlSendNotifier( cryptContext, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( FALSE );
		}

	/* Verify inability to perform state=high operation on state=low object */
	if( krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_CTX_ENCRYPT,
						 buffer, 8 ) != CRYPT_ERROR_NOTINITED )
		{
		krnlSendNotifier( cryptContext, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( FALSE );
		}

	/* Verify ability to transition state=low object to state=high */
	setResourceData( &msgData, ( void * ) key, 8 );
	status = krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_KEY );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( cryptContext, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( FALSE );
		}
	setResourceData( &msgData, ( void * ) key, 8 );
	krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
					 &msgData, CRYPT_CTXINFO_IV );

	/* Verify inability to perform state=low operations on state=high object.
	   These also test things like trying to load/generate a key into a non-
	   crypto context or non-native context since they're protected by the
	   same state=high check in the kernel */
	status = krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_KEY );
	if( status == CRYPT_ERROR_PERMISSION )
		status = krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_CTX_GENKEY,
								  NULL, FALSE );
	if( status != CRYPT_ERROR_PERMISSION )
		{
		krnlSendNotifier( cryptContext, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( FALSE );
		}

	/* Verify inability to perform disallowed action externally but still
	   perform it internally.  Note that the object does become very briefly
	   visible externally at this point, but there's nothing which can be
	   done with it */
	value = \
		MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
		MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );
	krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE, &value,
					 CRYPT_IATTRIBUTE_ACTIONPERMS );
	krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );
	if( krnlSendMessage( cryptContext, RESOURCE_MESSAGE_CTX_ENCRYPT,
						 buffer, 8 ) != CRYPT_ERROR_PERMISSION || \
		krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_CTX_ENCRYPT,
						 buffer, 8 ) != CRYPT_OK )
		{
		krnlSendNotifier( cryptContext, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( FALSE );
		}

	/* Verify ability to use object with a finite usage count and inability
	   to exceed the usage count */
	value = 1;
	status = krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
							  &value, CRYPT_PROPERTY_USAGECOUNT );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_CTX_ENCRYPT,
								  buffer, 8 );
	if( cryptStatusError( status ) || \
		krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_CTX_ENCRYPT,
						 buffer, 8 ) != CRYPT_ERROR_PERMISSION )
		{
		krnlSendNotifier( cryptContext, RESOURCE_IMESSAGE_DECREFCOUNT );
		return( FALSE );
		}

	krnlSendNotifier( cryptContext, RESOURCE_IMESSAGE_DECREFCOUNT );
	return( TRUE );
	}

/* Initialise and shut down the system */

#if defined( __WIN32__ ) && defined( STATIC_LIB )
DEFINE_LOCKING_VARS( initialisation )
BOOLEAN isWin95;
#endif /* __WIN32__ && STATIC_LIB */

static int initCrypt( void )
	{
	int initLevel = 0, status;

	/* If the Win32 version is being compiled as a static .LIB (not
	   recommended) we need to perform initialisation here.  Note that in
	   this form cryptlib is no longer thread-safe */
#if defined( __WIN32__ ) && defined( STATIC_LIB )
	static DWORD dwPlatform = ( DWORD ) CRYPT_ERROR;

	/* Figure out which OS we're running under */
	if( dwPlatform == CRYPT_ERROR )
		{
		OSVERSIONINFO osvi = { sizeof( osvi ) };

		GetVersionEx( &osvi );
		dwPlatform = osvi.dwPlatformId;
		isWin95 = ( dwPlatform == VER_PLATFORM_WIN32_WINDOWS ) ? TRUE : FALSE;

		/* Check for Win32s just in case someone tries to load the DLL under
		   it */
		if( dwPlatform == VER_PLATFORM_WIN32s )
			return( CRYPT_ERROR );
		}

	/* Set up the library initialisation lock */
	initGlobalResourceLock( initialisation );
#endif /* __WIN32__ && STATIC_LIB */

	/* If we've already been initialised, don't do anything */
	if( !beginInitialisation( TRUE ) )
		return( CRYPT_OK );

	/* VisualAge C++ doesn't set the TZ correctly */
#if defined( __IBMC__ ) || defined( __IBMCPP__ )
	tzset();
#endif /* VisualAge C++ */

	/* Set up the initial hardwired configuration options, the internal
	   resources (semaphores, message functions, and the object table), and
	   the randomness pseudo-device */
	status = initInternalFunctions();
	if( cryptStatusOK( status ) )
		{
		/* Internal functions initialised, create the system objects */
		initLevel++;
		status = createSystemDeviceObject();
		if( cryptStatusOK( status ) )
			status = createDefaultUserObject();
		}
	if( cryptStatusOK( status ) )
		{
		/* System object created, read the config options and initialise the
		   certificate trust info (we have to initialise the trust info first
		   because reading the config options typically also reads in any
		   saved trust information).  We ignore any return codes at this
		   point because we don't want all of cryptlib to fail because of a
		   problem in the config file - if there's a problem we fall back to
		   internal defaults */
		initLevel++;
		initTrustInfo();
		bindDrivers();
		}

	/* Everything's set up, verify that the kernel's security mechanisms
	   are working as required */
	if( cryptStatusOK( status ) && !testKernelMechanisms() )
		{
		/* We should probably sound klaxons as well at this point */
		assert( NOTREACHED );
		status = CRYPT_ERROR_FAILED;
		}

	/* If anything failed, shut down the internal functions and services
	   before we exit - this can only happens under exception circumstances,
	   because of this and because undoing the async.driver bind is rather
	   complex we don't bother with this (the OS will undo it anyway when
	   we're unloaded) */
	if( !cryptStatusOK( status ) )

⌨️ 快捷键说明

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