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

📄 cryptkrn.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*							cryptlib Security Kernel						*
*						Copyright Peter Gutmann 1992-2003					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#ifndef NDEBUG
#include <stdio.h>	/* Needed for POST macro on some systems */
#endif /* Debug version */
#include "crypt.h"
#include "cryptacd.h"

/* RAY and EGON look over code.

   EGON: The structure of this kernel is exactly like the kind of telemetry
         tracker that NASA uses to secure dead pulsars in deep space.

   RAY: All message dispatch mechanisms and callback functions.

   PETER (to other jailbirds): Everyone getting this so far?  So what?  I
         guess they just don't make them like they used to.

   RAY: No!  Nobody ever made them like this!  The architect was either a
        certified genius or an authentic wacko! */

/* "There is a fine line between genius and insanity.  I have erased this
    line" - Oscar Levant (or "Nullum magnum ingenium sine mixtura dementiae"
	if you want it in the usual style) */

/* The initialisation state and a lock to protect it.  The object
   management functions check the state before they do anything and return
   CRYPT_INITED if cryptlib hasn't been initialised.  Since everything in
   cryptlib depends on the creation of objects, any attempts to use cryptlib
   without it being properly initialised are caught.

   Reading the isInitialised flag presents something of a chicken-and-egg
   problem since the read should be protected by the intialisation mutex, but
   we can't try and grab it unless the mutex has been initialised.  If we
   just read the flag directly and rely on the object map mutex to protect
   access we run into a potential race condition on shutdown:

	thread1							thread2

	inited = T						read inited = T
	inited = F, destroy objects
									lock objects, die

   The usual way to avoid this is to perform an interlocked mutex lock, but
   this isn't possible here since the initialisation mutex may not be
   initialised.  Under Win32 it's set by DllMain() */

DECLARE_LOCKING_VARS( initialisation )
static BOOLEAN isInitialised = FALSE;
static BOOLEAN isClosingDown = FALSE;

/* Some messages communicate standard data values that are used again and
   again so we predefine values for these that can be used globally */

const int messageValueTrue = TRUE;
const int messageValueFalse = FALSE;
const int messageValueCryptOK = CRYPT_OK;
const int messageValueCryptError = CRYPT_ERROR;
const int messageValueCryptSignalled = CRYPT_ERROR_SIGNALLED;
const int messageValueCryptUnused = CRYPT_UNUSED;
const int messageValueCryptUseDefault = CRYPT_USE_DEFAULT;
const int messageValueCursorFirst = CRYPT_CURSOR_FIRST;
const int messageValueCursorNext = CRYPT_CURSOR_NEXT;
const int messageValueCursorPrevious = CRYPT_CURSOR_PREVIOUS;
const int messageValueCursorLast = CRYPT_CURSOR_LAST;

/****************************************************************************
*																			*
*						Object Definitions and Information					*
*																			*
****************************************************************************/

/* Macros to perform validity checks on objects and handles.  These checks
   are:

	isValidHandle(): Whether a handle is a valid index into the object table.
	isValidObject(): Whether a handle refers to an object in the table.
	isFreeObject(): Whether a handle refers to an empty entry in the table.
	isInternalObject(): Whether an object is an internal object.
	isInvalidObjectState(): Whether an object is in an invalid (error) state.
	isInUse(): Whether an object is currently in use (processing a message).
	isObjectOwner(): if inUse == TRUE, whether this thread is the one using
					 the object.
	isInHighState(): Whether an object is in the 'high' security state.
	isSameOwningObject(): Whether two objects have the same owner.  We also
						  have to handle the situation where the first object
						  is a user object, in which case it has to be the
						  owner of the second object.
	isAliasedObject(): Whether an object is an alias for another object and
					   subject to copy-on-write.
	isClonedObject(): Whether an aliased object is the original or the clone.
	isObjectAccessValid(): Internal/external object access check.
	isValidMessage(): Whether a message type is valid.
	isValidType(): Whether an object type is valid
	isValidSubtype(): Whether an object subtype is allowed based on access
					  bitflags */

#define isValidHandle( handle ) \
		( ( handle ) >= 0 && ( handle ) < objectTableSize )
#define isValidObject( handle ) \
		( isValidHandle( handle ) && objectTable[ ( handle ) ].objectPtr != NULL )
#define isFreeObject( handle ) \
		( isValidHandle( handle ) && objectTable[ ( handle ) ].objectPtr == NULL )
#define isInternalObject( handle ) \
		( objectTable[ handle ].flags & OBJECT_FLAG_INTERNAL )
#define isObjectAccessValid( objectHandle, message ) \
		!( isInternalObject( objectHandle ) && \
		   !( message & MESSAGE_FLAG_INTERNAL ) )
#define isInvalidObjectState( handle ) \
		( objectTable[ ( handle ) ].flags & OBJECT_FLAGMASK_STATUS )
#define isInUse( handle ) \
		( objectTable[ ( handle ) ].lockCount > 0 )
#define isObjectOwner( handle ) \
		THREAD_SAME( objectTable[ ( handle ) ].lockOwner, THREAD_SELF() )
#define isInHighState( handle ) \
		( objectTable[ ( handle ) ].flags & OBJECT_FLAG_HIGH )
#define isSameOwningObject( handle1, handle2 ) \
		( objectTable[ ( handle1 ) ].owner == CRYPT_UNUSED || \
		  objectTable[ ( handle2 ) ].owner == CRYPT_UNUSED || \
		  ( objectTable[ ( handle1 ) ].owner == objectTable[ ( handle2 ) ].owner ) || \
		  ( ( handle1 ) == objectTable[ ( handle2 ) ].owner ) )
#define isAliasedObject( handle ) \
		( objectTable[ handle ].flags & OBJECT_FLAG_ALIASED )
#define isClonedObject( handle ) \
		( objectTable[ handle ].flags & OBJECT_FLAG_CLONE )
#define isValidMessage( message ) \
		( ( message ) > MESSAGE_NONE && ( message ) < MESSAGE_LAST )
#define isValidType( type ) \
		( ( type ) > OBJECT_TYPE_NONE && ( type ) < OBJECT_TYPE_LAST )
#define isValidSubtype( subtypeMask, subtype ) \
		( ( ( subtypeMask ) & ( subtype ) ) == ( subtype ) )

/* Macros to test whether a message falls into a certain class.  These tests
   are:

	isParamMessage(): Whether a message contains an object as a parameter */

#define isParamMessage( message ) \
		( ( message ) == MESSAGE_CRT_SIGN || \
		  ( message ) == MESSAGE_CRT_SIGCHECK )

/* Macros to manage object ownership, if the OS supports it */

#define checkObjectOwnership( objectPtr ) \
		( !( ( objectPtr ).flags & OBJECT_FLAG_OWNED ) || \
		  THREAD_SAME( ( objectPtr ).objectOwner, THREAD_SELF() ) )

/* A macro to turn an abnormal status indicated in an object's flags into a
   status code.  The values are prioritised so notinited > signalled > busy */

#define getObjectStatusValue( flags ) \
		( ( flags & OBJECT_FLAG_NOTINITED ) ? CRYPT_ERROR_NOTINITED : \
		  ( flags & OBJECT_FLAG_SIGNALLED ) ? CRYPT_ERROR_SIGNALLED : \
		  ( flags & OBJECT_FLAG_BUSY ) ? CRYPT_ERROR_TIMEOUT : CRYPT_OK )

/* The initial allocation size of the object table.  In memory-starved
   environments we limit the size, in general these are embedded systems or
   single-tasking OSs that aren't going to need many objects anyway */

#ifdef CONFIG_CONSERVE_MEMORY
  #define OBJECT_TABLE_ALLOCSIZE	128
  #define INITIAL_LFSRPOLY			0x83
#else
  #define OBJECT_TABLE_ALLOCSIZE	1024
  #define INITIAL_LFSRPOLY			0x409
#endif /* Memory-starved environments */

/* The information maintained by the kernel for each object */

typedef struct {
	/* Object type and value */
	OBJECT_TYPE type;			/* Object type */
	int subType;				/* Object subtype */
	void *objectPtr;			/* Object data */

	/* Object properties */
	int flags;					/* Internal-only, locked, etc */
	int actionFlags;			/* Permitted actions */
	int referenceCount;			/* Number of references to this object */
	int lockCount;				/* Message-processing lock recursion count */
	THREAD_HANDLE lockOwner;	/* Lock owner if lockCount > 0 */
	unsigned int uniqueID;		/* Unique ID for this object */
/*	time_t lastAccess;			// Last access time */

	/* Object security properties */
	int forwardCount;			/* Number of times ownership can be transferred */
	int usageCount;				/* Number of times obj.can be used */
	THREAD_HANDLE objectOwner;	/* The object's owner */

	/* Object methods */
	MESSAGE_FUNCTION messageFunction;
								/* The object's message handler */
	/* Owning and dependent objects */
	CRYPT_USER owner;			/* Owner object handle */
	CRYPT_HANDLE dependentObject;	/* Dependent object (context or cert) */
	CRYPT_HANDLE dependentDevice;	/* Dependent crypto device */
	CRYPT_HANDLE clonedObject;	/* Cloned object if aliased */
	} OBJECT_INFO;

/* The flags that apply to each object in the table */

#define OBJECT_FLAG_NONE		0x0000	/* Non-flag */
#define OBJECT_FLAG_INTERNAL	0x0001	/* Internal-use only */
#define OBJECT_FLAG_NOTINITED	0x0002	/* Still being initialised */
#define OBJECT_FLAG_HIGH		0x0004	/* In 'high' security state */
#define OBJECT_FLAG_SIGNALLED	0x0008	/* In signalled state */
#define OBJECT_FLAG_BUSY		0x0010	/* Busy with async.op */
#define OBJECT_FLAG_ALIASED		0x0020	/* Object is alias for another object */
#define OBJECT_FLAG_CLONE		0x0040	/* Aliased object is the clone */
#define OBJECT_FLAG_OWNED		0x0080	/* Object is bound to a thread */
#define OBJECT_FLAG_ATTRLOCKED	0x0100	/* Security properties can't be modified */

/* The flags that convey information about an object's status */

#define OBJECT_FLAGMASK_STATUS \
		( OBJECT_FLAG_NOTINITED | OBJECT_FLAG_BUSY | OBJECT_FLAG_SIGNALLED )

/* The table to map external object handles to object data */

static OBJECT_INFO *objectTable;
static int objectTableSize;
DECLARE_LOCKING_VARS( objectTable )
static unsigned int objectUniqueID;

/* A template used to initialise object table entries.  Some of the entries
   are either object handles that have to be set to CRYPT_ERROR or values
   for which 0 is significant (so they're set to CRYPT_UNUSED), because of
   this we can't just memset the entry to all zeroes */

static const OBJECT_INFO OBJECT_INFO_TEMPLATE = {
	OBJECT_TYPE_NONE, 0, NULL,	/* Type, subtype, and data pointer */
	OBJECT_FLAG_INTERNAL | OBJECT_FLAG_NOTINITED,	/* Flags */
	0,							/* Action flags */
	0, 0, THREAD_INITIALISER, 	/* Ref.count, lock count, lock owner */
	0,							/* Unique ID */
	CRYPT_UNUSED, CRYPT_UNUSED,	THREAD_INITIALISER,
								/* Forward count, usage count, owner */
	NULL,						/* Message function */
	CRYPT_ERROR, CRYPT_ERROR,
	CRYPT_ERROR, CRYPT_ERROR	/* Owning/dependent objects */
	};

/* The object allocation state data and a template used to initialise it.
   This controls the allocation of handles to newly-created objects.  The
   first NO_SYSTEM_OBJECTS handles are system objects that exist with
   fixed handles, the remainder are allocated pseudorandomly under the
   control of an LFSR (see the comments further down for more details on
   this) */

typedef struct {
	int lfsrMask, lfsrPoly;		/* LFSR state values */
	int objectHandle;			/* Current object handle */
	} OBJECT_STATE_INFO;

static const OBJECT_STATE_INFO OBJECT_STATE_INFO_TEMPLATE = {
	OBJECT_TABLE_ALLOCSIZE,		/* Mask for LFSR output */
	INITIAL_LFSRPOLY,			/* LFSR polynomial */
	-1							/* Initial-1'th object handle */
	};
static OBJECT_STATE_INFO objectStateInfo;

/* Create and destroy the object table.  The destroy process is handled in
   two stages, the first of which is called fairly early in the shutdown
   process to destroy any remaining objects, and the second which is called
   at the end of the shutdown when the kernel data is being deleted.  This
   is because some of the objects are tied to things like external devices,
   and deleting them at the end when everything else has been shut down
   isn't possible */

static int initObjectTable( void )
	{
	int i;

	/* Allocate and initialise the object table */
	objectTable = clAlloc( "initObjectTable", 
						   OBJECT_TABLE_ALLOCSIZE * sizeof( OBJECT_INFO ) );
	if( objectTable == NULL )
		return( CRYPT_ERROR_MEMORY );
	for( i = 0; i < OBJECT_TABLE_ALLOCSIZE; i++ )
		objectTable[ i ] = OBJECT_INFO_TEMPLATE;
	objectTableSize = OBJECT_TABLE_ALLOCSIZE;
	objectStateInfo = OBJECT_STATE_INFO_TEMPLATE;

	/* Initialise object-related information.  This isn't strictly part of
	   the object table but is used to assing unique ID values to objects
	   within the table, since table entries (object handles) may be reused
	   as objects are destroyed and new ones created in their place */
	objectUniqueID = 0;

	/* Initialize any data structures required to make the object table
	   thread-safe */
	initResourceLock( objectTable );

	/* Postconditions */
	POST( objectTable != NULL );
	POST( objectTableSize == OBJECT_TABLE_ALLOCSIZE );
	FORALL( i, 0, OBJECT_TABLE_ALLOCSIZE,
			!memcmp( &objectTable[ i ], &OBJECT_INFO_TEMPLATE, \
					 sizeof( OBJECT_INFO ) ) );
	POST( objectStateInfo.lfsrMask == OBJECT_TABLE_ALLOCSIZE && \
		  objectStateInfo.lfsrPoly == INITIAL_LFSRPOLY && \
		  objectStateInfo.objectHandle == SYSTEM_OBJECT_HANDLE - 1 );
	POST( objectUniqueID == 0 );

	return( CRYPT_OK );
	}

static int destroySelectedObjects( const int currentDepth )
	{
	int objectHandle, status = CRYPT_OK;

	for( objectHandle = NO_SYSTEM_OBJECTS; objectHandle < objectTableSize;
		 objectHandle++ )
		{
		const int dependentObject = \
						objectTable[ objectHandle ].dependentObject;
		int depth = 1;

		/* If there's nothing there, continue */
		if( objectTable[ objectHandle ].objectPtr == NULL )
			continue;

		/* There's an object still present, determine its nesting depth.
		   Dependent devices are terminal so we only follow the path down for
		   dependent objects */

⌨️ 快捷键说明

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