📄 keyex.c
字号:
status = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,
&sessionKeyAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) )
status = krnlSendMessage( sessionKeyContext, MESSAGE_CHECK, NULL,
( sessionKeyAlgo >= CRYPT_ALGO_FIRST_MAC ) ? \
MESSAGE_CHECK_MAC_READY : \
MESSAGE_CHECK_CRYPT_READY );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM4 : status );
if( returnedContext != NULL )
return( CRYPT_ERROR_PARAM5 );
}
/* If the importing key is owned, bind the session key context to the same
owner before we load a key into it. We also need to save the original
owner so we can undo the binding later if things fail */
status = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,
&originalOwner, CRYPT_PROPERTY_OWNER );
if( cryptStatusError( status ) )
originalOwner = CRYPT_ERROR; /* Unowned object */
status = krnlSendMessage( importKey, MESSAGE_GETATTRIBUTE, &owner,
CRYPT_PROPERTY_OWNER );
if( cryptStatusOK( status ) )
krnlSendMessage( sessionKeyContext, MESSAGE_SETATTRIBUTE, &owner,
CRYPT_PROPERTY_OWNER );
/* Import it as appropriate */
if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
{
if( formatType == CRYPT_FORMAT_PGP )
{
status = importPublicKey( encryptedKey, encryptedKeyLength,
CRYPT_UNUSED, importKey,
&iReturnedContext, KEYEX_PGP );
if( cryptStatusOK( status ) )
/* Make the newly-created context externally visible */
krnlSendMessage( iReturnedContext, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE,
CRYPT_IATTRIBUTE_INTERNAL );
}
else
status = importPublicKey( encryptedKey, encryptedKeyLength,
sessionKeyContext, importKey, NULL,
( formatType == CRYPT_FORMAT_CMS ) ? \
KEYEX_CMS : KEYEX_CRYPTLIB );
}
else
status = importConventionalKey( encryptedKey, encryptedKeyLength,
sessionKeyContext, importKey,
( formatType == CRYPT_FORMAT_CRYPTLIB ) ? \
KEYEX_CRYPTLIB : KEYEX_PGP );
/* If the import failed, return the session key context to its
original owner */
if( cryptStatusError( status ) )
{
if( originalOwner != CRYPT_ERROR )
krnlSendMessage( sessionKeyContext, MESSAGE_SETATTRIBUTE,
&originalOwner, CRYPT_PROPERTY_OWNER );
}
else
/* If we created the session key as part of the import operation,
return it to the caller */
if( formatType == CRYPT_FORMAT_PGP )
*returnedContext = iReturnedContext;
if( cryptArgError( status ) )
/* If we get an argument error from the lower-level code, map the
parameter number to the function argument number */
status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
CRYPT_ERROR_PARAM4 : CRYPT_ERROR_PARAM3;
return( status );
}
C_RET cryptImportKey( C_IN void C_PTR encryptedKey,
C_IN int encryptedKeyLength,
C_IN CRYPT_CONTEXT importKey,
C_IN CRYPT_CONTEXT sessionKeyContext )
{
return( cryptImportKeyEx( encryptedKey, encryptedKeyLength, importKey,
sessionKeyContext, NULL ) );
}
/* Export an extended encrypted key, either a cryptlib key or a CMS key */
C_RET cryptExportKeyEx( C_OUT void C_PTR encryptedKey,
C_IN int encryptedKeyMaxLength,
C_OUT int C_PTR encryptedKeyLength,
C_IN CRYPT_FORMAT_TYPE formatType,
C_IN CRYPT_HANDLE exportKey,
C_IN CRYPT_CONTEXT sessionKeyContext )
{
CRYPT_ALGO_TYPE cryptAlgo;
CRYPT_MODE_TYPE sessionKeyMode;
MESSAGE_CHECK_TYPE checkType;
int status;
/* Perform basic error checking */
if( encryptedKey != NULL )
{
if( encryptedKeyMaxLength < MIN_CRYPT_OBJECTSIZE )
return( CRYPT_ERROR_PARAM2 );
if( !isWritePtr( encryptedKey, encryptedKeyMaxLength ) )
return( CRYPT_ERROR_PARAM1 );
memset( encryptedKey, 0, MIN_CRYPT_OBJECTSIZE );
}
if( !isWritePtr( encryptedKeyLength, sizeof( int ) ) )
return( CRYPT_ERROR_PARAM3 );
*encryptedKeyLength = 0;
if( formatType <= CRYPT_FORMAT_NONE || \
formatType >= CRYPT_FORMAT_LAST_EXTERNAL )
return( CRYPT_ERROR_PARAM4 );
/* Check the exporting key */
status = krnlSendMessage( exportKey, MESSAGE_GETATTRIBUTE, &cryptAlgo,
CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM5 : status );
if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
checkType = ( cryptAlgo == CRYPT_ALGO_DH ) ? \
MESSAGE_CHECK_PKC_KA_EXPORT : MESSAGE_CHECK_PKC_ENCRYPT;
else
checkType = MESSAGE_CHECK_CRYPT;
if( isDlpAlgo( cryptAlgo ) )
/* The DLP algorithms have specialised data-formatting requirements
and can't normally be directly accessed via external messages,
however if we're performing a key export this is OK since they're
being used from cryptlib-internal routines. Doing the check via
an internal message is safe since we've already checked its
external accessibility when we got the algorithm info */
status = krnlSendMessage( exportKey, IMESSAGE_CHECK, NULL,
checkType );
else
status = krnlSendMessage( exportKey, MESSAGE_CHECK, NULL,
checkType );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM5 : status );
if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \
cryptStatusError( sizeofAlgoIDex( cryptAlgo,
( CRYPT_ALGO_TYPE ) 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_PARAM5 );
/* Check the exported key */
status = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,
&sessionKeyMode, CRYPT_CTXINFO_MODE );
if( status == CRYPT_ARGERROR_VALUE )
{
/* No encryption mode attribute present, it has to be a MAC
context */
checkType = MESSAGE_CHECK_MAC;
status = CRYPT_OK;
}
else
checkType = MESSAGE_CHECK_CRYPT;
if( cryptStatusOK( status ) )
status = krnlSendMessage( sessionKeyContext, MESSAGE_CHECK, NULL,
checkType );
#ifdef USE_PGP
if( formatType == CRYPT_FORMAT_PGP )
{
CRYPT_ALGO_TYPE sessionKeyAlgo;
/* PGP can only handle a limited subset of algorithms, make sure this
is an algorithm type which can be represented in the PGP format */
status = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,
&sessionKeyAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM6 : status );
if( cryptlibToPgpAlgo( sessionKeyAlgo ) == PGP_ALGO_NONE )
return( CRYPT_ERROR_PARAM6 );
}
#endif /* USE_PGP */
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_PARAM4;
}
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM6 : status );
/* Export the key via the shared export function */
status = iCryptExportKeyEx( encryptedKey, encryptedKeyLength,
encryptedKeyMaxLength, formatType,
sessionKeyContext, exportKey,
CRYPT_UNUSED );
if( cryptArgError( status ) )
/* If we get an argument error from the lower-level code, map the
parameter number to the function argument number */
status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
CRYPT_ERROR_PARAM6 : CRYPT_ERROR_PARAM5;
return( status );
}
C_RET cryptExportKey( C_OUT void C_PTR encryptedKey,
C_IN int encryptedKeyMaxLength,
C_OUT int C_PTR encryptedKeyLength,
C_IN CRYPT_HANDLE exportKey,
C_IN CRYPT_CONTEXT sessionKeyContext )
{
int status;
status = cryptExportKeyEx( encryptedKey, encryptedKeyMaxLength,
encryptedKeyLength, CRYPT_FORMAT_CRYPTLIB,
exportKey, sessionKeyContext );
return( ( status == CRYPT_ERROR_PARAM5 ) ? CRYPT_ERROR_PARAM4 : \
( status == CRYPT_ERROR_PARAM6 ) ? CRYPT_ERROR_PARAM5 : 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_FORMAT_TYPE formatType,
const CRYPT_CONTEXT iImportKey,
const CRYPT_CONTEXT iSessionKeyContext,
CRYPT_CONTEXT *iReturnedContext )
{
CRYPT_ALGO_TYPE cryptAlgo;
const KEYEX_TYPE keyexType = \
( formatType == CRYPT_FORMAT_AUTO || \
formatType == CRYPT_FORMAT_CRYPTLIB ) ? KEYEX_CRYPTLIB : \
( formatType == CRYPT_FORMAT_PGP ) ? KEYEX_PGP : KEYEX_CMS;
int status;
assert( isReadPtr( encryptedKey, encryptedKeyLength ) );
assert( formatType > CRYPT_FORMAT_NONE && \
formatType < CRYPT_FORMAT_LAST );
assert( isHandleRangeValid( iImportKey ) );
assert( ( formatType == CRYPT_FORMAT_PGP && \
iSessionKeyContext == CRYPT_UNUSED ) || \
( formatType != CRYPT_FORMAT_PGP && \
isHandleRangeValid( iSessionKeyContext ) ) );
assert( ( formatType == CRYPT_FORMAT_PGP && \
iReturnedContext != NULL ) || \
( formatType != CRYPT_FORMAT_PGP && \
iReturnedContext == NULL ) );
/* Import it as appropriate. We don't handle key agreement at this
level */
status = krnlSendMessage( iImportKey, 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,
keyexType ) );
return( importPublicKey( encryptedKey, encryptedKeyLength,
iSessionKeyContext, iImportKey,
iReturnedContext, keyexType ) );
}
int iCryptExportKeyEx( void *encryptedKey, int *encryptedKeyLength,
const int encryptedKeyMaxLength,
const CRYPT_FORMAT_TYPE formatType,
const CRYPT_CONTEXT iSessionKeyContext,
const CRYPT_CONTEXT iExportKey,
const CRYPT_CONTEXT iAuxContext )
{
CRYPT_ALGO_TYPE cryptAlgo;
const KEYEX_TYPE keyexType = \
( formatType == CRYPT_FORMAT_CRYPTLIB ) ? KEYEX_CRYPTLIB : \
( formatType == CRYPT_FORMAT_PGP ) ? KEYEX_PGP : KEYEX_CMS;
DYNBUF auxDB;
BOOLEAN lockObject = FALSE;
int status;
assert( encryptedKey == NULL || \
isWritePtr( encryptedKey, MIN_CRYPT_OBJECTSIZE ) );
assert( isWritePtr( encryptedKeyLength, sizeof( int ) ) );
assert( formatType > CRYPT_FORMAT_NONE && \
formatType < CRYPT_FORMAT_LAST );
assert( isHandleRangeValid( iExportKey ) );
/* Clear return value */
*encryptedKeyLength = 0;
/* Perform simplified error checking */
status = krnlSendMessage( iExportKey, IMESSAGE_GETATTRIBUTE, &cryptAlgo,
CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ARGERROR_NUM2 : 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 ) )
{
/* Lock the cert for our exclusive use, and in case it's a cert
chain, select the first cert in the chain */
status = krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE,
CRYPT_IATTRIBUTE_LOCKED );
if( cryptStatusError( status ) )
return( CRYPT_ERROR_PARAM5 );
krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORFIRST,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
/* Get the recipient information from the cert */
status = dynCreate( &auxDB, iExportKey,
( cryptAlgo == CRYPT_ALGO_DH || \
cryptAlgo == CRYPT_ALGO_KEA ) ? \
CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER : \
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusError( status ) )
{
krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
return( CRYPT_ERROR_PARAM5 );
}
lockObject = TRUE;
}
else
dynCreate( &auxDB, CRYPT_UNUSED, CRYPT_UNUSED );
/* Export it as appropriate */
if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
status = exportPublicKey( encryptedKey, encryptedKeyLength,
( encryptedKey == NULL ) ? \
0 : encryptedKeyMaxLength,
iSessionKeyContext, iExportKey,
dynData( auxDB ), dynLength( auxDB ),
keyexType );
else
status = exportConventionalKey( encryptedKey, encryptedKeyLength,
( encryptedKey == NULL ) ? \
0 : encryptedKeyMaxLength,
iSessionKeyContext, iExportKey,
keyexType );
/* Clean up */
if( lockObject )
krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
dynDestroy( &auxDB );
return( status );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -