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

📄 cryptkrn.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
			}

		/* Precondition: We haven't exceeded the maximum number of objects */
		PRE( objectTableSize < MAX_OBJECTS );

		/* Expand the table */
		newTable = clDynAlloc( "krnlCreateObject", \
							   ( objectTableSize * 2 ) * sizeof( OBJECT_INFO ) );
		if( newTable == NULL )
			{
			unlockResource( objectTable );
			return( CRYPT_ERROR_MEMORY );
			}

		/* Copy the information across to the new table, set up the newly-
		   allocated entries, and clear the old table */
		memcpy( newTable, objectTable,
				objectTableSize * sizeof( OBJECT_INFO ) );
		for( i = objectTableSize; i < objectTableSize * 2; i++ )
			newTable[ i ] = OBJECT_INFO_TEMPLATE;
		zeroise( objectTable, objectTableSize * sizeof( OBJECT_INFO ) );
		clFree( "krnlCreateObject", objectTable );
		objectTable = newTable;
		objectTableSize *= 2;

		/* Add the new object at the end of the existing table */
		objectStateInfo.lfsrMask <<= 1;
		for( i = 0; i < 16; i++ )
			if( lfsrPolyTable[ i ] > objectStateInfo.lfsrPoly )
				break;
		objectStateInfo.lfsrPoly = lfsrPolyTable[ i ];
		objectHandle = findFreeResource( objectStateInfo.objectHandle );

		/* Postcondition: We've moved on to the next LFSR polynomial value,
		   and the LFSR output covers the entire table */
		POST( ( objectStateInfo.lfsrPoly & ~0x7F ) == \
			  ( ORIGINAL_VALUE( oldLfsrPoly ) & ~0xFF ) << 1 );
		POST( objectStateInfo.lfsrMask == \
			  ( objectStateInfo.lfsrPoly & ~0x7F ) );
		POST( objectTableSize == objectStateInfo.lfsrMask );
		}

	/* Set up the new object entry in the table and update the object table
	   state */
	objectTable[ objectHandle ] = objectInfo;
	if( objectHandle == NO_SYSTEM_OBJECTS - 1 )
		{
		/* If this is the last system object, we've been allocating handles
		   sequentially up to this point.  From now on we start allocating
		   handles starting from a randomised location in the table */
		objectStateInfo.objectHandle = \
			( ( int ) getTime() ) & ( objectStateInfo.lfsrMask - 1 );
		if( objectStateInfo.objectHandle < NO_SYSTEM_OBJECTS )
			/* Can occur with probability NO_SYSTEM_OBJECTS / 1024 */
			objectStateInfo.objectHandle = NO_SYSTEM_OBJECTS + 42;
		}
	else
		objectStateInfo.objectHandle = objectHandle;

	/* Update the object unique ID value */
	if( objectUniqueID >= INT_MAX - 1 )
		objectUniqueID = 0;
	else
		objectUniqueID++;
	POST( objectUniqueID >= 0 && objectUniqueID <= INT_MAX );

	/* Postconditions: It's a valid object set up as required */
	POST( isValidObject( objectHandle ) );
	POST( objectInfo.objectPtr == *objectDataPtr );
	POST( objectInfo.owner == owner );
	POST( objectInfo.type == type );
	POST( objectInfo.subType == subType );
	POST( objectInfo.actionFlags == actionFlags );
	POST( objectInfo.messageFunction == messageFunction );

	unlockResource( objectTable );
	return( objectHandle );
	}

/****************************************************************************
*																			*
*							Internal Message Handlers						*
*																			*
****************************************************************************/

/* Update an action permission.  This implements a ratchet that only allows
   permissions to be made more restrictive after they've initially been set,
   so once a permission is set to a given level it can't be set to a less
   restrictive level (i.e. it's a write-up policy) */

static int updateActionPerms( int currentPerm, const int newPerm )
	{
	int permMask = ACTION_PERM_MASK, i;

	/* For each permission, update its value if the new setting is more
	   restrictive than the current one.  Since smaller values are more
	   restrictive, we can do a simple range comparison and replace the
	   existing value if it's larger than the new one */
	for( i = 0; i < ACTION_PERM_COUNT; i++ )
		{
		if( ( newPerm & permMask ) < ( currentPerm & permMask ) )
			currentPerm = ( currentPerm & ~permMask ) | ( newPerm & permMask );
		permMask <<= ACTION_PERM_BITS;
		}

	/* Postcondition: The new permission is at least as restrictive (or more
	   so) than the old one */
	FORALL( i, 0, ACTION_PERM_COUNT,
			( currentPerm & ( ACTION_PERM_MASK << ( i * ACTION_PERM_BITS ) ) ) <= \
				( newPerm & ( ACTION_PERM_MASK << ( i * ACTION_PERM_BITS ) ) ) );

	return( currentPerm );
	}

/* Update the action permissions for an object based on the composite
   permissions for it and a dependent object.  This is a special-case
   function because it has to operate with the object table unlocked.  This
   is necessary because the dependent object may be owned by another thread,
   and if we were to leave the object table locked the two would deadlock if
   we were sending the object a message while owning the object table at the
   same time the other thread was sending a message while owning the object.

   There is one potential race condition possible here in which the object
   is destroyed and replaced by a new one while the object table is unlocked,
   so we end up updating the action permissions for a different object.  To
   protect against this, we check the unique ID after we re-lock the object
   table to make sure that it's the same object */

static int updateDependentObjectPerms( const CRYPT_HANDLE objectHandle,
									   const CRYPT_HANDLE dependentObject )
	{
	STATIC_FN int setPropertyAttribute( const int objectHandle,
										const CRYPT_ATTRIBUTE_TYPE attribute,
										void *messageDataPtr );
	const OBJECT_TYPE objectType = objectTable[ objectHandle ].type;
	const CRYPT_CONTEXT contextHandle = \
		( objectType == OBJECT_TYPE_CONTEXT ) ? objectHandle : dependentObject;
	const CRYPT_CERTIFICATE certHandle = \
		( objectType == OBJECT_TYPE_CERTIFICATE ) ? objectHandle : dependentObject;
	const unsigned int uniqueID = objectTable[ objectHandle ].uniqueID;
	int actionFlags = 0, status;
	ORIGINAL_INT_VAR( oldPerm, objectTable[ contextHandle ].actionFlags );

	/* Preconditions: Objects are valid, one is a cert and the other a
	   context, and they aren't dependent on each other (which would create
	   a dependency update loop) */
	PRE( isValidObject( objectHandle ) );
	PRE( isValidHandle( dependentObject ) );
	PRE( ( objectTable[ objectHandle ].type == OBJECT_TYPE_CONTEXT && \
		   objectTable[ dependentObject ].type == OBJECT_TYPE_CERTIFICATE ) || \
		 ( objectTable[ objectHandle ].type == OBJECT_TYPE_CERTIFICATE && \
		   objectTable[ dependentObject ].type == OBJECT_TYPE_CONTEXT ) );
	PRE( objectTable[ objectHandle ].dependentObject != dependentObject || \
		 objectTable[ dependentObject ].dependentObject != objectHandle );

	/* Since we're about to send messages to the dependent object, we have to
	   unlock the object table */
	unlockResource( objectTable );

#if 0	/* Removed 12/6/03 since privKey contexts are no longer attached to
		   certs, instead pubKey components are copied over and/or a new
		   pure pubKey context is created if necessary */
	/* When we attach a cert to a context or a public-key context to a cert,
	   we have to find the way in which the cert constrains the context and
	   adjust the context's action ACL as appropriate.  In contrast when we
	   attach a private key context to a cert (done when adding a key to a
	   freshly-created cert) we don't change the context's action ACL until
	   the context/cert pair is re-instantiated (e.g. by writing it to a
	   keyset and then re-reading it, which instantiates it as a context
	   with a cert attached).  The reason for this is that the cert key
	   usage may constrain the context in a way that renders its use
	   impossible (for example creating an encryption-only self-signed cert
	   would be impossible), or the context may be associated with multiple
	   mutually-exclusive certs (one signature-only, one encryption-only),
	   or the key usage in the cert may not be set until after the context
	   is attached, or any number of other variations.  Because of this a
	   cert -> context attach (done when instantiating a context+cert object
	   pair) or a public key context -> cert attach (done when importing a
	   cert, which creates the cert as the primary object and attaches the
	   context for non-data-only certs) imposes the cert constraint on the
	   context, but a private key context -> cert attach (done when adding a
	   key to a new cert object) doesn't impose them.  However, we do make
	   the actions for the key internal-only to ensure that it's only used
	   in an approved manner */
	if( objectType == OBJECT_TYPE_CERTIFICATE && \
		cryptStatusOK( \
			krnlSendMessage( dependentObject, IMESSAGE_CHECK, NULL,
							 MESSAGE_CHECK_PKC_PRIVATE ) ) )
		{
		static const int actionFlags = ACTION_PERM_NONE_EXTERNAL_ALL;

		/* The dependent object is a private-key context being attached to
		   a cert, make the key actions internal-only but don't do anything
		   else */
		lockResource( objectTable );
		if( objectTable[ objectHandle ].uniqueID != uniqueID )
			return( CRYPT_ERROR_SIGNALLED );
		return( krnlSendMessage( contextHandle, IMESSAGE_SETATTRIBUTE,
								 ( void * ) &actionFlags,
								 CRYPT_IATTRIBUTE_ACTIONPERMS ) );
		}
#else
	if( objectType == OBJECT_TYPE_CERTIFICATE && \
		cryptStatusOK( \
			krnlSendMessage( dependentObject, IMESSAGE_CHECK, NULL,
							 MESSAGE_CHECK_PKC_PRIVATE ) ) )
		{
		/* We can't make a private key dependent on a cert, which is a
		   public-key object */
		assert( NOTREACHED );
		return( CRYPT_ARGERROR_OBJECT );
		}
	if( objectType == OBJECT_TYPE_CONTEXT && \
		isValidObject( ( objectTable[ dependentObject ].dependentObject ) ) )
		{
		/* We can't attach a cert that's already associated with a context to
		   another context */
		assert( NOTREACHED );
		return( CRYPT_ARGERROR_OBJECT );
		}
#endif /* 0 */

	/* For each action type, enable its continued use only if the cert
	   allows it.  Because a key with a certificate attached indicates that
	   it's (probably) being used for some function that involves interaction
	   with a relying party (i.e. that it probably has more value than a raw
	   key with no strings attached), we set the action permission to
	   ACTION_PERM_NONE_EXTERNAL rather than allowing ACTION_PERM_ALL.  This
	   both ensures that it's only used in a safe manner via the cryptlib
	   internal mechanisms, and makes sure that it's not possible to utilize
	   the signature/encryption duality of some algorithms to create a
	   signature where it's been disallowed */
	if( cryptStatusOK( krnlSendMessage( certHandle,
					IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_SIGN ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_NONE_EXTERNAL );
	if( cryptStatusOK( krnlSendMessage( certHandle,
					IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_SIGCHECK ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL );
	if( cryptStatusOK( krnlSendMessage( certHandle,
					IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_ENCRYPT ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
	if( cryptStatusOK( krnlSendMessage( certHandle,
					IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_DECRYPT ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );
	if( cryptStatusOK( krnlSendMessage( certHandle,
					IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_KA_EXPORT ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
	if( cryptStatusOK( krnlSendMessage( certHandle,
					IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_KA_IMPORT ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );

	/* We're done querying the dependent object, re-lock the object table and
	   make sure that the original object hasn't been touched */
	lockResource( objectTable );
	if( objectTable[ objectHandle ].uniqueID != uniqueID )
		return( CRYPT_ERROR_SIGNALLED );
	status = setPropertyAttribute( contextHandle, CRYPT_IATTRIBUTE_ACTIONPERMS,
								   &actionFlags );

	/* Postcondition: The new permission is at least as restrictive (or more
	   so) than the old one */
	FORALL( i, 0, ACTION_PERM_COUNT,
			( objectTable[ contextHandle ].actionFlags & ( ACTION_PERM_MASK << ( i * 2 ) ) ) <= \
			( ORIGINAL_VALUE( oldPerm ) & ( ACTION_PERM_MASK << ( i * 2 ) ) ) );

	return( status );
	}

/* Get/set object property attributes.  We differentiate between a small
   number of user-accessible properties such as the object's owner, and
   properties that are only accessible by cryptlib.  The user-accessible
   properties can be locked, which makes them immutable (at least to being
   explicitly set, they can still be implicitly altered, for example setting
   a new object owner decrements the forwardcount value) and also unreadable
   by the user */

static int getPropertyAttribute( const int objectHandle,
								 const CRYPT_ATTRIBUTE_TYPE attribute,
								 void *messageDataPtr )
	{
	const OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];
	int *valuePtr = ( int * ) messageDataPtr;

	/* Preconditions */
	PRE( isValidObject( objectHandle ) );
	PRE( attribute == CRYPT_PROPERTY_OWNER || \
		 attribute == CRYPT_PROPERTY_FORWARDCOUNT || \
		 attribute == CRYPT_PROPERTY_LOCKED || \
		 attribute == CRYPT_PROPERTY_USAGECOUNT || \
		 attribute == CRYPT_IATTRIBUTE_TYPE || \
		 attribute == CRYPT_IATTRIBUTE_SUBTYPE || \
		 attribute == CRYPT_IATTRIBUTE_STATUS || \
		 attribute == CRYPT_IATTRIBUTE_INTERNAL || \
		 attribute == CRYPT_IATTRIBUTE_ACTIONPERMS );
	PRE( messageDataPtr != NULL );

	switch( attribute )
		{
		/* User-accessible properties */
		case CRYPT_PROPERTY_OWNER:
			/* We allow this to be read since its value can be determined
			   anyway with a trial access */
			if( !( objectInfoPtr->flags & OBJECT_FLAG_OWNED ) )
				return( CRYPT_ERROR_NOTINITED );
#if defined( __MVS__ ) || ( defined( __UNIX__ ) && defined( _MPRAS ) )
			/* A very small number of pthreads implementations use non-
			   scalar thread IDs, which we can't easily handle when all we
			   have is an integer handle.  However, the need to bind threads
			   to objects only exists because of Win32 security holes
			   arising from the ability to perform thread injection, so this
			   isn't a big issue */
			return( CRYPT_ERROR_FAILED );
#else
			*valuePtr = ( int ) objectInfoPtr->objectOwner;
#endif /* Non-scalar threading environments */
			break;

		case CRYPT_PROPERTY_FORWARDCOUNT:
			if( objectInfoPtr->flags & OBJECT_FLAG_ATTRLOCKED )
				return( CRYPT_ERROR_PERMISSION );
			*valuePtr = objectInfoPtr->forwardCount;
			break;

		case CRYPT_PROPERTY_LOCKED:
			/* We allow this to be read since its value can be determined
			   anyway with a trial write */

⌨️ 快捷键说明

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