📄 cryptctx.c
字号:
REQUIRES( message > MESSAGE_NONE && message < MESSAGE_LAST );
REQUIRES( messageValue >= 0 && messageValue < MAX_INTLENGTH );
/* Process destroy object messages */
if( message == MESSAGE_DESTROY )
{
const CONTEXT_TYPE contextType = contextInfoPtr->type;
REQUIRES( messageDataPtr == NULL && messageValue == 0 );
/* Perform any algorithm-specific shutdown */
if( capabilityInfo->endFunction != NULL )
capabilityInfo->endFunction( contextInfoPtr );
/* Perform context-type-specific cleanup */
if( contextType == CONTEXT_PKC )
freeContextBignums( contextInfoPtr->ctxPKC,
contextInfoPtr->flags );
return( CRYPT_OK );
}
/* Process attribute get/set/delete messages */
if( isAttributeMessage( message ) )
{
REQUIRES( message == MESSAGE_GETATTRIBUTE || \
message == MESSAGE_GETATTRIBUTE_S || \
message == MESSAGE_SETATTRIBUTE || \
message == MESSAGE_SETATTRIBUTE_S || \
message == MESSAGE_DELETEATTRIBUTE );
REQUIRES( isAttribute( messageValue ) || \
isInternalAttribute( messageValue ) );
if( message == MESSAGE_GETATTRIBUTE )
return( getContextAttribute( contextInfoPtr,
( int * ) messageDataPtr,
messageValue ) );
if( message == MESSAGE_GETATTRIBUTE_S )
return( getContextAttributeS( contextInfoPtr,
( MESSAGE_DATA * ) messageDataPtr,
messageValue ) );
if( message == MESSAGE_SETATTRIBUTE )
{
/* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message
with no parameters so we don't pass it down to the attribute-
handling code */
if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
return( CRYPT_OK );
return( setContextAttribute( contextInfoPtr,
*( ( int * ) messageDataPtr ),
messageValue ) );
}
if( message == MESSAGE_SETATTRIBUTE_S )
{
const MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
return( setContextAttributeS( contextInfoPtr, msgData->data,
msgData->length, messageValue ) );
}
if( message == MESSAGE_DELETEATTRIBUTE )
return( deleteContextAttribute( contextInfoPtr, messageValue ) );
retIntError();
}
/* Process action messages */
if( isActionMessage( message ) )
{
assert( ( message == MESSAGE_CTX_HASH && \
( messageValue == 0 || \
isReadPtr( messageDataPtr, messageValue ) ) ) || \
isWritePtr( messageDataPtr, messageValue ) );
switch( message )
{
case MESSAGE_CTX_ENCRYPT:
if( contextInfoPtr->type == CONTEXT_PKC )
status = encryptDataPKC( contextInfoPtr, messageDataPtr,
messageValue );
else
status = encryptDataConv( contextInfoPtr, messageDataPtr,
messageValue );
assert( cryptStatusOK( status ) );
break;
case MESSAGE_CTX_DECRYPT:
REQUIRES( !needsKey( contextInfoPtr ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC || \
( isStreamCipher( capabilityInfo->cryptAlgo ) || \
!needsIV( contextInfoPtr->ctxConv->mode ) ||
( contextInfoPtr->flags & CONTEXT_FLAG_IV_SET ) ) );
status = contextInfoPtr->decryptFunction( contextInfoPtr,
messageDataPtr, messageValue );
if( contextInfoPtr->type == CONTEXT_PKC && \
!( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY ) )
clearTempBignums( contextInfoPtr->ctxPKC );
assert( cryptStatusOK( status ) );
break;
case MESSAGE_CTX_SIGN:
status = capabilityInfo->signFunction( contextInfoPtr,
messageDataPtr, messageValue );
if( !( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY ) )
clearTempBignums( contextInfoPtr->ctxPKC );
assert( cryptStatusOK( status ) );
break;
case MESSAGE_CTX_SIGCHECK:
status = capabilityInfo->sigCheckFunction( contextInfoPtr,
messageDataPtr, messageValue );
if( !( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY ) )
clearTempBignums( contextInfoPtr->ctxPKC );
break;
case MESSAGE_CTX_HASH:
REQUIRES( ( 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_FLAG_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_FLAG_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_FLAG_HASH_DONE | \
CONTEXT_FLAG_HASH_INITED;
}
assert( cryptStatusOK( status ) );
break;
default:
retIntError();
}
return( status );
}
/* Process messages that compare object properties or clone the object */
if( message == MESSAGE_COMPARE )
{
const MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
assert( isReadPtr( messageDataPtr, sizeof( MESSAGE_DATA ) ) );
REQUIRES( 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_FLAG_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->pgp2KeyID,
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:
retIntError();
}
/* 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_STATE:
/* State-change reflected down from the controlling certificate
object, this doesn't affect us */
break;
case MESSAGE_CHANGENOTIFY_OBJHANDLE:
{
const CRYPT_HANDLE iCryptHandle = *( ( int * ) messageDataPtr );
REQUIRES( contextInfoPtr->type == CONTEXT_CONV || \
contextInfoPtr->type == CONTEXT_HASH || \
contextInfoPtr->type == CONTEXT_MAC );
REQUIRES( contextInfoPtr->objectHandle != iCryptHandle );
REQUIRES( contextInfoPtr->ctxConv != \
( CONV_INFO * ) contextInfoPtr->storage );
/* We've been cloned, update the object handle and internal
state pointers */
contextInfoPtr->objectHandle = iCryptHandle;
status = initContextStorage( contextInfoPtr,
( contextInfoPtr->type == CONTEXT_CONV ) ? \
sizeof( CONV_INFO ) : \
( contextInfoPtr->type == CONTEXT_HASH ) ? \
sizeof( HASH_INFO ) : sizeof( MAC_INFO ) );
if( cryptStatusError( status ) )
return( status );
break;
}
case MESSAGE_CHANGENOTIFY_OWNERHANDLE:
/* The second stage of a cloning, update the owner handle */
contextInfoPtr->ownerHandle = *( ( int * ) messageDataPtr );
break;
default:
retIntError();
}
return( CRYPT_OK );
}
/* Process object-specific messages */
if( message == MESSAGE_CTX_GENKEY )
{
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 );
REQUIRES( contextInfoPtr->type == CONTEXT_CONV || \
contextInfoPtr->type == CONTEXT_MAC ||
contextInfoPtr->type == CONTEXT_PKC );
REQUIRES( needsKey( contextInfoPtr ) );
/* If it's a private key context or a persistent context we need to
have a key label set before we can continue */
if( ( ( contextInfoPtr->type == CONTEXT_PKC ) || \
( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT ) ) && \
contextInfoPtr->labelSize <= 0 )
return( CRYPT_ERROR_NOTINITED );
/* Generate a new key into the context */
status = contextInfoPtr->generateKeyFunction( contextInfoPtr );
if( cryptStatusError( status ) )
return( status );
/* There's now a key loaded, remember this and 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 */
contextInfoPtr->flags |= CONTEXT_FLAG_KEY_SET;
return( krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_SETATTRIBUTE,
( void * ) &actionFlags,
CRYPT_IATTRIBUTE_ACTIONPERMS ) );
}
if( message == MESSAGE_CTX_GENIV )
{
MESSAGE_DATA msgData;
BYTE iv[ CRYPT_MAX_IVSIZE + 8 ];
const int ivSize = capabilityInfo->blockSize;
REQUIRES( contextInfoPtr->type == CONTEXT_CONV );
/* If it's not a conventional encryption context or it's a mode that
doesn't use an IV then the generate IV operation is meaningless */
if( !needsIV( contextInfoPtr->ctxConv->mode ) || \
isStreamCipher( capabilityInfo->cryptAlgo ) )
return( CRYPT_ERROR_NOTAVAIL );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -