📄 crypt.c
字号:
messageDataPtr, messageValue );
break;
default:
assert( NOTREACHED );
}
unlockResourceExit( cryptInfoPtr, status );
}
/* Process messages which compare object properties or clone the object */
if( message == RESOURCE_MESSAGE_COMPARE )
{
const RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
assert( messageValue == RESOURCE_MESSAGE_COMPARE_HASH || \
messageValue == RESOURCE_MESSAGE_COMPARE_KEYID );
status = CRYPT_ERROR; /* Default = failed comparison */
if( messageValue == RESOURCE_MESSAGE_COMPARE_HASH )
{
const int hashSize = cryptInfoPtr->capabilityInfo->blockSize;
/* If it's a hash or MAC context, compare the hash value */
if( cryptInfoPtr->type == CONTEXT_HASH )
{
if( !cryptInfoPtr->ctxHash.done )
status = CRYPT_ERROR_INCOMPLETE;
else
if( msgData->length == hashSize && \
!memcmp( msgData->data, cryptInfoPtr->ctxHash.hash,
hashSize ) )
status = CRYPT_OK;
}
if( cryptInfoPtr->type == CONTEXT_MAC )
{
if( !cryptInfoPtr->ctxMAC.done )
status = CRYPT_ERROR_INCOMPLETE;
else
if( msgData->length == hashSize && \
!memcmp( msgData->data, cryptInfoPtr->ctxMAC.mac,
hashSize ) )
status = CRYPT_OK;
}
}
if( messageValue == RESOURCE_MESSAGE_COMPARE_KEYID )
{
/* If it's a PKC context, compare the key ID */
if( cryptInfoPtr->type == CONTEXT_PKC && \
msgData->length == KEYID_SIZE && \
!memcmp( msgData->data, cryptInfoPtr->ctxPKC.keyID,
KEYID_SIZE ) )
status = CRYPT_OK;
}
unlockResourceExit( cryptInfoPtr, status );
}
if( message == RESOURCE_MESSAGE_CLONE )
{
CRYPT_CONTEXT *iDestContext = ( CRYPT_CONTEXT * ) messageDataPtr;
int deviceObjectHandle;
*iDestContext = CRYPT_ERROR;
/* Cloning of non-native contexts is somewhat complex because we
usually can't clone a device object, so we have to detect requests
to clone these objects and increment their reference count
instead. This isn't a major problem because cryptlib always
creates native contexts for clonable algorithms, if the user
explicitly overrides this by using their own device-specific
context then the usage will usually be create, add to envelope,
destroy, so there's no need to clone the context anyway. The
only time there's a potential problem is if they override the use
of native contexts by adding device contexts to multiple envelopes,
but in that case it's assumed they'll be aware of potential
problems with this approach */
krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_GETDEPENDENT,
&deviceObjectHandle, OBJECT_TYPE_DEVICE );
if( deviceObjectHandle != SYSTEM_OBJECT_HANDLE )
{
status = krnlSendNotifier( cryptContext,
RESOURCE_IMESSAGE_INCREFCOUNT );
if( cryptStatusOK( status ) )
*iDestContext = cryptContext;
}
else
status = cloneContext( messageDataPtr, cryptContext );
unlockResourceExit( cryptInfoPtr, status );
}
/* Process messages which check a context */
if( message == RESOURCE_MESSAGE_CHECK )
{
status = checkContext( cryptInfoPtr, messageValue );
unlockResourceExit( cryptInfoPtr, status );
}
/* Process messages which lock/unlock an object for exclusive use */
if( message == RESOURCE_MESSAGE_LOCK )
/* Exit without unlocking the object. Any other threads trying to
use the object after this point will be blocked */
return( CRYPT_OK );
if( message == RESOURCE_MESSAGE_UNLOCK )
{
/* "Wenn drei Leute in ein Zimmer reingehen und fuenf kommen raus,
dann muessen erst mal zwei wieder reingehen bis das Zimmer leer
ist" */
unlockResource( cryptInfoPtr ); /* Undo RESOURCE_MESSAGE_LOCK lock */
unlockResourceExit( cryptInfoPtr, CRYPT_OK );
}
/* Process internal notification messages */
if( message == RESOURCE_MESSAGE_CHANGENOTIFY && \
messageValue == CRYPT_IATTRIBUTE_STATUS )
{
/* If the context is still busy and we're trying to reset its status
from CRYPT_ERROR_BUSY back to CRYPT_OK, set the abort flag to
indicate that the operation which is keeping it busy should be
cancelled, and return an error so that the busy status is
maintained until the context has processed the abort */
if( !cryptInfoPtr->done )
{
cryptInfoPtr->doAbort = TRUE;
status = CRYPT_ERROR_BUSY;
}
else
/* The context finished whatever it was doing, reset the status
back to normal */
status = CRYPT_OK;
unlockResourceExit( cryptInfoPtr, status );
}
/* Process object-specific messages */
if( message == RESOURCE_MESSAGE_CTX_GENKEY )
{
assert( cryptInfoPtr->type == CONTEXT_CONV || \
cryptInfoPtr->type == CONTEXT_MAC ||
cryptInfoPtr->type == CONTEXT_PKC );
assert( needsKey( cryptInfoPtr ) );
/* If it's a private key context, we need to have a key label set
before we can continue */
if( cryptInfoPtr->type == CONTEXT_PKC && !cryptInfoPtr->labelSize )
{
setErrorInfo( cryptInfoPtr, CRYPT_CTXINFO_LABEL,
CRYPT_ERRTYPE_ATTR_ABSENT );
unlockResourceExit( cryptInfoPtr, CRYPT_ERROR_NOTINITED );
}
/* Generate a new key into the context */
status = generateKey( cryptInfoPtr, messageValue );
unlockResourceExit( cryptInfoPtr, status );
}
if( message == RESOURCE_MESSAGE_CTX_GENIV )
{
BYTE buffer[ CRYPT_MAX_IVSIZE ];
assert( cryptInfoPtr->type == CONTEXT_CONV );
/* If it's not a conventional encryption context or a mode which
doesn't use an IV, the generate IV operation is meaningless */
if( !needsIV( cryptInfoPtr->ctxConv.mode ) || \
isStreamCipher ( cryptInfoPtr->capabilityInfo->cryptAlgo ) )
unlockResourceExit( cryptInfoPtr, CRYPT_ERROR_NOTAVAIL );
/* Generate a new IV and load it */
getNonce( buffer, CRYPT_MAX_IVSIZE );
cryptInfoPtr->capabilityInfo->initIVFunction( cryptInfoPtr, buffer,
CRYPT_USE_DEFAULT );
unlockResourceExit( cryptInfoPtr, CRYPT_OK );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
/* Create an encryption context based on an encryption capability template.
This is a common function called by devices to create a context once
they've got the appropriate capability template */
int createContextFromCapability( CRYPT_CONTEXT *cryptContext,
const CRYPT_USER cryptOwner,
const CAPABILITY_INFO *capabilityInfoPtr,
const int objectFlags )
{
const CRYPT_ALGO cryptAlgo = capabilityInfoPtr->cryptAlgo;
const CONTEXT_TYPE contextType = \
( ( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL ) && \
( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL ) ) ? CONTEXT_CONV : \
( ( cryptAlgo >= CRYPT_ALGO_FIRST_PKC ) && \
( cryptAlgo <= CRYPT_ALGO_LAST_PKC ) ) ? CONTEXT_PKC : \
( ( cryptAlgo >= CRYPT_ALGO_FIRST_HASH ) && \
( cryptAlgo <= CRYPT_ALGO_LAST_HASH ) ) ? CONTEXT_HASH : CONTEXT_MAC;
CRYPT_INFO *cryptInfoPtr;
const int createFlags = objectFlags | \
( needsSecureMemory( contextType ) ? \
CREATEOBJECT_FLAG_SECUREMALLOC : 0 );
int initStatus = CRYPT_OK, subType, status;
int actionFlags = 0, actionPerms = ACTION_PERM_ALL;
assert( cryptAlgo > CRYPT_ALGO_NONE && cryptAlgo < CRYPT_ALGO_LAST_MAC );
/* Clear the return values */
*cryptContext = CRYPT_ERROR;
/* Set up the initial permitted action flags */
switch( contextType )
{
case CONTEXT_CONV:
subType = SUBTYPE_CTX_CONV;
if( capabilityInfoPtr->encryptFunction != NULL || \
capabilityInfoPtr->encryptCBCFunction != NULL || \
capabilityInfoPtr->encryptCFBFunction != NULL || \
capabilityInfoPtr->encryptOFBFunction != NULL )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT,
ACTION_PERM_ALL );
if( capabilityInfoPtr->decryptFunction != NULL || \
capabilityInfoPtr->decryptCBCFunction != NULL || \
capabilityInfoPtr->decryptCFBFunction != NULL || \
capabilityInfoPtr->decryptOFBFunction != NULL )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT,
ACTION_PERM_ALL );
if( capabilityInfoPtr->generateKeyFunction != NULL )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_GENKEY,
ACTION_PERM_ALL );
break;
case CONTEXT_PKC:
subType = SUBTYPE_CTX_PKC;
if( isDlpAlgo( cryptAlgo ) )
/* The DLP-based PKC's have somewhat specialised usage
requirements so we don't allow direct access by users */
actionPerms = ACTION_PERM_NONE_EXTERNAL;
if( capabilityInfoPtr->encryptFunction != NULL )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT,
actionPerms );
if( capabilityInfoPtr->decryptFunction != NULL )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT,
actionPerms );
if( capabilityInfoPtr->signFunction != NULL )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGN,
actionPerms );
if( capabilityInfoPtr->sigCheckFunction != NULL )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGCHECK,
actionPerms );
if( capabilityInfoPtr->generateKeyFunction != NULL )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_GENKEY,
actionPerms );
break;
case CONTEXT_HASH:
subType = SUBTYPE_CTX_HASH;
actionFlags = \
MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_HASH, ACTION_PERM_ALL );
break;
case CONTEXT_MAC:
subType = SUBTYPE_CTX_MAC;
actionFlags = \
MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_HASH, ACTION_PERM_ALL );
if( capabilityInfoPtr->generateKeyFunction != NULL )
actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_GENKEY,
ACTION_PERM_ALL );
break;
}
/* Create the context and initialise the variables in it */
status = krnlCreateObject( ( void ** ) &cryptInfoPtr, cryptOwner,
OBJECT_TYPE_CONTEXT, subType,
sizeof( CRYPT_INFO ), createFlags,
actionFlags, contextMessageFunction );
if( cryptStatusError( status ) )
return( status );
initResourceLock( cryptInfoPtr );
lockResource( cryptInfoPtr );
*cryptContext = cryptInfoPtr->objectHandle = status;
cryptInfoPtr->ownerHandle = cryptOwner;
cryptInfoPtr->capabilityInfo = capabilityInfoPtr;
cryptInfoPtr->type = contextType;
if( cryptInfoPtr->type == CONTEXT_PKC && \
!( objectFlags & CREATEOBJECT_FLAG_DUMMY ) )
{
cryptInfoPtr->ctxPKC.keySizeBits = 0;
/* Initialise the bignum information */
cryptInfoPtr->ctxPKC.param1 = BN_new();
cryptInfoPtr->ctxPKC.param2 = BN_new();
cryptInfoPtr->ctxPKC.param3 = BN_new();
cryptInfoPtr->ctxPKC.param4 = BN_new();
cryptInfoPtr->ctxPKC.param5 = BN_new();
cryptInfoPtr->ctxPKC.param6 = BN_new();
cryptInfoPtr->ctxPKC.param7 = BN_new();
cryptInfoPtr->ctxPKC.param8 = BN_new();
}
if( cryptInfoPtr->type == CONTEXT_CONV )
/* Set the default encryption mode, which is always CBC if possible */
cryptInfoPtr->ctxConv.mode = isStreamCipher( cryptAlgo ) ? \
CRYPT_MODE_OFB : CRYPT_MODE_CBC;
/* Perform any algorithm-specific initialization */
if( capabilityInfoPtr->initFunction != NULL && \
!( objectFlags & CREATEOBJECT_FLAG_DUMMY ) )
{
initStatus = capabilityInfoPtr->initFunction( cryptInfoPtr );
if( cryptStatusError( initStatus ) )
/* The algorithm-specific init failed, make sure the object gets
destroyed when we notify the kernel that the setup process is
complete */
krnlSendNotifier( *cryptContext, RESOURCE_IMESSAGE_DESTROY );
}
if( cryptStatusOK( initStatus ) )
cryptInfoPtr->keyingInfoInited = TRUE;
/* We've finished setting up the object-type-specific info, tell the
kernel the object is ready for use */
unlockResource( cryptInfoPtr );
status = krnlSendMessage( *cryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
if( cryptStatusError( initStatus ) )
status = initStatus;
if( cryptStatusError( status ) )
{
*cryptContext = CRYPT_ERROR;
return( status );
}
if( cryptInfoPtr->type == CONTEXT_HASH )
/* If it's a hash context there's no explicit keygen or load so we
need to send an "object initialised" message to get the kernel to
move it into the high state. If this isn't done, any attempt to
use the context will be blocked */
krnlSendMessage( *cryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_UNUSED, CRYPT_IATTRIBUTE_INITIALISED );
return( CRYPT_OK );
}
/* Create an encryption context object */
int createContext( MESSAGE_CREATEOBJECT_INFO *createInfo,
const void *auxDataPtr, const int auxValue )
{
CRYPT_CONTEXT iCryptContext;
const CAPABILITY_INFO FAR_BSS *capabilityInfoPtr;
int status;
assert( auxDataPtr != NULL );
/* Perform basic error checking */
if( createInfo->arg1 <= CRYPT_ALGO_NONE || \
createInfo->arg1 >= CRYPT_ALGO_LAST )
return( CRYPT_ARGERROR_NUM1 );
/* Find the capability correspo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -