📄 keyex.c
字号:
/* The importing key is owned, set the imported key's owner if it's
present */
if( sessionKeyContext != CRYPT_UNUSED )
{
status = krnlSendMessage( sessionKeyContext, MESSAGE_SETATTRIBUTE,
&owner, CRYPT_PROPERTY_OWNER );
if( cryptStatusError( status ) )
return( status );
}
}
else
{
/* Don't try and change the session key ownership */
originalOwner = CRYPT_ERROR;
}
/* Import it as appropriate */
status = iCryptImportKey( encryptedKey, encryptedKeyLength, formatType,
importKey, sessionKeyContext,
( formatType == CRYPT_FORMAT_PGP ) ? \
&iReturnedContext : NULL );
if( cryptStatusError( status ) )
{
/* The import failed, return the session key context to its
original owner. If this fails there's not much that we can do
to recover so we don't do anything with the return value */
if( originalOwner != CRYPT_ERROR )
{
( void ) krnlSendMessage( sessionKeyContext,
MESSAGE_SETATTRIBUTE,
&originalOwner, CRYPT_PROPERTY_OWNER );
}
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 );
}
#ifdef USE_PGP
/* If it's a PGP key import then the session key was recreated from
information stored with the wrapped key so we have to make it
externally visible before it can be used by the caller */
if( formatType == CRYPT_FORMAT_PGP && \
importAlgo >= CRYPT_ALGO_FIRST_PKC && importAlgo <= CRYPT_ALGO_LAST_PKC )
{
/* If the importing key is owned, set the imported key's owner */
if( originalOwner != CRYPT_ERROR )
{
status = krnlSendMessage( iReturnedContext,
IMESSAGE_SETATTRIBUTE,
&owner, CRYPT_PROPERTY_OWNER );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iReturnedContext, IMESSAGE_DECREFCOUNT );
return( status );
}
}
/* Make the newly-created context externally visible */
status = krnlSendMessage( iReturnedContext, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE,
CRYPT_IATTRIBUTE_INTERNAL );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iReturnedContext, IMESSAGE_DECREFCOUNT );
return( status );
}
*returnedContext = iReturnedContext;
}
#endif /* USE_PGP */
return( CRYPT_OK );
}
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 a Session Key *
* *
****************************************************************************/
/* Export an extended encrypted key, either a cryptlib key or a CMS key */
C_RET cryptExportKeyEx( C_OUT_OPT 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 exportAlgo, sessionKeyAlgo;
int status;
/* Perform basic error checking */
if( encryptedKey != NULL )
{
if( encryptedKeyMaxLength <= MIN_CRYPT_OBJECTSIZE || \
encryptedKeyMaxLength >= MAX_INTLENGTH )
return( CRYPT_ERROR_PARAM2 );
if( !isWritePtr( encryptedKey, encryptedKeyMaxLength ) )
return( CRYPT_ERROR_PARAM1 );
memset( encryptedKey, 0, MIN_CRYPT_OBJECTSIZE );
}
else
{
if( encryptedKeyMaxLength != 0 )
return( CRYPT_ERROR_PARAM2 );
}
if( !isWritePtr( encryptedKeyLength, sizeof( int ) ) )
return( CRYPT_ERROR_PARAM3 );
*encryptedKeyLength = 0;
if( formatType != CRYPT_FORMAT_CRYPTLIB && \
formatType != CRYPT_FORMAT_CMS && \
formatType != CRYPT_FORMAT_SMIME && \
formatType != CRYPT_FORMAT_PGP )
return( CRYPT_ERROR_PARAM4 );
if( !isHandleRangeValid( exportKey ) )
return( CRYPT_ERROR_PARAM5 );
if( !isHandleRangeValid( sessionKeyContext ) )
return( CRYPT_ERROR_PARAM6 );
/* Check the exporting key */
status = checkWrapKey( exportKey, &exportAlgo, FALSE );
if( cryptStatusError( status ) )
return( cryptArgError( status ) ? CRYPT_ERROR_PARAM5 : status );
status = checkContextsEncodable( exportKey, exportAlgo,
sessionKeyContext, formatType );
if( cryptStatusError( status ) )
{
return( ( status == CRYPT_ERROR_PARAM1 ) ? CRYPT_ERROR_PARAM5 : \
( status == CRYPT_ERROR_PARAM3 ) ? CRYPT_ERROR_PARAM6 : \
CRYPT_ERROR_PARAM4 );
}
/* Check the exported key */
status = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,
&sessionKeyAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( CRYPT_ERROR_PARAM6 );
status = krnlSendMessage( sessionKeyContext, MESSAGE_CHECK, NULL,
( sessionKeyAlgo >= CRYPT_ALGO_FIRST_MAC && \
sessionKeyAlgo <= CRYPT_ALGO_LAST_MAC ) ? \
MESSAGE_CHECK_MAC : MESSAGE_CHECK_CRYPT );
if( cryptStatusError( status ) )
return( cryptArgError( status ) ? CRYPT_ERROR_PARAM6 : status );
/* Export the key via the shared export function */
status = iCryptExportKey( encryptedKey, encryptedKeyMaxLength,
encryptedKeyLength, formatType,
sessionKeyContext, exportKey );
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_OPT 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 explicit
checking done by the external versions (e.g. "Is this value really a
handle to a valid PKC context?") since they're only called by cryptlib
internal functions rather than being passed untrusted user data */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int iCryptImportKey( IN_BUFFER( encryptedKeyLength ) const void *encryptedKey,
IN_LENGTH_SHORT const int encryptedKeyLength,
IN_ENUM( CRYPT_FORMAT ) const CRYPT_FORMAT_TYPE formatType,
IN_HANDLE const CRYPT_CONTEXT iImportKey,
IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,
OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iReturnedContext )
{
CRYPT_ALGO_TYPE importAlgo;
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_PGP && \
isWritePtr( iReturnedContext, sizeof( CRYPT_CONTEXT ) ) ) || \
( formatType != CRYPT_FORMAT_PGP && \
iReturnedContext == NULL ) );
REQUIRES( encryptedKeyLength > MIN_CRYPT_OBJECTSIZE && \
encryptedKeyLength < MAX_INTLENGTH_SHORT );
REQUIRES( formatType > CRYPT_FORMAT_NONE && \
formatType < CRYPT_FORMAT_LAST );
REQUIRES( isHandleRangeValid( iImportKey ) );
REQUIRES( ( formatType == CRYPT_FORMAT_PGP && \
iSessionKeyContext == CRYPT_UNUSED ) || \
( formatType != CRYPT_FORMAT_PGP && \
isHandleRangeValid( iSessionKeyContext ) ) );
REQUIRES( ( 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 since it's a protocol-specific mechanism used by SSH and SSL,
which are internal-only formats */
status = krnlSendMessage( iImportKey, IMESSAGE_GETATTRIBUTE, &importAlgo,
CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( status );
if( importAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
importAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
{
return( importConventionalKey( encryptedKey, encryptedKeyLength,
iSessionKeyContext, iImportKey,
keyexType ) );
}
return( importPublicKey( encryptedKey, encryptedKeyLength,
iSessionKeyContext, iImportKey,
iReturnedContext, keyexType ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
int iCryptExportKey( OUT_BUFFER_OPT( encryptedKeyMaxLength, *encryptedKeyLength ) \
void *encryptedKey,
IN_LENGTH_Z const int encryptedKeyMaxLength,
OUT_LENGTH_Z int *encryptedKeyLength,
IN_ENUM( CRYPT_FORMAT ) const CRYPT_FORMAT_TYPE formatType,
IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,
IN_HANDLE const CRYPT_CONTEXT iExportKey )
{
CRYPT_ALGO_TYPE exportAlgo;
const KEYEX_TYPE keyexType = \
( formatType == CRYPT_FORMAT_CRYPTLIB ) ? KEYEX_CRYPTLIB : \
( formatType == CRYPT_FORMAT_PGP ) ? KEYEX_PGP : KEYEX_CMS;
DYNBUF auxDB;
const int encKeyMaxLength = ( encryptedKey == NULL ) ? \
0 : encryptedKeyMaxLength;
int status;
assert( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \
( encryptedKeyMaxLength >= MIN_CRYPT_OBJECTSIZE && \
isWritePtr( encryptedKey, encryptedKeyMaxLength ) ) );
assert( isWritePtr( encryptedKeyLength, sizeof( int ) ) );
REQUIRES( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \
( encryptedKeyMaxLength > MIN_CRYPT_OBJECTSIZE && \
encryptedKeyMaxLength < MAX_INTLENGTH ) );
REQUIRES( formatType > CRYPT_FORMAT_NONE && \
formatType < CRYPT_FORMAT_LAST );
REQUIRES( ( formatType == CRYPT_FORMAT_PGP && \
iSessionKeyContext == CRYPT_UNUSED ) || \
isHandleRangeValid( iSessionKeyContext ) );
REQUIRES( isHandleRangeValid( iExportKey ) );
/* Clear return value */
*encryptedKeyLength = 0;
/* Perform simplified error checking */
status = krnlSendMessage( iExportKey, IMESSAGE_GETATTRIBUTE, &exportAlgo,
CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );
/* If it's a non-PKC export, pass the call down to the low-level export
function */
if( exportAlgo < CRYPT_ALGO_FIRST_PKC || exportAlgo > CRYPT_ALGO_LAST_PKC )
{
return( exportConventionalKey( encryptedKey, encKeyMaxLength,
encryptedKeyLength, iSessionKeyContext,
iExportKey, keyexType ) );
}
REQUIRES( isHandleRangeValid( iSessionKeyContext ) );
/* If it's a non-CMS/SMIME PKC export, pass the call down to the low-
level export function */
if( formatType != CRYPT_FORMAT_CMS && formatType != CRYPT_FORMAT_SMIME )
{
return( exportPublicKey( encryptedKey, encKeyMaxLength,
encryptedKeyLength, iSessionKeyContext,
iExportKey, NULL, 0, keyexType ) );
}
/* We're exporting a key in CMS format we need to obtain recipient
information from the certificate associated with the export context.
First we 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 );
status = krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORFIRST,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
if( cryptStatusError( status ) )
{
/* Unlock the chain before we exit. If this fails there's not much
that we can do to recover so we don't do anything with the return
value */
( void ) krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE,
CRYPT_IATTRIBUTE_LOCKED );
return( CRYPT_ERROR_PARAM5 );
}
/* Next we get the recipient information from the cert into a dynbuf */
status = dynCreate( &auxDB, iExportKey,
( exportAlgo == CRYPT_ALGO_KEA ) ? \
CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER : \
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusError( status ) )
{
( void ) krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE,
CRYPT_IATTRIBUTE_LOCKED );
return( CRYPT_ERROR_PARAM5 );
}
/* We're ready to export the key alongside the key ID as auxiliary
data */
status = exportPublicKey( encryptedKey, encKeyMaxLength,
encryptedKeyLength, iSessionKeyContext,
iExportKey, dynData( auxDB ),
dynLength( auxDB ), keyexType );
/* Clean up. If the unlock fails there's not much that we can do to
recover so we don't do anything with the return value */
( void ) krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
dynDestroy( &auxDB );
return( status );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -