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

📄 cryptkrn.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
		objectHandle == SYSTEM_OBJECT_HANDLE || \
		objectTable[ objectHandle ].type != type || \
		!checkObjectOwnership( objectTable[ objectHandle ] ) )
		{
		unlockResource( objectTable );
		return( errorCode );
		}

	/* It's a valid object, get its info */
	objectInfoPtr = &objectTable[ objectHandle ];

	/* Inner precondition: The object is of the requested type */
	PRE( objectInfoPtr->type == type );

	/* This function can only be called on certificates (used when copying
	   internal state such as cert extensions or CRL info from one cert
	   object to another), crypto hardware devices other than the system
	   object (used when a context tied to a crypto hardware device needs to
	   perform an operation using the device), and user objects (used when
	   updating config data, which can take awhile) */
	if( objectInfoPtr->type != OBJECT_TYPE_CERTIFICATE && \
		objectInfoPtr->type != OBJECT_TYPE_DEVICE && \
		objectInfoPtr->type != OBJECT_TYPE_USER )
		{
		unlockResource( objectTable );
		assert( NOTREACHED );
		return( CRYPT_ERROR_PERMISSION );
		}

	/* Inner precondition: It's a certificate or a crypto device */
	PRE( objectInfoPtr->type == OBJECT_TYPE_CERTIFICATE || \
		 objectInfoPtr->type == OBJECT_TYPE_DEVICE || \
		 objectInfoPtr->type == OBJECT_TYPE_USER );

	/* If the object is busy, wait for it to become available */
	if( isInUse( objectHandle ) && !isObjectOwner( objectHandle ) )
		status = waitForObject( objectHandle, &objectInfoPtr );
	if( cryptStatusOK( status ) )
		{
		objectInfoPtr->lockCount++;
		objectInfoPtr->lockOwner = THREAD_SELF();
		*objectPtr = objectInfoPtr->objectPtr;
		}

	unlockResource( objectTable );
	return( status );
	}

int krnlReleaseObject( const int objectHandle )
	{
	return( releaseObject( objectHandle, TRUE ) );
	}

/* Relinquish ownership of the system object to another thread.  This
   procedure is needed to allow a background polling thread to add entropy
   to the system device.  The way it works is that the calling thread hands
   ownership over to the polling thread and suspends itself until the
   polling thread completes.  When the polling thread has completed, it
   terminates, whereupon the original thread wakes up and reacquires
   ownership */

int krnlReleaseSystemObject( const THREAD_HANDLE objectOwner )
	{
	OBJECT_INFO *objectInfoPtr = &objectTable[ SYSTEM_OBJECT_HANDLE ];
	int status = CRYPT_OK;

	/* Preconditions: The object is in use */
	PRE( isInUse( SYSTEM_OBJECT_HANDLE ) );

	lockResource( objectTable );

	/* Precondition: We're relinquishing ownership, we're currently the
	   owner */
	PRE( isObjectOwner( SYSTEM_OBJECT_HANDLE ) );

	objectInfoPtr->lockOwner = objectOwner;

	unlockResource( objectTable );
	return( status );
	}

int krnlReacquireSystemObject( void )
	{
	OBJECT_INFO *objectInfoPtr = &objectTable[ SYSTEM_OBJECT_HANDLE ];
	int status = CRYPT_OK;

	/* Preconditions: The object is in use */
	PRE( isInUse( SYSTEM_OBJECT_HANDLE ) );

	lockResource( objectTable );

	/* Precondition: We're reacquiring ownership, we're not currently the
	   owner */
	PRE( !isObjectOwner( SYSTEM_OBJECT_HANDLE ) );

	objectInfoPtr->lockOwner = THREAD_SELF();

	unlockResource( objectTable );
	return( status );
	}

/****************************************************************************
*																			*
*							Object Creation/Destruction						*
*																			*
****************************************************************************/

/* Create a new object.  This function has to be very careful about locking
   to ensure that another thread can't manipulate the newly-created object
   while it's in an indeterminate state.  To accomplish this it locks the
   object table and tries to create the new object.  If this succeeds it sets
   the OBJECT_FLAG_NOTINITED flag pending completion of the object's
   initialisation by the caller, unlocks the object table, and returns
   control to the caller.  While the object is in this state, the kernel
   will allow it to process only two message types, either a notification
   from the caller that the init stage is complete (which sets the object's
   state to OK), or a destroy object message, which sets the
   OBJECT_FLAG_SIGNALLED flag pending arrival of the init complete
   notification, whereupon the object is immediately destroyed.  The state
   diagram for this is:
									 State
						  Notinited			Signalled
			--------+-------------------+-----------------
			-> OK	| state -> OK,		| Msg -> Destroy
					| ret( OK )			|
	Msg.	Destroy	| state -> Sig'd,	| state -> Sig'd,
					| ret( OK )			| ret( OK )
			CtrlMsg	| process as usual	| process as usual
			NonCtrl	| ret( Notinited )	| ret( Sig'd )

   The initialisation process for an object is therefore:

	status = krnlCreateObject( ... );
	if( cryptStatusError( status ) )
		return( status );

	// Complete object-specific initialisation
	initStatus = ...;

	status = krnlSendMessage( ..., state -> CRYPT_OK );
	return( ( cryptStatusError( initStatus ) ? initStatus : status );

   If the object is destroyed during the object-specific initialisation
   (either by the init code when an error is encountered or due to an
   external signal), the destroy is deferred until the change state message
   at the end occurs.  If a destroy is pending, the change state is converted
   to a destroy and the newly-created object is destroyed.

   This mechanism ensures that the object table is only locked for a very
   short time (typically for only a few lines of executed code in the create
   object function) so that slow initialisation (for example of keyset
   objects associated with network links) can't block other objects.

   The locking is complicated by the fact that the object table and lock may
   not have been initialised yet, so we also need to check the initialisation
   lock before we try to lock or use the object table.  Even this can create
   problems since the initialisation lock may not have been set up yet, but
   we can't really fix that.  In any case under Win32 it's OK since the mutex
   is set up by DllMain(), and under most Unixen the storage for the mutex is
   set to all-zero which is equivalent to an initialised mutex.

   In addition to the locking, we need to be careful with how we create new
   objects because if we just allocate handles sequentially and reuse handles
   as soon as possible, an existing object could be signalled and a new one
   created in its place without the caller or owning object realizing that
   they're now working with a different object (although the kernel can tell
   them apart because it maintains an internal unique ID for each object).
   Unix systems handle this by always incrementing pids and assuming there
   won't be any problems when they wrap, we do the same thing but in
   addition allocate handles in a non-sequential manner using an LFSR to
   step through the object table.  There's no strong reason for this, but it
   only costs a few extra clocks so we may as well do it */

static int findFreeResource( int value )
	{
	int oldValue = value;
	TEMP_INT( iterations = 0 );

	/* Preconditions: We're starting with a valid object handle, and it's not
	   a system object */
	PRE( isValidHandle( value ) );
	PRE( value >= NO_SYSTEM_OBJECTS );

	/* Step through the entire table looking for a free entry */
	do
		{
		/* Get the next value: Multiply by x and reduce by the polynomial */
		value <<= 1;
		if( value & objectStateInfo.lfsrMask )
			value ^= objectStateInfo.lfsrPoly;

		INV( iterations++ < objectTableSize );
		}
	while( objectTable[ value ].objectPtr != NULL && \
		   value != oldValue );

	if( value == oldValue )
		{
		/* Postcondition: We tried all locations and there are no free slots
		   available */
		POST( iterations == objectTableSize - 1 );
		FORALL( i, 0, objectTableSize,
				objectTable[ i ].objectPtr != NULL );

		return( CRYPT_ERROR );
		}

	/* Postconditions: We found a handle to a free slot */
	POST( isValidHandle( value ) );
	POST( isFreeObject( value ) );

	return( value );
	}

int krnlCreateObject( void **objectDataPtr, const int objectDataSize,
					  const OBJECT_TYPE type, const int subType,
					  const int createObjectFlags, const CRYPT_USER owner,
					  const int actionFlags,
					  MESSAGE_FUNCTION messageFunction )
	{
	OBJECT_INFO objectInfo;
	int objectHandle = objectStateInfo.objectHandle;
	TEMP_INT( bitCount );

	/* Preconditions (the subType check is just the standard hakmem bitcount
	   which ensures that we don't try and create multi-typed objects, the
	   sole exception to this rule is the default user object that acts as
	   both a user and SO object) */
	PRE( objectDataPtr != NULL );
	PRE( objectDataSize > 16 && objectDataSize < 16384 );
	PRE( isValidType( type ) );
	PRE( ( bitCount = ( subType & ~SUBTYPE_CLASS_MASK ) - \
						( ( ( subType & ~SUBTYPE_CLASS_MASK ) >> 1 ) & 033333333333 ) - \
						( ( ( subType & ~SUBTYPE_CLASS_MASK ) >> 2 ) & 011111111111 ) ) != 0 );
	PRE( ( ( bitCount + ( bitCount >> 3 ) ) & 030707070707 ) % 63 == 1 );
	PRE( !( createObjectFlags & \
			~( CREATEOBJECT_FLAG_SECUREMALLOC | CREATEOBJECT_FLAG_DUMMY ) ) );
	PRE( owner == CRYPT_UNUSED || isValidHandle( owner ) );
	PRE( actionFlags < ACTION_PERM_LAST );
	PRE( messageFunction != NULL );

	*objectDataPtr = NULL;

	/* If we're in the middle of a shutdown, we can't create any new
	   objects */
	if( isClosingDown )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_PERMISSION );
		}

	/* Allocate memory for the object and set up the object table entry.  The
	   object is always created as an internal object, it's up to the caller
	   to make it externally visible.  Since this step doesn't access the
	   object table, we do it outside the locked section */
	if( createObjectFlags & CREATEOBJECT_FLAG_SECUREMALLOC )
		{
		int status = krnlMemalloc( objectDataPtr, objectDataSize );
		if( cryptStatusError( status ) )
			return( status );
		}
	else
		if( ( *objectDataPtr = clAlloc( "krnlCreateObject", \
										objectDataSize ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
	memset( *objectDataPtr, 0, objectDataSize );
	objectInfo = OBJECT_INFO_TEMPLATE;
	objectInfo.objectPtr = *objectDataPtr;
	objectInfo.owner = owner;
	objectInfo.type = type;
	objectInfo.subType = subType;
	objectInfo.actionFlags = actionFlags;
	objectInfo.uniqueID = objectUniqueID;
	objectInfo.messageFunction = messageFunction;

	/* Make sure that the kernel has been initialised, and if it has lock
	   the object table for exclusive access */
	lockResource( initialisation );
	if( !isInitialised )
		{
		unlockResource( initialisation );
		return( CRYPT_ERROR_NOTINITED );
		}
	lockResource( objectTable );
	unlockResource( initialisation );

	/* The first objects created are internal objects with predefined
	   handles (spes lucis aeternae).  As we create these objects we ratchet
	   up through the fixed handles until we reached the last fixed object,
	   whereupon we allocate handles normally */
	if( objectHandle < NO_SYSTEM_OBJECTS - 1 )
		{
		PRE( ( objectHandle == SYSTEM_OBJECT_HANDLE - 1 && \
			   owner == CRYPT_UNUSED && \
			   type == OBJECT_TYPE_DEVICE && \
			   subType == SUBTYPE_DEV_SYSTEM ) || \
			 ( objectHandle == DEFAULTUSER_OBJECT_HANDLE - 1 && \
			   owner == SYSTEM_OBJECT_HANDLE && \
			   type == OBJECT_TYPE_USER && \
			   subType == SUBTYPE_USER_SO ) );
		objectHandle++;
		POST( isValidHandle( objectHandle ) && \
			  objectHandle < NO_SYSTEM_OBJECTS && \
			  objectHandle == objectStateInfo.objectHandle + 1 );
		}
	else
		{
		PRE( isValidHandle( owner ) );

		/* Search the table for a free entry */
		objectHandle = findFreeResource( objectHandle );
		}

	/* If the table is full, expand it */
	if( objectHandle == CRYPT_ERROR )
		{
		static const int lfsrPolyTable[] = \
							{	  0x83,	   0x11D,	 0x211,	   0x409,
								 0x805,   0x1053,   0x201B,   0x402B,
								0x8003,  0x1002D,  0x20009,  0x40027,
							   0x80027, 0x100009, 0x200005, 0x400003 };
		OBJECT_INFO *newTable;
		int i;
		ORIGINAL_INT_VAR( oldLfsrPoly, objectStateInfo.lfsrPoly );

		/* If we're already at the maximum number of allowed objects, don't
		   create any more.  This prevents both accidental runaway code
		   that creates huge numbers of objects and DOS attacks */
		if( objectTableSize >= MAX_OBJECTS )
			{
			unlockResource( objectTable );
			return( CRYPT_ERROR_MEMORY );

⌨️ 快捷键说明

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