📄 lib_keyx.c
字号:
C_IN CRYPT_CONTEXT sessionKeyContext )
{
/* cryptImportKey() and cryptImportKeyEx() do the same thing */
return( cryptImportKeyEx( encryptedKey, importKey, sessionKeyContext ) );
}
/* Export an extended encrypted key, either a cryptlib key or a CMS key */
C_RET cryptExportKeyEx( C_OUT void C_PTR encryptedKey,
C_OUT int C_PTR encryptedKeyLength,
C_IN CRYPT_FORMAT_TYPE formatType,
C_IN CRYPT_HANDLE exportKey,
C_IN CRYPT_CONTEXT sessionKeyContext )
{
CRYPT_ALGO cryptAlgo;
CRYPT_MODE sessionKeyMode;
const RECIPIENT_TYPE recipientType = \
( formatType == CRYPT_FORMAT_CRYPTLIB ) ? RECIPIENT_CRYPTLIB : \
( formatType == CRYPT_FORMAT_CMS || \
formatType == CRYPT_FORMAT_SMIME ) ? RECIPIENT_CMS : RECIPIENT_NONE;
BYTE auxDataBuffer[ 1024 ], *auxData = auxDataBuffer;
RESOURCE_MESSAGE_CHECK_TYPE checkType;
int auxDataLength = 1024, status;
/* Perform basic error checking */
if( encryptedKey != NULL )
{
if( checkBadPtrWrite( encryptedKey, MIN_CRYPT_OBJECTSIZE ) )
return( CRYPT_ERROR_PARAM1 );
memset( encryptedKey, 0, MIN_CRYPT_OBJECTSIZE );
}
if( checkBadPtrWrite( encryptedKeyLength, sizeof( int ) ) )
return( CRYPT_ERROR_PARAM2 );
*encryptedKeyLength = 0;
if( formatType != CRYPT_FORMAT_CRYPTLIB && \
formatType != CRYPT_FORMAT_CMS && formatType != CRYPT_FORMAT_SMIME )
return( CRYPT_ERROR_PARAM3 );
/* Check the exporting key */
status = krnlSendMessage( exportKey, RESOURCE_MESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM3 : status );
if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
checkType = ( cryptAlgo == CRYPT_ALGO_DH ) ? \
RESOURCE_MESSAGE_CHECK_PKC_KA_EXPORT : \
RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT;
else
checkType = RESOURCE_MESSAGE_CHECK_CRYPT;
status = krnlSendMessage( exportKey, RESOURCE_MESSAGE_CHECK, NULL,
checkType );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM3 : status );
if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \
cryptStatusError( sizeofAlgoIDex( cryptAlgo,
( CRYPT_ALGO ) CRYPT_MODE_CBC, 0 ) ) )
/* Conventional key wrap requires the use of an CBC mode for the
wrapping (which also implies the use of a block cipher). CBC mode
isn't essential but it's a good safety check, the use of a block
cipher is essential */
return( CRYPT_ERROR_PARAM3 );
/* Check the exported key */
status = krnlSendMessage( sessionKeyContext, RESOURCE_MESSAGE_GETATTRIBUTE,
&sessionKeyMode, CRYPT_CTXINFO_MODE );
if( status == CRYPT_ARGERROR_VALUE )
{
/* No encryption mode attribute present, it has to be a MAC
context */
checkType = RESOURCE_MESSAGE_CHECK_MAC;
status = CRYPT_OK;
}
else
checkType = RESOURCE_MESSAGE_CHECK_CRYPT;
if( cryptStatusOK( status ) )
status = krnlSendMessage( sessionKeyContext, RESOURCE_MESSAGE_CHECK,
NULL, checkType );
if( cryptAlgo == CRYPT_ALGO_DH )
{
/* If we're using a key agreement algorithm it doesn't matter if the
session key context has a key attribute present or not, but the
format has to be cryptlib */
if( status == CRYPT_ERROR_NOTINITED )
status = CRYPT_OK;
if( formatType == CRYPT_FORMAT_CMS || \
formatType == CRYPT_FORMAT_SMIME )
status = CRYPT_ERROR_PARAM3;
}
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM4 : status );
/* If we're exporting a key in CMS format using a public key we need to
obtain recipient information */
if( ( formatType == CRYPT_FORMAT_CMS || \
formatType == CRYPT_FORMAT_SMIME ) &&
( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
cryptAlgo <= CRYPT_ALGO_LAST_PKC ) )
{
if( cryptAlgo == CRYPT_ALGO_DH || cryptAlgo == CRYPT_ALGO_KEA )
{
RESOURCE_DATA msgData;
setResourceData( &msgData, auxDataBuffer, 1024 );
status = krnlSendMessage( exportKey,
RESOURCE_MESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
if( cryptStatusError( status ) )
status = CRYPT_ERROR_PARAM4;
auxDataLength = msgData.length;
}
else
status = getIssuerAndSerialNumber( exportKey, &auxData,
&auxDataLength );
if( cryptStatusError( status ) )
return( status );
}
/* Export it as appropriate */
if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
{
if( cryptAlgo == CRYPT_ALGO_DH || cryptAlgo == CRYPT_ALGO_KEA )
status = exportKeyAgreeKey( encryptedKey, encryptedKeyLength,
sessionKeyContext, exportKey,
CRYPT_UNUSED, auxData, auxDataLength );
else
status = exportPublicKey( encryptedKey, encryptedKeyLength,
sessionKeyContext, exportKey, auxData,
auxDataLength, recipientType );
}
else
status = exportConventionalKey( encryptedKey, encryptedKeyLength,
sessionKeyContext, exportKey );
/* Clean up */
if( auxData != auxDataBuffer )
free( auxData );
if( cryptArgError( status ) )
/* If we get an argument error from the mechanism-level code, map the
mechanism parameter number to the function argument number */
status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
CRYPT_ERROR_PARAM5 : CRYPT_ERROR_PARAM4;
return( status );
}
C_RET cryptExportKey( C_OUT void C_PTR encryptedKey,
C_OUT int C_PTR encryptedKeyLength,
C_IN CRYPT_HANDLE exportKey,
C_IN CRYPT_CONTEXT sessionKeyContext )
{
int status;
status = cryptExportKeyEx( encryptedKey, encryptedKeyLength,
CRYPT_FORMAT_CRYPTLIB, exportKey,
sessionKeyContext );
return( ( status == CRYPT_ERROR_PARAM4 ) ? CRYPT_ERROR_PARAM3 : \
( status == CRYPT_ERROR_PARAM5 ) ? CRYPT_ERROR_PARAM4 : status );
}
/****************************************************************************
* *
* Internal Import/Export Functions *
* *
****************************************************************************/
/* Internal versions of the above. These skip a lot of the checking done by
the external versions since they're only called by cryptlib internal
functions which have already checked the parameters for validity */
int iCryptImportKeyEx( const void *encryptedKey, const int encryptedKeyLength,
const CRYPT_CONTEXT iImportKey,
const CRYPT_CONTEXT iSessionKeyContext )
{
CRYPT_ALGO cryptAlgo;
int status;
/* Import it as appropriate. We don't handle key agreement at this
level */
status = krnlSendMessage( iImportKey, RESOURCE_IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( status );
if( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
return( importConventionalKey( encryptedKey, encryptedKeyLength,
iSessionKeyContext, iImportKey ) );
return( importPublicKey( encryptedKey, encryptedKeyLength,
iSessionKeyContext, iImportKey ) );
}
int iCryptExportKeyEx( void *encryptedKey, int *encryptedKeyLength,
const CRYPT_FORMAT_TYPE formatType,
const CRYPT_CONTEXT iSessionKeyContext,
const CRYPT_CONTEXT iExportKey,
const CRYPT_CONTEXT iAuxContext )
{
CRYPT_ALGO cryptAlgo;
const RECIPIENT_TYPE recipientType = \
( formatType == CRYPT_FORMAT_CRYPTLIB ) ? RECIPIENT_CRYPTLIB : \
( formatType == CRYPT_FORMAT_CMS || \
formatType == CRYPT_FORMAT_SMIME ) ? RECIPIENT_CMS : RECIPIENT_NONE;
BYTE auxDataBuffer[ 1024 ], *auxData = auxDataBuffer;
int auxDataLength = 1024, status;
*encryptedKeyLength = 0;
/* Perform simplified error checking */
status = krnlSendMessage( iExportKey, RESOURCE_IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( status );
/* If we're exporting a key in CMS format using a public key we need to
obtain recipient information */
if( ( formatType == CRYPT_FORMAT_CMS || \
formatType == CRYPT_FORMAT_SMIME ) && \
( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
cryptAlgo <= CRYPT_ALGO_LAST_PKC ) )
{
if( cryptAlgo == CRYPT_ALGO_DH || cryptAlgo == CRYPT_ALGO_KEA )
{
RESOURCE_DATA msgData;
setResourceData( &msgData, auxDataBuffer, 1024 );
status = krnlSendMessage( iExportKey,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
if( cryptStatusError( status ) )
status = CRYPT_ARGERROR_OBJECT;
auxDataLength = msgData.length;
}
else
status = getIssuerAndSerialNumber( iExportKey, &auxData,
&auxDataLength );
if( cryptStatusError( status ) )
return( status );
}
/* Export it as appropriate. We don't handle key agreement at this
level */
if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
{
if( cryptAlgo == CRYPT_ALGO_DH || cryptAlgo == CRYPT_ALGO_KEA )
status = exportKeyAgreeKey( encryptedKey, encryptedKeyLength,
iSessionKeyContext, iExportKey,
iAuxContext, auxData, auxDataLength );
else
status = exportPublicKey( encryptedKey, encryptedKeyLength,
iSessionKeyContext, iExportKey,
auxData, auxDataLength, recipientType );
}
else
status = exportConventionalKey( encryptedKey, encryptedKeyLength,
iSessionKeyContext, iExportKey );
/* Clean up */
if( auxData != auxDataBuffer )
free( auxData );
return( status );
}
/****************************************************************************
* *
* Object Query Function *
* *
****************************************************************************/
/* Query an object. This is just a wrapper which provides an external
interface for queryObject() */
C_RET cryptQueryObject( C_IN void C_PTR objectData,
C_OUT CRYPT_OBJECT_INFO C_PTR cryptObjectInfo )
{
QUERY_INFO queryInfo;
STREAM stream;
int status;
/* Perform basic error checking */
if( checkBadPtrRead( objectData, MIN_CRYPT_OBJECTSIZE ) )
return( CRYPT_ERROR_PARAM1 );
if( checkBadPtrWrite( cryptObjectInfo, sizeof( CRYPT_OBJECT_INFO ) ) )
return( CRYPT_ERROR_PARAM2 );
memset( cryptObjectInfo, 0, sizeof( CRYPT_OBJECT_INFO ) );
/* Query the object. This is just a wrapper for the lower-level
queryObject() function. The length should be specified as a user
parameter, unfortunately the early cryptlib API didn't take length
parameters when it wasn't absolutely necessary so we have to take a
guess at a safe size limit and hope that the data isn't all done
with an indefinite encoding */
sMemConnect( &stream, ( void * ) objectData, 2048 );
status = queryObject( &stream, &queryInfo );
sMemDisconnect( &stream );
/* Copy the externally-visible fields across */
if( cryptStatusOK( status ) )
{
cryptObjectInfo->objectType = queryInfo.type;
cryptObjectInfo->cryptAlgo = queryInfo.cryptAlgo;
cryptObjectInfo->cryptMode = queryInfo.cryptMode;
if( queryInfo.type == CRYPT_OBJECT_SIGNATURE )
cryptObjectInfo->hashAlgo = queryInfo.hashAlgo;
if( queryInfo.type == CRYPT_OBJECT_ENCRYPTED_KEY && \
queryInfo.saltLength )
{
memcpy( cryptObjectInfo->salt, queryInfo.salt,
queryInfo.saltLength );
cryptObjectInfo->saltSize = queryInfo.saltLength;
}
}
return( status );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -