📄 crypt.c
字号:
krnlSendNotifier( *iDestContext, RESOURCE_IMESSAGE_DESTROY );
}
if( cryptStatusError( status ) )
{
*iDestContext = CRYPT_ERROR;
return( status );
}
return( CRYPT_OK );
}
/* Checks that a context meets the given requirements */
static int checkContext( CRYPT_INFO *cryptInfoPtr,
const RESOURCE_MESSAGE_CHECK_TYPE checkType )
{
const CAPABILITY_INFO *capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
const CRYPT_ALGO cryptAlgo = capabilityInfoPtr->cryptAlgo;
int usageCount, status;
/* Make sure that the object's usage count is still valid. The usage
count is a type of meta-capability which 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( cryptInfoPtr->objectHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE,
&usageCount, CRYPT_PROPERTY_USAGECOUNT );
if( cryptStatusError( status ) || \
( usageCount != CRYPT_UNUSED && usageCount <= 0 ) )
return( CRYPT_ERROR_PERMISSION );
/* 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 == RESOURCE_MESSAGE_CHECK_KEYGEN )
{
if( cryptInfoPtr->type == CONTEXT_HASH )
return( CRYPT_ERROR_NOTAVAIL ); /* No key for hash algorithms */
if( !needsKey( cryptInfoPtr ) )
{
setErrorInfo( cryptInfoPtr, CRYPT_CTXINFO_KEY,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
return( ( capabilityInfoPtr->generateKeyFunction != NULL ) ? \
CRYPT_OK : CRYPT_ARGERROR_OBJECT );
}
/* Perform general checks */
if( needsKey( cryptInfoPtr ) )
{
setErrorInfo( cryptInfoPtr, CRYPT_CTXINFO_KEY,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
/* Check for hash, MAC, and conventional encryption contexts */
if( checkType == RESOURCE_MESSAGE_CHECK_HASH )
return( ( cryptInfoPtr->type == CONTEXT_HASH ) ? \
CRYPT_OK : CRYPT_ARGERROR_OBJECT );
if( checkType == RESOURCE_MESSAGE_CHECK_MAC )
return( ( cryptInfoPtr->type == CONTEXT_MAC ) ? \
CRYPT_OK : CRYPT_ARGERROR_OBJECT );
if( checkType == RESOURCE_MESSAGE_CHECK_CRYPT )
return( ( cryptInfoPtr->type != CONTEXT_CONV ) ? \
CRYPT_ARGERROR_OBJECT : CRYPT_OK );
/* Make sure it's a PKC context */
if( cryptInfoPtr->type != CONTEXT_PKC )
return( CRYPT_ARGERROR_OBJECT );
if( checkType == RESOURCE_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 */
return( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_PRIVATE || \
checkType == RESOURCE_MESSAGE_CHECK_PKC_KA_EXPORT || \
checkType == RESOURCE_MESSAGE_CHECK_PKC_KA_IMPORT ) ? \
CRYPT_OK : CRYPT_ARGERROR_OBJECT );
if( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_KA_EXPORT || \
checkType == RESOURCE_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 */
if( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT || \
checkType == RESOURCE_MESSAGE_CHECK_PKC_DECRYPT ) && \
cryptAlgo == CRYPT_ALGO_DSA )
return( CRYPT_ARGERROR_OBJECT ); /* Must be an encryption algorithm */
if( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT && \
capabilityInfoPtr->encryptFunction == NULL ) || \
( checkType == RESOURCE_MESSAGE_CHECK_PKC_DECRYPT && \
capabilityInfoPtr->decryptFunction == NULL ) || \
( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_SIGN || \
checkType == RESOURCE_MESSAGE_CHECK_CA ) && \
capabilityInfoPtr->signFunction == NULL ) || \
( checkType == RESOURCE_MESSAGE_CHECK_PKC_SIGCHECK && \
capabilityInfoPtr->sigCheckFunction == NULL ) )
return( CRYPT_ARGERROR_OBJECT ); /* Capability not supported */
/* Check that it's a private key if this is required */
if( ( checkType == RESOURCE_MESSAGE_CHECK_PKC_PRIVATE || \
checkType == RESOURCE_MESSAGE_CHECK_PKC_DECRYPT || \
checkType == RESOURCE_MESSAGE_CHECK_PKC_SIGN || \
checkType == RESOURCE_MESSAGE_CHECK_CA ) && \
cryptInfoPtr->ctxPKC.isPublicKey )
return( CRYPT_ARGERROR_OBJECT );
return( CRYPT_OK );
}
/* Handle data sent to or read from a context */
static int exitNotInited( CRYPT_INFO *cryptInfoPtr,
const CRYPT_ATTRIBUTE_TYPE errorLocus )
{
setErrorInfo( cryptInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
static int processGetAttribute( CRYPT_INFO *cryptInfoPtr,
void *messageDataPtr, const int messageValue )
{
const CAPABILITY_INFO *capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
const CONTEXT_TYPE contextType = cryptInfoPtr->type;
int *valuePtr = ( int * ) messageDataPtr, value;
switch( messageValue )
{
case CRYPT_ATTRIBUTE_ERRORTYPE:
*valuePtr = cryptInfoPtr->errorType;
return( CRYPT_OK );
case CRYPT_ATTRIBUTE_ERRORLOCUS:
*valuePtr = cryptInfoPtr->errorLocus;
return( CRYPT_OK );
case CRYPT_CTXINFO_ALGO:
*valuePtr = capabilityInfoPtr->cryptAlgo;
return( CRYPT_OK );
case CRYPT_CTXINFO_MODE:
assert( contextType == CONTEXT_CONV );
*valuePtr = cryptInfoPtr->ctxConv.mode;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYSIZE:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_PKC || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
value = cryptInfoPtr->ctxConv.userKeyLength;
else
if( contextType == CONTEXT_MAC )
value = cryptInfoPtr->ctxMAC.userKeyLength;
else
value = bitsToBytes( cryptInfoPtr->ctxPKC.keySizeBits );
if( !value )
/* If a key hasn't been loaded yet, we return the default
key size */
value = cryptInfoPtr->capabilityInfo->keySize;
*valuePtr = value;
return( CRYPT_OK );
case CRYPT_CTXINFO_BLOCKSIZE:
if( contextType == CONTEXT_CONV && \
( cryptInfoPtr->ctxConv.mode == CRYPT_MODE_CFB || \
cryptInfoPtr->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( cryptInfoPtr->ctxConv.mode ) || \
isStreamCipher( cryptInfoPtr->capabilityInfo->cryptAlgo ) )
return( CRYPT_ERROR_NOTAVAIL );
*valuePtr = capabilityInfoPtr->blockSize;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYING_ALGO:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
value = cryptInfoPtr->ctxConv.keySetupAlgorithm;
else
value = cryptInfoPtr->ctxMAC.keySetupAlgorithm;
if( !value )
return( exitNotInited( cryptInfoPtr,
CRYPT_CTXINFO_KEYING_ALGO ) );
*valuePtr = value;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYING_ITERATIONS:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
value = cryptInfoPtr->ctxConv.keySetupIterations;
else
value = cryptInfoPtr->ctxMAC.keySetupIterations;
if( !value )
return( exitNotInited( cryptInfoPtr,
CRYPT_CTXINFO_KEYING_ITERATIONS ) );
*valuePtr = value;
return( CRYPT_OK );
case CRYPT_IATTRIBUTE_DEVICEOBJECT:
*valuePtr = ( int ) cryptInfoPtr->deviceObject;
return( CRYPT_OK );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
static int processGetAttributeS( CRYPT_INFO *cryptInfoPtr,
void *messageDataPtr, const int messageValue )
{
const CAPABILITY_INFO *capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
const CONTEXT_TYPE contextType = cryptInfoPtr->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( cryptInfoPtr->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 );
case CRYPT_CTXINFO_KEYING_SALT:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
{
if( !cryptInfoPtr->ctxConv.saltLength )
return( exitNotInited( cryptInfoPtr,
CRYPT_CTXINFO_KEYING_SALT ) );
return( attributeCopy( msgData, cryptInfoPtr->ctxConv.salt,
cryptInfoPtr->ctxConv.saltLength ) );
}
if( !cryptInfoPtr->ctxMAC.saltLength )
return( exitNotInited( cryptInfoPtr,
CRYPT_CTXINFO_KEYING_SALT ) );
return( attributeCopy( msgData, cryptInfoPtr->ctxMAC.salt,
cryptInfoPtr->ctxMAC.saltLength ) );
case CRYPT_CTXINFO_IV:
assert( contextType == CONTEXT_CONV );
if( !needsIV( cryptInfoPtr->ctxConv.mode ) || \
isStreamCipher( cryptInfoPtr->capabilityInfo->cryptAlgo ) )
return( CRYPT_ERROR_NOTAVAIL );
if( !cryptInfoPtr->ctxConv.ivSet )
return( exitNotInited( cryptInfoPtr, CRYPT_CTXINFO_IV ) );
return( attributeCopy( msgData, cryptInfoPtr->ctxConv.iv,
cryptInfoPtr->ctxConv.ivLength ) );
case CRYPT_CTXINFO_HASHVALUE:
assert( contextType == CONTEXT_HASH || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_HASH )
{
if( !cryptInfoPtr->ctxHash.done )
return( CRYPT_ERROR_INCOMPLETE );
return( attributeCopy( msgData, cryptInfoPtr->ctxHash.hash,
capabilityInfoPtr->blockSize ) );
}
if( !cryptInfoPtr->ctxMAC.done )
return( CRYPT_ERROR_INCOMPLETE );
return( attributeCopy( msgData, cryptInfoPtr->ctxMAC.mac,
capabilityInfoPtr->blockSize ) );
case CRYPT_CTXINFO_LABEL:
if( !cryptInfoPtr->labelSize )
return( exitNotInited( cryptInfoPtr, CRYPT_CTXINFO_LABEL ) );
return( attributeCopy( msgData, cryptInfoPtr->label,
cryptInfoPtr->labelSize ) );
case CRYPT_IATTRIBUTE_KEYID:
assert( contextType == CONTEXT_PKC );
return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.keyID,
KEYID_SIZE ) );
case CRYPT_IATTRIBUTE_PGP_KEYID:
assert( contextType == CONTEXT_PKC );
if( cryptInfoPtr->capabilityInfo->cryptAlgo != CRYPT_ALGO_RSA )
return( CRYPT_ERROR_NOTFOUND );
return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.pgpKeyID,
PGP_KEYID_SIZE ) );
case CRYPT_IATTRIBUTE_OPENPGP_KEYID:
assert( contextType == CONTEXT_PKC );
assert( cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA || \
cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \
cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL );
return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.openPGPKeyID,
PGP_KEYID_SIZE ) );
case CRYPT_IATTRIBUTE_DOMAINPARAMS:
assert( contextType == CONTEXT_PKC );
return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.domainParamPtr,
cryptInfoPtr->ctxPKC.domainParamSize ) );
case CRYPT_IATTRIBUTE_PUBLICVALUE:
assert( contextType == CONTEXT_PKC );
return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.publicValuePtr,
cryptInfoPtr->ctxPKC.publicValueSize ) );
case CRYPT_IATTRIBUTE_PUBLICKEY:
assert( contextType == CONTEXT_PKC );
assert( cryptInfoPtr->ctxPKC.keySet );
if( cryptInfoPtr->ctxPKC.publicKeyInfo != NULL )
/* If the data is available in pre-encoded form, copy it
out */
return( attributeCopy( msgData, cryptInfoPtr->ctxPKC.publicKeyInfo,
cryptInfoPtr->ctxPKC.publicKeyInfoSize ) );
/* Write the public key info to the message buffer */
sMemOpen( &stream, msgData->data, msgData->length );
status = writePublicKey( &stream, cryptInfoPtr );
if( cryptStatusOK( status ) )
msgData->length = stell( &stream );
sMemDisconnect( &stream );
return( status );
case CRYPT_IATTRIBUTE_SSH1_PUBLICKEY:
assert( contextType == CONTEXT_PKC );
/* Write the SSHv1-format key data from the context */
sMemOpen( &stream, msgData->data, msgData->length );
status = writeSsh1PublicKey( &stream, cryptInfoPtr );
if( cryptStatusOK( status ) )
msgData->length = stell( &stream );
sMemDisconnect( &stream );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -