📄 cryptctx.c
字号:
do
{
THREAD_SLEEP( 250 ); /* Wait 1/4s */
krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,
&status, CRYPT_IATTRIBUTE_STATUS );
}
while( status & OBJECT_FLAG_BUSY );
getCheckInternalResource( cryptContext, contextInfoPtr, OBJECT_TYPE_CONTEXT );
}
#endif /* 0 */
/* Perform any algorithm-specific shutdown */
if( ( contextInfoPtr->flags & CONTEXT_KEYINFO_INITED ) && \
capabilityInfo->endFunction != NULL )
capabilityInfo->endFunction( contextInfoPtr );
/* Perform context-type-specific cleanup */
if( contextType == CONTEXT_PKC )
{
PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
BN_clear_free( &pkcInfo->param1 );
BN_clear_free( &pkcInfo->param2 );
BN_clear_free( &pkcInfo->param3 );
BN_clear_free( &pkcInfo->param4 );
BN_clear_free( &pkcInfo->param5 );
BN_clear_free( &pkcInfo->param6 );
BN_clear_free( &pkcInfo->param7 );
BN_clear_free( &pkcInfo->param8 );
if( contextInfoPtr->flags & CONTEXT_SIDECHANNELPROTECTION )
{
BN_clear_free( &pkcInfo->blind1 );
BN_clear_free( &pkcInfo->blind2 );
}
BN_clear_free( &pkcInfo->tmp1 );
BN_clear_free( &pkcInfo->tmp2 );
BN_clear_free( &pkcInfo->tmp3 );
BN_MONT_CTX_free( &pkcInfo->montCTX1 );
BN_MONT_CTX_free( &pkcInfo->montCTX2 );
BN_MONT_CTX_free( &pkcInfo->montCTX3 );
BN_CTX_free( &pkcInfo->bnCTX );
if( pkcInfo->publicKeyInfo != NULL )
clFree( "contextMessageFunction", pkcInfo->publicKeyInfo );
}
/* Delete the object itself */
endVarStruct( contextInfoPtr, CONTEXT_INFO );
if( needsSecureMemory( contextType ) )
krnlMemfree( ( void ** ) &contextInfoPtr );
else
clFree( "contextMessageFunction", contextInfoPtr );
return( CRYPT_OK );
}
/* Process attribute get/set/delete messages */
if( isAttributeMessage( message ) )
{
if( message == MESSAGE_GETATTRIBUTE )
return( processGetAttribute( contextInfoPtr, messageDataPtr,
messageValue ) );
if( message == MESSAGE_GETATTRIBUTE_S )
return( processGetAttributeS( contextInfoPtr, messageDataPtr,
messageValue ) );
if( message == MESSAGE_SETATTRIBUTE )
return( processSetAttribute( contextInfoPtr, messageDataPtr,
messageValue ) );
if( message == MESSAGE_SETATTRIBUTE_S )
return( processSetAttributeS( contextInfoPtr, messageDataPtr,
messageValue ) );
if( message == MESSAGE_DELETEATTRIBUTE )
return( processDeleteAttribute( contextInfoPtr, messageValue ) );
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
/* Process action messages */
if( isActionMessage( message ) )
{
switch( message )
{
case MESSAGE_CTX_ENCRYPT:
assert( contextInfoPtr->encryptFunction != NULL );
if( contextInfoPtr->type == CONTEXT_CONV )
{
BYTE data[ 8 ];
assert( isStreamCipher( capabilityInfo->cryptAlgo ) || \
!needsIV( contextInfoPtr->ctxConv->mode ) ||
( contextInfoPtr->flags & CONTEXT_IV_SET ) );
if( messageValue >= 8 )
memcpy( data, messageDataPtr, 8 );
status = contextInfoPtr->encryptFunction( contextInfoPtr,
messageDataPtr, messageValue );
if( cryptStatusOK( status ) && messageValue >= 8 )
{
/* Check for a catastrophic failure of the
encryption. This check unfortunately isn't
completely foolproof for ciphers in CBC mode
because of the way the IV is applied to the
input. For the CBC encryption operation:
out = enc( in ^ IV )
if out == IV the operation turns into a no-op.
Consider the simple case where IV == in, so
IV ^ in == 0. Then out = enc( 0 ) == IV, with
the input appearing again at the output. In fact
this can occur during normal operation once every
2^32 blocks (for a 64-bit block cipher).
Although the chances of this happening are fairly
low (the collision would have to occur on the
first encrypted block in a message, since that's
the one we check), way may have to switch to
checking the first two blocks if we're using a
64-bit block cipher in CBC mode in order to
reduce false positives */
if( !memcmp( data, messageDataPtr, 8 ) )
{
zeroise( messageDataPtr, messageValue );
status = CRYPT_ERROR_FAILED;
}
zeroise( data, 8 );
}
}
else
{
BYTE data[ 8 ];
const BOOLEAN isDLP = \
isDlpAlgo( capabilityInfo->cryptAlgo );
const BOOLEAN isKeyx = \
isKeyxAlgo( capabilityInfo->cryptAlgo );
assert( contextInfoPtr->type == CONTEXT_PKC );
assert( !isDLP ||
( isKeyx && messageValue == sizeof( KEYAGREE_PARAMS ) ) || \
( !isKeyx && messageValue == sizeof( DLP_PARAMS ) ) );
if( !isKeyx )
memcpy( data, isDLP ? \
( ( DLP_PARAMS * ) messageDataPtr )->inParam1 : \
messageDataPtr, 8 );
status = contextInfoPtr->encryptFunction( contextInfoPtr,
messageDataPtr, messageValue );
if( cryptStatusOK( status ) && !isKeyx )
{
/* Check for a catastrophic failure of the
encryption */
if( isDLP )
{
DLP_PARAMS *dlpParams = \
( DLP_PARAMS * ) messageDataPtr;
if( !memcmp( data, dlpParams->outParam, 8 ) )
{
zeroise( dlpParams->outParam, \
dlpParams->outLen );
status = CRYPT_ERROR_FAILED;
}
}
else
if( !memcmp( data, messageDataPtr, 8 ) )
{
zeroise( messageDataPtr, messageValue );
status = CRYPT_ERROR_FAILED;
}
zeroise( data, 8 );
}
clearTempBignums( contextInfoPtr->ctxPKC );
}
assert( cryptStatusOK( status ) );
break;
case MESSAGE_CTX_DECRYPT:
assert( contextInfoPtr->decryptFunction != NULL );
if( contextInfoPtr->type == CONTEXT_CONV )
{
assert( isStreamCipher( capabilityInfo->cryptAlgo ) || \
!needsIV( contextInfoPtr->ctxConv->mode ) ||
( contextInfoPtr->flags & CONTEXT_IV_SET ) );
status = contextInfoPtr->decryptFunction( contextInfoPtr,
messageDataPtr, messageValue );
}
else
{
/* Make sure that we're not trying to decrypt with a
public key. The kernel doesn't know about subtypes,
so we have to perform the check at this level */
if( contextInfoPtr->flags & CONTEXT_ISPUBLICKEY )
return( CRYPT_ERROR_NOTAVAIL );
status = contextInfoPtr->decryptFunction( contextInfoPtr,
messageDataPtr, messageValue );
clearTempBignums( contextInfoPtr->ctxPKC );
}
break;
case MESSAGE_CTX_SIGN:
assert( capabilityInfo->signFunction != NULL );
/* Make sure that we're not trying to decrypt with a public
key. The kernel doesn't know about subtypes, so we have
to perform the check at this level */
if( contextInfoPtr->flags & CONTEXT_ISPUBLICKEY )
return( CRYPT_ERROR_NOTAVAIL );
status = capabilityInfo->signFunction( contextInfoPtr,
messageDataPtr, messageValue );
clearTempBignums( contextInfoPtr->ctxPKC );
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 );
/* 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 )
/* 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
contextInfoPtr->flags |= CONTEXT_HASH_DONE;
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 )
{
if( messageValue == CRYPT_IATTRIBUTE_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, reset the status
back to normal */
return( CRYPT_OK );
}
if( messageValue == CRYPT_IATTRIBUTE_LOCKED )
return( CRYPT_OK );
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
/* 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 conte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -