📄 keyex.c
字号:
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_PARAM3 : CRYPT_ERROR_PARAM2;
return( status );
}
C_RET cryptImportKey( C_IN void C_PTR encryptedKey,
C_IN CRYPT_CONTEXT importKey,
C_IN CRYPT_CONTEXT sessionKeyContext )
{
return( cryptImportKeyEx( encryptedKey, 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_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;
const KEYEX_TYPE keyexType = \
( formatType == CRYPT_FORMAT_AUTO || \
formatType == CRYPT_FORMAT_CRYPTLIB ) ? KEYEX_CRYPTLIB : \
( formatType == CRYPT_FORMAT_PGP ) ? KEYEX_PGP : KEYEX_CMS;
DYNBUF auxDB;
MESSAGE_CHECK_TYPE checkType;
int 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_NONE || \
formatType >= CRYPT_FORMAT_LAST_EXTERNAL )
return( CRYPT_ERROR_PARAM3 );
/* Check the exporting key */
status = krnlSendMessage( exportKey, MESSAGE_GETATTRIBUTE, &cryptAlgo,
CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM4 : 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;
status = krnlSendMessage( exportKey, MESSAGE_CHECK, NULL, checkType );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM4 : 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_PARAM4 );
/* 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_PARAM5 : status );
if( cryptStatusError( cryptlibToPgpAlgo( sessionKeyAlgo ) ) )
return( CRYPT_ERROR_PARAM5 );
}
#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_PARAM3;
}
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM5 : 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 ) )
{
status = dynCreate( &auxDB, exportKey,
( cryptAlgo == CRYPT_ALGO_DH || \
cryptAlgo == CRYPT_ALGO_KEA ) ? \
CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER : \
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusError( status ) )
return( CRYPT_ERROR_PARAM4 );
}
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 : STREAMSIZE_UNKNOWN,
sessionKeyContext, exportKey,
dynData( auxDB ), dynLength( auxDB ),
keyexType );
else
status = exportConventionalKey( encryptedKey, encryptedKeyLength,
( encryptedKey == NULL ) ? \
0 : STREAMSIZE_UNKNOWN,
sessionKeyContext, exportKey,
keyexType );
/* Clean up */
dynDestroy( &auxDB );
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_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_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_CRYPTLIB ) ? KEYEX_CRYPTLIB : \
( formatType == CRYPT_FORMAT_CMS || \
formatType == CRYPT_FORMAT_SMIME ) ? KEYEX_CMS : KEYEX_PGP;
int status;
assert( isReadPtr( encryptedKey, encryptedKeyLength ) );
assert( formatType > CRYPT_FORMAT_NONE && \
formatType < CRYPT_FORMAT_LAST );
assert( checkHandleRange( iImportKey ) );
assert( ( formatType == CRYPT_FORMAT_PGP && \
iSessionKeyContext == CRYPT_UNUSED ) || \
( formatType != CRYPT_FORMAT_PGP && \
checkHandleRange( 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_CMS || \
formatType == CRYPT_FORMAT_SMIME ) ? KEYEX_CMS : KEYEX_PGP;
DYNBUF auxDB;
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( checkHandleRange( 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 ) )
{
status = dynCreate( &auxDB, iExportKey,
( cryptAlgo == CRYPT_ALGO_DH || \
cryptAlgo == CRYPT_ALGO_KEA ) ? \
CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER : \
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusError( status ) )
return( CRYPT_ERROR_PARAM4 );
}
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,
encryptedKeyMaxLength, iSessionKeyContext,
iExportKey, dynData( auxDB ),
dynLength( auxDB ), keyexType );
else
status = exportConventionalKey( encryptedKey, encryptedKeyLength,
encryptedKeyMaxLength,
iSessionKeyContext, iExportKey,
keyexType );
/* Clean up */
dynDestroy( &auxDB );
return( status );
}
/****************************************************************************
* *
* Object Query Function *
* *
****************************************************************************/
/* Query an object. This is just a wrapper which provides an external
interface for the lower-level object-query routines */
C_RET cryptQueryObject( C_IN void C_PTR objectData,
C_OUT CRYPT_OBJECT_INFO C_PTR cryptObjectInfo )
{
QUERY_INFO queryInfo;
STREAM stream;
int value, status;
/* Perform basic error checking and clear the return value */
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 object-
query functions. 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 );
value = *( ( BYTE * ) objectData );
if( value == BER_SEQUENCE || value == MAKE_CTAG( 3 ) )
status = queryAsn1Object( &stream, &queryInfo );
#ifdef USE_PGP
else
status = queryPgpObject( &stream, &queryInfo );
#endif /* USE_PGP */
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 + -