📄 obj_acc.c
字号:
for correct object types */
status = checkAccessValid( objectHandle, checkType,
CRYPT_ERROR_PERMISSION );
if( cryptStatusError( status ) )
{
MUTEX_UNLOCK( objectTable );
THREAD_NOTIFY_CANCELLED( objectHandle );
retIntError_Ext( status );
}
/* Perform additional checks for correct object types. The ownership
check in checkAccessValid() simply checks whether the current thread
is the overall object owner, isObjectOwner() checks whether the
current thread owns the lock on the object */
if( !isInUse( objectHandle ) || !isObjectOwner( objectHandle ) )
{
MUTEX_UNLOCK( objectTable );
THREAD_NOTIFY_CANCELLED( objectHandle );
retIntError_Ext( CRYPT_ERROR_PERMISSION );
}
/* It's a valid object, get its info */
objectInfoPtr = &objectTable[ objectHandle ];
/* If it was an external access to certificate/device info or an
internal access to the object's keying data, decrement the object's
reference count to allow others access again */
if( checkType == ACCESS_CHECK_EXTACCESS || \
checkType == ACCESS_CHECK_KEYACCESS )
{
STORE_ORIGINAL_INT( lockCount, objectInfoPtr->lockCount );
objectInfoPtr->lockCount--;
/* Postcondition: The object's lock count has been decremented and
is non-negative */
POST( objectInfoPtr->lockCount == \
ORIGINAL_VALUE( lockCount ) - 1 );
POST( objectInfoPtr->lockCount >= 0 );
}
else
{
/* It's an external access to free the object for access by others,
clear the reference count */
PRE( checkType == ACCESS_CHECK_SUSPEND );
*refCount = objectInfoPtr->lockCount;
objectInfoPtr->lockCount = 0;
/* Postcondition: The object has been completely released */
POST( !isInUse( objectHandle ) );
}
MUTEX_UNLOCK( objectTable );
THREAD_NOTIFY_RELEASED( objectHandle );
return( CRYPT_OK );
}
/****************************************************************************
* *
* Init/Shutdown Functions *
* *
****************************************************************************/
int initObjectAltAccess( KERNEL_DATA *krnlDataPtr )
{
PRE( isWritePtr( krnlDataPtr, sizeof( KERNEL_DATA ) ) );
/* Set up the reference to the kernel data block */
krnlData = krnlDataPtr;
return( CRYPT_OK );
}
void endObjectAltAccess( void )
{
krnlData = NULL;
}
/****************************************************************************
* *
* Direct Object Access Functions *
* *
****************************************************************************/
/* Acquire/release an object */
int krnlAcquireObject( const int objectHandle, const OBJECT_TYPE type,
void **objectPtr, const int errorCode )
{
return( getObject( objectHandle, type, ACCESS_CHECK_EXTACCESS,
objectPtr, CRYPT_UNUSED, errorCode ) );
}
int krnlReleaseObject( const int objectHandle )
{
return( releaseObject( objectHandle, ACCESS_CHECK_EXTACCESS, NULL ) );
}
/* Temporarily suspend use of an object to allow other threads access, and
resume object use afterwards */
int krnlSuspendObject( const int objectHandle, int *refCount )
{
return( releaseObject( objectHandle, ACCESS_CHECK_SUSPEND, refCount ) );
}
int krnlResumeObject( const int objectHandle, const int refCount )
{
return( getObject( objectHandle,
( objectHandle == SYSTEM_OBJECT_HANDLE ) ? \
OBJECT_TYPE_DEVICE : OBJECT_TYPE_USER,
ACCESS_CHECK_SUSPEND, NULL, refCount,
CRYPT_ERROR_FAILED ) );
}
/****************************************************************************
* *
* Key Extract Functions *
* *
****************************************************************************/
/* The cryptlib equivalent of trusted downgraders in other security models:
Functions that extract a key from a context. These functions need to
bypass the kernel's security checking in order to allow key export and
are the only ones that can do this. This is an unavoidable requirement
in the complete-isolation model - some bypass mechanism needs to be
present in order to allow a key to be exported from an encryption action
object. The three functions that perform the necessary operations are:
extractKeyData: Extract a session key from a conventional/MAC context
prior to encryption with a KEK.
exportPrivateKey: Write private key data to a stream prior to encryption
with a KEK.
importPrivateKey: Read private key data from a stream after decryption
with a KEK. We use this rather than a generic
external private key load to avoid having the key
marked as an untrusted user-set key, and also because
it's easier to read the key data directly into the
context's bignum storage rather than adding indirection
via a CRYPT_PKCINFO_xxx structure */
#define PKC_CONTEXT /* Indicate that we're working with PKC context */
#if defined( INC_ALL )
#include "context.h"
#include "mech_int.h"
#else
#include "context/context.h"
#include "mechs/mech_int.h"
#endif /* Compiler-specific includes */
CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \
int extractKeyData( IN_HANDLE const CRYPT_CONTEXT iCryptContext,
OUT_BUFFER_FIXED( keyDataLen ) void *keyData,
IN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int keyDataLen,
IN_BUFFER( accessKeyLen ) const char *accessKey,
IN_LENGTH_FIXED( 7 ) const int accessKeyLen )
{
CONTEXT_INFO *contextInfoPtr;
int status;
assert( isWritePtr( keyData, keyDataLen ) );
assert( isReadPtr( accessKey, accessKeyLen ) );
REQUIRES( isHandleRangeValid( iCryptContext ) );
REQUIRES( keyDataLen >= MIN_KEYSIZE && keyDataLen < MAX_INTLENGTH_SHORT );
REQUIRES( accessKeyLen == 7 );
/* Clear return values */
memset( keyData, 0, keyDataLen );
/* Make sure that we really intended to call this function */
ENSURES( accessKeyLen == 7 && !memcmp( accessKey, "keydata", 7 ) );
/* Make sure that we've been given a conventional encryption or MAC
context with a key loaded. This has already been checked at a higher
level, but we perform a sanity check here to be safe */
status = getObject( iCryptContext, OBJECT_TYPE_CONTEXT,
ACCESS_CHECK_KEYACCESS,
( void ** ) &contextInfoPtr, CRYPT_UNUSED,
CRYPT_ARGERROR_OBJECT );
if( cryptStatusError( status ) )
return( status );
if( ( contextInfoPtr->type != CONTEXT_CONV && \
contextInfoPtr->type != CONTEXT_MAC ) || \
!( contextInfoPtr->flags & CONTEXT_FLAG_KEY_SET ) )
{
releaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );
return( CRYPT_ARGERROR_OBJECT );
}
/* Export the key data from the context */
switch( contextInfoPtr->type )
{
case CONTEXT_CONV:
if( contextInfoPtr->ctxConv->userKeyLength > keyDataLen )
{
assert( DEBUG_WARN );
status = CRYPT_ERROR_OVERFLOW;
}
else
{
memcpy( keyData, contextInfoPtr->ctxConv->userKey,
contextInfoPtr->ctxConv->userKeyLength );
}
break;
case CONTEXT_MAC:
if( contextInfoPtr->ctxMAC->userKeyLength > keyDataLen )
{
assert( DEBUG_WARN );
status = CRYPT_ERROR_OVERFLOW;
}
else
{
memcpy( keyData, contextInfoPtr->ctxMAC->userKey,
contextInfoPtr->ctxMAC->userKeyLength );
}
break;
default:
retIntError();
}
releaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );
return( status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
int exportPrivateKeyData( INOUT STREAM *stream,
IN_HANDLE const CRYPT_CONTEXT iCryptContext,
IN_ENUM( KEYFORMAT ) const KEYFORMAT_TYPE formatType,
IN_BUFFER( accessKeyLen ) const char *accessKey,
IN_LENGTH_FIXED( 11 ) const int accessKeyLen )
{
CONTEXT_INFO *contextInfoPtr;
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( accessKey, accessKeyLen ) );
REQUIRES( isHandleRangeValid( iCryptContext ) );
REQUIRES( formatType > KEYFORMAT_NONE && formatType < KEYFORMAT_LAST );
REQUIRES( accessKeyLen == 11 );
/* Make sure that we really intended to call this function */
ENSURES( accessKeyLen == 11 && !memcmp( accessKey, "private_key", 11 ) );
/* Make sure that we've been given a PKC context with a private key
loaded. This has already been checked at a higher level, but we
perform a sanity check here to be safe */
status = getObject( iCryptContext, OBJECT_TYPE_CONTEXT,
ACCESS_CHECK_KEYACCESS,
( void ** ) &contextInfoPtr, CRYPT_UNUSED,
CRYPT_ARGERROR_OBJECT );
if( cryptStatusError( status ) )
return( status );
if( contextInfoPtr->type != CONTEXT_PKC || \
!( contextInfoPtr->flags & CONTEXT_FLAG_KEY_SET ) || \
( contextInfoPtr->flags & CONTEXT_FLAG_ISPUBLICKEY ) )
{
releaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );
return( CRYPT_ARGERROR_OBJECT );
}
/* Export the key data from the context */
status = contextInfoPtr->ctxPKC->writePrivateKeyFunction( stream,
contextInfoPtr, formatType,
accessKey, accessKeyLen );
releaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );
return( status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int importPrivateKeyData( INOUT STREAM *stream,
IN_HANDLE const CRYPT_CONTEXT iCryptContext,
IN_ENUM( KEYFORMAT ) \
const KEYFORMAT_TYPE formatType )
{
CONTEXT_INFO *contextInfoPtr;
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES( isHandleRangeValid( iCryptContext ) );
REQUIRES( formatType > KEYFORMAT_NONE && formatType < KEYFORMAT_LAST );
/* Make sure that we've been given a PKC context with no private key
loaded. This has already been checked at a higher level, but we
perform a sanity check here to be safe */
status = getObject( iCryptContext, OBJECT_TYPE_CONTEXT,
ACCESS_CHECK_KEYACCESS,
( void ** ) &contextInfoPtr, CRYPT_UNUSED,
CRYPT_ARGERROR_OBJECT );
if( cryptStatusError( status ) )
return( status );
if( contextInfoPtr->type != CONTEXT_PKC || \
( contextInfoPtr->flags & CONTEXT_FLAG_KEY_SET ) || \
( contextInfoPtr->flags & CONTEXT_FLAG_ISPUBLICKEY ) )
{
releaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );
return( CRYPT_ARGERROR_OBJECT );
}
/* Import the key data into the context */
status = contextInfoPtr->ctxPKC->readPrivateKeyFunction( stream,
contextInfoPtr, formatType );
if( cryptStatusOK( status ) )
{
/* If everything went OK, perform an internal load that uses the
values already present in the context */
status = contextInfoPtr->loadKeyFunction( contextInfoPtr, NULL, 0 );
if( cryptStatusOK( status ) )
{
krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_UNUSED,
CRYPT_IATTRIBUTE_INITIALISED );
contextInfoPtr->flags |= CONTEXT_FLAG_KEY_SET;
}
else
{
/* If the problem was indicated as a function argument error,
map it to a more appropriate code */
if( cryptArgError( status ) )
status = CRYPT_ERROR_BADDATA;
}
}
releaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );
return( status );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -