📄 cryptctx.c
字号:
{
case MESSAGE_CTX_ENCRYPT:
status = encryptData( contextInfoPtr, messageDataPtr,
messageValue );
assert( cryptStatusOK( status ) );
break;
case MESSAGE_CTX_DECRYPT:
assert( contextInfoPtr->decryptFunction != NULL );
assert( contextInfoPtr->type == CONTEXT_PKC || \
( isStreamCipher( capabilityInfo->cryptAlgo ) || \
!needsIV( contextInfoPtr->ctxConv->mode ) ||
( contextInfoPtr->flags & CONTEXT_IV_SET ) ) );
status = contextInfoPtr->decryptFunction( contextInfoPtr,
messageDataPtr, messageValue );
if( contextInfoPtr->type == CONTEXT_PKC )
clearTempBignums( contextInfoPtr->ctxPKC );
assert( cryptStatusOK( status ) );
break;
case MESSAGE_CTX_SIGN:
assert( capabilityInfo->signFunction != NULL );
status = capabilityInfo->signFunction( contextInfoPtr,
messageDataPtr, messageValue );
clearTempBignums( contextInfoPtr->ctxPKC );
assert( cryptStatusOK( status ) );
break;
case MESSAGE_CTX_SIGCHECK:
assert( capabilityInfo->sigCheckFunction != NULL );
status = capabilityInfo->sigCheckFunction( contextInfoPtr,
messageDataPtr, messageValue );
clearTempBignums( contextInfoPtr->ctxPKC );
break;
case MESSAGE_CTX_HASH:
assert( capabilityInfo->encryptFunction != NULL );
assert( ( contextInfoPtr->type == CONTEXT_HASH && \
contextInfoPtr->ctxHash->hashInfo == \
contextInfoPtr->storage + sizeof( HASH_INFO ) ) || \
( contextInfoPtr->type == CONTEXT_MAC && \
contextInfoPtr->ctxMAC->macInfo == \
contextInfoPtr->storage + sizeof( MAC_INFO ) ) );
/* If we've already completed the hashing/MACing, we can't
continue */
if( contextInfoPtr->flags & CONTEXT_HASH_DONE )
return( CRYPT_ERROR_COMPLETE );
status = capabilityInfo->encryptFunction( contextInfoPtr,
messageDataPtr, messageValue );
if( messageValue > 0 )
/* Usually the MAC initialisation happens when we load
the key, but if we've deleted the MAC value to process
another piece of data it'll happen on-demand, so we
have to set the flag here */
contextInfoPtr->flags |= CONTEXT_HASH_INITED;
else
/* Usually a hash of zero bytes is used to wrap up an
ongoing hash operation, however it can also be the
only operation if a zero-byte string is being hashed.
To handle this we have to set the inited flag as well
as the done flag */
contextInfoPtr->flags |= CONTEXT_HASH_DONE | \
CONTEXT_HASH_INITED;
assert( cryptStatusOK( status ) );
break;
default:
assert( NOTREACHED );
}
return( status );
}
/* Process messages that compare object properties or clone the object */
if( message == MESSAGE_COMPARE )
{
const RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
assert( messageValue == MESSAGE_COMPARE_HASH || \
messageValue == MESSAGE_COMPARE_KEYID || \
messageValue == MESSAGE_COMPARE_KEYID_PGP || \
messageValue == MESSAGE_COMPARE_KEYID_OPENPGP );
switch( messageValue )
{
case MESSAGE_COMPARE_HASH:
/* If it's a hash or MAC context, compare the hash value */
if( !( contextInfoPtr->flags & CONTEXT_HASH_DONE ) )
return( CRYPT_ERROR_INCOMPLETE );
if( contextInfoPtr->type == CONTEXT_HASH && \
msgData->length == capabilityInfo->blockSize && \
!memcmp( msgData->data, contextInfoPtr->ctxHash->hash,
msgData->length ) )
return( CRYPT_OK );
if( contextInfoPtr->type == CONTEXT_MAC && \
msgData->length == capabilityInfo->blockSize && \
!memcmp( msgData->data, contextInfoPtr->ctxMAC->mac,
msgData->length ) )
return( CRYPT_OK );
break;
case MESSAGE_COMPARE_KEYID:
/* If it's a PKC context, compare the key ID */
if( contextInfoPtr->type == CONTEXT_PKC && \
msgData->length == KEYID_SIZE && \
!memcmp( msgData->data, contextInfoPtr->ctxPKC->keyID,
KEYID_SIZE ) )
return( CRYPT_OK );
break;
case MESSAGE_COMPARE_KEYID_PGP:
/* If it's a PKC context, compare the PGP key ID */
if( contextInfoPtr->type == CONTEXT_PKC && \
msgData->length == PGP_KEYID_SIZE && \
!memcmp( msgData->data, contextInfoPtr->ctxPKC->pgpKeyID,
PGP_KEYID_SIZE ) )
return( CRYPT_OK );
break;
case MESSAGE_COMPARE_KEYID_OPENPGP:
/* If it's a PKC context, compare the OpenPGP key ID */
if( contextInfoPtr->type == CONTEXT_PKC && \
contextInfoPtr->ctxPKC->openPgpKeyIDSet && \
msgData->length == PGP_KEYID_SIZE && \
!memcmp( msgData->data, contextInfoPtr->ctxPKC->openPgpKeyID,
PGP_KEYID_SIZE ) )
return( CRYPT_OK );
break;
default:
assert( NOTREACHED );
}
/* The comparison failed */
return( CRYPT_ERROR );
}
/* Process messages that check a context */
if( message == MESSAGE_CHECK )
return( checkContext( contextInfoPtr, messageValue ) );
/* Process internal notification messages */
if( message == MESSAGE_CHANGENOTIFY )
{
switch( messageValue )
{
case MESSAGE_CHANGENOTIFY_STATUS:
/* If the context is still busy and we're trying to reset
its status from CRYPT_ERROR_TIMEOUT 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( !( contextInfoPtr->flags & CONTEXT_ASYNC_DONE ) )
{
contextInfoPtr->flags |= CONTEXT_ASYNC_ABORT;
return( CRYPT_ERROR_TIMEOUT );
}
/* The context finished whatever it was doing, we're back to
normal */
break;
case MESSAGE_CHANGENOTIFY_STATE:
/* State-change reflected down from the controlling cert
object, this doesn't affect us */
break;
case MESSAGE_CHANGENOTIFY_OBJHANDLE:
assert( contextInfoPtr->type == CONTEXT_CONV || \
contextInfoPtr->type == CONTEXT_HASH || \
contextInfoPtr->type == CONTEXT_MAC );
assert( contextInfoPtr->objectHandle != \
*( ( int * ) messageDataPtr ) );
assert( contextInfoPtr->ctxConv != \
( CONV_INFO * ) contextInfoPtr->storage );
/* We've been cloned, update the object handle and internal
state pointers */
contextInfoPtr->objectHandle = *( ( int * ) messageDataPtr );
initContextStorage( contextInfoPtr,
( contextInfoPtr->type == CONTEXT_CONV ) ? \
sizeof( CONV_INFO ) : \
( contextInfoPtr->type == CONTEXT_HASH ) ? \
sizeof( HASH_INFO ) : sizeof( MAC_INFO ) );
break;
case MESSAGE_CHANGENOTIFY_OWNERHANDLE:
/* The second stage of a cloning, update the owner handle */
contextInfoPtr->ownerHandle = *( ( int * ) messageDataPtr );
break;
default:
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
return( CRYPT_OK );
}
/* Process object-specific messages */
if( message == MESSAGE_CTX_GENKEY )
{
assert( contextInfoPtr->type == CONTEXT_CONV || \
contextInfoPtr->type == CONTEXT_MAC ||
contextInfoPtr->type == CONTEXT_PKC );
assert( needsKey( contextInfoPtr ) );
/* If it's a private key context, we need to have a key label set
before we can continue */
if( contextInfoPtr->type == CONTEXT_PKC && \
contextInfoPtr->labelSize <= 0 )
{
setErrorInfo( contextInfoPtr, CRYPT_CTXINFO_LABEL,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
/* Generate a new key into the context */
status = contextInfoPtr->generateKeyFunction( contextInfoPtr,
messageValue );
if( cryptStatusOK( status ) )
/* There's now a key loaded */
contextInfoPtr->flags |= CONTEXT_KEY_SET | CONTEXT_EPHEMERAL;
else
/* If the status is OK_SPECIAL, it's an async keygen that has
begun, but that hasn't resulted in the context containing a
key yet */
if( status == OK_SPECIAL )
status = CRYPT_OK;
if( cryptStatusOK( status ) )
{
static const int actionFlags = \
MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL ) | \
MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL ) | \
MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL ) | \
MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \
MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL );
/* There's a key loaded, disable further key generation. The
kernel won't allow a keygen anyway once the object is in the
high state, but taking this additional step can't hurt */
status = krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_SETATTRIBUTE,
( void * ) &actionFlags,
CRYPT_IATTRIBUTE_ACTIONPERMS );
}
return( status );
}
if( message == MESSAGE_CTX_GENIV )
{
RESOURCE_DATA msgData;
BYTE buffer[ CRYPT_MAX_IVSIZE ];
assert( contextInfoPtr->type == CONTEXT_CONV );
/* If it's not a conventional encryption context, or a mode that
doesn't use an IV, the generate IV operation is meaningless */
if( !needsIV( contextInfoPtr->ctxConv->mode ) || \
isStreamCipher ( capabilityInfo->cryptAlgo ) )
return( CRYPT_ERROR_NOTAVAIL );
/* Generate a new IV and load it */
setMessageData( &msgData, buffer, CRYPT_MAX_IVSIZE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
if( cryptStatusOK( status ) )
status = capabilityInfo->initKeyParamsFunction( contextInfoPtr,
buffer, CRYPT_USE_DEFAULT, CRYPT_MODE_NONE );
return( status );
}
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_TYPE 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;
CONTEXT_INFO *contextInfoPtr;
BOOLEAN useSideChannelProtection;
const int createFlags = objectFlags | \
( needsSecureMemory( contextType ) ? \
CREATEOBJECT_FLAG_SECUREMALLOC : 0 );
int actionFlags = 0, actionPerms = ACTION_PERM_ALL;
int storageSize, stateStorageSize = 0, subType;
int initStatus = CRYPT_OK, status;
assert( cryptAlgo > CRYPT_ALGO_NONE && cryptAlgo < CRYPT_ALGO_LAST_MAC );
/* Clear the return values */
*cryptContext = CRYPT_ERROR;
/* Get general config information */
status = krnlSendMessage( cryptOwner, IMESSAGE_GETATTRIBUTE,
&useSideChannelProtection,
CRYPT_OPTION_MISC_SIDECHANNELPROTECTION );
if( cryptStatusError( status ) )
return( status );
/* Set up subtype-specific information */
switch( contextType )
{
case CONTEXT_CONV:
subType = SUBTYPE_CTX_CONV;
storageSize = sizeof( CONV_INFO );
stateStorageSize = \
capabilityInfoPtr->getInfoFunction( CAPABILITY_INFO_STATESIZE,
NULL, 0 );
if( capabilityInfoPtr->encryptFunction != NULL || \
capabilityInfoPtr->encryptCBCFunction != NULL || \
capabilityInfoPtr->encryptCFBFunction != NULL || \
capabilityInfoPtr->encryptOFBFunction != NULL )
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT,
ACTION_PERM_ALL );
if( capabilityInfoPtr->decryptFunction != NULL || \
capabilityInfoPtr->decryptCBCFunction != NULL || \
capabilityInfoPtr->decryptCFBFunction != NULL || \
capabilityInfoPtr->decryptOFBFunction != NULL )
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT,
ACTION_PERM_ALL );
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_GENKEY, ACTION_PERM_ALL );
break;
case CONTEXT_PKC:
subType = SUBTYPE_CTX_PKC;
storageSize = sizeof( PKC_INFO );
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( MESSAGE_CTX_ENCRYPT,
actionPerms );
if( capabilityInfoPtr->decryptFunction != NULL )
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT,
actionPerms );
if( capabilityInfoPtr->signFunction != NULL )
actionFlags |= MK_ACTION_PERM( M
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -