📄 cryptctx.c
字号:
case CAPABILITY_INFO_KEYSIZE:
return( getKeysize( varParam, constParam ) );
case CAPABILITY_INFO_STATESIZE:
return( 0 );
}
assert( NOTREACHED );
return( CRYPT_ERROR );
}
/* Clear temporary bignum values used during PKC operations */
void clearTempBignums( PKC_INFO *pkcInfo )
{
BN_clear( &pkcInfo->tmp1 );
BN_clear( &pkcInfo->tmp2 );
BN_clear( &pkcInfo->tmp3 );
BN_CTX_clear( &pkcInfo->bnCTX );
}
/* Check that a context meets the given requirements */
#define checkActionPerm( action, perms ) \
( MK_ACTION_PERM( ( action ), ACTION_PERM_ALL ) & ( perms ) )
static int checkContext( CONTEXT_INFO *contextInfoPtr,
const MESSAGE_CHECK_TYPE checkType )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
const CRYPT_ALGO_TYPE cryptAlgo = capabilityInfoPtr->cryptAlgo;
int usageCount, actionPerms, status;
/* Make sure that the object's usage count is still valid. The usage
count is a type of meta-capability that overrides all other
capabilities in that an object with an expired usage count isn't
valid for anything no matter what the available capabilities are */
status = krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_GETATTRIBUTE, &usageCount,
CRYPT_PROPERTY_USAGECOUNT );
if( cryptStatusError( status ) || \
( usageCount != CRYPT_UNUSED && usageCount <= 0 ) )
return( exitError( contextInfoPtr, CRYPT_PROPERTY_USAGECOUNT,
CRYPT_ERRTYPE_ATTR_VALUE, CRYPT_ERROR_PERMISSION ) );
/* Make sure that the object's action permissions allow the operation */
status = krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_GETATTRIBUTE, &actionPerms,
CRYPT_IATTRIBUTE_ACTIONPERMS );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_OBJECT );
/* If it's a check for a key generation capability (which is algorithm-
type independent), we check it before performing any algorithm-
specific checks */
if( checkType == MESSAGE_CHECK_KEYGEN )
{
if( contextInfoPtr->type == CONTEXT_HASH )
return( CRYPT_ERROR_NOTAVAIL ); /* No key for hash algorithms */
if( !needsKey( contextInfoPtr ) )
return( exitErrorInited( contextInfoPtr, CRYPT_CTXINFO_KEY ) );
return( ( capabilityInfoPtr->generateKeyFunction != NULL && \
!checkActionPerm( MESSAGE_CTX_GENKEY, actionPerms ) ) ? \
CRYPT_OK : CRYPT_ARGERROR_OBJECT );
}
/* Perform general checks */
if( contextInfoPtr->type != CONTEXT_HASH && needsKey( contextInfoPtr ) )
return( exitErrorNotInited( contextInfoPtr, CRYPT_CTXINFO_KEY ) );
/* Check for hash, MAC, and conventional encryption contexts */
if( checkType == MESSAGE_CHECK_HASH )
return( ( contextInfoPtr->type == CONTEXT_HASH && \
checkActionPerm( MESSAGE_CTX_HASH, actionPerms ) ) ? \
CRYPT_OK : CRYPT_ARGERROR_OBJECT );
if( checkType == MESSAGE_CHECK_MAC )
return( ( contextInfoPtr->type == CONTEXT_MAC && \
checkActionPerm( MESSAGE_CTX_HASH, actionPerms ) ) ? \
CRYPT_OK : CRYPT_ARGERROR_OBJECT );
if( checkType == MESSAGE_CHECK_CRYPT )
return( ( contextInfoPtr->type != CONTEXT_CONV && \
!checkActionPerm( MESSAGE_CTX_ENCRYPT, actionPerms ) ) ? \
CRYPT_ARGERROR_OBJECT : CRYPT_OK );
/* Make sure that it's a PKC context */
if( contextInfoPtr->type != CONTEXT_PKC )
return( CRYPT_ARGERROR_OBJECT );
if( checkType == MESSAGE_CHECK_PKC )
return( CRYPT_OK );
/* Check for key-agreement algorithms */
if( isKeyxAlgo( cryptAlgo ) )
/* DH can never be used for encryption or signatures (if it is then
we call it Elgamal) and KEA is explicitly for key agreement only.
Note that the status of DH is a bit ambiguous in that every DH key
is both a public and private key since it's a key-agreement
algorithm, in order to avoid confusion in situations where we're
checking for real private keys we always denote a DH context as
key-agreement only without taking a side about whether it's a
public or private key */
return( ( checkType == MESSAGE_CHECK_PKC_KA_EXPORT || \
checkType == MESSAGE_CHECK_PKC_KA_IMPORT ) ? \
CRYPT_OK : CRYPT_ARGERROR_OBJECT );
if( ( checkType == MESSAGE_CHECK_PKC_KA_EXPORT || \
checkType == MESSAGE_CHECK_PKC_KA_IMPORT ) )
return( CRYPT_ARGERROR_OBJECT ); /* Must be a key agreement algorithm */
/* Check that the algorithm complies and the capability is available */
switch( checkType )
{
case MESSAGE_CHECK_PKC_ENCRYPT:
if( cryptAlgo == CRYPT_ALGO_DSA )
/* Must be an encryption algorithm */
return( CRYPT_ARGERROR_OBJECT );
if( capabilityInfoPtr->encryptFunction == NULL || \
!checkActionPerm( MESSAGE_CTX_ENCRYPT, actionPerms ) )
return( CRYPT_ARGERROR_OBJECT );
break;
case MESSAGE_CHECK_PKC_DECRYPT:
if( cryptAlgo == CRYPT_ALGO_DSA )
/* Must be an encryption algorithm */
return( CRYPT_ARGERROR_OBJECT );
if( capabilityInfoPtr->decryptFunction == NULL || \
!checkActionPerm( MESSAGE_CTX_DECRYPT, actionPerms ) )
return( CRYPT_ARGERROR_OBJECT );
break;
case MESSAGE_CHECK_PKC_SIGN:
if( capabilityInfoPtr->signFunction == NULL || \
!checkActionPerm( MESSAGE_CTX_SIGN, actionPerms ) )
return( CRYPT_ARGERROR_OBJECT );
break;
case MESSAGE_CHECK_PKC_SIGCHECK:
if( capabilityInfoPtr->sigCheckFunction == NULL || \
!checkActionPerm( MESSAGE_CTX_SIGCHECK, actionPerms ) )
return( CRYPT_ARGERROR_OBJECT );
break;
case MESSAGE_CHECK_CA:
if( capabilityInfoPtr->signFunction == NULL && \
capabilityInfoPtr->sigCheckFunction == NULL )
return( CRYPT_ARGERROR_OBJECT );
if( !checkActionPerm( MESSAGE_CTX_SIGN, actionPerms ) && \
!checkActionPerm( MESSAGE_CTX_SIGCHECK, actionPerms ) )
return( CRYPT_ARGERROR_OBJECT );
}
/* Check that it's a private key if this is required */
if( ( checkType == MESSAGE_CHECK_PKC_PRIVATE || \
checkType == MESSAGE_CHECK_PKC_DECRYPT || \
checkType == MESSAGE_CHECK_PKC_SIGN ) && \
( contextInfoPtr->flags & CONTEXT_ISPUBLICKEY ) )
return( CRYPT_ARGERROR_OBJECT );
return( CRYPT_OK );
}
/****************************************************************************
* *
* Context Attribute Handling Functions *
* *
****************************************************************************/
/* Handle data sent to or read from a context */
static int processGetAttribute( CONTEXT_INFO *contextInfoPtr,
void *messageDataPtr, const int messageValue )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
const CONTEXT_TYPE contextType = contextInfoPtr->type;
int *valuePtr = ( int * ) messageDataPtr, value;
switch( messageValue )
{
case CRYPT_ATTRIBUTE_ERRORTYPE:
*valuePtr = contextInfoPtr->errorType;
return( CRYPT_OK );
case CRYPT_ATTRIBUTE_ERRORLOCUS:
*valuePtr = contextInfoPtr->errorLocus;
return( CRYPT_OK );
case CRYPT_CTXINFO_ALGO:
*valuePtr = capabilityInfoPtr->cryptAlgo;
return( CRYPT_OK );
case CRYPT_CTXINFO_MODE:
assert( contextType == CONTEXT_CONV );
*valuePtr = contextInfoPtr->ctxConv->mode;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYSIZE:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_PKC || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
value = contextInfoPtr->ctxConv->userKeyLength;
else
if( contextType == CONTEXT_MAC )
value = contextInfoPtr->ctxMAC->userKeyLength;
else
value = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );
if( !value )
/* If a key hasn't been loaded yet, we return the default
key size */
value = capabilityInfoPtr->keySize;
*valuePtr = value;
return( CRYPT_OK );
case CRYPT_CTXINFO_BLOCKSIZE:
if( contextType == CONTEXT_CONV && \
( contextInfoPtr->ctxConv->mode == CRYPT_MODE_CFB || \
contextInfoPtr->ctxConv->mode == CRYPT_MODE_OFB ) )
*valuePtr = 1; /* Block cipher in stream mode */
else
*valuePtr = capabilityInfoPtr->blockSize;
return( CRYPT_OK );
case CRYPT_CTXINFO_IVSIZE:
assert( contextType == CONTEXT_CONV );
if( !needsIV( contextInfoPtr->ctxConv->mode ) || \
isStreamCipher( capabilityInfoPtr->cryptAlgo ) )
return( CRYPT_ERROR_NOTAVAIL );
*valuePtr = capabilityInfoPtr->blockSize;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYING_ALGO:
case CRYPT_OPTION_KEYING_ALGO:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
value = contextInfoPtr->ctxConv->keySetupAlgorithm;
else
value = contextInfoPtr->ctxMAC->keySetupAlgorithm;
if( !value )
return( exitErrorNotInited( contextInfoPtr,
CRYPT_CTXINFO_KEYING_ALGO ) );
*valuePtr = value;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYING_ITERATIONS:
case CRYPT_OPTION_KEYING_ITERATIONS:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
value = contextInfoPtr->ctxConv->keySetupIterations;
else
value = contextInfoPtr->ctxMAC->keySetupIterations;
if( !value )
return( exitErrorNotInited( contextInfoPtr,
CRYPT_CTXINFO_KEYING_ITERATIONS ) );
*valuePtr = value;
return( CRYPT_OK );
case CRYPT_IATTRIBUTE_KEYFEATURES:
assert( contextType == CONTEXT_PKC );
*valuePtr = ( contextInfoPtr->flags & CONTEXT_PBO ) ? 1 : 0;
#ifdef USE_DEVICES
*valuePtr |= ( contextInfoPtr->deviceObject > 0 ) ? 2 : 0;
#endif /* USE_DEVICES */
return( CRYPT_OK );
#ifdef USE_DEVICES
case CRYPT_IATTRIBUTE_DEVICEOBJECT:
if( contextInfoPtr->deviceObject < 0 )
return( CRYPT_ERROR_NOTFOUND );
*valuePtr = ( int ) contextInfoPtr->deviceObject;
return( CRYPT_OK );
#else
case CRYPT_IATTRIBUTE_DEVICEOBJECT:
return( CRYPT_ERROR_NOTFOUND );
#endif /* USE_DEVICES */
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
static int processGetAttributeS( CONTEXT_INFO *contextInfoPtr,
void *messageDataPtr, const int messageValue )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
const CONTEXT_TYPE contextType = contextInfoPtr->type;
RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
STREAM stream;
int status;
switch( messageValue )
{
case CRYPT_CTXINFO_NAME_ALGO:
return( attributeCopy( msgData, capabilityInfoPtr->algoName,
strlen( capabilityInfoPtr->algoName ) ) );
case CRYPT_CTXINFO_NAME_MODE:
assert( contextType == CONTEXT_CONV );
switch( contextInfoPtr->ctxConv->mode )
{
case CRYPT_MODE_ECB:
return( attributeCopy( msgData, "ECB", 3 ) );
case CRYPT_MODE_CBC:
return( attributeCopy( msgData, "CBC", 3 ) );
case CRYPT_MODE_CFB:
return( attributeCopy( msgData, "CFB", 3 ) );
case CRYPT_MODE_OFB:
return( attributeCopy( msgData, "OFB", 3 ) );
}
assert( NOTREACHED );
break;
case CRYPT_CTXINFO_KEYING_SALT:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
{
if( !contextInfoPtr->ctxConv->saltLength )
return( exitErrorInited( contextInfoPtr,
CRYPT_CTXINFO_KEYING_SALT ) );
return( attributeCopy( msgData, contextInfoPtr->ctxConv->salt,
contextInfoPtr->ctxConv->saltLength ) );
}
if( !contextInfoPtr->ctxMAC->saltLength )
return( exitErrorInited( contextInfoPtr,
CRYPT_CTXINFO_KEYING_SALT ) );
return( attributeCopy( msgData, contextInfoPtr->ctxMAC->salt,
contextInfoPtr->ctxMAC->saltLength ) );
case CRYPT_CTXINFO_IV:
assert( contextType == CONTEXT_CONV );
if( !needsIV( contextInfoPtr->ctxConv->mode ) || \
isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
return( CRYPT_ERROR_NOTAVAIL );
if( !( contextInfoPtr->flags & CONTEXT_IV_SET ) )
return( exitErrorNotInited( contextInfoPtr, CRYPT_CTXINFO_IV ) );
return( attributeCopy( msgData, contextInfoPtr->ctxConv->iv,
contextInfoPtr->ctxConv->ivLength ) );
case CRYPT_CTXINFO_HASHVALUE:
assert( contextType == CONTEXT_HASH || \
contextType == CONTEXT_MAC );
if( !( contextInfoPtr->flags & CONTEXT_HASH_INITED ) )
return( CRYPT_ERROR_NOTINITED );
if( !( contextInfoPtr->flags & CONTEXT_HASH_DONE ) )
return( CRYPT_ERROR_INCOMPLETE );
return( attributeCopy( msgData, ( contextType == CONTEXT_HASH ) ? \
contextInfoPtr->ctxHash->hash : \
contextInfoPtr->ctxMAC->mac,
capabilityInfoPtr->blockSize ) );
case CRYPT_CTXINFO_LABEL:
if( !contextInfoPtr->labelSize )
return( exitErrorNotInited( contextInfoPtr,
CRYPT_CTXINFO_LABEL ) );
return( attributeCopy( msgData, contextInfoPtr->label,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -