📄 crypt.c
字号:
return( status );
case CRYPT_IATTRIBUTE_SSH2_PUBLICKEY:
assert( contextType == CONTEXT_PKC );
/* Write the SSHv2-format key data from the context */
sMemOpen( &stream, msgData->data, msgData->length );
status = writeSsh2PublicKey( &stream, cryptInfoPtr );
if( cryptStatusOK( status ) )
msgData->length = stell( &stream );
sMemDisconnect( &stream );
return( status );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
static int processSetAttribute( CRYPT_INFO *cryptInfoPtr,
void *messageDataPtr, const int messageValue )
{
const CAPABILITY_INFO *capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
const CONTEXT_TYPE contextType = cryptInfoPtr->type;
const int *valuePtr = ( int * ) messageDataPtr;
int ( *cryptFunction )( CRYPT_INFO *cryptInfoPtr, void *buffer,
int length ) = NULL;
int status;
switch( messageValue )
{
case CRYPT_CTXINFO_MODE:
assert( contextType == CONTEXT_CONV );
switch( *valuePtr )
{
case CRYPT_MODE_ECB:
cryptFunction = capabilityInfoPtr->encryptFunction;
break;
case CRYPT_MODE_CBC:
cryptFunction = capabilityInfoPtr->encryptCBCFunction;
break;
case CRYPT_MODE_CFB:
cryptFunction = capabilityInfoPtr->encryptCFBFunction;
break;
case CRYPT_MODE_OFB:
cryptFunction = capabilityInfoPtr->encryptOFBFunction;
break;
default:
assert( NOTREACHED );
}
if( cryptFunction == NULL )
return( CRYPT_ERROR_NOTAVAIL );
cryptInfoPtr->ctxConv.mode = *valuePtr;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYSIZE:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_PKC || \
contextType == CONTEXT_MAC );
/* Trim the user-supplied value to the correct shape, taking
into account various issues such as limitations with the
underlying crypto code/hardware and the (in)ability to export
overly long keys with short public keys */
status = getOptimalKeysize( cryptInfoPtr, *valuePtr );
if( cryptStatusError( status ) )
return( status );
if( contextType == CONTEXT_CONV )
cryptInfoPtr->ctxConv.userKeyLength = status;
else
if( contextType == CONTEXT_MAC )
cryptInfoPtr->ctxMAC.userKeyLength = status;
else
cryptInfoPtr->ctxPKC.keySizeBits = bytesToBits( status );
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYING_ALGO:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
cryptInfoPtr->ctxConv.keySetupAlgorithm = *valuePtr;
else
cryptInfoPtr->ctxMAC.keySetupAlgorithm = *valuePtr;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYING_ITERATIONS:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
cryptInfoPtr->ctxConv.keySetupIterations = *valuePtr;
else
cryptInfoPtr->ctxMAC.keySetupIterations = *valuePtr;
return( CRYPT_OK );
case CRYPT_IATTRIBUTE_INITIALISED:
return( CRYPT_OK );
case CRYPT_IATTRIBUTE_KEYSIZE:
if( contextType == CONTEXT_CONV )
{
cryptInfoPtr->ctxConv.keySet = TRUE;
cryptInfoPtr->ctxConv.keyLength = *valuePtr;
return( CRYPT_OK );
}
if( contextType == CONTEXT_PKC )
{
if( !cryptInfoPtr->labelSize )
/* PKC context must have a key label set */
return( exitNotInited( cryptInfoPtr,
CRYPT_CTXINFO_LABEL ) );
cryptInfoPtr->ctxPKC.keySet = TRUE;
cryptInfoPtr->ctxPKC.keySizeBits = bytesToBits( *valuePtr );
return( CRYPT_OK );
}
if( contextType == CONTEXT_MAC )
{
cryptInfoPtr->ctxMAC.keySet = TRUE;
cryptInfoPtr->ctxMAC.userKeyLength = *valuePtr;
return( CRYPT_OK );
}
assert( NOTREACHED );
case CRYPT_IATTRIBUTE_DEVICEOBJECT:
cryptInfoPtr->deviceObject = *valuePtr;
return( CRYPT_OK );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
static int processSetAttributeS( CRYPT_INFO *cryptInfoPtr,
void *messageDataPtr, const int messageValue )
{
const CAPABILITY_INFO *capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
const CONTEXT_TYPE contextType = cryptInfoPtr->type;
const RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
MECHANISM_DERIVE_INFO mechanismInfo;
STREAM stream;
int status;
switch( messageValue )
{
case CRYPT_CTXINFO_KEYING_SALT:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
if( contextType == CONTEXT_CONV )
{
if( cryptInfoPtr->ctxConv.saltLength )
{
setErrorInfo( cryptInfoPtr, CRYPT_CTXINFO_KEYING_SALT,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
memcpy( cryptInfoPtr->ctxConv.salt, msgData->data,
msgData->length );
cryptInfoPtr->ctxConv.saltLength = msgData->length;
return( CRYPT_OK );
}
if( cryptInfoPtr->ctxMAC.saltLength )
{
setErrorInfo( cryptInfoPtr, CRYPT_CTXINFO_KEYING_SALT,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
memcpy( cryptInfoPtr->ctxMAC.salt, msgData->data,
msgData->length );
cryptInfoPtr->ctxMAC.saltLength = msgData->length;
return( CRYPT_OK );
case CRYPT_CTXINFO_KEYING_VALUE:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
assert( needsKey( cryptInfoPtr ) );
/* Set up various parameters if they're not already set */
if( contextType == CONTEXT_CONV )
{
if( !cryptInfoPtr->ctxConv.saltLength )
{
getNonce( cryptInfoPtr->ctxConv.salt, PKCS5_SALT_SIZE );
cryptInfoPtr->ctxConv.saltLength = PKCS5_SALT_SIZE;
}
setMechanismDeriveInfo( &mechanismInfo,
cryptInfoPtr->ctxConv.userKey,
getOptimalKeysize( cryptInfoPtr, 0 ),
msgData->data, msgData->length, CRYPT_ALGO_SHA,
cryptInfoPtr->ctxConv.salt, cryptInfoPtr->ctxConv.saltLength,
cryptInfoPtr->ctxConv.keySetupIterations );
cryptInfoPtr->ctxConv.keySetupAlgorithm = CRYPT_ALGO_HMAC_SHA;
}
else
{
if( !cryptInfoPtr->ctxMAC.saltLength )
{
getNonce( cryptInfoPtr->ctxMAC.salt, PKCS5_SALT_SIZE );
cryptInfoPtr->ctxMAC.saltLength = PKCS5_SALT_SIZE;
}
setMechanismDeriveInfo( &mechanismInfo,
cryptInfoPtr->ctxMAC.userKey,
getOptimalKeysize( cryptInfoPtr, 0 ),
msgData->data, msgData->length, CRYPT_ALGO_SHA,
cryptInfoPtr->ctxMAC.salt, cryptInfoPtr->ctxMAC.saltLength,
cryptInfoPtr->ctxMAC.keySetupIterations );
cryptInfoPtr->ctxMAC.keySetupAlgorithm = CRYPT_ALGO_HMAC_SHA;
}
if( !mechanismInfo.iterations )
{
krnlSendMessage( cryptInfoPtr->ownerHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE, &mechanismInfo.iterations,
CRYPT_OPTION_KEYING_ITERATIONS );
if( contextType == CONTEXT_CONV )
cryptInfoPtr->ctxConv.keySetupIterations = \
mechanismInfo.iterations;
else
cryptInfoPtr->ctxMAC.keySetupIterations = \
mechanismInfo.iterations;
}
/* Turn the user key into an encryption context key */
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_DERIVE,
&mechanismInfo, MECHANISM_PKCS5 );
if( cryptStatusError( status ) )
return( status );
/* Load the key into the context */
return( loadKey( cryptInfoPtr, mechanismInfo.dataOut,
mechanismInfo.dataOutLength ) );
case CRYPT_CTXINFO_KEY:
assert( contextType == CONTEXT_CONV || \
contextType == CONTEXT_MAC );
assert( needsKey( cryptInfoPtr ) );
/* The kernel performs a general check on the size of this
attribute but doesn't know about context-subtype-specific
limits so we perform a context-specific check here */
if( msgData->length < capabilityInfoPtr->minKeySize || \
msgData->length > capabilityInfoPtr->maxKeySize )
return( CRYPT_ARGERROR_NUM1 );
/* Load the key into the context */
return( loadKey( cryptInfoPtr, msgData->data, msgData->length ) );
case CRYPT_CTXINFO_KEY_COMPONENTS:
assert( contextType == CONTEXT_PKC );
assert( needsKey( cryptInfoPtr ) );
/* Make sure the supplied key data is valid */
if( msgData->length != sizeof( CRYPT_PKCINFO_RSA ) && \
msgData->length != sizeof( CRYPT_PKCINFO_DLP ) && \
msgData->length != sizeof( PKCINFO_LOADINTERNAL ) )
return( CRYPT_ARGERROR_NUM1 );
/* We need to have a key label set before we can continue,
however if we're creating a public-key context through an
internal read (for example as part of importing a cert) there
won't be one available so we don't require a label for
internal loads of public keys */
if( !cryptInfoPtr->labelSize && \
msgData->length != sizeof( PKCINFO_LOADINTERNAL ) )
return( exitNotInited( cryptInfoPtr, CRYPT_CTXINFO_LABEL ) );
/* Load the key into the context */
return( loadKey( cryptInfoPtr, msgData->data, msgData->length ) );
case CRYPT_CTXINFO_IV:
assert( contextType == CONTEXT_CONV );
/* If it's a mode which doesn't use an IV, the load IV operation
is meaningless */
if( !needsIV( cryptInfoPtr->ctxConv.mode ) || \
isStreamCipher( cryptInfoPtr->capabilityInfo->cryptAlgo ) )
return( CRYPT_ERROR_NOTAVAIL );
/* Make sure the data size is valid */
if( msgData->length != capabilityInfoPtr->blockSize )
return( CRYPT_ARGERROR_NUM1 );
/* Load the IV */
assert( capabilityInfoPtr->initIVFunction != NULL );
return( capabilityInfoPtr->initIVFunction( cryptInfoPtr,
msgData->data, msgData->length ) );
case CRYPT_CTXINFO_LABEL:
if( cryptInfoPtr->labelSize )
{
setErrorInfo( cryptInfoPtr, CRYPT_CTXINFO_LABEL,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* Check any device object the context is associated with to
make sure 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 which depends
on the device (at context creation, on key load/generation, or
at some other point). Because of this we perform a preemptive
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( cryptInfoPtr->objectHandle,
RESOURCE_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( cryptInfoPtr->objectHandle,
RESOURCE_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( cryptInfoPtr->objectHandle,
RESOURCE_MESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PRIVATEKEY );
}
if( cryptStatusOK( status ) )
/* We found something with this label, we can't use
it again */
return( CRYPT_ERROR_DUPLICATE );
}
}
/* Set the label */
memcpy( cryptInfoPtr->label, msgData->data, msgData->length );
cryptInfoPtr->labelSize = msgData->length;
return( CRYPT_OK );
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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -