📄 cryptctx.c
字号:
return( status );
#ifndef USE_FIPS140
case CRYPT_CTXINFO_KEY_COMPONENTS:
assert( contextType == CONTEXT_PKC );
assert( needsKey( contextInfoPtr ) );
assert( msgData->length == sizeof( CRYPT_PKCINFO_RSA ) || \
msgData->length == sizeof( CRYPT_PKCINFO_DLP ) );
/* We need to have a key label set before we can continue */
if( !contextInfoPtr->labelSize )
return( exitErrorNotInited( contextInfoPtr,
CRYPT_CTXINFO_LABEL ) );
/* Load the key into the context */
status = contextInfoPtr->loadKeyFunction( contextInfoPtr,
msgData->data, msgData->length );
if( cryptStatusOK( status ) )
contextInfoPtr->flags |= CONTEXT_KEY_SET | CONTEXT_EPHEMERAL | \
CONTEXT_PBO;
return( status );
#endif /* USE_FIPS140 */
case CRYPT_CTXINFO_IV:
assert( contextType == CONTEXT_CONV );
/* If it's a mode that doesn't use an IV, the load IV operation
is meaningless */
if( !needsIV( contextInfoPtr->ctxConv->mode ) || \
isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
return( CRYPT_ERROR_NOTAVAIL );
/* Make sure that the data size is valid */
if( msgData->length != capabilityInfoPtr->blockSize )
return( CRYPT_ARGERROR_NUM1 );
/* Load the IV */
assert( capabilityInfoPtr->initKeyParamsFunction != NULL );
return( capabilityInfoPtr->initKeyParamsFunction( contextInfoPtr,
msgData->data, msgData->length, CRYPT_UNUSED ) );
case CRYPT_CTXINFO_LABEL:
if( contextInfoPtr->labelSize )
return( exitErrorInited( contextInfoPtr,
CRYPT_CTXINFO_LABEL ) );
/* Check any device object the context is associated with to
make sure that nothing with that label already exists in the
device. The semantics for keysets are somewhat different,
the check for duplicates is performed when the context is
explicitly added to the keyset but with devices the context
is implicitly created within the device at some future point
that depends on the device (at context creation, on key load/
generation, or at some other point). Because of this we
perform a pre-emptive check for duplicates to avoid a
potentially confusing error condition at some point in the
future. In addition, we can't send the message to the context
because the kernel won't forward this message type (sending a
get-key message to a context doesn't make sense) so we have to
explicitly get the dependent device and send the get-key
directly to it */
if( contextType == CONTEXT_PKC )
{
CRYPT_HANDLE cryptHandle;
status = krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_GETDEPENDENT,
&cryptHandle, OBJECT_TYPE_DEVICE );
if( cryptStatusOK( status ) )
{
MESSAGE_KEYMGMT_INFO getkeyInfo;
setMessageKeymgmtInfo( &getkeyInfo,
CRYPT_KEYID_NAME, msgData->data,
msgData->length, NULL, 0,
KEYMGMT_FLAG_CHECK_ONLY );
status = krnlSendMessage( contextInfoPtr->objectHandle,
MESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PUBLICKEY );
if( cryptStatusError( status ) )
{
setMessageKeymgmtInfo( &getkeyInfo,
CRYPT_KEYID_NAME, msgData->data,
msgData->length, NULL, 0,
KEYMGMT_FLAG_CHECK_ONLY );
status = krnlSendMessage( contextInfoPtr->objectHandle,
MESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PRIVATEKEY );
}
if( cryptStatusOK( status ) )
/* We found something with this label already
present, we can't use it again */
return( CRYPT_ERROR_DUPLICATE );
}
}
/* Set the label */
memcpy( contextInfoPtr->label, msgData->data, msgData->length );
contextInfoPtr->labelSize = msgData->length;
return( CRYPT_OK );
case CRYPT_IATTRIBUTE_KEYID_OPENPGP:
assert( contextType == CONTEXT_PKC );
assert( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA || \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \
contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL );
assert( msgData->length == PGP_KEYID_SIZE );
memcpy( contextInfoPtr->ctxPKC->openPgpKeyID, msgData->data,
msgData->length );
contextInfoPtr->ctxPKC->openPgpKeyIDSet = TRUE;
return( CRYPT_OK );
case CRYPT_IATTRIBUTE_KEY_SPKI:
assert( contextType == CONTEXT_PKC );
/* If the keys are held externally (e.g. in a crypto device),
copy the data in and set up any other information that we may
need from it. This information is used when loading a
context from a key contained in a device, where the actual
key components aren't directly available in the context but
may be needed in the future for things like cert requests */
if( contextInfoPtr->flags & CONTEXT_DUMMY )
{
if( ( contextInfoPtr->ctxPKC->publicKeyInfo = \
clAlloc( "processSetAttributeS", \
msgData->length ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memcpy( contextInfoPtr->ctxPKC->publicKeyInfo, msgData->data,
msgData->length );
contextInfoPtr->ctxPKC->publicKeyInfoSize = msgData->length;
return( calculateKeyID( contextInfoPtr ) );
}
/* Drop through */
case CRYPT_IATTRIBUTE_KEY_SSH1:
case CRYPT_IATTRIBUTE_KEY_SSH2:
case CRYPT_IATTRIBUTE_KEY_PGP:
case CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL:
case CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL:
{
static const int actionFlags = \
MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
static const int actionFlagsDH = ACTION_PERM_NONE_EXTERNAL_ALL;
static const int actionFlagsPGP = \
MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \
MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
STREAM stream;
assert( contextType == CONTEXT_PKC );
/* Read the appropriately-formatted key data into the context,
applying a lowest-common-denominator set of usage flags to
the loaded key (more specific usage restrictions will be set
by higher-level code) */
sMemConnect( &stream, msgData->data, msgData->length );
status = contextInfoPtr->ctxPKC->readPublicKeyFunction( &stream,
contextInfoPtr,
( messageValue == CRYPT_IATTRIBUTE_KEY_SPKI || \
messageValue == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL ) ? \
KEYFORMAT_CERT : \
( messageValue == CRYPT_IATTRIBUTE_KEY_SSH1 ) ? \
KEYFORMAT_SSH1 : \
( messageValue == CRYPT_IATTRIBUTE_KEY_SSH2 ) ? \
KEYFORMAT_SSH2 : KEYFORMAT_PGP );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
return( status );
/* If it's a partial load of the public portions of a private
key with further key component operations to follow, there's
nothing more to do at this point and we're done */
if( messageValue == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL || \
messageValue == CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL )
return( calculateKeyID( contextInfoPtr ) );
/* Perform an internal load that uses the key component values
that we've just read into the context */
contextInfoPtr->flags |= CONTEXT_ISPUBLICKEY;
status = contextInfoPtr->loadKeyFunction( contextInfoPtr, NULL, 0 );
if( cryptStatusError( status ) )
/* Map the status to a more appropriate code if necessary */
return( cryptArgError( status ) ? \
CRYPT_ERROR_BADDATA : status );
contextInfoPtr->flags |= CONTEXT_KEY_SET;
/* Restrict the key usage to public-key-only actions if
necessary. For PGP key loads (which, apart from the
restrictions specified with the stored key data aren't
constrained by the presence of ACLs in the form of certs) we
allow external usage, for DH (whose keys can be both public
and private keys even though technically it's a public key)
we allow both encryption and decryption usage, and for public
keys read from certs we allow internal usage only */
status = krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_SETATTRIBUTE,
( messageValue == CRYPT_IATTRIBUTE_KEY_PGP ) ? \
( void * ) &actionFlagsPGP : \
( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH ) ? \
( void * ) &actionFlagsDH : \
( void * ) &actionFlags,
CRYPT_IATTRIBUTE_ACTIONPERMS );
if( cryptStatusError( status ) )
return( status );
contextInfoPtr->flags |= CONTEXT_KEY_SET;
return( calculateKeyID( contextInfoPtr ) );
}
case CRYPT_IATTRIBUTE_PGPVALIDITY:
assert( contextType == CONTEXT_PKC );
contextInfoPtr->ctxPKC->pgpCreationTime = \
*( ( time_t * ) msgData->data );
return( CRYPT_OK );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
static int processDeleteAttribute( CONTEXT_INFO *contextInfoPtr,
const int messageValue )
{
const CONTEXT_TYPE contextType = contextInfoPtr->type;
switch( messageValue )
{
case CRYPT_CTXINFO_KEYING_ALGO:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
{
if( contextInfoPtr->ctxConv->keySetupAlgorithm == CRYPT_ALGO_NONE )
return( exitErrorNotFound( contextInfoPtr,
CRYPT_CTXINFO_KEYING_ALGO ) );
contextInfoPtr->ctxConv->keySetupAlgorithm = CRYPT_ALGO_NONE;
return( CRYPT_OK );
}
if( !contextInfoPtr->ctxMAC->keySetupAlgorithm )
return( exitErrorNotFound( contextInfoPtr,
CRYPT_CTXINFO_KEYING_ALGO ) );
contextInfoPtr->ctxMAC->keySetupAlgorithm = CRYPT_ALGO_NONE;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYING_ITERATIONS:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
{
if( !contextInfoPtr->ctxConv->keySetupIterations )
return( exitErrorNotFound( contextInfoPtr,
CRYPT_CTXINFO_KEYING_ITERATIONS ) );
contextInfoPtr->ctxConv->keySetupIterations = 0;
return( CRYPT_OK );
}
if( !contextInfoPtr->ctxMAC->keySetupIterations )
return( exitErrorNotFound( contextInfoPtr,
CRYPT_CTXINFO_KEYING_ITERATIONS ) );
contextInfoPtr->ctxMAC->keySetupIterations = 0;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYING_SALT:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
{
if( !contextInfoPtr->ctxConv->saltLength )
return( exitErrorNotFound( contextInfoPtr,
CRYPT_CTXINFO_KEYING_SALT ) );
zeroise( contextInfoPtr->ctxConv->salt, CRYPT_MAX_HASHSIZE );
contextInfoPtr->ctxConv->saltLength = 0;
return( CRYPT_OK );
}
if( !contextInfoPtr->ctxMAC->saltLength )
return( exitErrorNotFound( contextInfoPtr,
CRYPT_CTXINFO_KEYING_SALT ) );
zeroise( contextInfoPtr->ctxMAC->salt, CRYPT_MAX_HASHSIZE );
contextInfoPtr->ctxMAC->saltLength = 0;
return( CRYPT_OK );
case CRYPT_CTXINFO_IV:
assert( contextType == CONTEXT_CONV );
if( !needsIV( contextInfoPtr->ctxConv->mode ) || \
isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
return( exitErrorNotFound( contextInfoPtr,
CRYPT_CTXINFO_IV ) );
contextInfoPtr->ctxConv->ivLength = \
contextInfoPtr->ctxConv->ivCount = 0;
contextInfoPtr->flags &= ~CONTEXT_IV_SET;
return( CRYPT_OK );
case CRYPT_CTXINFO_LABEL:
if( !contextInfoPtr->labelSize )
return( exitErrorNotFound( contextInfoPtr,
CRYPT_CTXINFO_LABEL ) );
zeroise( contextInfoPtr->label, contextInfoPtr->labelSize );
contextInfoPtr->labelSize = 0;
return( CRYPT_OK );
case CRYPT_CTXINFO_HASHVALUE:
assert( contextType == CONTEXT_HASH || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_HASH )
zeroise( contextInfoPtr->ctxHash->hash, CRYPT_MAX_HASHSIZE );
else
zeroise( contextInfoPtr->ctxMAC->mac, CRYPT_MAX_HASHSIZE );
contextInfoPtr->flags &= ~( CONTEXT_HASH_INITED | \
CONTEXT_HASH_DONE );
return( CRYPT_OK );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
/****************************************************************************
* *
* Context Message Handler *
* *
****************************************************************************/
/* Handle a message sent to an encryption context */
static int contextMessageFunction( const void *objectInfoPtr,
const MESSAGE_TYPE message,
void *messageDataPtr,
const int messageValue )
{
CONTEXT_INFO *contextInfoPtr = ( CONTEXT_INFO * ) objectInfoPtr;
const CAPABILITY_INFO *capabilityInfo = contextInfoPtr->capabilityInfo;
int status;
/* Process destroy object messages */
if( message == MESSAGE_DESTROY )
{
const CONTEXT_TYPE contextType = contextInfoPtr->type;
#if 0 /* 9/12/02 We can never get here because we can't send a message to a
busy object any more */
/* If the context is busy, abort the async.operation. We do this by
setting the abort flag (which is OK, since the context is about to
be destroyed anyway) and then waiting for the busy flag to be
cleared */
contextInfoPtr->flags |= CONTEXT_ASYNC_ABORT;
krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE, &status,
CRYPT_IATTRIBUTE_STATUS );
if( status & OBJECT_FLAG_BUSY )
{
/* Unlock the object so the background thread can access it.
Nothing else will get in because the object is in the
signalled state */
unlockResource( contextInfoPtr );
/* Wait awhile and check whether we've left the busy state */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -